Flutter Engine
The Flutter Engine
SkSVGTextPriv.h
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
8#ifndef SkSVGTextPriv_DEFINED
9#define SkSVGTextPriv_DEFINED
10
15#include "src/base/SkTLazy.h"
16
17#include <functional>
18#include <tuple>
19
21struct SkRSXform;
22
23// SkSVGTextContext is responsible for sequencing input text chars into "chunks".
24// A single text chunk can span multiple structural elements (<text>, <tspan>, etc),
25// and per [1] new chunks are emitted
26//
27// a) for each top level text element (<text>, <textPath>)
28// b) whenever a character with an explicit absolute position is encountered
29//
30// The implementation queues shaped run data until a full text chunk is resolved, at which
31// point we have enough information to perform final alignment and rendering.
32//
33// [1] https://www.w3.org/TR/SVG11/text.html#TextLayoutIntroduction
35public:
37 const sk_sp<SkTextBlob>&,
38 const SkPaint*,
39 const SkPaint*)>;
40
41 // Helper for encoding optional positional attributes.
42 class PosAttrs {
43 public:
44 // TODO: rotate
45 enum Attr : size_t {
46 kX = 0,
47 kY = 1,
48 kDx = 2,
49 kDy = 3,
51 };
52
53 float operator[](Attr a) const { return fStorage[a]; }
54 float& operator[](Attr a) { return fStorage[a]; }
55
56 bool has(Attr a) const { return fStorage[a] != kNone; }
57 bool hasAny() const {
58 return this->has(kX)
59 || this->has(kY)
60 || this->has(kDx)
61 || this->has(kDy)
62 || this->has(kRotate);
63 }
64
65 void setImplicitRotate(bool imp) { fImplicitRotate = imp; }
66 bool isImplicitRotate() const { return fImplicitRotate; }
67
68 private:
69 inline static constexpr auto kNone = std::numeric_limits<float>::infinity();
70
71 float fStorage[5] = { kNone, kNone, kNone, kNone, kNone };
72 bool fImplicitRotate = false;
73 };
74
75 // Helper for cascading position attribute resolution (x, y, dx, dy, rotate) [1]:
76 // - each text position element can specify an arbitrary-length attribute array
77 // - for each character, we look up a given attribute first in its local attribute array,
78 // then in the ancestor chain (cascading/fallback) - and return the first value encountered.
79 // - the lookup is based on character index relative to the text content subtree
80 // (i.e. the index crosses chunk boundaries)
81 //
82 // [1] https://www.w3.org/TR/SVG11/text.html#TSpanElementXAttribute
84 public:
86 size_t);
87
89
91
92 PosAttrs resolve(size_t charIndex) const;
93
94 private:
95 SkSVGTextContext* fTextContext;
96 const ScopedPosResolver* fParent; // parent resolver (fallback)
97 const size_t fCharIndexOffset; // start index for the current resolver
98 const std::vector<float> fX,
99 fY,
100 fDx,
101 fDy;
102 const std::vector<float>& fRotate;
103
104 // cache for the last known index with explicit positioning
105 mutable size_t fLastPosIndex = std::numeric_limits<size_t>::max();
106
107 };
108
110 const ShapedTextCallback&,
111 const SkSVGTextPath* = nullptr);
112 ~SkSVGTextContext() override;
113
114 // Shape and queue codepoints for final alignment.
116
117 // Perform final adjustments and push shaped blobs to the callback.
118 void flushChunk(const SkSVGRenderContext& ctx);
119
120 const ShapedTextCallback& getCallback() const { return fCallback; }
121
122private:
123 struct PositionAdjustment {
125 float rotation;
126 };
127
128 struct ShapeBuffer {
130 // per-utf8-char cumulative pos adjustments
132
133 void reserve(size_t size) {
134 fUtf8.reserve_exact(fUtf8.size() + SkToInt(size));
135 fUtf8PosAdjust.reserve_exact(fUtf8PosAdjust.size() + SkToInt(size));
136 }
137
138 void reset() {
139 fUtf8.clear();
140 fUtf8PosAdjust.clear();
141 }
142
143 void append(SkUnichar, PositionAdjustment);
144 };
145
146 struct RunRec {
147 SkFont font;
148 std::unique_ptr<SkPaint> fillPaint,
149 strokePaint;
150 std::unique_ptr<SkGlyphID[]> glyphs; // filled by SkShaper
151 std::unique_ptr<SkPoint[]> glyphPos; // filled by SkShaper
152 std::unique_ptr<PositionAdjustment[]> glyhPosAdjust; // deferred positioning adjustments
153 size_t glyphCount;
154 SkVector advance;
155 };
156
157 // Caches path information to accelerate position lookups.
158 class PathData {
159 public:
160 PathData(const SkSVGRenderContext&, const SkSVGTextPath&);
161
162 SkMatrix getMatrixAt(float offset) const;
163
164 float length() const { return fLength; }
165
166 private:
167 std::vector<sk_sp<SkContourMeasure>> fContours;
168 float fLength = 0; // total path length
169 };
170
171 void shapePendingBuffer(const SkSVGRenderContext&, const SkFont&);
172
173 SkRSXform computeGlyphXform(SkGlyphID, const SkFont&, const SkPoint& glyph_pos,
174 const PositionAdjustment&) const;
175
176 // SkShaper callbacks
177 void beginLine() override {}
178 void runInfo(const RunInfo&) override {}
179 void commitRunInfo() override {}
180 Buffer runBuffer(const RunInfo& ri) override;
181 void commitRunBuffer(const RunInfo& ri) override;
182 void commitLine() override;
183
184 // http://www.w3.org/TR/SVG11/text.html#TextLayout
185 const SkSVGRenderContext& fRenderContext; // original render context
186 const ShapedTextCallback& fCallback;
187 std::unique_ptr<SkShaper> fShaper;
188 std::vector<RunRec> fRuns;
189 const ScopedPosResolver* fPosResolver = nullptr;
190 std::unique_ptr<PathData> fPathData;
191
192 // shaper state
193 ShapeBuffer fShapeBuffer;
194 std::vector<uint32_t> fShapeClusterBuffer;
195
196 // chunk state
197 SkPoint fChunkPos = {0,0}; // current text chunk position
198 SkVector fChunkAdvance = {0,0}; // cumulative advance
199 float fChunkAlignmentFactor; // current chunk alignment
200
201 // tracks the global text subtree char index (cross chunks). Used for position resolution.
202 size_t fCurrentCharIndex = 0;
203
204 // cached for access from SkShaper callbacks.
205 SkTLazy<SkPaint> fCurrentFill;
206 SkTLazy<SkPaint> fCurrentStroke;
207
208 bool fPrevCharSpace = true; // WS filter state
209 bool fForcePrimitiveShaping = false;
210};
211
212#endif // SkSVGTextPriv_DEFINED
m reset()
uint16_t glyphs[5]
Definition: FontMgrTest.cpp:46
SkSVGXmlSpace
Definition: SkSVGTypes.h:714
constexpr int SkToInt(S x)
Definition: SkTo.h:29
int32_t SkUnichar
Definition: SkTypes.h:175
uint16_t SkGlyphID
Definition: SkTypes.h:179
Definition: SkFont.h:35
float & operator[](Attr a)
Definition: SkSVGTextPriv.h:54
void setImplicitRotate(bool imp)
Definition: SkSVGTextPriv.h:65
float operator[](Attr a) const
Definition: SkSVGTextPriv.h:53
bool has(Attr a) const
Definition: SkSVGTextPriv.h:56
ScopedPosResolver(const SkSVGTextContainer &, const SkSVGLengthContext &, SkSVGTextContext *, size_t)
Definition: SkSVGText.cpp:121
PosAttrs resolve(size_t charIndex) const
Definition: SkSVGText.cpp:146
const ShapedTextCallback & getCallback() const
void flushChunk(const SkSVGRenderContext &ctx)
Definition: SkSVGText.cpp:463
void shapeFragment(const SkString &, const SkSVGRenderContext &, SkSVGXmlSpace)
Definition: SkSVGText.cpp:314
std::function< void(const SkSVGRenderContext &, const sk_sp< SkTextBlob > &, const SkPaint *, const SkPaint *)> ShapedTextCallback
Definition: SkSVGTextPriv.h:39
SkSVGTextContext(const SkSVGRenderContext &, const ShapedTextCallback &, const SkSVGTextPath *=nullptr)
Definition: SkSVGText.cpp:274
~SkSVGTextContext() override
Definition: SkSVGText.cpp:310
int size() const
Definition: SkTArray.h:421
void reserve_exact(int n)
Definition: SkTArray.h:181
static void append(char **dst, size_t *count, const char *src, size_t n)
Definition: editor.cpp:211
struct MyStruct a[10]
Dart_NativeFunction function
Definition: fuchsia.cc:51
static float max(float r, float g, float b)
Definition: hsl.cpp:49
size_t length
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
font
Font Metadata and Metrics.
SeparatedVector2 offset