2 * Methods for dealing with opentype font tables
4 * Copyright 2014 Aric Stewart for CodeWeavers
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #define NONAMELESSUNION
24 #include "dwrite_private.h"
27 WINE_DEFAULT_DEBUG_CHANNEL(dwrite
);
29 #define MS_HEAD_TAG DWRITE_MAKE_OPENTYPE_TAG('h','e','a','d')
30 #define MS_HHEA_TAG DWRITE_MAKE_OPENTYPE_TAG('h','h','e','a')
31 #define MS_OTTO_TAG DWRITE_MAKE_OPENTYPE_TAG('O','T','T','O')
32 #define MS_OS2_TAG DWRITE_MAKE_OPENTYPE_TAG('O','S','/','2')
33 #define MS_POST_TAG DWRITE_MAKE_OPENTYPE_TAG('p','o','s','t')
34 #define MS_TTCF_TAG DWRITE_MAKE_OPENTYPE_TAG('t','t','c','f')
35 #define MS_GPOS_TAG DWRITE_MAKE_OPENTYPE_TAG('G','P','O','S')
36 #define MS_GSUB_TAG DWRITE_MAKE_OPENTYPE_TAG('G','S','U','B')
37 #define MS_NAME_TAG DWRITE_MAKE_OPENTYPE_TAG('n','a','m','e')
38 #define MS_GLYF_TAG DWRITE_MAKE_OPENTYPE_TAG('g','l','y','f')
39 #define MS_CFF__TAG DWRITE_MAKE_OPENTYPE_TAG('C','F','F',' ')
40 #define MS_CFF2_TAG DWRITE_MAKE_OPENTYPE_TAG('C','F','F','2')
41 #define MS_COLR_TAG DWRITE_MAKE_OPENTYPE_TAG('C','O','L','R')
42 #define MS_SVG__TAG DWRITE_MAKE_OPENTYPE_TAG('S','V','G',' ')
43 #define MS_SBIX_TAG DWRITE_MAKE_OPENTYPE_TAG('s','b','i','x')
44 #define MS_MAXP_TAG DWRITE_MAKE_OPENTYPE_TAG('m','a','x','p')
45 #define MS_CBLC_TAG DWRITE_MAKE_OPENTYPE_TAG('C','B','L','C')
48 #define MS_PNG__TAG DWRITE_MAKE_OPENTYPE_TAG('p','n','g',' ')
49 #define MS_JPG__TAG DWRITE_MAKE_OPENTYPE_TAG('j','p','g',' ')
50 #define MS_TIFF_TAG DWRITE_MAKE_OPENTYPE_TAG('t','i','f','f')
52 #define MS_WOFF_TAG DWRITE_MAKE_OPENTYPE_TAG('w','O','F','F')
53 #define MS_WOF2_TAG DWRITE_MAKE_OPENTYPE_TAG('w','O','F','2')
55 #ifdef WORDS_BIGENDIAN
56 #define GET_BE_WORD(x) (x)
57 #define GET_BE_DWORD(x) (x)
59 #define GET_BE_WORD(x) RtlUshortByteSwap(x)
60 #define GET_BE_DWORD(x) RtlUlongByteSwap(x)
89 } CMAP_EncodingRecord
;
94 CMAP_EncodingRecord tables
[1];
101 } CMAP_SegmentedCoverage_group
;
109 CMAP_SegmentedCoverage_group groups
[1];
110 } CMAP_SegmentedCoverage
;
121 } CMAP_SegmentMapping_0
;
123 enum OPENTYPE_CMAP_TABLE_FORMAT
125 OPENTYPE_CMAP_TABLE_SEGMENT_MAPPING
= 4,
126 OPENTYPE_CMAP_TABLE_SEGMENTED_COVERAGE
= 12
129 /* PANOSE is 10 bytes in size, need to pack the structure properly */
130 #include "pshpack2.h"
147 USHORT lowestRecPPEM
;
148 SHORT direction_hint
;
150 SHORT glyphdata_format
;
153 enum TT_HEAD_MACSTYLE
155 TT_HEAD_MACSTYLE_BOLD
= 1 << 0,
156 TT_HEAD_MACSTYLE_ITALIC
= 1 << 1,
157 TT_HEAD_MACSTYLE_UNDERLINE
= 1 << 2,
158 TT_HEAD_MACSTYLE_OUTLINE
= 1 << 3,
159 TT_HEAD_MACSTYLE_SHADOW
= 1 << 4,
160 TT_HEAD_MACSTYLE_CONDENSED
= 1 << 5,
161 TT_HEAD_MACSTYLE_EXTENDED
= 1 << 6,
168 SHORT underlinePosition
;
169 SHORT underlineThickness
;
181 USHORT usWeightClass
;
184 SHORT ySubscriptXSize
;
185 SHORT ySubscriptYSize
;
186 SHORT ySubscriptXOffset
;
187 SHORT ySubscriptYOffset
;
188 SHORT ySuperscriptXSize
;
189 SHORT ySuperscriptYSize
;
190 SHORT ySuperscriptXOffset
;
191 SHORT ySuperscriptYOffset
;
192 SHORT yStrikeoutSize
;
193 SHORT yStrikeoutPosition
;
196 ULONG ulUnicodeRange1
;
197 ULONG ulUnicodeRange2
;
198 ULONG ulUnicodeRange3
;
199 ULONG ulUnicodeRange4
;
202 USHORT usFirstCharIndex
;
203 USHORT usLastCharIndex
;
204 /* According to the Apple spec, original version didn't have the below fields,
205 * version numbers were taken from the OpenType spec.
207 /* version 0 (TrueType 1.5) */
208 USHORT sTypoAscender
;
209 USHORT sTypoDescender
;
213 /* version 1 (TrueType 1.66) */
214 ULONG ulCodePageRange1
;
215 ULONG ulCodePageRange2
;
216 /* version 2 (OpenType 1.2) */
219 USHORT usDefaultChar
;
230 USHORT advanceWidthMax
;
231 SHORT minLeftSideBearing
;
232 SHORT minRightSideBearing
;
234 SHORT caretSlopeRise
;
238 SHORT metricDataFormat
;
239 USHORT numberOfHMetrics
;
246 DWORD strikeOffset
[1];
252 DWORD glyphDataOffsets
[1];
278 DWORD indexSubTableArrayOffset
;
279 DWORD indexTablesSize
;
280 DWORD numberofIndexSubTables
;
282 sbitLineMetrics hori
;
283 sbitLineMetrics vert
;
284 WORD startGlyphIndex
;
290 } CBLCBitmapSizeTable
;
293 enum OS2_FSSELECTION
{
294 OS2_FSSELECTION_ITALIC
= 1 << 0,
295 OS2_FSSELECTION_UNDERSCORE
= 1 << 1,
296 OS2_FSSELECTION_NEGATIVE
= 1 << 2,
297 OS2_FSSELECTION_OUTLINED
= 1 << 3,
298 OS2_FSSELECTION_STRIKEOUT
= 1 << 4,
299 OS2_FSSELECTION_BOLD
= 1 << 5,
300 OS2_FSSELECTION_REGULAR
= 1 << 6,
301 OS2_FSSELECTION_USE_TYPO_METRICS
= 1 << 7,
302 OS2_FSSELECTION_WWS
= 1 << 8,
303 OS2_FSSELECTION_OBLIQUE
= 1 << 9
319 TT_NameRecord nameRecord
[1];
358 OT_FeatureRecord FeatureRecord
[1];
362 WORD LookupOrder
; /* Reserved */
363 WORD ReqFeatureIndex
;
365 WORD FeatureIndex
[1];
376 OT_LangSysRecord LangSysRecord
[1];
386 OT_ScriptRecord ScriptRecord
[1];
396 enum OPENTYPE_PLATFORM_ID
398 OPENTYPE_PLATFORM_UNICODE
= 0,
399 OPENTYPE_PLATFORM_MAC
,
400 OPENTYPE_PLATFORM_ISO
,
401 OPENTYPE_PLATFORM_WIN
,
402 OPENTYPE_PLATFORM_CUSTOM
408 WORD LookupListIndex
[1];
427 } GSUB_SingleSubstFormat1
;
434 } GSUB_SingleSubstFormat2
;
438 WORD ExtensionLookupType
;
439 DWORD ExtensionOffset
;
440 } GSUB_ExtensionPosFormat1
;
442 enum OPENTYPE_GPOS_LOOKUPS
444 OPENTYPE_GPOS_SINGLE_SUBST
= 1,
445 OPENTYPE_GPOS_EXTENSION_SUBST
= 7
448 enum TT_NAME_WINDOWS_ENCODING_ID
450 TT_NAME_WINDOWS_ENCODING_SYMBOL
= 0,
451 TT_NAME_WINDOWS_ENCODING_UCS2
,
452 TT_NAME_WINDOWS_ENCODING_SJIS
,
453 TT_NAME_WINDOWS_ENCODING_PRC
,
454 TT_NAME_WINDOWS_ENCODING_BIG5
,
455 TT_NAME_WINDOWS_ENCODING_WANSUNG
,
456 TT_NAME_WINDOWS_ENCODING_JOHAB
,
457 TT_NAME_WINDOWS_ENCODING_RESERVED1
,
458 TT_NAME_WINDOWS_ENCODING_RESERVED2
,
459 TT_NAME_WINDOWS_ENCODING_RESERVED3
,
460 TT_NAME_WINDOWS_ENCODING_UCS4
463 enum TT_NAME_MAC_ENCODING_ID
465 TT_NAME_MAC_ENCODING_ROMAN
= 0,
466 TT_NAME_MAC_ENCODING_JAPANESE
,
467 TT_NAME_MAC_ENCODING_TRAD_CHINESE
,
468 TT_NAME_MAC_ENCODING_KOREAN
,
469 TT_NAME_MAC_ENCODING_ARABIC
,
470 TT_NAME_MAC_ENCODING_HEBREW
,
471 TT_NAME_MAC_ENCODING_GREEK
,
472 TT_NAME_MAC_ENCODING_RUSSIAN
,
473 TT_NAME_MAC_ENCODING_RSYMBOL
,
474 TT_NAME_MAC_ENCODING_DEVANAGARI
,
475 TT_NAME_MAC_ENCODING_GURMUKHI
,
476 TT_NAME_MAC_ENCODING_GUJARATI
,
477 TT_NAME_MAC_ENCODING_ORIYA
,
478 TT_NAME_MAC_ENCODING_BENGALI
,
479 TT_NAME_MAC_ENCODING_TAMIL
,
480 TT_NAME_MAC_ENCODING_TELUGU
,
481 TT_NAME_MAC_ENCODING_KANNADA
,
482 TT_NAME_MAC_ENCODING_MALAYALAM
,
483 TT_NAME_MAC_ENCODING_SINHALESE
,
484 TT_NAME_MAC_ENCODING_BURMESE
,
485 TT_NAME_MAC_ENCODING_KHMER
,
486 TT_NAME_MAC_ENCODING_THAI
,
487 TT_NAME_MAC_ENCODING_LAOTIAN
,
488 TT_NAME_MAC_ENCODING_GEORGIAN
,
489 TT_NAME_MAC_ENCODING_ARMENIAN
,
490 TT_NAME_MAC_ENCODING_SIMPL_CHINESE
,
491 TT_NAME_MAC_ENCODING_TIBETAN
,
492 TT_NAME_MAC_ENCODING_MONGOLIAN
,
493 TT_NAME_MAC_ENCODING_GEEZ
,
494 TT_NAME_MAC_ENCODING_SLAVIC
,
495 TT_NAME_MAC_ENCODING_VIETNAMESE
,
496 TT_NAME_MAC_ENCODING_SINDHI
,
497 TT_NAME_MAC_ENCODING_UNINTERPRETED
500 enum TT_NAME_MAC_LANGUAGE_ID
502 TT_NAME_MAC_LANGID_ENGLISH
= 0,
503 TT_NAME_MAC_LANGID_FRENCH
,
504 TT_NAME_MAC_LANGID_GERMAN
,
505 TT_NAME_MAC_LANGID_ITALIAN
,
506 TT_NAME_MAC_LANGID_DUTCH
,
507 TT_NAME_MAC_LANGID_SWEDISH
,
508 TT_NAME_MAC_LANGID_SPANISH
,
509 TT_NAME_MAC_LANGID_DANISH
,
510 TT_NAME_MAC_LANGID_PORTUGUESE
,
511 TT_NAME_MAC_LANGID_NORWEGIAN
,
512 TT_NAME_MAC_LANGID_HEBREW
,
513 TT_NAME_MAC_LANGID_JAPANESE
,
514 TT_NAME_MAC_LANGID_ARABIC
,
515 TT_NAME_MAC_LANGID_FINNISH
,
516 TT_NAME_MAC_LANGID_GREEK
,
517 TT_NAME_MAC_LANGID_ICELANDIC
,
518 TT_NAME_MAC_LANGID_MALTESE
,
519 TT_NAME_MAC_LANGID_TURKISH
,
520 TT_NAME_MAC_LANGID_CROATIAN
,
521 TT_NAME_MAC_LANGID_TRAD_CHINESE
,
522 TT_NAME_MAC_LANGID_URDU
,
523 TT_NAME_MAC_LANGID_HINDI
,
524 TT_NAME_MAC_LANGID_THAI
,
525 TT_NAME_MAC_LANGID_KOREAN
,
526 TT_NAME_MAC_LANGID_LITHUANIAN
,
527 TT_NAME_MAC_LANGID_POLISH
,
528 TT_NAME_MAC_LANGID_HUNGARIAN
,
529 TT_NAME_MAC_LANGID_ESTONIAN
,
530 TT_NAME_MAC_LANGID_LATVIAN
,
531 TT_NAME_MAC_LANGID_SAMI
,
532 TT_NAME_MAC_LANGID_FAROESE
,
533 TT_NAME_MAC_LANGID_FARSI
,
534 TT_NAME_MAC_LANGID_RUSSIAN
,
535 TT_NAME_MAC_LANGID_SIMPL_CHINESE
,
536 TT_NAME_MAC_LANGID_FLEMISH
,
537 TT_NAME_MAC_LANGID_GAELIC
,
538 TT_NAME_MAC_LANGID_ALBANIAN
,
539 TT_NAME_MAC_LANGID_ROMANIAN
,
540 TT_NAME_MAC_LANGID_CZECH
,
541 TT_NAME_MAC_LANGID_SLOVAK
,
542 TT_NAME_MAC_LANGID_SLOVENIAN
,
543 TT_NAME_MAC_LANGID_YIDDISH
,
544 TT_NAME_MAC_LANGID_SERBIAN
,
545 TT_NAME_MAC_LANGID_MACEDONIAN
,
546 TT_NAME_MAC_LANGID_BULGARIAN
,
547 TT_NAME_MAC_LANGID_UKRAINIAN
,
548 TT_NAME_MAC_LANGID_BYELORUSSIAN
,
549 TT_NAME_MAC_LANGID_UZBEK
,
550 TT_NAME_MAC_LANGID_KAZAKH
,
551 TT_NAME_MAC_LANGID_AZERB_CYR
,
552 TT_NAME_MAC_LANGID_AZERB_ARABIC
,
553 TT_NAME_MAC_LANGID_ARMENIAN
,
554 TT_NAME_MAC_LANGID_GEORGIAN
,
555 TT_NAME_MAC_LANGID_MOLDAVIAN
,
556 TT_NAME_MAC_LANGID_KIRGHIZ
,
557 TT_NAME_MAC_LANGID_TAJIKI
,
558 TT_NAME_MAC_LANGID_TURKMEN
,
559 TT_NAME_MAC_LANGID_MONGOLIAN
,
560 TT_NAME_MAC_LANGID_MONGOLIAN_CYR
,
561 TT_NAME_MAC_LANGID_PASHTO
,
562 TT_NAME_MAC_LANGID_KURDISH
,
563 TT_NAME_MAC_LANGID_KASHMIRI
,
564 TT_NAME_MAC_LANGID_SINDHI
,
565 TT_NAME_MAC_LANGID_TIBETAN
,
566 TT_NAME_MAC_LANGID_NEPALI
,
567 TT_NAME_MAC_LANGID_SANSKRIT
,
568 TT_NAME_MAC_LANGID_MARATHI
,
569 TT_NAME_MAC_LANGID_BENGALI
,
570 TT_NAME_MAC_LANGID_ASSAMESE
,
571 TT_NAME_MAC_LANGID_GUJARATI
,
572 TT_NAME_MAC_LANGID_PUNJABI
,
573 TT_NAME_MAC_LANGID_ORIYA
,
574 TT_NAME_MAC_LANGID_MALAYALAM
,
575 TT_NAME_MAC_LANGID_KANNADA
,
576 TT_NAME_MAC_LANGID_TAMIL
,
577 TT_NAME_MAC_LANGID_TELUGU
,
578 TT_NAME_MAC_LANGID_SINHALESE
,
579 TT_NAME_MAC_LANGID_BURMESE
,
580 TT_NAME_MAC_LANGID_KHMER
,
581 TT_NAME_MAC_LANGID_LAO
,
582 TT_NAME_MAC_LANGID_VIETNAMESE
,
583 TT_NAME_MAC_LANGID_INDONESIAN
,
584 TT_NAME_MAC_LANGID_TAGALOG
,
585 TT_NAME_MAC_LANGID_MALAY_ROMAN
,
586 TT_NAME_MAC_LANGID_MALAY_ARABIC
,
587 TT_NAME_MAC_LANGID_AMHARIC
,
588 TT_NAME_MAC_LANGID_TIGRINYA
,
589 TT_NAME_MAC_LANGID_GALLA
,
590 TT_NAME_MAC_LANGID_SOMALI
,
591 TT_NAME_MAC_LANGID_SWAHILI
,
592 TT_NAME_MAC_LANGID_KINYARWANDA
,
593 TT_NAME_MAC_LANGID_RUNDI
,
594 TT_NAME_MAC_LANGID_NYANJA
,
595 TT_NAME_MAC_LANGID_MALAGASY
,
596 TT_NAME_MAC_LANGID_ESPERANTO
,
597 TT_NAME_MAC_LANGID_WELSH
= 128,
598 TT_NAME_MAC_LANGID_BASQUE
,
599 TT_NAME_MAC_LANGID_CATALAN
,
600 TT_NAME_MAC_LANGID_LATIN
,
601 TT_NAME_MAC_LANGID_QUECHUA
,
602 TT_NAME_MAC_LANGID_GUARANI
,
603 TT_NAME_MAC_LANGID_AYMARA
,
604 TT_NAME_MAC_LANGID_TATAR
,
605 TT_NAME_MAC_LANGID_UIGHUR
,
606 TT_NAME_MAC_LANGID_DZONGKHA
,
607 TT_NAME_MAC_LANGID_JAVANESE
,
608 TT_NAME_MAC_LANGID_SUNDANESE
,
609 TT_NAME_MAC_LANGID_GALICIAN
,
610 TT_NAME_MAC_LANGID_AFRIKAANS
,
611 TT_NAME_MAC_LANGID_BRETON
,
612 TT_NAME_MAC_LANGID_INUKTITUT
,
613 TT_NAME_MAC_LANGID_SCOTTISH_GAELIC
,
614 TT_NAME_MAC_LANGID_MANX_GAELIC
,
615 TT_NAME_MAC_LANGID_IRISH_GAELIC
,
616 TT_NAME_MAC_LANGID_TONGAN
,
617 TT_NAME_MAC_LANGID_GREEK_POLYTONIC
,
618 TT_NAME_MAC_LANGID_GREENLANDIC
,
619 TT_NAME_MAC_LANGID_AZER_ROMAN
622 /* Names are indexed with TT_NAME_MAC_LANGUAGE_ID values */
623 static const char name_mac_langid_to_locale
[][10] = {
777 enum OPENTYPE_STRING_ID
779 OPENTYPE_STRING_COPYRIGHT_NOTICE
= 0,
780 OPENTYPE_STRING_FAMILY_NAME
,
781 OPENTYPE_STRING_SUBFAMILY_NAME
,
782 OPENTYPE_STRING_UNIQUE_IDENTIFIER
,
783 OPENTYPE_STRING_FULL_FONTNAME
,
784 OPENTYPE_STRING_VERSION_STRING
,
785 OPENTYPE_STRING_POSTSCRIPT_FONTNAME
,
786 OPENTYPE_STRING_TRADEMARK
,
787 OPENTYPE_STRING_MANUFACTURER
,
788 OPENTYPE_STRING_DESIGNER
,
789 OPENTYPE_STRING_DESCRIPTION
,
790 OPENTYPE_STRING_VENDOR_URL
,
791 OPENTYPE_STRING_DESIGNER_URL
,
792 OPENTYPE_STRING_LICENSE_DESCRIPTION
,
793 OPENTYPE_STRING_LICENSE_INFO_URL
,
794 OPENTYPE_STRING_RESERVED_ID15
,
795 OPENTYPE_STRING_PREFERRED_FAMILY_NAME
,
796 OPENTYPE_STRING_PREFERRED_SUBFAMILY_NAME
,
797 OPENTYPE_STRING_COMPATIBLE_FULLNAME
,
798 OPENTYPE_STRING_SAMPLE_TEXT
,
799 OPENTYPE_STRING_POSTSCRIPT_CID_NAME
,
800 OPENTYPE_STRING_WWS_FAMILY_NAME
,
801 OPENTYPE_STRING_WWS_SUBFAMILY_NAME
804 static const UINT16 dwriteid_to_opentypeid
[DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_CID_NAME
+1] =
806 (UINT16
)-1, /* DWRITE_INFORMATIONAL_STRING_NONE is not used */
807 OPENTYPE_STRING_COPYRIGHT_NOTICE
,
808 OPENTYPE_STRING_VERSION_STRING
,
809 OPENTYPE_STRING_TRADEMARK
,
810 OPENTYPE_STRING_MANUFACTURER
,
811 OPENTYPE_STRING_DESIGNER
,
812 OPENTYPE_STRING_DESIGNER_URL
,
813 OPENTYPE_STRING_DESCRIPTION
,
814 OPENTYPE_STRING_VENDOR_URL
,
815 OPENTYPE_STRING_LICENSE_DESCRIPTION
,
816 OPENTYPE_STRING_LICENSE_INFO_URL
,
817 OPENTYPE_STRING_FAMILY_NAME
,
818 OPENTYPE_STRING_SUBFAMILY_NAME
,
819 OPENTYPE_STRING_PREFERRED_FAMILY_NAME
,
820 OPENTYPE_STRING_PREFERRED_SUBFAMILY_NAME
,
821 OPENTYPE_STRING_SAMPLE_TEXT
,
822 OPENTYPE_STRING_FULL_FONTNAME
,
823 OPENTYPE_STRING_POSTSCRIPT_FONTNAME
,
824 OPENTYPE_STRING_POSTSCRIPT_CID_NAME
831 USHORT numPaletteEntries
;
833 USHORT numColorRecords
;
834 ULONG offsetFirstColorRecord
;
835 USHORT colorRecordIndices
[1];
838 /* for version == 1, this comes after full CPAL_Header_0 */
839 struct CPAL_SubHeader_1
841 ULONG offsetPaletteTypeArray
;
842 ULONG offsetPaletteLabelArray
;
843 ULONG offsetPaletteEntryLabelArray
;
846 struct CPAL_ColorRecord
858 USHORT numBaseGlyphRecords
;
859 ULONG offsetBaseGlyphRecord
;
860 ULONG offsetLayerRecord
;
861 USHORT numLayerRecords
;
864 struct COLR_BaseGlyphRecord
867 USHORT firstLayerIndex
;
871 struct COLR_LayerRecord
877 BOOL
is_face_type_supported(DWRITE_FONT_FACE_TYPE type
)
879 return (type
== DWRITE_FONT_FACE_TYPE_CFF
) ||
880 (type
== DWRITE_FONT_FACE_TYPE_TRUETYPE
) ||
881 (type
== DWRITE_FONT_FACE_TYPE_OPENTYPE_COLLECTION
) ||
882 (type
== DWRITE_FONT_FACE_TYPE_RAW_CFF
);
885 typedef HRESULT (*dwrite_fontfile_analyzer
)(IDWriteFontFileStream
*stream
, UINT32
*font_count
, DWRITE_FONT_FILE_TYPE
*file_type
,
886 DWRITE_FONT_FACE_TYPE
*face_type
);
888 static HRESULT
opentype_ttc_analyzer(IDWriteFontFileStream
*stream
, UINT32
*font_count
, DWRITE_FONT_FILE_TYPE
*file_type
,
889 DWRITE_FONT_FACE_TYPE
*face_type
)
891 static const DWORD ttctag
= MS_TTCF_TAG
;
892 const TTC_Header_V1
*header
;
896 hr
= IDWriteFontFileStream_ReadFileFragment(stream
, (const void**)&header
, 0, sizeof(header
), &context
);
900 if (!memcmp(header
->TTCTag
, &ttctag
, sizeof(ttctag
))) {
901 *font_count
= GET_BE_DWORD(header
->numFonts
);
902 *file_type
= DWRITE_FONT_FILE_TYPE_OPENTYPE_COLLECTION
;
903 *face_type
= DWRITE_FONT_FACE_TYPE_OPENTYPE_COLLECTION
;
906 IDWriteFontFileStream_ReleaseFileFragment(stream
, context
);
908 return *file_type
!= DWRITE_FONT_FILE_TYPE_UNKNOWN
? S_OK
: S_FALSE
;
911 static HRESULT
opentype_ttf_analyzer(IDWriteFontFileStream
*stream
, UINT32
*font_count
, DWRITE_FONT_FILE_TYPE
*file_type
,
912 DWRITE_FONT_FACE_TYPE
*face_type
)
918 hr
= IDWriteFontFileStream_ReadFileFragment(stream
, (const void**)&header
, 0, sizeof(*header
), &context
);
922 if (GET_BE_DWORD(*header
) == 0x10000) {
924 *file_type
= DWRITE_FONT_FILE_TYPE_TRUETYPE
;
925 *face_type
= DWRITE_FONT_FACE_TYPE_TRUETYPE
;
928 IDWriteFontFileStream_ReleaseFileFragment(stream
, context
);
930 return *file_type
!= DWRITE_FONT_FILE_TYPE_UNKNOWN
? S_OK
: S_FALSE
;
933 static HRESULT
opentype_otf_analyzer(IDWriteFontFileStream
*stream
, UINT32
*font_count
, DWRITE_FONT_FILE_TYPE
*file_type
,
934 DWRITE_FONT_FACE_TYPE
*face_type
)
940 hr
= IDWriteFontFileStream_ReadFileFragment(stream
, (const void**)&header
, 0, sizeof(*header
), &context
);
944 if (GET_BE_DWORD(*header
) == MS_OTTO_TAG
) {
946 *file_type
= DWRITE_FONT_FILE_TYPE_CFF
;
947 *face_type
= DWRITE_FONT_FACE_TYPE_CFF
;
950 IDWriteFontFileStream_ReleaseFileFragment(stream
, context
);
952 return *file_type
!= DWRITE_FONT_FILE_TYPE_UNKNOWN
? S_OK
: S_FALSE
;
955 static HRESULT
opentype_type1_analyzer(IDWriteFontFileStream
*stream
, UINT32
*font_count
, DWRITE_FONT_FILE_TYPE
*file_type
,
956 DWRITE_FONT_FACE_TYPE
*face_type
)
958 #include "pshpack1.h"
959 /* Specified in Adobe TechNote #5178 */
968 struct type1_header
{
972 const struct type1_header
*header
;
976 hr
= IDWriteFontFileStream_ReadFileFragment(stream
, (const void**)&header
, 0, sizeof(*header
), &context
);
980 /* tag is followed by plain text section */
981 if (header
->tag
== 0x8001 &&
982 (!memcmp(header
->data
, "%!PS-AdobeFont", 14) ||
983 !memcmp(header
->data
, "%!FontType", 10))) {
985 *file_type
= DWRITE_FONT_FILE_TYPE_TYPE1_PFB
;
986 *face_type
= DWRITE_FONT_FACE_TYPE_TYPE1
;
989 IDWriteFontFileStream_ReleaseFileFragment(stream
, context
);
991 /* let's see if it's a .pfm metrics file */
992 if (*file_type
== DWRITE_FONT_FILE_TYPE_UNKNOWN
) {
993 const struct pfm_header
*pfm_header
;
998 hr
= IDWriteFontFileStream_GetFileSize(stream
, &filesize
);
1002 hr
= IDWriteFontFileStream_ReadFileFragment(stream
, (const void**)&pfm_header
, 0, sizeof(*pfm_header
), &context
);
1006 offset
= pfm_header
->dfDevice
;
1007 header_checked
= pfm_header
->dfVersion
== 0x100 && pfm_header
->dfSize
== filesize
;
1008 IDWriteFontFileStream_ReleaseFileFragment(stream
, context
);
1010 /* as a last test check static string in PostScript information section */
1011 if (header_checked
) {
1012 static const char postscript
[] = "PostScript";
1015 hr
= IDWriteFontFileStream_ReadFileFragment(stream
, (const void**)&devtype_name
, offset
, sizeof(postscript
), &context
);
1019 if (!memcmp(devtype_name
, postscript
, sizeof(postscript
))) {
1021 *file_type
= DWRITE_FONT_FILE_TYPE_TYPE1_PFM
;
1022 *face_type
= DWRITE_FONT_FACE_TYPE_TYPE1
;
1025 IDWriteFontFileStream_ReleaseFileFragment(stream
, context
);
1029 return *file_type
!= DWRITE_FONT_FILE_TYPE_UNKNOWN
? S_OK
: S_FALSE
;
1032 HRESULT
opentype_analyze_font(IDWriteFontFileStream
*stream
, BOOL
*supported
, DWRITE_FONT_FILE_TYPE
*file_type
,
1033 DWRITE_FONT_FACE_TYPE
*face_type
, UINT32
*face_count
)
1035 static dwrite_fontfile_analyzer fontfile_analyzers
[] = {
1036 opentype_ttf_analyzer
,
1037 opentype_otf_analyzer
,
1038 opentype_ttc_analyzer
,
1039 opentype_type1_analyzer
,
1042 dwrite_fontfile_analyzer
*analyzer
= fontfile_analyzers
;
1043 DWRITE_FONT_FACE_TYPE face
;
1049 *file_type
= DWRITE_FONT_FILE_TYPE_UNKNOWN
;
1050 *face_type
= DWRITE_FONT_FACE_TYPE_UNKNOWN
;
1054 hr
= (*analyzer
)(stream
, face_count
, file_type
, face_type
);
1064 *supported
= is_face_type_supported(*face_type
);
1068 HRESULT
opentype_get_font_table(struct file_stream_desc
*stream_desc
, UINT32 tag
, const void **table_data
,
1069 void **table_context
, UINT32
*table_size
, BOOL
*found
)
1071 void *table_directory_context
, *sfnt_context
;
1072 TT_TableRecord
*table_record
= NULL
;
1073 TTC_SFNT_V1
*font_header
= NULL
;
1074 UINT32 table_offset
= 0;
1078 if (found
) *found
= FALSE
;
1079 if (table_size
) *table_size
= 0;
1082 *table_context
= NULL
;
1084 if (stream_desc
->face_type
== DWRITE_FONT_FACE_TYPE_OPENTYPE_COLLECTION
) {
1085 const TTC_Header_V1
*ttc_header
;
1087 hr
= IDWriteFontFileStream_ReadFileFragment(stream_desc
->stream
, (const void**)&ttc_header
, 0, sizeof(*ttc_header
), &ttc_context
);
1088 if (SUCCEEDED(hr
)) {
1089 if (stream_desc
->face_index
>= GET_BE_DWORD(ttc_header
->numFonts
))
1092 table_offset
= GET_BE_DWORD(ttc_header
->OffsetTable
[stream_desc
->face_index
]);
1093 hr
= IDWriteFontFileStream_ReadFileFragment(stream_desc
->stream
, (const void**)&font_header
, table_offset
, sizeof(*font_header
), &sfnt_context
);
1095 IDWriteFontFileStream_ReleaseFileFragment(stream_desc
->stream
, ttc_context
);
1099 hr
= IDWriteFontFileStream_ReadFileFragment(stream_desc
->stream
, (const void**)&font_header
, 0, sizeof(*font_header
), &sfnt_context
);
1104 table_count
= GET_BE_WORD(font_header
->numTables
);
1105 table_offset
+= sizeof(*font_header
);
1107 IDWriteFontFileStream_ReleaseFileFragment(stream_desc
->stream
, sfnt_context
);
1109 hr
= IDWriteFontFileStream_ReadFileFragment(stream_desc
->stream
, (const void **)&table_record
, table_offset
,
1110 table_count
* sizeof(*table_record
), &table_directory_context
);
1114 for (i
= 0; i
< table_count
; i
++) {
1115 if (table_record
->tag
== tag
) {
1116 UINT32 offset
= GET_BE_DWORD(table_record
->offset
);
1117 UINT32 length
= GET_BE_DWORD(table_record
->length
);
1122 *table_size
= length
;
1123 hr
= IDWriteFontFileStream_ReadFileFragment(stream_desc
->stream
, table_data
, offset
,
1124 length
, table_context
);
1130 IDWriteFontFileStream_ReleaseFileFragment(stream_desc
->stream
, table_directory_context
);
1140 static UINT32
opentype_cmap_get_unicode_ranges_count(const CMAP_Header
*CMAP_Table
)
1145 for (i
= 0; i
< GET_BE_WORD(CMAP_Table
->numTables
); i
++) {
1149 if (GET_BE_WORD(CMAP_Table
->tables
[i
].platformID
) != 3)
1152 table
= (WORD
*)(((BYTE
*)CMAP_Table
) + GET_BE_DWORD(CMAP_Table
->tables
[i
].offset
));
1153 type
= GET_BE_WORD(*table
);
1154 TRACE("table type %i\n", type
);
1158 case OPENTYPE_CMAP_TABLE_SEGMENT_MAPPING
:
1160 CMAP_SegmentMapping_0
*format
= (CMAP_SegmentMapping_0
*)table
;
1161 count
+= GET_BE_WORD(format
->segCountX2
)/2;
1164 case OPENTYPE_CMAP_TABLE_SEGMENTED_COVERAGE
:
1166 CMAP_SegmentedCoverage
*format
= (CMAP_SegmentedCoverage
*)table
;
1167 count
+= GET_BE_DWORD(format
->nGroups
);
1171 FIXME("table type %i unhandled.\n", type
);
1178 HRESULT
opentype_cmap_get_unicode_ranges(void *data
, UINT32 max_count
, DWRITE_UNICODE_RANGE
*ranges
, UINT32
*count
)
1180 CMAP_Header
*CMAP_Table
= data
;
1186 *count
= opentype_cmap_get_unicode_ranges_count(CMAP_Table
);
1188 for (i
= 0; i
< GET_BE_WORD(CMAP_Table
->numTables
) && k
< max_count
; i
++)
1194 if (GET_BE_WORD(CMAP_Table
->tables
[i
].platformID
) != 3)
1197 table
= (WORD
*)(((BYTE
*)CMAP_Table
) + GET_BE_DWORD(CMAP_Table
->tables
[i
].offset
));
1198 type
= GET_BE_WORD(*table
);
1199 TRACE("table type %i\n", type
);
1203 case OPENTYPE_CMAP_TABLE_SEGMENT_MAPPING
:
1205 CMAP_SegmentMapping_0
*format
= (CMAP_SegmentMapping_0
*)table
;
1206 UINT16 segment_count
= GET_BE_WORD(format
->segCountX2
)/2;
1207 UINT16
*startCode
= (WORD
*)((BYTE
*)format
+ sizeof(CMAP_SegmentMapping_0
) + (sizeof(WORD
) * segment_count
));
1209 for (j
= 0; j
< segment_count
&& GET_BE_WORD(format
->endCode
[j
]) < 0xffff && k
< max_count
; j
++, k
++) {
1210 ranges
[k
].first
= GET_BE_WORD(startCode
[j
]);
1211 ranges
[k
].last
= GET_BE_WORD(format
->endCode
[j
]);
1215 case OPENTYPE_CMAP_TABLE_SEGMENTED_COVERAGE
:
1217 CMAP_SegmentedCoverage
*format
= (CMAP_SegmentedCoverage
*)table
;
1218 for (j
= 0; j
< GET_BE_DWORD(format
->nGroups
) && k
< max_count
; j
++, k
++) {
1219 ranges
[k
].first
= GET_BE_DWORD(format
->groups
[j
].startCharCode
);
1220 ranges
[k
].last
= GET_BE_DWORD(format
->groups
[j
].endCharCode
);
1225 FIXME("table type %i unhandled.\n", type
);
1229 return *count
> max_count
? E_NOT_SUFFICIENT_BUFFER
: S_OK
;
1232 void opentype_get_font_metrics(struct file_stream_desc
*stream_desc
, DWRITE_FONT_METRICS1
*metrics
, DWRITE_CARET_METRICS
*caret
)
1234 void *os2_context
, *head_context
, *post_context
, *hhea_context
;
1235 const TT_OS2_V2
*tt_os2
;
1236 const TT_HEAD
*tt_head
;
1237 const TT_POST
*tt_post
;
1238 const TT_HHEA
*tt_hhea
;
1240 memset(metrics
, 0, sizeof(*metrics
));
1242 opentype_get_font_table(stream_desc
, MS_OS2_TAG
, (const void**)&tt_os2
, &os2_context
, NULL
, NULL
);
1243 opentype_get_font_table(stream_desc
, MS_HEAD_TAG
, (const void**)&tt_head
, &head_context
, NULL
, NULL
);
1244 opentype_get_font_table(stream_desc
, MS_POST_TAG
, (const void**)&tt_post
, &post_context
, NULL
, NULL
);
1245 opentype_get_font_table(stream_desc
, MS_HHEA_TAG
, (const void**)&tt_hhea
, &hhea_context
, NULL
, NULL
);
1248 metrics
->designUnitsPerEm
= GET_BE_WORD(tt_head
->unitsPerEm
);
1249 metrics
->glyphBoxLeft
= GET_BE_WORD(tt_head
->xMin
);
1250 metrics
->glyphBoxTop
= GET_BE_WORD(tt_head
->yMax
);
1251 metrics
->glyphBoxRight
= GET_BE_WORD(tt_head
->xMax
);
1252 metrics
->glyphBoxBottom
= GET_BE_WORD(tt_head
->yMin
);
1257 caret
->slopeRise
= GET_BE_WORD(tt_hhea
->caretSlopeRise
);
1258 caret
->slopeRun
= GET_BE_WORD(tt_hhea
->caretSlopeRun
);
1259 caret
->offset
= GET_BE_WORD(tt_hhea
->caretOffset
);
1262 caret
->slopeRise
= 0;
1263 caret
->slopeRun
= 0;
1269 USHORT version
= GET_BE_WORD(tt_os2
->version
);
1271 metrics
->ascent
= GET_BE_WORD(tt_os2
->usWinAscent
);
1272 /* Some fonts have usWinDescent value stored as signed short, which could be wrongly
1273 interpreted as large unsigned value. */
1274 metrics
->descent
= abs((SHORT
)GET_BE_WORD(tt_os2
->usWinDescent
));
1276 /* line gap is estimated using two sets of ascender/descender values and 'hhea' line gap */
1278 SHORT descender
= (SHORT
)GET_BE_WORD(tt_hhea
->descender
);
1281 linegap
= GET_BE_WORD(tt_hhea
->ascender
) + abs(descender
) + GET_BE_WORD(tt_hhea
->linegap
) -
1282 metrics
->ascent
- metrics
->descent
;
1283 metrics
->lineGap
= linegap
> 0 ? linegap
: 0;
1286 metrics
->strikethroughPosition
= GET_BE_WORD(tt_os2
->yStrikeoutPosition
);
1287 metrics
->strikethroughThickness
= GET_BE_WORD(tt_os2
->yStrikeoutSize
);
1288 metrics
->subscriptPositionX
= GET_BE_WORD(tt_os2
->ySubscriptXOffset
);
1289 /* Y offset is stored as positive offset below baseline */
1290 metrics
->subscriptPositionY
= -GET_BE_WORD(tt_os2
->ySubscriptYOffset
);
1291 metrics
->subscriptSizeX
= GET_BE_WORD(tt_os2
->ySubscriptXSize
);
1292 metrics
->subscriptSizeY
= GET_BE_WORD(tt_os2
->ySubscriptYSize
);
1293 metrics
->superscriptPositionX
= GET_BE_WORD(tt_os2
->ySuperscriptXOffset
);
1294 metrics
->superscriptPositionY
= GET_BE_WORD(tt_os2
->ySuperscriptYOffset
);
1295 metrics
->superscriptSizeX
= GET_BE_WORD(tt_os2
->ySuperscriptXSize
);
1296 metrics
->superscriptSizeY
= GET_BE_WORD(tt_os2
->ySuperscriptYSize
);
1298 /* version 2 fields */
1300 metrics
->capHeight
= GET_BE_WORD(tt_os2
->sCapHeight
);
1301 metrics
->xHeight
= GET_BE_WORD(tt_os2
->sxHeight
);
1304 if (GET_BE_WORD(tt_os2
->fsSelection
) & OS2_FSSELECTION_USE_TYPO_METRICS
) {
1305 SHORT descent
= GET_BE_WORD(tt_os2
->sTypoDescender
);
1306 metrics
->ascent
= GET_BE_WORD(tt_os2
->sTypoAscender
);
1307 metrics
->descent
= descent
< 0 ? -descent
: 0;
1308 metrics
->lineGap
= GET_BE_WORD(tt_os2
->sTypoLineGap
);
1309 metrics
->hasTypographicMetrics
= TRUE
;
1313 metrics
->strikethroughPosition
= metrics
->designUnitsPerEm
/ 3;
1315 metrics
->ascent
= GET_BE_WORD(tt_hhea
->ascender
);
1316 metrics
->descent
= abs((SHORT
)GET_BE_WORD(tt_hhea
->descender
));
1321 metrics
->underlinePosition
= GET_BE_WORD(tt_post
->underlinePosition
);
1322 metrics
->underlineThickness
= GET_BE_WORD(tt_post
->underlineThickness
);
1325 if (metrics
->underlineThickness
== 0)
1326 metrics
->underlineThickness
= metrics
->designUnitsPerEm
/ 14;
1327 if (metrics
->strikethroughThickness
== 0)
1328 metrics
->strikethroughThickness
= metrics
->underlineThickness
;
1330 /* estimate missing metrics */
1331 if (metrics
->xHeight
== 0)
1332 metrics
->xHeight
= metrics
->designUnitsPerEm
/ 2;
1333 if (metrics
->capHeight
== 0)
1334 metrics
->capHeight
= metrics
->designUnitsPerEm
* 7 / 10;
1337 IDWriteFontFileStream_ReleaseFileFragment(stream_desc
->stream
, os2_context
);
1339 IDWriteFontFileStream_ReleaseFileFragment(stream_desc
->stream
, head_context
);
1341 IDWriteFontFileStream_ReleaseFileFragment(stream_desc
->stream
, post_context
);
1343 IDWriteFontFileStream_ReleaseFileFragment(stream_desc
->stream
, hhea_context
);
1346 void opentype_get_font_properties(struct file_stream_desc
*stream_desc
, struct dwrite_font_props
*props
)
1348 void *os2_context
, *head_context
;
1349 const TT_OS2_V2
*tt_os2
;
1350 const TT_HEAD
*tt_head
;
1352 opentype_get_font_table(stream_desc
, MS_OS2_TAG
, (const void**)&tt_os2
, &os2_context
, NULL
, NULL
);
1353 opentype_get_font_table(stream_desc
, MS_HEAD_TAG
, (const void**)&tt_head
, &head_context
, NULL
, NULL
);
1355 /* default stretch, weight and style to normal */
1356 props
->stretch
= DWRITE_FONT_STRETCH_NORMAL
;
1357 props
->weight
= DWRITE_FONT_WEIGHT_NORMAL
;
1358 props
->style
= DWRITE_FONT_STYLE_NORMAL
;
1359 memset(&props
->panose
, 0, sizeof(props
->panose
));
1360 memset(&props
->fontsig
, 0, sizeof(props
->fontsig
));
1361 memset(&props
->lf
, 0, sizeof(props
->lf
));
1363 /* DWRITE_FONT_STRETCH enumeration values directly match font data values */
1365 USHORT version
= GET_BE_WORD(tt_os2
->version
);
1366 USHORT fsSelection
= GET_BE_WORD(tt_os2
->fsSelection
);
1367 USHORT usWeightClass
= GET_BE_WORD(tt_os2
->usWeightClass
);
1368 USHORT usWidthClass
= GET_BE_WORD(tt_os2
->usWidthClass
);
1370 if (usWidthClass
> DWRITE_FONT_STRETCH_UNDEFINED
&& usWidthClass
<= DWRITE_FONT_STRETCH_ULTRA_EXPANDED
)
1371 props
->stretch
= usWidthClass
;
1373 if (usWeightClass
>= 1 && usWeightClass
<= 9)
1374 usWeightClass
*= 100;
1376 if (usWeightClass
> DWRITE_FONT_WEIGHT_ULTRA_BLACK
)
1377 props
->weight
= DWRITE_FONT_WEIGHT_ULTRA_BLACK
;
1378 else if (usWeightClass
> 0)
1379 props
->weight
= usWeightClass
;
1381 if (version
>= 4 && (fsSelection
& OS2_FSSELECTION_OBLIQUE
))
1382 props
->style
= DWRITE_FONT_STYLE_OBLIQUE
;
1383 else if (fsSelection
& OS2_FSSELECTION_ITALIC
)
1384 props
->style
= DWRITE_FONT_STYLE_ITALIC
;
1385 props
->lf
.lfItalic
= !!(fsSelection
& OS2_FSSELECTION_ITALIC
);
1387 memcpy(&props
->panose
, &tt_os2
->panose
, sizeof(props
->panose
));
1390 props
->fontsig
.fsUsb
[0] = GET_BE_DWORD(tt_os2
->ulUnicodeRange1
);
1391 props
->fontsig
.fsUsb
[1] = GET_BE_DWORD(tt_os2
->ulUnicodeRange2
);
1392 props
->fontsig
.fsUsb
[2] = GET_BE_DWORD(tt_os2
->ulUnicodeRange3
);
1393 props
->fontsig
.fsUsb
[3] = GET_BE_DWORD(tt_os2
->ulUnicodeRange4
);
1395 if (GET_BE_WORD(tt_os2
->version
) == 0) {
1396 props
->fontsig
.fsCsb
[0] = 0;
1397 props
->fontsig
.fsCsb
[1] = 0;
1400 props
->fontsig
.fsCsb
[0] = GET_BE_DWORD(tt_os2
->ulCodePageRange1
);
1401 props
->fontsig
.fsCsb
[1] = GET_BE_DWORD(tt_os2
->ulCodePageRange2
);
1405 USHORT macStyle
= GET_BE_WORD(tt_head
->macStyle
);
1407 if (macStyle
& TT_HEAD_MACSTYLE_CONDENSED
)
1408 props
->stretch
= DWRITE_FONT_STRETCH_CONDENSED
;
1409 else if (macStyle
& TT_HEAD_MACSTYLE_EXTENDED
)
1410 props
->stretch
= DWRITE_FONT_STRETCH_EXPANDED
;
1412 if (macStyle
& TT_HEAD_MACSTYLE_BOLD
)
1413 props
->weight
= DWRITE_FONT_WEIGHT_BOLD
;
1415 if (macStyle
& TT_HEAD_MACSTYLE_ITALIC
) {
1416 props
->style
= DWRITE_FONT_STYLE_ITALIC
;
1417 props
->lf
.lfItalic
= 1;
1421 props
->lf
.lfWeight
= props
->weight
;
1423 TRACE("stretch=%d, weight=%d, style %d\n", props
->stretch
, props
->weight
, props
->style
);
1426 IDWriteFontFileStream_ReleaseFileFragment(stream_desc
->stream
, os2_context
);
1428 IDWriteFontFileStream_ReleaseFileFragment(stream_desc
->stream
, head_context
);
1431 static UINT
get_name_record_codepage(enum OPENTYPE_PLATFORM_ID platform
, USHORT encoding
)
1436 case OPENTYPE_PLATFORM_UNICODE
:
1438 case OPENTYPE_PLATFORM_MAC
:
1441 case TT_NAME_MAC_ENCODING_ROMAN
:
1444 case TT_NAME_MAC_ENCODING_JAPANESE
:
1447 case TT_NAME_MAC_ENCODING_TRAD_CHINESE
:
1450 case TT_NAME_MAC_ENCODING_KOREAN
:
1453 case TT_NAME_MAC_ENCODING_ARABIC
:
1456 case TT_NAME_MAC_ENCODING_HEBREW
:
1459 case TT_NAME_MAC_ENCODING_GREEK
:
1462 case TT_NAME_MAC_ENCODING_RUSSIAN
:
1465 case TT_NAME_MAC_ENCODING_SIMPL_CHINESE
:
1468 case TT_NAME_MAC_ENCODING_THAI
:
1472 FIXME("encoding %u not handled, platform %d.\n", encoding
, platform
);
1476 case OPENTYPE_PLATFORM_WIN
:
1479 case TT_NAME_WINDOWS_ENCODING_SYMBOL
:
1480 case TT_NAME_WINDOWS_ENCODING_UCS2
:
1482 case TT_NAME_WINDOWS_ENCODING_SJIS
:
1485 case TT_NAME_WINDOWS_ENCODING_PRC
:
1488 case TT_NAME_WINDOWS_ENCODING_BIG5
:
1491 case TT_NAME_WINDOWS_ENCODING_WANSUNG
:
1494 case TT_NAME_WINDOWS_ENCODING_JOHAB
:
1498 FIXME("encoding %u not handled, platform %d.\n", encoding
, platform
);
1503 FIXME("unknown platform %d\n", platform
);
1509 static void get_name_record_locale(enum OPENTYPE_PLATFORM_ID platform
, USHORT lang_id
, WCHAR
*locale
, USHORT locale_len
)
1511 static const WCHAR enusW
[] = {'e','n','-','U','S',0};
1514 case OPENTYPE_PLATFORM_MAC
:
1516 const char *locale_name
= NULL
;
1518 if (lang_id
> TT_NAME_MAC_LANGID_AZER_ROMAN
)
1519 WARN("invalid mac lang id %d\n", lang_id
);
1520 else if (!name_mac_langid_to_locale
[lang_id
][0])
1521 FIXME("failed to map mac lang id %d to locale name\n", lang_id
);
1523 locale_name
= name_mac_langid_to_locale
[lang_id
];
1526 MultiByteToWideChar(CP_ACP
, 0, name_mac_langid_to_locale
[lang_id
], -1, locale
, locale_len
);
1528 strcpyW(locale
, enusW
);
1531 case OPENTYPE_PLATFORM_WIN
:
1532 if (!LCIDToLocaleName(MAKELCID(lang_id
, SORT_DEFAULT
), locale
, locale_len
, 0)) {
1533 FIXME("failed to get locale name for lcid=0x%08x\n", MAKELCID(lang_id
, SORT_DEFAULT
));
1534 strcpyW(locale
, enusW
);
1537 case OPENTYPE_PLATFORM_UNICODE
:
1538 strcpyW(locale
, enusW
);
1541 FIXME("unknown platform %d\n", platform
);
1545 static BOOL
opentype_decode_namerecord(const TT_NAME_V0
*header
, BYTE
*storage_area
, USHORT recid
, IDWriteLocalizedStrings
*strings
)
1547 const TT_NameRecord
*record
= &header
->nameRecord
[recid
];
1548 USHORT lang_id
, length
, offset
, encoding
, platform
;
1551 platform
= GET_BE_WORD(record
->platformID
);
1552 lang_id
= GET_BE_WORD(record
->languageID
);
1553 length
= GET_BE_WORD(record
->length
);
1554 offset
= GET_BE_WORD(record
->offset
);
1555 encoding
= GET_BE_WORD(record
->encodingID
);
1557 if (lang_id
< 0x8000) {
1558 WCHAR locale
[LOCALE_NAME_MAX_LENGTH
];
1562 codepage
= get_name_record_codepage(platform
, encoding
);
1563 get_name_record_locale(platform
, lang_id
, locale
, ARRAY_SIZE(locale
));
1566 DWORD len
= MultiByteToWideChar(codepage
, 0, (LPSTR
)(storage_area
+ offset
), length
, NULL
, 0);
1567 name_string
= heap_alloc(sizeof(WCHAR
) * (len
+1));
1568 MultiByteToWideChar(codepage
, 0, (LPSTR
)(storage_area
+ offset
), length
, name_string
, len
);
1569 name_string
[len
] = 0;
1574 length
/= sizeof(WCHAR
);
1575 name_string
= heap_strdupnW((LPWSTR
)(storage_area
+ offset
), length
);
1576 for (i
= 0; i
< length
; i
++)
1577 name_string
[i
] = GET_BE_WORD(name_string
[i
]);
1580 TRACE("string %s for locale %s found\n", debugstr_w(name_string
), debugstr_w(locale
));
1581 add_localizedstring(strings
, locale
, name_string
);
1582 heap_free(name_string
);
1586 FIXME("handle NAME format 1\n");
1591 static HRESULT
opentype_get_font_strings_from_id(const void *table_data
, enum OPENTYPE_STRING_ID id
, IDWriteLocalizedStrings
**strings
)
1593 const TT_NAME_V0
*header
;
1594 BYTE
*storage_area
= 0;
1604 hr
= create_localizedstrings(strings
);
1605 if (FAILED(hr
)) return hr
;
1607 header
= table_data
;
1608 format
= GET_BE_WORD(header
->format
);
1615 FIXME("unsupported NAME format %d\n", format
);
1618 storage_area
= (LPBYTE
)table_data
+ GET_BE_WORD(header
->stringOffset
);
1619 count
= GET_BE_WORD(header
->count
);
1623 for (i
= 0; i
< count
; i
++) {
1624 const TT_NameRecord
*record
= &header
->nameRecord
[i
];
1627 if (GET_BE_WORD(record
->nameID
) != id
)
1630 /* Right now only accept unicode and windows encoded fonts */
1631 platform
= GET_BE_WORD(record
->platformID
);
1632 if (platform
!= OPENTYPE_PLATFORM_UNICODE
&&
1633 platform
!= OPENTYPE_PLATFORM_MAC
&&
1634 platform
!= OPENTYPE_PLATFORM_WIN
)
1636 FIXME("platform %i not supported\n", platform
);
1640 /* Skip such entries for now, fonts tend to duplicate those strings as
1641 WIN platform entries. If font does not have WIN or MAC entry for this id, we will
1642 use this Unicode platform entry while assuming en-US locale. */
1643 if (platform
== OPENTYPE_PLATFORM_UNICODE
) {
1648 if (!opentype_decode_namerecord(header
, storage_area
, i
, *strings
))
1655 if (candidate
!= -1)
1656 exists
= opentype_decode_namerecord(header
, storage_area
, candidate
, *strings
);
1658 IDWriteLocalizedStrings_Release(*strings
);
1663 return exists
? S_OK
: E_FAIL
;
1666 /* Provides a conversion from DWRITE to OpenType name ids, input id should be valid, it's not checked. */
1667 HRESULT
opentype_get_font_info_strings(const void *table_data
, DWRITE_INFORMATIONAL_STRING_ID id
, IDWriteLocalizedStrings
**strings
)
1669 return opentype_get_font_strings_from_id(table_data
, dwriteid_to_opentypeid
[id
], strings
);
1672 /* FamilyName locating order is WWS Family Name -> Preferred Family Name -> Family Name. If font claims to
1673 have 'Preferred Family Name' in WWS format, then WWS name is not used. */
1674 HRESULT
opentype_get_font_familyname(struct file_stream_desc
*stream_desc
, IDWriteLocalizedStrings
**names
)
1676 const TT_OS2_V2
*tt_os2
;
1677 void *os2_context
, *name_context
;
1678 const void *name_table
;
1681 opentype_get_font_table(stream_desc
, MS_OS2_TAG
, (const void**)&tt_os2
, &os2_context
, NULL
, NULL
);
1682 opentype_get_font_table(stream_desc
, MS_NAME_TAG
, &name_table
, &name_context
, NULL
, NULL
);
1686 /* if Preferred Family doesn't conform to WWS model try WWS name */
1687 if (tt_os2
&& !(GET_BE_WORD(tt_os2
->fsSelection
) & OS2_FSSELECTION_WWS
))
1688 hr
= opentype_get_font_strings_from_id(name_table
, OPENTYPE_STRING_WWS_FAMILY_NAME
, names
);
1693 hr
= opentype_get_font_strings_from_id(name_table
, OPENTYPE_STRING_PREFERRED_FAMILY_NAME
, names
);
1695 hr
= opentype_get_font_strings_from_id(name_table
, OPENTYPE_STRING_FAMILY_NAME
, names
);
1698 IDWriteFontFileStream_ReleaseFileFragment(stream_desc
->stream
, os2_context
);
1700 IDWriteFontFileStream_ReleaseFileFragment(stream_desc
->stream
, name_context
);
1705 /* FaceName locating order is WWS Face Name -> Preferred Face Name -> Face Name. If font claims to
1706 have 'Preferred Face Name' in WWS format, then WWS name is not used. */
1707 HRESULT
opentype_get_font_facename(struct file_stream_desc
*stream_desc
, WCHAR
*lfname
, IDWriteLocalizedStrings
**names
)
1709 IDWriteLocalizedStrings
*lfnames
;
1710 void *os2_context
, *name_context
;
1711 const TT_OS2_V2
*tt_os2
;
1712 const void *name_table
;
1715 opentype_get_font_table(stream_desc
, MS_OS2_TAG
, (const void**)&tt_os2
, &os2_context
, NULL
, NULL
);
1716 opentype_get_font_table(stream_desc
, MS_NAME_TAG
, &name_table
, &name_context
, NULL
, NULL
);
1720 /* if Preferred Family doesn't conform to WWS model try WWS name */
1721 if (tt_os2
&& !(GET_BE_WORD(tt_os2
->fsSelection
) & OS2_FSSELECTION_WWS
))
1722 hr
= opentype_get_font_strings_from_id(name_table
, OPENTYPE_STRING_WWS_SUBFAMILY_NAME
, names
);
1727 hr
= opentype_get_font_strings_from_id(name_table
, OPENTYPE_STRING_PREFERRED_SUBFAMILY_NAME
, names
);
1729 hr
= opentype_get_font_strings_from_id(name_table
, OPENTYPE_STRING_SUBFAMILY_NAME
, names
);
1731 /* User locale is preferred, with fallback to en-us. */
1733 if (SUCCEEDED(opentype_get_font_strings_from_id(name_table
, OPENTYPE_STRING_FAMILY_NAME
, &lfnames
))) {
1734 static const WCHAR enusW
[] = {'e','n','-','u','s',0};
1735 WCHAR localeW
[LOCALE_NAME_MAX_LENGTH
];
1740 if (GetSystemDefaultLocaleName(localeW
, ARRAY_SIZE(localeW
)))
1741 IDWriteLocalizedStrings_FindLocaleName(lfnames
, localeW
, &index
, &exists
);
1744 IDWriteLocalizedStrings_FindLocaleName(lfnames
, enusW
, &index
, &exists
);
1750 IDWriteLocalizedStrings_GetStringLength(lfnames
, index
, &length
);
1751 nameW
= heap_alloc((length
+ 1) * sizeof(WCHAR
));
1754 IDWriteLocalizedStrings_GetString(lfnames
, index
, nameW
, length
+ 1);
1755 lstrcpynW(lfname
, nameW
, LF_FACESIZE
);
1760 IDWriteLocalizedStrings_Release(lfnames
);
1764 IDWriteFontFileStream_ReleaseFileFragment(stream_desc
->stream
, os2_context
);
1766 IDWriteFontFileStream_ReleaseFileFragment(stream_desc
->stream
, name_context
);
1771 static inline const OT_Script
*opentype_get_script(const OT_ScriptList
*scriptlist
, UINT32 scripttag
)
1775 for (j
= 0; j
< GET_BE_WORD(scriptlist
->ScriptCount
); j
++) {
1776 const char *tag
= scriptlist
->ScriptRecord
[j
].ScriptTag
;
1777 if (scripttag
== DWRITE_MAKE_OPENTYPE_TAG(tag
[0], tag
[1], tag
[2], tag
[3]))
1778 return (OT_Script
*)((BYTE
*)scriptlist
+ GET_BE_WORD(scriptlist
->ScriptRecord
[j
].Script
));
1784 static inline const OT_LangSys
*opentype_get_langsys(const OT_Script
*script
, UINT32 languagetag
)
1788 for (j
= 0; j
< GET_BE_WORD(script
->LangSysCount
); j
++) {
1789 const char *tag
= script
->LangSysRecord
[j
].LangSysTag
;
1790 if (languagetag
== DWRITE_MAKE_OPENTYPE_TAG(tag
[0], tag
[1], tag
[2], tag
[3]))
1791 return (OT_LangSys
*)((BYTE
*)script
+ GET_BE_WORD(script
->LangSysRecord
[j
].LangSys
));
1797 static void opentype_add_font_features(const GPOS_GSUB_Header
*header
, const OT_LangSys
*langsys
,
1798 UINT32 max_tagcount
, UINT32
*count
, DWRITE_FONT_FEATURE_TAG
*tags
)
1800 const OT_FeatureList
*features
= (const OT_FeatureList
*)((const BYTE
*)header
+ GET_BE_WORD(header
->FeatureList
));
1803 for (j
= 0; j
< GET_BE_WORD(langsys
->FeatureCount
); j
++) {
1804 const OT_FeatureRecord
*feature
= &features
->FeatureRecord
[langsys
->FeatureIndex
[j
]];
1805 const char *tag
= feature
->FeatureTag
;
1807 if (*count
< max_tagcount
)
1808 tags
[*count
] = DWRITE_MAKE_OPENTYPE_TAG(tag
[0], tag
[1], tag
[2], tag
[3]);
1814 HRESULT
opentype_get_typographic_features(IDWriteFontFace
*fontface
, UINT32 scripttag
, UINT32 languagetag
, UINT32 max_tagcount
,
1815 UINT32
*count
, DWRITE_FONT_FEATURE_TAG
*tags
)
1817 UINT32 tables
[2] = { MS_GSUB_TAG
, MS_GPOS_TAG
};
1822 for (i
= 0; i
< ARRAY_SIZE(tables
); i
++) {
1823 const OT_ScriptList
*scriptlist
;
1824 const GPOS_GSUB_Header
*header
;
1825 const OT_Script
*script
;
1832 hr
= IDWriteFontFace_TryGetFontTable(fontface
, tables
[i
], &ptr
, &size
, &context
, &exists
);
1839 header
= (const GPOS_GSUB_Header
*)ptr
;
1840 scriptlist
= (const OT_ScriptList
*)((const BYTE
*)header
+ GET_BE_WORD(header
->ScriptList
));
1842 script
= opentype_get_script(scriptlist
, scripttag
);
1844 const OT_LangSys
*langsys
= opentype_get_langsys(script
, languagetag
);
1846 opentype_add_font_features(header
, langsys
, max_tagcount
, count
, tags
);
1849 IDWriteFontFace_ReleaseFontTable(fontface
, context
);
1852 return *count
> max_tagcount
? E_NOT_SUFFICIENT_BUFFER
: S_OK
;
1855 static const struct VDMX_group
*find_vdmx_group(const struct VDMX_Header
*hdr
)
1857 WORD num_ratios
, i
, group_offset
= 0;
1858 struct VDMX_Ratio
*ratios
= (struct VDMX_Ratio
*)(hdr
+ 1);
1859 BYTE dev_x_ratio
= 1, dev_y_ratio
= 1;
1861 num_ratios
= GET_BE_WORD(hdr
->numRatios
);
1863 for (i
= 0; i
< num_ratios
; i
++) {
1865 if (!ratios
[i
].bCharSet
) continue;
1867 if ((ratios
[i
].xRatio
== 0 && ratios
[i
].yStartRatio
== 0 &&
1868 ratios
[i
].yEndRatio
== 0) ||
1869 (ratios
[i
].xRatio
== dev_x_ratio
&& ratios
[i
].yStartRatio
<= dev_y_ratio
&&
1870 ratios
[i
].yEndRatio
>= dev_y_ratio
))
1872 group_offset
= GET_BE_WORD(*((WORD
*)(ratios
+ num_ratios
) + i
));
1877 return (const struct VDMX_group
*)((BYTE
*)hdr
+ group_offset
);
1881 BOOL
opentype_get_vdmx_size(const void *data
, INT emsize
, UINT16
*ascent
, UINT16
*descent
)
1883 const struct VDMX_Header
*hdr
= (const struct VDMX_Header
*)data
;
1884 const struct VDMX_group
*group
;
1885 const struct VDMX_vTable
*tables
;
1891 group
= find_vdmx_group(hdr
);
1895 recs
= GET_BE_WORD(group
->recs
);
1896 if (emsize
< group
->startsz
|| emsize
>= group
->endsz
) return FALSE
;
1898 tables
= (const struct VDMX_vTable
*)(group
+ 1);
1899 for (i
= 0; i
< recs
; i
++) {
1900 WORD ppem
= GET_BE_WORD(tables
[i
].yPelHeight
);
1901 if (ppem
> emsize
) {
1902 FIXME("interpolate %d\n", emsize
);
1906 if (ppem
== emsize
) {
1907 *ascent
= (SHORT
)GET_BE_WORD(tables
[i
].yMax
);
1908 *descent
= -(SHORT
)GET_BE_WORD(tables
[i
].yMin
);
1915 WORD
opentype_get_gasp_flags(const WORD
*ptr
, UINT32 size
, INT emsize
)
1917 WORD num_recs
, version
;
1923 version
= GET_BE_WORD( *ptr
++ );
1924 num_recs
= GET_BE_WORD( *ptr
++ );
1925 if (version
> 1 || size
< (num_recs
* 2 + 2) * sizeof(WORD
)) {
1926 ERR("unsupported gasp table: ver %d size %d recs %d\n", version
, size
, num_recs
);
1930 while (num_recs
--) {
1931 flags
= GET_BE_WORD( *(ptr
+ 1) );
1932 if (emsize
<= GET_BE_WORD( *ptr
)) break;
1940 UINT32
opentype_get_cpal_palettecount(const void *cpal
)
1942 const struct CPAL_Header_0
*header
= (const struct CPAL_Header_0
*)cpal
;
1943 return header
? GET_BE_WORD(header
->numPalette
) : 0;
1946 UINT32
opentype_get_cpal_paletteentrycount(const void *cpal
)
1948 const struct CPAL_Header_0
*header
= (const struct CPAL_Header_0
*)cpal
;
1949 return header
? GET_BE_WORD(header
->numPaletteEntries
) : 0;
1952 HRESULT
opentype_get_cpal_entries(const void *cpal
, UINT32 palette
, UINT32 first_entry_index
, UINT32 entry_count
,
1953 DWRITE_COLOR_F
*entries
)
1955 const struct CPAL_Header_0
*header
= (const struct CPAL_Header_0
*)cpal
;
1956 const struct CPAL_ColorRecord
*records
;
1957 UINT32 palettecount
, entrycount
, i
;
1959 if (!header
) return DWRITE_E_NOCOLOR
;
1961 palettecount
= GET_BE_WORD(header
->numPalette
);
1962 if (palette
>= palettecount
)
1963 return DWRITE_E_NOCOLOR
;
1965 entrycount
= GET_BE_WORD(header
->numPaletteEntries
);
1966 if (first_entry_index
+ entry_count
> entrycount
)
1967 return E_INVALIDARG
;
1969 records
= (const struct CPAL_ColorRecord
*)((BYTE
*)cpal
+ GET_BE_DWORD(header
->offsetFirstColorRecord
));
1970 first_entry_index
+= GET_BE_WORD(header
->colorRecordIndices
[palette
]);
1972 for (i
= 0; i
< entry_count
; i
++) {
1973 entries
[i
].u1
.r
= records
[first_entry_index
+ i
].red
/ 255.0f
;
1974 entries
[i
].u2
.g
= records
[first_entry_index
+ i
].green
/ 255.0f
;
1975 entries
[i
].u3
.b
= records
[first_entry_index
+ i
].blue
/ 255.0f
;
1976 entries
[i
].u4
.a
= records
[first_entry_index
+ i
].alpha
/ 255.0f
;
1982 static int colr_compare_gid(const void *g
, const void *r
)
1984 const struct COLR_BaseGlyphRecord
*record
= r
;
1985 UINT16 glyph
= *(UINT16
*)g
, GID
= GET_BE_WORD(record
->GID
);
1990 else if (glyph
< GID
)
1996 HRESULT
opentype_get_colr_glyph(const void *colr
, UINT16 glyph
, struct dwrite_colorglyph
*ret
)
1998 const struct COLR_BaseGlyphRecord
*record
;
1999 const struct COLR_Header
*header
= colr
;
2000 const struct COLR_LayerRecord
*layer
;
2001 DWORD layerrecordoffset
= GET_BE_DWORD(header
->offsetLayerRecord
);
2002 DWORD baserecordoffset
= GET_BE_DWORD(header
->offsetBaseGlyphRecord
);
2003 WORD numbaserecords
= GET_BE_WORD(header
->numBaseGlyphRecords
);
2005 record
= bsearch(&glyph
, (BYTE
*)colr
+ baserecordoffset
, numbaserecords
, sizeof(struct COLR_BaseGlyphRecord
),
2009 ret
->first_layer
= 0;
2010 ret
->num_layers
= 0;
2012 ret
->palette_index
= 0xffff;
2017 ret
->first_layer
= GET_BE_WORD(record
->firstLayerIndex
);
2018 ret
->num_layers
= GET_BE_WORD(record
->numLayers
);
2020 layer
= (struct COLR_LayerRecord
*)((BYTE
*)colr
+ layerrecordoffset
) + ret
->first_layer
+ ret
->layer
;
2021 ret
->glyph
= GET_BE_WORD(layer
->GID
);
2022 ret
->palette_index
= GET_BE_WORD(layer
->paletteIndex
);
2027 void opentype_colr_next_glyph(const void *colr
, struct dwrite_colorglyph
*glyph
)
2029 const struct COLR_Header
*header
= colr
;
2030 const struct COLR_LayerRecord
*layer
;
2031 DWORD layerrecordoffset
= GET_BE_DWORD(header
->offsetLayerRecord
);
2033 /* iterated all the way through */
2034 if (glyph
->layer
== glyph
->num_layers
)
2038 layer
= (struct COLR_LayerRecord
*)((BYTE
*)colr
+ layerrecordoffset
) + glyph
->first_layer
+ glyph
->layer
;
2039 glyph
->glyph
= GET_BE_WORD(layer
->GID
);
2040 glyph
->palette_index
= GET_BE_WORD(layer
->paletteIndex
);
2043 BOOL
opentype_has_vertical_variants(IDWriteFontFace4
*fontface
)
2045 const OT_FeatureList
*featurelist
;
2046 const OT_LookupList
*lookup_list
;
2047 BOOL exists
= FALSE
, ret
= FALSE
;
2048 const GPOS_GSUB_Header
*header
;
2055 hr
= IDWriteFontFace4_TryGetFontTable(fontface
, MS_GSUB_TAG
, &data
, &size
, &context
, &exists
);
2056 if (FAILED(hr
) || !exists
)
2060 featurelist
= (OT_FeatureList
*)((BYTE
*)header
+ GET_BE_WORD(header
->FeatureList
));
2061 lookup_list
= (const OT_LookupList
*)((BYTE
*)header
+ GET_BE_WORD(header
->LookupList
));
2063 for (i
= 0; i
< GET_BE_WORD(featurelist
->FeatureCount
); i
++) {
2064 if (*(UINT32
*)featurelist
->FeatureRecord
[i
].FeatureTag
== DWRITE_FONT_FEATURE_TAG_VERTICAL_WRITING
) {
2065 const OT_Feature
*feature
= (const OT_Feature
*)((BYTE
*)featurelist
+ GET_BE_WORD(featurelist
->FeatureRecord
[i
].Feature
));
2066 UINT16 lookup_count
= GET_BE_WORD(feature
->LookupCount
), i
, index
, count
, type
;
2067 const GSUB_SingleSubstFormat2
*subst2
;
2068 const OT_LookupTable
*lookup_table
;
2071 if (lookup_count
== 0)
2074 for (i
= 0; i
< lookup_count
; i
++) {
2075 /* check if lookup is empty */
2076 index
= GET_BE_WORD(feature
->LookupListIndex
[i
]);
2077 lookup_table
= (const OT_LookupTable
*)((BYTE
*)lookup_list
+ GET_BE_WORD(lookup_list
->Lookup
[index
]));
2079 type
= GET_BE_WORD(lookup_table
->LookupType
);
2080 if (type
!= OPENTYPE_GPOS_SINGLE_SUBST
&& type
!= OPENTYPE_GPOS_EXTENSION_SUBST
)
2083 count
= GET_BE_WORD(lookup_table
->SubTableCount
);
2087 offset
= GET_BE_WORD(lookup_table
->SubTable
[0]);
2088 if (type
== OPENTYPE_GPOS_EXTENSION_SUBST
) {
2089 const GSUB_ExtensionPosFormat1
*ext
= (const GSUB_ExtensionPosFormat1
*)((const BYTE
*)lookup_table
+ offset
);
2090 if (GET_BE_WORD(ext
->SubstFormat
) == 1)
2091 offset
+= GET_BE_DWORD(ext
->ExtensionOffset
);
2093 FIXME("Unhandled Extension Substitution Format %u\n", GET_BE_WORD(ext
->SubstFormat
));
2096 subst2
= (const GSUB_SingleSubstFormat2
*)((BYTE
*)lookup_table
+ offset
);
2097 index
= GET_BE_WORD(subst2
->SubstFormat
);
2099 FIXME("Validate Single Substitution Format 1\n");
2100 else if (index
== 2) {
2101 /* SimSun-ExtB has 0 glyph count for this substitution */
2102 if (GET_BE_WORD(subst2
->GlyphCount
) > 0) {
2108 WARN("Unknown Single Substitution Format, %u\n", index
);
2113 IDWriteFontFace4_ReleaseFontTable(fontface
, context
);
2118 static BOOL
opentype_has_font_table(IDWriteFontFace4
*fontface
, UINT32 tag
)
2120 BOOL exists
= FALSE
;
2126 hr
= IDWriteFontFace4_TryGetFontTable(fontface
, tag
, &data
, &size
, &context
, &exists
);
2131 IDWriteFontFace4_ReleaseFontTable(fontface
, context
);
2136 static DWORD
opentype_get_sbix_formats(IDWriteFontFace4
*fontface
)
2138 UINT32 size
, s
, num_strikes
;
2139 const sbix_header
*header
;
2140 UINT16 g
, num_glyphs
;
2141 BOOL exists
= FALSE
;
2148 hr
= IDWriteFontFace4_TryGetFontTable(fontface
, MS_MAXP_TAG
, &data
, &size
, &context
, &exists
);
2149 if (FAILED(hr
) || !exists
)
2153 num_glyphs
= GET_BE_WORD(maxp
->numGlyphs
);
2155 IDWriteFontFace4_ReleaseFontTable(fontface
, context
);
2157 if (FAILED(IDWriteFontFace4_TryGetFontTable(fontface
, MS_SBIX_TAG
, &data
, &size
, &context
, &exists
))) {
2158 WARN("Failed to get 'sbix' table, %#x\n", hr
);
2163 num_strikes
= GET_BE_DWORD(header
->numStrikes
);
2165 for (s
= 0; s
< num_strikes
; s
++) {
2166 sbix_strike
*strike
= (sbix_strike
*)((BYTE
*)header
+ GET_BE_DWORD(header
->strikeOffset
[s
]));
2168 for (g
= 0; g
< num_glyphs
; g
++) {
2169 DWORD offset
= GET_BE_DWORD(strike
->glyphDataOffsets
[g
]);
2170 DWORD offset_next
= GET_BE_DWORD(strike
->glyphDataOffsets
[g
+ 1]);
2171 sbix_glyph_data
*glyph_data
;
2174 if (offset
== offset_next
)
2177 glyph_data
= (sbix_glyph_data
*)((BYTE
*)strike
+ offset
);
2178 switch (format
= glyph_data
->graphicType
)
2181 ret
|= DWRITE_GLYPH_IMAGE_FORMATS_PNG
;
2184 ret
|= DWRITE_GLYPH_IMAGE_FORMATS_JPEG
;
2187 ret
|= DWRITE_GLYPH_IMAGE_FORMATS_TIFF
;
2190 format
= GET_BE_DWORD(format
);
2191 FIXME("unexpected bitmap format %s\n", debugstr_an((char *)&format
, 4));
2196 IDWriteFontFace4_ReleaseFontTable(fontface
, context
);
2201 static UINT32
opentype_get_cblc_formats(IDWriteFontFace4
*fontface
)
2203 CBLCBitmapSizeTable
*sizes
;
2204 UINT32 num_sizes
, size
, s
;
2205 BOOL exists
= FALSE
;
2211 if (FAILED(hr
= IDWriteFontFace4_TryGetFontTable(fontface
, MS_CBLC_TAG
, (const void **)&header
, &size
,
2212 &context
, &exists
)))
2218 num_sizes
= GET_BE_DWORD(header
->numSizes
);
2219 sizes
= (CBLCBitmapSizeTable
*)(header
+ 1);
2221 for (s
= 0; s
< num_sizes
; s
++) {
2222 BYTE bpp
= sizes
->bitDepth
;
2224 if (bpp
== 1 || bpp
== 2 || bpp
== 4 || bpp
== 8)
2225 ret
|= DWRITE_GLYPH_IMAGE_FORMATS_PNG
;
2227 ret
|= DWRITE_GLYPH_IMAGE_FORMATS_PREMULTIPLIED_B8G8R8A8
;
2230 IDWriteFontFace4_ReleaseFontTable(fontface
, context
);
2235 UINT32
opentype_get_glyph_image_formats(IDWriteFontFace4
*fontface
)
2237 UINT32 ret
= DWRITE_GLYPH_IMAGE_FORMATS_NONE
;
2239 if (opentype_has_font_table(fontface
, MS_GLYF_TAG
))
2240 ret
|= DWRITE_GLYPH_IMAGE_FORMATS_TRUETYPE
;
2242 if (opentype_has_font_table(fontface
, MS_CFF__TAG
) ||
2243 opentype_has_font_table(fontface
, MS_CFF2_TAG
))
2244 ret
|= DWRITE_GLYPH_IMAGE_FORMATS_CFF
;
2246 if (opentype_has_font_table(fontface
, MS_COLR_TAG
))
2247 ret
|= DWRITE_GLYPH_IMAGE_FORMATS_COLR
;
2249 if (opentype_has_font_table(fontface
, MS_SVG__TAG
))
2250 ret
|= DWRITE_GLYPH_IMAGE_FORMATS_SVG
;
2252 if (opentype_has_font_table(fontface
, MS_SBIX_TAG
))
2253 ret
|= opentype_get_sbix_formats(fontface
);
2255 if (opentype_has_font_table(fontface
, MS_CBLC_TAG
))
2256 ret
|= opentype_get_cblc_formats(fontface
);
2261 DWRITE_CONTAINER_TYPE
opentype_analyze_container_type(void const *data
, UINT32 data_size
)
2265 if (data_size
< sizeof(DWORD
))
2266 return DWRITE_CONTAINER_TYPE_UNKNOWN
;
2268 /* Both WOFF and WOFF2 start with 4 bytes signature. */
2269 signature
= *(DWORD
*)data
;
2274 return DWRITE_CONTAINER_TYPE_WOFF
;
2276 return DWRITE_CONTAINER_TYPE_WOFF2
;
2278 return DWRITE_CONTAINER_TYPE_UNKNOWN
;