📄 gdft.c
字号:
} for (dir = strtok (path, PATHSEPARATOR); dir; dir = strtok (0, PATHSEPARATOR)) { if (!strcmp(dir, ".")) { TSRMLS_FETCH();#if HAVE_GETCWD dir = VCWD_GETCWD(cur_dir, MAXPATHLEN);#elif HAVE_GETWD dir = VCWD_GETWD(cur_dir);#endif if (!dir) { continue; } }#define GD_CHECK_FONT_PATH(ext) \ snprintf(fullname, sizeof(fullname) - 1, "%s/%s%s", dir, name, ext); \ if (access(fullname, R_OK) == 0) { \ font_found++; \ break; \ } \ GD_CHECK_FONT_PATH(""); GD_CHECK_FONT_PATH(".ttf"); GD_CHECK_FONT_PATH(".pfa"); GD_CHECK_FONT_PATH(".pfb"); GD_CHECK_FONT_PATH(".dfont"); } gdFree(path); path = NULL; if (font_found) { break; } } if (path) { gdFree(path); } gdFree(fontlist); if (!font_found) { gdPFree(a->fontlist); gdPFree(a); *error = "Could not find/open font"; return NULL; } err = FT_New_Face (*b->library, fullname, 0, &a->face); if (err) { gdPFree(a->fontlist); gdPFree(a); *error = "Could not read font"; return NULL; } /* FIXME - This mapping stuff is imcomplete - where is the spec? */ /* EAM - It's worse than that. It's pointless to match character encodings here. * As currently written, the stored a->face->charmap only matches one of * the actual charmaps and we cannot know at this stage if it is the right * one. We should just skip all this stuff, and check in gdImageStringFTEx * if some particular charmap is preferred and if so whether it is held in * one of the a->face->charmaps[0..num_charmaps]. * And why is it so bad not to find any recognized charmap? The user may * still know what mapping to use, even if we do not. In that case we can * just use the map in a->face->charmaps[num_charmaps] and be done with it. */ a->have_char_map_unicode = 0; a->have_char_map_big5 = 0; a->have_char_map_sjis = 0; a->have_char_map_apple_roman = 0; for (n = 0; n < a->face->num_charmaps; n++) { charmap = a->face->charmaps[n]; platform = charmap->platform_id; encoding = charmap->encoding_id;/* EAM DEBUG - Newer versions of libfree2 make it easier by defining encodings */#if (defined(FREETYPE_MAJOR) && ((FREETYPE_MAJOR == 2 && ((FREETYPE_MINOR == 1 && FREETYPE_PATCH >= 3) || FREETYPE_MINOR > 1) || FREETYPE_MAJOR > 2))) if (charmap->encoding == FT_ENCODING_MS_SYMBOL || charmap->encoding == FT_ENCODING_ADOBE_CUSTOM || charmap->encoding == FT_ENCODING_ADOBE_STANDARD) { a->have_char_map_unicode = 1; found = charmap; a->face->charmap = charmap; return (void *)a; }#endif /* Freetype 2.1.3 or better *//* EAM DEBUG */ if ((platform == 3 && encoding == 1) /* Windows Unicode */ || (platform == 3 && encoding == 0) /* Windows Symbol */ || (platform == 2 && encoding == 1) /* ISO Unicode */ || (platform == 0)) { /* Apple Unicode */ a->have_char_map_unicode = 1; found = charmap; } else if (platform == 3 && encoding == 4) { /* Windows Big5 */ a->have_char_map_big5 = 1; found = charmap; } else if (platform == 3 && encoding == 2) { /* Windows Sjis */ a->have_char_map_sjis = 1; found = charmap; } else if ((platform == 1 && encoding == 0) /* Apple Roman */ || (platform == 2 && encoding == 0)) { /* ISO ASCII */ a->have_char_map_apple_roman = 1; found = charmap; } } if (!found) { gdPFree(a->fontlist); gdPFree(a); *error = "Unable to find a CharMap that I can handle"; return NULL; } /* 2.0.5: we should actually return this */ a->face->charmap = found; return (void *) a;}static void fontRelease (void *element){ font_t *a = (font_t *) element; FT_Done_Face (a->face); gdPFree(a->fontlist); gdPFree((char *) element);}/********************************************************************//* tweencolor cache functions */static int tweenColorTest (void *element, void *key){ tweencolor_t *a = (tweencolor_t *) element; tweencolorkey_t *b = (tweencolorkey_t *) key; return (a->pixel == b->pixel && a->bgcolor == b->bgcolor && a->fgcolor == b->fgcolor && a->im == b->im);}/* * Computes a color in im's color table that is part way between * the background and foreground colors proportional to the gray * pixel value in the range 0-NUMCOLORS. The fg and bg colors must already * be in the color table for palette images. For truecolor images the * returned value simply has an alpha component and gdImageAlphaBlend * does the work so that text can be alpha blended across a complex * background (TBB; and for real in 2.0.2). */static void * tweenColorFetch (char **error, void *key){ tweencolor_t *a; tweencolorkey_t *b = (tweencolorkey_t *) key; int pixel, npixel, bg, fg; gdImagePtr im; a = (tweencolor_t *) gdMalloc (sizeof (tweencolor_t)); pixel = a->pixel = b->pixel; bg = a->bgcolor = b->bgcolor; fg = a->fgcolor = b->fgcolor; im = b->im; /* if fg is specified by a negative color idx, then don't antialias */ if (fg < 0) { if ((pixel + pixel) >= NUMCOLORS) { a->tweencolor = -fg; } else { a->tweencolor = bg; } } else { npixel = NUMCOLORS - pixel; if (im->trueColor) { /* 2.0.1: use gdImageSetPixel to do the alpha blending work, * or to just store the alpha level. All we have to do here * is incorporate our knowledge of the percentage of this * pixel that is really "lit" by pushing the alpha value * up toward transparency in edge regions. */ a->tweencolor = gdTrueColorAlpha( gdTrueColorGetRed(fg), gdTrueColorGetGreen(fg), gdTrueColorGetBlue(fg), gdAlphaMax - (gdTrueColorGetAlpha (fg) * pixel / NUMCOLORS)); } else { a->tweencolor = gdImageColorResolve(im, (pixel * im->red[fg] + npixel * im->red[bg]) / NUMCOLORS, (pixel * im->green[fg] + npixel * im->green[bg]) / NUMCOLORS, (pixel * im->blue[fg] + npixel * im->blue[bg]) / NUMCOLORS); } } return (void *) a;}static void tweenColorRelease (void *element){ gdFree((char *) element);}/* draw_bitmap - transfers glyph bitmap to GD image */static char * gdft_draw_bitmap (gdCache_head_t *tc_cache, gdImage * im, int fg, FT_Bitmap bitmap, int pen_x, int pen_y){ unsigned char *pixel = NULL; int *tpixel = NULL; int x, y, row, col, pc, pcr; tweencolor_t *tc_elem; tweencolorkey_t tc_key; /* copy to image, mapping colors */ tc_key.fgcolor = fg; tc_key.im = im; /* Truecolor version; does not require the cache */ if (im->trueColor) { for (row = 0; row < bitmap.rows; row++) { pc = row * bitmap.pitch; pcr = pc; y = pen_y + row; /* clip if out of bounds */ /* 2.0.16: clipping rectangle, not image bounds */ if ((y > im->cy2) || (y < im->cy1)) { continue; } for (col = 0; col < bitmap.width; col++, pc++) { int level; if (bitmap.pixel_mode == ft_pixel_mode_grays) { /* Scale to 128 levels of alpha for gd use. * alpha 0 is opacity, so be sure to invert at the end */ level = (bitmap.buffer[pc] * gdAlphaMax / (bitmap.num_grays - 1)); } else if (bitmap.pixel_mode == ft_pixel_mode_mono) { /* 2.0.5: mode_mono fix from Giuliano Pochini */ level = ((bitmap.buffer[(col>>3)+pcr]) & (1<<(~col&0x07))) ? gdAlphaTransparent : gdAlphaOpaque; } else { return "Unsupported ft_pixel_mode"; } if ((fg >= 0) && (im->trueColor)) { /* Consider alpha in the foreground color itself to be an * upper bound on how opaque things get, when truecolor is * available. Without truecolor this results in far too many * color indexes. */ level = level * (gdAlphaMax - gdTrueColorGetAlpha(fg)) / gdAlphaMax; } level = gdAlphaMax - level; x = pen_x + col; /* clip if out of bounds */ /* 2.0.16: clip to clipping rectangle, Matt McNabb */ if ((x > im->cx2) || (x < im->cx1)) { continue; } /* get pixel location in gd buffer */ tpixel = &im->tpixels[y][x]; if (fg < 0) { if (level < (gdAlphaMax / 2)) { *tpixel = -fg; } } else { if (im->alphaBlendingFlag) { *tpixel = gdAlphaBlend(*tpixel, (level << 24) + (fg & 0xFFFFFF)); } else { *tpixel = (level << 24) + (fg & 0xFFFFFF); } } } } return (char *) NULL; } /* Non-truecolor case, restored to its more or less original form */ for (row = 0; row < bitmap.rows; row++) { int pcr; pc = row * bitmap.pitch; pcr = pc; if (bitmap.pixel_mode==ft_pixel_mode_mono) { pc *= 8; /* pc is measured in bits for monochrome images */ } y = pen_y + row; /* clip if out of bounds */ if (y >= im->sy || y < 0) { continue; } for (col = 0; col < bitmap.width; col++, pc++) { if (bitmap.pixel_mode == ft_pixel_mode_grays) { /* * Round to NUMCOLORS levels of antialiasing for * index color images since only 256 colors are * available. */ tc_key.pixel = ((bitmap.buffer[pc] * NUMCOLORS) + bitmap.num_grays / 2) / (bitmap.num_grays - 1); } else if (bitmap.pixel_mode == ft_pixel_mode_mono) { tc_key.pixel = ((bitmap.buffer[pc / 8] << (pc % 8)) & 128) ? NUMCOLORS : 0; /* 2.0.5: mode_mono fix from Giuliano Pochini */ tc_key.pixel = ((bitmap.buffer[(col>>3)+pcr]) & (1<<(~col&0x07))) ? NUMCOLORS : 0; } else { return "Unsupported ft_pixel_mode"; } if (tc_key.pixel > 0) { /* if not background */ x = pen_x + col; /* clip if out of bounds */ if (x >= im->sx || x < 0) { continue; } /* get pixel location in gd buffer */ pixel = &im->pixels[y][x]; if (tc_key.pixel == NUMCOLORS) { /* use fg color directly. gd 2.0.2: watch out for * negative indexes (thanks to David Marwood). */ *pixel = (fg < 0) ? -fg : fg; } else { /* find antialised color */ tc_key.bgcolor = *pixel; tc_elem = (tweencolor_t *) gdCacheGet(tc_cache, &tc_key); *pixel = tc_elem->tweencolor; } } } } return (char *) NULL;}static intgdroundupdown (FT_F26Dot6 v1, int updown){ return (!updown) ? (v1 < 0 ? ((v1 - 63) >> 6) : v1 >> 6) : (v1 > 0 ? ((v1 + 63) >> 6) : v1 >> 6);}extern int any2eucjp (char *, char *, unsigned int);/* Persistent font cache until explicitly cleared *//* Fonts can be used across multiple images *//* 2.0.16: thread safety (the font cache is shared) */gdMutexDeclare(gdFontCacheMutex);static gdCache_head_t *fontCache = NULL;static FT_Library library;void gdFontCacheShutdown(){ if (fontCache) { gdMutexShutdown(gdFontCacheMutex); gdCacheDelete(fontCache); fontCache = NULL; FT_Done_FreeType(library); }}void gdFreeFontCache(){ gdFontCacheShutdown();}int gdFontCacheSetup(void){ if (fontCache) { /* Already set up */ return 0; } gdMutexSetup(gdFontCacheMutex); if (FT_Init_FreeType(&library)) { gdMutexShutdown(gdFontCacheMutex); return -1; } fontCache = gdCacheCreate (FONTCACHESIZE, fontTest, fontFetch, fontRelease); return 0;}/********************************************************************//* gdImageStringFT - render a utf8 string onto a gd image */char *
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -