common: ignoring color/alpha/opacity of a clip object

According to the svg specs clip's fill and opacity
should be ignored. Till now setting the alpha/opacity
value to zero resulted in the shape's rendering abort.

@Issue: https://github.com/Samsung/thorvg/issues/1192
This commit is contained in:
Mira Grudzinska 2022-12-27 16:21:42 +01:00 committed by Mira Grudzinska
parent b58c20b881
commit 0de3872be3
4 changed files with 34 additions and 3 deletions

View file

@ -363,6 +363,20 @@ public:
*/ */
CompositeMethod composite(const Paint** target) const noexcept; CompositeMethod composite(const Paint** target) const noexcept;
/**
* @brief Gets the composition source object and the composition method.
*
* @param[out] source The paint of the composition source object.
* @param[out] method The method used to composite the source object with the target.
*
* @return Result::Success when the paint object used as a composition target, Result::InsufficientCondition otherwise.
*
* @warning Please do not use it, this API is not official one. It could be modified in the next version.
*
* @BETA_API
*/
Result composite(const Paint** source, CompositeMethod* method) const noexcept;
/** /**
* @brief Return the unique id value of the paint instance. * @brief Return the unique id value of the paint instance.
* *

View file

@ -77,7 +77,9 @@ struct SwShapeTask : SwTask
void run(unsigned tid) override void run(unsigned tid) override
{ {
if (opacity == 0) return; //Invisible auto compMethod = CompositeMethod::None;
auto usedAsClip = (sdata->composite(nullptr, &compMethod) == Result::Success) && (compMethod == CompositeMethod::ClipPath);
if (opacity == 0 && !usedAsClip) return; //Invisible
uint8_t strokeAlpha = 0; uint8_t strokeAlpha = 0;
auto visibleStroke = false; auto visibleStroke = false;
@ -99,7 +101,7 @@ struct SwShapeTask : SwTask
sdata->fillColor(nullptr, nullptr, nullptr, &alpha); sdata->fillColor(nullptr, nullptr, nullptr, &alpha);
alpha = static_cast<uint8_t>(static_cast<uint32_t>(alpha) * opacity / 255); alpha = static_cast<uint8_t>(static_cast<uint32_t>(alpha) * opacity / 255);
visibleFill = (alpha > 0 || sdata->fill()); visibleFill = (alpha > 0 || sdata->fill());
if (visibleFill || visibleStroke) { if (visibleFill || visibleStroke || usedAsClip) {
shapeReset(&shape); shapeReset(&shape);
if (!shapePrepare(&shape, sdata, transform, clipRegion, bbox, mpool, tid, clips.count > 0 ? true : false)) goto err; if (!shapePrepare(&shape, sdata, transform, clipRegion, bbox, mpool, tid, clips.count > 0 ? true : false)) goto err;
} }
@ -111,7 +113,7 @@ struct SwShapeTask : SwTask
//Fill //Fill
if (flags & (RenderUpdateFlag::Gradient | RenderUpdateFlag::Transform | RenderUpdateFlag::Color)) { if (flags & (RenderUpdateFlag::Gradient | RenderUpdateFlag::Transform | RenderUpdateFlag::Color)) {
if (visibleFill) { if (visibleFill || usedAsClip) {
/* We assume that if stroke width is bigger than 2, /* We assume that if stroke width is bigger than 2,
shape outline below stroke could be full covered by stroke drawing. shape outline below stroke could be full covered by stroke drawing.
Thus it turns off antialising in that condition. Thus it turns off antialising in that condition.

View file

@ -385,6 +385,19 @@ CompositeMethod Paint::composite(const Paint** target) const noexcept
} }
Result Paint::composite(const Paint** source, CompositeMethod* method) const noexcept
{
if (source) *source = pImpl->compSource;
auto met = (pImpl->compSource && pImpl->compSource->pImpl->compData ?
pImpl->compSource->pImpl->compData->method : CompositeMethod::None);
if (method) *method = met;
if (pImpl->compSource != nullptr && met != CompositeMethod::None)
return Result::Success;
return Result::InsufficientCondition;
}
Result Paint::opacity(uint8_t o) noexcept Result Paint::opacity(uint8_t o) noexcept
{ {
if (pImpl->opacity == o) return Result::Success; if (pImpl->opacity == o) return Result::Success;

View file

@ -63,6 +63,7 @@ namespace tvg
StrategyMethod* smethod = nullptr; StrategyMethod* smethod = nullptr;
RenderTransform* rTransform = nullptr; RenderTransform* rTransform = nullptr;
Composite* compData = nullptr; Composite* compData = nullptr;
Paint* compSource = nullptr;
uint32_t renderFlag = RenderUpdateFlag::None; uint32_t renderFlag = RenderUpdateFlag::None;
uint32_t ctxFlag = ContextFlag::Invalid; uint32_t ctxFlag = ContextFlag::Invalid;
uint32_t id; uint32_t id;
@ -137,6 +138,7 @@ namespace tvg
if (!target && method == CompositeMethod::None) return true; if (!target && method == CompositeMethod::None) return true;
compData = static_cast<Composite*>(calloc(1, sizeof(Composite))); compData = static_cast<Composite*>(calloc(1, sizeof(Composite)));
} }
target->pImpl->compSource = source;
compData->target = target; compData->target = target;
compData->source = source; compData->source = source;
compData->method = method; compData->method = method;