[PATCH 1/4] dwrite: Add support for dlng/slng metadata.
Nikolay Sivov
nsivov at codeweavers.com
Sun Jan 26 23:52:48 CST 2020
Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
dlls/dwrite/dwrite_private.h | 2 +-
dlls/dwrite/font.c | 6 +-
dlls/dwrite/main.c | 11 ++-
dlls/dwrite/opentype.c | 149 +++++++++++++++++++++++++++++++++--
4 files changed, 152 insertions(+), 16 deletions(-)
diff --git a/dlls/dwrite/dwrite_private.h b/dlls/dwrite/dwrite_private.h
index 6adba28280..e5ca5306c2 100644
--- a/dlls/dwrite/dwrite_private.h
+++ b/dlls/dwrite/dwrite_private.h
@@ -231,7 +231,7 @@ struct dwrite_fontface
FONTSIGNATURE fontsig;
UINT32 glyph_image_formats;
- IDWriteLocalizedStrings *info_strings[DWRITE_INFORMATIONAL_STRING_WEIGHT_STRETCH_STYLE_FAMILY_NAME + 1];
+ IDWriteLocalizedStrings *info_strings[DWRITE_INFORMATIONAL_STRING_SUPPORTED_SCRIPT_LANGUAGE_TAG + 1];
IDWriteLocalizedStrings *family_names;
IDWriteLocalizedStrings *names;
diff --git a/dlls/dwrite/font.c b/dlls/dwrite/font.c
index 8bcbe11fcb..847070816b 100644
--- a/dlls/dwrite/font.c
+++ b/dlls/dwrite/font.c
@@ -82,7 +82,7 @@ struct dwrite_font_data
struct dwrite_font_propvec propvec;
DWRITE_FONT_METRICS1 metrics;
- IDWriteLocalizedStrings *info_strings[DWRITE_INFORMATIONAL_STRING_WEIGHT_STRETCH_STYLE_FAMILY_NAME + 1];
+ IDWriteLocalizedStrings *info_strings[DWRITE_INFORMATIONAL_STRING_SUPPORTED_SCRIPT_LANGUAGE_TAG + 1];
IDWriteLocalizedStrings *family_names;
IDWriteLocalizedStrings *names;
@@ -1291,8 +1291,8 @@ static HRESULT get_font_info_strings(const struct file_stream_desc *stream_desc,
*exists = FALSE;
*ret = NULL;
- if (stringid > DWRITE_INFORMATIONAL_STRING_WEIGHT_STRETCH_STYLE_FAMILY_NAME
- || stringid == DWRITE_INFORMATIONAL_STRING_NONE)
+ if (stringid > DWRITE_INFORMATIONAL_STRING_SUPPORTED_SCRIPT_LANGUAGE_TAG
+ || stringid <= DWRITE_INFORMATIONAL_STRING_NONE)
{
return S_OK;
}
diff --git a/dlls/dwrite/main.c b/dlls/dwrite/main.c
index 283cccb76c..b940d0d801 100644
--- a/dlls/dwrite/main.c
+++ b/dlls/dwrite/main.c
@@ -446,10 +446,13 @@ HRESULT add_localizedstring(IDWriteLocalizedStrings *iface, const WCHAR *locale,
struct localizedstrings *strings = impl_from_IDWriteLocalizedStrings(iface);
size_t i, count = strings->count;
- /* make sure there's no duplicates */
- for (i = 0; i < count; i++)
- if (!strcmpW(strings->data[i].locale, locale))
- return S_OK;
+ /* Make sure there's no duplicates, unless it's empty. This is used by dlng/slng entries of 'meta' table. */
+ if (*locale)
+ {
+ for (i = 0; i < count; i++)
+ if (!strcmpW(strings->data[i].locale, locale))
+ return S_OK;
+ }
if (!dwrite_array_reserve((void **)&strings->data, &strings->size, strings->count + 1, sizeof(*strings->data)))
return E_OUTOFMEMORY;
diff --git a/dlls/dwrite/opentype.c b/dlls/dwrite/opentype.c
index fd420e4360..23d7669eb6 100644
--- a/dlls/dwrite/opentype.c
+++ b/dlls/dwrite/opentype.c
@@ -46,6 +46,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(dwrite);
#define MS_MAXP_TAG DWRITE_MAKE_OPENTYPE_TAG('m','a','x','p')
#define MS_CBLC_TAG DWRITE_MAKE_OPENTYPE_TAG('C','B','L','C')
#define MS_CMAP_TAG DWRITE_MAKE_OPENTYPE_TAG('c','m','a','p')
+#define MS_META_TAG DWRITE_MAKE_OPENTYPE_TAG('m','e','t','a')
/* 'sbix' formats */
#define MS_PNG__TAG DWRITE_MAKE_OPENTYPE_TAG('p','n','g',' ')
@@ -55,6 +56,10 @@ WINE_DEFAULT_DEBUG_CHANNEL(dwrite);
#define MS_WOFF_TAG DWRITE_MAKE_OPENTYPE_TAG('w','O','F','F')
#define MS_WOF2_TAG DWRITE_MAKE_OPENTYPE_TAG('w','O','F','2')
+/* 'meta' tags */
+#define MS_DLNG_TAG DWRITE_MAKE_OPENTYPE_TAG('d','l','n','g')
+#define MS_SLNG_TAG DWRITE_MAKE_OPENTYPE_TAG('s','l','n','g')
+
#ifdef WORDS_BIGENDIAN
#define GET_BE_WORD(x) (x)
#define GET_BE_DWORD(x) (x)
@@ -1164,6 +1169,22 @@ struct colr_layer_record
USHORT palette_index;
};
+struct meta_data_map
+{
+ DWORD tag;
+ DWORD offset;
+ DWORD length;
+};
+
+struct meta_header
+{
+ DWORD version;
+ DWORD flags;
+ DWORD reserved;
+ DWORD data_maps_count;
+ struct meta_data_map maps[1];
+};
+
static const void *table_read_ensure(const struct dwrite_fonttable *table, unsigned int offset, unsigned int size)
{
if (size > table->size || offset > table->size - size)
@@ -2109,23 +2130,135 @@ static HRESULT opentype_get_font_strings_from_id(const void *table_data, enum OP
return exists ? S_OK : E_FAIL;
}
-/* Provides a conversion from DWRITE to OpenType name ids, input id should be valid, it's not checked. */
-HRESULT opentype_get_font_info_strings(const struct file_stream_desc *stream_desc, DWRITE_INFORMATIONAL_STRING_ID id,
- IDWriteLocalizedStrings **strings)
+static WCHAR *meta_get_lng_name(WCHAR *str, WCHAR **ctx)
{
- struct dwrite_fonttable name;
+ static const WCHAR delimW[] = {',',' ',0};
+ WCHAR *ret;
+
+ if (!str) str = *ctx;
+ while (*str && strchrW(delimW, *str)) str++;
+ if (!*str) return NULL;
+ ret = str++;
+ while (*str && !strchrW(delimW, *str)) str++;
+ if (*str) *str++ = 0;
+ *ctx = str;
+
+ return ret;
+}
+
+static HRESULT opentype_get_font_strings_from_meta(const struct file_stream_desc *stream_desc,
+ DWRITE_INFORMATIONAL_STRING_ID id, IDWriteLocalizedStrings **ret)
+{
+ static const WCHAR emptyW[] = { 0 };
+ const struct meta_data_map *maps;
+ IDWriteLocalizedStrings *strings;
+ struct dwrite_fonttable meta;
+ DWORD version, i, count, tag;
HRESULT hr;
- opentype_get_font_table(stream_desc, MS_NAME_TAG, &name);
+ *ret = NULL;
- hr = opentype_get_font_strings_from_id(name.data, dwriteid_to_opentypeid[id], strings);
+ hr = create_localizedstrings(&strings);
+ if (FAILED(hr))
+ return hr;
- if (name.context)
- IDWriteFontFileStream_ReleaseFileFragment(stream_desc->stream, name.context);
+ switch (id)
+ {
+ case DWRITE_INFORMATIONAL_STRING_DESIGN_SCRIPT_LANGUAGE_TAG:
+ tag = MS_DLNG_TAG;
+ break;
+ case DWRITE_INFORMATIONAL_STRING_SUPPORTED_SCRIPT_LANGUAGE_TAG:
+ tag = MS_SLNG_TAG;
+ break;
+ default:
+ WARN("Unexpected id %d.\n", id);
+ return S_OK;
+ }
+
+ opentype_get_font_table(stream_desc, MS_META_TAG, &meta);
+
+ if (meta.data)
+ {
+ version = table_read_be_dword(&meta, 0);
+ if (version != 1)
+ {
+ WARN("Unexpected meta table version %d.\n", version);
+ goto end;
+ }
+
+ count = table_read_be_dword(&meta, FIELD_OFFSET(struct meta_header, data_maps_count));
+ if (!(maps = table_read_ensure(&meta, FIELD_OFFSET(struct meta_header, maps),
+ count * sizeof(struct meta_data_map))))
+ goto end;
+
+ for (i = 0; i < count; ++i)
+ {
+ const char *data;
+
+ if (maps[i].tag == tag && maps[i].length)
+ {
+ DWORD length = GET_BE_DWORD(maps[i].length), j;
+
+ if ((data = table_read_ensure(&meta, GET_BE_DWORD(maps[i].offset), length)))
+ {
+ WCHAR *ptrW = heap_alloc((length + 1) * sizeof(WCHAR)), *ctx, *token;
+
+ if (!ptrW)
+ {
+ hr = E_OUTOFMEMORY;
+ goto end;
+ }
+
+ /* Data is stored in comma separated list, ASCII range only. */
+ for (j = 0; j < length; ++j)
+ ptrW[j] = data[j];
+ ptrW[length] = 0;
+
+ token = meta_get_lng_name(ptrW, &ctx);
+
+ while (token)
+ {
+ add_localizedstring(strings, emptyW, token);
+ token = meta_get_lng_name(NULL, &ctx);
+ }
+
+ heap_free(ptrW);
+ }
+ }
+ }
+end:
+ IDWriteFontFileStream_ReleaseFileFragment(stream_desc->stream, meta.context);
+ }
+
+ if (IDWriteLocalizedStrings_GetCount(strings))
+ *ret = strings;
+ else
+ IDWriteLocalizedStrings_Release(strings);
return hr;
}
+HRESULT opentype_get_font_info_strings(const struct file_stream_desc *stream_desc, DWRITE_INFORMATIONAL_STRING_ID id,
+ IDWriteLocalizedStrings **strings)
+{
+ struct dwrite_fonttable name;
+
+ switch (id)
+ {
+ case DWRITE_INFORMATIONAL_STRING_DESIGN_SCRIPT_LANGUAGE_TAG:
+ case DWRITE_INFORMATIONAL_STRING_SUPPORTED_SCRIPT_LANGUAGE_TAG:
+ opentype_get_font_strings_from_meta(stream_desc, id, strings);
+ break;
+ default:
+ opentype_get_font_table(stream_desc, MS_NAME_TAG, &name);
+ opentype_get_font_strings_from_id(name.data, dwriteid_to_opentypeid[id], strings);
+ if (name.context)
+ IDWriteFontFileStream_ReleaseFileFragment(stream_desc->stream, name.context);
+ }
+
+ return S_OK;
+}
+
/* FamilyName locating order is WWS Family Name -> Preferred Family Name -> Family Name. If font claims to
have 'Preferred Family Name' in WWS format, then WWS name is not used. */
HRESULT opentype_get_font_familyname(struct file_stream_desc *stream_desc, IDWriteLocalizedStrings **names)
--
2.24.1
More information about the wine-devel
mailing list