raw_loader Loader: Introduce Raw image loader

Add RawLoader class that loads and display raw images,
and adds a Rasterizer for image data.
Image data can be loaded via picture.
Loaded image supports Composition, Transformation and Alpha blending.

New API
Result load(uint32_t* data, uint32_t width, uint32_t height, bool isCopy) noexcept;
This commit is contained in:
JunsuChoi 2020-11-23 18:12:36 +09:00 committed by GitHub
parent e259213b44
commit e00f948705
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
42 changed files with 1008 additions and 82 deletions

View file

@ -279,6 +279,7 @@ public:
Result load(const std::string& path) noexcept; Result load(const std::string& path) noexcept;
Result load(const char* data, uint32_t size) noexcept; Result load(const char* data, uint32_t size) noexcept;
Result load(uint32_t* data, uint32_t w, uint32_t h, bool copy) noexcept;
Result viewbox(float* x, float* y, float* w, float* h) const noexcept; Result viewbox(float* x, float* y, float* w, float* h) const noexcept;
static std::unique_ptr<Picture> gen() noexcept; static std::unique_ptr<Picture> gen() noexcept;

View file

@ -6,7 +6,7 @@ project('thorvg',
config_h = configuration_data() config_h = configuration_data()
add_project_arguments('-DEXAMPLE_DIR="@0@/src/examples/svgs"'.format(meson.current_source_dir()), language : 'cpp') add_project_arguments('-DEXAMPLE_DIR="@0@/src/examples/images"'.format(meson.current_source_dir()), language : 'cpp')
if get_option('engines').contains('sw') == true if get_option('engines').contains('sw') == true
config_h.set10('THORVG_SW_RASTER_SUPPORT', true) config_h.set10('THORVG_SW_RASTER_SUPPORT', true)

157
src/examples/PixelImage.cpp Normal file
View file

@ -0,0 +1,157 @@
#include "Common.h"
#include <fstream>
/************************************************************************/
/* Drawing Commands */
/************************************************************************/
uint32_t *data = nullptr;
void tvgDrawCmds(tvg::Canvas* canvas)
{
if (!canvas) return;
//Background
auto shape = tvg::Shape::gen();
shape->appendRect(0, 0, WIDTH, HEIGHT, 0, 0);
shape->fill(255, 255, 255, 255);
if (canvas->push(move(shape)) != tvg::Result::Success) return;
string path(EXAMPLE_DIR"/rawimage_200x300.raw");
ifstream file(path);
if (!file.is_open()) return ;
data = (uint32_t*)malloc(sizeof(uint32_t) * (200*300));
file.read(reinterpret_cast<char *>(data), sizeof (data) * 200 * 300);
file.close();
auto picture = tvg::Picture::gen();
if (picture->load(data, 200, 300, true) != tvg::Result::Success) return;
picture->translate(400, 250);
canvas->push(move(picture));
auto picture2 = tvg::Picture::gen();
if (picture2->load(data, 200, 300, true) != tvg::Result::Success) return;
picture2->translate(400, 200);
picture2->rotate(47);
picture2->scale(1.5);
picture2->opacity(128);
auto circle = tvg::Shape::gen();
circle->appendCircle(350, 350, 200,200);
circle->fill(255, 255, 255, 255);
picture2->composite(move(circle), tvg::CompositeMethod::ClipPath);
canvas->push(move(picture2));
}
/************************************************************************/
/* Sw Engine Test Code */
/************************************************************************/
static unique_ptr<tvg::SwCanvas> swCanvas;
void tvgSwTest(uint32_t* buffer)
{
//Create a Canvas
swCanvas = tvg::SwCanvas::gen();
swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT, tvg::SwCanvas::ARGB8888);
/* Push the shape into the Canvas drawing list
When this shape is into the canvas list, the shape could update & prepare
internal data asynchronously for coming rendering.
Canvas keeps this shape node unless user call canvas->clear() */
tvgDrawCmds(swCanvas.get());
}
void drawSwView(void* data, Eo* obj)
{
if (swCanvas->draw() == tvg::Result::Success) {
swCanvas->sync();
}
}
/************************************************************************/
/* GL Engine Test Code */
/************************************************************************/
static unique_ptr<tvg::GlCanvas> glCanvas;
void initGLview(Evas_Object *obj)
{
static constexpr auto BPP = 4;
//Create a Canvas
glCanvas = tvg::GlCanvas::gen();
glCanvas->target(nullptr, WIDTH * BPP, WIDTH, HEIGHT);
/* Push the shape into the Canvas drawing list
When this shape is into the canvas list, the shape could update & prepare
internal data asynchronously for coming rendering.
Canvas keeps this shape node unless user call canvas->clear() */
tvgDrawCmds(glCanvas.get());
}
void drawGLview(Evas_Object *obj)
{
auto gl = elm_glview_gl_api_get(obj);
gl->glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
gl->glClear(GL_COLOR_BUFFER_BIT);
if (glCanvas->draw() == tvg::Result::Success) {
glCanvas->sync();
}
}
/************************************************************************/
/* Main Code */
/************************************************************************/
int main(int argc, char **argv)
{
tvg::CanvasEngine tvgEngine = tvg::CanvasEngine::Sw;
if (argc > 1) {
if (!strcmp(argv[1], "gl")) tvgEngine = tvg::CanvasEngine::Gl;
}
//Initialize ThorVG Engine
if (tvgEngine == tvg::CanvasEngine::Sw) {
cout << "tvg engine: software" << endl;
} else {
cout << "tvg engine: opengl" << endl;
}
//Threads Count
auto threads = std::thread::hardware_concurrency();
//Initialize ThorVG Engine
if (tvg::Initializer::init(tvgEngine, threads) == tvg::Result::Success) {
elm_init(argc, argv);
if (tvgEngine == tvg::CanvasEngine::Sw) {
createSwView();
} else {
createGlView();
}
elm_run();
elm_shutdown();
//Terminate ThorVG Engine
tvg::Initializer::term(tvg::CanvasEngine::Sw);
if (data) free(data);
} else {
cout << "engine is not supported" << endl;
}
return 0;
}

View file

Before

Width:  |  Height:  |  Size: 807 B

After

Width:  |  Height:  |  Size: 807 B

View file

Before

Width:  |  Height:  |  Size: 1 KiB

After

Width:  |  Height:  |  Size: 1 KiB

View file

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View file

Before

Width:  |  Height:  |  Size: 794 B

After

Width:  |  Height:  |  Size: 794 B

View file

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

View file

Before

Width:  |  Height:  |  Size: 919 B

After

Width:  |  Height:  |  Size: 919 B

View file

Before

Width:  |  Height:  |  Size: 1 KiB

After

Width:  |  Height:  |  Size: 1 KiB

View file

Before

Width:  |  Height:  |  Size: 330 B

After

Width:  |  Height:  |  Size: 330 B

View file

Before

Width:  |  Height:  |  Size: 4.4 KiB

After

Width:  |  Height:  |  Size: 4.4 KiB

View file

Before

Width:  |  Height:  |  Size: 514 B

After

Width:  |  Height:  |  Size: 514 B

View file

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

View file

Before

Width:  |  Height:  |  Size: 501 B

After

Width:  |  Height:  |  Size: 501 B

File diff suppressed because one or more lines are too long

View file

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

View file

Before

Width:  |  Height:  |  Size: 84 KiB

After

Width:  |  Height:  |  Size: 84 KiB

View file

Before

Width:  |  Height:  |  Size: 633 B

After

Width:  |  Height:  |  Size: 633 B

View file

Before

Width:  |  Height:  |  Size: 282 B

After

Width:  |  Height:  |  Size: 282 B

View file

@ -17,6 +17,7 @@ source_file = [
'Opacity.cpp', 'Opacity.cpp',
'PathCopy.cpp', 'PathCopy.cpp',
'Path.cpp', 'Path.cpp',
'PixelImage.cpp',
'RadialGradient.cpp', 'RadialGradient.cpp',
'Scene.cpp', 'Scene.cpp',
'SceneTransform.cpp', 'SceneTransform.cpp',

View file

@ -130,7 +130,7 @@ bool GlRenderer::render(const Shape& shape, void* data)
} }
bool GlRenderer::dispose(TVG_UNUSED const Shape& shape, void *data) bool GlRenderer::dispose(void *data)
{ {
GlShape* sdata = static_cast<GlShape*>(data); GlShape* sdata = static_cast<GlShape*>(data);
if (!sdata) return false; if (!sdata) return false;

View file

@ -1,6 +1,7 @@
source_file = [ source_file = [
'tvgSwCommon.h', 'tvgSwCommon.h',
'tvgSwFill.cpp', 'tvgSwFill.cpp',
'tvgSwImage.cpp',
'tvgSwMath.cpp', 'tvgSwMath.cpp',
'tvgSwRenderer.h', 'tvgSwRenderer.h',
'tvgSwRaster.cpp', 'tvgSwRaster.cpp',

View file

@ -212,6 +212,16 @@ struct SwShape
bool rect; //Fast Track: Othogonal rectangle? bool rect; //Fast Track: Othogonal rectangle?
}; };
struct SwImage
{
SwOutline* outline = nullptr;
SwRleData* rle = nullptr;
uint32_t* data = nullptr;
SwBBox bbox;
uint32_t width;
uint32_t height;
};
struct SwCompositor struct SwCompositor
{ {
uint32_t (*join)(uint8_t r, uint8_t g, uint8_t b, uint8_t a); uint32_t (*join)(uint8_t r, uint8_t g, uint8_t b, uint8_t a);
@ -284,6 +294,14 @@ bool strokeParseOutline(SwStroke* stroke, const SwOutline& outline);
SwOutline* strokeExportOutline(SwStroke* stroke, unsigned tid); SwOutline* strokeExportOutline(SwStroke* stroke, unsigned tid);
void strokeFree(SwStroke* stroke); void strokeFree(SwStroke* stroke);
bool imagePrepare(SwImage* image, const Picture* pdata, unsigned tid, const SwSize& clip, const Matrix* transform);
bool imagePrepared(SwImage* image);
bool imageGenRle(SwImage* image, TVG_UNUSED const Picture* pdata, const SwSize& clip, bool antiAlias, bool hasComposite);
void imageDelOutline(SwImage* image, uint32_t tid);
void imageReset(SwImage* image);
bool imageGenOutline(SwImage* image, const Picture* pdata, unsigned tid, const Matrix* transform);
void imageFree(SwImage* image);
bool fillGenColorTable(SwFill* fill, const Fill* fdata, const Matrix* transform, SwSurface* surface, bool ctable); bool fillGenColorTable(SwFill* fill, const Fill* fdata, const Matrix* transform, SwSurface* surface, bool ctable);
void fillReset(SwFill* fill); void fillReset(SwFill* fill);
void fillFree(SwFill* fill); void fillFree(SwFill* fill);
@ -307,6 +325,7 @@ void mpoolRetStrokeOutline(unsigned idx);
bool rasterCompositor(SwSurface* surface); bool rasterCompositor(SwSurface* surface);
bool rasterGradientShape(SwSurface* surface, SwShape* shape, unsigned id); bool rasterGradientShape(SwSurface* surface, SwShape* shape, unsigned id);
bool rasterSolidShape(SwSurface* surface, SwShape* shape, uint8_t r, uint8_t g, uint8_t b, uint8_t a); bool rasterSolidShape(SwSurface* surface, SwShape* shape, uint8_t r, uint8_t g, uint8_t b, uint8_t a);
bool rasterImage(SwSurface* surface, SwImage* image, uint8_t opacity, const Matrix* transform);
bool rasterStroke(SwSurface* surface, SwShape* shape, uint8_t r, uint8_t g, uint8_t b, uint8_t a); bool rasterStroke(SwSurface* surface, SwShape* shape, uint8_t r, uint8_t g, uint8_t b, uint8_t a);
bool rasterClear(SwSurface* surface); bool rasterClear(SwSurface* surface);
@ -335,4 +354,14 @@ static inline void rasterRGBA32(uint32_t *dst, uint32_t val, uint32_t offset, in
#endif #endif
} }
static inline SwPoint mathTransform(const Point* to, const Matrix* transform)
{
if (!transform) return {TO_SWCOORD(to->x), TO_SWCOORD(to->y)};
auto tx = ((to->x * transform->e11 + to->y * transform->e12 + transform->e13) + 0.5f);
auto ty = ((to->x * transform->e21 + to->y * transform->e22 + transform->e23) + 0.5f);
return {TO_SWCOORD(tx), TO_SWCOORD(ty)};
}
#endif /* _TVG_SW_COMMON_H_ */ #endif /* _TVG_SW_COMMON_H_ */

View file

@ -0,0 +1,175 @@
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include <math.h>
#include "tvgSwCommon.h"
/************************************************************************/
/* Internal Class Implementation */
/************************************************************************/
static void _initBBox(SwBBox& bbox)
{
bbox.min.x = bbox.min.y = 0;
bbox.max.x = bbox.max.y = 0;
}
static bool _updateBBox(SwOutline* outline, SwBBox& bbox, const SwSize& clip)
{
if (!outline) return false;
auto pt = outline->pts;
if (outline->ptsCnt <= 0) {
_initBBox(bbox);
return false;
}
auto xMin = pt->x;
auto xMax = pt->x;
auto yMin = pt->y;
auto yMax = pt->y;
++pt;
for(uint32_t i = 1; i < outline->ptsCnt; ++i, ++pt) {
if (xMin > pt->x) xMin = pt->x;
if (xMax < pt->x) xMax = pt->x;
if (yMin > pt->y) yMin = pt->y;
if (yMax < pt->y) yMax = pt->y;
}
bbox.min.x = xMin >> 6;
bbox.max.x = (xMax + 63) >> 6;
bbox.min.y = yMin >> 6;
bbox.max.y = (yMax + 63) >> 6;
bbox.min.x = max(bbox.min.x, TO_SWCOORD(0));
bbox.min.y = max(bbox.min.y, TO_SWCOORD(0));
bbox.max.x = min(bbox.max.x, clip.w);
bbox.max.y = min(bbox.max.y, clip.h);
if (xMax - xMin < 1 && yMax - yMin < 1) return false;
return true;
}
static bool _checkValid(const SwOutline* outline, const SwBBox& bbox, const SwSize& clip)
{
if (outline->ptsCnt == 0 || outline->cntrsCnt <= 0) return false;
//Check boundary
if (bbox.min.x >= clip.w || bbox.min.y >= clip.h || bbox.max.x <= 0 || bbox.max.y <= 0) return false;
return true;
}
/************************************************************************/
/* External Class Implementation */
/************************************************************************/
bool imagePrepare(SwImage* image, const Picture* pdata, unsigned tid, const SwSize& clip, const Matrix* transform)
{
if (!imageGenOutline(image, pdata, tid, transform)) return false;
if (!_updateBBox(image->outline, image->bbox, clip)) return false;
if (!_checkValid(image->outline, image->bbox, clip)) return false;
return true;
}
bool imagePrepared(SwImage* image)
{
return image->rle ? true : false;
}
bool imageGenRle(SwImage* image, TVG_UNUSED const Picture* pdata, const SwSize& clip, bool antiAlias, bool hasComposite)
{
if ((image->rle = rleRender(image->rle, image->outline, image->bbox, clip, antiAlias))) return true;
return false;
}
void imageDelOutline(SwImage* image, uint32_t tid)
{
mpoolRetOutline(tid);
image->outline = nullptr;
}
void imageReset(SwImage* image)
{
rleReset(image->rle);
image->rle = nullptr;
_initBBox(image->bbox);
}
bool imageGenOutline(SwImage* image, const Picture* pdata, unsigned tid, const Matrix* transform)
{
image->outline = mpoolReqOutline(tid);
auto outline = image->outline;
float w, h;
pdata->viewbox(nullptr, nullptr, &w, &h);
if (w == 0 || h == 0) return false;
outline->reservedPtsCnt = 5;
outline->pts = static_cast<SwPoint*>(realloc(outline->pts, outline->reservedPtsCnt * sizeof(SwPoint)));
outline->types = static_cast<uint8_t*>(realloc(outline->types, outline->reservedPtsCnt * sizeof(uint8_t)));
outline->reservedCntrsCnt = 1;
outline->cntrs = static_cast<uint32_t*>(realloc(outline->cntrs, outline->reservedCntrsCnt * sizeof(uint32_t)));
Point to[4] = {{0 ,0}, {w, 0}, {w, h}, {0, h}};
for (int i = 0; i < 4; i++) {
outline->pts[outline->ptsCnt] = mathTransform(&to[i], transform);
outline->types[outline->ptsCnt] = SW_CURVE_TYPE_POINT;
++outline->ptsCnt;
}
outline->pts[outline->ptsCnt] = outline->pts[0];
outline->types[outline->ptsCnt] = SW_CURVE_TYPE_POINT;
++outline->ptsCnt;
outline->cntrs[outline->cntrsCnt] = outline->ptsCnt - 1;
++outline->cntrsCnt;
outline->opened = false;
image->outline = outline;
image->width = w;
image->height = h;
return true;
}
void imageFree(SwImage* image)
{
rleFree(image->rle);
}

View file

@ -22,6 +22,7 @@
#include "tvgSwCommon.h" #include "tvgSwCommon.h"
#include "tvgRender.h" #include "tvgRender.h"
#include <float.h> #include <float.h>
#include <math.h>
/************************************************************************/ /************************************************************************/
/* Internal Class Implementation */ /* Internal Class Implementation */
@ -45,6 +46,39 @@ static uint32_t _argbJoin(uint8_t r, uint8_t g, uint8_t b, uint8_t a)
} }
static void _inverse(const Matrix* transform, Matrix* invM)
{
// computes the inverse of a matrix m
auto det = transform->e11 * (transform->e22 * transform->e33 - transform->e32 * transform->e23) -
transform->e12 * (transform->e21 * transform->e33 - transform->e23 * transform->e31) +
transform->e13 * (transform->e21 * transform->e32 - transform->e22 * transform->e31);
auto invDet = 1 / det;
invM->e11 = (transform->e22 * transform->e33 - transform->e32 * transform->e23) * invDet;
invM->e12 = (transform->e13 * transform->e32 - transform->e12 * transform->e33) * invDet;
invM->e13 = (transform->e12 * transform->e23 - transform->e13 * transform->e22) * invDet;
invM->e21 = (transform->e23 * transform->e31 - transform->e21 * transform->e33) * invDet;
invM->e22 = (transform->e11 * transform->e33 - transform->e13 * transform->e31) * invDet;
invM->e23 = (transform->e21 * transform->e13 - transform->e11 * transform->e23) * invDet;
invM->e31 = (transform->e21 * transform->e32 - transform->e31 * transform->e22) * invDet;
invM->e32 = (transform->e31 * transform->e12 - transform->e11 * transform->e32) * invDet;
invM->e33 = (transform->e11 * transform->e22 - transform->e21 * transform->e12) * invDet;
}
static bool _identify(const Matrix* transform)
{
if (!transform ||
transform->e11 != 1.0f || transform->e12 != 0.0f || transform->e13 != 0.0f ||
transform->e21 != 0.0f || transform->e22 != 1.0f || transform->e23 != 0.0f ||
transform->e31 != 0.0f || transform->e32 != 0.0f || transform->e33 != 1.0f)
return false;
return true;
}
static SwBBox _clipRegion(Surface* surface, SwBBox& in) static SwBBox _clipRegion(Surface* surface, SwBBox& in)
{ {
auto bbox = in; auto bbox = in;
@ -108,6 +142,141 @@ static bool _rasterTranslucentRle(SwSurface* surface, SwRleData* rle, uint32_t c
} }
static bool _rasterTranslucentImageRle(SwSurface* surface, SwRleData* rle, uint32_t *img, uint32_t opacity, const Matrix* invTransform, uint32_t w, uint32_t h)
{
auto span = rle->spans;
for (uint32_t i = 0; i < rle->size; ++i) {
for (uint32_t x = 0; x < span->len; ++x) {
auto rX = static_cast<uint32_t>(roundf((span->x + x) * invTransform->e11 + span->y * invTransform->e12 + invTransform->e13));
auto rY = static_cast<uint32_t>(roundf((span->x + x) * invTransform->e21 + span->y * invTransform->e22 + invTransform->e23));
if (rX < 0 || rX >= w || rY < 0 || rY >= h) continue;
auto dst = &surface->buffer[span->y * surface->stride + span->x + x];
auto index = rY * w + rX; //TODO: need to use image's stride
if (dst && img && img[index]) {
auto alpha = ALPHA_MULTIPLY(span->coverage, opacity);
auto src = ALPHA_BLEND(img[index], alpha);
auto invAlpha = 255 - surface->comp.alpha(src);
*dst = src + ALPHA_BLEND(*dst, invAlpha);
}
}
++span;
}
return true;
}
static bool _rasterImageRle(SwSurface* surface, SwRleData* rle, uint32_t *img, const Matrix* invTransform, uint32_t w, uint32_t h)
{
if (!rle) return false;
auto span = rle->spans;
for (uint32_t i = 0; i < rle->size; ++i) {
for (uint32_t x = 0; x < span->len; ++x) {
auto rX = static_cast<uint32_t>(roundf((span->x + x) * invTransform->e11 + span->y * invTransform->e12 + invTransform->e13));
auto rY = static_cast<uint32_t>(roundf((span->x + x) * invTransform->e21 + span->y * invTransform->e22 + invTransform->e23));
if (rX < 0 || rX >= w || rY < 0 || rY >= h) continue;
auto dst = &surface->buffer[span->y * surface->stride + span->x + x];
auto index = rY * w + rX; //TODO: need to use image's stride
if (dst && img && img[index]) {
auto src = ALPHA_BLEND(img[index], span->coverage);
auto invAlpha = 255 - surface->comp.alpha(src);
*dst = src + ALPHA_BLEND(*dst, invAlpha);
}
}
++span;
}
return true;
}
static bool _rasterTranslucentImage(SwSurface* surface, uint32_t *img, uint32_t opacity,const SwBBox& region, const Matrix* invTransform, uint32_t w, uint32_t h)
{
for (auto y = region.min.y; y < region.max.y; y++) {
for (auto x = region.min.x; x < region.max.x; x++) {
auto rX = static_cast<uint32_t>(roundf(x * invTransform->e11 + y * invTransform->e12 + invTransform->e13));
auto rY = static_cast<uint32_t>(roundf(x * invTransform->e21 + y * invTransform->e22 + invTransform->e23));
if (rX < 0 || rX >= w || rY < 0 || rY >= h) continue;
auto dst = &surface->buffer[y * surface->stride + x];
auto index = rX + (rY * w); //TODO: need to use image's stride
if (dst && img && img[index]) {
auto src = ALPHA_BLEND(img[index], opacity);
auto invAlpha = 255 - surface->comp.alpha(src);
*dst = src + ALPHA_BLEND(*dst, invAlpha);
}
}
}
return true;
}
static bool _rasterImage(SwSurface* surface, uint32_t *img, const SwBBox& region, uint32_t w, uint32_t h)
{
for (auto y = region.min.y; y < region.max.y; y++) {
for (auto x = region.min.x; x < region.max.x; x++) {
auto dst = &surface->buffer[y * surface->stride + x];
auto index = x + (y * w); //TODO: need to use image's stride
if (dst && img && img[index]) {
auto src = img[index];
auto invAlpha = 255 - surface->comp.alpha(src);
*dst = src + ALPHA_BLEND(*dst, invAlpha);
}
}
}
return true;
}
static bool _rasterImage(SwSurface* surface, uint32_t *img, const SwBBox& region, const Matrix* invTransform, uint32_t w, uint32_t h)
{
for (auto y = region.min.y; y < region.max.y; y++) {
for (auto x = region.min.x; x < region.max.x; x++) {
auto rX = static_cast<uint32_t>(roundf(x * invTransform->e11 + y * invTransform->e12 + invTransform->e13));
auto rY = static_cast<uint32_t>(roundf(x * invTransform->e21 + y * invTransform->e22 + invTransform->e23));
if (rX < 0 || rX >= w || rY < 0 || rY >= h) continue;
auto dst = &surface->buffer[y * surface->stride + x];
auto index = rX + (rY * w); //TODO: need to use image's stride
if (dst && img && img[index]) {
auto src = img[index];
auto invAlpha = 255 - surface->comp.alpha(src);
*dst = src + ALPHA_BLEND(*dst, invAlpha);
}
}
}
return true;
}
bool rasterImage(SwSurface* surface, SwImage* image, uint8_t opacity, const Matrix* transform)
{
Matrix invTransform;
_inverse(transform, &invTransform);
if (image->rle) {
if (opacity < 255) return _rasterTranslucentImageRle(surface, image->rle, image->data, opacity, &invTransform, image->width, image->height );
return _rasterImageRle(surface, image->rle, image->data, &invTransform, image->width, image->height );
}
else {
// Fast track
if (_identify(transform)) {
return _rasterImage(surface, image->data, image->bbox, image->width, image->height);
}
else {
if (opacity < 255) return _rasterTranslucentImage(surface, image->data, opacity, image->bbox, &invTransform, image->width, image->height);
return _rasterImage(surface, image->data, image->bbox, &invTransform, image->width, image->height);
}
}
}
static bool _rasterSolidRle(SwSurface* surface, SwRleData* rle, uint32_t color) static bool _rasterSolidRle(SwSurface* surface, SwRleData* rle, uint32_t color)
{ {
if (!rle) return false; if (!rle) return false;

View file

@ -31,14 +31,21 @@ static uint32_t rendererCnt = 0;
struct SwTask : Task struct SwTask : Task
{ {
SwShape shape;
const Shape* sdata = nullptr;
Matrix* transform = nullptr; Matrix* transform = nullptr;
SwSurface* surface = nullptr; SwSurface* surface = nullptr;
RenderUpdateFlag flags = RenderUpdateFlag::None; RenderUpdateFlag flags = RenderUpdateFlag::None;
vector<Composite> compList; vector<Composite> compList;
uint32_t opacity; uint32_t opacity;
virtual bool dispose() = 0;
};
struct SwShapeTask : SwTask
{
SwShape shape;
const Shape* sdata = nullptr;
void run(unsigned tid) override void run(unsigned tid) override
{ {
if (opacity == 0) return; //Invisible if (opacity == 0) return; //Invisible
@ -52,7 +59,7 @@ struct SwTask : Task
SwSize clip = {static_cast<SwCoord>(surface->w), static_cast<SwCoord>(surface->h)}; SwSize clip = {static_cast<SwCoord>(surface->w), static_cast<SwCoord>(surface->h)};
//Invisiable shape turned to visible by alpha. //invisible shape turned to visible by alpha.
auto prepareShape = false; auto prepareShape = false;
if (!shapePrepared(&shape) && ((flags & RenderUpdateFlag::Color) || (opacity > 0))) prepareShape = true; if (!shapePrepared(&shape) && ((flags & RenderUpdateFlag::Color) || (opacity > 0))) prepareShape = true;
@ -98,7 +105,7 @@ struct SwTask : Task
//Composition //Composition
for (auto comp : compList) { for (auto comp : compList) {
SwShape *compShape = &static_cast<SwTask*>(comp.edata)->shape; SwShape *compShape = &static_cast<SwShapeTask*>(comp.edata)->shape;
if (comp.method == CompositeMethod::ClipPath) { if (comp.method == CompositeMethod::ClipPath) {
//Clip to fill(path) rle //Clip to fill(path) rle
if (shape.rle && compShape->rect) rleClipRect(shape.rle, &compShape->bbox); if (shape.rle && compShape->rect) rleClipRect(shape.rle, &compShape->bbox);
@ -112,8 +119,61 @@ struct SwTask : Task
end: end:
shapeDelOutline(&shape, tid); shapeDelOutline(&shape, tid);
} }
bool dispose() override
{
shapeFree(&shape);
return true;
}
}; };
struct SwImageTask : SwTask
{
SwImage image;
const Picture* pdata = nullptr;
uint32_t *pixels = nullptr;
void run(unsigned tid) override
{
SwSize clip = {static_cast<SwCoord>(surface->w), static_cast<SwCoord>(surface->h)};
//Invisiable shape turned to visible by alpha.
auto prepareImage = false;
if (!imagePrepared(&image) && ((flags & RenderUpdateFlag::Image) || (opacity > 0))) prepareImage = true;
if (prepareImage) {
imageReset(&image);
if (!imagePrepare(&image, pdata, tid, clip, transform)) goto end;
if (compList.size() > 0) {
if (!imageGenRle(&image, pdata, clip, false, true)) goto end;
//Composition
for (auto comp : compList) {
SwShape *compShape = &static_cast<SwShapeTask*>(comp.edata)->shape;
if (comp.method == CompositeMethod::ClipPath) {
//Clip to fill(path) rle
if (image.rle && compShape->rect) rleClipRect(image.rle, &compShape->bbox);
else if (image.rle && compShape->rle) rleClipPath(image.rle, compShape->rle);
}
}
}
}
if (this->pixels) image.data = this->pixels;
end:
imageDelOutline(&image, tid);
}
bool dispose() override
{
imageFree(&image);
return true;
}
};
static void _termEngine() static void _termEngine()
{ {
if (rendererCnt > 0) return; if (rendererCnt > 0) return;
@ -178,9 +238,17 @@ bool SwRenderer::postRender()
} }
bool SwRenderer::render(const Shape& shape, void *data) bool SwRenderer::render(TVG_UNUSED const Picture& picture, void *data)
{ {
auto task = static_cast<SwTask*>(data); auto task = static_cast<SwImageTask*>(data);
task->done();
return rasterImage(surface, &task->image, task->opacity, task->transform);
}
bool SwRenderer::render(TVG_UNUSED const Shape& shape, void *data)
{
auto task = static_cast<SwShapeTask*>(data);
task->done(); task->done();
uint8_t r, g, b, a; uint8_t r, g, b, a;
@ -200,13 +268,13 @@ bool SwRenderer::render(const Shape& shape, void *data)
} }
bool SwRenderer::dispose(TVG_UNUSED const Shape& sdata, void *data) bool SwRenderer::dispose(void *data)
{ {
auto task = static_cast<SwTask*>(data); auto task = static_cast<SwTask*>(data);
if (!task) return true; if (!task) return true;
task->done(); task->done();
shapeFree(&task->shape); task->dispose();
if (task->transform) free(task->transform); if (task->transform) free(task->transform);
delete(task); delete(task);
@ -214,25 +282,11 @@ bool SwRenderer::dispose(TVG_UNUSED const Shape& sdata, void *data)
} }
void* SwRenderer::prepare(const Shape& sdata, void* data, const RenderTransform* transform, uint32_t opacity, vector<Composite>& compList, RenderUpdateFlag flags) void SwRenderer::prepareCommon(SwTask* task, const RenderTransform* transform, uint32_t opacity, vector<Composite>& compList, RenderUpdateFlag flags)
{ {
//prepare task
auto task = static_cast<SwTask*>(data);
if (!task) {
task = new SwTask;
if (!task) return nullptr;
}
if (flags == RenderUpdateFlag::None) return task;
//Finish previous task if it has duplicated request.
task->done();
task->sdata = &sdata;
if (compList.size() > 0) { if (compList.size() > 0) {
//Guarantee composition targets get ready. //Guarantee composition targets get ready.
for (auto comp : compList) static_cast<SwTask*>(comp.edata)->done(); for (auto comp : compList) static_cast<SwShapeTask*>(comp.edata)->done();
task->compList.assign(compList.begin(), compList.end()); task->compList.assign(compList.begin(), compList.end());
} }
@ -250,6 +304,48 @@ void* SwRenderer::prepare(const Shape& sdata, void* data, const RenderTransform*
tasks.push_back(task); tasks.push_back(task);
TaskScheduler::request(task); TaskScheduler::request(task);
}
void* SwRenderer::prepare(const Picture& pdata, void* data, uint32_t *pixels, const RenderTransform* transform, uint32_t opacity, vector<Composite>& compList, RenderUpdateFlag flags)
{
//prepare task
auto task = static_cast<SwImageTask*>(data);
if (!task) {
task = new SwImageTask;
if (!task) return nullptr;
}
if (flags == RenderUpdateFlag::None) return task;
//Finish previous task if it has duplicated request.
task->done();
task->pdata = &pdata;
task->pixels = pixels;
prepareCommon(task, transform, opacity, compList, flags);
return task;
}
void* SwRenderer::prepare(const Shape& sdata, void* data, const RenderTransform* transform, uint32_t opacity, vector<Composite>& compList, RenderUpdateFlag flags)
{
//prepare task
auto task = static_cast<SwShapeTask*>(data);
if (!task) {
task = new SwShapeTask;
if (!task) return nullptr;
}
if (flags == RenderUpdateFlag::None) return task;
//Finish previous task if it has duplicated request.
task->done();
task->sdata = &sdata;
prepareCommon(task, transform, opacity, compList, flags);
return task; return task;
} }

View file

@ -35,12 +35,14 @@ class SwRenderer : public RenderMethod
{ {
public: public:
void* prepare(const Shape& shape, void* data, const RenderTransform* transform, uint32_t opacity, vector<Composite>& compList, RenderUpdateFlag flags) override; void* prepare(const Shape& shape, void* data, const RenderTransform* transform, uint32_t opacity, vector<Composite>& compList, RenderUpdateFlag flags) override;
bool dispose(const Shape& shape, void *data) override; void* prepare(const Picture& picture, void* data, uint32_t *buffer, const RenderTransform* transform, uint32_t opacity, vector<Composite>& compList, RenderUpdateFlag flags) override;
bool dispose(void *data) override;
bool preRender() override; bool preRender() override;
bool postRender() override; bool postRender() override;
bool target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h, uint32_t cs); bool target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h, uint32_t cs);
bool clear() override; bool clear() override;
bool render(const Shape& shape, void *data) override; bool render(const Shape& shape, void *data) override;
bool render(const Picture& picture, void *data) override;
static SwRenderer* gen(); static SwRenderer* gen();
static bool init(uint32_t threads); static bool init(uint32_t threads);
@ -52,6 +54,8 @@ private:
SwRenderer(){}; SwRenderer(){};
~SwRenderer(); ~SwRenderer();
void prepareCommon(SwTask* task, const RenderTransform* transform, uint32_t opacity, vector<Composite>& compList, RenderUpdateFlag flags);
}; };
} }

View file

@ -19,7 +19,6 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. * SOFTWARE.
*/ */
#include <math.h>
#include "tvgSwCommon.h" #include "tvgSwCommon.h"
#include "tvgBezier.h" #include "tvgBezier.h"
@ -34,17 +33,6 @@ struct Line
}; };
static SwPoint _transform(const Point* to, const Matrix* transform)
{
if (!transform) return {TO_SWCOORD(to->x), TO_SWCOORD(to->y)};
auto tx = round(to->x * transform->e11 + to->y * transform->e12 + transform->e13);
auto ty = round(to->x * transform->e21 + to->y * transform->e22 + transform->e23);
return {TO_SWCOORD(tx), TO_SWCOORD(ty)};
}
static float _lineLength(const Point& pt1, const Point& pt2) static float _lineLength(const Point& pt1, const Point& pt2)
{ {
/* approximate sqrt(x*x + y*y) using alpha max plus beta min algorithm. /* approximate sqrt(x*x + y*y) using alpha max plus beta min algorithm.
@ -101,7 +89,7 @@ static void _outlineMoveTo(SwOutline& outline, const Point* to, const Matrix* tr
{ {
_growOutlinePoint(outline, 1); _growOutlinePoint(outline, 1);
outline.pts[outline.ptsCnt] = _transform(to, transform); outline.pts[outline.ptsCnt] = mathTransform(to, transform);
outline.types[outline.ptsCnt] = SW_CURVE_TYPE_POINT; outline.types[outline.ptsCnt] = SW_CURVE_TYPE_POINT;
if (outline.ptsCnt > 0) { if (outline.ptsCnt > 0) {
@ -118,7 +106,7 @@ static void _outlineLineTo(SwOutline& outline, const Point* to, const Matrix* tr
{ {
_growOutlinePoint(outline, 1); _growOutlinePoint(outline, 1);
outline.pts[outline.ptsCnt] = _transform(to, transform); outline.pts[outline.ptsCnt] = mathTransform(to, transform);
outline.types[outline.ptsCnt] = SW_CURVE_TYPE_POINT; outline.types[outline.ptsCnt] = SW_CURVE_TYPE_POINT;
++outline.ptsCnt; ++outline.ptsCnt;
} }
@ -128,15 +116,15 @@ static void _outlineCubicTo(SwOutline& outline, const Point* ctrl1, const Point*
{ {
_growOutlinePoint(outline, 3); _growOutlinePoint(outline, 3);
outline.pts[outline.ptsCnt] = _transform(ctrl1, transform); outline.pts[outline.ptsCnt] = mathTransform(ctrl1, transform);
outline.types[outline.ptsCnt] = SW_CURVE_TYPE_CUBIC; outline.types[outline.ptsCnt] = SW_CURVE_TYPE_CUBIC;
++outline.ptsCnt; ++outline.ptsCnt;
outline.pts[outline.ptsCnt] = _transform(ctrl2, transform); outline.pts[outline.ptsCnt] = mathTransform(ctrl2, transform);
outline.types[outline.ptsCnt] = SW_CURVE_TYPE_CUBIC; outline.types[outline.ptsCnt] = SW_CURVE_TYPE_CUBIC;
++outline.ptsCnt; ++outline.ptsCnt;
outline.pts[outline.ptsCnt] = _transform(to, transform); outline.pts[outline.ptsCnt] = mathTransform(to, transform);
outline.types[outline.ptsCnt] = SW_CURVE_TYPE_POINT; outline.types[outline.ptsCnt] = SW_CURVE_TYPE_POINT;
++outline.ptsCnt; ++outline.ptsCnt;
} }

View file

@ -38,11 +38,13 @@ public:
virtual ~Loader() {} virtual ~Loader() {}
virtual bool open(const char* path) = 0; virtual bool open(const string& path) { /* Not supported */ return false; };
virtual bool open(const char* data, uint32_t size) = 0; virtual bool open(const char* data, uint32_t size) { /* Not supported */ return false; };
virtual bool open(const uint32_t* data, uint32_t w, uint32_t h, bool copy) { /* Not supported */ return false; };
virtual bool read() = 0; virtual bool read() = 0;
virtual bool close() = 0; virtual bool close() = 0;
virtual unique_ptr<Scene> data() = 0; virtual const uint32_t* pixels() { return nullptr; };
virtual unique_ptr<Scene> scene() { return nullptr; };
}; };
} }

View file

@ -24,6 +24,7 @@
#ifdef THORVG_SVG_LOADER_SUPPORT #ifdef THORVG_SVG_LOADER_SUPPORT
#include "tvgSvgLoader.h" #include "tvgSvgLoader.h"
#endif #endif
#include "tvgRawLoader.h"
/************************************************************************/ /************************************************************************/
/* Internal Class Implementation */ /* Internal Class Implementation */
@ -41,6 +42,10 @@ static Loader* _find(FileType type)
#endif #endif
break; break;
} }
case FileType::Raw: {
return new RawLoader;
break;
}
default: { default: {
break; break;
} }
@ -88,7 +93,7 @@ unique_ptr<Loader> LoaderMgr::loader(const string& path)
{ {
auto loader = _find(path); auto loader = _find(path);
if (loader && loader->open(path.c_str())) return unique_ptr<Loader>(loader); if (loader && loader->open(path)) return unique_ptr<Loader>(loader);
return nullptr; return nullptr;
} }
@ -102,3 +107,13 @@ unique_ptr<Loader> LoaderMgr::loader(const char* data, uint32_t size)
} }
return nullptr; return nullptr;
} }
unique_ptr<Loader> LoaderMgr::loader(uint32_t *data, uint32_t w, uint32_t h, bool copy)
{
for (int i = 0; i < static_cast<int>(FileType::Unknown); i++) {
auto loader = _find(static_cast<FileType>(i));
if (loader && loader->open(data, w, h, copy)) return unique_ptr<Loader>(loader);
}
return nullptr;
}

View file

@ -24,14 +24,15 @@
#include "tvgLoader.h" #include "tvgLoader.h"
enum class FileType { Svg = 0, Unknown}; enum class FileType { Svg = 0, Raw, Unknown };
struct LoaderMgr struct LoaderMgr
{ {
static bool init(); static bool init();
static bool term(); static bool term();
static unique_ptr<Loader> loader(const char* data, uint32_t size);
static unique_ptr<Loader> loader(const string& path); static unique_ptr<Loader> loader(const string& path);
static unique_ptr<Loader> loader(const char* data, uint32_t size);
static unique_ptr<Loader> loader(uint32_t* data, uint32_t w, uint32_t h, bool copy);
}; };
#endif //_TVG_LOADER_MGR_H_ #endif //_TVG_LOADER_MGR_H_

View file

@ -26,7 +26,7 @@
/* External Class Implementation */ /* External Class Implementation */
/************************************************************************/ /************************************************************************/
Picture::Picture() : pImpl(new Impl()) Picture::Picture() : pImpl(new Impl(this))
{ {
Paint::pImpl->method(new PaintMethod<Picture::Impl>(pImpl)); Paint::pImpl->method(new PaintMethod<Picture::Impl>(pImpl));
} }
@ -60,6 +60,14 @@ Result Picture::load(const char* data, uint32_t size) noexcept
} }
Result Picture::load(uint32_t* data, uint32_t w, uint32_t h, bool copy) noexcept
{
if (!data || w <= 0 || h <= 0) return Result::InvalidArguments;
return pImpl->load(data, w, h, copy);
}
Result Picture::viewbox(float* x, float* y, float* w, float* h) const noexcept Result Picture::viewbox(float* x, float* y, float* w, float* h) const noexcept
{ {
if (pImpl->viewbox(x, y, w, h)) return Result::Success; if (pImpl->viewbox(x, y, w, h)) return Result::Success;

View file

@ -34,43 +34,61 @@ struct Picture::Impl
{ {
unique_ptr<Loader> loader = nullptr; unique_ptr<Loader> loader = nullptr;
Paint* paint = nullptr; Paint* paint = nullptr;
uint32_t *pixels = nullptr;
Picture *picture = nullptr;
void *edata = nullptr; //engine data
Impl(Picture* p) : picture(p)
{
}
bool dispose(RenderMethod& renderer) bool dispose(RenderMethod& renderer)
{ {
if (!paint) return false; if (paint) {
paint->pImpl->dispose(renderer);
delete(paint);
paint->pImpl->dispose(renderer); return true;
delete(paint); }
else if (pixels) {
return true; return renderer.dispose(edata);
}
return false;
} }
void reload() uint32_t reload()
{ {
if (loader && !paint) { if (loader) {
auto scene = loader->data(); if (!paint) {
if (scene) { auto scene = loader->scene();
paint = scene.release(); if (scene) {
if (!paint) return; paint = scene.release();
loader->close(); loader->close();
if (paint) return RenderUpdateFlag::None;
}
}
if (!pixels) {
pixels = (uint32_t*)loader->pixels();
if (pixels) return RenderUpdateFlag::Image;
} }
} }
return RenderUpdateFlag::None;
} }
void* update(RenderMethod &renderer, const RenderTransform* transform, uint32_t opacity, vector<Composite>& compList, RenderUpdateFlag pFlag)
void* update(RenderMethod &renderer, const RenderTransform* transform, uint32_t opacity, vector<Composite>& compList, RenderUpdateFlag flag)
{ {
reload(); uint32_t flag = reload();
if (!paint) return nullptr; if (pixels) edata = renderer.prepare(*picture, edata, pixels, transform, opacity, compList, static_cast<RenderUpdateFlag>(pFlag | flag));
else if (paint) edata = paint->pImpl->update(renderer, transform, opacity, compList, static_cast<RenderUpdateFlag>(pFlag | flag));
return paint->pImpl->update(renderer, transform, opacity, compList, flag); return edata;
} }
bool render(RenderMethod &renderer) bool render(RenderMethod &renderer)
{ {
if (!paint) return false; if (pixels) return renderer.render(*picture, edata);
return paint->pImpl->render(renderer); else if (paint) return paint->pImpl->render(renderer);
return false;
} }
bool viewbox(float* x, float* y, float* w, float* h) bool viewbox(float* x, float* y, float* w, float* h)
@ -107,6 +125,14 @@ struct Picture::Impl
return Result::Success; return Result::Success;
} }
Result load(uint32_t* data, uint32_t w, uint32_t h, bool copy)
{
if (loader) loader->close();
loader = LoaderMgr::loader(data, w, h, copy);
if (!loader) return Result::NonSupport;
return Result::Success;
}
Paint* duplicate() Paint* duplicate()
{ {
reload(); reload();

View file

@ -42,7 +42,7 @@ struct Composite {
CompositeMethod method; CompositeMethod method;
}; };
enum RenderUpdateFlag {None = 0, Path = 1, Color = 2, Gradient = 4, Stroke = 8, Transform = 16, All = 32}; enum RenderUpdateFlag {None = 0, Path = 1, Color = 2, Gradient = 4, Stroke = 8, Transform = 16, Image = 32, All = 64};
struct RenderTransform struct RenderTransform
{ {
@ -66,9 +66,11 @@ class RenderMethod
public: public:
virtual ~RenderMethod() {} virtual ~RenderMethod() {}
virtual void* prepare(TVG_UNUSED const Shape& shape, TVG_UNUSED void* data, TVG_UNUSED const RenderTransform* transform, uint32_t opacity, TVG_UNUSED vector<Composite>& compList, TVG_UNUSED RenderUpdateFlag flags) { return nullptr; } virtual void* prepare(TVG_UNUSED const Shape& shape, TVG_UNUSED void* data, TVG_UNUSED const RenderTransform* transform, uint32_t opacity, TVG_UNUSED vector<Composite>& compList, TVG_UNUSED RenderUpdateFlag flags) { return nullptr; }
virtual bool dispose(TVG_UNUSED const Shape& shape, TVG_UNUSED void *data) { return true; } virtual void* prepare(TVG_UNUSED const Picture& picture, TVG_UNUSED void* data, TVG_UNUSED uint32_t *buffer, TVG_UNUSED const RenderTransform* transform, TVG_UNUSED uint32_t opacity, TVG_UNUSED vector<Composite>& compList, TVG_UNUSED RenderUpdateFlag flags) { return nullptr; }
virtual bool dispose(TVG_UNUSED void *data) { return true; }
virtual bool preRender() { return true; } virtual bool preRender() { return true; }
virtual bool render(TVG_UNUSED const Shape& shape, TVG_UNUSED void *data) { return true; } virtual bool render(TVG_UNUSED const Shape& shape, TVG_UNUSED void *data) { return true; }
virtual bool render(TVG_UNUSED const Picture& picture, TVG_UNUSED void *data) { return true; }
virtual bool postRender() { return true; } virtual bool postRender() { return true; }
virtual bool clear() { return true; } virtual bool clear() { return true; }
virtual bool sync() { return true; } virtual bool sync() { return true; }

View file

@ -215,7 +215,7 @@ struct Shape::Impl
bool dispose(RenderMethod& renderer) bool dispose(RenderMethod& renderer)
{ {
return renderer.dispose(*shape, edata); return renderer.dispose(edata);
} }
bool render(RenderMethod& renderer) bool render(RenderMethod& renderer)

View file

@ -5,6 +5,8 @@ if get_option('loaders').contains('svg') == true
message('Enable SVG Loader') message('Enable SVG Loader')
endif endif
subdir('raw')
loader_dep = declare_dependency( loader_dep = declare_dependency(
dependencies: subloader_dep, dependencies: subloader_dep,
include_directories : include_directories('.'), include_directories : include_directories('.'),

View file

@ -0,0 +1,9 @@
source_file = [
'tvgRawLoader.h',
'tvgRawLoader.cpp',
]
subloader_dep += [declare_dependency(
include_directories : include_directories('.'),
sources : source_file
)]

View file

@ -0,0 +1,84 @@
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include <fstream>
#include <string.h>
#include "tvgLoaderMgr.h"
#include "tvgRawLoader.h"
/************************************************************************/
/* Internal Class Implementation */
/************************************************************************/
/************************************************************************/
/* External Class Implementation */
/************************************************************************/
RawLoader::RawLoader()
{
}
RawLoader::~RawLoader()
{
if (copy && content) {
free((void*)content);
content = nullptr;
}
}
bool RawLoader::open(const uint32_t* data, uint32_t w, uint32_t h, bool copy)
{
if (!data || w == 0 || h == 0) return false;
vw = w;
vh = h;
this->copy = copy;
if (copy) {
content = (uint32_t*)malloc(sizeof(uint32_t) * vw * vh);
if (!content) return false;
memcpy((void*)content, data, sizeof(uint32_t) * vw * vh);
}
else content = data;
return true;
}
bool RawLoader::read()
{
return true;
}
bool RawLoader::close()
{
return true;
}
const uint32_t* RawLoader::pixels()
{
return this->content;
}

View file

@ -0,0 +1,43 @@
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef _TVG_RAW_LOADER_H_
#define _TVG_RAW_LOADER_H_
class RawLoader : public Loader
{
public:
const uint32_t* content = nullptr;
bool copy;
RawLoader();
~RawLoader();
using Loader::open;
bool open(const uint32_t* data, uint32_t w, uint32_t h, bool copy) override;
bool read() override;
bool close() override;
const uint32_t* pixels() override;
};
#endif //_TVG_RAW_LOADER_H_

View file

@ -2483,7 +2483,7 @@ bool SvgLoader::open(const char* data, uint32_t size)
} }
bool SvgLoader::open(const char* path) bool SvgLoader::open(const string& path)
{ {
ifstream f; ifstream f;
f.open(path); f.open(path);
@ -2539,9 +2539,10 @@ bool SvgLoader::close()
} }
unique_ptr<Scene> SvgLoader::data() unique_ptr<Scene> SvgLoader::scene()
{ {
this->done(); this->done();
if (root) return move(root); if (root) return move(root);
else return nullptr; else return nullptr;
} }

View file

@ -39,14 +39,16 @@ public:
SvgLoader(); SvgLoader();
~SvgLoader(); ~SvgLoader();
bool open(const char* path) override; using Loader::open;
bool open(const string& path) override;
bool open(const char* data, uint32_t size) override; bool open(const char* data, uint32_t size) override;
bool header(); bool header();
bool read() override; bool read() override;
bool close() override; bool close() override;
void run(unsigned tid) override; void run(unsigned tid) override;
unique_ptr<Scene> data() override; unique_ptr<Scene> scene() override;
}; };