common: enhance clipping behavior.

If a paint is used as a clipper, it must be determined in the paint behavior.
Propagate its decision to the immediate derived classes so that
not only shapes but also scenes must be dealt as a clipper properly.

This revised this change 0de3872be3
for better a solution.
This commit is contained in:
Hermet Park 2023-01-28 11:36:54 +09:00
parent 6452f4a591
commit d701f6dae4
10 changed files with 26 additions and 25 deletions

View file

@ -197,7 +197,7 @@ RenderData GlRenderer::prepare(TVG_UNUSED Surface* image, TVG_UNUSED Polygon* tr
} }
RenderData GlRenderer::prepare(const Shape& shape, RenderData data, const RenderTransform* transform, TVG_UNUSED uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags) RenderData GlRenderer::prepare(const Shape& shape, RenderData data, const RenderTransform* transform, TVG_UNUSED uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags, TVG_UNUSED bool clipper)
{ {
//prepare shape data //prepare shape data
GlShape* sdata = static_cast<GlShape*>(data); GlShape* sdata = static_cast<GlShape*>(data);

View file

@ -30,7 +30,7 @@ class GlRenderer : public RenderMethod
public: public:
Surface surface = {nullptr, 0, 0, 0}; Surface surface = {nullptr, 0, 0, 0};
RenderData prepare(const Shape& shape, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags) override; RenderData prepare(const Shape& shape, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags, bool clipper) override;
RenderData prepare(Surface* image, Polygon* triangles, uint32_t triangleCnt, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags) override; RenderData prepare(Surface* image, Polygon* triangles, uint32_t triangleCnt, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags) override;
bool preRender() override; bool preRender() override;
bool renderShape(RenderData data) override; bool renderShape(RenderData data) override;

View file

@ -74,12 +74,11 @@ struct SwShapeTask : SwTask
SwShape shape; SwShape shape;
const Shape* sdata = nullptr; const Shape* sdata = nullptr;
bool cmpStroking = false; bool cmpStroking = false;
bool clipper = false;
void run(unsigned tid) override void run(unsigned tid) override
{ {
auto compMethod = CompositeMethod::None; if (opacity == 0 && !clipper) return; //Invisible
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;
@ -101,7 +100,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 || usedAsClip) { if (visibleFill || visibleStroke || clipper) {
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;
} }
@ -113,7 +112,7 @@ struct SwShapeTask : SwTask
//Fill //Fill
if (flags & (RenderUpdateFlag::Gradient | RenderUpdateFlag::Transform | RenderUpdateFlag::Color)) { if (flags & (RenderUpdateFlag::Gradient | RenderUpdateFlag::Transform | RenderUpdateFlag::Color)) {
if (visibleFill || usedAsClip) { if (visibleFill || clipper) {
/* 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.
@ -644,13 +643,14 @@ RenderData SwRenderer::prepare(Surface* image, Polygon* triangles, uint32_t tria
} }
RenderData SwRenderer::prepare(const Shape& sdata, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags) RenderData SwRenderer::prepare(const Shape& sdata, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags, bool clipper)
{ {
//prepare task //prepare task
auto task = static_cast<SwShapeTask*>(data); auto task = static_cast<SwShapeTask*>(data);
if (!task) { if (!task) {
task = new SwShapeTask; task = new SwShapeTask;
task->sdata = &sdata; task->sdata = &sdata;
task->clipper = clipper;
} }
return prepareCommon(task, transform, opacity, clips, flags); return prepareCommon(task, transform, opacity, clips, flags);
} }

View file

@ -36,7 +36,7 @@ namespace tvg
class SwRenderer : public RenderMethod class SwRenderer : public RenderMethod
{ {
public: public:
RenderData prepare(const Shape& shape, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags) override; RenderData prepare(const Shape& shape, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags, bool clipper) override;
RenderData prepare(Surface* image, Polygon* triangles, uint32_t triangleCnt, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags) override; RenderData prepare(Surface* image, Polygon* triangles, uint32_t triangleCnt, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags) override;
bool preRender() override; bool preRender() override;
bool renderShape(RenderData data) override; bool renderShape(RenderData data) override;

View file

@ -184,7 +184,7 @@ bool Paint::Impl::render(RenderMethod& renderer)
} }
void* Paint::Impl::update(RenderMethod& renderer, const RenderTransform* pTransform, uint32_t opacity, Array<RenderData>& clips, uint32_t pFlag) void* Paint::Impl::update(RenderMethod& renderer, const RenderTransform* pTransform, uint32_t opacity, Array<RenderData>& clips, uint32_t pFlag, bool clipper)
{ {
if (renderFlag & RenderUpdateFlag::Transform) { if (renderFlag & RenderUpdateFlag::Transform) {
if (!rTransform) return nullptr; if (!rTransform) return nullptr;
@ -224,7 +224,8 @@ void* Paint::Impl::update(RenderMethod& renderer, const RenderTransform* pTransf
} }
} }
if (!compFastTrack) { if (!compFastTrack) {
tdata = target->pImpl->update(renderer, pTransform, 255, clips, pFlag); auto clipper = compData->method == CompositeMethod::ClipPath ? true : false;
tdata = target->pImpl->update(renderer, pTransform, 255, clips, pFlag, clipper);
if (method == CompositeMethod::ClipPath) clips.push(tdata); if (method == CompositeMethod::ClipPath) clips.push(tdata);
} }
} }
@ -237,10 +238,10 @@ void* Paint::Impl::update(RenderMethod& renderer, const RenderTransform* pTransf
if (rTransform && pTransform) { if (rTransform && pTransform) {
RenderTransform outTransform(pTransform, rTransform); RenderTransform outTransform(pTransform, rTransform);
edata = smethod->update(renderer, &outTransform, opacity, clips, newFlag); edata = smethod->update(renderer, &outTransform, opacity, clips, newFlag, clipper);
} else { } else {
auto outTransform = pTransform ? pTransform : rTransform; auto outTransform = pTransform ? pTransform : rTransform;
edata = smethod->update(renderer, outTransform, opacity, clips, newFlag); edata = smethod->update(renderer, outTransform, opacity, clips, newFlag, clipper);
} }
/* 3. Composition Post Processing */ /* 3. Composition Post Processing */

View file

@ -43,7 +43,7 @@ namespace tvg
virtual ~StrategyMethod() {} virtual ~StrategyMethod() {}
virtual bool dispose(RenderMethod& renderer) = 0; virtual bool dispose(RenderMethod& renderer) = 0;
virtual void* update(RenderMethod& renderer, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag pFlag) = 0; //Return engine data if it has. virtual void* update(RenderMethod& renderer, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag pFlag, bool clipper) = 0; //Return engine data if it has.
virtual bool render(RenderMethod& renderer) = 0; virtual bool render(RenderMethod& renderer) = 0;
virtual bool bounds(float* x, float* y, float* w, float* h) = 0; virtual bool bounds(float* x, float* y, float* w, float* h) = 0;
virtual RenderRegion bounds(RenderMethod& renderer) const = 0; virtual RenderRegion bounds(RenderMethod& renderer) const = 0;
@ -149,7 +149,7 @@ namespace tvg
bool scale(float factor); bool scale(float factor);
bool translate(float x, float y); bool translate(float x, float y);
bool bounds(float* x, float* y, float* w, float* h, bool transformed); bool bounds(float* x, float* y, float* w, float* h, bool transformed);
void* update(RenderMethod& renderer, const RenderTransform* pTransform, uint32_t opacity, Array<RenderData>& clips, uint32_t pFlag); void* update(RenderMethod& renderer, const RenderTransform* pTransform, uint32_t opacity, Array<RenderData>& clips, uint32_t pFlag, bool clipper = false);
bool render(RenderMethod& renderer); bool render(RenderMethod& renderer);
Paint* duplicate(); Paint* duplicate();
}; };
@ -178,9 +178,9 @@ namespace tvg
return inst->dispose(renderer); return inst->dispose(renderer);
} }
void* update(RenderMethod& renderer, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag renderFlag) override void* update(RenderMethod& renderer, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag renderFlag, bool clipper) override
{ {
return inst->update(renderer, transform, opacity, clips, renderFlag); return inst->update(renderer, transform, opacity, clips, renderFlag, clipper);
} }
bool render(RenderMethod& renderer) override bool render(RenderMethod& renderer) override

View file

@ -126,7 +126,7 @@ struct Picture::Impl
else return RenderTransform(pTransform, &tmp); else return RenderTransform(pTransform, &tmp);
} }
void* update(RenderMethod &renderer, const RenderTransform* pTransform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag pFlag) void* update(RenderMethod &renderer, const RenderTransform* pTransform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag pFlag, bool clipper)
{ {
auto flag = reload(); auto flag = reload();
@ -138,7 +138,7 @@ struct Picture::Impl
loader->resize(paint, w, h); loader->resize(paint, w, h);
resizing = false; resizing = false;
} }
rdata = paint->pImpl->update(renderer, pTransform, opacity, clips, static_cast<RenderUpdateFlag>(pFlag | flag)); rdata = paint->pImpl->update(renderer, pTransform, opacity, clips, static_cast<RenderUpdateFlag>(pFlag | flag), clipper);
} }
return rdata; return rdata;
} }

View file

@ -90,7 +90,7 @@ class RenderMethod
{ {
public: public:
virtual ~RenderMethod() {} virtual ~RenderMethod() {}
virtual RenderData prepare(const Shape& shape, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags) = 0; virtual RenderData prepare(const Shape& shape, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags, bool clipper) = 0;
virtual RenderData prepare(Surface* image, Polygon* triangles, uint32_t triangleCnt, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags) = 0; virtual RenderData prepare(Surface* image, Polygon* triangles, uint32_t triangleCnt, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags) = 0;
virtual bool preRender() = 0; virtual bool preRender() = 0;
virtual bool renderShape(RenderData data) = 0; virtual bool renderShape(RenderData data) = 0;

View file

@ -102,7 +102,7 @@ struct Scene::Impl
return false; return false;
} }
void* update(RenderMethod &renderer, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flag) void* update(RenderMethod &renderer, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flag, bool clipper)
{ {
/* Overriding opacity value. If this scene is half-translucent, /* Overriding opacity value. If this scene is half-translucent,
It must do intermeidate composition with that opacity value. */ It must do intermeidate composition with that opacity value. */
@ -110,7 +110,7 @@ struct Scene::Impl
if (needComposition(opacity)) opacity = 255; if (needComposition(opacity)) opacity = 255;
for (auto paint = paints.data; paint < (paints.data + paints.count); ++paint) { for (auto paint = paints.data; paint < (paints.data + paints.count); ++paint) {
(*paint)->pImpl->update(renderer, transform, opacity, clips, static_cast<uint32_t>(flag)); (*paint)->pImpl->update(renderer, transform, opacity, clips, static_cast<uint32_t>(flag), clipper);
} }
/* FXIME: it requires to return list of children engine data /* FXIME: it requires to return list of children engine data

View file

@ -235,9 +235,9 @@ struct Shape::Impl
return renderer.renderShape(rdata); return renderer.renderShape(rdata);
} }
void* update(RenderMethod& renderer, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag pFlag) void* update(RenderMethod& renderer, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag pFlag, bool clipper)
{ {
this->rdata = renderer.prepare(*shape, this->rdata, transform, opacity, clips, static_cast<RenderUpdateFlag>(pFlag | flag)); this->rdata = renderer.prepare(*shape, this->rdata, transform, opacity, clips, static_cast<RenderUpdateFlag>(pFlag | flag), clipper);
flag = RenderUpdateFlag::None; flag = RenderUpdateFlag::None;
return this->rdata; return this->rdata;
} }