diff --git a/include/core/SkSamplingOptions.h b/include/core/SkSamplingOptions.h index 41049a076aa92..5afd9cdd4181c 100644 --- a/include/core/SkSamplingOptions.h +++ b/include/core/SkSamplingOptions.h @@ -66,15 +66,6 @@ struct SK_API SkSamplingOptions { , cubic(c) {} explicit SkSamplingOptions(SkFilterQuality); - - bool operator==(const SkSamplingOptions& other) const { - return useCubic == other.useCubic - && cubic.B == other.cubic.B - && cubic.C == other.cubic.C - && filter == other.filter - && mipmap == other.mipmap; - } - bool operator!=(const SkSamplingOptions& other) const { return !(*this == other); } }; #endif diff --git a/modules/skottie/BUILD.gn b/modules/skottie/BUILD.gn index f4df67bc66d09..f0f06869968a7 100644 --- a/modules/skottie/BUILD.gn +++ b/modules/skottie/BUILD.gn @@ -55,7 +55,6 @@ if (skia_enable_skottie) { sources = [ "src/SkottieTest.cpp", "tests/AudioLayer.cpp", - "tests/Image.cpp", "tests/Keyframe.cpp", "tests/Text.cpp", ] diff --git a/modules/skottie/src/layers/FootageLayer.cpp b/modules/skottie/src/layers/FootageLayer.cpp index dd6e6e3349e16..f0b81210fdaff 100644 --- a/modules/skottie/src/layers/FootageLayer.cpp +++ b/modules/skottie/src/layers/FootageLayer.cpp @@ -17,14 +17,11 @@ namespace internal { namespace { -SkMatrix image_matrix(const ImageAsset::FrameData& frame_data, const SkISize& dest_size) { - if (!frame_data.image) { - return SkMatrix::I(); - } - - return frame_data.matrix * SkMatrix::MakeRectToRect(SkRect::Make(frame_data.image->bounds()), - SkRect::Make(dest_size), - SkMatrix::kCenter_ScaleToFit); +SkMatrix image_matrix(const sk_sp& image, const SkISize& dest_size) { + return image ? SkMatrix::MakeRectToRect(SkRect::Make(image->bounds()), + SkRect::Make(dest_size), + SkMatrix::kCenter_ScaleToFit) + : SkMatrix::I(); } class FootageAnimator final : public Animator { @@ -48,15 +45,10 @@ class FootageAnimator final : public Animator { return false; } - auto frame_data = fAsset->getFrameData((t + fTimeBias) * fTimeScale); - const auto m = image_matrix(frame_data, fAssetSize); - if (frame_data.image != fImageNode->getImage() || - frame_data.sampling != fImageNode->getSamplingOptions() || - m != fImageTransformNode->getMatrix()) { - - fImageNode->setImage(std::move(frame_data.image)); - fImageNode->setSamplingOptions(frame_data.sampling); - fImageTransformNode->setMatrix(m); + auto frame = fAsset->getFrame((t + fTimeBias) * fTimeScale); + if (frame != fImageNode->getImage()) { + fImageTransformNode->setMatrix(image_matrix(frame, fAssetSize)); + fImageNode->setImage(std::move(frame)); return true; } @@ -110,6 +102,7 @@ sk_sp AnimationBuilder::attachFootageAsset(const skjson::Objec SkASSERT(asset_info->fAsset); auto image_node = sksg::Image::Make(nullptr); + image_node->setQuality(kMedium_SkFilterQuality); // Optional image transform (mapping the intrinsic image size to declared asset size). sk_sp> image_transform; @@ -128,19 +121,17 @@ sk_sp AnimationBuilder::attachFootageAsset(const skjson::Objec 1 / fFrameRate)); } else { // No animator needed, resolve the (only) frame upfront. - auto frame_data = asset_info->fAsset->getFrameData(0); - if (!frame_data.image) { + auto frame = asset_info->fAsset->getFrame(0); + if (!frame) { this->log(Logger::Level::kError, nullptr, "Could not load single-frame image asset."); return nullptr; } - const auto m = image_matrix(frame_data, asset_info->fSize); - if (!m.isIdentity()) { - image_transform = sksg::Matrix::Make(m); + if (frame->bounds().size() != asset_info->fSize) { + image_transform = sksg::Matrix::Make(image_matrix(frame, asset_info->fSize)); } - image_node->setImage(std::move(frame_data.image)); - image_node->setSamplingOptions(frame_data.sampling); + image_node->setImage(std::move(frame)); } // Image layers are sized explicitly. diff --git a/modules/skottie/tests/Image.cpp b/modules/skottie/tests/Image.cpp deleted file mode 100644 index 8299d7ea59de9..0000000000000 --- a/modules/skottie/tests/Image.cpp +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright 2020 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "include/core/SkSurface.h" -#include "modules/skottie/include/Skottie.h" -#include "tests/Test.h" - -using namespace skottie; - -DEF_TEST(Skottie_Image_CustomTransform, r) { - static constexpr char json[] = - R"({ - "v": "5.2.1", - "w": 100, - "h": 100, - "fr": 10, - "ip": 0, - "op": 100, - "assets": [{ - "id": "img_0", - "p" : "img_0.png", - "u" : "images/", - "w" : 100, - "h" : 50 - }], - "layers": [ - { - "ip": 0, - "op": 100, - "ty": 2, - "refId": "img_0", - "ks": { - "p": { "a": 0, "k": [0,25] } - } - } - ] - })"; - - SkMemoryStream stream(json, strlen(json)); - - static const struct TestData { - float t; - SkMatrix m; - SkColor c[5]; // expected color samples at center/L/T/R/B - } tests[] { - { 0, SkMatrix::I(), - {0xffff0000, 0xffff0000, 0xff00ff00, 0xffff0000, 0xff00ff00}}, - { 1, SkMatrix::Translate(50,25) * SkMatrix::Scale(.5f,.5f) * SkMatrix::Translate(-50,-25), - {0xffff0000, 0xff00ff00, 0xff00ff00, 0xff00ff00, 0xff00ff00}}, - { 2, SkMatrix::Translate(-50, 0), - {0xff00ff00, 0xffff0000, 0xff00ff00, 0xff00ff00, 0xff00ff00}}, - { 3, SkMatrix::Translate(0, -25), - {0xff00ff00, 0xff00ff00, 0xffff0000, 0xff00ff00, 0xff00ff00}}, - { 4, SkMatrix::Translate(50, 0), - {0xffff0000, 0xff00ff00, 0xff00ff00, 0xffff0000, 0xff00ff00}}, - { 5, SkMatrix::Translate(0, 25), - {0xffff0000, 0xffff0000, 0xff00ff00, 0xffff0000, 0xffff0000}}, - }; - - class TestImageAsset final : public ImageAsset { - public: - TestImageAsset(const TestData* tst, skiatest::Reporter* r) - : fTest(tst) - , fReporter(r) { - - auto surf = SkSurface::MakeRasterN32Premul(200, 100); - surf->getCanvas()->drawColor(0xffff0000); - fImage = surf->makeImageSnapshot(); - } - - private: - bool isMultiFrame() override { return true; } - - FrameData getFrameData(float t) override { - REPORTER_ASSERT(fReporter, t == fTest->t); - - return { fImage, SkSamplingOptions(), fTest++->m }; - } - - sk_sp fImage; - const TestData* fTest; - skiatest::Reporter* fReporter; - }; - - class TestResourceProvider final : public ResourceProvider { - public: - TestResourceProvider(const TestData* tst, skiatest::Reporter* r) - : fTest(tst) - , fReporter(r) {} - - private: - sk_sp loadImageAsset(const char[], const char[], const char[]) const override { - return sk_make_sp(fTest, fReporter); - } - - const TestData* fTest; - skiatest::Reporter* fReporter; - }; - - auto anim = Animation::Builder() - .setResourceProvider(sk_make_sp(tests, r)) - .make(&stream); - - REPORTER_ASSERT(r, anim); - - static constexpr SkSize render_size{100, 100}; - auto surf = SkSurface::MakeRasterN32Premul(render_size.width(), render_size.height()); - auto rect = SkRect::MakeSize(render_size); - - SkPixmap pmap; - surf->peekPixels(&pmap); - - for (const auto& tst : tests) { - surf->getCanvas()->clear(0xff00ff00); - anim->seekFrameTime(tst.t); - anim->render(surf->getCanvas(), &rect); - - REPORTER_ASSERT(r, - tst.c[0] == pmap.getColor(render_size.width() / 2, render_size.height() / 2)); - REPORTER_ASSERT(r, - tst.c[1] == pmap.getColor(1 , render_size.height() / 2)); - REPORTER_ASSERT(r, - tst.c[2] == pmap.getColor(render_size.width() / 2, 1)); - REPORTER_ASSERT(r, - tst.c[3] == pmap.getColor(render_size.width() - 1, render_size.height() / 2)); - REPORTER_ASSERT(r, - tst.c[4] == pmap.getColor(render_size.width() /2 , render_size.height() - 1)); - } -} diff --git a/modules/skresources/include/SkResources.h b/modules/skresources/include/SkResources.h index a29fb31d165e7..c7121f3c50f45 100644 --- a/modules/skresources/include/SkResources.h +++ b/modules/skresources/include/SkResources.h @@ -9,9 +9,7 @@ #define SkResources_DEFINED #include "include/core/SkData.h" -#include "include/core/SkMatrix.h" #include "include/core/SkRefCnt.h" -#include "include/core/SkSamplingOptions.h" #include "include/core/SkString.h" #include "include/core/SkTypeface.h" #include "include/core/SkTypes.h" @@ -36,33 +34,9 @@ class SK_API ImageAsset : public SkRefCnt { virtual bool isMultiFrame() = 0; /** - * DEPRECATED: override getFrameData() instead. - * * Returns the SkImage for a given frame. * - * If the image asset is static, getFrame() is only called once, at animation load time. - * Otherwise, this gets invoked every time the animation time is adjusted (on every seek). - * - * Embedders should cache and serve the same SkImage whenever possible, for efficiency. - * - * @param t Frame time code, in seconds, relative to the image layer timeline origin - * (in-point). - */ - virtual sk_sp getFrame(float t); - - struct FrameData { - // SkImage payload. - sk_sp image; - // Resampling parameters. - SkSamplingOptions sampling; - // Additional image transform to be applied before AE scaling rules. - SkMatrix matrix = SkMatrix::I(); - }; - - /** - * Returns the payload for a given frame. - * - * If the image asset is static, getFrameData() is only called once, at animation load time. + * If the image asset is static, getImage() is only called once, at animation load time. * Otherwise, this gets invoked every time the animation time is adjusted (on every seek). * * Embedders should cache and serve the same SkImage whenever possible, for efficiency. @@ -70,7 +44,7 @@ class SK_API ImageAsset : public SkRefCnt { * @param t Frame time code, in seconds, relative to the image layer timeline origin * (in-point). */ - virtual FrameData getFrameData(float t); + virtual sk_sp getFrame(float t) = 0; }; class MultiFrameImageAsset final : public ImageAsset { diff --git a/modules/skresources/src/SkResources.cpp b/modules/skresources/src/SkResources.cpp index 02874f92d7e64..e4639d3bd3113 100644 --- a/modules/skresources/src/SkResources.cpp +++ b/modules/skresources/src/SkResources.cpp @@ -88,19 +88,6 @@ class VideoAsset final : public ImageAsset { } // namespace -sk_sp ImageAsset::getFrame(float t) { - return nullptr; -} - -ImageAsset::FrameData ImageAsset::getFrameData(float t) { - // legacy behavior - return { - this->getFrame(t), - SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kNearest), - SkMatrix::I(), - }; -} - sk_sp MultiFrameImageAsset::Make(sk_sp data, bool predecode) { if (auto codec = SkCodec::MakeFromData(std::move(data))) { return sk_sp( diff --git a/modules/sksg/include/SkSGImage.h b/modules/sksg/include/SkSGImage.h index 3f64f9da5bde3..6da8e1005c0db 100644 --- a/modules/sksg/include/SkSGImage.h +++ b/modules/sksg/include/SkSGImage.h @@ -10,7 +10,7 @@ #include "modules/sksg/include/SkSGRenderNode.h" -#include "include/core/SkSamplingOptions.h" +#include "include/core/SkFilterQuality.h" class SkImage; @@ -26,9 +26,9 @@ class Image final : public RenderNode { return sk_sp(new Image(std::move(image))); } - SG_ATTRIBUTE(Image , sk_sp , fImage ) - SG_ATTRIBUTE(SamplingOptions, SkSamplingOptions, fSamplingOptions) - SG_ATTRIBUTE(AntiAlias , bool , fAntiAlias ) + SG_ATTRIBUTE(Image, sk_sp , fImage ) + SG_ATTRIBUTE(Quality , SkFilterQuality, fQuality ) + SG_ATTRIBUTE(AntiAlias, bool , fAntiAlias) protected: explicit Image(sk_sp); @@ -39,9 +39,9 @@ class Image final : public RenderNode { SkRect onRevalidate(InvalidationController*, const SkMatrix&) override; private: - SkSamplingOptions fSamplingOptions; - sk_sp fImage; - bool fAntiAlias = true; + sk_sp fImage; + SkFilterQuality fQuality = kNone_SkFilterQuality; + bool fAntiAlias = true; using INHERITED = RenderNode; }; diff --git a/modules/sksg/src/SkSGImage.cpp b/modules/sksg/src/SkSGImage.cpp index 46c161b6ee2ac..5cd00aaf813e6 100644 --- a/modules/sksg/src/SkSGImage.cpp +++ b/modules/sksg/src/SkSGImage.cpp @@ -19,19 +19,9 @@ void Image::onRender(SkCanvas* canvas, const RenderContext* ctx) const { return; } - // Ignoring cubic params and trilerp for now. - // TODO: convert to drawImage(sampling options) when available. - auto legacy_quality = [](const SkSamplingOptions& sampling) { - return - sampling.useCubic ? SkFilterQuality::kHigh_SkFilterQuality : - sampling.filter == SkFilterMode::kNearest ? SkFilterQuality::kNone_SkFilterQuality : - sampling.mipmap == SkMipmapMode::kNone ? SkFilterQuality::kLow_SkFilterQuality : - SkFilterQuality::kMedium_SkFilterQuality; - }; - SkPaint paint; paint.setAntiAlias(fAntiAlias); - paint.setFilterQuality(legacy_quality(fSamplingOptions)); + paint.setFilterQuality(fQuality); sksg::RenderNode::ScopedRenderContext local_ctx(canvas, ctx); if (ctx) {