📄 gdft.c
字号:
ch = *next; /* carriage returns */ if (ch == '\r') { penf.x = 0; previous = 0; /* clear kerning flag */ next++; continue; } /* newlines */ if (ch == '\n') { /* 2.0.13: reset penf.x. Christopher J. Grayce */ penf.x = 0; penf.y += linespace * ptsize * 64 * METRIC_RES / 72; penf.y &= ~63; /* round down to 1/METRIC_RES */ previous = 0; /* clear kerning flag */ next++; continue; } switch (encoding) { case gdFTEX_Unicode: { /* use UTF-8 mapping from ASCII */ len = gdTcl_UtfToUniChar (next, &ch);/* EAM DEBUG *//* TBB: get this exactly right: 2.1.3 *or better*, all possible cases. *//* 2.0.24: David R. Morrison: use the more complete ifdef here. */#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)#else if (charmap->platform_id == 3 && charmap->encoding_id == 0)#endif /* Freetype 2.1 or better */ { /* I do not know the significance of the constant 0xf000. */ /* It was determined by inspection of the character codes */ /* stored in Microsoft font symbol.ttf */ ch |= 0xf000; }/* EAM DEBUG */ next += len; } break; case gdFTEX_Shift_JIS: { unsigned char c; int jiscode; c = *next; if (0xA1 <= c && c <= 0xFE) { next++; jiscode = 0x100 * (c & 0x7F) + ((*next) & 0x7F); ch = (jiscode >> 8) & 0xFF; jiscode &= 0xFF; if (ch & 1) jiscode += 0x40 - 0x21; else jiscode += 0x9E - 0x21; if (jiscode >= 0x7F) jiscode++; ch = (ch - 0x21) / 2 + 0x81; if (ch >= 0xA0) ch += 0x40; ch = (ch << 8) + jiscode; } else { ch = c & 0xFF; /* don't extend sign */ } next++; } break; case gdFTEX_Big5: { /* * Big 5 mapping: * use "JIS-8 half-width katakana" coding from 8-bit characters. Ref: * ftp://ftp.ora.com/pub/examples/nutshell/ujip/doc/japan.inf-032092.sjs */ ch = (*next) & 0xFF; /* don't extend sign */ next++; if (ch >= 161 /* first code of JIS-8 pair */ && *next) { /* don't advance past '\0' */ /* TBB: Fix from Kwok Wah On: & 255 needed */ ch = (ch * 256) + ((*next) & 255); next++; } } break; } /* Convert character code to glyph index */ glyph_index = FT_Get_Char_Index (face, ch); /* retrieve kerning distance */ if ( ! (strex && (strex->flags & gdFTEX_DISABLE_KERNING)) && ! FT_IS_FIXED_WIDTH(face) && FT_HAS_KERNING(face) && previous && glyph_index) FT_Get_Kerning (face, previous, glyph_index, ft_kerning_default, &delta); else delta.x = delta.y = 0; penf.x += delta.x; /* When we know the position of the second or subsequent character, save the (kerned) advance from the preceeding character in the xshow vector */ if (i && strex && (strex->flags & gdFTEX_XSHOW)) { /* make sure we have enough allocation for two numbers so we don't have to recheck for the terminating number */ if (! xshow_alloc) { xshow_alloc = 100; strex->xshow = malloc(xshow_alloc); xshow_pos = 0; } else if (xshow_pos + 20 > xshow_alloc) { xshow_alloc += 100; strex->xshow = realloc(strex->xshow, xshow_alloc); } xshow_pos += sprintf(strex->xshow + xshow_pos, "%g ", (double)(penf.x - oldpenf.x) * hdpi / (64 * METRIC_RES)); } oldpenf.x = penf.x; /* load glyph image into the slot (erase previous one) */ err = FT_Load_Glyph (face, glyph_index, render_mode); if (err) { gdCacheDelete (tc_cache); gdMutexUnlock (gdFontCacheMutex); return "Problem loading glyph"; } horiAdvance = slot->metrics.horiAdvance; if (brect) { /* only if need brect */ glyph_min.x = penf.x + slot->metrics.horiBearingX; glyph_min.y = penf.y - slot->metrics.horiBearingY;#if 0 if (ch == ' ') /* special case for trailing space */ { glyph_max.x = penf.x + horiAdvance; } else { glyph_max.x = glyph_min.x + slot->metrics.width; }#else glyph_max.x = penf.x + horiAdvance;#endif glyph_max.y = glyph_min.y + slot->metrics.height; if (i==0) { total_min = glyph_min; total_max = glyph_max; } else { if (glyph_min.x < total_min.x) total_min.x = glyph_min.x; if (glyph_min.y < total_min.y) total_min.y = glyph_min.y; if (glyph_max.x > total_max.x) total_max.x = glyph_max.x; if (glyph_max.y > total_max.y) total_max.y = glyph_max.y; } } if (render) { FT_Activate_Size (platform_specific); /* load glyph again into the slot (erase previous one) - this time with scaling */ err = FT_Load_Glyph (face, glyph_index, render_mode); if (err) { gdCacheDelete (tc_cache); gdMutexUnlock (gdFontCacheMutex); return "Problem loading glyph"; } /* load and transform glyph image */ FT_Get_Glyph (slot, &image); if (image->format != ft_glyph_format_bitmap) { err = FT_Glyph_To_Bitmap (&image, ft_render_mode_normal, 0, 1); if (err) { gdCacheDelete (tc_cache); gdMutexUnlock (gdFontCacheMutex); return "Problem rendering glyph"; } } /* now, draw to our target surface */ bm = (FT_BitmapGlyph) image; /* position rounded down to nearest pixel at current dpi (the estimate was rounded up to next 1/METRIC_RES, so this should fit) */ gdft_draw_bitmap (tc_cache, im, fg, bm->bitmap, x + (penf.x * cos_a + penf.y * sin_a)*hdpi/(METRIC_RES*64) + bm->left, y - (penf.x * sin_a - penf.y * cos_a)*vdpi/(METRIC_RES*64) - bm->top); FT_Done_Glyph (image); } /* record current glyph index for kerning */ previous = glyph_index; penf.x += horiAdvance; } /* Save the (unkerned) advance from the last character in the xshow vector */ if (strex && (strex->flags & gdFTEX_XSHOW) && strex->xshow) { sprintf(strex->xshow + xshow_pos, "%g", (double)(penf.x - oldpenf.x) * hdpi / (64 * METRIC_RES) ); } if (brect) { /* only if need brect */ double dpix, dpiy; dpix = 64 * METRIC_RES / hdpi; dpiy = 64 * METRIC_RES / vdpi; /* increase by 1 pixel to allow for rounding */ total_min.x -= METRIC_RES; total_min.y -= METRIC_RES; total_max.x += METRIC_RES; total_max.y += METRIC_RES; /* rotate bounding rectangle, scale and round to int pixels, and translate */ brect[0] = x + (total_min.x * cos_a + total_max.y * sin_a)/dpix; brect[1] = y - (total_min.x * sin_a - total_max.y * cos_a)/dpiy; brect[2] = x + (total_max.x * cos_a + total_max.y * sin_a)/dpix; brect[3] = y - (total_max.x * sin_a - total_max.y * cos_a)/dpiy; brect[4] = x + (total_max.x * cos_a + total_min.y * sin_a)/dpix; brect[5] = y - (total_max.x * sin_a - total_min.y * cos_a)/dpiy; brect[6] = x + (total_min.x * cos_a + total_min.y * sin_a)/dpix; brect[7] = y - (total_min.x * sin_a - total_min.y * cos_a)/dpiy; } FT_Done_Size (platform_independent); if (render) FT_Done_Size (platform_specific); if (tmpstr) gdFree (tmpstr); gdCacheDelete (tc_cache); gdMutexUnlock (gdFontCacheMutex); return (char *) NULL;}#endif /* HAVE_LIBFREETYPE */#ifdef HAVE_LIBFONTCONFIG/* Code to find font path, with special mapping for Postscript font names. * * Dag Lem <dag@nimrod.no> */#include <fontconfig/fontconfig.h>/* #define NO_POSTSCRIPT_ALIAS 1 */#ifndef NO_POSTSCRIPT_ALIAStypedef struct _PostscriptAlias { char* name; char* family; char* style;} PostscriptAlias;/* This table maps standard Postscript font names to URW Type 1 fonts. The mapping is converted from Ghostscript (Fontmap.GS) for use with fontconfig. */static PostscriptAlias postscript_alias[] = { { "AvantGarde-Book", "URW Gothic L", "Book" }, { "AvantGarde-BookOblique", "URW Gothic L", "Book Oblique" }, { "AvantGarde-Demi", "URW Gothic L", "Demi" }, { "AvantGarde-DemiOblique", "URW Gothic L", "Demi Oblique" }, { "Bookman-Demi", "URW Bookman L", "Demi Bold" }, { "Bookman-DemiItalic", "URW Bookman L", "Demi Bold Italic" }, { "Bookman-Light", "URW Bookman L", "Light" }, { "Bookman-LightItalic", "URW Bookman L", "Light Italic" }, { "Courier", "Nimbus Mono L", "Regular" }, { "Courier-Oblique", "Nimbus Mono L", "Regular Oblique" }, { "Courier-Bold", "Nimbus Mono L", "Bold" }, { "Courier-BoldOblique", "Nimbus Mono L", "Bold Oblique" }, { "Helvetica", "Nimbus Sans L", "Regular" }, { "Helvetica-Oblique", "Nimbus Sans L", "Regular Italic" }, { "Helvetica-Bold", "Nimbus Sans L", "Bold" }, { "Helvetica-BoldOblique", "Nimbus Sans L", "Bold Italic" }, { "Helvetica-Narrow", "Nimbus Sans L", "Regular Condensed" }, { "Helvetica-Narrow-Oblique", "Nimbus Sans L", "Regular Condensed Italic" }, { "Helvetica-Narrow-Bold", "Nimbus Sans L", "Bold Condensed" }, { "Helvetica-Narrow-BoldOblique", "Nimbus Sans L", "Bold Condensed Italic" }, { "NewCenturySchlbk-Roman", "Century Schoolbook L", "Roman" }, { "NewCenturySchlbk-Italic", "Century Schoolbook L", "Italic" }, { "NewCenturySchlbk-Bold", "Century Schoolbook L", "Bold" }, { "NewCenturySchlbk-BoldItalic", "Century Schoolbook L", "Bold Italic" }, { "Palatino-Roman", "URW Palladio L", "Roman" }, { "Palatino-Italic", "URW Palladio L", "Italic" }, { "Palatino-Bold", "URW Palladio L", "Bold" }, { "Palatino-BoldItalic", "URW Palladio L", "Bold Italic" }, { "Symbol", "Standard Symbols L", "Regular" }, { "Times-Roman", "Nimbus Roman No9 L", "Regular" }, { "Times-Italic", "Nimbus Roman No9 L", "Regular Italic" }, { "Times-Bold", "Nimbus Roman No9 L", "Medium" }, { "Times-BoldItalic", "Nimbus Roman No9 L", "Medium Italic" }, { "ZapfChancery-MediumItalic", "URW Chancery L", "Medium Italic" }, { "ZapfDingbats", "Dingbats", "" },};#endifstatic FcPattern* find_font(FcPattern* pattern){ FcResult result; FcConfigSubstitute(0, pattern, FcMatchPattern); FcConfigSubstitute(0, pattern, FcMatchFont); FcDefaultSubstitute(pattern); return FcFontMatch(0, pattern, &result);}#ifndef NO_POSTSCRIPT_ALIASstatic char* find_postscript_font(FcPattern **fontpattern, char* fontname){ FcPattern* font = NULL; int i; *fontpattern = NULL; for (i = 0; i < sizeof(postscript_alias)/sizeof(*postscript_alias); i++) { if (strcmp(fontname, postscript_alias[i].name) == 0) { FcChar8* family; FcPattern* pattern = FcPatternBuild(0, FC_FAMILY, FcTypeString, postscript_alias[i].family, FC_STYLE, FcTypeString, postscript_alias[i].style, (char*)0); font = find_font(pattern); FcPatternDestroy(pattern); if (!font || FcPatternGetString(font, FC_FAMILY, 0, &family) != FcResultMatch) return "fontconfig: Couldn't retrieve font family name."; /* Check whether we got the font family we wanted. */ if (strcmp((const char *)family, postscript_alias[i].family) != 0) { FcPatternDestroy(font); return "fontconfig: Didn't find expected font family. Perhaps URW Type 1 fonts need installing?"; } break; } } *fontpattern = font; return NULL;}#endifstatic char * font_pattern(char **fontpath, char *fontpattern){ FcPattern* font = NULL; FcChar8* file; FcPattern* pattern;#ifndef NO_POSTSCRIPT_ALIAS char *error;#endif *fontpath = NULL;#ifndef NO_POSTSCRIPT_ALIAS error = find_postscript_font(&font, fontpattern); if (!font) { if (error) return error;#endif pattern = FcNameParse((const FcChar8 *)fontpattern); font = find_font(pattern); FcPatternDestroy(pattern);#ifndef NO_POSTSCRIPT_ALIAS }#endif if (!font || FcPatternGetString(font, FC_FILE, 0, &file) != FcResultMatch) return "fontconfig: Couldn't retrieve font file name."; *fontpath = strdup((const char *)file); FcPatternDestroy(font); return NULL;}#endif /* HAVE_LIBFONTCONFIG *//* Look up font using font names as file names. */static char * font_path(char **fontpath, char *name_list){ int font_found = 0; char *fontsearchpath, *fontlist; char *fullname = NULL; char *name, *path, *dir; char *strtok_ptr; /* * Search the pathlist for any of a list of font names. */ *fontpath = NULL; fontsearchpath = getenv ("GDFONTPATH"); if (!fontsearchpath) fontsearchpath = DEFAULT_FONTPATH; fontlist = strdup (name_list); /* * 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)) { /* make a fresh copy each time - strtok corrupts it. */ path = strdup (fontsearchpath); /* * Allocate an oversized buffer that is guaranteed to be * big enough for all paths to be tested. */ /* 2.0.22: Thorben Kundinger: +8 is needed, not +6. */ fullname = gdRealloc (fullname, strlen (fontsearchpath) + strlen (name) + 8); /* if name is an absolute or relative pathname then test directly */ if (strchr (name, '/') || (name[0] != 0 && name[1] == ':' && (name[2] == '/' || name[2] == '\\'))) { sprintf (fullname, "%s", name); if (access (fullname, R_OK) == 0) { font_found++; /* 2.0.16: memory leak fixed, Gustavo Scotti */ gdFree (path); break; } } for (dir = strtok (path, PATHSEPARATOR); dir; dir = strtok (0, PATHSEPARATOR)) { if (strchr (name, '.')) { sprintf (fullname, "%s/%s", dir, name); if (access (fullname, R_OK) == 0) { font_found++; break; } else { continue; } } sprintf (fullname, "%s/%s.ttf", dir, name); if (access (fullname, R_OK) == 0) { font_found++; break; } sprintf (fullname, "%s/%s.pfa", dir, name); if (access (fullname, R_OK) == 0) { font_found++; break; } sprintf (fullname, "%s/%s.pfb", dir, name); if (access (fullname, R_OK) == 0) { font_found++; break; } sprintf (fullname, "%s/%s.dfont", dir, name); if (access (fullname, R_OK) == 0) { font_found++; break; } } gdFree (path); if (font_found) break; } gdFree (fontlist); if (!font_found) { free (fullname); return "Could not find/open font"; } *fontpath = fullname; return NULL;}BGD_DECLARE(int) gdFTUseFontConfig(int flag){#ifdef HAVE_LIBFONTCONFIG fontConfigFlag = 1; return 1;#else return 0;#endif /* HAVE_LIBFONTCONFIG */}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -