comparison src/w32font.c @ 101518:280a537a4f06

(w32font_list_internal): Return quickly if registry is unknown. Simplify final return. (add_font_entity_to_list): Break complex logic down into more manageable chunks. Move unknown registry check to w32font_list_internal.
author Jason Rumney <jasonr@gnu.org>
date Mon, 26 Jan 2009 14:31:29 +0000
parents 21dea33fa8fd
children a36cf7879fb6
comparison
equal deleted inserted replaced
101517:9f423e131117 101518:280a537a4f06
729 match_data.frame = frame; 729 match_data.frame = frame;
730 730
731 bzero (&match_data.pattern, sizeof (LOGFONT)); 731 bzero (&match_data.pattern, sizeof (LOGFONT));
732 fill_in_logfont (f, &match_data.pattern, font_spec); 732 fill_in_logfont (f, &match_data.pattern, font_spec);
733 733
734 /* If the charset is unrecognized, then we won't find a font, so don't
735 waste time looking for one. */
736 if (match_data.pattern.lfCharSet == DEFAULT_CHARSET)
737 {
738 Lisp_Object spec_charset = AREF (font_spec, FONT_REGISTRY_INDEX);
739 if (!NILP (spec_charset)
740 && !EQ (spec_charset, Qiso10646_1)
741 && !EQ (spec_charset, Qunicode_bmp)
742 && !EQ (spec_charset, Qunicode_sip)
743 && !EQ (spec_charset, Qunknown))
744 return Qnil;
745 }
746
734 match_data.opentype_only = opentype_only; 747 match_data.opentype_only = opentype_only;
735 if (opentype_only) 748 if (opentype_only)
736 match_data.pattern.lfOutPrecision = OUT_OUTLINE_PRECIS; 749 match_data.pattern.lfOutPrecision = OUT_OUTLINE_PRECIS;
737 750
738 if (match_data.pattern.lfFaceName[0] == '\0') 751 if (match_data.pattern.lfFaceName[0] == '\0')
749 (FONTENUMPROC) add_font_entity_to_list, 762 (FONTENUMPROC) add_font_entity_to_list,
750 (LPARAM) &match_data, 0); 763 (LPARAM) &match_data, 0);
751 release_frame_dc (f, dc); 764 release_frame_dc (f, dc);
752 } 765 }
753 766
754 return NILP (match_data.list) ? Qnil : match_data.list; 767 return match_data.list;
755 } 768 }
756 769
757 /* Internal implementation of w32font_match. 770 /* Internal implementation of w32font_match.
758 Additional parameter opentype_only restricts the returned fonts to 771 Additional parameter opentype_only restricts the returned fonts to
759 opentype fonts, which can be used with the Uniscribe backend. */ 772 opentype fonts, which can be used with the Uniscribe backend. */
1384 LPARAM lParam; 1397 LPARAM lParam;
1385 { 1398 {
1386 struct font_callback_data *match_data 1399 struct font_callback_data *match_data
1387 = (struct font_callback_data *) lParam; 1400 = (struct font_callback_data *) lParam;
1388 Lisp_Object backend = match_data->opentype_only ? Quniscribe : Qgdi; 1401 Lisp_Object backend = match_data->opentype_only ? Quniscribe : Qgdi;
1389 1402 Lisp_Object entity;
1390 if ((!match_data->opentype_only 1403
1391 || (((physical_font->ntmTm.ntmFlags & NTMFLAGS_OPENTYPE) 1404 int is_unicode = physical_font->ntmFontSig.fsUsb[3]
1392 || (font_type & TRUETYPE_FONTTYPE)) 1405 || physical_font->ntmFontSig.fsUsb[2]
1393 /* For the uniscribe backend, only consider fonts that claim 1406 || physical_font->ntmFontSig.fsUsb[1]
1394 to cover at least some part of Unicode. */ 1407 || physical_font->ntmFontSig.fsUsb[0] & 0x3fffffff;
1395 && (physical_font->ntmFontSig.fsUsb[3] 1408
1396 || physical_font->ntmFontSig.fsUsb[2] 1409 /* Skip non matching fonts. */
1397 || physical_font->ntmFontSig.fsUsb[1] 1410
1398 || (physical_font->ntmFontSig.fsUsb[0] & 0x3fffffff)))) 1411 /* For uniscribe backend, consider only truetype or opentype fonts
1399 && logfonts_match (&logical_font->elfLogFont, &match_data->pattern) 1412 that have some unicode coverage. */
1400 && font_matches_spec (font_type, physical_font, 1413 if (match_data->opentype_only
1401 match_data->orig_font_spec, backend, 1414 && ((!physical_font->ntmTm.ntmFlags & NTMFLAGS_OPENTYPE
1402 &logical_font->elfLogFont) 1415 && !(font_type & TRUETYPE_FONTTYPE))
1403 && w32font_coverage_ok (&physical_font->ntmFontSig, 1416 || !is_unicode))
1404 match_data->pattern.lfCharSet) 1417 return 1;
1405 /* Avoid substitutions involving raster fonts (eg Helv -> MS Sans Serif) 1418
1406 We limit this to raster fonts, because the test can catch some 1419 /* Ensure a match. */
1407 genuine fonts (eg the full name of DejaVu Sans Mono Light is actually 1420 if (!logfonts_match (&logical_font->elfLogFont, &match_data->pattern)
1408 DejaVu Sans Mono ExtraLight). Helvetica -> Arial substitution will 1421 || !font_matches_spec (font_type, physical_font,
1409 therefore get through this test. Since full names can be prefixed 1422 match_data->orig_font_spec, backend,
1410 by a foundry, we accept raster fonts if the font name is found 1423 &logical_font->elfLogFont)
1411 anywhere within the full name. */ 1424 || !w32font_coverage_ok (&physical_font->ntmFontSig,
1412 && (logical_font->elfLogFont.lfOutPrecision != OUT_STRING_PRECIS 1425 match_data->pattern.lfCharSet))
1413 || strstr (logical_font->elfFullName, 1426 return 1;
1414 logical_font->elfLogFont.lfFaceName)) 1427
1428 /* Avoid substitutions involving raster fonts (eg Helv -> MS Sans Serif)
1429 We limit this to raster fonts, because the test can catch some
1430 genuine fonts (eg the full name of DejaVu Sans Mono Light is actually
1431 DejaVu Sans Mono ExtraLight). Helvetica -> Arial substitution will
1432 therefore get through this test. Since full names can be prefixed
1433 by a foundry, we accept raster fonts if the font name is found
1434 anywhere within the full name. */
1435 if ((logical_font->elfLogFont.lfOutPrecision == OUT_STRING_PRECIS
1436 && strstr (logical_font->elfFullName,
1437 logical_font->elfLogFont.lfFaceName))
1415 /* Check for well known substitutions that mess things up in the 1438 /* Check for well known substitutions that mess things up in the
1416 presence of Type-1 fonts of the same name. */ 1439 presence of Type-1 fonts of the same name. */
1417 && (match_data->pattern.lfFaceName[0] 1440 || (match_data->pattern.lfFaceName[0]
1418 && check_face_name (&logical_font->elfLogFont, 1441 && !check_face_name (&logical_font->elfLogFont,
1419 logical_font->elfFullName))) 1442 logical_font->elfFullName)))
1420 { 1443 return 1;
1421 Lisp_Object entity 1444
1422 = w32_enumfont_pattern_entity (match_data->frame, logical_font, 1445 /* Make a font entity for the font. */
1423 physical_font, font_type, 1446 entity = w32_enumfont_pattern_entity (match_data->frame, logical_font,
1424 &match_data->pattern, 1447 physical_font, font_type,
1425 backend); 1448 &match_data->pattern,
1426 if (!NILP (entity)) 1449 backend);
1427 { 1450
1428 Lisp_Object spec_charset = AREF (match_data->orig_font_spec, 1451 if (!NILP (entity))
1429 FONT_REGISTRY_INDEX); 1452 {
1430 1453 Lisp_Object spec_charset = AREF (match_data->orig_font_spec,
1431 /* If registry was specified as iso10646-1, only report 1454 FONT_REGISTRY_INDEX);
1432 ANSI and DEFAULT charsets, as most unicode fonts will 1455
1433 contain one of those plus others. */ 1456 /* iso10646-1 fonts must contain unicode mapping tables. */
1434 if ((EQ (spec_charset, Qiso10646_1) 1457 if (EQ (spec_charset, Qiso10646_1))
1435 || EQ (spec_charset, Qunicode_bmp)) 1458 {
1436 && logical_font->elfLogFont.lfCharSet != DEFAULT_CHARSET 1459 if (!is_unicode)
1437 && logical_font->elfLogFont.lfCharSet != ANSI_CHARSET)
1438 return 1;
1439 /* unicode-sip fonts must contain characters beyond the BMP,
1440 so look for bit 57 (surrogates) in the Unicode subranges. */
1441 else if (EQ (spec_charset, Qunicode_sip)
1442 && (!(physical_font->ntmFontSig.fsUsb[1] & 0x02000000)
1443 || !(physical_font->ntmFontSig.fsUsb[1] & 0x28000000)))
1444 return 1; 1460 return 1;
1445 /* If registry was specified, but did not map to a windows 1461 }
1446 charset, don't report any fonts. */ 1462 /* unicode-bmp fonts must contain characters from the BMP. */
1447 else if (!NILP (spec_charset) 1463 else if (EQ (spec_charset, Qunicode_bmp))
1448 && !EQ (spec_charset, Qiso10646_1) 1464 {
1449 && !EQ (spec_charset, Qunicode_bmp) 1465 if (!physical_font->ntmFontSig.fsUsb[3]
1450 && !EQ (spec_charset, Qunicode_sip) 1466 && !(physical_font->ntmFontSig.fsUsb[2] & 0xFFFFFF9E)
1451 && match_data->pattern.lfCharSet == DEFAULT_CHARSET) 1467 && !(physical_font->ntmFontSig.fsUsb[1] & 0xE81FFFFF)
1452 return 0; 1468 && !(physical_font->ntmFontSig.fsUsb[0] & 0x007F001F))
1453 1469 return 1;
1454 /* If registry was specified, ensure it is reported as the same. */ 1470 }
1455 if (!NILP (spec_charset)) 1471 /* unicode-sip fonts must contain characters in unicode plane 2.
1456 ASET (entity, FONT_REGISTRY_INDEX, spec_charset); 1472 so look for bit 57 (surrogates) in the Unicode subranges, plus
1457 1473 the bits for CJK ranges that include those characters. */
1458 match_data->list = Fcons (entity, match_data->list); 1474 else if (EQ (spec_charset, Qunicode_sip))
1459 1475 {
1460 /* If no registry specified, duplicate iso8859-1 truetype fonts 1476 if (!physical_font->ntmFontSig.fsUsb[1] & 0x02000000
1461 as iso10646-1. */ 1477 || !physical_font->ntmFontSig.fsUsb[1] & 0x28000000)
1462 if (NILP (spec_charset) 1478 return 1;
1463 && font_type == TRUETYPE_FONTTYPE 1479 }
1464 && logical_font->elfLogFont.lfCharSet == ANSI_CHARSET) 1480
1465 { 1481 /* This font matches. */
1466 Lisp_Object tem = Fcopy_font_spec (entity); 1482
1467 ASET (tem, FONT_REGISTRY_INDEX, Qiso10646_1); 1483 /* If registry was specified, ensure it is reported as the same. */
1468 match_data->list = Fcons (tem, match_data->list); 1484 if (!NILP (spec_charset))
1469 } 1485 ASET (entity, FONT_REGISTRY_INDEX, spec_charset);
1470 } 1486
1487 /* Otherwise if using the uniscribe backend, report ANSI and DEFAULT
1488 fonts as unicode and skip other charsets. */
1489 else if (match_data->opentype_only)
1490 {
1491 if (logical_font->elfLogFont.lfCharSet == ANSI_CHARSET
1492 || logical_font->elfLogFont.lfCharSet == DEFAULT_CHARSET)
1493 ASET (entity, FONT_REGISTRY_INDEX, Qiso10646_1);
1494 else
1495 return 1;
1496 }
1497
1498 /* Add this font to the list. */
1499 match_data->list = Fcons (entity, match_data->list);
1471 } 1500 }
1472 return 1; 1501 return 1;
1473 } 1502 }
1474 1503
1475 /* Callback function for EnumFontFamiliesEx. 1504 /* Callback function for EnumFontFamiliesEx.