X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/fdb396e222923dc98d46c170381c6b33dc1e8d99..416148257afedb97bbe6d732eea3a0c72473dab0:/src/ftfont.c diff --git a/src/ftfont.c b/src/ftfont.c index 14896e3f66..4c12ef5d3a 100644 --- a/src/ftfont.c +++ b/src/ftfont.c @@ -1,5 +1,5 @@ /* ftfont.c -- FreeType font driver. - Copyright (C) 2006-2013 Free Software Foundation, Inc. + Copyright (C) 2006-2014 Free Software Foundation, Inc. Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 National Institute of Advanced Industrial Science and Technology (AIST) Registration Number H13PRO009 @@ -24,6 +24,8 @@ along with GNU Emacs. If not, see . */ #include #include +#include + #include "lisp.h" #include "dispextern.h" #include "frame.h" @@ -54,7 +56,7 @@ static Lisp_Object freetype_font_cache; /* Cache for FT_Face and FcCharSet. */ static Lisp_Object ft_face_cache; -/* The actual structure for FreeType font that can be casted to struct +/* The actual structure for FreeType font that can be cast to struct font. */ struct ftfont_info @@ -87,8 +89,6 @@ static Lisp_Object ftfont_lookup_cache (Lisp_Object, static void ftfont_filter_properties (Lisp_Object font, Lisp_Object alist); -Lisp_Object ftfont_font_format (FcPattern *, Lisp_Object); - #define SYMBOL_FcChar8(SYM) (FcChar8 *) SDATA (SYMBOL_NAME (SYM)) static struct @@ -142,6 +142,12 @@ static struct { NULL } }; +static bool +matching_prefix (char const *str, ptrdiff_t len, char const *pat) +{ + return len == strlen (pat) && c_strncasecmp (str, pat, len) == 0; +} + /* Dirty hack for handing ADSTYLE property. Fontconfig (actually the underlying FreeType) gives such ADSTYLE @@ -173,18 +179,10 @@ get_adstyle_property (FcPattern *p) return Qnil; str = (char *) fcstr; for (end = str; *end && *end != ' '; end++); - if (*end) - { - char *newstr = alloca (end - str + 1); - memcpy (newstr, str, end - str); - newstr[end - str] = '\0'; - end = newstr + (end - str); - str = newstr; - } - if (xstrcasecmp (str, "Regular") == 0 - || xstrcasecmp (str, "Bold") == 0 - || xstrcasecmp (str, "Oblique") == 0 - || xstrcasecmp (str, "Italic") == 0) + if (matching_prefix (str, end - str, "Regular") + || matching_prefix (str, end - str, "Bold") + || matching_prefix (str, end - str, "Oblique") + || matching_prefix (str, end - str, "Italic")) return Qnil; adstyle = font_intern_prop (str, end - str, 1); if (font_style_to_value (FONT_WIDTH_INDEX, adstyle, 0) >= 0) @@ -493,16 +491,16 @@ ftfont_get_otf (struct ftfont_info *ftfont_info) } #endif /* HAVE_LIBOTF */ -static Lisp_Object ftfont_get_cache (FRAME_PTR); +static Lisp_Object ftfont_get_cache (struct frame *); static Lisp_Object ftfont_list (struct frame *, Lisp_Object); static Lisp_Object ftfont_match (struct frame *, Lisp_Object); static Lisp_Object ftfont_list_family (struct frame *); -static Lisp_Object ftfont_open (FRAME_PTR, Lisp_Object, int); -static void ftfont_close (FRAME_PTR, struct font *); +static Lisp_Object ftfont_open (struct frame *, Lisp_Object, int); +static void ftfont_close (struct font *); static int ftfont_has_char (Lisp_Object, int); static unsigned ftfont_encode_char (struct font *, int); -static int ftfont_text_extents (struct font *, unsigned *, int, - struct font_metrics *); +static void ftfont_text_extents (struct font *, unsigned *, int, + struct font_metrics *); static int ftfont_get_bitmap (struct font *, unsigned, struct font_bitmap *, int); static int ftfont_anchor_point (struct font *, unsigned, int, @@ -540,8 +538,6 @@ struct font_driver ftfont_driver = NULL, /* draw */ ftfont_get_bitmap, NULL, /* free_bitmap */ - NULL, /* get_outline */ - NULL, /* free_outline */ ftfont_anchor_point, #ifdef HAVE_LIBOTF ftfont_otf_capability, @@ -568,7 +564,7 @@ struct font_driver ftfont_driver = }; static Lisp_Object -ftfont_get_cache (FRAME_PTR f) +ftfont_get_cache (struct frame *f) { return freetype_font_cache; } @@ -577,7 +573,8 @@ static int ftfont_get_charset (Lisp_Object registry) { char *str = SSDATA (SYMBOL_NAME (registry)); - char *re = alloca (SBYTES (SYMBOL_NAME (registry)) * 2 + 1); + USE_SAFE_ALLOCA; + char *re = SAFE_ALLOCA (SBYTES (SYMBOL_NAME (registry)) * 2 + 1); Lisp_Object regexp; int i, j; @@ -593,6 +590,7 @@ ftfont_get_charset (Lisp_Object registry) } re[j] = '\0'; regexp = make_unibyte_string (re, j); + SAFE_FREE (); for (i = 0; fc_charset_table[i].name; i++) if (fast_c_string_match_ignore_case (regexp, fc_charset_table[i].name, @@ -806,7 +804,7 @@ ftfont_spec_pattern (Lisp_Object spec, char *otlayout, struct OpenTypeSpec **ots *otspec = ftfont_get_open_type_spec (val); if (! *otspec) return NULL; - strcat (otlayout, "otlayout:"); + strcpy (otlayout, "otlayout:"); OTF_TAG_STR ((*otspec)->script_tag, otlayout + 9); script = (*otspec)->script; } @@ -1011,6 +1009,7 @@ ftfont_list (struct frame *f, Lisp_Object spec) if (otspec) { FcChar8 *file; + bool passed; OTF *otf; if (FcPatternGetString (fontset->fonts[i], FC_FILE, 0, &file) @@ -1019,14 +1018,16 @@ ftfont_list (struct frame *f, Lisp_Object spec) otf = OTF_open ((char *) file); if (! otf) continue; - if (OTF_check_features (otf, 1, - otspec->script_tag, otspec->langsys_tag, - otspec->features[0], - otspec->nfeatures[0]) != 1 - || OTF_check_features (otf, 0, - otspec->script_tag, otspec->langsys_tag, - otspec->features[1], - otspec->nfeatures[1]) != 1) + passed = (OTF_check_features (otf, 1, otspec->script_tag, + otspec->langsys_tag, + otspec->features[0], + otspec->nfeatures[0]) == 1 + && OTF_check_features (otf, 0, otspec->script_tag, + otspec->langsys_tag, + otspec->features[1], + otspec->nfeatures[1]) == 1); + OTF_close (otf); + if (!passed) continue; } #endif /* HAVE_LIBOTF */ @@ -1173,7 +1174,7 @@ ftfont_list_family (struct frame *f) static Lisp_Object -ftfont_open (FRAME_PTR f, Lisp_Object entity, int pixel_size) +ftfont_open (struct frame *f, Lisp_Object entity, int pixel_size) { struct ftfont_info *ftfont_info; struct font *font; @@ -1184,8 +1185,7 @@ ftfont_open (FRAME_PTR f, Lisp_Object entity, int pixel_size) Lisp_Object val, filename, idx, cache, font_object; bool scalable; int spacing; - char name[256]; - int i, len; + int i; int upEM; val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX)); @@ -1222,19 +1222,9 @@ ftfont_open (FRAME_PTR f, Lisp_Object entity, int pixel_size) return Qnil; } - font_object = font_make_object (VECSIZE (struct ftfont_info), entity, size); - ASET (font_object, FONT_TYPE_INDEX, Qfreetype); - len = font_unparse_xlfd (entity, size, name, 256); - if (len > 0) - ASET (font_object, FONT_NAME_INDEX, make_string (name, len)); - len = font_unparse_fcname (entity, size, name, 256); - if (len > 0) - ASET (font_object, FONT_FULLNAME_INDEX, make_string (name, len)); - else - ASET (font_object, FONT_FULLNAME_INDEX, - AREF (font_object, FONT_NAME_INDEX)); + font_object = font_build_object (VECSIZE (struct ftfont_info), + Qfreetype, entity, size); ASET (font_object, FONT_FILE_INDEX, filename); - ASET (font_object, FONT_FORMAT_INDEX, ftfont_font_format (NULL, filename)); font = XFONT_OBJECT (font_object); ftfont_info = (struct ftfont_info *) font; ftfont_info->ft_size = ft_face->size; @@ -1317,7 +1307,7 @@ ftfont_open (FRAME_PTR f, Lisp_Object entity, int pixel_size) } static void -ftfont_close (FRAME_PTR f, struct font *font) +ftfont_close (struct font *font) { struct ftfont_info *ftfont_info = (struct ftfont_info *) font; Lisp_Object val, cache; @@ -1383,19 +1373,18 @@ ftfont_encode_char (struct font *font, int c) return (code > 0 ? code : FONT_INVALID_CODE); } -static int -ftfont_text_extents (struct font *font, unsigned int *code, int nglyphs, struct font_metrics *metrics) +static void +ftfont_text_extents (struct font *font, unsigned int *code, + int nglyphs, struct font_metrics *metrics) { struct ftfont_info *ftfont_info = (struct ftfont_info *) font; FT_Face ft_face = ftfont_info->ft_size->face; - int width = 0; - int i; + int i, width = 0; bool first; if (ftfont_info->ft_size != ft_face->size) FT_Activate_Size (ftfont_info->ft_size); - if (metrics) - memset (metrics, 0, sizeof (struct font_metrics)); + for (i = 0, first = 1; i < nglyphs; i++) { if (FT_Load_Glyph (ft_face, code[i], FT_LOAD_DEFAULT) == 0) @@ -1404,39 +1393,28 @@ ftfont_text_extents (struct font *font, unsigned int *code, int nglyphs, struct if (first) { - if (metrics) - { - metrics->lbearing = m->horiBearingX >> 6; - metrics->rbearing = (m->horiBearingX + m->width) >> 6; - metrics->ascent = m->horiBearingY >> 6; - metrics->descent = (m->height - m->horiBearingY) >> 6; - } + metrics->lbearing = m->horiBearingX >> 6; + metrics->rbearing = (m->horiBearingX + m->width) >> 6; + metrics->ascent = m->horiBearingY >> 6; + metrics->descent = (m->height - m->horiBearingY) >> 6; first = 0; } - if (metrics) - { - if (metrics->lbearing > width + (m->horiBearingX >> 6)) - metrics->lbearing = width + (m->horiBearingX >> 6); - if (metrics->rbearing - < width + ((m->horiBearingX + m->width) >> 6)) - metrics->rbearing - = width + ((m->horiBearingX + m->width) >> 6); - if (metrics->ascent < (m->horiBearingY >> 6)) - metrics->ascent = m->horiBearingY >> 6; - if (metrics->descent > ((m->height - m->horiBearingY) >> 6)) - metrics->descent = (m->height - m->horiBearingY) >> 6; - } + if (metrics->lbearing > width + (m->horiBearingX >> 6)) + metrics->lbearing = width + (m->horiBearingX >> 6); + if (metrics->rbearing + < width + ((m->horiBearingX + m->width) >> 6)) + metrics->rbearing + = width + ((m->horiBearingX + m->width) >> 6); + if (metrics->ascent < (m->horiBearingY >> 6)) + metrics->ascent = m->horiBearingY >> 6; + if (metrics->descent > ((m->height - m->horiBearingY) >> 6)) + metrics->descent = (m->height - m->horiBearingY) >> 6; width += m->horiAdvance >> 6; } else - { - width += font->space_width; - } + width += font->space_width; } - if (metrics) - metrics->width = width; - - return width; + metrics->width = width; } static int @@ -1478,7 +1456,6 @@ ftfont_get_bitmap (struct font *font, unsigned int code, struct font_bitmap *bit bitmap->left = ft_face->glyph->bitmap_left; bitmap->top = ft_face->glyph->bitmap_top; bitmap->advance = ft_face->glyph->metrics.horiAdvance >> 6; - bitmap->extra = NULL; return 0; } @@ -1713,7 +1690,8 @@ ftfont_check_otf (MFLTFont *font, MFLTOtfSpec *spec) else if (! otf) return 0; for (n = 1; spec->features[i][n]; n++); - tags = alloca (sizeof (OTF_Tag) * n); + USE_SAFE_ALLOCA; + SAFE_NALLOCA (tags, 1, n); for (n = 0, negative = 0; spec->features[i][n]; n++) { if (spec->features[i][n] == 0xFFFFFFFF) @@ -1723,16 +1701,17 @@ ftfont_check_otf (MFLTFont *font, MFLTOtfSpec *spec) else tags[n] = spec->features[i][n]; } -#ifdef M17N_FLT_USE_NEW_FEATURE - if (OTF_check_features (otf, i == 0, spec->script, spec->langsys, - tags, n - negative) != 1) - return 0; -#else /* not M17N_FLT_USE_NEW_FEATURE */ - if (n - negative > 0 - && OTF_check_features (otf, i == 0, spec->script, spec->langsys, - tags, n - negative) != 1) + bool passed = true; +#ifndef M17N_FLT_USE_NEW_FEATURE + passed = n - negative > 0; +#endif + if (passed) + passed = (OTF_check_features (otf, i == 0, spec->script, + spec->langsys, tags, n - negative) + != 1); + SAFE_FREE (); + if (passed) return 0; -#endif /* not M17N_FLT_USE_NEW_FEATURE */ } return 1; #undef FEATURE_NONE @@ -1824,11 +1803,15 @@ ftfont_drive_otf (MFLTFont *font, if (len == 0) return from; OTF_tag_name (spec->script, script); + + char langsysbuf[5]; if (spec->langsys) { - langsys = alloca (5); + langsys = langsysbuf; OTF_tag_name (spec->langsys, langsys); } + + USE_SAFE_ALLOCA; for (i = 0; i < 2; i++) { char *p; @@ -1836,10 +1819,11 @@ ftfont_drive_otf (MFLTFont *font, if (spec->features[i] && spec->features[i][1] != 0xFFFFFFFF) { for (j = 0; spec->features[i][j]; j++); + SAFE_NALLOCA (p, 6, j); if (i == 0) - p = gsub_features = alloca (6 * j); + gsub_features = p; else - p = gpos_features = alloca (6 * j); + gpos_features = p; for (j = 0; spec->features[i][j]; j++) { if (spec->features[i][j] == 0xFFFFFFFF) @@ -1871,7 +1855,10 @@ ftfont_drive_otf (MFLTFont *font, gsub_features) < 0) goto simple_copy; if (out->allocated < out->used + otf_gstring.used) - return -2; + { + SAFE_FREE (); + return -2; + } features = otf->gsub->FeatureList.Feature; for (i = 0, otfg = otf_gstring.glyphs; i < otf_gstring.used; ) { @@ -1960,7 +1947,10 @@ ftfont_drive_otf (MFLTFont *font, else if (out) { if (out->allocated < out->used + len) - return -2; + { + SAFE_FREE (); + return -2; + } for (i = 0; i < len; i++) out->glyphs[out->used++] = in->glyphs[from + i]; } @@ -1972,7 +1962,10 @@ ftfont_drive_otf (MFLTFont *font, if (OTF_drive_gpos_with_log (otf, &otf_gstring, script, langsys, gpos_features) < 0) - return to; + { + SAFE_FREE (); + return to; + } features = otf->gpos->FeatureList.Feature; x_ppem = ft_face->size->metrics.x_ppem; y_ppem = ft_face->size->metrics.y_ppem; @@ -2094,7 +2087,10 @@ ftfont_drive_otf (MFLTFont *font, { if (OTF_drive_gpos_with_log (otf, &otf_gstring, script, langsys, gpos_features) < 0) - return to; + { + SAFE_FREE (); + return to; + } features = otf->gpos->FeatureList.Feature; for (i = 0, otfg = otf_gstring.glyphs; i < otf_gstring.used; i++, otfg++) @@ -2114,9 +2110,11 @@ ftfont_drive_otf (MFLTFont *font, } } } + SAFE_FREE (); return to; simple_copy: + SAFE_FREE (); if (! out) return to; if (out->allocated < out->used + len) @@ -2154,11 +2152,15 @@ ftfont_drive_otf (MFLTFont *font, MFLTOtfSpec *spec, MFLTGlyphString *in, if (len == 0) return from; OTF_tag_name (spec->script, script); + + char langsysbuf[5]; if (spec->langsys) { - langsys = alloca (5); + langsys = langsysbuf; OTF_tag_name (spec->langsys, langsys); } + + USE_SAFE_ALLOCA; for (i = 0; i < 2; i++) { char *p; @@ -2166,10 +2168,11 @@ ftfont_drive_otf (MFLTFont *font, MFLTOtfSpec *spec, MFLTGlyphString *in, if (spec->features[i] && spec->features[i][1] != 0xFFFFFFFF) { for (j = 0; spec->features[i][j]; j++); + SAFE_NALLOCA (p, 6, j); if (i == 0) - p = gsub_features = alloca (6 * j); + gsub_features = p; else - p = gpos_features = alloca (6 * j); + gpos_features = p; for (j = 0; spec->features[i][j]; j++) { if (spec->features[i][j] == 0xFFFFFFFF) @@ -2201,7 +2204,10 @@ ftfont_drive_otf (MFLTFont *font, MFLTOtfSpec *spec, MFLTGlyphString *in, < 0) goto simple_copy; if (out->allocated < out->used + otf_gstring.used) - return -2; + { + SAFE_FREE (); + return -2; + } for (i = 0, otfg = otf_gstring.glyphs; i < otf_gstring.used; ) { MFLTGlyph *g; @@ -2252,7 +2258,10 @@ ftfont_drive_otf (MFLTFont *font, MFLTOtfSpec *spec, MFLTGlyphString *in, else { if (out->allocated < out->used + len) - return -2; + { + SAFE_FREE (); + return -2; + } for (i = 0; i < len; i++) out->glyphs[out->used++] = in->glyphs[from + i]; } @@ -2264,7 +2273,10 @@ ftfont_drive_otf (MFLTFont *font, MFLTOtfSpec *spec, MFLTGlyphString *in, if (OTF_drive_gpos (otf, &otf_gstring, script, langsys, gpos_features) < 0) - return to; + { + SAFE_FREE (); + return to; + } x_ppem = ft_face->size->metrics.x_ppem; y_ppem = ft_face->size->metrics.y_ppem; @@ -2374,9 +2386,11 @@ ftfont_drive_otf (MFLTFont *font, MFLTOtfSpec *spec, MFLTGlyphString *in, base = g; } } + SAFE_FREE (); return to; simple_copy: + SAFE_FREE (); if (out->allocated < out->used + len) return -2; font->get_metrics (font, in, from, to); @@ -2425,7 +2439,6 @@ ftfont_shape_by_flt (Lisp_Object lgstring, struct font *font, } len = i; - lint_assume (len <= STRING_BYTES_BOUND); if (with_variation_selector) { @@ -2600,46 +2613,6 @@ ftfont_variation_glyphs (struct font *font, int c, unsigned variations[256]) #endif /* HAVE_OTF_GET_VARIATION_GLYPHS */ #endif /* HAVE_LIBOTF */ -Lisp_Object -ftfont_font_format (FcPattern *pattern, Lisp_Object filename) -{ - FcChar8 *str; - -#ifdef FC_FONTFORMAT - if (pattern) - { - if (FcPatternGetString (pattern, FC_FONTFORMAT, 0, &str) != FcResultMatch) - return Qnil; - if (strcmp ((char *) str, "TrueType") == 0) - return intern ("truetype"); - if (strcmp ((char *) str, "Type 1") == 0) - return intern ("type1"); - if (strcmp ((char *) str, "PCF") == 0) - return intern ("pcf"); - if (strcmp ((char *) str, "BDF") == 0) - return intern ("bdf"); - } -#endif /* FC_FONTFORMAT */ - if (STRINGP (filename)) - { - int len = SBYTES (filename); - - if (len >= 4) - { - str = (FcChar8 *) (SDATA (filename) + len - 4); - if (xstrcasecmp ((char *) str, ".ttf") == 0) - return intern ("truetype"); - if (xstrcasecmp ((char *) str, ".pfb") == 0) - return intern ("type1"); - if (xstrcasecmp ((char *) str, ".pcf") == 0) - return intern ("pcf"); - if (xstrcasecmp ((char *) str, ".bdf") == 0) - return intern ("bdf"); - } - } - return intern ("unknown"); -} - static const char *const ftfont_booleans [] = { ":antialias", ":hinting",