diff --git a/inc/thorvg.h b/inc/thorvg.h index 54c7e113..bdca5a20 100644 --- a/inc/thorvg.h +++ b/inc/thorvg.h @@ -228,8 +228,8 @@ public: Result close() noexcept; //Shape - Result appendRect(float x, float y, float w, float h, float cornerRadius) noexcept; - Result appendCircle(float cx, float cy, float radiusW, float radiusH) noexcept; + Result appendRect(float x, float y, float w, float h, float rx, float ry) noexcept; + Result appendCircle(float cx, float cy, float rx, float ry) noexcept; Result appendPath(const PathCommand* cmds, uint32_t cmdCnt, const Point* pts, uint32_t ptsCnt) noexcept; //Stroke diff --git a/src/lib/tvgShape.cpp b/src/lib/tvgShape.cpp index f7699b4b..36aefedd 100644 --- a/src/lib/tvgShape.cpp +++ b/src/lib/tvgShape.cpp @@ -154,20 +154,20 @@ Result Shape::close() noexcept } -Result Shape::appendCircle(float cx, float cy, float radiusW, float radiusH) noexcept +Result Shape::appendCircle(float cx, float cy, float rx, float ry) noexcept { auto impl = pImpl.get(); if (!impl || !impl->path) return Result::MemoryCorruption; - auto halfKappaW = radiusW * PATH_KAPPA; - auto halfKappaH = radiusH * PATH_KAPPA; + auto rxKappa = rx * PATH_KAPPA; + auto ryKappa = ry * PATH_KAPPA; impl->path->grow(6, 13); - impl->path->moveTo(cx, cy - radiusH); - impl->path->cubicTo(cx + halfKappaW, cy - radiusH, cx + radiusW, cy - halfKappaH, cx + radiusW, cy); - impl->path->cubicTo(cx + radiusW, cy + halfKappaH, cx + halfKappaW, cy + radiusH, cx, cy + radiusH); - impl->path->cubicTo(cx - halfKappaW, cy + radiusH, cx - radiusW, cy + halfKappaH, cx - radiusW, cy); - impl->path->cubicTo(cx - radiusW, cy - halfKappaH, cx - halfKappaW, cy - radiusH, cx, cy - radiusH); + impl->path->moveTo(cx, cy - ry); + impl->path->cubicTo(cx + rxKappa, cy - ry, cx + rx, cy - ryKappa, cx + rx, cy); + impl->path->cubicTo(cx + rx, cy + ryKappa, cx + rxKappa, cy + ry, cx, cy + ry); + impl->path->cubicTo(cx - rxKappa, cy + ry, cx - rx, cy + ryKappa, cx - rx, cy); + impl->path->cubicTo(cx - rx, cy - ryKappa, cx - rxKappa, cy - ry, cx, cy - ry); impl->path->close(); impl->flag |= RenderUpdateFlag::Path; @@ -176,17 +176,20 @@ Result Shape::appendCircle(float cx, float cy, float radiusW, float radiusH) noe } -Result Shape::appendRect(float x, float y, float w, float h, float cornerRadius) noexcept +Result Shape::appendRect(float x, float y, float w, float h, float rx, float ry) noexcept { auto impl = pImpl.get(); if (!impl || !impl->path) return Result::MemoryCorruption; + auto halfW = w * 0.5f; + auto halfH = h * 0.5f; + //clamping cornerRadius by minimum size - auto min = (w < h ? w : h) * 0.5f; - if (cornerRadius > min) cornerRadius = min; + if (rx > halfW) rx = halfW; + if (ry > halfH) ry = halfH; //rectangle - if (cornerRadius == 0) { + if (rx == 0 && ry == 0) { impl->path->grow(5, 4); impl->path->moveTo(x, y); impl->path->lineTo(x + w, y); @@ -194,20 +197,21 @@ Result Shape::appendRect(float x, float y, float w, float h, float cornerRadius) impl->path->lineTo(x, y + h); impl->path->close(); //circle - } else if (w == h && cornerRadius * 2 == w) { - return appendCircle(x + (w * 0.5f), y + (h * 0.5f), cornerRadius, cornerRadius); + } else if (fabsf(rx - halfW) < FLT_EPSILON && fabsf(ry - halfH) < FLT_EPSILON) { + return appendCircle(x + (w * 0.5f), y + (h * 0.5f), rx, ry); } else { - auto halfKappa = cornerRadius * 0.5; + auto hrx = rx * 0.5f; + auto hry = ry * 0.5f; impl->path->grow(10, 17); - impl->path->moveTo(x + cornerRadius, y); - impl->path->lineTo(x + w - cornerRadius, y); - impl->path->cubicTo(x + w - cornerRadius + halfKappa, y, x + w, y + cornerRadius - halfKappa, x + w, y + cornerRadius); - impl->path->lineTo(x + w, y + h - cornerRadius); - impl->path->cubicTo(x + w, y + h - cornerRadius + halfKappa, x + w - cornerRadius + halfKappa, y + h, x + w - cornerRadius, y + h); - impl->path->lineTo(x + cornerRadius, y + h); - impl->path->cubicTo(x + cornerRadius - halfKappa, y + h, x, y + h - cornerRadius + halfKappa, x, y + h - cornerRadius); - impl->path->lineTo(x, y + cornerRadius); - impl->path->cubicTo(x, y + cornerRadius - halfKappa, x + cornerRadius - halfKappa, y, x + cornerRadius, y); + impl->path->moveTo(x + rx, y); + impl->path->lineTo(x + w - rx, y); + impl->path->cubicTo(x + w - rx + hrx, y, x + w, y + ry - hry, x + w, y + ry); + impl->path->lineTo(x + w, y + h - ry); + impl->path->cubicTo(x + w, y + h - ry + hry, x + w - rx + hrx, y + h, x + w - rx, y + h); + impl->path->lineTo(x + rx, y + h); + impl->path->cubicTo(x + rx - hrx, y + h, x, y + h - ry + hry, x, y + h - ry); + impl->path->lineTo(x, y + ry); + impl->path->cubicTo(x, y + ry - hry, x + rx - hrx, y, x + rx, y); impl->path->close(); } diff --git a/src/loaders/svg_loader/tvgSvgSceneBuilder.cpp b/src/loaders/svg_loader/tvgSvgSceneBuilder.cpp index 2451103e..2be01222 100644 --- a/src/loaders/svg_loader/tvgSvgSceneBuilder.cpp +++ b/src/loaders/svg_loader/tvgSvgSceneBuilder.cpp @@ -150,29 +150,7 @@ unique_ptr _shapeBuildHelper(SvgNode* node) break; } case SvgNodeType::Rect: { - if (node->node.rect.rx == node->node.rect.ry || (node->node.rect.rx == 0 || node->node.rect.ry == 0)) { - shape->appendRect(node->node.rect.x, node->node.rect.y, node->node.rect.w, node->node.rect.h, node->node.rect.rx); - } - else { - float x = node->node.rect.x; - float y = node->node.rect.y; - float w = node->node.rect.w; - float h = node->node.rect.h; - float rx = node->node.rect.rx; - float ry = node->node.rect.ry; - float rhx = rx / 2; - float rhy = ry / 2; - shape->moveTo(x + rx, y); - shape->lineTo(x + w - rx, y); - shape->cubicTo(x + w - rx + rhx, y, x + w, y + ry - rhy, x + w, y + ry); - shape->lineTo(x + w, y + h - ry); - shape->cubicTo(x + w, y + h - ry + rhy, x + w - rx + rhx, y + h, x + w - rx, y + h); - shape->lineTo(x + rx, y + h); - shape->cubicTo(x + rx - rhx, y + h, x, y + h - ry + rhy, x, y + h - ry); - shape->lineTo(x, y + ry); - shape->cubicTo(x, y + ry - rhy, x + rx - rhx, y, x + rx, y); - shape->close(); - } + shape->appendRect(node->node.rect.x, node->node.rect.y, node->node.rect.w, node->node.rect.h, node->node.rect.rx, node->node.rect.ry); break; } case SvgNodeType::Line: { diff --git a/test/testAsync.cpp b/test/testAsync.cpp index ca1d473d..bb890abf 100644 --- a/test/testAsync.cpp +++ b/test/testAsync.cpp @@ -29,7 +29,7 @@ bool tvgUpdateCmds(tvg::Canvas* canvas) float w = 1 + rand() % (int)(WIDTH * 1.3 / 2); float h = 1 + rand() % (int)(HEIGHT * 1.3 / 2); - shape->appendRect(x, y, w, h, 0); + shape->appendRect(x, y, w, h, 0, 0); //LinearGradient auto fill = tvg::LinearGradient::gen(); diff --git a/test/testBlending.cpp b/test/testBlending.cpp index 14bc9acf..6f5f6e1b 100644 --- a/test/testBlending.cpp +++ b/test/testBlending.cpp @@ -10,7 +10,7 @@ void tvgDrawCmds(tvg::Canvas* canvas) //Prepare Round Rectangle auto shape1 = tvg::Shape::gen(); - shape1->appendRect(0, 0, 400, 400, 50); //x, y, w, h, cornerRadius + shape1->appendRect(0, 0, 400, 400, 50, 50); //x, y, w, h, rx, ry shape1->fill(0, 255, 0, 255); //r, g, b, a if (canvas->push(move(shape1)) != tvg::Result::Success) return; @@ -151,4 +151,4 @@ int main(int argc, char **argv) //Terminate ThorVG Engine tvg::Initializer::term(tvgEngine); -} \ No newline at end of file +} diff --git a/test/testBoundary.cpp b/test/testBoundary.cpp index ca598e45..b23b82ec 100644 --- a/test/testBoundary.cpp +++ b/test/testBoundary.cpp @@ -10,19 +10,19 @@ void tvgDrawCmds(tvg::Canvas* canvas) //Prepare Shape1 auto shape1 = tvg::Shape::gen(); - shape1->appendRect(-100, -100, 1000, 1000, 50); + shape1->appendRect(-100, -100, 1000, 1000, 50, 50); shape1->fill(255, 255, 255, 255); if (canvas->push(move(shape1)) != tvg::Result::Success) return; //Prepare Shape2 auto shape2 = tvg::Shape::gen(); - shape2->appendRect(-100, -100, 250, 250, 50); + shape2->appendRect(-100, -100, 250, 250, 50, 50); shape2->fill(0, 0, 255, 255); if (canvas->push(move(shape2)) != tvg::Result::Success) return; //Prepare Shape3 auto shape3 = tvg::Shape::gen(); - shape3->appendRect(500, 500, 550, 550, 0); + shape3->appendRect(500, 500, 550, 550, 0, 0); shape3->fill(0, 255, 255, 255); if (canvas->push(move(shape3)) != tvg::Result::Success) return; @@ -140,4 +140,4 @@ int main(int argc, char **argv) //Terminate ThorVG Engine tvg::Initializer::term(tvgEngine); -} \ No newline at end of file +} diff --git a/test/testDirectUpdate.cpp b/test/testDirectUpdate.cpp index 24fae64b..437ad1f4 100644 --- a/test/testDirectUpdate.cpp +++ b/test/testDirectUpdate.cpp @@ -14,7 +14,7 @@ void tvgDrawCmds(tvg::Canvas* canvas) instead, you should consider not to interrupt this pointer life-cycle. */ pShape = shape.get(); - shape->appendRect(-100, -100, 200, 200, 0); + shape->appendRect(-100, -100, 200, 200, 0, 0); //fill property will be retained shape->fill(127, 255, 255, 255); @@ -32,7 +32,7 @@ void tvgUpdateCmds(tvg::Canvas* canvas, float progress) //Reset Shape if (pShape->reset() == tvg::Result::Success) { - pShape->appendRect(-100 + (800 * progress), -100 + (800 * progress), 200, 200, (100 * progress)); + pShape->appendRect(-100 + (800 * progress), -100 + (800 * progress), 200, 200, (100 * progress), (100 * progress)); pShape->stroke(30 * progress); //Update shape for drawing (this may work asynchronously) @@ -166,4 +166,4 @@ int main(int argc, char **argv) //Terminate ThorVG Engine tvg::Initializer::term(tvgEngine); -} \ No newline at end of file +} diff --git a/test/testGradientTransform.cpp b/test/testGradientTransform.cpp index ddc9c880..fd5a563f 100644 --- a/test/testGradientTransform.cpp +++ b/test/testGradientTransform.cpp @@ -16,8 +16,8 @@ void tvgDrawCmds(tvg::Canvas* canvas) instead, you should consider not to interrupt this pointer life-cycle. */ pShape = shape.get(); - shape->appendRect(-285, -300, 200, 200, 0); - shape->appendRect(-185, -200, 300, 300, 100); + shape->appendRect(-285, -300, 200, 200, 0, 0); + shape->appendRect(-185, -200, 300, 300, 100, 100); shape->appendCircle(115, 100, 100, 100); shape->appendCircle(115, 200, 170, 100); @@ -39,7 +39,7 @@ void tvgDrawCmds(tvg::Canvas* canvas) //Shape2 auto shape2 = tvg::Shape::gen(); pShape2 = shape2.get(); - shape2->appendRect(-50, -50, 100, 100, 0); + shape2->appendRect(-50, -50, 100, 100, 0, 0); shape2->translate(400, 400); //LinearGradient @@ -61,7 +61,7 @@ void tvgDrawCmds(tvg::Canvas* canvas) /* Look, how shape3's origin is different with shape2 The center of the shape is the anchor point for transformation. */ - shape3->appendRect(100, 100, 150, 100, 20); + shape3->appendRect(100, 100, 150, 100, 20, 20); //RadialGradient auto fill3 = tvg::RadialGradient::gen(); @@ -231,4 +231,4 @@ int main(int argc, char **argv) //Terminate ThorVG Engine tvg::Initializer::term(tvgEngine); -} \ No newline at end of file +} diff --git a/test/testLinearGradient.cpp b/test/testLinearGradient.cpp index d6f04e47..45f38d75 100644 --- a/test/testLinearGradient.cpp +++ b/test/testLinearGradient.cpp @@ -10,7 +10,7 @@ void tvgDrawCmds(tvg::Canvas* canvas) //Prepare Round Rectangle auto shape1 = tvg::Shape::gen(); - shape1->appendRect(0, 0, 400, 400, 0); //x, y, w, h, cornerRadius + shape1->appendRect(0, 0, 400, 400, 0, 0); //x, y, w, h, rx, ry //LinearGradient auto fill = tvg::LinearGradient::gen(); @@ -169,4 +169,4 @@ int main(int argc, char **argv) //Terminate ThorVG Engine tvg::Initializer::term(tvgEngine); -} \ No newline at end of file +} diff --git a/test/testMultiShapes.cpp b/test/testMultiShapes.cpp index b5c6d42c..ec46f2f9 100644 --- a/test/testMultiShapes.cpp +++ b/test/testMultiShapes.cpp @@ -10,7 +10,7 @@ void tvgDrawCmds(tvg::Canvas* canvas) //Prepare Round Rectangle auto shape1 = tvg::Shape::gen(); - shape1->appendRect(0, 0, 400, 400, 50); //x, y, w, h, cornerRadius + shape1->appendRect(0, 0, 400, 400, 50, 50); //x, y, w, h, rx, ry shape1->fill(0, 255, 0, 255); //r, g, b, a if (canvas->push(move(shape1)) != tvg::Result::Success) return; @@ -129,4 +129,4 @@ int main(int argc, char **argv) //Terminate ThorVG Engine tvg::Initializer::term(tvgEngine); -} \ No newline at end of file +} diff --git a/test/testRadialGradient.cpp b/test/testRadialGradient.cpp index de93d469..71cfaaef 100644 --- a/test/testRadialGradient.cpp +++ b/test/testRadialGradient.cpp @@ -10,7 +10,7 @@ void tvgDrawCmds(tvg::Canvas* canvas) //Prepare Round Rectangle auto shape1 = tvg::Shape::gen(); - shape1->appendRect(0, 0, 400, 400, 0); //x, y, w, h, cornerRadius + shape1->appendRect(0, 0, 400, 400, 0, 0); //x, y, w, h, rx, ry //RadialGradient auto fill = tvg::RadialGradient::gen(); @@ -169,4 +169,4 @@ int main(int argc, char **argv) //Terminate ThorVG Engine tvg::Initializer::term(tvgEngine); -} \ No newline at end of file +} diff --git a/test/testScene.cpp b/test/testScene.cpp index ec1ed4a8..bee2b54f 100644 --- a/test/testScene.cpp +++ b/test/testScene.cpp @@ -12,7 +12,7 @@ void tvgDrawCmds(tvg::Canvas* canvas) //Prepare Round Rectangle auto shape1 = tvg::Shape::gen(); - shape1->appendRect(0, 0, 400, 400, 50); //x, y, w, h, cornerRadius + shape1->appendRect(0, 0, 400, 400, 50, 50); //x, y, w, h, rx, ry shape1->fill(0, 255, 0, 255); //r, g, b, a scene->push(move(shape1)); @@ -176,4 +176,4 @@ int main(int argc, char **argv) //Terminate ThorVG Engine tvg::Initializer::term(tvgEngine); -} \ No newline at end of file +} diff --git a/test/testSceneTransform.cpp b/test/testSceneTransform.cpp index c1b16629..d5d538d5 100644 --- a/test/testSceneTransform.cpp +++ b/test/testSceneTransform.cpp @@ -15,7 +15,7 @@ void tvgDrawCmds(tvg::Canvas* canvas) //Prepare Round Rectangle (Scene1) auto shape1 = tvg::Shape::gen(); - shape1->appendRect(-235, -250, 400, 400, 50); //x, y, w, h, cornerRadius + shape1->appendRect(-235, -250, 400, 400, 50, 50); //x, y, w, h, rx, ry shape1->fill(0, 255, 0, 255); //r, g, b, a shape1->stroke(5); //width shape1->stroke(255, 255, 255, 255); //r, g, b, a diff --git a/test/testShape.cpp b/test/testShape.cpp index 617d024f..e5e4c572 100644 --- a/test/testShape.cpp +++ b/test/testShape.cpp @@ -8,11 +8,11 @@ void tvgDrawCmds(tvg::Canvas* canvas) { //Prepare a Shape (Rectangle + Rectangle + Circle + Circle) auto shape1 = tvg::Shape::gen(); - shape1->appendRect(0, 0, 200, 200, 0); //x, y, w, h, cornerRadius - shape1->appendRect(100, 100, 300, 300, 100); //x, y, w, h, cornerRadius - shape1->appendCircle(400, 400, 100, 100); //cx, cy, radiusW, radiusH - shape1->appendCircle(400, 500, 170, 100); //cx, cy, radiusW, radiusH - shape1->fill(255, 255, 0, 255); //r, g, b, a + shape1->appendRect(0, 0, 200, 200, 0, 0); //x, y, w, h, rx, ry + shape1->appendRect(100, 100, 300, 300, 100, 100); //x, y, w, h, rx, ry + shape1->appendCircle(400, 400, 100, 100); //cx, cy, radiusW, radiusH + shape1->appendCircle(400, 500, 170, 100); //cx, cy, radiusW, radiusH + shape1->fill(255, 255, 0, 255); //r, g, b, a canvas->push(move(shape1)); } diff --git a/test/testStroke.cpp b/test/testStroke.cpp index b9cfb4cf..f4f7c8c0 100644 --- a/test/testStroke.cpp +++ b/test/testStroke.cpp @@ -8,7 +8,7 @@ void tvgDrawCmds(tvg::Canvas* canvas) { //Shape 1 auto shape1 = tvg::Shape::gen(); - shape1->appendRect(50, 50, 200, 200, 0); + shape1->appendRect(50, 50, 200, 200, 0, 0); shape1->fill(50, 50, 50, 255); shape1->stroke(255, 255, 255, 255); //color: r, g, b, a shape1->stroke(tvg::StrokeJoin::Bevel); //default is Bevel @@ -18,7 +18,7 @@ void tvgDrawCmds(tvg::Canvas* canvas) //Shape 2 auto shape2 = tvg::Shape::gen(); - shape2->appendRect(300, 50, 200, 200, 0); + shape2->appendRect(300, 50, 200, 200, 0, 0); shape2->fill(50, 50, 50, 255); shape2->stroke(255, 255, 255, 255); shape2->stroke(tvg::StrokeJoin::Round); @@ -28,7 +28,7 @@ void tvgDrawCmds(tvg::Canvas* canvas) //Shape 3 auto shape3 = tvg::Shape::gen(); - shape3->appendRect(550, 50, 200, 200, 0); + shape3->appendRect(550, 50, 200, 200, 0, 0); shape3->fill(50, 50, 50, 255); shape3->stroke(255, 255, 255, 255); shape3->stroke(tvg::StrokeJoin::Miter); @@ -166,4 +166,4 @@ int main(int argc, char **argv) //Terminate ThorVG Engine tvg::Initializer::term(tvgEngine); -} \ No newline at end of file +} diff --git a/test/testSvg.cpp b/test/testSvg.cpp index e0232748..04b9ab0e 100644 --- a/test/testSvg.cpp +++ b/test/testSvg.cpp @@ -33,7 +33,7 @@ void tvgDrawCmds(tvg::Canvas* canvas) { //Background auto shape = tvg::Shape::gen(); - shape->appendRect(0, 0, WIDTH, HEIGHT, 0); //x, y, w, h, cornerRadius + shape->appendRect(0, 0, WIDTH, HEIGHT, 0, 0); //x, y, w, h, rx, ry shape->fill(255, 255, 255, 255); //r, g, b, a if (canvas->push(move(shape)) != tvg::Result::Success) return; diff --git a/test/testTransform.cpp b/test/testTransform.cpp index 35b237c9..65492b11 100644 --- a/test/testTransform.cpp +++ b/test/testTransform.cpp @@ -16,8 +16,8 @@ void tvgDrawCmds(tvg::Canvas* canvas) instead, you should consider not to interrupt this pointer life-cycle. */ pShape = shape.get(); - shape->appendRect(-285, -300, 200, 200, 0); - shape->appendRect(-185, -200, 300, 300, 100); + shape->appendRect(-285, -300, 200, 200, 0, 0); + shape->appendRect(-185, -200, 300, 300, 100, 100); shape->appendCircle(115, 100, 100, 100); shape->appendCircle(115, 200, 170, 100); shape->fill(255, 255, 255, 255); @@ -27,7 +27,7 @@ void tvgDrawCmds(tvg::Canvas* canvas) //Shape2 auto shape2 = tvg::Shape::gen(); pShape2 = shape2.get(); - shape2->appendRect(-50, -50, 100, 100, 0); + shape2->appendRect(-50, -50, 100, 100, 0, 0); shape2->fill(0, 255, 255, 255); shape2->translate(400, 400); if (canvas->push(move(shape2)) != tvg::Result::Success) return; @@ -38,7 +38,7 @@ void tvgDrawCmds(tvg::Canvas* canvas) /* Look, how shape3's origin is different with shape2 The center of the shape is the anchor point for transformation. */ - shape3->appendRect(100, 100, 150, 50, 20); + shape3->appendRect(100, 100, 150, 50, 20, 20); shape3->fill(255, 0, 255, 255); shape3->translate(400, 400); if (canvas->push(move(shape3)) != tvg::Result::Success) return; @@ -194,4 +194,4 @@ int main(int argc, char **argv) //Terminate ThorVG Engine tvg::Initializer::term(tvgEngine); -} \ No newline at end of file +} diff --git a/test/testUpdate.cpp b/test/testUpdate.cpp index 051a5810..6bfbddcf 100644 --- a/test/testUpdate.cpp +++ b/test/testUpdate.cpp @@ -8,7 +8,7 @@ void tvgDrawCmds(tvg::Canvas* canvas) { //Shape auto shape = tvg::Shape::gen(); - shape->appendRect(-100, -100, 200, 200, 0); + shape->appendRect(-100, -100, 200, 200, 0, 0); shape->fill(255, 255, 255, 255); canvas->push(move(shape)); } @@ -20,7 +20,7 @@ void tvgUpdateCmds(tvg::Canvas* canvas, float progress) //Shape auto shape = tvg::Shape::gen(); - shape->appendRect(-100, -100, 200, 200, (100 * progress)); + shape->appendRect(-100, -100, 200, 200, (100 * progress), (100 * progress)); shape->fill(rand()%255, rand()%255, rand()%255, 255); shape->translate(800 * progress, 800 * progress); shape->scale(1 - 0.75 * progress); @@ -155,4 +155,4 @@ int main(int argc, char **argv) //Terminate ThorVG Engine tvg::Initializer::term(tvgEngine); -} \ No newline at end of file +}