[svg] Text asPath() support

Enables use of text as a clip path.

Bug: skia:10840
Change-Id: I9de40e23696083e8cdd7e0b82221da3f3c36ac8b
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/358533
Reviewed-by: Tyler Denniston <tdenniston@google.com>
Commit-Queue: Florin Malita <fmalita@google.com>
This commit is contained in:
Florin Malita 2021-01-26 08:49:10 -05:00 committed by Skia Commit-Bot
parent 233de6d8cd
commit f661ec788b
2 changed files with 50 additions and 1 deletions

View File

@ -29,7 +29,7 @@ protected:
void onRender(const SkSVGRenderContext&) const override {}
private:
SkPath onAsPath(const SkSVGRenderContext&) const final;
SkPath onAsPath(const SkSVGRenderContext&) const override;
using INHERITED = SkSVGTransformableNode;
};
@ -70,6 +70,7 @@ private:
void onRender(const SkSVGRenderContext&) const override;
SkRect onObjectBoundingBox(const SkSVGRenderContext&) const override;
SkPath onAsPath(const SkSVGRenderContext&) const override;
using INHERITED = SkSVGTextContainer;
};

View File

@ -14,6 +14,7 @@
#include "include/core/SkFont.h"
#include "include/core/SkFontMgr.h"
#include "include/core/SkFontStyle.h"
#include "include/core/SkPathBuilder.h"
#include "include/core/SkRSXform.h"
#include "include/core/SkString.h"
#include "modules/skshaper/include/SkShaper.h"
@ -594,6 +595,53 @@ SkRect SkSVGText::onObjectBoundingBox(const SkSVGRenderContext& ctx) const {
return bounds;
}
SkPath SkSVGText::onAsPath(const SkSVGRenderContext& ctx) const {
SkPathBuilder builder;
const SkSVGTextContext::ShapedTextCallback as_path =
[&builder](const SkSVGRenderContext& ctx, const sk_sp<SkTextBlob>& blob, const SkPaint*,
const SkPaint*) {
if (!blob) {
return;
}
SkTextBlobRunIterator it(blob.get());
for (SkTextBlobRunIterator it(blob.get()); !it.done(); it.next()) {
struct GetPathsCtx {
SkPathBuilder& builder;
const SkRSXform* xform;
} get_paths_ctx {builder, it.xforms()};
it.font().getPaths(it.glyphs(), it.glyphCount(), [](const SkPath* path,
const SkMatrix& matrix,
void* raw_ctx) {
auto* get_paths_ctx = static_cast<GetPathsCtx*>(raw_ctx);
const auto& glyph_rsx = *get_paths_ctx->xform++;
if (!path) {
return;
}
SkMatrix glyph_matrix;
glyph_matrix.setRSXform(glyph_rsx);
glyph_matrix.preConcat(matrix);
get_paths_ctx->builder.addPath(path->makeTransform(glyph_matrix));
}, &get_paths_ctx);
}
};
{
SkSVGTextContext tctx(ctx, as_path);
this->onShapeText(ctx, &tctx, this->getXmlSpace());
}
auto path = builder.detach();
this->mapToParent(&path);
return path;
}
void SkSVGTextPath::onShapeText(const SkSVGRenderContext& ctx, SkSVGTextContext* parent_tctx,
SkSVGXmlSpace xs) const {
SkASSERT(parent_tctx);