📄 gdft.c
字号:
/********************************************//* gd interface to freetype library *//* *//* John Ellson ellson@lucent.com *//********************************************/#include <stdio.h>#include <stdlib.h>#include <string.h>#include <math.h>#include "gd.h"#include "gdhelpers.h"#ifndef MSWIN32#include <unistd.h>#else#define R_OK 2#endif/* number of antialised colors for indexed bitmaps */#define NUMCOLORS 8char *gdImageStringTTF (gdImage * im, int *brect, int fg, char *fontlist, double ptsize, double angle, int x, int y, char *string){ gdImageStringFT (im, brect, fg, fontlist, ptsize, angle, x, y, string);}#ifndef HAVE_LIBFREETYPEchar *gdImageStringFT (gdImage * im, int *brect, int fg, char *fontlist, double ptsize, double angle, int x, int y, char *string){ return "libgd was not built with FreeType font support\n";}#else#include "gdcache.h"#include <ft2build.h>#include FT_FREETYPE_H#include FT_GLYPH_H/* number of fonts cached before least recently used is replaced */#define FONTCACHESIZE 6/* number of antialias color lookups cached */#define TWEENCOLORCACHESIZE 32/* * 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/* * The character (space) used to separate alternate fonts in the * fontlist parameter to gdImageStringFT. */#define LISTSEPARATOR " "/* * DEFAULT_FONTPATH and PATHSEPARATOR are host type dependent and * are normally set by configure in gvconfig.h. These are just * some last resort values that might match some Un*x system * if building this version of gd separate from graphviz. */#ifndef DEFAULT_FONTPATH#define DEFAULT_FONTPATH "/usr/share/fonts/truetype"#endif#ifndef PATHSEPARATOR#define PATHSEPARATOR ":"#endif#ifndef TRUE#define FALSE 0#define TRUE !FALSE#endif#define MAX(a,b) ((a)>(b)?(a):(b))#define MIN(a,b) ((a)<(b)?(a):(b))typedef struct{ char *fontlist; /* key */ FT_Library *library; FT_Face face; FT_Bool have_char_map_unicode, have_char_map_big5, have_char_map_sjis, have_char_map_apple_roman; gdCache_head_t *glyphCache;}font_t;typedef struct { char *fontlist; /* key */ FT_Library *library; }fontkey_t;typedef struct { int pixel; /* key */ int bgcolor; /* key */ int fgcolor; /* key *//* -ve means no antialias */ gdImagePtr im; /* key */ int tweencolor; }tweencolor_t;typedef struct { int pixel; /* key */ int bgcolor; /* key */ int fgcolor; /* key *//* -ve means no antialias */ gdImagePtr im; /* key */ }tweencolorkey_t;/******************************************************************** * gdTcl_UtfToUniChar is borrowed from Tcl ... *//* * 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. * *--------------------------------------------------------------------------- */#ifdef JISX0208#include "jisx0208.h"#endif#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 = *((unsigned char *) str);#ifdef JISX0208 if (0xA1 <= byte && byte <= 0xFE) { int ku, ten; ku = (byte & 0x7F) - 0x20; ten = (str[1] & 0x7F) - 0x20; if ((ku < 1 || ku > 92) || (ten < 1 || ten > 94)) { *chPtr = (Tcl_UniChar) byte; return 1; } *chPtr = (Tcl_UniChar) UnicodeTbl[ku - 1][ten - 1]; return 2; } else#endif /* JISX0208 */ 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 ((str[1] & 0xC0) == 0x80) { /* * Two-byte-character lead-byte followed * by a trail-byte. */ *chPtr = (Tcl_UniChar) (((byte & 0x1F) << 6) | (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 (((str[1] & 0xC0) == 0x80) && ((str[2] & 0xC0) == 0x80)) { /* * Three-byte-character lead byte followed by * two trail bytes. */ *chPtr = (Tcl_UniChar) (((byte & 0x0F) << 12) | ((str[1] & 0x3F) << 6) | (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 ((*str & 0xC0) != 0x80) { *chPtr = byte; return 1; } ch <<= 6; ch |= (*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->fontlist, b->fontlist) == 0);}static void *fontFetch (char **error, void *key){ font_t *a; fontkey_t *b = (fontkey_t *) key; int n; int font_found = 0; unsigned short platform, encoding; char *fontsearchpath, *fontpath, *fontlist; char *fullname = NULL; char *name, *path, *dir; char *strtok_ptr; FT_Error err; FT_CharMap found = 0; FT_CharMap charmap; a = (font_t *) gdMalloc (sizeof (font_t)); a->fontlist = strdup (b->fontlist); a->library = b->library; /* * Search the pathlist for any of a list of font names. */ fontsearchpath = getenv ("GDFONTPATH"); if (!fontsearchpath) fontsearchpath = DEFAULT_FONTPATH; path = strdup (fontsearchpath); fontlist = strdup (a->fontlist); /* * Must use gd_strtok_r else pointer corrupted by strtok in nested loop. */ for (name = gd_strtok_r (fontlist, LISTSEPARATOR, &strtok_ptr); name; name = gd_strtok_r (0, LISTSEPARATOR, &strtok_ptr)) { /* * Allocate an oversized buffer that is guaranteed to be * big enough for all paths to be tested. */ fullname = gdRealloc (fullname, strlen (fontsearchpath) + strlen (name) + 6); /* if name is an absolute filename then test directly */ if (*name == '/') { sprintf (fullname, "%s", name); if (access (fullname, R_OK) == 0) { font_found++; break; } } for (dir = strtok (path, PATHSEPARATOR); dir; dir = strtok (0, PATHSEPARATOR)) { sprintf (fullname, "%s/%s.ttf", dir, name); if (access (fullname, R_OK) == 0) { font_found++; break; } } if (font_found) break; } gdFree (path); gdFree (fontlist); if (!font_found) { *error = "Could not find/open font"; return NULL; } err = FT_New_Face (*b->library, fullname, 0, &a->face); if (err) { *error = "Could not read font"; return NULL; } gdFree (fullname);/* FIXME - This mapping stuff is imcomplete - where is the spec? */ 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; 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) { *error = "Unable to find a CharMap that I can handle"; return NULL; } return (void *) a;}static voidfontRelease (void *element){ font_t *a = (font_t *) element; FT_Done_Face (a->face); gdFree (a->fontlist); gdFree ((char *) element);}/********************************************************************//* tweencolor cache functions */static inttweenColorTest (void *element, void *key){ tweencolor_t *a = (tweencolor_t *) element; tweencolorkey_t *b = (tweencolorkey_t *) key;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -