📄 gdttf.c
字号:
/* gd interface to freetype library *//* *//* John Ellson ellson@lucent.com *//* $Id: gdttf.c,v 1.16.10.4 2005/01/09 21:05:31 sniper Exp $ */#include "php.h"#if PHP_WIN32#include "config.w32.h"#else#include <php_config.h>#endif#if HAVE_LIBTTF && !defined(USE_GD_IMGSTRTTF)#include <stdio.h>#include <stdlib.h>#include <string.h>#include <math.h>#include <gd.h>#include "gdttf.h"#include "gdcache.h"#include <freetype.h>#ifndef HAVE_GDIMAGECOLORRESOLVEextern int gdImageColorResolve(gdImagePtr, int, int, int);#endif/* number of fonts cached before least recently used is replaced */#define FONTCACHESIZE 6/* number of character glyphs cached per font before least-recently-used is replaced */#define GLYPHCACHESIZE 120/* number of bitmaps cached per glyph before least-recently-used is replaced */#define BITMAPCACHESIZE 8/* number of antialias color lookups cached */#define TWEENCOLORCACHESIZE 32/* ptsize below which anti-aliasing is ineffective */#define MINANTIALIASPTSIZE 0/* display resolution - (Not really. This has to be 72 or hinting is wrong) */ #define RESOLUTION 72/* Number of colors used for anti-aliasing */#undef NUMCOLORS#define NUMCOLORS 4/* Line separation as a factor of font height. No space between if LINESPACE = 1.00 Line separation will be rounded up to next pixel row*/#define LINESPACE 1.05#ifndef TRUE#define FALSE 0#define TRUE !FALSE#endif#ifndef MAX#define MAX(a, b) ((a)>(b)?(a):(b))#endif#ifndef MIN#define MIN(a, b) ((a)<(b)?(a):(b))#endiftypedef struct { char *fontname; /* key */ double ptsize; /* key */ double angle; /* key */ double sin_a, cos_a; TT_Engine *engine; TT_Face face; TT_Face_Properties properties; TT_Instance instance; TT_CharMap char_map_Unicode; TT_CharMap char_map_Big5; TT_CharMap char_map_Roman; int have_char_map_Unicode; int have_char_map_Big5; int have_char_map_Roman; TT_Matrix matrix; TT_Instance_Metrics imetrics; gdCache_head_t *glyphCache;} font_t;typedef struct { char *fontname; /* key */ double ptsize; /* key */ double angle; /* key */ TT_Engine *engine;} fontkey_t;typedef struct { int character; /* key */ int hinting; /* key */ TT_Glyph glyph; TT_Glyph_Metrics metrics; TT_Outline outline; TT_Pos oldx, oldy; TT_Raster_Map Bit; int gray_render; int xmin, xmax, ymin, ymax; gdCache_head_t *bitmapCache;} glyph_t;typedef struct { int character; /* key */ int hinting; /* key */ int gray_render; font_t *font;} glyphkey_t;typedef struct { int xoffset; /* key */ int yoffset; /* key */ char *bitmap;} bitmap_t;typedef struct { int xoffset; /* key */ int yoffset; /* key */ glyph_t *glyph;} bitmapkey_t;typedef struct { unsigned char pixel; /* key */ unsigned char bgcolor; /* key */ int fgcolor; /* key */ /* -ve means no antialias */ gdImagePtr im; /* key */ unsigned char tweencolor;} tweencolor_t;typedef struct { unsigned char pixel; /* key */ unsigned char bgcolor; /* key */ int fgcolor; /* key */ /* -ve means no antialias */ gdImagePtr im; /* key */} tweencolorkey_t; /* forward declarations so that glyphCache can be initialized by font code */static int glyphTest ( void *element, void *key );static void *glyphFetch ( char **error, void *key );static void glyphRelease( void *element );/* forward declarations so that bitmapCache can be initialized by glyph code */static int bitmapTest ( void *element, void *key );static void *bitmapFetch ( char **error, void *key );static void bitmapRelease( void *element );/* local prototype */char *gdttfchar(gdImage *im, int fg, font_t *font, int x, int y, TT_F26Dot6 x1, TT_F26Dot6 y1, TT_F26Dot6 *advance, TT_BBox **bbox, char **next);/******************************************************************** * gdTcl_UtfToUniChar is borrowed from ... *//* * tclUtf.c -- * * Routines for manipulating UTF-8 strings. * * Copyright (c) 1997-1998 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * * SCCS: @(#) tclUtf.c 1.25 98/01/28 18:02:43 *//* *--------------------------------------------------------------------------- * * gdTcl_UtfToUniChar -- * * Extract the Tcl_UniChar represented by the UTF-8 string. Bad * UTF-8 sequences are converted to valid Tcl_UniChars and processing * continues. Equivalent to Plan 9 chartorune(). * * The caller must ensure that the source buffer is long enough that * this routine does not run off the end and dereference non-existent * memory looking for trail bytes. If the source buffer is known to * be '\0' terminated, this cannot happen. Otherwise, the caller * should call Tcl_UtfCharComplete() before calling this routine to * ensure that enough bytes remain in the string. * * Results: * *chPtr is filled with the Tcl_UniChar, and the return value is the * number of bytes from the UTF-8 string that were consumed. * * Side effects: * None. * *--------------------------------------------------------------------------- */ #ifndef CHARSET_EBCDIC#define ASC(ch) (ch)#else /*CHARSET_EBCDIC*/#define ASC(ch) os_toascii[(unsigned char) (ch)]#endif /*CHARSET_EBCDIC*/#define Tcl_UniChar int#define TCL_UTF_MAX 3static intgdTcl_UtfToUniChar(char *str, Tcl_UniChar *chPtr)/* str is the UTF8 next character pointer *//* chPtr is the int for the result */{ int byte; /* HTML4.0 entities in decimal form, e.g. Å */ byte = *((unsigned char *) str); if (byte == '&') { int i, n=0; byte = *((unsigned char *) (str+1)); if (byte == '#') { for (i = 2; i < 8; i++) { byte = *((unsigned char *) (str+i)); if (byte >= '0' && byte <= '9') { n = (n * 10) + (byte - '0'); } else break; } if (byte == ';') { *chPtr = (Tcl_UniChar) n; return ++i; } } } /* * Unroll 1 to 3 byte UTF-8 sequences, use loop to handle longer ones. */ byte = ASC(*((unsigned char *) str)); if (byte < 0xC0) { /* * Handles properly formed UTF-8 characters between 0x01 and 0x7F. * Also treats \0 and naked trail bytes 0x80 to 0xBF as valid * characters representing themselves. */ *chPtr = (Tcl_UniChar) byte; return 1; } else if (byte < 0xE0) { if ((ASC(str[1]) & 0xC0) == 0x80) { /* * Two-byte-character lead-byte followed by a trail-byte. */ *chPtr = (Tcl_UniChar) (((byte & 0x1F) << 6) | (ASC(str[1]) & 0x3F)); return 2; } /* * A two-byte-character lead-byte not followed by trail-byte * represents itself. */ *chPtr = (Tcl_UniChar) byte; return 1; } else if (byte < 0xF0) { if (((ASC(str[1]) & 0xC0) == 0x80) && ((ASC(str[2]) & 0xC0) == 0x80)) { /* * Three-byte-character lead byte followed by two trail bytes. */ *chPtr = (Tcl_UniChar) (((byte & 0x0F) << 12) | ((ASC(str[1]) & 0x3F) << 6) | (ASC(str[2]) & 0x3F)); return 3; } /* * A three-byte-character lead-byte not followed by two trail-bytes * represents itself. */ *chPtr = (Tcl_UniChar) byte; return 1; }#if TCL_UTF_MAX > 3 else { int ch, total, trail; total = totalBytes[byte]; trail = total - 1; if (trail > 0) { ch = byte & (0x3F >> trail); do { str++; if ((ASC(*str) & 0xC0) != 0x80) { *chPtr = byte; return 1; } ch <<= 6; ch |= (ASC(*str) & 0x3F); trail--; } while (trail > 0); *chPtr = ch; return total; } }#endif *chPtr = (Tcl_UniChar) byte; return 1;}/********************************************************************//* font cache functions */static intfontTest ( void *element, void *key ){ font_t *a=(font_t *)element; fontkey_t *b=(fontkey_t *)key; return ( strcmp(a->fontname, b->fontname) == 0 && a->ptsize == b->ptsize && a->angle == b->angle);}static void *fontFetch ( char **error, void *key ){ TT_Error err; font_t *a; fontkey_t *b=(fontkey_t *)key; int i, n, map_found; short platform, encoding; TSRMLS_FETCH(); a = (font_t *)pemalloc(sizeof(font_t), 1);#ifdef VIRTUAL_DIR /* a->fontname will be freed in fontRelease() later on */ if (virtual_filepath(b->fontname, &a->fontname TSRMLS_CC)) { *error = "Could not find/open font"; pefree(a, 1); return NULL; }#else a->fontname = (char *)pemalloc(strlen(b->fontname) + 1, 1); strcpy(a->fontname, b->fontname);#endif a->ptsize = b->ptsize; a->angle = b->angle; a->sin_a = sin(a->angle); a->cos_a = cos(a->angle); a->engine = b->engine; if ((err = TT_Open_Face(*b->engine, a->fontname, &a->face))) { if (err == TT_Err_Could_Not_Open_File) { *error = "Could not find/open font"; } else { *error = "Could not read font"; } pefree(a, 1); return NULL; } /* get face properties and allocate preload arrays */ TT_Get_Face_Properties(a->face, &a->properties); /* create instance */ if (TT_New_Instance(a->face, &a->instance)) { *error = "Could not create face instance"; pefree(a, 1); return NULL; } if (TT_Set_Instance_Resolutions(a->instance, RESOLUTION, RESOLUTION)) { *error = "Could not set device resolutions"; pefree(a, 1); return NULL; } if (TT_Set_Instance_CharSize(a->instance, (TT_F26Dot6)(a->ptsize*64))) { *error = "Could not set character size"; pefree(a, 1); return NULL; } TT_Get_Instance_Metrics(a->instance, &a->imetrics); /* First, look for a Unicode charmap */ n = TT_Get_CharMap_Count(a->face); for (i = 0; i < n; i++) { TT_Get_CharMap_ID(a->face, i, &platform, &encoding); if ((platform == 3 && encoding == 1) /* Windows Unicode */ || (platform == 2 && encoding == 1) || (platform == 0)) { /* ?? Unicode */ TT_Get_CharMap(a->face, i, &a->char_map_Unicode); a->have_char_map_Unicode = 1; map_found++; } else if (platform == 3 && encoding == 4) { /* Windows Big5 */ TT_Get_CharMap(a->face, i, &a->char_map_Big5); a->have_char_map_Big5 = 1; map_found++; } else if (platform == 1 && encoding == 0) { /* Apple Roman */ TT_Get_CharMap(a->face, i, &a->char_map_Roman); a->have_char_map_Roman = 1; map_found++; } } if (! map_found) { *error = "Unable to find a CharMap that I can handle"; pefree(a, 1); return NULL; } a->matrix.xx = (TT_Fixed) (a->cos_a * (1<<16)); a->matrix.yx = (TT_Fixed) (a->sin_a * (1<<16)); a->matrix.xy = - a->matrix.yx; a->matrix.yy = a->matrix.xx; a->glyphCache = gdCacheCreate( GLYPHCACHESIZE, glyphTest, glyphFetch, glyphRelease); return (void *)a;}static voidfontRelease( void *element ){ font_t *a=(font_t *)element; gdCacheDelete(a->glyphCache); TT_Done_Instance(a->instance); TT_Close_Face(a->face); pefree(a->fontname, 1); pefree((char *)element, 1);}/********************************************************************//* glyph cache functions */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -