api: revise the clip() apis.

- Paint explicity allows a shape as a clipper
- Added clipper getter apis

API Updates
 + Shape* Paint::clip()
 * Result Paint::clip(Paint* clipper) -> Result Paint::clip(Shape* clipper)

CAPI Updates
 + Tvg_Paint* tvg_paint_get_clip(const Tvg_Paint* paint)
 * Tvg_Result tvg_paint_clip(Tvg_Paint* paint, Tvg_Paint* clipper)
   -> Tvg_Result tvg_paint_set_clip(Tvg_Paint* paint, Tvg_Paint* clipper);

Please note that clipper type can be changed again to tvg::Path
in the upcoming update.
This commit is contained in:
Hermet Park 2025-05-29 13:10:22 +09:00
parent e2909dd6a4
commit 2eb2b83bb0
6 changed files with 55 additions and 16 deletions

View file

@ -65,6 +65,7 @@ namespace tvg
class RenderMethod;
class Animation;
class Shape;
/**
* @defgroup ThorVG ThorVG
@ -396,13 +397,13 @@ public:
*
* @param[in] clipper The shape object as the clipper.
*
* @retval Result::NonSupport If the @p clipper type is not Shape.
* @retval Result::InsufficientCondition if the target has already belonged to another paint.
* @retval Result::InsufficientCondition if the @p clipper has already belonged to another paint.
*
* @see Paint::clip()
*
* @note @p clipper only supports the Shape type.
* @since 1.0
*/
Result clip(Paint* clipper) noexcept;
Result clip(Shape* clipper) noexcept;
/**
* @brief Sets the blending method for the paint object.
@ -478,6 +479,19 @@ public:
*/
MaskMethod mask(const Paint** target) const noexcept;
/**
* @brief Get the clipper shape of the paint object.
*
* This function returns the clipper that has been previously set to this paint object.
*
* @return The shape object used as the clipper, or @c nullptr if no clipper is set.
*
* @see Paint::clip(Shape* clipper)
*
* @since 1.0
*/
Shape* clip() const noexcept;
/**
* @brief Increment the reference count for the Paint instance.
*

View file

@ -972,7 +972,7 @@ TVG_API Tvg_Result tvg_paint_set_mask_method(Tvg_Paint* paint, Tvg_Paint* target
TVG_API Tvg_Result tvg_paint_get_mask_method(const Tvg_Paint* paint, const Tvg_Paint** target, Tvg_Mask_Method* method);
/*!
/**
* @brief Clip the drawing region of the paint object.
*
* This function restricts the drawing area of the paint object to the specified shape's paths.
@ -985,10 +985,24 @@ TVG_API Tvg_Result tvg_paint_get_mask_method(const Tvg_Paint* paint, const Tvg_P
* @retval TVG_RESULT_INSUFFICIENT_CONDITION if the target has already belonged to another paint.
* @retval TVG_RESULT_NOT_SUPPORTED If the @p clipper type is not Shape.
*
* @see tvg_paint_get_clip()
* @since 1.0
*/
TVG_API Tvg_Result tvg_paint_clip(Tvg_Paint* paint, Tvg_Paint* clipper);
TVG_API Tvg_Result tvg_paint_set_clip(Tvg_Paint* paint, Tvg_Paint* clipper);
/**
* @brief Get the clipper shape of the paint object.
*
* This function returns the clipper that has been previously set to this paint object.
*
* @return The shape object used as the clipper, or @c nullptr if no clipper is set.
*
* @see tvg_paint_set_clip()
*
* @since 1.0
*/
TVG_API Tvg_Paint* tvg_paint_get_clip(const Tvg_Paint* paint);
/**
* @brief Retrieves the parent paint object.

View file

@ -304,10 +304,17 @@ TVG_API Tvg_Result tvg_paint_get_type(const Tvg_Paint* paint, Tvg_Type* type)
}
TVG_API Tvg_Result tvg_paint_clip(Tvg_Paint* paint, Tvg_Paint* clipper)
TVG_API Tvg_Result tvg_paint_set_clip(Tvg_Paint* paint, Tvg_Paint* clipper)
{
if (!paint) return TVG_RESULT_INVALID_ARGUMENT;
return (Tvg_Result) reinterpret_cast<Paint*>(paint)->clip((Paint*)(clipper));
return (Tvg_Result) reinterpret_cast<Paint*>(paint)->clip((Shape*)(clipper));
}
TVG_API Tvg_Paint* tvg_paint_get_clip(const Tvg_Paint* paint)
{
if (!paint) return nullptr;
return (Tvg_Paint*) reinterpret_cast<const Paint*>(paint)->clip();
}

View file

@ -168,7 +168,7 @@ Paint* Paint::Impl::duplicate(Paint* ret)
ret->pImpl->opacity = opacity;
if (maskData) ret->mask(maskData->target->duplicate(), maskData->method);
if (clipper) ret->clip(clipper->duplicate());
if (clipper) ret->clip(static_cast<Shape*>(clipper->duplicate()));
return ret;
}
@ -376,16 +376,18 @@ Paint* Paint::duplicate() const noexcept
}
Result Paint::clip(Paint* clipper) noexcept
Result Paint::clip(Shape* clipper) noexcept
{
if (clipper && clipper->type() != Type::Shape) {
TVGERR("RENDERER", "Clipping only supports the Shape!");
return Result::NonSupport;
}
return pImpl->clip(clipper);
}
Shape* Paint::clip() const noexcept
{
return pImpl->clipper;
}
Result Paint::mask(Paint* target, MaskMethod method) noexcept
{
return pImpl->mask(target, method);

View file

@ -54,7 +54,7 @@ namespace tvg
Paint* paint = nullptr;
Paint* parent = nullptr;
Mask* maskData = nullptr;
Paint* clipper = nullptr;
Shape* clipper = nullptr;
RenderMethod* renderer = nullptr;
RenderData rd = nullptr;
@ -163,7 +163,7 @@ namespace tvg
return tm;
}
Result clip(Paint* clp)
Result clip(Shape* clp)
{
if (clp && PAINT(clp)->parent) return Result::InsufficientCondition;
if (clipper) PAINT(clipper)->unref(clipper != clp);

View file

@ -223,7 +223,9 @@ TEST_CASE("Composition", "[tvgPaint]")
//Clipping
auto comp = Shape::gen();
REQUIRE(shape->clip() == nullptr);
REQUIRE(shape->clip(comp) == Result::Success);
REQUIRE(shape->clip() == comp);
//AlphaMask
comp = Shape::gen();