[PATCH 2/2] dwrite: Improve empty contours handling in GetGlyphRunOutline()

Nikolay Sivov nsivov at codeweavers.com
Fri Aug 25 00:29:46 CDT 2017


Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
 dlls/dwrite/freetype.c          |  57 ++++++++++++++++++++++------------------
 dlls/dwrite/tests/font.c        |  16 +++++++++--
 dlls/dwrite/tests/wine_test.sfd |  20 +++++++++++---
 dlls/dwrite/tests/wine_test.ttf | Bin 1776 -> 1812 bytes
 4 files changed, 61 insertions(+), 32 deletions(-)

diff --git a/dlls/dwrite/freetype.c b/dlls/dwrite/freetype.c
index 934ca80a51..571fa24c33 100644
--- a/dlls/dwrite/freetype.c
+++ b/dlls/dwrite/freetype.c
@@ -320,7 +320,6 @@ struct decompose_context {
     FLOAT xoffset;
     FLOAT yoffset;
     BOOL figure_started;
-    BOOL figure_closed;
     BOOL move_to;     /* last call was 'move_to' */
     FT_Vector origin; /* 'pen' position from last call */
 };
@@ -331,21 +330,29 @@ static inline void ft_vector_to_d2d_point(const FT_Vector *v, FLOAT xoffset, FLO
     p->y = (v->y / 64.0f) + yoffset;
 }
 
+static void decompose_beginfigure(struct decompose_context *ctxt)
+{
+    D2D1_POINT_2F point;
+
+    if (!ctxt->move_to)
+        return;
+
+    ft_vector_to_d2d_point(&ctxt->origin, ctxt->xoffset, ctxt->yoffset, &point);
+    ID2D1SimplifiedGeometrySink_BeginFigure(ctxt->sink, point, D2D1_FIGURE_BEGIN_FILLED);
+
+    ctxt->figure_started = TRUE;
+    ctxt->move_to = FALSE;
+}
+
 static int decompose_move_to(const FT_Vector *to, void *user)
 {
     struct decompose_context *ctxt = (struct decompose_context*)user;
-    D2D1_POINT_2F point;
 
     if (ctxt->figure_started) {
         ID2D1SimplifiedGeometrySink_EndFigure(ctxt->sink, D2D1_FIGURE_END_CLOSED);
-        ctxt->figure_closed = TRUE;
+        ctxt->figure_started = FALSE;
     }
-    else
-        ctxt->figure_closed = FALSE;
-    ctxt->figure_started = TRUE;
 
-    ft_vector_to_d2d_point(to, ctxt->xoffset, ctxt->yoffset, &point);
-    ID2D1SimplifiedGeometrySink_BeginFigure(ctxt->sink, point, D2D1_FIGURE_BEGIN_FILLED);
     ctxt->move_to = TRUE;
     ctxt->origin = *to;
     return 0;
@@ -354,18 +361,17 @@ static int decompose_move_to(const FT_Vector *to, void *user)
 static int decompose_line_to(const FT_Vector *to, void *user)
 {
     struct decompose_context *ctxt = (struct decompose_context*)user;
-    /* special case for empty contours, in a way freetype returns them */
-    if (ctxt->move_to && !memcmp(to, &ctxt->origin, sizeof(*to))) {
-        ID2D1SimplifiedGeometrySink_EndFigure(ctxt->sink, D2D1_FIGURE_END_CLOSED);
-        ctxt->figure_closed = TRUE;
-    }
-    else {
-        D2D1_POINT_2F point;
-        ft_vector_to_d2d_point(to, ctxt->xoffset, ctxt->yoffset, &point);
-        ID2D1SimplifiedGeometrySink_AddLines(ctxt->sink, &point, 1);
-        ctxt->figure_closed = FALSE;
-    }
-    ctxt->move_to = FALSE;
+    D2D1_POINT_2F point;
+
+    /* Special case for empty contours, in a way freetype returns them. */
+    if (ctxt->move_to && !memcmp(to, &ctxt->origin, sizeof(*to)))
+        return 0;
+
+    decompose_beginfigure(ctxt);
+
+    ft_vector_to_d2d_point(to, ctxt->xoffset, ctxt->yoffset, &point);
+    ID2D1SimplifiedGeometrySink_AddLines(ctxt->sink, &point, 1);
+
     ctxt->origin = *to;
     return 0;
 }
@@ -376,6 +382,8 @@ static int decompose_conic_to(const FT_Vector *control, const FT_Vector *to, voi
     D2D1_POINT_2F points[3];
     FT_Vector cubic[3];
 
+    decompose_beginfigure(ctxt);
+
     /* convert from quadratic to cubic */
 
     /*
@@ -410,8 +418,6 @@ static int decompose_conic_to(const FT_Vector *control, const FT_Vector *to, voi
     ft_vector_to_d2d_point(cubic + 1, ctxt->xoffset, ctxt->yoffset, points + 1);
     ft_vector_to_d2d_point(cubic + 2, ctxt->xoffset, ctxt->yoffset, points + 2);
     ID2D1SimplifiedGeometrySink_AddBeziers(ctxt->sink, (D2D1_BEZIER_SEGMENT*)points, 1);
-    ctxt->figure_closed = FALSE;
-    ctxt->move_to = FALSE;
     ctxt->origin = *to;
     return 0;
 }
@@ -422,12 +428,12 @@ static int decompose_cubic_to(const FT_Vector *control1, const FT_Vector *contro
     struct decompose_context *ctxt = (struct decompose_context*)user;
     D2D1_POINT_2F points[3];
 
+    decompose_beginfigure(ctxt);
+
     ft_vector_to_d2d_point(control1, ctxt->xoffset, ctxt->yoffset, points);
     ft_vector_to_d2d_point(control2, ctxt->xoffset, ctxt->yoffset, points + 1);
     ft_vector_to_d2d_point(to, ctxt->xoffset, ctxt->yoffset, points + 2);
     ID2D1SimplifiedGeometrySink_AddBeziers(ctxt->sink, (D2D1_BEZIER_SEGMENT*)points, 1);
-    ctxt->figure_closed = FALSE;
-    ctxt->move_to = FALSE;
     ctxt->origin = *to;
     return 0;
 }
@@ -448,14 +454,13 @@ static void decompose_outline(FT_Outline *outline, FLOAT xoffset, FLOAT yoffset,
     context.xoffset = xoffset;
     context.yoffset = yoffset;
     context.figure_started = FALSE;
-    context.figure_closed = FALSE;
     context.move_to = FALSE;
     context.origin.x = 0;
     context.origin.y = 0;
 
     pFT_Outline_Decompose(outline, &decompose_funcs, &context);
 
-    if (!context.figure_closed && outline->n_points)
+    if (context.figure_started)
         ID2D1SimplifiedGeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
 }
 
diff --git a/dlls/dwrite/tests/font.c b/dlls/dwrite/tests/font.c
index 417cc21aa2..54dcc75c81 100644
--- a/dlls/dwrite/tests/font.c
+++ b/dlls/dwrite/tests/font.c
@@ -3061,7 +3061,7 @@ if (face2) {
 
     hr = IDWriteFontFace_GetGlyphIndices(face, codePoints, 1, indices);
     ok(hr == S_OK, "got 0x%08x\n", hr);
-    ok(indices[0] == 6, "got index %i\n", indices[0]);
+    ok(indices[0] == 7, "Unexpected glyph index, %u.\n", indices[0]);
     IDWriteFontFace_Release(face);
     IDWriteFontFile_Release(file);
 
@@ -4420,6 +4420,18 @@ static void test_GetGlyphRunOutline(void)
     hr = IDWriteFontFace_GetGlyphRunOutline(face, 1024.0, glyphs, NULL, NULL, 0, FALSE, FALSE, &test_geomsink2);
     ok(hr == S_OK, "got 0x%08x\n", hr);
 
+    /* Glyph with open figure, single contour point. */
+    codepoint = 'B';
+    glyphs[0] = 0;
+    hr = IDWriteFontFace_GetGlyphIndices(face, &codepoint, 1, glyphs);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    ok(glyphs[0] > 0, "got %u\n", glyphs[0]);
+
+    SET_EXPECT(setfillmode);
+    hr = IDWriteFontFace_GetGlyphRunOutline(face, 1024.0, glyphs, NULL, NULL, 1, FALSE, FALSE, &test_geomsink2);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    CHECK_CALLED(setfillmode);
+
     IDWriteFactory_Release(factory);
     IDWriteFontFace_Release(face);
     DELETE_FONTFILE(path);
@@ -4578,7 +4590,7 @@ static void test_GetGlyphCount(void)
     IDWriteFontFile_Release(file);
 
     count = IDWriteFontFace_GetGlyphCount(fontface);
-    ok(count == 7, "got %u\n", count);
+    ok(count == 8, "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 c985b433d6..e533323db7 100644
--- a/dlls/dwrite/tests/wine_test.sfd
+++ b/dlls/dwrite/tests/wine_test.sfd
@@ -83,10 +83,10 @@ NameList: Adobe Glyph List
 DisplaySize: -24
 AntiAlias: 1
 FitToEm: 1
-WinInfo: 48 16 4
+WinInfo: 47 47 13
 BeginPrivate: 0
 EndPrivate
-BeginChars: 65539 7
+BeginChars: 65539 8
 
 StartChar: .notdef
 Encoding: 65536 -1 0
@@ -207,7 +207,7 @@ StartChar: A
 Encoding: 65 65 5
 Width: 1000
 VWidth: 0
-Flags: WO
+Flags: W
 LayerCount: 2
 Fore
 SplineSet
@@ -226,7 +226,7 @@ StartChar: D
 Encoding: 68 68 6
 Width: 1000
 VWidth: 0
-Flags: WO
+Flags: W
 LayerCount: 2
 Fore
 SplineSet
@@ -240,5 +240,17 @@ SplineSet
  461 -30.7998 l 25,0,-1
 EndSplineSet
 EndChar
+
+StartChar: B
+Encoding: 66 66 7
+Width: 2048
+VWidth: 0
+Flags: W
+LayerCount: 2
+Fore
+SplineSet
+500 500 m 24,0,-1
+EndSplineSet
+EndChar
 EndChars
 EndSplineFont
diff --git a/dlls/dwrite/tests/wine_test.ttf b/dlls/dwrite/tests/wine_test.ttf
index 1562a326ac7e4fd1dc72639fa3716b3084758bd6..72dadf5d5438ffbcfff5b2442eb62028245aa9a3 100644
GIT binary patch
delta 401
zcmW+yO-lk%6g}^a^HG#!Nd`)|u#bg(xv+g`MU*Xyh!*8!<`6SEq=c>tS_D#|jH~(w
zEfZR`5`v;l+g7 at C5z#`z-E?Po-22|S=e&FFd%uHqZ#8hy0}xtCB$u&>2q1kDp5EM=
zi``bw+5poCr!$6XN`1aE;SR+~=DZk2Li7Q`Hu0XES}<)J0^NTjtmO3a at mKJ}AYLcE
zU(2dTdpC~`_e~MksL=l)z5s`eOcBwHVrdj&g2aw!T+e4z7R4Vm*d;t{s3j9AB#B=o
z96nWz>{F{UN#2(LA2IWVqTNJ;2B;Gs1EWmgUw?hC_2OKCHO~UF?A8 at 4#X{WkW9iHs
zP{6uEhh5_yu-a^fEm>Y36q@#d73FC`gk;rtmR=^)zGH0&L-HE-Q6Y6&xEks*caa;I
ob8NJPXTG4g?i?Qa(g{rA&f&r6i?}<1m(Uo(lpV~dcT<}E2ear|HUIzs

delta 368
zcmbQj_knkUc>NUy1_l{-7gsk1GX at m~2DUXozJ`CWzESUl!dnasj2S?FLUL|m0V6wq
z1(5#$h_jN*N)#AeSOpmvn0<iqEa{2G1^@puFaz~30rEN0b1Ksw8eD1t$|nHTGi0PD
zrbP9uIsue>1H@(-Kmo4VjEfi;k{E%OGN@$amQ--FG9?2QgA_^R<R>RGtYMS at 8V~^F
z3*;tN6fpQQxB}%pfP96##N5<P_q)`9b|)|}FbNmr7nl4uWt0Lspadvy0JIZiFN2!Z
z>FS9;%$S&8Og3N?XJ-YAvrqP8lmQ9lFcz>dwlmC{{DM(e-jTtDVa5M{KyNTGC^A5J
zzyJUL|LFhW{|EoaO*Ual0Q!%0@<OKA$s3rs7}<cVu*sp!0?Z){4U==2n>RDFY+~YP
Z2V2a<zyb_Sb%wslC)i|xN}sXm0RVl^T`&Lu

-- 
2.14.1




More information about the wine-patches mailing list