dwrite: Initial implementation of GetGlyphPlacements().

This commit is contained in:
Nikolay Sivov 2015-01-22 14:43:24 +03:00 committed by Alexandre Julliard
parent 270431c220
commit 711b9f0414
3 changed files with 185 additions and 9 deletions

View file

@ -962,17 +962,51 @@ done:
return hr;
}
static inline FLOAT get_scaled_advance_width(INT32 advance, FLOAT emSize, const DWRITE_FONT_METRICS *metrics)
{
return (FLOAT)advance * emSize / (FLOAT)metrics->designUnitsPerEm;
}
static HRESULT WINAPI dwritetextanalyzer_GetGlyphPlacements(IDWriteTextAnalyzer2 *iface,
WCHAR const* text, UINT16 const* clustermap, DWRITE_SHAPING_TEXT_PROPERTIES* props,
UINT32 text_len, UINT16 const* glyph_indices, DWRITE_SHAPING_GLYPH_PROPERTIES const* glyph_props,
UINT32 glyph_count, IDWriteFontFace * font_face, FLOAT fontEmSize, BOOL is_sideways, BOOL is_rtl,
UINT32 text_len, UINT16 const* glyphs, DWRITE_SHAPING_GLYPH_PROPERTIES const* glyph_props,
UINT32 glyph_count, IDWriteFontFace *fontface, FLOAT emSize, BOOL is_sideways, BOOL is_rtl,
DWRITE_SCRIPT_ANALYSIS const* analysis, WCHAR const* locale, DWRITE_TYPOGRAPHIC_FEATURES const** features,
UINT32 const* feature_range_len, UINT32 feature_ranges, FLOAT* glyph_advances, DWRITE_GLYPH_OFFSET* glyph_offsets)
UINT32 const* feature_range_len, UINT32 feature_ranges, FLOAT *advances, DWRITE_GLYPH_OFFSET *offsets)
{
FIXME("(%s %p %p %u %p %p %u %p %f %d %d %p %s %p %p %u %p %p): stub\n", debugstr_w(text),
clustermap, props, text_len, glyph_indices, glyph_props, glyph_count, font_face, fontEmSize, is_sideways,
is_rtl, analysis, debugstr_w(locale), features, feature_range_len, feature_ranges, glyph_advances, glyph_offsets);
return E_NOTIMPL;
DWRITE_FONT_METRICS metrics;
IDWriteFontFace1 *fontface1;
HRESULT hr;
UINT32 i;
TRACE("(%s %p %p %u %p %p %u %p %.2f %d %d %p %s %p %p %u %p %p)\n", debugstr_w(text),
clustermap, props, text_len, glyphs, glyph_props, glyph_count, fontface, emSize, is_sideways,
is_rtl, analysis, debugstr_w(locale), features, feature_range_len, feature_ranges, advances, offsets);
if (glyph_count == 0)
return S_OK;
hr = IDWriteFontFace_QueryInterface(fontface, &IID_IDWriteFontFace1, (void**)&fontface1);
if (FAILED(hr)) {
WARN("failed to get IDWriteFontFace1.\n");
return hr;
}
IDWriteFontFace_GetMetrics(fontface, &metrics);
for (i = 0; i < glyph_count; i++) {
INT32 a;
hr = IDWriteFontFace1_GetDesignGlyphAdvances(fontface1, 1, &glyphs[i], &a, is_sideways);
if (FAILED(hr))
a = 0;
advances[i] = get_scaled_advance_width(a, emSize, &metrics);
offsets[i].advanceOffset = 0.0;
offsets[i].ascenderOffset = 0.0;
}
/* FIXME: actually apply features */
return S_OK;
}
static HRESULT WINAPI dwritetextanalyzer_GetGdiCompatibleGlyphPlacements(IDWriteTextAnalyzer2 *iface,

View file

@ -30,6 +30,7 @@
#include "wine/test.h"
static IDWriteFactory *factory;
static const WCHAR test_fontfile[] = {'w','i','n','e','_','t','e','s','t','_','f','o','n','t','.','t','t','f',0};
enum analysis_kind {
ScriptAnalysis,
@ -442,6 +443,40 @@ static IDWriteFontFace *create_fontface(void)
return fontface;
}
static void create_testfontfile(const WCHAR *filename)
{
DWORD written;
HANDLE file;
HRSRC res;
void *ptr;
file = CreateFileW(filename, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
ok(file != INVALID_HANDLE_VALUE, "file creation failed\n");
res = FindResourceA(GetModuleHandleA(NULL), (LPCSTR)MAKEINTRESOURCE(1), (LPCSTR)RT_RCDATA);
ok(res != 0, "couldn't find resource\n");
ptr = LockResource(LoadResource(GetModuleHandleA(NULL), res));
WriteFile(file, ptr, SizeofResource(GetModuleHandleA(NULL), res), &written, NULL);
ok(written == SizeofResource(GetModuleHandleA(NULL), res), "couldn't write resource\n");
CloseHandle(file);
}
static IDWriteFontFace *create_testfontface(const WCHAR *filename)
{
IDWriteFontFace *face;
IDWriteFontFile *file;
HRESULT hr;
hr = IDWriteFactory_CreateFontFileReference(factory, filename, NULL, &file);
ok(hr == S_OK, "got 0x%08x\n",hr);
hr = IDWriteFactory_CreateFontFace(factory, DWRITE_FONT_FACE_TYPE_TRUETYPE, 1, &file, 0,
DWRITE_FONT_SIMULATIONS_NONE, &face);
ok(hr == S_OK, "got 0x%08x\n", hr);
return face;
}
struct sa_test {
const WCHAR string[50];
int item_count;
@ -1291,6 +1326,112 @@ todo_wine {
IDWriteTextAnalyzer2_Release(analyzer2);
}
static void test_GetGlyphPlacements(void)
{
DWRITE_SHAPING_GLYPH_PROPERTIES glyphprops[2];
DWRITE_SHAPING_TEXT_PROPERTIES textprops[2];
static const WCHAR aW[] = {'A','D',0};
UINT16 clustermap[2], glyphs[2];
DWRITE_GLYPH_OFFSET offsets[2];
IDWriteTextAnalyzer *analyzer;
IDWriteFontFace *fontface;
DWRITE_SCRIPT_ANALYSIS sa;
FLOAT advances[2];
UINT32 count, len;
HRESULT hr;
hr = IDWriteFactory_CreateTextAnalyzer(factory, &analyzer);
ok(hr == S_OK, "got 0x%08x\n", hr);
create_testfontfile(test_fontfile);
fontface = create_testfontface(test_fontfile);
get_script_analysis(aW, &sa);
count = 0;
len = lstrlenW(aW);
hr = IDWriteTextAnalyzer_GetGlyphs(analyzer, aW, len, fontface, FALSE, FALSE, &sa, NULL,
NULL, NULL, NULL, 0, len, clustermap, textprops, glyphs, glyphprops, &count);
ok(hr == S_OK, "got 0x%08x\n", hr);
ok(count == 2, "got %u\n", count);
/* just return on zero glyphs */
advances[0] = advances[1] = 1.0;
offsets[0].advanceOffset = offsets[0].ascenderOffset = 2.0;
hr = IDWriteTextAnalyzer_GetGlyphPlacements(analyzer, aW, clustermap, textprops,
len, glyphs, glyphprops, 0, fontface, 0.0, FALSE, FALSE, &sa, NULL, NULL,
NULL, 0, advances, offsets);
ok(hr == S_OK, "got 0x%08x\n", hr);
ok(advances[0] == 1.0, "got %.2f\n", advances[0]);
ok(offsets[0].advanceOffset == 2.0 && offsets[0].ascenderOffset == 2.0, "got %.2f,%.2f\n",
offsets[0].advanceOffset, offsets[0].ascenderOffset);
/* advances/offsets are scaled with provided font emSize and designed eM box size */
advances[0] = advances[1] = 1.0;
memset(offsets, 0xcc, sizeof(offsets));
hr = IDWriteTextAnalyzer_GetGlyphPlacements(analyzer, aW, clustermap, textprops,
len, glyphs, glyphprops, len, fontface, 0.0, FALSE, FALSE, &sa, NULL, NULL,
NULL, 0, advances, offsets);
ok(hr == S_OK, "got 0x%08x\n", hr);
ok(advances[0] == 0.0, "got %.2f\n", advances[0]);
ok(offsets[0].advanceOffset == 0.0 && offsets[0].ascenderOffset == 0.0, "got %.2f,%.2f\n",
offsets[0].advanceOffset, offsets[0].ascenderOffset);
advances[0] = advances[1] = 1.0;
memset(offsets, 0xcc, sizeof(offsets));
hr = IDWriteTextAnalyzer_GetGlyphPlacements(analyzer, aW, clustermap, textprops,
len, glyphs, glyphprops, len, fontface, 2048.0, FALSE, FALSE, &sa, NULL, NULL,
NULL, 0, advances, offsets);
ok(hr == S_OK, "got 0x%08x\n", hr);
ok(advances[0] == 1000.0, "got %.2f\n", advances[0]);
ok(offsets[0].advanceOffset == 0.0 && offsets[0].ascenderOffset == 0.0, "got %.2f,%.2f\n",
offsets[0].advanceOffset, offsets[0].ascenderOffset);
advances[0] = advances[1] = 1.0;
memset(offsets, 0xcc, sizeof(offsets));
hr = IDWriteTextAnalyzer_GetGlyphPlacements(analyzer, aW, clustermap, textprops,
len, glyphs, glyphprops, len, fontface, 1024.0, FALSE, FALSE, &sa, NULL, NULL,
NULL, 0, advances, offsets);
ok(hr == S_OK, "got 0x%08x\n", hr);
ok(advances[0] == 500.0, "got %.2f\n", advances[0]);
ok(advances[1] == 500.0, "got %.2f\n", advances[1]);
ok(offsets[0].advanceOffset == 0.0 && offsets[0].ascenderOffset == 0.0, "got %.2f,%.2f\n",
offsets[0].advanceOffset, offsets[0].ascenderOffset);
advances[0] = advances[1] = 1.0;
memset(offsets, 0xcc, sizeof(offsets));
hr = IDWriteTextAnalyzer_GetGlyphPlacements(analyzer, aW, clustermap, textprops,
len, glyphs, glyphprops, len, fontface, 20.48, FALSE, FALSE, &sa, NULL, NULL,
NULL, 0, advances, offsets);
ok(hr == S_OK, "got 0x%08x\n", hr);
ok(advances[0] == 10.0, "got %.2f\n", advances[0]);
ok(advances[1] == 10.0, "got %.2f\n", advances[1]);
ok(offsets[0].advanceOffset == 0.0 && offsets[0].ascenderOffset == 0.0, "got %.2f,%.2f\n",
offsets[0].advanceOffset, offsets[0].ascenderOffset);
/* without clustermap */
advances[0] = advances[1] = 1.0;
hr = IDWriteTextAnalyzer_GetGlyphPlacements(analyzer, aW, NULL, textprops,
len, glyphs, glyphprops, len, fontface, 1024.0, FALSE, FALSE, &sa, NULL, NULL,
NULL, 0, advances, offsets);
ok(hr == S_OK, "got 0x%08x\n", hr);
ok(advances[0] == 500.0, "got %.2f\n", advances[0]);
ok(advances[1] == 500.0, "got %.2f\n", advances[1]);
/* it's happy to use negative size too */
advances[0] = advances[1] = 1.0;
memset(offsets, 0xcc, sizeof(offsets));
hr = IDWriteTextAnalyzer_GetGlyphPlacements(analyzer, aW, clustermap, textprops,
len, glyphs, glyphprops, len, fontface, -10.24, FALSE, FALSE, &sa, NULL, NULL,
NULL, 0, advances, offsets);
ok(hr == S_OK, "got 0x%08x\n", hr);
ok(advances[0] == -5.0, "got %.2f\n", advances[0]);
ok(offsets[0].advanceOffset == 0.0 && offsets[0].ascenderOffset == 0.0, "got %.2f,%.2f\n",
offsets[0].advanceOffset, offsets[0].ascenderOffset);
IDWriteTextAnalyzer_Release(analyzer);
DeleteFileW(test_fontfile);
}
START_TEST(analyzer)
{
HRESULT hr;
@ -1313,6 +1454,7 @@ START_TEST(analyzer)
test_GetGlyphs();
test_numbersubstitution();
test_GetTypographicFeatures();
test_GetGlyphPlacements();
IDWriteFactory_Release(factory);
}

View file

@ -921,10 +921,10 @@ static void test_GetClusterMetrics(void)
count = 0;
hr = IDWriteTextLayout_GetClusterMetrics(layout, NULL, 0, &count);
todo_wine {
todo_wine
ok(hr == E_NOT_SUFFICIENT_BUFFER, "got 0x%08x\n", hr);
ok(count == 4, "got %u\n", count);
}
hr = IDWriteFactory_CreateEllipsisTrimmingSign(factory, format, &trimm);
ok(hr == S_OK, "got 0x%08x\n", hr);