testBoundary
testPath
testPathCopy
+testBlending
public:
~SwCanvas();
- int target(uint32_t* buffer, size_t stride, size_t height) noexcept;
+ int target(uint32_t* buffer, size_t stride, size_t w, size_t h) noexcept;
int sync() noexcept override;
- static std::unique_ptr<SwCanvas> gen(uint32_t* buffer = nullptr, size_t stride = 0, size_t height = 0) noexcept;
+ static std::unique_ptr<SwCanvas> gen() noexcept;
_TIZENVG_DECLARE_PRIVATE(SwCanvas);
};
bool shapeTransformOutline(const ShapeNode& shape, SwShape& sdata);
SwRleData* rleRender(const SwShape& sdata, const SwSize& clip);
-bool rasterShape(Surface& surface, SwShape& sdata, size_t color);
+bool rasterShape(Surface& surface, SwShape& sdata, uint8_t r, uint8_t g, uint8_t b, uint8_t a);
#endif /* _TVG_SW_COMMON_H_ */
#include "tvgSwCommon.h"
-bool rasterShape(Surface& surface, SwShape& sdata, size_t color)
+/************************************************************************/
+/* Internal Class Implementation */
+/************************************************************************/
+
+static inline size_t COLOR_ALPHA_BLEND(size_t color, size_t alpha)
+{
+ return (((((color >> 8) & 0x00ff00ff) * alpha) & 0xff00ff00) +
+ ((((color & 0x00ff00ff) * alpha) >> 8) & 0x00ff00ff));
+}
+
+
+static inline size_t COLOR_ARGB_JOIN(uint8_t r, uint8_t g, uint8_t b, uint8_t a)
+{
+ return (a << 24 | r << 16 | g << 8 | b);
+}
+
+
+static void
+_drawTranslucentSpan(uint32_t* dst, size_t len, size_t color, size_t alpha)
+{
+ //OPTIMIZE ME: SIMD
+ auto ialpha = 255 - alpha;
+ for (size_t i = 0; i < len; ++i) {
+ dst[i] = color + COLOR_ALPHA_BLEND(dst[i], ialpha);
+ }
+}
+
+
+static void
+_drawSolidSpan(uint32_t* dst, size_t len, size_t color)
+{
+ //OPTIMIZE ME: SIMD
+ for (size_t i = 0; i < len; ++i) {
+ dst[i] = color;
+ }
+}
+
+
+/************************************************************************/
+/* External Class Implementation */
+/************************************************************************/
+
+bool rasterShape(Surface& surface, SwShape& sdata, uint8_t r, uint8_t g, uint8_t b, uint8_t a)
{
SwRleData* rle = sdata.rle;
if (!rle) return false;
- auto stride = surface.stride;
auto span = rle->spans;
+ auto stride = surface.stride;
+ auto color = COLOR_ARGB_JOIN(r, g, b, a);
for (size_t i = 0; i < rle->size; ++i) {
assert(span);
-// printf("raster y(%d) x(%d) len(%d)\n", span->y, span->x, span->len);
- for (auto j = 0; j < span->len; ++j) {
- surface.buffer[span->y * stride + span->x + j] = color;
- }
+
+ auto dst = &surface.buffer[span->y * stride + span->x];
+ assert(dst);
+
+ if (a == 255) _drawSolidSpan(dst, span->len, color);
+ else _drawTranslucentSpan(dst, span->len, color, a);
+
++span;
}
static RenderInitializer renderInit;
-static inline size_t COLOR(uint8_t r, uint8_t g, uint8_t b, uint8_t a)
-{
- return (a << 24 | r << 16 | g << 8 | b);
-}
-
/************************************************************************/
/* External Class Implementation */
/************************************************************************/
-bool SwRenderer::target(uint32_t* buffer, size_t stride, size_t height)
+bool SwRenderer::clear()
+{
+ if (!surface.buffer) return false;
+
+ assert(surface.stride > 0 && surface.w > 0 && surface.h > 0);
+
+ //OPTIMIZE ME: SIMD!
+ for (size_t i = 0; i < surface.h; i++) {
+ for (size_t j = 0; j < surface.w; j++)
+ surface.buffer[surface.stride * i + j] = 0xff000000; //Solid Black
+ }
+
+ return true;
+}
+
+bool SwRenderer::target(uint32_t* buffer, size_t stride, size_t w, size_t h)
{
- assert(buffer && stride > 0 && height > 0);
+ assert(buffer && stride > 0 && w > 0 && h > 0);
surface.buffer = buffer;
surface.stride = stride;
- surface.height = height;
+ surface.w = w;
+ surface.h = h;
return true;
}
shape.fill(&r, &g, &b, &a);
//TODO: Threading
- return rasterShape(surface, *sdata, COLOR(r, g, b, a));
+ return rasterShape(surface, *sdata, r, g, b, a);
}
if (!shapeGenOutline(shape, *sdata)) return sdata;
if (!shapeTransformOutline(shape, *sdata)) return sdata;
- SwSize clip = {static_cast<SwCoord>(surface.stride), static_cast<SwCoord>(surface.height)};
+ SwSize clip = {static_cast<SwCoord>(surface.w), static_cast<SwCoord>(surface.h)};
if (!shapeGenRle(shape, *sdata, clip)) return sdata;
}
void* prepare(const ShapeNode& shape, void* data, UpdateFlag flags) override;
bool dispose(const ShapeNode& shape, void *data) override;
bool render(const ShapeNode& shape, void *data) override;
- bool target(uint32_t* buffer, size_t stride, size_t height);
+ bool target(uint32_t* buffer, size_t stride, size_t w, size_t h);
+ bool clear();
size_t ref() override;
size_t unref() override;
//TODO: Union for multiple types
uint32_t* buffer;
size_t stride;
- size_t height;
+ size_t w, h;
};
class RenderMethod
}
-int SwCanvas::target(uint32_t* buffer, size_t stride, size_t height) noexcept
+int SwCanvas::target(uint32_t* buffer, size_t stride, size_t w, size_t h) noexcept
{
auto renderer = dynamic_cast<SwRenderer*>(engine());
assert(renderer);
- if (!renderer->target(buffer, stride, height)) return -1;
+ if (!renderer->target(buffer, stride, w, h)) return -1;
+ if (!renderer->clear()) return -1;
return 0;
}
}
-unique_ptr<SwCanvas> SwCanvas::gen(uint32_t* buffer, size_t stride, size_t height) noexcept
+unique_ptr<SwCanvas> SwCanvas::gen() noexcept
{
auto canvas = unique_ptr<SwCanvas>(new SwCanvas);
assert(canvas);
- int ret = canvas.get()->target(buffer, stride, height);
- if (ret > 0) return nullptr;
-
return canvas;
}
gcc -o testBoundary testBoundary.cpp -g -lstdc++ `pkg-config --cflags --libs elementary tizenvg`
gcc -o testPath testPath.cpp -g -lstdc++ `pkg-config --cflags --libs elementary tizenvg`
gcc -o testPathCopy testPathCopy.cpp -g -lstdc++ `pkg-config --cflags --libs elementary tizenvg`
+ gcc -o testBlending testBlending.cpp -g -lstdc++ `pkg-config --cflags --libs elementary tizenvg`
--- /dev/null
+#include <tizenvg.h>
+#include <Elementary.h>
+
+using namespace std;
+
+#define WIDTH 800
+#define HEIGHT 800
+
+static uint32_t buffer[WIDTH * HEIGHT];
+
+void tvgtest()
+{
+ //Initialize TizenVG Engine
+ tvg::Engine::init();
+
+ //Create a Canvas
+ auto canvas = tvg::SwCanvas::gen();
+ canvas->target(buffer, WIDTH, WIDTH, HEIGHT);
+ canvas->reserve(5);
+
+ //Prepare Round Rectangle
+ auto shape1 = tvg::ShapeNode::gen();
+ shape1->appendRect(0, 0, 400, 400, 50); //x, y, w, h, cornerRadius
+ shape1->fill(0, 255, 0, 255); //r, g, b, a
+ canvas->push(move(shape1));
+
+ //Prepare Circle
+ auto shape2 = tvg::ShapeNode::gen();
+ shape2->appendCircle(400, 400, 200, 200); //cx, cy, radiusW, radiusH
+ shape2->fill(170, 170, 0, 170); //r, g, b, a
+ canvas->push(move(shape2));
+
+ //Prepare Ellipse
+ auto shape3 = tvg::ShapeNode::gen();
+ shape3->appendCircle(400, 400, 250, 100); //cx, cy, radiusW, radiusH
+ shape3->fill(100, 100, 100, 100); //r, g, b, a
+ canvas->push(move(shape3));
+
+ //Prepare Star
+ auto shape4 = tvg::ShapeNode::gen();
+ shape4->moveTo(199, 234);
+ shape4->lineTo(253, 343);
+ shape4->lineTo(374, 360);
+ shape4->lineTo(287, 444);
+ shape4->lineTo(307, 565);
+ shape4->lineTo(199, 509);
+ shape4->lineTo(97, 565);
+ shape4->lineTo(112, 445);
+ shape4->lineTo(26, 361);
+ shape4->lineTo(146, 343);
+ shape4->close();
+ shape4->fill(200, 0, 200, 200);
+ canvas->push(move(shape4));
+
+ //Prepare Opaque Ellipse
+ auto shape5 = tvg::ShapeNode::gen();
+ shape5->appendCircle(600, 650, 200, 150);
+ shape5->fill(0, 0, 255, 255);
+ canvas->push(move(shape5));
+
+ //Draw the Shapes onto the Canvas
+ canvas->draw();
+ canvas->sync();
+
+ //Terminate TizenVG Engine
+ tvg::Engine::term();
+}
+
+void
+win_del(void *data, Evas_Object *o, void *ev)
+{
+ elm_exit();
+}
+
+int main(int argc, char **argv)
+{
+ tvgtest();
+
+ //Show the result using EFL...
+ elm_init(argc, argv);
+
+ Eo* win = elm_win_util_standard_add(NULL, "TizenVG Test");
+ evas_object_smart_callback_add(win, "delete,request", win_del, 0);
+
+ Eo* img = evas_object_image_filled_add(evas_object_evas_get(win));
+ evas_object_image_size_set(img, WIDTH, HEIGHT);
+ evas_object_image_data_set(img, buffer);
+ evas_object_size_hint_weight_set(img, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+ evas_object_show(img);
+
+ elm_win_resize_object_add(win, img);
+ evas_object_geometry_set(win, 0, 0, WIDTH, HEIGHT);
+ evas_object_show(win);
+
+ elm_run();
+ elm_shutdown();
+}
tvg::Engine::init();
//Create a Canvas
- auto canvas = tvg::SwCanvas::gen(buffer, WIDTH, HEIGHT);
+ auto canvas = tvg::SwCanvas::gen();
+ canvas->target(buffer, WIDTH, WIDTH, HEIGHT);
canvas->reserve(5); //reserve 5 shape nodes (optional)
//Prepare Shape1
tvg::Engine::init();
//Create a Canvas
- auto canvas = tvg::SwCanvas::gen(buffer, WIDTH, HEIGHT);
+ auto canvas = tvg::SwCanvas::gen();
+ canvas->target(buffer, WIDTH, WIDTH, HEIGHT);
//Prepare a Shape (Rectangle + Rectangle + Circle + Circle)
auto shape1 = tvg::ShapeNode::gen();
tvg::Engine::init();
//Create a Canvas
- auto canvas = tvg::SwCanvas::gen(buffer, WIDTH, HEIGHT);
+ auto canvas = tvg::SwCanvas::gen();
+ canvas->target(buffer, WIDTH, WIDTH, HEIGHT);
canvas->reserve(3); //reserve 3 shape nodes (optional)
//Prepare Round Rectangle
tvg::Engine::init();
//Create a Canvas
- auto canvas = tvg::SwCanvas::gen(buffer, WIDTH, HEIGHT);
+ auto canvas = tvg::SwCanvas::gen();
+ canvas->target(buffer, WIDTH, WIDTH, HEIGHT);
//Star
auto shape1 = tvg::ShapeNode::gen();
tvg::Engine::init();
//Create a Canvas
- auto canvas = tvg::SwCanvas::gen(buffer, WIDTH, HEIGHT);
+ auto canvas = tvg::SwCanvas::gen();
+ canvas->target(buffer, WIDTH, WIDTH, HEIGHT);
/* Star */
tvg::Engine::init();
//Create a Canvas
- auto canvas = tvg::SwCanvas::gen(buffer, WIDTH, HEIGHT);
+ auto canvas = tvg::SwCanvas::gen();
+ canvas->target(buffer, WIDTH, WIDTH, HEIGHT);
//Prepare a Shape (Rectangle)
auto shape1 = tvg::ShapeNode::gen();