Commit bc77ee68 authored by Aric Stewart's avatar Aric Stewart Committed by Alexandre Julliard

dwrite: Implement TryGetFontTable and ReleaseFontTable.

parent 26977d4a
......@@ -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;
......@@ -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,
......
......@@ -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;
}
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