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
7 * Device-independent font and text drawing routines
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.
23 #if (UNIX | DOS_DJGPP)
24 #define strcmpi strcasecmp
27 #if HAVE_T1LIB_SUPPORT
29 #define T1LIB_USE_AA_HIGH
32 PMWFONTPROCS fontprocs; /* common hdr*/
37 int fontid; /* t1lib stuff*/
38 } MWT1LIBFONT, *PMWT1LIBFONT;
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);
49 /* handling routines for MWT1LIBFONT*/
50 static MWFONTPROCS t1lib_procs = {
51 MWTF_ASCII, /* routines expect ascii*/
54 NULL, /* gettextbits*/
57 NULL, /* setfontsize*/
58 NULL, /* setfontrotation*/
59 NULL, /* setfontattr*/
63 #ifdef T1LIB_USE_AA_HIGH
64 typedef unsigned long OUTPIXELVAL;
66 typedef MWPIXELVAL OUTPIXELVAL;
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>
79 typedef struct xTT_Glyph_Cache_ {
86 struct xTT_Glyph_Cache_ * l;
87 struct xTT_Glyph_Cache_ * r;
91 typedef struct xTT_Instance_Object_ {
96 xTT_Glyph_Cache * head;
98 } xTT_Instance_Object;
100 typedef struct xTT_Instance_ {
102 xTT_Instance_Object * instance;
106 typedef struct xTT_Outline_Object_ {
111 } xTT_Outline_Object;
113 typedef struct xTT_Outline_ {
115 xTT_Outline_Object * outline;
119 typedef struct xTT_Glyph_Object_ {
123 xTT_Outline_Object outline;
127 typedef struct xTT_Glyph_ {
129 xTT_Glyph_Object * glyph;
134 xTT_Glyph_Cache_Find ( xTT_Instance instance,
136 TT_UShort glyphIndex,
137 TT_UShort loadFlags )
139 xTT_Glyph_Cache * node;
140 xTT_Glyph_Cache ** inode = &instance.instance->head;
150 node = *inode = calloc(1,sizeof(**inode));
153 return TT_Err_Out_Of_Memory;
155 node->error = TT_New_Glyph(instance.instance->face,&(node->glyph));
157 if (node->error == 0)
158 node->error = TT_Load_Glyph(instance.instance->instance,
160 (node->index = glyphIndex),
161 (node->flags = loadFlags));
163 if (node->error != 0)
164 TT_Done_Glyph(node->glyph);
171 if (glyphIndex < node->index)
173 else if (glyphIndex > node->index)
175 else if (loadFlags < node->flags)
177 else if (loadFlags > node->flags)
181 static int count [] = { 0, 0 };
183 printf("\r(%s | hit %d | miss %d)",__TIME__,count[0],count[1]);
184 glyph.glyph->glyph = &node->glyph;
191 xTT_Glyph_Cache_Free ( xTT_Glyph_Cache ** pnode )
193 xTT_Glyph_Cache * node;
204 xTT_Glyph_Cache_Free(&node->l);
207 xTT_Glyph_Cache_Free(&node->r);
209 TT_Done_Glyph(node->glyph);
216 xTT_New_Instance ( TT_Face face,
217 xTT_Instance * instance )
219 instance->instance = calloc(1,sizeof(*instance->instance));
220 if (instance->instance == 0)
221 return TT_Err_Out_Of_Memory;
223 instance->instance->face = face;
224 instance->instance->head = 0;
226 return TT_New_Instance(face,&instance->instance->instance);
230 xTT_Done_Instance ( xTT_Instance instance )
234 xTT_Glyph_Cache_Free(&instance.instance->head);
235 error = TT_Done_Instance(instance.instance->instance);
237 free(instance.instance);
243 xTT_Get_Instance_Metrics ( xTT_Instance instance,
244 TT_Instance_Metrics * imetrics )
246 return TT_Get_Instance_Metrics(instance.instance->instance,imetrics);
250 xTT_Set_Instance_CharSize ( xTT_Instance instance,
251 TT_F26Dot6 charsize )
253 xTT_Glyph_Cache_Free(&instance.instance->head);
254 return TT_Set_Instance_CharSize(instance.instance->instance,charsize);
258 xTT_Set_Instance_PixelSizes ( xTT_Instance instance,
259 TT_UShort pixelWidth,
260 TT_UShort pixelHeight,
261 TT_F26Dot6 pointSize )
263 xTT_Glyph_Cache_Free(&instance.instance->head);
264 return TT_Set_Instance_PixelSizes(instance.instance->instance,
271 xTT_Set_Instance_Transform_Flags ( xTT_Instance instance,
275 xTT_Glyph_Cache_Free(&instance.instance->head);
276 return TT_Set_Instance_Resolutions(instance.instance->instance,
282 xTT_Set_Instance_Resolutions ( xTT_Instance instance,
283 TT_UShort xResolution,
284 TT_UShort yResolution )
286 xTT_Glyph_Cache_Free(&instance.instance->head);
287 return TT_Set_Instance_Resolutions(instance.instance->instance,
293 xTT_New_Glyph ( TT_Face face,
296 glyph->glyph = calloc(1,sizeof(*glyph->glyph));
297 if (glyph->glyph == 0)
298 return TT_Err_Out_Of_Memory;
303 xTT_Done_Glyph ( xTT_Glyph glyph )
310 xTT_Load_Glyph ( xTT_Instance instance,
312 TT_UShort glyphIndex,
313 TT_UShort loadFlags )
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);
325 xTT_Get_Glyph_Metrics ( xTT_Glyph glyph,
326 TT_Glyph_Metrics * metrics )
328 return TT_Get_Glyph_Metrics(*glyph.glyph->glyph,metrics);
332 xTT_Get_Glyph_Outline ( xTT_Glyph glyph,
333 xTT_Outline * outline )
335 outline->outline = &glyph.glyph->outline;
340 xTT_Get_Outline_BBox ( xTT_Outline * outline,
343 *bbox = outline->outline->bbox;
348 xTT_Transform_Outline ( xTT_Outline * outline,
351 TT_Transform_Outline(&outline->outline->outline,matrix);
352 TT_Get_Outline_BBox(&outline->outline->outline,
353 &outline->outline->bbox);
357 xTT_Get_Glyph_Bitmap ( xTT_Glyph glyph,
358 TT_Raster_Map * bitmap,
362 return TT_Get_Glyph_Bitmap(*glyph.glyph->glyph,
369 xTT_Get_Glyph_Pixmap ( xTT_Glyph glyph,
370 TT_Raster_Map * pixmap,
374 return TT_Get_Glyph_Pixmap(*glyph.glyph->glyph,
386 #define TT_Instance xTT_Instance
387 #define TT_Outline xTT_Outline
388 #define TT_Glyph xTT_Glyph
390 #define TT_New_Instance xTT_New_Instance
391 #define TT_Done_Instance xTT_Done_Instance
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
399 #define TT_New_Glyph xTT_New_Glyph
400 #define TT_Done_Glyph xTT_Done_Glyph
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
408 #define TT_Get_Outline_BBox xTT_Get_Outline_BBox
409 #define TT_Transform_Outline xTT_Transform_Outline
415 #ifndef FREETYPE_FONT_DIR
416 #define FREETYPE_FONT_DIR "/usr/local/microwin/fonts"
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"
424 #ifndef MWFREETYPEFONT_CACHE
425 #define MWFREETYPEFONT_CACHE 1
428 #if MWFREETYPEFONT_CACHE
430 #ifndef MWFREETYPEFONT_CACHEBITMAP
431 #define MWFREETYPEFONT_CACHEBITMAP 1
434 typedef struct mwfreetypefontcache {
437 #if MWFREETYPEFONT_CACHEBITMAP
443 struct mwfreetypefontcache * l;
444 struct mwfreetypefontcache * r;
445 } MWFREETYPEFONTCACHE;
451 PMWFONTPROCS fontprocs; /* common hdr*/
456 TT_Face face; /* freetype stuff*/
457 TT_Instance instance;
459 TT_Kerning directory;
463 short last_glyph_code;
466 #if MWFREETYPEFONT_CACHE
467 MWFREETYPEFONTCACHE * glyph_cache;
470 } MWFREETYPEFONT, *PMWFREETYPEFONT;
472 static int freetype_init(PSD psd);
473 static PMWFREETYPEFONT freetype_createfont(const char *name, MWCOORD height,
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);
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,
492 freetype_setfontsize,
493 freetype_setfontrotation,
494 NULL, /* setfontattr*/
497 static TT_Engine engine; /* THE ONLY freetype engine */
498 #endif /* HAVE_FREETYPE_SUPPORT*/
502 * 12x12 and 16x16 ascii and chinese fonts
503 * Big5 and GB2312 encodings supported
510 unsigned long use_count;
512 char file[MAX_PATH + 1];
515 static int use_big5=1;
516 static HZKFONT CFont[2]; /* font cache*/
517 static HZKFONT AFont[2]; /* font cache*/
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;
527 PMWFONTPROCS fontprocs; /* common hdr*/
532 HZKFONT CFont; /* hzkfont stuff */
539 } MWHZKFONT, *PMWHZKFONT;
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);*/
554 /* handling routines for MWHZKFONT*/
555 static MWFONTPROCS hzk_procs = {
556 MWTF_ASCII, /* routines expect ASCII*/
559 NULL, /* hzk_gettextbits*/
563 NULL, /* setfontrotation*/
564 NULL, /* setfontattr*/
568 UC16_to_GB(const unsigned char *uc16, int cc, unsigned char *ascii);
569 #endif /* HAVE_HZK_SUPPORT*/
571 static PMWFONT gr_pfont; /* current font*/
573 /* temp extern decls*/
574 extern MWPIXELVAL gr_foreground;
575 extern MWPIXELVAL gr_background;
576 extern MWBOOL gr_usebg;
578 static int utf8_to_utf16(const unsigned char *utf8, int cc,
579 unsigned short *unicode16);
582 /* entry point for font selection*/
583 int select_font(const PMWLOGFONT plogfont, char *physname);
587 * Set the font for future calls.
590 GdSetFont(PMWFONT pfont)
592 PMWFONT oldfont = gr_pfont;
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.
602 * If height is 0, return builtin font from passed name.
603 * Otherwise find builtin font best match based on height.
606 GdCreateFont(PSD psd, const char *name, MWCOORD height,
607 const PMWLOGFONT plogfont)
615 PMWCOREFONT pf = psd->builtin_fonts;
617 MWSCREENINFO scrinfo;
620 GdGetScreenInfo(psd, &scrinfo);
622 /* if plogfont not specified, use name and height*/
625 name = MWFONT_SYSTEM_VAR;
626 strcpy(fontname, name);
627 fontclass = MWLF_CLASS_ANY;
630 /* otherwise, use MWLOGFONT name and height*/
631 fontclass = select_font(plogfont, fontname);
634 name = MWFONT_SYSTEM_VAR;
635 strcpy(fontname, name);
636 fontclass = MWLF_CLASS_ANY;
638 height = plogfont->lfHeight;
639 if (plogfont->lfUnderline)
640 fontattr = MWTF_UNDERLINE;
642 height = abs(height);
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];
658 /* return first builtin font*/
659 if (height == 0 || fontclass == MWLF_CLASS_BUILTIN)
664 /* Make sure the library is initialized */
666 pfont = (PMWFONT)hzk_createfont(name, height, fontattr);
669 printf("hzk_createfont: %s not found\n", name);
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 &&
679 fontattr |= MWTF_ANTIALIAS;
681 pfont = (PMWFONT)freetype_createfont(fontname, height,
684 /* temp kaffe kluge*/
685 pfont->fontattr |= FS_FREETYPE;
688 DPRINTF("freetype_createfont: %s,%d not found\n",
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,
701 DPRINTF("t1lib_createfont: %s,%d not found\n",
707 /* find builtin font closest in height*/
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)) {
717 fontht = abs(height-fontinfo.height);
720 pf[fontno].fontsize = pf[fontno].cfont->height;
721 pf[fontno].fontattr = fontattr;
722 return (PMWFONT)&pf[fontno];
726 /* Return first builtin font*/
727 pf->fontsize = pf->cfont->height;
728 pf->fontattr = fontattr;
729 return (PMWFONT)&pf[0];
732 /* Set the font size for the passed font*/
734 GdSetFontSize(PMWFONT pfont, MWCOORD fontsize)
736 MWCOORD oldfontsize = pfont->fontsize;
738 pfont->fontsize = fontsize;
740 if (pfont->fontprocs->SetFontSize)
741 pfont->fontprocs->SetFontSize(pfont, fontsize);
746 /* Set the font rotation angle in tenths of degrees for the passed font*/
748 GdSetFontRotation(PMWFONT pfont, int tenthdegrees)
750 MWCOORD oldrotation = pfont->fontrotation;
752 pfont->fontrotation = tenthdegrees;
754 if (pfont->fontprocs->SetFontRotation)
755 pfont->fontprocs->SetFontRotation(pfont, tenthdegrees);
761 * Set/reset font attributes (MWTF_KERNING, MWTF_ANTIALIAS)
762 * for the passed font.
765 GdSetFontAttr(PMWFONT pfont, int setflags, int clrflags)
767 MWCOORD oldattr = pfont->fontattr;
769 pfont->fontattr &= ~clrflags;
770 pfont->fontattr |= setflags;
772 if (pfont->fontprocs->SetFontAttr)
773 pfont->fontprocs->SetFontAttr(pfont, setflags, clrflags);
778 /* Unload and deallocate font*/
780 GdDestroyFont(PMWFONT pfont)
782 if (pfont->fontprocs->DestroyFont)
783 pfont->fontprocs->DestroyFont(pfont);
786 /* Return information about a specified font*/
788 GdGetFontInfo(PMWFONT pfont, PMWFONTINFO pfontinfo)
790 if(!pfont || !pfont->fontprocs->GetFontInfo)
793 return pfont->fontprocs->GetFontInfo(pfont, pfontinfo);
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
802 GdConvertEncoding(const void *istr, int iflags, int cc, void *ostr, int oflags)
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;
812 unsigned short buf16[512];
814 iflags &= MWTF_PACKMASK;
815 oflags &= MWTF_PACKMASK;
817 /* allow -1 for len with ascii*/
818 if(cc == -1 && (iflags == MWTF_ASCII))
819 cc = strlen((char *)istr);
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);
827 if(oflags == MWTF_UC16 || cc < 0)
830 /* will decode again to requested format (probably ascii)*/
836 if(iflags == MWTF_UC16 && oflags == MWTF_ASCII) {
837 /* only support uc16 convert to ascii now...*/
838 cc = UC16_to_GB( istr, cc, ostr);
851 /* Convert between formats. Note that there's no error
867 *ostr8++ = (unsigned char)ch;
870 *ostr16++ = (unsigned short)ch;
879 /* Get the width and height of passed text string in the passed font*/
881 GdGetTextSize(PMWFONT pfont, const void *str, int cc, MWCOORD *pwidth,
882 MWCOORD *pheight, MWCOORD *pbase, int flags)
885 unsigned long buf[256];
886 int defencoding = pfont->fontprocs->encoding;
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;
896 if(cc == -1 && (flags & MWTF_PACKMASK) == MWTF_ASCII)
897 cc = strlen((char *)str);
899 if(cc <= 0 || !pfont->fontprocs->GetTextSize) {
900 *pwidth = *pheight = *pbase = 0;
904 /* calc height and width of string*/
905 pfont->fontprocs->GetTextSize(pfont, text, cc, pwidth, pheight, pbase);
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.
914 GdText(PSD psd, MWCOORD x, MWCOORD y, const void *str, int cc, int flags)
917 unsigned long buf[256];
918 int defencoding = gr_pfont->fontprocs->encoding;
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;
928 if(cc == -1 && (flags & MWTF_PACKMASK) == MWTF_ASCII)
929 cc = strlen((char *)str);
931 if(cc <= 0 || !gr_pfont->fontprocs->DrawText)
934 /* draw text string*/
935 gr_pfont->fontprocs->DrawText(gr_pfont, psd, x, y, text, cc, flags);
939 * Draw ascii text using COREFONT type font.
942 corefont_drawtext(PMWFONT pfont, PSD psd, MWCOORD x, MWCOORD y,
943 const void *text, int cc, int flags)
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];
953 pfont->fontprocs->GetTextSize(pfont, str, cc, &width, &height, &base);
955 if(flags & MWTF_BASELINE)
957 else if(flags & MWTF_BOTTOM)
962 switch (GdClipArea(psd, x, y, x + width - 1, y + height - 1)) {
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
969 psd->FillRect(psd, x, y, x + width - 1, y + height - 1,
971 psd->DrawText(psd, x, y, str, cc, gr_foreground, pfont);
981 /* Get the bitmap for each character individually, and then display
982 * them using clipping for each one.
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++;
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++;
1003 pfont->fontprocs->GetTextBits(pfont, ch, bitmap, &width,
1006 /* note: change to bitmap*/
1007 GdBitmap(psd, x, y, width, height, bitmap);
1011 if (pfont->fontattr & MWTF_UNDERLINE)
1012 GdLine(psd, startx, starty, x, starty, FALSE);
1017 #if HAVE_T1LIB_SUPPORT | HAVE_FREETYPE_SUPPORT
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.
1024 alphablend(PSD psd, OUTPIXELVAL *out, MWPIXELVAL src, MWPIXELVAL dst,
1025 unsigned char *alpha, int count)
1028 unsigned char r, g, b;
1029 MWCOLORVAL palsrc, paldst;
1030 extern MWPALENTRY gr_palette[256];
1032 while (--count >= 0) {
1035 #define BITS(pixel,shift,mask) (((pixel)>>shift)&(mask))
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;
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;
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;
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;
1083 case MWPF_TRUECOLOR233:
1084 d = BITS(dst, 0, 0x07);
1085 r = (unsigned char)(((BITS(src, 0, 0x07) - d)*a)>>8) + d;
1086 d = BITS(dst, 3, 0x07);
1087 g = (unsigned char)(((BITS(src, 3, 0x07) - d)*a)>>8) + d;
1088 d = BITS(dst, 6, 0x03);
1089 b = (unsigned char)(((BITS(src, 6, 0x03) - d)*a)>>8) + d;
1090 *out++ = (r << 0) | (g << 3) | (b << 6);
1094 /* reverse lookup palette entry for blend ;-)*/
1095 palsrc = GETPALENTRY(gr_palette, src);
1096 paldst = GETPALENTRY(gr_palette, dst);
1097 d = REDVALUE(paldst);
1098 r = (unsigned char)(((REDVALUE(palsrc) - d)*a)>>8) + d;
1099 d = GREENVALUE(paldst);
1100 g = (unsigned char)(((GREENVALUE(palsrc) - d)*a)>>8) + d;
1101 d = BLUEVALUE(paldst);
1102 b = (unsigned char)(((BLUEVALUE(palsrc) - d)*a)>>8) + d;
1103 *out++ = GdFindNearestColor(gr_palette, (int)psd->ncolors,
1109 #endif /*HAVE_T1LIB_SUPPORT | HAVE_FREETYPE_SUPPORT*/
1111 #if HAVE_T1LIB_SUPPORT
1112 /* contributed by Vidar Hokstad*/
1117 static int inited = 0;
1125 #ifdef T1LIB_USE_AA_HIGH
1126 T1_AASetLevel(T1_AA_HIGH);
1128 T1_AASetLevel(T1_AA_LOW);
1131 /* kluge: this is required if 16bpp drawarea driver is used*/
1133 T1_AASetBitsPerPixel(16);
1136 T1_AASetBitsPerPixel(sizeof(MWPIXELVAL)*8);
1143 t1lib_createfont(const char *name, MWCOORD height, int attr)
1150 /* match name against t1 font id's from t1 font database*/
1151 for(id=0; id<T1_Get_no_fonts(); ++id) {
1152 strncpy(buf, T1_GetFontFileName(id), sizeof(buf));
1154 /* remove extension*/
1155 for(p=buf; *p; ++p) {
1162 if(!strcmpi(name, buf)) {
1163 /* allocate font structure*/
1164 pf = (PMWT1LIBFONT)calloc(sizeof(MWT1LIBFONT), 1);
1167 pf->fontprocs = &t1lib_procs;
1168 GdSetFontSize((PMWFONT)pf, height);
1169 GdSetFontRotation((PMWFONT)pf, 0);
1170 GdSetFontAttr((PMWFONT)pf, attr, 0);
1179 * Draw ascii text string using T1LIB type font
1182 t1lib_drawtext(PMWFONT pfont, PSD psd, MWCOORD x, MWCOORD y,
1183 const void *text, int cc, int flags)
1185 PMWT1LIBFONT pf = (PMWT1LIBFONT)pfont;
1186 const unsigned char *str = text;
1187 MWCOORD width; /* width of text area */
1188 MWCOORD height; /* height of text area */
1190 GLYPH * g; /* T1lib glyph structure. Memory handling by T1lib */
1191 #ifdef T1LIB_USE_AA_HIGH
1192 OUTPIXELVAL gvals[17];
1194 /* Blending array for antialiasing. The steeper the values increase
1195 * near the end, the sharper the characters look, but also more jagged
1197 static unsigned char blend[17] = {
1198 0x00, 0x00, 0x04, 0x0c, 0x10, 0x14, 0x18, 0x20,
1199 0x30, 0x38, 0x40, 0x50, 0x70, 0x80, 0xa0, 0xc0, 0xff
1202 OUTPIXELVAL gvals[5];
1203 static unsigned char blend[5] = { 0x00, 0x44, 0x88, 0xcc, 0xff };
1206 /* Check if we should throw out some fonts */
1208 if (pf->fontattr&MWTF_ANTIALIAS) {
1209 #ifdef T1LIB_USE_AA_HIGH
1210 alphablend(psd, gvals, gr_foreground, gr_background, blend, 17);
1211 T1_AAHSetGrayValues(gvals);
1213 alphablend(psd, gvals, gr_foreground, gr_background, blend, 5);
1214 T1_AASetGrayValues(gvals[0],gvals[1],gvals[2],gvals[3],gvals[4]);
1216 g = T1_AASetString(pf->fontid,(char *)str,cc,0,
1217 (pf->fontattr&MWTF_KERNING)? T1_KERNING: 0,
1218 pf->fontsize * 1.0, 0);
1221 /*MWPIXELVAL save = gr_background;*/
1222 width = g->metrics.rightSideBearing - g->metrics.leftSideBearing;
1223 height = g->metrics.ascent - g->metrics.descent;
1225 if(flags & MWTF_BASELINE)
1226 y -= g->metrics.ascent;
1227 else if(flags & MWTF_BOTTOM)
1229 underliney = y + g->metrics.ascent;
1231 /* FIXME: Looks damn ugly if usebg is false.
1232 * Will be handled when using alphablending in GdArea...
1234 /* clipping handled in GdArea*/
1235 /*FIXME kluge for transparency*/
1236 /*gr_background = gr_foreground + 1;*/
1238 GdArea(psd,x,y, width, height, g->bits, MWPF_PIXELVAL);
1239 /*gr_background = save;*/
1241 if (pf->fontattr & MWTF_UNDERLINE)
1242 GdLine(psd, x, underliney, x+width, underliney, FALSE);
1246 /* Do non-aa drawing */
1247 g = T1_SetString(pf->fontid,(char *)str,cc,0,
1248 (pf->fontattr&MWTF_KERNING)? T1_KERNING: 0,
1249 pf->fontsize * 1.0, 0);
1257 /* I'm sure this sorry excuse for a bitmap rendering routine can
1258 * be optimized quite a bit ;)
1260 width = g->metrics.rightSideBearing - g->metrics.leftSideBearing;
1261 height = g->metrics.ascent - g->metrics.descent;
1263 if(flags & MWTF_BASELINE)
1264 y -= g->metrics.ascent;
1265 else if(flags & MWTF_BOTTOM)
1267 underliney = y + g->metrics.ascent;
1272 /* if ((x + width) > psd->xvirtres) {
1273 xmod = (x + width - psd->xvirtres + 7) >> 3;
1274 width = width + x + width - psd->xvirtres;
1281 while (xoff < width ) {
1287 if (GdClipPoint(psd, x+xoff,y)) {
1289 psd->DrawPixel(psd,x+xoff,y,
1290 data & (1 << (xoff % 8)) ?
1291 gr_foreground : gr_background);
1292 } else if (data & (1 << (xoff % 8))) {
1293 psd->DrawPixel(psd,x+xoff,y, gr_foreground);
1301 if (pf->fontattr & MWTF_UNDERLINE)
1302 GdLine(psd, x, underliney, x+xoff, underliney, FALSE);
1307 /* Save some memory */
1309 g->bits = 0; /* Make sure T1lib doesnt try to free it again */
1316 t1lib_getfontinfo(PMWFONT pfont, PMWFONTINFO pfontinfo)
1319 MWCOORD width, height, baseline;
1321 /* FIXME, guess all sizes*/
1322 GdGetTextSize(pfont, "A", 1, &width, &height, &baseline, MWTF_ASCII);
1323 pfontinfo->height = height;
1324 pfontinfo->maxwidth = width;
1325 pfontinfo->baseline = 0;
1326 pfontinfo->firstchar = 32;
1327 pfontinfo->lastchar = 255;
1328 pfontinfo->fixed = TRUE;
1329 for(i=0; i<256; ++i)
1330 pfontinfo->widths[i] = width;
1334 /* Get the width and height of passed text string in the current font*/
1336 t1lib_gettextsize(PMWFONT pfont, const void *text, int cc,
1337 MWCOORD *pwidth, MWCOORD *pheight, MWCOORD *pbase)
1339 PMWT1LIBFONT pf = (PMWT1LIBFONT)pfont;
1340 const unsigned char * str = text;
1343 g = T1_SetString(pf->fontid, (char *)str, cc, 0,
1344 (pf->fontattr&MWTF_KERNING)? T1_KERNING: 0, pf->fontsize * 1.0, 0);
1345 *pwidth = g->metrics.rightSideBearing - g->metrics.leftSideBearing;
1346 *pheight = g->metrics.ascent - g->metrics.descent;
1354 /* FIXME. Something is *VERY* wrong here */
1355 b = T1_GetStringBBox(pf->fontid, str, cc, 0, (pf->fontattr&MWTF_KERNING)?T1_KERNING:0);
1357 DPRINTF("b.urx = %d, b.llx = %d\n",b.urx, b.llx);
1358 DPRINTF("b.ury = %d, b.lly = %d\n",b.ury, b.lly);
1359 *pwidth = (b.urx - b.llx);
1360 *pheight = (b.lly - b.ury);
1365 t1lib_destroyfont(PMWFONT pfont)
1367 PMWT1LIBFONT pf = (PMWT1LIBFONT)pfont;
1369 T1_DeleteAllSizes(pf->fontid);
1373 #endif /* HAVE_T1LIB_SUPPORT*/
1375 #if HAVE_FREETYPE_SUPPORT
1376 static OUTPIXELVAL gray_palette[5];
1379 freetype_init(PSD psd)
1381 static int inited = 0;
1386 /* Init freetype library */
1387 if (TT_Init_FreeType (&engine) != TT_Err_Ok) {
1391 /* Init kerning extension */
1392 if (TT_Init_Kerning_Extension (engine) != TT_Err_Ok)
1399 static PMWFREETYPEFONT
1400 freetype_createfont(const char *name, MWCOORD height, int attr)
1403 unsigned short i, n;
1404 unsigned short platform, encoding;
1405 TT_Face_Properties properties;
1409 /* check for pathname prefix*/
1410 if (strchr(name, '/') != NULL)
1411 strcpy(fontname, name);
1413 strcpy(fontname, FREETYPE_FONT_DIR);
1414 strcat(fontname, "/");
1415 strcat(fontname, name);
1418 /* check for extension*/
1419 if ((p = strrchr(fontname, '.')) == NULL ||
1420 strcmp(p, ".ttf") != 0) {
1421 strcat(fontname, ".ttf");
1424 /* allocate font structure*/
1425 pf = (PMWFREETYPEFONT)calloc(sizeof(MWFREETYPEFONT), 1);
1428 pf->fontprocs = &freetype_procs;
1431 if (TT_Open_Face (engine, fontname, &pf->face) != TT_Err_Ok)
1434 /* Load first kerning table */
1435 pf->can_kern = TRUE;
1436 if (TT_Load_Kerning_Table (pf->face, 0) != TT_Err_Ok)
1437 pf->can_kern = FALSE;
1439 if (TT_Get_Kerning_Directory (pf->face, &pf->directory)
1441 pf->can_kern = FALSE;
1443 /* Support only version 0 kerning table ... */
1444 if ((pf->directory.version != 0) ||
1445 (pf->directory.nTables <= 0) ||
1446 (pf->directory.tables->loaded != 1) ||
1447 (pf->directory.tables->version != 0) ||
1448 (pf->directory.tables->t.kern0.nPairs <= 0))
1449 pf->can_kern = FALSE;
1453 /* get face properties and allocate preload arrays */
1454 TT_Get_Face_Properties (pf->face, &properties);
1458 * Use header information for ascent and descent
1459 * to compute scaled ascent/descent for current font height.
1461 h = properties.os2->sTypoAscender - properties.os2->sTypoDescender
1462 + properties.os2->sTypoLineGap;
1463 ascent = properties.os2->sTypoAscender
1464 + properties.os2->sTypoLineGap/2;
1465 pf->ascent = (ascent * height + h/2) / h;
1466 pf->descent = height - pf->ascent;
1468 /* Create a glyph container */
1469 if (TT_New_Glyph (pf->face, &pf->glyph) != TT_Err_Ok)
1472 /* create instance */
1473 if (TT_New_Instance (pf->face, &pf->instance) != TT_Err_Ok)
1476 /* Set the instance resolution */
1477 if (TT_Set_Instance_Resolutions (pf->instance, 96, 96) != TT_Err_Ok)
1480 /* Look for a Unicode charmap: Windows flavor of Apple flavor only */
1481 n = properties.num_CharMaps;
1483 for (i = 0; i < n; i++) {
1484 TT_Get_CharMap_ID (pf->face, i, &platform, &encoding);
1485 if (((platform == TT_PLATFORM_MICROSOFT) &&
1486 (encoding == TT_MS_ID_UNICODE_CS)) ||
1487 ((platform == TT_PLATFORM_APPLE_UNICODE) &&
1488 (encoding == TT_APPLE_ID_DEFAULT)))
1490 TT_Get_CharMap (pf->face, i, &pf->char_map);
1495 DPRINTF("freetype_createfont: no unicode map table\n");
1499 GdSetFontSize((PMWFONT)pf, height);
1500 GdSetFontRotation((PMWFONT)pf, 0);
1501 GdSetFontAttr((PMWFONT)pf, attr, 0);
1511 compute_kernval(PMWFREETYPEFONT pf, short current_glyph_code)
1515 int nPairs = pf->directory.tables->t.kern0.nPairs;
1516 TT_Kern_0_Pair *pair = pf->directory.tables->t.kern0.pairs;
1518 if (pf->last_glyph_code != -1) {
1519 while ((pair->left != pf->last_glyph_code)
1520 && (pair->right != current_glyph_code))
1531 /* We round the value (hence the +32) */
1532 kernval = (pair->value + 32) & -64;
1540 Get_Glyph_Width(PMWFREETYPEFONT pf, TT_UShort glyph_index)
1542 TT_Glyph_Metrics metrics;
1544 if (TT_Load_Glyph ( pf->instance, pf->glyph,
1545 TT_Char_Index (pf->char_map,glyph_index),
1546 TTLOAD_SCALE_GLYPH|TTLOAD_HINT_GLYPH) != TT_Err_Ok)
1548 /* Try to load default glyph: index 0 */
1549 if (TT_Load_Glyph ( pf->instance, pf->glyph, 0,
1550 TTLOAD_SCALE_GLYPH|TTLOAD_HINT_GLYPH) != TT_Err_Ok)
1554 TT_Get_Glyph_Metrics (pf->glyph, &metrics);
1555 return((metrics.advance & 0xFFFFFFC0) >> 6);
1558 static MWFREETYPEFONTCACHE *
1559 find_cache_glyph ( PMWFREETYPEFONT pf, unsigned curchar )
1561 MWFREETYPEFONTCACHE ** inode = &pf->glyph_cache;
1567 *inode = calloc(sizeof(MWFREETYPEFONTCACHE),1);
1568 (*inode)->curchar = curchar;
1571 if (curchar < (*inode)->curchar)
1572 inode = &(*inode)->l;
1573 else if (curchar > (*inode)->curchar)
1574 inode = &(*inode)->r;
1581 free_cache_glyph ( MWFREETYPEFONTCACHE * node )
1584 free_cache_glyph(node->l);
1587 free_cache_glyph(node->r);
1592 /* Render a single glyph*/
1594 drawchar(PMWFREETYPEFONT pf, PSD psd, unsigned curchar, int x_offset,
1597 TT_F26Dot6 xmin, ymin, xmax, ymax, x, y, z;
1598 unsigned char *src, *srcptr;
1599 MWPIXELVAL *dst, *dstptr;
1601 int size, width, height;
1604 TT_Raster_Map Raster;
1606 /*MWPIXELVAL save;*/
1607 MWFREETYPEFONTCACHE * cache;
1609 /* we begin by grid-fitting the bounding box */
1610 TT_Get_Glyph_Outline (pf->glyph, &outline);
1611 TT_Get_Outline_BBox (&outline, &bbox);
1613 xmin = (bbox.xMin & -64) >> 6;
1614 ymin = (bbox.yMin & -64) >> 6;
1615 xmax = ((bbox.xMax + 63) & -64) >> 6;
1616 ymax = ((bbox.yMax + 63) & -64) >> 6;
1617 width = xmax - xmin;
1618 height = ymax - ymin;
1619 size = width * height;
1621 /* now re-allocate the raster bitmap */
1622 Raster.rows = height;
1623 Raster.width = width;
1625 if (pf->fontattr&MWTF_ANTIALIAS)
1626 Raster.cols = (Raster.width + 3) & -4; /* pad to 32-bits */
1628 Raster.cols = (Raster.width + 7) & -8; /* pad to 64-bits ??? */
1630 cache = find_cache_glyph(pf,curchar);
1631 /* SDR: if cache is 0 here, something really really bad happened */
1633 Raster.flow = TT_Flow_Up;
1634 Raster.size = Raster.rows * Raster.cols;
1635 Raster.bitmap = cache->buffer;
1637 if (Raster.bitmap == 0)
1639 Raster.bitmap = malloc (Raster.size);
1641 memset (Raster.bitmap, 0, Raster.size);
1643 /* now render the glyph in the small pixmap */
1645 /* IMPORTANT NOTE: the offset parameters passed to the function */
1646 /* TT_Get_Glyph_Bitmap() must be integer pixel values, i.e., */
1647 /* multiples of 64. HINTING WILL BE RUINED IF THIS ISN'T THE CASE! */
1648 /* This is why we _did_ grid-fit the bounding box, especially xmin */
1651 if (!(pf->fontattr&MWTF_ANTIALIAS))
1652 error = TT_Get_Glyph_Bitmap (pf->glyph, &Raster,
1653 -xmin * 64, -ymin * 64);
1655 error = TT_Get_Glyph_Pixmap (pf->glyph, &Raster,
1656 -xmin * 64, -ymin * 64);
1659 free (Raster.bitmap);
1663 cache->buffer = Raster.bitmap;
1666 #if MWFREETYPEFONT_CACHEBITMAP
1667 if ((memcmp(&gr_foreground,&cache->fg,sizeof(gr_foreground)) != 0) ||
1668 (memcmp(&gr_background,&cache->bg,sizeof(gr_background)) != 0) ||
1669 (gr_usebg != cache->usebg))
1673 free(cache->bitmap);
1678 bitmap = cache->bitmap;
1685 bitmap = malloc (size * sizeof (MWPIXELVAL));
1686 memset (bitmap, 0, size * sizeof (MWPIXELVAL));
1688 src = (char *) Raster.bitmap;
1689 dst = bitmap + (size - width);
1691 for (y = ymin; y < ymax; y++)
1696 for (x = xmin; x < xmax; x++)
1698 if (pf->fontattr&MWTF_ANTIALIAS)
1699 *dstptr++ = gray_palette[(int) *srcptr];
1703 z <= ((xmax-x-1) < 7 ? (xmax-x-1) : 7);
1705 *dstptr++ = ((*srcptr << z) & 0x80) ? gr_foreground : gr_background;
1715 #if MWFREETYPEFONT_CACHEBITMAP
1716 cache->fg = gr_foreground;
1717 cache->bg = gr_background;
1718 cache->usebg = gr_usebg;
1719 cache->bitmap = bitmap;
1723 /* Now draw the bitmap ... */
1724 GdArea(psd, x_offset + xmin, y_offset - (ymin + height), width, height,
1725 bitmap, MWPF_PIXELVAL);
1727 #if !MWFREETYPEFONT_CACHEBITMAP
1733 * Draw unicode 16 text string using FREETYPE type font
1736 freetype_drawtext(PMWFONT pfont, PSD psd, MWCOORD ax, MWCOORD ay,
1737 const void *text, int cc, int flags)
1739 PMWFREETYPEFONT pf = (PMWFREETYPEFONT)pfont;
1740 const unsigned short * str = text;
1741 TT_F26Dot6 x = ax, y = ay;
1742 TT_Pos vec_x, vec_y;
1744 TT_F26Dot6 startx, starty;
1747 TT_Glyph_Metrics metrics;
1748 TT_Face_Properties properties;
1749 TT_Instance_Metrics imetrics;
1750 TT_F26Dot6 ascent, descent;
1751 static unsigned char blend[5] = { 0x00, 0x44, 0x88, 0xcc, 0xff };
1752 static unsigned char virtual_palette[5] = { 0, 1, 2, 3, 4 };
1754 pf->last_glyph_code = -1; /* reset kerning*/
1755 pf->last_pen_pos = -32767;
1758 * Compute instance ascent & descent values
1759 * in fractional units (1/64th pixel)
1761 TT_Get_Face_Properties (pf->face, &properties);
1762 TT_Get_Instance_Metrics(pf->instance, &imetrics);
1764 ascent = ((properties.horizontal->Ascender * imetrics.y_scale)/0x10000);
1765 descent = ((properties.horizontal->Descender*imetrics.y_scale)/0x10000);
1768 * Offset the starting point if necessary,
1769 * FreeType always aligns at baseline
1771 if (flags&MWTF_BOTTOM) {
1774 TT_Transform_Vector(&vec_x, &vec_y,&pf->matrix);
1777 } else if (flags&MWTF_TOP) {
1780 TT_Transform_Vector(&vec_x, &vec_y,&pf->matrix);
1785 /* Set the "graylevels" */
1786 if (pf->fontattr&MWTF_ANTIALIAS) {
1787 TT_Set_Raster_Gray_Palette (engine, virtual_palette);
1789 alphablend(psd, gray_palette, gr_foreground, gr_background,
1795 for (i = 0; i < cc; i++) {
1796 curchar = TT_Char_Index (pf->char_map, str[i]);
1798 if (TT_Load_Glyph (pf->instance, pf->glyph, curchar,
1799 TTLOAD_DEFAULT) != TT_Err_Ok)
1802 if (pf->fontrotation) {
1803 TT_Get_Glyph_Outline (pf->glyph, &outline);
1804 TT_Transform_Outline (&outline, &pf->matrix);
1807 TT_Get_Glyph_Metrics (pf->glyph, &metrics);
1809 if ((pf->fontattr&MWTF_KERNING) && pf->can_kern) {
1810 if (pf->fontrotation) {
1811 vec_x = compute_kernval(pf, curchar);
1813 TT_Transform_Vector(&vec_x, &vec_y,&pf->matrix);
1818 x += compute_kernval(pf, curchar) / 64;
1821 drawchar(pf, psd, curchar, x, y);
1823 if (pf->fontrotation) {
1824 vec_x = metrics.advance;
1826 TT_Transform_Vector (&vec_x, &vec_y, &pf->matrix);
1831 x += metrics.advance / 64;
1833 /* Kerning point syndrome avoidance */
1834 if (pf->last_pen_pos > x)
1835 x = pf->last_pen_pos;
1836 pf->last_pen_pos = x;
1839 pf->last_glyph_code = curchar;
1842 if (pf->fontattr & MWTF_UNDERLINE)
1843 GdLine(psd, startx, starty, x, y, FALSE);
1847 * Return information about a specified font.
1850 freetype_getfontinfo(PMWFONT pfont, PMWFONTINFO pfontinfo)
1853 PMWFREETYPEFONT pf = (PMWFREETYPEFONT)pfont;
1854 TT_Face_Properties properties;
1855 TT_Instance_Metrics imetrics;
1856 TT_UShort last_glyph_index;
1858 TT_Get_Face_Properties (pf->face, &properties);
1859 TT_Get_Instance_Metrics(pf->instance, &imetrics);
1861 /* Fill up the fields */
1862 pfontinfo->height = (((properties.horizontal->Ascender * \
1863 imetrics.y_scale)/ 0x10000) >> 6) -
1864 (((properties.horizontal->Descender * \
1865 imetrics.y_scale)/ 0x10000) >> 6);
1866 pfontinfo->maxwidth = ((properties.horizontal->xMax_Extent * \
1867 imetrics.x_scale)/ 0x10000) >> 6;
1868 pfontinfo->baseline = ((properties.horizontal->Ascender * \
1869 imetrics.y_scale)/ 0x10000) >> 6;
1870 pfontinfo->firstchar = TT_CharMap_First(pf->char_map, NULL);
1871 pfontinfo->lastchar = TT_CharMap_Last(pf->char_map, NULL);
1872 pfontinfo->fixed = properties.postscript->isFixedPitch;
1874 last_glyph_index = properties.num_Glyphs > 255 ? 255: properties.num_Glyphs-1;
1876 /* Doesn't work ... don't know why ....*/
1878 if (TT_Get_Face_Widths( pf->face, 0,
1879 last_glyph_index, widths, NULL ) != TT_Err_Ok) {
1883 for(i=0; i<=last_glyph_index; i++)
1884 DPRINTF("widths[%d]: %d\n", i, widths[i]);
1887 /* Get glyphs widths */
1888 for(i=0; i<=last_glyph_index; i++)
1889 pfontinfo->widths[i] = Get_Glyph_Width(pf, i);
1892 DPRINTF("x_ppem: %d\ny_ppem: %d\nx_scale: %d\ny_scale: %d\n\
1893 x_resolution: %d\ny_resolution: %d\n",
1894 imetrics.x_ppem, imetrics.y_ppem, imetrics.x_scale, \
1895 imetrics.y_scale, imetrics.x_resolution, imetrics.y_resolution);
1897 DPRINTF("Ascender: %d\nDescender: %d\nxMax_Extent: %d\n\
1898 Mac Style Say Italic?: %d\nMac Style Say Bold?: %d\n\
1899 sTypoAscender: %d\nsTypoDescender: %d\nusWinAscent: %d\n\
1900 usWinDescent: %d\nusFirstCharIndex: %d\nusLastCharIndex: %d\n\
1901 OS2 Say Italic?: %d\nOS2 Say Bold?: %d\nOS2 Say monospaced?: %d\n\
1902 Postscript Say monospaced?: %d\n",\
1903 properties.horizontal->Ascender,
1904 properties.horizontal->Descender,
1905 properties.horizontal->xMax_Extent,
1906 (properties.header->Mac_Style & 0x2)?1:0,
1907 (properties.header->Mac_Style & 0x1)?1:0,
1908 properties.os2->sTypoAscender,
1909 properties.os2->sTypoDescender,
1910 properties.os2->usWinAscent,
1911 properties.os2->usWinDescent,
1912 properties.os2->usFirstCharIndex,
1913 properties.os2->usLastCharIndex,
1914 (properties.os2->fsSelection & 0x1)?1:0,
1915 (properties.os2->fsSelection & 0x20)?1:0,
1916 properties.postscript->isFixedPitch,
1917 (properties.os2->panose[3] == 9)?1:0);
1924 freetype_gettextsize(PMWFONT pfont, const void *text, int cc,
1925 MWCOORD *pwidth, MWCOORD *pheight, MWCOORD *pbase)
1927 PMWFREETYPEFONT pf = (PMWFREETYPEFONT)pfont;
1928 const unsigned short * str = text;
1932 TT_Glyph_Metrics metrics;
1933 TT_Face_Properties properties;
1934 TT_Instance_Metrics imetrics;
1936 TT_Get_Face_Properties (pf->face, &properties);
1937 TT_Get_Instance_Metrics(pf->instance, &imetrics);
1939 pf->last_glyph_code = -1; /* reset kerning*/
1940 pf->last_pen_pos = -32767;
1942 for (i = 0; i < cc; i++) {
1943 curchar = TT_Char_Index (pf->char_map, str[i]);
1945 if (TT_Load_Glyph (pf->instance, pf->glyph, curchar,
1946 TTLOAD_SCALE_GLYPH|TTLOAD_HINT_GLYPH) != TT_Err_Ok)
1949 TT_Get_Glyph_Metrics (pf->glyph, &metrics);
1951 if ((pf->fontattr&MWTF_KERNING) && pf->can_kern) {
1952 x += compute_kernval(pf, curchar) / 64;
1955 x += metrics.advance / 64;
1957 /* Kerning point syndrome avoidance */
1958 if (pf->last_pen_pos > x)
1959 x = pf->last_pen_pos;
1960 pf->last_pen_pos = x;
1962 pf->last_glyph_code = curchar;
1966 *pheight = (((properties.horizontal->Ascender *
1967 imetrics.y_scale)/ 0x10000) >> 6) -
1968 (((properties.horizontal->Descender *
1969 imetrics.y_scale)/ 0x10000) >> 6);
1970 /* FIXME: is it what's required ?? */
1971 *pbase = (((-properties.horizontal->Descender) *
1972 imetrics.y_scale)/ 0x10000) >> 6;
1976 freetype_destroyfont(PMWFONT pfont)
1978 PMWFREETYPEFONT pf = (PMWFREETYPEFONT)pfont;
1980 TT_Close_Face(pf->face);
1984 if (pf->glyph_cache != 0)
1985 free_cache_glyph(pf->glyph_cache);
1993 freetype_setfontsize(PMWFONT pfont, MWCOORD fontsize)
1995 PMWFREETYPEFONT pf = (PMWFREETYPEFONT)pfont;
1997 pf->fontsize = fontsize;
1999 /* We want real pixel sizes ... not points ...*/
2000 TT_Set_Instance_PixelSizes( pf->instance, pf->fontsize,
2001 pf->fontsize, pf->fontsize * 64 );
2003 /* set charsize (convert to points for freetype)*/
2004 TT_Set_Instance_CharSize (pf->instance,
2005 ((pf->fontsize * 72 + 96/2) / 96) * 64);
2010 freetype_setfontrotation(PMWFONT pfont, int tenthdegrees)
2012 PMWFREETYPEFONT pf = (PMWFREETYPEFONT)pfont;
2015 pf->fontrotation = tenthdegrees;
2017 /* Build the rotation matrix with the given angle */
2018 TT_Set_Instance_Transform_Flags (pf->instance, TRUE, FALSE);
2020 angle = pf->fontrotation * M_PI / 1800;
2021 pf->matrix.yy = (TT_Fixed) (cos (angle) * (1 << 16));
2022 pf->matrix.yx = (TT_Fixed) (sin (angle) * (1 << 16));
2023 pf->matrix.xx = pf->matrix.yy;
2024 pf->matrix.xy = -pf->matrix.yx;
2027 #endif /* HAVE_FREETYPE_SUPPORT*/
2029 /* UTF-8 to UTF-16 conversion. Surrogates are handeled properly, e.g.
2030 * a single 4-byte UTF-8 character is encoded into a surrogate pair.
2031 * On the other hand, if the UTF-8 string contains surrogate values, this
2032 * is considered an error and returned as such.
2034 * The destination array must be able to hold as many Unicode-16 characters
2035 * as there are ASCII characters in the UTF-8 string. This in case all UTF-8
2036 * characters are ASCII characters. No more will be needed.
2038 * Copyright (c) 2000 Morten Rolland, Screen Media
2041 utf8_to_utf16(const unsigned char *utf8, int cc, unsigned short *unicode16)
2044 unsigned char c0, c1;
2045 unsigned long scalar;
2049 /*DPRINTF("Trying: %02x\n",c0);*/
2052 /* Plain ASCII character, simple translation :-) */
2058 if ( (c0 & 0xc0) == 0x80 )
2059 /* Illegal; starts with 10xxxxxx */
2062 /* c0 must be 11xxxxxx if we get here => at least 2 bytes */
2067 /*DPRINTF("c1=%02x\n",c1);*/
2068 if ( (c1 & 0xc0) != 0x80 )
2072 scalar |= (c1 & 0x3f);
2074 if ( !(c0 & 0x20) ) {
2075 /* Two bytes UTF-8 */
2076 if ( scalar < 0x80 )
2077 return -1; /* Overlong encoding */
2078 *unicode16++ = scalar & 0x7ff;
2083 /* c0 must be 111xxxxx if we get here => at least 3 bytes */
2087 /*DPRINTF("c1=%02x\n",c1);*/
2088 if ( (c1 & 0xc0) != 0x80 )
2092 scalar |= (c1 & 0x3f);
2094 if ( !(c0 & 0x10) ) {
2095 /*DPRINTF("####\n");*/
2096 /* Three bytes UTF-8 */
2097 if ( scalar < 0x800 )
2098 return -1; /* Overlong encoding */
2099 if ( scalar >= 0xd800 && scalar < 0xe000 )
2100 return -1; /* UTF-16 high/low halfs */
2101 *unicode16++ = scalar & 0xffff;
2106 /* c0 must be 1111xxxx if we get here => at least 4 bytes */
2110 /*DPRINTF("c1=%02x\n",c1);*/
2111 if ( (c1 & 0xc0) != 0x80 )
2115 scalar |= (c1 & 0x3f);
2117 if ( !(c0 & 0x08) ) {
2118 /* Four bytes UTF-8, needs encoding as surrogates */
2119 if ( scalar < 0x10000 )
2120 return -1; /* Overlong encoding */
2122 *unicode16++ = ((scalar >> 10) & 0x3ff) + 0xd800;
2123 *unicode16++ = (scalar & 0x3ff) + 0xdc00;
2128 return -1; /* No support for more than four byte UTF-8 */
2133 #if HAVE_HZK_SUPPORT
2135 /* UniCode-16 (MWTF_UC16) to GB(MWTF_ASCII) Chinese Characters conversion.
2136 * a single 2-byte UC16 character is encoded into a surrogate pair.
2137 * return -1 ,if error;
2138 * The destination array must be able to hold as many
2139 * as there are Unicode-16 characters.
2141 * Copyright (c) 2000 Tang Hao (TownHall)(tang_hao@263.net).
2144 UC16_to_GB(const unsigned char *uc16, int cc, unsigned char *ascii)
2148 unsigned char *uc16p;
2150 unsigned char *filebuffer;
2151 unsigned short *uc16pp,*table;
2152 unsigned short uc16px;
2158 uc16p=(unsigned char *) uc16;
2159 uc16pp=(unsigned short *) uc16;
2161 strcpy(buffer,HZK_FONT_DIR);
2163 strcat(buffer,"/BG2UBG.KU");
2165 strcat(buffer,"/UGB2GB.KU");
2166 if(!(fp = fopen(buffer, "rb")))
2168 fprintf (stderr, "Error.\nThe %s file can not be found!\n",buffer);
2172 filebuffer= (unsigned char *)malloc ( length);
2174 if(fread(filebuffer, sizeof(char),length, fp) < length) {
2175 fprintf (stderr, "Error in reading ugb2gb.ku file!\n");
2183 table=(unsigned short *)filebuffer;
2192 if((uc16px)<=0x00ff)
2194 ascii[i]=(char)(*uc16pp);
2199 ascii[i]=0xa1; ascii[i+1]=0x40;
2200 for (k=0; k<13710; k++)
2202 if (*(table+(k*2+1))==(uc16px))
2204 ascii[i]=(char)((*(table+(k*2)) & 0xff00) >> 8);
2205 ascii[i+1]=(char)(*(table+(k*2)) & 0x00ff);
2223 if((*((uc16p)+j)==0)&&(*((uc16p)+j+1)==0))
2230 if(*((uc16p)+j+1)==0)
2232 ascii[i]=*((uc16p)+j);
2238 /* to find the place of unicode charater .¶þ·Ö·¨Æ¥Åä*/
2240 int p1=0,p2=length-4,p;
2241 unsigned int c1,c2,c,d;
2242 c1=((unsigned int )filebuffer[p1])*0x100+(filebuffer[p1+1]);
2243 c2=((unsigned int )filebuffer[p2])*0x100+(filebuffer[p2+1]);
2244 d=((unsigned int )*((uc16p)+j))*0x100+*((uc16p)+j+1);
2247 ascii[i]=filebuffer[p1+2];
2248 ascii[i+1]=filebuffer[p1+3];
2253 ascii[i]=filebuffer[p2+2];
2254 ascii[i+1]=filebuffer[p2+3];
2259 p=(((p2-p1)/2+p1)>>2)<<2;
2260 c=((unsigned int )filebuffer[p])*0x100+(filebuffer[p+1]);
2261 if(d==c) /*find it*/
2263 ascii[i]=filebuffer[p+2];
2264 ascii[i+1]=filebuffer[p+3];
2267 else if(p2<=p1+4) /*can't find.*/
2269 ascii[i]='.';/*((uc16p)+j);*/
2270 ascii[i+1]='.';/*((uc16p)+j+1);*/
2297 /************************** functions definition ******************************/
2299 static int hzk_id( PMWHZKFONT pf )
2301 switch(pf->font_height)
2310 /* This function get Chinese font info from etc file.*/
2311 static MWBOOL GetCFontInfo( PMWHZKFONT pf )
2316 charset=(13094+408);
2320 CFont[hzk_id(pf)].width = pf->cfont_width;
2321 pf->CFont.width = pf->cfont_width;
2323 CFont[hzk_id(pf)].height = pf->font_height;
2324 pf->CFont.height = pf->font_height;
2326 CFont[hzk_id(pf)].size = ((pf->CFont.width + 7) / 8) *
2327 pf->CFont.height * charset;
2328 pf->CFont.size = ((pf->CFont.width + 7) / 8) * pf->CFont.height * charset;
2330 if(pf->CFont.size < charset * 8)
2333 strcpy(CFont[hzk_id(pf)].file,HZK_FONT_DIR);
2334 strcpy(pf->CFont.file,HZK_FONT_DIR);
2336 if(pf->font_height==16)
2338 strcat(CFont[hzk_id(pf)].file,"/hzk16");
2339 strcat(pf->CFont.file,"/hzk16");
2343 strcat(CFont[hzk_id(pf)].file,"/hzk12");
2344 strcat(pf->CFont.file,"/hzk12");
2349 CFont[hzk_id(pf)].file[strlen(pf->CFont.file)-3]+=use_big5;
2350 pf->CFont.file[strlen(pf->CFont.file)-3]+=use_big5;
2356 /* This function get ASCII font info from etc file.*/
2357 static MWBOOL GetAFontInfo( PMWHZKFONT pf )
2359 AFont[hzk_id(pf)].width = pf->afont_width;
2360 pf->AFont.width = pf->afont_width;
2362 AFont[hzk_id(pf)].height = pf->font_height;
2363 pf->AFont.height = pf->font_height;
2365 AFont[hzk_id(pf)].size = ((pf->AFont.width + 7) / 8) *
2366 pf->AFont.height * 255;
2367 pf->AFont.size = ((pf->AFont.width + 7) / 8) * pf->AFont.height * 255;
2369 if(pf->AFont.size < 255 * 8)
2372 strcpy(AFont[hzk_id(pf)].file,HZK_FONT_DIR);
2373 strcpy(pf->AFont.file,HZK_FONT_DIR);
2375 if(pf->font_height==16)
2377 strcat(AFont[hzk_id(pf)].file,"/asc16");
2378 strcat(pf->AFont.file,"/asc16");
2382 strcat(AFont[hzk_id(pf)].file,"/asc12");
2383 strcat(pf->AFont.file,"/asc12");
2388 /* This function load system font into memory.*/
2389 static MWBOOL LoadFont( PMWHZKFONT pf )
2393 if(!GetCFontInfo(pf))
2395 fprintf (stderr, "Get Chinese HZK font info failure!\n");
2398 if(CFont[hzk_id(pf)].pFont == NULL)/*check font cache*/
2402 /* Allocate system memory for Chinese font.*/
2403 if( !(CFont[hzk_id(pf)].pFont = (char *)malloc(pf->CFont.size)) )
2405 fprintf (stderr, "Allocate memory for Chinese HZK font failure.\n");
2409 /* Open font file and read information to the system memory.*/
2410 fprintf (stderr, "Loading Chinese HZK font from file(%s)..." ,pf->CFont.file);
2411 if(!(fp = fopen(CFont[hzk_id(pf)].file, "rb")))
2413 fprintf (stderr, "Error.\nThe Chinese HZK font file can not be found!\n");
2416 if(fread(CFont[hzk_id(pf)].pFont, sizeof(char), pf->CFont.size, fp) < pf->CFont.size)
2418 fprintf (stderr, "Error in reading Chinese HZK font file!\n");
2425 CFont[hzk_id(pf)].use_count=0;
2427 fprintf (stderr, "done.\n" );
2430 cfont_address = CFont[hzk_id(pf)].pFont;
2431 pf->cfont_address = CFont[hzk_id(pf)].pFont;
2432 pf->CFont.pFont = CFont[hzk_id(pf)].pFont;
2434 CFont[hzk_id(pf)].use_count++;
2436 if(!GetAFontInfo(pf))
2438 fprintf (stderr, "Get ASCII HZK font info failure!\n");
2441 if(AFont[hzk_id(pf)].pFont == NULL)/*check font cache*/
2445 /* Allocate system memory for ASCII font.*/
2446 if( !(AFont[hzk_id(pf)].pFont = (char *)malloc(pf->AFont.size)) )
2448 fprintf (stderr, "Allocate memory for ASCII HZK font failure.\n");
2449 free(CFont[hzk_id(pf)].pFont);
2450 CFont[hzk_id(pf)].pFont = NULL;
2454 /* Load ASCII font information to the near memory.*/
2455 fprintf (stderr, "Loading ASCII HZK font..." );
2456 if(!(fp = fopen(AFont[hzk_id(pf)].file, "rb")))
2458 fprintf (stderr, "Error.\nThe ASCII HZK font file can not be found!\n");
2461 if(fread(AFont[hzk_id(pf)].pFont, sizeof(char), pf->AFont.size, fp) < pf->AFont.size)
2463 fprintf (stderr, "Error in reading ASCII HZK font file!\n");
2470 AFont[hzk_id(pf)].use_count=0;
2472 fprintf (stderr, "done.\n" );
2475 afont_address = AFont[hzk_id(pf)].pFont;
2476 pf->afont_address = AFont[hzk_id(pf)].pFont;
2477 pf->AFont.pFont = AFont[hzk_id(pf)].pFont;
2479 AFont[hzk_id(pf)].use_count++;
2484 /* This function unload system font from memory.*/
2485 static void UnloadFont( PMWHZKFONT pf )
2487 CFont[hzk_id(pf)].use_count--;
2488 AFont[hzk_id(pf)].use_count--;
2490 if (!CFont[hzk_id(pf)].use_count)
2492 free(pf->CFont.pFont);
2493 free(pf->AFont.pFont);
2495 CFont[hzk_id(pf)].pFont = NULL;
2496 AFont[hzk_id(pf)].pFont = NULL;
2503 /* FIXME: *.KU file should be opened and
2509 hzk_createfont(const char *name, MWCOORD height, int attr)
2513 if(strcmp(name,"HZKFONT")!=0 && strcmp(name,"HZXFONT")!=0)
2516 printf("hzk_createfont(%s,%d)\n",name,height);
2518 use_big5=name[2]-'K';
2520 /* allocate font structure*/
2521 pf = (PMWHZKFONT)calloc(sizeof(MWHZKFONT), 1);
2524 pf->fontprocs = &hzk_procs;
2526 pf->fontsize=height;
2527 /*GdSetFontSize((PMWFONT)pf, height);*/
2528 GdSetFontRotation((PMWFONT)pf, 0);
2529 GdSetFontAttr((PMWFONT)pf, attr, 0);
2537 pf->afont_width = 6;
2538 pf->cfont_width = 12;
2539 pf->font_height = 12;
2547 pf->afont_width = 8;
2548 pf->cfont_width = 16;
2549 pf->font_height = 16;
2552 /* Load the font library to the system memory.*/
2561 if ((i>=0xa140 && i<=0xa3bf) || /* a140-a3bf(!a3e0) */
2562 (i>=0xa440 && i<=0xc67e) || /* a440-c67e */
2563 (i>=0xc6a1 && i<=0xc8d3) || /* c6a1-c8d3(!c8fe) */
2564 (i>=0xc940 && i<=0xf9fe)) /* c940-f9fe */
2571 * following several function is used in hzk_drawtext
2574 static int getnextchar(char* s, unsigned char* cc)
2576 if( s[0] == '\0') return 0;
2578 cc[0] = (unsigned char)(*s);
2579 cc[1] = (unsigned char)(*(s + 1));
2583 if( IsBig5( (int) ( (cc[0] << 8) + cc[1]) ) )
2588 if( ((unsigned char)cc[0] > 0xa0) &&
2589 ((unsigned char)cc[1] > 0xa0) )
2599 expandcchar(PMWHZKFONT pf, int bg, int fg, unsigned char* c, MWPIXELVAL* bitmap)
2604 unsigned char *font;
2605 int b = 0; /* keep gcc happy with b = 0 - MW */
2608 pixelsize=sizeof(MWPIXELVAL);
2615 /*ladd=loby-(if(loby<127)?64:98)*/
2618 /*hadd=(hiby-164)*157*/
2619 if (c1>=0xa4)/*standard font*/
2621 seq=(((c1-164)*157)+c2);
2622 if (seq>=5809) seq-=408;
2625 /*hadd=(hiby-161)*157*/
2626 if (c1<=0xa3)/*special font*/
2627 seq=(((c1-161)*157)+c2)+13094;
2630 seq=((c1 - 161)*94 + c2 - 161);
2632 font = pf->cfont_address + ((seq) *
2633 (pf->font_height * ((pf->cfont_width + 7) / 8)));
2635 for (y = 0; y < pf->font_height; y++)
2636 for (x = 0; x < pf->cfont_width; x++)
2641 if (b & (128 >> (x % 8))) /* pixel */
2648 static void expandchar(PMWHZKFONT pf, int bg, int fg, int c, MWPIXELVAL* bitmap)
2652 unsigned char *font;
2654 int b = 0; /* keep gcc happy with b = 0 - MW */
2656 pixelsize=sizeof(MWPIXELVAL);
2658 font = pf->afont_address + c * (pf->font_height *
2659 ((pf->afont_width + 7) / 8));
2661 for (y = 0; y < pf->font_height; y++)
2662 for (x = 0; x < pf->afont_width; x++)
2666 if (b & (128 >> (x % 8))) /* pixel */
2674 * Draw ASCII text string using HZK type font
2677 hzk_drawtext(PMWFONT pfont, PSD psd, MWCOORD ax, MWCOORD ay,
2678 const void *text, int cc, int flags)
2680 PMWHZKFONT pf=(PMWHZKFONT)pfont;
2684 unsigned char s1[3];
2691 s1[0]=*((unsigned char*)text);
2698 bitmap = (MWPIXELVAL *)ALLOCA(pf->cfont_width * pf->font_height *
2699 sizeof(MWPIXELVAL));
2701 while( getnextchar(s, c) )
2705 expandcchar(pf, gr_background,gr_foreground,
2707 /* Now draw the bitmap ... */
2710 GdArea(psd,ax, ay, pf->cfont_width,
2711 pf->font_height, bitmap, MWPF_PIXELVAL);
2713 GdArea(psd,ax, ay-pf->font_height+2,
2714 pf->cfont_width, pf->font_height,
2715 bitmap, MWPF_PIXELVAL);
2718 ax += pf->cfont_width;
2722 expandchar(pf, gr_background,gr_foreground,
2724 /* Now draw the bitmap ... */
2727 GdArea(psd,ax, ay, pf->afont_width,
2728 pf->font_height, bitmap, MWPF_PIXELVAL);
2730 GdArea(psd,ax, ay-pf->font_height+2,
2731 pf->afont_width, pf->font_height,
2732 bitmap, MWPF_PIXELVAL);
2735 ax += pf->afont_width;
2738 if(s>=sbegin+cc)break;
2745 * Return information about a specified font.
2748 hzk_getfontinfo(PMWFONT pfont, PMWFONTINFO pfontinfo)
2750 PMWHZKFONT pf=(PMWHZKFONT)pfont;
2754 pfontinfo->height = pf->font_height;
2755 pfontinfo->maxwidth = pf->cfont_width;
2756 pfontinfo->baseline = pf->font_height-2;
2757 pfontinfo->firstchar = 0;
2758 pfontinfo->lastchar = 0;
2759 pfontinfo->fixed = TRUE;
2761 for(i=0; i<=256; i++)
2762 pfontinfo->widths[i] = pf->afont_width;
2768 hzk_gettextsize(PMWFONT pfont, const void *text, int cc,
2769 MWCOORD *pwidth, MWCOORD *pheight, MWCOORD *pbase)
2771 PMWHZKFONT pf=(PMWHZKFONT)pfont;
2775 unsigned char s1[3];
2785 *pheight = pf->font_height;
2786 *pbase = pf->font_height-2;
2791 s1[0]=*((unsigned char*)text);
2797 while( getnextchar(s, c) )
2802 ax += pf->cfont_width;
2807 ax += pf->afont_width;
2809 if(s>=sbegin+cc)break;
2810 /* fprintf(stderr,"s=%x,sbegin=%x,cc=%x\n",s,sbegin,cc);*/
2813 /* fprintf(stderr,"ax=%d,\n",ax);*/
2816 *pheight = pf->font_height;
2817 *pbase = pf->font_height-2;
2821 hzk_destroyfont(PMWFONT pfont)
2823 PMWHZKFONT pf=(PMWHZKFONT)pfont;
2830 hzk_setfontsize(PMWFONT pfont, MWCOORD fontsize)
2832 PMWHZKFONT pf=(PMWHZKFONT)pfont;
2834 /*jmt: hzk_setfontsize not supported*/
2835 /*jmt: & pf->fontsize can't be changed*/
2836 /*jmt: because of hzk_id() :p*/
2837 pf->fontsize=pf->font_height;
2839 #endif /* HAVE_HZK_SUPPORT*/
2841 /* FIXME: this routine should work for all font renderers...*/
2843 GdGetTextSizeEx(PMWFONT pfont, const void *str, int cc,int nMaxExtent,
2844 int* lpnFit, int* alpDx,MWCOORD *pwidth,MWCOORD *pheight,
2845 MWCOORD *pbase, int flags)
2847 #ifdef HAVE_FREETYPE_SUPPORT
2848 unsigned short buf[256];
2849 unsigned short* text;
2850 PMWFREETYPEFONT pf = (PMWFREETYPEFONT)pfont;
2851 int defencoding = pf->fontprocs->encoding;
2855 TT_Glyph_Metrics metrics;
2856 TT_Face_Properties properties;
2857 TT_Instance_Metrics imetrics;
2861 *pwidth = *pheight = *pbase = 0;
2864 /* convert encoding if required*/
2865 if((flags & MWTF_PACKMASK) != defencoding)
2867 cc = GdConvertEncoding(str, flags, cc, buf, defencoding);
2868 flags &= ~MWTF_PACKMASK;
2869 flags |= defencoding;
2871 } else text =(unsigned short*)str;
2874 *pwidth = *pheight = *pbase = 0;
2878 TT_Get_Face_Properties (pf->face, &properties);
2879 TT_Get_Instance_Metrics(pf->instance, &imetrics);
2881 pf->last_glyph_code = -1; /* reset kerning*/
2882 pf->last_pen_pos = -32767;
2885 for (i = 0; i < cc; i++)
2887 curchar = TT_Char_Index (pf->char_map,text[i]);
2889 if (TT_Load_Glyph (pf->instance, pf->glyph, curchar,
2890 TTLOAD_SCALE_GLYPH|TTLOAD_HINT_GLYPH) != TT_Err_Ok)
2892 printf("Unable to load glyph with index=%d\n",curchar);
2895 TT_Get_Glyph_Metrics (pf->glyph, &metrics);
2896 if ((pf->fontattr&MWTF_KERNING) && pf->can_kern)
2898 x += compute_kernval(pf, curchar) / 64;
2900 x += metrics.advance / 64;
2901 if((lpnFit)&&(alpDx))
2909 /* Kerning point syndrome avoidance */
2910 if (pf->last_pen_pos > x)
2911 x = pf->last_pen_pos;
2912 pf->last_pen_pos = x;
2913 pf->last_glyph_code = curchar;
2915 if ((lpnFit)&&(*lpnFit==-1))
2918 *pheight = (((properties.horizontal->Ascender *
2919 imetrics.y_scale)/ 0x10000) >> 6) -
2920 (((properties.horizontal->Descender *
2921 imetrics.y_scale)/ 0x10000) >> 6);
2922 /*FIXME: is it what's required ??*/
2924 *pbase = (((-properties.horizontal->Descender) *
2925 imetrics.y_scale)/ 0x10000) >> 6;
2927 #else /* HAVE_FREETYPE_SUPPORT*/
2928 *pwidth = *pheight = *pbase = 0;