mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-07 21:23:32 +00:00
renderer: revise the pImpl design with a better efficiency
The following is a redesign that extends the class internally. The main goal is to preserve the characteristics of the pImpl idiom for data encapsulation, while simultaneously reducing the memory allocation overhead typically associated with pImpl. The stragegy is here: Rather than alloc the impl memory inside of the thorvg engine, impl extends the API classes in order to consolidate the memory. size has been decreased by -4kb with optimization=s issue: https://github.com/thorvg/thorvg/issues/3214
This commit is contained in:
parent
7feb43201b
commit
1a332acd37
18 changed files with 192 additions and 189 deletions
23
inc/thorvg.h
23
inc/thorvg.h
|
@ -801,8 +801,10 @@ public:
|
||||||
*
|
*
|
||||||
* Besides the APIs inherited from the Fill class, it enables setting and getting the linear gradient bounds.
|
* Besides the APIs inherited from the Fill class, it enables setting and getting the linear gradient bounds.
|
||||||
* The behavior outside the gradient bounds depends on the value specified in the spread API.
|
* The behavior outside the gradient bounds depends on the value specified in the spread API.
|
||||||
|
*
|
||||||
|
* @warning This class is not designed for inheritance.
|
||||||
*/
|
*/
|
||||||
class TVG_API LinearGradient final : public Fill
|
class TVG_API LinearGradient : public Fill
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
|
@ -863,8 +865,9 @@ public:
|
||||||
*
|
*
|
||||||
* @brief A class representing the radial gradient fill of the Shape object.
|
* @brief A class representing the radial gradient fill of the Shape object.
|
||||||
*
|
*
|
||||||
|
* @warning This class is not designed for inheritance.
|
||||||
*/
|
*/
|
||||||
class TVG_API RadialGradient final : public Fill
|
class TVG_API RadialGradient : public Fill
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
|
@ -939,8 +942,10 @@ public:
|
||||||
*
|
*
|
||||||
* The stroke of Shape is an optional property in case the Shape needs to be represented with/without the outline borders.
|
* The stroke of Shape is an optional property in case the Shape needs to be represented with/without the outline borders.
|
||||||
* It's efficient since the shape path and the stroking path can be shared with each other. It's also convenient when controlling both in one context.
|
* It's efficient since the shape path and the stroking path can be shared with each other. It's also convenient when controlling both in one context.
|
||||||
|
*
|
||||||
|
* @warning This class is not designed for inheritance.
|
||||||
*/
|
*/
|
||||||
class TVG_API Shape final : public Paint
|
class TVG_API Shape : public Paint
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
|
@ -1319,8 +1324,10 @@ public:
|
||||||
*
|
*
|
||||||
* @note Supported formats are depended on the available TVG loaders.
|
* @note Supported formats are depended on the available TVG loaders.
|
||||||
* @note See Animation class if the picture data is animatable.
|
* @note See Animation class if the picture data is animatable.
|
||||||
|
*
|
||||||
|
* @warning This class is not designed for inheritance.
|
||||||
*/
|
*/
|
||||||
class TVG_API Picture final : public Paint
|
class TVG_API Picture : public Paint
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
|
@ -1450,8 +1457,10 @@ public:
|
||||||
*
|
*
|
||||||
* As a group, the scene can be transformed, made translucent and composited with other target paints,
|
* As a group, the scene can be transformed, made translucent and composited with other target paints,
|
||||||
* its children will be affected by the scene world.
|
* its children will be affected by the scene world.
|
||||||
|
*
|
||||||
|
* @warning This class is not designed for inheritance.
|
||||||
*/
|
*/
|
||||||
class TVG_API Scene final : public Paint
|
class TVG_API Scene : public Paint
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
|
@ -1546,9 +1555,11 @@ public:
|
||||||
*
|
*
|
||||||
* @brief A class to represent text objects in a graphical context, allowing for rendering and manipulation of unicode text.
|
* @brief A class to represent text objects in a graphical context, allowing for rendering and manipulation of unicode text.
|
||||||
*
|
*
|
||||||
|
* @warning This class is not designed for inheritance.
|
||||||
|
*
|
||||||
* @since 0.15
|
* @since 0.15
|
||||||
*/
|
*/
|
||||||
class TVG_API Text final : public Paint
|
class TVG_API Text : public Paint
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -481,7 +481,7 @@ void LottieBuilder::updatePath(LottieGroup* parent, LottieObject** child, float
|
||||||
if (ctx->repeaters.empty()) {
|
if (ctx->repeaters.empty()) {
|
||||||
_draw(parent, path, ctx);
|
_draw(parent, path, ctx);
|
||||||
if (path->pathset(frameNo, SHAPE(ctx->merging)->rs.path, ctx->transform, tween, exps, ctx->modifier)) {
|
if (path->pathset(frameNo, SHAPE(ctx->merging)->rs.path, ctx->transform, tween, exps, ctx->modifier)) {
|
||||||
PAINT(ctx->merging)->update(RenderUpdateFlag::Path);
|
PAINT(ctx->merging)->mark(RenderUpdateFlag::Path);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
auto shape = path->pooling();
|
auto shape = path->pooling();
|
||||||
|
@ -695,7 +695,7 @@ void LottieBuilder::updatePolystar(LottieGroup* parent, LottieObject** child, fl
|
||||||
_draw(parent, star, ctx);
|
_draw(parent, star, ctx);
|
||||||
if (star->type == LottiePolyStar::Star) updateStar(star, frameNo, (identity ? nullptr : &matrix), ctx->merging, ctx, tween, exps);
|
if (star->type == LottiePolyStar::Star) updateStar(star, frameNo, (identity ? nullptr : &matrix), ctx->merging, ctx, tween, exps);
|
||||||
else updatePolygon(parent, star, frameNo, (identity ? nullptr : &matrix), ctx->merging, ctx, tween, exps);
|
else updatePolygon(parent, star, frameNo, (identity ? nullptr : &matrix), ctx->merging, ctx, tween, exps);
|
||||||
PAINT(ctx->merging)->update(RenderUpdateFlag::Path);
|
PAINT(ctx->merging)->mark(RenderUpdateFlag::Path);
|
||||||
} else {
|
} else {
|
||||||
auto shape = star->pooling();
|
auto shape = star->pooling();
|
||||||
shape->reset();
|
shape->reset();
|
||||||
|
@ -1037,7 +1037,7 @@ void LottieBuilder::updateText(LottieLayer* layer, float frameNo)
|
||||||
auto group = static_cast<LottieGroup*>(*p);
|
auto group = static_cast<LottieGroup*>(*p);
|
||||||
ARRAY_FOREACH(p, group->children) {
|
ARRAY_FOREACH(p, group->children) {
|
||||||
if (static_cast<LottiePath*>(*p)->pathset(frameNo, SHAPE(shape)->rs.path, nullptr, tween, exps)) {
|
if (static_cast<LottiePath*>(*p)->pathset(frameNo, SHAPE(shape)->rs.path, nullptr, tween, exps)) {
|
||||||
PAINT(shape)->update(RenderUpdateFlag::Path);
|
PAINT(shape)->mark(RenderUpdateFlag::Path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1469,10 +1469,10 @@ RenderData GlRenderer::prepare(const RenderShape& rshape, RenderData data, const
|
||||||
if (clipper) {
|
if (clipper) {
|
||||||
sdata->updateFlag = (rshape.stroke && (rshape.stroke->width > 0)) ? RenderUpdateFlag::Stroke : RenderUpdateFlag::Path;
|
sdata->updateFlag = (rshape.stroke && (rshape.stroke->width > 0)) ? RenderUpdateFlag::Stroke : RenderUpdateFlag::Path;
|
||||||
} else {
|
} else {
|
||||||
if (alphaF) sdata->updateFlag = static_cast<RenderUpdateFlag>(RenderUpdateFlag::Color | sdata->updateFlag);
|
if (alphaF) sdata->updateFlag = (RenderUpdateFlag::Color | sdata->updateFlag);
|
||||||
if (rshape.fill) sdata->updateFlag = static_cast<RenderUpdateFlag>(RenderUpdateFlag::Gradient | sdata->updateFlag);
|
if (rshape.fill) sdata->updateFlag = (RenderUpdateFlag::Gradient | sdata->updateFlag);
|
||||||
if (alphaS) sdata->updateFlag = static_cast<RenderUpdateFlag>(RenderUpdateFlag::Stroke | sdata->updateFlag);
|
if (alphaS) sdata->updateFlag = (RenderUpdateFlag::Stroke | sdata->updateFlag);
|
||||||
if (rshape.strokeFill()) sdata->updateFlag = static_cast<RenderUpdateFlag>(RenderUpdateFlag::GradientStroke | sdata->updateFlag);
|
if (rshape.strokeFill()) sdata->updateFlag = (RenderUpdateFlag::GradientStroke | sdata->updateFlag);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sdata->updateFlag == RenderUpdateFlag::None) return sdata;
|
if (sdata->updateFlag == RenderUpdateFlag::None) return sdata;
|
||||||
|
|
|
@ -67,10 +67,10 @@ static uint32_t _estimateAAMargin(const Fill* fdata)
|
||||||
constexpr float marginScalingFactor = 800.0f;
|
constexpr float marginScalingFactor = 800.0f;
|
||||||
|
|
||||||
if (fdata->type() == Type::RadialGradient) {
|
if (fdata->type() == Type::RadialGradient) {
|
||||||
auto radius = RADIAL(fdata)->r;
|
auto radius = CONST_RADIAL(fdata)->r;
|
||||||
return tvg::zero(radius) ? 0 : static_cast<uint32_t>(marginScalingFactor / radius);
|
return tvg::zero(radius) ? 0 : static_cast<uint32_t>(marginScalingFactor / radius);
|
||||||
} else {
|
} else {
|
||||||
auto grad = LINEAR(fdata);
|
auto grad = CONST_LINEAR(fdata);
|
||||||
Point p1 {grad->x1, grad->y1};
|
Point p1 {grad->x1, grad->y1};
|
||||||
Point p2 {grad->x2, grad->y2};
|
Point p2 {grad->x2, grad->y2};
|
||||||
auto len = length(&p1, &p2);
|
auto len = length(&p1, &p2);
|
||||||
|
@ -226,7 +226,7 @@ bool _prepareLinear(SwFill* fill, const LinearGradient* linear, const Matrix& pT
|
||||||
fill->linear.dy /= len;
|
fill->linear.dy /= len;
|
||||||
fill->linear.offset = -fill->linear.dx * x1 - fill->linear.dy * y1;
|
fill->linear.offset = -fill->linear.dx * x1 - fill->linear.dy * y1;
|
||||||
|
|
||||||
auto transform = pTransform * linear->transform();
|
const auto& transform = pTransform * linear->transform();
|
||||||
|
|
||||||
Matrix itransform;
|
Matrix itransform;
|
||||||
if (!inverse(&transform, &itransform)) return false;
|
if (!inverse(&transform, &itransform)) return false;
|
||||||
|
@ -279,7 +279,7 @@ bool _prepareRadial(SwFill* fill, const RadialGradient* radial, const Matrix& pT
|
||||||
|
|
||||||
if (fill->radial.a > 0) fill->radial.invA = 1.0f / fill->radial.a;
|
if (fill->radial.a > 0) fill->radial.invA = 1.0f / fill->radial.a;
|
||||||
|
|
||||||
auto transform = pTransform * radial->transform();
|
const auto& transform = pTransform * radial->transform();
|
||||||
|
|
||||||
Matrix itransform;
|
Matrix itransform;
|
||||||
if (!inverse(&transform, &itransform)) return false;
|
if (!inverse(&transform, &itransform)) return false;
|
||||||
|
|
|
@ -89,8 +89,6 @@ namespace tvg {
|
||||||
|
|
||||||
uint16_t THORVG_VERSION_NUMBER();
|
uint16_t THORVG_VERSION_NUMBER();
|
||||||
|
|
||||||
#define PIMPL(INST, CLASS) ((CLASS::Impl*)INST->pImpl) //Access to pimpl
|
|
||||||
|
|
||||||
#define TVG_DELETE(PAINT) \
|
#define TVG_DELETE(PAINT) \
|
||||||
if (PAINT->refCnt() == 0) delete(PAINT)
|
if (PAINT->refCnt() == 0) delete(PAINT)
|
||||||
|
|
||||||
|
|
|
@ -27,16 +27,8 @@
|
||||||
/* Fill Class Implementation */
|
/* Fill Class Implementation */
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
|
|
||||||
Fill::Fill()
|
Fill::Fill() = default;
|
||||||
{
|
Fill::~Fill() = default;
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Fill::~Fill()
|
|
||||||
{
|
|
||||||
delete(pImpl);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Result Fill::colorStops(const ColorStop* colorStops, uint32_t cnt) noexcept
|
Result Fill::colorStops(const ColorStop* colorStops, uint32_t cnt) noexcept
|
||||||
{
|
{
|
||||||
|
@ -79,7 +71,9 @@ Matrix& Fill::transform() const noexcept
|
||||||
|
|
||||||
Fill* Fill::duplicate() const noexcept
|
Fill* Fill::duplicate() const noexcept
|
||||||
{
|
{
|
||||||
return pImpl->duplicate();
|
if (type() == Type::LinearGradient) return CONST_LINEAR(this)->duplicate();
|
||||||
|
else if (type() == Type::RadialGradient) return CONST_RADIAL(this)->duplicate();
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -87,11 +81,7 @@ Fill* Fill::duplicate() const noexcept
|
||||||
/* RadialGradient Class Implementation */
|
/* RadialGradient Class Implementation */
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
|
|
||||||
|
RadialGradient::RadialGradient() = default;
|
||||||
RadialGradient::RadialGradient()
|
|
||||||
{
|
|
||||||
Fill::pImpl = new Impl;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Result RadialGradient::radial(float cx, float cy, float r, float fx, float fy, float fr) noexcept
|
Result RadialGradient::radial(float cx, float cy, float r, float fx, float fy, float fr) noexcept
|
||||||
|
@ -102,13 +92,13 @@ Result RadialGradient::radial(float cx, float cy, float r, float fx, float fy, f
|
||||||
|
|
||||||
Result RadialGradient::radial(float* cx, float* cy, float* r, float* fx, float* fy, float* fr) const noexcept
|
Result RadialGradient::radial(float* cx, float* cy, float* r, float* fx, float* fy, float* fr) const noexcept
|
||||||
{
|
{
|
||||||
return RADIAL(this)->radial(cx, cy, r, fx, fy, fr);
|
return CONST_RADIAL(this)->radial(cx, cy, r, fx, fy, fr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
RadialGradient* RadialGradient::gen() noexcept
|
RadialGradient* RadialGradient::gen() noexcept
|
||||||
{
|
{
|
||||||
return new RadialGradient;
|
return new RadialGradientImpl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -122,11 +112,7 @@ Type RadialGradient::type() const noexcept
|
||||||
/* LinearGradient Class Implementation */
|
/* LinearGradient Class Implementation */
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
|
|
||||||
|
LinearGradient::LinearGradient() = default;
|
||||||
LinearGradient::LinearGradient()
|
|
||||||
{
|
|
||||||
Fill::pImpl = new Impl;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Result LinearGradient::linear(float x1, float y1, float x2, float y2) noexcept
|
Result LinearGradient::linear(float x1, float y1, float x2, float y2) noexcept
|
||||||
|
@ -137,13 +123,13 @@ Result LinearGradient::linear(float x1, float y1, float x2, float y2) noexcept
|
||||||
|
|
||||||
Result LinearGradient::linear(float* x1, float* y1, float* x2, float* y2) const noexcept
|
Result LinearGradient::linear(float* x1, float* y1, float* x2, float* y2) const noexcept
|
||||||
{
|
{
|
||||||
return LINEAR(this)->linear(x1, y1, x2, y2);
|
return CONST_LINEAR(this)->linear(x1, y1, x2, y2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
LinearGradient* LinearGradient::gen() noexcept
|
LinearGradient* LinearGradient::gen() noexcept
|
||||||
{
|
{
|
||||||
return new LinearGradient;
|
return new LinearGradientImpl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -26,8 +26,11 @@
|
||||||
#include "tvgCommon.h"
|
#include "tvgCommon.h"
|
||||||
#include "tvgMath.h"
|
#include "tvgMath.h"
|
||||||
|
|
||||||
#define LINEAR(A) PIMPL(A, LinearGradient)
|
#define LINEAR(A) static_cast<LinearGradientImpl*>(A)
|
||||||
#define RADIAL(A) PIMPL(A, RadialGradient)
|
#define CONST_LINEAR(A) static_cast<const LinearGradientImpl*>(A)
|
||||||
|
|
||||||
|
#define RADIAL(A) static_cast<RadialGradientImpl*>(A)
|
||||||
|
#define CONST_RADIAL(A) static_cast<const RadialGradientImpl*>(A)
|
||||||
|
|
||||||
struct Fill::Impl
|
struct Fill::Impl
|
||||||
{
|
{
|
||||||
|
@ -41,13 +44,13 @@ struct Fill::Impl
|
||||||
tvg::free(colorStops);
|
tvg::free(colorStops);
|
||||||
}
|
}
|
||||||
|
|
||||||
void copy(Fill::Impl* dup)
|
void copy(const Fill::Impl& dup)
|
||||||
{
|
{
|
||||||
cnt = dup->cnt;
|
cnt = dup.cnt;
|
||||||
spread = dup->spread;
|
spread = dup.spread;
|
||||||
colorStops = tvg::malloc<ColorStop*>(sizeof(ColorStop) * dup->cnt);
|
colorStops = tvg::malloc<ColorStop*>(sizeof(ColorStop) * dup.cnt);
|
||||||
if (dup->cnt > 0) memcpy(colorStops, dup->colorStops, sizeof(ColorStop) * dup->cnt);
|
if (dup.cnt > 0) memcpy(colorStops, dup.colorStops, sizeof(ColorStop) * dup.cnt);
|
||||||
transform = dup->transform;
|
transform = dup.transform;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result update(const ColorStop* colorStops, uint32_t cnt)
|
Result update(const ColorStop* colorStops, uint32_t cnt)
|
||||||
|
@ -72,21 +75,26 @@ struct Fill::Impl
|
||||||
|
|
||||||
return Result::Success;
|
return Result::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual Fill* duplicate() = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
struct RadialGradient::Impl : Fill::Impl
|
struct RadialGradientImpl : RadialGradient
|
||||||
{
|
{
|
||||||
|
Fill::Impl impl;
|
||||||
|
|
||||||
float cx = 0.0f, cy = 0.0f;
|
float cx = 0.0f, cy = 0.0f;
|
||||||
float fx = 0.0f, fy = 0.0f;
|
float fx = 0.0f, fy = 0.0f;
|
||||||
float r = 0.0f, fr = 0.0f;
|
float r = 0.0f, fr = 0.0f;
|
||||||
|
|
||||||
Fill* duplicate() override
|
RadialGradientImpl()
|
||||||
|
{
|
||||||
|
Fill::pImpl = &impl;
|
||||||
|
}
|
||||||
|
|
||||||
|
Fill* duplicate() const
|
||||||
{
|
{
|
||||||
auto ret = RadialGradient::gen();
|
auto ret = RadialGradient::gen();
|
||||||
RADIAL(ret)->copy(this);
|
RADIAL(ret)->impl.copy(this->impl);
|
||||||
RADIAL(ret)->cx = cx;
|
RADIAL(ret)->cx = cx;
|
||||||
RADIAL(ret)->cy = cy;
|
RADIAL(ret)->cy = cy;
|
||||||
RADIAL(ret)->r = r;
|
RADIAL(ret)->r = r;
|
||||||
|
@ -125,17 +133,24 @@ struct RadialGradient::Impl : Fill::Impl
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
struct LinearGradient::Impl : Fill::Impl
|
struct LinearGradientImpl : LinearGradient
|
||||||
{
|
{
|
||||||
|
Fill::Impl impl;
|
||||||
|
|
||||||
float x1 = 0.0f;
|
float x1 = 0.0f;
|
||||||
float y1 = 0.0f;
|
float y1 = 0.0f;
|
||||||
float x2 = 0.0f;
|
float x2 = 0.0f;
|
||||||
float y2 = 0.0f;
|
float y2 = 0.0f;
|
||||||
|
|
||||||
Fill* duplicate() override
|
LinearGradientImpl()
|
||||||
|
{
|
||||||
|
Fill::pImpl = &impl;
|
||||||
|
}
|
||||||
|
|
||||||
|
Fill* duplicate() const
|
||||||
{
|
{
|
||||||
auto ret = LinearGradient::gen();
|
auto ret = LinearGradient::gen();
|
||||||
LINEAR(ret)->copy(this);
|
LINEAR(ret)->impl.copy(this->impl);
|
||||||
LINEAR(ret)->x1 = x1;
|
LINEAR(ret)->x1 = x1;
|
||||||
LINEAR(ret)->y1 = y1;
|
LINEAR(ret)->y1 = y1;
|
||||||
LINEAR(ret)->x2 = x2;
|
LINEAR(ret)->x2 = x2;
|
||||||
|
|
|
@ -163,7 +163,7 @@ Paint* Paint::Impl::duplicate(Paint* ret)
|
||||||
|
|
||||||
//duplicate Transform
|
//duplicate Transform
|
||||||
ret->pImpl->tr = tr;
|
ret->pImpl->tr = tr;
|
||||||
ret->pImpl->renderFlag |= RenderUpdateFlag::Transform;
|
ret->pImpl->mark(RenderUpdateFlag::Transform);
|
||||||
|
|
||||||
ret->pImpl->opacity = opacity;
|
ret->pImpl->opacity = opacity;
|
||||||
|
|
||||||
|
@ -247,7 +247,7 @@ RenderData Paint::Impl::update(RenderMethod* renderer, const Matrix& pm, Array<R
|
||||||
/* 2. Clipping */
|
/* 2. Clipping */
|
||||||
if (this->clipper) {
|
if (this->clipper) {
|
||||||
auto pclip = PAINT(this->clipper);
|
auto pclip = PAINT(this->clipper);
|
||||||
if (pclip->renderFlag) renderFlag |= RenderUpdateFlag::Clip;
|
if (pclip->renderFlag) mark(RenderUpdateFlag::Clip);
|
||||||
pclip->ctxFlag &= ~ContextFlag::FastTrack; //reset
|
pclip->ctxFlag &= ~ContextFlag::FastTrack; //reset
|
||||||
viewport = renderer->viewport();
|
viewport = renderer->viewport();
|
||||||
/* TODO: Intersect the clipper's clipper, if both are FastTrack.
|
/* TODO: Intersect the clipper's clipper, if both are FastTrack.
|
||||||
|
@ -263,7 +263,7 @@ RenderData Paint::Impl::update(RenderMethod* renderer, const Matrix& pm, Array<R
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 3. Main Update */
|
/* 3. Main Update */
|
||||||
auto newFlag = static_cast<RenderUpdateFlag>(pFlag | renderFlag);
|
auto newFlag = pFlag | renderFlag;
|
||||||
renderFlag = RenderUpdateFlag::None;
|
renderFlag = RenderUpdateFlag::None;
|
||||||
opacity = MULTIPLY(opacity, this->opacity);
|
opacity = MULTIPLY(opacity, this->opacity);
|
||||||
|
|
||||||
|
@ -317,15 +317,8 @@ Result Paint::Impl::bounds(Point* pt4, Matrix* pm, bool obb, bool stroking)
|
||||||
/* External Class Implementation */
|
/* External Class Implementation */
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
|
|
||||||
Paint :: Paint()
|
Paint :: Paint() = default;
|
||||||
{
|
Paint :: ~Paint() = default;
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Paint :: ~Paint()
|
|
||||||
{
|
|
||||||
delete(pImpl);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Result Paint::rotate(float degree) noexcept
|
Result Paint::rotate(float degree) noexcept
|
||||||
|
@ -410,7 +403,7 @@ Result Paint::opacity(uint8_t o) noexcept
|
||||||
if (pImpl->opacity == o) return Result::Success;
|
if (pImpl->opacity == o) return Result::Success;
|
||||||
|
|
||||||
pImpl->opacity = o;
|
pImpl->opacity = o;
|
||||||
pImpl->renderFlag |= RenderUpdateFlag::Color;
|
pImpl->mark(RenderUpdateFlag::Color);
|
||||||
|
|
||||||
return Result::Success;
|
return Result::Success;
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,8 @@
|
||||||
#include "tvgRender.h"
|
#include "tvgRender.h"
|
||||||
#include "tvgMath.h"
|
#include "tvgMath.h"
|
||||||
|
|
||||||
#define PAINT(A) PIMPL(A, Paint)
|
|
||||||
|
#define PAINT(A) ((Paint::Impl*)A->pImpl)
|
||||||
|
|
||||||
namespace tvg
|
namespace tvg
|
||||||
{
|
{
|
||||||
|
@ -85,6 +86,7 @@ namespace tvg
|
||||||
|
|
||||||
Impl(Paint* pnt) : paint(pnt)
|
Impl(Paint* pnt) : paint(pnt)
|
||||||
{
|
{
|
||||||
|
pnt->pImpl = this;
|
||||||
reset();
|
reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,7 +131,7 @@ namespace tvg
|
||||||
return refCnt;
|
return refCnt;
|
||||||
}
|
}
|
||||||
|
|
||||||
void update(RenderUpdateFlag flag)
|
void mark(RenderUpdateFlag flag)
|
||||||
{
|
{
|
||||||
renderFlag |= flag;
|
renderFlag |= flag;
|
||||||
}
|
}
|
||||||
|
@ -138,7 +140,7 @@ namespace tvg
|
||||||
{
|
{
|
||||||
if (&tr.m != &m) tr.m = m;
|
if (&tr.m != &m) tr.m = m;
|
||||||
tr.overriding = true;
|
tr.overriding = true;
|
||||||
renderFlag |= RenderUpdateFlag::Transform;
|
mark(RenderUpdateFlag::Transform);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -236,7 +238,7 @@ namespace tvg
|
||||||
if (tr.overriding) return false;
|
if (tr.overriding) return false;
|
||||||
if (tvg::equal(degree, tr.degree)) return true;
|
if (tvg::equal(degree, tr.degree)) return true;
|
||||||
tr.degree = degree;
|
tr.degree = degree;
|
||||||
renderFlag |= RenderUpdateFlag::Transform;
|
mark(RenderUpdateFlag::Transform);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -246,7 +248,7 @@ namespace tvg
|
||||||
if (tr.overriding) return false;
|
if (tr.overriding) return false;
|
||||||
if (tvg::equal(factor, tr.scale)) return true;
|
if (tvg::equal(factor, tr.scale)) return true;
|
||||||
tr.scale = factor;
|
tr.scale = factor;
|
||||||
renderFlag |= RenderUpdateFlag::Transform;
|
mark(RenderUpdateFlag::Transform);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -257,7 +259,7 @@ namespace tvg
|
||||||
if (tvg::equal(x, tr.m.e13) && tvg::equal(y, tr.m.e23)) return true;
|
if (tvg::equal(x, tr.m.e13) && tvg::equal(y, tr.m.e23)) return true;
|
||||||
tr.m.e13 = x;
|
tr.m.e13 = x;
|
||||||
tr.m.e23 = y;
|
tr.m.e23 = y;
|
||||||
renderFlag |= RenderUpdateFlag::Transform;
|
mark(RenderUpdateFlag::Transform);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -266,7 +268,7 @@ namespace tvg
|
||||||
{
|
{
|
||||||
if (blendMethod != method) {
|
if (blendMethod != method) {
|
||||||
blendMethod = method;
|
blendMethod = method;
|
||||||
renderFlag |= RenderUpdateFlag::Blend;
|
mark(RenderUpdateFlag::Blend);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,15 +23,12 @@
|
||||||
#include "tvgPaint.h"
|
#include "tvgPaint.h"
|
||||||
#include "tvgPicture.h"
|
#include "tvgPicture.h"
|
||||||
|
|
||||||
Picture::Picture()
|
Picture::Picture() = default;
|
||||||
{
|
|
||||||
pImpl = new Impl(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Picture* Picture::gen() noexcept
|
Picture* Picture::gen() noexcept
|
||||||
{
|
{
|
||||||
return new Picture;
|
return new PictureImpl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -74,7 +71,7 @@ Result Picture::size(float w, float h) noexcept
|
||||||
|
|
||||||
Result Picture::size(float* w, float* h) const noexcept
|
Result Picture::size(float* w, float* h) const noexcept
|
||||||
{
|
{
|
||||||
return PICTURE(this)->size(w, h);
|
return CONST_PICTURE(this)->size(w, h);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,8 @@
|
||||||
#include "tvgPaint.h"
|
#include "tvgPaint.h"
|
||||||
#include "tvgLoader.h"
|
#include "tvgLoader.h"
|
||||||
|
|
||||||
#define PICTURE(A) PIMPL(A, Picture)
|
#define PICTURE(A) static_cast<PictureImpl*>(A)
|
||||||
|
#define CONST_PICTURE(A) static_cast<const PictureImpl*>(A)
|
||||||
|
|
||||||
struct PictureIterator : Iterator
|
struct PictureIterator : Iterator
|
||||||
{
|
{
|
||||||
|
@ -55,8 +56,9 @@ struct PictureIterator : Iterator
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
struct Picture::Impl : Paint::Impl
|
struct PictureImpl : Picture
|
||||||
{
|
{
|
||||||
|
Paint::Impl impl;
|
||||||
ImageLoader* loader = nullptr;
|
ImageLoader* loader = nullptr;
|
||||||
Paint* vector = nullptr; //vector picture uses
|
Paint* vector = nullptr; //vector picture uses
|
||||||
RenderSurface* bitmap = nullptr; //bitmap picture uses
|
RenderSurface* bitmap = nullptr; //bitmap picture uses
|
||||||
|
@ -64,11 +66,11 @@ struct Picture::Impl : Paint::Impl
|
||||||
uint8_t compFlag = CompositionFlag::Invalid;
|
uint8_t compFlag = CompositionFlag::Invalid;
|
||||||
bool resizing = false;
|
bool resizing = false;
|
||||||
|
|
||||||
Impl(Picture* p) : Paint::Impl(p)
|
PictureImpl() : impl(Paint::Impl(this))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
~Impl()
|
~PictureImpl()
|
||||||
{
|
{
|
||||||
LoaderMgr::retrieve(loader);
|
LoaderMgr::retrieve(loader);
|
||||||
delete(vector);
|
delete(vector);
|
||||||
|
@ -76,10 +78,10 @@ struct Picture::Impl : Paint::Impl
|
||||||
|
|
||||||
RenderData update(RenderMethod* renderer, const Matrix& transform, Array<RenderData>& clips, uint8_t opacity, RenderUpdateFlag pFlag, TVG_UNUSED bool clipper)
|
RenderData update(RenderMethod* renderer, const Matrix& transform, Array<RenderData>& clips, uint8_t opacity, RenderUpdateFlag pFlag, TVG_UNUSED bool clipper)
|
||||||
{
|
{
|
||||||
auto flag = static_cast<RenderUpdateFlag>(pFlag | load());
|
auto flag = (pFlag | load());
|
||||||
|
|
||||||
if (bitmap) {
|
if (bitmap) {
|
||||||
if (flag == RenderUpdateFlag::None) return rd;
|
if (flag == RenderUpdateFlag::None) return impl.rd;
|
||||||
|
|
||||||
//Overriding Transformation by the desired image size
|
//Overriding Transformation by the desired image size
|
||||||
auto sx = w / loader->w;
|
auto sx = w / loader->w;
|
||||||
|
@ -87,7 +89,7 @@ struct Picture::Impl : Paint::Impl
|
||||||
auto scale = sx < sy ? sx : sy;
|
auto scale = sx < sy ? sx : sy;
|
||||||
auto m = transform * Matrix{scale, 0, 0, 0, scale, 0, 0, 0, 1};
|
auto m = transform * Matrix{scale, 0, 0, 0, scale, 0, 0, 0, 1};
|
||||||
|
|
||||||
rd = renderer->prepare(bitmap, rd, m, clips, opacity, flag);
|
impl.rd = renderer->prepare(bitmap, impl.rd, m, clips, opacity, flag);
|
||||||
} else if (vector) {
|
} else if (vector) {
|
||||||
if (resizing) {
|
if (resizing) {
|
||||||
loader->resize(vector, w, h);
|
loader->resize(vector, w, h);
|
||||||
|
@ -96,7 +98,7 @@ struct Picture::Impl : Paint::Impl
|
||||||
queryComposition(opacity);
|
queryComposition(opacity);
|
||||||
return vector->pImpl->update(renderer, transform, clips, opacity, flag, false);
|
return vector->pImpl->update(renderer, transform, clips, opacity, flag, false);
|
||||||
}
|
}
|
||||||
return rd;
|
return impl.rd;
|
||||||
}
|
}
|
||||||
|
|
||||||
void size(float w, float h)
|
void size(float w, float h)
|
||||||
|
@ -173,7 +175,7 @@ struct Picture::Impl : Paint::Impl
|
||||||
if (loader) {
|
if (loader) {
|
||||||
dup->loader = loader;
|
dup->loader = loader;
|
||||||
++dup->loader->sharing;
|
++dup->loader->sharing;
|
||||||
PAINT(picture)->renderFlag |= RenderUpdateFlag::Image;
|
PAINT(picture)->mark(RenderUpdateFlag::Image);
|
||||||
}
|
}
|
||||||
|
|
||||||
dup->bitmap = bitmap;
|
dup->bitmap = bitmap;
|
||||||
|
@ -214,7 +216,7 @@ struct Picture::Impl : Paint::Impl
|
||||||
} else {
|
} else {
|
||||||
vector = loader->paint();
|
vector = loader->paint();
|
||||||
if (vector) {
|
if (vector) {
|
||||||
PAINT(vector)->parent = paint;
|
PAINT(vector)->parent = this;
|
||||||
if (w != loader->w || h != loader->h) {
|
if (w != loader->w || h != loader->h) {
|
||||||
if (!resizing) {
|
if (!resizing) {
|
||||||
w = loader->w;
|
w = loader->w;
|
||||||
|
@ -244,7 +246,7 @@ struct Picture::Impl : Paint::Impl
|
||||||
|
|
||||||
//Composition test
|
//Composition test
|
||||||
const Paint* target;
|
const Paint* target;
|
||||||
paint->mask(&target);
|
PAINT(this)->mask(&target);
|
||||||
if (!target || target->pImpl->opacity == 255 || target->pImpl->opacity == 0) return;
|
if (!target || target->pImpl->opacity == 255 || target->pImpl->opacity == 0) return;
|
||||||
compFlag = CompositionFlag::Opacity;
|
compFlag = CompositionFlag::Opacity;
|
||||||
}
|
}
|
||||||
|
@ -252,9 +254,9 @@ struct Picture::Impl : Paint::Impl
|
||||||
bool render(RenderMethod* renderer)
|
bool render(RenderMethod* renderer)
|
||||||
{
|
{
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
renderer->blend(blendMethod);
|
renderer->blend(impl.blendMethod);
|
||||||
|
|
||||||
if (bitmap) return renderer->renderImage(rd);
|
if (bitmap) return renderer->renderImage(impl.rd);
|
||||||
else if (vector) {
|
else if (vector) {
|
||||||
RenderCompositor* cmp = nullptr;
|
RenderCompositor* cmp = nullptr;
|
||||||
if (compFlag) {
|
if (compFlag) {
|
||||||
|
@ -269,7 +271,7 @@ struct Picture::Impl : Paint::Impl
|
||||||
|
|
||||||
RenderRegion bounds(RenderMethod* renderer)
|
RenderRegion bounds(RenderMethod* renderer)
|
||||||
{
|
{
|
||||||
if (rd) return renderer->region(rd);
|
if (impl.rd) return renderer->region(impl.rd);
|
||||||
if (vector) return vector->pImpl->bounds(renderer);
|
if (vector) return vector->pImpl->bounds(renderer);
|
||||||
return {0, 0, 0, 0};
|
return {0, 0, 0, 0};
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,6 +45,12 @@ static inline void operator|=(RenderUpdateFlag& a, const RenderUpdateFlag b)
|
||||||
a = RenderUpdateFlag(uint16_t(a) | uint16_t(b));
|
a = RenderUpdateFlag(uint16_t(a) | uint16_t(b));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline RenderUpdateFlag operator|(const RenderUpdateFlag a, const RenderUpdateFlag b)
|
||||||
|
{
|
||||||
|
return RenderUpdateFlag(uint16_t(a) | uint16_t(b));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
struct RenderSurface
|
struct RenderSurface
|
||||||
{
|
{
|
||||||
union {
|
union {
|
||||||
|
|
|
@ -23,15 +23,12 @@
|
||||||
#include "tvgScene.h"
|
#include "tvgScene.h"
|
||||||
|
|
||||||
|
|
||||||
Scene::Scene()
|
Scene::Scene() = default;
|
||||||
{
|
|
||||||
pImpl = new Impl(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Scene* Scene::gen() noexcept
|
Scene* Scene::gen() noexcept
|
||||||
{
|
{
|
||||||
return new Scene;
|
return new SceneImpl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -56,7 +53,7 @@ Result Scene::remove(Paint* paint) noexcept
|
||||||
|
|
||||||
const list<Paint*>& Scene::paints() const noexcept
|
const list<Paint*>& Scene::paints() const noexcept
|
||||||
{
|
{
|
||||||
return SCENE(this)->paints;
|
return CONST_SCENE(this)->paints;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,8 @@
|
||||||
#include "tvgMath.h"
|
#include "tvgMath.h"
|
||||||
#include "tvgPaint.h"
|
#include "tvgPaint.h"
|
||||||
|
|
||||||
#define SCENE(A) PIMPL(A, Scene)
|
#define SCENE(A) static_cast<SceneImpl*>(A)
|
||||||
|
#define CONST_SCENE(A) static_cast<const SceneImpl*>(A)
|
||||||
|
|
||||||
struct SceneIterator : Iterator
|
struct SceneIterator : Iterator
|
||||||
{
|
{
|
||||||
|
@ -59,22 +60,22 @@ struct SceneIterator : Iterator
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Scene::Impl : Paint::Impl
|
struct SceneImpl : Scene
|
||||||
{
|
{
|
||||||
|
Paint::Impl impl;
|
||||||
list<Paint*> paints; //children list
|
list<Paint*> paints; //children list
|
||||||
RenderRegion vport = {0, 0, INT32_MAX, INT32_MAX};
|
RenderRegion vport = {0, 0, INT32_MAX, INT32_MAX};
|
||||||
Array<RenderEffect*>* effects = nullptr;
|
Array<RenderEffect*>* effects = nullptr;
|
||||||
uint8_t compFlag = CompositionFlag::Invalid;
|
uint8_t compFlag = CompositionFlag::Invalid;
|
||||||
uint8_t opacity; //for composition
|
uint8_t opacity; //for composition
|
||||||
|
|
||||||
Impl(Scene* s) : Paint::Impl(s)
|
SceneImpl() : impl(Paint::Impl(this))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
~Impl()
|
~SceneImpl()
|
||||||
{
|
{
|
||||||
resetEffects();
|
resetEffects();
|
||||||
|
|
||||||
clearPaints();
|
clearPaints();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,8 +87,8 @@ struct Scene::Impl : Paint::Impl
|
||||||
|
|
||||||
//post effects, masking, blending may require composition
|
//post effects, masking, blending may require composition
|
||||||
if (effects) compFlag |= CompositionFlag::PostProcessing;
|
if (effects) compFlag |= CompositionFlag::PostProcessing;
|
||||||
if (paint->mask(nullptr) != MaskMethod::None) compFlag |= CompositionFlag::Masking;
|
if (PAINT(this)->mask(nullptr) != MaskMethod::None) compFlag |= CompositionFlag::Masking;
|
||||||
if (blendMethod != BlendMethod::Normal) compFlag |= CompositionFlag::Blending;
|
if (impl.blendMethod != BlendMethod::Normal) compFlag |= CompositionFlag::Blending;
|
||||||
|
|
||||||
//Half translucent requires intermediate composition.
|
//Half translucent requires intermediate composition.
|
||||||
if (opacity == 255) return compFlag;
|
if (opacity == 255) return compFlag;
|
||||||
|
@ -130,7 +131,7 @@ struct Scene::Impl : Paint::Impl
|
||||||
RenderCompositor* cmp = nullptr;
|
RenderCompositor* cmp = nullptr;
|
||||||
auto ret = true;
|
auto ret = true;
|
||||||
|
|
||||||
renderer->blend(blendMethod);
|
renderer->blend(impl.blendMethod);
|
||||||
|
|
||||||
if (compFlag) {
|
if (compFlag) {
|
||||||
cmp = renderer->target(bounds(renderer), renderer->colorSpace(), static_cast<CompositionFlag>(compFlag));
|
cmp = renderer->target(bounds(renderer), renderer->colorSpace(), static_cast<CompositionFlag>(compFlag));
|
||||||
|
@ -258,7 +259,7 @@ struct Scene::Impl : Paint::Impl
|
||||||
|
|
||||||
Result remove(Paint* paint)
|
Result remove(Paint* paint)
|
||||||
{
|
{
|
||||||
if (PAINT(paint)->parent != this->paint) return Result::InsufficientCondition;
|
if (PAINT(paint)->parent != this) return Result::InsufficientCondition;
|
||||||
PAINT(paint)->unref();
|
PAINT(paint)->unref();
|
||||||
paints.remove(paint);
|
paints.remove(paint);
|
||||||
return Result::Success;
|
return Result::Success;
|
||||||
|
@ -273,7 +274,7 @@ struct Scene::Impl : Paint::Impl
|
||||||
target->ref();
|
target->ref();
|
||||||
|
|
||||||
//Relocated the paint to the current scene space
|
//Relocated the paint to the current scene space
|
||||||
timpl->renderFlag |= RenderUpdateFlag::Transform;
|
timpl->mark(RenderUpdateFlag::Transform);
|
||||||
|
|
||||||
if (!at) {
|
if (!at) {
|
||||||
paints.push_back(target);
|
paints.push_back(target);
|
||||||
|
@ -283,9 +284,9 @@ struct Scene::Impl : Paint::Impl
|
||||||
if (itr == paints.end()) return Result::InvalidArguments;
|
if (itr == paints.end()) return Result::InvalidArguments;
|
||||||
paints.insert(itr, target);
|
paints.insert(itr, target);
|
||||||
}
|
}
|
||||||
timpl->parent = paint;
|
timpl->parent = this;
|
||||||
if (timpl->clipper) PAINT(timpl->clipper)->parent = paint;
|
if (timpl->clipper) PAINT(timpl->clipper)->parent = this;
|
||||||
if (timpl->maskData) PAINT(timpl->maskData->target)->parent = paint;
|
if (timpl->maskData) PAINT(timpl->maskData->target)->parent = this;
|
||||||
return Result::Success;
|
return Result::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -298,7 +299,7 @@ struct Scene::Impl : Paint::Impl
|
||||||
{
|
{
|
||||||
if (effects) {
|
if (effects) {
|
||||||
ARRAY_FOREACH(p, *effects) {
|
ARRAY_FOREACH(p, *effects) {
|
||||||
renderer->dispose(*p);
|
impl.renderer->dispose(*p);
|
||||||
delete(*p);
|
delete(*p);
|
||||||
}
|
}
|
||||||
delete(effects);
|
delete(effects);
|
||||||
|
|
|
@ -24,15 +24,12 @@
|
||||||
#include "tvgShape.h"
|
#include "tvgShape.h"
|
||||||
|
|
||||||
|
|
||||||
Shape :: Shape()
|
Shape :: Shape() = default;
|
||||||
{
|
|
||||||
pImpl = new Impl(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Shape* Shape::gen() noexcept
|
Shape* Shape::gen() noexcept
|
||||||
{
|
{
|
||||||
return new Shape;
|
return new ShapeImpl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -51,11 +48,11 @@ Result Shape::reset() noexcept
|
||||||
|
|
||||||
Result Shape::path(const PathCommand** cmds, uint32_t* cmdsCnt, const Point** pts, uint32_t* ptsCnt) const noexcept
|
Result Shape::path(const PathCommand** cmds, uint32_t* cmdsCnt, const Point** pts, uint32_t* ptsCnt) const noexcept
|
||||||
{
|
{
|
||||||
if (cmds) *cmds = SHAPE(this)->rs.path.cmds.data;
|
if (cmds) *cmds = CONST_SHAPE(this)->rs.path.cmds.data;
|
||||||
if (cmdsCnt) *cmdsCnt = SHAPE(this)->rs.path.cmds.count;
|
if (cmdsCnt) *cmdsCnt = CONST_SHAPE(this)->rs.path.cmds.count;
|
||||||
|
|
||||||
if (pts) *pts = SHAPE(this)->rs.path.pts.data;
|
if (pts) *pts = CONST_SHAPE(this)->rs.path.pts.data;
|
||||||
if (ptsCnt) *ptsCnt = SHAPE(this)->rs.path.pts.count;
|
if (ptsCnt) *ptsCnt = CONST_SHAPE(this)->rs.path.pts.count;
|
||||||
|
|
||||||
return Result::Success;
|
return Result::Success;
|
||||||
}
|
}
|
||||||
|
@ -124,14 +121,14 @@ Result Shape::fill(Fill* f) noexcept
|
||||||
|
|
||||||
Result Shape::fill(uint8_t* r, uint8_t* g, uint8_t* b, uint8_t* a) const noexcept
|
Result Shape::fill(uint8_t* r, uint8_t* g, uint8_t* b, uint8_t* a) const noexcept
|
||||||
{
|
{
|
||||||
SHAPE(this)->rs.fillColor(r, g, b, a);
|
CONST_SHAPE(this)->rs.fillColor(r, g, b, a);
|
||||||
return Result::Success;
|
return Result::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const Fill* Shape::fill() const noexcept
|
const Fill* Shape::fill() const noexcept
|
||||||
{
|
{
|
||||||
return SHAPE(this)->rs.fill;
|
return CONST_SHAPE(this)->rs.fill;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -151,7 +148,7 @@ Result Shape::strokeWidth(float width) noexcept
|
||||||
|
|
||||||
float Shape::strokeWidth() const noexcept
|
float Shape::strokeWidth() const noexcept
|
||||||
{
|
{
|
||||||
return SHAPE(this)->rs.strokeWidth();
|
return CONST_SHAPE(this)->rs.strokeWidth();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -164,7 +161,7 @@ Result Shape::strokeFill(uint8_t r, uint8_t g, uint8_t b, uint8_t a) noexcept
|
||||||
|
|
||||||
Result Shape::strokeFill(uint8_t* r, uint8_t* g, uint8_t* b, uint8_t* a) const noexcept
|
Result Shape::strokeFill(uint8_t* r, uint8_t* g, uint8_t* b, uint8_t* a) const noexcept
|
||||||
{
|
{
|
||||||
if (!SHAPE(this)->rs.strokeFill(r, g, b, a)) return Result::InsufficientCondition;
|
if (!CONST_SHAPE(this)->rs.strokeFill(r, g, b, a)) return Result::InsufficientCondition;
|
||||||
return Result::Success;
|
return Result::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -177,7 +174,7 @@ Result Shape::strokeFill(Fill* f) noexcept
|
||||||
|
|
||||||
const Fill* Shape::strokeFill() const noexcept
|
const Fill* Shape::strokeFill() const noexcept
|
||||||
{
|
{
|
||||||
return SHAPE(this)->rs.strokeFill();
|
return CONST_SHAPE(this)->rs.strokeFill();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -189,7 +186,7 @@ Result Shape::strokeDash(const float* dashPattern, uint32_t cnt, float offset) n
|
||||||
|
|
||||||
uint32_t Shape::strokeDash(const float** dashPattern, float* offset) const noexcept
|
uint32_t Shape::strokeDash(const float** dashPattern, float* offset) const noexcept
|
||||||
{
|
{
|
||||||
return SHAPE(this)->rs.strokeDash(dashPattern, offset);
|
return CONST_SHAPE(this)->rs.strokeDash(dashPattern, offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -215,19 +212,19 @@ Result Shape::strokeMiterlimit(float miterlimit) noexcept
|
||||||
|
|
||||||
StrokeCap Shape::strokeCap() const noexcept
|
StrokeCap Shape::strokeCap() const noexcept
|
||||||
{
|
{
|
||||||
return SHAPE(this)->rs.strokeCap();
|
return CONST_SHAPE(this)->rs.strokeCap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
StrokeJoin Shape::strokeJoin() const noexcept
|
StrokeJoin Shape::strokeJoin() const noexcept
|
||||||
{
|
{
|
||||||
return SHAPE(this)->rs.strokeJoin();
|
return CONST_SHAPE(this)->rs.strokeJoin();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
float Shape::strokeMiterlimit() const noexcept
|
float Shape::strokeMiterlimit() const noexcept
|
||||||
{
|
{
|
||||||
return SHAPE(this)->rs.strokeMiterlimit();
|
return CONST_SHAPE(this)->rs.strokeMiterlimit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -247,5 +244,5 @@ Result Shape::fill(FillRule r) noexcept
|
||||||
|
|
||||||
FillRule Shape::fillRule() const noexcept
|
FillRule Shape::fillRule() const noexcept
|
||||||
{
|
{
|
||||||
return SHAPE(this)->rs.rule;
|
return CONST_SHAPE(this)->rs.rule;
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,32 +27,34 @@
|
||||||
#include "tvgMath.h"
|
#include "tvgMath.h"
|
||||||
#include "tvgPaint.h"
|
#include "tvgPaint.h"
|
||||||
|
|
||||||
#define SHAPE(A) PIMPL(A, Shape)
|
#define SHAPE(A) static_cast<ShapeImpl*>(A)
|
||||||
|
#define CONST_SHAPE(A) static_cast<const ShapeImpl*>(A)
|
||||||
|
|
||||||
struct Shape::Impl : Paint::Impl
|
struct ShapeImpl : Shape
|
||||||
{
|
{
|
||||||
|
Paint::Impl impl;
|
||||||
RenderShape rs;
|
RenderShape rs;
|
||||||
uint8_t compFlag = CompositionFlag::Invalid;
|
uint8_t compFlag = CompositionFlag::Invalid;
|
||||||
uint8_t opacity; //for composition
|
uint8_t opacity; //for composition
|
||||||
|
|
||||||
Impl(Shape* s) : Paint::Impl(s)
|
ShapeImpl() : impl(Paint::Impl(this))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bool render(RenderMethod* renderer)
|
bool render(RenderMethod* renderer)
|
||||||
{
|
{
|
||||||
if (!rd) return false;
|
if (!impl.rd) return false;
|
||||||
|
|
||||||
RenderCompositor* cmp = nullptr;
|
RenderCompositor* cmp = nullptr;
|
||||||
|
|
||||||
renderer->blend(blendMethod);
|
renderer->blend(impl.blendMethod);
|
||||||
|
|
||||||
if (compFlag) {
|
if (compFlag) {
|
||||||
cmp = renderer->target(bounds(renderer), renderer->colorSpace(), static_cast<CompositionFlag>(compFlag));
|
cmp = renderer->target(bounds(renderer), renderer->colorSpace(), static_cast<CompositionFlag>(compFlag));
|
||||||
renderer->beginComposite(cmp, MaskMethod::None, opacity);
|
renderer->beginComposite(cmp, MaskMethod::None, opacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto ret = renderer->renderShape(rd);
|
auto ret = renderer->renderShape(impl.rd);
|
||||||
if (cmp) renderer->endComposite(cmp);
|
if (cmp) renderer->endComposite(cmp);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -75,10 +77,10 @@ struct Shape::Impl : Paint::Impl
|
||||||
|
|
||||||
//Composition test
|
//Composition test
|
||||||
const Paint* target;
|
const Paint* target;
|
||||||
auto method = paint->mask(&target);
|
auto method = PAINT(this)->mask(&target);
|
||||||
if (!target) return false;
|
if (!target) return false;
|
||||||
|
|
||||||
if ((target->pImpl->opacity == 255 || target->pImpl->opacity == 0) && target->type() == Type::Shape) {
|
if ((target->pImpl->opacity == 255 || target->pImpl->opacity == 0) && target->type() == tvg::Type::Shape) {
|
||||||
auto shape = static_cast<const Shape*>(target);
|
auto shape = static_cast<const Shape*>(target);
|
||||||
if (!shape->fill()) {
|
if (!shape->fill()) {
|
||||||
uint8_t r, g, b, a;
|
uint8_t r, g, b, a;
|
||||||
|
@ -97,7 +99,7 @@ struct Shape::Impl : Paint::Impl
|
||||||
|
|
||||||
RenderData update(RenderMethod* renderer, const Matrix& transform, Array<RenderData>& clips, uint8_t opacity, RenderUpdateFlag pFlag, bool clipper)
|
RenderData update(RenderMethod* renderer, const Matrix& transform, Array<RenderData>& clips, uint8_t opacity, RenderUpdateFlag pFlag, bool clipper)
|
||||||
{
|
{
|
||||||
if (static_cast<RenderUpdateFlag>(pFlag | renderFlag) == RenderUpdateFlag::None) return rd;
|
if ((pFlag | impl.renderFlag) == RenderUpdateFlag::None) return impl.rd;
|
||||||
|
|
||||||
if (needComposition(opacity)) {
|
if (needComposition(opacity)) {
|
||||||
/* Overriding opacity value. If this scene is half-translucent,
|
/* Overriding opacity value. If this scene is half-translucent,
|
||||||
|
@ -106,14 +108,14 @@ struct Shape::Impl : Paint::Impl
|
||||||
opacity = 255;
|
opacity = 255;
|
||||||
}
|
}
|
||||||
|
|
||||||
rd = renderer->prepare(rs, rd, transform, clips, opacity, static_cast<RenderUpdateFlag>(pFlag | renderFlag), clipper);
|
impl.rd = renderer->prepare(rs, impl.rd, transform, clips, opacity, (pFlag | impl.renderFlag), clipper);
|
||||||
return rd;
|
return impl.rd;
|
||||||
}
|
}
|
||||||
|
|
||||||
RenderRegion bounds(RenderMethod* renderer)
|
RenderRegion bounds(RenderMethod* renderer)
|
||||||
{
|
{
|
||||||
if (!rd) return {0, 0, 0, 0};
|
if (!impl.rd) return {0, 0, 0, 0};
|
||||||
return renderer->region(rd);
|
return renderer->region(impl.rd);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result bounds(Point* pt4, Matrix& m, bool obb, bool stroking)
|
Result bounds(Point* pt4, Matrix& m, bool obb, bool stroking)
|
||||||
|
@ -178,7 +180,7 @@ struct Shape::Impl : Paint::Impl
|
||||||
{
|
{
|
||||||
rs.path.cmds.push(PathCommand::LineTo);
|
rs.path.cmds.push(PathCommand::LineTo);
|
||||||
rs.path.pts.push({x, y});
|
rs.path.pts.push({x, y});
|
||||||
renderFlag |= RenderUpdateFlag::Path;
|
impl.mark(RenderUpdateFlag::Path);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cubicTo(float cx1, float cy1, float cx2, float cy2, float x, float y)
|
void cubicTo(float cx1, float cy1, float cx2, float cy2, float x, float y)
|
||||||
|
@ -188,7 +190,7 @@ struct Shape::Impl : Paint::Impl
|
||||||
rs.path.pts.push({cx2, cy2});
|
rs.path.pts.push({cx2, cy2});
|
||||||
rs.path.pts.push({x, y});
|
rs.path.pts.push({x, y});
|
||||||
|
|
||||||
renderFlag |= RenderUpdateFlag::Path;
|
impl.mark(RenderUpdateFlag::Path);
|
||||||
}
|
}
|
||||||
|
|
||||||
void close()
|
void close()
|
||||||
|
@ -196,14 +198,14 @@ struct Shape::Impl : Paint::Impl
|
||||||
//Don't close multiple times.
|
//Don't close multiple times.
|
||||||
if (rs.path.cmds.count > 0 && rs.path.cmds.last() == PathCommand::Close) return;
|
if (rs.path.cmds.count > 0 && rs.path.cmds.last() == PathCommand::Close) return;
|
||||||
rs.path.cmds.push(PathCommand::Close);
|
rs.path.cmds.push(PathCommand::Close);
|
||||||
renderFlag |= RenderUpdateFlag::Path;
|
impl.mark(RenderUpdateFlag::Path);
|
||||||
}
|
}
|
||||||
|
|
||||||
void strokeWidth(float width)
|
void strokeWidth(float width)
|
||||||
{
|
{
|
||||||
if (!rs.stroke) rs.stroke = new RenderStroke();
|
if (!rs.stroke) rs.stroke = new RenderStroke();
|
||||||
rs.stroke->width = width;
|
rs.stroke->width = width;
|
||||||
renderFlag |= RenderUpdateFlag::Stroke;
|
impl.mark(RenderUpdateFlag::Stroke);
|
||||||
}
|
}
|
||||||
|
|
||||||
void trimpath(const RenderTrimPath& trim)
|
void trimpath(const RenderTrimPath& trim)
|
||||||
|
@ -216,7 +218,7 @@ struct Shape::Impl : Paint::Impl
|
||||||
if (tvg::equal(rs.stroke->trim.begin, trim.begin) && tvg::equal(rs.stroke->trim.end, trim.end) && rs.stroke->trim.simultaneous == trim.simultaneous) return;
|
if (tvg::equal(rs.stroke->trim.begin, trim.begin) && tvg::equal(rs.stroke->trim.end, trim.end) && rs.stroke->trim.simultaneous == trim.simultaneous) return;
|
||||||
|
|
||||||
rs.stroke->trim = trim;
|
rs.stroke->trim = trim;
|
||||||
renderFlag |= RenderUpdateFlag::Path;
|
impl.mark(RenderUpdateFlag::Path);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool trimpath(float* begin, float* end)
|
bool trimpath(float* begin, float* end)
|
||||||
|
@ -236,14 +238,14 @@ struct Shape::Impl : Paint::Impl
|
||||||
{
|
{
|
||||||
if (!rs.stroke) rs.stroke = new RenderStroke();
|
if (!rs.stroke) rs.stroke = new RenderStroke();
|
||||||
rs.stroke->cap = cap;
|
rs.stroke->cap = cap;
|
||||||
renderFlag |= RenderUpdateFlag::Stroke;
|
impl.mark(RenderUpdateFlag::Stroke);
|
||||||
}
|
}
|
||||||
|
|
||||||
void strokeJoin(StrokeJoin join)
|
void strokeJoin(StrokeJoin join)
|
||||||
{
|
{
|
||||||
if (!rs.stroke) rs.stroke = new RenderStroke();
|
if (!rs.stroke) rs.stroke = new RenderStroke();
|
||||||
rs.stroke->join = join;
|
rs.stroke->join = join;
|
||||||
renderFlag |= RenderUpdateFlag::Stroke;
|
impl.mark(RenderUpdateFlag::Stroke);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result strokeMiterlimit(float miterlimit)
|
Result strokeMiterlimit(float miterlimit)
|
||||||
|
@ -253,7 +255,7 @@ struct Shape::Impl : Paint::Impl
|
||||||
if (miterlimit < 0.0f) return Result::InvalidArguments;
|
if (miterlimit < 0.0f) return Result::InvalidArguments;
|
||||||
if (!rs.stroke) rs.stroke = new RenderStroke();
|
if (!rs.stroke) rs.stroke = new RenderStroke();
|
||||||
rs.stroke->miterlimit = miterlimit;
|
rs.stroke->miterlimit = miterlimit;
|
||||||
renderFlag |= RenderUpdateFlag::Stroke;
|
impl.mark(RenderUpdateFlag::Stroke);
|
||||||
|
|
||||||
return Result::Success;
|
return Result::Success;
|
||||||
}
|
}
|
||||||
|
@ -264,12 +266,12 @@ struct Shape::Impl : Paint::Impl
|
||||||
if (rs.stroke->fill) {
|
if (rs.stroke->fill) {
|
||||||
delete(rs.stroke->fill);
|
delete(rs.stroke->fill);
|
||||||
rs.stroke->fill = nullptr;
|
rs.stroke->fill = nullptr;
|
||||||
renderFlag |= RenderUpdateFlag::GradientStroke;
|
impl.mark(RenderUpdateFlag::GradientStroke);
|
||||||
}
|
}
|
||||||
|
|
||||||
rs.stroke->color = {r, g, b, a};
|
rs.stroke->color = {r, g, b, a};
|
||||||
|
|
||||||
renderFlag |= RenderUpdateFlag::Stroke;
|
impl.mark(RenderUpdateFlag::Stroke);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result strokeFill(Fill* f)
|
Result strokeFill(Fill* f)
|
||||||
|
@ -281,8 +283,7 @@ struct Shape::Impl : Paint::Impl
|
||||||
rs.stroke->fill = f;
|
rs.stroke->fill = f;
|
||||||
rs.stroke->color.a = 0;
|
rs.stroke->color.a = 0;
|
||||||
|
|
||||||
renderFlag |= RenderUpdateFlag::Stroke;
|
impl.mark(RenderUpdateFlag::Stroke | RenderUpdateFlag::GradientStroke);
|
||||||
renderFlag |= RenderUpdateFlag::GradientStroke;
|
|
||||||
|
|
||||||
return Result::Success;
|
return Result::Success;
|
||||||
}
|
}
|
||||||
|
@ -311,7 +312,7 @@ struct Shape::Impl : Paint::Impl
|
||||||
}
|
}
|
||||||
rs.stroke->dash.count = cnt;
|
rs.stroke->dash.count = cnt;
|
||||||
rs.stroke->dash.offset = offset;
|
rs.stroke->dash.offset = offset;
|
||||||
renderFlag |= RenderUpdateFlag::Stroke;
|
impl.mark(RenderUpdateFlag::Stroke);
|
||||||
|
|
||||||
return Result::Success;
|
return Result::Success;
|
||||||
}
|
}
|
||||||
|
@ -326,7 +327,7 @@ struct Shape::Impl : Paint::Impl
|
||||||
{
|
{
|
||||||
if (!rs.stroke) rs.stroke = new RenderStroke();
|
if (!rs.stroke) rs.stroke = new RenderStroke();
|
||||||
rs.stroke->strokeFirst = strokeFirst;
|
rs.stroke->strokeFirst = strokeFirst;
|
||||||
renderFlag |= RenderUpdateFlag::Stroke;
|
impl.mark(RenderUpdateFlag::Stroke);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result fill(Fill* f)
|
Result fill(Fill* f)
|
||||||
|
@ -335,7 +336,7 @@ struct Shape::Impl : Paint::Impl
|
||||||
|
|
||||||
if (rs.fill && rs.fill != f) delete(rs.fill);
|
if (rs.fill && rs.fill != f) delete(rs.fill);
|
||||||
rs.fill = f;
|
rs.fill = f;
|
||||||
renderFlag |= RenderUpdateFlag::Gradient;
|
impl.mark(RenderUpdateFlag::Gradient);
|
||||||
|
|
||||||
return Result::Success;
|
return Result::Success;
|
||||||
}
|
}
|
||||||
|
@ -345,20 +346,20 @@ struct Shape::Impl : Paint::Impl
|
||||||
if (rs.fill) {
|
if (rs.fill) {
|
||||||
delete(rs.fill);
|
delete(rs.fill);
|
||||||
rs.fill = nullptr;
|
rs.fill = nullptr;
|
||||||
renderFlag |= RenderUpdateFlag::Gradient;
|
impl.mark(RenderUpdateFlag::Gradient);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (r == rs.color.r && g == rs.color.g && b == rs.color.b && a == rs.color.a) return;
|
if (r == rs.color.r && g == rs.color.g && b == rs.color.b && a == rs.color.a) return;
|
||||||
|
|
||||||
rs.color = {r, g, b, a};
|
rs.color = {r, g, b, a};
|
||||||
renderFlag |= RenderUpdateFlag::Color;
|
impl.mark(RenderUpdateFlag::Color);
|
||||||
}
|
}
|
||||||
|
|
||||||
void resetPath()
|
void resetPath()
|
||||||
{
|
{
|
||||||
rs.path.cmds.clear();
|
rs.path.cmds.clear();
|
||||||
rs.path.pts.clear();
|
rs.path.pts.clear();
|
||||||
renderFlag |= RenderUpdateFlag::Path;
|
impl.mark(RenderUpdateFlag::Path);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result appendPath(const PathCommand *cmds, uint32_t cmdCnt, const Point* pts, uint32_t ptsCnt)
|
Result appendPath(const PathCommand *cmds, uint32_t cmdCnt, const Point* pts, uint32_t ptsCnt)
|
||||||
|
@ -367,7 +368,7 @@ struct Shape::Impl : Paint::Impl
|
||||||
|
|
||||||
grow(cmdCnt, ptsCnt);
|
grow(cmdCnt, ptsCnt);
|
||||||
append(cmds, cmdCnt, pts, ptsCnt);
|
append(cmds, cmdCnt, pts, ptsCnt);
|
||||||
renderFlag |= RenderUpdateFlag::Path;
|
impl.mark(RenderUpdateFlag::Path);
|
||||||
|
|
||||||
return Result::Success;
|
return Result::Success;
|
||||||
}
|
}
|
||||||
|
@ -403,7 +404,7 @@ struct Shape::Impl : Paint::Impl
|
||||||
|
|
||||||
rs.path.pts.count += 13;
|
rs.path.pts.count += 13;
|
||||||
|
|
||||||
renderFlag |= RenderUpdateFlag::Path;
|
impl.mark(RenderUpdateFlag::Path);
|
||||||
}
|
}
|
||||||
|
|
||||||
void appendRect(float x, float y, float w, float h, float rx, float ry, bool cw)
|
void appendRect(float x, float y, float w, float h, float rx, float ry, bool cw)
|
||||||
|
@ -478,7 +479,7 @@ struct Shape::Impl : Paint::Impl
|
||||||
rs.path.cmds.count += 10;
|
rs.path.cmds.count += 10;
|
||||||
rs.path.pts.count += 17;
|
rs.path.pts.count += 17;
|
||||||
}
|
}
|
||||||
renderFlag |= RenderUpdateFlag::Path;
|
impl.mark(RenderUpdateFlag::Path);
|
||||||
}
|
}
|
||||||
|
|
||||||
Paint* duplicate(Paint* ret)
|
Paint* duplicate(Paint* ret)
|
||||||
|
@ -491,7 +492,7 @@ struct Shape::Impl : Paint::Impl
|
||||||
delete(dup->rs.fill);
|
delete(dup->rs.fill);
|
||||||
|
|
||||||
//Default Properties
|
//Default Properties
|
||||||
dup->renderFlag = RenderUpdateFlag::All;
|
dup->impl.mark(RenderUpdateFlag::All);
|
||||||
dup->rs.rule = rs.rule;
|
dup->rs.rule = rs.rule;
|
||||||
dup->rs.color = rs.color;
|
dup->rs.color = rs.color;
|
||||||
|
|
||||||
|
@ -517,7 +518,7 @@ struct Shape::Impl : Paint::Impl
|
||||||
|
|
||||||
void reset()
|
void reset()
|
||||||
{
|
{
|
||||||
PAINT(paint)->reset();
|
PAINT(this)->reset();
|
||||||
rs.path.cmds.clear();
|
rs.path.cmds.clear();
|
||||||
rs.path.pts.clear();
|
rs.path.pts.clear();
|
||||||
|
|
||||||
|
|
|
@ -24,10 +24,7 @@
|
||||||
#include "tvgText.h"
|
#include "tvgText.h"
|
||||||
|
|
||||||
|
|
||||||
Text::Text()
|
Text::Text() = default;
|
||||||
{
|
|
||||||
pImpl = new Impl(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Result Text::text(const char* text) noexcept
|
Result Text::text(const char* text) noexcept
|
||||||
|
@ -102,7 +99,7 @@ Result Text::fill(Fill* f) noexcept
|
||||||
|
|
||||||
Text* Text::gen() noexcept
|
Text* Text::gen() noexcept
|
||||||
{
|
{
|
||||||
return new Text;
|
return new TextImpl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -29,10 +29,12 @@
|
||||||
#include "tvgFill.h"
|
#include "tvgFill.h"
|
||||||
#include "tvgLoader.h"
|
#include "tvgLoader.h"
|
||||||
|
|
||||||
#define TEXT(A) PIMPL(A, Text)
|
#define TEXT(A) static_cast<TextImpl*>(A)
|
||||||
|
#define CONST_TEXT(A) static_cast<const TextImpl*>(A)
|
||||||
|
|
||||||
struct Text::Impl : Paint::Impl
|
struct TextImpl : Text
|
||||||
{
|
{
|
||||||
|
Paint::Impl impl;
|
||||||
Shape* shape; //text shape
|
Shape* shape; //text shape
|
||||||
FontLoader* loader = nullptr;
|
FontLoader* loader = nullptr;
|
||||||
FontMetrics metrics;
|
FontMetrics metrics;
|
||||||
|
@ -41,13 +43,13 @@ struct Text::Impl : Paint::Impl
|
||||||
bool italic = false;
|
bool italic = false;
|
||||||
bool changed = false;
|
bool changed = false;
|
||||||
|
|
||||||
Impl(Text* p) : Paint::Impl(p), shape(Shape::gen())
|
TextImpl() : impl(Paint::Impl(this)), shape(Shape::gen())
|
||||||
{
|
{
|
||||||
PAINT(shape)->parent = p;
|
PAINT(shape)->parent = this;
|
||||||
shape->fill(FillRule::EvenOdd);
|
shape->fill(FillRule::EvenOdd);
|
||||||
}
|
}
|
||||||
|
|
||||||
~Impl()
|
~TextImpl()
|
||||||
{
|
{
|
||||||
tvg::free(utf8);
|
tvg::free(utf8);
|
||||||
LoaderMgr::retrieve(loader);
|
LoaderMgr::retrieve(loader);
|
||||||
|
@ -95,7 +97,7 @@ struct Text::Impl : Paint::Impl
|
||||||
bool render(RenderMethod* renderer)
|
bool render(RenderMethod* renderer)
|
||||||
{
|
{
|
||||||
if (!loader) return true;
|
if (!loader) return true;
|
||||||
renderer->blend(blendMethod);
|
renderer->blend(impl.blendMethod);
|
||||||
return PAINT(shape)->render(renderer);
|
return PAINT(shape)->render(renderer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,7 +120,7 @@ struct Text::Impl : Paint::Impl
|
||||||
|
|
||||||
//transform the gradient coordinates based on the final scaled font.
|
//transform the gradient coordinates based on the final scaled font.
|
||||||
auto fill = SHAPE(shape)->rs.fill;
|
auto fill = SHAPE(shape)->rs.fill;
|
||||||
if (fill && SHAPE(shape)->renderFlag & RenderUpdateFlag::Gradient) {
|
if (fill && SHAPE(shape)->impl.renderFlag & RenderUpdateFlag::Gradient) {
|
||||||
if (fill->type() == Type::LinearGradient) {
|
if (fill->type() == Type::LinearGradient) {
|
||||||
LINEAR(fill)->x1 *= scale;
|
LINEAR(fill)->x1 *= scale;
|
||||||
LINEAR(fill)->y1 *= scale;
|
LINEAR(fill)->y1 *= scale;
|
||||||
|
@ -172,6 +174,4 @@ struct Text::Impl : Paint::Impl
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif //_TVG_TEXT_H
|
#endif //_TVG_TEXT_H
|
||||||
|
|
Loading…
Add table
Reference in a new issue