mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-09 14:13:43 +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);
|
TVGLOG("GL_ENGINE", "SceneEffect(%d) is not supported", (int)effect->type);
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -87,7 +87,7 @@ public:
|
||||||
bool endComposite(RenderCompositor* cmp) override;
|
bool endComposite(RenderCompositor* cmp) override;
|
||||||
|
|
||||||
bool prepare(RenderEffect* effect) 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 GlRenderer* gen();
|
||||||
static int init(TVG_UNUSED uint32_t threads);
|
static int init(TVG_UNUSED uint32_t threads);
|
||||||
|
|
|
@ -572,9 +572,9 @@ void rasterUnpremultiply(RenderSurface* surface);
|
||||||
void rasterPremultiply(RenderSurface* surface);
|
void rasterPremultiply(RenderSurface* surface);
|
||||||
bool rasterConvertCS(RenderSurface* surface, ColorSpace to);
|
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 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);
|
bool effectDropShadowPrepare(RenderEffectDropShadow* effect);
|
||||||
|
|
||||||
#endif /* _TVG_SW_COMMON_H_ */
|
#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)) {
|
if (cmp->image.channelSize != sizeof(uint32_t)) {
|
||||||
TVGERR("SW_ENGINE", "Not supported grayscale Gaussian Blur!");
|
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);
|
auto iarr = 1.0f / (dimension + dimension + 1);
|
||||||
|
|
||||||
//#pragma omp parallel for
|
#pragma omp parallel for
|
||||||
for (int y = 0; y < h; ++y) {
|
for (int y = 0; y < h; ++y) {
|
||||||
auto p = y * stride;
|
auto p = y * stride;
|
||||||
auto i = p; //current index
|
auto i = p; //current index
|
||||||
|
@ -335,7 +335,7 @@ bool effectDropShadowPrepare(RenderEffectDropShadow* params)
|
||||||
//A quite same integration with effectGaussianBlur(). See it for detailed comments.
|
//A quite same integration with effectGaussianBlur(). See it for detailed comments.
|
||||||
//surface[0]: the original image, to overlay it into the filtered image.
|
//surface[0]: the original image, to overlay it into the filtered image.
|
||||||
//surface[1]: temporary buffer for generating 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)) {
|
if (cmp->image.channelSize != sizeof(uint32_t)) {
|
||||||
TVGERR("SW_ENGINE", "Not supported grayscale Drop Shadow!");
|
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 stride = cmp->image.stride;
|
||||||
auto front = cmp->image.buf32;
|
auto front = cmp->image.buf32;
|
||||||
auto back = buffer[1]->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);
|
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;
|
if (effect->invalid) return false;
|
||||||
|
|
||||||
|
@ -658,14 +658,14 @@ bool SwRenderer::effect(RenderCompositor* cmp, const RenderEffect* effect, bool
|
||||||
|
|
||||||
switch (effect->type) {
|
switch (effect->type) {
|
||||||
case SceneEffect::GaussianBlur: {
|
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: {
|
case SceneEffect::DropShadow: {
|
||||||
auto cmp1 = request(surface->channelSize);
|
auto cmp1 = request(surface->channelSize);
|
||||||
cmp1->compositor->valid = false;
|
cmp1->compositor->valid = false;
|
||||||
auto cmp2 = request(surface->channelSize);
|
auto cmp2 = request(surface->channelSize);
|
||||||
SwSurface* surfaces[] = {cmp1, cmp2};
|
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;
|
cmp1->compositor->valid = true;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,7 +61,7 @@ public:
|
||||||
void clearCompositors();
|
void clearCompositors();
|
||||||
|
|
||||||
bool prepare(RenderEffect* effect) 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 SwRenderer* gen();
|
static SwRenderer* gen();
|
||||||
static bool init(uint32_t threads);
|
static bool init(uint32_t threads);
|
||||||
|
|
|
@ -343,7 +343,7 @@ public:
|
||||||
virtual bool endComposite(RenderCompositor* cmp) = 0;
|
virtual bool endComposite(RenderCompositor* cmp) = 0;
|
||||||
|
|
||||||
virtual bool prepare(RenderEffect* effect) = 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)
|
static inline bool MASK_REGION_MERGING(MaskMethod method)
|
||||||
|
|
|
@ -142,7 +142,7 @@ struct Scene::Impl
|
||||||
if (effects) {
|
if (effects) {
|
||||||
auto direct = effects->count == 1 ? true : false;
|
auto direct = effects->count == 1 ? true : false;
|
||||||
for (auto e = effects->begin(); e < effects->end(); ++e) {
|
for (auto e = effects->begin(); e < effects->end(); ++e) {
|
||||||
renderer->effect(cmp, *e, direct);
|
renderer->effect(cmp, *e, opacity, direct);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
renderer->endComposite(cmp);
|
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);
|
TVGLOG("WG_ENGINE", "SceneEffect(%d) is not supported", (int)effect->type);
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -52,7 +52,7 @@ public:
|
||||||
bool endComposite(RenderCompositor* cmp) override;
|
bool endComposite(RenderCompositor* cmp) override;
|
||||||
|
|
||||||
bool prepare(RenderEffect* effect) 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 WgRenderer* gen();
|
||||||
static bool init(uint32_t threads);
|
static bool init(uint32_t threads);
|
||||||
|
|
Loading…
Add table
Reference in a new issue