NEWS/Changelog for previous commit.
[fvwm.git] / libs / Fft.c
blob8b364f9c1aa16bdb5303dc8863f59e4d22b695de
1 /* -*-c-*- */
2 /* This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 /* ---------------------------- included header files ---------------------- */
19 #include "config.h"
21 #include <stdio.h>
23 #include <X11/Xlib.h>
25 #include "fvwmlib.h"
26 #include "wild.h"
27 #include "Strings.h"
28 #include "Flocale.h"
29 #include "Fft.h"
30 #include "FlocaleCharset.h"
31 #include "FftInterface.h"
32 #include "FRenderInit.h"
33 #include "PictureBase.h"
35 /* ---------------------------- local definitions -------------------------- */
37 /* ---------------------------- local macros ------------------------------- */
39 #define FFT_SET_ROTATED_90_MATRIX(m) \
40 ((m)->xx = (m)->yy = 0, (m)->xy = 1, (m)->yx = -1)
42 #define FFT_SET_ROTATED_270_MATRIX(m) \
43 ((m)->xx = (m)->yy = 0, (m)->xy = -1, (m)->yx = 1)
45 #define FFT_SET_ROTATED_180_MATRIX(m) \
46 ((m)->xx = (m)->yy = -1, (m)->xy = (m)->yx = 0)
48 /* ---------------------------- imports ------------------------------------ */
50 /* ---------------------------- included code files ------------------------ */
52 /* ---------------------------- local types -------------------------------- */
54 /* ---------------------------- forward declarations ----------------------- */
56 /* ---------------------------- local variables ---------------------------- */
58 static Display *fftdpy = NULL;
59 static int fftscreen;
60 static int fft_initialized = False;
62 /* ---------------------------- exported variables (globals) --------------- */
64 /* ---------------------------- local functions ---------------------------- */
66 static
67 void init_fft(Display *dpy)
69 fftdpy = dpy;
70 fftscreen = DefaultScreen(dpy);
71 fft_initialized = True;
74 static
75 FftChar16 *FftUtf8ToFftString16(unsigned char *str, int len, int *nl)
77 FftChar16 *new;
78 int i = 0, j= 0;
80 new = (FftChar16 *)safemalloc((len+1)*sizeof(FftChar16));
81 while(i < len && str[i] != 0)
83 if (str[i] <= 0x7f)
85 new[j] = str[i];
87 else if (str[i] <= 0xdf && i+1 < len)
89 new[j] = ((str[i] & 0x1f) << 6) + (str[i+1] & 0x3f);
90 i++;
92 else if (i+2 < len)
94 new[j] = ((str[i] & 0x0f) << 12) +
95 ((str[i+1] & 0x3f) << 6) +
96 (str[i+2] & 0x3f);
97 i += 2;
99 i++; j++;
101 *nl = j;
102 return new;
105 static
106 void FftSetupEncoding(
107 Display *dpy, FftFontType *fftf, char *encoding, char *module)
109 FlocaleCharset *fc;
111 if (!FftSupport || fftf == NULL)
112 return;
114 fftf->encoding = NULL;
115 fftf->str_encoding = NULL;
117 if (encoding != NULL)
119 fftf->str_encoding = encoding;
121 if (FftSupportUseXft2)
123 if (encoding != NULL)
125 fftf->encoding = encoding;
127 else if ((fc =
128 FlocaleCharsetGetDefaultCharset(dpy,NULL)) != NULL &&
129 StrEquals(fc->x,FLC_FFT_ENCODING_ISO8859_1))
131 fftf->encoding = FLC_FFT_ENCODING_ISO8859_1;
133 else
135 fftf->encoding = FLC_FFT_ENCODING_ISO10646_1;
138 else if (FftSupport)
140 int i = 0;
141 FftPatternElt *e;
142 Fft1Font *f;
144 f = (Fft1Font *)fftf->fftfont;
145 while(i < f->pattern->num)
147 e = &f->pattern->elts[i];
148 if (StrEquals(e->object, FFT_ENCODING) &&
149 e->values->value.u.s != NULL)
151 fftf->encoding = e->values->value.u.s;
152 return;
154 i++;
159 static
160 FftFont *FftGetRotatedFont(
161 Display *dpy, FftFont *f, rotation_t rotation)
163 FftPattern *rotated_pat;
164 FftMatrix r,b;
165 FftMatrix *pm = NULL;
166 FftFont *rf = NULL;
168 if (f == NULL)
169 return NULL;
171 rotated_pat = FftPatternDuplicate(f->pattern);
173 if (rotated_pat == NULL)
175 return NULL;
178 if (rotation == ROTATION_90)
180 FFT_SET_ROTATED_90_MATRIX(&r);
182 else if (rotation == ROTATION_180)
184 FFT_SET_ROTATED_180_MATRIX(&r);
186 else if (rotation == ROTATION_270)
188 FFT_SET_ROTATED_270_MATRIX(&r);
190 else
192 goto bail;
195 if ((FftPatternGetMatrix(
196 rotated_pat, FFT_MATRIX, 0, &pm) == FftResultMatch) && pm)
198 /* rotate the matrice */
199 b.xx = r.xx * pm->xx + r.xy * pm->yx;
200 b.xy = r.xx * pm->xy + r.xy * pm->yy;
201 b.yx = r.yx * pm->xx + r.yy * pm->yx;
202 b.yy = r.yx * pm->xy + r.yy * pm->yy;
204 else
206 b.xx = r.xx;
207 b.xy = r.xy;
208 b.yx = r.yx;
209 b.yy = r.yy;
211 if (FftPatternDel(rotated_pat, FFT_MATRIX))
213 /* nothing */
215 if (!FftPatternAddMatrix(rotated_pat, FFT_MATRIX, &b))
217 goto bail;
219 rf = FftFontOpenPattern(dpy, rotated_pat);
221 bail:
222 if (!rf && rotated_pat)
224 FftPatternDestroy(rotated_pat);
226 return rf;
229 void FftPDumyFunc(void)
233 /* ---------------------------- interface functions ------------------------ */
235 void FftGetFontHeights(
236 FftFontType *fftf, int *height, int *ascent, int *descent)
238 /* fft font height may be > fftfont->ascent + fftfont->descent, this
239 * depends on the minspace value */
240 *height = fftf->fftfont->height;
241 *ascent = fftf->fftfont->ascent;
242 *descent = fftf->fftfont->descent;
244 return;
247 void FftGetFontWidths(
248 FlocaleFont *flf, int *max_char_width)
250 FGlyphInfo extents;
252 /* FIXME: max_char_width should not be use in the all fvwm! */
253 if (FftUtf8Support && FLC_ENCODING_TYPE_IS_UTF_8(flf->fc))
255 FftTextExtentsUtf8(fftdpy, flf->fftf.fftfont, (FftChar8*)"W",
256 1, &extents);
258 else
260 FftTextExtents8(fftdpy, flf->fftf.fftfont, (FftChar8*)"W", 1,
261 &extents);
263 *max_char_width = extents.xOff;
265 return;
268 FftFontType *FftGetFont(Display *dpy, char *fontname, char *module)
270 FftFont *fftfont = NULL;
271 FftFontType *fftf = NULL;
272 char *fn = NULL, *str_enc = NULL;
273 FlocaleCharset *fc;
274 FftPattern *src_pat = NULL, *load_pat = NULL;
275 FftMatrix *a = NULL;
276 FftResult result;
278 result = 0;
279 if (!FftSupport || !(FRenderGetExtensionSupported() || 1))
281 return NULL;
283 if (!fontname)
285 return NULL;
287 if (!fft_initialized)
289 init_fft(dpy);
291 /* Xft2 always load an USC-4 fonts, that we consider as an USC-2 font
292 * (i.e., an ISO106464-1 font) or an ISO8859-1 if the user ask for this
293 * or the locale charset is ISO8859-1.
294 * Xft1 support ISO106464-1, ISO8859-1 and others we load an
295 * ISO8859-1 font by default if the locale charset is ISO8859-1 and
296 * an ISO106464-1 one if this not the case */
297 if (matchWildcards("*?8859-1*", fontname))
299 str_enc = FLC_FFT_ENCODING_ISO8859_1;
301 else if (matchWildcards("*?10646-1*", fontname))
303 str_enc = FLC_FFT_ENCODING_ISO10646_1;
305 if (!FftSupportUseXft2 && str_enc == NULL)
307 if ((fc = FlocaleCharsetGetFLCXOMCharset()) != NULL &&
308 StrEquals(fc->x,FLC_FFT_ENCODING_ISO8859_1))
310 fn = CatString2(fontname,":encoding=ISO8859-1");
312 else
314 fn = CatString2(fontname,":encoding=ISO10646-1");
317 else
319 fn = fontname;
321 if ((src_pat = FftNameParse(fn)) == NULL)
323 goto bail;
325 if ((load_pat = FftFontMatch(dpy, fftscreen, src_pat, &result)) == NULL)
327 goto bail;
329 /* safety check */
330 if (FftPatternGetMatrix(
331 load_pat, FFT_MATRIX, 0, &a) == FftResultMatch && a)
333 FftMatrix b;
334 Bool cm = False;
336 if (a->xx < 0)
338 a->xx = -a->xx;
339 cm = True;
341 if (a->yx != 0)
343 a->yx = 0;
344 cm = True;
346 if (cm)
348 b.xx = a->xx;
349 b.xy = a->xy;
350 b.yx = a->yx;
351 b.yy = a->yy;
352 if (FftPatternDel(load_pat, FFT_MATRIX))
354 /* nothing */
356 if (!FftPatternAddMatrix(load_pat, FFT_MATRIX, &b))
358 goto bail;
362 /* FIXME: other safety checking ? */
363 fftfont = FftFontOpenPattern(dpy, load_pat);
365 if (!fftfont)
367 goto bail;
369 fftf = (FftFontType *)safemalloc(sizeof(FftFontType));
370 fftf->fftfont = fftfont;
371 fftf->fftfont_rotated_90 = NULL;
372 fftf->fftfont_rotated_180 = NULL;
373 fftf->fftfont_rotated_270 = NULL;
374 FftSetupEncoding(dpy, fftf, str_enc, module);
376 bail:
377 if (src_pat)
379 FftPatternDestroy(src_pat);
381 if (!fftf && load_pat)
383 FftPatternDestroy(load_pat);
385 return fftf;
388 void FftDrawString(
389 Display *dpy, FlocaleFont *flf, FlocaleWinString *fws,
390 Pixel fg, Pixel fgsh, Bool has_fg_pixels, int len, unsigned long flags)
392 FftDraw *fftdraw = NULL;
393 typedef void (*DrawStringFuncType)(
394 FftDraw *fftdraw, FftColor *fft_fg, FftFont *uf, int xt,
395 int yt, char *str, int len);
396 DrawStringFuncType DrawStringFunc;
397 char *str;
398 Bool free_str = False;
399 XGCValues vr;
400 XColor xfg, xfgsh;
401 FftColor fft_fg, fft_fgsh;
402 FftFontType *fftf;
403 FftFont *uf;
404 int x,y, xt,yt;
405 float alpha_factor;
406 flocale_gstp_args gstp_args;
408 if (!FftSupport)
410 return;
413 fftf = &flf->fftf;
414 if (fws->flags.text_rotation == ROTATION_90) /* CW */
416 if (fftf->fftfont_rotated_90 == NULL)
418 fftf->fftfont_rotated_90 =
419 FftGetRotatedFont(dpy, fftf->fftfont,
420 fws->flags.text_rotation);
422 uf = fftf->fftfont_rotated_90;
423 #ifdef FFT_BUGGY_FREETYPE
424 y = fws->y + FftTextWidth(flf, fws->e_str, len);
425 #else
426 y = fws->y;
427 #endif
428 x = fws->x - FLF_SHADOW_BOTTOM_SIZE(flf);
430 else if (fws->flags.text_rotation == ROTATION_180)
432 if (fftf->fftfont_rotated_180 == NULL)
434 fftf->fftfont_rotated_180 =
435 FftGetRotatedFont(dpy, fftf->fftfont,
436 fws->flags.text_rotation);
438 uf = fftf->fftfont_rotated_180;
439 y = fws->y;
440 x = fws->x + FftTextWidth(flf, fws->e_str, len);
442 else if (fws->flags.text_rotation == ROTATION_270)
444 if (fftf->fftfont_rotated_270 == NULL)
446 fftf->fftfont_rotated_270 =
447 FftGetRotatedFont(dpy, fftf->fftfont,
448 fws->flags.text_rotation);
450 uf = fftf->fftfont_rotated_270;
451 #ifdef FFT_BUGGY_FREETYPE
452 y = fws->y;
453 #else
454 y = fws->y + FftTextWidth(flf, fws->e_str, len);
455 #endif
456 x = fws->x - FLF_SHADOW_UPPER_SIZE(flf);
458 else
460 uf = fftf->fftfont;
461 y = fws->y;
462 x = fws->x;
465 if (uf == NULL)
466 return;
468 fftdraw = FftDrawCreate(dpy, (Drawable)fws->win, Pvisual, Pcmap);
469 if (fws->flags.has_clip_region)
471 if (FftDrawSetClip(fftdraw, fws->clip_region) == False)
473 /* just to suppress a compiler warning */
476 if (has_fg_pixels)
478 xfg.pixel = fg;
479 xfgsh.pixel = fgsh;
481 else if (fws->gc &&
482 XGetGCValues(dpy, fws->gc, GCForeground, &vr))
484 xfg.pixel = vr.foreground;
486 else
488 #if 0
489 fprintf(stderr, "[fvwmlibs][FftDrawString]: ERROR --"
490 " cannot find color\n");
491 #endif
492 xfg.pixel = PictureBlackPixel();
495 XQueryColor(dpy, Pcmap, &xfg);
496 alpha_factor = ((fws->flags.has_colorset)?
497 ((float)fws->colorset->fg_alpha_percent/100) : 1);
498 /* Render uses premultiplied alpha */
499 fft_fg.color.red = xfg.red * alpha_factor;
500 fft_fg.color.green = xfg.green * alpha_factor;
501 fft_fg.color.blue = xfg.blue * alpha_factor;
502 fft_fg.color.alpha = 0xffff * alpha_factor;
503 fft_fg.pixel = xfg.pixel;
504 if (flf->shadow_size != 0 && has_fg_pixels)
506 XQueryColor(dpy, Pcmap, &xfgsh);
507 fft_fgsh.color.red = xfgsh.red * alpha_factor;
508 fft_fgsh.color.green = xfgsh.green * alpha_factor;
509 fft_fgsh.color.blue = xfgsh.blue * alpha_factor;
510 fft_fgsh.color.alpha = 0xffff * alpha_factor;
511 fft_fgsh.pixel = xfgsh.pixel;
514 xt = x;
515 yt = y;
517 str = fws->e_str;
518 if (FftUtf8Support && FLC_ENCODING_TYPE_IS_UTF_8(flf->fc))
520 DrawStringFunc = (DrawStringFuncType)FftPDrawStringUtf8;
522 else if (FLC_ENCODING_TYPE_IS_UTF_8(flf->fc))
524 DrawStringFunc = (DrawStringFuncType)FftPDrawString16;
525 str = (char *)FftUtf8ToFftString16(
526 (unsigned char *)fws->e_str, len, &len);
527 free_str = True;
529 else if (FLC_ENCODING_TYPE_IS_USC_2(flf->fc))
531 DrawStringFunc = (DrawStringFuncType)FftPDrawString16;
533 else if (FLC_ENCODING_TYPE_IS_USC_4(flf->fc))
535 DrawStringFunc = (DrawStringFuncType)FftPDrawString32;
537 else
539 DrawStringFunc = (DrawStringFuncType)FftPDrawString8;
542 FlocaleInitGstpArgs(&gstp_args, flf, fws, x, y);
543 if (flf->shadow_size != 0 && has_fg_pixels)
545 while (FlocaleGetShadowTextPosition(&xt, &yt, &gstp_args))
547 DrawStringFunc(
548 fftdraw, &fft_fgsh, uf, xt, yt, str, len);
551 xt = gstp_args.orig_x;
552 yt = gstp_args.orig_y;
553 DrawStringFunc(fftdraw, &fft_fg, uf, xt, yt, str, len);
555 if (free_str && str != NULL)
557 free(str);
559 FftDrawDestroy(fftdraw);
561 return;
564 int FftTextWidth(FlocaleFont *flf, char *str, int len)
566 FGlyphInfo extents;
567 int result = 0;
569 if (!FftSupport)
571 return 0;
573 if (FftUtf8Support && FLC_ENCODING_TYPE_IS_UTF_8(flf->fc))
575 FftTextExtentsUtf8(
576 fftdpy, flf->fftf.fftfont, (FftChar8*)str, len,
577 &extents);
578 result = extents.xOff;
580 else if (FLC_ENCODING_TYPE_IS_UTF_8(flf->fc))
582 FftChar16 *new;
583 int nl;
585 new = FftUtf8ToFftString16((unsigned char *)str, len, &nl);
586 if (new != NULL)
588 FftTextExtents16(
589 fftdpy, flf->fftf.fftfont, new, nl, &extents);
590 result = extents.xOff;
591 free(new);
594 else if (FLC_ENCODING_TYPE_IS_USC_2(flf->fc))
596 FftTextExtents16(
597 fftdpy, flf->fftf.fftfont, (FftChar16 *)str, len,
598 &extents);
599 result = extents.xOff;
601 else if (FLC_ENCODING_TYPE_IS_USC_4(flf->fc))
603 FftTextExtents32(
604 fftdpy, flf->fftf.fftfont, (FftChar32 *)str, len,
605 &extents);
606 result = extents.xOff;
608 else
610 FftTextExtents8(
611 fftdpy, flf->fftf.fftfont, (FftChar8 *)str, len,
612 &extents);
613 result = extents.xOff;
616 return result;
620 void FftPrintPatternInfo(FftFont *f, Bool vertical)
622 /* FftPatternPrint use stdout */
623 fflush (stderr);
624 printf("\n height: %i, ascent: %i, descent: %i, maw: %i\n",
625 f->height, f->ascent, f->descent, f->max_advance_width);
626 if (!vertical)
628 printf(" ");
629 FftPatternPrint(f->pattern);
631 else
633 FftMatrix *pm = NULL;
635 if (FftPatternGetMatrix(
636 f->pattern, FFT_MATRIX, 0, &pm) == FftResultMatch && pm)
638 printf(" matrix: (%f %f %f %f)\n",
639 pm->xx, pm->xy, pm->yx, pm->yy);
642 fflush (stdout);
643 return;