mirror of
https://github.com/rive-app/rive-cpp.git
synced 2026-01-18 21:21:17 +01:00
Expose localBounds in CPP (#10537) 0ed12de980
Implement some missing localBounds methods in CPP on core objects that expose this. Basically ported over from Dart. This was requested in order for the new rive_native Flutter runtime to provide a similar API to the legacy Flutter runtime. Co-authored-by: Philip Chung <philterdesign@gmail.com>
This commit is contained in:
@@ -1 +1 @@
|
||||
e58f44d5ecca903e13d6770d7bf7d54d7fbaf76a
|
||||
0ed12de9806f4e2caaf5e696b047abc9b79fa99d
|
||||
|
||||
@@ -32,6 +32,7 @@ public:
|
||||
const Mat2D& inverseWorld) const override;
|
||||
Vec2D deformWorldPoint(Vec2D point) const override;
|
||||
Vec2D scaleForNSlicer() const;
|
||||
AABB localBounds() const override;
|
||||
|
||||
Vec2D measureLayout(float width,
|
||||
LayoutMeasureMode widthMode,
|
||||
|
||||
@@ -191,6 +191,7 @@ public:
|
||||
m_layout.height());
|
||||
}
|
||||
size_t numLayoutNodes() override { return 1; }
|
||||
AABB constraintBounds() const override { return localBounds(); }
|
||||
AABB localBounds() const override
|
||||
{
|
||||
return AABB::fromLTWH(0.0f, 0.0f, m_layout.width(), m_layout.height());
|
||||
|
||||
@@ -33,9 +33,7 @@ public:
|
||||
#ifdef DEBUG
|
||||
void printCode() const;
|
||||
#endif
|
||||
#ifdef WITH_RIVE_TOOLS
|
||||
AABB preciseBounds() const;
|
||||
#endif
|
||||
size_t countMoveTos() const;
|
||||
|
||||
void move(Vec2D);
|
||||
|
||||
@@ -42,6 +42,7 @@ public:
|
||||
float width() const;
|
||||
float height() const;
|
||||
void assetUpdated() override;
|
||||
AABB localBounds() const override;
|
||||
|
||||
#ifdef TESTING
|
||||
Mesh* mesh() const;
|
||||
|
||||
@@ -79,6 +79,7 @@ public:
|
||||
#endif
|
||||
|
||||
void buildPath(RawPath&) const;
|
||||
AABB localBounds() const override;
|
||||
};
|
||||
} // namespace rive
|
||||
|
||||
|
||||
@@ -59,6 +59,7 @@ public:
|
||||
float length() override;
|
||||
void setLength(float value) override {}
|
||||
|
||||
AABB localBounds() const override { return computeLocalBounds(); }
|
||||
AABB worldBounds()
|
||||
{
|
||||
if ((static_cast<DrawableFlag>(drawableFlags()) &
|
||||
|
||||
@@ -92,6 +92,7 @@ public:
|
||||
const TextStylePaint* styleFromShaperId(uint16_t id) const;
|
||||
bool modifierRangesNeedShape() const;
|
||||
AABB localBounds() const override;
|
||||
AABB constraintBounds() const override { return localBounds(); }
|
||||
void originXChanged() override;
|
||||
void originYChanged() override;
|
||||
|
||||
|
||||
@@ -55,6 +55,7 @@ public:
|
||||
void scaleYChanged() override;
|
||||
|
||||
void addConstraint(Constraint* constraint);
|
||||
virtual AABB constraintBounds() const { return AABB(); }
|
||||
virtual AABB localBounds() const;
|
||||
void markDirtyIfConstrained();
|
||||
};
|
||||
|
||||
@@ -8,7 +8,7 @@ using namespace rive;
|
||||
|
||||
const Mat2D TransformConstraint::targetTransform() const
|
||||
{
|
||||
AABB bounds = m_Target->localBounds();
|
||||
AABB bounds = m_Target->constraintBounds();
|
||||
Mat2D local =
|
||||
Mat2D::fromTranslate(bounds.left() + bounds.width() * originX(),
|
||||
bounds.top() + bounds.height() * originY());
|
||||
|
||||
@@ -30,6 +30,11 @@ void NSlicedNode::axisChanged() { markPathDirtyRecursive(); }
|
||||
void NSlicedNode::widthChanged() { markPathDirtyRecursive(); }
|
||||
void NSlicedNode::heightChanged() { markPathDirtyRecursive(); }
|
||||
|
||||
AABB NSlicedNode::localBounds() const
|
||||
{
|
||||
return AABB(0, 0, initialWidth(), initialHeight());
|
||||
}
|
||||
|
||||
void NSlicedNode::update(ComponentDirt value)
|
||||
{
|
||||
Super::update(value);
|
||||
|
||||
@@ -539,7 +539,7 @@ void RawPath::printCode() const
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
#endif
|
||||
#ifdef WITH_RIVE_TOOLS
|
||||
|
||||
static void expandAxisBounds(AABB& bounds, int axis, float value)
|
||||
{
|
||||
switch (axis)
|
||||
@@ -713,7 +713,6 @@ AABB RawPath::preciseBounds() const
|
||||
}
|
||||
return bounds;
|
||||
}
|
||||
#endif
|
||||
|
||||
float RawPath::computeCoarseArea() const
|
||||
{
|
||||
|
||||
@@ -150,7 +150,7 @@ float Image::width() const
|
||||
rive::RenderImage* renderImage = asset->renderImage();
|
||||
if (renderImage == nullptr)
|
||||
{
|
||||
return 0.0f;
|
||||
return asset->width();
|
||||
}
|
||||
return (float)renderImage->width();
|
||||
}
|
||||
@@ -166,7 +166,7 @@ float Image::height() const
|
||||
rive::RenderImage* renderImage = asset->renderImage();
|
||||
if (renderImage == nullptr)
|
||||
{
|
||||
return 0.0f;
|
||||
return asset->height();
|
||||
}
|
||||
return (float)renderImage->height();
|
||||
}
|
||||
@@ -243,6 +243,18 @@ void Image::updateImageScale()
|
||||
}
|
||||
}
|
||||
|
||||
AABB Image::localBounds() const
|
||||
{
|
||||
if (imageAsset() == nullptr)
|
||||
{
|
||||
return AABB();
|
||||
}
|
||||
return AABB::fromLTWH(-width() * originX(),
|
||||
-height() * originY(),
|
||||
width(),
|
||||
height());
|
||||
}
|
||||
|
||||
ImageAsset* Image::imageAsset() const { return (ImageAsset*)m_fileAsset.get(); }
|
||||
|
||||
#ifdef TESTING
|
||||
|
||||
@@ -127,6 +127,8 @@ bool Path::canDeferPathUpdate()
|
||||
|
||||
const Mat2D& Path::pathTransform() const { return worldTransform(); }
|
||||
|
||||
AABB Path::localBounds() const { return m_rawPath.preciseBounds(); }
|
||||
|
||||
void Path::buildPath(RawPath& rawPath) const
|
||||
{
|
||||
const bool isClosed = isPathClosed();
|
||||
|
||||
BIN
tests/unit_tests/assets/local_bounds.riv
Normal file
BIN
tests/unit_tests/assets/local_bounds.riv
Normal file
Binary file not shown.
@@ -1,7 +1,12 @@
|
||||
#include "rive/file.hpp"
|
||||
#include "rive/node.hpp"
|
||||
#include "rive/shapes/shape.hpp"
|
||||
#include "rive/layout/n_sliced_node.hpp"
|
||||
#include "rive/layout_component.hpp"
|
||||
#include "rive/math/transform_components.hpp"
|
||||
#include "rive/node.hpp"
|
||||
#include "rive/shapes/image.hpp"
|
||||
#include "rive/shapes/path.hpp"
|
||||
#include "rive/shapes/shape.hpp"
|
||||
#include "rive/text/text.hpp"
|
||||
#include "rive/text/text_value_run.hpp"
|
||||
#include "utils/no_op_renderer.hpp"
|
||||
#include "rive_file_reader.hpp"
|
||||
@@ -67,4 +72,115 @@ TEST_CASE("compute precise bounds of a raw path", "[bounds]")
|
||||
CHECK(preciseBounds.top() == Approx(-1.78456f));
|
||||
CHECK(preciseBounds.right() == Approx(428.90216f));
|
||||
CHECK(preciseBounds.bottom() == Approx(466.05313f));
|
||||
}
|
||||
|
||||
TEST_CASE("test local bounds", "[bounds]")
|
||||
{
|
||||
auto file = ReadRiveFile("assets/local_bounds.riv");
|
||||
|
||||
auto artboard = file->artboard();
|
||||
|
||||
REQUIRE(artboard->find<rive::Shape>("Shape1") != nullptr);
|
||||
REQUIRE(artboard->find<rive::Shape>("Shape2") != nullptr);
|
||||
REQUIRE(artboard->find<rive::Shape>("Shape3") != nullptr);
|
||||
REQUIRE(artboard->find<rive::Text>("Text1") != nullptr);
|
||||
REQUIRE(artboard->find<rive::Text>("Text2") != nullptr);
|
||||
REQUIRE(artboard->find<rive::Node>("Group1") != nullptr);
|
||||
REQUIRE(artboard->find<rive::Image>("Image1") != nullptr);
|
||||
REQUIRE(artboard->find<rive::Image>("Image1")->imageAsset() != nullptr);
|
||||
REQUIRE(artboard->find<rive::NSlicedNode>("NSlice2") != nullptr);
|
||||
REQUIRE(artboard->find<rive::Shape>("CustomShape1") != nullptr);
|
||||
REQUIRE(artboard->find<rive::Path>("CustomPath1") != nullptr);
|
||||
REQUIRE(artboard->find<rive::LayoutComponent>("LayoutContainer") !=
|
||||
nullptr);
|
||||
REQUIRE(artboard->find<rive::LayoutComponent>("LayoutCellLeft") != nullptr);
|
||||
auto shape1 = artboard->find<rive::Shape>("Shape1");
|
||||
auto shape2 = artboard->find<rive::Shape>("Shape2");
|
||||
auto shape3 = artboard->find<rive::Shape>("Shape3");
|
||||
auto text1 = artboard->find<rive::Text>("Text1");
|
||||
auto text2 = artboard->find<rive::Text>("Text2");
|
||||
auto group1 = artboard->find<rive::Node>("Group1");
|
||||
auto image1 = artboard->find<rive::Image>("Image1");
|
||||
auto nslice2 = artboard->find<rive::NSlicedNode>("NSlice2");
|
||||
auto customShape1 = artboard->find<rive::Shape>("CustomShape1");
|
||||
auto customPath1 = artboard->find<rive::Path>("CustomPath1");
|
||||
auto layoutContainer =
|
||||
artboard->find<rive::LayoutComponent>("LayoutContainer");
|
||||
auto layoutCell = artboard->find<rive::LayoutComponent>("LayoutCellLeft");
|
||||
|
||||
artboard->advance(0.0f);
|
||||
|
||||
// Origin 0.5,0.5
|
||||
auto shape1Bounds = shape1->localBounds();
|
||||
CHECK(shape1Bounds.left() == -35.0f);
|
||||
CHECK(shape1Bounds.top() == -35.0f);
|
||||
CHECK(shape1Bounds.right() == 35.0f);
|
||||
CHECK(shape1Bounds.bottom() == 35.0f);
|
||||
// Origin 1.0,1.0
|
||||
auto shape2Bounds = shape2->localBounds();
|
||||
CHECK(shape2Bounds.left() == -80.0f);
|
||||
CHECK(shape2Bounds.top() == -80.0f);
|
||||
CHECK(shape2Bounds.right() == 0.0f);
|
||||
CHECK(shape2Bounds.bottom() == 0.0f);
|
||||
// Origin 0.0,0.0
|
||||
auto shape3Bounds = shape3->localBounds();
|
||||
CHECK(shape3Bounds.left() == 0.0f);
|
||||
CHECK(shape3Bounds.top() == 0.0f);
|
||||
CHECK(shape3Bounds.right() == 60.0f);
|
||||
CHECK(shape3Bounds.bottom() == 60.0f);
|
||||
// Origin 0.0,0.0
|
||||
auto text1Bounds = text1->localBounds();
|
||||
CHECK(text1Bounds.left() == 0.0f);
|
||||
CHECK(text1Bounds.top() == 0.0f);
|
||||
CHECK(text1Bounds.right() == Approx(159.55078f));
|
||||
CHECK(text1Bounds.bottom() == Approx(24.19921f));
|
||||
// Origin 0.5,0.5
|
||||
auto text2Bounds = text2->localBounds();
|
||||
CHECK(text2Bounds.left() == Approx(-79.77539f));
|
||||
CHECK(text2Bounds.top() == Approx(-12.099609f));
|
||||
CHECK(text2Bounds.right() == Approx(79.77539f));
|
||||
CHECK(text2Bounds.bottom() == Approx(12.099609f));
|
||||
|
||||
auto group1Bounds = group1->localBounds();
|
||||
CHECK(group1Bounds.left() == 0.0f);
|
||||
CHECK(group1Bounds.top() == 0.0f);
|
||||
CHECK(group1Bounds.right() == 0.0f);
|
||||
CHECK(group1Bounds.bottom() == 0.0f);
|
||||
|
||||
// Origin 0.5,0.5
|
||||
auto image1Bounds = image1->localBounds();
|
||||
CHECK(image1Bounds.left() == -64.0f);
|
||||
CHECK(image1Bounds.top() == -64.0f);
|
||||
CHECK(image1Bounds.right() == 64.0f);
|
||||
CHECK(image1Bounds.bottom() == 64.0f);
|
||||
|
||||
auto nslice2Bounds = nslice2->localBounds();
|
||||
CHECK(nslice2Bounds.left() == 0.0f);
|
||||
CHECK(nslice2Bounds.top() == 0.0f);
|
||||
CHECK(nslice2Bounds.right() == Approx(112.1891f));
|
||||
CHECK(nslice2Bounds.bottom() == Approx(77.7086f));
|
||||
|
||||
auto customShape1Bounds = customShape1->localBounds();
|
||||
CHECK(customShape1Bounds.left() == Approx(-27.82596f));
|
||||
CHECK(customShape1Bounds.top() == Approx(-32.0276f));
|
||||
CHECK(customShape1Bounds.right() == Approx(105.36988f));
|
||||
CHECK(customShape1Bounds.bottom() == Approx(52.38258f));
|
||||
|
||||
auto customPath1Bounds = customPath1->localBounds();
|
||||
CHECK(customPath1Bounds.left() == Approx(-11.52589f));
|
||||
CHECK(customPath1Bounds.top() == Approx(-25.32601f));
|
||||
CHECK(customPath1Bounds.right() == Approx(100.66321f));
|
||||
CHECK(customPath1Bounds.bottom() == Approx(52.38258f));
|
||||
|
||||
auto layoutContainerBounds = layoutContainer->localBounds();
|
||||
CHECK(layoutContainerBounds.left() == 0.0f);
|
||||
CHECK(layoutContainerBounds.top() == 0.0f);
|
||||
CHECK(layoutContainerBounds.right() == 200.0f);
|
||||
CHECK(layoutContainerBounds.bottom() == 100.0f);
|
||||
|
||||
auto layoutCellBounds = layoutCell->localBounds();
|
||||
CHECK(layoutCellBounds.left() == 0.0f);
|
||||
CHECK(layoutCellBounds.top() == 0.0f);
|
||||
CHECK(layoutCellBounds.right() == 88.0f);
|
||||
CHECK(layoutCellBounds.bottom() == 84.0f);
|
||||
}
|
||||
Reference in New Issue
Block a user