From 54c36a0a342911ef03146a2bf5729db47fc3250c Mon Sep 17 00:00:00 2001 From: blakdragan7 Date: Fri, 6 Sep 2024 23:53:08 +0000 Subject: [PATCH] SkChop party! mandoline and cubicpaths Diffs= 2f7836f9c SkChop party! mandoline and cubicpaths (#8085) Co-authored-by: Luigi Rosso Co-authored-by: blakdragan7 --- .rive_head | 2 +- include/rive/math/math_types.hpp | 2 + tests/common/rand.hpp | 5 + tests/gm/cubicpaths.cpp | 160 +++++++++---------------------- tests/gm/mandoline.cpp | 90 ++++++++--------- 5 files changed, 100 insertions(+), 159 deletions(-) diff --git a/.rive_head b/.rive_head index f442ec85..a0b55e1c 100644 --- a/.rive_head +++ b/.rive_head @@ -1 +1 @@ -451599d0313086cc5c3cf0e7eebf4eb18c0ea0fc +2f7836f9cc8a94c6286d67e97b95e42de04dba5b diff --git a/include/rive/math/math_types.hpp b/include/rive/math/math_types.hpp index b34adc35..e9aea80b 100644 --- a/include/rive/math/math_types.hpp +++ b/include/rive/math/math_types.hpp @@ -131,6 +131,8 @@ RIVE_ALWAYS_INLINE static float clamp(float x, float lo, float hi) { return fminf(fmaxf(lo, x), hi); } + +RIVE_ALWAYS_INLINE static float degreesToRadians(float degrees) { return degrees * (PI / 180.0f); } } // namespace math template T lerp(const T& a, const T& b, float t) { return a + (b - a) * t; } diff --git a/tests/common/rand.hpp b/tests/common/rand.hpp index 582e57e6..dd3266bc 100644 --- a/tests/common/rand.hpp +++ b/tests/common/rand.hpp @@ -17,6 +17,11 @@ class Rand : public std::mt19937_64 bool boolean() { return m_impl() & 1; } + uint32_t u32(uint32_t start, uint32_t end) + { + return static_cast(std::uniform_int_distribution(start, end)(m_impl)); + } + private: std::mt19937_64 m_impl; }; diff --git a/tests/gm/cubicpaths.cpp b/tests/gm/cubicpaths.cpp index dfcc0153..bb6f6073 100644 --- a/tests/gm/cubicpaths.cpp +++ b/tests/gm/cubicpaths.cpp @@ -8,10 +8,8 @@ #include "gm.hpp" #include "gmutils.hpp" -#include "include/core/SkColor.h" -#include "include/core/SkMatrix.h" -#include "include/core/SkScalar.h" -#include "include/utils/SkRandom.h" +#include "rive/shapes/paint/color.hpp" +#include "rive/math/mat2d.hpp" #include "rive/renderer.hpp" using namespace rivegm; @@ -35,10 +33,10 @@ class ClippedCubicGM : public GM Paint paint; AABB bounds = {0, 0, 170, 150}; // path.getBounds(); - for (SkScalar dy = -1; dy <= 1; dy += 1) + for (float dy = -1; dy <= 1; dy += 1) { canvas->save(); - for (SkScalar dx = -1; dx <= 1; dx += 1) + for (float dx = -1; dx <= 1; dx += 1) { canvas->save(); canvas->clipPath(PathBuilder::Rect(bounds)); @@ -113,13 +111,12 @@ class ClippedCubic2GM : public GM -0.013089005235602302f, 131); fPath->close(); - SkMatrix matrix; - matrix.reset(); - matrix.setScaleX(0); - matrix.setScaleY(0); - matrix.setSkewX(1); - matrix.setSkewY(1); - fFlipped->addRenderPath(fPath, mat2d_fromSkMatrix(matrix)); + Mat2D matrix; + matrix[0] = 0.0f; + matrix[1] = 1.0f; + matrix[2] = 1.0f; + matrix[3] = 0.0f; + fFlipped->addRenderPath(fPath, matrix); } Path fPath; @@ -140,7 +137,7 @@ class CubicPathGM : public GM StrokeJoin join, RenderPaintStyle style, FillRule fill, - SkScalar strokeWidth) + float strokeWidth) { path->fillRule(fill); Paint paint; @@ -165,10 +162,6 @@ class CubicPathGM : public GM constexpr FillAndName gFills[] = { {FillRule::nonZero, "Winding"}, {FillRule::evenOdd, "Even / Odd"}, -#if 0 - {SkPathFillType::kInverseWinding, "Inverse Winding"}, - {SkPathFillType::kInverseEvenOdd, "Inverse Even / Odd"}, -#endif }; struct StyleAndName { @@ -178,9 +171,6 @@ class CubicPathGM : public GM constexpr StyleAndName gStyles[] = { {RenderPaintStyle::fill, "Fill"}, {RenderPaintStyle::stroke, "Stroke"}, -#if 0 - {SkPaint::kStrokeAndFill_Style, "Stroke And Fill"}, -#endif }; struct CapAndName { @@ -197,49 +187,33 @@ class CubicPathGM : public GM const char* fName; }; PathAndName path; - path.fPath->moveTo(25 * SK_Scalar1, 10 * SK_Scalar1); - path.fPath->cubicTo(40 * SK_Scalar1, - 20 * SK_Scalar1, - 60 * SK_Scalar1, - 20 * SK_Scalar1, - 75 * SK_Scalar1, - 10 * SK_Scalar1); + path.fPath->moveTo(25 * 1.0f, 10 * 1.0f); + path.fPath->cubicTo(40 * 1.0f, 20 * 1.0f, 60 * 1.0f, 20 * 1.0f, 75 * 1.0f, 10 * 1.0f); path.fName = "moveTo-cubic"; -#if 0 - SkPaint titlePaint; - titlePaint.setColor(SK_ColorBLACK); - titlePaint.setAntiAlias(true); - SkFont font(ToolUtils::create_portable_typeface(), 15); - const char title[] = "Cubic Drawn Into Rectangle Clips With " - "Indicated Style, Fill and Linecaps, with stroke width 10"; - canvas->drawString(title, 20, 20, font, titlePaint); -#endif - - SkRandom rand; - AABB rect = {0, 0, 100 * SK_Scalar1, 30 * SK_Scalar1}; + AABB rect = {0, 0, 100 * 1.0f, 30 * 1.0f}; canvas->save(); - canvas->translate(10 * SK_Scalar1, 30 * SK_Scalar1); + canvas->translate(10 * 1.0f, 30 * 1.0f); canvas->save(); - for (size_t cap = 0; cap < SK_ARRAY_COUNT(gCaps); ++cap) + for (size_t cap = 0; cap < std::size(gCaps); ++cap) { if (0 < cap) { - canvas->translate((rect.width() + 40 * SK_Scalar1) * SK_ARRAY_COUNT(gStyles), 0); + canvas->translate((rect.width() + 40 * 1.0f) * std::size(gStyles), 0); } canvas->save(); - for (size_t fill = 0; fill < SK_ARRAY_COUNT(gFills); ++fill) + for (size_t fill = 0; fill < std::size(gFills); ++fill) { if (0 < fill) { - canvas->translate(0, rect.height() + 40 * SK_Scalar1); + canvas->translate(0, rect.height() + 40 * 1.0f); } canvas->save(); - for (size_t style = 0; style < SK_ARRAY_COUNT(gStyles); ++style) + for (size_t style = 0; style < std::size(gStyles); ++style) { if (0 < style) { - canvas->translate(rect.width() + 40 * SK_Scalar1, 0); + canvas->translate(rect.width() + 40 * 1.0f, 0); } ColorInt color = 0xff007000; @@ -251,23 +225,13 @@ class CubicPathGM : public GM gCaps[cap].fJoin, gStyles[style].fStyle, gFills[fill].fFill, - SK_Scalar1 * 10); + 1.0f * 10); Paint rectPaint; - rectPaint->color(SK_ColorBLACK); + rectPaint->color(0xFF000000); rectPaint->style(RenderPaintStyle::stroke); rectPaint->thickness(-1); canvas->drawPath(PathBuilder::Rect(rect), rectPaint); - -#if 0 - SkPaint labelPaint; - labelPaint.setColor(color); - font.setSize(10); - canvas->drawString( - gStyles[style].fName, 0, rect.height() + 12, font, labelPaint); - canvas->drawString(gFills[fill].fName, 0, rect.height() + 24, font, labelPaint); - canvas->drawString(gCaps[cap].fName, 0, rect.height() + 36, font, labelPaint); -#endif } canvas->restore(); } @@ -292,7 +256,7 @@ class CubicClosePathGM : public GM StrokeJoin join, RenderPaintStyle style, FillRule fill, - SkScalar strokeWidth) + float strokeWidth) { path->fillRule(fill); Paint paint; @@ -317,10 +281,6 @@ class CubicClosePathGM : public GM constexpr FillAndName gFills[] = { {FillRule::nonZero, "Winding"}, {FillRule::evenOdd, "Even / Odd"}, -#if 0 - {SkPathFillType::kInverseWinding, "Inverse Winding"}, - {SkPathFillType::kInverseEvenOdd, "Inverse Even / Odd"}, -#endif }; struct StyleAndName { @@ -330,9 +290,6 @@ class CubicClosePathGM : public GM constexpr StyleAndName gStyles[] = { {RenderPaintStyle::fill, "Fill"}, {RenderPaintStyle::stroke, "Stroke"}, -#if 0 - {SkPaint::kStrokeAndFill_Style, "Stroke And Fill"}, -#endif }; struct CapAndName { @@ -349,53 +306,37 @@ class CubicClosePathGM : public GM const char* fName; }; PathAndName path; - path.fPath->moveTo(25 * SK_Scalar1, 10 * SK_Scalar1); - path.fPath->cubicTo(40 * SK_Scalar1, - 20 * SK_Scalar1, - 60 * SK_Scalar1, - 20 * SK_Scalar1, - 75 * SK_Scalar1, - 10 * SK_Scalar1); + path.fPath->moveTo(25 * 1.0f, 10 * 1.0f); + path.fPath->cubicTo(40 * 1.0f, 20 * 1.0f, 60 * 1.0f, 20 * 1.0f, 75 * 1.0f, 10 * 1.0f); path.fPath->close(); path.fName = "moveTo-cubic-close"; -#if 0 - SkPaint titlePaint; - titlePaint.setColor(SK_ColorBLACK); - titlePaint.setAntiAlias(true); - SkFont font(ToolUtils::create_portable_typeface(), 15); - const char title[] = "Cubic Closed Drawn Into Rectangle Clips With " - "Indicated Style, Fill and Linecaps, with stroke width 10"; - canvas->drawString(title, 20, 20, font, titlePaint); -#endif - - SkRandom rand; - AABB rect = {0, 0, 100 * SK_Scalar1, 30 * SK_Scalar1}; + AABB rect = {0, 0, 100 * 1.0f, 30 * 1.0f}; canvas->save(); - canvas->translate(10 * SK_Scalar1, 30 * SK_Scalar1); + canvas->translate(10 * 1.0f, 30 * 1.0f); canvas->save(); - for (size_t cap = 0; cap < SK_ARRAY_COUNT(gCaps); ++cap) + for (size_t cap = 0; cap < std::size(gCaps); ++cap) { if (0 < cap) { - canvas->translate((rect.width() + 40 * SK_Scalar1) * SK_ARRAY_COUNT(gStyles), 0); + canvas->translate((rect.width() + 40 * 1.0f) * std::size(gStyles), 0); } canvas->save(); - for (size_t fill = 0; fill < SK_ARRAY_COUNT(gFills); ++fill) + for (size_t fill = 0; fill < std::size(gFills); ++fill) { if (0 < fill) { - canvas->translate(0, rect.height() + 40 * SK_Scalar1); + canvas->translate(0, rect.height() + 40 * 1.0f); } canvas->save(); - for (size_t style = 0; style < SK_ARRAY_COUNT(gStyles); ++style) + for (size_t style = 0; style < std::size(gStyles); ++style) { if (0 < style) { - canvas->translate(rect.width() + 40 * SK_Scalar1, 0); + canvas->translate(rect.width() + 40 * 1.0f, 0); } - SkColor color = 0xff007000; + ColorInt color = 0xff007000; this->drawPath(path.fPath, canvas, color, @@ -404,24 +345,13 @@ class CubicClosePathGM : public GM gCaps[cap].fJoin, gStyles[style].fStyle, gFills[fill].fFill, - SK_Scalar1 * 10); + 1.0f * 10); Paint rectPaint; - rectPaint->color(SK_ColorBLACK); + rectPaint->color(0xFF000000); rectPaint->style(RenderPaintStyle::stroke); rectPaint->thickness(-1); canvas->drawPath(PathBuilder::Rect(rect), rectPaint); - -#if 0 - SkPaint labelPaint; - labelPaint.setColor(color); - labelPaint.setAntiAlias(true); - font.setSize(10); - canvas->drawString( - gStyles[style].fName, 0, rect.height() + 12, font, labelPaint); - canvas->drawString(gFills[fill].fName, 0, rect.height() + 24, font, labelPaint); - canvas->drawString(gCaps[cap].fName, 0, rect.height() + 36, font, labelPaint); -#endif } canvas->restore(); } @@ -435,7 +365,7 @@ class CubicClosePathGM : public GM DEF_SIMPLE_GM(bug5099, 50, 50, canvas) { Paint p; - p->color(SK_ColorRED); + p->color(0xFFFF0000); p->style(RenderPaintStyle::stroke); p->thickness(10); @@ -448,24 +378,24 @@ DEF_SIMPLE_GM(bug5099, 50, 50, canvas) DEF_SIMPLE_GM(bug6083, 100, 50, canvas) { Paint p; - p->color(SK_ColorRED); + p->color(0xFFFF0000); p->style(RenderPaintStyle::stroke); p->thickness(15); canvas->translate(-500, -130); Path path; path->moveTo(500.988f, 155.200f); path->lineTo(526.109f, 155.200f); - SkPoint p1 = {526.109f, 155.200f}; - SkPoint p2 = {525.968f, 212.968f}; - SkPoint p3 = {526.109f, 241.840f}; - path->cubicTo(p1.x(), p1.y(), p2.x(), p2.y(), p3.x(), p3.y()); + Vec2D p1 = {526.109f, 155.200f}; + Vec2D p2 = {525.968f, 212.968f}; + Vec2D p3 = {526.109f, 241.840f}; + path->cubicTo(p1.x, p1.y, p2.x, p2.y, p3.x, p3.y); canvas->drawPath(path, p); canvas->translate(50, 0); path = Path(); - p2.set(525.968f, 213.172f); + p2 = Vec2D(525.968f, 213.172f); path->moveTo(500.988f, 155.200f); path->lineTo(526.109f, 155.200f); - path->cubicTo(p1.x(), p1.y(), p2.x(), p2.y(), p3.x(), p3.y()); + path->cubicTo(p1.x, p1.y, p2.x, p2.y, p3.x, p3.y); canvas->drawPath(path, p); } diff --git a/tests/gm/mandoline.cpp b/tests/gm/mandoline.cpp index 6c2e166c..9da34ee0 100644 --- a/tests/gm/mandoline.cpp +++ b/tests/gm/mandoline.cpp @@ -10,35 +10,37 @@ #include "gmutils.hpp" #include "rive/renderer.hpp" #include "rive/renderer/render_context.hpp" -#include "include/core/SkPoint.h" -#include "include/utils/SkRandom.h" +#include "rive/math/vec2d.hpp" +#include "rive/math/math_types.hpp" +#include "common/rand.hpp" +#include "path_utils.hpp" +#include using namespace rivegm; using namespace rive; - -extern void SkChopQuadAt(const SkPoint src[3], SkPoint dst[5], SkScalar t); -extern void SkChopCubicAt(const SkPoint src[4], SkPoint dst[7], SkScalar t); +using namespace rive::math; +using namespace rive::pathutils; // Slices paths into sliver-size contours shaped like ice cream cones. class MandolineSlicer { public: - MandolineSlicer(SkPoint anchorPt) { this->reset(anchorPt); } + MandolineSlicer(Vec2D anchorPt) { this->reset(anchorPt); } - void reset(SkPoint anchorPt) + void reset(Vec2D anchorPt) { fPath = Path(); fPath->fillRule(FillRule::evenOdd); fLastPt = fAnchorPt = anchorPt; } - void sliceLine(SkPoint pt, int numSubdivisions) + void sliceLine(Vec2D pt, int numSubdivisions) { if (numSubdivisions <= 0) { - fPath->moveTo(fAnchorPt.x(), fAnchorPt.y()); - fPath->lineTo(fLastPt.x(), fLastPt.y()); - fPath->lineTo(pt.x(), pt.y()); + fPath->moveTo(fAnchorPt.x, fAnchorPt.y); + fPath->lineTo(fLastPt.x, fLastPt.y); + fPath->lineTo(pt.x, pt.y); fPath->close(); fLastPt = pt; return; @@ -48,23 +50,23 @@ class MandolineSlicer { return; } - SkPoint midpt = fLastPt * (1 - T) + pt * T; + Vec2D midpt = fLastPt * (1 - T) + pt * T; this->sliceLine(midpt, numSubdivisions - 1); this->sliceLine(pt, numSubdivisions - 1); } - void sliceQuadratic(SkPoint p1, SkPoint p2, int numSubdivisions) + void sliceQuadratic(Vec2D p1, Vec2D p2, int numSubdivisions) { if (numSubdivisions <= 0) { - fPath->moveTo(fAnchorPt.x(), fAnchorPt.y()); - fPath->lineTo(fLastPt.x(), fLastPt.y()); - fPath->cubicTo(fLastPt.x() + (p1.x() - fLastPt.x()) * (2 / 3.f), - fLastPt.y() + (p1.y() - fLastPt.y()) * (2 / 3.f), - p2.x() + (p1.x() - p2.x()) * (2 / 3.f), - p2.y() + (p1.y() - p2.y()) * (2 / 3.f), - p2.x(), - p2.y()); + fPath->moveTo(fAnchorPt.x, fAnchorPt.y); + fPath->lineTo(fLastPt.x, fLastPt.y); + fPath->cubicTo(fLastPt.x + (p1.x - fLastPt.x) * (2 / 3.f), + fLastPt.y + (p1.y - fLastPt.y) * (2 / 3.f), + p2.x + (p1.x - p2.x) * (2 / 3.f), + p2.y + (p1.y - p2.y) * (2 / 3.f), + p2.x, + p2.y); fPath->close(); fLastPt = p2; return; @@ -74,19 +76,21 @@ class MandolineSlicer { return; } - SkPoint P[3] = {fLastPt, p1, p2}, PP[5]; - SkChopQuadAt(P, PP, T); - this->sliceQuadratic(PP[1], PP[2], numSubdivisions - 1); - this->sliceQuadratic(PP[3], PP[4], numSubdivisions - 1); + Vec2D P[4] = {fLastPt, Vec2D::lerp(fLastPt, p1, 2 / 3.f), Vec2D::lerp(p2, p1, 2 / 3.f), p2}, + PP[7]; + ChopCubicAt(P, PP, T); + + this->sliceCubic(PP[1], PP[2], PP[3], numSubdivisions - 1); + this->sliceCubic(PP[4], PP[5], PP[6], numSubdivisions - 1); } - void sliceCubic(SkPoint p1, SkPoint p2, SkPoint p3, int numSubdivisions) + void sliceCubic(Vec2D p1, Vec2D p2, Vec2D p3, int numSubdivisions) { if (numSubdivisions <= 0) { - fPath->moveTo(fAnchorPt.x(), fAnchorPt.y()); - fPath->lineTo(fLastPt.x(), fLastPt.y()); - fPath->cubicTo(p1.x(), p1.y(), p2.x(), p2.y(), p3.x(), p3.y()); + fPath->moveTo(fAnchorPt.x, fAnchorPt.y); + fPath->lineTo(fLastPt.x, fLastPt.y); + fPath->cubicTo(p1.x, p1.y, p2.x, p2.y, p3.x, p3.y); fPath->close(); fLastPt = p3; return; @@ -96,8 +100,8 @@ class MandolineSlicer { return; } - SkPoint P[4] = {fLastPt, p1, p2, p3}, PP[7]; - SkChopCubicAt(P, PP, T); + Vec2D P[4] = {fLastPt, p1, p2, p3}, PP[7]; + ChopCubicAt(P, PP, T); this->sliceCubic(PP[1], PP[2], PP[3], numSubdivisions - 1); this->sliceCubic(PP[4], PP[5], PP[6], numSubdivisions - 1); } @@ -107,20 +111,20 @@ class MandolineSlicer private: float chooseChopT(int numSubdivisions) { - SkASSERT(numSubdivisions > 0); + assert(numSubdivisions > 0); if (numSubdivisions > 1) { return .5f; } - float T = (0 == fRand.nextU() % 10) ? 0 : scalbnf(1, -(int)fRand.nextRangeU(10, 149)); - SkASSERT(T >= 0 && T < 1); + float T = (0 == fRand.u32() % 10) ? 0 : scalbnf(1, -(int)fRand.u32(10, 149)); + assert(T >= 0 && T < 1); return T; } - SkRandom fRand; + Rand fRand; Path fPath; - SkPoint fAnchorPt; - SkPoint fLastPt; + Vec2D fAnchorPt; + Vec2D fLastPt; }; class MandolineGM : public GM @@ -164,16 +168,16 @@ class MandolineGM : public GM renderer->save(); renderer->translate(421, 105); renderer->scale(100, 81); - mandoline.reset({-cosf(SkDegreesToRadians(-60)), sinf(SkDegreesToRadians(-60))}); + mandoline.reset({-cosf(degreesToRadians(-60)), sinf(degreesToRadians(-60))}); mandoline.sliceQuadratic({-2, 0}, - {-cosf(SkDegreesToRadians(60)), sinf(SkDegreesToRadians(60))}, + {-cosf(degreesToRadians(60)), sinf(degreesToRadians(60))}, subdivisions); mandoline.sliceQuadratic( - {-cosf(SkDegreesToRadians(120)) * 2, sinf(SkDegreesToRadians(120)) * 2}, + {-cosf(degreesToRadians(120)) * 2, sinf(degreesToRadians(120)) * 2}, {1, 0}, subdivisions); mandoline.sliceLine({0, 0}, subdivisions); - mandoline.sliceLine({-cosf(SkDegreesToRadians(-60)), sinf(SkDegreesToRadians(-60))}, + mandoline.sliceLine({-cosf(degreesToRadians(-60)), sinf(degreesToRadians(-60))}, subdivisions); renderer->drawPath(mandoline.path(), paint); renderer->restore(); @@ -185,8 +189,8 @@ class MandolineGM : public GM constexpr int nquads = 5; for (int i = 0; i < nquads; ++i) { - float theta1 = 2 * SK_ScalarPI / nquads * (i + .5f); - float theta2 = 2 * SK_ScalarPI / nquads * (i + 1); + float theta1 = 2 * PI / nquads * (i + .5f); + float theta2 = 2 * PI / nquads * (i + 1); mandoline.sliceQuadratic({cosf(theta1) * 2, sinf(theta1) * 2}, {cosf(theta2), sinf(theta2)}, subdivisions);