📄 gdft.c
字号:
/********************************************//* gd interface to freetype library *//* *//* John Ellson ellson@graphviz.org *//********************************************/#ifdef HAVE_CONFIG_H#include "config.h"#endif#include <stdio.h>#include <stdlib.h>#include <string.h>#include <math.h>#include "gd.h"#include "gdhelpers.h"#include "entities.h"/* 2.0.10: WIN32, not MSWIN32 */#ifndef WIN32#include <unistd.h>#else#include <io.h>#define R_OK 04 /* Needed in Windows */#endif/* number of antialised colors for indexed bitmaps */#define NUMCOLORS 8static int fontConfigFlag = 0;static char *font_path(char **fontpath, char *name_list);/* translate a fontconfig fontpattern into a fontpath. return NULL if OK, else return error string */static char *font_pattern(char **fontpath, char *fontpattern);/* 2.0.30: move these up here so we can build correctly without freetype but with fontconfig *//* * The character (space) used to separate alternate fonts in the * fontlist parameter to gdImageStringFT. 2.0.18: space was a * poor choice for this. */#define LISTSEPARATOR ";"/* * DEFAULT_FONTPATH and PATHSEPARATOR are host type dependent and * are normally set by configure in config.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#if defined(__APPLE__) || (defined(__MWERKS__) && defined(macintosh))#define DEFAULT_FONTPATH "/usr/share/fonts/truetype:/System/Library/Fonts:/Library/Fonts"#else#define DEFAULT_FONTPATH "/usr/share/fonts/truetype"#endif#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))BGD_DECLARE(char *) gdImageStringTTF (gdImage * im, int *brect, int fg, char *fontlist, double ptsize, double angle, int x, int y, char *string){ /* 2.0.6: valid return */ return gdImageStringFT (im, brect, fg, fontlist, ptsize, angle, x, y, string);}#ifndef HAVE_LIBFREETYPEBGD_DECLARE(char *) gdImageStringFTEx (gdImage * im, int *brect, int fg, char *fontlist, double ptsize, double angle, int x, int y, char *string, gdFTStringExtraPtr strex){ return "libgd was not built with FreeType font support\n";}BGD_DECLARE(char *) 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#ifndef HAVE_LIBFONTCONFIGstatic char * font_pattern(char **fontpath, char *fontpattern){ return "libgd was not built with FontConfig support\n";}#endif /* HAVE_LIBFONTCONFIG */#include "gdcache.h"/* 2.0.16 Christophe Thomas: starting with FreeType 2.1.6, this is mandatory, and it has been supported for a long while. */#ifdef HAVE_FT2BUILD_H#include <ft2build.h>#include FT_FREETYPE_H#include FT_GLYPH_H#include FT_SIZES_H#else#include <freetype/freetype.h>#include <freetype/ftglyph.h>#include <freetype/ftsizes.h>#endif/* 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.05typedef struct{ char *fontlist; /* key */ int flags; /* key */ char *fontpath; FT_Library *library; FT_Face face;}font_t;typedef struct{ char *fontlist; /* key */ int flags; /* 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"#endifstatic int comp_entities(const void *e1, const void *e2) { struct entities_s *en1 = (struct entities_s *) e1; struct entities_s *en2 = (struct entities_s *) e2; return strcmp(en1->name, en2->name);}#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; char entity_name_buf[ENTITY_NAME_LENGTH_MAX+1]; char *p; struct entities_s key, *res; /* HTML4.0 entities in decimal form, e.g. Å */ /* or in hexadecimal form, e.g. 水 */ byte = *((unsigned char *) str); if (byte == '&') { int i, n = 0; byte = *((unsigned char *) (str + 1)); if (byte == '#') { byte = *((unsigned char *) (str + 2)); if (byte == 'x' || byte == 'X') { for (i = 3; i < 8; i++) { byte = *((unsigned char *) (str + i)); if (byte >= 'A' && byte <= 'F') byte = byte - 'A' + 10; else if (byte >= 'a' && byte <= 'f') byte = byte - 'a' + 10; else if (byte >= '0' && byte <= '9') byte = byte - '0'; else break; n = (n * 16) + byte; } } else { 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; } } else { key.name = p = entity_name_buf; for (i = 1; i < 1 + ENTITY_NAME_LENGTH_MAX; i++) { byte = *((unsigned char *) (str + i)); if (byte == '\0') break; if (byte == ';') { *p++ = '\0'; res = bsearch(&key, entities, NR_OF_ENTITIES, sizeof(entities[0]), *comp_entities); if (res) { *chPtr = (Tcl_UniChar) res->value; return ++i; } break; } *p++ = byte; } } } /* * 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 && a->flags == b->flags);}static int useFontConfig(int flag){ if (fontConfigFlag) { return (!(flag & gdFTEX_FONTPATHNAME)); } else { return flag & gdFTEX_FONTCONFIG; }}static void *fontFetch (char **error, void *key){ font_t *a; fontkey_t *b = (fontkey_t *) key; char *suffix; FT_Error err; *error = NULL; a = (font_t *) gdMalloc (sizeof (font_t)); a->fontlist = strdup (b->fontlist); a->flags = b->flags; a->library = b->library; a->fontpath = NULL;#ifdef HAVE_LIBFONTCONFIG if (!useFontConfig(b->flags)) *error = font_path(&(a->fontpath), a->fontlist); else *error = font_pattern(&(a->fontpath), a->fontlist);#else *error = font_path(&(a->fontpath), a->fontlist);#endif /* HAVE_LIBFONTCONFIG */ if (*error || !a->fontpath || !a->fontpath[0]) { /* 2.0.12: TBB: free these. Thanks to Frank Faubert. */ free (a->fontlist); if (a->fontpath) free (a->fontpath); gdFree (a); if (! *error) *error = "font_path() returned an empty font pathname"; return NULL; }#if 0fprintf(stderr,"fontpathname=%s\n",fullname);#endif err = FT_New_Face(*b->library, a->fontpath, 0, &a->face); /* Read kerning metrics for Postscript fonts. */ if (!err && ((suffix = strstr(a->fontpath, ".pfa")) || (suffix = strstr(a->fontpath, ".pfb"))) && ((strcpy(suffix, ".afm") && (access(a->fontpath, R_OK) == 0)) || (strcpy(suffix, ".pfm") && (access(a->fontpath, R_OK) == 0)))) { err = FT_Attach_File(a->face, a->fontpath); } if (err) { /* 2.0.12: TBB: free these. Thanks to Frank Faubert. */ free (a->fontlist); free (a->fontpath); gdFree (a); *error = "Could not read font"; return NULL; } return (void *) a;}static voidfontRelease (void *element){ font_t *a = (font_t *) element; FT_Done_Face (a->face); gdFree (a->fontlist); gdFree (a->fontpath); gdFree ((char *) element);}/********************************************************************//* tweencolor cache functions */static inttweenColorTest (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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -