diff --git a/src/renderer/tvgPaint.cpp b/src/renderer/tvgPaint.cpp index 10fb13e2..d537acaa 100644 --- a/src/renderer/tvgPaint.cpp +++ b/src/renderer/tvgPaint.cpp @@ -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(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(v1.x); - viewport.y = static_cast(v1.y); - viewport.w = static_cast(ceil(v2.x - viewport.x)); - viewport.h = static_cast(ceil(v2.y - viewport.y)); + after.x = static_cast(v1.x); + after.y = static_cast(v1.y); + after.w = static_cast(ceil(v2.x - after.x)); + after.h = static_cast(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); + viewport = renderer->viewport(); + if ((compFastTrack = _compFastTrack(renderer, target, pTransform, target->pImpl->rTransform, viewport)) == Result::Success) { target->pImpl->ctxFlag |= ContextFlag::FastTrack; } }