mirror of
git://source.winehq.org/git/wine.git
synced 2024-09-01 21:33:38 +00:00
![Jacek Caban](/assets/img/avatar_default.png)
Signed-off-by: Jacek Caban <jacek@codeweavers.com> Signed-off-by: Huw Davies <huw@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
772 lines
24 KiB
C
772 lines
24 KiB
C
/*
|
|
* Copyright 2020 Rémi Bernon for CodeWeavers
|
|
* Copyright 2014 Aric Stewart for CodeWeavers
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
|
*/
|
|
|
|
#if 0
|
|
#pragma makedep unix
|
|
#endif
|
|
|
|
#include <stdarg.h>
|
|
#include <stdlib.h>
|
|
|
|
#include "windef.h"
|
|
#include "winbase.h"
|
|
#include "winnls.h"
|
|
|
|
#include "wine/debug.h"
|
|
|
|
#include "ntgdi_private.h"
|
|
|
|
WINE_DEFAULT_DEBUG_CHANNEL(font);
|
|
|
|
#define MS_OTTO_TAG MS_MAKE_TAG('O','T','T','O')
|
|
#define MS_HEAD_TAG MS_MAKE_TAG('h','e','a','d')
|
|
#define MS_HHEA_TAG MS_MAKE_TAG('h','h','e','a')
|
|
#define MS_OS_2_TAG MS_MAKE_TAG('O','S','/','2')
|
|
#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')
|
|
#define MS_CFF__TAG MS_MAKE_TAG('C','F','F',' ')
|
|
|
|
#ifdef WORDS_BIGENDIAN
|
|
#define GET_BE_WORD(x) (x)
|
|
#define GET_BE_DWORD(x) (x)
|
|
#else
|
|
#define GET_BE_WORD(x) RtlUshortByteSwap(x)
|
|
#define GET_BE_DWORD(x) RtlUlongByteSwap(x)
|
|
#endif
|
|
|
|
#include "pshpack2.h"
|
|
struct ttc_header_v1
|
|
{
|
|
CHAR TTCTag[4];
|
|
DWORD Version;
|
|
DWORD numFonts;
|
|
DWORD OffsetTable[1];
|
|
};
|
|
|
|
struct ttc_sfnt_v1
|
|
{
|
|
DWORD version;
|
|
WORD numTables;
|
|
WORD searchRange;
|
|
WORD entrySelector;
|
|
WORD rangeShift;
|
|
};
|
|
|
|
struct tt_tablerecord
|
|
{
|
|
DWORD tag;
|
|
DWORD checkSum;
|
|
DWORD offset;
|
|
DWORD length;
|
|
};
|
|
|
|
struct tt_os2_v1
|
|
{
|
|
USHORT version;
|
|
SHORT xAvgCharWidth;
|
|
USHORT usWeightClass;
|
|
USHORT usWidthClass;
|
|
SHORT fsType;
|
|
SHORT ySubscriptXSize;
|
|
SHORT ySubscriptYSize;
|
|
SHORT ySubscriptXOffset;
|
|
SHORT ySubscriptYOffset;
|
|
SHORT ySuperscriptXSize;
|
|
SHORT ySuperscriptYSize;
|
|
SHORT ySuperscriptXOffset;
|
|
SHORT ySuperscriptYOffset;
|
|
SHORT yStrikeoutSize;
|
|
SHORT yStrikeoutPosition;
|
|
SHORT sFamilyClass;
|
|
PANOSE panose;
|
|
ULONG ulUnicodeRange1;
|
|
ULONG ulUnicodeRange2;
|
|
ULONG ulUnicodeRange3;
|
|
ULONG ulUnicodeRange4;
|
|
CHAR achVendID[4];
|
|
USHORT fsSelection;
|
|
USHORT usFirstCharIndex;
|
|
USHORT usLastCharIndex;
|
|
/* According to the Apple spec, original version didn't have the below fields,
|
|
* version numbers were taken from the OpenType spec.
|
|
*/
|
|
/* version 0 (TrueType 1.5) */
|
|
USHORT sTypoAscender;
|
|
USHORT sTypoDescender;
|
|
USHORT sTypoLineGap;
|
|
USHORT usWinAscent;
|
|
USHORT usWinDescent;
|
|
/* version 1 (TrueType 1.66) */
|
|
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];
|
|
};
|
|
|
|
struct tt_head
|
|
{
|
|
USHORT majorVersion;
|
|
USHORT minorVersion;
|
|
ULONG revision;
|
|
ULONG checksumadj;
|
|
ULONG magic;
|
|
USHORT flags;
|
|
USHORT unitsPerEm;
|
|
ULONGLONG created;
|
|
ULONGLONG modified;
|
|
SHORT xMin;
|
|
SHORT yMin;
|
|
SHORT xMax;
|
|
SHORT yMax;
|
|
USHORT macStyle;
|
|
USHORT lowestRecPPEM;
|
|
SHORT direction_hint;
|
|
SHORT index_format;
|
|
SHORT glyphdata_format;
|
|
};
|
|
#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
|
|
};
|
|
|
|
enum OS2_FSSELECTION
|
|
{
|
|
OS2_FSSELECTION_ITALIC = 1 << 0,
|
|
OS2_FSSELECTION_UNDERSCORE = 1 << 1,
|
|
OS2_FSSELECTION_NEGATIVE = 1 << 2,
|
|
OS2_FSSELECTION_OUTLINED = 1 << 3,
|
|
OS2_FSSELECTION_STRIKEOUT = 1 << 4,
|
|
OS2_FSSELECTION_BOLD = 1 << 5,
|
|
OS2_FSSELECTION_REGULAR = 1 << 6,
|
|
OS2_FSSELECTION_USE_TYPO_METRICS = 1 << 7,
|
|
OS2_FSSELECTION_WWS = 1 << 8,
|
|
OS2_FSSELECTION_OBLIQUE = 1 << 9
|
|
};
|
|
|
|
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 )
|
|
{
|
|
const struct tt_tablerecord *table_record;
|
|
UINT16 i, table_count;
|
|
UINT32 offset, length;
|
|
|
|
if (!ttc_sfnt_v1) return FALSE;
|
|
|
|
table_record = (const struct tt_tablerecord *)(ttc_sfnt_v1 + 1);
|
|
table_count = GET_BE_WORD( ttc_sfnt_v1->numTables );
|
|
for (i = 0; i < table_count; i++, table_record++)
|
|
{
|
|
if (table_record->tag != table_tag) continue;
|
|
offset = GET_BE_DWORD( table_record->offset );
|
|
length = GET_BE_DWORD( table_record->length );
|
|
if (size < offset + length) return FALSE;
|
|
if (table_size && length < *table_size) return FALSE;
|
|
|
|
if (table_ptr) *table_ptr = (const char *)data + offset;
|
|
if (table_size) *table_size = length;
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static BOOL opentype_get_tt_os2_v1( const void *data, size_t size, const struct ttc_sfnt_v1 *ttc_sfnt_v1,
|
|
const struct tt_os2_v1 **tt_os2_v1 )
|
|
{
|
|
UINT32 table_size = sizeof(**tt_os2_v1);
|
|
return opentype_get_table_ptr( data, size, ttc_sfnt_v1, MS_OS_2_TAG, (const void **)tt_os2_v1, &table_size );
|
|
}
|
|
|
|
static BOOL opentype_get_tt_head( const void *data, size_t size, const struct ttc_sfnt_v1 *ttc_sfnt_v1,
|
|
const struct tt_head **tt_head )
|
|
{
|
|
UINT32 table_size = sizeof(**tt_head);
|
|
return opentype_get_table_ptr( data, size, ttc_sfnt_v1, MS_HEAD_TAG, (const void **)tt_head, &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;
|
|
}
|
|
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;
|
|
const struct tt_os2_v1 *tt_os2_v1;
|
|
UINT32 offset, fourcc;
|
|
|
|
*ttc_sfnt_v1 = NULL;
|
|
*count = 1;
|
|
|
|
if (size < sizeof(fourcc)) return FALSE;
|
|
memcpy( &fourcc, data, sizeof(fourcc) );
|
|
|
|
switch (fourcc)
|
|
{
|
|
default:
|
|
WARN( "unsupported font format %x\n", fourcc );
|
|
return FALSE;
|
|
case MS_TTCF_TAG:
|
|
if (size < sizeof(ttc_header_v1)) return FALSE;
|
|
if (index >= (*count = GET_BE_DWORD( ttc_header_v1->numFonts ))) return FALSE;
|
|
offset = GET_BE_DWORD( ttc_header_v1->OffsetTable[index] );
|
|
break;
|
|
case 0x00000100:
|
|
case MS_OTTO_TAG:
|
|
offset = 0;
|
|
break;
|
|
}
|
|
|
|
if (size < offset + sizeof(**ttc_sfnt_v1)) return FALSE;
|
|
*ttc_sfnt_v1 = (const struct ttc_sfnt_v1 *)((const char *)data + offset);
|
|
|
|
if (!opentype_get_table_ptr( data, size, *ttc_sfnt_v1, MS_HEAD_TAG, NULL, NULL ))
|
|
{
|
|
WARN( "unsupported sfnt font: missing head table.\n" );
|
|
return FALSE;
|
|
}
|
|
|
|
if (!opentype_get_table_ptr( data, size, *ttc_sfnt_v1, MS_HHEA_TAG, NULL, NULL ))
|
|
{
|
|
WARN( "unsupported sfnt font: missing hhea table.\n" );
|
|
return FALSE;
|
|
}
|
|
|
|
if (!opentype_get_tt_os2_v1( data, size, *ttc_sfnt_v1, &tt_os2_v1 ))
|
|
{
|
|
WARN( "unsupported sfnt font: missing OS/2 table.\n" );
|
|
return FALSE;
|
|
}
|
|
|
|
/* Wine uses ttfs as an intermediate step in building its bitmap fonts;
|
|
we don't want to load these. */
|
|
if (!memcmp( tt_os2_v1->achVendID, "Wine", sizeof(tt_os2_v1->achVendID) ) &&
|
|
opentype_get_table_ptr( data, size, *ttc_sfnt_v1, MS_EBSC_TAG, NULL, NULL ))
|
|
{
|
|
TRACE( "ignoring wine bitmap-only sfnt font.\n" );
|
|
return FALSE;
|
|
}
|
|
|
|
if (opentype_get_table_ptr( data, size, *ttc_sfnt_v1, MS_EBDT_TAG, NULL, NULL ) ||
|
|
opentype_get_table_ptr( data, size, *ttc_sfnt_v1, MS_CBDT_TAG, NULL, NULL ))
|
|
{
|
|
WARN( "unsupported sfnt font: embedded bitmap data.\n" );
|
|
return FALSE;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
BOOL opentype_get_properties( const void *data, size_t size, const struct ttc_sfnt_v1 *ttc_sfnt_v1,
|
|
DWORD *version, FONTSIGNATURE *fs, DWORD *ntm_flags )
|
|
{
|
|
const struct tt_os2_v1 *tt_os2_v1;
|
|
const struct tt_head *tt_head;
|
|
const void *cff_header;
|
|
UINT32 table_size = 0;
|
|
USHORT idx, selection;
|
|
DWORD flags = 0;
|
|
|
|
if (!opentype_get_tt_head( data, size, ttc_sfnt_v1, &tt_head )) return FALSE;
|
|
if (!opentype_get_tt_os2_v1( data, size, ttc_sfnt_v1, &tt_os2_v1 )) return FALSE;
|
|
|
|
*version = GET_BE_DWORD( tt_head->revision );
|
|
|
|
fs->fsUsb[0] = GET_BE_DWORD( tt_os2_v1->ulUnicodeRange1 );
|
|
fs->fsUsb[1] = GET_BE_DWORD( tt_os2_v1->ulUnicodeRange2 );
|
|
fs->fsUsb[2] = GET_BE_DWORD( tt_os2_v1->ulUnicodeRange3 );
|
|
fs->fsUsb[3] = GET_BE_DWORD( tt_os2_v1->ulUnicodeRange4 );
|
|
|
|
if (tt_os2_v1->version == 0)
|
|
{
|
|
idx = GET_BE_WORD( tt_os2_v1->usFirstCharIndex );
|
|
if (idx >= 0xf000 && idx < 0xf100) fs->fsCsb[0] = FS_SYMBOL;
|
|
else fs->fsCsb[0] = FS_LATIN1;
|
|
fs->fsCsb[1] = 0;
|
|
}
|
|
else
|
|
{
|
|
fs->fsCsb[0] = GET_BE_DWORD( tt_os2_v1->ulCodePageRange1 );
|
|
fs->fsCsb[1] = GET_BE_DWORD( tt_os2_v1->ulCodePageRange2 );
|
|
}
|
|
|
|
selection = GET_BE_WORD( tt_os2_v1->fsSelection );
|
|
|
|
if (selection & OS2_FSSELECTION_ITALIC) flags |= NTM_ITALIC;
|
|
if (selection & OS2_FSSELECTION_BOLD) flags |= NTM_BOLD;
|
|
if (selection & OS2_FSSELECTION_REGULAR) flags |= NTM_REGULAR;
|
|
if (flags == 0) flags = NTM_REGULAR;
|
|
|
|
if (opentype_get_table_ptr( data, size, ttc_sfnt_v1, MS_CFF__TAG, &cff_header, &table_size ))
|
|
flags |= NTM_PS_OPENTYPE;
|
|
|
|
*ntm_flags = flags;
|
|
return TRUE;
|
|
}
|