mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-08 13:43:43 +00:00
renderer: optimize the ClipPath fast-track.
this optimization applies when the clipper is not an axis-aligned rectangle under the following conditions: a. Coverage where the clipper is a regional superset of the viewport. b. Coverage where the clipper is completely outside of the viewport. issue: https://github.com/thorvg/thorvg/issues/2332
This commit is contained in:
parent
3b821c33cc
commit
abb083eb02
1 changed files with 52 additions and 15 deletions
|
@ -41,8 +41,39 @@
|
|||
}
|
||||
|
||||
|
||||
static Result _clipRect(RenderMethod* renderer, const Point* pts, const RenderTransform* pTransform, RenderTransform* rTransform, RenderRegion& before)
|
||||
{
|
||||
//sorting
|
||||
Point tmp[4];
|
||||
Point min = {FLT_MAX, FLT_MAX};
|
||||
Point max = {0.0f, 0.0f};
|
||||
|
||||
static Result _compFastTrack(Paint* cmpTarget, const RenderTransform* pTransform, RenderTransform* rTransform, RenderRegion& viewport)
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
tmp[i] = pts[i];
|
||||
if (rTransform) tmp[i] *= rTransform->m;
|
||||
if (pTransform) tmp[i] *= pTransform->m;
|
||||
if (tmp[i].x < min.x) min.x = tmp[i].x;
|
||||
if (tmp[i].x > max.x) max.x = tmp[i].x;
|
||||
if (tmp[i].y < min.y) min.y = tmp[i].y;
|
||||
if (tmp[i].y > max.y) max.y = tmp[i].y;
|
||||
}
|
||||
|
||||
float region[4] = {float(before.x), float(before.x + before.w), float(before.y), float(before.y + before.h)};
|
||||
|
||||
//figure out if the clipper is a superset of the current viewport(before) region
|
||||
if (min.x <= region[0] && max.x >= region[1] && min.y <= region[2] && max.y >= region[3]) {
|
||||
//viewport region is same, nothing to do.
|
||||
return Result::Success;
|
||||
//figure out if the clipper is totally outside of the viewport
|
||||
} else if (max.x <= region[0] || min.x >= region[1] || max.y <= region[2] || min.y >= region[3]) {
|
||||
renderer->viewport({0, 0, 0, 0});
|
||||
return Result::Success;
|
||||
}
|
||||
return Result::InsufficientCondition;
|
||||
}
|
||||
|
||||
|
||||
static Result _compFastTrack(RenderMethod* renderer, Paint* cmpTarget, const RenderTransform* pTransform, RenderTransform* rTransform, RenderRegion& before)
|
||||
{
|
||||
/* Access Shape class by Paint is bad... but it's ok still it's an internal usage. */
|
||||
auto shape = static_cast<Shape*>(cmpTarget);
|
||||
|
@ -58,9 +89,13 @@ static Result _compFastTrack(Paint* cmpTarget, const RenderTransform* pTransform
|
|||
|
||||
if (rTransform) rTransform->update();
|
||||
|
||||
//No rotation and no skewing
|
||||
if (pTransform && (!mathRightAngle(&pTransform->m) || mathSkewed(&pTransform->m))) return Result::InsufficientCondition;
|
||||
if (rTransform && (!mathRightAngle(&rTransform->m) || mathSkewed(&rTransform->m))) return Result::InsufficientCondition;
|
||||
//No rotation and no skewing, still can try out clipping the rect region.
|
||||
auto tryClip = false;
|
||||
|
||||
if (pTransform && (!mathRightAngle(&pTransform->m) || mathSkewed(&pTransform->m))) tryClip = true;
|
||||
if (rTransform && (!mathRightAngle(&rTransform->m) || mathSkewed(&rTransform->m))) tryClip = true;
|
||||
|
||||
if (tryClip) return _clipRect(renderer, pts, pTransform, rTransform, before);
|
||||
|
||||
//Perpendicular Rectangle?
|
||||
auto pt1 = pts + 0;
|
||||
|
@ -71,6 +106,8 @@ static Result _compFastTrack(Paint* cmpTarget, const RenderTransform* pTransform
|
|||
if ((mathEqual(pt1->x, pt2->x) && mathEqual(pt2->y, pt3->y) && mathEqual(pt3->x, pt4->x) && mathEqual(pt1->y, pt4->y)) ||
|
||||
(mathEqual(pt2->x, pt3->x) && mathEqual(pt1->y, pt2->y) && mathEqual(pt1->x, pt4->x) && mathEqual(pt3->y, pt4->y))) {
|
||||
|
||||
RenderRegion after;
|
||||
|
||||
auto v1 = *pt1;
|
||||
auto v2 = *pt3;
|
||||
|
||||
|
@ -88,13 +125,16 @@ static Result _compFastTrack(Paint* cmpTarget, const RenderTransform* pTransform
|
|||
if (v1.x > v2.x) std::swap(v1.x, v2.x);
|
||||
if (v1.y > v2.y) std::swap(v1.y, v2.y);
|
||||
|
||||
viewport.x = static_cast<int32_t>(v1.x);
|
||||
viewport.y = static_cast<int32_t>(v1.y);
|
||||
viewport.w = static_cast<int32_t>(ceil(v2.x - viewport.x));
|
||||
viewport.h = static_cast<int32_t>(ceil(v2.y - viewport.y));
|
||||
after.x = static_cast<int32_t>(v1.x);
|
||||
after.y = static_cast<int32_t>(v1.y);
|
||||
after.w = static_cast<int32_t>(ceil(v2.x - after.x));
|
||||
after.h = static_cast<int32_t>(ceil(v2.y - after.y));
|
||||
|
||||
if (viewport.w < 0) viewport.w = 0;
|
||||
if (viewport.h < 0) viewport.h = 0;
|
||||
if (after.w < 0) after.w = 0;
|
||||
if (after.h < 0) after.h = 0;
|
||||
|
||||
after.intersect(before);
|
||||
renderer->viewport(after);
|
||||
|
||||
return Result::Success;
|
||||
}
|
||||
|
@ -255,11 +295,8 @@ RenderData Paint::Impl::update(RenderMethod* renderer, const RenderTransform* pT
|
|||
}
|
||||
}
|
||||
if (tryFastTrack) {
|
||||
RenderRegion viewport2;
|
||||
if ((compFastTrack = _compFastTrack(target, pTransform, target->pImpl->rTransform, viewport2)) == Result::Success) {
|
||||
viewport = renderer->viewport();
|
||||
viewport2.intersect(viewport);
|
||||
renderer->viewport(viewport2);
|
||||
if ((compFastTrack = _compFastTrack(renderer, target, pTransform, target->pImpl->rTransform, viewport)) == Result::Success) {
|
||||
target->pImpl->ctxFlag |= ContextFlag::FastTrack;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue