dwrite: Implement GetUnicodeRanges().
This commit is contained in:
parent
d3cdec0e66
commit
4c0ec6700c
|
@ -48,7 +48,7 @@
|
|||
#include "wine/debug.h"
|
||||
#include "wine/list.h"
|
||||
|
||||
#include "dwrite.h"
|
||||
#include "dwrite_1.h"
|
||||
#include "dwrite_private.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(bidi);
|
||||
|
|
|
@ -109,6 +109,7 @@ extern HRESULT font_create_fontface(IDWriteFactory *iface, DWRITE_FONT_FACE_TYPE
|
|||
extern HRESULT opentype_analyze_font(IDWriteFontFileStream*,UINT32*,DWRITE_FONT_FILE_TYPE*,DWRITE_FONT_FACE_TYPE*,BOOL*) DECLSPEC_HIDDEN;
|
||||
extern HRESULT opentype_get_font_table(IDWriteFontFileStream*,DWRITE_FONT_FACE_TYPE,UINT32,UINT32,const void**,void**,UINT32*,BOOL*) DECLSPEC_HIDDEN;
|
||||
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 bidi_computelevels(const WCHAR*,UINT32,UINT8,UINT8*,UINT8*);
|
||||
|
|
|
@ -163,6 +163,24 @@ static inline struct dwrite_fontcollection *impl_from_IDWriteFontCollection(IDWr
|
|||
return CONTAINING_RECORD(iface, struct dwrite_fontcollection, IDWriteFontCollection_iface);
|
||||
}
|
||||
|
||||
static inline void* get_fontface_cmap(struct dwrite_fontface *fontface)
|
||||
{
|
||||
BOOL exists = FALSE;
|
||||
HRESULT hr;
|
||||
|
||||
if (fontface->cmap.data)
|
||||
return fontface->cmap.data;
|
||||
|
||||
hr = IDWriteFontFace2_TryGetFontTable(&fontface->IDWriteFontFace2_iface, MS_CMAP_TAG, (const void**)&fontface->cmap.data,
|
||||
&fontface->cmap.size, &fontface->cmap.context, &exists);
|
||||
if (FAILED(hr) || !exists) {
|
||||
ERR("Font does not have a CMAP table\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return fontface->cmap.data;
|
||||
}
|
||||
|
||||
static HRESULT _dwritefontfile_GetFontFileStream(IDWriteFontFile *iface, IDWriteFontFileStream **stream)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
@ -377,21 +395,16 @@ static HRESULT WINAPI dwritefontface_GetGlyphIndices(IDWriteFontFace2 *iface, UI
|
|||
}
|
||||
else
|
||||
{
|
||||
HRESULT hr;
|
||||
void *data;
|
||||
|
||||
TRACE("(%p)->(%p %u %p)\n", This, codepoints, count, glyph_indices);
|
||||
if (!This->cmap.data)
|
||||
{
|
||||
BOOL exists = FALSE;
|
||||
hr = IDWriteFontFace2_TryGetFontTable(iface, MS_CMAP_TAG, (const void**)&This->cmap.data, &This->cmap.size, &This->cmap.context, &exists);
|
||||
if (FAILED(hr) || !exists)
|
||||
{
|
||||
ERR("Font does not have a CMAP table\n");
|
||||
return E_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
data = get_fontface_cmap(This);
|
||||
if (!data)
|
||||
return E_FAIL;
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
opentype_cmap_get_glyphindex(This->cmap.data, codepoints[i], &glyph_indices[i]);
|
||||
opentype_cmap_get_glyphindex(data, codepoints[i], &glyph_indices[i]);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
@ -523,8 +536,14 @@ static HRESULT WINAPI dwritefontface1_GetUnicodeRanges(IDWriteFontFace2 *iface,
|
|||
DWRITE_UNICODE_RANGE *ranges, UINT32 *count)
|
||||
{
|
||||
struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
|
||||
FIXME("(%p)->(%u %p %p): stub\n", This, max_count, ranges, count);
|
||||
return E_NOTIMPL;
|
||||
|
||||
TRACE("(%p)->(%u %p %p)\n", This, max_count, ranges, count);
|
||||
|
||||
*count = 0;
|
||||
if (max_count && !ranges)
|
||||
return E_INVALIDARG;
|
||||
|
||||
return opentype_cmap_get_unicode_ranges(get_fontface_cmap(This), max_count, ranges, count);
|
||||
}
|
||||
|
||||
static BOOL WINAPI dwritefontface1_IsMonospacedFont(IDWriteFontFace2 *iface)
|
||||
|
@ -907,8 +926,23 @@ static void WINAPI dwritefont1_GetPanose(IDWriteFont2 *iface, DWRITE_PANOSE *pan
|
|||
static HRESULT WINAPI dwritefont1_GetUnicodeRanges(IDWriteFont2 *iface, UINT32 max_count, DWRITE_UNICODE_RANGE *ranges, UINT32 *count)
|
||||
{
|
||||
struct dwrite_font *This = impl_from_IDWriteFont2(iface);
|
||||
FIXME("(%p)->(%u %p %p): stub\n", This, max_count, ranges, count);
|
||||
return E_NOTIMPL;
|
||||
IDWriteFontFace2 *fontface2;
|
||||
IDWriteFontFace *fontface;
|
||||
HRESULT hr;
|
||||
|
||||
TRACE("(%p)->(%u %p %p)\n", This, max_count, ranges, count);
|
||||
|
||||
hr = IDWriteFont2_CreateFontFace(iface, &fontface);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
IDWriteFontFace_QueryInterface(fontface, &IID_IDWriteFontFace2, (void**)&fontface2);
|
||||
IDWriteFontFace_Release(fontface);
|
||||
|
||||
hr = IDWriteFontFace2_GetUnicodeRanges(fontface2, max_count, ranges, count);
|
||||
IDWriteFontFace2_Release(fontface2);
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI dwritefont1_IsMonospacedFont(IDWriteFont2 *iface)
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
#include "windef.h"
|
||||
#include "winbase.h"
|
||||
#include "wingdi.h"
|
||||
#include "dwrite.h"
|
||||
#include "dwrite_1.h"
|
||||
#include "dwrite_private.h"
|
||||
|
||||
#include "wine/debug.h"
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
|
||||
#define COBJMACROS
|
||||
|
||||
#include "dwrite.h"
|
||||
#include "dwrite_1.h"
|
||||
#include "dwrite_private.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(dwrite);
|
||||
|
@ -393,6 +393,98 @@ void opentype_cmap_get_glyphindex(void *data, UINT32 utf32c, UINT16 *pgi)
|
|||
}
|
||||
}
|
||||
|
||||
static UINT32 opentype_cmap_get_unicode_ranges_count(const CMAP_Header *CMAP_Table)
|
||||
{
|
||||
UINT32 count = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < GET_BE_WORD(CMAP_Table->numTables); i++) {
|
||||
WORD type;
|
||||
WORD *table;
|
||||
|
||||
if (GET_BE_WORD(CMAP_Table->tables[i].platformID) != 3)
|
||||
continue;
|
||||
|
||||
table = (WORD*)(((BYTE*)CMAP_Table) + GET_BE_DWORD(CMAP_Table->tables[i].offset));
|
||||
type = GET_BE_WORD(*table);
|
||||
TRACE("table type %i\n", type);
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case OPENTYPE_CMAP_TABLE_SEGMENT_MAPPING:
|
||||
{
|
||||
CMAP_SegmentMapping_0 *format = (CMAP_SegmentMapping_0*)table;
|
||||
count += GET_BE_WORD(format->segCountX2)/2;
|
||||
break;
|
||||
}
|
||||
case OPENTYPE_CMAP_TABLE_SEGMENTED_COVERAGE:
|
||||
{
|
||||
CMAP_SegmentedCoverage *format = (CMAP_SegmentedCoverage*)table;
|
||||
count += GET_BE_DWORD(format->nGroups);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
FIXME("table type %i unhandled.\n", type);
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
HRESULT opentype_cmap_get_unicode_ranges(void *data, UINT32 max_count, DWRITE_UNICODE_RANGE *ranges, UINT32 *count)
|
||||
{
|
||||
CMAP_Header *CMAP_Table = data;
|
||||
int i, k = 0;
|
||||
|
||||
if (!CMAP_Table)
|
||||
return E_FAIL;
|
||||
|
||||
*count = opentype_cmap_get_unicode_ranges_count(CMAP_Table);
|
||||
|
||||
for (i = 0; i < GET_BE_WORD(CMAP_Table->numTables) && k < max_count; i++)
|
||||
{
|
||||
WORD type;
|
||||
WORD *table;
|
||||
int j;
|
||||
|
||||
if (GET_BE_WORD(CMAP_Table->tables[i].platformID) != 3)
|
||||
continue;
|
||||
|
||||
table = (WORD*)(((BYTE*)CMAP_Table) + GET_BE_DWORD(CMAP_Table->tables[i].offset));
|
||||
type = GET_BE_WORD(*table);
|
||||
TRACE("table type %i\n", type);
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case OPENTYPE_CMAP_TABLE_SEGMENT_MAPPING:
|
||||
{
|
||||
CMAP_SegmentMapping_0 *format = (CMAP_SegmentMapping_0*)table;
|
||||
UINT16 segment_count = GET_BE_WORD(format->segCountX2)/2;
|
||||
UINT16 *startCode = (WORD*)((BYTE*)format + sizeof(CMAP_SegmentMapping_0) + (sizeof(WORD) * segment_count));
|
||||
|
||||
for (j = 0; j < segment_count && GET_BE_WORD(format->endCode[j]) < 0xffff && k < max_count; j++, k++) {
|
||||
ranges[k].first = GET_BE_WORD(startCode[j]);
|
||||
ranges[k].last = GET_BE_WORD(format->endCode[j]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case OPENTYPE_CMAP_TABLE_SEGMENTED_COVERAGE:
|
||||
{
|
||||
CMAP_SegmentedCoverage *format = (CMAP_SegmentedCoverage*)table;
|
||||
for (j = 0; j < GET_BE_DWORD(format->nGroups) && k < max_count; j++, k++) {
|
||||
ranges[k].first = GET_BE_DWORD(format->groups[j].startCharCode);
|
||||
ranges[k].last = GET_BE_DWORD(format->groups[j].endCharCode);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
FIXME("table type %i unhandled.\n", type);
|
||||
}
|
||||
}
|
||||
|
||||
return *count > max_count ? E_NOT_SUFFICIENT_BUFFER : S_OK;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
TT_OS2_V2 *tt_os2 = (TT_OS2_V2*)os2;
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
|
||||
#define COBJMACROS
|
||||
|
||||
#include "dwrite.h"
|
||||
#include "dwrite_1.h"
|
||||
#include "dwrite_private.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(dwrite);
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
#define COBJMACROS
|
||||
|
||||
#include "windows.h"
|
||||
#include "dwrite.h"
|
||||
#include "dwrite_1.h"
|
||||
|
||||
#include "wine/test.h"
|
||||
|
||||
|
@ -37,6 +37,16 @@ static void _expect_ref(IUnknown* obj, ULONG ref, int line)
|
|||
ok_(__FILE__,line)(rc == ref, "expected refcount %d, got %d\n", ref, rc);
|
||||
}
|
||||
|
||||
static inline void *heap_alloc(size_t len)
|
||||
{
|
||||
return HeapAlloc(GetProcessHeap(), 0, len);
|
||||
}
|
||||
|
||||
static inline BOOL heap_free(void *mem)
|
||||
{
|
||||
return HeapFree(GetProcessHeap(), 0, mem);
|
||||
}
|
||||
|
||||
static IDWriteFactory *factory;
|
||||
|
||||
static const WCHAR tahomaW[] = {'T','a','h','o','m','a',0};
|
||||
|
@ -189,6 +199,7 @@ static const struct IDWriteFontFileLoaderVtbl resourcefontfileloadervtbl = {
|
|||
resourcefontfileloader_CreateStreamFromKey
|
||||
};
|
||||
|
||||
static IDWriteFontFileLoader rloader = { &resourcefontfileloadervtbl };
|
||||
|
||||
static void test_CreateFontFromLOGFONT(void)
|
||||
{
|
||||
|
@ -939,7 +950,6 @@ static void test_FontLoader(void)
|
|||
IDWriteFontFileLoader floader = { &dwritefontfileloadervtbl };
|
||||
IDWriteFontFileLoader floader2 = { &dwritefontfileloadervtbl };
|
||||
IDWriteFontFileLoader floader3 = { &dwritefontfileloadervtbl };
|
||||
IDWriteFontFileLoader rloader = { &resourcefontfileloadervtbl };
|
||||
IDWriteFontFile *ffile = NULL;
|
||||
BOOL support = 1;
|
||||
DWRITE_FONT_FILE_TYPE type = 1;
|
||||
|
@ -1117,6 +1127,68 @@ static void test_shared_isolated(void)
|
|||
IDWriteFactory_Release(isolated2);
|
||||
}
|
||||
|
||||
static void test_GetUnicodeRanges(void)
|
||||
{
|
||||
DWRITE_UNICODE_RANGE *ranges, r;
|
||||
IDWriteFontFile *ffile = NULL;
|
||||
IDWriteFontFace1 *fontface1;
|
||||
IDWriteFontFace *fontface;
|
||||
UINT32 count;
|
||||
HRESULT hr;
|
||||
HRSRC font;
|
||||
|
||||
hr = IDWriteFactory_RegisterFontFileLoader(factory, &rloader);
|
||||
ok(hr == S_OK, "got 0x%08x\n", hr);
|
||||
|
||||
font = FindResourceA(GetModuleHandleA(NULL), (LPCSTR)MAKEINTRESOURCE(1), (LPCSTR)RT_RCDATA);
|
||||
ok(font != NULL, "Failed to find font resource\n");
|
||||
|
||||
hr = IDWriteFactory_CreateCustomFontFileReference(factory, &font, sizeof(HRSRC), &rloader, &ffile);
|
||||
ok(hr == S_OK, "got 0x%08x\n", hr);
|
||||
|
||||
hr = IDWriteFactory_CreateFontFace(factory, DWRITE_FONT_FACE_TYPE_TRUETYPE, 1, &ffile, 0, DWRITE_FONT_SIMULATIONS_NONE, &fontface);
|
||||
ok(hr == S_OK, "got 0x%08x\n", hr);
|
||||
IDWriteFontFile_Release(ffile);
|
||||
|
||||
hr = IDWriteFontFace_QueryInterface(fontface, &IID_IDWriteFontFace1, (void**)&fontface1);
|
||||
IDWriteFontFace_Release(fontface);
|
||||
if (hr != S_OK) {
|
||||
win_skip("GetUnicodeRanges() is not supported.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
count = 0;
|
||||
hr = IDWriteFontFace1_GetUnicodeRanges(fontface1, 0, NULL, &count);
|
||||
ok(hr == E_NOT_SUFFICIENT_BUFFER, "got 0x%08x\n", hr);
|
||||
ok(count > 0, "got %u\n", count);
|
||||
|
||||
count = 1;
|
||||
hr = IDWriteFontFace1_GetUnicodeRanges(fontface1, 1, NULL, &count);
|
||||
ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
|
||||
ok(count == 0, "got %u\n", count);
|
||||
|
||||
count = 0;
|
||||
hr = IDWriteFontFace1_GetUnicodeRanges(fontface1, 1, &r, &count);
|
||||
ok(hr == E_NOT_SUFFICIENT_BUFFER, "got 0x%08x\n", hr);
|
||||
ok(count > 1, "got %u\n", count);
|
||||
|
||||
ranges = heap_alloc(count*sizeof(DWRITE_UNICODE_RANGE));
|
||||
hr = IDWriteFontFace1_GetUnicodeRanges(fontface1, count, ranges, &count);
|
||||
ok(hr == S_OK, "got 0x%08x\n", hr);
|
||||
|
||||
ranges[0].first = ranges[0].last = 0;
|
||||
hr = IDWriteFontFace1_GetUnicodeRanges(fontface1, 1, ranges, &count);
|
||||
ok(hr == E_NOT_SUFFICIENT_BUFFER, "got 0x%08x\n", hr);
|
||||
ok(ranges[0].first != 0 && ranges[0].last != 0, "got 0x%x-0x%0x\n", ranges[0].first, ranges[0].last);
|
||||
|
||||
heap_free(ranges);
|
||||
|
||||
hr = IDWriteFactory_UnregisterFontFileLoader(factory, &rloader);
|
||||
ok(hr == S_OK, "got 0x%08x\n", hr);
|
||||
|
||||
IDWriteFontFace1_Release(fontface1);
|
||||
}
|
||||
|
||||
START_TEST(font)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
@ -1141,6 +1213,7 @@ START_TEST(font)
|
|||
test_FontLoader();
|
||||
test_CreateFontFileReference();
|
||||
test_shared_isolated();
|
||||
test_GetUnicodeRanges();
|
||||
|
||||
IDWriteFactory_Release(factory);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue