dwrite: Correct return glyph origins for RTL runs.

Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Nikolay Sivov 2021-02-22 21:29:35 +03:00 committed by Alexandre Julliard
parent 7315afbc13
commit 87bc6aac20
2 changed files with 31 additions and 60 deletions

View File

@ -1551,76 +1551,48 @@ static HRESULT WINAPI dwritefactory4_TranslateColorGlyphRun(IDWriteFactory7 *ifa
}
static HRESULT compute_glyph_origins(DWRITE_GLYPH_RUN const *run, DWRITE_MEASURING_MODE measuring_mode,
D2D1_POINT_2F baseline_origin, DWRITE_MATRIX const *transform, D2D1_POINT_2F *origins)
D2D1_POINT_2F baseline_origin, DWRITE_MATRIX const *transform, D2D1_POINT_2F *origins)
{
IDWriteFontFace1 *fontface1 = NULL;
DWRITE_FONT_METRICS metrics;
FLOAT rtl_factor;
HRESULT hr;
UINT32 i;
struct dwrite_fontface *font_obj;
unsigned int i;
float advance;
rtl_factor = run->bidiLevel & 1 ? -1.0f : 1.0f;
if (run->fontFace) {
IDWriteFontFace_GetMetrics(run->fontFace, &metrics);
if (FAILED(hr = IDWriteFontFace_QueryInterface(run->fontFace, &IID_IDWriteFontFace1, (void **)&fontface1)))
WARN("Failed to get IDWriteFontFace1, %#x.\n", hr);
}
for (i = 0; i < run->glyphCount; i++) {
FLOAT advance;
/* Use nominal advances if not provided by caller. */
if (run->glyphAdvances)
advance = rtl_factor * run->glyphAdvances[i];
else {
INT32 a;
advance = 0.0f;
switch (measuring_mode)
{
case DWRITE_MEASURING_MODE_NATURAL:
if (SUCCEEDED(IDWriteFontFace1_GetDesignGlyphAdvances(fontface1, 1, run->glyphIndices + i, &a,
run->isSideways)))
advance = rtl_factor * get_scaled_advance_width(a, run->fontEmSize, &metrics);
break;
case DWRITE_MEASURING_MODE_GDI_CLASSIC:
case DWRITE_MEASURING_MODE_GDI_NATURAL:
if (SUCCEEDED(IDWriteFontFace1_GetGdiCompatibleGlyphAdvances(fontface1, run->fontEmSize,
1.0f, transform, measuring_mode == DWRITE_MEASURING_MODE_GDI_NATURAL,
run->isSideways, 1, run->glyphIndices + i, &a)))
advance = rtl_factor * floorf(a * run->fontEmSize / metrics.designUnitsPerEm + 0.5f);
break;
default:
;
}
}
font_obj = unsafe_impl_from_IDWriteFontFace(run->fontFace);
for (i = 0; i < run->glyphCount; ++i)
{
origins[i] = baseline_origin;
/* Apply offsets. */
if (run->glyphOffsets) {
FLOAT advanceoffset = rtl_factor * run->glyphOffsets[i].advanceOffset;
FLOAT ascenderoffset = -run->glyphOffsets[i].ascenderOffset;
if (run->bidiLevel & 1)
{
advance = fontface_get_scaled_design_advance(font_obj, measuring_mode, run->fontEmSize,
1.0f, transform, run->glyphIndices[i], run->isSideways);
if (run->isSideways) {
origins[i].x += ascenderoffset;
origins[i].y += advanceoffset;
}
else {
origins[i].x += advanceoffset;
origins[i].y += ascenderoffset;
origins[i].x -= advance;
if (run->glyphOffsets)
{
origins[i].x -= run->glyphOffsets[i].advanceOffset;
origins[i].y -= run->glyphOffsets[i].ascenderOffset;
}
baseline_origin.x -= run->glyphAdvances ? run->glyphAdvances[i] : advance;
}
if (run->isSideways)
baseline_origin.y += advance;
else
baseline_origin.x += advance;
{
if (run->glyphOffsets)
{
origins[i].x += run->glyphOffsets[i].advanceOffset;
origins[i].y -= run->glyphOffsets[i].ascenderOffset;
}
baseline_origin.x += run->glyphAdvances ? run->glyphAdvances[i] :
fontface_get_scaled_design_advance(font_obj, measuring_mode, run->fontEmSize, 1.0f, transform,
run->glyphIndices[i], run->isSideways);
}
}
if (fontface1)
IDWriteFontFace1_Release(fontface1);
return S_OK;
}

View File

@ -8468,7 +8468,6 @@ static void test_ComputeGlyphOrigins(void)
ok(hr == S_OK, "%u: failed to compute glyph origins, hr %#x.\n", i, hr);
for (j = 0; j < run.glyphCount; ++j)
{
todo_wine_if(run.bidiLevel & 1)
ok(!memcmp(&origins[j], &expected_origins[j], sizeof(origins[j])),
"%u: unexpected origin[%u] (%f, %f) - (%f, %f).\n", i, j, origins[j].x, origins[j].y,
expected_origins[j].x, expected_origins[j].y);