comparison packages/services/gfx/mw/current/src/engine/devfont.caching.c @ 208:e0c0827131d1 ecos

Merge from eCos master repository on 2002-05-20-20:11:54-BST
author jlarmour
date Mon, 20 May 2002 22:19:26 +0000
parents
children e1afd37f2f1d
comparison
equal deleted inserted replaced
207:74c807ddde34 208:e0c0827131d1
1 /*
2 * Copyright (c) 2000 Greg Haerr <greg@censoft.com>
3 * T1lib Adobe type1 routines contributed by Vidar Hokstad
4 * Freetype TrueType routines contributed by Martin Jolicoeur
5 * Han Zi Ku routines contributed by Tanghao and Jauming
6 *
7 * Device-independent font and text drawing routines
8 *
9 * These routines do the necessary range checking, clipping, and cursor
10 * overwriting checks, and then call the lower level device dependent
11 * routines to actually do the drawing. The lower level routines are
12 * only called when it is known that all the pixels to be drawn are
13 * within the device area and are visible.
14 */
15 /*#define NDEBUG*/
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <string.h>
19 #include <assert.h>
20 #include <string.h>
21
22 #include "device.h"
23 #if (UNIX | DOS_DJGPP)
24 #define strcmpi strcasecmp
25 #endif
26
27 #if HAVE_T1LIB_SUPPORT
28 #include <t1lib.h>
29 #define T1LIB_USE_AA_HIGH
30
31 typedef struct {
32 PMWFONTPROCS fontprocs; /* common hdr*/
33 MWCOORD fontsize;
34 int fontrotation;
35 int fontattr;
36
37 int fontid; /* t1lib stuff*/
38 } MWT1LIBFONT, *PMWT1LIBFONT;
39
40 static int t1lib_init(PSD psd);
41 static PMWT1LIBFONT t1lib_createfont(const char *name, MWCOORD height,int attr);
42 static void t1lib_drawtext(PMWFONT pfont, PSD psd, MWCOORD x, MWCOORD y,
43 const void *text, int cc, int flags);
44 static MWBOOL t1lib_getfontinfo(PMWFONT pfont, PMWFONTINFO pfontinfo);
45 static void t1lib_gettextsize(PMWFONT pfont, const void *text, int cc,
46 MWCOORD *pwidth, MWCOORD *pheight, MWCOORD *pbase);
47 static void t1lib_destroyfont(PMWFONT pfont);
48
49 /* handling routines for MWT1LIBFONT*/
50 static MWFONTPROCS t1lib_procs = {
51 MWTF_ASCII, /* routines expect ascii*/
52 t1lib_getfontinfo,
53 t1lib_gettextsize,
54 NULL, /* gettextbits*/
55 t1lib_destroyfont,
56 t1lib_drawtext,
57 NULL, /* setfontsize*/
58 NULL, /* setfontrotation*/
59 NULL, /* setfontattr*/
60 };
61 #endif
62
63 #ifdef T1LIB_USE_AA_HIGH
64 typedef unsigned long OUTPIXELVAL;
65 #else
66 typedef MWPIXELVAL OUTPIXELVAL;
67 #endif
68
69 #if HAVE_FREETYPE_SUPPORT
70 #include <freetype/freetype.h>
71 #include <freetype/ftxkern.h>
72 #include <freetype/ftnameid.h>
73 #include <freetype/ftxcmap.h>
74 #include <freetype/ftxwidth.h>
75 #include <math.h>
76
77 /************/
78
79 typedef struct xTT_Glyph_Cache_ {
80
81 TT_Error error;
82 TT_Glyph glyph;
83 TT_UShort index;
84 TT_UShort flags;
85
86 struct xTT_Glyph_Cache_ * l;
87 struct xTT_Glyph_Cache_ * r;
88
89 } xTT_Glyph_Cache;
90
91 typedef struct xTT_Instance_Object_ {
92
93 TT_Face face;
94 TT_Instance instance;
95
96 xTT_Glyph_Cache * head;
97
98 } xTT_Instance_Object;
99
100 typedef struct xTT_Instance_ {
101
102 xTT_Instance_Object * instance;
103
104 } xTT_Instance;
105
106 typedef struct xTT_Outline_Object_ {
107
108 TT_Outline outline;
109 TT_BBox bbox;
110
111 } xTT_Outline_Object;
112
113 typedef struct xTT_Outline_ {
114
115 xTT_Outline_Object * outline;
116
117 } xTT_Outline;
118
119 typedef struct xTT_Glyph_Object_ {
120
121 TT_Glyph * glyph;
122
123 xTT_Outline_Object outline;
124
125 } xTT_Glyph_Object;
126
127 typedef struct xTT_Glyph_ {
128
129 xTT_Glyph_Object * glyph;
130
131 } xTT_Glyph;
132
133 TT_Error
134 xTT_Glyph_Cache_Find ( xTT_Instance instance,
135 xTT_Glyph glyph,
136 TT_UShort glyphIndex,
137 TT_UShort loadFlags )
138 {
139 xTT_Glyph_Cache * node;
140 xTT_Glyph_Cache ** inode = &instance.instance->head;
141
142 int miss = 0;
143
144 while ( 1 )
145 {
146 if (*inode == 0)
147 {
148 miss = 1;
149
150 node = *inode = calloc(1,sizeof(**inode));
151
152 if (node == 0)
153 return TT_Err_Out_Of_Memory;
154
155 node->error = TT_New_Glyph(instance.instance->face,&(node->glyph));
156
157 if (node->error == 0)
158 node->error = TT_Load_Glyph(instance.instance->instance,
159 node->glyph,
160 (node->index = glyphIndex),
161 (node->flags = loadFlags));
162
163 if (node->error != 0)
164 TT_Done_Glyph(node->glyph);
165 }
166 else
167 {
168 node = *inode;
169 }
170
171 if (glyphIndex < node->index)
172 inode = &node->l;
173 else if (glyphIndex > node->index)
174 inode = &node->r;
175 else if (loadFlags < node->flags)
176 inode = &node->l;
177 else if (loadFlags > node->flags)
178 inode = &node->r;
179 else
180 {
181 static int count [] = { 0, 0 };
182 ++count[miss];
183 printf("\r(%s | hit %d | miss %d)",__TIME__,count[0],count[1]);
184 glyph.glyph->glyph = &node->glyph;
185 return node->error;
186 }
187 }
188 }
189
190 void
191 xTT_Glyph_Cache_Free ( xTT_Glyph_Cache ** pnode )
192 {
193 xTT_Glyph_Cache * node;
194
195 if (pnode == 0)
196 return;
197
198 node = *pnode;
199
200 if (node == 0)
201 return;
202
203 if (node->l)
204 xTT_Glyph_Cache_Free(&node->l);
205
206 if (node->r)
207 xTT_Glyph_Cache_Free(&node->r);
208
209 TT_Done_Glyph(node->glyph);
210 free(node);
211
212 *pnode = 0;
213 }
214
215 TT_Error
216 xTT_New_Instance ( TT_Face face,
217 xTT_Instance * instance )
218 {
219 instance->instance = calloc(1,sizeof(*instance->instance));
220 if (instance->instance == 0)
221 return TT_Err_Out_Of_Memory;
222
223 instance->instance->face = face;
224 instance->instance->head = 0;
225
226 return TT_New_Instance(face,&instance->instance->instance);
227 }
228
229 TT_Error
230 xTT_Done_Instance ( xTT_Instance instance )
231 {
232 TT_Error error;
233
234 xTT_Glyph_Cache_Free(&instance.instance->head);
235 error = TT_Done_Instance(instance.instance->instance);
236
237 free(instance.instance);
238
239 return error;
240 }
241
242 TT_Error
243 xTT_Get_Instance_Metrics ( xTT_Instance instance,
244 TT_Instance_Metrics * imetrics )
245 {
246 return TT_Get_Instance_Metrics(instance.instance->instance,imetrics);
247 }
248
249 TT_Error
250 xTT_Set_Instance_CharSize ( xTT_Instance instance,
251 TT_F26Dot6 charsize )
252 {
253 xTT_Glyph_Cache_Free(&instance.instance->head);
254 return TT_Set_Instance_CharSize(instance.instance->instance,charsize);
255 }
256
257 TT_Error
258 xTT_Set_Instance_PixelSizes ( xTT_Instance instance,
259 TT_UShort pixelWidth,
260 TT_UShort pixelHeight,
261 TT_F26Dot6 pointSize )
262 {
263 xTT_Glyph_Cache_Free(&instance.instance->head);
264 return TT_Set_Instance_PixelSizes(instance.instance->instance,
265 pixelWidth,
266 pixelHeight,
267 pointSize);
268 }
269
270 TT_Error
271 xTT_Set_Instance_Transform_Flags ( xTT_Instance instance,
272 TT_Bool rotated,
273 TT_Bool stretched )
274 {
275 xTT_Glyph_Cache_Free(&instance.instance->head);
276 return TT_Set_Instance_Resolutions(instance.instance->instance,
277 rotated,
278 stretched);
279 }
280
281 TT_Error
282 xTT_Set_Instance_Resolutions ( xTT_Instance instance,
283 TT_UShort xResolution,
284 TT_UShort yResolution )
285 {
286 xTT_Glyph_Cache_Free(&instance.instance->head);
287 return TT_Set_Instance_Resolutions(instance.instance->instance,
288 xResolution,
289 yResolution);
290 }
291
292 TT_Error
293 xTT_New_Glyph ( TT_Face face,
294 xTT_Glyph * glyph )
295 {
296 glyph->glyph = calloc(1,sizeof(*glyph->glyph));
297 if (glyph->glyph == 0)
298 return TT_Err_Out_Of_Memory;
299 return 0;
300 }
301
302 TT_Error
303 xTT_Done_Glyph ( xTT_Glyph glyph )
304 {
305 free(glyph.glyph);
306 return 0;
307 }
308
309 TT_Error
310 xTT_Load_Glyph ( xTT_Instance instance,
311 xTT_Glyph glyph,
312 TT_UShort glyphIndex,
313 TT_UShort loadFlags )
314 {
315 TT_Error error;
316 error = xTT_Glyph_Cache_Find(instance,glyph,glyphIndex,loadFlags);
317 TT_Get_Glyph_Outline(*glyph.glyph->glyph,
318 &glyph.glyph->outline.outline);
319 TT_Get_Outline_BBox(&glyph.glyph->outline.outline,
320 &glyph.glyph->outline.bbox);
321 return error;
322 }
323
324 TT_Error
325 xTT_Get_Glyph_Metrics ( xTT_Glyph glyph,
326 TT_Glyph_Metrics * metrics )
327 {
328 return TT_Get_Glyph_Metrics(*glyph.glyph->glyph,metrics);
329 }
330
331 TT_Error
332 xTT_Get_Glyph_Outline ( xTT_Glyph glyph,
333 xTT_Outline * outline )
334 {
335 outline->outline = &glyph.glyph->outline;
336 return 0;
337 }
338
339 TT_Error
340 xTT_Get_Outline_BBox ( xTT_Outline * outline,
341 TT_BBox * bbox )
342 {
343 *bbox = outline->outline->bbox;
344 return 0;
345 }
346
347 void
348 xTT_Transform_Outline ( xTT_Outline * outline,
349 TT_Matrix * matrix )
350 {
351 TT_Transform_Outline(&outline->outline->outline,matrix);
352 TT_Get_Outline_BBox(&outline->outline->outline,
353 &outline->outline->bbox);
354 }
355
356 TT_Error
357 xTT_Get_Glyph_Bitmap ( xTT_Glyph glyph,
358 TT_Raster_Map * bitmap,
359 TT_F26Dot6 xOffset,
360 TT_F26Dot6 yOffset )
361 {
362 return TT_Get_Glyph_Bitmap(*glyph.glyph->glyph,
363 bitmap,
364 xOffset,
365 yOffset);
366 }
367
368 TT_Error
369 xTT_Get_Glyph_Pixmap ( xTT_Glyph glyph,
370 TT_Raster_Map * pixmap,
371 TT_F26Dot6 xOffset,
372 TT_F26Dot6 yOffset )
373 {
374 return TT_Get_Glyph_Pixmap(*glyph.glyph->glyph,
375 pixmap,
376 xOffset,
377 yOffset);
378 }
379
380 #ifndef xTT_ALIAS
381 #define xTT_ALIAS 1
382 #endif
383
384 #if xTT_ALIAS
385
386 #define TT_Instance xTT_Instance
387 #define TT_Outline xTT_Outline
388 #define TT_Glyph xTT_Glyph
389
390 #define TT_New_Instance xTT_New_Instance
391 #define TT_Done_Instance xTT_Done_Instance
392
393 #define TT_Get_Instance_Metrics xTT_Get_Instance_Metrics
394 #define TT_Set_Instance_CharSize xTT_Set_Instance_CharSize
395 #define TT_Set_Instance_PixelSizes xTT_Set_Instance_PixelSizes
396 #define TT_Set_Instance_Transform_Flags xTT_Set_Instance_Transform_Flags
397 #define TT_Set_Instance_Resolutions xTT_Set_Instance_Resolutions
398
399 #define TT_New_Glyph xTT_New_Glyph
400 #define TT_Done_Glyph xTT_Done_Glyph
401
402 #define TT_Load_Glyph xTT_Load_Glyph
403 #define TT_Get_Glyph_Metrics xTT_Get_Glyph_Metrics
404 #define TT_Get_Glyph_Outline xTT_Get_Glyph_Outline
405 #define TT_Get_Glyph_Bitmap xTT_Get_Glyph_Bitmap
406 #define TT_Get_Glyph_Pixmap xTT_Get_Glyph_Pixmap
407
408 #define TT_Get_Outline_BBox xTT_Get_Outline_BBox
409 #define TT_Transform_Outline xTT_Transform_Outline
410
411 #endif
412
413 /************/
414
415 #ifndef FREETYPE_FONT_DIR
416 #define FREETYPE_FONT_DIR "/usr/local/microwin/fonts"
417 #endif
418
419 #if TT_FREETYPE_MAJOR != 1 | TT_FREETYPE_MINOR < 3
420 #error "You must link with freetype lib version 1.3.x +, and not freetype 2. \
421 Download it at http://www.freetype.org or http://microwindows.org"
422 #endif
423
424 #ifndef MWFREETYPEFONT_CACHE
425 #define MWFREETYPEFONT_CACHE 1
426 #endif
427
428 #if MWFREETYPEFONT_CACHE
429
430 #ifndef MWFREETYPEFONT_CACHEBITMAP
431 #define MWFREETYPEFONT_CACHEBITMAP 1
432 #endif
433
434 typedef struct mwfreetypefontcache {
435 unsigned curchar;
436 void * buffer;
437 #if MWFREETYPEFONT_CACHEBITMAP
438 MWPIXELVAL fg;
439 MWPIXELVAL bg;
440 MWBOOL usebg;
441 void * bitmap;
442 #endif
443 struct mwfreetypefontcache * l;
444 struct mwfreetypefontcache * r;
445 } MWFREETYPEFONTCACHE;
446
447 #endif
448
449 typedef struct {
450
451 PMWFONTPROCS fontprocs; /* common hdr*/
452 MWCOORD fontsize;
453 int fontrotation;
454 int fontattr;
455
456 TT_Face face; /* freetype stuff*/
457 TT_Instance instance;
458 TT_CharMap char_map;
459 TT_Kerning directory;
460 TT_Matrix matrix;
461 TT_Glyph glyph;
462 MWBOOL can_kern;
463 short last_glyph_code;
464 short last_pen_pos;
465
466 #if MWFREETYPEFONT_CACHE
467 MWFREETYPEFONTCACHE * glyph_cache;
468 #endif
469
470 } MWFREETYPEFONT, *PMWFREETYPEFONT;
471
472 static int freetype_init(PSD psd);
473 static PMWFREETYPEFONT freetype_createfont(const char *name, MWCOORD height,
474 int attr);
475 static MWBOOL freetype_getfontinfo(PMWFONT pfont, PMWFONTINFO pfontinfo);
476 static void freetype_gettextsize(PMWFONT pfont, const void *text,
477 int cc, MWCOORD *pwidth, MWCOORD *pheight, MWCOORD *pbase);
478 static void freetype_destroyfont(PMWFONT pfont);
479 static void freetype_drawtext(PMWFONT pfont, PSD psd, MWCOORD x, MWCOORD y,
480 const void *text, int cc, int flags);
481 static void freetype_setfontsize(PMWFONT pfont, MWCOORD fontsize);
482 static void freetype_setfontrotation(PMWFONT pfont, int tenthdegrees);
483
484 /* handling routines for MWFREETYPEFONT*/
485 static MWFONTPROCS freetype_procs = {
486 MWTF_UC16, /* routines expect unicode 16*/
487 freetype_getfontinfo,
488 freetype_gettextsize,
489 NULL, /* gettextbits*/
490 freetype_destroyfont,
491 freetype_drawtext,
492 freetype_setfontsize,
493 freetype_setfontrotation,
494 NULL, /* setfontattr*/
495 };
496
497 static TT_Engine engine; /* THE ONLY freetype engine */
498 #endif /* HAVE_FREETYPE_SUPPORT*/
499
500 #if HAVE_HZK_SUPPORT
501 /*
502 * 12x12 and 16x16 ascii and chinese fonts
503 * Big5 and GB2312 encodings supported
504 */
505 #define MAX_PATH 256
506 typedef struct {
507 int width;
508 int height;
509 int size;
510 unsigned long use_count;
511 char * pFont;
512 char file[MAX_PATH + 1];
513 } HZKFONT;
514
515 static int use_big5=1;
516 static HZKFONT CFont[2]; /* font cache*/
517 static HZKFONT AFont[2]; /* font cache*/
518
519 /*jmt: moved inside MWHZKFONT*/
520 static int afont_width = 8;
521 static int cfont_width = 16;
522 static int font_height = 16;
523 static char *afont_address;
524 static char *cfont_address;
525
526 typedef struct {
527 PMWFONTPROCS fontprocs; /* common hdr*/
528 MWCOORD fontsize;
529 int fontrotation;
530 int fontattr;
531
532 HZKFONT CFont; /* hzkfont stuff */
533 HZKFONT AFont;
534 int afont_width;
535 int cfont_width;
536 int font_height;
537 char *afont_address;
538 char *cfont_address;
539 } MWHZKFONT, *PMWHZKFONT;
540
541 static int hzk_init(PSD psd);
542 static PMWHZKFONT hzk_createfont(const char *name, MWCOORD height,int fontattr);
543 static MWBOOL hzk_getfontinfo(PMWFONT pfont, PMWFONTINFO pfontinfo);
544 static void hzk_gettextsize(PMWFONT pfont, const void *text,
545 int cc, MWCOORD *pwidth, MWCOORD *pheight, MWCOORD *pbase);
546 /*static void hzk_gettextbits(PMWFONT pfont, int ch, IMAGEBITS *retmap,
547 MWCOORD *pwidth, MWCOORD *pheight, MWCOORD *pbase);*/
548 static void hzk_destroyfont(PMWFONT pfont);
549 static void hzk_drawtext(PMWFONT pfont, PSD psd, MWCOORD x, MWCOORD y,
550 const void *text, int cc, int flags);
551 static void hzk_setfontsize(PMWFONT pfont, MWCOORD fontsize);
552 /*static void hzk_setfontrotation(PMWFONT pfont, int tenthdegrees);*/
553
554 /* handling routines for MWHZKFONT*/
555 static MWFONTPROCS hzk_procs = {
556 MWTF_ASCII, /* routines expect ASCII*/
557 hzk_getfontinfo,
558 hzk_gettextsize,
559 NULL, /* hzk_gettextbits*/
560 hzk_destroyfont,
561 hzk_drawtext,
562 hzk_setfontsize,
563 NULL, /* setfontrotation*/
564 NULL, /* setfontattr*/
565 };
566
567 static int
568 UC16_to_GB(const unsigned char *uc16, int cc, unsigned char *ascii);
569 #endif /* HAVE_HZK_SUPPORT*/
570
571 static PMWFONT gr_pfont; /* current font*/
572
573 /* temp extern decls*/
574 extern MWPIXELVAL gr_foreground;
575 extern MWPIXELVAL gr_background;
576 extern MWBOOL gr_usebg;
577
578 static int utf8_to_utf16(const unsigned char *utf8, int cc,
579 unsigned short *unicode16);
580
581 #if FONTMAPPER
582 /* entry point for font selection*/
583 int select_font(const PMWLOGFONT plogfont, char *physname);
584 #endif
585
586 /*
587 * Set the font for future calls.
588 */
589 PMWFONT
590 GdSetFont(PMWFONT pfont)
591 {
592 PMWFONT oldfont = gr_pfont;
593 gr_pfont = pfont;
594 return oldfont;
595 }
596
597 /*
598 * Select a font, based on various parameters.
599 * If plogfont is specified, name and height parms are ignored
600 * and instead used from MWLOGFONT.
601 *
602 * If height is 0, return builtin font from passed name.
603 * Otherwise find builtin font best match based on height.
604 */
605 PMWFONT
606 GdCreateFont(PSD psd, const char *name, MWCOORD height,
607 const PMWLOGFONT plogfont)
608 {
609 int i;
610 int fontht;
611 int fontno;
612 int fontclass;
613 int fontattr = 0;
614 PMWFONT pfont;
615 PMWCOREFONT pf = psd->builtin_fonts;
616 MWFONTINFO fontinfo;
617 MWSCREENINFO scrinfo;
618 char fontname[128];
619
620 GdGetScreenInfo(psd, &scrinfo);
621
622 /* if plogfont not specified, use name and height*/
623 if (!plogfont) {
624 if (!name)
625 name = MWFONT_SYSTEM_VAR;
626 strcpy(fontname, name);
627 fontclass = MWLF_CLASS_ANY;
628 } else {
629 #if FONTMAPPER
630 /* otherwise, use MWLOGFONT name and height*/
631 fontclass = select_font(plogfont, fontname);
632 #else
633 if (!name)
634 name = MWFONT_SYSTEM_VAR;
635 strcpy(fontname, name);
636 fontclass = MWLF_CLASS_ANY;
637 #endif
638 height = plogfont->lfHeight;
639 if (plogfont->lfUnderline)
640 fontattr = MWTF_UNDERLINE;
641 }
642 height = abs(height);
643
644 if (!fontclass)
645 goto first;
646
647 /* use builtin screen fonts, FONT_xxx, if height is 0 */
648 if (height == 0 || fontclass == MWLF_CLASS_ANY ||
649 fontclass == MWLF_CLASS_BUILTIN) {
650 for(i = 0; i < scrinfo.fonts; ++i) {
651 if(!strcmpi(pf[i].name, fontname)) {
652 pf[i].fontsize = pf[i].cfont->height;
653 pf[i].fontattr = fontattr;
654 return (PMWFONT)&pf[i];
655 }
656 }
657
658 /* return first builtin font*/
659 if (height == 0 || fontclass == MWLF_CLASS_BUILTIN)
660 goto first;
661 }
662
663 #if HAVE_HZK_SUPPORT
664 /* Make sure the library is initialized */
665 if (hzk_init(psd)) {
666 pfont = (PMWFONT)hzk_createfont(name, height, fontattr);
667 if(pfont)
668 return pfont;
669 printf("hzk_createfont: %s not found\n", name);
670 }
671 #endif
672
673 #if HAVE_FREETYPE_SUPPORT
674 if (fontclass == MWLF_CLASS_ANY || fontclass == MWLF_CLASS_FREETYPE) {
675 if (freetype_init(psd)) {
676 /* auto antialias for height > 14 for kaffe*/
677 if (plogfont && plogfont->lfHeight > 14 &&
678 plogfont->lfQuality)
679 fontattr |= MWTF_ANTIALIAS;
680
681 pfont = (PMWFONT)freetype_createfont(fontname, height,
682 fontattr);
683 if(pfont) {
684 /* temp kaffe kluge*/
685 pfont->fontattr |= FS_FREETYPE;
686 return pfont;
687 }
688 DPRINTF("freetype_createfont: %s,%d not found\n",
689 fontname, height);
690 }
691 }
692 #endif
693
694 #if HAVE_T1LIB_SUPPORT
695 if (fontclass == MWLF_CLASS_ANY || fontclass == MWLF_CLASS_T1LIB) {
696 if (t1lib_init(psd)) {
697 pfont = (PMWFONT)t1lib_createfont(fontname, height,
698 fontattr);
699 if(pfont)
700 return pfont;
701 DPRINTF("t1lib_createfont: %s,%d not found\n",
702 fontname, height);
703 }
704 }
705 #endif
706
707 /* find builtin font closest in height*/
708 if(height != 0) {
709 fontno = 0;
710 height = abs(height);
711 fontht = MAX_MWCOORD;
712 for(i = 0; i < scrinfo.fonts; ++i) {
713 pfont = (PMWFONT)&pf[i];
714 GdGetFontInfo(pfont, &fontinfo);
715 if(fontht > abs(height-fontinfo.height)) {
716 fontno = i;
717 fontht = abs(height-fontinfo.height);
718 }
719 }
720 pf[fontno].fontsize = pf[fontno].cfont->height;
721 pf[fontno].fontattr = fontattr;
722 return (PMWFONT)&pf[fontno];
723 }
724
725 first:
726 /* Return first builtin font*/
727 pf->fontsize = pf->cfont->height;
728 pf->fontattr = fontattr;
729 return (PMWFONT)&pf[0];
730 }
731
732 /* Set the font size for the passed font*/
733 MWCOORD
734 GdSetFontSize(PMWFONT pfont, MWCOORD fontsize)
735 {
736 MWCOORD oldfontsize = pfont->fontsize;
737
738 pfont->fontsize = fontsize;
739
740 if (pfont->fontprocs->SetFontSize)
741 pfont->fontprocs->SetFontSize(pfont, fontsize);
742
743 return oldfontsize;
744 }
745
746 /* Set the font rotation angle in tenths of degrees for the passed font*/
747 int
748 GdSetFontRotation(PMWFONT pfont, int tenthdegrees)
749 {
750 MWCOORD oldrotation = pfont->fontrotation;
751
752 pfont->fontrotation = tenthdegrees;
753
754 if (pfont->fontprocs->SetFontRotation)
755 pfont->fontprocs->SetFontRotation(pfont, tenthdegrees);
756
757 return oldrotation;
758 }
759
760 /*
761 * Set/reset font attributes (MWTF_KERNING, MWTF_ANTIALIAS)
762 * for the passed font.
763 */
764 int
765 GdSetFontAttr(PMWFONT pfont, int setflags, int clrflags)
766 {
767 MWCOORD oldattr = pfont->fontattr;
768
769 pfont->fontattr &= ~clrflags;
770 pfont->fontattr |= setflags;
771
772 if (pfont->fontprocs->SetFontAttr)
773 pfont->fontprocs->SetFontAttr(pfont, setflags, clrflags);
774
775 return oldattr;
776 }
777
778 /* Unload and deallocate font*/
779 void
780 GdDestroyFont(PMWFONT pfont)
781 {
782 if (pfont->fontprocs->DestroyFont)
783 pfont->fontprocs->DestroyFont(pfont);
784 }
785
786 /* Return information about a specified font*/
787 MWBOOL
788 GdGetFontInfo(PMWFONT pfont, PMWFONTINFO pfontinfo)
789 {
790 if(!pfont || !pfont->fontprocs->GetFontInfo)
791 return FALSE;
792
793 return pfont->fontprocs->GetFontInfo(pfont, pfontinfo);
794 }
795
796 /*
797 * Convert from one encoding to another
798 * Input cc and returned cc is character count, not bytes
799 * Return < 0 on error or can't translate
800 */
801 int
802 GdConvertEncoding(const void *istr, int iflags, int cc, void *ostr, int oflags)
803 {
804 const unsigned char *istr8;
805 const unsigned short *istr16;
806 const unsigned long *istr32;
807 unsigned char *ostr8;
808 unsigned short *ostr16;
809 unsigned long *ostr32;
810 unsigned int ch;
811 int icc;
812 unsigned short buf16[512];
813
814 iflags &= MWTF_PACKMASK;
815 oflags &= MWTF_PACKMASK;
816
817 /* allow -1 for len with ascii*/
818 if(cc == -1 && (iflags == MWTF_ASCII))
819 cc = strlen((char *)istr);
820
821 /* first check for utf8 input encoding*/
822 if(iflags == MWTF_UTF8) {
823 /* we've only got uc16 now so convert to uc16...*/
824 cc = utf8_to_utf16((unsigned char *)istr, cc,
825 oflags==MWTF_UC16?(unsigned short*) ostr: buf16);
826
827 if(oflags == MWTF_UC16 || cc < 0)
828 return cc;
829
830 /* will decode again to requested format (probably ascii)*/
831 iflags = MWTF_UC16;
832 istr = buf16;
833 }
834
835 #if HAVE_HZK_SUPPORT
836 if(iflags == MWTF_UC16 && oflags == MWTF_ASCII) {
837 /* only support uc16 convert to ascii now...*/
838 cc = UC16_to_GB( istr, cc, ostr);
839 return cc;
840 }
841 #endif
842
843 icc = cc;
844 istr8 = istr;
845 istr16 = istr;
846 istr32 = istr;
847 ostr8 = ostr;
848 ostr16 = ostr;
849 ostr32 = ostr;
850
851 /* Convert between formats. Note that there's no error
852 * checking here yet.
853 */
854 while(--icc >= 0) {
855 switch(iflags) {
856 default:
857 ch = *istr8++;
858 break;
859 case MWTF_UC16:
860 ch = *istr16++;
861 break;
862 case MWTF_UC32:
863 ch = *istr32++;
864 }
865 switch(oflags) {
866 default:
867 *ostr8++ = (unsigned char)ch;
868 break;
869 case MWTF_UC16:
870 *ostr16++ = (unsigned short)ch;
871 break;
872 case MWTF_UC32:
873 *ostr32++ = ch;
874 }
875 }
876 return cc;
877 }
878
879 /* Get the width and height of passed text string in the passed font*/
880 void
881 GdGetTextSize(PMWFONT pfont, const void *str, int cc, MWCOORD *pwidth,
882 MWCOORD *pheight, MWCOORD *pbase, int flags)
883 {
884 const void * text;
885 unsigned long buf[256];
886 int defencoding = pfont->fontprocs->encoding;
887
888 /* convert encoding if required*/
889 if((flags & MWTF_PACKMASK) != defencoding) {
890 cc = GdConvertEncoding(str, flags, cc, buf, defencoding);
891 flags &= ~MWTF_PACKMASK;
892 flags |= defencoding;
893 text = buf;
894 } else text = str;
895
896 if(cc == -1 && (flags & MWTF_PACKMASK) == MWTF_ASCII)
897 cc = strlen((char *)str);
898
899 if(cc <= 0 || !pfont->fontprocs->GetTextSize) {
900 *pwidth = *pheight = *pbase = 0;
901 return;
902 }
903
904 /* calc height and width of string*/
905 pfont->fontprocs->GetTextSize(pfont, text, cc, pwidth, pheight, pbase);
906 }
907
908 /* Draw a text string at a specifed coordinates in the foreground color
909 * (and possibly the background color), applying clipping if necessary.
910 * The background color is only drawn if the gr_usebg flag is set.
911 * Use the current font.
912 */
913 void
914 GdText(PSD psd, MWCOORD x, MWCOORD y, const void *str, int cc, int flags)
915 {
916 const void * text;
917 unsigned long buf[256];
918 int defencoding = gr_pfont->fontprocs->encoding;
919
920 /* convert encoding if required*/
921 if((flags & MWTF_PACKMASK) != defencoding) {
922 cc = GdConvertEncoding(str, flags, cc, buf, defencoding);
923 flags &= ~MWTF_PACKMASK;
924 flags |= defencoding;
925 text = buf;
926 } else text = str;
927
928 if(cc == -1 && (flags & MWTF_PACKMASK) == MWTF_ASCII)
929 cc = strlen((char *)str);
930
931 if(cc <= 0 || !gr_pfont->fontprocs->DrawText)
932 return;
933
934 /* draw text string*/
935 gr_pfont->fontprocs->DrawText(gr_pfont, psd, x, y, text, cc, flags);
936 }
937
938 /*
939 * Draw ascii text using COREFONT type font.
940 */
941 void
942 corefont_drawtext(PMWFONT pfont, PSD psd, MWCOORD x, MWCOORD y,
943 const void *text, int cc, int flags)
944 {
945 const unsigned char *str = text;
946 MWCOORD width; /* width of text area */
947 MWCOORD height; /* height of text area */
948 MWCOORD base; /* baseline of text*/
949 MWCOORD startx, starty;
950 /* bitmap for characters */
951 MWIMAGEBITS bitmap[MAX_CHAR_HEIGHT*MAX_CHAR_WIDTH/MWIMAGE_BITSPERIMAGE];
952
953 pfont->fontprocs->GetTextSize(pfont, str, cc, &width, &height, &base);
954
955 if(flags & MWTF_BASELINE)
956 y -= base;
957 else if(flags & MWTF_BOTTOM)
958 y -= (height - 1);
959 startx = x;
960 starty = y + base;
961
962 switch (GdClipArea(psd, x, y, x + width - 1, y + height - 1)) {
963 case CLIP_VISIBLE:
964 /*
965 * For size considerations, there's no low-level text
966 * draw, so we've got to draw all text
967 * with per-point clipping for the time being
968 if (gr_usebg)
969 psd->FillRect(psd, x, y, x + width - 1, y + height - 1,
970 gr_background);
971 psd->DrawText(psd, x, y, str, cc, gr_foreground, pfont);
972 GdFixCursor(psd);
973 return;
974 */
975 break;
976
977 case CLIP_INVISIBLE:
978 return;
979 }
980
981 /* Get the bitmap for each character individually, and then display
982 * them using clipping for each one.
983 */
984 while (--cc >= 0 && x < psd->xvirtres) {
985 unsigned int ch = *str++;
986 #if HAVE_BIG5_SUPPORT
987 /* chinese big5 decoding*/
988 if (ch >= 0xA1 && ch <= 0xF9 && cc >= 1 &&
989 ((*str >= 0x40 && *str <= 0x7E) ||
990 (*str >= 0xA1 && *str <= 0xFE)) ) {
991 ch = (ch << 8) | *str++;
992 --cc;
993 }
994 #endif
995 #if HAVE_GB2312_SUPPORT
996 /* chinese gb2312 decoding*/
997 if (ch >= 0xA1 && ch < 0xF8 && cc >= 1 &&
998 *str >= 0xA1 && *str < 0xFF) {
999 ch = (ch << 8) | *str++;
1000 --cc;
1001 }
1002 #endif
1003 pfont->fontprocs->GetTextBits(pfont, ch, bitmap, &width,
1004 &height, &base);
1005
1006 /* note: change to bitmap*/
1007 GdBitmap(psd, x, y, width, height, bitmap);
1008 x += width;
1009 }
1010
1011 if (pfont->fontattr & MWTF_UNDERLINE)
1012 GdLine(psd, startx, starty, x, starty, FALSE);
1013
1014 GdFixCursor(psd);
1015 }
1016
1017 #if HAVE_T1LIB_SUPPORT | HAVE_FREETYPE_SUPPORT
1018 /*
1019 * Produce blend table from src and dst based on passed alpha table
1020 * Used because we don't quite yet have GdArea with alphablending,
1021 * so we pre-blend fg/bg colors for fade effect.
1022 */
1023 static void
1024 alphablend(PSD psd, OUTPIXELVAL *out, MWPIXELVAL src, MWPIXELVAL dst,
1025 unsigned char *alpha, int count)
1026 {
1027 unsigned int a, d;
1028 unsigned char r, g, b;
1029 MWCOLORVAL palsrc, paldst;
1030 extern MWPALENTRY gr_palette[256];
1031
1032 while (--count >= 0) {
1033 a = *alpha++;
1034
1035 #define BITS(pixel,shift,mask) (((pixel)>>shift)&(mask))
1036 if(a == 0)
1037 *out++ = dst;
1038 else if(a == 255)
1039 *out++ = src;
1040 else
1041 switch(psd->pixtype) {
1042 case MWPF_TRUECOLOR0888:
1043 case MWPF_TRUECOLOR888:
1044 d = BITS(dst, 16, 0xff);
1045 r = (unsigned char)(((BITS(src, 16, 0xff) - d)*a)>>8) + d;
1046 d = BITS(dst, 8, 0xff);
1047 g = (unsigned char)(((BITS(src, 8, 0xff) - d)*a)>>8) + d;
1048 d = BITS(dst, 0, 0xff);
1049 b = (unsigned char)(((BITS(src, 0, 0xff) - d)*a)>>8) + d;
1050 *out++ = (r << 16) | (g << 8) | b;
1051 break;
1052
1053 case MWPF_TRUECOLOR565:
1054 d = BITS(dst, 11, 0x1f);
1055 r = (unsigned char)(((BITS(src, 11, 0x1f) - d)*a)>>8) + d;
1056 d = BITS(dst, 5, 0x3f);
1057 g = (unsigned char)(((BITS(src, 5, 0x3f) - d)*a)>>8) + d;
1058 d = BITS(dst, 0, 0x1f);
1059 b = (unsigned char)(((BITS(src, 0, 0x1f) - d)*a)>>8) + d;
1060 *out++ = (r << 11) | (g << 5) | b;
1061 break;
1062
1063 case MWPF_TRUECOLOR555:
1064 d = BITS(dst, 10, 0x1f);
1065 r = (unsigned char)(((BITS(src, 10, 0x1f) - d)*a)>>8) + d;
1066 d = BITS(dst, 5, 0x1f);
1067 g = (unsigned char)(((BITS(src, 5, 0x1f) - d)*a)>>8) + d;
1068 d = BITS(dst, 0, 0x1f);
1069 b = (unsigned char)(((BITS(src, 0, 0x1f) - d)*a)>>8) + d;
1070 *out++ = (r << 10) | (g << 5) | b;
1071 break;
1072
1073 case MWPF_TRUECOLOR332:
1074 d = BITS(dst, 5, 0x07);
1075 r = (unsigned char)(((BITS(src, 5, 0x07) - d)*a)>>8) + d;
1076 d = BITS(dst, 2, 0x07);
1077 g = (unsigned char)(((BITS(src, 2, 0x07) - d)*a)>>8) + d;
1078 d = BITS(dst, 0, 0x03);
1079 b = (unsigned char)(((BITS(src, 0, 0x03) - d)*a)>>8) + d;
1080 *out++ = (r << 5) | (g << 2) | b;
1081 break;
1082
1083 case MWPF_PALETTE:
1084 /* reverse lookup palette entry for blend ;-)*/
1085 palsrc = GETPALENTRY(gr_palette, src);
1086 paldst = GETPALENTRY(gr_palette, dst);
1087 d = REDVALUE(paldst);
1088 r = (unsigned char)(((REDVALUE(palsrc) - d)*a)>>8) + d;
1089 d = GREENVALUE(paldst);
1090 g = (unsigned char)(((GREENVALUE(palsrc) - d)*a)>>8) + d;
1091 d = BLUEVALUE(paldst);
1092 b = (unsigned char)(((BLUEVALUE(palsrc) - d)*a)>>8) + d;
1093 *out++ = GdFindNearestColor(gr_palette, (int)psd->ncolors,
1094 MWRGB(r, g, b));
1095 break;
1096 }
1097 }
1098 }
1099 #endif /*HAVE_T1LIB_SUPPORT | HAVE_FREETYPE_SUPPORT*/
1100
1101 #if HAVE_T1LIB_SUPPORT
1102 /* contributed by Vidar Hokstad*/
1103
1104 static int
1105 t1lib_init(PSD psd)
1106 {
1107 static int inited = 0;
1108
1109 if (inited)
1110 return 1;
1111
1112 T1_SetBitmapPad(8);
1113 if (!T1_InitLib(0))
1114 return 0;
1115 #ifdef T1LIB_USE_AA_HIGH
1116 T1_AASetLevel(T1_AA_HIGH);
1117 #else
1118 T1_AASetLevel(T1_AA_LOW);
1119 #endif
1120 #if 0
1121 /* kluge: this is required if 16bpp drawarea driver is used*/
1122 if(psd->bpp == 16)
1123 T1_AASetBitsPerPixel(16);
1124 else
1125 #endif
1126 T1_AASetBitsPerPixel(sizeof(MWPIXELVAL)*8);
1127
1128 inited = 1;
1129 return 1;
1130 }
1131
1132 static PMWT1LIBFONT
1133 t1lib_createfont(const char *name, MWCOORD height, int attr)
1134 {
1135 PMWT1LIBFONT pf;
1136 int id;
1137 char * p;
1138 char buf[256];
1139
1140 /* match name against t1 font id's from t1 font database*/
1141 for(id=0; id<T1_Get_no_fonts(); ++id) {
1142 strncpy(buf, T1_GetFontFileName(id), sizeof(buf));
1143
1144 /* remove extension*/
1145 for(p=buf; *p; ++p) {
1146 if(*p == '.') {
1147 *p = 0;
1148 break;
1149 }
1150 }
1151
1152 if(!strcmpi(name, buf)) {
1153 /* allocate font structure*/
1154 pf = (PMWT1LIBFONT)calloc(sizeof(MWT1LIBFONT), 1);
1155 if (!pf)
1156 return NULL;
1157 pf->fontprocs = &t1lib_procs;
1158 GdSetFontSize((PMWFONT)pf, height);
1159 GdSetFontRotation((PMWFONT)pf, 0);
1160 GdSetFontAttr((PMWFONT)pf, attr, 0);
1161 pf->fontid = id;
1162 return pf;
1163 }
1164 }
1165 return NULL;
1166 }
1167
1168 /*
1169 * Draw ascii text string using T1LIB type font
1170 */
1171 static void
1172 t1lib_drawtext(PMWFONT pfont, PSD psd, MWCOORD x, MWCOORD y,
1173 const void *text, int cc, int flags)
1174 {
1175 PMWT1LIBFONT pf = (PMWT1LIBFONT)pfont;
1176 const unsigned char *str = text;
1177 MWCOORD width; /* width of text area */
1178 MWCOORD height; /* height of text area */
1179 MWCOORD underliney;
1180 GLYPH * g; /* T1lib glyph structure. Memory handling by T1lib */
1181 #ifdef T1LIB_USE_AA_HIGH
1182 OUTPIXELVAL gvals[17];
1183
1184 /* Blending array for antialiasing. The steeper the values increase
1185 * near the end, the sharper the characters look, but also more jagged
1186 */
1187 static unsigned char blend[17] = {
1188 0x00, 0x00, 0x04, 0x0c, 0x10, 0x14, 0x18, 0x20,
1189 0x30, 0x38, 0x40, 0x50, 0x70, 0x80, 0xa0, 0xc0, 0xff
1190 };
1191 #else
1192 OUTPIXELVAL gvals[5];
1193 static unsigned char blend[5] = { 0x00, 0x44, 0x88, 0xcc, 0xff };
1194 #endif
1195
1196 /* Check if we should throw out some fonts */
1197
1198 if (pf->fontattr&MWTF_ANTIALIAS) {
1199 #ifdef T1LIB_USE_AA_HIGH
1200 alphablend(psd, gvals, gr_foreground, gr_background, blend, 17);
1201 T1_AAHSetGrayValues(gvals);
1202 #else
1203 alphablend(psd, gvals, gr_foreground, gr_background, blend, 5);
1204 T1_AASetGrayValues(gvals[0],gvals[1],gvals[2],gvals[3],gvals[4]);
1205 #endif
1206 g = T1_AASetString(pf->fontid,(char *)str,cc,0,
1207 (pf->fontattr&MWTF_KERNING)? T1_KERNING: 0,
1208 pf->fontsize * 1.0, 0);
1209
1210 if (g && g->bits) {
1211 /*MWPIXELVAL save = gr_background;*/
1212 width = g->metrics.rightSideBearing - g->metrics.leftSideBearing;
1213 height = g->metrics.ascent - g->metrics.descent;
1214
1215 if(flags & MWTF_BASELINE)
1216 y -= g->metrics.ascent;
1217 else if(flags & MWTF_BOTTOM)
1218 y -= (height - 1);
1219 underliney = y + g->metrics.ascent;
1220
1221 /* FIXME: Looks damn ugly if usebg is false.
1222 * Will be handled when using alphablending in GdArea...
1223 */
1224 /* clipping handled in GdArea*/
1225 /*FIXME kluge for transparency*/
1226 /*gr_background = gr_foreground + 1;*/
1227 /*gr_usebg = 0;*/
1228 GdArea(psd,x,y, width, height, g->bits, MWPF_PIXELVAL);
1229 /*gr_background = save;*/
1230
1231 if (pf->fontattr & MWTF_UNDERLINE)
1232 GdLine(psd, x, underliney, x+width, underliney, FALSE);
1233
1234 }
1235 } else {
1236 /* Do non-aa drawing */
1237 g = T1_SetString(pf->fontid,(char *)str,cc,0,
1238 (pf->fontattr&MWTF_KERNING)? T1_KERNING: 0,
1239 pf->fontsize * 1.0, 0);
1240
1241 if (g && g->bits) {
1242 unsigned char * b;
1243 int xoff;
1244 int maxy;
1245 int xmod;
1246
1247 /* I'm sure this sorry excuse for a bitmap rendering routine can
1248 * be optimized quite a bit ;)
1249 */
1250 width = g->metrics.rightSideBearing - g->metrics.leftSideBearing;
1251 height = g->metrics.ascent - g->metrics.descent;
1252
1253 if(flags & MWTF_BASELINE)
1254 y -= g->metrics.ascent;
1255 else if(flags & MWTF_BOTTOM)
1256 y -= (height - 1);
1257 underliney = y + g->metrics.ascent;
1258
1259 b = g->bits;
1260 maxy = y + height;
1261
1262 /* if ((x + width) > psd->xvirtres) {
1263 xmod = (x + width - psd->xvirtres + 7) >> 3;
1264 width = width + x + width - psd->xvirtres;
1265 } else xmod = 0;
1266 */
1267 xmod = 0;
1268 while (y < maxy) {
1269 unsigned char data;
1270 xoff = 0;
1271 while (xoff < width ) {
1272 if (!(xoff % 8)) {
1273 data = *b;
1274 b++;
1275 }
1276
1277 if (GdClipPoint(psd, x+xoff,y)) {
1278 if (gr_usebg) {
1279 psd->DrawPixel(psd,x+xoff,y,
1280 data & (1 << (xoff % 8)) ?
1281 gr_foreground : gr_background);
1282 } else if (data & (1 << (xoff % 8))) {
1283 psd->DrawPixel(psd,x+xoff,y, gr_foreground);
1284 }
1285 }
1286 xoff++;
1287 }
1288 b += xmod;
1289 y++;
1290 }
1291 if (pf->fontattr & MWTF_UNDERLINE)
1292 GdLine(psd, x, underliney, x+xoff, underliney, FALSE);
1293 }
1294 }
1295
1296 if (g && g->bits) {
1297 /* Save some memory */
1298 free(g->bits);
1299 g->bits = 0; /* Make sure T1lib doesnt try to free it again */
1300 }
1301
1302 GdFixCursor(psd);
1303 }
1304
1305 static MWBOOL
1306 t1lib_getfontinfo(PMWFONT pfont, PMWFONTINFO pfontinfo)
1307 {
1308 int i;
1309 MWCOORD width, height, baseline;
1310
1311 /* FIXME, guess all sizes*/
1312 GdGetTextSize(pfont, "A", 1, &width, &height, &baseline, MWTF_ASCII);
1313 pfontinfo->height = height;
1314 pfontinfo->maxwidth = width;
1315 pfontinfo->baseline = 0;
1316 pfontinfo->firstchar = 32;
1317 pfontinfo->lastchar = 255;
1318 pfontinfo->fixed = TRUE;
1319 for(i=0; i<256; ++i)
1320 pfontinfo->widths[i] = width;
1321 return TRUE;
1322 }
1323
1324 /* Get the width and height of passed text string in the current font*/
1325 static void
1326 t1lib_gettextsize(PMWFONT pfont, const void *text, int cc,
1327 MWCOORD *pwidth, MWCOORD *pheight, MWCOORD *pbase)
1328 {
1329 PMWT1LIBFONT pf = (PMWT1LIBFONT)pfont;
1330 const unsigned char * str = text;
1331 GLYPH * g;
1332
1333 g = T1_SetString(pf->fontid, (char *)str, cc, 0,
1334 (pf->fontattr&MWTF_KERNING)? T1_KERNING: 0, pf->fontsize * 1.0, 0);
1335 *pwidth = g->metrics.rightSideBearing - g->metrics.leftSideBearing;
1336 *pheight = g->metrics.ascent - g->metrics.descent;
1337 if(g && g->bits) {
1338 free(g->bits);
1339 g->bits = 0;
1340 }
1341 #if 0
1342 BBox b;
1343
1344 /* FIXME. Something is *VERY* wrong here */
1345 b = T1_GetStringBBox(pf->fontid, str, cc, 0, (pf->fontattr&MWTF_KERNING)?T1_KERNING:0);
1346
1347 DPRINTF("b.urx = %d, b.llx = %d\n",b.urx, b.llx);
1348 DPRINTF("b.ury = %d, b.lly = %d\n",b.ury, b.lly);
1349 *pwidth = (b.urx - b.llx);
1350 *pheight = (b.lly - b.ury);
1351 #endif
1352 }
1353
1354 static void
1355 t1lib_destroyfont(PMWFONT pfont)
1356 {
1357 PMWT1LIBFONT pf = (PMWT1LIBFONT)pfont;
1358
1359 T1_DeleteAllSizes(pf->fontid);
1360 free(pf);
1361 }
1362
1363 #endif /* HAVE_T1LIB_SUPPORT*/
1364
1365 #if HAVE_FREETYPE_SUPPORT
1366 static OUTPIXELVAL gray_palette[5];
1367
1368 static int
1369 freetype_init(PSD psd)
1370 {
1371 static int inited = 0;
1372
1373 if (inited)
1374 return 1;
1375
1376 /* Init freetype library */
1377 if (TT_Init_FreeType (&engine) != TT_Err_Ok) {
1378 return 0;
1379 }
1380
1381 /* Init kerning extension */
1382 if (TT_Init_Kerning_Extension (engine) != TT_Err_Ok)
1383 return 0;
1384
1385 inited = 1;
1386 return 1;
1387 }
1388
1389 static PMWFREETYPEFONT
1390 freetype_createfont(const char *name, MWCOORD height, int attr)
1391 {
1392 PMWFREETYPEFONT pf;
1393 unsigned short i, n;
1394 unsigned short platform, encoding;
1395 TT_Face_Properties properties;
1396 char * p;
1397 char fontname[128];
1398
1399 /* check for pathname prefix*/
1400 if (strchr(name, '/') != NULL)
1401 strcpy(fontname, name);
1402 else {
1403 strcpy(fontname, FREETYPE_FONT_DIR);
1404 strcat(fontname, "/");
1405 strcat(fontname, name);
1406 }
1407
1408 /* check for extension*/
1409 if ((p = strrchr(fontname, '.')) == NULL ||
1410 strcmp(p, ".ttf") != 0) {
1411 strcat(fontname, ".ttf");
1412 }
1413
1414 /* allocate font structure*/
1415 pf = (PMWFREETYPEFONT)calloc(sizeof(MWFREETYPEFONT), 1);
1416 if (!pf)
1417 return NULL;
1418 pf->fontprocs = &freetype_procs;
1419
1420 /* Load face */
1421 if (TT_Open_Face (engine, fontname, &pf->face) != TT_Err_Ok)
1422 goto out;
1423
1424 /* Load first kerning table */
1425 pf->can_kern = TRUE;
1426 if (TT_Load_Kerning_Table (pf->face, 0) != TT_Err_Ok)
1427 pf->can_kern = FALSE;
1428 else {
1429 if (TT_Get_Kerning_Directory (pf->face, &pf->directory)
1430 != TT_Err_Ok)
1431 pf->can_kern = FALSE;
1432 else {
1433 /* Support only version 0 kerning table ... */
1434 if ((pf->directory.version != 0) ||
1435 (pf->directory.nTables <= 0) ||
1436 (pf->directory.tables->loaded != 1) ||
1437 (pf->directory.tables->version != 0) ||
1438 (pf->directory.tables->t.kern0.nPairs <= 0))
1439 pf->can_kern = FALSE;
1440 }
1441 }
1442
1443 /* get face properties and allocate preload arrays */
1444 TT_Get_Face_Properties (pf->face, &properties);
1445
1446 #if 0
1447 /*
1448 * Use header information for ascent and descent
1449 * to compute scaled ascent/descent for current font height.
1450 */
1451 h = properties.os2->sTypoAscender - properties.os2->sTypoDescender
1452 + properties.os2->sTypoLineGap;
1453 ascent = properties.os2->sTypoAscender
1454 + properties.os2->sTypoLineGap/2;
1455 pf->ascent = (ascent * height + h/2) / h;
1456 pf->descent = height - pf->ascent;
1457 #endif
1458 /* Create a glyph container */
1459 if (TT_New_Glyph (pf->face, &pf->glyph) != TT_Err_Ok)
1460 goto out;
1461
1462 /* create instance */
1463 if (TT_New_Instance (pf->face, &pf->instance) != TT_Err_Ok)
1464 goto out;
1465
1466 /* Set the instance resolution */
1467 if (TT_Set_Instance_Resolutions (pf->instance, 96, 96) != TT_Err_Ok)
1468 goto out;
1469
1470 /* Look for a Unicode charmap: Windows flavor of Apple flavor only */
1471 n = properties.num_CharMaps;
1472
1473 for (i = 0; i < n; i++) {
1474 TT_Get_CharMap_ID (pf->face, i, &platform, &encoding);
1475 if (((platform == TT_PLATFORM_MICROSOFT) &&
1476 (encoding == TT_MS_ID_UNICODE_CS)) ||
1477 ((platform == TT_PLATFORM_APPLE_UNICODE) &&
1478 (encoding == TT_APPLE_ID_DEFAULT)))
1479 {
1480 TT_Get_CharMap (pf->face, i, &pf->char_map);
1481 i = n + 1;
1482 }
1483 }
1484 if (i == n) {
1485 DPRINTF("freetype_createfont: no unicode map table\n");
1486 goto out;
1487 }
1488
1489 GdSetFontSize((PMWFONT)pf, height);
1490 GdSetFontRotation((PMWFONT)pf, 0);
1491 GdSetFontAttr((PMWFONT)pf, attr, 0);
1492
1493 return pf;
1494
1495 out:
1496 free(pf);
1497 return NULL;
1498 }
1499
1500 static int
1501 compute_kernval(PMWFREETYPEFONT pf, short current_glyph_code)
1502 {
1503 int i = 0;
1504 int kernval;
1505 int nPairs = pf->directory.tables->t.kern0.nPairs;
1506 TT_Kern_0_Pair *pair = pf->directory.tables->t.kern0.pairs;
1507
1508 if (pf->last_glyph_code != -1) {
1509 while ((pair->left != pf->last_glyph_code)
1510 && (pair->right != current_glyph_code))
1511 {
1512 pair++;
1513 i++;
1514 if (i == nPairs)
1515 break;
1516 }
1517
1518 if (i == nPairs)
1519 kernval = 0;
1520 else
1521 /* We round the value (hence the +32) */
1522 kernval = (pair->value + 32) & -64;
1523 } else
1524 kernval = 0;
1525
1526 return kernval;
1527 }
1528
1529 static TT_UShort
1530 Get_Glyph_Width(PMWFREETYPEFONT pf, TT_UShort glyph_index)
1531 {
1532 TT_Glyph_Metrics metrics;
1533
1534 if (TT_Load_Glyph ( pf->instance, pf->glyph,
1535 TT_Char_Index (pf->char_map,glyph_index),
1536 TTLOAD_SCALE_GLYPH|TTLOAD_HINT_GLYPH) != TT_Err_Ok)
1537 {
1538 /* Try to load default glyph: index 0 */
1539 if (TT_Load_Glyph ( pf->instance, pf->glyph, 0,
1540 TTLOAD_SCALE_GLYPH|TTLOAD_HINT_GLYPH) != TT_Err_Ok)
1541 return 0;
1542 }
1543
1544 TT_Get_Glyph_Metrics (pf->glyph, &metrics);
1545 return((metrics.advance & 0xFFFFFFC0) >> 6);
1546 }
1547
1548 static MWFREETYPEFONTCACHE *
1549 find_cache_glyph ( PMWFREETYPEFONT pf, unsigned curchar )
1550 {
1551 MWFREETYPEFONTCACHE ** inode = &pf->glyph_cache;
1552
1553 while (1)
1554 {
1555 if (*inode == 0)
1556 {
1557 *inode = calloc(sizeof(MWFREETYPEFONTCACHE),1);
1558 (*inode)->curchar = curchar;
1559 }
1560
1561 if (curchar < (*inode)->curchar)
1562 inode = &(*inode)->l;
1563 else if (curchar > (*inode)->curchar)
1564 inode = &(*inode)->r;
1565 else
1566 return *inode;
1567 }
1568 }
1569
1570 static void
1571 free_cache_glyph ( MWFREETYPEFONTCACHE * node )
1572 {
1573 if (node->l != 0)
1574 free_cache_glyph(node->l);
1575
1576 if (node->r != 0)
1577 free_cache_glyph(node->r);
1578
1579 free(node);
1580 }
1581
1582 /* Render a single glyph*/
1583 static void
1584 drawchar(PMWFREETYPEFONT pf, PSD psd, unsigned curchar, int x_offset,
1585 int y_offset)
1586 {
1587 TT_F26Dot6 xmin, ymin, xmax, ymax, x, y, z;
1588 unsigned char *src, *srcptr;
1589 MWPIXELVAL *dst, *dstptr;
1590 MWPIXELVAL *bitmap;
1591 int size, width, height;
1592 TT_Outline outline;
1593 TT_BBox bbox;
1594 TT_Raster_Map Raster;
1595 TT_Error error;
1596 /*MWPIXELVAL save;*/
1597 MWFREETYPEFONTCACHE * cache;
1598
1599 /* we begin by grid-fitting the bounding box */
1600 TT_Get_Glyph_Outline (pf->glyph, &outline);
1601 TT_Get_Outline_BBox (&outline, &bbox);
1602
1603 xmin = (bbox.xMin & -64) >> 6;
1604 ymin = (bbox.yMin & -64) >> 6;
1605 xmax = ((bbox.xMax + 63) & -64) >> 6;
1606 ymax = ((bbox.yMax + 63) & -64) >> 6;
1607 width = xmax - xmin;
1608 height = ymax - ymin;
1609 size = width * height;
1610
1611 /* now re-allocate the raster bitmap */
1612 Raster.rows = height;
1613 Raster.width = width;
1614
1615 if (pf->fontattr&MWTF_ANTIALIAS)
1616 Raster.cols = (Raster.width + 3) & -4; /* pad to 32-bits */
1617 else
1618 Raster.cols = (Raster.width + 7) & -8; /* pad to 64-bits ??? */
1619
1620 cache = find_cache_glyph(pf,curchar);
1621 /* SDR: if cache is 0 here, something really really bad happened */
1622
1623 Raster.flow = TT_Flow_Up;
1624 Raster.size = Raster.rows * Raster.cols;
1625 Raster.bitmap = cache->buffer;
1626
1627 if (Raster.bitmap == 0)
1628 {
1629 Raster.bitmap = malloc (Raster.size);
1630
1631 memset (Raster.bitmap, 0, Raster.size);
1632
1633 /* now render the glyph in the small pixmap */
1634
1635 /* IMPORTANT NOTE: the offset parameters passed to the function */
1636 /* TT_Get_Glyph_Bitmap() must be integer pixel values, i.e., */
1637 /* multiples of 64. HINTING WILL BE RUINED IF THIS ISN'T THE CASE! */
1638 /* This is why we _did_ grid-fit the bounding box, especially xmin */
1639 /* and ymin. */
1640
1641 if (!(pf->fontattr&MWTF_ANTIALIAS))
1642 error = TT_Get_Glyph_Bitmap (pf->glyph, &Raster,
1643 -xmin * 64, -ymin * 64);
1644 else
1645 error = TT_Get_Glyph_Pixmap (pf->glyph, &Raster,
1646 -xmin * 64, -ymin * 64);
1647
1648 if (error) {
1649 free (Raster.bitmap);
1650 return;
1651 }
1652
1653 cache->buffer = Raster.bitmap;
1654 }
1655
1656 #if MWFREETYPEFONT_CACHEBITMAP
1657 if ((memcmp(&gr_foreground,&cache->fg,sizeof(gr_foreground)) != 0) ||
1658 (memcmp(&gr_background,&cache->bg,sizeof(gr_background)) != 0) ||
1659 (gr_usebg != cache->usebg))
1660 {
1661 if (cache->bitmap)
1662 {
1663 free(cache->bitmap);
1664 cache->bitmap = 0;
1665 }
1666 }
1667
1668 bitmap = cache->bitmap;
1669 #else
1670 bitmap = 0;
1671 #endif
1672
1673 if (bitmap == 0)
1674 {
1675 bitmap = malloc (size * sizeof (MWPIXELVAL));
1676 memset (bitmap, 0, size * sizeof (MWPIXELVAL));
1677
1678 src = (char *) Raster.bitmap;
1679 dst = bitmap + (size - width);
1680
1681 for (y = ymin; y < ymax; y++)
1682 {
1683 srcptr = src;
1684 dstptr = dst;
1685
1686 for (x = xmin; x < xmax; x++)
1687 {
1688 if (pf->fontattr&MWTF_ANTIALIAS)
1689 *dstptr++ = gray_palette[(int) *srcptr];
1690 else
1691 {
1692 for ( z=0;
1693 z <= ((xmax-x-1) < 7 ? (xmax-x-1) : 7);
1694 z++ )
1695 *dstptr++ = ((*srcptr << z) & 0x80) ? gr_foreground : gr_background;
1696 x += 7;
1697 }
1698
1699 srcptr++;
1700 }
1701
1702 src += Raster.cols;
1703 dst -= width;
1704 }
1705 #if MWFREETYPEFONT_CACHEBITMAP
1706 cache->fg = gr_foreground;
1707 cache->bg = gr_background;
1708 cache->usebg = gr_usebg;
1709 cache->bitmap = bitmap;
1710 #endif
1711 }
1712
1713 /* Now draw the bitmap ... */
1714 GdArea(psd, x_offset + xmin, y_offset - (ymin + height), width, height,
1715 bitmap, MWPF_PIXELVAL);
1716
1717 #if !MWFREETYPEFONT_CACHEBITMAP
1718 free(bitmap);
1719 #endif
1720 }
1721
1722 /*
1723 * Draw unicode 16 text string using FREETYPE type font
1724 */
1725 static void
1726 freetype_drawtext(PMWFONT pfont, PSD psd, MWCOORD ax, MWCOORD ay,
1727 const void *text, int cc, int flags)
1728 {
1729 PMWFREETYPEFONT pf = (PMWFREETYPEFONT)pfont;
1730 const unsigned short * str = text;
1731 TT_F26Dot6 x = ax, y = ay;
1732 TT_Pos vec_x, vec_y;
1733 int i;
1734 TT_F26Dot6 startx, starty;
1735 TT_Outline outline;
1736 TT_UShort curchar;
1737 TT_Glyph_Metrics metrics;
1738 TT_Face_Properties properties;
1739 TT_Instance_Metrics imetrics;
1740 TT_F26Dot6 ascent, descent;
1741 static unsigned char blend[5] = { 0x00, 0x44, 0x88, 0xcc, 0xff };
1742 static unsigned char virtual_palette[5] = { 0, 1, 2, 3, 4 };
1743
1744 pf->last_glyph_code = -1; /* reset kerning*/
1745 pf->last_pen_pos = -32767;
1746
1747 /*
1748 * Compute instance ascent & descent values
1749 * in fractional units (1/64th pixel)
1750 */
1751 TT_Get_Face_Properties (pf->face, &properties);
1752 TT_Get_Instance_Metrics(pf->instance, &imetrics);
1753
1754 ascent = ((properties.horizontal->Ascender * imetrics.y_scale)/0x10000);
1755 descent = ((properties.horizontal->Descender*imetrics.y_scale)/0x10000);
1756
1757 /*
1758 * Offset the starting point if necessary,
1759 * FreeType always aligns at baseline
1760 */
1761 if (flags&MWTF_BOTTOM) {
1762 vec_x = 0;
1763 vec_y = descent;
1764 TT_Transform_Vector(&vec_x, &vec_y,&pf->matrix);
1765 x -= vec_x / 64;
1766 y += vec_y / 64;
1767 } else if (flags&MWTF_TOP) {
1768 vec_x = 0;
1769 vec_y = ascent;
1770 TT_Transform_Vector(&vec_x, &vec_y,&pf->matrix);
1771 x -= vec_x / 64;
1772 y += vec_y / 64;
1773 }
1774
1775 /* Set the "graylevels" */
1776 if (pf->fontattr&MWTF_ANTIALIAS) {
1777 TT_Set_Raster_Gray_Palette (engine, virtual_palette);
1778
1779 alphablend(psd, gray_palette, gr_foreground, gr_background,
1780 blend, 5);
1781 }
1782
1783 startx = x;
1784 starty = y;
1785 for (i = 0; i < cc; i++) {
1786 curchar = TT_Char_Index (pf->char_map, str[i]);
1787
1788 if (TT_Load_Glyph (pf->instance, pf->glyph, curchar,
1789 TTLOAD_DEFAULT) != TT_Err_Ok)
1790 continue;
1791
1792 if (pf->fontrotation) {
1793 TT_Get_Glyph_Outline (pf->glyph, &outline);
1794 TT_Transform_Outline (&outline, &pf->matrix);
1795 }
1796
1797 TT_Get_Glyph_Metrics (pf->glyph, &metrics);
1798
1799 if ((pf->fontattr&MWTF_KERNING) && pf->can_kern) {
1800 if (pf->fontrotation) {
1801 vec_x = compute_kernval(pf, curchar);
1802 vec_y = 0;
1803 TT_Transform_Vector(&vec_x, &vec_y,&pf->matrix);
1804
1805 x += vec_x / 64;
1806 y -= vec_y / 64;
1807 } else
1808 x += compute_kernval(pf, curchar) / 64;
1809 }
1810
1811 drawchar(pf, psd, curchar, x, y);
1812
1813 if (pf->fontrotation) {
1814 vec_x = metrics.advance;
1815 vec_y = 0;
1816 TT_Transform_Vector (&vec_x, &vec_y, &pf->matrix);
1817
1818 x += vec_x / 64;
1819 y -= vec_y / 64;
1820 } else {
1821 x += metrics.advance / 64;
1822
1823 /* Kerning point syndrome avoidance */
1824 if (pf->last_pen_pos > x)
1825 x = pf->last_pen_pos;
1826 pf->last_pen_pos = x;
1827 }
1828
1829 pf->last_glyph_code = curchar;
1830 }
1831
1832 if (pf->fontattr & MWTF_UNDERLINE)
1833 GdLine(psd, startx, starty, x, y, FALSE);
1834 }
1835
1836 /*
1837 * Return information about a specified font.
1838 */
1839 static MWBOOL
1840 freetype_getfontinfo(PMWFONT pfont, PMWFONTINFO pfontinfo)
1841 {
1842 int i;
1843 PMWFREETYPEFONT pf = (PMWFREETYPEFONT)pfont;
1844 TT_Face_Properties properties;
1845 TT_Instance_Metrics imetrics;
1846 TT_UShort last_glyph_index;
1847
1848 TT_Get_Face_Properties (pf->face, &properties);
1849 TT_Get_Instance_Metrics(pf->instance, &imetrics);
1850
1851 /* Fill up the fields */
1852 pfontinfo->height = (((properties.horizontal->Ascender * \
1853 imetrics.y_scale)/ 0x10000) >> 6) -
1854 (((properties.horizontal->Descender * \
1855 imetrics.y_scale)/ 0x10000) >> 6);
1856 pfontinfo->maxwidth = ((properties.horizontal->xMax_Extent * \
1857 imetrics.x_scale)/ 0x10000) >> 6;
1858 pfontinfo->baseline = ((properties.horizontal->Ascender * \
1859 imetrics.y_scale)/ 0x10000) >> 6;
1860 pfontinfo->firstchar = TT_CharMap_First(pf->char_map, NULL);
1861 pfontinfo->lastchar = TT_CharMap_Last(pf->char_map, NULL);
1862 pfontinfo->fixed = properties.postscript->isFixedPitch;
1863
1864 last_glyph_index = properties.num_Glyphs > 255 ? 255: properties.num_Glyphs-1;
1865
1866 /* Doesn't work ... don't know why ....*/
1867 #if 0
1868 if (TT_Get_Face_Widths( pf->face, 0,
1869 last_glyph_index, widths, NULL ) != TT_Err_Ok) {
1870 return TRUE;
1871 }
1872
1873 for(i=0; i<=last_glyph_index; i++)
1874 DPRINTF("widths[%d]: %d\n", i, widths[i]);
1875 #endif
1876
1877 /* Get glyphs widths */
1878 for(i=0; i<=last_glyph_index; i++)
1879 pfontinfo->widths[i] = Get_Glyph_Width(pf, i);
1880
1881 #if 0
1882 DPRINTF("x_ppem: %d\ny_ppem: %d\nx_scale: %d\ny_scale: %d\n\
1883 x_resolution: %d\ny_resolution: %d\n",
1884 imetrics.x_ppem, imetrics.y_ppem, imetrics.x_scale, \
1885 imetrics.y_scale, imetrics.x_resolution, imetrics.y_resolution);
1886
1887 DPRINTF("Ascender: %d\nDescender: %d\nxMax_Extent: %d\n\
1888 Mac Style Say Italic?: %d\nMac Style Say Bold?: %d\n\
1889 sTypoAscender: %d\nsTypoDescender: %d\nusWinAscent: %d\n\
1890 usWinDescent: %d\nusFirstCharIndex: %d\nusLastCharIndex: %d\n\
1891 OS2 Say Italic?: %d\nOS2 Say Bold?: %d\nOS2 Say monospaced?: %d\n\
1892 Postscript Say monospaced?: %d\n",\
1893 properties.horizontal->Ascender,
1894 properties.horizontal->Descender,
1895 properties.horizontal->xMax_Extent,
1896 (properties.header->Mac_Style & 0x2)?1:0,
1897 (properties.header->Mac_Style & 0x1)?1:0,
1898 properties.os2->sTypoAscender,
1899 properties.os2->sTypoDescender,
1900 properties.os2->usWinAscent,
1901 properties.os2->usWinDescent,
1902 properties.os2->usFirstCharIndex,
1903 properties.os2->usLastCharIndex,
1904 (properties.os2->fsSelection & 0x1)?1:0,
1905 (properties.os2->fsSelection & 0x20)?1:0,
1906 properties.postscript->isFixedPitch,
1907 (properties.os2->panose[3] == 9)?1:0);
1908 #endif
1909
1910 return TRUE;
1911 }
1912
1913 static void
1914 freetype_gettextsize(PMWFONT pfont, const void *text, int cc,
1915 MWCOORD *pwidth, MWCOORD *pheight, MWCOORD *pbase)
1916 {
1917 PMWFREETYPEFONT pf = (PMWFREETYPEFONT)pfont;
1918 const unsigned short * str = text;
1919 TT_F26Dot6 x = 0;
1920 int i;
1921 TT_UShort curchar;
1922 TT_Glyph_Metrics metrics;
1923 TT_Face_Properties properties;
1924 TT_Instance_Metrics imetrics;
1925
1926 TT_Get_Face_Properties (pf->face, &properties);
1927 TT_Get_Instance_Metrics(pf->instance, &imetrics);
1928
1929 pf->last_glyph_code = -1; /* reset kerning*/
1930 pf->last_pen_pos = -32767;
1931
1932 for (i = 0; i < cc; i++) {
1933 curchar = TT_Char_Index (pf->char_map, str[i]);
1934
1935 if (TT_Load_Glyph (pf->instance, pf->glyph, curchar,
1936 TTLOAD_SCALE_GLYPH|TTLOAD_HINT_GLYPH) != TT_Err_Ok)
1937 continue;
1938
1939 TT_Get_Glyph_Metrics (pf->glyph, &metrics);
1940
1941 if ((pf->fontattr&MWTF_KERNING) && pf->can_kern) {
1942 x += compute_kernval(pf, curchar) / 64;
1943 }
1944
1945 x += metrics.advance / 64;
1946
1947 /* Kerning point syndrome avoidance */
1948 if (pf->last_pen_pos > x)
1949 x = pf->last_pen_pos;
1950 pf->last_pen_pos = x;
1951
1952 pf->last_glyph_code = curchar;
1953 }
1954
1955 *pwidth = x;
1956 *pheight = (((properties.horizontal->Ascender *
1957 imetrics.y_scale)/ 0x10000) >> 6) -
1958 (((properties.horizontal->Descender *
1959 imetrics.y_scale)/ 0x10000) >> 6);
1960 /* FIXME: is it what's required ?? */
1961 *pbase = (((-properties.horizontal->Descender) *
1962 imetrics.y_scale)/ 0x10000) >> 6;
1963 }
1964
1965 static void
1966 freetype_destroyfont(PMWFONT pfont)
1967 {
1968 PMWFREETYPEFONT pf = (PMWFREETYPEFONT)pfont;
1969
1970 TT_Close_Face(pf->face);
1971
1972 /*----------*/
1973
1974 if (pf->glyph_cache != 0)
1975 free_cache_glyph(pf->glyph_cache);
1976
1977 /*----------*/
1978
1979 free(pf);
1980 }
1981
1982 static void
1983 freetype_setfontsize(PMWFONT pfont, MWCOORD fontsize)
1984 {
1985 PMWFREETYPEFONT pf = (PMWFREETYPEFONT)pfont;
1986
1987 pf->fontsize = fontsize;
1988
1989 /* We want real pixel sizes ... not points ...*/
1990 TT_Set_Instance_PixelSizes( pf->instance, pf->fontsize,
1991 pf->fontsize, pf->fontsize * 64 );
1992 #if 0
1993 /* set charsize (convert to points for freetype)*/
1994 TT_Set_Instance_CharSize (pf->instance,
1995 ((pf->fontsize * 72 + 96/2) / 96) * 64);
1996 #endif
1997 }
1998
1999 static void
2000 freetype_setfontrotation(PMWFONT pfont, int tenthdegrees)
2001 {
2002 PMWFREETYPEFONT pf = (PMWFREETYPEFONT)pfont;
2003 float angle;
2004
2005 pf->fontrotation = tenthdegrees;
2006
2007 /* Build the rotation matrix with the given angle */
2008 TT_Set_Instance_Transform_Flags (pf->instance, TRUE, FALSE);
2009
2010 angle = pf->fontrotation * M_PI / 1800;
2011 pf->matrix.yy = (TT_Fixed) (cos (angle) * (1 << 16));
2012 pf->matrix.yx = (TT_Fixed) (sin (angle) * (1 << 16));
2013 pf->matrix.xx = pf->matrix.yy;
2014 pf->matrix.xy = -pf->matrix.yx;
2015 }
2016
2017 #endif /* HAVE_FREETYPE_SUPPORT*/
2018
2019 /* UTF-8 to UTF-16 conversion. Surrogates are handeled properly, e.g.
2020 * a single 4-byte UTF-8 character is encoded into a surrogate pair.
2021 * On the other hand, if the UTF-8 string contains surrogate values, this
2022 * is considered an error and returned as such.
2023 *
2024 * The destination array must be able to hold as many Unicode-16 characters
2025 * as there are ASCII characters in the UTF-8 string. This in case all UTF-8
2026 * characters are ASCII characters. No more will be needed.
2027 *
2028 * Copyright (c) 2000 Morten Rolland, Screen Media
2029 */
2030 static int
2031 utf8_to_utf16(const unsigned char *utf8, int cc, unsigned short *unicode16)
2032 {
2033 int count = 0;
2034 unsigned char c0, c1;
2035 unsigned long scalar;
2036
2037 while(--cc >= 0) {
2038 c0 = *utf8++;
2039 /*DPRINTF("Trying: %02x\n",c0);*/
2040
2041 if ( c0 < 0x80 ) {
2042 /* Plain ASCII character, simple translation :-) */
2043 *unicode16++ = c0;
2044 count++;
2045 continue;
2046 }
2047
2048 if ( (c0 & 0xc0) == 0x80 )
2049 /* Illegal; starts with 10xxxxxx */
2050 return -1;
2051
2052 /* c0 must be 11xxxxxx if we get here => at least 2 bytes */
2053 scalar = c0;
2054 if(--cc < 0)
2055 return -1;
2056 c1 = *utf8++;
2057 /*DPRINTF("c1=%02x\n",c1);*/
2058 if ( (c1 & 0xc0) != 0x80 )
2059 /* Bad byte */
2060 return -1;
2061 scalar <<= 6;
2062 scalar |= (c1 & 0x3f);
2063
2064 if ( !(c0 & 0x20) ) {
2065 /* Two bytes UTF-8 */
2066 if ( scalar < 0x80 )
2067 return -1; /* Overlong encoding */
2068 *unicode16++ = scalar & 0x7ff;
2069 count++;
2070 continue;
2071 }
2072
2073 /* c0 must be 111xxxxx if we get here => at least 3 bytes */
2074 if(--cc < 0)
2075 return -1;
2076 c1 = *utf8++;
2077 /*DPRINTF("c1=%02x\n",c1);*/
2078 if ( (c1 & 0xc0) != 0x80 )
2079 /* Bad byte */
2080 return -1;
2081 scalar <<= 6;
2082 scalar |= (c1 & 0x3f);
2083
2084 if ( !(c0 & 0x10) ) {
2085 /*DPRINTF("####\n");*/
2086 /* Three bytes UTF-8 */
2087 if ( scalar < 0x800 )
2088 return -1; /* Overlong encoding */
2089 if ( scalar >= 0xd800 && scalar < 0xe000 )
2090 return -1; /* UTF-16 high/low halfs */
2091 *unicode16++ = scalar & 0xffff;
2092 count++;
2093 continue;
2094 }
2095
2096 /* c0 must be 1111xxxx if we get here => at least 4 bytes */
2097 c1 = *utf8++;
2098 if(--cc < 0)
2099 return -1;
2100 /*DPRINTF("c1=%02x\n",c1);*/
2101 if ( (c1 & 0xc0) != 0x80 )
2102 /* Bad byte */
2103 return -1;
2104 scalar <<= 6;
2105 scalar |= (c1 & 0x3f);
2106
2107 if ( !(c0 & 0x08) ) {
2108 /* Four bytes UTF-8, needs encoding as surrogates */
2109 if ( scalar < 0x10000 )
2110 return -1; /* Overlong encoding */
2111 scalar -= 0x10000;
2112 *unicode16++ = ((scalar >> 10) & 0x3ff) + 0xd800;
2113 *unicode16++ = (scalar & 0x3ff) + 0xdc00;
2114 count += 2;
2115 continue;
2116 }
2117
2118 return -1; /* No support for more than four byte UTF-8 */
2119 }
2120 return count;
2121 }
2122
2123 #if HAVE_HZK_SUPPORT
2124
2125 /* UniCode-16 (MWTF_UC16) to GB(MWTF_ASCII) Chinese Characters conversion.
2126 * a single 2-byte UC16 character is encoded into a surrogate pair.
2127 * return -1 ,if error;
2128 * The destination array must be able to hold as many
2129 * as there are Unicode-16 characters.
2130 *
2131 * Copyright (c) 2000 Tang Hao (TownHall)(tang_hao@263.net).
2132 */
2133 static int
2134 UC16_to_GB(const unsigned char *uc16, int cc, unsigned char *ascii)
2135 {
2136 FILE* fp;
2137 char buffer[256];
2138 unsigned char *uc16p;
2139 int i=0,j=0, k;
2140 unsigned char *filebuffer;
2141 unsigned short *uc16pp,*table;
2142 unsigned short uc16px;
2143 int length=31504;
2144
2145 if (use_big5)
2146 length=54840;
2147
2148 uc16p=(unsigned char *) uc16;
2149 uc16pp=(unsigned short *) uc16;
2150
2151 strcpy(buffer,HZK_FONT_DIR);
2152 if (use_big5)
2153 strcat(buffer,"/BG2UBG.KU");
2154 else
2155 strcat(buffer,"/UGB2GB.KU");
2156 if(!(fp = fopen(buffer, "rb")))
2157 {
2158 fprintf (stderr, "Error.\nThe %s file can not be found!\n",buffer);
2159 return -1;
2160 }
2161
2162 filebuffer= (unsigned char *)malloc ( length);
2163
2164 if(fread(filebuffer, sizeof(char),length, fp) < length) {
2165 fprintf (stderr, "Error in reading ugb2gb.ku file!\n");
2166 fclose(fp);
2167 return -1;
2168 }
2169 fclose(fp);
2170
2171 if (use_big5)
2172 {
2173 table=(unsigned short *)filebuffer;
2174 while(1)
2175 {
2176 if(j>=cc)
2177 {
2178 ascii[i]=0;
2179 break;
2180 }
2181 uc16px=*uc16pp;
2182 if((uc16px)<=0x00ff)
2183 {
2184 ascii[i]=(char)(*uc16pp);
2185 i++;
2186 }
2187 else
2188 {
2189 ascii[i]=0xa1; ascii[i+1]=0x40;
2190 for (k=0; k<13710; k++)
2191 {
2192 if (*(table+(k*2+1))==(uc16px))
2193 {
2194 ascii[i]=(char)((*(table+(k*2)) & 0xff00) >> 8);
2195 ascii[i+1]=(char)(*(table+(k*2)) & 0x00ff);
2196 break;
2197 }
2198 }
2199 i+=2;
2200 }
2201 uc16pp++; j++;
2202 }
2203 }
2204 else
2205 {
2206 while(1)
2207 {
2208 if(j>=cc)
2209 {
2210 ascii[i]=0;
2211 break;
2212 }
2213 if((*((uc16p)+j)==0)&&(*((uc16p)+j+1)==0))
2214 {
2215 ascii[i]=0;
2216 break;
2217 }
2218 else
2219 {
2220 if(*((uc16p)+j+1)==0)
2221 {
2222 ascii[i]=*((uc16p)+j);
2223 i++;
2224 j+=2;
2225 }
2226 else
2227 {
2228 /* to find the place of unicode charater .¶þ·Ö·¨Æ¥Åä*/
2229 {
2230 int p1=0,p2=length-4,p;
2231 unsigned int c1,c2,c,d;
2232 c1=((unsigned int )filebuffer[p1])*0x100+(filebuffer[p1+1]);
2233 c2=((unsigned int )filebuffer[p2])*0x100+(filebuffer[p2+1]);
2234 d=((unsigned int )*((uc16p)+j))*0x100+*((uc16p)+j+1);
2235 if(c1==d)
2236 {
2237 ascii[i]=filebuffer[p1+2];
2238 ascii[i+1]=filebuffer[p1+3];
2239 goto findit;
2240 }
2241 if(c2==d)
2242 {
2243 ascii[i]=filebuffer[p2+2];
2244 ascii[i+1]=filebuffer[p2+3];
2245 goto findit;
2246 }
2247 while(1)
2248 {
2249 p=(((p2-p1)/2+p1)>>2)<<2;
2250 c=((unsigned int )filebuffer[p])*0x100+(filebuffer[p+1]);
2251 if(d==c) /*find it*/
2252 {
2253 ascii[i]=filebuffer[p+2];
2254 ascii[i+1]=filebuffer[p+3];
2255 break;
2256 }
2257 else if(p2<=p1+4) /*can't find.*/
2258 {
2259 ascii[i]='.';/*((uc16p)+j);*/
2260 ascii[i+1]='.';/*((uc16p)+j+1);*/
2261 break;
2262 }
2263 else if(d<c)
2264 {
2265 p2=p;
2266 c2=c;
2267 }
2268 else
2269 {
2270 p1=p;
2271 c1=c;
2272 }
2273 }
2274 }
2275 findit:
2276 i+=2;
2277 j+=2;
2278 }
2279 }
2280 }
2281 }
2282 free(filebuffer);
2283
2284 return i;
2285 }
2286
2287 /************************** functions definition ******************************/
2288
2289 static int hzk_id( PMWHZKFONT pf )
2290 {
2291 switch(pf->font_height)
2292 {
2293 case 12:
2294 return 0;
2295 case 16: default:
2296 return 1;
2297 }
2298 }
2299
2300 /* This function get Chinese font info from etc file.*/
2301 static MWBOOL GetCFontInfo( PMWHZKFONT pf )
2302 {
2303 int charset;
2304
2305 if (use_big5)
2306 charset=(13094+408);
2307 else
2308 charset=8178;
2309
2310 CFont[hzk_id(pf)].width = pf->cfont_width;
2311 pf->CFont.width = pf->cfont_width;
2312
2313 CFont[hzk_id(pf)].height = pf->font_height;
2314 pf->CFont.height = pf->font_height;
2315
2316 CFont[hzk_id(pf)].size = ((pf->CFont.width + 7) / 8) *
2317 pf->CFont.height * charset;
2318 pf->CFont.size = ((pf->CFont.width + 7) / 8) * pf->CFont.height * charset;
2319
2320 if(pf->CFont.size < charset * 8)
2321 return FALSE;
2322
2323 strcpy(CFont[hzk_id(pf)].file,HZK_FONT_DIR);
2324 strcpy(pf->CFont.file,HZK_FONT_DIR);
2325
2326 if(pf->font_height==16)
2327 {
2328 strcat(CFont[hzk_id(pf)].file,"/hzk16");
2329 strcat(pf->CFont.file,"/hzk16");
2330 }
2331 else
2332 {
2333 strcat(CFont[hzk_id(pf)].file,"/hzk12");
2334 strcat(pf->CFont.file,"/hzk12");
2335 }
2336
2337 if (use_big5)
2338 {
2339 CFont[hzk_id(pf)].file[strlen(pf->CFont.file)-3]+=use_big5;
2340 pf->CFont.file[strlen(pf->CFont.file)-3]+=use_big5;
2341 }
2342
2343 return TRUE;
2344 }
2345
2346 /* This function get ASCII font info from etc file.*/
2347 static MWBOOL GetAFontInfo( PMWHZKFONT pf )
2348 {
2349 AFont[hzk_id(pf)].width = pf->afont_width;
2350 pf->AFont.width = pf->afont_width;
2351
2352 AFont[hzk_id(pf)].height = pf->font_height;
2353 pf->AFont.height = pf->font_height;
2354
2355 AFont[hzk_id(pf)].size = ((pf->AFont.width + 7) / 8) *
2356 pf->AFont.height * 255;
2357 pf->AFont.size = ((pf->AFont.width + 7) / 8) * pf->AFont.height * 255;
2358
2359 if(pf->AFont.size < 255 * 8)
2360 return FALSE;
2361
2362 strcpy(AFont[hzk_id(pf)].file,HZK_FONT_DIR);
2363 strcpy(pf->AFont.file,HZK_FONT_DIR);
2364
2365 if(pf->font_height==16)
2366 {
2367 strcat(AFont[hzk_id(pf)].file,"/asc16");
2368 strcat(pf->AFont.file,"/asc16");
2369 }
2370 else
2371 {
2372 strcat(AFont[hzk_id(pf)].file,"/asc12");
2373 strcat(pf->AFont.file,"/asc12");
2374 }
2375 return TRUE;
2376 }
2377
2378 /* This function load system font into memory.*/
2379 static MWBOOL LoadFont( PMWHZKFONT pf )
2380 {
2381 FILE* fp;
2382
2383 if(!GetCFontInfo(pf))
2384 {
2385 fprintf (stderr, "Get Chinese HZK font info failure!\n");
2386 return FALSE;
2387 }
2388 if(CFont[hzk_id(pf)].pFont == NULL)/*check font cache*/
2389 {
2390
2391
2392 /* Allocate system memory for Chinese font.*/
2393 if( !(CFont[hzk_id(pf)].pFont = (char *)malloc(pf->CFont.size)) )
2394 {
2395 fprintf (stderr, "Allocate memory for Chinese HZK font failure.\n");
2396 return FALSE;
2397 }
2398
2399 /* Open font file and read information to the system memory.*/
2400 fprintf (stderr, "Loading Chinese HZK font from file(%s)..." ,pf->CFont.file);
2401 if(!(fp = fopen(CFont[hzk_id(pf)].file, "rb")))
2402 {
2403 fprintf (stderr, "Error.\nThe Chinese HZK font file can not be found!\n");
2404 return FALSE;
2405 }
2406 if(fread(CFont[hzk_id(pf)].pFont, sizeof(char), pf->CFont.size, fp) < pf->CFont.size)
2407 {
2408 fprintf (stderr, "Error in reading Chinese HZK font file!\n");
2409 fclose(fp);
2410 return FALSE;
2411 }
2412
2413 fclose(fp);
2414
2415 CFont[hzk_id(pf)].use_count=0;
2416
2417 fprintf (stderr, "done.\n" );
2418
2419 }
2420 cfont_address = CFont[hzk_id(pf)].pFont;
2421 pf->cfont_address = CFont[hzk_id(pf)].pFont;
2422 pf->CFont.pFont = CFont[hzk_id(pf)].pFont;
2423
2424 CFont[hzk_id(pf)].use_count++;
2425
2426 if(!GetAFontInfo(pf))
2427 {
2428 fprintf (stderr, "Get ASCII HZK font info failure!\n");
2429 return FALSE;
2430 }
2431 if(AFont[hzk_id(pf)].pFont == NULL)/*check font cache*/
2432 {
2433
2434
2435 /* Allocate system memory for ASCII font.*/
2436 if( !(AFont[hzk_id(pf)].pFont = (char *)malloc(pf->AFont.size)) )
2437 {
2438 fprintf (stderr, "Allocate memory for ASCII HZK font failure.\n");
2439 free(CFont[hzk_id(pf)].pFont);
2440 CFont[hzk_id(pf)].pFont = NULL;
2441 return FALSE;
2442 }
2443
2444 /* Load ASCII font information to the near memory.*/
2445 fprintf (stderr, "Loading ASCII HZK font..." );
2446 if(!(fp = fopen(AFont[hzk_id(pf)].file, "rb")))
2447 {
2448 fprintf (stderr, "Error.\nThe ASCII HZK font file can not be found!\n");
2449 return FALSE;
2450 }
2451 if(fread(AFont[hzk_id(pf)].pFont, sizeof(char), pf->AFont.size, fp) < pf->AFont.size)
2452 {
2453 fprintf (stderr, "Error in reading ASCII HZK font file!\n");
2454 fclose(fp);
2455 return FALSE;
2456 }
2457
2458 fclose(fp);
2459
2460 AFont[hzk_id(pf)].use_count=0;
2461
2462 fprintf (stderr, "done.\n" );
2463
2464 }
2465 afont_address = AFont[hzk_id(pf)].pFont;
2466 pf->afont_address = AFont[hzk_id(pf)].pFont;
2467 pf->AFont.pFont = AFont[hzk_id(pf)].pFont;
2468
2469 AFont[hzk_id(pf)].use_count++;
2470
2471 return TRUE;
2472 }
2473
2474 /* This function unload system font from memory.*/
2475 static void UnloadFont( PMWHZKFONT pf )
2476 {
2477 CFont[hzk_id(pf)].use_count--;
2478 AFont[hzk_id(pf)].use_count--;
2479
2480 if (!CFont[hzk_id(pf)].use_count)
2481 {
2482 free(pf->CFont.pFont);
2483 free(pf->AFont.pFont);
2484
2485 CFont[hzk_id(pf)].pFont = NULL;
2486 AFont[hzk_id(pf)].pFont = NULL;
2487 }
2488 }
2489
2490 static int
2491 hzk_init(PSD psd)
2492 {
2493 /* FIXME: *.KU file should be opened and
2494 * read in here...*/
2495 return 1;
2496 }
2497
2498 static PMWHZKFONT
2499 hzk_createfont(const char *name, MWCOORD height, int attr)
2500 {
2501 PMWHZKFONT pf;
2502
2503 if(strcmp(name,"HZKFONT")!=0 && strcmp(name,"HZXFONT")!=0)
2504 return FALSE;
2505
2506 printf("hzk_createfont(%s,%d)\n",name,height);
2507
2508 use_big5=name[2]-'K';
2509
2510 /* allocate font structure*/
2511 pf = (PMWHZKFONT)calloc(sizeof(MWHZKFONT), 1);
2512 if (!pf)
2513 return NULL;
2514 pf->fontprocs = &hzk_procs;
2515
2516 pf->fontsize=height;
2517 /*GdSetFontSize((PMWFONT)pf, height);*/
2518 GdSetFontRotation((PMWFONT)pf, 0);
2519 GdSetFontAttr((PMWFONT)pf, attr, 0);
2520
2521 if(height==12)
2522 {
2523 afont_width = 6;
2524 cfont_width = 12;
2525 font_height = 12;
2526
2527 pf->afont_width = 6;
2528 pf->cfont_width = 12;
2529 pf->font_height = 12;
2530 }
2531 else
2532 {
2533 afont_width = 8;
2534 cfont_width = 16;
2535 font_height = 16;
2536
2537 pf->afont_width = 8;
2538 pf->cfont_width = 16;
2539 pf->font_height = 16;
2540 }
2541
2542 /* Load the font library to the system memory.*/
2543 if(!LoadFont(pf))
2544 return FALSE;
2545
2546 return pf;
2547 }
2548
2549 int IsBig5(int i)
2550 {
2551 if ((i>=0xa140 && i<=0xa3bf) || /* a140-a3bf(!a3e0) */
2552 (i>=0xa440 && i<=0xc67e) || /* a440-c67e */
2553 (i>=0xc6a1 && i<=0xc8d3) || /* c6a1-c8d3(!c8fe) */
2554 (i>=0xc940 && i<=0xf9fe)) /* c940-f9fe */
2555 return 1;
2556 else
2557 return 0;
2558 }
2559
2560 /*
2561 * following several function is used in hzk_drawtext
2562 */
2563
2564 static int getnextchar(char* s, unsigned char* cc)
2565 {
2566 if( s[0] == '\0') return 0;
2567
2568 cc[0] = (unsigned char)(*s);
2569 cc[1] = (unsigned char)(*(s + 1));
2570
2571 if (use_big5)
2572 {
2573 if( IsBig5( (int) ( (cc[0] << 8) + cc[1]) ) )
2574 return 1;
2575 }
2576 else
2577 {
2578 if( ((unsigned char)cc[0] > 0xa0) &&
2579 ((unsigned char)cc[1] > 0xa0) )
2580 return 1;
2581 }
2582
2583 cc[1] = '\0';
2584
2585 return 1;
2586 }
2587
2588 static void
2589 expandcchar(PMWHZKFONT pf, int bg, int fg, unsigned char* c, MWPIXELVAL* bitmap)
2590 {
2591 int i=0;
2592 int c1, c2, seq;
2593 int x,y;
2594 unsigned char *font;
2595 int b = 0; /* keep gcc happy with b = 0 - MW */
2596
2597 int pixelsize;
2598 pixelsize=sizeof(MWPIXELVAL);
2599
2600 c1 = c[0];
2601 c2 = c[1];
2602 if (use_big5)
2603 {
2604 seq=0;
2605 /*ladd=loby-(if(loby<127)?64:98)*/
2606 c2-=(c2<127?64:98);
2607
2608 /*hadd=(hiby-164)*157*/
2609 if (c1>=0xa4)/*standard font*/
2610 {
2611 seq=(((c1-164)*157)+c2);
2612 if (seq>=5809) seq-=408;
2613 }
2614
2615 /*hadd=(hiby-161)*157*/
2616 if (c1<=0xa3)/*special font*/
2617 seq=(((c1-161)*157)+c2)+13094;
2618 }
2619 else
2620 seq=((c1 - 161)*94 + c2 - 161);
2621
2622 font = pf->cfont_address + ((seq) *
2623 (pf->font_height * ((pf->cfont_width + 7) / 8)));
2624
2625 for (y = 0; y < pf->font_height; y++)
2626 for (x = 0; x < pf->cfont_width; x++)
2627 {
2628 if (x % 8 == 0)
2629 b = *font++;
2630
2631 if (b & (128 >> (x % 8))) /* pixel */
2632 bitmap[i++]=fg;
2633 else
2634 bitmap[i++]=bg;
2635 }
2636 }
2637
2638 static void expandchar(PMWHZKFONT pf, int bg, int fg, int c, MWPIXELVAL* bitmap)
2639 {
2640 int i=0;
2641 int x,y;
2642 unsigned char *font;
2643 int pixelsize;
2644 int b = 0; /* keep gcc happy with b = 0 - MW */
2645
2646 pixelsize=sizeof(MWPIXELVAL);
2647
2648 font = pf->afont_address + c * (pf->font_height *
2649 ((pf->afont_width + 7) / 8));
2650
2651 for (y = 0; y < pf->font_height; y++)
2652 for (x = 0; x < pf->afont_width; x++)
2653 {
2654 if (x % 8 == 0)
2655 b = *font++;
2656 if (b & (128 >> (x % 8))) /* pixel */
2657 bitmap[i++]=fg;
2658 else
2659 bitmap[i++]=bg;
2660 }
2661 }
2662
2663 /*
2664 * Draw ASCII text string using HZK type font
2665 */
2666 static void
2667 hzk_drawtext(PMWFONT pfont, PSD psd, MWCOORD ax, MWCOORD ay,
2668 const void *text, int cc, int flags)
2669 {
2670 PMWHZKFONT pf=(PMWHZKFONT)pfont;
2671
2672 unsigned char c[2];
2673 MWPIXELVAL *bitmap;
2674 unsigned char s1[3];
2675 char *s,*sbegin;
2676
2677 s=(char *)text;
2678
2679 if(cc==1)
2680 {
2681 s1[0]=*((unsigned char*)text);
2682 s1[1]=0x0;
2683 s1[2]=0x0;
2684 s=s1;
2685 }
2686
2687 sbegin=s;
2688 bitmap = (MWPIXELVAL *)ALLOCA(pf->cfont_width * pf->font_height *
2689 sizeof(MWPIXELVAL));
2690
2691 while( getnextchar(s, c) )
2692 {
2693 if( c[1] != '\0')
2694 {
2695 expandcchar(pf, gr_background,gr_foreground,
2696 c, bitmap);
2697 /* Now draw the bitmap ... */
2698
2699 if (flags&MWTF_TOP)
2700 GdArea(psd,ax, ay, pf->cfont_width,
2701 pf->font_height, bitmap, MWPF_PIXELVAL);
2702 else
2703 GdArea(psd,ax, ay-pf->font_height+2,
2704 pf->cfont_width, pf->font_height,
2705 bitmap, MWPF_PIXELVAL);
2706
2707 s += 2;
2708 ax += pf->cfont_width;
2709 }
2710 else
2711 {
2712 expandchar(pf, gr_background,gr_foreground,
2713 c[0], bitmap);
2714 /* Now draw the bitmap ... */
2715
2716 if (flags&MWTF_TOP)
2717 GdArea(psd,ax, ay, pf->afont_width,
2718 pf->font_height, bitmap, MWPF_PIXELVAL);
2719 else
2720 GdArea(psd,ax, ay-pf->font_height+2,
2721 pf->afont_width, pf->font_height,
2722 bitmap, MWPF_PIXELVAL);
2723
2724 s += 1;
2725 ax += pf->afont_width;
2726 }
2727
2728 if(s>=sbegin+cc)break;
2729 }
2730
2731 FREEA(bitmap);
2732 }
2733
2734 /*
2735 * Return information about a specified font.
2736 */
2737 static MWBOOL
2738 hzk_getfontinfo(PMWFONT pfont, PMWFONTINFO pfontinfo)
2739 {
2740 PMWHZKFONT pf=(PMWHZKFONT)pfont;
2741
2742 int i;
2743
2744 pfontinfo->height = pf->font_height;
2745 pfontinfo->maxwidth = pf->cfont_width;
2746 pfontinfo->baseline = pf->font_height-2;
2747 pfontinfo->firstchar = 0;
2748 pfontinfo->lastchar = 0;
2749 pfontinfo->fixed = TRUE;
2750
2751 for(i=0; i<=256; i++)
2752 pfontinfo->widths[i] = pf->afont_width;
2753
2754 return TRUE;
2755 }
2756
2757 static void
2758 hzk_gettextsize(PMWFONT pfont, const void *text, int cc,
2759 MWCOORD *pwidth, MWCOORD *pheight, MWCOORD *pbase)
2760 {
2761 PMWHZKFONT pf=(PMWHZKFONT)pfont;
2762
2763 unsigned char c[2];
2764 char *s,*sbegin;
2765 unsigned char s1[3];
2766
2767 int ax=0;
2768
2769
2770
2771 s=(char *)text;
2772 if(cc==0)
2773 {
2774 *pwidth = 0;
2775 *pheight = pf->font_height;
2776 *pbase = pf->font_height-2;
2777
2778 }
2779 if(cc==1)
2780 {
2781 s1[0]=*((unsigned char*)text);
2782 s1[1]=0x0;
2783 s1[2]=0x0;
2784 s=s1;
2785 }
2786 sbegin=s;
2787 while( getnextchar(s, c) )
2788 {
2789 if( c[1] != '\0')
2790 {
2791 s += 2;
2792 ax += pf->cfont_width;
2793 }
2794 else
2795 {
2796 s += 1;
2797 ax += pf->afont_width;
2798 }
2799 if(s>=sbegin+cc)break;
2800 /* fprintf(stderr,"s=%x,sbegin=%x,cc=%x\n",s,sbegin,cc);*/
2801
2802 }
2803 /* fprintf(stderr,"ax=%d,\n",ax);*/
2804
2805 *pwidth = ax;
2806 *pheight = pf->font_height;
2807 *pbase = pf->font_height-2;
2808 }
2809
2810 static void
2811 hzk_destroyfont(PMWFONT pfont)
2812 {
2813 PMWHZKFONT pf=(PMWHZKFONT)pfont;
2814
2815 UnloadFont(pf);
2816 free(pf);
2817 }
2818
2819 static void
2820 hzk_setfontsize(PMWFONT pfont, MWCOORD fontsize)
2821 {
2822 PMWHZKFONT pf=(PMWHZKFONT)pfont;
2823
2824 /*jmt: hzk_setfontsize not supported*/
2825 /*jmt: & pf->fontsize can't be changed*/
2826 /*jmt: because of hzk_id() :p*/
2827 pf->fontsize=pf->font_height;
2828 }
2829 #endif /* HAVE_HZK_SUPPORT*/
2830
2831 /* FIXME: this routine should work for all font renderers...*/
2832 int
2833 GdGetTextSizeEx(PMWFONT pfont, const void *str, int cc,int nMaxExtent,
2834 int* lpnFit, int* alpDx,MWCOORD *pwidth,MWCOORD *pheight,
2835 MWCOORD *pbase, int flags)
2836 {
2837 #ifdef HAVE_FREETYPE_SUPPORT
2838 unsigned short buf[256];
2839 unsigned short* text;
2840 PMWFREETYPEFONT pf = (PMWFREETYPEFONT)pfont;
2841 int defencoding = pf->fontprocs->encoding;
2842 int x = 0;
2843 int i;
2844 TT_UShort curchar;
2845 TT_Glyph_Metrics metrics;
2846 TT_Face_Properties properties;
2847 TT_Instance_Metrics imetrics;
2848
2849 if ((cc<0)||(!str))
2850 {
2851 *pwidth = *pheight = *pbase = 0;
2852 return 0;
2853 }
2854 /* convert encoding if required*/
2855 if((flags & MWTF_PACKMASK) != defencoding)
2856 {
2857 cc = GdConvertEncoding(str, flags, cc, buf, defencoding);
2858 flags &= ~MWTF_PACKMASK;
2859 flags |= defencoding;
2860 text=buf;
2861 } else text =(unsigned short*)str;
2862 if(cc <= 0)
2863 {
2864 *pwidth = *pheight = *pbase = 0;
2865 return 0;
2866 }
2867
2868 TT_Get_Face_Properties (pf->face, &properties);
2869 TT_Get_Instance_Metrics(pf->instance, &imetrics);
2870
2871 pf->last_glyph_code = -1; /* reset kerning*/
2872 pf->last_pen_pos = -32767;
2873 if (lpnFit)
2874 *lpnFit=-1;
2875 for (i = 0; i < cc; i++)
2876 {
2877 curchar = TT_Char_Index (pf->char_map,text[i]);
2878
2879 if (TT_Load_Glyph (pf->instance, pf->glyph, curchar,
2880 TTLOAD_SCALE_GLYPH|TTLOAD_HINT_GLYPH) != TT_Err_Ok)
2881 {
2882 printf("Unable to load glyph with index=%d\n",curchar);
2883 return 0;
2884 }
2885 TT_Get_Glyph_Metrics (pf->glyph, &metrics);
2886 if ((pf->fontattr&MWTF_KERNING) && pf->can_kern)
2887 {
2888 x += compute_kernval(pf, curchar) / 64;
2889 }
2890 x += metrics.advance / 64;
2891 if((lpnFit)&&(alpDx))
2892 {
2893 if (x<=nMaxExtent)
2894 alpDx[i]=x;
2895 else
2896 if (*lpnFit==-1)
2897 (*lpnFit)=i;
2898 }
2899 /* Kerning point syndrome avoidance */
2900 if (pf->last_pen_pos > x)
2901 x = pf->last_pen_pos;
2902 pf->last_pen_pos = x;
2903 pf->last_glyph_code = curchar;
2904 }
2905 if ((lpnFit)&&(*lpnFit==-1))
2906 *lpnFit=cc;
2907 *pwidth = x;
2908 *pheight = (((properties.horizontal->Ascender *
2909 imetrics.y_scale)/ 0x10000) >> 6) -
2910 (((properties.horizontal->Descender *
2911 imetrics.y_scale)/ 0x10000) >> 6);
2912 /*FIXME: is it what's required ??*/
2913 if (pbase)
2914 *pbase = (((-properties.horizontal->Descender) *
2915 imetrics.y_scale)/ 0x10000) >> 6;
2916 return 1;
2917 #else /* HAVE_FREETYPE_SUPPORT*/
2918 *pwidth = *pheight = *pbase = 0;
2919 return 0;
2920 #endif
2921 }