From 324bff30d15b3be66144a681a5ffa813b7592143 Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Thu, 19 Dec 2024 14:30:31 +0900 Subject: [PATCH] sw_engine: allow the stroke clipper clipping with a stroke is useful for various visual effects. TVG can support this approach as it offers better efficiency compared to alpha masking. If a valid stroke is defined in the clipper shape, the renderer prioritizes clipping with the stroke over the shape's fill. issue: https://github.com/thorvg/thorvg/issues/3063 --- src/renderer/sw_engine/tvgSwRenderer.cpp | 12 +++++------- src/renderer/sw_engine/tvgSwShape.cpp | 4 ---- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/src/renderer/sw_engine/tvgSwRenderer.cpp b/src/renderer/sw_engine/tvgSwRenderer.cpp index 7680548f..73ec94a9 100644 --- a/src/renderer/sw_engine/tvgSwRenderer.cpp +++ b/src/renderer/sw_engine/tvgSwRenderer.cpp @@ -88,14 +88,14 @@ struct SwShapeTask : SwTask return strokeWidth < 2.0f || rshape->stroke->dashCnt > 0 || rshape->stroke->strokeFirst || rshape->strokeTrim() || rshape->stroke->color.a < 255; } - float validStrokeWidth() + float validStrokeWidth(bool clipper) { if (!rshape->stroke) return 0.0f; auto width = rshape->stroke->width; if (tvg::zero(width)) return 0.0f; - if (!rshape->stroke->fill && (MULTIPLY(rshape->stroke->color.a, opacity) == 0)) return 0.0f; + if (!clipper && (!rshape->stroke->fill && (MULTIPLY(rshape->stroke->color.a, opacity) == 0))) return 0.0f; if (tvg::zero(rshape->stroke->trim.begin - rshape->stroke->trim.end)) return 0.0f; return (width * sqrt(transform.e11 * transform.e11 + transform.e12 * transform.e12)); @@ -103,8 +103,9 @@ struct SwShapeTask : SwTask bool clip(SwRle* target) override { + if (shape.strokeRle) return rleClip(target, shape.strokeRle); if (shape.fastTrack) return rleClip(target, &bbox); - else if (shape.rle) return rleClip(target, shape.rle); + if (shape.rle) return rleClip(target, shape.rle); return false; } @@ -116,7 +117,7 @@ struct SwShapeTask : SwTask return; } - auto strokeWidth = validStrokeWidth(); + auto strokeWidth = validStrokeWidth(clipper); SwBBox renderRegion{}; auto visibleFill = false; @@ -154,14 +155,11 @@ struct SwShapeTask : SwTask if (flags & (RenderUpdateFlag::Path | RenderUpdateFlag::Stroke | RenderUpdateFlag::Transform)) { if (strokeWidth > 0.0f) { shapeResetStroke(&shape, rshape, transform); - if (!shapeGenStrokeRle(&shape, rshape, transform, bbox, renderRegion, mpool, tid)) goto err; if (auto fill = rshape->strokeFill()) { auto ctable = (flags & RenderUpdateFlag::GradientStroke) ? true : false; if (ctable) shapeResetStrokeFill(&shape); if (!shapeGenStrokeFillColors(&shape, fill, transform, surface, opacity, ctable)) goto err; - } else { - shapeDelStrokeFill(&shape); } } else { shapeDelStroke(&shape); diff --git a/src/renderer/sw_engine/tvgSwShape.cpp b/src/renderer/sw_engine/tvgSwShape.cpp index cae99856..ccb592e8 100644 --- a/src/renderer/sw_engine/tvgSwShape.cpp +++ b/src/renderer/sw_engine/tvgSwShape.cpp @@ -511,10 +511,6 @@ bool shapePrepared(const SwShape* shape) bool shapeGenRle(SwShape* shape, TVG_UNUSED const RenderShape* rshape, bool antiAlias) { - //FIXME: Should we draw it? - //Case: Stroke Line - //if (shape.outline->opened) return true; - //Case A: Fast Track Rectangle Drawing if (shape->fastTrack) return true;