Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
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:
36 using ShapedTextCallback = std::function<void(const SkSVGRenderContext&,
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]
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
void setImplicitRotate(bool imp)
float operator[](Attr a) const
bool has(Attr a) const
PosAttrs resolve(size_t charIndex) const
const ShapedTextCallback & getCallback() const
void commitRunBuffer(const RunInfo &ri) override
Buffer runBuffer(const RunInfo &ri) override
void beginLine() override
void flushChunk(const SkSVGRenderContext &ctx)
void shapeFragment(const SkString &, const SkSVGRenderContext &, SkSVGXmlSpace)
void runInfo(const RunInfo &) override
std::function< void(const SkSVGRenderContext &, const sk_sp< SkTextBlob > &, const SkPaint *, const SkPaint *)> ShapedTextCallback
void commitRunInfo() override
void commitLine() override
~SkSVGTextContext() override
int size() const
Definition SkTArray.h:416
void reserve_exact(int n)
Definition SkTArray.h:176
struct MyStruct a[10]
size_t length
font
Font Metadata and Metrics.
Point offset