small fixes.
[wmaker-crm.git] / plugins / libwmfun / drawstring.c
blobfc18616b1e30674104e2f9c754e183ca821a0f8e
1 #include <proplist.h>
2 #include <WINGs.h>
3 #include <WINGsP.h>
4 #include "generic.h"
6 #ifdef USE_FREETYPE
7 #include <freetype/freetype.h>
8 #endif
10 #define MAX_GLYPHS 256
12 #define _debug(f...) {fprintf(stderr, "debug: ");fprintf(stderr, ##f);fflush(stderr);}
14 /* #define _debug(s) printf(s);*/
16 /* drawPlainString */
17 static Display *ds_dpy = 0;
18 static Colormap ds_cmap;
19 static RContext *rc = 0;
21 RColor black_color = {0, 0, 0, 0};
23 #ifdef USE_FREETYPE
24 FT_Library ft_library;
25 static int inst_ft_library = 0;
27 typedef struct __FreeTypeRImage{
28 RImage *image;
29 int advance_x;
30 int advance_y;
31 int left;
32 int top;
33 } WMFreeTypeRImage;
35 typedef struct __FreeTypeData{
36 FT_Face face;
37 RColor color;
38 WMFreeTypeRImage **glyphs_array;
39 WMFreeTypeRImage **glyphs_shadow_array;
40 void (*strwidth)();
41 } WMFreeTypeData;
42 #endif /* USE_FREETYPE */
44 int getColor (const char *string, Colormap cmap, XColor *xcolor) {
45 if (!XParseColor (ds_dpy, cmap, string, xcolor)) {
46 return 0;
48 if (!XAllocColor (ds_dpy, cmap, xcolor)) {
49 return 0;
52 return 1;
55 void
56 initDrawPlainString(Display *dpy, Colormap *cmap) {
57 ds_dpy = dpy;
58 ds_cmap = *cmap;
61 void
62 destroyDrawPlainString(proplist_t pl, WPluginData *func_data) {
63 return;
66 /* FIX FIX FIX */
67 void
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;
73 char *plcolor;
74 int i, length;
75 static int g;
76 Pixmap drawbuffer;
77 GC gc;
78 WMFont *font;
80 length = strlen(text);
81 gc = func_data->array[2];
82 font = func_data->array[3];
86 printf("%d members\n",PLGetNumberOfElements(pl));
87 for (i =0;i<7;i++) {
88 printf("%d %s\n",i,PLGetString(PLGetArrayElement(pl,i)));
90 return;
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);
104 } else {
105 XmbDrawString(ds_dpy, drawbuffer, font->font.set, gc, x+4, y+4 + font->y,
106 text, length);
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);
119 } else {
120 XmbDrawString(ds_dpy, drawbuffer, font->font.set, gc, x, y + font->y,
121 text, length);
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);
134 } else {
135 XmbDrawString(ds_dpy, drawbuffer, font->font.set, gc, x-1, y-1 + font->y,
136 text, length);
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);
151 #ifdef USE_FREETYPE
153 WMFreeTypeRImage *renderChar(FT_Face face, FT_ULong char_index, RColor *color) {
154 FT_GlyphSlot slot;
155 FT_Bitmap* bitmap;
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);
164 if (error) {
165 _debug("error loading glyph\n");
166 return NULL;
168 FT_Render_Glyph(face->glyph, ft_render_mode_normal);
170 slot = face->glyph;
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);
188 return tmp_data;
191 void
192 widthOfFreeTypeString (unsigned char *text, int length, WPluginData *func_data,
193 int *width, int *height, int *top) {
194 WMFreeTypeData *data;
195 RImage *rimg;
196 int i;
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 */
206 if (text)
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;
223 XColor xcolor;
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;
250 if (!rc) {
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);
264 inst_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);
271 void
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);
293 free(data);
294 inst_ft_library--;
295 if (!inst_ft_library) FT_Done_FreeType(ft_library);
298 void
299 logicalCombineArea(RImage *bg, RImage *image,
300 int _sx, int _sy,
301 int _sw, int _sh,
302 int _dx, int _dy,
303 int opaquueness) {
306 if (_dx < 0) {
307 _sx = -_dx;
308 _sw = _sw + _dx;
309 _dx = 0;
312 if (_dx + _sw > bg->width) {
313 _sw = bg->width - _dx;
316 if (_dy < 0) {
317 _sy = -_dy;
318 _sh = _sh + _dy;
319 _dy = 0;
322 if (_dy + _sh > bg->height) {
323 _sh = bg->height - _dy;
327 if (_sh > 0 && _sw > 0) {
328 if (opaquueness) {
329 RCombineAreaWithOpaqueness(bg, image, _sx, _sy,
330 _sw, _sh, _dx, _dy, opaquueness);
331 } else {
332 RCombineArea(bg, image, _sx, _sy,
333 _sw, _sh, _dx, _dy);
339 void
340 drawFreeTypeString (proplist_t pl, Drawable d,
341 int x, int y,
342 unsigned char *text, int length, WPluginData *func_data) {
343 WMFreeTypeData *data;
344 RImage *rimg;
345 int i, j, width, height;
346 Pixmap pixmap;
347 GC gc;
348 int xwidth, xheight, dummy;
349 Window wdummy;
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);
368 } else {
369 rimg = RCreateImageFromDrawable(rc, pixmap, None);
372 if (rimg) {
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);
400 RDestroyImage(rimg);
405 #endif /* USE_FREETYPE */
407 /* core */
409 void
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);
417 #ifdef USE_FREETYPE
418 void
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);
426 #endif
428 void
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]);
433 #ifdef USE_FREETYPE
434 else if (strcmp(PLGetString(PLGetArrayElement(pl, 2)), "drawFreeTypeString") == 0)
435 initDrawFreeTypeString(pl, init_data);
436 #endif
437 _debug("finish initDrawString\n");