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
;
1314 metrics
->underlinePosition
= GET_BE_WORD(tt_post
->underlinePosition
);
1315 metrics
->underlineThickness
= GET_BE_WORD(tt_post
->underlineThickness
);
1318 if (metrics
->underlineThickness
== 0)
1319 metrics
->underlineThickness
= metrics
->designUnitsPerEm
/ 14;
1320 if (metrics
->strikethroughThickness
== 0)
1321 metrics
->strikethroughThickness
= metrics
->underlineThickness
;
1323 /* estimate missing metrics */
1324 if (metrics
->xHeight
== 0)
1325 metrics
->xHeight
= metrics
->designUnitsPerEm
/ 2;
1326 if (metrics
->capHeight
== 0)
1327 metrics
->capHeight
= metrics
->designUnitsPerEm
* 7 / 10;
1330 IDWriteFontFileStream_ReleaseFileFragment(stream_desc
->stream
, os2_context
);
1332 IDWriteFontFileStream_ReleaseFileFragment(stream_desc
->stream
, head_context
);
1334 IDWriteFontFileStream_ReleaseFileFragment(stream_desc
->stream
, post_context
);
1336 IDWriteFontFileStream_ReleaseFileFragment(stream_desc
->stream
, hhea_context
);
1339 void opentype_get_font_properties(struct file_stream_desc
*stream_desc
, struct dwrite_font_props
*props
)
1341 void *os2_context
, *head_context
;
1342 const TT_OS2_V2
*tt_os2
;
1343 const TT_HEAD
*tt_head
;
1345 opentype_get_font_table(stream_desc
, MS_OS2_TAG
, (const void**)&tt_os2
, &os2_context
, NULL
, NULL
);
1346 opentype_get_font_table(stream_desc
, MS_HEAD_TAG
, (const void**)&tt_head
, &head_context
, NULL
, NULL
);
1348 /* default stretch, weight and style to normal */
1349 props
->stretch
= DWRITE_FONT_STRETCH_NORMAL
;
1350 props
->weight
= DWRITE_FONT_WEIGHT_NORMAL
;
1351 props
->style
= DWRITE_FONT_STYLE_NORMAL
;
1352 memset(&props
->panose
, 0, sizeof(props
->panose
));
1353 memset(&props
->fontsig
, 0, sizeof(props
->fontsig
));
1354 memset(&props
->lf
, 0, sizeof(props
->lf
));
1356 /* DWRITE_FONT_STRETCH enumeration values directly match font data values */
1358 USHORT version
= GET_BE_WORD(tt_os2
->version
);
1359 USHORT fsSelection
= GET_BE_WORD(tt_os2
->fsSelection
);
1360 USHORT usWeightClass
= GET_BE_WORD(tt_os2
->usWeightClass
);
1361 USHORT usWidthClass
= GET_BE_WORD(tt_os2
->usWidthClass
);
1363 if (usWidthClass
> DWRITE_FONT_STRETCH_UNDEFINED
&& usWidthClass
<= DWRITE_FONT_STRETCH_ULTRA_EXPANDED
)
1364 props
->stretch
= usWidthClass
;
1366 if (usWeightClass
>= 1 && usWeightClass
<= 9)
1367 usWeightClass
*= 100;
1369 if (usWeightClass
> DWRITE_FONT_WEIGHT_ULTRA_BLACK
)
1370 props
->weight
= DWRITE_FONT_WEIGHT_ULTRA_BLACK
;
1371 else if (usWeightClass
> 0)
1372 props
->weight
= usWeightClass
;
1374 if (version
>= 4 && (fsSelection
& OS2_FSSELECTION_OBLIQUE
))
1375 props
->style
= DWRITE_FONT_STYLE_OBLIQUE
;
1376 else if (fsSelection
& OS2_FSSELECTION_ITALIC
)
1377 props
->style
= DWRITE_FONT_STYLE_ITALIC
;
1379 memcpy(&props
->panose
, &tt_os2
->panose
, sizeof(props
->panose
));
1382 props
->fontsig
.fsUsb
[0] = GET_BE_DWORD(tt_os2
->ulUnicodeRange1
);
1383 props
->fontsig
.fsUsb
[1] = GET_BE_DWORD(tt_os2
->ulUnicodeRange2
);
1384 props
->fontsig
.fsUsb
[2] = GET_BE_DWORD(tt_os2
->ulUnicodeRange3
);
1385 props
->fontsig
.fsUsb
[3] = GET_BE_DWORD(tt_os2
->ulUnicodeRange4
);
1387 if (GET_BE_WORD(tt_os2
->version
) == 0) {
1388 props
->fontsig
.fsCsb
[0] = 0;
1389 props
->fontsig
.fsCsb
[1] = 0;
1392 props
->fontsig
.fsCsb
[0] = GET_BE_DWORD(tt_os2
->ulCodePageRange1
);
1393 props
->fontsig
.fsCsb
[1] = GET_BE_DWORD(tt_os2
->ulCodePageRange2
);
1397 USHORT macStyle
= GET_BE_WORD(tt_head
->macStyle
);
1399 if (macStyle
& TT_HEAD_MACSTYLE_CONDENSED
)
1400 props
->stretch
= DWRITE_FONT_STRETCH_CONDENSED
;
1401 else if (macStyle
& TT_HEAD_MACSTYLE_EXTENDED
)
1402 props
->stretch
= DWRITE_FONT_STRETCH_EXPANDED
;
1404 if (macStyle
& TT_HEAD_MACSTYLE_BOLD
)
1405 props
->weight
= DWRITE_FONT_WEIGHT_BOLD
;
1407 if (macStyle
& TT_HEAD_MACSTYLE_ITALIC
)
1408 props
->style
= DWRITE_FONT_STYLE_ITALIC
;
1411 props
->lf
.lfWeight
= props
->weight
;
1412 props
->lf
.lfItalic
= props
->style
== DWRITE_FONT_STYLE_ITALIC
;
1414 TRACE("stretch=%d, weight=%d, style %d\n", props
->stretch
, props
->weight
, props
->style
);
1417 IDWriteFontFileStream_ReleaseFileFragment(stream_desc
->stream
, os2_context
);
1419 IDWriteFontFileStream_ReleaseFileFragment(stream_desc
->stream
, head_context
);
1422 static UINT
get_name_record_codepage(enum OPENTYPE_PLATFORM_ID platform
, USHORT encoding
)
1427 case OPENTYPE_PLATFORM_UNICODE
:
1429 case OPENTYPE_PLATFORM_MAC
:
1432 case TT_NAME_MAC_ENCODING_ROMAN
:
1435 case TT_NAME_MAC_ENCODING_JAPANESE
:
1438 case TT_NAME_MAC_ENCODING_TRAD_CHINESE
:
1441 case TT_NAME_MAC_ENCODING_KOREAN
:
1444 case TT_NAME_MAC_ENCODING_ARABIC
:
1447 case TT_NAME_MAC_ENCODING_HEBREW
:
1450 case TT_NAME_MAC_ENCODING_GREEK
:
1453 case TT_NAME_MAC_ENCODING_RUSSIAN
:
1456 case TT_NAME_MAC_ENCODING_SIMPL_CHINESE
:
1459 case TT_NAME_MAC_ENCODING_THAI
:
1463 FIXME("encoding %u not handled, platform %d.\n", encoding
, platform
);
1467 case OPENTYPE_PLATFORM_WIN
:
1470 case TT_NAME_WINDOWS_ENCODING_SYMBOL
:
1471 case TT_NAME_WINDOWS_ENCODING_UCS2
:
1473 case TT_NAME_WINDOWS_ENCODING_SJIS
:
1476 case TT_NAME_WINDOWS_ENCODING_PRC
:
1479 case TT_NAME_WINDOWS_ENCODING_BIG5
:
1482 case TT_NAME_WINDOWS_ENCODING_WANSUNG
:
1485 case TT_NAME_WINDOWS_ENCODING_JOHAB
:
1489 FIXME("encoding %u not handled, platform %d.\n", encoding
, platform
);
1494 FIXME("unknown platform %d\n", platform
);
1500 static void get_name_record_locale(enum OPENTYPE_PLATFORM_ID platform
, USHORT lang_id
, WCHAR
*locale
, USHORT locale_len
)
1502 static const WCHAR enusW
[] = {'e','n','-','U','S',0};
1505 case OPENTYPE_PLATFORM_MAC
:
1507 const char *locale_name
= NULL
;
1509 if (lang_id
> TT_NAME_MAC_LANGID_AZER_ROMAN
)
1510 WARN("invalid mac lang id %d\n", lang_id
);
1511 else if (!name_mac_langid_to_locale
[lang_id
][0])
1512 FIXME("failed to map mac lang id %d to locale name\n", lang_id
);
1514 locale_name
= name_mac_langid_to_locale
[lang_id
];
1517 MultiByteToWideChar(CP_ACP
, 0, name_mac_langid_to_locale
[lang_id
], -1, locale
, locale_len
);
1519 strcpyW(locale
, enusW
);
1522 case OPENTYPE_PLATFORM_WIN
:
1523 if (!LCIDToLocaleName(MAKELCID(lang_id
, SORT_DEFAULT
), locale
, locale_len
, 0)) {
1524 FIXME("failed to get locale name for lcid=0x%08x\n", MAKELCID(lang_id
, SORT_DEFAULT
));
1525 strcpyW(locale
, enusW
);
1528 case OPENTYPE_PLATFORM_UNICODE
:
1529 strcpyW(locale
, enusW
);
1532 FIXME("unknown platform %d\n", platform
);
1536 static BOOL
opentype_decode_namerecord(const TT_NAME_V0
*header
, BYTE
*storage_area
, USHORT recid
, IDWriteLocalizedStrings
*strings
)
1538 const TT_NameRecord
*record
= &header
->nameRecord
[recid
];
1539 USHORT lang_id
, length
, offset
, encoding
, platform
;
1542 platform
= GET_BE_WORD(record
->platformID
);
1543 lang_id
= GET_BE_WORD(record
->languageID
);
1544 length
= GET_BE_WORD(record
->length
);
1545 offset
= GET_BE_WORD(record
->offset
);
1546 encoding
= GET_BE_WORD(record
->encodingID
);
1548 if (lang_id
< 0x8000) {
1549 WCHAR locale
[LOCALE_NAME_MAX_LENGTH
];
1553 codepage
= get_name_record_codepage(platform
, encoding
);
1554 get_name_record_locale(platform
, lang_id
, locale
, sizeof(locale
)/sizeof(WCHAR
));
1557 DWORD len
= MultiByteToWideChar(codepage
, 0, (LPSTR
)(storage_area
+ offset
), length
, NULL
, 0);
1558 name_string
= heap_alloc(sizeof(WCHAR
) * (len
+1));
1559 MultiByteToWideChar(codepage
, 0, (LPSTR
)(storage_area
+ offset
), length
, name_string
, len
);
1560 name_string
[len
] = 0;
1565 length
/= sizeof(WCHAR
);
1566 name_string
= heap_strdupnW((LPWSTR
)(storage_area
+ offset
), length
);
1567 for (i
= 0; i
< length
; i
++)
1568 name_string
[i
] = GET_BE_WORD(name_string
[i
]);
1571 TRACE("string %s for locale %s found\n", debugstr_w(name_string
), debugstr_w(locale
));
1572 add_localizedstring(strings
, locale
, name_string
);
1573 heap_free(name_string
);
1577 FIXME("handle NAME format 1\n");
1582 static HRESULT
opentype_get_font_strings_from_id(const void *table_data
, enum OPENTYPE_STRING_ID id
, IDWriteLocalizedStrings
**strings
)
1584 const TT_NAME_V0
*header
;
1585 BYTE
*storage_area
= 0;
1595 hr
= create_localizedstrings(strings
);
1596 if (FAILED(hr
)) return hr
;
1598 header
= table_data
;
1599 format
= GET_BE_WORD(header
->format
);
1606 FIXME("unsupported NAME format %d\n", format
);
1609 storage_area
= (LPBYTE
)table_data
+ GET_BE_WORD(header
->stringOffset
);
1610 count
= GET_BE_WORD(header
->count
);
1614 for (i
= 0; i
< count
; i
++) {
1615 const TT_NameRecord
*record
= &header
->nameRecord
[i
];
1618 if (GET_BE_WORD(record
->nameID
) != id
)
1621 /* Right now only accept unicode and windows encoded fonts */
1622 platform
= GET_BE_WORD(record
->platformID
);
1623 if (platform
!= OPENTYPE_PLATFORM_UNICODE
&&
1624 platform
!= OPENTYPE_PLATFORM_MAC
&&
1625 platform
!= OPENTYPE_PLATFORM_WIN
)
1627 FIXME("platform %i not supported\n", platform
);
1631 /* Skip such entries for now, fonts tend to duplicate those strings as
1632 WIN platform entries. If font does not have WIN or MAC entry for this id, we will
1633 use this Unicode platform entry while assuming en-US locale. */
1634 if (platform
== OPENTYPE_PLATFORM_UNICODE
) {
1639 if (!opentype_decode_namerecord(header
, storage_area
, i
, *strings
))
1646 if (candidate
!= -1)
1647 exists
= opentype_decode_namerecord(header
, storage_area
, candidate
, *strings
);
1649 IDWriteLocalizedStrings_Release(*strings
);
1654 return exists
? S_OK
: E_FAIL
;
1657 /* Provides a conversion from DWRITE to OpenType name ids, input id should be valid, it's not checked. */
1658 HRESULT
opentype_get_font_info_strings(const void *table_data
, DWRITE_INFORMATIONAL_STRING_ID id
, IDWriteLocalizedStrings
**strings
)
1660 return opentype_get_font_strings_from_id(table_data
, dwriteid_to_opentypeid
[id
], strings
);
1663 /* FamilyName locating order is WWS Family Name -> Preferred Family Name -> Family Name. If font claims to
1664 have 'Preferred Family Name' in WWS format, then WWS name is not used. */
1665 HRESULT
opentype_get_font_familyname(struct file_stream_desc
*stream_desc
, IDWriteLocalizedStrings
**names
)
1667 const TT_OS2_V2
*tt_os2
;
1668 void *os2_context
, *name_context
;
1669 const void *name_table
;
1672 opentype_get_font_table(stream_desc
, MS_OS2_TAG
, (const void**)&tt_os2
, &os2_context
, NULL
, NULL
);
1673 opentype_get_font_table(stream_desc
, MS_NAME_TAG
, &name_table
, &name_context
, NULL
, NULL
);
1677 /* if Preferred Family doesn't conform to WWS model try WWS name */
1678 if (tt_os2
&& !(GET_BE_WORD(tt_os2
->fsSelection
) & OS2_FSSELECTION_WWS
))
1679 hr
= opentype_get_font_strings_from_id(name_table
, OPENTYPE_STRING_WWS_FAMILY_NAME
, names
);
1684 hr
= opentype_get_font_strings_from_id(name_table
, OPENTYPE_STRING_PREFERRED_FAMILY_NAME
, names
);
1686 hr
= opentype_get_font_strings_from_id(name_table
, OPENTYPE_STRING_FAMILY_NAME
, names
);
1689 IDWriteFontFileStream_ReleaseFileFragment(stream_desc
->stream
, os2_context
);
1691 IDWriteFontFileStream_ReleaseFileFragment(stream_desc
->stream
, name_context
);
1696 /* FaceName locating order is WWS Face Name -> Preferred Face Name -> Face Name. If font claims to
1697 have 'Preferred Face Name' in WWS format, then WWS name is not used. */
1698 HRESULT
opentype_get_font_facename(struct file_stream_desc
*stream_desc
, WCHAR
*lfname
, IDWriteLocalizedStrings
**names
)
1700 IDWriteLocalizedStrings
*lfnames
;
1701 void *os2_context
, *name_context
;
1702 const TT_OS2_V2
*tt_os2
;
1703 const void *name_table
;
1706 opentype_get_font_table(stream_desc
, MS_OS2_TAG
, (const void**)&tt_os2
, &os2_context
, NULL
, NULL
);
1707 opentype_get_font_table(stream_desc
, MS_NAME_TAG
, &name_table
, &name_context
, NULL
, NULL
);
1711 /* if Preferred Family doesn't conform to WWS model try WWS name */
1712 if (tt_os2
&& !(GET_BE_WORD(tt_os2
->fsSelection
) & OS2_FSSELECTION_WWS
))
1713 hr
= opentype_get_font_strings_from_id(name_table
, OPENTYPE_STRING_WWS_SUBFAMILY_NAME
, names
);
1718 hr
= opentype_get_font_strings_from_id(name_table
, OPENTYPE_STRING_PREFERRED_SUBFAMILY_NAME
, names
);
1720 hr
= opentype_get_font_strings_from_id(name_table
, OPENTYPE_STRING_SUBFAMILY_NAME
, names
);
1722 /* User locale is preferred, with fallback to en-us. */
1724 if (SUCCEEDED(opentype_get_font_strings_from_id(name_table
, OPENTYPE_STRING_FAMILY_NAME
, &lfnames
))) {
1725 static const WCHAR enusW
[] = {'e','n','-','u','s',0};
1726 WCHAR localeW
[LOCALE_NAME_MAX_LENGTH
];
1731 if (GetSystemDefaultLocaleName(localeW
, sizeof(localeW
)/sizeof(WCHAR
)))
1732 IDWriteLocalizedStrings_FindLocaleName(lfnames
, localeW
, &index
, &exists
);
1735 IDWriteLocalizedStrings_FindLocaleName(lfnames
, enusW
, &index
, &exists
);
1738 IDWriteLocalizedStrings_GetString(lfnames
, index
, lfname
, LF_FACESIZE
);
1740 IDWriteLocalizedStrings_Release(lfnames
);
1744 IDWriteFontFileStream_ReleaseFileFragment(stream_desc
->stream
, os2_context
);
1746 IDWriteFontFileStream_ReleaseFileFragment(stream_desc
->stream
, name_context
);
1751 static inline const OT_Script
*opentype_get_script(const OT_ScriptList
*scriptlist
, UINT32 scripttag
)
1755 for (j
= 0; j
< GET_BE_WORD(scriptlist
->ScriptCount
); j
++) {
1756 const char *tag
= scriptlist
->ScriptRecord
[j
].ScriptTag
;
1757 if (scripttag
== DWRITE_MAKE_OPENTYPE_TAG(tag
[0], tag
[1], tag
[2], tag
[3]))
1758 return (OT_Script
*)((BYTE
*)scriptlist
+ GET_BE_WORD(scriptlist
->ScriptRecord
[j
].Script
));
1764 static inline const OT_LangSys
*opentype_get_langsys(const OT_Script
*script
, UINT32 languagetag
)
1768 for (j
= 0; j
< GET_BE_WORD(script
->LangSysCount
); j
++) {
1769 const char *tag
= script
->LangSysRecord
[j
].LangSysTag
;
1770 if (languagetag
== DWRITE_MAKE_OPENTYPE_TAG(tag
[0], tag
[1], tag
[2], tag
[3]))
1771 return (OT_LangSys
*)((BYTE
*)script
+ GET_BE_WORD(script
->LangSysRecord
[j
].LangSys
));
1777 static void opentype_add_font_features(const GPOS_GSUB_Header
*header
, const OT_LangSys
*langsys
,
1778 UINT32 max_tagcount
, UINT32
*count
, DWRITE_FONT_FEATURE_TAG
*tags
)
1780 const OT_FeatureList
*features
= (const OT_FeatureList
*)((const BYTE
*)header
+ GET_BE_WORD(header
->FeatureList
));
1783 for (j
= 0; j
< GET_BE_WORD(langsys
->FeatureCount
); j
++) {
1784 const OT_FeatureRecord
*feature
= &features
->FeatureRecord
[langsys
->FeatureIndex
[j
]];
1785 const char *tag
= feature
->FeatureTag
;
1787 if (*count
< max_tagcount
)
1788 tags
[*count
] = DWRITE_MAKE_OPENTYPE_TAG(tag
[0], tag
[1], tag
[2], tag
[3]);
1794 HRESULT
opentype_get_typographic_features(IDWriteFontFace
*fontface
, UINT32 scripttag
, UINT32 languagetag
, UINT32 max_tagcount
,
1795 UINT32
*count
, DWRITE_FONT_FEATURE_TAG
*tags
)
1797 UINT32 tables
[2] = { MS_GSUB_TAG
, MS_GPOS_TAG
};
1802 for (i
= 0; i
< sizeof(tables
)/sizeof(tables
[0]); i
++) {
1803 const OT_ScriptList
*scriptlist
;
1804 const GPOS_GSUB_Header
*header
;
1805 const OT_Script
*script
;
1812 hr
= IDWriteFontFace_TryGetFontTable(fontface
, tables
[i
], &ptr
, &size
, &context
, &exists
);
1819 header
= (const GPOS_GSUB_Header
*)ptr
;
1820 scriptlist
= (const OT_ScriptList
*)((const BYTE
*)header
+ GET_BE_WORD(header
->ScriptList
));
1822 script
= opentype_get_script(scriptlist
, scripttag
);
1824 const OT_LangSys
*langsys
= opentype_get_langsys(script
, languagetag
);
1826 opentype_add_font_features(header
, langsys
, max_tagcount
, count
, tags
);
1829 IDWriteFontFace_ReleaseFontTable(fontface
, context
);
1832 return *count
> max_tagcount
? E_NOT_SUFFICIENT_BUFFER
: S_OK
;
1835 static const struct VDMX_group
*find_vdmx_group(const struct VDMX_Header
*hdr
)
1837 WORD num_ratios
, i
, group_offset
= 0;
1838 struct VDMX_Ratio
*ratios
= (struct VDMX_Ratio
*)(hdr
+ 1);
1839 BYTE dev_x_ratio
= 1, dev_y_ratio
= 1;
1841 num_ratios
= GET_BE_WORD(hdr
->numRatios
);
1843 for (i
= 0; i
< num_ratios
; i
++) {
1845 if (!ratios
[i
].bCharSet
) continue;
1847 if ((ratios
[i
].xRatio
== 0 && ratios
[i
].yStartRatio
== 0 &&
1848 ratios
[i
].yEndRatio
== 0) ||
1849 (ratios
[i
].xRatio
== dev_x_ratio
&& ratios
[i
].yStartRatio
<= dev_y_ratio
&&
1850 ratios
[i
].yEndRatio
>= dev_y_ratio
))
1852 group_offset
= GET_BE_WORD(*((WORD
*)(ratios
+ num_ratios
) + i
));
1857 return (const struct VDMX_group
*)((BYTE
*)hdr
+ group_offset
);
1861 BOOL
opentype_get_vdmx_size(const void *data
, INT emsize
, UINT16
*ascent
, UINT16
*descent
)
1863 const struct VDMX_Header
*hdr
= (const struct VDMX_Header
*)data
;
1864 const struct VDMX_group
*group
;
1865 const struct VDMX_vTable
*tables
;
1871 group
= find_vdmx_group(hdr
);
1875 recs
= GET_BE_WORD(group
->recs
);
1876 if (emsize
< group
->startsz
|| emsize
>= group
->endsz
) return FALSE
;
1878 tables
= (const struct VDMX_vTable
*)(group
+ 1);
1879 for (i
= 0; i
< recs
; i
++) {
1880 WORD ppem
= GET_BE_WORD(tables
[i
].yPelHeight
);
1881 if (ppem
> emsize
) {
1882 FIXME("interpolate %d\n", emsize
);
1886 if (ppem
== emsize
) {
1887 *ascent
= (SHORT
)GET_BE_WORD(tables
[i
].yMax
);
1888 *descent
= -(SHORT
)GET_BE_WORD(tables
[i
].yMin
);
1895 WORD
opentype_get_gasp_flags(const WORD
*ptr
, UINT32 size
, INT emsize
)
1897 WORD num_recs
, version
;
1903 version
= GET_BE_WORD( *ptr
++ );
1904 num_recs
= GET_BE_WORD( *ptr
++ );
1905 if (version
> 1 || size
< (num_recs
* 2 + 2) * sizeof(WORD
)) {
1906 ERR("unsupported gasp table: ver %d size %d recs %d\n", version
, size
, num_recs
);
1910 while (num_recs
--) {
1911 flags
= GET_BE_WORD( *(ptr
+ 1) );
1912 if (emsize
<= GET_BE_WORD( *ptr
)) break;
1920 UINT32
opentype_get_cpal_palettecount(const void *cpal
)
1922 const struct CPAL_Header_0
*header
= (const struct CPAL_Header_0
*)cpal
;
1923 return header
? GET_BE_WORD(header
->numPalette
) : 0;
1926 UINT32
opentype_get_cpal_paletteentrycount(const void *cpal
)
1928 const struct CPAL_Header_0
*header
= (const struct CPAL_Header_0
*)cpal
;
1929 return header
? GET_BE_WORD(header
->numPaletteEntries
) : 0;
1932 HRESULT
opentype_get_cpal_entries(const void *cpal
, UINT32 palette
, UINT32 first_entry_index
, UINT32 entry_count
,
1933 DWRITE_COLOR_F
*entries
)
1935 const struct CPAL_Header_0
*header
= (const struct CPAL_Header_0
*)cpal
;
1936 const struct CPAL_ColorRecord
*records
;
1937 UINT32 palettecount
, entrycount
, i
;
1939 if (!header
) return DWRITE_E_NOCOLOR
;
1941 palettecount
= GET_BE_WORD(header
->numPalette
);
1942 if (palette
>= palettecount
)
1943 return DWRITE_E_NOCOLOR
;
1945 entrycount
= GET_BE_WORD(header
->numPaletteEntries
);
1946 if (first_entry_index
+ entry_count
> entrycount
)
1947 return E_INVALIDARG
;
1949 records
= (const struct CPAL_ColorRecord
*)((BYTE
*)cpal
+ GET_BE_DWORD(header
->offsetFirstColorRecord
));
1950 first_entry_index
+= GET_BE_WORD(header
->colorRecordIndices
[palette
]);
1952 for (i
= 0; i
< entry_count
; i
++) {
1953 entries
[i
].u1
.r
= records
[first_entry_index
+ i
].red
/ 255.0f
;
1954 entries
[i
].u2
.g
= records
[first_entry_index
+ i
].green
/ 255.0f
;
1955 entries
[i
].u3
.b
= records
[first_entry_index
+ i
].blue
/ 255.0f
;
1956 entries
[i
].u4
.a
= records
[first_entry_index
+ i
].alpha
/ 255.0f
;
1962 static int colr_compare_gid(const void *g
, const void *r
)
1964 const struct COLR_BaseGlyphRecord
*record
= r
;
1965 UINT16 glyph
= *(UINT16
*)g
, GID
= GET_BE_WORD(record
->GID
);
1970 else if (glyph
< GID
)
1976 HRESULT
opentype_get_colr_glyph(const void *colr
, UINT16 glyph
, struct dwrite_colorglyph
*ret
)
1978 const struct COLR_BaseGlyphRecord
*record
;
1979 const struct COLR_Header
*header
= colr
;
1980 const struct COLR_LayerRecord
*layer
;
1981 DWORD layerrecordoffset
= GET_BE_DWORD(header
->offsetLayerRecord
);
1982 DWORD baserecordoffset
= GET_BE_DWORD(header
->offsetBaseGlyphRecord
);
1983 WORD numbaserecords
= GET_BE_WORD(header
->numBaseGlyphRecords
);
1985 record
= bsearch(&glyph
, (BYTE
*)colr
+ baserecordoffset
, numbaserecords
, sizeof(struct COLR_BaseGlyphRecord
),
1989 ret
->first_layer
= 0;
1990 ret
->num_layers
= 0;
1992 ret
->palette_index
= 0xffff;
1997 ret
->first_layer
= GET_BE_WORD(record
->firstLayerIndex
);
1998 ret
->num_layers
= GET_BE_WORD(record
->numLayers
);
2000 layer
= (struct COLR_LayerRecord
*)((BYTE
*)colr
+ layerrecordoffset
) + ret
->first_layer
+ ret
->layer
;
2001 ret
->glyph
= GET_BE_WORD(layer
->GID
);
2002 ret
->palette_index
= GET_BE_WORD(layer
->paletteIndex
);
2007 void opentype_colr_next_glyph(const void *colr
, struct dwrite_colorglyph
*glyph
)
2009 const struct COLR_Header
*header
= colr
;
2010 const struct COLR_LayerRecord
*layer
;
2011 DWORD layerrecordoffset
= GET_BE_DWORD(header
->offsetLayerRecord
);
2013 /* iterated all the way through */
2014 if (glyph
->layer
== glyph
->num_layers
)
2018 layer
= (struct COLR_LayerRecord
*)((BYTE
*)colr
+ layerrecordoffset
) + glyph
->first_layer
+ glyph
->layer
;
2019 glyph
->glyph
= GET_BE_WORD(layer
->GID
);
2020 glyph
->palette_index
= GET_BE_WORD(layer
->paletteIndex
);
2023 BOOL
opentype_has_vertical_variants(IDWriteFontFace4
*fontface
)
2025 const OT_FeatureList
*featurelist
;
2026 const OT_LookupList
*lookup_list
;
2027 BOOL exists
= FALSE
, ret
= FALSE
;
2028 const GPOS_GSUB_Header
*header
;
2035 hr
= IDWriteFontFace4_TryGetFontTable(fontface
, MS_GSUB_TAG
, &data
, &size
, &context
, &exists
);
2036 if (FAILED(hr
) || !exists
)
2040 featurelist
= (OT_FeatureList
*)((BYTE
*)header
+ GET_BE_WORD(header
->FeatureList
));
2041 lookup_list
= (const OT_LookupList
*)((BYTE
*)header
+ GET_BE_WORD(header
->LookupList
));
2043 for (i
= 0; i
< GET_BE_WORD(featurelist
->FeatureCount
); i
++) {
2044 if (*(UINT32
*)featurelist
->FeatureRecord
[i
].FeatureTag
== DWRITE_FONT_FEATURE_TAG_VERTICAL_WRITING
) {
2045 const OT_Feature
*feature
= (const OT_Feature
*)((BYTE
*)featurelist
+ GET_BE_WORD(featurelist
->FeatureRecord
[i
].Feature
));
2046 UINT16 lookup_count
= GET_BE_WORD(feature
->LookupCount
), i
, index
, count
, type
;
2047 const GSUB_SingleSubstFormat2
*subst2
;
2048 const OT_LookupTable
*lookup_table
;
2051 if (lookup_count
== 0)
2054 for (i
= 0; i
< lookup_count
; i
++) {
2055 /* check if lookup is empty */
2056 index
= GET_BE_WORD(feature
->LookupListIndex
[i
]);
2057 lookup_table
= (const OT_LookupTable
*)((BYTE
*)lookup_list
+ GET_BE_WORD(lookup_list
->Lookup
[index
]));
2059 type
= GET_BE_WORD(lookup_table
->LookupType
);
2060 if (type
!= OPENTYPE_GPOS_SINGLE_SUBST
&& type
!= OPENTYPE_GPOS_EXTENSION_SUBST
)
2063 count
= GET_BE_WORD(lookup_table
->SubTableCount
);
2067 offset
= GET_BE_WORD(lookup_table
->SubTable
[0]);
2068 if (type
== OPENTYPE_GPOS_EXTENSION_SUBST
) {
2069 const GSUB_ExtensionPosFormat1
*ext
= (const GSUB_ExtensionPosFormat1
*)((const BYTE
*)lookup_table
+ offset
);
2070 if (GET_BE_WORD(ext
->SubstFormat
) == 1)
2071 offset
+= GET_BE_DWORD(ext
->ExtensionOffset
);
2073 FIXME("Unhandled Extension Substitution Format %u\n", GET_BE_WORD(ext
->SubstFormat
));
2076 subst2
= (const GSUB_SingleSubstFormat2
*)((BYTE
*)lookup_table
+ offset
);
2077 index
= GET_BE_WORD(subst2
->SubstFormat
);
2079 FIXME("Validate Single Substitution Format 1\n");
2080 else if (index
== 2) {
2081 /* SimSun-ExtB has 0 glyph count for this substitution */
2082 if (GET_BE_WORD(subst2
->GlyphCount
) > 0) {
2088 WARN("Unknown Single Substitution Format, %u\n", index
);
2093 IDWriteFontFace4_ReleaseFontTable(fontface
, context
);
2098 static BOOL
opentype_has_font_table(IDWriteFontFace4
*fontface
, UINT32 tag
)
2100 BOOL exists
= FALSE
;
2106 hr
= IDWriteFontFace4_TryGetFontTable(fontface
, tag
, &data
, &size
, &context
, &exists
);
2111 IDWriteFontFace4_ReleaseFontTable(fontface
, context
);
2116 static DWORD
opentype_get_sbix_formats(IDWriteFontFace4
*fontface
)
2118 UINT32 size
, s
, num_strikes
;
2119 const sbix_header
*header
;
2120 UINT16 g
, num_glyphs
;
2121 BOOL exists
= FALSE
;
2128 hr
= IDWriteFontFace4_TryGetFontTable(fontface
, MS_MAXP_TAG
, &data
, &size
, &context
, &exists
);
2129 if (FAILED(hr
) || !exists
)
2133 num_glyphs
= GET_BE_WORD(maxp
->numGlyphs
);
2135 IDWriteFontFace4_ReleaseFontTable(fontface
, context
);
2137 if (FAILED(IDWriteFontFace4_TryGetFontTable(fontface
, MS_SBIX_TAG
, &data
, &size
, &context
, &exists
))) {
2138 WARN("Failed to get 'sbix' table, %#x\n", hr
);
2143 num_strikes
= GET_BE_DWORD(header
->numStrikes
);
2145 for (s
= 0; s
< num_strikes
; s
++) {
2146 sbix_strike
*strike
= (sbix_strike
*)((BYTE
*)header
+ GET_BE_DWORD(header
->strikeOffset
[s
]));
2148 for (g
= 0; g
< num_glyphs
; g
++) {
2149 DWORD offset
= GET_BE_DWORD(strike
->glyphDataOffsets
[g
]);
2150 DWORD offset_next
= GET_BE_DWORD(strike
->glyphDataOffsets
[g
+ 1]);
2151 sbix_glyph_data
*glyph_data
;
2154 if (offset
== offset_next
)
2157 glyph_data
= (sbix_glyph_data
*)((BYTE
*)strike
+ offset
);
2158 switch (format
= glyph_data
->graphicType
)
2161 ret
|= DWRITE_GLYPH_IMAGE_FORMATS_PNG
;
2164 ret
|= DWRITE_GLYPH_IMAGE_FORMATS_JPEG
;
2167 ret
|= DWRITE_GLYPH_IMAGE_FORMATS_TIFF
;
2170 format
= GET_BE_DWORD(format
);
2171 FIXME("unexpected bitmap format %s\n", debugstr_an((char *)&format
, 4));
2176 IDWriteFontFace4_ReleaseFontTable(fontface
, context
);
2181 static UINT32
opentype_get_cblc_formats(IDWriteFontFace4
*fontface
)
2183 CBLCBitmapSizeTable
*sizes
;
2184 UINT32 num_sizes
, size
, s
;
2185 BOOL exists
= FALSE
;
2191 if (FAILED(hr
= IDWriteFontFace4_TryGetFontTable(fontface
, MS_CBLC_TAG
, (const void **)&header
, &size
,
2192 &context
, &exists
)))
2198 num_sizes
= GET_BE_DWORD(header
->numSizes
);
2199 sizes
= (CBLCBitmapSizeTable
*)(header
+ 1);
2201 for (s
= 0; s
< num_sizes
; s
++) {
2202 BYTE bpp
= sizes
->bitDepth
;
2204 if (bpp
== 1 || bpp
== 2 || bpp
== 4 || bpp
== 8)
2205 ret
|= DWRITE_GLYPH_IMAGE_FORMATS_PNG
;
2207 ret
|= DWRITE_GLYPH_IMAGE_FORMATS_PREMULTIPLIED_B8G8R8A8
;
2210 IDWriteFontFace4_ReleaseFontTable(fontface
, context
);
2215 UINT32
opentype_get_glyph_image_formats(IDWriteFontFace4
*fontface
)
2217 UINT32 ret
= DWRITE_GLYPH_IMAGE_FORMATS_NONE
;
2219 if (opentype_has_font_table(fontface
, MS_GLYF_TAG
))
2220 ret
|= DWRITE_GLYPH_IMAGE_FORMATS_TRUETYPE
;
2222 if (opentype_has_font_table(fontface
, MS_CFF__TAG
) ||
2223 opentype_has_font_table(fontface
, MS_CFF2_TAG
))
2224 ret
|= DWRITE_GLYPH_IMAGE_FORMATS_CFF
;
2226 if (opentype_has_font_table(fontface
, MS_COLR_TAG
))
2227 ret
|= DWRITE_GLYPH_IMAGE_FORMATS_COLR
;
2229 if (opentype_has_font_table(fontface
, MS_SVG__TAG
))
2230 ret
|= DWRITE_GLYPH_IMAGE_FORMATS_SVG
;
2232 if (opentype_has_font_table(fontface
, MS_SBIX_TAG
))
2233 ret
|= opentype_get_sbix_formats(fontface
);
2235 if (opentype_has_font_table(fontface
, MS_CBLC_TAG
))
2236 ret
|= opentype_get_cblc_formats(fontface
);
2241 DWRITE_CONTAINER_TYPE
opentype_analyze_container_type(void const *data
, UINT32 data_size
)
2245 if (data_size
< sizeof(DWORD
))
2246 return DWRITE_CONTAINER_TYPE_UNKNOWN
;
2248 /* Both WOFF and WOFF2 start with 4 bytes signature. */
2249 signature
= *(DWORD
*)data
;
2254 return DWRITE_CONTAINER_TYPE_WOFF
;
2256 return DWRITE_CONTAINER_TYPE_WOFF2
;
2258 return DWRITE_CONTAINER_TYPE_UNKNOWN
;