mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-08 05:33:36 +00:00
implement shape basics sw engine.
Change-Id: I93788f40f7c4f59bcc9ab4dff9127bcb4e6c1466
This commit is contained in:
parent
701b482131
commit
f9fcd58744
11 changed files with 249 additions and 86 deletions
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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_ */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -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_
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Reference in a new issue