mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-08 21:53:41 +00:00
renderer/sw_engine: fix omitted alpha multiplication in the dropshadow effect
When a scene has a valid opacity, it must be multiplied with the direct dropshadow image to ensure correct rendering.
This commit is contained in:
parent
077a0481c4
commit
877c524e5e
10 changed files with 16 additions and 16 deletions
|
@ -982,7 +982,7 @@ bool GlRenderer::prepare(TVG_UNUSED RenderEffect* effect)
|
|||
}
|
||||
|
||||
|
||||
bool GlRenderer::effect(TVG_UNUSED RenderCompositor* cmp, TVG_UNUSED const RenderEffect* effect, TVG_UNUSED bool direct)
|
||||
bool GlRenderer::effect(TVG_UNUSED RenderCompositor* cmp, TVG_UNUSED const RenderEffect* effect, TVG_UNUSED uint8_t opacity, TVG_UNUSED bool direct)
|
||||
{
|
||||
TVGLOG("GL_ENGINE", "SceneEffect(%d) is not supported", (int)effect->type);
|
||||
return false;
|
||||
|
|
|
@ -87,7 +87,7 @@ public:
|
|||
bool endComposite(RenderCompositor* cmp) override;
|
||||
|
||||
bool prepare(RenderEffect* effect) override;
|
||||
bool effect(RenderCompositor* cmp, const RenderEffect* effect, bool direct) override;
|
||||
bool effect(RenderCompositor* cmp, const RenderEffect* effect, uint8_t opacity, bool direct) override;
|
||||
|
||||
static GlRenderer* gen();
|
||||
static int init(TVG_UNUSED uint32_t threads);
|
||||
|
|
|
@ -572,9 +572,9 @@ void rasterUnpremultiply(RenderSurface* surface);
|
|||
void rasterPremultiply(RenderSurface* surface);
|
||||
bool rasterConvertCS(RenderSurface* surface, ColorSpace to);
|
||||
|
||||
bool effectGaussianBlur(SwCompositor* cmp, SwSurface* surface, const RenderEffectGaussianBlur* params, bool direct);
|
||||
bool effectGaussianBlur(SwCompositor* cmp, SwSurface* surface, const RenderEffectGaussianBlur* params);
|
||||
bool effectGaussianBlurPrepare(RenderEffectGaussianBlur* effect);
|
||||
bool effectDropShadow(SwCompositor* cmp, SwSurface* surfaces[2], const RenderEffectDropShadow* params, bool direct);
|
||||
bool effectDropShadow(SwCompositor* cmp, SwSurface* surfaces[2], const RenderEffectDropShadow* params, uint8_t opacity, bool direct);
|
||||
bool effectDropShadowPrepare(RenderEffectDropShadow* effect);
|
||||
|
||||
#endif /* _TVG_SW_COMMON_H_ */
|
||||
|
|
|
@ -163,7 +163,7 @@ bool effectGaussianBlurPrepare(RenderEffectGaussianBlur* params)
|
|||
}
|
||||
|
||||
|
||||
bool effectGaussianBlur(SwCompositor* cmp, SwSurface* surface, const RenderEffectGaussianBlur* params, TVG_UNUSED bool direct)
|
||||
bool effectGaussianBlur(SwCompositor* cmp, SwSurface* surface, const RenderEffectGaussianBlur* params)
|
||||
{
|
||||
if (cmp->image.channelSize != sizeof(uint32_t)) {
|
||||
TVGERR("SW_ENGINE", "Not supported grayscale Gaussian Blur!");
|
||||
|
@ -237,7 +237,7 @@ static void _dropShadowFilter(uint32_t* dst, uint32_t* src, int stride, int w, i
|
|||
}
|
||||
auto iarr = 1.0f / (dimension + dimension + 1);
|
||||
|
||||
//#pragma omp parallel for
|
||||
#pragma omp parallel for
|
||||
for (int y = 0; y < h; ++y) {
|
||||
auto p = y * stride;
|
||||
auto i = p; //current index
|
||||
|
@ -335,7 +335,7 @@ bool effectDropShadowPrepare(RenderEffectDropShadow* params)
|
|||
//A quite same integration with effectGaussianBlur(). See it for detailed comments.
|
||||
//surface[0]: the original image, to overlay it into the filtered image.
|
||||
//surface[1]: temporary buffer for generating the filtered image.
|
||||
bool effectDropShadow(SwCompositor* cmp, SwSurface* surface[2], const RenderEffectDropShadow* params, bool direct)
|
||||
bool effectDropShadow(SwCompositor* cmp, SwSurface* surface[2], const RenderEffectDropShadow* params, uint8_t opacity, bool direct)
|
||||
{
|
||||
if (cmp->image.channelSize != sizeof(uint32_t)) {
|
||||
TVGERR("SW_ENGINE", "Not supported grayscale Drop Shadow!");
|
||||
|
@ -357,7 +357,7 @@ bool effectDropShadow(SwCompositor* cmp, SwSurface* surface[2], const RenderEffe
|
|||
auto stride = cmp->image.stride;
|
||||
auto front = cmp->image.buf32;
|
||||
auto back = buffer[1]->buf32;
|
||||
auto opacity = params->color[3];
|
||||
opacity = MULTIPLY(params->color[3], opacity);
|
||||
|
||||
TVGLOG("SW_ENGINE", "DropShadow region(%ld, %ld, %ld, %ld) params(%f %f %f), level(%d)", bbox.min.x, bbox.min.y, bbox.max.x, bbox.max.y, params->angle, params->distance, params->sigma, data->level);
|
||||
|
||||
|
|
|
@ -650,7 +650,7 @@ bool SwRenderer::prepare(RenderEffect* effect)
|
|||
}
|
||||
|
||||
|
||||
bool SwRenderer::effect(RenderCompositor* cmp, const RenderEffect* effect, bool direct)
|
||||
bool SwRenderer::effect(RenderCompositor* cmp, const RenderEffect* effect, uint8_t opacity, bool direct)
|
||||
{
|
||||
if (effect->invalid) return false;
|
||||
|
||||
|
@ -658,14 +658,14 @@ bool SwRenderer::effect(RenderCompositor* cmp, const RenderEffect* effect, bool
|
|||
|
||||
switch (effect->type) {
|
||||
case SceneEffect::GaussianBlur: {
|
||||
return effectGaussianBlur(p, request(surface->channelSize), static_cast<const RenderEffectGaussianBlur*>(effect), direct);
|
||||
return effectGaussianBlur(p, request(surface->channelSize), static_cast<const RenderEffectGaussianBlur*>(effect));
|
||||
}
|
||||
case SceneEffect::DropShadow: {
|
||||
auto cmp1 = request(surface->channelSize);
|
||||
cmp1->compositor->valid = false;
|
||||
auto cmp2 = request(surface->channelSize);
|
||||
SwSurface* surfaces[] = {cmp1, cmp2};
|
||||
auto ret = effectDropShadow(p, surfaces, static_cast<const RenderEffectDropShadow*>(effect), direct);
|
||||
auto ret = effectDropShadow(p, surfaces, static_cast<const RenderEffectDropShadow*>(effect), opacity, direct);
|
||||
cmp1->compositor->valid = true;
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -61,7 +61,7 @@ public:
|
|||
void clearCompositors();
|
||||
|
||||
bool prepare(RenderEffect* effect) override;
|
||||
bool effect(RenderCompositor* cmp, const RenderEffect* effect, bool direct) override;
|
||||
bool effect(RenderCompositor* cmp, const RenderEffect* effect, uint8_t opacity, bool direct) override;
|
||||
|
||||
static SwRenderer* gen();
|
||||
static bool init(uint32_t threads);
|
||||
|
|
|
@ -343,7 +343,7 @@ public:
|
|||
virtual bool endComposite(RenderCompositor* cmp) = 0;
|
||||
|
||||
virtual bool prepare(RenderEffect* effect) = 0;
|
||||
virtual bool effect(RenderCompositor* cmp, const RenderEffect* effect, bool direct) = 0;
|
||||
virtual bool effect(RenderCompositor* cmp, const RenderEffect* effect, uint8_t opacity, bool direct) = 0;
|
||||
};
|
||||
|
||||
static inline bool MASK_REGION_MERGING(MaskMethod method)
|
||||
|
|
|
@ -142,7 +142,7 @@ struct Scene::Impl
|
|||
if (effects) {
|
||||
auto direct = effects->count == 1 ? true : false;
|
||||
for (auto e = effects->begin(); e < effects->end(); ++e) {
|
||||
renderer->effect(cmp, *e, direct);
|
||||
renderer->effect(cmp, *e, opacity, direct);
|
||||
}
|
||||
}
|
||||
renderer->endComposite(cmp);
|
||||
|
|
|
@ -469,7 +469,7 @@ bool WgRenderer::prepare(TVG_UNUSED RenderEffect* effect)
|
|||
}
|
||||
|
||||
|
||||
bool WgRenderer::effect(TVG_UNUSED RenderCompositor* cmp, TVG_UNUSED const RenderEffect* effect, TVG_UNUSED bool direct)
|
||||
bool WgRenderer::effect(TVG_UNUSED RenderCompositor* cmp, TVG_UNUSED const RenderEffect* effect, TVG_UNUSED uint8_t opacity, TVG_UNUSED bool direct)
|
||||
{
|
||||
TVGLOG("WG_ENGINE", "SceneEffect(%d) is not supported", (int)effect->type);
|
||||
return false;
|
||||
|
|
|
@ -52,7 +52,7 @@ public:
|
|||
bool endComposite(RenderCompositor* cmp) override;
|
||||
|
||||
bool prepare(RenderEffect* effect) override;
|
||||
bool effect(RenderCompositor* cmp, const RenderEffect* effect, bool direct) override;
|
||||
bool effect(RenderCompositor* cmp, const RenderEffect* effect, uint8_t opacity, bool direct) override;
|
||||
|
||||
static WgRenderer* gen();
|
||||
static bool init(uint32_t threads);
|
||||
|
|
Loading…
Add table
Reference in a new issue