rotate(), scale() won't be retained.
When you call reset() for the shape, these values will be reset as well.
These are working in fire & forget method,
it actually modify the path data for avoiding compuatation every frames.
Thus user needs to keep the last values to understand the final accumulated values.
Change-Id: I41f260271cdefc977eea01a778d49632440c777f
{
public:
virtual ~Paint() {}
+
virtual int update(RenderMethod*) = 0;
+
+ virtual int rotate(float degree) = 0;
+ virtual int scale(float factor) = 0;
+
+ virtual int bounds(float&x, float& y, float& w, float& h) const = 0;
};
int fill(size_t r, size_t g, size_t b, size_t a) noexcept;
+ int rotate(float degree) noexcept override;
+ int scale(float factor) noexcept override;
+
int pathCommands(const PathCommand** cmds) const noexcept;
int pathCoords(const Point** pts) const noexcept;
int fill(size_t* r, size_t* g, size_t* b, size_t* a) const noexcept;
+ int bounds(float&x, float& y, float& w, float& h) const noexcept override;
static std::unique_ptr<Shape> gen() noexcept;
~Scene();
int update(RenderMethod* engine) noexcept override;
-
int push(std::unique_ptr<Shape> shape) noexcept;
+ int rotate(float degree) noexcept override;
+ int scale(float factor) noexcept override;
+
+ int bounds(float&x, float& y, float& w, float& h) const noexcept override;
+
static std::unique_ptr<Scene> gen() noexcept;
_TIZENVG_DECLARE_PRIVATE(Scene);
return 0;
}
-#endif /* _TVG_SCENE_CPP_ */
+
+int Scene::scale(float scaleFacator) noexcept
+{
+ return 0;
+}
+
+
+int Scene::rotate(float degree) noexcept
+{
+ return 0;
+}
+
+
+int Scene::bounds(float& x, float& y, float& w, float& h) const noexcept
+{
+ return 0;
+}
+
+#endif /* _TVG_SCENE_CPP_ */
\ No newline at end of file
};
-struct ShapeTransform
-{
- float e[4*4];
-};
-
-
struct Shape::Impl
{
- ShapeTransform *transform = nullptr;
ShapeFill *fill = nullptr;
ShapeStroke *stroke = nullptr;
ShapePath *path = nullptr;
uint8_t color[4] = {0, 0, 0, 0}; //r, g, b, a
+ float scale = 1;
+ float rotate = 0;
void *edata = nullptr; //engine data
Impl() : path(new ShapePath)
if (path) delete(path);
if (stroke) delete(stroke);
if (fill) delete(fill);
- if (transform) delete(transform);
+ }
+
+ bool update()
+ {
+ if (path->scale(scale)) scale = 1;
+ if (path->rotate(rotate)) rotate = 0;
+
+ return true;
}
};
auto impl = pImpl.get();
assert(impl);
+ if (!impl->update()) return -1;
impl->edata = engine->prepare(*this, impl->edata, RenderMethod::UpdateFlag::All);
if (impl->edata) return 0;
return - 1;
int Shape::reset() noexcept
{
auto impl = pImpl.get();
- assert(impl);
+ assert(impl && impl->path);
impl->path->reset();
int Shape::pathCommands(const PathCommand** cmds) const noexcept
{
auto impl = pImpl.get();
- assert(impl && cmds);
+ assert(impl && impl->path && cmds);
*cmds = impl->path->cmds;
int Shape::pathCoords(const Point** pts) const noexcept
{
auto impl = pImpl.get();
- assert(impl && pts);
+ assert(impl && impl->path && pts);
*pts = impl->path->pts;
assert(cmds && pts);
auto impl = pImpl.get();
- assert(impl);
+ assert(impl && impl->path);
impl->path->grow(cmdCnt, ptsCnt);
impl->path->append(cmds, cmdCnt, pts, ptsCnt);
int Shape::moveTo(float x, float y) noexcept
{
auto impl = pImpl.get();
- assert(impl);
+ assert(impl && impl->path);
impl->path->moveTo(x, y);
int Shape::lineTo(float x, float y) noexcept
{
auto impl = pImpl.get();
- assert(impl);
+ assert(impl && impl->path);
impl->path->lineTo(x, y);
int Shape::cubicTo(float cx1, float cy1, float cx2, float cy2, float x, float y) noexcept
{
auto impl = pImpl.get();
- assert(impl);
+ assert(impl && impl->path);
impl->path->cubicTo(cx1, cy1, cx2, cy2, x, y);
int Shape::close() noexcept
{
auto impl = pImpl.get();
- assert(impl);
+ assert(impl && impl->path);
impl->path->close();
int Shape::appendCircle(float cx, float cy, float radiusW, float radiusH) noexcept
{
auto impl = pImpl.get();
- assert(impl);
+ assert(impl && impl->path);
auto halfKappaW = radiusW * PATH_KAPPA;
auto halfKappaH = radiusH * PATH_KAPPA;
int Shape::appendRect(float x, float y, float w, float h, float cornerRadius) noexcept
{
auto impl = pImpl.get();
- assert(impl);
+ assert(impl && impl->path);
//clamping cornerRadius by minimum size
auto min = (w < h ? w : h) * 0.5f;
return 0;
}
+
+int Shape::scale(float factor) noexcept
+{
+ if (factor < FLT_EPSILON || fabsf(factor - 1) <= FLT_EPSILON) return -1;
+
+ auto impl = pImpl.get();
+ assert(impl);
+
+ impl->scale *= factor;
+
+ return 0;
+}
+
+
+int Shape::rotate(float degree) noexcept
+{
+ if (fabsf(degree) <= FLT_EPSILON) return -1;
+
+ auto impl = pImpl.get();
+ assert(impl);
+
+ impl->rotate += degree;
+
+ return 0;
+}
+
+
+int Shape::bounds(float& x, float& y, float& w, float& h) const noexcept
+{
+ auto impl = pImpl.get();
+ assert(impl && impl->path);
+
+ if (!impl->path->bounds(x, y, w, h)) return -1;
+
+ return 0;
+}
+
#endif //_TVG_SHAPE_CPP_
if (cmdCnt + 1 > reservedCmdCnt) reserveCmd((cmdCnt + 1) * 2);
cmds[cmdCnt++] = PathCommand::Close;
}
+
+ bool bounds(float& x, float& y, float& w, float& h)
+ {
+ if (ptsCnt == 0) return false;
+
+ Point min = { pts[0].x, pts[0].y };
+ Point max = { pts[0].x, pts[0].y };
+
+ for(size_t i = 1; i < ptsCnt; ++i) {
+ if (pts[i].x < min.x) min.x = pts[i].x;
+ if (pts[i].y < min.y) min.y = pts[i].y;
+ if (pts[i].x > max.x) max.x = pts[i].x;
+ if (pts[i].y > max.y) max.y = pts[i].y;
+ }
+
+ x = min.x;
+ y = min.y;
+ w = max.x - min.x;
+ h = max.y - min.y;
+
+ return true;
+ }
+
+ bool rotate(float degree)
+ {
+ constexpr auto PI = 3.141592f;
+
+ if (fabsf(degree) <= FLT_EPSILON) return false;
+
+ float x, y, w, h;
+ if (!bounds(x, y, w, h)) return false;
+
+ auto radian = degree / 180.0f * PI;
+ auto cx = x + w * 0.5f;
+ auto cy = y + h * 0.5f;
+ auto cosVal = cosf(radian);
+ auto sinVal = sinf(radian);
+
+ for(size_t i = 0; i < ptsCnt; ++i) {
+ auto dx = pts[i].x - cx;
+ auto dy = pts[i].y - cy;
+ pts[i].x = (cosVal * dx - sinVal * dy) + cx;
+ pts[i].y = (sinVal * dx + cosVal * dy) + cy;
+ }
+
+ return true;
+ }
+
+ bool scale(float factor)
+ {
+ if (fabsf(factor - 1) <= FLT_EPSILON) return false;
+
+ float x, y, w, h;
+ if (!bounds(x, y, w, h)) return false;
+
+ auto cx = x + w * 0.5f;
+ auto cy = y + h * 0.5f;
+
+ for(size_t i = 0; i < ptsCnt; ++i) {
+ pts[i].x = (pts[i].x - cx) * factor + cx;
+ pts[i].y = (pts[i].y - cy) * factor + cy;
+ }
+
+ return true;
+ }
};
#endif //_TVG_SHAPE_PATH_CPP_
shape->appendRect(-100, -100, 200, 200, 0);
shape->fill(127, 255, 255, 255);
+ shape->rotate(45);
canvas->push(move(shape));
//Draw first frame
pShape->appendRect(-100 + (800 * progress), -100 + (800 * progress), 200, 200, (100 * progress));
+ /* rotate, scale won't be retained, when you call reset() for the shape, these values will be reset as well.
+ These are working in fire & forget method, it actually modify the path data for avoiding compuatation every frames.
+ Thus user needs to keep the last values to understand the final accumulated values. */
+ pShape->rotate(45);
+ pShape->scale(1 - 0.75 * progress);
+
//Update shape for drawing (this may work asynchronously)
pShape->update(canvas->engine());
auto shape = tvg::Shape::gen();
shape->appendRect(-100 + (800 * progress), -100 + (800 * progress), 200, 200, (100 * progress));
shape->fill(rand()%255, rand()%255, rand()%255, 255);
+ shape->scale(1 - 0.75 * progress);
+ shape->rotate(360 * progress);
+
canvas->push(move(shape));
//Draw Next frames