From f06a68051c1ebd7b45862555c80b13842bb85dfa Mon Sep 17 00:00:00 2001 From: Bas Schouten Date: Thu, 7 Nov 2013 22:10:53 +1300 Subject: [PATCH] Bug 935297 - Part 2: Implement new API to allow streaming paths to arbitrary sinks on Direct2D. r=mattwoodrow --- gfx/2d/PathD2D.cpp | 80 ++++++++++++++++++++++++++++++++++++++++++++++ gfx/2d/PathD2D.h | 2 +- 2 files changed, 81 insertions(+), 1 deletion(-) diff --git a/gfx/2d/PathD2D.cpp b/gfx/2d/PathD2D.cpp index ef5d74669af..a6bd78e1736 100644 --- a/gfx/2d/PathD2D.cpp +++ b/gfx/2d/PathD2D.cpp @@ -91,6 +91,70 @@ private: bool mNeedsFigureEnded; }; +class StreamingGeometrySink : public ID2D1SimplifiedGeometrySink +{ +public: + StreamingGeometrySink(PathSink *aSink) + : mSink(aSink) + { + } + + HRESULT STDMETHODCALLTYPE QueryInterface(const IID &aIID, void **aPtr) + { + if (!aPtr) { + return E_POINTER; + } + + if (aIID == IID_IUnknown) { + *aPtr = static_cast(this); + return S_OK; + } else if (aIID == IID_ID2D1SimplifiedGeometrySink) { + *aPtr = static_cast(this); + return S_OK; + } + + return E_NOINTERFACE; + } + + ULONG STDMETHODCALLTYPE AddRef() + { + return 1; + } + + ULONG STDMETHODCALLTYPE Release() + { + return 1; + } + + // We ignore SetFillMode, this depends on the destination sink. + STDMETHOD_(void, SetFillMode)(D2D1_FILL_MODE aMode) + { return; } + STDMETHOD_(void, BeginFigure)(D2D1_POINT_2F aPoint, D2D1_FIGURE_BEGIN aBegin) + { mSink->MoveTo(ToPoint(aPoint)); } + STDMETHOD_(void, AddLines)(const D2D1_POINT_2F *aLines, UINT aCount) + { for (UINT i = 0; i < aCount; i++) { mSink->LineTo(ToPoint(aLines[i])); } } + STDMETHOD_(void, AddBeziers)(const D2D1_BEZIER_SEGMENT *aSegments, UINT aCount) + { + for (UINT i = 0; i < aCount; i++) { + mSink->BezierTo(ToPoint(aSegments[i].point1), ToPoint(aSegments[i].point2), ToPoint(aSegments[i].point3)); + } + } + STDMETHOD(Close)() + { /* Should never be called! */ return S_OK; } + STDMETHOD_(void, SetSegmentFlags)(D2D1_PATH_SEGMENT aFlags) + { /* Should never be called! */ } + + STDMETHOD_(void, EndFigure)(D2D1_FIGURE_END aEnd) + { + if (aEnd == D2D1_FIGURE_END_CLOSED) { + return mSink->Close(); + } + } +private: + + PathSink *mSink; +}; + PathBuilderD2D::~PathBuilderD2D() { } @@ -292,6 +356,22 @@ PathD2D::TransformedCopyToBuilder(const Matrix &aTransform, FillRule aFillRule) return pathBuilder; } +void +PathD2D::StreamToSink(PathSink *aSink) const +{ + HRESULT hr; + + StreamingGeometrySink sink(aSink); + + hr = mGeometry->Simplify(D2D1_GEOMETRY_SIMPLIFICATION_OPTION_CUBICS_AND_LINES, + D2D1::IdentityMatrix(), &sink); + + if (FAILED(hr)) { + gfxWarning() << "Failed to stream D2D path to sink. Code: " << hr; + return; + } +} + bool PathD2D::ContainsPoint(const Point &aPoint, const Matrix &aTransform) const { diff --git a/gfx/2d/PathD2D.h b/gfx/2d/PathD2D.h index 58a8194e1cb..28cc7f827dc 100644 --- a/gfx/2d/PathD2D.h +++ b/gfx/2d/PathD2D.h @@ -85,7 +85,7 @@ public: virtual Rect GetStrokedBounds(const StrokeOptions &aStrokeOptions, const Matrix &aTransform = Matrix()) const; - virtual void StreamToSink(PathSink *aSink) const { MOZ_ASSERT(false); } + virtual void StreamToSink(PathSink *aSink) const; virtual FillRule GetFillRule() const { return mFillRule; }