1 
2 /********************************************/
3 /* gd interface to freetype library         */
4 /*                                          */
5 /* John Ellson   ellson@lucent.com          */
6 /********************************************/
7 
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <math.h>
12 #include "gd.h"
13 #include "gdhelpers.h"
14 
15 #ifndef MSWIN32
16 #include <unistd.h>
17 #else
18 #define R_OK 2
19 #endif
20 
21 /* number of antialised colors for indexed bitmaps */
22 #define NUMCOLORS 8
23 
24 char *
gdImageStringTTF(gdImage * im,int * brect,int fg,char * fontlist,double ptsize,double angle,int x,int y,char * string)25 gdImageStringTTF (gdImage * im, int *brect, int fg, char *fontlist,
26 		  double ptsize, double angle, int x, int y, char *string)
27 {
28   return gdImageStringFT (im, brect, fg, fontlist, ptsize,
29 		   angle, x, y, string);
30 }
31 
32 #ifndef HAVE_LIBFREETYPE
33 char *
gdImageStringFT(gdImage * im,int * brect,int fg,char * fontlist,double ptsize,double angle,int x,int y,char * string)34 gdImageStringFT (gdImage * im, int *brect, int fg, char *fontlist,
35 		 double ptsize, double angle, int x, int y, char *string)
36 {
37   return "libgd was not built with FreeType font support\n";
38 }
39 #else
40 
41 #include "gdcache.h"
42 #include <ft2build.h>
43 #include FT_FREETYPE_H
44 #include FT_GLYPH_H
45 /* number of fonts cached before least recently used is replaced */
46 #define FONTCACHESIZE 6
47 
48 /* number of antialias color lookups cached */
49 #define TWEENCOLORCACHESIZE 32
50 
51 /*
52  * Line separation as a factor of font height.
53  *      No space between if LINESPACE = 1.00
54  *      Line separation will be rounded up to next pixel row.
55  */
56 #define LINESPACE 1.05
57 
58 /*
59  * The character (space) used to separate alternate fonts in the
60  * fontlist parameter to gdImageStringFT.
61  */
62 #define LISTSEPARATOR " "
63 
64 /*
65  * DEFAULT_FONTPATH and PATHSEPARATOR are host type dependent and
66  * are normally set by configure in gvconfig.h.  These are just
67  * some last resort values that might match some Un*x system
68  * if building this version of gd separate from graphviz.
69  */
70 #ifndef DEFAULT_FONTPATH
71 #define DEFAULT_FONTPATH "/usr/share/fonts/truetype"
72 #endif
73 #ifndef PATHSEPARATOR
74 #define PATHSEPARATOR ":"
75 #endif
76 
77 #ifndef TRUE
78 #define FALSE 0
79 #define TRUE !FALSE
80 #endif
81 
82 #define MAX(a,b) ((a)>(b)?(a):(b))
83 #define MIN(a,b) ((a)<(b)?(a):(b))
84 
85 typedef struct
86 {
87   char *fontlist;		/* key */
88   FT_Library *library;
89   FT_Face face;
90   FT_Bool have_char_map_unicode, have_char_map_big5, have_char_map_sjis,
91     have_char_map_apple_roman;
92   gdCache_head_t *glyphCache;
93 }
94 font_t;
95 
96 typedef struct
97   {
98     char *fontlist;		/* key */
99     FT_Library *library;
100   }
101 fontkey_t;
102 
103 typedef struct
104   {
105     int pixel;			/* key */
106     int bgcolor;		/* key */
107     int fgcolor;		/* key *//* -ve means no antialias */
108     gdImagePtr im;		/* key */
109     int tweencolor;
110   }
111 tweencolor_t;
112 
113 typedef struct
114   {
115     int pixel;			/* key */
116     int bgcolor;		/* key */
117     int fgcolor;		/* key *//* -ve means no antialias */
118     gdImagePtr im;		/* key */
119   }
120 tweencolorkey_t;
121 
122 /********************************************************************
123  * gdTcl_UtfToUniChar is borrowed from Tcl ...
124  */
125 /*
126  * tclUtf.c --
127  *
128  *      Routines for manipulating UTF-8 strings.
129  *
130  * Copyright (c) 1997-1998 Sun Microsystems, Inc.
131  *
132  * See the file "license.terms" for information on usage and redistribution
133  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
134  *
135  * SCCS: @(#) tclUtf.c 1.25 98/01/28 18:02:43
136  */
137 
138 /*
139  *---------------------------------------------------------------------------
140  *
141  * gdTcl_UtfToUniChar --
142  *
143  *      Extract the Tcl_UniChar represented by the UTF-8 string.  Bad
144  *      UTF-8 sequences are converted to valid Tcl_UniChars and processing
145  *      continues.  Equivalent to Plan 9 chartorune().
146  *
147  *      The caller must ensure that the source buffer is long enough that
148  *      this routine does not run off the end and dereference non-existent
149  *      memory looking for trail bytes.  If the source buffer is known to
150  *      be '\0' terminated, this cannot happen.  Otherwise, the caller
151  *      should call Tcl_UtfCharComplete() before calling this routine to
152  *      ensure that enough bytes remain in the string.
153  *
154  * Results:
155  *      *chPtr is filled with the Tcl_UniChar, and the return value is the
156  *      number of bytes from the UTF-8 string that were consumed.
157  *
158  * Side effects:
159  *      None.
160  *
161  *---------------------------------------------------------------------------
162  */
163 
164 #ifdef JISX0208
165 #include "jisx0208.h"
166 #endif
167 
168 #define Tcl_UniChar int
169 #define TCL_UTF_MAX 3
170 static int
gdTcl_UtfToUniChar(char * str,Tcl_UniChar * chPtr)171 gdTcl_UtfToUniChar (char *str, Tcl_UniChar * chPtr)
172 /* str is the UTF8 next character pointer */
173 /* chPtr is the int for the result */
174 {
175   int byte;
176 
177   /* HTML4.0 entities in decimal form, e.g. &#197; */
178   byte = *((unsigned char *) str);
179   if (byte == '&')
180     {
181       int i, n = 0;
182 
183       byte = *((unsigned char *) (str + 1));
184       if (byte == '#')
185 	{
186 	  for (i = 2; i < 8; i++)
187 	    {
188 	      byte = *((unsigned char *) (str + i));
189 	      if (byte >= '0' && byte <= '9')
190 		{
191 		  n = (n * 10) + (byte - '0');
192 		}
193 	      else
194 		break;
195 	    }
196 	  if (byte == ';')
197 	    {
198 	      *chPtr = (Tcl_UniChar) n;
199 	      return ++i;
200 	    }
201 	}
202     }
203 
204   /*
205    * Unroll 1 to 3 byte UTF-8 sequences, use loop to handle longer ones.
206    */
207 
208   byte = *((unsigned char *) str);
209 #ifdef JISX0208
210   if (0xA1 <= byte && byte <= 0xFE)
211     {
212       int ku, ten;
213 
214       ku = (byte & 0x7F) - 0x20;
215       ten = (str[1] & 0x7F) - 0x20;
216       if ((ku < 1 || ku > 92) || (ten < 1 || ten > 94))
217 	{
218 	  *chPtr = (Tcl_UniChar) byte;
219 	  return 1;
220 	}
221 
222       *chPtr = (Tcl_UniChar) UnicodeTbl[ku - 1][ten - 1];
223       return 2;
224     }
225   else
226 #endif /* JISX0208 */
227   if (byte < 0xC0)
228     {
229       /*
230        * Handles properly formed UTF-8 characters between
231        * 0x01 and 0x7F.  Also treats \0 and naked trail
232        * bytes 0x80 to 0xBF as valid characters representing
233        * themselves.
234        */
235 
236       *chPtr = (Tcl_UniChar) byte;
237       return 1;
238     }
239   else if (byte < 0xE0)
240     {
241       if ((str[1] & 0xC0) == 0x80)
242 	{
243 	  /*
244 	   * Two-byte-character lead-byte followed
245 	   * by a trail-byte.
246 	   */
247 
248 	  *chPtr = (Tcl_UniChar) (((byte & 0x1F) << 6)
249 				  | (str[1] & 0x3F));
250 	  return 2;
251 	}
252       /*
253        * A two-byte-character lead-byte not followed by trail-byte
254        * represents itself.
255        */
256 
257       *chPtr = (Tcl_UniChar) byte;
258       return 1;
259     }
260   else if (byte < 0xF0)
261     {
262       if (((str[1] & 0xC0) == 0x80) && ((str[2] & 0xC0) == 0x80))
263 	{
264 	  /*
265 	   * Three-byte-character lead byte followed by
266 	   * two trail bytes.
267 	   */
268 
269 	  *chPtr = (Tcl_UniChar) (((byte & 0x0F) << 12)
270 				| ((str[1] & 0x3F) << 6) | (str[2] & 0x3F));
271 	  return 3;
272 	}
273       /*
274        * A three-byte-character lead-byte not followed by
275        * two trail-bytes represents itself.
276        */
277 
278       *chPtr = (Tcl_UniChar) byte;
279       return 1;
280     }
281 #if TCL_UTF_MAX > 3
282   else
283     {
284       int ch, total, trail;
285 
286       total = totalBytes[byte];
287       trail = total - 1;
288       if (trail > 0)
289 	{
290 	  ch = byte & (0x3F >> trail);
291 	  do
292 	    {
293 	      str++;
294 	      if ((*str & 0xC0) != 0x80)
295 		{
296 		  *chPtr = byte;
297 		  return 1;
298 		}
299 	      ch <<= 6;
300 	      ch |= (*str & 0x3F);
301 	      trail--;
302 	    }
303 	  while (trail > 0);
304 	  *chPtr = ch;
305 	  return total;
306 	}
307     }
308 #endif
309 
310   *chPtr = (Tcl_UniChar) byte;
311   return 1;
312 }
313 
314 /********************************************************************/
315 /* font cache functions                                             */
316 
317 static int
fontTest(void * element,void * key)318 fontTest (void *element, void *key)
319 {
320   font_t *a = (font_t *) element;
321   fontkey_t *b = (fontkey_t *) key;
322 
323   return (strcmp (a->fontlist, b->fontlist) == 0);
324 }
325 
326 static void *
fontFetch(char ** error,void * key)327 fontFetch (char **error, void *key)
328 {
329   font_t *a;
330   fontkey_t *b = (fontkey_t *) key;
331   int n;
332   int font_found = 0;
333   unsigned short platform, encoding;
334   char *fontsearchpath, *fontlist;
335   char *fullname = NULL;
336   char *name, *path, *dir;
337   char dummy = 0;
338   char *strtok_ptr = &dummy;
339   FT_Error err;
340   FT_CharMap found = 0;
341   FT_CharMap charmap;
342 
343   a = (font_t *) gdMalloc (sizeof (font_t));
344   a->fontlist = strdup (b->fontlist);
345   a->library = b->library;
346 
347   /*
348    * Search the pathlist for any of a list of font names.
349    */
350   fontsearchpath = getenv ("GDFONTPATH");
351   if (!fontsearchpath)
352     fontsearchpath = DEFAULT_FONTPATH;
353   path = strdup (fontsearchpath);
354   fontlist = strdup (a->fontlist);
355 
356   /*
357    * Must use gd_strtok_r else pointer corrupted by strtok in nested loop.
358    */
359   for (name = gd_strtok_r (fontlist, LISTSEPARATOR, &strtok_ptr); name;
360        name = gd_strtok_r (0, LISTSEPARATOR, &strtok_ptr))
361     {
362 
363       /*
364        * Allocate an oversized buffer that is guaranteed to be
365        * big enough for all paths to be tested.
366        */
367       fullname = gdRealloc (fullname,
368 			    strlen (fontsearchpath) + strlen (name) + 6);
369       /* if name is an absolute filename then test directly */
370       if (*name == '/')
371 	{
372 	  sprintf (fullname, "%s", name);
373 	  if (access (fullname, R_OK) == 0)
374 	    {
375 	      font_found++;
376 	      break;
377 	    }
378 	}
379       for (dir = strtok (path, PATHSEPARATOR); dir;
380 	   dir = strtok (0, PATHSEPARATOR))
381 	{
382 	  sprintf (fullname, "%s/%s.ttf", dir, name);
383 	  if (access (fullname, R_OK) == 0)
384 	    {
385 	      font_found++;
386 	      break;
387 	    }
388 	}
389       if (font_found)
390 	break;
391     }
392   gdFree (path);
393   gdFree (fontlist);
394   if (!font_found)
395     {
396       *error = "Could not find/open font";
397       gdFree (fullname);
398       gdFree (a);
399       return NULL;
400     }
401 
402   err = FT_New_Face (*b->library, fullname, 0, &a->face);
403   gdFree (fullname);
404   if (err)
405     {
406       *error = "Could not read font";
407       gdFree (a);
408       return NULL;
409     }
410 
411 /* FIXME - This mapping stuff is imcomplete - where is the spec? */
412 
413   a->have_char_map_unicode = 0;
414   a->have_char_map_big5 = 0;
415   a->have_char_map_sjis = 0;
416   a->have_char_map_apple_roman = 0;
417   for (n = 0; n < a->face->num_charmaps; n++)
418     {
419       charmap = a->face->charmaps[n];
420       platform = charmap->platform_id;
421       encoding = charmap->encoding_id;
422       if ((platform == 3 && encoding == 1)	/* Windows Unicode */
423 	  || (platform == 3 && encoding == 0)	/* Windows Symbol */
424 	  || (platform == 2 && encoding == 1)	/* ISO Unicode */
425 	  || (platform == 0))
426 	{			/* Apple Unicode */
427 	  a->have_char_map_unicode = 1;
428 	  found = charmap;
429 	}
430       else if (platform == 3 && encoding == 4)
431 	{			/* Windows Big5 */
432 	  a->have_char_map_big5 = 1;
433 	  found = charmap;
434 	}
435       else if (platform == 3 && encoding == 2)
436 	{			/* Windows Sjis */
437 	  a->have_char_map_sjis = 1;
438 	  found = charmap;
439 	}
440       else if ((platform == 1 && encoding == 0)		/* Apple Roman */
441 	       || (platform == 2 && encoding == 0))
442 	{			/* ISO ASCII */
443 	  a->have_char_map_apple_roman = 1;
444 	  found = charmap;
445 	}
446     }
447   if (!found)
448     {
449       *error = "Unable to find a CharMap that I can handle";
450       gdFree (a);
451       return NULL;
452     }
453 
454   return (void *) a;
455 }
456 
457 static void
fontRelease(void * element)458 fontRelease (void *element)
459 {
460   font_t *a = (font_t *) element;
461 
462   FT_Done_Face (a->face);
463   gdFree (a->fontlist);
464   gdFree ((char *) element);
465 }
466 
467 /********************************************************************/
468 /* tweencolor cache functions                                            */
469 
470 static int
tweenColorTest(void * element,void * key)471 tweenColorTest (void *element, void *key)
472 {
473   tweencolor_t *a = (tweencolor_t *) element;
474   tweencolorkey_t *b = (tweencolorkey_t *) key;
475 
476   return (a->pixel == b->pixel
477 	  && a->bgcolor == b->bgcolor
478 	  && a->fgcolor == b->fgcolor
479 	  && a->im == b->im);
480 }
481 
482 /*
483  * Computes a color in im's color table that is part way between
484  * the background and foreground colors proportional to the gray
485  * pixel value in the range 0-NUMCOLORS. The fg and bg colors must already
486  * be in the color table.
487  */
488 static void *
tweenColorFetch(char ** error,void * key)489 tweenColorFetch (char **error, void *key)
490 {
491   tweencolor_t *a;
492   tweencolorkey_t *b = (tweencolorkey_t *) key;
493   int pixel, npixel, bg, fg;
494   gdImagePtr im;
495 
496   (void)error;
497 
498   a = (tweencolor_t *) gdMalloc (sizeof (tweencolor_t));
499   pixel = a->pixel = b->pixel;
500   bg = a->bgcolor = b->bgcolor;
501   fg = a->fgcolor = b->fgcolor;
502   im = b->im;
503 
504   /* if fg is specified by a negative color idx, then don't antialias */
505   if (fg < 0)
506     {
507       a->tweencolor = -fg;
508     }
509   else
510     {
511       npixel = NUMCOLORS - pixel;
512       if (im->trueColor)
513 	{
514 	  /* 2.0.1: use gdImageSetPixel to do the alpha blending work,
515 	     or to just store the alpha level. All we have to do here
516 	     is incorporate our knowledge of the percentage of this
517 	     pixel that is really "lit" by pushing the alpha value
518 	     up toward transparency in edge regions. */
519 	  a->tweencolor = gdTrueColorAlpha (
520 					     gdTrueColorGetRed (fg),
521 					     gdTrueColorGetGreen (fg),
522 					     gdTrueColorGetBlue (fg),
523 	       gdAlphaMax - (gdTrueColorGetAlpha (fg) * pixel / NUMCOLORS));
524 	}
525       else
526 	{
527 	  a->tweencolor = gdImageColorResolve (im,
528 		   (pixel * im->red[fg] + npixel * im->red[bg]) / NUMCOLORS,
529 	       (pixel * im->green[fg] + npixel * im->green[bg]) / NUMCOLORS,
530 		(pixel * im->blue[fg] + npixel * im->blue[bg]) / NUMCOLORS);
531 	}
532     }
533   return (void *) a;
534 }
535 
536 static void
tweenColorRelease(void * element)537 tweenColorRelease (void *element)
538 {
539   gdFree ((char *) element);
540 }
541 
542 /* draw_bitmap - transfers glyph bitmap to GD image */
543 static char *
gdft_draw_bitmap(gdImage * im,int fg,FT_Bitmap bitmap,int pen_x,int pen_y)544 gdft_draw_bitmap (gdImage * im, int fg, FT_Bitmap bitmap, int pen_x, int pen_y)
545 {
546   unsigned char *pixel = 0;
547   int *tpixel = 0;
548   int x, y, pc;
549   unsigned row, col;
550 
551   tweencolor_t *tc_elem;
552   tweencolorkey_t tc_key;
553 
554   /* initialize tweenColorCache on first call */
555   static gdCache_head_t *tc_cache;
556 
557   if (!tc_cache)
558     {
559       tc_cache = gdCacheCreate (TWEENCOLORCACHESIZE,
560 			tweenColorTest, tweenColorFetch, tweenColorRelease);
561     }
562 
563   /* copy to image, mapping colors */
564   tc_key.fgcolor = fg;
565   tc_key.im = im;
566   for (row = 0; row < bitmap.rows; row++)
567     {
568       pc = row * bitmap.pitch;
569       y = pen_y + row;
570 
571       /* clip if out of bounds */
572       if (y >= im->sy || y < 0)
573 	continue;
574 
575       for (col = 0; col < bitmap.width; col++, pc++)
576 	{
577 	  const int trueColor = im->trueColor;
578 	  if (bitmap.pixel_mode == ft_pixel_mode_grays)
579 	    {
580 	      /*
581 	       * Round to NUMCOLORS levels of antialiasing for
582 	       * index color images since only 256 colors are
583 	       * available.
584 	       */
585 	      tc_key.pixel = ((bitmap.buffer[pc] * NUMCOLORS)
586 			      + bitmap.num_grays / 2)
587 		/ (bitmap.num_grays - 1);
588 	    }
589 	  else if (bitmap.pixel_mode == ft_pixel_mode_mono)
590 	    {
591 	      tc_key.pixel = ((bitmap.buffer[pc / 8]
592 			       << (pc % 8)) & 128) ? NUMCOLORS : 0;
593 	    }
594 	  else
595 	    {
596 	      return "Unsupported ft_pixel_mode";
597 	    }
598 
599 	  if (tc_key.pixel > 0)
600 	    {			/* if not background */
601 	      x = pen_x + col;
602 
603 	      /* clip if out of bounds */
604 	      if (x >= im->sx || x < 0)
605 		continue;
606 	      /* get pixel location in gd buffer */
607 	      if (trueColor)
608 		{
609 		  tpixel = &im->tpixels[y][x];
610 		}
611 	      else
612 		{
613 		  pixel = &im->pixels[y][x];
614 		}
615 	      if (tc_key.pixel == NUMCOLORS)
616 		{
617 		  /* use fg color directly */
618 		  if (trueColor)
619 		    {
620 		      *tpixel = fg;
621 		    }
622 		  else
623 		    {
624 		      *pixel = fg;
625 		    }
626 		}
627 	      else
628 		{
629 		  tc_elem = (tweencolor_t *) gdCacheGet (tc_cache, &tc_key);
630 		  if (!tc_elem) return tc_cache->error;
631 		  /* find antialised color */
632 		  if (trueColor)
633 		    {
634 		      tc_key.bgcolor = *tpixel;
635 		      *tpixel = tc_elem->tweencolor;
636 		    }
637 		  else
638 		    {
639 		      tc_key.bgcolor = *pixel;
640 		      *pixel = tc_elem->tweencolor;
641 		    }
642 		}
643 	    }
644 	}
645     }
646   return (char *) NULL;
647 }
648 
649 static int
gdroundupdown(FT_F26Dot6 v1,int updown)650 gdroundupdown (FT_F26Dot6 v1, int updown)
651 {
652   return (!updown)
653     ? (v1 < 0 ? ((v1 - 63) >> 6) : v1 >> 6)
654     : (v1 > 0 ? ((v1 + 63) >> 6) : v1 >> 6);
655 }
656 
657 #pragma GCC visibility push(hidden)
658 extern int any2eucjp (char *, char *, unsigned int);
659 #pragma GCC visibility pop
660 
661 /********************************************************************/
662 /* gdImageStringFT -  render a utf8 string onto a gd image          */
663 
664 char *
gdImageStringFT(gdImage * im,int * brect,int fg,char * fontlist,double ptsize,double angle,int x,int y,char * string)665 gdImageStringFT (gdImage * im, int *brect, int fg, char *fontlist,
666 		 double ptsize, double angle, int x, int y, char *string)
667 {
668   FT_BBox bbox, glyph_bbox;
669   FT_Matrix matrix;
670   FT_Vector pen, delta, penf;
671   FT_Face face;
672   FT_Glyph image;
673   FT_GlyphSlot slot;
674   FT_Error err;
675   FT_Bool use_kerning;
676   FT_UInt glyph_index, previous;
677   double sin_a = sin (angle);
678   double cos_a = cos (angle);
679   int len, i = 0, ch;
680   int x1 = 0, y1 = 0;
681   font_t *font;
682   fontkey_t fontkey;
683   char *next;
684   char *tmpstr = NULL;
685   int render = (im && (im->trueColor || (fg <= 255 && fg >= -255)));
686   FT_BitmapGlyph bm;
687 
688 /***** initialize font library and font cache on first call ******/
689   static gdCache_head_t *fontCache;
690   static FT_Library library;
691 
692   if (!fontCache)
693     {
694       if (FT_Init_FreeType (&library))
695 	{
696 	  return "Failure to initialize font library";
697 	}
698       fontCache = gdCacheCreate (FONTCACHESIZE,
699 				 fontTest, fontFetch, fontRelease);
700     }
701 /*****/
702 
703   /* get the font (via font cache) */
704   fontkey.fontlist = fontlist;
705   fontkey.library = &library;
706   font = (font_t *) gdCacheGet (fontCache, &fontkey);
707   if (!font)
708     {
709       return fontCache->error;
710     }
711   face = font->face;		/* shortcut */
712   slot = face->glyph;		/* shortcut */
713 
714   if (FT_Set_Char_Size (face, 0, (FT_F26Dot6) (ptsize * 64),
715 			GD_RESOLUTION, GD_RESOLUTION))
716     {
717       return "Could not set character size";
718     }
719 
720   matrix.xx = (FT_Fixed) (cos_a * (1 << 16));
721   matrix.yx = (FT_Fixed) (sin_a * (1 << 16));
722   matrix.xy = -matrix.yx;
723   matrix.yy = matrix.xx;
724 
725   penf.x = penf.y = 0;		/* running position of non-rotated string */
726   pen.x = pen.y = 0;		/* running position of rotated string */
727   bbox.xMin = bbox.xMax = bbox.yMin = bbox.yMax = 0;
728 
729   use_kerning = FT_HAS_KERNING (face);
730   previous = 0;
731 
732 #ifndef JISX0208
733   if (font->have_char_map_sjis)
734     {
735 #endif
736       if ((tmpstr = (char *) gdMalloc (BUFSIZ)))
737 	{
738 	  any2eucjp (tmpstr, string, BUFSIZ);
739 	  next = tmpstr;
740 	}
741       else
742 	{
743 	  next = string;
744 	}
745 #ifndef JISX0208
746     }
747   else
748     {
749       next = string;
750     }
751 #endif
752   while (*next)
753     {
754       ch = *next;
755 
756       /* carriage returns */
757       if (ch == '\r')
758 	{
759 	  penf.x = 0;
760 	  x1 = (penf.x * cos_a - penf.y * sin_a + 32) / 64;
761 	  y1 = (penf.x * sin_a + penf.y * cos_a + 32) / 64;
762 	  pen.x = pen.y = 0;
763 	  previous = 0;		/* clear kerning flag */
764 	  next++;
765 	  continue;
766 	}
767       /* newlines */
768       if (ch == '\n')
769 	{
770 	  penf.y -= face->size->metrics.height * LINESPACE;
771 	  penf.y = (penf.y - 32) & -64;		/* round to next pixel row */
772 	  x1 = (penf.x * cos_a - penf.y * sin_a + 32) / 64;
773 	  y1 = (penf.x * sin_a + penf.y * cos_a + 32) / 64;
774 	  pen.x = pen.y = 0;
775 	  previous = 0;		/* clear kerning flag */
776 	  next++;
777 	  continue;
778 	}
779 
780       if (font->have_char_map_unicode)
781 	{
782 	  /* use UTF-8 mapping from ASCII */
783 	  len = gdTcl_UtfToUniChar (next, &ch);
784 	  next += len;
785 	}
786       else if (font->have_char_map_sjis)
787 	{
788 	  unsigned char c;
789 	  int jiscode;
790 
791 	  c = *next;
792 	  if (0xA1 <= c && c <= 0xFE)
793 	    {
794 	      next++;
795 	      jiscode = 0x100 * (c & 0x7F) + ((*next) & 0x7F);
796 
797 	      ch = (jiscode >> 8) & 0xFF;
798 	      jiscode &= 0xFF;
799 
800 	      if (ch & 1)
801 		jiscode += 0x40 - 0x21;
802 	      else
803 		jiscode += 0x9E - 0x21;
804 
805 	      if (jiscode >= 0x7F)
806 		jiscode++;
807 	      ch = (ch - 0x21) / 2 + 0x81;
808 	      if (ch >= 0xA0)
809 		ch += 0x40;
810 
811 	      ch = (ch << 8) + jiscode;
812 	    }
813 	  else
814 	    {
815 	      ch = c & 0xFF;	/* don't extend sign */
816 	    }
817 	  if (*next) next++;
818 	}
819       else
820 	{
821 	  /*
822 	   * Big 5 mapping:
823 	   * use "JIS-8 half-width katakana" coding from 8-bit characters. Ref:
824 	   * ftp://ftp.ora.com/pub/examples/nutshell/ujip/doc/japan.inf-032092.sjs
825 	   */
826 	  ch = (*next) & 0xFF;	/* don't extend sign */
827 	  next++;
828 	  if (ch >= 161		/* first code of JIS-8 pair */
829 	      && *next)
830 	    {			/* don't advance past '\0' */
831 	      /* TBB: Fix from Kwok Wah On: & 255 needed */
832 	      ch = (ch * 256) + ((*next) & 255);
833 	      next++;
834 	    }
835 	}
836 
837       /* Convert character code to glyph index */
838       glyph_index = FT_Get_Char_Index (face, ch);
839 
840       /* retrieve kerning distance and move pen position */
841       if (use_kerning && previous && glyph_index)
842 	{
843 	  FT_Get_Kerning (face, previous, glyph_index,
844 			  ft_kerning_default, &delta);
845 	  pen.x += delta.x;
846 	}
847 
848       /* load glyph image into the slot (erase previous one) */
849       err = FT_Load_Glyph (face, glyph_index, FT_LOAD_DEFAULT);
850       if (err)
851       {
852 	gdFree (tmpstr);
853 	return "Problem loading glyph";
854       }
855 
856       /* transform glyph image */
857       FT_Get_Glyph (slot, &image);
858       if (brect)
859 	{			/* only if need brect */
860 	  FT_Glyph_Get_CBox (image, ft_glyph_bbox_gridfit, &glyph_bbox);
861 	  if (!i)
862 	    {			/* if first character, init BB corner values */
863 	      bbox.xMin = bbox.yMin = (1 << 30) - 1;
864 	      bbox.xMax = bbox.yMax = -bbox.xMin;
865 	    }
866 	  glyph_bbox.xMin += penf.x;
867 	  glyph_bbox.yMin += penf.y;
868 	  glyph_bbox.xMax += penf.x;
869 	  glyph_bbox.yMax += penf.y;
870 	  if (bbox.xMin > glyph_bbox.xMin)
871 	    bbox.xMin = glyph_bbox.xMin;
872 	  if (bbox.yMin > glyph_bbox.yMin)
873 	    bbox.yMin = glyph_bbox.yMin;
874 	  if (bbox.xMax < glyph_bbox.xMax)
875 	    bbox.xMax = glyph_bbox.xMax;
876 	  if (bbox.yMax < glyph_bbox.yMax)
877 	    bbox.yMax = glyph_bbox.yMax;
878 	  i++;
879 	}
880 
881       /* transform glyph image */
882       FT_Glyph_Transform (image, &matrix, 0);
883 
884       if (render)
885 	{
886 	  if (image->format != ft_glyph_format_bitmap)
887 	    {
888 	      err = FT_Glyph_To_Bitmap (&image, ft_render_mode_normal, 0, 1);
889 	      if (err)
890 	      {
891 		gdFree (tmpstr);
892 		return "Problem rendering glyph";
893 	      }
894 	    }
895 
896 	  /* now, draw to our target surface */
897 	  bm = (FT_BitmapGlyph) image;
898 	  gdft_draw_bitmap (im, fg, bm->bitmap,
899 			    x + x1 + ((pen.x + 31) >> 6) + bm->left,
900 			    y - y1 + ((pen.y + 31) >> 6) - bm->top);
901 	}
902 
903       /* record current glyph index for kerning */
904       previous = glyph_index;
905 
906       /* increment pen position */
907       pen.x += image->advance.x >> 10;
908       pen.y -= image->advance.y >> 10;
909 
910       penf.x += slot->metrics.horiAdvance;
911 
912       FT_Done_Glyph (image);
913     }
914 
915   if (brect)
916     {				/* only if need brect */
917       /* For perfect rounding, must get sin(a + pi/4) and sin(a - pi/4). */
918       double d1 = sin (angle + 0.78539816339744830962);
919       double d2 = sin (angle - 0.78539816339744830962);
920 
921       /* rotate bounding rectangle */
922       brect[0] = (int) (bbox.xMin * cos_a - bbox.yMin * sin_a);
923       brect[1] = (int) (bbox.xMin * sin_a + bbox.yMin * cos_a);
924       brect[2] = (int) (bbox.xMax * cos_a - bbox.yMin * sin_a);
925       brect[3] = (int) (bbox.xMax * sin_a + bbox.yMin * cos_a);
926       brect[4] = (int) (bbox.xMax * cos_a - bbox.yMax * sin_a);
927       brect[5] = (int) (bbox.xMax * sin_a + bbox.yMax * cos_a);
928       brect[6] = (int) (bbox.xMin * cos_a - bbox.yMax * sin_a);
929       brect[7] = (int) (bbox.xMin * sin_a + bbox.yMax * cos_a);
930 
931       /* scale, round and offset brect */
932       brect[0] = x + gdroundupdown (brect[0], d2 > 0);
933       brect[1] = y - gdroundupdown (brect[1], d1 < 0);
934       brect[2] = x + gdroundupdown (brect[2], d1 > 0);
935       brect[3] = y - gdroundupdown (brect[3], d2 > 0);
936       brect[4] = x + gdroundupdown (brect[4], d2 < 0);
937       brect[5] = y - gdroundupdown (brect[5], d1 > 0);
938       brect[6] = x + gdroundupdown (brect[6], d1 < 0);
939       brect[7] = y - gdroundupdown (brect[7], d2 < 0);
940     }
941 
942   gdFree (tmpstr);
943   return (char *) NULL;
944 }
945 
946 #endif /* HAVE_LIBFREETYPE */
947