[svg] Cleanup text content model rules

Per spec (and empirically) <text> elements are not nestable (neither
directly or indirectly):
https://www.w3.org/TR/SVG11/intro.html#TermTextContentChildElement

Update the implementation to

 - only bridge onRender -> onRenderText in the root SkSVGText
   implementation
 - disallow <text> elements as text container descendants

Change-Id: I07b3abaf943b820e01c88f78bddf7ce5970ee508
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/358220
Commit-Queue: Florin Malita <fmalita@google.com>
Reviewed-by: Tyler Denniston <tdenniston@google.com>
This commit is contained in:
Florin Malita 2021-01-24 12:04:17 -05:00 committed by Skia Commit-Bot
parent fe8a4faa4b
commit 302ea2e03c
2 changed files with 10 additions and 19 deletions

View File

@ -26,6 +26,9 @@ protected:
virtual void onRenderText(const SkSVGRenderContext&, SkSVGTextContext*,
SkSVGXmlSpace) const = 0;
// Text nodes other than the root <text> element are not rendered directly.
void onRender(const SkSVGRenderContext&) const override {}
private:
SkPath onAsPath(const SkSVGRenderContext&) const final;
@ -53,8 +56,6 @@ protected:
bool parseAndSetAttribute(const char*, const char*) override;
private:
void onRender(const SkSVGRenderContext&) const final;
std::vector<sk_sp<SkSVGTextFragment>> fChildren;
using INHERITED = SkSVGTextFragment;
@ -67,7 +68,7 @@ public:
private:
SkSVGText() : INHERITED(SkSVGTag::kText) {}
void onRenderText(const SkSVGRenderContext&, SkSVGTextContext*, SkSVGXmlSpace) const override;
void onRender(const SkSVGRenderContext&) const override;
using INHERITED = SkSVGTextContainer;
};
@ -93,7 +94,6 @@ public:
private:
SkSVGTextLiteral() : INHERITED(SkSVGTag::kTextLiteral) {}
void onRender(const SkSVGRenderContext&) const override {}
void onRenderText(const SkSVGRenderContext&, SkSVGTextContext*, SkSVGXmlSpace) const override;
void appendChild(sk_sp<SkSVGNode>) override {}

View File

@ -490,9 +490,8 @@ SkPath SkSVGTextFragment::onAsPath(const SkSVGRenderContext&) const {
}
void SkSVGTextContainer::appendChild(sk_sp<SkSVGNode> child) {
// Only allow text nodes.
// Only allow text content child nodes.
switch (child->tag()) {
case SkSVGTag::kText:
case SkSVGTag::kTextLiteral:
case SkSVGTag::kTextPath:
case SkSVGTag::kTSpan:
@ -506,10 +505,7 @@ void SkSVGTextContainer::appendChild(sk_sp<SkSVGNode> child) {
void SkSVGTextContainer::onRenderText(const SkSVGRenderContext& ctx, SkSVGTextContext* tctx,
SkSVGXmlSpace) const {
if (!tctx) {
// No text context => missing top-level <text> node.
return;
}
SkASSERT(tctx);
const SkSVGTextContext::ScopedPosResolver resolver(*this, ctx.lengthContext(), tctx);
@ -542,10 +538,6 @@ bool SkSVGTextContainer::parseAndSetAttribute(const char* name, const char* valu
this->setXmlSpace(SkSVGAttributeParser::parse<SkSVGXmlSpace>("xml:space", name, value));
}
void SkSVGTextContainer::onRender(const SkSVGRenderContext& ctx) const {
this->onRenderText(ctx, nullptr, this->getXmlSpace());
}
void SkSVGTextLiteral::onRenderText(const SkSVGRenderContext& ctx, SkSVGTextContext* tctx,
SkSVGXmlSpace xs) const {
SkASSERT(tctx);
@ -553,17 +545,16 @@ void SkSVGTextLiteral::onRenderText(const SkSVGRenderContext& ctx, SkSVGTextCont
tctx->appendFragment(this->getText(), ctx, xs);
}
void SkSVGText::onRenderText(const SkSVGRenderContext& ctx, SkSVGTextContext*,
SkSVGXmlSpace xs) const {
// Root text nodes establish a new text layout context.
void SkSVGText::onRender(const SkSVGRenderContext& ctx) const {
// Root <text> nodes establish a text layout context.
SkSVGTextContext tctx(ctx);
this->INHERITED::onRenderText(ctx, &tctx, xs);
this->onRenderText(ctx, &tctx, this->getXmlSpace());
}
void SkSVGTextPath::onRenderText(const SkSVGRenderContext& ctx, SkSVGTextContext*,
SkSVGXmlSpace xs) const {
// Root text nodes establish a new text layout context.
// textPath nodes establish a new text layout context.
SkSVGTextContext tctx(ctx, this);
this->INHERITED::onRenderText(ctx, &tctx, xs);