aboutsummaryrefslogtreecommitdiffstats
path: root/src/ftfont.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/ftfont.c')
-rw-r--r--src/ftfont.c171
1 files changed, 99 insertions, 72 deletions
diff --git a/src/ftfont.c b/src/ftfont.c
index 419274a30aa..4c12ef5d3af 100644
--- a/src/ftfont.c
+++ b/src/ftfont.c
@@ -24,6 +24,8 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
24#include <fontconfig/fontconfig.h> 24#include <fontconfig/fontconfig.h>
25#include <fontconfig/fcfreetype.h> 25#include <fontconfig/fcfreetype.h>
26 26
27#include <c-strcase.h>
28
27#include "lisp.h" 29#include "lisp.h"
28#include "dispextern.h" 30#include "dispextern.h"
29#include "frame.h" 31#include "frame.h"
@@ -140,6 +142,12 @@ static struct
140 { NULL } 142 { NULL }
141 }; 143 };
142 144
145static bool
146matching_prefix (char const *str, ptrdiff_t len, char const *pat)
147{
148 return len == strlen (pat) && c_strncasecmp (str, pat, len) == 0;
149}
150
143/* Dirty hack for handing ADSTYLE property. 151/* Dirty hack for handing ADSTYLE property.
144 152
145 Fontconfig (actually the underlying FreeType) gives such ADSTYLE 153 Fontconfig (actually the underlying FreeType) gives such ADSTYLE
@@ -171,18 +179,10 @@ get_adstyle_property (FcPattern *p)
171 return Qnil; 179 return Qnil;
172 str = (char *) fcstr; 180 str = (char *) fcstr;
173 for (end = str; *end && *end != ' '; end++); 181 for (end = str; *end && *end != ' '; end++);
174 if (*end) 182 if (matching_prefix (str, end - str, "Regular")
175 { 183 || matching_prefix (str, end - str, "Bold")
176 char *newstr = alloca (end - str + 1); 184 || matching_prefix (str, end - str, "Oblique")
177 memcpy (newstr, str, end - str); 185 || matching_prefix (str, end - str, "Italic"))
178 newstr[end - str] = '\0';
179 end = newstr + (end - str);
180 str = newstr;
181 }
182 if (xstrcasecmp (str, "Regular") == 0
183 || xstrcasecmp (str, "Bold") == 0
184 || xstrcasecmp (str, "Oblique") == 0
185 || xstrcasecmp (str, "Italic") == 0)
186 return Qnil; 186 return Qnil;
187 adstyle = font_intern_prop (str, end - str, 1); 187 adstyle = font_intern_prop (str, end - str, 1);
188 if (font_style_to_value (FONT_WIDTH_INDEX, adstyle, 0) >= 0) 188 if (font_style_to_value (FONT_WIDTH_INDEX, adstyle, 0) >= 0)
@@ -499,8 +499,8 @@ static Lisp_Object ftfont_open (struct frame *, Lisp_Object, int);
499static void ftfont_close (struct font *); 499static void ftfont_close (struct font *);
500static int ftfont_has_char (Lisp_Object, int); 500static int ftfont_has_char (Lisp_Object, int);
501static unsigned ftfont_encode_char (struct font *, int); 501static unsigned ftfont_encode_char (struct font *, int);
502static int ftfont_text_extents (struct font *, unsigned *, int, 502static void ftfont_text_extents (struct font *, unsigned *, int,
503 struct font_metrics *); 503 struct font_metrics *);
504static int ftfont_get_bitmap (struct font *, unsigned, 504static int ftfont_get_bitmap (struct font *, unsigned,
505 struct font_bitmap *, int); 505 struct font_bitmap *, int);
506static int ftfont_anchor_point (struct font *, unsigned, int, 506static int ftfont_anchor_point (struct font *, unsigned, int,
@@ -573,7 +573,8 @@ static int
573ftfont_get_charset (Lisp_Object registry) 573ftfont_get_charset (Lisp_Object registry)
574{ 574{
575 char *str = SSDATA (SYMBOL_NAME (registry)); 575 char *str = SSDATA (SYMBOL_NAME (registry));
576 char *re = alloca (SBYTES (SYMBOL_NAME (registry)) * 2 + 1); 576 USE_SAFE_ALLOCA;
577 char *re = SAFE_ALLOCA (SBYTES (SYMBOL_NAME (registry)) * 2 + 1);
577 Lisp_Object regexp; 578 Lisp_Object regexp;
578 int i, j; 579 int i, j;
579 580
@@ -589,6 +590,7 @@ ftfont_get_charset (Lisp_Object registry)
589 } 590 }
590 re[j] = '\0'; 591 re[j] = '\0';
591 regexp = make_unibyte_string (re, j); 592 regexp = make_unibyte_string (re, j);
593 SAFE_FREE ();
592 for (i = 0; fc_charset_table[i].name; i++) 594 for (i = 0; fc_charset_table[i].name; i++)
593 if (fast_c_string_match_ignore_case 595 if (fast_c_string_match_ignore_case
594 (regexp, fc_charset_table[i].name, 596 (regexp, fc_charset_table[i].name,
@@ -802,7 +804,7 @@ ftfont_spec_pattern (Lisp_Object spec, char *otlayout, struct OpenTypeSpec **ots
802 *otspec = ftfont_get_open_type_spec (val); 804 *otspec = ftfont_get_open_type_spec (val);
803 if (! *otspec) 805 if (! *otspec)
804 return NULL; 806 return NULL;
805 strcat (otlayout, "otlayout:"); 807 strcpy (otlayout, "otlayout:");
806 OTF_TAG_STR ((*otspec)->script_tag, otlayout + 9); 808 OTF_TAG_STR ((*otspec)->script_tag, otlayout + 9);
807 script = (*otspec)->script; 809 script = (*otspec)->script;
808 } 810 }
@@ -1371,19 +1373,18 @@ ftfont_encode_char (struct font *font, int c)
1371 return (code > 0 ? code : FONT_INVALID_CODE); 1373 return (code > 0 ? code : FONT_INVALID_CODE);
1372} 1374}
1373 1375
1374static int 1376static void
1375ftfont_text_extents (struct font *font, unsigned int *code, int nglyphs, struct font_metrics *metrics) 1377ftfont_text_extents (struct font *font, unsigned int *code,
1378 int nglyphs, struct font_metrics *metrics)
1376{ 1379{
1377 struct ftfont_info *ftfont_info = (struct ftfont_info *) font; 1380 struct ftfont_info *ftfont_info = (struct ftfont_info *) font;
1378 FT_Face ft_face = ftfont_info->ft_size->face; 1381 FT_Face ft_face = ftfont_info->ft_size->face;
1379 int width = 0; 1382 int i, width = 0;
1380 int i;
1381 bool first; 1383 bool first;
1382 1384
1383 if (ftfont_info->ft_size != ft_face->size) 1385 if (ftfont_info->ft_size != ft_face->size)
1384 FT_Activate_Size (ftfont_info->ft_size); 1386 FT_Activate_Size (ftfont_info->ft_size);
1385 if (metrics) 1387
1386 memset (metrics, 0, sizeof (struct font_metrics));
1387 for (i = 0, first = 1; i < nglyphs; i++) 1388 for (i = 0, first = 1; i < nglyphs; i++)
1388 { 1389 {
1389 if (FT_Load_Glyph (ft_face, code[i], FT_LOAD_DEFAULT) == 0) 1390 if (FT_Load_Glyph (ft_face, code[i], FT_LOAD_DEFAULT) == 0)
@@ -1392,39 +1393,28 @@ ftfont_text_extents (struct font *font, unsigned int *code, int nglyphs, struct
1392 1393
1393 if (first) 1394 if (first)
1394 { 1395 {
1395 if (metrics) 1396 metrics->lbearing = m->horiBearingX >> 6;
1396 { 1397 metrics->rbearing = (m->horiBearingX + m->width) >> 6;
1397 metrics->lbearing = m->horiBearingX >> 6; 1398 metrics->ascent = m->horiBearingY >> 6;
1398 metrics->rbearing = (m->horiBearingX + m->width) >> 6; 1399 metrics->descent = (m->height - m->horiBearingY) >> 6;
1399 metrics->ascent = m->horiBearingY >> 6;
1400 metrics->descent = (m->height - m->horiBearingY) >> 6;
1401 }
1402 first = 0; 1400 first = 0;
1403 } 1401 }
1404 if (metrics) 1402 if (metrics->lbearing > width + (m->horiBearingX >> 6))
1405 { 1403 metrics->lbearing = width + (m->horiBearingX >> 6);
1406 if (metrics->lbearing > width + (m->horiBearingX >> 6)) 1404 if (metrics->rbearing
1407 metrics->lbearing = width + (m->horiBearingX >> 6); 1405 < width + ((m->horiBearingX + m->width) >> 6))
1408 if (metrics->rbearing 1406 metrics->rbearing
1409 < width + ((m->horiBearingX + m->width) >> 6)) 1407 = width + ((m->horiBearingX + m->width) >> 6);
1410 metrics->rbearing 1408 if (metrics->ascent < (m->horiBearingY >> 6))
1411 = width + ((m->horiBearingX + m->width) >> 6); 1409 metrics->ascent = m->horiBearingY >> 6;
1412 if (metrics->ascent < (m->horiBearingY >> 6)) 1410 if (metrics->descent > ((m->height - m->horiBearingY) >> 6))
1413 metrics->ascent = m->horiBearingY >> 6; 1411 metrics->descent = (m->height - m->horiBearingY) >> 6;
1414 if (metrics->descent > ((m->height - m->horiBearingY) >> 6))
1415 metrics->descent = (m->height - m->horiBearingY) >> 6;
1416 }
1417 width += m->horiAdvance >> 6; 1412 width += m->horiAdvance >> 6;
1418 } 1413 }
1419 else 1414 else
1420 { 1415 width += font->space_width;
1421 width += font->space_width;
1422 }
1423 } 1416 }
1424 if (metrics) 1417 metrics->width = width;
1425 metrics->width = width;
1426
1427 return width;
1428} 1418}
1429 1419
1430static int 1420static int
@@ -1700,7 +1690,8 @@ ftfont_check_otf (MFLTFont *font, MFLTOtfSpec *spec)
1700 else if (! otf) 1690 else if (! otf)
1701 return 0; 1691 return 0;
1702 for (n = 1; spec->features[i][n]; n++); 1692 for (n = 1; spec->features[i][n]; n++);
1703 tags = alloca (sizeof (OTF_Tag) * n); 1693 USE_SAFE_ALLOCA;
1694 SAFE_NALLOCA (tags, 1, n);
1704 for (n = 0, negative = 0; spec->features[i][n]; n++) 1695 for (n = 0, negative = 0; spec->features[i][n]; n++)
1705 { 1696 {
1706 if (spec->features[i][n] == 0xFFFFFFFF) 1697 if (spec->features[i][n] == 0xFFFFFFFF)
@@ -1710,16 +1701,17 @@ ftfont_check_otf (MFLTFont *font, MFLTOtfSpec *spec)
1710 else 1701 else
1711 tags[n] = spec->features[i][n]; 1702 tags[n] = spec->features[i][n];
1712 } 1703 }
1713#ifdef M17N_FLT_USE_NEW_FEATURE 1704 bool passed = true;
1714 if (OTF_check_features (otf, i == 0, spec->script, spec->langsys, 1705#ifndef M17N_FLT_USE_NEW_FEATURE
1715 tags, n - negative) != 1) 1706 passed = n - negative > 0;
1716 return 0; 1707#endif
1717#else /* not M17N_FLT_USE_NEW_FEATURE */ 1708 if (passed)
1718 if (n - negative > 0 1709 passed = (OTF_check_features (otf, i == 0, spec->script,
1719 && OTF_check_features (otf, i == 0, spec->script, spec->langsys, 1710 spec->langsys, tags, n - negative)
1720 tags, n - negative) != 1) 1711 != 1);
1712 SAFE_FREE ();
1713 if (passed)
1721 return 0; 1714 return 0;
1722#endif /* not M17N_FLT_USE_NEW_FEATURE */
1723 } 1715 }
1724 return 1; 1716 return 1;
1725#undef FEATURE_NONE 1717#undef FEATURE_NONE
@@ -1811,11 +1803,15 @@ ftfont_drive_otf (MFLTFont *font,
1811 if (len == 0) 1803 if (len == 0)
1812 return from; 1804 return from;
1813 OTF_tag_name (spec->script, script); 1805 OTF_tag_name (spec->script, script);
1806
1807 char langsysbuf[5];
1814 if (spec->langsys) 1808 if (spec->langsys)
1815 { 1809 {
1816 langsys = alloca (5); 1810 langsys = langsysbuf;
1817 OTF_tag_name (spec->langsys, langsys); 1811 OTF_tag_name (spec->langsys, langsys);
1818 } 1812 }
1813
1814 USE_SAFE_ALLOCA;
1819 for (i = 0; i < 2; i++) 1815 for (i = 0; i < 2; i++)
1820 { 1816 {
1821 char *p; 1817 char *p;
@@ -1823,10 +1819,11 @@ ftfont_drive_otf (MFLTFont *font,
1823 if (spec->features[i] && spec->features[i][1] != 0xFFFFFFFF) 1819 if (spec->features[i] && spec->features[i][1] != 0xFFFFFFFF)
1824 { 1820 {
1825 for (j = 0; spec->features[i][j]; j++); 1821 for (j = 0; spec->features[i][j]; j++);
1822 SAFE_NALLOCA (p, 6, j);
1826 if (i == 0) 1823 if (i == 0)
1827 p = gsub_features = alloca (6 * j); 1824 gsub_features = p;
1828 else 1825 else
1829 p = gpos_features = alloca (6 * j); 1826 gpos_features = p;
1830 for (j = 0; spec->features[i][j]; j++) 1827 for (j = 0; spec->features[i][j]; j++)
1831 { 1828 {
1832 if (spec->features[i][j] == 0xFFFFFFFF) 1829 if (spec->features[i][j] == 0xFFFFFFFF)
@@ -1858,7 +1855,10 @@ ftfont_drive_otf (MFLTFont *font,
1858 gsub_features) < 0) 1855 gsub_features) < 0)
1859 goto simple_copy; 1856 goto simple_copy;
1860 if (out->allocated < out->used + otf_gstring.used) 1857 if (out->allocated < out->used + otf_gstring.used)
1861 return -2; 1858 {
1859 SAFE_FREE ();
1860 return -2;
1861 }
1862 features = otf->gsub->FeatureList.Feature; 1862 features = otf->gsub->FeatureList.Feature;
1863 for (i = 0, otfg = otf_gstring.glyphs; i < otf_gstring.used; ) 1863 for (i = 0, otfg = otf_gstring.glyphs; i < otf_gstring.used; )
1864 { 1864 {
@@ -1947,7 +1947,10 @@ ftfont_drive_otf (MFLTFont *font,
1947 else if (out) 1947 else if (out)
1948 { 1948 {
1949 if (out->allocated < out->used + len) 1949 if (out->allocated < out->used + len)
1950 return -2; 1950 {
1951 SAFE_FREE ();
1952 return -2;
1953 }
1951 for (i = 0; i < len; i++) 1954 for (i = 0; i < len; i++)
1952 out->glyphs[out->used++] = in->glyphs[from + i]; 1955 out->glyphs[out->used++] = in->glyphs[from + i];
1953 } 1956 }
@@ -1959,7 +1962,10 @@ ftfont_drive_otf (MFLTFont *font,
1959 1962
1960 if (OTF_drive_gpos_with_log (otf, &otf_gstring, script, langsys, 1963 if (OTF_drive_gpos_with_log (otf, &otf_gstring, script, langsys,
1961 gpos_features) < 0) 1964 gpos_features) < 0)
1962 return to; 1965 {
1966 SAFE_FREE ();
1967 return to;
1968 }
1963 features = otf->gpos->FeatureList.Feature; 1969 features = otf->gpos->FeatureList.Feature;
1964 x_ppem = ft_face->size->metrics.x_ppem; 1970 x_ppem = ft_face->size->metrics.x_ppem;
1965 y_ppem = ft_face->size->metrics.y_ppem; 1971 y_ppem = ft_face->size->metrics.y_ppem;
@@ -2081,7 +2087,10 @@ ftfont_drive_otf (MFLTFont *font,
2081 { 2087 {
2082 if (OTF_drive_gpos_with_log (otf, &otf_gstring, script, langsys, 2088 if (OTF_drive_gpos_with_log (otf, &otf_gstring, script, langsys,
2083 gpos_features) < 0) 2089 gpos_features) < 0)
2084 return to; 2090 {
2091 SAFE_FREE ();
2092 return to;
2093 }
2085 features = otf->gpos->FeatureList.Feature; 2094 features = otf->gpos->FeatureList.Feature;
2086 for (i = 0, otfg = otf_gstring.glyphs; i < otf_gstring.used; 2095 for (i = 0, otfg = otf_gstring.glyphs; i < otf_gstring.used;
2087 i++, otfg++) 2096 i++, otfg++)
@@ -2101,9 +2110,11 @@ ftfont_drive_otf (MFLTFont *font,
2101 } 2110 }
2102 } 2111 }
2103 } 2112 }
2113 SAFE_FREE ();
2104 return to; 2114 return to;
2105 2115
2106 simple_copy: 2116 simple_copy:
2117 SAFE_FREE ();
2107 if (! out) 2118 if (! out)
2108 return to; 2119 return to;
2109 if (out->allocated < out->used + len) 2120 if (out->allocated < out->used + len)
@@ -2141,11 +2152,15 @@ ftfont_drive_otf (MFLTFont *font, MFLTOtfSpec *spec, MFLTGlyphString *in,
2141 if (len == 0) 2152 if (len == 0)
2142 return from; 2153 return from;
2143 OTF_tag_name (spec->script, script); 2154 OTF_tag_name (spec->script, script);
2155
2156 char langsysbuf[5];
2144 if (spec->langsys) 2157 if (spec->langsys)
2145 { 2158 {
2146 langsys = alloca (5); 2159 langsys = langsysbuf;
2147 OTF_tag_name (spec->langsys, langsys); 2160 OTF_tag_name (spec->langsys, langsys);
2148 } 2161 }
2162
2163 USE_SAFE_ALLOCA;
2149 for (i = 0; i < 2; i++) 2164 for (i = 0; i < 2; i++)
2150 { 2165 {
2151 char *p; 2166 char *p;
@@ -2153,10 +2168,11 @@ ftfont_drive_otf (MFLTFont *font, MFLTOtfSpec *spec, MFLTGlyphString *in,
2153 if (spec->features[i] && spec->features[i][1] != 0xFFFFFFFF) 2168 if (spec->features[i] && spec->features[i][1] != 0xFFFFFFFF)
2154 { 2169 {
2155 for (j = 0; spec->features[i][j]; j++); 2170 for (j = 0; spec->features[i][j]; j++);
2171 SAFE_NALLOCA (p, 6, j);
2156 if (i == 0) 2172 if (i == 0)
2157 p = gsub_features = alloca (6 * j); 2173 gsub_features = p;
2158 else 2174 else
2159 p = gpos_features = alloca (6 * j); 2175 gpos_features = p;
2160 for (j = 0; spec->features[i][j]; j++) 2176 for (j = 0; spec->features[i][j]; j++)
2161 { 2177 {
2162 if (spec->features[i][j] == 0xFFFFFFFF) 2178 if (spec->features[i][j] == 0xFFFFFFFF)
@@ -2188,7 +2204,10 @@ ftfont_drive_otf (MFLTFont *font, MFLTOtfSpec *spec, MFLTGlyphString *in,
2188 < 0) 2204 < 0)
2189 goto simple_copy; 2205 goto simple_copy;
2190 if (out->allocated < out->used + otf_gstring.used) 2206 if (out->allocated < out->used + otf_gstring.used)
2191 return -2; 2207 {
2208 SAFE_FREE ();
2209 return -2;
2210 }
2192 for (i = 0, otfg = otf_gstring.glyphs; i < otf_gstring.used; ) 2211 for (i = 0, otfg = otf_gstring.glyphs; i < otf_gstring.used; )
2193 { 2212 {
2194 MFLTGlyph *g; 2213 MFLTGlyph *g;
@@ -2239,7 +2258,10 @@ ftfont_drive_otf (MFLTFont *font, MFLTOtfSpec *spec, MFLTGlyphString *in,
2239 else 2258 else
2240 { 2259 {
2241 if (out->allocated < out->used + len) 2260 if (out->allocated < out->used + len)
2242 return -2; 2261 {
2262 SAFE_FREE ();
2263 return -2;
2264 }
2243 for (i = 0; i < len; i++) 2265 for (i = 0; i < len; i++)
2244 out->glyphs[out->used++] = in->glyphs[from + i]; 2266 out->glyphs[out->used++] = in->glyphs[from + i];
2245 } 2267 }
@@ -2251,7 +2273,10 @@ ftfont_drive_otf (MFLTFont *font, MFLTOtfSpec *spec, MFLTGlyphString *in,
2251 2273
2252 if (OTF_drive_gpos (otf, &otf_gstring, script, langsys, gpos_features) 2274 if (OTF_drive_gpos (otf, &otf_gstring, script, langsys, gpos_features)
2253 < 0) 2275 < 0)
2254 return to; 2276 {
2277 SAFE_FREE ();
2278 return to;
2279 }
2255 2280
2256 x_ppem = ft_face->size->metrics.x_ppem; 2281 x_ppem = ft_face->size->metrics.x_ppem;
2257 y_ppem = ft_face->size->metrics.y_ppem; 2282 y_ppem = ft_face->size->metrics.y_ppem;
@@ -2361,9 +2386,11 @@ ftfont_drive_otf (MFLTFont *font, MFLTOtfSpec *spec, MFLTGlyphString *in,
2361 base = g; 2386 base = g;
2362 } 2387 }
2363 } 2388 }
2389 SAFE_FREE ();
2364 return to; 2390 return to;
2365 2391
2366 simple_copy: 2392 simple_copy:
2393 SAFE_FREE ();
2367 if (out->allocated < out->used + len) 2394 if (out->allocated < out->used + len)
2368 return -2; 2395 return -2;
2369 font->get_metrics (font, in, from, to); 2396 font->get_metrics (font, in, from, to);