21#include <initializer_list>
36 , fScaledRotations{scaledRotations}
40 : fSource{that.fSource}
42 , fClusters{that.fClusters}
51 : fGlyphRuns{glyphRunList}
52 , fOriginalTextBlob{blob}
53 , fSourceBounds{bounds}
55 , fBuilder{builder} {}
62 , fOriginalTextBlob{
nullptr}
67uint64_t GlyphRunList::uniqueID()
const {
68 return fOriginalTextBlob !=
nullptr ? fOriginalTextBlob->uniqueID()
72bool GlyphRunList::anyRunsLCD()
const {
73 for (
const auto& r : fGlyphRuns) {
81void GlyphRunList::temporaryShuntBlobNotifyAddedToCache(uint32_t cacheID,
82 SkTextBlob::PurgeDelegate pd)
const {
83 SkASSERT(fOriginalTextBlob !=
nullptr);
85 fOriginalTextBlob->notifyAddedToCache(cacheID, pd);
90 for (
auto&
run : *
this) {
92 if (
run.scaledRotations().empty()) {
93 if (
run.text().empty()) {
94 buffer = builder.allocRunPos(
run.font(),
run.runSize(),
nullptr);
96 buffer = builder.allocRunTextPos(
run.font(),
run.runSize(),
run.text().size(),
nullptr);
99 auto clusters =
run.clusters();
100 memcpy(
buffer.clusters, clusters.data(), clusters.size_bytes());
102 auto positions =
run.positions();
103 memcpy(
buffer.points(), positions.data(), positions.size_bytes());
105 buffer = builder.allocRunRSXform(
run.font(),
run.runSize());
108 run.scaledRotations())) {
112 auto glyphIDs =
run.glyphsIDs();
113 memcpy(
buffer.glyphs, glyphIDs.data(), glyphIDs.size_bytes());
115 return builder.make();
136 if (scaledRotations.
empty()) {
138 auto scaleAndTranslateRect =
149 bounds.join(scaleAndTranslateRect(r,
pos));
156 for (
auto [
pos, scaleRotate, glyph] :
SkMakeZip(positions, scaledRotations,
glyphs)) {
157 if (!glyph->rect().isEmpty()) {
160 xform.
preScale(strikeToSourceScale, strikeToSourceScale);
161 bounds.join(xform.
mapRect(glyph->rect()));
169 if (scaledRotations.
empty()) {
171 bounds.setBounds(positions.
data(),
SkCount(positions));
172 bounds.fLeft += fontBounds.
left();
173 bounds.fTop += fontBounds.
top();
174 bounds.fRight += fontBounds.
right();
175 bounds.fBottom += fontBounds.
bottom();
181 for (
auto [
pos, scaleRotate] :
SkMakeZip(positions, scaledRotations)) {
200 auto glyphs = storage.glyphs(glyphIDs);
203 SkPoint endOfLastGlyph = origin;
204 for (
auto glyph :
glyphs) {
205 *positionCursor++ = endOfLastGlyph;
206 endOfLastGlyph += glyph->advanceVector();
213 const void* bytes,
size_t byteLength,
SkPoint origin,
215 auto glyphIDs = textToGlyphIDs(font, bytes, byteLength, encoding);
217 this->prepareBuffers(glyphIDs.size(), 0);
218 if (!glyphIDs.empty()) {
220 this->makeGlyphRun(font,
226 auto run = fGlyphRunListStorage.front();
230 return this->setGlyphRunList(
nullptr, bounds, origin);
236 this->initialize(blob);
238 SkPoint* positionCursor = fPositions;
239 SkVector* scaledRotationsCursor = fScaledRotations;
241 size_t runSize = it.glyphCount();
247 const SkFont& font = it.font();
252 switch (it.positioning()) {
255 positionCursor += positions.
size();
259 positions =
SkSpan(positionCursor, runSize);
266 positions =
SkSpan(it.points(), runSize);
270 positions =
SkSpan(positionCursor, runSize);
271 scaledRotations =
SkSpan(scaledRotationsCursor, runSize);
273 *positionCursor++ = {xform.fTx, xform.fTy};
274 *scaledRotationsCursor++ = {xform.fSCos, xform.fSSin};
280 const uint32_t* clusters = it.clusters();
290 return this->setGlyphRunList(&blob, blob.
bounds(), origin);
298 auto scaledRotations =
SkSpan(fScaledRotations.get(),
count);
299 for (
auto [
pos, sr, xform] :
SkMakeZip(positions, scaledRotations, xforms)) {
300 auto [scos, ssin, tx, ty] = xform;
304 return {positions, scaledRotations};
307void GlyphRunBuilder::initialize(
const SkTextBlob& blob) {
308 int positionCount = 0;
309 int rsxFormCount = 0;
312 positionCount += it.glyphCount();
315 rsxFormCount += it.glyphCount();
319 prepareBuffers(positionCount, rsxFormCount);
322void GlyphRunBuilder::prepareBuffers(
int positionCount,
int RSXFormCount) {
323 if (positionCount > fMaxTotalRunSize) {
324 fMaxTotalRunSize = positionCount;
325 fPositions.
reset(fMaxTotalRunSize);
328 if (RSXFormCount > fMaxScaledRotations) {
329 fMaxScaledRotations = RSXFormCount;
330 fScaledRotations.reset(RSXFormCount);
333 fGlyphRunListStorage.clear();
339 int count =
font.countText(bytes, byteLength, encoding);
341 fScratchGlyphIDs.resize(
count);
342 font.textToGlyphs(bytes, byteLength, encoding, fScratchGlyphIDs.data(),
count);
343 return SkSpan(fScratchGlyphIDs);
352void GlyphRunBuilder::makeGlyphRun(
361 if (!glyphIDs.
empty()) {
362 fGlyphRunListStorage.emplace_back(
372const GlyphRunList& sktext::GlyphRunBuilder::setGlyphRunList(
374 fGlyphRunList.emplace(blob, bounds, origin,
SkSpan(fGlyphRunListStorage),
this);
375 return fGlyphRunList.value();
@ kGlyphID
uses two byte words to represent glyph indices
constexpr int SkCount(const Container &c)
static constexpr uint32_t SK_InvalidUniqueID
constexpr auto SkMakeZip(Ts &&... ts)
static bool IsFinite(const SkFont &font)
static SkRect GetFontBounds(const SkFont &)
@ kSubpixelAntiAlias
glyph positioned in pixel using transparency
SkMatrix & setRSXform(const SkRSXform &rsxForm)
SkMatrix & preScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py)
bool mapRect(SkRect *dst, const SkRect &src, SkApplyPerspectiveClip pc=SkApplyPerspectiveClip::kYes) const
constexpr T * data() const
constexpr bool empty() const
constexpr size_t size() const
static SkStrikeSpec MakeWithNoDevice(const SkFont &font, const SkPaint *paint=nullptr)
static std::tuple< SkStrikeSpec, SkScalar > MakeCanonicalized(const SkFont &font, const SkPaint *paint=nullptr)
@ kHorizontal_Positioning
const SkRect & bounds() const
T * reset(size_t count=0)
std::tuple< SkSpan< const SkPoint >, SkSpan< const SkVector > > convertRSXForm(SkSpan< const SkRSXform > xforms)
const GlyphRunList & blobToGlyphRunList(const SkTextBlob &blob, SkPoint origin)
GlyphRunList(const SkTextBlob *blob, SkRect bounds, SkPoint origin, SkSpan< const GlyphRun > glyphRunList, GlyphRunBuilder *builder)
GlyphRun(const SkFont &font, SkSpan< const SkPoint > positions, SkSpan< const SkGlyphID > glyphIDs, SkSpan< const char > text, SkSpan< const uint32_t > clusters, SkSpan< const SkVector > scaledRotations)
static const uint8_t buffer[]
Optional< SkRect > bounds
font
Font Metadata and Metrics.
static SkRect glyphrun_source_bounds(const SkFont &font, const SkPaint &paint, SkZip< const SkGlyphID, const SkPoint > source, SkSpan< const SkVector > scaledRotations)
static SkSpan< const SkPoint > draw_text_positions(const SkFont &font, SkSpan< const SkGlyphID > glyphIDs, SkPoint origin, SkPoint *buffer)
static constexpr SkPoint Make(float x, float y)
constexpr float y() const
constexpr float x() const
static constexpr SkRect MakeEmpty()
constexpr float left() const
constexpr float top() const
constexpr float right() const
static constexpr SkRect MakeLTRB(float l, float t, float r, float b)
constexpr float bottom() const