return NotImplemented;
}
-/* Copied from msi/font.c */
-
-typedef struct _tagTT_OFFSET_TABLE {
- USHORT uMajorVersion;
- USHORT uMinorVersion;
- USHORT uNumOfTables;
- USHORT uSearchRange;
- USHORT uEntrySelector;
- USHORT uRangeShift;
-} TT_OFFSET_TABLE;
-
-typedef struct _tagTT_TABLE_DIRECTORY {
- char szTag[4]; /* table name */
- ULONG uCheckSum; /* Check sum */
- ULONG uOffset; /* Offset from beginning of file */
- ULONG uLength; /* length of the table in bytes */
-} TT_TABLE_DIRECTORY;
-
-typedef struct _tagTT_NAME_TABLE_HEADER {
- USHORT uFSelector; /* format selector. Always 0 */
- USHORT uNRCount; /* Name Records count */
- USHORT uStorageOffset; /* Offset for strings storage,
- * from start of the table */
-} TT_NAME_TABLE_HEADER;
+#define TT_PLATFORM_APPLE_UNICODE 0
+#define TT_PLATFORM_MACINTOSH 1
+#define TT_PLATFORM_MICROSOFT 3
+
+#define TT_APPLE_ID_DEFAULT 0
+#define TT_APPLE_ID_ISO_10646 2
+#define TT_APPLE_ID_UNICODE_2_0 3
+
+#define TT_MS_ID_SYMBOL_CS 0
+#define TT_MS_ID_UNICODE_CS 1
+
+#define TT_MAC_ID_SIMPLIFIED_CHINESE 25
#define NAME_ID_FULL_FONT_NAME 4
-#define NAME_ID_VERSION 5
-typedef struct _tagTT_NAME_RECORD {
- USHORT uPlatformID;
- USHORT uEncodingID;
- USHORT uLanguageID;
- USHORT uNameID;
- USHORT uStringLength;
- USHORT uStringOffset; /* from start of storage area */
-} TT_NAME_RECORD;
+typedef struct {
+ USHORT major_version;
+ USHORT minor_version;
+ USHORT tables_no;
+ USHORT search_range;
+ USHORT entry_selector;
+ USHORT range_shift;
+} tt_header;
+
+typedef struct {
+ char tag[4]; /* table name */
+ ULONG check_sum; /* Check sum */
+ ULONG offset; /* Offset from beginning of file */
+ ULONG length; /* length of the table in bytes */
+} tt_table_directory;
+
+typedef struct {
+ USHORT format; /* format selector. Always 0 */
+ USHORT count; /* Name Records count */
+ USHORT string_offset; /* Offset for strings storage, * from start of the table */
+} tt_name_table;
+
+typedef struct {
+ USHORT platform_id;
+ USHORT encoding_id;
+ USHORT language_id;
+ USHORT name_id;
+ USHORT length;
+ USHORT offset; /* from start of storage area */
+} tt_name_record;
+
+/* Copied from gdi32/freetype.c */
+
+static const LANGID mac_langid_table[] =
+{
+ MAKELANGID(LANG_ENGLISH,SUBLANG_DEFAULT), /* TT_MAC_LANGID_ENGLISH */
+ MAKELANGID(LANG_FRENCH,SUBLANG_DEFAULT), /* TT_MAC_LANGID_FRENCH */
+ MAKELANGID(LANG_GERMAN,SUBLANG_DEFAULT), /* TT_MAC_LANGID_GERMAN */
+ MAKELANGID(LANG_ITALIAN,SUBLANG_DEFAULT), /* TT_MAC_LANGID_ITALIAN */
+ MAKELANGID(LANG_DUTCH,SUBLANG_DEFAULT), /* TT_MAC_LANGID_DUTCH */
+ MAKELANGID(LANG_SWEDISH,SUBLANG_DEFAULT), /* TT_MAC_LANGID_SWEDISH */
+ MAKELANGID(LANG_SPANISH,SUBLANG_DEFAULT), /* TT_MAC_LANGID_SPANISH */
+ MAKELANGID(LANG_DANISH,SUBLANG_DEFAULT), /* TT_MAC_LANGID_DANISH */
+ MAKELANGID(LANG_PORTUGUESE,SUBLANG_DEFAULT), /* TT_MAC_LANGID_PORTUGUESE */
+ MAKELANGID(LANG_NORWEGIAN,SUBLANG_DEFAULT), /* TT_MAC_LANGID_NORWEGIAN */
+ MAKELANGID(LANG_HEBREW,SUBLANG_DEFAULT), /* TT_MAC_LANGID_HEBREW */
+ MAKELANGID(LANG_JAPANESE,SUBLANG_DEFAULT), /* TT_MAC_LANGID_JAPANESE */
+ MAKELANGID(LANG_ARABIC,SUBLANG_DEFAULT), /* TT_MAC_LANGID_ARABIC */
+ MAKELANGID(LANG_FINNISH,SUBLANG_DEFAULT), /* TT_MAC_LANGID_FINNISH */
+ MAKELANGID(LANG_GREEK,SUBLANG_DEFAULT), /* TT_MAC_LANGID_GREEK */
+ MAKELANGID(LANG_ICELANDIC,SUBLANG_DEFAULT), /* TT_MAC_LANGID_ICELANDIC */
+ MAKELANGID(LANG_MALTESE,SUBLANG_DEFAULT), /* TT_MAC_LANGID_MALTESE */
+ MAKELANGID(LANG_TURKISH,SUBLANG_DEFAULT), /* TT_MAC_LANGID_TURKISH */
+ MAKELANGID(LANG_CROATIAN,SUBLANG_DEFAULT), /* TT_MAC_LANGID_CROATIAN */
+ MAKELANGID(LANG_CHINESE_TRADITIONAL,SUBLANG_DEFAULT), /* TT_MAC_LANGID_CHINESE_TRADITIONAL */
+ MAKELANGID(LANG_URDU,SUBLANG_DEFAULT), /* TT_MAC_LANGID_URDU */
+ MAKELANGID(LANG_HINDI,SUBLANG_DEFAULT), /* TT_MAC_LANGID_HINDI */
+ MAKELANGID(LANG_THAI,SUBLANG_DEFAULT), /* TT_MAC_LANGID_THAI */
+ MAKELANGID(LANG_KOREAN,SUBLANG_DEFAULT), /* TT_MAC_LANGID_KOREAN */
+ MAKELANGID(LANG_LITHUANIAN,SUBLANG_DEFAULT), /* TT_MAC_LANGID_LITHUANIAN */
+ MAKELANGID(LANG_POLISH,SUBLANG_DEFAULT), /* TT_MAC_LANGID_POLISH */
+ MAKELANGID(LANG_HUNGARIAN,SUBLANG_DEFAULT), /* TT_MAC_LANGID_HUNGARIAN */
+ MAKELANGID(LANG_ESTONIAN,SUBLANG_DEFAULT), /* TT_MAC_LANGID_ESTONIAN */
+ MAKELANGID(LANG_LATVIAN,SUBLANG_DEFAULT), /* TT_MAC_LANGID_LETTISH */
+ MAKELANGID(LANG_SAMI,SUBLANG_DEFAULT), /* TT_MAC_LANGID_SAAMISK */
+ MAKELANGID(LANG_FAEROESE,SUBLANG_DEFAULT), /* TT_MAC_LANGID_FAEROESE */
+ MAKELANGID(LANG_FARSI,SUBLANG_DEFAULT), /* TT_MAC_LANGID_FARSI */
+ MAKELANGID(LANG_RUSSIAN,SUBLANG_DEFAULT), /* TT_MAC_LANGID_RUSSIAN */
+ MAKELANGID(LANG_CHINESE_SIMPLIFIED,SUBLANG_DEFAULT), /* TT_MAC_LANGID_CHINESE_SIMPLIFIED */
+ MAKELANGID(LANG_DUTCH,SUBLANG_DUTCH_BELGIAN), /* TT_MAC_LANGID_FLEMISH */
+ MAKELANGID(LANG_IRISH,SUBLANG_DEFAULT), /* TT_MAC_LANGID_IRISH */
+ MAKELANGID(LANG_ALBANIAN,SUBLANG_DEFAULT), /* TT_MAC_LANGID_ALBANIAN */
+ MAKELANGID(LANG_ROMANIAN,SUBLANG_DEFAULT), /* TT_MAC_LANGID_ROMANIAN */
+ MAKELANGID(LANG_CZECH,SUBLANG_DEFAULT), /* TT_MAC_LANGID_CZECH */
+ MAKELANGID(LANG_SLOVAK,SUBLANG_DEFAULT), /* TT_MAC_LANGID_SLOVAK */
+ MAKELANGID(LANG_SLOVENIAN,SUBLANG_DEFAULT), /* TT_MAC_LANGID_SLOVENIAN */
+ 0, /* TT_MAC_LANGID_YIDDISH */
+ MAKELANGID(LANG_SERBIAN,SUBLANG_DEFAULT), /* TT_MAC_LANGID_SERBIAN */
+ MAKELANGID(LANG_MACEDONIAN,SUBLANG_DEFAULT), /* TT_MAC_LANGID_MACEDONIAN */
+ MAKELANGID(LANG_BULGARIAN,SUBLANG_DEFAULT), /* TT_MAC_LANGID_BULGARIAN */
+ MAKELANGID(LANG_UKRAINIAN,SUBLANG_DEFAULT), /* TT_MAC_LANGID_UKRAINIAN */
+ MAKELANGID(LANG_BELARUSIAN,SUBLANG_DEFAULT), /* TT_MAC_LANGID_BYELORUSSIAN */
+ MAKELANGID(LANG_UZBEK,SUBLANG_DEFAULT), /* TT_MAC_LANGID_UZBEK */
+ MAKELANGID(LANG_KAZAK,SUBLANG_DEFAULT), /* TT_MAC_LANGID_KAZAKH */
+ MAKELANGID(LANG_AZERI,SUBLANG_AZERI_CYRILLIC), /* TT_MAC_LANGID_AZERBAIJANI */
+ 0, /* TT_MAC_LANGID_AZERBAIJANI_ARABIC_SCRIPT */
+ MAKELANGID(LANG_ARMENIAN,SUBLANG_DEFAULT), /* TT_MAC_LANGID_ARMENIAN */
+ MAKELANGID(LANG_GEORGIAN,SUBLANG_DEFAULT), /* TT_MAC_LANGID_GEORGIAN */
+ 0, /* TT_MAC_LANGID_MOLDAVIAN */
+ MAKELANGID(LANG_KYRGYZ,SUBLANG_DEFAULT), /* TT_MAC_LANGID_KIRGHIZ */
+ MAKELANGID(LANG_TAJIK,SUBLANG_DEFAULT), /* TT_MAC_LANGID_TAJIKI */
+ MAKELANGID(LANG_TURKMEN,SUBLANG_DEFAULT), /* TT_MAC_LANGID_TURKMEN */
+ MAKELANGID(LANG_MONGOLIAN,SUBLANG_DEFAULT), /* TT_MAC_LANGID_MONGOLIAN */
+ MAKELANGID(LANG_MONGOLIAN,SUBLANG_MONGOLIAN_CYRILLIC_MONGOLIA), /* TT_MAC_LANGID_MONGOLIAN_CYRILLIC_SCRIPT */
+ MAKELANGID(LANG_PASHTO,SUBLANG_DEFAULT), /* TT_MAC_LANGID_PASHTO */
+ 0, /* TT_MAC_LANGID_KURDISH */
+ MAKELANGID(LANG_KASHMIRI,SUBLANG_DEFAULT), /* TT_MAC_LANGID_KASHMIRI */
+ MAKELANGID(LANG_SINDHI,SUBLANG_DEFAULT), /* TT_MAC_LANGID_SINDHI */
+ MAKELANGID(LANG_TIBETAN,SUBLANG_DEFAULT), /* TT_MAC_LANGID_TIBETAN */
+ MAKELANGID(LANG_NEPALI,SUBLANG_DEFAULT), /* TT_MAC_LANGID_NEPALI */
+ MAKELANGID(LANG_SANSKRIT,SUBLANG_DEFAULT), /* TT_MAC_LANGID_SANSKRIT */
+ MAKELANGID(LANG_MARATHI,SUBLANG_DEFAULT), /* TT_MAC_LANGID_MARATHI */
+ MAKELANGID(LANG_BENGALI,SUBLANG_DEFAULT), /* TT_MAC_LANGID_BENGALI */
+ MAKELANGID(LANG_ASSAMESE,SUBLANG_DEFAULT), /* TT_MAC_LANGID_ASSAMESE */
+ MAKELANGID(LANG_GUJARATI,SUBLANG_DEFAULT), /* TT_MAC_LANGID_GUJARATI */
+ MAKELANGID(LANG_PUNJABI,SUBLANG_DEFAULT), /* TT_MAC_LANGID_PUNJABI */
+ MAKELANGID(LANG_ORIYA,SUBLANG_DEFAULT), /* TT_MAC_LANGID_ORIYA */
+ MAKELANGID(LANG_MALAYALAM,SUBLANG_DEFAULT), /* TT_MAC_LANGID_MALAYALAM */
+ MAKELANGID(LANG_KANNADA,SUBLANG_DEFAULT), /* TT_MAC_LANGID_KANNADA */
+ MAKELANGID(LANG_TAMIL,SUBLANG_DEFAULT), /* TT_MAC_LANGID_TAMIL */
+ MAKELANGID(LANG_TELUGU,SUBLANG_DEFAULT), /* TT_MAC_LANGID_TELUGU */
+ MAKELANGID(LANG_SINHALESE,SUBLANG_DEFAULT), /* TT_MAC_LANGID_SINHALESE */
+ 0, /* TT_MAC_LANGID_BURMESE */
+ MAKELANGID(LANG_KHMER,SUBLANG_DEFAULT), /* TT_MAC_LANGID_KHMER */
+ MAKELANGID(LANG_LAO,SUBLANG_DEFAULT), /* TT_MAC_LANGID_LAO */
+ MAKELANGID(LANG_VIETNAMESE,SUBLANG_DEFAULT), /* TT_MAC_LANGID_VIETNAMESE */
+ MAKELANGID(LANG_INDONESIAN,SUBLANG_DEFAULT), /* TT_MAC_LANGID_INDONESIAN */
+ 0, /* TT_MAC_LANGID_TAGALOG */
+ MAKELANGID(LANG_MALAY,SUBLANG_DEFAULT), /* TT_MAC_LANGID_MALAY_ROMAN_SCRIPT */
+ 0, /* TT_MAC_LANGID_MALAY_ARABIC_SCRIPT */
+ MAKELANGID(LANG_AMHARIC,SUBLANG_DEFAULT), /* TT_MAC_LANGID_AMHARIC */
+ MAKELANGID(LANG_TIGRIGNA,SUBLANG_DEFAULT), /* TT_MAC_LANGID_TIGRINYA */
+ 0, /* TT_MAC_LANGID_GALLA */
+ 0, /* TT_MAC_LANGID_SOMALI */
+ MAKELANGID(LANG_SWAHILI,SUBLANG_DEFAULT), /* TT_MAC_LANGID_SWAHILI */
+ 0, /* TT_MAC_LANGID_RUANDA */
+ 0, /* TT_MAC_LANGID_RUNDI */
+ 0, /* TT_MAC_LANGID_CHEWA */
+ MAKELANGID(LANG_MALAGASY,SUBLANG_DEFAULT), /* TT_MAC_LANGID_MALAGASY */
+ MAKELANGID(LANG_ESPERANTO,SUBLANG_DEFAULT), /* TT_MAC_LANGID_ESPERANTO */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 95-111 */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 112-127 */
+ MAKELANGID(LANG_WELSH,SUBLANG_DEFAULT), /* TT_MAC_LANGID_WELSH */
+ MAKELANGID(LANG_BASQUE,SUBLANG_DEFAULT), /* TT_MAC_LANGID_BASQUE */
+ MAKELANGID(LANG_CATALAN,SUBLANG_DEFAULT), /* TT_MAC_LANGID_CATALAN */
+ 0, /* TT_MAC_LANGID_LATIN */
+ MAKELANGID(LANG_QUECHUA,SUBLANG_DEFAULT), /* TT_MAC_LANGID_QUECHUA */
+ 0, /* TT_MAC_LANGID_GUARANI */
+ 0, /* TT_MAC_LANGID_AYMARA */
+ MAKELANGID(LANG_TATAR,SUBLANG_DEFAULT), /* TT_MAC_LANGID_TATAR */
+ MAKELANGID(LANG_UIGHUR,SUBLANG_DEFAULT), /* TT_MAC_LANGID_UIGHUR */
+ 0, /* TT_MAC_LANGID_DZONGKHA */
+ 0, /* TT_MAC_LANGID_JAVANESE */
+ 0, /* TT_MAC_LANGID_SUNDANESE */
+ MAKELANGID(LANG_GALICIAN,SUBLANG_DEFAULT), /* TT_MAC_LANGID_GALICIAN */
+ MAKELANGID(LANG_AFRIKAANS,SUBLANG_DEFAULT), /* TT_MAC_LANGID_AFRIKAANS */
+ MAKELANGID(LANG_BRETON,SUBLANG_DEFAULT), /* TT_MAC_LANGID_BRETON */
+ MAKELANGID(LANG_INUKTITUT,SUBLANG_DEFAULT), /* TT_MAC_LANGID_INUKTITUT */
+ MAKELANGID(LANG_SCOTTISH_GAELIC,SUBLANG_DEFAULT), /* TT_MAC_LANGID_SCOTTISH_GAELIC */
+ MAKELANGID(LANG_MANX_GAELIC,SUBLANG_DEFAULT), /* TT_MAC_LANGID_MANX_GAELIC */
+ MAKELANGID(LANG_IRISH,SUBLANG_IRISH_IRELAND), /* TT_MAC_LANGID_IRISH_GAELIC */
+ 0, /* TT_MAC_LANGID_TONGAN */
+ 0, /* TT_MAC_LANGID_GREEK_POLYTONIC */
+ MAKELANGID(LANG_GREENLANDIC,SUBLANG_DEFAULT), /* TT_MAC_LANGID_GREELANDIC */
+ MAKELANGID(LANG_AZERI,SUBLANG_AZERI_LATIN), /* TT_MAC_LANGID_AZERBAIJANI_ROMAN_SCRIPT */
+};
-#define SWAPWORD(x) MAKEWORD(HIBYTE(x), LOBYTE(x))
-#define SWAPLONG(x) MAKELONG(SWAPWORD(HIWORD(x)), SWAPWORD(LOWORD(x)))
+static inline WORD get_mac_code_page( const tt_name_record *name )
+{
+ WORD encoding_id = GET_BE_WORD(name->encoding_id);
+ if (encoding_id == TT_MAC_ID_SIMPLIFIED_CHINESE) return 10008; /* special case */
+ return 10000 + encoding_id;
+}
-/*
- * Code based off of code located here
- * http://www.codeproject.com/gdi/fontnamefromfile.asp
- */
-static WCHAR *load_ttf_name_id( const char *mem, DWORD_PTR size, DWORD id, WCHAR *ret, DWORD len )
+static int match_name_table_language( const tt_name_record *name, LANGID lang )
{
- const TT_TABLE_DIRECTORY *tblDir;
- TT_OFFSET_TABLE ttOffsetTable;
- TT_NAME_TABLE_HEADER ttNTHeader;
- TT_NAME_RECORD ttRecord;
- DWORD ofs, pos;
- int i;
+ LANGID name_lang;
- if (sizeof(TT_OFFSET_TABLE) > size)
+ switch (GET_BE_WORD(name->platform_id))
+ {
+ case TT_PLATFORM_MICROSOFT:
+ switch (GET_BE_WORD(name->encoding_id))
+ {
+ case TT_MS_ID_UNICODE_CS:
+ case TT_MS_ID_SYMBOL_CS:
+ name_lang = GET_BE_WORD(name->language_id);
+ break;
+ default:
+ return 0;
+ }
+ break;
+ case TT_PLATFORM_MACINTOSH:
+ if (!IsValidCodePage( get_mac_code_page( name ))) return 0;
+ name_lang = GET_BE_WORD(name->language_id);
+ if (name_lang >= sizeof(mac_langid_table)/sizeof(mac_langid_table[0])) return 0;
+ name_lang = mac_langid_table[name_lang];
+ break;
+ case TT_PLATFORM_APPLE_UNICODE:
+ switch (GET_BE_WORD(name->encoding_id))
+ {
+ case TT_APPLE_ID_DEFAULT:
+ case TT_APPLE_ID_ISO_10646:
+ case TT_APPLE_ID_UNICODE_2_0:
+ name_lang = GET_BE_WORD(name->language_id);
+ if (name_lang >= sizeof(mac_langid_table)/sizeof(mac_langid_table[0])) return 0;
+ name_lang = mac_langid_table[name_lang];
+ break;
+ default:
+ return 0;
+ }
+ break;
+ default:
+ return 0;
+ }
+ if (name_lang == lang) return 3;
+ if (PRIMARYLANGID( name_lang ) == PRIMARYLANGID( lang )) return 2;
+ if (name_lang == MAKELANGID( LANG_ENGLISH, SUBLANG_DEFAULT )) return 1;
+ return 0;
+}
+
+static WCHAR *copy_name_table_string( const tt_name_record *name, const BYTE *data, WCHAR *ret, DWORD len )
+{
+ WORD name_len = GET_BE_WORD(name->length);
+ WORD codepage;
+
+ switch (GET_BE_WORD(name->platform_id))
+ {
+ case TT_PLATFORM_APPLE_UNICODE:
+ case TT_PLATFORM_MICROSOFT:
+ if (name_len >= len*sizeof(WCHAR))
+ return NULL;
+ for (len = 0; len < name_len / 2; len++)
+ ret[len] = (data[len * 2] << 8) | data[len * 2 + 1];
+ ret[len] = 0;
+ return ret;
+ case TT_PLATFORM_MACINTOSH:
+ codepage = get_mac_code_page( name );
+ len = MultiByteToWideChar( codepage, 0, (char *)data, name_len, ret, len-1 );
+ if (!len)
+ return NULL;
+ ret[len] = 0;
+ return ret;
+ }
+ return NULL;
+}
+
+static WCHAR *load_ttf_name_id( const BYTE *mem, DWORD_PTR size, DWORD id, WCHAR *ret, DWORD len )
+{
+ LANGID lang = GetSystemDefaultLangID();
+ const tt_header *header;
+ const tt_name_table *name_table;
+ const tt_name_record *name_record;
+ DWORD pos, ofs, count;
+ int i, res, best_lang = 0, best_index = -1;
+
+ if (sizeof(tt_header) > size)
return NULL;
- ttOffsetTable = *(TT_OFFSET_TABLE*)mem;
- ttOffsetTable.uNumOfTables = SWAPWORD(ttOffsetTable.uNumOfTables);
- ttOffsetTable.uMajorVersion = SWAPWORD(ttOffsetTable.uMajorVersion);
- ttOffsetTable.uMinorVersion = SWAPWORD(ttOffsetTable.uMinorVersion);
+ header = (const tt_header*)mem;
+ count = GET_BE_WORD(header->tables_no);
- if (ttOffsetTable.uMajorVersion != 1 || ttOffsetTable.uMinorVersion != 0)
+ if (GET_BE_WORD(header->major_version) != 1 || GET_BE_WORD(header->minor_version) != 0)
return NULL;
- pos = sizeof(ttOffsetTable);
- for (i = 0; i < ttOffsetTable.uNumOfTables; i++)
+ pos = sizeof(*header);
+ for (i = 0; i < count; i++)
{
- tblDir = (const TT_TABLE_DIRECTORY*)&mem[pos];
- pos += sizeof(*tblDir);
- if (memcmp(tblDir->szTag,"name",4)==0)
+ const tt_table_directory *table_directory = (const tt_table_directory*)&mem[pos];
+ pos += sizeof(*table_directory);
+ if (memcmp(table_directory->tag, "name", 4) == 0)
{
- ofs = SWAPLONG(tblDir->uOffset);
+ ofs = GET_BE_DWORD(table_directory->offset);
break;
}
}
- if (i >= ttOffsetTable.uNumOfTables)
+ if (i >= count)
return NULL;
- pos = ofs + sizeof(ttNTHeader);
+ if (ofs >= size)
+ return NULL;
+ pos = ofs + sizeof(*name_table);
if (pos > size)
return NULL;
- ttNTHeader = *(TT_NAME_TABLE_HEADER*)&mem[ofs];
- ttNTHeader.uNRCount = SWAPWORD(ttNTHeader.uNRCount);
- ttNTHeader.uStorageOffset = SWAPWORD(ttNTHeader.uStorageOffset);
- for(i=0; i<ttNTHeader.uNRCount; i++)
+ name_table = (const tt_name_table*)&mem[ofs];
+ count = GET_BE_WORD(name_table->count);
+ if (GET_BE_WORD(name_table->string_offset) >= size - ofs) return NULL;
+ ofs += GET_BE_WORD(name_table->string_offset);
+ for (i=0; i<count; i++)
{
- ttRecord = *(TT_NAME_RECORD*)&mem[pos];
- pos += sizeof(ttRecord);
+ name_record = (const tt_name_record*)&mem[pos];
+ pos += sizeof(*name_record);
if (pos > size)
return NULL;
- ttRecord.uNameID = SWAPWORD(ttRecord.uNameID);
- if (ttRecord.uNameID == id)
+ if (GET_BE_WORD(name_record->name_id) != id) continue;
+ if (GET_BE_WORD(name_record->offset) >= size - ofs) return NULL;
+ if (GET_BE_WORD(name_record->length) > size - ofs - GET_BE_WORD(name_record->offset)) return NULL;
+
+ res = match_name_table_language( name_record, lang );
+ if (res > best_lang)
{
- const char *buf;
-
- ttRecord.uStringLength = SWAPWORD(ttRecord.uStringLength);
- ttRecord.uStringOffset = SWAPWORD(ttRecord.uStringOffset);
- if (ofs + ttRecord.uStringOffset + ttNTHeader.uStorageOffset + ttRecord.uStringLength > size)
- return NULL;
- buf = mem + ofs + ttRecord.uStringOffset + ttNTHeader.uStorageOffset;
- len = MultiByteToWideChar(CP_ACP, 0, buf, ttRecord.uStringLength, ret, len-1);
- ret[len] = 0;
- return ret;
+ best_lang = res;
+ best_index = i;
}
}
+
+ if (best_lang)
+ {
+ name_record = (const tt_name_record*)(name_table + 1) + best_index;
+ ret = copy_name_table_string( name_record, mem+ofs+GET_BE_WORD(name_record->offset), ret, len );
+ TRACE( "name %u found platform %u lang %04x %s\n", GET_BE_WORD(name_record->name_id),
+ GET_BE_WORD(name_record->platform_id), GET_BE_WORD(name_record->language_id), debugstr_w( ret ));
+ return ret;
+ }
return NULL;
}
GDIPCONST GpBrush *brush, GDIPCONST PointF *positions,
INT flags, GDIPCONST GpMatrix *matrix);
+static GpStatus get_graphics_transform(GpGraphics *graphics, GpCoordinateSpace dst_space,
+ GpCoordinateSpace src_space, GpMatrix *matrix);
+
/* Converts from gdiplus path point type to gdi path point type. */
static BYTE convert_path_point_type(BYTE type)
{
RestoreDC(graphics->hdc, state);
}
-static GpStatus get_graphics_transform(GpGraphics *graphics, GpCoordinateSpace dst_space,
- GpCoordinateSpace src_space, GpMatrix *matrix);
-
/* This helper applies all the changes that the points listed in ptf need in
* order to be drawn on the device context. In the end, this should include at
* least:
static GpStatus get_clip_hrgn(GpGraphics *graphics, HRGN *hrgn)
{
+ /* clipping region is in device coords */
return GdipGetRegionHRgn(graphics->clip, NULL, hrgn);
}
(pt[2].X-pt[0].X)*(pt[2].X-pt[0].X));
get_log_fontW(font, graphics, &lfw);
- lfw.lfHeight = gdip_round(font_height * rel_height);
+ lfw.lfHeight = -gdip_round(font_height * rel_height);
unscaled_font = CreateFontIndirectW(&lfw);
SelectObject(hdc, unscaled_font);
*/
GpStatus WINGDIPAPI GdipGetClipBounds(GpGraphics *graphics, GpRectF *rect)
{
+ GpStatus status;
+ GpRegion *clip;
+
TRACE("(%p, %p)\n", graphics, rect);
if(!graphics)
if(graphics->busy)
return ObjectBusy;
- return GdipGetRegionBounds(graphics->clip, graphics, rect);
+ status = GdipCreateRegion(&clip);
+ if (status != Ok) return status;
+
+ status = GdipGetClip(graphics, clip);
+ if (status == Ok)
+ status = GdipGetRegionBounds(clip, graphics, rect);
+
+ GdipDeleteRegion(clip);
+ return status;
}
/*****************************************************************************
if (scaled_rect.Height >= 1 << 23) scaled_rect.Height = 1 << 23;
if (!(format_flags & StringFormatFlagsNoClip) &&
- scaled_rect.Width != 1 << 23 && scaled_rect.Height != 1 << 23)
+ scaled_rect.Width != 1 << 23 && scaled_rect.Height != 1 << 23 &&
+ rect->Width > 0.0 && rect->Height > 0.0)
{
/* FIXME: If only the width or only the height is 0, we should probably still clip */
rgn = CreatePolygonRgn(corners, 4, ALTERNATE);
if(!graphics)
return InvalidParameter;
+ if(graphics->busy)
+ return ObjectBusy;
+
+ /* hrgn is already in device units */
status = GdipCreateRegionHrgn(hrgn, ®ion);
if(status != Ok)
return status;
- status = GdipSetClipRegion(graphics, region, mode);
+ status = GdipCombineRegionRegion(graphics->clip, region, mode);
GdipDeleteRegion(region);
return status;
GpStatus WINGDIPAPI GdipSetClipPath(GpGraphics *graphics, GpPath *path, CombineMode mode)
{
+ GpStatus status;
+ GpPath *clip_path;
+
TRACE("(%p, %p, %d)\n", graphics, path, mode);
if(!graphics)
if(graphics->busy)
return ObjectBusy;
- return GdipCombineRegionPath(graphics->clip, path, mode);
+ status = GdipClonePath(path, &clip_path);
+ if (status == Ok)
+ {
+ GpMatrix world_to_device;
+
+ get_graphics_transform(graphics, CoordinateSpaceDevice,
+ CoordinateSpaceWorld, &world_to_device);
+ status = GdipTransformPath(clip_path, &world_to_device);
+ if (status == Ok)
+ GdipCombineRegionPath(graphics->clip, clip_path, mode);
+
+ GdipDeletePath(clip_path);
+ }
+ return status;
}
GpStatus WINGDIPAPI GdipSetClipRect(GpGraphics *graphics, REAL x, REAL y,
REAL width, REAL height,
CombineMode mode)
{
+ GpStatus status;
GpRectF rect;
+ GpRegion *region;
TRACE("(%p, %.2f, %.2f, %.2f, %.2f, %d)\n", graphics, x, y, width, height, mode);
rect.Y = y;
rect.Width = width;
rect.Height = height;
+ status = GdipCreateRegionRect(&rect, ®ion);
+ if (status == Ok)
+ {
+ GpMatrix world_to_device;
+
+ get_graphics_transform(graphics, CoordinateSpaceDevice, CoordinateSpaceWorld, &world_to_device);
+ status = GdipTransformRegion(region, &world_to_device);
+ if (status == Ok)
+ status = GdipCombineRegionRegion(graphics->clip, region, mode);
- return GdipCombineRegionRect(graphics->clip, &rect, mode);
+ GdipDeleteRegion(region);
+ }
+ return status;
}
GpStatus WINGDIPAPI GdipSetClipRectI(GpGraphics *graphics, INT x, INT y,
GpStatus WINGDIPAPI GdipSetClipRegion(GpGraphics *graphics, GpRegion *region,
CombineMode mode)
{
+ GpStatus status;
+ GpRegion *clip;
+
TRACE("(%p, %p, %d)\n", graphics, region, mode);
if(!graphics || !region)
if(graphics->busy)
return ObjectBusy;
- return GdipCombineRegionRegion(graphics->clip, region, mode);
+ status = GdipCloneRegion(region, &clip);
+ if (status == Ok)
+ {
+ GpMatrix world_to_device;
+
+ get_graphics_transform(graphics, CoordinateSpaceDevice, CoordinateSpaceWorld, &world_to_device);
+ status = GdipTransformRegion(clip, &world_to_device);
+ if (status == Ok)
+ status = GdipCombineRegionRegion(graphics->clip, clip, mode);
+
+ GdipDeleteRegion(clip);
+ }
+ return status;
}
GpStatus WINGDIPAPI GdipSetMetafileDownLevelRasterizationLimit(GpMetafile *metafile,
{
GpRegion *clip;
GpStatus status;
+ GpMatrix device_to_world;
TRACE("(%p, %p)\n", graphics, region);
if((status = GdipCloneRegion(graphics->clip, &clip)) != Ok)
return status;
+ get_graphics_transform(graphics, CoordinateSpaceWorld, CoordinateSpaceDevice, &device_to_world);
+ status = GdipTransformRegion(clip, &device_to_world);
+ if (status != Ok)
+ {
+ GdipDeleteRegion(clip);
+ return status;
+ }
+
/* free everything except root node and header */
delete_element(®ion->node);
memcpy(region, clip, sizeof(GpRegion));