dwrite: Implement GetInformationalStrings().
This commit is contained in:
parent
177f601889
commit
04a237fe18
|
@ -113,6 +113,7 @@ extern HRESULT opentype_get_font_table(IDWriteFontFileStream*,DWRITE_FONT_FACE_T
|
|||
extern void opentype_cmap_get_glyphindex(void*,UINT32,UINT16*) DECLSPEC_HIDDEN;
|
||||
extern HRESULT opentype_cmap_get_unicode_ranges(void*,UINT32,DWRITE_UNICODE_RANGE*,UINT32*) DECLSPEC_HIDDEN;
|
||||
extern VOID get_font_properties(LPCVOID os2, LPCVOID head, LPCVOID post, DWRITE_FONT_METRICS *metrics, DWRITE_FONT_STRETCH *stretch, DWRITE_FONT_WEIGHT *weight, DWRITE_FONT_STYLE *style) DECLSPEC_HIDDEN;
|
||||
extern HRESULT opentype_get_font_strings_from_id(IDWriteFontFace2*,DWRITE_INFORMATIONAL_STRING_ID,IDWriteLocalizedStrings**) DECLSPEC_HIDDEN;
|
||||
|
||||
extern HRESULT bidi_computelevels(const WCHAR*,UINT32,UINT8,UINT8*,UINT8*) DECLSPEC_HIDDEN;
|
||||
extern WCHAR bidi_get_mirrored_char(WCHAR) DECLSPEC_HIDDEN;
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
/*
|
||||
* Font and collections
|
||||
*
|
||||
* Copyright 2012 Nikolay Sivov for CodeWeavers
|
||||
* Copyright 2012, 2014 Nikolay Sivov 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
|
||||
|
@ -47,6 +48,7 @@ struct dwrite_font_data {
|
|||
DWRITE_FONT_WEIGHT weight;
|
||||
DWRITE_FONT_SIMULATIONS simulations;
|
||||
DWRITE_FONT_METRICS metrics;
|
||||
IDWriteLocalizedStrings *info_strings[DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_CID_NAME+1];
|
||||
|
||||
struct dwrite_fontface_data *face_data;
|
||||
|
||||
|
@ -220,6 +222,11 @@ static VOID _free_font_data(struct dwrite_font_data *data)
|
|||
i = InterlockedDecrement(&data->ref);
|
||||
if (i > 0)
|
||||
return;
|
||||
|
||||
for (i = DWRITE_INFORMATIONAL_STRING_NONE; i < sizeof(data->info_strings)/sizeof(data->info_strings[0]); i++) {
|
||||
if (data->info_strings[i])
|
||||
IDWriteLocalizedStrings_Release(data->info_strings[i]);
|
||||
}
|
||||
_free_fontface_data(data->face_data);
|
||||
heap_free(data->facename);
|
||||
heap_free(data);
|
||||
|
@ -755,12 +762,9 @@ static HRESULT create_font_base(IDWriteFont **font)
|
|||
HRESULT ret;
|
||||
|
||||
*font = NULL;
|
||||
data = heap_alloc(sizeof(*data));
|
||||
data = heap_alloc_zero(sizeof(*data));
|
||||
if (!data) return E_OUTOFMEMORY;
|
||||
|
||||
data->ref = 0;
|
||||
data->face_data = NULL;
|
||||
|
||||
ret = create_font_from_data( data, NULL, font );
|
||||
if (FAILED(ret)) heap_free( data );
|
||||
return ret;
|
||||
|
@ -967,8 +971,35 @@ static HRESULT WINAPI dwritefont_GetInformationalStrings(IDWriteFont2 *iface,
|
|||
DWRITE_INFORMATIONAL_STRING_ID stringid, IDWriteLocalizedStrings **strings, BOOL *exists)
|
||||
{
|
||||
struct dwrite_font *This = impl_from_IDWriteFont2(iface);
|
||||
FIXME("(%p)->(%d %p %p): stub\n", This, stringid, strings, exists);
|
||||
return E_NOTIMPL;
|
||||
struct dwrite_font_data *data = This->data;
|
||||
HRESULT hr;
|
||||
|
||||
TRACE("(%p)->(%d %p %p)\n", This, stringid, strings, exists);
|
||||
|
||||
*exists = FALSE;
|
||||
*strings = NULL;
|
||||
|
||||
if (stringid > DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_CID_NAME || stringid == DWRITE_INFORMATIONAL_STRING_NONE)
|
||||
return S_OK;
|
||||
|
||||
if (!data->info_strings[stringid]) {
|
||||
IDWriteFontFace2 *fontface;
|
||||
|
||||
hr = get_fontface_from_font(This, &fontface);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
hr = opentype_get_font_strings_from_id(fontface, stringid, &data->info_strings[stringid]);
|
||||
if (FAILED(hr) || !data->info_strings[stringid])
|
||||
return hr;
|
||||
}
|
||||
|
||||
hr = clone_localizedstring(data->info_strings[stringid], strings);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
*exists = TRUE;
|
||||
return hr;
|
||||
}
|
||||
|
||||
static DWRITE_FONT_SIMULATIONS WINAPI dwritefont_GetSimulations(IDWriteFont2 *iface)
|
||||
|
|
|
@ -26,6 +26,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(dwrite);
|
|||
|
||||
#define MS_TTCF_TAG DWRITE_MAKE_OPENTYPE_TAG('t','t','c','f')
|
||||
#define MS_OTTO_TAG DWRITE_MAKE_OPENTYPE_TAG('O','T','T','O')
|
||||
#define MS_NAME_TAG DWRITE_MAKE_OPENTYPE_TAG('n','a','m','e')
|
||||
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
#define GET_BE_WORD(x) (x)
|
||||
|
@ -185,6 +186,87 @@ typedef struct
|
|||
} TT_OS2_V2;
|
||||
#include "poppack.h"
|
||||
|
||||
typedef struct {
|
||||
WORD platformID;
|
||||
WORD encodingID;
|
||||
WORD languageID;
|
||||
WORD nameID;
|
||||
WORD length;
|
||||
WORD offset;
|
||||
} TT_NameRecord;
|
||||
|
||||
typedef struct {
|
||||
WORD format;
|
||||
WORD count;
|
||||
WORD stringOffset;
|
||||
TT_NameRecord nameRecord[1];
|
||||
} TT_NAME_V0;
|
||||
|
||||
enum TT_NAME_WINDOWS_ENCODING_ID
|
||||
{
|
||||
TT_NAME_WINDOWS_ENCODING_SYMBOL = 0,
|
||||
TT_NAME_WINDOWS_ENCODING_UCS2,
|
||||
TT_NAME_WINDOWS_ENCODING_SJIS,
|
||||
TT_NAME_WINDOWS_ENCODING_PRC,
|
||||
TT_NAME_WINDOWS_ENCODING_BIG5,
|
||||
TT_NAME_WINDOWS_ENCODING_WANSUNG,
|
||||
TT_NAME_WINDOWS_ENCODING_JOHAB,
|
||||
TT_NAME_WINDOWS_ENCODING_RESERVED1,
|
||||
TT_NAME_WINDOWS_ENCODING_RESERVED2,
|
||||
TT_NAME_WINDOWS_ENCODING_RESERVED3,
|
||||
TT_NAME_WINDOWS_ENCODING_UCS4
|
||||
};
|
||||
|
||||
enum OPENTYPE_STRING_ID
|
||||
{
|
||||
OPENTYPE_STRING_COPYRIGHT_NOTICE = 0,
|
||||
OPENTYPE_STRING_FAMILY_NAME,
|
||||
OPENTYPE_STRING_SUBFAMILY_NAME,
|
||||
OPENTYPE_STRING_UNIQUE_IDENTIFIER,
|
||||
OPENTYPE_STRING_FULL_FONTNAME,
|
||||
OPENTYPE_STRING_VERSION_STRING,
|
||||
OPENTYPE_STRING_POSTSCRIPT_FONTNAME,
|
||||
OPENTYPE_STRING_TRADEMARK,
|
||||
OPENTYPE_STRING_MANUFACTURER,
|
||||
OPENTYPE_STRING_DESIGNER,
|
||||
OPENTYPE_STRING_DESCRIPTION,
|
||||
OPENTYPE_STRING_VENDOR_URL,
|
||||
OPENTYPE_STRING_DESIGNER_URL,
|
||||
OPENTYPE_STRING_LICENSE_DESCRIPTION,
|
||||
OPENTYPE_STRING_LICENSE_INFO_URL,
|
||||
OPENTYPE_STRING_RESERVED_ID15,
|
||||
OPENTYPE_STRING_PREFERRED_FAMILY_NAME,
|
||||
OPENTYPE_STRING_PREFERRED_SUBFAMILY_NAME,
|
||||
OPENTYPE_STRING_COMPATIBLE_FULLNAME,
|
||||
OPENTYPE_STRING_SAMPLE_TEXT,
|
||||
OPENTYPE_STRING_POSTSCRIPT_CID_NAME,
|
||||
OPENTYPE_STRING_WWS_FAMILY_NAME,
|
||||
OPENTYPE_STRING_WWS_SUBFAMILY_NAME
|
||||
};
|
||||
|
||||
static const UINT16 dwriteid_to_opentypeid[DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_CID_NAME+1] =
|
||||
{
|
||||
(UINT16)-1, /* DWRITE_INFORMATIONAL_STRING_NONE is not used */
|
||||
OPENTYPE_STRING_COPYRIGHT_NOTICE,
|
||||
OPENTYPE_STRING_VERSION_STRING,
|
||||
OPENTYPE_STRING_TRADEMARK,
|
||||
OPENTYPE_STRING_MANUFACTURER,
|
||||
OPENTYPE_STRING_DESIGNER,
|
||||
OPENTYPE_STRING_DESIGNER_URL,
|
||||
OPENTYPE_STRING_DESCRIPTION,
|
||||
OPENTYPE_STRING_VENDOR_URL,
|
||||
OPENTYPE_STRING_LICENSE_DESCRIPTION,
|
||||
OPENTYPE_STRING_LICENSE_INFO_URL,
|
||||
OPENTYPE_STRING_FAMILY_NAME,
|
||||
OPENTYPE_STRING_SUBFAMILY_NAME,
|
||||
OPENTYPE_STRING_PREFERRED_FAMILY_NAME,
|
||||
OPENTYPE_STRING_PREFERRED_SUBFAMILY_NAME,
|
||||
OPENTYPE_STRING_SAMPLE_TEXT,
|
||||
OPENTYPE_STRING_FULL_FONTNAME,
|
||||
OPENTYPE_STRING_POSTSCRIPT_FONTNAME,
|
||||
OPENTYPE_STRING_POSTSCRIPT_CID_NAME
|
||||
};
|
||||
|
||||
HRESULT opentype_analyze_font(IDWriteFontFileStream *stream, UINT32* font_count, DWRITE_FONT_FILE_TYPE *file_type, DWRITE_FONT_FACE_TYPE *face_type, BOOL *supported)
|
||||
{
|
||||
/* TODO: Do font validation */
|
||||
|
@ -532,3 +614,125 @@ VOID get_font_properties(LPCVOID os2, LPCVOID head, LPCVOID post, DWRITE_FONT_ME
|
|||
metrics->underlineThickness = GET_BE_WORD(tt_post->underlineThickness);
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT opentype_get_font_strings_from_id(IDWriteFontFace2 *fontface, DWRITE_INFORMATIONAL_STRING_ID id, IDWriteLocalizedStrings **strings)
|
||||
{
|
||||
const void *table_data = NULL;
|
||||
void *name_context = NULL;
|
||||
const TT_NAME_V0 *header;
|
||||
BYTE *storage_area = 0;
|
||||
BOOL exists = FALSE;
|
||||
USHORT count = 0;
|
||||
UINT16 name_id;
|
||||
UINT32 size;
|
||||
HRESULT hr;
|
||||
int i;
|
||||
|
||||
hr = IDWriteFontFace2_TryGetFontTable(fontface, MS_NAME_TAG, &table_data, &size, &name_context, &exists);
|
||||
if (FAILED(hr) || !exists) {
|
||||
FIXME("failed to get NAME table\n");
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
hr = create_localizedstrings(strings);
|
||||
if (FAILED(hr)) return hr;
|
||||
|
||||
header = table_data;
|
||||
storage_area = (LPBYTE)table_data + GET_BE_WORD(header->stringOffset);
|
||||
count = GET_BE_WORD(header->count);
|
||||
|
||||
name_id = dwriteid_to_opentypeid[id];
|
||||
|
||||
exists = FALSE;
|
||||
for (i = 0; i < count; i++) {
|
||||
const TT_NameRecord *record = &header->nameRecord[i];
|
||||
USHORT lang_id, length, offset, encoding, platform;
|
||||
|
||||
if (GET_BE_WORD(record->nameID) != name_id)
|
||||
continue;
|
||||
|
||||
exists = TRUE;
|
||||
|
||||
/* Right now only accept unicode and windows encoded fonts */
|
||||
platform = GET_BE_WORD(record->platformID);
|
||||
if (platform != 0 && platform != 3) {
|
||||
FIXME("platform %i not supported\n", platform);
|
||||
continue;
|
||||
}
|
||||
|
||||
lang_id = GET_BE_WORD(record->languageID);
|
||||
length = GET_BE_WORD(record->length);
|
||||
offset = GET_BE_WORD(record->offset);
|
||||
encoding = GET_BE_WORD(record->encodingID);
|
||||
|
||||
if (lang_id < 0x8000) {
|
||||
WCHAR locale[LOCALE_NAME_MAX_LENGTH];
|
||||
WCHAR *name_string;
|
||||
UINT codepage = 0;
|
||||
|
||||
if (platform == 3)
|
||||
{
|
||||
switch (encoding)
|
||||
{
|
||||
case TT_NAME_WINDOWS_ENCODING_SYMBOL:
|
||||
case TT_NAME_WINDOWS_ENCODING_UCS2:
|
||||
break;
|
||||
case TT_NAME_WINDOWS_ENCODING_SJIS:
|
||||
codepage = 932;
|
||||
break;
|
||||
case TT_NAME_WINDOWS_ENCODING_PRC:
|
||||
codepage = 936;
|
||||
break;
|
||||
case TT_NAME_WINDOWS_ENCODING_BIG5:
|
||||
codepage = 950;
|
||||
break;
|
||||
case TT_NAME_WINDOWS_ENCODING_WANSUNG:
|
||||
codepage = 20949;
|
||||
break;
|
||||
case TT_NAME_WINDOWS_ENCODING_JOHAB:
|
||||
codepage = 1361;
|
||||
break;
|
||||
default:
|
||||
FIXME("encoding %d not handled.\n", encoding);
|
||||
}
|
||||
}
|
||||
|
||||
if (codepage) {
|
||||
DWORD len = MultiByteToWideChar(codepage, 0, (LPSTR)(storage_area + offset), length, NULL, 0);
|
||||
name_string = heap_alloc(sizeof(WCHAR) * len);
|
||||
MultiByteToWideChar(codepage, 0, (LPSTR)(storage_area + offset), length, name_string, len);
|
||||
}
|
||||
else {
|
||||
int i;
|
||||
|
||||
length /= sizeof(WCHAR);
|
||||
name_string = heap_strdupnW((LPWSTR)(storage_area + offset), length);
|
||||
for (i = 0; i < length; i++)
|
||||
name_string[i] = GET_BE_WORD(name_string[i]);
|
||||
}
|
||||
|
||||
if (!LCIDToLocaleName(MAKELCID(lang_id, SORT_DEFAULT), locale, sizeof(locale)/sizeof(WCHAR), 0)) {
|
||||
static const WCHAR enusW[] = {'e','n','-','u','s',0};
|
||||
FIXME("failed to get locale name for lcid=0x%08x\n", MAKELCID(lang_id, SORT_DEFAULT));
|
||||
strcpyW(locale, enusW);
|
||||
}
|
||||
|
||||
TRACE("string %s for locale %s found\n", debugstr_w(name_string), debugstr_w(locale));
|
||||
add_localizedstring(*strings, locale, name_string);
|
||||
heap_free(name_string);
|
||||
}
|
||||
else {
|
||||
FIXME("handle NAME format 1");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
IDWriteFontFace2_ReleaseFontTable(fontface, name_context);
|
||||
|
||||
if (!exists) {
|
||||
IDWriteLocalizedStrings_Release(*strings);
|
||||
*strings = NULL;
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
|
|
@ -1325,11 +1325,10 @@ static void test_GetInformationalStrings(void)
|
|||
exists = TRUE;
|
||||
strings = (void*)0xdeadbeef;
|
||||
hr = IDWriteFont_GetInformationalStrings(font, DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_CID_NAME+1, &strings, &exists);
|
||||
todo_wine {
|
||||
ok(hr == S_OK, "got 0x%08x\n", hr);
|
||||
ok(exists == FALSE, "got %d\n", exists);
|
||||
ok(strings == NULL, "got %p\n", strings);
|
||||
}
|
||||
|
||||
exists = FALSE;
|
||||
strings = NULL;
|
||||
hr = IDWriteFont_GetInformationalStrings(font, DWRITE_INFORMATIONAL_STRING_WIN32_FAMILY_NAMES, &strings, &exists);
|
||||
|
@ -1337,14 +1336,11 @@ todo_wine {
|
|||
ok(hr == S_OK, "got 0x%08x\n", hr);
|
||||
ok(exists == TRUE, "got %d\n", exists);
|
||||
}
|
||||
|
||||
exists = TRUE;
|
||||
strings = NULL;
|
||||
hr = IDWriteFont_GetInformationalStrings(font, DWRITE_INFORMATIONAL_STRING_NONE, &strings, &exists);
|
||||
todo_wine {
|
||||
ok(hr == S_OK, "got 0x%08x\n", hr);
|
||||
ok(exists == FALSE, "got %d\n", exists);
|
||||
}
|
||||
|
||||
/* strings instance is not reused */
|
||||
strings2 = NULL;
|
||||
|
|
Loading…
Reference in New Issue