From: Tingzhong Luo luotingzhong@uniontech.com
Signed-off-by: Tingzhong Luo luotingzhong@uniontech.com --- dlls/dwrite/gdiinterop.c | 21 ++++- dlls/dwrite/tests/font.c | 134 +++++++++++++++++++++++++++++++- dlls/dwrite/tests/wine_test.sfd | 31 ++++++-- dlls/dwrite/tests/wine_test.ttf | Bin 1812 -> 1836 bytes 4 files changed, 173 insertions(+), 13 deletions(-)
diff --git a/dlls/dwrite/gdiinterop.c b/dlls/dwrite/gdiinterop.c index 2eafe4064d2..c87401f4c2a 100644 --- a/dlls/dwrite/gdiinterop.c +++ b/dlls/dwrite/gdiinterop.c @@ -337,6 +337,18 @@ static inline DWORD colorref_to_pixel_888(COLORREF color) return (((color >> 16) & 0xff) | (color & 0xff00) | ((color << 16) & 0xff0000)); }
+static inline void dwrite_matrix_multiply(DWRITE_MATRIX *a, const DWRITE_MATRIX *b) +{ + DWRITE_MATRIX tmp = *a; + + a->m11 = tmp.m11 * b->m11 + tmp.m12 * b->m21; + a->m12 = tmp.m11 * b->m12 + tmp.m12 * b->m22; + a->m21 = tmp.m21 * b->m11 + tmp.m22 * b->m21; + a->m22 = tmp.m21 * b->m12 + tmp.m22 * b->m22; + a->dx = tmp.dx * b->m11 + tmp.dy * b->m21 + b->dx; + a->dy = tmp.dy * b->m12 + tmp.dy * b->m22 + b->dx; +} + static HRESULT WINAPI rendertarget_DrawGlyphRun(IDWriteBitmapRenderTarget1 *iface, FLOAT originX, FLOAT originY, DWRITE_MEASURING_MODE measuring_mode, DWRITE_GLYPH_RUN const *run, IDWriteRenderingParams *params, COLORREF color, @@ -347,7 +359,7 @@ static HRESULT WINAPI rendertarget_DrawGlyphRun(IDWriteBitmapRenderTarget1 *ifac DWRITE_RENDERING_MODE1 rendermode; DWRITE_GRID_FIT_MODE gridfitmode; DWRITE_TEXTURE_TYPE texturetype; - DWRITE_GLYPH_RUN scaled_run; + DWRITE_MATRIX m, scale = { 0 }; IDWriteFontFace3 *fontface; RECT target_rect, bounds; HRESULT hr; @@ -429,9 +441,10 @@ static HRESULT WINAPI rendertarget_DrawGlyphRun(IDWriteBitmapRenderTarget1 *ifac return hr; }
- scaled_run = *run; - scaled_run.fontEmSize *= target->ppdip; - hr = IDWriteFactory7_CreateGlyphRunAnalysis(target->factory, &scaled_run, &target->m, rendermode, measuring_mode, + m = target->m; + scale.m11 = scale.m22 = target->ppdip; + dwrite_matrix_multiply(&m, &scale); + hr = IDWriteFactory7_CreateGlyphRunAnalysis(target->factory, run, &m, rendermode, measuring_mode, gridfitmode, target->antialiasmode, originX, originY, &analysis); if (FAILED(hr)) { diff --git a/dlls/dwrite/tests/font.c b/dlls/dwrite/tests/font.c index 5052de00329..342c32bd965 100644 --- a/dlls/dwrite/tests/font.c +++ b/dlls/dwrite/tests/font.c @@ -1205,18 +1205,61 @@ static void test_CreateFontFromLOGFONT(void) ok(ref == 0, "factory is not released, %lu\n", ref); }
+static IDWriteFontFace *create_winetest_fontface(IDWriteFactory *factory) +{ + static IDWriteFontFileLoader rloader = { &resourcefontfileloadervtbl }; + IDWriteFontFace *face; + IDWriteFontFile *file; + HRSRC fontsrc; + HRESULT hr; + + hr = IDWriteFactory_RegisterFontFileLoader(factory, &rloader); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + fontsrc = FindResourceA(GetModuleHandleA(NULL), (LPCSTR)MAKEINTRESOURCE(1), (LPCSTR)RT_RCDATA); + ok(fontsrc != NULL, "Failed to find font resource\n"); + + hr = IDWriteFactory_CreateCustomFontFileReference(factory, &fontsrc, sizeof(HRSRC), &rloader, &file); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(file != NULL, "Failed to create font file reference\n"); + + hr = IDWriteFactory_CreateFontFace(factory, DWRITE_FONT_FACE_TYPE_TRUETYPE, 1, &file, 0, DWRITE_FONT_SIMULATIONS_NONE, &face); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(face != NULL, "Failed to create font face\n"); + + hr = IDWriteFactory_UnregisterFontFileLoader(factory, &rloader); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + IDWriteFontFile_Release(file); + return face; +} + +static inline void dwrite_matrix_multiply(DWRITE_MATRIX *a, const DWRITE_MATRIX *b) +{ + DWRITE_MATRIX tmp = *a; + + a->m11 = tmp.m11 * b->m11 + tmp.m12 * b->m21; + a->m12 = tmp.m11 * b->m12 + tmp.m12 * b->m22; + a->m21 = tmp.m21 * b->m11 + tmp.m22 * b->m21; + a->m22 = tmp.m21 * b->m12 + tmp.m22 * b->m22; + a->dx = tmp.dx * b->m11 + tmp.dy * b->m21 + b->dx; + a->dy = tmp.dy * b->m12 + tmp.dy * b->m22 + b->dx; +} + static void test_CreateBitmapRenderTarget(void) { IDWriteBitmapRenderTarget *target, *target2; IDWriteBitmapRenderTarget1 *target1; IDWriteRenderingParams *params; + DWRITE_GLYPH_OFFSET offsets[2]; IDWriteGdiInterop *interop; IDWriteFontFace *fontface; + DWRITE_MATRIX m, m2, ms; IDWriteFactory *factory; DWRITE_GLYPH_RUN run; HBITMAP hbm, hbm2; UINT16 glyphs[2]; - DWRITE_MATRIX m; + RECT box, box2; DIBSECTION ds; XFORM xform; COLORREF c; @@ -1225,7 +1268,6 @@ static void test_CreateBitmapRenderTarget(void) SIZE size; ULONG ref; UINT32 ch; - RECT box; HDC hdc; int ret;
@@ -1515,6 +1557,92 @@ static void test_CreateBitmapRenderTarget(void) ok(hr == S_OK, "Failed to draw a run, hr %#lx.\n", hr); ok(!IsRectEmpty(&box), "got empty rect\n");
+ IDWriteFontFace_Release(fontface); + fontface = create_winetest_fontface(factory); + + /* 0xa9 map to a black rectangle */ + ch = 0xa9; + glyphs[0] = 0; + hr = IDWriteFontFace_GetGlyphIndices(fontface, &ch, 1, glyphs); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(glyphs[0] > 0, "got 0\n"); + glyphs[1] = glyphs[0]; + + offsets[0].advanceOffset = 0; + offsets[0].ascenderOffset = 0; + offsets[1].advanceOffset = 3; + offsets[1].ascenderOffset = 0; + + memset(&run, 0, sizeof(run)); + run.glyphCount = 2; + run.fontEmSize = 5.0f; + run.fontFace = fontface; + run.glyphIndices = glyphs; + run.glyphOffsets = offsets; + + hr = IDWriteBitmapRenderTarget1_Resize(target1, 40, 30); + ok(hr == S_OK, "Failed to set target size, hr %#lx.\n", hr); + + /* Check bounding box in different transform */ + memset(&ms, 0, sizeof(ms)); + ms.m11 = ms.m22 = 2.0f; + for (int i = 0; i < 3; i++) + { + m2 = m; + memset(&m, 0, sizeof(m)); + switch (i) + { + case 0: + /* dont apply transform first */ + m.m11 = m.m22 = 1; + break; + case 1: + /* then rotate 45 degree */ + m.m11 = m.m22 = cos(3.1415 / 4); + m.m12 = sin(3.1415 / 4); + m.m21 = -m.m12; + dwrite_matrix_multiply(&m, &m2); + break; + case 2: + /* then shift on x with 10px */ + m.m11 = m.m22 = 1; + m.dx = 10; + dwrite_matrix_multiply(&m, &m2); + break; + default: + m = m2; + break; + } + + /* Draw in double ddpi */ + hr = IDWriteBitmapRenderTarget_SetPixelsPerDip(target, 2.0); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + hr = IDWriteBitmapRenderTarget_SetCurrentTransform(target, &m); + ok(hr == S_OK, "Failed to set current transform, hr %#lx.\n", hr); + + SetRectEmpty(&box); + hr = IDWriteBitmapRenderTarget_DrawGlyphRun(target, 5.0f, 2.0f, DWRITE_MEASURING_MODE_GDI_NATURAL, + &run, params, RGB(255, 0, 0), &box); + ok(hr == S_OK, "Failed to draw a run, hr %#lx.\n", hr); + + /* Draw in one ddpi, scale in double first, then apply transform matrix */ + hr = IDWriteBitmapRenderTarget_SetPixelsPerDip(target, 1.0); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + m2 = m; + dwrite_matrix_multiply(&m2, &ms); + hr = IDWriteBitmapRenderTarget_SetCurrentTransform(target, &m2); + ok(hr == S_OK, "Failed to set current transform, hr %#lx.\n", hr); + + SetRectEmpty(&box2); + hr = IDWriteBitmapRenderTarget_DrawGlyphRun(target, 5.0f, 2.0f, DWRITE_MEASURING_MODE_GDI_NATURAL, + &run, params, RGB(255, 0, 0), &box2); + ok(hr == S_OK, "Failed to draw a run, hr %#lx.\n", hr); + + ok(box.left == box2.left && box.right == box2.right && box.top== box2.top && box.bottom == box2.bottom, + "%d: Bounding box dismatch %s != %s\n", i, wine_dbgstr_rect(&box), wine_dbgstr_rect(&box2)); + } + IDWriteRenderingParams_Release(params);
/* Zero sized target returns earlier. */ @@ -5533,7 +5661,7 @@ static void test_GetGlyphCount(void) IDWriteFontFile_Release(file);
count = IDWriteFontFace_GetGlyphCount(fontface); - ok(count == 8, "got %u\n", count); + ok(count == 9, "got %u\n", count);
IDWriteFontFace_Release(fontface); ref = IDWriteFactory_Release(factory); diff --git a/dlls/dwrite/tests/wine_test.sfd b/dlls/dwrite/tests/wine_test.sfd index e533323db75..cbc20ca7450 100644 --- a/dlls/dwrite/tests/wine_test.sfd +++ b/dlls/dwrite/tests/wine_test.sfd @@ -1,4 +1,4 @@ -SplineFontDB: 3.0 +SplineFontDB: 3.2 FontName: wine_test FullName: wine_test FamilyName: wine_test @@ -10,6 +10,7 @@ UnderlinePosition: -205 UnderlineWidth: 102 Ascent: 1638 Descent: 410 +InvalidEm: 0 sfntRevision: 0x00010000 LayerCount: 2 Layer: 0 1 "Back" 1 @@ -19,6 +20,8 @@ FSType: 0 OS2Version: 2 OS2_WeightWidthSlopeOnly: 0 OS2_UseTypoMetrics: 1 +CreationTime: 1690872262 +ModificationTime: 1696993054 PfmFamily: 17 TTFWeight: 500 TTFWidth: 5 @@ -83,14 +86,14 @@ NameList: Adobe Glyph List DisplaySize: -24 AntiAlias: 1 FitToEm: 1 -WinInfo: 47 47 13 +WinInfo: 0 47 13 BeginPrivate: 0 EndPrivate -BeginChars: 65539 8 +BeginChars: 65539 9
StartChar: .notdef Encoding: 65536 -1 0 -AltUni2: 00fffe.ffffffff.0 00fffd.ffffffff.0 00fffc.ffffffff.0 00fffb.ffffffff.0 +AltUni2: 00fffb.ffffffff.0 00fffc.ffffffff.0 00fffd.ffffffff.0 00fffe.ffffffff.0 Width: 748 Flags: W TtInstrs: @@ -189,7 +192,7 @@ SplineSet 620.215 824.429 m 1,0,1 760.84 777.554 760.84 777.554 713.965 636.929 c 1,2,-1 620.215 824.429 l 1,0,1 -154.883 324.971 m 0,3,-1 +154.883 324.971 m 1024,3,-1 254.492 773.213 m 1,4,5 310.707 834.805 310.707 834.805 374.609 767.354 c 1,6,7 410.471 728.672 410.471 728.672 374.609 691.182 c 0,8,9 @@ -249,7 +252,23 @@ Flags: W LayerCount: 2 Fore SplineSet -500 500 m 24,0,-1 +500 500 m 1048,0,-1 +EndSplineSet +EndChar + +StartChar: copyright +Encoding: 169 169 8 +Width: 1000 +VWidth: 0 +Flags: W +LayerCount: 2 +Fore +SplineSet +-3 -415 m 1,0,-1 + 997 -409 l 1,1,-1 + 997 84 l 1,2,-1 + -3 84 l 1,3,-1 + -3 -415 l 1,0,-1 EndSplineSet EndChar EndChars diff --git a/dlls/dwrite/tests/wine_test.ttf b/dlls/dwrite/tests/wine_test.ttf index 72dadf5d5438ffbcfff5b2442eb62028245aa9a3..937065fb87955c2d1ebc41946f8f80b09b69186d 100644 GIT binary patch delta 633 zcmYjPO=}ZT6g_v|OeV3C#8OisQWKgeqO@Za!4HJuBnqWwVJ*c?I>y8ik|wlW)Roz| z5)1meP*6eKSco9D;0K}$H~t1!Q7B|lMHenaC(k>RE*zNm=A8R^?w!?WJ8FXfMA3r4 zT%j;M_4H6`3NYi$?mcJc3pjvrAk<~Nzj$#xcjw;17C<iJxpLiU>RW@)@7kj`J4}SH z)oxUC>c=V|YV2gW73XTUSZ=e8gK*qsVqo2P$F>aPj9Xt?PLMId_!Hw)tx<O9Fs*R> zEaRcNv)n`xdA6VT?ek8(lDzfy5uiT=w0N_zxP*gr25>`ukz;`xR`l}4mG`CC>0j6v zW*X>xzg+O|FOwf0E6>{yo8~aXFf^a#hhxlPZv(HxP#%}x3^Mg?{nHGXh`c~aq3dsC zjZPUYq_HO3bW&5E?9%9o9YIQsX&Y;*rxeGgF@b05k5cL@pi2E>><8@RSBJr8NZQ&f zojFrJ(Prc&k)ZpsCO(Sa;;hW+#Uv@O=WtikyeEk4uCx%{zk7O4h`z~|J{gNqUpuEl zgl6SuJs%sPA@(Lc!rUO)>tn`Iiesj-uz0;OpR%kYW0qyf2S#dOdkU(GD%am#iUdt+ u+*}4({sUHU+h<sg7EHl!Jb{q_5lbQV<b4ED!7TY}`|kV<xjy)R1OEUVlZANz
delta 589 zcmX|8O-NKx7(MsBJ8xz}W=ba&jC!J0i>TKGh86U~o0*W(MJAyOec0Fw-g5?Zp%66d zs3@+xXwgo>MWj%RR!UIQrfsXDRf}ks1Yx)H?pPP@{W$0QzVrRuwcJY1hX9a612(41 z<*}<oWSn2L2P%H4jML~R{z!au^xBEygGcjU7!nds&%{C9$?jWz?DyS$M<R18TAuyX z^C1T8h(U$08r+<?|2*-1=N$}5?0J%ULmx%aAI6JIok;n_NzB2hHWP?r*k=9>;`TUL zs$&Et`Y#i^b3t5v`T5>qKsErYqh4EB)SFlbLT7~mMKcZiFI;*1eky<NCk|yu19t{q zH2zzEXTxfyyNENe5|)QK>8_m(yl%x?O{3KEwcfO0GHOKh*p~dEB5^i#0lipNYvK%L z)Hl&L)Mg|l=}Yjjs{d%s>|R_n=(pDTtKQO^da6}&S6?#Qw_ed8t)5xq>bl)2pdx$A zZrVetC`Z*(Ih@}s26wx1kQI|^TbA;!DDdZm%)&vtsH_jCPKgc|7_ZJR+^)^Jo_F%N z=XtI=@3?LMre#mFth2w83@gY={_y~g;Gt<quxZOw$`N;ias~?|J4m`rw#JQ_%a>Z+ Fe*qFdaiahL