Flutter Engine
The Flutter Engine
FillStroke.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2020 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
22#include "src/utils/SkJSON.h"
23
24#include <algorithm>
25#include <cstddef>
26#include <utility>
27#include <vector>
28
29namespace skottie {
30namespace internal {
31
32namespace {
33
34class FillStrokeAdapter final : public DiscardableAdapterBase<FillStrokeAdapter, sksg::PaintNode> {
35public:
36 enum class Type { kFill, kStroke };
37
38 FillStrokeAdapter(const skjson::ObjectValue& jpaint,
39 const AnimationBuilder& abuilder,
40 sk_sp<sksg::PaintNode> paint_node,
42 Type type)
43 : INHERITED(std::move(paint_node))
44 , fShaderType(gradient_adapter ? ShaderType::kGradient : ShaderType::kColor) {
45
46 this->attachDiscardableAdapter(std::move(gradient_adapter));
47
48 this->bind(abuilder, jpaint["o"], fOpacity);
49
50 this->node()->setAntiAlias(true);
51
52 if (type == Type::kStroke) {
53 this->bind(abuilder, jpaint["w"], fStrokeWidth);
54
55 this->node()->setStyle(SkPaint::kStroke_Style);
56 this->node()->setStrokeMiter(ParseDefault<SkScalar>(jpaint["ml"], 4.0f));
57
58 static constexpr SkPaint::Join gJoins[] = {
62 };
63 this->node()->setStrokeJoin(
64 gJoins[std::min<size_t>(ParseDefault<size_t>(jpaint["lj"], 1) - 1,
65 std::size(gJoins) - 1)]);
66
67 static constexpr SkPaint::Cap gCaps[] = {
71 };
72 this->node()->setStrokeCap(
73 gCaps[std::min<size_t>(ParseDefault<size_t>(jpaint["lc"], 1) - 1,
74 std::size(gCaps) - 1)]);
75 }
76
77 if (fShaderType == ShaderType::kColor) {
78 this->bind(abuilder, jpaint["c"], fColor);
79 }
80 }
81
82private:
83 void onSync() override {
84 this->node()->setOpacity(fOpacity * 0.01f);
85 this->node()->setStrokeWidth(fStrokeWidth);
86
87 if (fShaderType == ShaderType::kColor) {
88 auto* color_node = static_cast<sksg::Color*>(this->node().get());
89 color_node->setColor(fColor);
90 }
91 }
92
93 enum class ShaderType { kColor, kGradient };
94
95 const ShaderType fShaderType;
96
97 ColorValue fColor;
98 ScalarValue fOpacity = 100,
99 fStrokeWidth = 1;
100
101 using INHERITED = DiscardableAdapterBase<FillStrokeAdapter, sksg::PaintNode>;
102};
103
104class DashAdapter final : public DiscardableAdapterBase<DashAdapter, sksg::DashEffect> {
105public:
106 DashAdapter(const skjson::ArrayValue& jdash,
107 const AnimationBuilder& abuilder,
109 : INHERITED(sksg::DashEffect::Make(std::move(geo))) {
110 SkASSERT(jdash.size() > 1);
111
112 // The dash is encoded as an arbitrary number of intervals (alternating dash/gap),
113 // plus a single trailing offset. Each value can be animated independently.
114 const auto interval_count = jdash.size() - 1;
115 fIntervals.resize(interval_count, 0);
116
117 for (size_t i = 0; i < jdash.size(); ++i) {
118 if (const skjson::ObjectValue* jint = jdash[i]) {
119 auto* target = i < interval_count
120 ? &fIntervals[i]
121 : &fOffset;
122 this->bind(abuilder, (*jint)["v"], target);
123 }
124 }
125 }
126
127private:
128 void onSync() override {
129 this->node()->setPhase(fOffset);
130 this->node()->setIntervals(fIntervals);
131 }
132
133 std::vector<ScalarValue> fIntervals;
134 ScalarValue fOffset = 0;
135
136 using INHERITED = DiscardableAdapterBase<DashAdapter, sksg::DashEffect>;
137};
138
139} // namespace
140
141sk_sp<sksg::PaintNode> ShapeBuilder::AttachFill(const skjson::ObjectValue& jpaint,
142 const AnimationBuilder* abuilder,
143 sk_sp<sksg::PaintNode> paint_node,
145 return abuilder->attachDiscardableAdapter<FillStrokeAdapter>
146 (jpaint,
147 *abuilder,
148 std::move(paint_node),
149 std::move(gradient),
150 FillStrokeAdapter::Type::kFill);
151}
152
153sk_sp<sksg::PaintNode> ShapeBuilder::AttachStroke(const skjson::ObjectValue& jpaint,
154 const AnimationBuilder* abuilder,
155 sk_sp<sksg::PaintNode> paint_node,
157 return abuilder->attachDiscardableAdapter<FillStrokeAdapter>
158 (jpaint,
159 *abuilder,
160 std::move(paint_node),
161 std::move(gradient),
162 FillStrokeAdapter::Type::kStroke);
163}
164
166 const AnimationBuilder* abuilder) {
167 auto color_node = sksg::Color::Make(SK_ColorBLACK);
168 auto color_paint = AttachFill(jpaint, abuilder, color_node);
169 abuilder->dispatchColorProperty(color_node);
170 return color_paint;
171}
172
174 const AnimationBuilder* abuilder) {
175 auto color_node = sksg::Color::Make(SK_ColorBLACK);
176 auto color_paint = AttachStroke(jpaint, abuilder, color_node);
177 abuilder->dispatchColorProperty(color_node);
178 return color_paint;
179}
180
181std::vector<sk_sp<sksg::GeometryNode>> ShapeBuilder::AdjustStrokeGeometry(
182 const skjson::ObjectValue& jstroke,
183 const AnimationBuilder* abuilder,
184 std::vector<sk_sp<sksg::GeometryNode>>&& geos) {
185
186 const skjson::ArrayValue* jdash = jstroke["d"];
187 if (jdash && jdash->size() > 1) {
188 for (size_t i = 0; i < geos.size(); ++i) {
189 geos[i] = abuilder->attachDiscardableAdapter<DashAdapter>(
190 *jdash, *abuilder, std::move(geos[i]));
191 }
192 }
193
194 return std::move(geos);
195}
196
197} // namespace internal
198} // namespace skottie
static constexpr SkColor kColor
Definition: CanvasTest.cpp:265
SkScalar fIntervals[2]
Definition: DashOp.cpp:190
#define SkASSERT(cond)
Definition: SkAssert.h:116
constexpr SkColor SK_ColorBLACK
Definition: SkColor.h:103
#define INHERITED(method,...)
Definition: SkRecorder.cpp:128
GLenum type
@ kRound_Cap
adds circle
Definition: SkPaint.h:335
@ kButt_Cap
no stroke extension
Definition: SkPaint.h:334
@ kSquare_Cap
adds square
Definition: SkPaint.h:336
@ kStroke_Style
set to stroke geometry
Definition: SkPaint.h:194
@ kRound_Join
adds circle
Definition: SkPaint.h:360
@ kMiter_Join
extends to miter limit
Definition: SkPaint.h:359
@ kBevel_Join
connects outside edges
Definition: SkPaint.h:361
size_t size() const
Definition: SkJSON.h:262
bool dispatchColorProperty(const sk_sp< sksg::Color > &) const
Definition: Skottie.cpp:228
void attachDiscardableAdapter(sk_sp< T > adapter) const
Definition: SkottiePriv.h:139
static sk_sp< sksg::PaintNode > AttachColorStroke(const skjson::ObjectValue &, const AnimationBuilder *)
Definition: FillStroke.cpp:173
static sk_sp< sksg::PaintNode > AttachColorFill(const skjson::ObjectValue &, const AnimationBuilder *)
Definition: FillStroke.cpp:165
static std::vector< sk_sp< sksg::GeometryNode > > AdjustStrokeGeometry(const skjson::ObjectValue &, const AnimationBuilder *, std::vector< sk_sp< sksg::GeometryNode > > &&)
Definition: FillStroke.cpp:181
static sk_sp< Color > Make(SkColor c)
Definition: SkSGPaint.cpp:44
uint32_t * target
SK_API sk_sp< SkDocument > Make(SkWStream *dst, const SkSerialProcs *=nullptr, std::function< void(const SkPicture *)> onEndPage=nullptr)
@ kStroke
strokes boundary of shapes
@ kFill
fills interior of shapes
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition: switches.h:259
@ kColor
hue and saturation of source with luminosity of destination
SkScalar ScalarValue
Definition: SkottieValue.h:22
Definition: Skottie.h:32
Definition: ref_ptr.h:256