Commit 04a237fe authored by Nikolay Sivov's avatar Nikolay Sivov Committed by Alexandre Julliard

dwrite: Implement GetInformationalStrings().

parent 177f6018
......@@ -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;
......
/*
* 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;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment