40 double ptsize,
double angle,
int x,
int y,
char *
string)
43 return gdImageStringFT (im, brect, fg, fontlist, ptsize, angle, x, y,
string);
46#ifndef HAVE_LIBFREETYPE
49 double ptsize,
double angle,
int x,
int y,
char *
string,
52 return "libgd was not built with FreeType font support\n";
57 double ptsize,
double angle,
int x,
int y,
char *
string)
59 return "libgd was not built with FreeType font support\n";
69#define FONTCACHESIZE 6
72#define TWEENCOLORCACHESIZE 32
85#define LISTSEPARATOR ";"
93#ifndef DEFAULT_FONTPATH
94#if defined(__APPLE__) || (defined(__MWERKS__) && defined(macintosh))
95#define DEFAULT_FONTPATH "/usr/share/fonts/truetype:/System/Library/Fonts:/Library/Fonts"
97#define DEFAULT_FONTPATH "/usr/share/fonts/truetype"
101#define PATHSEPARATOR ":"
110#define MAX(a,b) ((a)>(b)?(a):(b))
114#define MIN(a,b) ((a)<(b)?(a):(b))
122 FT_Bool have_char_map_unicode, have_char_map_big5, have_char_map_sjis, have_char_map_apple_roman;
196extern int any2eucjp (
char *,
char *,
unsigned int);
204static FT_Library library;
206#define Tcl_UniChar int
208static int gdTcl_UtfToUniChar (
char *str, Tcl_UniChar * chPtr)
215 byte = *((
unsigned char *) str);
219 byte = *((
unsigned char *) (str + 1));
221 byte = *((
unsigned char *) (str + 2));
222 if (
byte ==
'x' ||
byte ==
'X') {
223 for (i = 3; i < 8; i++) {
224 byte = *((
unsigned char *) (str + i));
225 if (
byte >=
'A' &&
byte <=
'F')
226 byte =
byte -
'A' + 10;
227 else if (
byte >=
'a' &&
byte <=
'f')
228 byte =
byte -
'a' + 10;
229 else if (
byte >=
'0' &&
byte <=
'9')
236 for (i = 2; i < 8; i++) {
237 byte = *((
unsigned char *) (str + i));
238 if (
byte >=
'0' &&
byte <=
'9') {
239 n = (
n * 10) + (
byte -
'0');
246 *chPtr = (Tcl_UniChar)
n;
254 byte = *((
unsigned char *) str);
256 if (0xA1 <=
byte &&
byte <= 0xFE) {
259 ku = (
byte & 0x7F) - 0x20;
260 ten = (str[1] & 0x7F) - 0x20;
261 if ((ku < 1 || ku > 92) || (ten < 1 || ten > 94)) {
262 *chPtr = (Tcl_UniChar)
byte;
266 *chPtr = (Tcl_UniChar) UnicodeTbl[ku - 1][ten - 1];
277 *chPtr = (Tcl_UniChar)
byte;
279 }
else if (
byte < 0xE0) {
280 if ((str[1] & 0xC0) == 0x80) {
283 *chPtr = (Tcl_UniChar) (((
byte & 0x1F) << 6) | (str[1] & 0x3F));
291 *chPtr = (Tcl_UniChar)
byte;
293 }
else if (
byte < 0xF0) {
294 if (((str[1] & 0xC0) == 0x80) && ((str[2] & 0xC0) == 0x80)) {
297 *chPtr = (Tcl_UniChar) (((
byte & 0x0F) << 12) | ((str[1] & 0x3F) << 6) | (str[2] & 0x3F));
302 *chPtr = (Tcl_UniChar)
byte;
309 total = totalBytes[byte];
313 ch =
byte & (0x3F >> trail);
316 if ((*str & 0xC0) != 0x80) {
330 *chPtr = (Tcl_UniChar)
byte;
337static int fontTest (
void *element,
void *
key)
339 font_t *
a = (font_t *) element;
340 fontkey_t *b = (fontkey_t *)
key;
342 if (
strcmp (
a->fontlist, b->fontlist) == 0) {
343 switch (b->preferred_map) {
345 if (
a->have_char_map_unicode) {
350 if (
a->have_char_map_sjis) {
355 if (
a->have_char_map_sjis) {
364static void *fontFetch (
char **
error,
void *
key)
367 fontkey_t *b = (fontkey_t *)
key;
371 char *fontsearchpath, *fontlist;
376 FT_CharMap found = 0;
381 a->library = b->library;
386 fontsearchpath =
getenv (
"GDFONTPATH");
387 if (!fontsearchpath) {
396 char *strtok_ptr_path;
405 unsigned int min_length = 0;
406 if (
name[0] !=
'\0') {
407 if (
name[1] !=
'\0') {
417 if (access(fullname,
R_OK) == 0) {
427#elif defined(HAVE_GETWD)
435#define GD_CHECK_FONT_PATH(ext) \
436 snprintf(fullname, sizeof(fullname) - 1, "%s/%s%s", dir, name, ext); \
437 if (access(fullname, R_OK) == 0) { \
442 GD_CHECK_FONT_PATH(
"");
443 GD_CHECK_FONT_PATH(
".ttf");
444 GD_CHECK_FONT_PATH(
".pfa");
445 GD_CHECK_FONT_PATH(
".pfb");
446 GD_CHECK_FONT_PATH(
".dfont");
464 *
error =
"Could not find/open font";
468 err = FT_New_Face (*b->library, fullname, 0, &
a->face);
472 *
error =
"Could not read font";
488 for (
n = 0;
n <
a->face->num_charmaps;
n++) {
489 charmap =
a->face->charmaps[
n];
490 platform = charmap->platform_id;
494 a->have_char_map_unicode = 0;
495 a->have_char_map_big5 = 0;
496 a->have_char_map_sjis = 0;
497 a->have_char_map_apple_roman = 0;
500#if (defined(FREETYPE_MAJOR) && ((FREETYPE_MAJOR == 2 && ((FREETYPE_MINOR == 1 && FREETYPE_PATCH >= 3) || FREETYPE_MINOR > 1) || FREETYPE_MAJOR > 2)))
501 if (charmap->encoding == FT_ENCODING_MS_SYMBOL
502 || charmap->encoding == FT_ENCODING_ADOBE_CUSTOM
503 || charmap->encoding == FT_ENCODING_ADOBE_STANDARD) {
504 a->have_char_map_unicode = 1;
506 a->face->charmap = charmap;
512 if ((platform == 3 &&
encoding == 1)
517 a->have_char_map_unicode = 1;
522 }
else if (platform == 3 &&
encoding == 4) {
523 a->have_char_map_big5 = 1;
528 }
else if (platform == 3 &&
encoding == 2) {
529 a->have_char_map_sjis = 1;
534 }
else if ((platform == 1 &&
encoding == 0)
535 || (platform == 2 &&
encoding == 0))
537 a->have_char_map_apple_roman = 1;
547 *
error =
"Unable to find a CharMap that I can handle";
552 a->face->charmap = found;
556static void fontRelease (
void *element)
558 font_t *
a = (font_t *) element;
560 FT_Done_Face (
a->face);
568static int tweenColorTest (
void *element,
void *
key)
570 tweencolor_t *
a = (tweencolor_t *) element;
571 tweencolorkey_t *b = (tweencolorkey_t *)
key;
573 return (
a->pixel == b->pixel &&
a->bgcolor == b->bgcolor &&
a->fgcolor == b->fgcolor &&
a->im == b->im);
585static void * tweenColorFetch (
char **
error,
void *
key)
588 tweencolorkey_t *b = (tweencolorkey_t *)
key;
589 int pixel, npixel, bg, fg;
592 a = (tweencolor_t *)
gdMalloc (
sizeof (tweencolor_t));
593 pixel =
a->pixel = b->pixel;
594 bg =
a->bgcolor = b->bgcolor;
595 fg =
a->fgcolor = b->fgcolor;
629static void tweenColorRelease (
void *element)
635static char * gdft_draw_bitmap (
gdCache_head_t *tc_cache,
gdImage * im,
int fg, FT_Bitmap bitmap,
int pen_x,
int pen_y)
637 unsigned char *pixel =
NULL;
640 int x, y, row, col, pc, pcr;
642 tweencolor_t *tc_elem;
643 tweencolorkey_t tc_key;
650 for (row = 0; row < bitmap.rows; row++) {
651 pc = row * bitmap.pitch;
656 if ((y > im->
cy2) || (y < im->cy1)) {
659 for (col = 0; col < bitmap.width; col++, pc++) {
661 if (bitmap.pixel_mode == ft_pixel_mode_grays) {
665 level = (bitmap.buffer[pc] *
gdAlphaMax / (bitmap.num_grays - 1));
666 }
else if (bitmap.pixel_mode == ft_pixel_mode_mono) {
670 return "Unsupported ft_pixel_mode";
686 if ((x > im->
cx2) || (x < im->cx1)) {
700 (level << 24) + (fg & 0xFFFFFF));
702 *tpixel = (level << 24) + (fg & 0xFFFFFF);
705 *tpixel = (level << 24) + (fg & 0xFFFFFF);
710 return (
char *)
NULL;
713 for (row = 0; row < bitmap.rows; row++) {
715 pc = row * bitmap.pitch;
717 if (bitmap.pixel_mode==ft_pixel_mode_mono) {
723 if (y > im->
cy2 || y < im->cy1) {
727 for (col = 0; col < bitmap.width; col++, pc++) {
728 if (bitmap.pixel_mode == ft_pixel_mode_grays) {
734 tc_key.pixel = ((bitmap.buffer[pc] *
NUMCOLORS) + bitmap.num_grays / 2) / (bitmap.num_grays - 1);
735 }
else if (bitmap.pixel_mode == ft_pixel_mode_mono) {
736 tc_key.pixel = ((bitmap.buffer[pc / 8] << (pc % 8)) & 128) ?
NUMCOLORS : 0;
738 tc_key.pixel = ((bitmap.buffer[(col>>3)+pcr]) & (1<<(~col&0x07))) ?
NUMCOLORS : 0;
740 return "Unsupported ft_pixel_mode";
742 if (tc_key.pixel > 0) {
746 if (x > im->
cx2 || x < im->cx1) {
750 pixel = &im->
pixels[y][x];
755 *pixel = (fg < 0) ? -fg : fg;
758 tc_key.bgcolor = *pixel;
759 tc_elem = (tweencolor_t *)
gdCacheGet(tc_cache, &tc_key);
760 *pixel = tc_elem->tweencolor;
765 return (
char *)
NULL;
769gdroundupdown (FT_F26Dot6 v1,
int roundup)
771 return (!
roundup) ? v1 >> 6 : (v1 + 63) >> 6;
781 FT_Done_FreeType(library);
787void gdFreeFontCache(
void)
808 if (FT_Init_FreeType(&library)) {
811 fontCache =
gdCacheCreate (FONTCACHESIZE, fontTest, fontFetch, fontRelease);
821 double ptsize,
double angle,
int x,
int y,
char *
string)
823 return gdImageStringFTEx(im, brect, fg, fontlist, ptsize, angle, x, y,
string, 0);
829 FT_BBox bbox, glyph_bbox;
831 FT_Vector pen, delta, penf;
836 FT_UInt glyph_index, previous;
837 double sin_a =
sin (angle);
838 double cos_a =
cos (angle);
845 int render = (im && (im->
trueColor || (fg <= 255 && fg >= -255)));
848 int render_mode = FT_LOAD_DEFAULT;
851 double linespace = LINESPACE;
867 tc_cache =
gdCacheCreate(TWEENCOLORCACHESIZE, tweenColorTest, tweenColorFetch, tweenColorRelease);
876 return "Failure to initialize font library";
890 fontkey.fontlist = fontlist;
891 fontkey.library = &library;
892 fontkey.preferred_map = m;
893 font = (font_t *)
gdCacheGet (fontCache, &fontkey);
897 return fontCache->
error;
914 if (FT_Set_Char_Size(face, 0, (FT_F26Dot6) (ptsize * 64), hdpi, vdpi)) {
917 return "Could not set character size";
920 matrix.xx = (FT_Fixed) (cos_a * (1 << 16));
921 matrix.yx = (FT_Fixed) (sin_a * (1 << 16));
927 bbox.xMin = bbox.xMax = bbox.yMin = bbox.yMax = 0;
929 use_kerning = FT_HAS_KERNING (face);
932 render_mode |= FT_LOAD_MONOCHROME;
937 for (i = 0; i < 3; i++) {
940 if (font->have_char_map_unicode) {
945 if (font->have_char_map_sjis) {
963 return "No character set found";
967 if (font->have_char_map_sjis) {
985 x1 = (int)(- penf.y * sin_a + 32) / 64;
986 y1 = (int)(- penf.y * cos_a + 32) / 64;
994 if (!*(++
next))
break;
997 penf.y -= (long)(face->size->metrics.height * linespace);
998 penf.y = (penf.y - 32) & -64;
999 x1 = (int)(- penf.y * sin_a + 32) / 64;
1000 y1 = (int)(- penf.y * cos_a + 32) / 64;
1007#if (defined(FREETYPE_MAJOR) && ((FREETYPE_MAJOR == 2 && ((FREETYPE_MINOR == 1 && FREETYPE_PATCH >= 3) || FREETYPE_MINOR > 1) || FREETYPE_MAJOR > 2)))
1008 if (font->face->family_name && font->face->charmap->encoding &&
1009 font->face->charmap->encoding == FT_ENCODING_MS_SYMBOL &&
strcmp(font->face->family_name,
"Symbol") == 0) {
1025 if (font->have_char_map_unicode) {
1032 if (font->have_char_map_sjis) {
1036 if (0xA1 <= c && c <= 0xFE) {
1038 jiscode = 0x100 * (c & 0x7F) + ((*
next) & 0x7F);
1040 ch = (jiscode >> 8) & 0xFF;
1044 jiscode += 0x40 - 0x21;
1046 jiscode += 0x9E - 0x21;
1049 if (jiscode >= 0x7F) {
1052 ch = (
ch - 0x21) / 2 + 0x81;
1057 ch = (
ch << 8) + jiscode;
1070 ch = (*next) & 0xFF;
1085 glyph_index = FT_Get_Char_Index(face,
ch);
1088 if (use_kerning && previous && glyph_index) {
1089 FT_Get_Kerning(face, previous, glyph_index, ft_kerning_default, &delta);
1090 pen.x += (int)(delta.x * cos_a);
1091 pen.y -= (int)(delta.x * sin_a);
1097 if (FT_Load_Glyph(face, glyph_index, render_mode | FT_LOAD_IGNORE_TRANSFORM)) {
1103 return "Problem loading glyph";
1107 if (FT_Get_Glyph(slot, &image)) {
1113 return "Problem loading glyph";
1116 FT_Glyph_Get_CBox(image, ft_glyph_bbox_gridfit, &glyph_bbox);
1117 glyph_bbox.xMin += penf.x;
1118 glyph_bbox.yMin += penf.y;
1119 glyph_bbox.xMax += penf.x;
1120 glyph_bbox.yMax += penf.y;
1122 glyph_bbox.xMax += slot->metrics.horiAdvance;
1125 bbox.xMin = glyph_bbox.xMin;
1126 bbox.yMin = glyph_bbox.yMin;
1127 bbox.xMax = glyph_bbox.xMax;
1128 bbox.yMax = glyph_bbox.yMax;
1130 if (bbox.xMin > glyph_bbox.xMin) {
1131 bbox.xMin = glyph_bbox.xMin;
1133 if (bbox.yMin > glyph_bbox.yMin) {
1134 bbox.yMin = glyph_bbox.yMin;
1136 if (bbox.xMax < glyph_bbox.xMax) {
1137 bbox.xMax = glyph_bbox.xMax;
1139 if (bbox.yMax < glyph_bbox.yMax) {
1140 bbox.yMax = glyph_bbox.yMax;
1147 penf.x += slot->metrics.horiAdvance;
1150 if (!brect || angle != 0) {
1152 FT_Done_Glyph(image);
1155 if (FT_Load_Glyph(face, glyph_index, render_mode)) {
1161 return "Problem loading glyph";
1165 if (FT_Get_Glyph(slot, &image)) {
1171 return "Problem loading glyph";
1175 if (image->format != ft_glyph_format_bitmap && FT_Glyph_To_Bitmap(&image, ft_render_mode_normal, 0, 1)) {
1176 FT_Done_Glyph(image);
1182 return "Problem rendering glyph";
1186 bm = (FT_BitmapGlyph) image;
1187 gdft_draw_bitmap(tc_cache, im, fg, bm->bitmap, x + x1 + ((pen.x + 31) >> 6) + bm->left, y + y1 + ((pen.y + 31) >> 6) - bm->top);
1191 previous = glyph_index;
1194 pen.x += image->advance.x >> 10;
1195 pen.y -= image->advance.y >> 10;
1197 FT_Done_Glyph(image);
1202 double d1 =
sin (angle + 0.78539816339744830962);
1203 double d2 =
sin (angle - 0.78539816339744830962);
1206 brect[0] = (int) (bbox.xMin * cos_a - bbox.yMin * sin_a);
1207 brect[1] = (int) (bbox.xMin * sin_a + bbox.yMin * cos_a);
1208 brect[2] = (int) (bbox.xMax * cos_a - bbox.yMin * sin_a);
1209 brect[3] = (int) (bbox.xMax * sin_a + bbox.yMin * cos_a);
1210 brect[4] = (int) (bbox.xMax * cos_a - bbox.yMax * sin_a);
1211 brect[5] = (int) (bbox.xMax * sin_a + bbox.yMax * cos_a);
1212 brect[6] = (int) (bbox.xMin * cos_a - bbox.yMax * sin_a);
1213 brect[7] = (int) (bbox.xMin * sin_a + bbox.yMax * cos_a);
1216 brect[0] = x + gdroundupdown(brect[0],
d2 > 0);
1217 brect[1] = y - gdroundupdown(brect[1],
d1 < 0);
1218 brect[2] = x + gdroundupdown(brect[2],
d1 > 0);
1219 brect[3] = y - gdroundupdown(brect[3],
d2 > 0);
1220 brect[4] = x + gdroundupdown(brect[4],
d2 < 0);
1221 brect[5] = y - gdroundupdown(brect[5],
d1 > 0);
1222 brect[6] = x + gdroundupdown(brect[6],
d1 < 0);
1223 brect[7] = y - gdroundupdown(brect[7],
d2 < 0);
1231 return (
char *)
NULL;
getenv(?string $name=null, bool $local_only=false)
dir(string $directory, $context=null)
strstr(string $haystack, string $needle, bool $before_needle=false)
#define gdTrueColorGetBlue(c)
int gdFontCacheSetup(void)
void gdFontCacheMutexShutdown(void)
#define gdAlphaTransparent
#define gdTrueColorGetGreen(c)
#define gdTrueColorGetAlpha(c)
void gdFontCacheMutexSetup(void)
void gdFontCacheShutdown(void)
#define gdTrueColorGetRed(c)
#define gdFTEX_RESOLUTION
#define gdTrueColorAlpha(r, g, b, a)
struct gdFTStringExtra * gdFTStringExtraPtr
struct gdImageStruct gdImage
void gdCacheDelete(gdCache_head_t *head)
gdCache_head_t * gdCacheCreate(int size, gdCacheTestFn_t gdCacheTest, gdCacheFetchFn_t gdCacheFetch, gdCacheReleaseFn_t gdCacheRelease)
void * gdCacheGet(gdCache_head_t *head, void *keydata)
struct gdCache_head_s gdCache_head_t
char * gdImageStringFTEx(gdImage *im, int *brect, int fg, char *fontlist, double ptsize, double angle, int x, int y, char *string, gdFTStringExtraPtr strex)
char * gdImageStringTTF(gdImage *im, int *brect, int fg, char *fontlist, double ptsize, double angle, int x, int y, char *string)
char * gdImageStringFT(gdImage *im, int *brect, int fg, char *fontlist, double ptsize, double angle, int x, int y, char *string)
char * gd_strtok_r(char *s, char *sep, char **state)
#define gdMutexShutdown(x)
#define gdMutexDeclare(x)
int any2eucjp(unsigned char *dest, unsigned char *src, unsigned int dest_max)
int gdAlphaBlend(int dst, int src)
int gdImageColorResolve(gdImagePtr im, int r, int g, int b)
unsigned char key[REFLECTION_KEY_LEN]
xmlCharEncodingHandlerPtr encoding
strcmp(string $string1, string $string2)
#define ZEND_IGNORE_VALUE(x)
#define IS_ABSOLUTE_PATH(path, len)
#define VCWD_GETCWD(buff, size)