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();
int update(RasterMethod* engine) noexcept override;
int clear() noexcept;
int appendRect(float x, float y, float w, float h, 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 pathCommands(const PathCommand** cmds) noexcept;
int pathCoords(const Point** pts) noexcept;
int fill(size_t r, size_t g, size_t b, size_t a) 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;

View file

@ -23,11 +23,22 @@
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
{
public:
void* prepare(ShapeNode* shape, void* data) override;
void* prepare(const ShapeNode& shape, void* data) override;
static GlRaster* inst();
static int init();
static int term();

View file

@ -20,29 +20,31 @@
#include "tvgCommon.h"
using namespace tvg;
using SwPos = signed long;
struct SwVector
{
SwPos x;
SwPos y;
};
constexpr auto SW_CURVE_TAG_ON = 1;
constexpr auto SW_CURVE_TAG_CUBIC = 2;
struct SwOutline
{
short* cntrs; /* the contour end points */
short cntrsCnt; /* number of contours in glyph */
SwVector* pts; /* the outline's points */
short ptsCnt; /* number of points in the glyph */
char* tags; /* the points flags */
int flags; /* outline masks */
size_t* cntrs; //the contour end points
size_t cntrsCnt; //number of contours in glyph
size_t reservedCntrsCnt;
Point* pts; //the outline's points
size_t ptsCnt; //number of points in the glyph
size_t reservedPtsCnt;
char* tags; //the points flags
size_t flags; //outline masks
};
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_ */

View file

@ -26,16 +26,31 @@
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) {
sdata = static_cast<SwShape*>(calloc(1, sizeof(SwShape)));
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;
}

View file

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

View file

@ -19,86 +19,188 @@
#include "tvgSwCommon.h"
static void growOutlineContour(SwShape *sdata, size_t n)
{
sdata->outline.cntrsCnt = n;
/************************************************************************/
/* Internal Class Implementation */
/************************************************************************/
static void growOutlineContour(SwOutline& outline, size_t n)
{
if (n == 0) {
free(sdata->outline.cntrs);
sdata->outline.cntrs = nullptr;
free(outline.cntrs);
outline.cntrs = nullptr;
outline.cntrsCnt = 0;
outline.reservedCntrsCnt = 0;
return;
}
sdata->outline.cntrs = static_cast<short *>(realloc(sdata->outline.cntrs, n * sizeof(short)));
assert(sdata->outline.cntrs);
if (outline.reservedCntrsCnt >= outline.cntrsCnt + n) return;
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) {
free(sdata->outline.pts);
sdata->outline.pts = nullptr;
free(sdata->outline.tags);
sdata->outline.tags = nullptr;
free(outline.pts);
outline.pts = nullptr;
free(outline.tags);
outline.tags = nullptr;
outline.reservedPtsCnt = 0;
outline.ptsCnt = 0;
return;
}
sdata->outline.pts = static_cast<SwVector *>(realloc(sdata->outline.pts, n * sizeof(SwVector)));
assert(sdata->outline.pts);
sdata->outline.tags = static_cast<char*>(realloc(sdata->outline.tags, n * sizeof(char)));
assert(sdata->outline.tags);
if (outline.reservedPtsCnt >= outline.ptsCnt + n) return;
cout << "Grow Pts: " << outline.reservedPtsCnt << " -> " << outline.ptsCnt + n << endl;
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,
//grow contour 1
assert(pt);
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)
{
bool closed = false;
/************************************************************************/
/* External Class Implementation */
/************************************************************************/
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;
auto cmdCnt = shape->pathCommands(&cmds);
auto cmdCnt = shape.pathCommands(&cmds);
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 outlineCntrsCnt = 0;
// auto closed = false;
for (auto i = 0; i < cmdCnt; ++i) {
switch(*cmds) {
switch(*(cmds + i)) {
case PathCommand::Close: {
++outlinePtsCnt;
break;
@ -119,30 +221,40 @@ bool shapeGenOutline(ShapeNode *shape, SwShape* sdata)
}
}
++outlinePtsCnt; //for close
++outlinePtsCnt; //for close
++outlineCntrsCnt; //for end
growOutlinePoint(sdata, outlinePtsCnt);
growOutlineContour(sdata, outlineCntrsCnt);
SwOutline* outline = sdata.outline;
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
while (cmdCnt-- > 0) {
switch(*cmds) {
case PathCommand::Close: {
outlineClose(sdata);
outlineClose(*outline);
break;
}
case PathCommand::MoveTo: {
outlineMoveTo(sdata, pts);
outlineMoveTo(*outline, pts);
++pts;
break;
}
case PathCommand::LineTo: {
outlineLineTo(sdata, pts);
outlineLineTo(*outline, pts);
++pts;
break;
}
case PathCommand::CubicTo: {
outlineCubicTo(sdata, pts, pts + 1, pts + 2);
outlineCubicTo(*outline, pts, pts + 1, pts + 2);
pts += 3;
break;
}
@ -150,9 +262,11 @@ bool shapeGenOutline(ShapeNode *shape, SwShape* sdata)
++cmds;
}
outlineEnd(sdata);
outlineEnd(*outline);
return closed;
sdata.outline = outline;
return true;
}

View file

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

View file

@ -32,7 +32,7 @@ class RasterMethod
{
public:
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();
assert(impl);
impl->edata = engine->prepare(this, impl->edata);
impl->edata = engine->prepare(*this, impl->edata);
if (impl->edata) return 0;
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();
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();
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();
assert(impl);
@ -173,4 +173,18 @@ int ShapeNode :: fill(uint32_t r, uint32_t g, uint32_t b, uint32_t a) noexcept
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_

View file

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