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;
|
@ -279,6 +279,7 @@ public:
|
|||
|
||||
Result load(const std::string& path) 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;
|
||||
|
||||
static std::unique_ptr<Picture> gen() noexcept;
|
||||
|
|
|
@ -6,7 +6,7 @@ project('thorvg',
|
|||
|
||||
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
|
||||
config_h.set10('THORVG_SW_RASTER_SUPPORT', true)
|
||||
|
|
157
src/examples/PixelImage.cpp
Normal 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;
|
||||
}
|
Before Width: | Height: | Size: 807 B After Width: | Height: | Size: 807 B |
Before Width: | Height: | Size: 1 KiB After Width: | Height: | Size: 1 KiB |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 794 B After Width: | Height: | Size: 794 B |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 919 B After Width: | Height: | Size: 919 B |
Before Width: | Height: | Size: 1 KiB After Width: | Height: | Size: 1 KiB |
Before Width: | Height: | Size: 330 B After Width: | Height: | Size: 330 B |
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 4.4 KiB |
Before Width: | Height: | Size: 514 B After Width: | Height: | Size: 514 B |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 501 B After Width: | Height: | Size: 501 B |
110
src/examples/images/rawimage_200x300.raw
Normal file
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 84 KiB After Width: | Height: | Size: 84 KiB |
Before Width: | Height: | Size: 633 B After Width: | Height: | Size: 633 B |
Before Width: | Height: | Size: 282 B After Width: | Height: | Size: 282 B |
|
@ -17,6 +17,7 @@ source_file = [
|
|||
'Opacity.cpp',
|
||||
'PathCopy.cpp',
|
||||
'Path.cpp',
|
||||
'PixelImage.cpp',
|
||||
'RadialGradient.cpp',
|
||||
'Scene.cpp',
|
||||
'SceneTransform.cpp',
|
||||
|
|
|
@ -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);
|
||||
if (!sdata) return false;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
source_file = [
|
||||
'tvgSwCommon.h',
|
||||
'tvgSwFill.cpp',
|
||||
'tvgSwImage.cpp',
|
||||
'tvgSwMath.cpp',
|
||||
'tvgSwRenderer.h',
|
||||
'tvgSwRaster.cpp',
|
||||
|
|
|
@ -212,6 +212,16 @@ struct SwShape
|
|||
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
|
||||
{
|
||||
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);
|
||||
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);
|
||||
void fillReset(SwFill* fill);
|
||||
void fillFree(SwFill* fill);
|
||||
|
@ -307,6 +325,7 @@ void mpoolRetStrokeOutline(unsigned idx);
|
|||
bool rasterCompositor(SwSurface* surface);
|
||||
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 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 rasterClear(SwSurface* surface);
|
||||
|
||||
|
@ -335,4 +354,14 @@ static inline void rasterRGBA32(uint32_t *dst, uint32_t val, uint32_t offset, in
|
|||
#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_ */
|
||||
|
|
175
src/lib/sw_engine/tvgSwImage.cpp
Normal 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);
|
||||
}
|
|
@ -22,6 +22,7 @@
|
|||
#include "tvgSwCommon.h"
|
||||
#include "tvgRender.h"
|
||||
#include <float.h>
|
||||
#include <math.h>
|
||||
|
||||
/************************************************************************/
|
||||
/* 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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
if (!rle) return false;
|
||||
|
@ -368,4 +537,4 @@ bool rasterClear(SwSurface* surface)
|
|||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,14 +31,21 @@ static uint32_t rendererCnt = 0;
|
|||
|
||||
struct SwTask : Task
|
||||
{
|
||||
SwShape shape;
|
||||
const Shape* sdata = nullptr;
|
||||
Matrix* transform = nullptr;
|
||||
SwSurface* surface = nullptr;
|
||||
RenderUpdateFlag flags = RenderUpdateFlag::None;
|
||||
vector<Composite> compList;
|
||||
uint32_t opacity;
|
||||
|
||||
virtual bool dispose() = 0;
|
||||
};
|
||||
|
||||
|
||||
struct SwShapeTask : SwTask
|
||||
{
|
||||
SwShape shape;
|
||||
const Shape* sdata = nullptr;
|
||||
|
||||
void run(unsigned tid) override
|
||||
{
|
||||
if (opacity == 0) return; //Invisible
|
||||
|
@ -52,7 +59,7 @@ struct SwTask : Task
|
|||
|
||||
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;
|
||||
if (!shapePrepared(&shape) && ((flags & RenderUpdateFlag::Color) || (opacity > 0))) prepareShape = true;
|
||||
|
||||
|
@ -98,7 +105,7 @@ struct SwTask : Task
|
|||
|
||||
//Composition
|
||||
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) {
|
||||
//Clip to fill(path) rle
|
||||
if (shape.rle && compShape->rect) rleClipRect(shape.rle, &compShape->bbox);
|
||||
|
@ -112,8 +119,61 @@ struct SwTask : Task
|
|||
end:
|
||||
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()
|
||||
{
|
||||
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();
|
||||
|
||||
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);
|
||||
if (!task) return true;
|
||||
|
||||
task->done();
|
||||
shapeFree(&task->shape);
|
||||
task->dispose();
|
||||
if (task->transform) free(task->transform);
|
||||
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) {
|
||||
//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());
|
||||
}
|
||||
|
||||
|
@ -250,6 +304,48 @@ void* SwRenderer::prepare(const Shape& sdata, void* data, const RenderTransform*
|
|||
|
||||
tasks.push_back(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;
|
||||
}
|
||||
|
@ -283,4 +379,4 @@ SwRenderer* SwRenderer::gen()
|
|||
{
|
||||
++rendererCnt;
|
||||
return new SwRenderer();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,12 +35,14 @@ class SwRenderer : public RenderMethod
|
|||
{
|
||||
public:
|
||||
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 postRender() override;
|
||||
bool target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h, uint32_t cs);
|
||||
bool clear() override;
|
||||
bool render(const Shape& shape, void *data) override;
|
||||
bool render(const Picture& picture, void *data) override;
|
||||
|
||||
static SwRenderer* gen();
|
||||
static bool init(uint32_t threads);
|
||||
|
@ -52,6 +54,8 @@ private:
|
|||
|
||||
SwRenderer(){};
|
||||
~SwRenderer();
|
||||
|
||||
void prepareCommon(SwTask* task, const RenderTransform* transform, uint32_t opacity, vector<Composite>& compList, RenderUpdateFlag flags);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
#include <math.h>
|
||||
#include "tvgSwCommon.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)
|
||||
{
|
||||
/* 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);
|
||||
|
||||
outline.pts[outline.ptsCnt] = _transform(to, transform);
|
||||
outline.pts[outline.ptsCnt] = mathTransform(to, transform);
|
||||
outline.types[outline.ptsCnt] = SW_CURVE_TYPE_POINT;
|
||||
|
||||
if (outline.ptsCnt > 0) {
|
||||
|
@ -118,7 +106,7 @@ static void _outlineLineTo(SwOutline& outline, const Point* to, const Matrix* tr
|
|||
{
|
||||
_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.ptsCnt;
|
||||
}
|
||||
|
@ -128,15 +116,15 @@ static void _outlineCubicTo(SwOutline& outline, const Point* ctrl1, const Point*
|
|||
{
|
||||
_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.ptsCnt;
|
||||
|
||||
outline.pts[outline.ptsCnt] = _transform(ctrl2, transform);
|
||||
outline.pts[outline.ptsCnt] = mathTransform(ctrl2, transform);
|
||||
outline.types[outline.ptsCnt] = SW_CURVE_TYPE_CUBIC;
|
||||
++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.ptsCnt;
|
||||
}
|
||||
|
|
|
@ -38,13 +38,15 @@ public:
|
|||
|
||||
virtual ~Loader() {}
|
||||
|
||||
virtual bool open(const char* path) = 0;
|
||||
virtual bool open(const char* data, uint32_t size) = 0;
|
||||
virtual bool open(const string& path) { /* Not supported */ return false; };
|
||||
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 close() = 0;
|
||||
virtual unique_ptr<Scene> data() = 0;
|
||||
virtual const uint32_t* pixels() { return nullptr; };
|
||||
virtual unique_ptr<Scene> scene() { return nullptr; };
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif //_TVG_LOADER_H_
|
||||
#endif //_TVG_LOADER_H_
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#ifdef THORVG_SVG_LOADER_SUPPORT
|
||||
#include "tvgSvgLoader.h"
|
||||
#endif
|
||||
#include "tvgRawLoader.h"
|
||||
|
||||
/************************************************************************/
|
||||
/* Internal Class Implementation */
|
||||
|
@ -41,6 +42,10 @@ static Loader* _find(FileType type)
|
|||
#endif
|
||||
break;
|
||||
}
|
||||
case FileType::Raw: {
|
||||
return new RawLoader;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
|
@ -88,7 +93,7 @@ unique_ptr<Loader> LoaderMgr::loader(const string& 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;
|
||||
}
|
||||
|
@ -102,3 +107,13 @@ unique_ptr<Loader> LoaderMgr::loader(const char* data, uint32_t size)
|
|||
}
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -24,14 +24,15 @@
|
|||
|
||||
#include "tvgLoader.h"
|
||||
|
||||
enum class FileType { Svg = 0, Unknown};
|
||||
enum class FileType { Svg = 0, Raw, Unknown };
|
||||
|
||||
struct LoaderMgr
|
||||
{
|
||||
static bool init();
|
||||
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 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_
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
/* External Class Implementation */
|
||||
/************************************************************************/
|
||||
|
||||
Picture::Picture() : pImpl(new Impl())
|
||||
Picture::Picture() : pImpl(new Impl(this))
|
||||
{
|
||||
Paint::pImpl->method(new PaintMethod<Picture::Impl>(pImpl));
|
||||
}
|
||||
|
@ -60,8 +60,16 @@ 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
|
||||
{
|
||||
if (pImpl->viewbox(x, y, w, h)) return Result::Success;
|
||||
return Result::InsufficientCondition;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,43 +34,61 @@ struct Picture::Impl
|
|||
{
|
||||
unique_ptr<Loader> loader = 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)
|
||||
{
|
||||
if (!paint) return false;
|
||||
if (paint) {
|
||||
paint->pImpl->dispose(renderer);
|
||||
delete(paint);
|
||||
|
||||
paint->pImpl->dispose(renderer);
|
||||
delete(paint);
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
else if (pixels) {
|
||||
return renderer.dispose(edata);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void reload()
|
||||
uint32_t reload()
|
||||
{
|
||||
if (loader && !paint) {
|
||||
auto scene = loader->data();
|
||||
if (scene) {
|
||||
paint = scene.release();
|
||||
if (!paint) return;
|
||||
loader->close();
|
||||
if (loader) {
|
||||
if (!paint) {
|
||||
auto scene = loader->scene();
|
||||
if (scene) {
|
||||
paint = scene.release();
|
||||
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 flag)
|
||||
void* update(RenderMethod &renderer, const RenderTransform* transform, uint32_t opacity, vector<Composite>& compList, RenderUpdateFlag pFlag)
|
||||
{
|
||||
reload();
|
||||
uint32_t flag = reload();
|
||||
|
||||
if (!paint) return nullptr;
|
||||
|
||||
return paint->pImpl->update(renderer, transform, opacity, compList, flag);
|
||||
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 edata;
|
||||
}
|
||||
|
||||
bool render(RenderMethod &renderer)
|
||||
{
|
||||
if (!paint) return false;
|
||||
return paint->pImpl->render(renderer);
|
||||
if (pixels) return renderer.render(*picture, edata);
|
||||
else if (paint) return paint->pImpl->render(renderer);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool viewbox(float* x, float* y, float* w, float* h)
|
||||
|
@ -107,6 +125,14 @@ struct Picture::Impl
|
|||
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()
|
||||
{
|
||||
reload();
|
||||
|
|
|
@ -42,7 +42,7 @@ struct Composite {
|
|||
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
|
||||
{
|
||||
|
@ -66,9 +66,11 @@ class RenderMethod
|
|||
public:
|
||||
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 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 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 clear() { return true; }
|
||||
virtual bool sync() { return true; }
|
||||
|
|
|
@ -215,7 +215,7 @@ struct Shape::Impl
|
|||
|
||||
bool dispose(RenderMethod& renderer)
|
||||
{
|
||||
return renderer.dispose(*shape, edata);
|
||||
return renderer.dispose(edata);
|
||||
}
|
||||
|
||||
bool render(RenderMethod& renderer)
|
||||
|
|
|
@ -5,6 +5,8 @@ if get_option('loaders').contains('svg') == true
|
|||
message('Enable SVG Loader')
|
||||
endif
|
||||
|
||||
subdir('raw')
|
||||
|
||||
loader_dep = declare_dependency(
|
||||
dependencies: subloader_dep,
|
||||
include_directories : include_directories('.'),
|
||||
|
|
9
src/loaders/raw/meson.build
Normal file
|
@ -0,0 +1,9 @@
|
|||
source_file = [
|
||||
'tvgRawLoader.h',
|
||||
'tvgRawLoader.cpp',
|
||||
]
|
||||
|
||||
subloader_dep += [declare_dependency(
|
||||
include_directories : include_directories('.'),
|
||||
sources : source_file
|
||||
)]
|
84
src/loaders/raw/tvgRawLoader.cpp
Normal 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;
|
||||
}
|
43
src/loaders/raw/tvgRawLoader.h
Normal 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_
|
|
@ -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;
|
||||
f.open(path);
|
||||
|
@ -2539,9 +2539,10 @@ bool SvgLoader::close()
|
|||
}
|
||||
|
||||
|
||||
unique_ptr<Scene> SvgLoader::data()
|
||||
unique_ptr<Scene> SvgLoader::scene()
|
||||
{
|
||||
this->done();
|
||||
if (root) return move(root);
|
||||
else return nullptr;
|
||||
}
|
||||
|
||||
|
|
|
@ -39,14 +39,16 @@ public:
|
|||
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 header();
|
||||
bool read() override;
|
||||
bool close() override;
|
||||
void run(unsigned tid) override;
|
||||
|
||||
unique_ptr<Scene> data() override;
|
||||
unique_ptr<Scene> scene() override;
|
||||
};
|
||||
|
||||
|
||||
|
|