[Win][Direct2D] Use smart pointers for Direct2D Path types
authorbfulgham@apple.com <bfulgham@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 26 Oct 2016 01:57:44 +0000 (01:57 +0000)
committerbfulgham@apple.com <bfulgham@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 26 Oct 2016 01:57:44 +0000 (01:57 +0000)
https://bugs.webkit.org/show_bug.cgi?id=163994

Reviewed by Alex Christensen.

Tested by existing path tests.

* platform/graphics/Path.h:
(WebCore::Path::platformPath): Use a COMPtr for m_path.
* platform/graphics/win/GraphicsContextDirect2D.cpp:
(WebCore::GraphicsContext::systemFactory): Present better D2D debug output
when running a debug build.
(WebCore::GraphicsContext::platformInit): Initialize a D2D device from a
native GDI device context.
(WebCore::GraphicsContext::platformStrokeStyle): Added.
(WebCore::GraphicsContext::clipBounds): Simplify clip boundary calculations and
avoid doing math on infinities.
* platform/graphics/win/PathDirect2D.cpp:
(WebCore::scratchRenderTarget): Added.
(WebCore::Path::~Path): Switch to COMPtr implementation.
(WebCore::Path::ensurePlatformPath): Ditto.
(WebCore::Path::appendGeometry): Ditto.
(WebCore::Path::operator=): Ditto.
(WebCore::Path::initializePathState): Ditto.
(WebCore::Path::strokeContains): Provide an implementation.
(WebCore::Path::transform): Ditto.
(WebCore::Path::addEllipse): No need for explicit construction of the
D2D1::Point2F object.
(WebCore::Path::clear): Switch to COMPtr implementation.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@207863 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 3a86fea..a5f8091 100644 (file)
@@ -1,3 +1,35 @@
+2016-10-25  Brent Fulgham  <bfulgham@apple.com>
+
+        [Win][Direct2D] Use smart pointers for Direct2D Path types
+        https://bugs.webkit.org/show_bug.cgi?id=163994
+
+        Reviewed by Alex Christensen.
+
+        Tested by existing path tests.
+
+        * platform/graphics/Path.h:
+        (WebCore::Path::platformPath): Use a COMPtr for m_path.
+        * platform/graphics/win/GraphicsContextDirect2D.cpp:
+        (WebCore::GraphicsContext::systemFactory): Present better D2D debug output
+        when running a debug build.
+        (WebCore::GraphicsContext::platformInit): Initialize a D2D device from a
+        native GDI device context.
+        (WebCore::GraphicsContext::platformStrokeStyle): Added.
+        (WebCore::GraphicsContext::clipBounds): Simplify clip boundary calculations and
+        avoid doing math on infinities.
+        * platform/graphics/win/PathDirect2D.cpp:
+        (WebCore::scratchRenderTarget): Added.
+        (WebCore::Path::~Path): Switch to COMPtr implementation.
+        (WebCore::Path::ensurePlatformPath): Ditto.
+        (WebCore::Path::appendGeometry): Ditto.
+        (WebCore::Path::operator=): Ditto.
+        (WebCore::Path::initializePathState): Ditto.
+        (WebCore::Path::strokeContains): Provide an implementation.
+        (WebCore::Path::transform): Ditto.
+        (WebCore::Path::addEllipse): No need for explicit construction of the
+        D2D1::Point2F object.
+        (WebCore::Path::clear): Switch to COMPtr implementation.
+
 2016-10-25  Nan Wang  <n_wang@apple.com>
 
         LayoutTest accessibility/mac/meter-gauge-value-description.html failing
index 5b53f9f..a912447 100644 (file)
@@ -165,7 +165,11 @@ namespace WebCore {
 
         // To keep Path() cheap, it does not allocate a PlatformPath immediately
         // meaning Path::platformPath() can return null.
+#if USE(DIRECT2D)
+        PlatformPathPtr platformPath() const { return m_path.get(); }
+#else
         PlatformPathPtr platformPath() const { return m_path; }
+#endif
         // ensurePlatformPath() will allocate a PlatformPath if it has not yet been and will never return null.
         WEBCORE_EXPORT PlatformPathPtr ensurePlatformPath();
 
@@ -199,10 +203,12 @@ namespace WebCore {
 #endif
 
     private:
-        PlatformPathPtr m_path { nullptr };
 #if USE(DIRECT2D)
+        COMPtr<ID2D1GeometryGroup> m_path;
         COMPtr<ID2D1PathGeometry> m_activePathGeometry;
         COMPtr<ID2D1GeometrySink> m_activePath;
+#else
+        PlatformPathPtr m_path { nullptr };
 #endif
     };
 
index b726016..c0780d8 100644 (file)
@@ -71,7 +71,13 @@ ID2D1Factory* GraphicsContext::systemFactory()
 {
     static ID2D1Factory* direct2DFactory = nullptr;
     if (!direct2DFactory) {
+#ifndef NDEBUG
+        D2D1_FACTORY_OPTIONS options = { };
+        options.debugLevel = D2D1_DEBUG_LEVEL_INFORMATION;
+        HRESULT hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_MULTI_THREADED, options, &direct2DFactory);
+#else
         HRESULT hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_MULTI_THREADED, &direct2DFactory);
+#endif
         RELEASE_ASSERT(SUCCEEDED(hr));
     }
 
@@ -108,7 +114,23 @@ void GraphicsContext::platformInit(HDC hdc, bool hasAlpha)
     if (!hdc)
         return;
 
-    COMPtr<ID2D1RenderTarget> renderTarget;
+    HBITMAP bitmap = static_cast<HBITMAP>(GetCurrentObject(hdc, OBJ_BITMAP));
+
+    DIBPixelData pixelData(bitmap);
+
+    auto targetProperties = D2D1::RenderTargetProperties();
+    targetProperties.pixelFormat = D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_IGNORE);
+
+    COMPtr<ID2D1DCRenderTarget> renderTarget;
+    HRESULT hr = systemFactory()->CreateDCRenderTarget(&targetProperties, &renderTarget);
+    if (!SUCCEEDED(hr))
+        return;
+
+    RECT clientRect = IntRect(IntPoint(), pixelData.size());
+    hr = renderTarget->BindDC(hdc, &clientRect);
+    if (!SUCCEEDED(hr))
+        return;
+
     m_data = new GraphicsContextPlatformPrivate(renderTarget.get());
     m_data->m_hdc = hdc;
     // Make sure the context starts in sync with our state.
@@ -671,6 +693,11 @@ ID2D1StrokeStyle* GraphicsContextPlatformPrivate::strokeStyle()
     return m_d2dStrokeStyle.get();
 }
 
+ID2D1StrokeStyle* GraphicsContext::platformStrokeStyle() const
+{
+    return m_data->strokeStyle();
+}
+
 // This is only used to draw borders.
 void GraphicsContext::drawLine(const FloatPoint& point1, const FloatPoint& point2)
 {
@@ -1248,14 +1275,13 @@ IntRect GraphicsContext::clipBounds() const
         return IntRect(-2048, -2048, 4096, 4096); // FIXME: display lists.
     }
 
-    D2D1_RECT_F d2dClipBounds = D2D1::InfiniteRect();
-    FloatRect clipBounds(d2dClipBounds.left, d2dClipBounds.top, d2dClipBounds.right - d2dClipBounds.left, d2dClipBounds.bottom - d2dClipBounds.top);
+    D2D1_SIZE_F clipSize;
+    if (auto clipLayer = m_data->clipLayer())
+        clipSize = clipLayer->GetSize();
+    else
+        clipSize = platformContext()->GetSize();
 
-    if (m_data->clipLayer()) {
-        auto clipSize = m_data->clipLayer()->GetSize();
-        clipBounds.setWidth(clipSize.width);
-        clipBounds.setHeight(clipSize.height);
-    }
+    FloatRect clipBounds(IntPoint(), clipSize);
 
     return enclosingIntRect(clipBounds);
 }
index 62196eb..18e6d5e 100644 (file)
 
 namespace WebCore {
 
+static inline ID2D1RenderTarget* scratchRenderTarget()
+{
+    static COMPtr<ID2D1RenderTarget> renderTarget = adoptCOM(GraphicsContext::defaultRenderTarget());
+    return renderTarget.get();
+}
 
 Path Path::polygonPathFromPoints(const Vector<FloatPoint>& points)
 {
@@ -70,8 +75,6 @@ Path::Path()
 
 Path::~Path()
 {
-    if (m_path)
-        m_path->Release();
 }
 
 PlatformPathPtr Path::ensurePlatformPath()
@@ -83,7 +86,7 @@ PlatformPathPtr Path::ensurePlatformPath()
             return nullptr;
     }
 
-    return m_path;
+    return m_path.get();
 }
 
 void Path::appendGeometry(ID2D1Geometry* geometry)
@@ -101,7 +104,7 @@ void Path::appendGeometry(ID2D1Geometry* geometry)
 
     auto fillMode = m_path ? m_path->GetFillMode() : D2D1_FILL_MODE_WINDING;
 
-    COMPtr<ID2D1GeometryGroup> protectedPath = adoptCOM(m_path);
+    COMPtr<ID2D1GeometryGroup> protectedPath = m_path;
     m_path = nullptr;
 
     HRESULT hr = GraphicsContext::systemFactory()->CreateGeometryGroup(fillMode, geometries.data(), geometries.size(), &m_path);
@@ -162,13 +165,7 @@ Path::Path(const Path& other)
 
 Path& Path::operator=(const Path& other)
 {
-    if (m_path)
-        m_path->Release();
-
     m_path = other.m_path;
-    if (m_path)
-        m_path->AddRef();
-
     m_activePath = other.m_activePath;
     m_activePathGeometry = other.m_activePathGeometry;
 
@@ -177,8 +174,6 @@ Path& Path::operator=(const Path& other)
 
 HRESULT Path::initializePathState()
 {
-    if (m_path)
-        m_path->Release();
     m_path = nullptr;
     m_activePath = nullptr;
     m_activePathGeometry = nullptr;
@@ -231,10 +226,17 @@ bool Path::strokeContains(StrokeStyleApplier* applier, const FloatPoint& point)
     if (isNull())
         return false;
 
-    UNUSED_PARAM(applier);
-    UNUSED_PARAM(point);
-    notImplemented();
-    return false;
+    ASSERT(applier);
+
+    GraphicsContext scratchContext(scratchRenderTarget());
+    applier->strokeStyle(&scratchContext);
+
+    BOOL containsPoint = false;
+    HRESULT hr = m_path->StrokeContainsPoint(point, scratchContext.strokeThickness(), scratchContext.platformStrokeStyle(), nullptr, 1.0f, &containsPoint);
+    if (!SUCCEEDED(hr))
+        return false;
+
+    return containsPoint;
 }
 
 void Path::translate(const FloatSize& size)
@@ -257,7 +259,7 @@ void Path::transform(const AffineTransform& transform)
 
     const D2D1_MATRIX_3X2_F& d2dTransform = static_cast<const D2D1_MATRIX_3X2_F>(transform);
     COMPtr<ID2D1TransformedGeometry> transformedPath;
-    if (!SUCCEEDED(GraphicsContext::systemFactory()->CreateTransformedGeometry(m_path, d2dTransform, &transformedPath)))
+    if (!SUCCEEDED(GraphicsContext::systemFactory()->CreateTransformedGeometry(m_path.get(), d2dTransform, &transformedPath)))
         return;
 
     Vector<ID2D1Geometry*> geometries;
@@ -271,7 +273,6 @@ void Path::transform(const AffineTransform& transform)
 
     auto fillMode = m_path->GetFillMode();
 
-    m_path->Release();
     m_path = nullptr;
 
     HRESULT hr = GraphicsContext::systemFactory()->CreateGeometryGroup(fillMode, geometries.data(), geometries.size(), &m_path);
@@ -476,7 +477,7 @@ void Path::addEllipse(FloatPoint p, float radiusX, float radiusY, float rotation
 void Path::addEllipse(const FloatRect& r)
 {
     COMPtr<ID2D1EllipseGeometry> ellipse;
-    HRESULT hr = GraphicsContext::systemFactory()->CreateEllipseGeometry(D2D1::Ellipse(D2D1::Point2F(r.center().x(), r.center().y()), r.width(), r.height()), &ellipse);
+    HRESULT hr = GraphicsContext::systemFactory()->CreateEllipseGeometry(D2D1::Ellipse(r.center(), r.width(), r.height()), &ellipse);
     RELEASE_ASSERT(SUCCEEDED(hr));
     appendGeometry(ellipse.get());
 }
@@ -498,9 +499,6 @@ void Path::clear()
     if (isNull())
         return;
 
-    if (m_path)
-        m_path->Release();
-
     m_path = nullptr;
     m_activePath = nullptr;
     m_activePathGeometry = nullptr;