Skip to content

Commit

Permalink
Add a LayerStyle for drawing background blur effects. (#441)
Browse files Browse the repository at this point in the history
  • Loading branch information
Hparty authored Jan 24, 2025
1 parent 0b5d94c commit 3dbeed5
Show file tree
Hide file tree
Showing 13 changed files with 414 additions and 56 deletions.
9 changes: 6 additions & 3 deletions include/tgfx/layers/Layer.h
Original file line number Diff line number Diff line change
Expand Up @@ -513,10 +513,11 @@ class Layer {
* @param canvas The canvas to draw the layer content on.
* @param alpha The alpha transparency value used for drawing the layer content.
* @param forContour Whether to draw the layer content for the contour.
* @param drawChildren A callback function that draws the children of the layer.
* @param drawChildren A callback function that draws the children of the layer. if the function
* return false, the content above children should not be drawn.
*/
virtual void drawContents(LayerContent* content, Canvas* canvas, float alpha, bool forContour,
const std::function<void()>& drawChildren) const;
const std::function<bool()>& drawChildren) const;

/**
* Attachs a property to this layer.
Expand Down Expand Up @@ -563,7 +564,9 @@ class Layer {

void drawDirectly(const DrawArgs& args, Canvas* canvas, float alpha);

void drawChildren(const DrawArgs& args, Canvas* canvas, float alpha);
bool drawChildren(const DrawArgs& args, Canvas* canvas, float alpha, Layer* stopChild = nullptr);

void drawBackground(const DrawArgs& args, Canvas* canvas, float* contentAlpha = nullptr);

std::unique_ptr<LayerStyleSource> getLayerStyleSource(const DrawArgs& args, const Matrix& matrix);

Expand Down
2 changes: 1 addition & 1 deletion include/tgfx/layers/ShapeLayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ class ShapeLayer : public Layer {
std::unique_ptr<LayerContent> onUpdateContent() override;

void drawContents(LayerContent* content, Canvas* canvas, float alpha, bool forContour,
const std::function<void()>& drawChildren) const override;
const std::function<bool()>& drawChildren) const override;

private:
std::shared_ptr<Shape> _shape = nullptr;
Expand Down
100 changes: 100 additions & 0 deletions include/tgfx/layers/layerstyles/BackgroundBlurStyle.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/////////////////////////////////////////////////////////////////////////////////////////////////
//
// Tencent is pleased to support the open source community by making tgfx available.
//
// Copyright (C) 2025 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/layerstyles/LayerStyle.h"

namespace tgfx {

/**
* BackgroundBlurStyle adds a blur effect to the background of the layer.
* The background includes all layers below this layer and the layer's below layerStyles except for
* the BackgroundBlurStyle.
*/
class BackgroundBlurStyle : public LayerStyle {
public:
static std::shared_ptr<BackgroundBlurStyle> Make(float blurrinessX, float blurrinessY,
TileMode tileMode = TileMode::Clamp);
/**
* The x blurriness of the background.
*/
float blurrinessX() const {
return _blurrinessX;
}

/**
* Set x blurriness of the background.
*/
void setBlurrinessX(float blurriness);

/**
* The y blurriness of the background.
*/
float blurrinessY() const {
return _blurrinessY;
}

/**
* Set y blurriness of the background.
*/
void setBlurrinessY(float blurriness);

/**
* The tile mode of the background.
*/
TileMode tileMode() const {
return _tileMode;
}

/**
* Set tile mode of the background.
*/
void setTileMode(TileMode tileMode);

LayerStylePosition position() const override {
return LayerStylePosition::Below;
}

Rect filterBounds(const Rect& srcRect, float) override {
return srcRect;
}

LayerStyleExtraSourceType extraSourceType() const override {
return _blurrinessX > 0 && _blurrinessY > 0 ? LayerStyleExtraSourceType::Background
: LayerStyleExtraSourceType::None;
}

protected:
void onDraw(Canvas*, std::shared_ptr<Image>, float, float, BlendMode) override {
}

void onDrawWithExtraSource(Canvas* canvas, std::shared_ptr<Image> content, float contentScale,
std::shared_ptr<Image> extraSource, const Point& extraSourceOffset,
float alpha, BlendMode blendMode) override;

private:
explicit BackgroundBlurStyle(float blurrinessX, float blurrinessY, TileMode tileMode);

float _blurrinessX = 0;
float _blurrinessY = 0;

TileMode _tileMode = TileMode::Clamp;
};

} // namespace tgfx
10 changes: 5 additions & 5 deletions include/tgfx/layers/layerstyles/DropShadowStyle.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,17 +112,17 @@ class DropShadowStyle : public LayerStyle {

Rect filterBounds(const Rect& srcRect, float contentScale) override;

bool requireLayerContour() const override {
return !_showBehindLayer;
LayerStyleExtraSourceType extraSourceType() const override {
return !_showBehindLayer ? LayerStyleExtraSourceType::Contour : LayerStyleExtraSourceType::None;
}

protected:
void onDraw(Canvas* canvas, std::shared_ptr<Image> content, float contentScale, float alpha,
BlendMode blendMode) override;

void onDrawWithContour(Canvas* canvas, std::shared_ptr<Image> content, float contentScale,
std::shared_ptr<Image> contour, const Point& contourOffset, float alpha,
BlendMode blendMode) override;
void onDrawWithExtraSource(Canvas* canvas, std::shared_ptr<Image> content, float contentScale,
std::shared_ptr<Image> extraSource, const Point& extraSourceOffset,
float alpha, BlendMode blendMode) override;

private:
DropShadowStyle(float offsetX, float offsetY, float blurrinessX, float blurrinessY,
Expand Down
51 changes: 36 additions & 15 deletions include/tgfx/layers/layerstyles/LayerStyle.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,21 @@ enum class LayerStylePosition {
Below
};

enum class LayerStyleExtraSourceType {
/**
* The layerStyle requires no extra source.
*/
None,
/**
* The layerStyle requires the layer contour to be drawn.
*/
Contour,
/**
* The layerStyle requires the background content.
*/
Background
};

/**
* LayerStyle is used to change the appearance of a layer. Unlike LayerFilter, it does not create a
* new offscreen image to replace the original layer content. Instead, it adds visual elements
Expand Down Expand Up @@ -84,10 +99,11 @@ class LayerStyle : public LayerProperty {
}

/**
* Returns whether the layer style requires the layer contour to be drawn.
* Returns the type of the extra source required by the layer style.
* Default is LayerStyleExtraSourceType::None.
*/
virtual bool requireLayerContour() const {
return false;
virtual LayerStyleExtraSourceType extraSourceType() const {
return LayerStyleExtraSourceType::None;
}

/**
Expand All @@ -97,14 +113,16 @@ class LayerStyle : public LayerProperty {
* @param content The scaled layer content to apply the layer style to.
* @param contentScale The scale factor of the layer content relative to its original size.
* Some layer styles have size-related parameters that must be adjusted with this scale factor.
* @param contour The scaled layer contour to apply the layer style to.
* @param contourOffset The offset of the contour relative to the layer content.
* @param extraSource The scaled extra source to apply the layer style to. The source may be
* layer's contour or background content.
* @param extraSourceOffset The offset of the extra image relative to the layer content.
* @param alpha The alpha transparency value used for drawing the layer style.
*/
void drawWithContour(Canvas* canvas, std::shared_ptr<Image> content, float contentScale,
std::shared_ptr<Image> contour, const Point& contourOffset, float alpha) {
onDrawWithContour(canvas, std::move(content), contentScale, std::move(contour), contourOffset,
alpha, _blendMode);
void drawWithExtraSource(Canvas* canvas, std::shared_ptr<Image> content, float contentScale,
std::shared_ptr<Image> extraSource, const Point& extraSourceOffset,
float alpha) {
onDrawWithExtraSource(canvas, std::move(content), contentScale, std::move(extraSource),
extraSourceOffset, alpha, _blendMode);
}

protected:
Expand All @@ -122,19 +140,22 @@ class LayerStyle : public LayerProperty {
float alpha, BlendMode blendMode) = 0;

/**
* Applies the layer style with layer contour to the scaled image of the layer content and draws it on the canvas.
* Applies the layer style with layer contour to the scaled image of the layer content and draws
* it on the canvas.
* The default implementation calls onDraw with the layer content only.
* @param canvas The canvas to draw the layer style on.
* @param content The scaled layer content to apply the layer style to.
* @param contentScale The scale factor of the layer content relative to its original size.
* Some layer styles have size-related parameters that must be adjusted with this scale factor.
* @param contour The scaled layer contour to apply the layer style to.
* @param contourOffset The offset of the contour relative to the layer content.
* @param extraSource The scaled layer extra source to apply the layer style to.The source may be
* layer's contour or background content.
* @param extraSourceOffset The offset of the extra source relative to the layer content.
* @param alpha The alpha transparency value used for drawing the layer style.
*/
virtual void onDrawWithContour(Canvas* canvas, std::shared_ptr<Image> content, float contentScale,
std::shared_ptr<Image> contour, const Point& contourOffset,
float alpha, BlendMode blendMode);
virtual void onDrawWithExtraSource(Canvas* canvas, std::shared_ptr<Image> content,
float contentScale, std::shared_ptr<Image> extraSource,
const Point& extraSourceOffset, float alpha,
BlendMode blendMode);

private:
BlendMode _blendMode = BlendMode::SrcOver;
Expand Down
12 changes: 7 additions & 5 deletions src/layers/DrawArgs.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
#include "tgfx/gpu/Context.h"

namespace tgfx {

enum class DrawMode { Normal, Contour, Background };

/**
* DrawArgs represents the arguments passed to the draw method of a Layer.
*/
Expand All @@ -29,9 +32,9 @@ class DrawArgs {
DrawArgs() = default;

DrawArgs(Context* context, uint32_t renderFlags, bool cleanDirtyFlags = false,
bool excludeEffects = false, bool forContour = false)
bool excludeEffects = false, DrawMode drawMode = DrawMode::Normal)
: context(context), renderFlags(renderFlags), cleanDirtyFlags(cleanDirtyFlags),
excludeEffects(excludeEffects), forContour(forContour) {
excludeEffects(excludeEffects), drawMode(drawMode) {
}

// The GPU context to be used during the drawing process. Note: this could be nullptr.
Expand All @@ -42,8 +45,7 @@ class DrawArgs {
bool cleanDirtyFlags = false;
// Whether to exclude effects during the drawing process.
bool excludeEffects = false;
// Whether to draw the contour of the associated Layer during the drawing process. If true, the
// contour will be drawn instead of the content.
bool forContour = false;
// Determines the draw mode of the Layer.
DrawMode drawMode = DrawMode::Normal;
};
} // namespace tgfx
Loading

0 comments on commit 3dbeed5

Please sign in to comment.