implement shape basics sw engine.

Change-Id: I93788f40f7c4f59bcc9ab4dff9127bcb4e6c1466
This commit is contained in:
Hermet Park 2020-04-04 01:14:11 +09:00
parent 701b482131
commit f9fcd58744
11 changed files with 249 additions and 86 deletions

View file

@ -91,13 +91,16 @@ public:
~ShapeNode(); ~ShapeNode();
int update(RasterMethod* engine) noexcept override; int update(RasterMethod* engine) noexcept override;
int clear() noexcept;
int appendRect(float x, float y, float w, float h, float radius) noexcept; int appendRect(float x, float y, float w, float h, float radius) noexcept;
int appendCircle(float cx, float cy, float radius) noexcept; int appendCircle(float cx, float cy, float radius) noexcept;
int fill(uint32_t r, uint32_t g, uint32_t b, uint32_t a) noexcept;
int clear() noexcept; int fill(size_t r, size_t g, size_t b, size_t a) noexcept;
int pathCommands(const PathCommand** cmds) noexcept;
int pathCoords(const Point** pts) noexcept; 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;
static std::unique_ptr<ShapeNode> gen() noexcept; static std::unique_ptr<ShapeNode> gen() noexcept;

View file

@ -23,11 +23,22 @@
static GlRaster* pInst = nullptr; static GlRaster* pInst = nullptr;
void* GlRaster::prepare(ShapeNode* shape, void* data) struct GlShape
{ {
cout << "GlRaster prepare!!" << endl; //TODO:
};
return nullptr;
void* GlRaster::prepare(const ShapeNode& shape, void* data)
{
//prepare shape data
GlShape* sdata = static_cast<GlShape*>(data);
if (!sdata) {
sdata = static_cast<GlShape*>(calloc(1, sizeof(GlShape)));
assert(sdata);
}
return sdata;
} }

View file

@ -23,7 +23,7 @@ namespace tvg
class GlRaster : public RasterMethod class GlRaster : public RasterMethod
{ {
public: public:
void* prepare(ShapeNode* shape, void* data) override; void* prepare(const ShapeNode& shape, void* data) override;
static GlRaster* inst(); static GlRaster* inst();
static int init(); static int init();
static int term(); static int term();

View file

@ -20,29 +20,31 @@
#include "tvgCommon.h" #include "tvgCommon.h"
using namespace tvg; using namespace tvg;
using SwPos = signed long;
struct SwVector constexpr auto SW_CURVE_TAG_ON = 1;
{ constexpr auto SW_CURVE_TAG_CUBIC = 2;
SwPos x;
SwPos y;
};
struct SwOutline struct SwOutline
{ {
short* cntrs; /* the contour end points */ size_t* cntrs; //the contour end points
short cntrsCnt; /* number of contours in glyph */ size_t cntrsCnt; //number of contours in glyph
SwVector* pts; /* the outline's points */ size_t reservedCntrsCnt;
short ptsCnt; /* number of points in the glyph */ Point* pts; //the outline's points
char* tags; /* the points flags */ size_t ptsCnt; //number of points in the glyph
int flags; /* outline masks */ size_t reservedPtsCnt;
char* tags; //the points flags
size_t flags; //outline masks
}; };
struct SwShape struct SwShape
{ {
SwOutline outline; // SwRleRaster raster;
SwOutline* outline;
}; };
bool shapeGenOutline(ShapeNode *shape, SwShape* sdata); bool shapeGenOutline(const ShapeNode& shape, SwShape& sdata);
void shapeDelOutline(const ShapeNode& shape, SwShape& sdata);
bool shapeGenRle(const ShapeNode& shape, SwShape& sdata);
bool shapeUpdateBBox(const ShapeNode& shape, SwShape& sdata);
#endif /* _TVG_SW_COMMON_H_ */ #endif /* _TVG_SW_COMMON_H_ */

View file

@ -26,16 +26,31 @@
static SwRaster* pInst = nullptr; static SwRaster* pInst = nullptr;
/************************************************************************/
/* External Class Implementation */
/************************************************************************/
void* SwRaster::prepare(ShapeNode *shape, void* data) void* SwRaster::prepare(const ShapeNode& shape, void* data)
{ {
SwShape *sdata = static_cast<SwShape*>(data); //prepare shape data
SwShape* sdata = static_cast<SwShape*>(data);
if (!sdata) { if (!sdata) {
sdata = static_cast<SwShape*>(calloc(1, sizeof(SwShape))); sdata = static_cast<SwShape*>(calloc(1, sizeof(SwShape)));
assert(sdata); assert(sdata);
} }
bool closed = shapeGenOutline(shape, sdata); //invisible?
size_t alpha;
shape.fill(nullptr, nullptr, nullptr, &alpha);
if (alpha == 0) return sdata;
if (!shapeGenOutline(shape, *sdata)) return sdata;
//TODO: From below sequence starts threading?
if (!shapeGenRle(shape, *sdata)) return sdata;
if (!shapeUpdateBBox(shape, *sdata)) return sdata;
shapeDelOutline(shape, *sdata);
return sdata; return sdata;
} }

View file

@ -20,7 +20,7 @@
class SwRaster : public RasterMethod class SwRaster : public RasterMethod
{ {
public: public:
void* prepare(ShapeNode* shape, void* data) override; void* prepare(const ShapeNode& shape, void* data) override;
static SwRaster* inst(); static SwRaster* inst();
static int init(); static int init();
static int term(); static int term();

View file

@ -19,86 +19,188 @@
#include "tvgSwCommon.h" #include "tvgSwCommon.h"
static void growOutlineContour(SwShape *sdata, size_t n) /************************************************************************/
{ /* Internal Class Implementation */
sdata->outline.cntrsCnt = n; /************************************************************************/
static void growOutlineContour(SwOutline& outline, size_t n)
{
if (n == 0) { if (n == 0) {
free(sdata->outline.cntrs); free(outline.cntrs);
sdata->outline.cntrs = nullptr; outline.cntrs = nullptr;
outline.cntrsCnt = 0;
outline.reservedCntrsCnt = 0;
return; return;
} }
sdata->outline.cntrs = static_cast<short *>(realloc(sdata->outline.cntrs, n * sizeof(short))); if (outline.reservedCntrsCnt >= outline.cntrsCnt + n) return;
assert(sdata->outline.cntrs);
cout << "Grow Cntrs: " << outline.reservedCntrsCnt << " -> " << outline.cntrsCnt + n << endl;;
outline.reservedCntrsCnt = n;
outline.cntrs = static_cast<size_t*>(realloc(outline.cntrs, n * sizeof(size_t)));
assert(outline.cntrs);
} }
static void growOutlinePoint(SwShape *sdata, size_t n) static void growOutlinePoint(SwOutline& outline, size_t n)
{ {
sdata->outline.ptsCnt = n;
if (n == 0) { if (n == 0) {
free(sdata->outline.pts); free(outline.pts);
sdata->outline.pts = nullptr; outline.pts = nullptr;
free(sdata->outline.tags); free(outline.tags);
sdata->outline.tags = nullptr; outline.tags = nullptr;
outline.reservedPtsCnt = 0;
outline.ptsCnt = 0;
return; return;
} }
sdata->outline.pts = static_cast<SwVector *>(realloc(sdata->outline.pts, n * sizeof(SwVector))); if (outline.reservedPtsCnt >= outline.ptsCnt + n) return;
assert(sdata->outline.pts);
sdata->outline.tags = static_cast<char*>(realloc(sdata->outline.tags, n * sizeof(char))); cout << "Grow Pts: " << outline.reservedPtsCnt << " -> " << outline.ptsCnt + n << endl;
assert(sdata->outline.tags); outline.reservedPtsCnt = n;
outline.pts = static_cast<Point*>(realloc(outline.pts, n * sizeof(Point)));
assert(outline.pts);
outline.tags = static_cast<char*>(realloc(outline.tags, n * sizeof(char)));
assert(outline.tags);
} }
static void outlineEnd(SwShape* sdata) static void outlineEnd(SwOutline& outline)
{ {
//grow contour 1 growOutlineContour(outline, 1);
if (outline.ptsCnt > 0) {
outline.cntrs[outline.cntrsCnt] = outline.ptsCnt - 1;
++outline.cntrs;
}
} }
static void outlineMoveTo(SwShape* sdata, const Point* pt) static void outlineMoveTo(SwOutline& outline, const Point* pt)
{ {
//grow pts 1, assert(pt);
//grow contour 1
growOutlinePoint(outline, 1);
outline.pts[outline.ptsCnt] = *pt;
outline.tags[outline.ptsCnt] = SW_CURVE_TAG_ON;
if (outline.ptsCnt > 0) {
growOutlineContour(outline, 1);
outline.cntrs[outline.cntrsCnt] = outline.ptsCnt - 1;
++outline.cntrsCnt;
}
++outline.ptsCnt;
} }
static void outlineLineTo(SwShape* sdata, const Point* pt) static void outlineLineTo(SwOutline& outline, const Point* pt)
{ {
//grow pts 1 assert(pt);
growOutlinePoint(outline, 1);
outline.pts[outline.ptsCnt] = *pt;
outline.tags[outline.ptsCnt] = SW_CURVE_TAG_ON;
++outline.ptsCnt;
} }
static void outlineCubicTo(SwShape* sdata, const Point* ctrl1, const Point* ctrl2, const Point* pt) static void outlineCubicTo(SwOutline& outline, const Point* ctrl1, const Point* ctrl2, const Point* pt)
{ {
//grow pts 3 assert(ctrl1 && ctrl2 && pt);
growOutlinePoint(outline, 3);
outline.pts[outline.ptsCnt] = *ctrl1;
outline.tags[outline.ptsCnt] = SW_CURVE_TAG_CUBIC;
++outline.ptsCnt;
outline.pts[outline.ptsCnt] = *ctrl2;
outline.tags[outline.ptsCnt] = SW_CURVE_TAG_CUBIC;
++outline.ptsCnt;
outline.pts[outline.ptsCnt] = *ctrl1;
outline.tags[outline.ptsCnt] = SW_CURVE_TAG_ON;
++outline.ptsCnt;
} }
static void outlineClose(SwShape* sdata) static bool outlineClose(SwOutline& outline)
{ {
//grow pts 1 size_t i = 0;
if (outline.cntrsCnt > 0) {
i = outline.cntrs[outline.cntrsCnt - 1] + 1;
} else {
i = 0; //First Path
}
//Make sure there is at least one point in the current path
if (outline.ptsCnt == i) return false;
//Close the path
growOutlinePoint(outline, 1);
outline.pts[outline.ptsCnt] = outline.pts[i];
outline.tags[outline.ptsCnt] = SW_CURVE_TAG_ON;
++outline.ptsCnt;
return true;
} }
bool shapeGenOutline(ShapeNode *shape, SwShape* sdata) /************************************************************************/
{ /* External Class Implementation */
bool closed = false; /************************************************************************/
bool shapeGenRle(const ShapeNode& shape, SwShape& sdata)
{
//TODO: rle
return true;
}
bool shapeUpdateBBox(const ShapeNode& shape, SwShape& sdata)
{
//TODO:
return true;
}
void shapeDelOutline(const ShapeNode& shape, SwShape& sdata)
{
if (!sdata.outline) return;
SwOutline* outline = sdata.outline;
if (outline->cntrs) free(outline->cntrs);
if (outline->pts) free(outline->pts);
if (outline->tags) free(outline->tags);
free(outline);
sdata.outline = nullptr;
}
bool shapeGenOutline(const ShapeNode& shape, SwShape& sdata)
{
const PathCommand* cmds = nullptr; const PathCommand* cmds = nullptr;
auto cmdCnt = shape->pathCommands(&cmds); auto cmdCnt = shape.pathCommands(&cmds);
const Point* pts = nullptr; const Point* pts = nullptr;
shape->pathCoords(&pts); auto ptsCnt = shape.pathCoords(&pts);
//reservation //No actual shape data
if (cmdCnt == 0 || ptsCnt == 0) return false;
//smart reservation
auto outlinePtsCnt = 0; auto outlinePtsCnt = 0;
auto outlineCntrsCnt = 0; auto outlineCntrsCnt = 0;
// auto closed = false;
for (auto i = 0; i < cmdCnt; ++i) { for (auto i = 0; i < cmdCnt; ++i) {
switch(*cmds) { switch(*(cmds + i)) {
case PathCommand::Close: { case PathCommand::Close: {
++outlinePtsCnt; ++outlinePtsCnt;
break; break;
@ -120,29 +222,39 @@ bool shapeGenOutline(ShapeNode *shape, SwShape* sdata)
} }
++outlinePtsCnt; //for close ++outlinePtsCnt; //for close
++outlineCntrsCnt; //for end
growOutlinePoint(sdata, outlinePtsCnt); SwOutline* outline = sdata.outline;
growOutlineContour(sdata, outlineCntrsCnt);
if (!outline) {
outline = static_cast<SwOutline*>(calloc(1, sizeof(SwOutline)));
assert(outline);
} else {
cout << "Outline was already allocated? How?" << endl;
}
growOutlinePoint(*outline, outlinePtsCnt);
growOutlineContour(*outline, outlineCntrsCnt);
//Generate Outlines //Generate Outlines
while (cmdCnt-- > 0) { while (cmdCnt-- > 0) {
switch(*cmds) { switch(*cmds) {
case PathCommand::Close: { case PathCommand::Close: {
outlineClose(sdata); outlineClose(*outline);
break; break;
} }
case PathCommand::MoveTo: { case PathCommand::MoveTo: {
outlineMoveTo(sdata, pts); outlineMoveTo(*outline, pts);
++pts; ++pts;
break; break;
} }
case PathCommand::LineTo: { case PathCommand::LineTo: {
outlineLineTo(sdata, pts); outlineLineTo(*outline, pts);
++pts; ++pts;
break; break;
} }
case PathCommand::CubicTo: { case PathCommand::CubicTo: {
outlineCubicTo(sdata, pts, pts + 1, pts + 2); outlineCubicTo(*outline, pts, pts + 1, pts + 2);
pts += 3; pts += 3;
break; break;
} }
@ -150,9 +262,11 @@ bool shapeGenOutline(ShapeNode *shape, SwShape* sdata)
++cmds; ++cmds;
} }
outlineEnd(sdata); outlineEnd(*outline);
return closed; sdata.outline = outline;
return true;
} }

View file

@ -61,13 +61,17 @@ struct CanvasBase
assert(node); assert(node);
nodes.push_back(node); nodes.push_back(node);
#if 0
if (SceneNode *scene = dynamic_cast<SceneNode *>(node)) { if (SceneNode *scene = dynamic_cast<SceneNode *>(node)) {
} else if (ShapeNode *shape = dynamic_cast<ShapeNode *>(node)) { } else if (ShapeNode *shape = dynamic_cast<ShapeNode *>(node)) {
return shape->update(raster); return shape->update(raster);
} }
#else
if (ShapeNode *shape = dynamic_cast<ShapeNode *>(node)) {
return shape->update(raster);
}
#endif
cout << "What type of PaintNode? = " << node << endl; cout << "What type of PaintNode? = " << node << endl;
return -1; return -1;

View file

@ -32,7 +32,7 @@ class RasterMethod
{ {
public: public:
virtual ~RasterMethod() {} virtual ~RasterMethod() {}
virtual void* prepare(ShapeNode* shape, void* data) = 0; virtual void* prepare(const ShapeNode& shape, void* data) = 0;
}; };
} }

View file

@ -89,7 +89,7 @@ int ShapeNode :: update(RasterMethod* engine) noexcept
auto impl = pImpl.get(); auto impl = pImpl.get();
assert(impl); assert(impl);
impl->edata = engine->prepare(this, impl->edata); impl->edata = engine->prepare(*this, impl->edata);
if (impl->edata) return 0; if (impl->edata) return 0;
return - 1; return - 1;
} }
@ -104,7 +104,7 @@ int ShapeNode :: clear() noexcept
} }
int ShapeNode :: pathCommands(const PathCommand** cmds) noexcept int ShapeNode :: pathCommands(const PathCommand** cmds) const noexcept
{ {
auto impl = pImpl.get(); auto impl = pImpl.get();
assert(impl && cmds); assert(impl && cmds);
@ -115,7 +115,7 @@ int ShapeNode :: pathCommands(const PathCommand** cmds) noexcept
} }
int ShapeNode :: pathCoords(const Point** pts) noexcept int ShapeNode :: pathCoords(const Point** pts) const noexcept
{ {
auto impl = pImpl.get(); auto impl = pImpl.get();
assert(impl && pts); assert(impl && pts);
@ -160,7 +160,7 @@ int ShapeNode :: appendRect(float x, float y, float w, float h, float radius) no
} }
int ShapeNode :: fill(uint32_t r, uint32_t g, uint32_t b, uint32_t a) noexcept int ShapeNode :: fill(size_t r, size_t g, size_t b, size_t a) noexcept
{ {
auto impl = pImpl.get(); auto impl = pImpl.get();
assert(impl); assert(impl);
@ -173,4 +173,18 @@ int ShapeNode :: fill(uint32_t r, uint32_t g, uint32_t b, uint32_t a) noexcept
return 0; return 0;
} }
int ShapeNode :: fill(size_t* r, size_t* g, size_t* b, size_t* a) const noexcept
{
auto impl = pImpl.get();
assert(impl);
if (r) *r = impl->color[0];
if (g) *g = impl->color[0];
if (b) *b = impl->color[0];
if (a) *a = impl->color[0];
return 0;
}
#endif //_TVG_SHAPE_NODE_CPP_ #endif //_TVG_SHAPE_NODE_CPP_

View file

@ -26,12 +26,12 @@
struct ShapePath struct ShapePath
{ {
PathCommand* cmds = nullptr; PathCommand* cmds = nullptr;
uint32_t cmdCnt = 0; size_t cmdCnt = 0;
uint32_t reservedCmdCnt = 0; size_t reservedCmdCnt = 0;
Point *pts = nullptr; Point *pts = nullptr;
uint32_t ptsCnt = 0; size_t ptsCnt = 0;
uint32_t reservedPtsCnt = 0; size_t reservedPtsCnt = 0;
~ShapePath() ~ShapePath()
@ -40,7 +40,7 @@ struct ShapePath
if (pts) delete(pts); if (pts) delete(pts);
} }
int reserveCmd(uint32_t cmdCnt) int reserveCmd(size_t cmdCnt)
{ {
if (cmdCnt > reservedCmdCnt) { if (cmdCnt > reservedCmdCnt) {
reservedCmdCnt = cmdCnt; reservedCmdCnt = cmdCnt;
@ -50,7 +50,7 @@ struct ShapePath
return 0; return 0;
} }
int reservePts(uint32_t ptsCnt) int reservePts(size_t ptsCnt)
{ {
if (ptsCnt > reservedPtsCnt) { if (ptsCnt > reservedPtsCnt) {
reservedPtsCnt = ptsCnt; reservedPtsCnt = ptsCnt;
@ -60,7 +60,7 @@ struct ShapePath
return 0; return 0;
} }
int reserve(uint32_t cmdCnt, uint32_t ptsCnt) int reserve(size_t cmdCnt, size_t ptsCnt)
{ {
reserveCmd(cmdCnt); reserveCmd(cmdCnt);
reservePts(ptsCnt); reservePts(ptsCnt);
@ -126,7 +126,7 @@ struct ShapePath
Point min = { pts[0].x, pts[0].y }; Point min = { pts[0].x, pts[0].y };
Point max = { pts[0].x, pts[0].y }; Point max = { pts[0].x, pts[0].y };
for(uint32_t i = 1; i <= ptsCnt; ++i) { for(size_t i = 1; i <= ptsCnt; ++i) {
if (pts[i].x < min.x) min.x = pts[i].x; 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].y < min.y) min.y = pts[i].y;
if (pts[i].x > max.x) max.x = pts[i].x; if (pts[i].x > max.x) max.x = pts[i].x;