[svg] Refactor SkSVGImage to expose image loading

This is in preparation for reusing the image loading + aspect ratio
mapping for <feImage>.

Change-Id: I53dcf904476aae386f672488379201524855a703
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/404217
Reviewed-by: Florin Malita <fmalita@chromium.org>
Commit-Queue: Tyler Denniston <tdenniston@google.com>
This commit is contained in:
Tyler Denniston 2021-05-04 14:17:27 -04:00 committed by Skia Commit-Bot
parent 86f31f287e
commit 2992fb0d60
2 changed files with 41 additions and 20 deletions

View File

@ -11,6 +11,10 @@
#include "modules/svg/include/SkSVGTransformableNode.h"
#include "modules/svg/include/SkSVGTypes.h"
namespace skresources {
class ResourceProvider;
}
class SkSVGImage final : public SkSVGTransformableNode {
public:
static sk_sp<SkSVGImage> Make() {
@ -26,6 +30,15 @@ public:
SkPath onAsPath(const SkSVGRenderContext&) const override;
SkRect onObjectBoundingBox(const SkSVGRenderContext&) const override;
struct ImageInfo {
sk_sp<SkImage> fImage;
SkRect fDst;
};
static ImageInfo LoadImage(const sk_sp<skresources::ResourceProvider>&,
const SkSVGIRI&,
const SkRect&,
SkSVGPreserveAspectRatio);
SVG_ATTR(X , SkSVGLength , SkSVGLength(0))
SVG_ATTR(Y , SkSVGLength , SkSVGLength(0))
SVG_ATTR(Width , SkSVGLength , SkSVGLength(0))
@ -39,8 +52,6 @@ protected:
private:
SkSVGImage() : INHERITED(SkSVGTag::kImage) {}
SkRect resolveImageRect(const SkRect&, const SkRect&) const;
using INHERITED = SkSVGTransformableNode;
};

View File

@ -54,32 +54,42 @@ static sk_sp<SkImage> LoadImage(const sk_sp<skresources::ResourceProvider>& rp,
return imageAsset ? imageAsset->getFrameData(0).image : nullptr;
}
SkRect SkSVGImage::resolveImageRect(const SkRect& viewBox, const SkRect& viewPort) const {
const SkMatrix m = ComputeViewboxMatrix(viewBox, viewPort, fPreserveAspectRatio);
// Map and place at x, y specified by image attributes
return m.mapRect(viewBox).makeOffset(viewPort.fLeft, viewPort.fTop);
}
void SkSVGImage::onRender(const SkSVGRenderContext& ctx) const {
const auto& rp = ctx.resourceProvider();
SkSVGImage::ImageInfo SkSVGImage::LoadImage(const sk_sp<skresources::ResourceProvider>& rp,
const SkSVGIRI& iri,
const SkRect& viewPort,
SkSVGPreserveAspectRatio par) {
SkASSERT(rp);
// TODO: svg sources
sk_sp<SkImage> image = LoadImage(rp, fHref);
sk_sp<SkImage> image = ::LoadImage(rp, iri);
if (!image) {
return {};
}
// Per spec: raster content has implicit viewbox of '0 0 width height'.
const SkRect viewBox = SkRect::Make(image->bounds());
// Map and place at x, y specified by viewport
const SkMatrix m = ComputeViewboxMatrix(viewBox, viewPort, par);
const SkRect dst = m.mapRect(viewBox).makeOffset(viewPort.fLeft, viewPort.fTop);
return {std::move(image), dst};
}
void SkSVGImage::onRender(const SkSVGRenderContext& ctx) const {
// Per spec: x, w, width, height attributes establish the new viewport.
const SkSVGLengthContext& lctx = ctx.lengthContext();
const SkRect viewPort = lctx.resolveRect(fX, fY, fWidth, fHeight);
const auto imgInfo = LoadImage(ctx.resourceProvider(), fHref, viewPort, fPreserveAspectRatio);
if (!imgInfo.fImage) {
SkDebugf("can't render image: load image failed\n");
return;
}
// Per spec: x, w, width, height attributes establish the new viewport.
const SkSVGLengthContext& lctx = ctx.lengthContext();
const SkRect viewPort = lctx.resolveRect(fX, fY, fWidth, fHeight);
// Per spec: raster content has implicit viewbox of '0 0 width height'.
const SkRect viewBox = SkRect::Make(image->bounds());
ctx.canvas()->drawImageRect(image,
this->resolveImageRect(viewBox, viewPort),
SkSamplingOptions(SkFilterMode::kLinear));
// TODO: image-rendering property
ctx.canvas()->drawImageRect(
imgInfo.fImage, imgInfo.fDst, SkSamplingOptions(SkFilterMode::kLinear));
}
SkPath SkSVGImage::onAsPath(const SkSVGRenderContext&) const { return {}; }