fix fix
[wmaker-crm.git] / plugins / libwmfun / drawstring.c
blobba02d37666547f2c2c9cbd683afdd5d8ed3fe71a
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 /* will use this when we have frame window plugin */
41 /* char *last_titlestr; */
42 } WMFreeTypeData;
43 #endif /* USE_FREETYPE */
45 int getColor (const char *string, Colormap cmap, XColor *xcolor) {
46 if (!XParseColor (ds_dpy, cmap, string, xcolor)) {
47 return 0;
49 if (!XAllocColor (ds_dpy, cmap, xcolor)) {
50 return 0;
53 return 1;
56 void
57 initDrawPlainString(Display *dpy, Colormap *cmap) {
58 ds_dpy = dpy;
59 ds_cmap = *cmap;
62 void
63 destroyDrawPlainString(proplist_t pl, void **func_data) {
64 return;
67 void
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;
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[0];
82 font = func_data[1];
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 /* drawFreeTypeString */
192 void initDrawFreeTypeString(proplist_t pl, void **init_data) {
193 WMFreeTypeData *data;
194 XColor xcolor;
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));
209 data = init_data[3];
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);
220 if (!rc) {
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);
234 inst_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);
241 void
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);
263 free(data);
264 inst_ft_library--;
265 if (!inst_ft_library) FT_Done_FreeType(ft_library);
268 void
269 logicalCombineArea(RImage *bg, RImage *image,
270 int _sx, int _sy,
271 int _sw, int _sh,
272 int _dx, int _dy,
273 int opaquueness) {
276 if (_dx < 0) {
277 _sx = -_dx;
278 _sw = _sw + _dx;
279 _dx = 0;
282 if (_dx + _sw > bg->width) {
283 _sw = bg->width - _dx;
286 if (_dy < 0) {
287 _sy = -_dy;
288 _sh = _sh + _dy;
289 _dy = 0;
292 if (_dy + _sh > bg->height) {
293 _sh = bg->height - _dy;
297 if (_sh > 0 && _sw > 0) {
298 if (opaquueness) {
299 RCombineAreaWithOpaqueness(bg, image, _sx, _sy,
300 _sw, _sh, _dx, _dy, opaquueness);
301 } else {
302 RCombineArea(bg, image, _sx, _sy,
303 _sw, _sh, _dx, _dy);
308 void
309 drawFreeTypeString (proplist_t pl, Drawable d,
310 int x, int y,
311 unsigned char *text, int length, void **func_data) {
312 WMFreeTypeData *data;
313 RImage *rimg;
314 int i, j, width, height;
315 Pixmap pixmap;
316 GC gc;
317 int xwidth, xheight, dummy;
318 Window wdummy;
320 /* see framewin.c for the order of arguments (look in wPluginPackData) */
321 data = ((void **)func_data[1])[3]; /* initialized data */
322 if (func_data[2])
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 */
330 if (!func_data[2]) {
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);
337 } else {
338 rimg = RCreateImageFromDrawable(rc, pixmap, None);
341 if (rimg) {
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);
369 RDestroyImage(rimg);
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 */
383 /* core */
385 void
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);
393 void
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]);
398 #ifdef USE_FREETYPE
399 else if (strcmp(PLGetString(PLGetArrayElement(pl, 2)), "drawFreeTypeString") == 0)
400 initDrawFreeTypeString(pl, init_data);
401 #endif
402 _debug("finish initDrawString\n");