Aric Stewart : dwrite: Implement TryGetFontTable and ReleaseFontTable.
Alexandre Julliard
julliard at wine.codeweavers.com
Wed Aug 20 14:30:35 CDT 2014
Module: wine
Branch: master
Commit: bc77ee68180e402148f70f75d7a9464324fc7ea1
URL: http://source.winehq.org/git/wine.git/?a=commit;h=bc77ee68180e402148f70f75d7a9464324fc7ea1
Author: Aric Stewart <aric at codeweavers.com>
Date: Sat Aug 16 20:42:24 2014 -0500
dwrite: Implement TryGetFontTable and ReleaseFontTable.
---
dlls/dwrite/dwrite_private.h | 1 +
dlls/dwrite/font.c | 65 ++++++++++++++++++++++++++++++--
dlls/dwrite/opentype.c | 88 ++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 151 insertions(+), 3 deletions(-)
diff --git a/dlls/dwrite/dwrite_private.h b/dlls/dwrite/dwrite_private.h
index f56b6f0..a64e632 100644
--- a/dlls/dwrite/dwrite_private.h
+++ b/dlls/dwrite/dwrite_private.h
@@ -94,3 +94,4 @@ extern HRESULT font_create_fontface(IDWriteFactory *iface, DWRITE_FONT_FACE_TYPE
/* Opentype font table functions */
extern HRESULT analyze_opentype_font(const void* font_data, UINT32* font_count, DWRITE_FONT_FILE_TYPE *file_type, DWRITE_FONT_FACE_TYPE *face_type, BOOL *supported) DECLSPEC_HIDDEN;
+extern HRESULT find_font_table(IDWriteFontFileStream *stream, UINT32 font_index, UINT32 tag, const void** table_data, void** table_context, UINT32 *table_size, BOOL* found) DECLSPEC_HIDDEN;
diff --git a/dlls/dwrite/font.c b/dlls/dwrite/font.c
index 8c82d08..0683dd5 100644
--- a/dlls/dwrite/font.c
+++ b/dlls/dwrite/font.c
@@ -156,6 +156,14 @@ struct dwrite_font {
WCHAR *facename;
};
+#define DWRITE_FONTTABLE_MAGIC 0xededfafa
+
+struct dwrite_fonttable {
+ UINT32 magic;
+ LPVOID context;
+ UINT32 file_index;
+};
+
struct dwrite_fontface {
IDWriteFontFace IDWriteFontFace_iface;
LONG ref;
@@ -384,14 +392,65 @@ static HRESULT WINAPI dwritefontface_TryGetFontTable(IDWriteFontFace *iface, UIN
const void **table_data, UINT32 *table_size, void **context, BOOL *exists)
{
struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
- FIXME("(%p)->(%u %p %p %p %p): stub\n", This, table_tag, table_data, table_size, context, exists);
- return E_NOTIMPL;
+ if (This->is_system)
+ {
+ FIXME("(%p)->(%u %p %p %p %p): stub\n", This, table_tag, table_data, table_size, context, exists);
+ return E_NOTIMPL;
+ }
+ else
+ {
+ HRESULT hr = S_OK;
+ int i;
+ struct dwrite_fonttable *table;
+
+ TRACE("(%p)->(%u %p %p %p %p)\n", This, table_tag, table_data, table_size, context, exists);
+
+ table = heap_alloc(sizeof(struct dwrite_fonttable));
+ table->magic = DWRITE_FONTTABLE_MAGIC;
+ if (!table)
+ return E_OUTOFMEMORY;
+
+ *exists = FALSE;
+ for (i = 0; i < This->file_count && !(*exists); i++)
+ {
+ IDWriteFontFileStream *stream;
+ hr = _dwritefontfile_GetFontFileStream(This->files[i], &stream);
+ if (FAILED(hr))
+ continue;
+ table->file_index = i;
+
+ hr = find_font_table(stream, This->index, table_tag, table_data, &table->context, table_size, exists);
+
+ IDWriteFontFileStream_Release(stream);
+ }
+ if (FAILED(hr) && !*exists)
+ heap_free(table);
+ else
+ *context = (LPVOID)table;
+ return hr;
+ }
}
static void WINAPI dwritefontface_ReleaseFontTable(IDWriteFontFace *iface, void *table_context)
{
struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
- FIXME("(%p)->(%p): stub\n", This, table_context);
+ struct dwrite_fonttable *table = (struct dwrite_fonttable *)table_context;
+ IDWriteFontFileStream *stream;
+ HRESULT hr;
+ TRACE("(%p)->(%p)\n", This, table_context);
+
+ if (table->magic != DWRITE_FONTTABLE_MAGIC)
+ {
+ TRACE("Invalid table magic\n");
+ return;
+ }
+
+ hr = _dwritefontfile_GetFontFileStream(This->files[table->file_index], &stream);
+ if (FAILED(hr))
+ return;
+ IDWriteFontFileStream_ReleaseFileFragment(stream, table->context);
+ IDWriteFontFileStream_Release(stream);
+ heap_free(table);
}
static HRESULT WINAPI dwritefontface_GetGlyphRunOutline(IDWriteFontFace *iface, FLOAT emSize,
diff --git a/dlls/dwrite/opentype.c b/dlls/dwrite/opentype.c
index 538db98..6c90a96 100644
--- a/dlls/dwrite/opentype.c
+++ b/dlls/dwrite/opentype.c
@@ -47,6 +47,21 @@ typedef struct {
DWORD OffsetTable[1];
} TTC_Header_V1;
+typedef struct {
+ DWORD version;
+ WORD numTables;
+ WORD searchRange;
+ WORD entrySelector;
+ WORD rangeShift;
+} TTC_SFNT_V1;
+
+typedef struct {
+ CHAR tag[4];
+ DWORD checkSum;
+ DWORD offset;
+ DWORD length;
+} TT_TableRecord;
+
HRESULT analyze_opentype_font(const void* font_data, UINT32* font_count, DWRITE_FONT_FILE_TYPE *file_type, DWRITE_FONT_FACE_TYPE *face_type, BOOL *supported)
{
/* TODO: Do font validation */
@@ -81,3 +96,76 @@ HRESULT analyze_opentype_font(const void* font_data, UINT32* font_count, DWRITE_
}
return S_OK;
}
+
+HRESULT find_font_table(IDWriteFontFileStream *stream, UINT32 font_index, UINT32 tag, const void** table_data, void** table_context, UINT32 *table_size, BOOL* found)
+{
+ const CHAR *first_data;
+ void *first_context;
+ HRESULT hr;
+ TTC_SFNT_V1 *font_header = NULL;
+ void *sfnt_context;
+ TT_TableRecord *table_record = NULL;
+ void *table_record_context;
+ int i;
+ int table_count;
+ int table_offset = 0;
+
+ *found = FALSE;
+
+ hr = IDWriteFontFileStream_ReadFileFragment(stream, (const void**)&first_data, 0, 4, &first_context);
+ if (SUCCEEDED(hr))
+ {
+ if (DWRITE_MAKE_OPENTYPE_TAG(first_data[0], first_data[1], first_data[2], first_data[3]) == MS_TTCF_TAG)
+ {
+ const TTC_Header_V1 *ttc_header;
+ void * ttc_context;
+ hr = IDWriteFontFileStream_ReadFileFragment(stream, (const void**)&ttc_header, 0, sizeof(*ttc_header), &ttc_context);
+ if (SUCCEEDED(hr))
+ {
+ table_offset = GET_BE_DWORD(ttc_header->OffsetTable[0]);
+ if (font_index >= GET_BE_DWORD(ttc_header->numFonts))
+ hr = E_INVALIDARG;
+ else
+ hr = IDWriteFontFileStream_ReadFileFragment(stream, (const void**)&font_header, table_offset, sizeof(*font_header), &sfnt_context);
+ IDWriteFontFileStream_ReleaseFileFragment(stream, ttc_context);
+ }
+ }
+ else
+ {
+ if (font_index > 0)
+ hr = E_INVALIDARG;
+ else
+ hr = IDWriteFontFileStream_ReadFileFragment(stream, (const void**)&font_header, 0, sizeof(*font_header), &sfnt_context);
+ }
+ IDWriteFontFileStream_ReleaseFileFragment(stream, first_context);
+ }
+ if (FAILED(hr))
+ return hr;
+
+ table_count = GET_BE_WORD(font_header->numTables);
+ table_offset += sizeof(*font_header);
+ for (i = 0; i < table_count; i++)
+ {
+ hr = IDWriteFontFileStream_ReadFileFragment(stream, (const void**)&table_record, table_offset, sizeof(*table_record), &table_record_context);
+ if (FAILED(hr))
+ break;
+ if (DWRITE_MAKE_OPENTYPE_TAG(table_record->tag[0], table_record->tag[1], table_record->tag[2], table_record->tag[3]) == tag)
+ break;
+ IDWriteFontFileStream_ReleaseFileFragment(stream, table_record_context);
+ table_offset += sizeof(*table_record);
+ }
+
+ IDWriteFontFileStream_ReleaseFileFragment(stream, sfnt_context);
+ if (SUCCEEDED(hr) && i < table_count)
+ {
+ int offset = GET_BE_DWORD(table_record->offset);
+ int length = GET_BE_DWORD(table_record->length);
+ IDWriteFontFileStream_ReleaseFileFragment(stream, table_record_context);
+
+ *found = TRUE;
+ *table_size = length;
+ hr = IDWriteFontFileStream_ReadFileFragment(stream, table_data, offset, length, table_context);
+ }
+
+ return hr;
+}
More information about the wine-cvs
mailing list