Flutter Engine
The Flutter Engine
SkDWriteGeometrySink.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2012 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
9#if defined(SK_BUILD_FOR_WIN)
10
11#include "include/core/SkPath.h"
15
16#include <dwrite.h>
17#include <d2d1.h>
18
20 : fRefCount{1}, fPath{path}, fStarted{false}, fCurrent{0,0} {}
21
23
25 if (nullptr == object) {
26 return E_INVALIDARG;
27 }
28 if (iid == __uuidof(IUnknown) || iid == __uuidof(IDWriteGeometrySink)) {
29 *object = static_cast<IDWriteGeometrySink*>(this);
30 this->AddRef();
31 return S_OK;
32 } else {
33 *object = nullptr;
34 return E_NOINTERFACE;
35 }
36}
37
38SK_STDMETHODIMP_(ULONG) SkDWriteGeometrySink::AddRef(void) {
39 return static_cast<ULONG>(InterlockedIncrement(&fRefCount));
40}
41
42SK_STDMETHODIMP_(ULONG) SkDWriteGeometrySink::Release(void) {
43 ULONG res = static_cast<ULONG>(InterlockedDecrement(&fRefCount));
44 if (0 == res) {
45 delete this;
46 }
47 return res;
48}
49
50SK_STDMETHODIMP_(void) SkDWriteGeometrySink::SetFillMode(D2D1_FILL_MODE fillMode) {
51 switch (fillMode) {
52 case D2D1_FILL_MODE_ALTERNATE:
54 break;
55 case D2D1_FILL_MODE_WINDING:
57 break;
58 default:
59 SkDEBUGFAIL("Unknown D2D1_FILL_MODE.");
60 break;
61 }
62}
63
64SK_STDMETHODIMP_(void) SkDWriteGeometrySink::SetSegmentFlags(D2D1_PATH_SEGMENT vertexFlags) {
65 if (vertexFlags == D2D1_PATH_SEGMENT_NONE || vertexFlags == D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN) {
66 SkDEBUGFAIL("Invalid D2D1_PATH_SEGMENT value.");
67 }
68}
69
70SK_STDMETHODIMP_(void) SkDWriteGeometrySink::BeginFigure(D2D1_POINT_2F startPoint, D2D1_FIGURE_BEGIN figureBegin) {
71 if (figureBegin == D2D1_FIGURE_BEGIN_HOLLOW) {
72 SkDEBUGFAIL("Invalid D2D1_FIGURE_BEGIN value.");
73 }
74 fStarted = false;
75 fCurrent = startPoint;
76}
77
78SK_STDMETHODIMP_(void) SkDWriteGeometrySink::AddLines(const D2D1_POINT_2F *points, UINT pointsCount) {
79 for (const D2D1_POINT_2F *end = &points[pointsCount]; points < end; ++points) {
80 if (this->currentIsNot(*points)) {
81 this->goingTo(*points);
82 fPath->lineTo(points->x, points->y);
83 }
84 }
85}
86
87static bool approximately_equal(float a, float b) {
88 const SkFloatingPoint<float, 10> lhs(a), rhs(b);
89 return lhs.AlmostEquals(rhs);
90}
91
92typedef struct {
93 float x;
94 float y;
95} Cubic[4], Point;
96
97static bool check_quadratic(const Cubic& cubic, Point& quadraticP1) {
98 float dx10 = cubic[1].x - cubic[0].x;
99 float dx23 = cubic[2].x - cubic[3].x;
100 float midX = cubic[0].x + dx10 * 3 / 2;
101 //NOTE: !approximately_equal(midX - cubic[3].x, dx23 * 3 / 2)
102 //does not work as subnormals get in between the left side and 0.
103 if (!approximately_equal(midX, (dx23 * 3 / 2) + cubic[3].x)) {
104 return false;
105 }
106 float dy10 = cubic[1].y - cubic[0].y;
107 float dy23 = cubic[2].y - cubic[3].y;
108 float midY = cubic[0].y + dy10 * 3 / 2;
109 if (!approximately_equal(midY, (dy23 * 3 / 2) + cubic[3].y)) {
110 return false;
111 }
112 quadraticP1 = {midX, midY};
113 return true;
114}
115
116SK_STDMETHODIMP_(void) SkDWriteGeometrySink::AddBeziers(const D2D1_BEZIER_SEGMENT *beziers, UINT beziersCount) {
117 for (const D2D1_BEZIER_SEGMENT *end = &beziers[beziersCount]; beziers < end; ++beziers) {
118 if (this->currentIsNot(beziers->point1) ||
119 this->currentIsNot(beziers->point2) ||
120 this->currentIsNot(beziers->point3))
121 {
122 Cubic cubic = { { fCurrent.x, fCurrent.y },
123 { beziers->point1.x, beziers->point1.y },
124 { beziers->point2.x, beziers->point2.y },
125 { beziers->point3.x, beziers->point3.y }, };
126 this->goingTo(beziers->point3);
127 Point quadraticP1;
128 if (check_quadratic(cubic, quadraticP1)) {
129 fPath->quadTo( quadraticP1.x, quadraticP1.y,
130 beziers->point3.x, beziers->point3.y);
131 } else {
132 fPath->cubicTo(beziers->point1.x, beziers->point1.y,
133 beziers->point2.x, beziers->point2.y,
134 beziers->point3.x, beziers->point3.y);
135 }
136 }
137 }
138}
139
140SK_STDMETHODIMP_(void) SkDWriteGeometrySink::EndFigure(D2D1_FIGURE_END figureEnd) {
141 if (fStarted) {
142 fPath->close();
143 }
144}
145
147 return S_OK;
148}
149
150HRESULT SkDWriteGeometrySink::Create(SkPath* path, IDWriteGeometrySink** geometryToPath) {
151 *geometryToPath = new SkDWriteGeometrySink(path);
152 return S_OK;
153}
154
155#endif//defined(SK_BUILD_FOR_WIN)
SkPath fPath
static const int points[]
#define SkDEBUGFAIL(message)
Definition: SkAssert.h:118
#define SK_STDMETHODIMP_(type)
Definition: SkObjBase.h:23
#define SK_STDMETHODIMP
Definition: SkObjBase.h:22
bool approximately_equal(double x, double y)
static int check_quadratic(const SkDCubic &cubic, SkDCubic &reduction)
SkDWriteGeometrySink(SkPath *path)
static HRESULT Create(SkPath *path, IDWriteGeometrySink **geometryToPath)
SK_STDMETHODIMP Close() override
SK_STDMETHODIMP QueryInterface(REFIID iid, void **object) override
virtual ~SkDWriteGeometrySink()
Definition: SkPath.h:59
void setFillType(SkPathFillType ft)
Definition: SkPath.h:235
SkPath & lineTo(SkScalar x, SkScalar y)
Definition: SkPath.cpp:728
SkPath & quadTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2)
Definition: SkPath.cpp:746
SkPath & cubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, SkScalar x3, SkScalar y3)
Definition: SkPath.cpp:799
SkPath & close()
Definition: SkPath.cpp:823
static bool b
struct MyStruct a[10]
glong glong end
double y
double x
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir path
Definition: switches.h:57
TPoint< Scalar > Point
Definition: point.h:322
AI float cubic(float precision, const SkPoint pts[], const VectorXform &vectorXform=VectorXform())
Definition: WangsFormula.h:195
unsigned int UINT
Definition: windows_types.h:32
DWORD ULONG
Definition: windows_types.h:40