X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/fa5a9c7bae6d484107162641d16b1b38312ac225..89ce83b20249dfb4e45f09dfdddf4c4b66d82968:/src/ftfont.c diff --git a/src/ftfont.c b/src/ftfont.c index 98058aca34..1ae3f88daa 100644 --- a/src/ftfont.c +++ b/src/ftfont.c @@ -1,5 +1,5 @@ /* ftfont.c -- FreeType font driver. - Copyright (C) 2006-2015 Free Software Foundation, Inc. + Copyright (C) 2006-2016 Free Software Foundation, Inc. Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 National Institute of Advanced Industrial Science and Technology (AIST) Registration Number H13PRO009 @@ -8,8 +8,8 @@ This file is part of GNU Emacs. GNU Emacs is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. +the Free Software Foundation, either version 3 of the License, or (at +your option) any later version. GNU Emacs is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -28,13 +28,10 @@ along with GNU Emacs. If not, see . */ #include "lisp.h" #include "dispextern.h" -#include "frame.h" -#include "blockinput.h" #include "character.h" #include "charset.h" -#include "coding.h" +#include "category.h" #include "composite.h" -#include "fontset.h" #include "font.h" #include "ftfont.h" @@ -85,6 +82,8 @@ static Lisp_Object ftfont_lookup_cache (Lisp_Object, static void ftfont_filter_properties (Lisp_Object font, Lisp_Object alist); +static Lisp_Object ftfont_combining_capability (struct font *); + #define SYMBOL_FcChar8(SYM) (FcChar8 *) SDATA (SYMBOL_NAME (SYM)) static struct @@ -551,6 +550,10 @@ struct font_driver ftfont_driver = #endif ftfont_filter_properties, /* filter_properties */ + + NULL, /* cached_font_ok */ + + ftfont_combining_capability, }; static Lisp_Object @@ -565,7 +568,6 @@ ftfont_get_charset (Lisp_Object registry) char *str = SSDATA (SYMBOL_NAME (registry)); USE_SAFE_ALLOCA; char *re = SAFE_ALLOCA (SBYTES (SYMBOL_NAME (registry)) * 2 + 1); - Lisp_Object regexp; int i, j; for (i = j = 0; i < SBYTES (SYMBOL_NAME (registry)); i++, j++) @@ -579,13 +581,13 @@ ftfont_get_charset (Lisp_Object registry) re[j] = '.'; } re[j] = '\0'; - regexp = make_unibyte_string (re, j); - SAFE_FREE (); + AUTO_STRING_WITH_LEN (regexp, re, j); for (i = 0; fc_charset_table[i].name; i++) if (fast_c_string_match_ignore_case (regexp, fc_charset_table[i].name, strlen (fc_charset_table[i].name)) >= 0) break; + SAFE_FREE (); if (! fc_charset_table[i].name) return -1; if (! fc_charset_table[i].fc_charset) @@ -1780,9 +1782,11 @@ setup_otf_gstring (int size) { if (otf_gstring.size < size) { - otf_gstring.glyphs = xnrealloc (otf_gstring.glyphs, - size, sizeof (OTF_Glyph)); - otf_gstring.size = size; + ptrdiff_t new_size = otf_gstring.size; + xfree (otf_gstring.glyphs); + otf_gstring.glyphs = xpalloc (NULL, &new_size, size - otf_gstring.size, + INT_MAX, sizeof *otf_gstring.glyphs); + otf_gstring.size = new_size; } otf_gstring.used = size; memset (otf_gstring.glyphs, 0, sizeof (OTF_Glyph) * size); @@ -2234,6 +2238,8 @@ ftfont_drive_otf (MFLTFont *font, MFLTOtfSpec *spec, MFLTGlyphString *in, MFLTGlyphString *out, MFLTGlyphAdjustment *adjustment) { struct MFLTFontFT *flt_font_ft = (struct MFLTFontFT *) font; + MFLTGlyphFT *in_glyphs = (MFLTGlyphFT *) (in->glyphs) + from; + MFLTGlyphFT *out_glyphs = out ? (MFLTGlyphFT *) (out->glyphs) : NULL; FT_Face ft_face = flt_font_ft->ft_face; OTF *otf = flt_font_ft->otf; int len = to - from; @@ -2284,8 +2290,8 @@ ftfont_drive_otf (MFLTFont *font, MFLTOtfSpec *spec, MFLTGlyphString *in, setup_otf_gstring (len); for (i = 0; i < len; i++) { - otf_gstring.glyphs[i].c = in->glyphs[from + i].c; - otf_gstring.glyphs[i].glyph_id = in->glyphs[from + i].code; + otf_gstring.glyphs[i].c = in_glyphs[i].g.c; + otf_gstring.glyphs[i].glyph_id = in_glyphs[i].g.code; } OTF_drive_gdef (otf, &otf_gstring); @@ -2307,17 +2313,17 @@ ftfont_drive_otf (MFLTFont *font, MFLTOtfSpec *spec, MFLTGlyphString *in, int min_from, max_to; int j; - g = out->glyphs + out->used; - *g = in->glyphs[from + otfg->f.index.from]; - if (g->code != otfg->glyph_id) + g = out_glyphs + out->used; + *g = in_glyphs[otfg->f.index.from]; + if (g->g.code != otfg->glyph_id) { - g->c = 0; - g->code = otfg->glyph_id; - g->measured = 0; + g->g.c = 0; + g->g.code = otfg->glyph_id; + g->g.measured = 0; } out->used++; - min_from = g->from; - max_to = g->to; + min_from = g->g.from; + max_to = g->g.to; if (otfg->f.index.from < otfg->f.index.to) { /* OTFG substitutes multiple glyphs in IN. */ @@ -2329,20 +2335,20 @@ ftfont_drive_otf (MFLTFont *font, MFLTOtfSpec *spec, MFLTGlyphString *in, if (max_to < in->glyphs[j].to) max_to = in->glyphs[j].to; } - g->from = min_from; - g->to = max_to; + g->g.from = min_from; + g->g.to = max_to; } for (i++, otfg++; (i < otf_gstring.used && otfg->f.index.from == otfg[-1].f.index.from); i++, otfg++) { - g = out->glyphs + out->used; - *g = in->glyphs[from + otfg->f.index.to]; - if (g->code != otfg->glyph_id) + g = out_glyphs + out->used; + *g = in_glyphs[otfg->f.index.to]; + if (g->g.code != otfg->glyph_id) { - g->c = 0; - g->code = otfg->glyph_id; - g->measured = 0; + g->g.c = 0; + g->g.code = otfg->glyph_id; + g->g.measured = 0; } out->used++; } @@ -2356,7 +2362,7 @@ ftfont_drive_otf (MFLTFont *font, MFLTOtfSpec *spec, MFLTGlyphString *in, return -2; } for (i = 0; i < len; i++) - out->glyphs[out->used++] = in->glyphs[from + i]; + out_glyphs[out->used++] = in_glyphs[i]; } if (gpos_features) @@ -2376,7 +2382,7 @@ ftfont_drive_otf (MFLTFont *font, MFLTOtfSpec *spec, MFLTGlyphString *in, x_scale = ft_face->size->metrics.x_scale; y_scale = ft_face->size->metrics.y_scale; - for (i = 0, otfg = otf_gstring.glyphs, g = out->glyphs + gidx; + for (i = 0, otfg = otf_gstring.glyphs, g = out_glyphs + gidx; i < otf_gstring.used; i++, otfg++, g++) { MFLTGlyphFT *prev; @@ -2444,10 +2450,10 @@ ftfont_drive_otf (MFLTFont *font, MFLTOtfSpec *spec, MFLTGlyphString *in, mark_y = otfg->f.f4.mark_anchor->YCoordinate * y_scale / 0x10000; if (otfg->f.f4.base_anchor->AnchorFormat != 1) - adjust_anchor (ft_face, otfg->f.f4.base_anchor, - prev->code, x_ppem, y_ppem, &base_x, &base_y); + adjust_anchor (ft_face, otfg->f.f4.base_anchor, prev->g.code, + x_ppem, y_ppem, &base_x, &base_y); if (otfg->f.f4.mark_anchor->AnchorFormat != 1) - adjust_anchor (ft_face, otfg->f.f4.mark_anchor, g->code, + adjust_anchor (ft_face, otfg->f.f4.mark_anchor, g->g.code, x_ppem, y_ppem, &mark_x, &mark_y); adjustment[i].xoff = (base_x - mark_x); adjustment[i].yoff = - (base_y - mark_y); @@ -2455,19 +2461,19 @@ ftfont_drive_otf (MFLTFont *font, MFLTOtfSpec *spec, MFLTGlyphString *in, adjustment[i].xadv = 0; adjustment[i].advance_is_absolute = 1; adjustment[i].set = 1; - this_from = g->from; - this_to = g->to; + this_from = g->g.from; + this_to = g->g.to; for (j = 0; prev + j < g; j++) { - if (this_from > prev[j].from) - this_from = prev[j].from; - if (this_to < prev[j].to) - this_to = prev[j].to; + if (this_from > prev[j].g.from) + this_from = prev[j].g.from; + if (this_to < prev[j].g.to) + this_to = prev[j].g.to; } for (; prev <= g; prev++) { - prev->from = this_from; - prev->to = this_to; + prev->g.from = this_from; + prev->g.to = this_to; } } } @@ -2487,8 +2493,8 @@ ftfont_drive_otf (MFLTFont *font, MFLTOtfSpec *spec, MFLTGlyphString *in, if (out->allocated < out->used + len) return -2; font->get_metrics (font, in, from, to); - memcpy (out->glyphs + out->used, in->glyphs + from, - sizeof (MFLTGlyph) * len); + memcpy (out_glyphs + out->used, in_glyphs, + sizeof (MFLTGlyphFT) * len); out->used += len; return to; } @@ -2507,8 +2513,7 @@ ftfont_shape_by_flt (Lisp_Object lgstring, struct font *font, ptrdiff_t i; struct MFLTFontFT flt_font_ft; MFLT *flt = NULL; - bool with_variation_selector = 0; - MFLTGlyphFT *glyphs; + bool with_variation_selector = false; if (! m17n_flt_initialized) { @@ -2529,12 +2534,12 @@ ftfont_shape_by_flt (Lisp_Object lgstring, struct font *font, break; c = LGLYPH_CHAR (g); if (CHAR_VARIATION_SELECTOR_P (c)) - with_variation_selector = 1; + with_variation_selector = true; } len = i; - if (with_variation_selector) + if (otf && with_variation_selector) { setup_otf_gstring (len); for (i = 0; i < len; i++) @@ -2563,38 +2568,6 @@ ftfont_shape_by_flt (Lisp_Object lgstring, struct font *font, } } - if (INT_MAX / 2 < len) - memory_full (SIZE_MAX); - - if (gstring.allocated == 0) - { - gstring.glyph_size = sizeof (MFLTGlyphFT); - gstring.glyphs = xnmalloc (len * 2, sizeof (MFLTGlyphFT)); - gstring.allocated = len * 2; - } - else if (gstring.allocated < len * 2) - { - gstring.glyphs = xnrealloc (gstring.glyphs, len * 2, - sizeof (MFLTGlyphFT)); - gstring.allocated = len * 2; - } - glyphs = (MFLTGlyphFT *) (gstring.glyphs); - memset (glyphs, 0, len * sizeof (MFLTGlyphFT)); - for (i = 0; i < len; i++) - { - Lisp_Object g = LGSTRING_GLYPH (lgstring, i); - - glyphs[i].g.c = LGLYPH_CHAR (g); - if (with_variation_selector) - { - glyphs[i].g.code = LGLYPH_CODE (g); - glyphs[i].g.encoded = 1; - } - } - - gstring.used = len; - gstring.r2l = 0; - { Lisp_Object family = Ffont_get (LGSTRING_FONT (lgstring), QCfamily); @@ -2615,23 +2588,62 @@ ftfont_shape_by_flt (Lisp_Object lgstring, struct font *font, flt_font_ft.ft_face = ft_face; flt_font_ft.otf = otf; flt_font_ft.matrix = matrix->xx != 0 ? matrix : 0; - if (len > 1 - && gstring.glyphs[1].c >= 0x300 && gstring.glyphs[1].c <= 0x36F) - /* A little bit ad hoc. Perhaps, shaper must get script and - language information, and select a proper flt for them - here. */ - flt = mflt_get (msymbol ("combining")); - for (i = 0; i < 3; i++) - { - int result = mflt_run (&gstring, 0, len, &flt_font_ft.flt_font, flt); - if (result != -2) - break; - if (INT_MAX / 2 < gstring.allocated) - memory_full (SIZE_MAX); - gstring.glyphs = xnrealloc (gstring.glyphs, - gstring.allocated, 2 * sizeof (MFLTGlyphFT)); - gstring.allocated *= 2; + + if (1 < len) + { + /* A little bit ad hoc. Perhaps, shaper must get script and + language information, and select a proper flt for them + here. */ + int c1 = LGLYPH_CHAR (LGSTRING_GLYPH (lgstring, 1)); + /* For the combining characters in the range U+300..U+36F, + "combining" is the sole FLT provided by the m17n-lib. In + addition, it is the sole FLT that can handle the other + combining characters with non-OTF fonts. */ + if ((0x300 <= c1 && c1 <= 0x36F) + || (! otf && CHAR_HAS_CATEGORY (c1, '^'))) + flt = mflt_get (msymbol ("combining")); + } + if (! flt && ! otf) + { + flt = mflt_find (LGLYPH_CHAR (LGSTRING_GLYPH (lgstring, 0)), + &flt_font_ft.flt_font); + if (! flt) + return make_number (0); } + + MFLTGlyphFT *glyphs = (MFLTGlyphFT *) gstring.glyphs; + ptrdiff_t allocated = gstring.allocated; + ptrdiff_t incr_min = len - allocated; + + do + { + if (0 < incr_min) + { + xfree (glyphs); + glyphs = xpalloc (NULL, &allocated, incr_min, INT_MAX, sizeof *glyphs); + } + incr_min = 1; + + for (i = 0; i < len; i++) + { + Lisp_Object g = LGSTRING_GLYPH (lgstring, i); + memset (&glyphs[i], 0, sizeof glyphs[i]); + glyphs[i].g.c = LGLYPH_CHAR (g); + if (with_variation_selector) + { + glyphs[i].g.code = LGLYPH_CODE (g); + glyphs[i].g.encoded = 1; + } + } + + gstring.glyph_size = sizeof *glyphs; + gstring.glyphs = (MFLTGlyph *) glyphs; + gstring.allocated = allocated; + gstring.used = len; + gstring.r2l = 0; + } + while (mflt_run (&gstring, 0, len, &flt_font_ft.flt_font, flt) == -2); + if (gstring.used > LGSTRING_GLYPH_LEN (lgstring)) return Qnil; for (i = 0; i < gstring.used; i++) @@ -2681,8 +2693,6 @@ ftfont_shape (Lisp_Object lgstring) struct ftfont_info *ftfont_info = (struct ftfont_info *) font; OTF *otf = ftfont_get_otf (ftfont_info); - if (! otf) - return make_number (0); return ftfont_shape_by_flt (lgstring, font, ftfont_info->ft_size->face, otf, &ftfont_info->matrix); } @@ -2756,6 +2766,16 @@ ftfont_filter_properties (Lisp_Object font, Lisp_Object alist) } +static Lisp_Object +ftfont_combining_capability (struct font *font) +{ +#ifdef HAVE_M17N_FLT + return Qt; +#else + return Qnil; +#endif +} + void syms_of_ftfont (void) {