diff options
author | Akira Kakuto <kakuto@fuk.kindai.ac.jp> | 2020-04-10 03:40:48 +0000 |
---|---|---|
committer | Akira Kakuto <kakuto@fuk.kindai.ac.jp> | 2020-04-10 03:40:48 +0000 |
commit | 503c0227622254c0ae3209a1fa72bcb68bb450bc (patch) | |
tree | 48df20533f300f819504c15af33cdc03fc386a93 /Build/source/libs/gd/libgd-src/src/gdft.c | |
parent | a9d86b73ecf95b83666e16c4d90e348c4958a63b (diff) |
libgd 2.3.0
git-svn-id: svn://tug.org/texlive/trunk@54636 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/libs/gd/libgd-src/src/gdft.c')
-rw-r--r-- | Build/source/libs/gd/libgd-src/src/gdft.c | 272 |
1 files changed, 186 insertions, 86 deletions
diff --git a/Build/source/libs/gd/libgd-src/src/gdft.c b/Build/source/libs/gd/libgd-src/src/gdft.c index d989ecc3873..98e74fa346c 100644 --- a/Build/source/libs/gd/libgd-src/src/gdft.c +++ b/Build/source/libs/gd/libgd-src/src/gdft.c @@ -1,4 +1,3 @@ - /********************************************/ /* gd interface to freetype library */ /* */ @@ -72,9 +71,7 @@ static char *font_path(char **fontpath, char *name_list); */ #ifndef DEFAULT_FONTPATH -# ifdef NETWARE -# define DEFAULT_FONTPATH "sys:/java/nwgfx/lib/x11/fonts/ttf;." -# elif defined(_WIN32) +# if defined(_WIN32) # define DEFAULT_FONTPATH "C:\\WINDOWS\\FONTS;C:\\WINNT\\FONTS" # elif defined(__APPLE__) || (defined(__MWERKS__) && defined(macintosh)) # define DEFAULT_FONTPATH "/usr/share/fonts/truetype:/System/Library/Fonts:/Library/Fonts" @@ -85,7 +82,7 @@ static char *font_path(char **fontpath, char *name_list); #endif #ifndef PATHSEPARATOR -# if defined(NETWARE) || defined(_WIN32) +# if defined(_WIN32) # define PATHSEPARATOR ";" # else # define PATHSEPARATOR ":" @@ -103,8 +100,8 @@ static char *font_path(char **fontpath, char *name_list); * * Alias of <gdImageStringFT>. */ -BGD_DECLARE(char *) gdImageStringTTF (gdImage * im, int *brect, int fg, char *fontlist, - double ptsize, double angle, int x, int y, char *string) +BGD_DECLARE(char *) gdImageStringTTF (gdImage * im, int *brect, int fg, const char *fontlist, + double ptsize, double angle, int x, int y, const char *string) { /* 2.0.6: valid return */ return gdImageStringFT (im, brect, fg, fontlist, ptsize, @@ -112,8 +109,8 @@ BGD_DECLARE(char *) gdImageStringTTF (gdImage * im, int *brect, int fg, char *fo } #ifndef HAVE_LIBFREETYPE -BGD_DECLARE(char *) gdImageStringFTEx (gdImage * im, int *brect, int fg, char *fontlist, - double ptsize, double angle, int x, int y, char *string, +BGD_DECLARE(char *) gdImageStringFTEx (gdImage * im, int *brect, int fg, const char *fontlist, + double ptsize, double angle, int x, int y, const char *string, gdFTStringExtraPtr strex) { (void)im; @@ -130,8 +127,8 @@ BGD_DECLARE(char *) gdImageStringFTEx (gdImage * im, int *brect, int fg, char *f 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) +BGD_DECLARE(char *) gdImageStringFT (gdImage * im, int *brect, int fg, const char *fontlist, + double ptsize, double angle, int x, int y, const char *string) { (void)im; (void)brect; @@ -184,7 +181,7 @@ typedef struct { font_t; typedef struct { - char *fontlist; /* key */ + const char *fontlist; /* key */ int flags; /* key */ FT_Library *library; } @@ -260,7 +257,7 @@ static int comp_entities(const void *e1, const void *e2) return strcmp(en1->name, en2->name); } -extern int any2eucjp (char *, char *, unsigned int); +extern int any2eucjp (char *, const char *, unsigned int); /* Persistent font cache until explicitly cleared */ /* Fonts can be used across multiple images */ @@ -273,7 +270,7 @@ static FT_Library library; #define Tcl_UniChar int #define TCL_UTF_MAX 3 static int -gdTcl_UtfToUniChar (char *str, Tcl_UniChar * chPtr) +gdTcl_UtfToUniChar (const char *str, Tcl_UniChar * chPtr) /* str is the UTF8 next character pointer */ /* chPtr is the int for the result */ { @@ -432,6 +429,107 @@ gdTcl_UtfToUniChar (char *str, Tcl_UniChar * chPtr) return 1; } +#ifdef HAVE_LIBRAQM +#include <raqm.h> +#endif + +typedef struct { + unsigned int index; + FT_Pos x_advance; + FT_Pos x_offset; + FT_Pos y_offset; + uint32_t cluster; +} glyphInfo; + +static size_t +textLayout(uint32_t *text, int len, + FT_Face face, gdFTStringExtraPtr strex, + glyphInfo **glyph_info) +{ + size_t count; + glyphInfo *info; + +#ifdef HAVE_LIBRAQM + size_t i; + raqm_glyph_t *glyphs; + raqm_t *rq = raqm_create (); + + if (!rq || !raqm_set_text (rq, text, len) || + !raqm_set_freetype_face (rq, face) || + !raqm_set_par_direction (rq, RAQM_DIRECTION_DEFAULT) || + !raqm_layout (rq)) { + raqm_destroy (rq); + return 0; + } + + glyphs = raqm_get_glyphs (rq, &count); + if (!glyphs) { + raqm_destroy (rq); + return 0; + } + + info = (glyphInfo*) gdMalloc (sizeof (glyphInfo) * count); + if (!info) { + raqm_destroy (rq); + return 0; + } + + for (i = 0; i < count; i++) { + info[i].index = glyphs[i].index; + info[i].x_offset = glyphs[i].x_offset; + info[i].y_offset = glyphs[i].y_offset; + info[i].x_advance = glyphs[i].x_advance; + info[i].cluster = glyphs[i].cluster; + } + + raqm_destroy (rq); +#else + FT_UInt glyph_index = 0, previous = 0; + FT_Vector delta; + FT_Error err; + info = (glyphInfo*) gdMalloc (sizeof (glyphInfo) * len); + if (!info) { + return 0; + } + for (count = 0; count < len; count++) { + /* Convert character code to glyph index */ + glyph_index = FT_Get_Char_Index (face, text[count]); + + /* 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; + + err = FT_Load_Glyph (face, glyph_index, FT_LOAD_DEFAULT); + if (err) { + gdFree (info); + return 0; + } + info[count].index = glyph_index; + info[count].x_offset = 0; + info[count].y_offset = 0; + if (delta.x != 0) + info[count - 1].x_advance += delta.x; + info[count].x_advance = face->glyph->metrics.horiAdvance; + info[count].cluster = count; + + /* carriage returns or newlines */ + if (text[count] == '\r' || text[count] == '\n') + previous = 0; /* clear kerning flag */ + else + previous = glyph_index; + } +#endif + + *glyph_info = info; + return count; +} + /********************************************************************/ /* font cache functions */ @@ -475,7 +573,7 @@ fontFetch (char **error, void *key) gdFree(a); return "could not alloc full list of fonts"; } - strncpy(a->fontlist, b->fontlist, b_font_list_len); + memcpy(a->fontlist, b->fontlist, b_font_list_len); a->fontlist[b_font_list_len] = 0; a->flags = b->flags; @@ -824,8 +922,8 @@ BGD_DECLARE(void) gdFontCacheShutdown () * See also: * - <gdImageString> */ -BGD_DECLARE(char *) gdImageStringFT (gdImage * im, int *brect, int fg, char *fontlist, - double ptsize, double angle, int x, int y, char *string) +BGD_DECLARE(char *) gdImageStringFT (gdImage * im, int *brect, int fg, const char *fontlist, + double ptsize, double angle, int x, int y, const char *string) { return gdImageStringFTEx (im, brect, fg, fontlist, ptsize, angle, x, y, string, 0); @@ -872,13 +970,13 @@ BGD_DECLARE(int) gdFontCacheSetup (void) typedef struct { // logical OR of gdFTEX_ values int flags; - + // fine tune line spacing for '\n' double linespacing; - + // Preferred character mapping int charmap; - + // Rendering resolution int hdpi; int vdpi; @@ -982,32 +1080,35 @@ BGD_DECLARE(int) gdFontCacheSetup (void) > flags | gdFTEX_FONTPATHNAME; - For more information, see <gdImageStringFT>. + For more information, see <gdImageStringFT>. */ /* the platform-independent resolution used for size and position calculations */ /* the size of the error introduced by rounding is affected by this number */ #define METRIC_RES 300 -BGD_DECLARE(char *) gdImageStringFTEx (gdImage * im, int *brect, int fg, char *fontlist, - double ptsize, double angle, int x, int y, char *string, +BGD_DECLARE(char *) gdImageStringFTEx (gdImage * im, int *brect, int fg, const char *fontlist, + double ptsize, double angle, int x, int y, const char *string, gdFTStringExtraPtr strex) { FT_Matrix matrix; - FT_Vector penf, oldpenf, delta, total_min = {0,0}, total_max = {0,0}, glyph_min, glyph_max; + FT_Vector penf, oldpenf, total_min = {0,0}, total_max = {0,0}, glyph_min, glyph_max; FT_Face face; FT_CharMap charmap = NULL; FT_Glyph image; FT_GlyphSlot slot; FT_Error err; - FT_UInt glyph_index, previous; + FT_UInt glyph_index; double sin_a = sin (angle); double cos_a = cos (angle); - int len, i, ch; + int i, ch; font_t *font; fontkey_t fontkey; - char *next; + const char *next; char *tmpstr = 0; + uint32_t *text; + glyphInfo *info = NULL; + size_t count; int render = (im && (im->trueColor || (fg <= 255 && fg >= -255))); FT_BitmapGlyph bm; /* 2.0.13: Bob Ostermann: don't force autohint, that's just for testing @@ -1100,7 +1201,7 @@ BGD_DECLARE(char *) gdImageStringFTEx (gdImage * im, int *brect, int fg, char *f gdMutexUnlock(gdFontCacheMutex); return "could not alloc full list of fonts"; } - strncpy(strex->fontpath, font->fontpath, fontpath_len); + memcpy(strex->fontpath, font->fontpath, fontpath_len); strex->fontpath[fontpath_len] = 0; } } @@ -1220,31 +1321,11 @@ BGD_DECLARE(char *) gdImageStringFTEx (gdImage * im, int *brect, int fg, char *f oldpenf.x = oldpenf.y = 0; /* for postscript xshow operator */ penf.x = penf.y = 0; /* running position of non-rotated glyphs */ - previous = 0; /* index of previous glyph for kerning calculations */ - for (i=0; *next; i++) { - FT_Activate_Size (platform_independent); - + text = (uint32_t*) gdCalloc (sizeof (uint32_t), strlen(next)); + i = 0; + while (*next) { + int len; 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 */ @@ -1320,22 +1401,43 @@ BGD_DECLARE(char *) gdImageStringFTEx (gdImage * im, int *brect, int fg, char *f next++; break; } + text[i] = ch; + i++; + } - /* Convert character code to glyph index */ - glyph_index = FT_Get_Char_Index (face, ch); + FT_Activate_Size (platform_independent); - /* 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; + count = textLayout (text , i, face, strex, &info); - penf.x += delta.x; + if (!count) { + gdFree (text); + gdFree (tmpstr); + gdCacheDelete (tc_cache); + gdMutexUnlock (gdFontCacheMutex); + return "Problem doing text layout"; + } + for (i = 0; i < count; i++) { + FT_Activate_Size (platform_independent); + + ch = text[info[i].cluster]; + + /* carriage returns */ + if (ch == '\r') { + penf.x = 0; + 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 */ + continue; + } + + glyph_index = info[i].index; /* When we know the position of the second or subsequent character, save the (kerned) advance from the preceeding character in the xshow vector */ @@ -1348,6 +1450,7 @@ BGD_DECLARE(char *) gdImageStringFTEx (gdImage * im, int *brect, int fg, char *f if (!strex->xshow) { if (tmpstr) gdFree (tmpstr); + gdFree(text); gdCacheDelete (tc_cache); gdMutexUnlock (gdFontCacheMutex); return "Problem allocating memory"; @@ -1359,6 +1462,7 @@ BGD_DECLARE(char *) gdImageStringFTEx (gdImage * im, int *brect, int fg, char *f if (!strex->xshow) { if (tmpstr) gdFree (tmpstr); + gdFree(text); gdCacheDelete (tc_cache); gdMutexUnlock (gdFontCacheMutex); return "Problem allocating memory"; @@ -1374,12 +1478,13 @@ BGD_DECLARE(char *) gdImageStringFTEx (gdImage * im, int *brect, int fg, char *f if (err) { if (tmpstr) gdFree (tmpstr); + gdFree(text); gdCacheDelete (tc_cache); gdMutexUnlock (gdFontCacheMutex); return "Problem loading glyph"; } - horiAdvance = slot->metrics.horiAdvance; + horiAdvance = info[i].x_advance; if (brect) { /* only if need brect */ @@ -1414,6 +1519,8 @@ BGD_DECLARE(char *) gdImageStringFTEx (gdImage * im, int *brect, int fg, char *f } if (render) { + FT_Pos pen_x; + FT_Pos pen_y; FT_Activate_Size (platform_specific); /* load glyph again into the slot (erase previous one) - this time with scaling */ @@ -1421,6 +1528,7 @@ BGD_DECLARE(char *) gdImageStringFTEx (gdImage * im, int *brect, int fg, char *f if (err) { if (tmpstr) gdFree (tmpstr); + gdFree(text); gdCacheDelete (tc_cache); gdMutexUnlock (gdFontCacheMutex); return "Problem loading glyph"; @@ -1435,6 +1543,7 @@ BGD_DECLARE(char *) gdImageStringFTEx (gdImage * im, int *brect, int fg, char *f FT_Done_Glyph(image); if (tmpstr) gdFree (tmpstr); + gdFree(text); gdCacheDelete (tc_cache); gdMutexUnlock (gdFontCacheMutex); return "Problem rendering glyph"; @@ -1445,19 +1554,22 @@ BGD_DECLARE(char *) gdImageStringFTEx (gdImage * im, int *brect, int fg, char *f 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) */ + pen_x = penf.x + info[i].x_offset; + pen_y = penf.y - info[i].y_offset; gdft_draw_bitmap (tc_cache, im, fg, bm->bitmap, - (int)(x + (penf.x * cos_a + penf.y * sin_a)*hdpi/(METRIC_RES*64) + bm->left), - (int)(y - (penf.x * sin_a - penf.y * cos_a)*vdpi/(METRIC_RES*64) - bm->top)); + (int)(x + (pen_x * cos_a + pen_y * sin_a)*hdpi/(METRIC_RES*64) + bm->left), + (int)(y - (pen_x * sin_a - pen_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; } + gdFree(text); + gdFree(info); + /* 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", @@ -1469,12 +1581,6 @@ BGD_DECLARE(char *) gdImageStringFTEx (gdImage * im, int *brect, int fg, char *f double scalex = (double)hdpi / (64 * METRIC_RES); double scaley = (double)vdpi / (64 * METRIC_RES); - /* 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)*scalex; brect[1] = y - (total_min.x * sin_a - total_max.y * cos_a)*scaley; @@ -1656,7 +1762,7 @@ static char * font_pattern(char **fontpath, char *fontpattern) if (*fontpath == NULL) { return "could not alloc font path"; } - strncpy(*fontpath, (const char *)file, file_len); + memcpy(*fontpath, (const char *)file, file_len); (*fontpath)[file_len] = 0; } FcPatternDestroy(font); @@ -1685,11 +1791,11 @@ static char * font_path(char **fontpath, char *name_list) fontsearchpath = getenv ("GDFONTPATH"); #ifdef _WIN32 if (!fontsearchpath) { - char *ffptr = getenv ("SYSTEMROOT"); + char *ffptr = getenv ("WINDIR"); if (ffptr) { - fontsearchpath = malloc (strlen(ffptr) + strlen("\\fonts") + 1); + fontsearchpath = malloc (strlen(ffptr) + strlen("\\Fonts") + 1); strcpy(fontsearchpath, ffptr); - strcat(fontsearchpath, "\\fonts"); + strcat(fontsearchpath, "\\Fonts"); } } #endif @@ -1706,7 +1812,7 @@ static char * font_path(char **fontpath, char *name_list) gdFree(path); return "could not alloc full list of fonts"; } - strncpy(fontlist, name_list, name_list_len); + memcpy(fontlist, name_list, name_list_len); fontlist[name_list_len] = 0; /* @@ -1731,14 +1837,9 @@ static char * font_path(char **fontpath, char *name_list) return "could not alloc full path of font"; } /* if name is an absolute or relative pathname then test directly */ -#ifdef NETWARE - /* netware uses the format "volume:/path" or the standard "/path" */ - if (name[0] != 0 && (strstr(name, ":/") || name[0] == '/')) -#else if (strchr (name, '/') || (name[0] != 0 && name[1] == ':' && (name[2] == '/' || name[2] == '\\'))) -#endif { sprintf (fullname, "%s", name); if (access (fullname, R_OK) == 0) { @@ -1820,4 +1921,3 @@ BGD_DECLARE(int) gdFTUseFontConfig(int flag) return 0; #endif /* HAVE_LIBFONTCONFIG */ } - |