mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-07 21:23:32 +00:00
common picture: fix a composition bug.
Previously, a picture with a half-translucent mask would not function correctly. This fix addresses the bug by applying the expected composition step. Note: Even after applying this patch, a half-translucent mask with shape fill alpha will still not work properly. We should consider removing the fill alpha property, as it duplicates the Paint opacity. @Issue: https://github.com/thorvg/thorvg/issues/1423
This commit is contained in:
parent
c7d77b3517
commit
d8687314a6
4 changed files with 37 additions and 6 deletions
|
@ -37,7 +37,9 @@ void tvgDrawCmds(tvg::Canvas* canvas)
|
||||||
|
|
||||||
auto mask = tvg::Shape::gen();
|
auto mask = tvg::Shape::gen();
|
||||||
mask->appendCircle(WIDTH/2, HEIGHT/2, WIDTH/2, HEIGHT/2);
|
mask->appendCircle(WIDTH/2, HEIGHT/2, WIDTH/2, HEIGHT/2);
|
||||||
mask->fill(255, 255, 255, 100);
|
mask->fill(255, 255, 255, 255);
|
||||||
|
//Use the opacity for a half-translucent mask.
|
||||||
|
mask->opacity(125);
|
||||||
|
|
||||||
auto picture = tvg::Picture::gen();
|
auto picture = tvg::Picture::gen();
|
||||||
picture->load(EXAMPLE_DIR"/tiger.svg");
|
picture->load(EXAMPLE_DIR"/tiger.svg");
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
/* External Class Implementation */
|
/* External Class Implementation */
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
|
|
||||||
Picture::Picture() : pImpl(new Impl)
|
Picture::Picture() : pImpl(new Impl(this))
|
||||||
{
|
{
|
||||||
Paint::pImpl->id = TVG_CLASS_ID_PICTURE;
|
Paint::pImpl->id = TVG_CLASS_ID_PICTURE;
|
||||||
Paint::pImpl->method(new PaintMethod<Picture::Impl>(pImpl));
|
Paint::pImpl->method(new PaintMethod<Picture::Impl>(pImpl));
|
||||||
|
|
|
@ -67,7 +67,13 @@ struct Picture::Impl
|
||||||
RenderData rd = nullptr; //engine data
|
RenderData rd = nullptr; //engine data
|
||||||
float w = 0, h = 0;
|
float w = 0, h = 0;
|
||||||
RenderMesh rm; //mesh data
|
RenderMesh rm; //mesh data
|
||||||
|
Picture* picture = nullptr;
|
||||||
bool resizing = false;
|
bool resizing = false;
|
||||||
|
bool needComp = false; //need composition
|
||||||
|
|
||||||
|
Impl(Picture* p) : picture(p)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
~Impl()
|
~Impl()
|
||||||
{
|
{
|
||||||
|
@ -127,6 +133,19 @@ struct Picture::Impl
|
||||||
else return RenderTransform(pTransform, &tmp);
|
else return RenderTransform(pTransform, &tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool needComposition(uint32_t opacity)
|
||||||
|
{
|
||||||
|
//In this case, paint(scene) would try composition itself.
|
||||||
|
if (opacity < 255) return false;
|
||||||
|
|
||||||
|
//Composition test
|
||||||
|
const Paint* target;
|
||||||
|
auto method = picture->composite(&target);
|
||||||
|
if (!target || method == tvg::CompositeMethod::ClipPath) return false;
|
||||||
|
if (target->pImpl->opacity < 255 && target->pImpl->opacity > 0) return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
RenderData update(RenderMethod &renderer, const RenderTransform* pTransform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag pFlag, bool clipper)
|
RenderData update(RenderMethod &renderer, const RenderTransform* pTransform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag pFlag, bool clipper)
|
||||||
{
|
{
|
||||||
auto flag = load();
|
auto flag = load();
|
||||||
|
@ -139,6 +158,7 @@ struct Picture::Impl
|
||||||
loader->resize(paint, w, h);
|
loader->resize(paint, w, h);
|
||||||
resizing = false;
|
resizing = false;
|
||||||
}
|
}
|
||||||
|
needComp = needComposition(opacity) ? true : false;
|
||||||
rd = paint->pImpl->update(renderer, pTransform, opacity, clips, static_cast<RenderUpdateFlag>(pFlag | flag), clipper);
|
rd = paint->pImpl->update(renderer, pTransform, opacity, clips, static_cast<RenderUpdateFlag>(pFlag | flag), clipper);
|
||||||
}
|
}
|
||||||
return rd;
|
return rd;
|
||||||
|
@ -146,9 +166,18 @@ struct Picture::Impl
|
||||||
|
|
||||||
bool render(RenderMethod &renderer)
|
bool render(RenderMethod &renderer)
|
||||||
{
|
{
|
||||||
|
bool ret = false;
|
||||||
if (surface) return renderer.renderImage(rd);
|
if (surface) return renderer.renderImage(rd);
|
||||||
else if (paint) return paint->pImpl->render(renderer);
|
else if (paint) {
|
||||||
return false;
|
Compositor* cmp = nullptr;
|
||||||
|
if (needComp) {
|
||||||
|
cmp = renderer.target(bounds(renderer), renderer.colorSpace());
|
||||||
|
renderer.beginComposite(cmp, CompositeMethod::None, 255);
|
||||||
|
}
|
||||||
|
ret = paint->pImpl->render(renderer);
|
||||||
|
if (cmp) renderer.endComposite(cmp);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool viewbox(float* x, float* y, float* w, float* h)
|
bool viewbox(float* x, float* y, float* w, float* h)
|
||||||
|
|
|
@ -59,10 +59,10 @@ struct SceneIterator : Iterator
|
||||||
struct Scene::Impl
|
struct Scene::Impl
|
||||||
{
|
{
|
||||||
Array<Paint*> paints;
|
Array<Paint*> paints;
|
||||||
uint8_t opacity; //for composition
|
|
||||||
RenderMethod* renderer = nullptr; //keep it for explicit clear
|
RenderMethod* renderer = nullptr; //keep it for explicit clear
|
||||||
RenderData rd = nullptr;
|
RenderData rd = nullptr;
|
||||||
Scene* scene = nullptr;
|
Scene* scene = nullptr;
|
||||||
|
uint8_t opacity; //for composition
|
||||||
|
|
||||||
Impl(Scene* s) : scene(s)
|
Impl(Scene* s) : scene(s)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Reference in a new issue