86 font.setSubpixel(
true);
87 font.setLinearMetrics(
true);
88 font.setBaselineSnap(
false);
95 const std::vector<SkSVGLength>& lengths,
97 std::vector<float> resolved;
98 resolved.reserve(lengths.size());
100 for (
const auto& l : lengths) {
101 resolved.push_back(lctx.
resolve(l, lt));
124 size_t charIndexOffset)
126 , fParent(tctx->fPosResolver)
127 , fCharIndexOffset(charIndexOffset)
132 , fRotate(
txt.getRotate())
134 fTextContext->fPosResolver =
this;
143 fTextContext->fPosResolver = fParent;
149 if (charIndex < fLastPosIndex) {
150 SkASSERT(charIndex >= fCharIndexOffset);
151 const auto localCharIndex = charIndex - fCharIndexOffset;
153 const auto hasAllLocal = localCharIndex < fX.size() &&
154 localCharIndex < fY.size() &&
155 localCharIndex < fDx.size() &&
156 localCharIndex < fDy.size() &&
157 localCharIndex < fRotate.size();
158 if (!hasAllLocal && fParent) {
159 attrs = fParent->resolve(charIndex);
162 if (localCharIndex < fX.size()) {
165 if (localCharIndex < fY.size()) {
168 if (localCharIndex < fDx.size()) {
171 if (localCharIndex < fDy.size()) {
188 if (!fRotate.empty()) {
189 if (localCharIndex < fRotate.size()) {
204 fLastPosIndex = charIndex;
211void SkSVGTextContext::ShapeBuffer::append(
SkUnichar ch, PositionAdjustment
pos) {
213 if (!fUtf8PosAdjust.empty()) {
214 pos.
offset += fUtf8PosAdjust.back().offset;
219 fUtf8 .push_back_n(utf8_len, utf8_buf);
220 fUtf8PosAdjust.push_back_n(utf8_len,
pos);
224 const char*
utf8 = fShapeBuffer.fUtf8.data();
225 size_t utf8Bytes = fShapeBuffer.fUtf8.size();
227 std::unique_ptr<SkShaper::FontRunIterator> font_runs =
232 if (!fForcePrimitiveShaping) {
234 const uint8_t defaultLTR = 0;
235 std::unique_ptr<SkShaper::BiDiRunIterator> bidi =
237 std::unique_ptr<SkShaper::LanguageRunIterator> language =
241 if (bidi && script && language) {
252 fShapeBuffer.reset();
271 fShapeBuffer.reset();
277 : fRenderContext(ctx)
279 , fShaper(ctx.makeShaper())
280 , fChunkAlignmentFactor(ComputeAlignmentFactor(ctx.presentationContext())) {
284 fShaper = SkShapers::Primitive::PrimitiveText();
285 fForcePrimitiveShaping =
true;
288 fPathData = std::make_unique<PathData>(ctx, *tpath);
302 return offset.value() * fPathData->length() / 100;
306 fChunkPos.
fX = resolve_offset(tpath->getStartOffset());
331 if (fPrevCharSpace && ch ==
' ') {
342 if (ch ==
'\n' || ch ==
'\t') {
352 const auto font = ResolveFont(ctx);
353 fShapeBuffer.reserve(
txt.size());
355 const char* ch_ptr =
txt.c_str();
356 const char* ch_end = ch_ptr +
txt.size();
358 while (ch_ptr < ch_end) {
361 ? filterWSDefault(ch)
362 : filterWSPreserve(ch);
370 const auto pos = fPosResolver->
resolve(fCurrentCharIndex++);
375 this->shapePendingBuffer(ctx, font);
387 fShapeBuffer.append(ch, {
395 fPrevCharSpace = (ch ==
' ');
398 this->shapePendingBuffer(ctx, font);
414 fContours.push_back(std::move(
contour));
418SkMatrix SkSVGTextContext::PathData::getMatrixAt(
float offset)
const {
420 for (
const auto&
contour : fContours) {
421 const auto contour_len =
contour->length();
422 if (
offset < contour_len) {
432 std::numeric_limits<float>::infinity());
437 const PositionAdjustment& pos_adjust)
const {
438 SkPoint pos = fChunkPos + glyph_pos + pos_adjust.
offset + fChunkAdvance * fChunkAlignmentFactor;
448 font.getWidths(&glyph, 1, &glyph_width);
449 auto path_offset =
pos.
fX + glyph_width * .5f;
456 const auto m = fPathData->getMatrixAt(path_offset) *
466 for (
const auto&
run : fRuns) {
468 std::copy(
run.glyphs.get(),
run.glyphs.get() +
run.glyphCount, buf.glyphs);
469 for (
size_t i = 0; i <
run.glyphCount; ++i) {
470 buf.xforms()[i] = this->computeGlyphXform(
run.glyphs[i],
473 run.glyhPosAdjust[i]);
476 fCallback(ctx, blobBuilder.
make(),
run.fillPaint.get(),
run.strokePaint.get());
479 fChunkPos += fChunkAdvance;
480 fChunkAdvance = {0,0};
491 fCurrentFill.
isValid() ? std::make_unique<SkPaint>(*fCurrentFill) :
nullptr,
492 fCurrentStroke.
isValid() ? std::make_unique<SkPaint>(*fCurrentStroke) :
nullptr,
493 std::make_unique<SkGlyphID[] >(ri.
glyphCount),
495 std::make_unique<PositionAdjustment[]>(ri.
glyphCount),
501 fShapeClusterBuffer.resize(std::max(fShapeClusterBuffer.size(), ri.
glyphCount));
504 fRuns.back().glyphs.get(),
505 fRuns.back().glyphPos.get(),
507 fShapeClusterBuffer.data(),
513 const auto& current_run = fRuns.back();
517 const auto utf8_index = fShapeClusterBuffer[i];
518 current_run.glyhPosAdjust[i] = fShapeBuffer.fUtf8PosAdjust[
SkToInt(utf8_index)];
525 if (!fShapeBuffer.fUtf8PosAdjust.empty()) {
527 fChunkAdvance += fShapeBuffer.fUtf8PosAdjust.back().offset;
549 switch (child->tag()) {
567 for (
const auto& frag : fChildren) {
569 frag->renderText(ctx, tctx, this->getXmlSpace());
576 static constexpr std::tuple<const char*, SkSVGXmlSpace> gXmlSpaceMap[] = {
581 return this->parseEnumMap(gXmlSpaceMap, xs) && this->parseEOSToken();
593 this->setXmlSpace(SkSVGAttributeParser::parse<SkSVGXmlSpace>(
"xml:space",
name,
value));
619 this->
onShapeText(ctx, &tctx, this->getXmlSpace());
636 it.font().getBounds(it.glyphs(), it.glyphCount(), glyphBounds.
get(),
nullptr);
640 for (uint32_t i = 0; i < it.glyphCount(); ++i) {
641 m.setRSXform(it.xforms()[i]);
642 bounds.join(m.mapRect(glyphBounds[i]));
649 this->
onShapeText(ctx, &tctx, this->getXmlSpace());
669 } get_paths_ctx {builder, it.xforms()};
671 it.font().getPaths(it.glyphs(), it.glyphCount(), [](
const SkPath* path,
674 auto* get_paths_ctx =
static_cast<GetPathsCtx*
>(raw_ctx);
675 const auto& glyph_rsx = *get_paths_ctx->xform++;
685 get_paths_ctx->builder.addPath(path->makeTransform(glyph_matrix));
692 this->
onShapeText(ctx, &tctx, this->getXmlSpace());
695 auto path = builder.detach();
713 this->setHref(SkSVGAttributeParser::parse<SkSVGIRI>(
"xlink:href",
name,
value)) ||
714 this->setStartOffset(SkSVGAttributeParser::parse<SkSVGLength>(
"startOffset",
name,
value));
@ kNone
glyph outlines unchanged
#define SkDegreesToRadians(degrees)
constexpr int SkToInt(S x)
void drawTextBlob(const SkTextBlob *blob, SkScalar x, SkScalar y, const SkPaint &paint)
sk_sp< SkTypeface > legacyMakeTypeface(const char familyName[], SkFontStyle style) const
@ kAntiAlias
may have transparent pixels on glyph edges
static SkMatrix RotateRad(SkScalar rad)
static SkMatrix Translate(SkScalar dx, SkScalar dy)
SkMatrix & setRSXform(const SkRSXform &rsxForm)
static const SkMatrix & I()
SkMatrix & preConcat(const SkMatrix &other)
bool parse(SkSVGIntegerType *v)
const SkString & family() const
const SkSVGLength & size() const
SkScalar resolve(const SkSVGLength &, LengthType) const
virtual bool parseAndSetAttribute(const char *name, const char *value)
SkTLazy< SkPaint > fillPaint() const
BorrowedNode findNodeById(const SkSVGIRI &) const
sk_sp< SkFontMgr > fontMgr() const
const SkSVGPresentationContext & presentationContext() const
std::unique_ptr< SkShaper::ScriptRunIterator > makeScriptRunIterator(const char *utf8, size_t utf8Bytes) const
std::unique_ptr< SkShaper::BiDiRunIterator > makeBidiRunIterator(const char *utf8, size_t utf8Bytes, uint8_t bidiLevel) const
SkCanvas * canvas() const
const SkSVGLengthContext & lengthContext() const
SkTLazy< SkPaint > strokePaint() const
void onShapeText(const SkSVGRenderContext &, SkSVGTextContext *, SkSVGXmlSpace) const override
void appendChild(sk_sp< SkSVGNode >) final
bool parseAndSetAttribute(const char *, const char *) override
void setImplicitRotate(bool imp)
bool isImplicitRotate() const
ScopedPosResolver(const SkSVGTextContainer &, const SkSVGLengthContext &, SkSVGTextContext *, size_t)
PosAttrs resolve(size_t charIndex) const
const ShapedTextCallback & getCallback() const
void commitRunBuffer(const RunInfo &ri) override
Buffer runBuffer(const RunInfo &ri) override
void flushChunk(const SkSVGRenderContext &ctx)
void shapeFragment(const SkString &, const SkSVGRenderContext &, SkSVGXmlSpace)
std::function< void(const SkSVGRenderContext &, const sk_sp< SkTextBlob > &, const SkPaint *, const SkPaint *)> ShapedTextCallback
SkSVGTextContext(const SkSVGRenderContext &, const ShapedTextCallback &, const SkSVGTextPath *=nullptr)
void commitLine() override
~SkSVGTextContext() override
SkPath onAsPath(const SkSVGRenderContext &) const override
void renderText(const SkSVGRenderContext &, SkSVGTextContext *, SkSVGXmlSpace) const
virtual void onShapeText(const SkSVGRenderContext &, SkSVGTextContext *, SkSVGXmlSpace) const =0
void onShapeText(const SkSVGRenderContext &, SkSVGTextContext *, SkSVGXmlSpace) const override
void onShapeText(const SkSVGRenderContext &, SkSVGTextContext *, SkSVGXmlSpace) const override
bool parseAndSetAttribute(const char *, const char *) override
void onRender(const SkSVGRenderContext &) const override
SkRect onObjectBoundingBox(const SkSVGRenderContext &) const override
SkPath onAsPath(const SkSVGRenderContext &) const override
static std::unique_ptr< FontRunIterator > MakeFontMgrRunIterator(const char *utf8, size_t utf8Bytes, const SkFont &font, sk_sp< SkFontMgr > fallback)
static std::unique_ptr< LanguageRunIterator > MakeStdLanguageRunIterator(const char *utf8, size_t utf8Bytes)
const RunBuffer & allocRunRSXform(const SkFont &font, int count)
sk_sp< SkTextBlob > make()
SK_SPI size_t ToUTF8(SkUnichar uni, char utf8[kMaxBytesInUTF8Sequence]=nullptr)
constexpr unsigned kMaxBytesInUTF8Sequence
SK_SPI SkUnichar NextUTF8(const char **ptr, const char *end)
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
font
Font Metadata and Metrics.
void offset(float dx, float dy)
static constexpr SkRect MakeEmpty()
SkSVGProperty< SkSVGFontSize, true > fFontSize
SkSVGProperty< SkSVGFontFamily, true > fFontFamily
SkSVGProperty< SkSVGFontWeight, true > fFontWeight
SkSVGProperty< SkSVGTextAnchor, true > fTextAnchor
SkSVGProperty< SkSVGFontStyle, true > fFontStyle
SkSVGPresentationAttributes fInherited