aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJason Rumney2008-04-08 13:52:21 +0000
committerJason Rumney2008-04-08 13:52:21 +0000
commit8f112d5210cf530f35c77172a4d44e12703be53a (patch)
treebf96336df00c4cd672cfbb8e78e960f146b37d1b /src
parent20e3d3f1cad9f6b6c69f04fb613a5d2ad2232566 (diff)
downloademacs-8f112d5210cf530f35c77172a4d44e12703be53a.tar.gz
emacs-8f112d5210cf530f35c77172a4d44e12703be53a.zip
(Qja, Qko, Qzh): New symbols.
(syms_of_w32font): Initialise them. (font_matches_spec): Use them to filter by language. (recompute_cached_metrics): Remove function. (compute_metrics, clear_cached_metrics): New functions. (w32font_encode_char): Use them to manage metric cache. (w32font_text_extents): Cache metrics for all glyphs on demand. Delay converting glyph indices to WORD until needed. (w32font_open_internal): Initialize metric cache to empty. (registry_to_w32_charset): Charset should always be a symbol. (fill_in_logfont, list_all_matching_fonts): Family should always be a symbol.
Diffstat (limited to 'src')
-rw-r--r--src/w32font.c285
1 files changed, 168 insertions, 117 deletions
diff --git a/src/w32font.c b/src/w32font.c
index 866b86e2287..6bd0376810c 100644
--- a/src/w32font.c
+++ b/src/w32font.c
@@ -59,6 +59,9 @@ extern Lisp_Object QCantialias, QCotf, QClanguage; /* defined in font.c */
59extern Lisp_Object Qnone; /* reuse from w32fns.c */ 59extern Lisp_Object Qnone; /* reuse from w32fns.c */
60static Lisp_Object Qstandard, Qsubpixel, Qnatural; 60static Lisp_Object Qstandard, Qsubpixel, Qnatural;
61 61
62/* languages */
63static Lisp_Object Qja, Qko, Qzh;
64
62/* scripts */ 65/* scripts */
63static Lisp_Object Qlatin, Qgreek, Qcoptic, Qcyrillic, Qarmenian, Qhebrew; 66static Lisp_Object Qlatin, Qgreek, Qcoptic, Qcyrillic, Qarmenian, Qhebrew;
64static Lisp_Object Qarabic, Qsyriac, Qnko, Qthaana, Qdevanagari, Qbengali; 67static Lisp_Object Qarabic, Qsyriac, Qnko, Qthaana, Qdevanagari, Qbengali;
@@ -82,18 +85,18 @@ static Lisp_Object Qphonetic;
82/* Font spacing symbols - defined in font.c. */ 85/* Font spacing symbols - defined in font.c. */
83extern Lisp_Object Qc, Qp, Qm; 86extern Lisp_Object Qc, Qp, Qm;
84 87
85static void fill_in_logfont P_ ((FRAME_PTR f, LOGFONT *logfont, 88static void fill_in_logfont P_ ((FRAME_PTR, LOGFONT *, Lisp_Object));
86 Lisp_Object font_spec));
87 89
88static BYTE w32_antialias_type P_ ((Lisp_Object type)); 90static BYTE w32_antialias_type P_ ((Lisp_Object));
89static Lisp_Object lispy_antialias_type P_ ((BYTE type)); 91static Lisp_Object lispy_antialias_type P_ ((BYTE));
90 92
91static Lisp_Object font_supported_scripts P_ ((FONTSIGNATURE * sig)); 93static Lisp_Object font_supported_scripts P_ ((FONTSIGNATURE *));
92static int w32font_full_name P_ ((LOGFONT * font, Lisp_Object font_obj, 94static int w32font_full_name P_ ((LOGFONT *, Lisp_Object, int, char *, int));
93 int pixel_size, char *name, int nbytes)); 95static void compute_metrics P_ ((HDC, struct w32font_info *, unsigned int,
94static void recompute_cached_metrics P_ ((HDC dc, struct w32font_info * font)); 96 struct w32_metric_cache *));
97static void clear_cached_metrics P_ ((struct w32font_info *));
95 98
96static Lisp_Object w32_registry P_ ((LONG w32_charset, DWORD font_type)); 99static Lisp_Object w32_registry P_ ((LONG, DWORD));
97 100
98/* EnumFontFamiliesEx callbacks. */ 101/* EnumFontFamiliesEx callbacks. */
99static int CALLBACK add_font_entity_to_list P_ ((ENUMLOGFONTEX *, 102static int CALLBACK add_font_entity_to_list P_ ((ENUMLOGFONTEX *,
@@ -126,10 +129,10 @@ struct font_callback_data
126 129
127/* Handles the problem that EnumFontFamiliesEx will not return all 130/* Handles the problem that EnumFontFamiliesEx will not return all
128 style variations if the font name is not specified. */ 131 style variations if the font name is not specified. */
129static void list_all_matching_fonts P_ ((struct font_callback_data *match)); 132static void list_all_matching_fonts P_ ((struct font_callback_data *));
130 133
131/* From old font code in w32fns.c */ 134/* From old font code in w32fns.c */
132char * w32_to_x_charset P_ ((int charset, char * matching)); 135char * w32_to_x_charset P_ ((int, char *));
133 136
134 137
135static int 138static int
@@ -336,7 +339,8 @@ w32font_encode_char (font, c)
336 /* Mark this font as not supporting glyph indices. This can happen 339 /* Mark this font as not supporting glyph indices. This can happen
337 on Windows9x, and maybe with non-Truetype fonts on NT etc. */ 340 on Windows9x, and maybe with non-Truetype fonts on NT etc. */
338 w32_font->glyph_idx = 0; 341 w32_font->glyph_idx = 0;
339 recompute_cached_metrics (dc, w32_font); 342 /* Clear metrics cache. */
343 clear_cached_metrics (w32_font);
340 344
341 return c; 345 return c;
342 } 346 }
@@ -359,24 +363,13 @@ w32font_text_extents (font, code, nglyphs, metrics)
359 HDC dc = NULL; 363 HDC dc = NULL;
360 struct frame * f; 364 struct frame * f;
361 int total_width = 0; 365 int total_width = 0;
362 WORD *wcode = alloca(nglyphs * sizeof (WORD)); 366 WORD *wcode = NULL;
363 SIZE size; 367 SIZE size;
364 368
365 /* TODO: Frames can come and go, and their fonts outlive them. So we
366 can't cache the frame in the font structure. Use selected_frame
367 until the API is updated to pass in a frame. */
368 f = XFRAME (selected_frame);
369
370 if (metrics) 369 if (metrics)
371 { 370 {
372 GLYPHMETRICS gm;
373 MAT2 transform;
374 struct w32font_info *w32_font = (struct w32font_info *) font; 371 struct w32font_info *w32_font = (struct w32font_info *) font;
375 372
376 /* Set transform to the identity matrix. */
377 bzero (&transform, sizeof (transform));
378 transform.eM11.value = 1;
379 transform.eM22.value = 1;
380 metrics->width = 0; 373 metrics->width = 0;
381 metrics->ascent = font->ascent; 374 metrics->ascent = font->ascent;
382 metrics->descent = font->descent; 375 metrics->descent = font->descent;
@@ -384,65 +377,67 @@ w32font_text_extents (font, code, nglyphs, metrics)
384 377
385 for (i = 0; i < nglyphs; i++) 378 for (i = 0; i < nglyphs; i++)
386 { 379 {
387 if (*(code + i) < 128) 380 struct w32_metric_cache *char_metric;
388 { 381 int block = *(code + i) / CACHE_BLOCKSIZE;
389 /* Use cached metrics for ASCII. */ 382 int pos_in_block = *(code + i) % CACHE_BLOCKSIZE;
390 struct font_metrics *char_metric 383
391 = &w32_font->ascii_metrics[*(code+i)]; 384 if (block >= w32_font->n_cache_blocks)
392 385 {
393 /* If we couldn't get metrics when caching, use fallback. */ 386 if (!w32_font->cached_metrics)
394 if (char_metric->width == 0) 387 w32_font->cached_metrics
395 break; 388 = xmalloc ((block + 1)
396 389 * sizeof (struct w32_cached_metric *));
397 metrics->lbearing = min (metrics->lbearing, 390 else
398 metrics->width + char_metric->lbearing); 391 w32_font->cached_metrics
399 metrics->rbearing = max (metrics->rbearing, 392 = xrealloc (w32_font->cached_metrics,
400 metrics->width + char_metric->rbearing); 393 (block + 1)
401 metrics->width += char_metric->width; 394 * sizeof (struct w32_cached_metric *));
402 } 395 bzero (w32_font->cached_metrics + w32_font->n_cache_blocks,
403 else 396 ((block + 1 - w32_font->n_cache_blocks)
404 { 397 * sizeof (struct w32_cached_metric *)));
405 if (dc == NULL) 398 w32_font->n_cache_blocks = block + 1;
406 { 399 }
400
401 if (!w32_font->cached_metrics[block])
402 {
403 w32_font->cached_metrics[block]
404 = xmalloc (CACHE_BLOCKSIZE * sizeof (struct font_metrics));
405 bzero (w32_font->cached_metrics[block],
406 CACHE_BLOCKSIZE * sizeof (struct font_metrics));
407 }
408
409 char_metric = w32_font->cached_metrics[block] + pos_in_block;
410
411 if (char_metric->status == W32METRIC_NO_ATTEMPT)
412 {
413 if (dc == NULL)
414 {
415 /* TODO: Frames can come and go, and their fonts
416 outlive them. So we can't cache the frame in the
417 font structure. Use selected_frame until the API
418 is updated to pass in a frame. */
419 f = XFRAME (selected_frame);
420
407 dc = get_frame_dc (f); 421 dc = get_frame_dc (f);
408 old_font = SelectObject (dc, ((W32FontStruct *) 422 old_font = SelectObject (dc, ((W32FontStruct *)
409 (font->font.font))->hfont); 423 (font->font.font))->hfont);
410 } 424 }
411 if (GetGlyphOutlineW (dc, *(code + i), 425 compute_metrics (dc, w32_font, *(code + i), char_metric);
412 GGO_METRICS 426 }
413 | w32_font->glyph_idx
414 ? GGO_GLYPH_INDEX : 0,
415 &gm, 0, NULL, &transform) != GDI_ERROR)
416 {
417 int new_val = metrics->width + gm.gmBlackBoxX
418 + gm.gmptGlyphOrigin.x;
419 metrics->rbearing = max (metrics->rbearing, new_val);
420 new_val = metrics->width + gm.gmptGlyphOrigin.x;
421 metrics->lbearing = min (metrics->lbearing, new_val);
422 metrics->width += gm.gmCellIncX;
423 }
424 else
425 {
426 if (w32_font->glyph_idx)
427 {
428 /* Disable glyph indexing for this font, as we can't
429 handle the metrics. Abort this run, our recovery
430 strategies rely on having unicode code points here.
431 This will cause a glitch in display, but in practice,
432 any problems should be caught when initialising the
433 metrics cache. */
434 w32_font->glyph_idx = 0;
435 recompute_cached_metrics (dc, w32_font);
436 SelectObject (dc, old_font);
437 release_frame_dc (f, dc);
438 return 0;
439 }
440 /* Rely on an estimate based on the overall font metrics. */
441 break;
442 }
443 }
444 }
445 427
428 if (char_metric->status == W32METRIC_SUCCESS)
429 {
430 metrics->lbearing = min (metrics->lbearing,
431 metrics->width + char_metric->lbearing);
432 metrics->rbearing = max (metrics->rbearing,
433 metrics->width + char_metric->rbearing);
434 metrics->width += char_metric->width;
435 }
436 else
437 /* If we couldn't get metrics for a char,
438 use alternative method. */
439 break;
440 }
446 /* If we got through everything, return. */ 441 /* If we got through everything, return. */
447 if (i == nglyphs) 442 if (i == nglyphs)
448 { 443 {
@@ -460,19 +455,27 @@ w32font_text_extents (font, code, nglyphs, metrics)
460 /* For non-truetype fonts, GetGlyphOutlineW is not supported, so 455 /* For non-truetype fonts, GetGlyphOutlineW is not supported, so
461 fallback on other methods that will at least give some of the metric 456 fallback on other methods that will at least give some of the metric
462 information. */ 457 information. */
463 for (i = 0; i < nglyphs; i++) 458 if (!wcode) {
464 { 459 wcode = alloca (nglyphs * sizeof (WORD));
465 if (code[i] < 0x10000) 460 for (i = 0; i < nglyphs; i++)
466 wcode[i] = code[i]; 461 {
467 else 462 if (code[i] < 0x10000)
468 { 463 wcode[i] = code[i];
469 /* TODO: Convert to surrogate, reallocating array if needed */ 464 else
470 wcode[i] = 0xffff; 465 {
471 } 466 /* TODO: Convert to surrogate, reallocating array if needed */
472 } 467 wcode[i] = 0xffff;
473 468 }
469 }
470 }
474 if (dc == NULL) 471 if (dc == NULL)
475 { 472 {
473 /* TODO: Frames can come and go, and their fonts outlive
474 them. So we can't cache the frame in the font structure. Use
475 selected_frame until the API is updated to pass in a
476 frame. */
477 f = XFRAME (selected_frame);
478
476 dc = get_frame_dc (f); 479 dc = get_frame_dc (f);
477 old_font = SelectObject (dc, ((W32FontStruct *) 480 old_font = SelectObject (dc, ((W32FontStruct *)
478 (font->font.font))->hfont); 481 (font->font.font))->hfont);
@@ -792,8 +795,8 @@ w32font_open_internal (f, font_entity, pixel_size, w32_font)
792 795
793 w32_font->glyph_idx = ETO_GLYPH_INDEX; 796 w32_font->glyph_idx = ETO_GLYPH_INDEX;
794 797
795 /* Cache ASCII metrics. */ 798 w32_font->cached_metrics = NULL;
796 recompute_cached_metrics (dc, w32_font); 799 w32_font->n_cache_blocks = 0;
797 800
798 SelectObject (dc, old_font); 801 SelectObject (dc, old_font);
799 release_frame_dc (f, dc); 802 release_frame_dc (f, dc);
@@ -1226,6 +1229,36 @@ font_matches_spec (type, font, spec, backend, logfont)
1226 return 0; 1229 return 0;
1227 } 1230 }
1228 } 1231 }
1232 else if (EQ (key, QClanguage) && SYMBOLP (val))
1233 {
1234 /* Just handle the CJK languages here, as the language
1235 parameter is used to select a font with appropriate
1236 glyphs in the cjk unified ideographs block. Other fonts
1237 support for a language can be solely determined by
1238 its character coverage. */
1239 if (EQ (val, Qja))
1240 {
1241 if (font->ntmTm.tmCharSet != SHIFTJIS_CHARSET)
1242 return 0;
1243 }
1244 else if (EQ (val, Qko))
1245 {
1246 if (font->ntmTm.tmCharSet != HANGUL_CHARSET
1247 && font->ntmTm.tmCharSet != JOHAB_CHARSET)
1248 return 0;
1249 }
1250 else if (EQ (val, Qzh))
1251 {
1252 if (font->ntmTm.tmCharSet != GB2312_CHARSET
1253 && font->ntmTm.tmCharSet != CHINESEBIG5_CHARSET)
1254 return 0;
1255 }
1256 else
1257 /* Any other language, we don't recognize it. Fontset
1258 spec should have a fallback, as some backends do
1259 not recognize language at all. */
1260 return 0;
1261 }
1229 else if (EQ (key, QCotf) && CONSP (val)) 1262 else if (EQ (key, QCotf) && CONSP (val))
1230 { 1263 {
1231 /* OTF features only supported by the uniscribe backend. */ 1264 /* OTF features only supported by the uniscribe backend. */
@@ -1345,8 +1378,6 @@ registry_to_w32_charset (charset)
1345 return ANSI_CHARSET; 1378 return ANSI_CHARSET;
1346 else if (SYMBOLP (charset)) 1379 else if (SYMBOLP (charset))
1347 return x_to_w32_charset (SDATA (SYMBOL_NAME (charset))); 1380 return x_to_w32_charset (SDATA (SYMBOL_NAME (charset)));
1348 else if (STRINGP (charset))
1349 return x_to_w32_charset (SDATA (charset));
1350 else 1381 else
1351 return DEFAULT_CHARSET; 1382 return DEFAULT_CHARSET;
1352} 1383}
@@ -1449,8 +1480,6 @@ fill_in_logfont (f, logfont, font_spec)
1449 user input. */ 1480 user input. */
1450 else if (SYMBOLP (tmp)) 1481 else if (SYMBOLP (tmp))
1451 strncpy (logfont->lfFaceName, SDATA (SYMBOL_NAME (tmp)), LF_FACESIZE); 1482 strncpy (logfont->lfFaceName, SDATA (SYMBOL_NAME (tmp)), LF_FACESIZE);
1452 else if (STRINGP (tmp))
1453 strncpy (logfont->lfFaceName, SDATA (tmp), LF_FACESIZE);
1454 } 1483 }
1455 1484
1456 tmp = AREF (font_spec, FONT_ADSTYLE_INDEX); 1485 tmp = AREF (font_spec, FONT_ADSTYLE_INDEX);
@@ -1550,10 +1579,10 @@ list_all_matching_fonts (match_data)
1550 families = CDR (families); 1579 families = CDR (families);
1551 if (NILP (family)) 1580 if (NILP (family))
1552 continue; 1581 continue;
1553 else if (STRINGP (family)) 1582 else if (SYMBOLP (family))
1554 name = SDATA (family);
1555 else
1556 name = SDATA (SYMBOL_NAME (family)); 1583 name = SDATA (SYMBOL_NAME (family));
1584 else
1585 continue;
1557 1586
1558 strncpy (match_data->pattern.lfFaceName, name, LF_FACESIZE); 1587 strncpy (match_data->pattern.lfFaceName, name, LF_FACESIZE);
1559 match_data->pattern.lfFaceName[LF_FACESIZE - 1] = '\0'; 1588 match_data->pattern.lfFaceName[LF_FACESIZE - 1] = '\0';
@@ -1807,38 +1836,55 @@ w32font_full_name (font, font_obj, pixel_size, name, nbytes)
1807} 1836}
1808 1837
1809 1838
1810static void 1839static void compute_metrics (dc, w32_font, code, metrics)
1811recompute_cached_metrics (dc, w32_font)
1812 HDC dc; 1840 HDC dc;
1813 struct w32font_info *w32_font; 1841 struct w32font_info *w32_font;
1842 unsigned int code;
1843 struct w32_metric_cache *metrics;
1814{ 1844{
1815 GLYPHMETRICS gm; 1845 GLYPHMETRICS gm;
1816 MAT2 transform; 1846 MAT2 transform;
1817 unsigned int i; 1847 unsigned int options = GGO_METRICS;
1848
1849 if (w32_font->glyph_idx)
1850 options |= GGO_GLYPH_INDEX;
1818 1851
1819 bzero (&transform, sizeof (transform)); 1852 bzero (&transform, sizeof (transform));
1820 transform.eM11.value = 1; 1853 transform.eM11.value = 1;
1821 transform.eM22.value = 1; 1854 transform.eM22.value = 1;
1822 1855
1823 for (i = 0; i < 128; i++) 1856 if (GetGlyphOutlineW (dc, code, options, &gm, 0, NULL, &transform)
1857 != GDI_ERROR)
1858 {
1859 metrics->lbearing = gm.gmptGlyphOrigin.x;
1860 metrics->rbearing = gm.gmptGlyphOrigin.x + gm.gmBlackBoxX;
1861 metrics->width = gm.gmCellIncX;
1862 metrics->status = W32METRIC_SUCCESS;
1863 }
1864 else
1824 { 1865 {
1825 struct font_metrics* char_metric = &w32_font->ascii_metrics[i];
1826 unsigned int options = GGO_METRICS;
1827 if (w32_font->glyph_idx) 1866 if (w32_font->glyph_idx)
1828 options |= GGO_GLYPH_INDEX; 1867 {
1829 1868 /* Can't use glyph indexes after all.
1830 if (GetGlyphOutlineW (dc, i, options, &gm, 0, NULL, &transform) 1869 Avoid it in future, and clear any metrics that were based on
1831 != GDI_ERROR) 1870 glyph indexes. */
1832 { 1871 w32_font->glyph_idx = 0;
1833 char_metric->lbearing = gm.gmptGlyphOrigin.x; 1872 clear_cached_metrics (w32_font);
1834 char_metric->rbearing = gm.gmBlackBoxX + gm.gmptGlyphOrigin.x; 1873 }
1835 char_metric->width = gm.gmCellIncX; 1874 metrics->status = W32METRIC_FAIL;
1836 }
1837 else
1838 char_metric->width = 0;
1839 } 1875 }
1840} 1876}
1841 1877
1878static void
1879clear_cached_metrics (w32_font)
1880 struct w32font_info *w32_font;
1881{
1882 int i;
1883 for (i = 0; i < w32_font->n_cache_blocks; i++)
1884 bzero (w32_font->cached_metrics[i],
1885 CACHE_BLOCKSIZE * sizeof (struct font_metrics));
1886}
1887
1842struct font_driver w32font_driver = 1888struct font_driver w32font_driver =
1843 { 1889 {
1844 0, /* Qgdi */ 1890 0, /* Qgdi */
@@ -1898,6 +1944,11 @@ syms_of_w32font ()
1898 DEFSYM (Qsubpixel, "subpixel"); 1944 DEFSYM (Qsubpixel, "subpixel");
1899 DEFSYM (Qnatural, "natural"); 1945 DEFSYM (Qnatural, "natural");
1900 1946
1947 /* Languages */
1948 DEFSYM (Qja, "ja");
1949 DEFSYM (Qko, "ko");
1950 DEFSYM (Qzh, "zh");
1951
1901 /* Scripts */ 1952 /* Scripts */
1902 DEFSYM (Qlatin, "latin"); 1953 DEFSYM (Qlatin, "latin");
1903 DEFSYM (Qgreek, "greek"); 1954 DEFSYM (Qgreek, "greek");