[PATCH 4/6] gdi32: Try to parse font names without FreeType.
Rémi Bernon
rbernon at codeweavers.com
Tue Dec 1 08:54:49 CST 2020
Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
---
dlls/gdi32/freetype.c | 131 ++++++++++-
dlls/gdi32/gdi_private.h | 18 ++
dlls/gdi32/opentype.c | 459 +++++++++++++++++++++++++++++++++++++++
3 files changed, 603 insertions(+), 5 deletions(-)
diff --git a/dlls/gdi32/freetype.c b/dlls/gdi32/freetype.c
index 686f2b54682..06bc29ff86a 100644
--- a/dlls/gdi32/freetype.c
+++ b/dlls/gdi32/freetype.c
@@ -1092,6 +1092,86 @@ fail:
return NULL;
}
+struct family_names_data
+{
+ LANGID primary_langid;
+ struct opentype_name family_name;
+ struct opentype_name second_name;
+ BOOL primary_seen;
+ BOOL english_seen;
+};
+
+static BOOL search_family_names_callback( LANGID langid, struct opentype_name *name, void *user )
+{
+ struct family_names_data *data = user;
+
+ if (langid == MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT))
+ {
+ data->english_seen = TRUE;
+ if (data->primary_langid == langid) data->primary_seen = TRUE;
+
+ if (!data->family_name.bytes) data->family_name = *name;
+ else if (data->primary_langid != langid) data->second_name = *name;
+ }
+ else if (data->primary_langid == langid)
+ {
+ data->primary_seen = TRUE;
+ if (!data->second_name.bytes) data->second_name = data->family_name;
+ data->family_name = *name;
+ }
+ else if (!data->second_name.bytes) data->second_name = *name;
+
+ if (data->family_name.bytes && data->second_name.bytes && data->primary_seen && data->english_seen)
+ return TRUE;
+ return FALSE;
+}
+
+struct face_name_data
+{
+ LANGID primary_langid;
+ struct opentype_name face_name;;
+};
+
+static BOOL search_face_name_callback( LANGID langid, struct opentype_name *name, void *user )
+{
+ struct face_name_data *data = user;
+
+ if (langid == data->primary_langid || (langid == MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT) && !data->face_name.bytes))
+ data->face_name = *name;
+
+ return langid == data->primary_langid;
+}
+
+static WCHAR *decode_opentype_name( struct opentype_name *name )
+{
+ CPTABLEINFO codepage_info;
+ USHORT *codepage_ptr;
+ SIZE_T codepage_size;
+ WCHAR buffer[512];
+ DWORD len;
+
+ if (!name->codepage)
+ {
+ len = min( ARRAY_SIZE(buffer), name->length / sizeof(WCHAR) );
+ while (len--) buffer[len] = GET_BE_WORD( ((WORD *)name->bytes)[len] );
+ len = min( ARRAY_SIZE(buffer), name->length / sizeof(WCHAR) );
+ }
+ else
+ {
+ NtGetNlsSectionPtr( 11, name->codepage, NULL, (void **)&codepage_ptr, &codepage_size );
+ RtlInitCodePageTable( codepage_ptr, &codepage_info );
+ RtlCustomCPToUnicodeN( &codepage_info, buffer, sizeof(buffer), &len, name->bytes, name->length );
+ len /= sizeof(WCHAR);
+ NtUnmapViewOfSection( GetCurrentProcess(), codepage_ptr );
+ }
+
+ buffer[ARRAY_SIZE(buffer) - 1] = 0;
+ if (len == ARRAY_SIZE(buffer)) WARN("Truncated font name %s -> %s\n", debugstr_an(name->bytes, name->length), debugstr_w(buffer));
+ else buffer[len] = 0;
+
+ return strdupW( buffer );
+}
+
struct unix_face
{
FT_Face ft_face;
@@ -1110,11 +1190,14 @@ struct unix_face
static struct unix_face *unix_face_create( const char *unix_name, void *data_ptr, DWORD data_size,
UINT face_index, DWORD flags )
{
+ static const WCHAR space_w[] = {' ',0};
+
const struct ttc_sfnt_v1 *ttc_sfnt_v1;
+ const struct tt_name_v0 *tt_name_v0;
struct unix_face *This;
struct stat st;
DWORD face_count;
- int fd;
+ int fd, length;
TRACE( "unix_name %s, face_index %u, data_ptr %p, data_size %u, flags %#x\n",
unix_name, face_index, data_ptr, data_size, flags );
@@ -1140,20 +1223,55 @@ static struct unix_face *unix_face_create( const char *unix_name, void *data_ptr
RtlFreeHeap( GetProcessHeap(), 0, This );
This = NULL;
}
- else if (opentype_get_ttc_sfnt_v1( data_ptr, data_size, face_index, &face_count, &ttc_sfnt_v1 ))
+ else if (opentype_get_ttc_sfnt_v1( data_ptr, data_size, face_index, &face_count, &ttc_sfnt_v1 ) &&
+ opentype_get_tt_name_v0( data_ptr, data_size, ttc_sfnt_v1, &tt_name_v0 ))
{
+ struct family_names_data family_names;
+ struct face_name_data style_name;
+ struct face_name_data full_name;
+ LANGID primary_langid = system_lcid;
+
This->scalable = TRUE;
This->num_faces = face_count;
+
+ memset( &family_names, 0, sizeof(family_names) );
+ family_names.primary_langid = primary_langid;
+ opentype_enum_family_names( tt_name_v0, search_family_names_callback, &family_names );
+ This->family_name = decode_opentype_name( &family_names.family_name );
+ This->second_name = decode_opentype_name( &family_names.second_name );
+
+ memset( &style_name, 0, sizeof(style_name) );
+ style_name.primary_langid = primary_langid;
+ opentype_enum_style_names( tt_name_v0, search_face_name_callback, &style_name );
+ This->style_name = decode_opentype_name( &style_name.face_name );
+
+ memset( &full_name, 0, sizeof(full_name) );
+ style_name.primary_langid = primary_langid;
+ opentype_enum_full_names( tt_name_v0, search_face_name_callback, &full_name );
+ This->full_name = decode_opentype_name( &full_name.face_name );
+
+ TRACE( "parsed font names family_name %s, second_name %s, primary_seen %d, english_seen %d, "
+ "full_name %s, style_name %s\n",
+ debugstr_w(This->family_name), debugstr_w(This->second_name),
+ family_names.primary_seen, family_names.english_seen,
+ debugstr_w(This->full_name), debugstr_w(This->style_name) );
+
+ if (!This->full_name && This->family_name && This->style_name)
+ {
+ length = lstrlenW( This->family_name ) + lstrlenW( space_w ) + lstrlenW( This->style_name ) + 1;
+ This->full_name = RtlAllocateHeap( GetProcessHeap(), 0, length * sizeof(WCHAR) );
+ lstrcpyW( This->full_name, This->family_name );
+ lstrcatW( This->full_name, space_w );
+ lstrcatW( This->full_name, This->style_name );
+ WARN( "full name not found, using %s instead\n", debugstr_w(This->full_name) );
+ }
}
else
{
WARN( "unable to parse font, falling back to FreeType\n" );
This->scalable = FT_IS_SCALABLE( This->ft_face );
This->num_faces = This->ft_face->num_faces;
- }
- if (This)
- {
This->family_name = ft_face_get_family_name( This->ft_face, system_lcid );
This->second_name = ft_face_get_family_name( This->ft_face, MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT) );
@@ -1173,7 +1291,10 @@ static struct unix_face *unix_face_create( const char *unix_name, void *data_ptr
This->style_name = ft_face_get_style_name( This->ft_face, system_lcid );
This->full_name = ft_face_get_full_name( This->ft_face, system_lcid );
+ }
+ if (This)
+ {
This->ntm_flags = get_ntm_flags( This->ft_face );
This->font_version = get_font_version( This->ft_face );
if (!This->scalable) get_bitmap_size( This->ft_face, &This->size );
diff --git a/dlls/gdi32/gdi_private.h b/dlls/gdi32/gdi_private.h
index a529cb0890c..9a988d08d7e 100644
--- a/dlls/gdi32/gdi_private.h
+++ b/dlls/gdi32/gdi_private.h
@@ -417,9 +417,27 @@ extern void font_init(void) DECLSPEC_HIDDEN;
/* opentype.c */
struct ttc_sfnt_v1;
+struct tt_name_v0;
+
+struct opentype_name
+{
+ DWORD codepage;
+ DWORD length;
+ const void *bytes;
+};
extern BOOL opentype_get_ttc_sfnt_v1( const void *data, size_t size, DWORD index, DWORD *count,
const struct ttc_sfnt_v1 **ttc_sfnt_v1 ) DECLSPEC_HIDDEN;
+extern BOOL opentype_get_tt_name_v0( const void *data, size_t size, const struct ttc_sfnt_v1 *ttc_sfnt_v1,
+ const struct tt_name_v0 **tt_name_v0 ) DECLSPEC_HIDDEN;
+
+typedef BOOL ( *opentype_enum_names_cb )( LANGID langid, struct opentype_name *name, void *user );
+extern BOOL opentype_enum_family_names( const struct tt_name_v0 *tt_name_v0,
+ opentype_enum_names_cb callback, void *user ) DECLSPEC_HIDDEN;
+extern BOOL opentype_enum_style_names( const struct tt_name_v0 *tt_name_v0,
+ opentype_enum_names_cb callback, void *user ) DECLSPEC_HIDDEN;
+extern BOOL opentype_enum_full_names( const struct tt_name_v0 *tt_name_v0,
+ opentype_enum_names_cb callback, void *user ) DECLSPEC_HIDDEN;
/* gdiobj.c */
extern HGDIOBJ alloc_gdi_handle( void *obj, WORD type, const struct gdi_obj_funcs *funcs ) DECLSPEC_HIDDEN;
diff --git a/dlls/gdi32/opentype.c b/dlls/gdi32/opentype.c
index 2363439cdc5..4200b08d318 100644
--- a/dlls/gdi32/opentype.c
+++ b/dlls/gdi32/opentype.c
@@ -26,6 +26,7 @@
#include "windef.h"
#include "winbase.h"
+#include "winnls.h"
#include "wine/debug.h"
@@ -40,6 +41,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(font);
#define MS_EBSC_TAG MS_MAKE_TAG('E','B','S','C')
#define MS_EBDT_TAG MS_MAKE_TAG('E','B','D','T')
#define MS_CBDT_TAG MS_MAKE_TAG('C','B','D','T')
+#define MS_NAME_TAG MS_MAKE_TAG('n','a','m','e')
#ifdef WORDS_BIGENDIAN
#define GET_BE_WORD(x) (x)
@@ -115,8 +117,125 @@ struct tt_os2_v1
ULONG ulCodePageRange1;
ULONG ulCodePageRange2;
};
+
+struct tt_namerecord
+{
+ WORD platformID;
+ WORD encodingID;
+ WORD languageID;
+ WORD nameID;
+ WORD length;
+ WORD offset;
+};
+
+struct tt_name_v0
+{
+ WORD format;
+ WORD count;
+ WORD stringOffset;
+ struct tt_namerecord nameRecord[1];
+};
#include "poppack.h"
+enum OPENTYPE_PLATFORM_ID
+{
+ OPENTYPE_PLATFORM_UNICODE = 0,
+ OPENTYPE_PLATFORM_MAC,
+ OPENTYPE_PLATFORM_ISO,
+ OPENTYPE_PLATFORM_WIN,
+ OPENTYPE_PLATFORM_CUSTOM
+};
+
+enum TT_NAME_WIN_ENCODING_ID
+{
+ TT_NAME_WIN_ENCODING_SYMBOL = 0,
+ TT_NAME_WIN_ENCODING_UNICODE_BMP,
+ TT_NAME_WIN_ENCODING_SJIS,
+ TT_NAME_WIN_ENCODING_PRC,
+ TT_NAME_WIN_ENCODING_BIG5,
+ TT_NAME_WIN_ENCODING_WANSUNG,
+ TT_NAME_WIN_ENCODING_JOHAB,
+ TT_NAME_WIN_ENCODING_RESERVED1,
+ TT_NAME_WIN_ENCODING_RESERVED2,
+ TT_NAME_WIN_ENCODING_RESERVED3,
+ TT_NAME_WIN_ENCODING_UNICODE_FULL
+};
+
+enum TT_NAME_UNICODE_ENCODING_ID
+{
+ TT_NAME_UNICODE_ENCODING_1_0 = 0,
+ TT_NAME_UNICODE_ENCODING_1_1,
+ TT_NAME_UNICODE_ENCODING_ISO_10646,
+ TT_NAME_UNICODE_ENCODING_2_0_BMP,
+ TT_NAME_UNICODE_ENCODING_2_0_FULL,
+ TT_NAME_UNICODE_ENCODING_VAR,
+ TT_NAME_UNICODE_ENCODING_FULL,
+};
+
+enum TT_NAME_MAC_ENCODING_ID
+{
+ TT_NAME_MAC_ENCODING_ROMAN = 0,
+ TT_NAME_MAC_ENCODING_JAPANESE,
+ TT_NAME_MAC_ENCODING_TRAD_CHINESE,
+ TT_NAME_MAC_ENCODING_KOREAN,
+ TT_NAME_MAC_ENCODING_ARABIC,
+ TT_NAME_MAC_ENCODING_HEBREW,
+ TT_NAME_MAC_ENCODING_GREEK,
+ TT_NAME_MAC_ENCODING_RUSSIAN,
+ TT_NAME_MAC_ENCODING_RSYMBOL,
+ TT_NAME_MAC_ENCODING_DEVANAGARI,
+ TT_NAME_MAC_ENCODING_GURMUKHI,
+ TT_NAME_MAC_ENCODING_GUJARATI,
+ TT_NAME_MAC_ENCODING_ORIYA,
+ TT_NAME_MAC_ENCODING_BENGALI,
+ TT_NAME_MAC_ENCODING_TAMIL,
+ TT_NAME_MAC_ENCODING_TELUGU,
+ TT_NAME_MAC_ENCODING_KANNADA,
+ TT_NAME_MAC_ENCODING_MALAYALAM,
+ TT_NAME_MAC_ENCODING_SINHALESE,
+ TT_NAME_MAC_ENCODING_BURMESE,
+ TT_NAME_MAC_ENCODING_KHMER,
+ TT_NAME_MAC_ENCODING_THAI,
+ TT_NAME_MAC_ENCODING_LAOTIAN,
+ TT_NAME_MAC_ENCODING_GEORGIAN,
+ TT_NAME_MAC_ENCODING_ARMENIAN,
+ TT_NAME_MAC_ENCODING_SIMPL_CHINESE,
+ TT_NAME_MAC_ENCODING_TIBETAN,
+ TT_NAME_MAC_ENCODING_MONGOLIAN,
+ TT_NAME_MAC_ENCODING_GEEZ,
+ TT_NAME_MAC_ENCODING_SLAVIC,
+ TT_NAME_MAC_ENCODING_VIETNAMESE,
+ TT_NAME_MAC_ENCODING_SINDHI,
+ TT_NAME_MAC_ENCODING_UNINTERPRETED
+};
+
+enum OPENTYPE_NAME_ID
+{
+ OPENTYPE_NAME_COPYRIGHT_NOTICE = 0,
+ OPENTYPE_NAME_FAMILY,
+ OPENTYPE_NAME_SUBFAMILY,
+ OPENTYPE_NAME_UNIQUE_IDENTIFIER,
+ OPENTYPE_NAME_FULLNAME,
+ OPENTYPE_NAME_VERSION_STRING,
+ OPENTYPE_NAME_POSTSCRIPT,
+ OPENTYPE_NAME_TRADEMARK,
+ OPENTYPE_NAME_MANUFACTURER,
+ OPENTYPE_NAME_DESIGNER,
+ OPENTYPE_NAME_DESCRIPTION,
+ OPENTYPE_NAME_VENDOR_URL,
+ OPENTYPE_NAME_DESIGNER_URL,
+ OPENTYPE_NAME_LICENSE_DESCRIPTION,
+ OPENTYPE_NAME_LICENSE_INFO_URL,
+ OPENTYPE_NAME_RESERVED_ID15,
+ OPENTYPE_NAME_TYPOGRAPHIC_FAMILY,
+ OPENTYPE_NAME_TYPOGRAPHIC_SUBFAMILY,
+ OPENTYPE_NAME_COMPATIBLE_FULLNAME,
+ OPENTYPE_NAME_SAMPLE_TEXT,
+ OPENTYPE_NAME_POSTSCRIPT_CID,
+ OPENTYPE_NAME_WWS_FAMILY,
+ OPENTYPE_NAME_WWS_SUBFAMILY
+};
+
static BOOL opentype_get_table_ptr( const void *data, size_t size, const struct ttc_sfnt_v1 *ttc_sfnt_v1,
UINT32 table_tag, const void **table_ptr, UINT32 *table_size )
{
@@ -151,6 +270,306 @@ static BOOL opentype_get_tt_os2_v1( const void *data, size_t size, const struct
return opentype_get_table_ptr( data, size, ttc_sfnt_v1, MS_OS_2_TAG, (const void **)tt_os2_v1, &table_size );
}
+static UINT get_name_record_codepage( enum OPENTYPE_PLATFORM_ID platform, USHORT encoding )
+{
+ switch (platform)
+ {
+ case OPENTYPE_PLATFORM_UNICODE:
+ return 0;
+ case OPENTYPE_PLATFORM_MAC:
+ switch (encoding)
+ {
+ case TT_NAME_MAC_ENCODING_ROMAN:
+ return 10000;
+ case TT_NAME_MAC_ENCODING_JAPANESE:
+ return 10001;
+ case TT_NAME_MAC_ENCODING_TRAD_CHINESE:
+ return 10002;
+ case TT_NAME_MAC_ENCODING_KOREAN:
+ return 10003;
+ case TT_NAME_MAC_ENCODING_ARABIC:
+ return 10004;
+ case TT_NAME_MAC_ENCODING_HEBREW:
+ return 10005;
+ case TT_NAME_MAC_ENCODING_GREEK:
+ return 10006;
+ case TT_NAME_MAC_ENCODING_RUSSIAN:
+ return 10007;
+ case TT_NAME_MAC_ENCODING_SIMPL_CHINESE:
+ return 10008;
+ case TT_NAME_MAC_ENCODING_THAI:
+ return 10021;
+ default:
+ FIXME( "encoding %u not handled, platform %d.\n", encoding, platform );
+ break;
+ }
+ break;
+ case OPENTYPE_PLATFORM_WIN:
+ switch (encoding)
+ {
+ case TT_NAME_WIN_ENCODING_SYMBOL:
+ case TT_NAME_WIN_ENCODING_UNICODE_BMP:
+ case TT_NAME_WIN_ENCODING_UNICODE_FULL:
+ return 0;
+ case TT_NAME_WIN_ENCODING_SJIS:
+ return 932;
+ case TT_NAME_WIN_ENCODING_PRC:
+ return 936;
+ case TT_NAME_WIN_ENCODING_BIG5:
+ return 950;
+ case TT_NAME_WIN_ENCODING_WANSUNG:
+ return 20949;
+ case TT_NAME_WIN_ENCODING_JOHAB:
+ return 1361;
+ default:
+ FIXME( "encoding %u not handled, platform %d.\n", encoding, platform );
+ break;
+ }
+ break;
+ default:
+ FIXME( "unknown platform %d\n", platform );
+ break;
+ }
+
+ return 0;
+}
+
+static const LANGID mac_langid_table[] =
+{
+ MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT),
+ MAKELANGID(LANG_FRENCH, SUBLANG_DEFAULT),
+ MAKELANGID(LANG_GERMAN, SUBLANG_DEFAULT),
+ MAKELANGID(LANG_ITALIAN, SUBLANG_DEFAULT),
+ MAKELANGID(LANG_DUTCH, SUBLANG_DEFAULT),
+ MAKELANGID(LANG_SWEDISH, SUBLANG_DEFAULT),
+ MAKELANGID(LANG_SPANISH, SUBLANG_DEFAULT),
+ MAKELANGID(LANG_DANISH, SUBLANG_DEFAULT),
+ MAKELANGID(LANG_PORTUGUESE, SUBLANG_DEFAULT),
+ MAKELANGID(LANG_NORWEGIAN, SUBLANG_DEFAULT),
+ MAKELANGID(LANG_HEBREW, SUBLANG_DEFAULT),
+ MAKELANGID(LANG_JAPANESE, SUBLANG_DEFAULT),
+ MAKELANGID(LANG_ARABIC, SUBLANG_DEFAULT),
+ MAKELANGID(LANG_FINNISH, SUBLANG_DEFAULT),
+ MAKELANGID(LANG_GREEK, SUBLANG_DEFAULT),
+ MAKELANGID(LANG_ICELANDIC, SUBLANG_DEFAULT),
+ MAKELANGID(LANG_MALTESE, SUBLANG_DEFAULT),
+ MAKELANGID(LANG_TURKISH, SUBLANG_DEFAULT),
+ MAKELANGID(LANG_CROATIAN, SUBLANG_DEFAULT),
+ MAKELANGID(LANG_CHINESE_TRADITIONAL, SUBLANG_DEFAULT),
+ MAKELANGID(LANG_URDU, SUBLANG_DEFAULT),
+ MAKELANGID(LANG_HINDI, SUBLANG_DEFAULT),
+ MAKELANGID(LANG_THAI, SUBLANG_DEFAULT),
+ MAKELANGID(LANG_KOREAN, SUBLANG_DEFAULT),
+ MAKELANGID(LANG_LITHUANIAN, SUBLANG_DEFAULT),
+ MAKELANGID(LANG_POLISH, SUBLANG_DEFAULT),
+ MAKELANGID(LANG_HUNGARIAN, SUBLANG_DEFAULT),
+ MAKELANGID(LANG_ESTONIAN, SUBLANG_DEFAULT),
+ MAKELANGID(LANG_LATVIAN, SUBLANG_DEFAULT),
+ MAKELANGID(LANG_SAMI, SUBLANG_DEFAULT),
+ MAKELANGID(LANG_FAEROESE, SUBLANG_DEFAULT),
+ MAKELANGID(LANG_FARSI, SUBLANG_DEFAULT),
+ MAKELANGID(LANG_RUSSIAN, SUBLANG_DEFAULT),
+ MAKELANGID(LANG_CHINESE_SIMPLIFIED, SUBLANG_DEFAULT),
+ MAKELANGID(LANG_DUTCH, SUBLANG_DUTCH_BELGIAN),
+ MAKELANGID(LANG_IRISH, SUBLANG_DEFAULT),
+ MAKELANGID(LANG_ALBANIAN, SUBLANG_DEFAULT),
+ MAKELANGID(LANG_ROMANIAN, SUBLANG_DEFAULT),
+ MAKELANGID(LANG_CZECH, SUBLANG_DEFAULT),
+ MAKELANGID(LANG_SLOVAK, SUBLANG_DEFAULT),
+ MAKELANGID(LANG_SLOVENIAN, SUBLANG_DEFAULT),
+ 0,
+ MAKELANGID(LANG_SERBIAN, SUBLANG_DEFAULT),
+ MAKELANGID(LANG_MACEDONIAN, SUBLANG_DEFAULT),
+ MAKELANGID(LANG_BULGARIAN, SUBLANG_DEFAULT),
+ MAKELANGID(LANG_UKRAINIAN, SUBLANG_DEFAULT),
+ MAKELANGID(LANG_BELARUSIAN, SUBLANG_DEFAULT),
+ MAKELANGID(LANG_UZBEK, SUBLANG_DEFAULT),
+ MAKELANGID(LANG_KAZAK, SUBLANG_DEFAULT),
+ MAKELANGID(LANG_AZERI, SUBLANG_AZERI_CYRILLIC),
+ 0,
+ MAKELANGID(LANG_ARMENIAN, SUBLANG_DEFAULT),
+ MAKELANGID(LANG_GEORGIAN, SUBLANG_DEFAULT),
+ 0,
+ MAKELANGID(LANG_KYRGYZ, SUBLANG_DEFAULT),
+ MAKELANGID(LANG_TAJIK, SUBLANG_DEFAULT),
+ MAKELANGID(LANG_TURKMEN, SUBLANG_DEFAULT),
+ MAKELANGID(LANG_MONGOLIAN, SUBLANG_DEFAULT),
+ MAKELANGID(LANG_MONGOLIAN, SUBLANG_MONGOLIAN_CYRILLIC_MONGOLIA),
+ MAKELANGID(LANG_PASHTO, SUBLANG_DEFAULT),
+ 0,
+ MAKELANGID(LANG_KASHMIRI, SUBLANG_DEFAULT),
+ MAKELANGID(LANG_SINDHI, SUBLANG_DEFAULT),
+ MAKELANGID(LANG_TIBETAN, SUBLANG_DEFAULT),
+ MAKELANGID(LANG_NEPALI, SUBLANG_DEFAULT),
+ MAKELANGID(LANG_SANSKRIT, SUBLANG_DEFAULT),
+ MAKELANGID(LANG_MARATHI, SUBLANG_DEFAULT),
+ MAKELANGID(LANG_BENGALI, SUBLANG_DEFAULT),
+ MAKELANGID(LANG_ASSAMESE, SUBLANG_DEFAULT),
+ MAKELANGID(LANG_GUJARATI, SUBLANG_DEFAULT),
+ MAKELANGID(LANG_PUNJABI, SUBLANG_DEFAULT),
+ MAKELANGID(LANG_ORIYA, SUBLANG_DEFAULT),
+ MAKELANGID(LANG_MALAYALAM, SUBLANG_DEFAULT),
+ MAKELANGID(LANG_KANNADA, SUBLANG_DEFAULT),
+ MAKELANGID(LANG_TAMIL, SUBLANG_DEFAULT),
+ MAKELANGID(LANG_TELUGU, SUBLANG_DEFAULT),
+ MAKELANGID(LANG_SINHALESE, SUBLANG_DEFAULT),
+ 0,
+ MAKELANGID(LANG_KHMER, SUBLANG_DEFAULT),
+ MAKELANGID(LANG_LAO, SUBLANG_DEFAULT),
+ MAKELANGID(LANG_VIETNAMESE, SUBLANG_DEFAULT),
+ MAKELANGID(LANG_INDONESIAN, SUBLANG_DEFAULT),
+ 0,
+ MAKELANGID(LANG_MALAY, SUBLANG_DEFAULT),
+ 0,
+ MAKELANGID(LANG_AMHARIC, SUBLANG_DEFAULT),
+ MAKELANGID(LANG_TIGRIGNA, SUBLANG_DEFAULT),
+ 0,
+ 0,
+ MAKELANGID(LANG_SWAHILI, SUBLANG_DEFAULT),
+ 0,
+ 0,
+ 0,
+ MAKELANGID(LANG_MALAGASY, SUBLANG_DEFAULT),
+ MAKELANGID(LANG_ESPERANTO, SUBLANG_DEFAULT),
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ MAKELANGID(LANG_WELSH, SUBLANG_DEFAULT),
+ MAKELANGID(LANG_BASQUE, SUBLANG_DEFAULT),
+ MAKELANGID(LANG_CATALAN, SUBLANG_DEFAULT),
+ 0,
+ MAKELANGID(LANG_QUECHUA, SUBLANG_DEFAULT),
+ 0,
+ 0,
+ MAKELANGID(LANG_TATAR, SUBLANG_DEFAULT),
+ MAKELANGID(LANG_UIGHUR, SUBLANG_DEFAULT),
+ 0,
+ 0,
+ 0,
+ MAKELANGID(LANG_GALICIAN, SUBLANG_DEFAULT),
+ MAKELANGID(LANG_AFRIKAANS, SUBLANG_DEFAULT),
+ MAKELANGID(LANG_BRETON, SUBLANG_DEFAULT),
+ MAKELANGID(LANG_INUKTITUT, SUBLANG_DEFAULT),
+ MAKELANGID(LANG_SCOTTISH_GAELIC, SUBLANG_DEFAULT),
+ MAKELANGID(LANG_MANX_GAELIC, SUBLANG_DEFAULT),
+ MAKELANGID(LANG_IRISH, SUBLANG_IRISH_IRELAND),
+ 0,
+ 0,
+ MAKELANGID(LANG_GREENLANDIC, SUBLANG_DEFAULT),
+ MAKELANGID(LANG_AZERI, SUBLANG_AZERI_LATIN),
+};
+
+static LANGID get_name_record_langid( enum OPENTYPE_PLATFORM_ID platform, USHORT encoding, USHORT language )
+{
+ switch (platform)
+ {
+ case OPENTYPE_PLATFORM_WIN:
+ return language;
+ case OPENTYPE_PLATFORM_MAC:
+ if (language < ARRAY_SIZE(mac_langid_table)) return mac_langid_table[language];
+ WARN( "invalid mac lang id %d\n", language );
+ break;
+ case OPENTYPE_PLATFORM_UNICODE:
+ switch (encoding)
+ {
+ case TT_NAME_UNICODE_ENCODING_1_0:
+ case TT_NAME_UNICODE_ENCODING_ISO_10646:
+ case TT_NAME_UNICODE_ENCODING_2_0_BMP:
+ if (language < ARRAY_SIZE(mac_langid_table)) return mac_langid_table[language];
+ WARN( "invalid unicode lang id %d\n", language );
+ break;
+ default:
+ break;
+ }
+ default:
+ FIXME( "unknown platform %d\n", platform );
+ break;
+ }
+
+ return MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL);
+}
+
+static BOOL opentype_enum_font_names( const struct tt_name_v0 *header, enum OPENTYPE_PLATFORM_ID platform,
+ enum OPENTYPE_NAME_ID name, opentype_enum_names_cb callback, void *user )
+{
+ const char *name_data;
+ USHORT i, name_count, encoding, language, length, offset;
+ USHORT platform_id = GET_BE_WORD( platform ), name_id = GET_BE_WORD( name );
+ LANGID langid;
+ BOOL ret = FALSE;
+
+ switch (GET_BE_WORD( header->format ))
+ {
+ case 0:
+ case 1:
+ break;
+ default:
+ FIXME( "unsupported name format %d\n", GET_BE_WORD( header->format ) );
+ return FALSE;
+ }
+
+ name_data = (const char *)header + GET_BE_WORD( header->stringOffset );
+ name_count = GET_BE_WORD( header->count );
+ for (i = 0; i < name_count; i++)
+ {
+ const struct tt_namerecord *record = &header->nameRecord[i];
+ struct opentype_name opentype_name;
+
+ if (record->nameID != name_id) continue;
+ if (record->platformID != platform_id) continue;
+
+ language = GET_BE_WORD( record->languageID );
+ if (language >= 0x8000)
+ {
+ FIXME( "handle name format 1\n" );
+ continue;
+ }
+
+ encoding = GET_BE_WORD( record->encodingID );
+ offset = GET_BE_WORD( record->offset );
+ length = GET_BE_WORD( record->length );
+ langid = get_name_record_langid( platform, encoding, language );
+
+ opentype_name.codepage = get_name_record_codepage( platform, encoding );
+ opentype_name.length = length;
+ opentype_name.bytes = name_data + offset;
+
+ if ((ret = callback( langid, &opentype_name, user ))) break;
+ }
+
+ return ret;
+}
+
BOOL opentype_get_ttc_sfnt_v1( const void *data, size_t size, DWORD index, DWORD *count, const struct ttc_sfnt_v1 **ttc_sfnt_v1 )
{
const struct ttc_header_v1 *ttc_header_v1 = data;
@@ -218,3 +637,43 @@ BOOL opentype_get_ttc_sfnt_v1( const void *data, size_t size, DWORD index, DWORD
return TRUE;
}
+
+BOOL opentype_get_tt_name_v0( const void *data, size_t size, const struct ttc_sfnt_v1 *ttc_sfnt_v1,
+ const struct tt_name_v0 **tt_name_v0 )
+{
+ UINT32 table_size = sizeof(**tt_name_v0);
+ return opentype_get_table_ptr( data, size, ttc_sfnt_v1, MS_NAME_TAG, (const void **)tt_name_v0, &table_size );
+}
+
+BOOL opentype_enum_family_names( const struct tt_name_v0 *header, opentype_enum_names_cb callback, void *user )
+{
+ if (opentype_enum_font_names( header, OPENTYPE_PLATFORM_WIN, OPENTYPE_NAME_FAMILY, callback, user ))
+ return TRUE;
+ if (opentype_enum_font_names( header, OPENTYPE_PLATFORM_MAC, OPENTYPE_NAME_FAMILY, callback, user ))
+ return TRUE;
+ if (opentype_enum_font_names( header, OPENTYPE_PLATFORM_UNICODE, OPENTYPE_NAME_FAMILY, callback, user ))
+ return TRUE;
+ return FALSE;
+}
+
+BOOL opentype_enum_style_names( const struct tt_name_v0 *header, opentype_enum_names_cb callback, void *user )
+{
+ if (opentype_enum_font_names( header, OPENTYPE_PLATFORM_WIN, OPENTYPE_NAME_SUBFAMILY, callback, user ))
+ return TRUE;
+ if (opentype_enum_font_names( header, OPENTYPE_PLATFORM_MAC, OPENTYPE_NAME_SUBFAMILY, callback, user ))
+ return TRUE;
+ if (opentype_enum_font_names( header, OPENTYPE_PLATFORM_UNICODE, OPENTYPE_NAME_SUBFAMILY, callback, user ))
+ return TRUE;
+ return FALSE;
+}
+
+BOOL opentype_enum_full_names( const struct tt_name_v0 *header, opentype_enum_names_cb callback, void *user )
+{
+ if (opentype_enum_font_names( header, OPENTYPE_PLATFORM_WIN, OPENTYPE_NAME_FULLNAME, callback, user ))
+ return TRUE;
+ if (opentype_enum_font_names( header, OPENTYPE_PLATFORM_MAC, OPENTYPE_NAME_FULLNAME, callback, user ))
+ return TRUE;
+ if (opentype_enum_font_names( header, OPENTYPE_PLATFORM_UNICODE, OPENTYPE_NAME_FULLNAME, callback, user ))
+ return TRUE;
+ return FALSE;
+}
--
2.29.2
More information about the wine-devel
mailing list