diff --git a/inc/thorvg.h b/inc/thorvg.h index 37df5293..9a029eb0 100644 --- a/inc/thorvg.h +++ b/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: /** diff --git a/src/loaders/lottie/tvgLottieBuilder.cpp b/src/loaders/lottie/tvgLottieBuilder.cpp index 5b83d8d9..6f12338e 100644 --- a/src/loaders/lottie/tvgLottieBuilder.cpp +++ b/src/loaders/lottie/tvgLottieBuilder.cpp @@ -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(*p); ARRAY_FOREACH(p, group->children) { if (static_cast(*p)->pathset(frameNo, SHAPE(shape)->rs.path, nullptr, tween, exps)) { - PAINT(shape)->update(RenderUpdateFlag::Path); + PAINT(shape)->mark(RenderUpdateFlag::Path); } } } diff --git a/src/renderer/gl_engine/tvgGlRenderer.cpp b/src/renderer/gl_engine/tvgGlRenderer.cpp index c8cdd986..f38504a9 100644 --- a/src/renderer/gl_engine/tvgGlRenderer.cpp +++ b/src/renderer/gl_engine/tvgGlRenderer.cpp @@ -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::Color | sdata->updateFlag); - if (rshape.fill) sdata->updateFlag = static_cast(RenderUpdateFlag::Gradient | sdata->updateFlag); - if (alphaS) sdata->updateFlag = static_cast(RenderUpdateFlag::Stroke | sdata->updateFlag); - if (rshape.strokeFill()) sdata->updateFlag = static_cast(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; diff --git a/src/renderer/sw_engine/tvgSwFill.cpp b/src/renderer/sw_engine/tvgSwFill.cpp index 01814566..fd31a744 100644 --- a/src/renderer/sw_engine/tvgSwFill.cpp +++ b/src/renderer/sw_engine/tvgSwFill.cpp @@ -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(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; diff --git a/src/renderer/tvgCommon.h b/src/renderer/tvgCommon.h index fdd6b48f..b9071c44 100644 --- a/src/renderer/tvgCommon.h +++ b/src/renderer/tvgCommon.h @@ -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) diff --git a/src/renderer/tvgFill.cpp b/src/renderer/tvgFill.cpp index 279f5ab1..acbbcfd5 100644 --- a/src/renderer/tvgFill.cpp +++ b/src/renderer/tvgFill.cpp @@ -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; } diff --git a/src/renderer/tvgFill.h b/src/renderer/tvgFill.h index 0a4b1743..86325871 100644 --- a/src/renderer/tvgFill.h +++ b/src/renderer/tvgFill.h @@ -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(A) +#define CONST_LINEAR(A) static_cast(A) + +#define RADIAL(A) static_cast(A) +#define CONST_RADIAL(A) static_cast(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(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(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; diff --git a/src/renderer/tvgPaint.cpp b/src/renderer/tvgPaint.cpp index ad9fa0b2..e4d9d26e 100644 --- a/src/renderer/tvgPaint.cpp +++ b/src/renderer/tvgPaint.cpp @@ -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, Arrayclipper) { 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(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; } diff --git a/src/renderer/tvgPaint.h b/src/renderer/tvgPaint.h index 9c02af46..d0d84455 100644 --- a/src/renderer/tvgPaint.h +++ b/src/renderer/tvgPaint.h @@ -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); } } diff --git a/src/renderer/tvgPicture.cpp b/src/renderer/tvgPicture.cpp index 2997fa7c..7f710de5 100644 --- a/src/renderer/tvgPicture.cpp +++ b/src/renderer/tvgPicture.cpp @@ -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); } diff --git a/src/renderer/tvgPicture.h b/src/renderer/tvgPicture.h index 259e790a..5a032c5a 100644 --- a/src/renderer/tvgPicture.h +++ b/src/renderer/tvgPicture.h @@ -26,7 +26,8 @@ #include "tvgPaint.h" #include "tvgLoader.h" -#define PICTURE(A) PIMPL(A, Picture) +#define PICTURE(A) static_cast(A) +#define CONST_PICTURE(A) static_cast(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& clips, uint8_t opacity, RenderUpdateFlag pFlag, TVG_UNUSED bool clipper) { - auto flag = static_cast(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}; } diff --git a/src/renderer/tvgRender.h b/src/renderer/tvgRender.h index 6c76cf50..16e209c2 100644 --- a/src/renderer/tvgRender.h +++ b/src/renderer/tvgRender.h @@ -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 { diff --git a/src/renderer/tvgScene.cpp b/src/renderer/tvgScene.cpp index 1ca7e664..207eb07f 100644 --- a/src/renderer/tvgScene.cpp +++ b/src/renderer/tvgScene.cpp @@ -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& Scene::paints() const noexcept { - return SCENE(this)->paints; + return CONST_SCENE(this)->paints; } diff --git a/src/renderer/tvgScene.h b/src/renderer/tvgScene.h index 62fe6a85..8f4395b0 100644 --- a/src/renderer/tvgScene.h +++ b/src/renderer/tvgScene.h @@ -28,7 +28,8 @@ #include "tvgMath.h" #include "tvgPaint.h" -#define SCENE(A) PIMPL(A, Scene) +#define SCENE(A) static_cast(A) +#define CONST_SCENE(A) static_cast(A) struct SceneIterator : Iterator { @@ -59,22 +60,22 @@ struct SceneIterator : Iterator } }; -struct Scene::Impl : Paint::Impl +struct SceneImpl : Scene { + Paint::Impl impl; list paints; //children list RenderRegion vport = {0, 0, INT32_MAX, INT32_MAX}; Array* 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(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); diff --git a/src/renderer/tvgShape.cpp b/src/renderer/tvgShape.cpp index e82cd80d..db6baf98 100644 --- a/src/renderer/tvgShape.cpp +++ b/src/renderer/tvgShape.cpp @@ -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; } diff --git a/src/renderer/tvgShape.h b/src/renderer/tvgShape.h index d99b5d7b..c0950724 100644 --- a/src/renderer/tvgShape.h +++ b/src/renderer/tvgShape.h @@ -27,32 +27,34 @@ #include "tvgMath.h" #include "tvgPaint.h" -#define SHAPE(A) PIMPL(A, Shape) +#define SHAPE(A) static_cast(A) +#define CONST_SHAPE(A) static_cast(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(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(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& clips, uint8_t opacity, RenderUpdateFlag pFlag, bool clipper) { - if (static_cast(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(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(); diff --git a/src/renderer/tvgText.cpp b/src/renderer/tvgText.cpp index 35336747..9389e4d3 100644 --- a/src/renderer/tvgText.cpp +++ b/src/renderer/tvgText.cpp @@ -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; } diff --git a/src/renderer/tvgText.h b/src/renderer/tvgText.h index 32b58077..edc95e1d 100644 --- a/src/renderer/tvgText.h +++ b/src/renderer/tvgText.h @@ -29,10 +29,12 @@ #include "tvgFill.h" #include "tvgLoader.h" -#define TEXT(A) PIMPL(A, Text) +#define TEXT(A) static_cast(A) +#define CONST_TEXT(A) static_cast(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