mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-20 06:52:03 +00:00
common: order(bool strokeFirst) api introduced
The new api is introduced to handle the rendering order of a stroke and a fill. By default fill is rendered as the first one, stroke as the second one. This order can be reversed by calling order(true). @Issue: https://github.com/thorvg/thorvg/issues/1340
This commit is contained in:
parent
e61857f27d
commit
69a9583354
5 changed files with 64 additions and 19 deletions
12
inc/thorvg.h
12
inc/thorvg.h
|
@ -977,6 +977,18 @@ public:
|
|||
*/
|
||||
Result fill(FillRule r) noexcept;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Sets the rendering order of the stroke and the fill.
|
||||
*
|
||||
* @param[in] strokeFirst If @c true the stroke is rendered before the fill, otherwise the stroke is rendered as the second one (the default option).
|
||||
*
|
||||
* @return Result::Success when succeed, Result::FailedAllocation otherwise.
|
||||
* @BETA_API
|
||||
*/
|
||||
Result order(bool strokeFirst) noexcept;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Gets the commands data of the path.
|
||||
*
|
||||
|
|
|
@ -96,7 +96,7 @@ struct SwShapeTask : SwTask
|
|||
}
|
||||
|
||||
void run(unsigned tid) override
|
||||
{
|
||||
{
|
||||
if (opacity == 0 && !clipper) return; //Invisible
|
||||
|
||||
uint8_t strokeAlpha = 0;
|
||||
|
@ -136,7 +136,7 @@ struct SwShapeTask : SwTask
|
|||
shape outline below stroke could be full covered by stroke drawing.
|
||||
Thus it turns off antialising in that condition.
|
||||
Also, it shouldn't be dash style. */
|
||||
auto antiAlias = (strokeAlpha == 255 && rshape->strokeWidth() > 2 && rshape->strokeDash(nullptr) == 0) ? false : true;
|
||||
auto antiAlias = strokeAlpha < 255 || rshape->strokeWidth() <= 2 || rshape->strokeDash(nullptr) > 0 || (rshape->stroke && rshape->stroke->strokeFirst);
|
||||
|
||||
if (!shapeGenRle(&shape, rshape, antiAlias)) goto err;
|
||||
}
|
||||
|
@ -322,6 +322,31 @@ static void _termEngine()
|
|||
}
|
||||
|
||||
|
||||
static void _renderFill(SwShapeTask* task, SwSurface* surface, uint32_t opacity)
|
||||
{
|
||||
uint8_t r, g, b, a;
|
||||
if (auto fill = task->rshape->fill) {
|
||||
rasterGradientShape(surface, &task->shape, fill->identifier());
|
||||
} else {
|
||||
task->rshape->fillColor(&r, &g, &b, &a);
|
||||
a = static_cast<uint8_t>((opacity * (uint32_t) a) / 255);
|
||||
if (a > 0) rasterShape(surface, &task->shape, r, g, b, a);
|
||||
}
|
||||
}
|
||||
|
||||
static void _renderStroke(SwShapeTask* task, SwSurface* surface, uint32_t opacity)
|
||||
{
|
||||
uint8_t r, g, b, a;
|
||||
if (auto strokeFill = task->rshape->strokeFill()) {
|
||||
rasterGradientStroke(surface, &task->shape, strokeFill->identifier());
|
||||
} else {
|
||||
if (task->rshape->strokeColor(&r, &g, &b, &a)) {
|
||||
a = static_cast<uint8_t>((opacity * (uint32_t) a) / 255);
|
||||
if (a > 0) rasterStroke(surface, &task->shape, r, g, b, a);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* External Class Implementation */
|
||||
/************************************************************************/
|
||||
|
@ -482,23 +507,12 @@ bool SwRenderer::renderShape(RenderData data)
|
|||
}
|
||||
|
||||
//Main raster stage
|
||||
uint8_t r, g, b, a;
|
||||
|
||||
if (auto fill = task->rshape->fill) {
|
||||
rasterGradientShape(surface, &task->shape, fill->identifier());
|
||||
if (task->rshape->stroke && task->rshape->stroke->strokeFirst) {
|
||||
_renderStroke(task, surface, opacity);
|
||||
_renderFill(task, surface, opacity);
|
||||
} else {
|
||||
task->rshape->fillColor(&r, &g, &b, &a);
|
||||
a = static_cast<uint8_t>((opacity * (uint32_t) a) / 255);
|
||||
if (a > 0) rasterShape(surface, &task->shape, r, g, b, a);
|
||||
}
|
||||
|
||||
if (auto strokeFill = task->rshape->strokeFill()) {
|
||||
rasterGradientStroke(surface, &task->shape, strokeFill->identifier());
|
||||
} else {
|
||||
if (task->rshape->strokeColor(&r, &g, &b, &a)) {
|
||||
a = static_cast<uint8_t>((opacity * (uint32_t) a) / 255);
|
||||
if (a > 0) rasterStroke(surface, &task->shape, r, g, b, a);
|
||||
}
|
||||
_renderFill(task, surface, opacity);
|
||||
_renderStroke(task, surface, opacity);
|
||||
}
|
||||
|
||||
if (task->cmpStroking) endComposite(cmp);
|
||||
|
|
|
@ -94,6 +94,7 @@ struct RenderStroke
|
|||
uint32_t dashCnt = 0;
|
||||
StrokeCap cap = StrokeCap::Square;
|
||||
StrokeJoin join = StrokeJoin::Bevel;
|
||||
bool strokeFirst = false;
|
||||
|
||||
~RenderStroke()
|
||||
{
|
||||
|
|
|
@ -288,6 +288,14 @@ const Fill* Shape::fill() const noexcept
|
|||
}
|
||||
|
||||
|
||||
Result Shape::order(bool strokeFirst) noexcept
|
||||
{
|
||||
if (!pImpl->strokeFirst(strokeFirst)) return Result::FailedAllocation;
|
||||
|
||||
return Result::Success;
|
||||
}
|
||||
|
||||
|
||||
Result Shape::stroke(float width) noexcept
|
||||
{
|
||||
if (!pImpl->strokeWidth(width)) return Result::FailedAllocation;
|
||||
|
@ -390,4 +398,4 @@ Result Shape::fill(FillRule r) noexcept
|
|||
FillRule Shape::fillRule() const noexcept
|
||||
{
|
||||
return pImpl->rs.rule;
|
||||
}
|
||||
}
|
|
@ -262,6 +262,15 @@ struct Shape::Impl
|
|||
return true;
|
||||
}
|
||||
|
||||
bool strokeFirst(bool strokeFirst)
|
||||
{
|
||||
if (!rs.stroke) rs.stroke = new RenderStroke();
|
||||
rs.stroke->strokeFirst = strokeFirst;
|
||||
flag |= RenderUpdateFlag::Stroke;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Paint* duplicate()
|
||||
{
|
||||
auto ret = Shape::gen();
|
||||
|
@ -295,6 +304,7 @@ struct Shape::Impl
|
|||
dup->rs.stroke->dashCnt = rs.stroke->dashCnt;
|
||||
dup->rs.stroke->cap = rs.stroke->cap;
|
||||
dup->rs.stroke->join = rs.stroke->join;
|
||||
dup->rs.stroke->strokeFirst = rs.stroke->strokeFirst;
|
||||
memcpy(dup->rs.stroke->color, rs.stroke->color, sizeof(rs.stroke->color));
|
||||
|
||||
if (rs.stroke->dashCnt > 0) {
|
||||
|
|
Loading…
Add table
Reference in a new issue