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.
|
||||
* 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:
|
||||
/**
|
||||
|
@ -863,8 +865,9 @@ public:
|
|||
*
|
||||
* @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:
|
||||
/**
|
||||
|
@ -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.
|
||||
* 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:
|
||||
/**
|
||||
|
@ -1319,8 +1324,10 @@ public:
|
|||
*
|
||||
* @note Supported formats are depended on the available TVG loaders.
|
||||
* @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:
|
||||
/**
|
||||
|
@ -1450,8 +1457,10 @@ public:
|
|||
*
|
||||
* 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.
|
||||
*
|
||||
* @warning This class is not designed for inheritance.
|
||||
*/
|
||||
class TVG_API Scene final : public Paint
|
||||
class TVG_API Scene : public Paint
|
||||
{
|
||||
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.
|
||||
*
|
||||
* @warning This class is not designed for inheritance.
|
||||
*
|
||||
* @since 0.15
|
||||
*/
|
||||
class TVG_API Text final : public Paint
|
||||
class TVG_API Text : public Paint
|
||||
{
|
||||
public:
|
||||
/**
|
||||
|
|
|
@ -481,7 +481,7 @@ void LottieBuilder::updatePath(LottieGroup* parent, LottieObject** child, float
|
|||
if (ctx->repeaters.empty()) {
|
||||
_draw(parent, path, ctx);
|
||||
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 {
|
||||
auto shape = path->pooling();
|
||||
|
@ -695,7 +695,7 @@ void LottieBuilder::updatePolystar(LottieGroup* parent, LottieObject** child, fl
|
|||
_draw(parent, star, ctx);
|
||||
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);
|
||||
PAINT(ctx->merging)->update(RenderUpdateFlag::Path);
|
||||
PAINT(ctx->merging)->mark(RenderUpdateFlag::Path);
|
||||
} else {
|
||||
auto shape = star->pooling();
|
||||
shape->reset();
|
||||
|
@ -1037,7 +1037,7 @@ void LottieBuilder::updateText(LottieLayer* layer, float frameNo)
|
|||
auto group = static_cast<LottieGroup*>(*p);
|
||||
ARRAY_FOREACH(p, group->children) {
|
||||
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) {
|
||||
sdata->updateFlag = (rshape.stroke && (rshape.stroke->width > 0)) ? RenderUpdateFlag::Stroke : RenderUpdateFlag::Path;
|
||||
} else {
|
||||
if (alphaF) sdata->updateFlag = static_cast<RenderUpdateFlag>(RenderUpdateFlag::Color | sdata->updateFlag);
|
||||
if (rshape.fill) sdata->updateFlag = static_cast<RenderUpdateFlag>(RenderUpdateFlag::Gradient | sdata->updateFlag);
|
||||
if (alphaS) sdata->updateFlag = static_cast<RenderUpdateFlag>(RenderUpdateFlag::Stroke | sdata->updateFlag);
|
||||
if (rshape.strokeFill()) sdata->updateFlag = static_cast<RenderUpdateFlag>(RenderUpdateFlag::GradientStroke | sdata->updateFlag);
|
||||
if (alphaF) sdata->updateFlag = (RenderUpdateFlag::Color | sdata->updateFlag);
|
||||
if (rshape.fill) sdata->updateFlag = (RenderUpdateFlag::Gradient | sdata->updateFlag);
|
||||
if (alphaS) sdata->updateFlag = (RenderUpdateFlag::Stroke | sdata->updateFlag);
|
||||
if (rshape.strokeFill()) sdata->updateFlag = (RenderUpdateFlag::GradientStroke | sdata->updateFlag);
|
||||
}
|
||||
|
||||
if (sdata->updateFlag == RenderUpdateFlag::None) return sdata;
|
||||
|
|
|
@ -67,10 +67,10 @@ static uint32_t _estimateAAMargin(const Fill* fdata)
|
|||
constexpr float marginScalingFactor = 800.0f;
|
||||
|
||||
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);
|
||||
} else {
|
||||
auto grad = LINEAR(fdata);
|
||||
auto grad = CONST_LINEAR(fdata);
|
||||
Point p1 {grad->x1, grad->y1};
|
||||
Point p2 {grad->x2, grad->y2};
|
||||
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.offset = -fill->linear.dx * x1 - fill->linear.dy * y1;
|
||||
|
||||
auto transform = pTransform * linear->transform();
|
||||
const auto& transform = pTransform * linear->transform();
|
||||
|
||||
Matrix itransform;
|
||||
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;
|
||||
|
||||
auto transform = pTransform * radial->transform();
|
||||
const auto& transform = pTransform * radial->transform();
|
||||
|
||||
Matrix itransform;
|
||||
if (!inverse(&transform, &itransform)) return false;
|
||||
|
|
|
@ -89,8 +89,6 @@ namespace tvg {
|
|||
|
||||
uint16_t THORVG_VERSION_NUMBER();
|
||||
|
||||
#define PIMPL(INST, CLASS) ((CLASS::Impl*)INST->pImpl) //Access to pimpl
|
||||
|
||||
#define TVG_DELETE(PAINT) \
|
||||
if (PAINT->refCnt() == 0) delete(PAINT)
|
||||
|
||||
|
|
|
@ -27,16 +27,8 @@
|
|||
/* Fill Class Implementation */
|
||||
/************************************************************************/
|
||||
|
||||
Fill::Fill()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Fill::~Fill()
|
||||
{
|
||||
delete(pImpl);
|
||||
}
|
||||
|
||||
Fill::Fill() = default;
|
||||
Fill::~Fill() = default;
|
||||
|
||||
Result Fill::colorStops(const ColorStop* colorStops, uint32_t cnt) noexcept
|
||||
{
|
||||
|
@ -79,7 +71,9 @@ Matrix& Fill::transform() 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::RadialGradient()
|
||||
{
|
||||
Fill::pImpl = new Impl;
|
||||
}
|
||||
RadialGradient::RadialGradient() = default;
|
||||
|
||||
|
||||
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
|
||||
{
|
||||
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
|
||||
{
|
||||
return new RadialGradient;
|
||||
return new RadialGradientImpl;
|
||||
}
|
||||
|
||||
|
||||
|
@ -122,11 +112,7 @@ Type RadialGradient::type() const noexcept
|
|||
/* LinearGradient Class Implementation */
|
||||
/************************************************************************/
|
||||
|
||||
|
||||
LinearGradient::LinearGradient()
|
||||
{
|
||||
Fill::pImpl = new Impl;
|
||||
}
|
||||
LinearGradient::LinearGradient() = default;
|
||||
|
||||
|
||||
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
|
||||
{
|
||||
return LINEAR(this)->linear(x1, y1, x2, y2);
|
||||
return CONST_LINEAR(this)->linear(x1, y1, x2, y2);
|
||||
}
|
||||
|
||||
|
||||
LinearGradient* LinearGradient::gen() noexcept
|
||||
{
|
||||
return new LinearGradient;
|
||||
return new LinearGradientImpl;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -26,8 +26,11 @@
|
|||
#include "tvgCommon.h"
|
||||
#include "tvgMath.h"
|
||||
|
||||
#define LINEAR(A) PIMPL(A, LinearGradient)
|
||||
#define RADIAL(A) PIMPL(A, RadialGradient)
|
||||
#define LINEAR(A) static_cast<LinearGradientImpl*>(A)
|
||||
#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
|
||||
{
|
||||
|
@ -41,13 +44,13 @@ struct Fill::Impl
|
|||
tvg::free(colorStops);
|
||||
}
|
||||
|
||||
void copy(Fill::Impl* dup)
|
||||
void copy(const Fill::Impl& dup)
|
||||
{
|
||||
cnt = dup->cnt;
|
||||
spread = dup->spread;
|
||||
colorStops = tvg::malloc<ColorStop*>(sizeof(ColorStop) * dup->cnt);
|
||||
if (dup->cnt > 0) memcpy(colorStops, dup->colorStops, sizeof(ColorStop) * dup->cnt);
|
||||
transform = dup->transform;
|
||||
cnt = dup.cnt;
|
||||
spread = dup.spread;
|
||||
colorStops = tvg::malloc<ColorStop*>(sizeof(ColorStop) * dup.cnt);
|
||||
if (dup.cnt > 0) memcpy(colorStops, dup.colorStops, sizeof(ColorStop) * dup.cnt);
|
||||
transform = dup.transform;
|
||||
}
|
||||
|
||||
Result update(const ColorStop* colorStops, uint32_t cnt)
|
||||
|
@ -72,21 +75,26 @@ struct Fill::Impl
|
|||
|
||||
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 fx = 0.0f, fy = 0.0f;
|
||||
float r = 0.0f, fr = 0.0f;
|
||||
|
||||
Fill* duplicate() override
|
||||
RadialGradientImpl()
|
||||
{
|
||||
Fill::pImpl = &impl;
|
||||
}
|
||||
|
||||
Fill* duplicate() const
|
||||
{
|
||||
auto ret = RadialGradient::gen();
|
||||
RADIAL(ret)->copy(this);
|
||||
RADIAL(ret)->impl.copy(this->impl);
|
||||
RADIAL(ret)->cx = cx;
|
||||
RADIAL(ret)->cy = cy;
|
||||
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 y1 = 0.0f;
|
||||
float x2 = 0.0f;
|
||||
float y2 = 0.0f;
|
||||
|
||||
Fill* duplicate() override
|
||||
LinearGradientImpl()
|
||||
{
|
||||
Fill::pImpl = &impl;
|
||||
}
|
||||
|
||||
Fill* duplicate() const
|
||||
{
|
||||
auto ret = LinearGradient::gen();
|
||||
LINEAR(ret)->copy(this);
|
||||
LINEAR(ret)->impl.copy(this->impl);
|
||||
LINEAR(ret)->x1 = x1;
|
||||
LINEAR(ret)->y1 = y1;
|
||||
LINEAR(ret)->x2 = x2;
|
||||
|
|
|
@ -163,7 +163,7 @@ Paint* Paint::Impl::duplicate(Paint* ret)
|
|||
|
||||
//duplicate Transform
|
||||
ret->pImpl->tr = tr;
|
||||
ret->pImpl->renderFlag |= RenderUpdateFlag::Transform;
|
||||
ret->pImpl->mark(RenderUpdateFlag::Transform);
|
||||
|
||||
ret->pImpl->opacity = opacity;
|
||||
|
||||
|
@ -247,7 +247,7 @@ RenderData Paint::Impl::update(RenderMethod* renderer, const Matrix& pm, Array<R
|
|||
/* 2. Clipping */
|
||||
if (this->clipper) {
|
||||
auto pclip = PAINT(this->clipper);
|
||||
if (pclip->renderFlag) renderFlag |= RenderUpdateFlag::Clip;
|
||||
if (pclip->renderFlag) mark(RenderUpdateFlag::Clip);
|
||||
pclip->ctxFlag &= ~ContextFlag::FastTrack; //reset
|
||||
viewport = renderer->viewport();
|
||||
/* 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 */
|
||||
auto newFlag = static_cast<RenderUpdateFlag>(pFlag | renderFlag);
|
||||
auto newFlag = pFlag | renderFlag;
|
||||
renderFlag = RenderUpdateFlag::None;
|
||||
opacity = MULTIPLY(opacity, this->opacity);
|
||||
|
||||
|
@ -317,15 +317,8 @@ Result Paint::Impl::bounds(Point* pt4, Matrix* pm, bool obb, bool stroking)
|
|||
/* External Class Implementation */
|
||||
/************************************************************************/
|
||||
|
||||
Paint :: Paint()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Paint :: ~Paint()
|
||||
{
|
||||
delete(pImpl);
|
||||
}
|
||||
Paint :: Paint() = default;
|
||||
Paint :: ~Paint() = default;
|
||||
|
||||
|
||||
Result Paint::rotate(float degree) noexcept
|
||||
|
@ -410,7 +403,7 @@ Result Paint::opacity(uint8_t o) noexcept
|
|||
if (pImpl->opacity == o) return Result::Success;
|
||||
|
||||
pImpl->opacity = o;
|
||||
pImpl->renderFlag |= RenderUpdateFlag::Color;
|
||||
pImpl->mark(RenderUpdateFlag::Color);
|
||||
|
||||
return Result::Success;
|
||||
}
|
||||
|
|
|
@ -27,7 +27,8 @@
|
|||
#include "tvgRender.h"
|
||||
#include "tvgMath.h"
|
||||
|
||||
#define PAINT(A) PIMPL(A, Paint)
|
||||
|
||||
#define PAINT(A) ((Paint::Impl*)A->pImpl)
|
||||
|
||||
namespace tvg
|
||||
{
|
||||
|
@ -85,6 +86,7 @@ namespace tvg
|
|||
|
||||
Impl(Paint* pnt) : paint(pnt)
|
||||
{
|
||||
pnt->pImpl = this;
|
||||
reset();
|
||||
}
|
||||
|
||||
|
@ -129,7 +131,7 @@ namespace tvg
|
|||
return refCnt;
|
||||
}
|
||||
|
||||
void update(RenderUpdateFlag flag)
|
||||
void mark(RenderUpdateFlag flag)
|
||||
{
|
||||
renderFlag |= flag;
|
||||
}
|
||||
|
@ -138,7 +140,7 @@ namespace tvg
|
|||
{
|
||||
if (&tr.m != &m) tr.m = m;
|
||||
tr.overriding = true;
|
||||
renderFlag |= RenderUpdateFlag::Transform;
|
||||
mark(RenderUpdateFlag::Transform);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -236,7 +238,7 @@ namespace tvg
|
|||
if (tr.overriding) return false;
|
||||
if (tvg::equal(degree, tr.degree)) return true;
|
||||
tr.degree = degree;
|
||||
renderFlag |= RenderUpdateFlag::Transform;
|
||||
mark(RenderUpdateFlag::Transform);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -246,7 +248,7 @@ namespace tvg
|
|||
if (tr.overriding) return false;
|
||||
if (tvg::equal(factor, tr.scale)) return true;
|
||||
tr.scale = factor;
|
||||
renderFlag |= RenderUpdateFlag::Transform;
|
||||
mark(RenderUpdateFlag::Transform);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -257,7 +259,7 @@ namespace tvg
|
|||
if (tvg::equal(x, tr.m.e13) && tvg::equal(y, tr.m.e23)) return true;
|
||||
tr.m.e13 = x;
|
||||
tr.m.e23 = y;
|
||||
renderFlag |= RenderUpdateFlag::Transform;
|
||||
mark(RenderUpdateFlag::Transform);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -266,7 +268,7 @@ namespace tvg
|
|||
{
|
||||
if (blendMethod != method) {
|
||||
blendMethod = method;
|
||||
renderFlag |= RenderUpdateFlag::Blend;
|
||||
mark(RenderUpdateFlag::Blend);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -23,15 +23,12 @@
|
|||
#include "tvgPaint.h"
|
||||
#include "tvgPicture.h"
|
||||
|
||||
Picture::Picture()
|
||||
{
|
||||
pImpl = new Impl(this);
|
||||
}
|
||||
Picture::Picture() = default;
|
||||
|
||||
|
||||
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
|
||||
{
|
||||
return PICTURE(this)->size(w, h);
|
||||
return CONST_PICTURE(this)->size(w, h);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -26,7 +26,8 @@
|
|||
#include "tvgPaint.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
|
||||
{
|
||||
|
@ -55,8 +56,9 @@ struct PictureIterator : Iterator
|
|||
};
|
||||
|
||||
|
||||
struct Picture::Impl : Paint::Impl
|
||||
struct PictureImpl : Picture
|
||||
{
|
||||
Paint::Impl impl;
|
||||
ImageLoader* loader = nullptr;
|
||||
Paint* vector = nullptr; //vector picture uses
|
||||
RenderSurface* bitmap = nullptr; //bitmap picture uses
|
||||
|
@ -64,11 +66,11 @@ struct Picture::Impl : Paint::Impl
|
|||
uint8_t compFlag = CompositionFlag::Invalid;
|
||||
bool resizing = false;
|
||||
|
||||
Impl(Picture* p) : Paint::Impl(p)
|
||||
PictureImpl() : impl(Paint::Impl(this))
|
||||
{
|
||||
}
|
||||
|
||||
~Impl()
|
||||
~PictureImpl()
|
||||
{
|
||||
LoaderMgr::retrieve(loader);
|
||||
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)
|
||||
{
|
||||
auto flag = static_cast<RenderUpdateFlag>(pFlag | load());
|
||||
auto flag = (pFlag | load());
|
||||
|
||||
if (bitmap) {
|
||||
if (flag == RenderUpdateFlag::None) return rd;
|
||||
if (flag == RenderUpdateFlag::None) return impl.rd;
|
||||
|
||||
//Overriding Transformation by the desired image size
|
||||
auto sx = w / loader->w;
|
||||
|
@ -87,7 +89,7 @@ struct Picture::Impl : Paint::Impl
|
|||
auto scale = sx < sy ? sx : sy;
|
||||
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) {
|
||||
if (resizing) {
|
||||
loader->resize(vector, w, h);
|
||||
|
@ -96,7 +98,7 @@ struct Picture::Impl : Paint::Impl
|
|||
queryComposition(opacity);
|
||||
return vector->pImpl->update(renderer, transform, clips, opacity, flag, false);
|
||||
}
|
||||
return rd;
|
||||
return impl.rd;
|
||||
}
|
||||
|
||||
void size(float w, float h)
|
||||
|
@ -173,7 +175,7 @@ struct Picture::Impl : Paint::Impl
|
|||
if (loader) {
|
||||
dup->loader = loader;
|
||||
++dup->loader->sharing;
|
||||
PAINT(picture)->renderFlag |= RenderUpdateFlag::Image;
|
||||
PAINT(picture)->mark(RenderUpdateFlag::Image);
|
||||
}
|
||||
|
||||
dup->bitmap = bitmap;
|
||||
|
@ -214,7 +216,7 @@ struct Picture::Impl : Paint::Impl
|
|||
} else {
|
||||
vector = loader->paint();
|
||||
if (vector) {
|
||||
PAINT(vector)->parent = paint;
|
||||
PAINT(vector)->parent = this;
|
||||
if (w != loader->w || h != loader->h) {
|
||||
if (!resizing) {
|
||||
w = loader->w;
|
||||
|
@ -244,7 +246,7 @@ struct Picture::Impl : Paint::Impl
|
|||
|
||||
//Composition test
|
||||
const Paint* target;
|
||||
paint->mask(&target);
|
||||
PAINT(this)->mask(&target);
|
||||
if (!target || target->pImpl->opacity == 255 || target->pImpl->opacity == 0) return;
|
||||
compFlag = CompositionFlag::Opacity;
|
||||
}
|
||||
|
@ -252,9 +254,9 @@ struct Picture::Impl : Paint::Impl
|
|||
bool render(RenderMethod* renderer)
|
||||
{
|
||||
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) {
|
||||
RenderCompositor* cmp = nullptr;
|
||||
if (compFlag) {
|
||||
|
@ -269,7 +271,7 @@ struct Picture::Impl : Paint::Impl
|
|||
|
||||
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);
|
||||
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));
|
||||
}
|
||||
|
||||
static inline RenderUpdateFlag operator|(const RenderUpdateFlag a, const RenderUpdateFlag b)
|
||||
{
|
||||
return RenderUpdateFlag(uint16_t(a) | uint16_t(b));
|
||||
}
|
||||
|
||||
|
||||
struct RenderSurface
|
||||
{
|
||||
union {
|
||||
|
|
|
@ -23,15 +23,12 @@
|
|||
#include "tvgScene.h"
|
||||
|
||||
|
||||
Scene::Scene()
|
||||
{
|
||||
pImpl = new Impl(this);
|
||||
}
|
||||
Scene::Scene() = default;
|
||||
|
||||
|
||||
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
|
||||
{
|
||||
return SCENE(this)->paints;
|
||||
return CONST_SCENE(this)->paints;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -28,7 +28,8 @@
|
|||
#include "tvgMath.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
|
||||
{
|
||||
|
@ -59,22 +60,22 @@ struct SceneIterator : Iterator
|
|||
}
|
||||
};
|
||||
|
||||
struct Scene::Impl : Paint::Impl
|
||||
struct SceneImpl : Scene
|
||||
{
|
||||
Paint::Impl impl;
|
||||
list<Paint*> paints; //children list
|
||||
RenderRegion vport = {0, 0, INT32_MAX, INT32_MAX};
|
||||
Array<RenderEffect*>* effects = nullptr;
|
||||
uint8_t compFlag = CompositionFlag::Invalid;
|
||||
uint8_t opacity; //for composition
|
||||
|
||||
Impl(Scene* s) : Paint::Impl(s)
|
||||
SceneImpl() : impl(Paint::Impl(this))
|
||||
{
|
||||
}
|
||||
|
||||
~Impl()
|
||||
~SceneImpl()
|
||||
{
|
||||
resetEffects();
|
||||
|
||||
clearPaints();
|
||||
}
|
||||
|
||||
|
@ -86,8 +87,8 @@ struct Scene::Impl : Paint::Impl
|
|||
|
||||
//post effects, masking, blending may require composition
|
||||
if (effects) compFlag |= CompositionFlag::PostProcessing;
|
||||
if (paint->mask(nullptr) != MaskMethod::None) compFlag |= CompositionFlag::Masking;
|
||||
if (blendMethod != BlendMethod::Normal) compFlag |= CompositionFlag::Blending;
|
||||
if (PAINT(this)->mask(nullptr) != MaskMethod::None) compFlag |= CompositionFlag::Masking;
|
||||
if (impl.blendMethod != BlendMethod::Normal) compFlag |= CompositionFlag::Blending;
|
||||
|
||||
//Half translucent requires intermediate composition.
|
||||
if (opacity == 255) return compFlag;
|
||||
|
@ -130,7 +131,7 @@ struct Scene::Impl : Paint::Impl
|
|||
RenderCompositor* cmp = nullptr;
|
||||
auto ret = true;
|
||||
|
||||
renderer->blend(blendMethod);
|
||||
renderer->blend(impl.blendMethod);
|
||||
|
||||
if (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)
|
||||
{
|
||||
if (PAINT(paint)->parent != this->paint) return Result::InsufficientCondition;
|
||||
if (PAINT(paint)->parent != this) return Result::InsufficientCondition;
|
||||
PAINT(paint)->unref();
|
||||
paints.remove(paint);
|
||||
return Result::Success;
|
||||
|
@ -273,7 +274,7 @@ struct Scene::Impl : Paint::Impl
|
|||
target->ref();
|
||||
|
||||
//Relocated the paint to the current scene space
|
||||
timpl->renderFlag |= RenderUpdateFlag::Transform;
|
||||
timpl->mark(RenderUpdateFlag::Transform);
|
||||
|
||||
if (!at) {
|
||||
paints.push_back(target);
|
||||
|
@ -283,9 +284,9 @@ struct Scene::Impl : Paint::Impl
|
|||
if (itr == paints.end()) return Result::InvalidArguments;
|
||||
paints.insert(itr, target);
|
||||
}
|
||||
timpl->parent = paint;
|
||||
if (timpl->clipper) PAINT(timpl->clipper)->parent = paint;
|
||||
if (timpl->maskData) PAINT(timpl->maskData->target)->parent = paint;
|
||||
timpl->parent = this;
|
||||
if (timpl->clipper) PAINT(timpl->clipper)->parent = this;
|
||||
if (timpl->maskData) PAINT(timpl->maskData->target)->parent = this;
|
||||
return Result::Success;
|
||||
}
|
||||
|
||||
|
@ -298,7 +299,7 @@ struct Scene::Impl : Paint::Impl
|
|||
{
|
||||
if (effects) {
|
||||
ARRAY_FOREACH(p, *effects) {
|
||||
renderer->dispose(*p);
|
||||
impl.renderer->dispose(*p);
|
||||
delete(*p);
|
||||
}
|
||||
delete(effects);
|
||||
|
|
|
@ -24,15 +24,12 @@
|
|||
#include "tvgShape.h"
|
||||
|
||||
|
||||
Shape :: Shape()
|
||||
{
|
||||
pImpl = new Impl(this);
|
||||
}
|
||||
Shape :: Shape() = default;
|
||||
|
||||
|
||||
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
|
||||
{
|
||||
if (cmds) *cmds = SHAPE(this)->rs.path.cmds.data;
|
||||
if (cmdsCnt) *cmdsCnt = SHAPE(this)->rs.path.cmds.count;
|
||||
if (cmds) *cmds = CONST_SHAPE(this)->rs.path.cmds.data;
|
||||
if (cmdsCnt) *cmdsCnt = CONST_SHAPE(this)->rs.path.cmds.count;
|
||||
|
||||
if (pts) *pts = SHAPE(this)->rs.path.pts.data;
|
||||
if (ptsCnt) *ptsCnt = SHAPE(this)->rs.path.pts.count;
|
||||
if (pts) *pts = CONST_SHAPE(this)->rs.path.pts.data;
|
||||
if (ptsCnt) *ptsCnt = CONST_SHAPE(this)->rs.path.pts.count;
|
||||
|
||||
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
|
||||
{
|
||||
SHAPE(this)->rs.fillColor(r, g, b, a);
|
||||
CONST_SHAPE(this)->rs.fillColor(r, g, b, a);
|
||||
return Result::Success;
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
{
|
||||
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
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -177,7 +174,7 @@ Result Shape::strokeFill(Fill* f) 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
|
||||
{
|
||||
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
|
||||
{
|
||||
return SHAPE(this)->rs.strokeCap();
|
||||
return CONST_SHAPE(this)->rs.strokeCap();
|
||||
}
|
||||
|
||||
|
||||
StrokeJoin Shape::strokeJoin() const noexcept
|
||||
{
|
||||
return SHAPE(this)->rs.strokeJoin();
|
||||
return CONST_SHAPE(this)->rs.strokeJoin();
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
{
|
||||
return SHAPE(this)->rs.rule;
|
||||
return CONST_SHAPE(this)->rs.rule;
|
||||
}
|
||||
|
|
|
@ -27,32 +27,34 @@
|
|||
#include "tvgMath.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;
|
||||
uint8_t compFlag = CompositionFlag::Invalid;
|
||||
uint8_t opacity; //for composition
|
||||
|
||||
Impl(Shape* s) : Paint::Impl(s)
|
||||
ShapeImpl() : impl(Paint::Impl(this))
|
||||
{
|
||||
}
|
||||
|
||||
bool render(RenderMethod* renderer)
|
||||
{
|
||||
if (!rd) return false;
|
||||
if (!impl.rd) return false;
|
||||
|
||||
RenderCompositor* cmp = nullptr;
|
||||
|
||||
renderer->blend(blendMethod);
|
||||
renderer->blend(impl.blendMethod);
|
||||
|
||||
if (compFlag) {
|
||||
cmp = renderer->target(bounds(renderer), renderer->colorSpace(), static_cast<CompositionFlag>(compFlag));
|
||||
renderer->beginComposite(cmp, MaskMethod::None, opacity);
|
||||
}
|
||||
|
||||
auto ret = renderer->renderShape(rd);
|
||||
auto ret = renderer->renderShape(impl.rd);
|
||||
if (cmp) renderer->endComposite(cmp);
|
||||
return ret;
|
||||
}
|
||||
|
@ -75,10 +77,10 @@ struct Shape::Impl : Paint::Impl
|
|||
|
||||
//Composition test
|
||||
const Paint* target;
|
||||
auto method = paint->mask(&target);
|
||||
auto method = PAINT(this)->mask(&target);
|
||||
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);
|
||||
if (!shape->fill()) {
|
||||
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)
|
||||
{
|
||||
if (static_cast<RenderUpdateFlag>(pFlag | renderFlag) == RenderUpdateFlag::None) return rd;
|
||||
if ((pFlag | impl.renderFlag) == RenderUpdateFlag::None) return impl.rd;
|
||||
|
||||
if (needComposition(opacity)) {
|
||||
/* Overriding opacity value. If this scene is half-translucent,
|
||||
|
@ -106,14 +108,14 @@ struct Shape::Impl : Paint::Impl
|
|||
opacity = 255;
|
||||
}
|
||||
|
||||
rd = renderer->prepare(rs, rd, transform, clips, opacity, static_cast<RenderUpdateFlag>(pFlag | renderFlag), clipper);
|
||||
return rd;
|
||||
impl.rd = renderer->prepare(rs, impl.rd, transform, clips, opacity, (pFlag | impl.renderFlag), clipper);
|
||||
return impl.rd;
|
||||
}
|
||||
|
||||
RenderRegion bounds(RenderMethod* renderer)
|
||||
{
|
||||
if (!rd) return {0, 0, 0, 0};
|
||||
return renderer->region(rd);
|
||||
if (!impl.rd) return {0, 0, 0, 0};
|
||||
return renderer->region(impl.rd);
|
||||
}
|
||||
|
||||
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.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)
|
||||
|
@ -188,7 +190,7 @@ struct Shape::Impl : Paint::Impl
|
|||
rs.path.pts.push({cx2, cy2});
|
||||
rs.path.pts.push({x, y});
|
||||
|
||||
renderFlag |= RenderUpdateFlag::Path;
|
||||
impl.mark(RenderUpdateFlag::Path);
|
||||
}
|
||||
|
||||
void close()
|
||||
|
@ -196,14 +198,14 @@ struct Shape::Impl : Paint::Impl
|
|||
//Don't close multiple times.
|
||||
if (rs.path.cmds.count > 0 && rs.path.cmds.last() == PathCommand::Close) return;
|
||||
rs.path.cmds.push(PathCommand::Close);
|
||||
renderFlag |= RenderUpdateFlag::Path;
|
||||
impl.mark(RenderUpdateFlag::Path);
|
||||
}
|
||||
|
||||
void strokeWidth(float width)
|
||||
{
|
||||
if (!rs.stroke) rs.stroke = new RenderStroke();
|
||||
rs.stroke->width = width;
|
||||
renderFlag |= RenderUpdateFlag::Stroke;
|
||||
impl.mark(RenderUpdateFlag::Stroke);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
rs.stroke->trim = trim;
|
||||
renderFlag |= RenderUpdateFlag::Path;
|
||||
impl.mark(RenderUpdateFlag::Path);
|
||||
}
|
||||
|
||||
bool trimpath(float* begin, float* end)
|
||||
|
@ -236,14 +238,14 @@ struct Shape::Impl : Paint::Impl
|
|||
{
|
||||
if (!rs.stroke) rs.stroke = new RenderStroke();
|
||||
rs.stroke->cap = cap;
|
||||
renderFlag |= RenderUpdateFlag::Stroke;
|
||||
impl.mark(RenderUpdateFlag::Stroke);
|
||||
}
|
||||
|
||||
void strokeJoin(StrokeJoin join)
|
||||
{
|
||||
if (!rs.stroke) rs.stroke = new RenderStroke();
|
||||
rs.stroke->join = join;
|
||||
renderFlag |= RenderUpdateFlag::Stroke;
|
||||
impl.mark(RenderUpdateFlag::Stroke);
|
||||
}
|
||||
|
||||
Result strokeMiterlimit(float miterlimit)
|
||||
|
@ -253,7 +255,7 @@ struct Shape::Impl : Paint::Impl
|
|||
if (miterlimit < 0.0f) return Result::InvalidArguments;
|
||||
if (!rs.stroke) rs.stroke = new RenderStroke();
|
||||
rs.stroke->miterlimit = miterlimit;
|
||||
renderFlag |= RenderUpdateFlag::Stroke;
|
||||
impl.mark(RenderUpdateFlag::Stroke);
|
||||
|
||||
return Result::Success;
|
||||
}
|
||||
|
@ -264,12 +266,12 @@ struct Shape::Impl : Paint::Impl
|
|||
if (rs.stroke->fill) {
|
||||
delete(rs.stroke->fill);
|
||||
rs.stroke->fill = nullptr;
|
||||
renderFlag |= RenderUpdateFlag::GradientStroke;
|
||||
impl.mark(RenderUpdateFlag::GradientStroke);
|
||||
}
|
||||
|
||||
rs.stroke->color = {r, g, b, a};
|
||||
|
||||
renderFlag |= RenderUpdateFlag::Stroke;
|
||||
impl.mark(RenderUpdateFlag::Stroke);
|
||||
}
|
||||
|
||||
Result strokeFill(Fill* f)
|
||||
|
@ -281,8 +283,7 @@ struct Shape::Impl : Paint::Impl
|
|||
rs.stroke->fill = f;
|
||||
rs.stroke->color.a = 0;
|
||||
|
||||
renderFlag |= RenderUpdateFlag::Stroke;
|
||||
renderFlag |= RenderUpdateFlag::GradientStroke;
|
||||
impl.mark(RenderUpdateFlag::Stroke | RenderUpdateFlag::GradientStroke);
|
||||
|
||||
return Result::Success;
|
||||
}
|
||||
|
@ -311,7 +312,7 @@ struct Shape::Impl : Paint::Impl
|
|||
}
|
||||
rs.stroke->dash.count = cnt;
|
||||
rs.stroke->dash.offset = offset;
|
||||
renderFlag |= RenderUpdateFlag::Stroke;
|
||||
impl.mark(RenderUpdateFlag::Stroke);
|
||||
|
||||
return Result::Success;
|
||||
}
|
||||
|
@ -326,7 +327,7 @@ struct Shape::Impl : Paint::Impl
|
|||
{
|
||||
if (!rs.stroke) rs.stroke = new RenderStroke();
|
||||
rs.stroke->strokeFirst = strokeFirst;
|
||||
renderFlag |= RenderUpdateFlag::Stroke;
|
||||
impl.mark(RenderUpdateFlag::Stroke);
|
||||
}
|
||||
|
||||
Result fill(Fill* f)
|
||||
|
@ -335,7 +336,7 @@ struct Shape::Impl : Paint::Impl
|
|||
|
||||
if (rs.fill && rs.fill != f) delete(rs.fill);
|
||||
rs.fill = f;
|
||||
renderFlag |= RenderUpdateFlag::Gradient;
|
||||
impl.mark(RenderUpdateFlag::Gradient);
|
||||
|
||||
return Result::Success;
|
||||
}
|
||||
|
@ -345,20 +346,20 @@ struct Shape::Impl : Paint::Impl
|
|||
if (rs.fill) {
|
||||
delete(rs.fill);
|
||||
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;
|
||||
|
||||
rs.color = {r, g, b, a};
|
||||
renderFlag |= RenderUpdateFlag::Color;
|
||||
impl.mark(RenderUpdateFlag::Color);
|
||||
}
|
||||
|
||||
void resetPath()
|
||||
{
|
||||
rs.path.cmds.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)
|
||||
|
@ -367,7 +368,7 @@ struct Shape::Impl : Paint::Impl
|
|||
|
||||
grow(cmdCnt, ptsCnt);
|
||||
append(cmds, cmdCnt, pts, ptsCnt);
|
||||
renderFlag |= RenderUpdateFlag::Path;
|
||||
impl.mark(RenderUpdateFlag::Path);
|
||||
|
||||
return Result::Success;
|
||||
}
|
||||
|
@ -403,7 +404,7 @@ struct Shape::Impl : Paint::Impl
|
|||
|
||||
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)
|
||||
|
@ -478,7 +479,7 @@ struct Shape::Impl : Paint::Impl
|
|||
rs.path.cmds.count += 10;
|
||||
rs.path.pts.count += 17;
|
||||
}
|
||||
renderFlag |= RenderUpdateFlag::Path;
|
||||
impl.mark(RenderUpdateFlag::Path);
|
||||
}
|
||||
|
||||
Paint* duplicate(Paint* ret)
|
||||
|
@ -491,7 +492,7 @@ struct Shape::Impl : Paint::Impl
|
|||
delete(dup->rs.fill);
|
||||
|
||||
//Default Properties
|
||||
dup->renderFlag = RenderUpdateFlag::All;
|
||||
dup->impl.mark(RenderUpdateFlag::All);
|
||||
dup->rs.rule = rs.rule;
|
||||
dup->rs.color = rs.color;
|
||||
|
||||
|
@ -517,7 +518,7 @@ struct Shape::Impl : Paint::Impl
|
|||
|
||||
void reset()
|
||||
{
|
||||
PAINT(paint)->reset();
|
||||
PAINT(this)->reset();
|
||||
rs.path.cmds.clear();
|
||||
rs.path.pts.clear();
|
||||
|
||||
|
|
|
@ -24,10 +24,7 @@
|
|||
#include "tvgText.h"
|
||||
|
||||
|
||||
Text::Text()
|
||||
{
|
||||
pImpl = new Impl(this);
|
||||
}
|
||||
Text::Text() = default;
|
||||
|
||||
|
||||
Result Text::text(const char* text) noexcept
|
||||
|
@ -102,7 +99,7 @@ Result Text::fill(Fill* f) noexcept
|
|||
|
||||
Text* Text::gen() noexcept
|
||||
{
|
||||
return new Text;
|
||||
return new TextImpl;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -29,10 +29,12 @@
|
|||
#include "tvgFill.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
|
||||
FontLoader* loader = nullptr;
|
||||
FontMetrics metrics;
|
||||
|
@ -41,13 +43,13 @@ struct Text::Impl : Paint::Impl
|
|||
bool italic = 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);
|
||||
}
|
||||
|
||||
~Impl()
|
||||
~TextImpl()
|
||||
{
|
||||
tvg::free(utf8);
|
||||
LoaderMgr::retrieve(loader);
|
||||
|
@ -95,7 +97,7 @@ struct Text::Impl : Paint::Impl
|
|||
bool render(RenderMethod* renderer)
|
||||
{
|
||||
if (!loader) return true;
|
||||
renderer->blend(blendMethod);
|
||||
renderer->blend(impl.blendMethod);
|
||||
return PAINT(shape)->render(renderer);
|
||||
}
|
||||
|
||||
|
@ -118,7 +120,7 @@ struct Text::Impl : Paint::Impl
|
|||
|
||||
//transform the gradient coordinates based on the final scaled font.
|
||||
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) {
|
||||
LINEAR(fill)->x1 *= scale;
|
||||
LINEAR(fill)->y1 *= scale;
|
||||
|
@ -172,6 +174,4 @@ struct Text::Impl : Paint::Impl
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif //_TVG_TEXT_H
|
||||
|
|
Loading…
Add table
Reference in a new issue