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;
|
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.
|
* @brief Gets the commands data of the path.
|
||||||
*
|
*
|
||||||
|
|
|
@ -136,7 +136,7 @@ struct SwShapeTask : SwTask
|
||||||
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.
|
||||||
Also, it shouldn't be dash style. */
|
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;
|
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 */
|
/* External Class Implementation */
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
|
@ -482,23 +507,12 @@ bool SwRenderer::renderShape(RenderData data)
|
||||||
}
|
}
|
||||||
|
|
||||||
//Main raster stage
|
//Main raster stage
|
||||||
uint8_t r, g, b, a;
|
if (task->rshape->stroke && task->rshape->stroke->strokeFirst) {
|
||||||
|
_renderStroke(task, surface, opacity);
|
||||||
if (auto fill = task->rshape->fill) {
|
_renderFill(task, surface, opacity);
|
||||||
rasterGradientShape(surface, &task->shape, fill->identifier());
|
|
||||||
} else {
|
} else {
|
||||||
task->rshape->fillColor(&r, &g, &b, &a);
|
_renderFill(task, surface, opacity);
|
||||||
a = static_cast<uint8_t>((opacity * (uint32_t) a) / 255);
|
_renderStroke(task, surface, opacity);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (task->cmpStroking) endComposite(cmp);
|
if (task->cmpStroking) endComposite(cmp);
|
||||||
|
|
|
@ -94,6 +94,7 @@ struct RenderStroke
|
||||||
uint32_t dashCnt = 0;
|
uint32_t dashCnt = 0;
|
||||||
StrokeCap cap = StrokeCap::Square;
|
StrokeCap cap = StrokeCap::Square;
|
||||||
StrokeJoin join = StrokeJoin::Bevel;
|
StrokeJoin join = StrokeJoin::Bevel;
|
||||||
|
bool strokeFirst = false;
|
||||||
|
|
||||||
~RenderStroke()
|
~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
|
Result Shape::stroke(float width) noexcept
|
||||||
{
|
{
|
||||||
if (!pImpl->strokeWidth(width)) return Result::FailedAllocation;
|
if (!pImpl->strokeWidth(width)) return Result::FailedAllocation;
|
||||||
|
|
|
@ -262,6 +262,15 @@ struct Shape::Impl
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool strokeFirst(bool strokeFirst)
|
||||||
|
{
|
||||||
|
if (!rs.stroke) rs.stroke = new RenderStroke();
|
||||||
|
rs.stroke->strokeFirst = strokeFirst;
|
||||||
|
flag |= RenderUpdateFlag::Stroke;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
Paint* duplicate()
|
Paint* duplicate()
|
||||||
{
|
{
|
||||||
auto ret = Shape::gen();
|
auto ret = Shape::gen();
|
||||||
|
@ -295,6 +304,7 @@ struct Shape::Impl
|
||||||
dup->rs.stroke->dashCnt = rs.stroke->dashCnt;
|
dup->rs.stroke->dashCnt = rs.stroke->dashCnt;
|
||||||
dup->rs.stroke->cap = rs.stroke->cap;
|
dup->rs.stroke->cap = rs.stroke->cap;
|
||||||
dup->rs.stroke->join = rs.stroke->join;
|
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));
|
memcpy(dup->rs.stroke->color, rs.stroke->color, sizeof(rs.stroke->color));
|
||||||
|
|
||||||
if (rs.stroke->dashCnt > 0) {
|
if (rs.stroke->dashCnt > 0) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue