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
;
40 /* will use this when we have frame window plugin */
41 /* char *last_titlestr; */
43 #endif /* USE_FREETYPE */
45 int getColor (const char *string
, Colormap cmap
, XColor
*xcolor
) {
46 if (!XParseColor (ds_dpy
, cmap
, string
, xcolor
)) {
49 if (!XAllocColor (ds_dpy
, cmap
, xcolor
)) {
57 initDrawPlainString(Display
*dpy
, Colormap
*cmap
) {
63 destroyDrawPlainString(proplist_t pl
, void **func_data
) {
68 drawPlainString (proplist_t pl
, Drawable d
,
69 int x
, int y
, unsigned width
, unsigned height
,
70 char *text
, void **func_data
)
72 XColor color1
, color2
, color3
, color4
;
80 length
= strlen(text
);
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
);
191 /* drawFreeTypeString */
192 void initDrawFreeTypeString(proplist_t pl
, void **init_data
) {
193 WMFreeTypeData
*data
;
196 _debug("invoke initDrawFreeTypeString with init_data[3] %s\n", init_data
[3]);
198 _debug("%x is ds_dpy\n", ds_dpy
);
199 initDrawPlainString((Display
*)init_data
[1], (Colormap
*)init_data
[2]);
200 _debug("then %x is ds_dpy\n", ds_dpy
);
202 /* set init_data[2] to array of RImage */
205 * this would better to have sharable font system but
206 * I want to see this more in WINGs though -- ]d
208 init_data
[3] = malloc(sizeof(WMFreeTypeData
));
210 getColor(PLGetString(PLGetArrayElement(pl
, 3)), ds_cmap
, &xcolor
);
211 data
->color
.red
= xcolor
.red
>> 8;
212 data
->color
.green
= xcolor
.green
>> 8;
213 data
->color
.blue
= xcolor
.blue
>> 8;
215 data
->glyphs_array
= malloc(sizeof(WMFreeTypeRImage
*) * MAX_GLYPHS
);
216 memset(data
->glyphs_array
, 0, sizeof(WMFreeTypeRImage
*) * MAX_GLYPHS
);
217 data
->glyphs_shadow_array
= malloc(sizeof(WMFreeTypeRImage
*) * MAX_GLYPHS
);
218 memset(data
->glyphs_shadow_array
, 0, sizeof(WMFreeTypeRImage
*) * MAX_GLYPHS
);
221 RContextAttributes rcattr
;
223 rcattr
.flags
= RC_RenderMode
| RC_ColorsPerChannel
;
224 rcattr
.render_mode
= RDitheredRendering
;
225 rcattr
.colors_per_channel
= 4;
227 rc
= RCreateContext(ds_dpy
, DefaultScreen(ds_dpy
), &rcattr
);
230 /* case 1 -- no no case 2 yet :P */
231 if (!inst_ft_library
) {
232 FT_Init_FreeType(&ft_library
);
236 FT_New_Face(ft_library
, PLGetString(PLGetArrayElement(pl
, 4)), 0, &data
->face
);
237 FT_Set_Pixel_Sizes(data
->face
, 0, atoi(PLGetString(PLGetArrayElement(pl
, 5))));
238 _debug("initialize freetype library %d %d %d\n", ft_library
, data
->face
, inst_ft_library
);
242 destroyDrawFreeTypeString(proplist_t pl
, void **func_data
) {
243 int i
; /* error? no no no */
244 WMFreeTypeData
*data
;
246 data
= (WMFreeTypeData
*) func_data
[3];
247 for (i
= 0; i
< MAX_GLYPHS
; i
++) {
248 if (data
->glyphs_array
[i
]) {
249 if (data
->glyphs_array
[i
]->image
)
250 RDestroyImage(data
->glyphs_array
[i
]->image
);
251 free(data
->glyphs_array
[i
]);
253 if (data
->glyphs_shadow_array
[i
]) {
254 if (data
->glyphs_shadow_array
[i
]->image
)
255 RDestroyImage(data
->glyphs_shadow_array
[i
]->image
);
256 free(data
->glyphs_shadow_array
[i
]);
259 free(data
->glyphs_array
);
260 free(data
->glyphs_shadow_array
);
261 _debug("destroy freetype library %d %d %d\n", ft_library
, data
->face
, inst_ft_library
);
262 FT_Done_Face(data
->face
);
265 if (!inst_ft_library
) FT_Done_FreeType(ft_library
);
269 logicalCombineArea(RImage
*bg
, RImage
*image
,
282 if (_dx + _sw > bg->width) {
283 _sw = bg->width - _dx;
292 if (_dy + _sh > bg->height) {
293 _sh = bg->height - _dy;
297 if (_sh
> 0 && _sw
> 0) {
299 RCombineAreaWithOpaqueness(bg
, image
, _sx
, _sy
,
300 _sw
, _sh
, _dx
, _dy
, opaquueness
);
302 RCombineArea(bg
, image
, _sx
, _sy
,
309 drawFreeTypeString (proplist_t pl
, Drawable d
,
311 unsigned char *text
, int length
, void **func_data
) {
312 WMFreeTypeData
*data
;
314 int i
, j
, width
, height
;
317 int xwidth
, xheight
, dummy
;
320 /* see framewin.c for the order of arguments (look in wPluginPackData) */
321 data
= ((void **)func_data
[1])[3]; /* initialized data */
323 pixmap
= *(Pixmap
*)func_data
[2];
324 gc
= *(GC
*)func_data
[3];
325 width
= *(int *)func_data
[5];
326 height
= *(int *)func_data
[6];
329 /* create temp for drawing */
331 XGetGeometry(ds_dpy
, d
, &wdummy
, &dummy
, &dummy
, &xwidth
, &xheight
, &dummy
, &dummy
);
332 pixmap
= XCreatePixmap(ds_dpy
, d
, xwidth
, xheight
, DefaultDepth(ds_dpy
, DefaultScreen(ds_dpy
)));
333 XClearWindow(ds_dpy
, d
);
334 XCopyArea(ds_dpy
, d
, pixmap
, gc
, 0, 0, xwidth
, xheight
, 0, 0);
335 rimg
= RCreateImageFromDrawable(rc
, pixmap
, None
);
336 XFreePixmap(ds_dpy
, pixmap
);
338 rimg
= RCreateImageFromDrawable(rc
, pixmap
, None
);
342 for (i
= 0, j
= x
; i
< strlen(text
); i
++) {
343 if (!data
->glyphs_array
[text
[i
]]) {
344 data
->glyphs_array
[text
[i
]] = renderChar(data
->face
, (FT_ULong
)text
[i
], &data
->color
);
345 data
->glyphs_shadow_array
[text
[i
]] = renderChar(data
->face
, (FT_ULong
)text
[i
], &black_color
);
347 if (data
->glyphs_array
[text
[i
]])
348 if (data
->glyphs_array
[text
[i
]]->image
) {
349 int _dx
, _dy
, _sw
, _sh
;
351 _dx
= j
+ data
->glyphs_array
[text
[i
]]->left
;
352 _dy
= (height
+ data
->face
->size
->metrics
.y_ppem
)/2 -
353 data
->glyphs_array
[text
[i
]]->top
;
354 _sw
= data
->glyphs_array
[text
[i
]]->image
->width
;
355 _sh
= data
->glyphs_array
[text
[i
]]->image
->height
;
357 logicalCombineArea(rimg
, data
->glyphs_shadow_array
[text
[i
]]->image
,
358 0, 0, _sw
, _sh
, _dx
-2, _dy
+2, 100);
359 logicalCombineArea(rimg
, data
->glyphs_array
[text
[i
]]->image
,
360 0, 0, _sw
, _sh
, _dx
-3, _dy
+1, 0);
362 j
+= data
->glyphs_array
[text
[i
]]->advance_x
>> 6;
366 RConvertImage(rc
, rimg
, &pixmap
);
367 XCopyArea(ds_dpy
, pixmap
, d
, gc
, 0, 0, rimg
->width
, height
, 0, y
);
368 XFreePixmap(ds_dpy
, pixmap
);
372 _debug("%d\n", height);
373 i = (height + data->face->size->metrics.y_ppem)/2 - data->face->size->metrics.y_ppem;
374 XDrawLine(ds_dpy, d, gc, 5, y + i, 100, y + data->face->size->metrics.y_ppem);
375 XDrawLine(ds_dpy, d, gc, 100, y + i, 5, y + data->face->size->metrics.y_ppem);
381 #endif /* USE_FREETYPE */
386 destroyDrawString (proplist_t pl
, void **init_data
) {
387 if (strcmp(PLGetString(PLGetArrayElement(pl
, 2)), "drawPlainString") == 0)
388 destroyDrawPlainString((Display
*)init_data
[0], NULL
);
389 else if (strcmp(PLGetString(PLGetArrayElement(pl
, 2)), "drawFreeTypeString") == 0)
390 destroyDrawFreeTypeString(pl
, init_data
);
394 initDrawString (proplist_t pl
, void **init_data
) {
395 _debug("invoke initDrawString: %s\n", PLGetString(PLGetArrayElement(pl
, 2)));
396 if (strcmp(PLGetString(PLGetArrayElement(pl
, 2)), "drawPlainString") == 0)
397 initDrawPlainString((Display
*)init_data
[1], (Colormap
*)init_data
[2]);
399 else if (strcmp(PLGetString(PLGetArrayElement(pl
, 2)), "drawFreeTypeString") == 0)
400 initDrawFreeTypeString(pl
, init_data
);
402 _debug("finish initDrawString\n");