Skip to content

Commit

Permalink
Fix the issue where innerShadow is drawn incorrectly in certain cases. (
Browse files Browse the repository at this point in the history
  • Loading branch information
Hparty authored Jan 8, 2025
1 parent d76b591 commit c08f94a
Show file tree
Hide file tree
Showing 7 changed files with 68 additions and 11 deletions.
8 changes: 7 additions & 1 deletion src/core/ImageFilter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "gpu/TPArgs.h"
#include "gpu/processors/FragmentProcessor.h"
#include "gpu/processors/TextureEffect.h"
#include "gpu/processors/TiledTextureEffect.h"
#include "gpu/proxies/RenderTargetProxy.h"

namespace tgfx {
Expand Down Expand Up @@ -92,6 +93,11 @@ std::unique_ptr<FragmentProcessor> ImageFilter::makeFPFromTextureProxy(
if (uvMatrix != nullptr) {
fpMatrix.preConcat(*uvMatrix);
}
return TextureEffect::Make(std::move(textureProxy), sampling, &fpMatrix, isAlphaOnly);
if (dstBounds.contains(clipBounds)) {
return TextureEffect::Make(std::move(textureProxy), sampling, &fpMatrix, isAlphaOnly);
} else {
return TiledTextureEffect::Make(std::move(textureProxy), TileMode::Decal, TileMode::Decal,
sampling, &fpMatrix, isAlphaOnly);
}
}
} // namespace tgfx
5 changes: 5 additions & 0 deletions src/core/filters/DropShadowImageFilter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,11 @@ Rect DropShadowImageFilter::onFilterBounds(const Rect& srcRect) const {
std::unique_ptr<FragmentProcessor> DropShadowImageFilter::asFragmentProcessor(
std::shared_ptr<Image> source, const FPArgs& args, const SamplingOptions& sampling,
const Matrix* uvMatrix) const {
if (color.alpha <= 0) {
// The filer will not be created if filter is not drop shadow only and alpha < 0.So if color is
// transparent, the image after applying the filter will be transparent.
return nullptr;
}
source = source->makeRasterized();
std::unique_ptr<FragmentProcessor> shadowProcessor;
auto shadowMatrix = Matrix::MakeTrans(-dx, -dy);
Expand Down
5 changes: 5 additions & 0 deletions src/core/filters/InnerShadowImageFilter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,11 @@ InnerShadowImageFilter::InnerShadowImageFilter(float dx, float dy, float blurrin
std::unique_ptr<FragmentProcessor> InnerShadowImageFilter::asFragmentProcessor(
std::shared_ptr<Image> source, const FPArgs& args, const SamplingOptions& sampling,
const Matrix* uvMatrix) const {
if (color.alpha <= 0) {
// The filer will not be created if filter is not drop shadow only and alpha < 0.So if color is
// transparent, the image after applying the filter will be transparent.
return nullptr;
}
source = source->makeRasterized();
// get inverted shadow mask
auto shadowMatrix = Matrix::MakeTrans(-dx, -dy);
Expand Down
10 changes: 3 additions & 7 deletions src/gpu/UniformHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,8 @@
namespace tgfx {
SamplerHandle UniformHandler::addSampler(const tgfx::TextureSampler* sampler,
const std::string& name) {
auto result = samplerMap.find(sampler);
if (result != samplerMap.end()) {
return result->second;
}
auto handle = internalAddSampler(sampler, name);
samplerMap[sampler] = handle;
return handle;
// The same sampler can be added multiple times with different names because the same handler of
// the program can be used with different samplers.
return internalAddSampler(sampler, name);
}
} // namespace tgfx
2 changes: 0 additions & 2 deletions src/gpu/UniformHandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,6 @@ class UniformHandler {
ProgramBuilder* programBuilder;

private:
std::unordered_map<const TextureSampler*, SamplerHandle> samplerMap = {};

virtual const ShaderVar& samplerVariable(SamplerHandle samplerHandle) const = 0;

virtual const Swizzle& samplerSwizzle(SamplerHandle samplerHandle) const = 0;
Expand Down
4 changes: 3 additions & 1 deletion test/baseline/version.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
"rasterized": "5a971dd",
"rasterized_mipmap": "5a971dd",
"rasterized_scale_up": "5a971dd",
"saveLayer": "3888c19",
"saveLayer": "b9a42bf",
"shape": "bc64712",
"text_shape": "b062b9a",
"tile_mode_normal": "8cb853c",
Expand All @@ -73,7 +73,9 @@
"ComposeColorFilter": "f710e29",
"ComposeImageFilter": "2028a1b",
"ComposeImageFilter2": "2028a1b",
"EmptyShadowTest": "b9a42bf",
"ImageFilterShader": "2028a1b",
"InnerShadowBadCase": "b9a42bf",
"ModeColorFilter": "c2b0b18",
"RuntimeEffect": "d93c573",
"blur": "4d6ab20",
Expand Down
45 changes: 45 additions & 0 deletions test/src/FilterTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -572,4 +572,49 @@ TGFX_TEST(FilterTest, AlphaThreshold) {
canvas->drawRect(rect, paint);
EXPECT_TRUE(Baseline::Compare(surface, "FilterTest/AlphaThreshold"));
}

TGFX_TEST(FilterTest, EmptyShadowTest) {
ContextScope scope;
auto context = scope.getContext();
EXPECT_TRUE(context != nullptr);
auto surface = Surface::Make(context, 100, 100);
auto canvas = surface->getCanvas();
auto paint = Paint();
paint.setColor(Color::FromRGBA(100, 0, 0, 255));
auto filter = ImageFilter::DropShadow(20, 20, 0, 0, Color::Transparent());
EXPECT_EQ(filter, nullptr);
filter = ImageFilter::DropShadowOnly(20, 20, 0, 0, Color::Transparent());
EXPECT_NE(filter, nullptr);
paint.setImageFilter(filter);

auto rect = Rect::MakeWH(100, 100);
canvas->drawRect(rect, paint);
EXPECT_TRUE(Baseline::Compare(surface, "FilterTest/EmptyShadowTest"));

filter = ImageFilter::InnerShadow(20, 20, 0, 0, Color::Transparent());
EXPECT_EQ(filter, nullptr);

filter = ImageFilter::InnerShadowOnly(20, 20, 0, 0, Color::Transparent());
EXPECT_NE(filter, nullptr);
paint.setImageFilter(filter);
canvas->drawRect(rect, paint);
EXPECT_TRUE(Baseline::Compare(surface, "FilterTest/EmptyShadowTest"));
}

TGFX_TEST(FilterTest, InnerShadowBadCase) {
ContextScope scope;
auto context = scope.getContext();
EXPECT_TRUE(context != nullptr);
auto surface = Surface::Make(context, 400, 400);
auto canvas = surface->getCanvas();
auto paint = Paint();
paint.setColor(Color::FromRGBA(255, 0, 0, 255));
auto filter = ImageFilter::InnerShadow(80, 80, 1, 1, Color::Green());
paint.setImageFilter(filter);
auto rect = Rect::MakeWH(250, 250);
Path path;
path.addOval(rect);
canvas->drawPath(path, paint);
EXPECT_TRUE(Baseline::Compare(surface, "FilterTest/InnerShadowBadCase"));
}
} // namespace tgfx

0 comments on commit c08f94a

Please sign in to comment.