[Windows][DirectX] Be more rigors about BeginFigure/EndFigure and Close operations.
authorbfulgham@apple.com <bfulgham@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 9 Nov 2018 17:32:32 +0000 (17:32 +0000)
committerbfulgham@apple.com <bfulgham@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 9 Nov 2018 17:32:32 +0000 (17:32 +0000)
https://bugs.webkit.org/show_bug.cgi?id=191452
<rdar://problem/45933964>

Reviewed by Zalan Bujtas.

Do a better job of balancing the BeginFigure/EndFigure calls in
the PathDirect2D implementation. Failure to do so puts the Geometry sink
into an error state that prevents it from producing drawing output.

* platform/graphics/Path.h:
* platform/graphics/win/GraphicsContextDirect2D.cpp:
(WebCore::GraphicsContext::drawPath): Flush is needed here.
(WebCore::GraphicsContext::fillPath): Ditto.
(WebCore::GraphicsContext::strokePath): Ditto.
* platform/graphics/win/PathDirect2D.cpp:
(WebCore::Path::drawDidComplete):
(WebCore::Path::closeAnyOpenGeometries):
(WebCore::Path::transform):
(WebCore::Path::openFigureAtCurrentPointIfNecessary):
(WebCore::Path::moveTo):
(WebCore::Path::closeSubpath):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@238037 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebCore/ChangeLog
Source/WebCore/platform/graphics/Path.h
Source/WebCore/platform/graphics/win/GraphicsContextDirect2D.cpp
Source/WebCore/platform/graphics/win/PathDirect2D.cpp

index c32691d..935566c 100644 (file)
@@ -1,3 +1,29 @@
+2018-11-09  Brent Fulgham  <bfulgham@apple.com>
+
+        [Windows][DirectX] Be more rigors about BeginFigure/EndFigure and Close operations. 
+        https://bugs.webkit.org/show_bug.cgi?id=191452
+        <rdar://problem/45933964>
+
+        Reviewed by Zalan Bujtas.
+
+        Do a better job of balancing the BeginFigure/EndFigure calls in
+        the PathDirect2D implementation. Failure to do so puts the Geometry sink
+        into an error state that prevents it from producing drawing output.
+      
+
+        * platform/graphics/Path.h:
+        * platform/graphics/win/GraphicsContextDirect2D.cpp:
+        (WebCore::GraphicsContext::drawPath): Flush is needed here.
+        (WebCore::GraphicsContext::fillPath): Ditto.
+        (WebCore::GraphicsContext::strokePath): Ditto.
+        * platform/graphics/win/PathDirect2D.cpp:
+        (WebCore::Path::drawDidComplete):
+        (WebCore::Path::closeAnyOpenGeometries):
+        (WebCore::Path::transform):
+        (WebCore::Path::openFigureAtCurrentPointIfNecessary):
+        (WebCore::Path::moveTo):
+        (WebCore::Path::closeSubpath):
+
 2018-11-09  Jer Noble  <jer.noble@apple.com>
 
         [Cocoa] Fix failing imported/w3c/web-platform-tests/media-source/mediasource-changetype-play.html test
index cc12b86..910e12b 100644 (file)
@@ -201,6 +201,7 @@ namespace WebCore {
 
         HRESULT initializePathState();
         void openFigureAtCurrentPointIfNecessary();
+        void closeAnyOpenGeometries();
 #endif
 
 #ifndef NDEBUG
@@ -212,7 +213,7 @@ namespace WebCore {
         COMPtr<ID2D1GeometryGroup> m_path;
         COMPtr<ID2D1PathGeometry> m_activePathGeometry;
         COMPtr<ID2D1GeometrySink> m_activePath;
-        bool m_doesHaveOpenFigure { false };
+        size_t m_openFigureCount { 0 };
 #else
         PlatformPathPtr m_path { nullptr };
 #endif
index 113819d..b8f65b4 100644 (file)
@@ -940,6 +940,8 @@ void GraphicsContext::drawPath(const Path& path)
         auto brush = m_state.strokePattern ? patternStrokeBrush() : solidStrokeBrush();
         renderTarget->DrawGeometry(path.platformPath(), brush, strokeThickness(), m_data->strokeStyle());
     });
+
+    flush();
 }
 
 void GraphicsContext::drawWithoutShadow(const FloatRect& /*boundingRect*/, const WTF::Function<void(ID2D1RenderTarget*)>& drawCommands)
@@ -1043,6 +1045,8 @@ void GraphicsContext::fillPath(const Path& path)
             drawWithShadow(boundingRect, drawFunction);
         else
             drawWithoutShadow(boundingRect, drawFunction);
+
+        flush();
         return;
     }
 
@@ -1059,6 +1063,8 @@ void GraphicsContext::fillPath(const Path& path)
         auto brush = m_state.fillPattern ? patternFillBrush() : solidFillBrush();
         renderTarget->FillGeometry(pathToFill.get(), brush);
     });
+
+    flush();
 }
 
 void GraphicsContext::strokePath(const Path& path)
@@ -1089,6 +1095,7 @@ void GraphicsContext::strokePath(const Path& path)
         else
             drawWithoutShadow(boundingRect, drawFunction);
 
+        flush();
         return;
     }
 
@@ -1102,6 +1109,8 @@ void GraphicsContext::strokePath(const Path& path)
         auto brush = m_state.strokePattern ? patternStrokeBrush() : solidStrokeBrush();
         renderTarget->DrawGeometry(path.platformPath(), brush, strokeThickness(), m_data->strokeStyle());
     });
+
+    flush();
 }
 
 void GraphicsContext::fillRect(const FloatRect& rect)
index eb85631..5465ea7 100644 (file)
@@ -224,7 +224,7 @@ void Path::drawDidComplete()
     m_activePath->SetFillMode(D2D1_FILL_MODE_WINDING);
 
     m_activePath->BeginFigure(currentPoint, D2D1_FIGURE_BEGIN_FILLED);
-    m_doesHaveOpenFigure = true;
+    ++m_openFigureCount;
 }
 
 bool Path::contains(const FloatPoint& point, WindRule rule) const
@@ -260,6 +260,22 @@ bool Path::strokeContains(StrokeStyleApplier* applier, const FloatPoint& point)
     return containsPoint;
 }
 
+void Path::closeAnyOpenGeometries()
+{
+    ASSERT(m_activePath);
+
+    if (!m_openFigureCount)
+        return;
+
+    while (m_openFigureCount) {
+        m_activePath->EndFigure(D2D1_FIGURE_END_OPEN);
+        --m_openFigureCount;
+    }
+
+    HRESULT hr = m_activePath->Close();
+    ASSERT(SUCCEEDED(hr));
+}
+
 void Path::translate(const FloatSize& size)
 {
     transform(AffineTransform(1, 0, 0, 1, size.width(), size.height()));
@@ -276,9 +292,7 @@ void Path::transform(const AffineTransform& transform)
 
     bool pathIsActive = false;
     if (m_activePath) {
-        m_activePath->EndFigure(D2D1_FIGURE_END_OPEN);
-        m_doesHaveOpenFigure = false;
-        m_activePath->Close();
+        closeAnyOpenGeometries();
         m_activePath = nullptr;
         m_activePathGeometry = nullptr;
         pathIsActive = true;
@@ -311,7 +325,7 @@ void Path::transform(const AffineTransform& transform)
 
     auto transformedPoint = transform.mapPoint(currentPoint.value());
     m_activePath->BeginFigure(transformedPoint, D2D1_FIGURE_BEGIN_FILLED);
-    m_doesHaveOpenFigure = true;
+    m_openFigureCount = 1;
 }
 
 FloatRect Path::boundingRect() const
@@ -355,21 +369,20 @@ FloatRect Path::strokeBoundingRect(StrokeStyleApplier* applier) const
 
 void Path::openFigureAtCurrentPointIfNecessary()
 {
-    if (m_doesHaveOpenFigure)
+    if (m_openFigureCount)
         return;
 
     m_activePath->SetFillMode(D2D1_FILL_MODE_WINDING);
     m_activePath->BeginFigure(currentPoint(), D2D1_FIGURE_BEGIN_FILLED);
-    m_doesHaveOpenFigure = true;
+    ++m_openFigureCount;
 }
 
 void Path::moveTo(const FloatPoint& point)
 {
     if (m_activePath) {
-        m_activePath->Close();
+        closeAnyOpenGeometries();
         m_activePath = nullptr;
         m_activePathGeometry = nullptr;
-        m_doesHaveOpenFigure = false;
     }
 
     GraphicsContext::systemFactory()->CreatePathGeometry(&m_activePathGeometry);
@@ -381,7 +394,7 @@ void Path::moveTo(const FloatPoint& point)
 
     m_activePath->SetFillMode(D2D1_FILL_MODE_WINDING);
     m_activePath->BeginFigure(point, D2D1_FIGURE_BEGIN_FILLED);
-    m_doesHaveOpenFigure = true;
+    m_openFigureCount = 1;
 }
 
 void Path::addLineTo(const FloatPoint& point)
@@ -488,14 +501,24 @@ void Path::closeSubpath()
     if (isNull())
         return;
 
-    if (m_activePath) {
-        m_activePath->EndFigure(D2D1_FIGURE_END_CLOSED);
-        m_activePath->Close();
-        m_activePath = nullptr;
-        m_activePathGeometry = nullptr;
+    if (!m_activePath) {
+        ASSERT(!m_openFigureCount);
+        ASSERT(!m_activePathGeometry);
+        return;
+    }
+
+    if (!m_openFigureCount)
+        return;
+
+    m_activePath->EndFigure(D2D1_FIGURE_END_CLOSED);
+    --m_openFigureCount;
+    if (m_openFigureCount > 0) {
+        ASSERT(m_activePathGeometry);
+        return;
     }
 
-    m_doesHaveOpenFigure = false;
+    HRESULT hr = m_activePath->Close();
+    ASSERT(SUCCEEDED(hr));
 }
 
 static FloatPoint arcStart(const FloatPoint& center, float radius, float startAngle)