-
Notifications
You must be signed in to change notification settings - Fork 69
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add an ImageFilter to draw inner shadow. (#323)
- Loading branch information
Showing
8 changed files
with
458 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
///////////////////////////////////////////////////////////////////////////////////////////////// | ||
// | ||
// Tencent is pleased to support the open source community by making tgfx available. | ||
// | ||
// Copyright (C) 2024 THL A29 Limited, a Tencent company. All rights reserved. | ||
// | ||
// Licensed under the BSD 3-Clause License (the "License"); you may not use this file except | ||
// in compliance with the License. You may obtain a copy of the License at | ||
// | ||
// https://opensource.org/licenses/BSD-3-Clause | ||
// | ||
// unless required by applicable law or agreed to in writing, software distributed under the | ||
// license is distributed on an "as is" basis, without warranties or conditions of any kind, | ||
// either express or implied. see the license for the specific language governing permissions | ||
// and limitations under the license. | ||
// | ||
///////////////////////////////////////////////////////////////////////////////////////////////// | ||
|
||
#pragma once | ||
|
||
#include "tgfx/layers/filters/LayerFilter.h" | ||
|
||
namespace tgfx { | ||
class InnerShadowFilter : public LayerFilter { | ||
public: | ||
virtual ~InnerShadowFilter() = default; | ||
|
||
/** | ||
* Create a filter that draws an inner shadow over the input content. | ||
*/ | ||
static std::shared_ptr<InnerShadowFilter> Make(float offsetX, float offsetY, float blurrinessX, | ||
float blurrinessY, const Color& color, | ||
bool innerShadowOnly = false); | ||
|
||
/** | ||
* The x offset of the shadow. | ||
*/ | ||
float offsetX() const { | ||
return _offsetX; | ||
} | ||
|
||
/** | ||
* Set x offset of the shadow. | ||
* @param offsetX | ||
*/ | ||
void setOffsetX(float offsetX); | ||
|
||
/** | ||
* The y offset of the shadow. | ||
*/ | ||
float offsetY() const { | ||
return _offsetY; | ||
} | ||
|
||
/** | ||
* Set y offset of the shadow. | ||
* @param offsetY | ||
*/ | ||
void setOffsetY(float offsetY); | ||
|
||
/** | ||
* The blur radius for the shadow, along the X axis. | ||
*/ | ||
float blurrinessX() const { | ||
return _blurrinessX; | ||
} | ||
|
||
/** | ||
* Set blur radius for the shadow, along the X axis. | ||
* @param blurrinessX | ||
*/ | ||
void setBlurrinessX(float blurrinessX); | ||
|
||
/** | ||
* The blur radius for the shadow, along the Y axis. | ||
*/ | ||
float blurrinessY() const { | ||
return _blurrinessY; | ||
} | ||
|
||
/** | ||
* Set blur radius for the shadow, along the Y axis. | ||
* @param blurrinessY | ||
*/ | ||
void setBlurrinessY(float blurrinessY); | ||
|
||
/** | ||
* The color of the shadow. | ||
*/ | ||
Color color() const { | ||
return _color; | ||
} | ||
|
||
/** | ||
* Set the color of the shadow. | ||
* @param color | ||
*/ | ||
void setColor(const Color& color); | ||
|
||
/** | ||
* Whether the resulting image does not include the input content. | ||
*/ | ||
bool innerShadowOnly() const { | ||
return _innerShadowOnly; | ||
} | ||
|
||
/** | ||
* Set whether the resulting image does not include the input content. | ||
*/ | ||
void setInnerShadowOnly(bool value); | ||
|
||
protected: | ||
std::shared_ptr<ImageFilter> onCreateImageFilter(float scale) override; | ||
|
||
private: | ||
InnerShadowFilter(float offsetX, float offsetY, float blurrinessX, float blurrinessY, | ||
const Color& color, bool innerShadowOnly); | ||
float _offsetX = 0.0f; | ||
float _offsetY = 0.0f; | ||
float _blurrinessX = 0.0f; | ||
float _blurrinessY = 0.0f; | ||
Color _color = Color::Black(); | ||
bool _innerShadowOnly = false; | ||
}; | ||
|
||
} // namespace tgfx |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
///////////////////////////////////////////////////////////////////////////////////////////////// | ||
// | ||
// Tencent is pleased to support the open source community by making tgfx available. | ||
// | ||
// Copyright (C) 2024 THL A29 Limited, a Tencent company. All rights reserved. | ||
// | ||
// Licensed under the BSD 3-Clause License (the "License"); you may not use this file except | ||
// in compliance with the License. You may obtain a copy of the License at | ||
// | ||
// https://opensource.org/licenses/BSD-3-Clause | ||
// | ||
// unless required by applicable law or agreed to in writing, software distributed under the | ||
// license is distributed on an "as is" basis, without warranties or conditions of any kind, | ||
// either express or implied. see the license for the specific language governing permissions | ||
// and limitations under the license. | ||
// | ||
///////////////////////////////////////////////////////////////////////////////////////////////// | ||
|
||
#include "InnerShadowImageFilter.h" | ||
#include "core/images/TextureImage.h" | ||
#include "core/utils/NeedMipmaps.h" | ||
#include "gpu/processors/ConstColorProcessor.h" | ||
#include "gpu/processors/FragmentProcessor.h" | ||
#include "gpu/processors/XfermodeFragmentProcessor.h" | ||
namespace tgfx { | ||
std::shared_ptr<ImageFilter> ImageFilter::InnerShadow(float dx, float dy, float blurrinessX, | ||
float blurrinessY, const Color& color) { | ||
return std::make_shared<InnerShadowImageFilter>(dx, dy, blurrinessX, blurrinessY, color, false); | ||
} | ||
|
||
std::shared_ptr<ImageFilter> ImageFilter::InnerShadowOnly(float dx, float dy, float blurrinessX, | ||
float blurrinessY, const Color& color) { | ||
|
||
return std::make_shared<InnerShadowImageFilter>(dx, dy, blurrinessX, blurrinessY, color, true); | ||
} | ||
|
||
InnerShadowImageFilter::InnerShadowImageFilter(float dx, float dy, float blurrinessX, | ||
float blurrinessY, const Color& color, | ||
bool shadowOnly) | ||
|
||
: dx(dx), dy(dy), blurFilter(ImageFilter::Blur(blurrinessX, blurrinessY)), color(color), | ||
shadowOnly(shadowOnly) { | ||
} | ||
|
||
std::unique_ptr<FragmentProcessor> InnerShadowImageFilter::asFragmentProcessor( | ||
std::shared_ptr<Image> source, const FPArgs& args, const SamplingOptions& sampling, | ||
const Matrix* uvMatrix) const { | ||
if (source->isComplex()) { | ||
auto needMipmaps = NeedMipmaps(sampling, args.viewMatrix, uvMatrix); | ||
source = source->makeRasterized(needMipmaps, sampling); | ||
} | ||
|
||
// get inverted shadow mask | ||
auto shadowMatrix = Matrix::MakeTrans(-dx, -dy); | ||
if (uvMatrix != nullptr) { | ||
shadowMatrix.preConcat(*uvMatrix); | ||
} | ||
std::unique_ptr<FragmentProcessor> invertShadowMask; | ||
if (blurFilter != nullptr) { | ||
invertShadowMask = blurFilter->asFragmentProcessor(source, args, sampling, &shadowMatrix); | ||
} else { | ||
invertShadowMask = FragmentProcessor::Make(source, args, TileMode::Decal, TileMode::Decal, | ||
sampling, &shadowMatrix); | ||
} | ||
|
||
auto colorProcessor = ConstColorProcessor::Make(color, InputMode::Ignore); | ||
|
||
// get shadow mask and fill it with color | ||
auto colorShadowProcessor = XfermodeFragmentProcessor::MakeFromTwoProcessors( | ||
std::move(colorProcessor), std::move(invertShadowMask), BlendMode::SrcOut); | ||
|
||
auto imageProcessor = FragmentProcessor::Make(std::move(source), args, TileMode::Decal, | ||
TileMode::Decal, sampling, uvMatrix); | ||
|
||
if (shadowOnly) { | ||
// mask the image with origin image | ||
return XfermodeFragmentProcessor::MakeFromTwoProcessors( | ||
std::move(colorShadowProcessor), std::move(imageProcessor), BlendMode::SrcIn); | ||
} else { | ||
// mask the image with origin image and draw the inner shadow mask on top | ||
return XfermodeFragmentProcessor::MakeFromTwoProcessors( | ||
std::move(colorShadowProcessor), std::move(imageProcessor), BlendMode::SrcATop); | ||
} | ||
} | ||
|
||
} // namespace tgfx |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
///////////////////////////////////////////////////////////////////////////////////////////////// | ||
// | ||
// Tencent is pleased to support the open source community by making tgfx available. | ||
// | ||
// Copyright (C) 2024 THL A29 Limited, a Tencent company. All rights reserved. | ||
// | ||
// Licensed under the BSD 3-Clause License (the "License"); you may not use this file except | ||
// in compliance with the License. You may obtain a copy of the License at | ||
// | ||
// https://opensource.org/licenses/BSD-3-Clause | ||
// | ||
// unless required by applicable law or agreed to in writing, software distributed under the | ||
// license is distributed on an "as is" basis, without warranties or conditions of any kind, | ||
// either express or implied. see the license for the specific language governing permissions | ||
// and limitations under the license. | ||
// | ||
///////////////////////////////////////////////////////////////////////////////////////////////// | ||
|
||
#pragma once | ||
|
||
#include "tgfx/core/ImageFilter.h" | ||
|
||
namespace tgfx { | ||
class InnerShadowImageFilter : public ImageFilter { | ||
public: | ||
InnerShadowImageFilter(float dx, float dy, float blurrinessX, float blurrinessY, | ||
const Color& color, bool shadowOnly); | ||
|
||
protected: | ||
std::unique_ptr<FragmentProcessor> asFragmentProcessor(std::shared_ptr<Image> source, | ||
const FPArgs& args, | ||
const SamplingOptions& sampling, | ||
const Matrix* uvMatrix) const override; | ||
|
||
private: | ||
float dx = 0.0f; | ||
float dy = 0.0f; | ||
std::shared_ptr<ImageFilter> blurFilter = nullptr; | ||
Color color = Color::Black(); | ||
bool shadowOnly = false; | ||
}; | ||
} // namespace tgfx |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
///////////////////////////////////////////////////////////////////////////////////////////////// | ||
// | ||
// Tencent is pleased to support the open source community by making tgfx available. | ||
// | ||
// Copyright (C) 2024 THL A29 Limited, a Tencent company. All rights reserved. | ||
// | ||
// Licensed under the BSD 3-Clause License (the "License"); you may not use this file except | ||
// in compliance with the License. You may obtain a copy of the License at | ||
// | ||
// https://opensource.org/licenses/BSD-3-Clause | ||
// | ||
// unless required by applicable law or agreed to in writing, software distributed under the | ||
// license is distributed on an "as is" basis, without warranties or conditions of any kind, | ||
// either express or implied. see the license for the specific language governing permissions | ||
// and limitations under the license. | ||
// | ||
///////////////////////////////////////////////////////////////////////////////////////////////// | ||
|
||
#include "tgfx/layers/filters/InnerShadowFilter.h" | ||
|
||
namespace tgfx { | ||
std::shared_ptr<InnerShadowFilter> InnerShadowFilter::Make(float offsetX, float offsetY, | ||
float blurrinessX, float blurrinessY, | ||
const Color& color, | ||
bool innerShadowOnly) { | ||
return std::shared_ptr<InnerShadowFilter>( | ||
new InnerShadowFilter(offsetX, offsetY, blurrinessX, blurrinessY, color, innerShadowOnly)); | ||
} | ||
|
||
void InnerShadowFilter::setOffsetX(float offsetX) { | ||
if (_offsetX == offsetX) { | ||
return; | ||
} | ||
_offsetX = offsetX; | ||
invalidateFilter(); | ||
} | ||
|
||
void InnerShadowFilter::setOffsetY(float offsetY) { | ||
if (_offsetY == offsetY) { | ||
return; | ||
} | ||
_offsetY = offsetY; | ||
invalidateFilter(); | ||
} | ||
|
||
void InnerShadowFilter::setBlurrinessX(float blurrinessX) { | ||
if (_blurrinessX == blurrinessX) { | ||
return; | ||
} | ||
_blurrinessX = blurrinessX; | ||
invalidateFilter(); | ||
} | ||
|
||
void InnerShadowFilter::setBlurrinessY(float blurrinessY) { | ||
if (_blurrinessY == blurrinessY) { | ||
return; | ||
} | ||
_blurrinessY = blurrinessY; | ||
invalidateFilter(); | ||
} | ||
|
||
void InnerShadowFilter::setColor(const Color& color) { | ||
if (_color == color) { | ||
return; | ||
} | ||
_color = color; | ||
invalidateFilter(); | ||
} | ||
|
||
void InnerShadowFilter::setInnerShadowOnly(bool value) { | ||
if (_innerShadowOnly == value) { | ||
return; | ||
} | ||
_innerShadowOnly = value; | ||
invalidateFilter(); | ||
} | ||
|
||
std::shared_ptr<ImageFilter> InnerShadowFilter::onCreateImageFilter(float scale) { | ||
if (_innerShadowOnly) { | ||
return ImageFilter::InnerShadowOnly(_offsetX * scale, _offsetY * scale, _blurrinessX * scale, | ||
_blurrinessY * scale, _color); | ||
} | ||
return ImageFilter::InnerShadow(_offsetX * scale, _offsetY * scale, _blurrinessX * scale, | ||
_blurrinessY * scale, _color); | ||
} | ||
|
||
InnerShadowFilter::InnerShadowFilter(float offsetX, float offsetY, float blurrinessX, | ||
float blurrinessY, const Color& color, bool innerShadowOnly) | ||
: LayerFilter(), _offsetX(offsetX), _offsetY(offsetY), _blurrinessX(blurrinessX), | ||
_blurrinessY(blurrinessY), _color(std::move(color)), _innerShadowOnly(innerShadowOnly) { | ||
} | ||
|
||
} // namespace tgfx |
Oops, something went wrong.