aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/ftfont.c179
1 files changed, 93 insertions, 86 deletions
diff --git a/src/ftfont.c b/src/ftfont.c
index f2fa877c554..8b0bb06a886 100644
--- a/src/ftfont.c
+++ b/src/ftfont.c
@@ -44,7 +44,7 @@ Lisp_Object Qfreetype;
44static Lisp_Object Qmonospace, Qsans_serif, Qserif, Qmono, Qsans, Qsans__serif; 44static Lisp_Object Qmonospace, Qsans_serif, Qserif, Qmono, Qsans, Qsans__serif;
45 45
46/* Special ADSTYLE properties to avoid fonts used for Latin characters. */ 46/* Special ADSTYLE properties to avoid fonts used for Latin characters. */
47static Lisp_Object Qja, Qko; 47Lisp_Object Qja, Qko;
48 48
49/* Flag to tell if FcInit is already called or not. */ 49/* Flag to tell if FcInit is already called or not. */
50static int fc_initialized; 50static int fc_initialized;
@@ -74,11 +74,19 @@ struct ftfont_info
74 int index; 74 int index;
75}; 75};
76 76
77enum ftfont_cache_for
78 {
79 FTFONT_CACHE_FOR_FACE,
80 FTFONT_CACHE_FOR_CHARSET,
81 FTFONT_CACHE_FOR_ENTITY
82 };
83
77static Lisp_Object ftfont_pattern_entity P_ ((FcPattern *, Lisp_Object)); 84static Lisp_Object ftfont_pattern_entity P_ ((FcPattern *, Lisp_Object));
78 85
79static Lisp_Object ftfont_resolve_generic_family P_ ((Lisp_Object, 86static Lisp_Object ftfont_resolve_generic_family P_ ((Lisp_Object,
80 FcPattern *)); 87 FcPattern *));
81static Lisp_Object ftfont_lookup_cache P_ ((Lisp_Object, int)); 88static Lisp_Object ftfont_lookup_cache P_ ((Lisp_Object,
89 enum ftfont_cache_for));
82 90
83Lisp_Object ftfont_font_format P_ ((FcPattern *, Lisp_Object)); 91Lisp_Object ftfont_font_format P_ ((FcPattern *, Lisp_Object));
84 92
@@ -95,7 +103,7 @@ static struct
95 /* set on demand */ 103 /* set on demand */
96 FcCharSet *fc_charset; 104 FcCharSet *fc_charset;
97} fc_charset_table[] = 105} fc_charset_table[] =
98 { { "iso8859-1", { } }, /* ftfont_get_latin1_charset handles it. */ 106 { { "iso8859-1", { 0x00A0, 0x00A1, 0x00B4, 0x00BC, 0x00D0 } },
99 { "iso8859-2", { 0x00A0, 0x010E }}, 107 { "iso8859-2", { 0x00A0, 0x010E }},
100 { "iso8859-3", { 0x00A0, 0x0108 }}, 108 { "iso8859-3", { 0x00A0, 0x0108 }},
101 { "iso8859-4", { 0x00A0, 0x00AF, 0x0128, 0x0156, 0x02C7 }}, 109 { "iso8859-4", { 0x00A0, 0x00AF, 0x0128, 0x0156, 0x02C7 }},
@@ -135,29 +143,6 @@ static struct
135 { NULL } 143 { NULL }
136 }; 144 };
137 145
138/* Return a FcCharSet for iso8859-1 from fc_charset_table[0]. If the
139 charset is not yet ready, create it. */
140static FcCharSet *
141ftfont_get_latin1_charset ()
142{
143 FcCharSet *cs;
144 FcChar32 c;
145
146 if (fc_charset_table[0].fc_charset)
147 return fc_charset_table[0].fc_charset;
148 cs = FcCharSetCreate ();
149 if (! cs)
150 return NULL;
151 for (c = 33; c <= 0xFF; c++)
152 {
153 FcCharSetAddChar (cs, c);
154 if (c == 0x7E)
155 c = 0xA0;
156 }
157 fc_charset_table[0].fc_charset = cs;
158 return cs;
159}
160
161extern Lisp_Object Qc, Qm, Qp, Qd; 146extern Lisp_Object Qc, Qm, Qp, Qd;
162 147
163/* Dirty hack for handing ADSTYLE property. 148/* Dirty hack for handing ADSTYLE property.
@@ -206,7 +191,7 @@ ftfont_pattern_entity (p, extra)
206 FcPattern *p; 191 FcPattern *p;
207 Lisp_Object extra; 192 Lisp_Object extra;
208{ 193{
209 Lisp_Object entity; 194 Lisp_Object key, cache, entity;
210 char *file, *str; 195 char *file, *str;
211 int index; 196 int index;
212 int numeric; 197 int numeric;
@@ -218,7 +203,14 @@ ftfont_pattern_entity (p, extra)
218 if (FcPatternGetInteger (p, FC_INDEX, 0, &index) != FcResultMatch) 203 if (FcPatternGetInteger (p, FC_INDEX, 0, &index) != FcResultMatch)
219 return Qnil; 204 return Qnil;
220 205
206 key = Fcons (make_unibyte_string ((char *) file, strlen ((char *) file)),
207 make_number (index));
208 cache = ftfont_lookup_cache (key, FTFONT_CACHE_FOR_ENTITY);
209 entity = XCAR (cache);
210 if (! NILP (entity))
211 return entity;
221 entity = font_make_entity (); 212 entity = font_make_entity ();
213 XSETCAR (cache, entity);
222 214
223 ASET (entity, FONT_TYPE_INDEX, Qfreetype); 215 ASET (entity, FONT_TYPE_INDEX, Qfreetype);
224 ASET (entity, FONT_REGISTRY_INDEX, Qiso10646_1); 216 ASET (entity, FONT_REGISTRY_INDEX, Qiso10646_1);
@@ -244,12 +236,7 @@ ftfont_pattern_entity (p, extra)
244 } 236 }
245 if (FcPatternGetDouble (p, FC_PIXEL_SIZE, 0, &dbl) == FcResultMatch) 237 if (FcPatternGetDouble (p, FC_PIXEL_SIZE, 0, &dbl) == FcResultMatch)
246 { 238 {
247 Lisp_Object adstyle;
248
249 ASET (entity, FONT_SIZE_INDEX, make_number (dbl)); 239 ASET (entity, FONT_SIZE_INDEX, make_number (dbl));
250 /* As this font has PIXEL_SIZE property, parhaps this is a BDF
251 or PCF font. */
252 ASET (entity, FONT_ADSTYLE_INDEX, get_adstyle_property (p));
253 } 240 }
254 else 241 else
255 ASET (entity, FONT_SIZE_INDEX, make_number (0)); 242 ASET (entity, FONT_SIZE_INDEX, make_number (0));
@@ -262,13 +249,31 @@ ftfont_pattern_entity (p, extra)
262 } 249 }
263 if (FcPatternGetBool (p, FC_SCALABLE, 0, &b) == FcResultMatch 250 if (FcPatternGetBool (p, FC_SCALABLE, 0, &b) == FcResultMatch
264 && b == FcTrue) 251 && b == FcTrue)
265 ASET (entity, FONT_AVGWIDTH_INDEX, make_number (0)); 252 {
253 ASET (entity, FONT_SIZE_INDEX, make_number (0));
254 ASET (entity, FONT_AVGWIDTH_INDEX, make_number (0));
255 }
256 else
257 {
258 /* As this font is not scalable, parhaps this is a BDF or PCF
259 font. */
260 FT_Face ft_face;
261
262 ASET (entity, FONT_ADSTYLE_INDEX, get_adstyle_property (p));
263 if ((ft_library || FT_Init_FreeType (&ft_library) == 0)
264 && FT_New_Face (ft_library, file, index, &ft_face) == 0)
265 {
266 BDF_PropertyRec rec;
267
268 if (FT_Get_BDF_Property (ft_face, "AVERAGE_WIDTH", &rec) == 0
269 && rec.type == BDF_PROPERTY_TYPE_INTEGER)
270 ASET (entity, FONT_AVGWIDTH_INDEX, make_number (rec.u.integer));
271 FT_Done_Face (ft_face);
272 }
273 }
266 274
267 ASET (entity, FONT_EXTRA_INDEX, Fcopy_sequence (extra)); 275 ASET (entity, FONT_EXTRA_INDEX, Fcopy_sequence (extra));
268 font_put_extra (entity, QCfont_entity, 276 font_put_extra (entity, QCfont_entity, key);
269 Fcons (make_unibyte_string ((char *) file,
270 strlen ((char *) file)),
271 make_number (index)));
272 return entity; 277 return entity;
273} 278}
274 279
@@ -335,9 +340,9 @@ struct ftfont_cache_data
335}; 340};
336 341
337static Lisp_Object 342static Lisp_Object
338ftfont_lookup_cache (key, for_face) 343ftfont_lookup_cache (key, cache_for)
339 Lisp_Object key; 344 Lisp_Object key;
340 int for_face; 345 enum ftfont_cache_for cache_for;
341{ 346{
342 Lisp_Object cache, val, entity; 347 Lisp_Object cache, val, entity;
343 struct ftfont_cache_data *cache_data; 348 struct ftfont_cache_data *cache_data;
@@ -352,29 +357,45 @@ ftfont_lookup_cache (key, for_face)
352 else 357 else
353 entity = Qnil; 358 entity = Qnil;
354 359
355 cache = assoc_no_quit (key, ft_face_cache); 360 if (NILP (ft_face_cache))
361 cache = Qnil;
362 else
363 cache = Fgethash (key, ft_face_cache, Qnil);
356 if (NILP (cache)) 364 if (NILP (cache))
357 { 365 {
366 if (NILP (ft_face_cache))
367 {
368 Lisp_Object args[2];
369
370 args[0] = QCtest;
371 args[1] = Qequal;
372 ft_face_cache = Fmake_hash_table (2, args);
373 }
358 cache_data = xmalloc (sizeof (struct ftfont_cache_data)); 374 cache_data = xmalloc (sizeof (struct ftfont_cache_data));
359 cache_data->ft_face = NULL; 375 cache_data->ft_face = NULL;
360 cache_data->fc_charset = NULL; 376 cache_data->fc_charset = NULL;
361 val = make_save_value (NULL, 0); 377 val = make_save_value (NULL, 0);
362 XSAVE_VALUE (val)->integer = 0; 378 XSAVE_VALUE (val)->integer = 0;
363 XSAVE_VALUE (val)->pointer = cache_data; 379 XSAVE_VALUE (val)->pointer = cache_data;
364 cache = Fcons (key, val); 380 cache = Fcons (Qnil, val);
365 ft_face_cache = Fcons (cache, ft_face_cache); 381 Fputhash (key, cache, ft_face_cache);
366 } 382 }
367 else 383 else
368 { 384 {
369 val = XCDR (cache); 385 val = XCDR (cache);
370 cache_data = XSAVE_VALUE (val)->pointer; 386 cache_data = XSAVE_VALUE (val)->pointer;
371 } 387 }
372 if (for_face ? ! cache_data->ft_face : ! cache_data->fc_charset) 388
389 if (cache_for == FTFONT_CACHE_FOR_ENTITY)
390 return cache;
391
392 if (cache_for == FTFONT_CACHE_FOR_FACE
393 ? ! cache_data->ft_face : ! cache_data->fc_charset)
373 { 394 {
374 char *filename = (char *) SDATA (XCAR (key)); 395 char *filename = (char *) SDATA (XCAR (key));
375 int index = XINT (XCDR (key)); 396 int index = XINT (XCDR (key));
376 397
377 if (for_face) 398 if (cache_for == FTFONT_CACHE_FOR_FACE)
378 { 399 {
379 if (! ft_library 400 if (! ft_library
380 && FT_Init_FreeType (&ft_library) != 0) 401 && FT_Init_FreeType (&ft_library) != 0)
@@ -400,31 +421,11 @@ ftfont_lookup_cache (key, for_face)
400 fontset = FcFontList (NULL, pat, objset); 421 fontset = FcFontList (NULL, pat, objset);
401 if (! fontset) 422 if (! fontset)
402 goto finish; 423 goto finish;
403 if (fontset && fontset->nfont > 0) 424 if (fontset && fontset->nfont > 0
404 { 425 && (FcPatternGetCharSet (fontset->fonts[0], FC_CHARSET, 0,
405 if (FcPatternGetCharSet (fontset->fonts[0], FC_CHARSET, 0,
406 &charset) 426 &charset)
407 == FcResultMatch) 427 == FcResultMatch))
408 { 428 cache_data->fc_charset = FcCharSetCopy (charset);
409 /* Dirty hack. Fonts of "ja" and "ko" adstyle are
410 not suitable for Latin characters. */
411 if (! NILP (entity)
412 && (EQ (AREF (entity, FONT_ADSTYLE_INDEX), Qja)
413 || EQ (AREF (entity, FONT_ADSTYLE_INDEX), Qko)))
414 {
415 FcCharSet *latin1 = ftfont_get_latin1_charset ();
416
417 if (! latin1)
418 goto finish;
419 cache_data->fc_charset = FcCharSetSubtract (charset,
420 latin1);
421 }
422 else
423 cache_data->fc_charset = FcCharSetCopy (charset);
424 }
425 else
426 cache_data->fc_charset = FcCharSetCreate ();
427 }
428 else 429 else
429 cache_data->fc_charset = FcCharSetCreate (); 430 cache_data->fc_charset = FcCharSetCreate ();
430 431
@@ -447,7 +448,7 @@ ftfont_get_fc_charset (entity)
447 Lisp_Object val, cache; 448 Lisp_Object val, cache;
448 struct ftfont_cache_data *cache_data; 449 struct ftfont_cache_data *cache_data;
449 450
450 cache = ftfont_lookup_cache (entity, 0); 451 cache = ftfont_lookup_cache (entity, FTFONT_CACHE_FOR_CHARSET);
451 val = XCDR (cache); 452 val = XCDR (cache);
452 cache_data = XSAVE_VALUE (val)->pointer; 453 cache_data = XSAVE_VALUE (val)->pointer;
453 return cache_data->fc_charset; 454 return cache_data->fc_charset;
@@ -582,23 +583,18 @@ ftfont_get_charset (registry)
582 return -1; 583 return -1;
583 if (! fc_charset_table[i].fc_charset) 584 if (! fc_charset_table[i].fc_charset)
584 { 585 {
585 if (i == 0) 586 FcCharSet *charset = FcCharSetCreate ();
586 ftfont_get_latin1_charset (); 587 int *uniquifier = fc_charset_table[i].uniquifier;
587 else
588 {
589 FcCharSet *charset = FcCharSetCreate ();
590 int *uniquifier = fc_charset_table[i].uniquifier;
591 588
592 if (! charset) 589 if (! charset)
590 return -1;
591 for (j = 0; uniquifier[j]; j++)
592 if (! FcCharSetAddChar (charset, uniquifier[j]))
593 {
594 FcCharSetDestroy (charset);
593 return -1; 595 return -1;
594 for (j = 0; uniquifier[j]; j++) 596 }
595 if (! FcCharSetAddChar (charset, uniquifier[j])) 597 fc_charset_table[i].fc_charset = charset;
596 {
597 FcCharSetDestroy (charset);
598 return -1;
599 }
600 fc_charset_table[i].fc_charset = charset;
601 }
602 } 598 }
603 return i; 599 return i;
604} 600}
@@ -1170,7 +1166,7 @@ ftfont_open (f, entity, pixel_size)
1170 if (! CONSP (val)) 1166 if (! CONSP (val))
1171 return Qnil; 1167 return Qnil;
1172 val = XCDR (val); 1168 val = XCDR (val);
1173 cache = ftfont_lookup_cache (entity, 1); 1169 cache = ftfont_lookup_cache (entity, FTFONT_CACHE_FOR_FACE);
1174 if (NILP (cache)) 1170 if (NILP (cache))
1175 return Qnil; 1171 return Qnil;
1176 filename = XCAR (val); 1172 filename = XCAR (val);
@@ -1297,7 +1293,7 @@ ftfont_close (f, font)
1297 Lisp_Object val, cache; 1293 Lisp_Object val, cache;
1298 1294
1299 val = Fcons (font->props[FONT_FILE_INDEX], make_number (ftfont_info->index)); 1295 val = Fcons (font->props[FONT_FILE_INDEX], make_number (ftfont_info->index));
1300 cache = ftfont_lookup_cache (val, 1); 1296 cache = ftfont_lookup_cache (val, FTFONT_CACHE_FOR_FACE);
1301 xassert (CONSP (cache)); 1297 xassert (CONSP (cache));
1302 val = XCDR (cache); 1298 val = XCDR (cache);
1303 (XSAVE_VALUE (val)->integer)--; 1299 (XSAVE_VALUE (val)->integer)--;
@@ -1321,6 +1317,17 @@ ftfont_has_char (font, c)
1321 Lisp_Object font; 1317 Lisp_Object font;
1322 int c; 1318 int c;
1323{ 1319{
1320 struct charset *cs = NULL;
1321
1322 if (EQ (AREF (font, FONT_ADSTYLE_INDEX), Qja)
1323 && charset_jisx0208 >= 0)
1324 cs = CHARSET_FROM_ID (charset_jisx0208);
1325 else if (EQ (AREF (font, FONT_ADSTYLE_INDEX), Qko)
1326 && charset_ksc5601 >= 0)
1327 cs = CHARSET_FROM_ID (charset_ksc5601);
1328 if (cs)
1329 return (ENCODE_CHAR (cs, c) != CHARSET_INVALID_CODE (cs));
1330
1324 if (FONT_ENTITY_P (font)) 1331 if (FONT_ENTITY_P (font))
1325 { 1332 {
1326 FcCharSet *charset = ftfont_get_fc_charset (font); 1333 FcCharSet *charset = ftfont_get_fc_charset (font);