7 #include <freetype/freetype.h>
10 #define MAX_GLYPHS 256
12 #define _debug(f...) {fprintf(stderr, "debug: ");fprintf(stderr, ##f);fflush(stderr);}
14 /* #define _debug(s) printf(s);*/
17 static Display
*ds_dpy
= 0;
18 static Colormap ds_cmap
;
19 static RContext
*rc
= 0;
21 RColor black_color
= {0, 0, 0, 0};
24 FT_Library ft_library
;
25 static int inst_ft_library
= 0;
27 typedef struct __FreeTypeRImage
{
35 typedef struct __FreeTypeData
{
38 WMFreeTypeRImage
**glyphs_array
;
39 WMFreeTypeRImage
**glyphs_shadow_array
;
42 #endif /* USE_FREETYPE */
44 int getColor (const char *string
, Colormap cmap
, XColor
*xcolor
) {
45 if (!XParseColor (ds_dpy
, cmap
, string
, xcolor
)) {
48 if (!XAllocColor (ds_dpy
, cmap
, xcolor
)) {
56 initDrawPlainString(Display
*dpy
, Colormap
*cmap
) {
62 destroyDrawPlainString(proplist_t pl
, WPluginData
*func_data
) {
68 drawPlainString (proplist_t pl
, Drawable d
,
69 int x
, int y
, unsigned width
, unsigned height
,
70 char *text
, WPluginData
*func_data
)
72 XColor color1
, color2
, color3
, color4
;
80 length
= strlen(text
);
81 gc
= func_data
->array
[2];
82 font
= func_data
->array
[3];
86 printf("%d members\n",PLGetNumberOfElements(pl));
88 printf("%d %s\n",i,PLGetString(PLGetArrayElement(pl,i)));
92 drawbuffer
= XCreatePixmap(ds_dpy
, d
,
93 width
, height
*4+6, DefaultDepth(ds_dpy
,DefaultScreen(ds_dpy
)));
94 XCopyArea(ds_dpy
, d
, drawbuffer
,gc
,0,y
-1,width
,height
,0,0);
96 if (PLGetNumberOfElements(pl
) > 5) {
97 plcolor
= PLGetArrayElement(pl
, 5);
98 if (getColor(PLGetString(plcolor
),ds_cmap
, &color3
)) {
99 XSetForeground(ds_dpy
, gc
, color3
.pixel
);
101 if (font
->notFontSet
) {
102 XSetFont(ds_dpy
, gc
, font
->font
.normal
->fid
);
103 XDrawString(ds_dpy
, drawbuffer
, gc
, x
+3, font
->y
+3, text
, length
);
105 XmbDrawString(ds_dpy
, drawbuffer
, font
->font
.set
, gc
, x
+4, y
+4 + font
->y
,
111 if (PLGetNumberOfElements(pl
) > 4) {
112 plcolor
= PLGetArrayElement(pl
, 4);
113 if (getColor(PLGetString(plcolor
),ds_cmap
, &color1
)) {
114 XSetForeground(ds_dpy
, gc
, color1
.pixel
);
116 if (font
->notFontSet
) {
117 XSetFont(ds_dpy
, gc
, font
->font
.normal
->fid
);
118 XDrawString(ds_dpy
, drawbuffer
, gc
, x
+1, font
->y
+1, text
, length
);
120 XmbDrawString(ds_dpy
, drawbuffer
, font
->font
.set
, gc
, x
, y
+ font
->y
,
126 if (PLGetNumberOfElements(pl
) > 3) {
127 plcolor
= PLGetArrayElement(pl
, 3);
128 if (getColor(PLGetString(plcolor
),ds_cmap
, &color2
)) {
129 XSetForeground(ds_dpy
, gc
, color2
.pixel
);
131 if (font
->notFontSet
) {
132 XSetFont(ds_dpy
, gc
, font
->font
.normal
->fid
);
133 XDrawString(ds_dpy
, drawbuffer
, gc
, x
,font
->y
, text
, length
);
135 XmbDrawString(ds_dpy
, drawbuffer
, font
->font
.set
, gc
, x
-1, y
-1 + font
->y
,
142 plcolor = PLGetArrayElement(pl, 6);
143 parse_xcolor(PLGetString(plcolor), &color4);
146 XCopyArea(ds_dpy
, drawbuffer
, d
,gc
,0,0,width
,height
,0,y
-1);
148 XFreePixmap(ds_dpy
, drawbuffer
);
153 WMFreeTypeRImage
*renderChar(FT_Face face
, FT_ULong char_index
, RColor
*color
) {
156 WMFreeTypeRImage
*tmp_data
;
157 int index
, x
, y
, i
, error
; /* error? no no no */
159 tmp_data
= malloc(sizeof(WMFreeTypeRImage
));
161 index
= FT_Get_Char_Index(face
, char_index
);
163 error
= FT_Load_Glyph(face
, index
, FT_LOAD_DEFAULT
);
165 _debug("error loading glyph\n");
168 FT_Render_Glyph(face
->glyph
, ft_render_mode_normal
);
171 bitmap
= &slot
->bitmap
;
172 tmp_data
->advance_x
= slot
->advance
.x
;
173 tmp_data
->advance_y
= slot
->advance
.y
;
174 tmp_data
->top
= slot
->bitmap_top
;
175 tmp_data
->left
= slot
->bitmap_left
;
176 if (bitmap
->width
> 0 && bitmap
->rows
> 0) {
177 tmp_data
->image
= RCreateImage(bitmap
->width
, bitmap
->rows
, True
);
179 else tmp_data
->image
= NULL
;
181 for (y
=0; y
< bitmap
->rows
; y
++) {
182 for (x
=0; x
< bitmap
->width
; x
++) {
183 color
->alpha
= bitmap
->buffer
[y
* bitmap
->width
+ x
];
184 ROperatePixel(tmp_data
->image
,
185 RCopyOperation
, x
, y
, color
);
192 widthOfFreeTypeString (unsigned char *text
, int length
, WPluginData
*func_data
,
193 int *width
, int *height
, int *top
) {
194 WMFreeTypeData
*data
;
198 /* see framewin.c for the order of arguments (look in wPluginPackData) */
199 data
= ((WPluginData
*)func_data
->array
[0])->array
[2]; /* initialized data */
201 if (width
) *width
= 0;
202 if (height
) *height
= data
->face
->size
->metrics
.y_ppem
;
203 /* may finish height & top later if they really are neccessary */
205 /* create temp for drawing */
207 for (i
= 0; i
< length
; i
++) {
208 if (!data
->glyphs_array
[text
[i
]]) {
209 data
->glyphs_array
[text
[i
]] = renderChar(data
->face
, (FT_ULong
)text
[i
], &data
->color
);
210 data
->glyphs_shadow_array
[text
[i
]] = renderChar(data
->face
, (FT_ULong
)text
[i
], &black_color
);
212 if (data
->glyphs_array
[text
[i
]])
213 if (data
->glyphs_array
[text
[i
]]->image
) {
214 if (width
) *width
+= data
->glyphs_array
[text
[i
]]->advance_x
>> 6;
220 /* drawFreeTypeString */
221 void initDrawFreeTypeString(proplist_t pl
, WPluginData
*init_data
) {
222 WMFreeTypeData
*data
;
225 _debug("invoke initDrawFreeTypeString with init_data[3] %s\n",
226 init_data
->array
[2]);
227 _debug("%x is ds_dpy\n", ds_dpy
);
228 initDrawPlainString((Display
*)init_data
->array
[0], (Colormap
*)init_data
->array
[1]);
229 _debug("then %x is ds_dpy\n", ds_dpy
);
231 /* set init_data[2] to array of RImage */
234 * this would better to have sharable font system but
235 * I want to see this more in WINGs though -- ]d
237 init_data
->array
[2] = malloc(sizeof(WMFreeTypeData
));
238 data
= init_data
->array
[2];
239 getColor(PLGetString(PLGetArrayElement(pl
, 3)), ds_cmap
, &xcolor
);
240 data
->color
.red
= xcolor
.red
>> 8;
241 data
->color
.green
= xcolor
.green
>> 8;
242 data
->color
.blue
= xcolor
.blue
>> 8;
244 data
->glyphs_array
= malloc(sizeof(WMFreeTypeRImage
*) * MAX_GLYPHS
);
245 memset(data
->glyphs_array
, 0, sizeof(WMFreeTypeRImage
*) * MAX_GLYPHS
);
246 data
->glyphs_shadow_array
= malloc(sizeof(WMFreeTypeRImage
*) * MAX_GLYPHS
);
247 memset(data
->glyphs_shadow_array
, 0, sizeof(WMFreeTypeRImage
*) * MAX_GLYPHS
);
248 data
->strwidth
= widthOfFreeTypeString
;
251 RContextAttributes rcattr
;
253 rcattr
.flags
= RC_RenderMode
| RC_ColorsPerChannel
;
254 rcattr
.render_mode
= RDitheredRendering
;
255 rcattr
.colors_per_channel
= 4;
257 rc
= RCreateContext(ds_dpy
, DefaultScreen(ds_dpy
), &rcattr
);
260 /* case 1 -- no no case 2 yet :P */
261 if (!inst_ft_library
) {
262 FT_Init_FreeType(&ft_library
);
266 FT_New_Face(ft_library
, PLGetString(PLGetArrayElement(pl
, 4)), 0, &data
->face
);
267 FT_Set_Pixel_Sizes(data
->face
, 0, atoi(PLGetString(PLGetArrayElement(pl
, 5))));
268 _debug("initialize freetype library %d %d %d\n", ft_library
, data
->face
, inst_ft_library
);
272 destroyDrawFreeTypeString(proplist_t pl
, WPluginData
*func_data
) {
273 int i
; /* error? no no no */
274 WMFreeTypeData
*data
;
276 data
= (WMFreeTypeData
*) func_data
->array
[2];
277 for (i
= 0; i
< MAX_GLYPHS
; i
++) {
278 if (data
->glyphs_array
[i
]) {
279 if (data
->glyphs_array
[i
]->image
)
280 RDestroyImage(data
->glyphs_array
[i
]->image
);
281 free(data
->glyphs_array
[i
]);
283 if (data
->glyphs_shadow_array
[i
]) {
284 if (data
->glyphs_shadow_array
[i
]->image
)
285 RDestroyImage(data
->glyphs_shadow_array
[i
]->image
);
286 free(data
->glyphs_shadow_array
[i
]);
289 free(data
->glyphs_array
);
290 free(data
->glyphs_shadow_array
);
291 _debug("destroy freetype library %d %d %d\n", ft_library
, data
->face
, inst_ft_library
);
292 FT_Done_Face(data
->face
);
295 if (!inst_ft_library
) FT_Done_FreeType(ft_library
);
299 logicalCombineArea(RImage
*bg
, RImage
*image
,
312 if (_dx + _sw > bg->width) {
313 _sw = bg->width - _dx;
322 if (_dy + _sh > bg->height) {
323 _sh = bg->height - _dy;
327 if (_sh
> 0 && _sw
> 0) {
329 RCombineAreaWithOpaqueness(bg
, image
, _sx
, _sy
,
330 _sw
, _sh
, _dx
, _dy
, opaquueness
);
332 RCombineArea(bg
, image
, _sx
, _sy
,
340 drawFreeTypeString (proplist_t pl
, Drawable d
,
342 unsigned char *text
, int length
, WPluginData
*func_data
) {
343 WMFreeTypeData
*data
;
345 int i
, j
, width
, height
;
348 int xwidth
, xheight
, dummy
;
351 /* see framewin.c for the order of arguments (look in wPluginPackData) */
352 data
= ((WPluginData
*)func_data
->array
[0])->array
[2]; /* initialized data */
353 if (func_data
->array
[1])
354 pixmap
= *(Pixmap
*)func_data
->array
[1];
355 gc
= *(GC
*)func_data
->array
[2];
356 width
= *(int *)func_data
->array
[4];
357 height
= *(int *)func_data
->array
[5];
360 /* create temp for drawing */
361 if (!func_data
->array
[1]) {
362 XGetGeometry(ds_dpy
, d
, &wdummy
, &dummy
, &dummy
, &xwidth
, &xheight
, &dummy
, &dummy
);
363 pixmap
= XCreatePixmap(ds_dpy
, d
, xwidth
, xheight
, DefaultDepth(ds_dpy
, DefaultScreen(ds_dpy
)));
364 XClearWindow(ds_dpy
, d
);
365 XCopyArea(ds_dpy
, d
, pixmap
, gc
, 0, 0, xwidth
, xheight
, 0, 0);
366 rimg
= RCreateImageFromDrawable(rc
, pixmap
, None
);
367 XFreePixmap(ds_dpy
, pixmap
);
369 rimg
= RCreateImageFromDrawable(rc
, pixmap
, None
);
373 for (i
= 0, j
= x
; i
< strlen(text
); i
++) {
374 if (!data
->glyphs_array
[text
[i
]]) {
375 data
->glyphs_array
[text
[i
]] = renderChar(data
->face
, (FT_ULong
)text
[i
], &data
->color
);
376 data
->glyphs_shadow_array
[text
[i
]] = renderChar(data
->face
, (FT_ULong
)text
[i
], &black_color
);
378 if (data
->glyphs_array
[text
[i
]])
379 if (data
->glyphs_array
[text
[i
]]->image
) {
380 int _dx
, _dy
, _sw
, _sh
;
382 _dx
= j
+ data
->glyphs_array
[text
[i
]]->left
;
383 _dy
= (height
+ data
->face
->size
->metrics
.y_ppem
)/2 -
384 data
->glyphs_array
[text
[i
]]->top
;
385 _sw
= data
->glyphs_array
[text
[i
]]->image
->width
;
386 _sh
= data
->glyphs_array
[text
[i
]]->image
->height
;
388 logicalCombineArea(rimg
, data
->glyphs_shadow_array
[text
[i
]]->image
,
389 0, 0, _sw
, _sh
, _dx
-2, _dy
+2, 100);
390 logicalCombineArea(rimg
, data
->glyphs_array
[text
[i
]]->image
,
391 0, 0, _sw
, _sh
, _dx
-3, _dy
+1, 0);
393 j
+= data
->glyphs_array
[text
[i
]]->advance_x
>> 6;
397 RConvertImage(rc
, rimg
, &pixmap
);
398 XCopyArea(ds_dpy
, pixmap
, d
, gc
, 0, 0, rimg
->width
, height
, 0, y
);
399 XFreePixmap(ds_dpy
, pixmap
);
405 #endif /* USE_FREETYPE */
410 destroyDrawString (proplist_t pl
, WPluginData
*init_data
) {
411 if (strcmp(PLGetString(PLGetArrayElement(pl
, 2)), "drawPlainString") == 0)
412 destroyDrawPlainString((Display
*)init_data
->array
[0], NULL
);
413 else if (strcmp(PLGetString(PLGetArrayElement(pl
, 2)), "drawFreeTypeString") == 0)
414 destroyDrawFreeTypeString(pl
, init_data
);
419 widthOfString (unsigned char *text
, int length
, WPluginData
*func_data
,
420 int *width
, int *height
, int *top
) {
421 WMFreeTypeData
*data
;
423 data
= ((WPluginData
*)func_data
->array
[0])->array
[2];
424 data
->strwidth(text
, length
, func_data
, width
, height
, top
);
429 initDrawString (proplist_t pl
, WPluginData
*init_data
) {
430 _debug("invoke initDrawString: %s\n", PLGetString(PLGetArrayElement(pl
, 2)));
431 if (strcmp(PLGetString(PLGetArrayElement(pl
, 2)), "drawPlainString") == 0)
432 initDrawPlainString((Display
*)init_data
->array
[0], (Colormap
*)init_data
->array
[1]);
434 else if (strcmp(PLGetString(PLGetArrayElement(pl
, 2)), "drawFreeTypeString") == 0)
435 initDrawFreeTypeString(pl
, init_data
);
437 _debug("finish initDrawString\n");