tvg_loader: code refactoring.

revise it under the tvg coding convention.
This commit is contained in:
Hermet Park 2021-06-11 15:08:40 +09:00 committed by Hermet Park
parent 52d95dcb59
commit 15b56a66de
9 changed files with 259 additions and 285 deletions

View file

@ -6,7 +6,7 @@ option('engines',
option('loaders',
type: 'array',
choices: ['', 'svg', 'png'],
choices: ['', 'svg', 'tvg', 'png'],
value: ['svg'],
description: 'Enable File Loaders in thorvg')

View file

@ -14,6 +14,7 @@ source_file = [
'tvgCanvasImpl.h',
'tvgCommon.h',
'tvgBezier.h',
'tvgBinaryDesc.h',
'tvgFill.h',
'tvgLoader.h',
'tvgLoaderMgr.h',
@ -22,7 +23,6 @@ source_file = [
'tvgSceneImpl.h',
'tvgShapeImpl.h',
'tvgTaskScheduler.h',
'tvgTvgHelper.h',
'tvgBezier.cpp',
'tvgCanvas.cpp',
'tvgFill.cpp',

View file

@ -19,8 +19,8 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef _TVG_TVG_HELPER_H_
#define _TVG_TVG_HELPER_H_
#ifndef _TVG_BINARY_DESC_H_
#define _TVG_BINARY_DESC_H_
// now only little endian
#define _read_tvg_ui16(dst, src) memcpy(dst, (src), sizeof(uint16_t))
@ -30,6 +30,7 @@
using TvgIndicator = uint8_t;
using ByteCounter = uint32_t;
using TvgFlag = uint8_t;
#define TVG_INDICATOR_SIZE sizeof(TvgIndicator)
#define BYTE_COUNTER_SIZE sizeof(ByteCounter)
#define TVG_FLAG_SIZE sizeof(TvgFlag)
@ -39,17 +40,25 @@ struct tvgBlock
TvgIndicator type;
ByteCounter length;
const char* data;
const char* blockEnd;
const char* end;
};
#define TVG_HEADER_TVG_SIGN_CODE "TVG"
#define TVG_HEADER_TVG_VERSION_CODE "000"
#define TVG_HEADER_TVG_SIGN_CODE_LENGTH 3
#define TVG_HEADER_TVG_VERSION_CODE_LENGTH 3
//TODO: replace it when this feature is completed.
#if 0
#define TVG_BIN_HEADER_SIGNATURE "ThorVG"
#define TVG_BIN_HEADER_SIGNATURE_LENGTH 6
#define TVG_BIN_HEADER_VERSION "000200"
#define TVG_BIN_HEADER_VERSION_LENGTH 6
#else
#define TVG_BIN_HEADER_SIGNATURE "TVG"
#define TVG_BIN_HEADER_SIGNATURE_LENGTH 3
#define TVG_BIN_HEADER_VERSION "000"
#define TVG_BIN_HEADER_VERSION_LENGTH 3
#endif
#define TVG_SCENE_BEGIN_INDICATOR (TvgIndicator)0xfe // Scene indicator
#define TVG_SHAPE_BEGIN_INDICATOR (TvgIndicator)0xfd // Shape indicator
#define TVG_PICTURE_BEGIN_INDICATOR (TvgIndicator)0xfc // Picture indicator
#define TVG_SCENE_BEGIN_INDICATOR (TvgIndicator)0xfe
#define TVG_SHAPE_BEGIN_INDICATOR (TvgIndicator)0xfd
#define TVG_PICTURE_BEGIN_INDICATOR (TvgIndicator)0xfc
// Paint
#define TVG_PAINT_OPACITY_INDICATOR (TvgIndicator)0x10 // Paint opacity
@ -100,4 +109,4 @@ struct tvgBlock
// Picture
#define TVG_RAW_IMAGE_BEGIN_INDICATOR (TvgIndicator)0x70 // Picture raw data
#endif //_TVG_TVG_HELPER_H_
#endif //_TVG_BINARY_DESC_H_

View file

@ -10,8 +10,12 @@ if get_option('loaders').contains('png') == true
message('Enable PNG Loader')
endif
if get_option('loaders').contains('tvg') == true
subdir('tvg')
message('Enable TVG Loader')
endif
subdir('raw')
subdir('tvg')
loader_dep = declare_dependency(
dependencies: subloader_dep,

View file

@ -2630,6 +2630,8 @@ bool SvgLoader::header()
bool SvgLoader::open(const char* data, uint32_t size)
{
//TODO: verify memory leak if open() is called multiple times.
this->content = data;
this->size = size;
@ -2639,22 +2641,20 @@ bool SvgLoader::open(const char* data, uint32_t size)
bool SvgLoader::open(const string& path)
{
//TODO: verify memory leak if open() is called multiple times.
ifstream f;
f.open(path);
if (!f.is_open())
{
//LOG: Failed to open file
return false;
} else {
getline(f, filePath, '\0');
f.close();
if (!f.is_open()) return false;
if (filePath.empty()) return false;
getline(f, filePath, '\0');
f.close();
this->content = filePath.c_str();
this->size = filePath.size();
}
if (filePath.empty()) return false;
content = filePath.c_str();
size = filePath.size();
return header();
}

View file

@ -20,76 +20,85 @@
* SOFTWARE.
*/
#include <string.h>
#include <memory.h>
#include "tvgTvgLoadParser.h"
/************************************************************************/
/* Internal Class Implementation */
/************************************************************************/
enum class LoaderResult { InvalidType, Success, SizeCorruption, MemoryCorruption, LogicalCorruption };
static LoaderResult _parsePaint(tvgBlock block, Paint ** paint);
static tvgBlock _readTvgBlock(const char *pointer)
static tvgBlock _readTvgBlock(const char *ptr)
{
tvgBlock block;
block.type = *pointer;
_read_tvg_ui32(&block.length, pointer + TVG_INDICATOR_SIZE);
block.data = pointer + TVG_INDICATOR_SIZE + BYTE_COUNTER_SIZE;
block.blockEnd = block.data + block.length;
block.type = *ptr;
_read_tvg_ui32(&block.length, ptr + TVG_INDICATOR_SIZE);
block.data = ptr + TVG_INDICATOR_SIZE + BYTE_COUNTER_SIZE;
block.end = block.data + block.length;
return block;
}
static bool _readTvgHeader(const char **pointer)
static bool _readTvgHeader(const char **ptr)
{
// Sign phase, always "TVG" declared in TVG_HEADER_TVG_SIGN_CODE
if (memcmp(*pointer, TVG_HEADER_TVG_SIGN_CODE, TVG_HEADER_TVG_SIGN_CODE_LENGTH)) return false;
*pointer += TVG_HEADER_TVG_SIGN_CODE_LENGTH; // move after sing code
//Sign phase, always TVG_BIN_HEADER_SIGNATURE is declared
if (memcmp(*ptr, TVG_BIN_HEADER_SIGNATURE, TVG_BIN_HEADER_SIGNATURE_LENGTH)) return false;
*ptr += TVG_BIN_HEADER_SIGNATURE_LENGTH;
// Standard version number, declared in TVG_HEADER_TVG_VERSION_CODE
if (memcmp(*pointer, TVG_HEADER_TVG_VERSION_CODE, TVG_HEADER_TVG_VERSION_CODE_LENGTH)) return false;
*pointer += TVG_HEADER_TVG_VERSION_CODE_LENGTH; // move after version code
//Version number, declared in TVG_BIN_HEADER_VERSION
if (memcmp(*ptr, TVG_BIN_HEADER_VERSION, TVG_BIN_HEADER_VERSION_LENGTH)) return false;
*ptr += TVG_BIN_HEADER_VERSION_LENGTH;
// Matadata phase
uint16_t meta_length; // Matadata phase length
_read_tvg_ui16(&meta_length, *pointer);
*pointer += 2; // move after length
//Mata data for proof?
uint16_t metaLen;
_read_tvg_ui16(&metaLen, *ptr);
*ptr += 2;
//Meta data... Necessary?
#ifdef THORVG_LOG_ENABLED
char metadata[meta_length + 1];
memcpy(metadata, *pointer, meta_length);
metadata[meta_length] = '\0';
printf("TVG_LOADER: Header is valid, metadata[%d]: %s.\n", meta_length, metadata);
char metadata[metaLen + 1];
memcpy(metadata, *ptr, metaLen);
metadata[metaLen] = '\0';
printf("TVG_LOADER: Header is valid, metadata[%d]: %s.\n", metaLen, metadata);
#endif
*pointer += meta_length;
*ptr += metaLen;
return true;
}
// Paint
static LoaderResult _parseCmpTarget(const char *pointer, const char *end, Paint *paint)
static LoaderResult _parseCmpTarget(const char *ptr, const char *end, Paint *paint)
{
auto block = _readTvgBlock(pointer);
if (block.blockEnd > end) return LoaderResult::SizeCorruption;
auto block = _readTvgBlock(ptr);
if (block.end > end) return LoaderResult::SizeCorruption;
CompositeMethod cmpMethod;
if (block.type != TVG_PAINT_CMP_METHOD_INDICATOR) return LoaderResult::LogicalCorruption;
if (block.length != sizeof(TvgFlag)) return LoaderResult::SizeCorruption;
switch (*block.data)
{
case TVG_PAINT_CMP_METHOD_CLIPPATH_FLAG:
switch (*block.data) {
case TVG_PAINT_CMP_METHOD_CLIPPATH_FLAG: {
cmpMethod = CompositeMethod::ClipPath;
break;
case TVG_PAINT_CMP_METHOD_ALPHAMASK_FLAG:
}
case TVG_PAINT_CMP_METHOD_ALPHAMASK_FLAG: {
cmpMethod = CompositeMethod::AlphaMask;
break;
case TVG_PAINT_CMP_METHOD_INV_ALPHAMASK_FLAG:
}
case TVG_PAINT_CMP_METHOD_INV_ALPHAMASK_FLAG: {
cmpMethod = CompositeMethod::InvAlphaMask;
break;
default:
return LoaderResult::LogicalCorruption;
}
default: return LoaderResult::LogicalCorruption;
}
pointer = block.blockEnd;
auto block_paint = _readTvgBlock(pointer);
if (block_paint.blockEnd > end) return LoaderResult::SizeCorruption;
ptr = block.end;
auto block_paint = _readTvgBlock(ptr);
if (block_paint.end > end) return LoaderResult::SizeCorruption;
Paint* cmpTarget;
auto result = _parsePaint(block_paint, &cmpTarget);
@ -99,40 +108,35 @@ static LoaderResult _parseCmpTarget(const char *pointer, const char *end, Paint
return LoaderResult::Success;
}
static LoaderResult _parsePaintProperty(tvgBlock block, Paint *paint)
{
switch (block.type)
{
case TVG_PAINT_OPACITY_INDICATOR:
{ // opacity
switch (block.type) {
case TVG_PAINT_OPACITY_INDICATOR: {
if (block.length != sizeof(uint8_t)) return LoaderResult::SizeCorruption;
paint->opacity(*block.data);
return LoaderResult::Success;
}
case TVG_PAINT_TRANSFORM_MATRIX_INDICATOR:
{ // transform matrix
case TVG_PAINT_TRANSFORM_MATRIX_INDICATOR: {
if (block.length != sizeof(Matrix)) return LoaderResult::SizeCorruption;
Matrix matrix;
memcpy(&matrix, block.data, sizeof(Matrix));
if (paint->transform(matrix) != Result::Success) return LoaderResult::MemoryCorruption;
return LoaderResult::Success;
}
case TVG_PAINT_CMP_TARGET_INDICATOR:
{ // cmp target
case TVG_PAINT_CMP_TARGET_INDICATOR: {
if (block.length < TVG_INDICATOR_SIZE + BYTE_COUNTER_SIZE) return LoaderResult::SizeCorruption;
return _parseCmpTarget(block.data, block.blockEnd, paint);
return _parseCmpTarget(block.data, block.end, paint);
}
}
return LoaderResult::InvalidType;
}
// Scene
static LoaderResult _parseSceneProperty(tvgBlock block, Scene *scene)
{
switch (block.type)
{
case TVG_SCENE_FLAG_RESERVEDCNT:
{
switch (block.type) {
case TVG_SCENE_FLAG_RESERVEDCNT: {
if (block.length != sizeof(uint32_t)) return LoaderResult::SizeCorruption;
uint32_t reservedCnt;
_read_tvg_ui32(&reservedCnt, block.data);
@ -151,104 +155,100 @@ static LoaderResult _parseSceneProperty(tvgBlock block, Scene *scene)
return result;
}
// Shape
static LoaderResult _parseShapePath(const char *pointer, const char *end, Shape *shape)
static LoaderResult _parseShapePath(const char *ptr, const char *end, Shape *shape)
{
// ShapePath
//Shape Path
uint32_t cmdCnt, ptsCnt;
_read_tvg_ui32(&cmdCnt, pointer);
pointer += sizeof(uint32_t);
_read_tvg_ui32(&ptsCnt, pointer);
pointer += sizeof(uint32_t);
_read_tvg_ui32(&cmdCnt, ptr);
ptr += sizeof(uint32_t);
_read_tvg_ui32(&ptsCnt, ptr);
ptr += sizeof(uint32_t);
const PathCommand* cmds = (PathCommand*) pointer;
pointer += sizeof(PathCommand) * cmdCnt;
const Point* pts = (Point*) pointer;
pointer += sizeof(Point) * ptsCnt;
const PathCommand* cmds = (PathCommand*) ptr;
ptr += sizeof(PathCommand) * cmdCnt;
const Point* pts = (Point*) ptr;
ptr += sizeof(Point) * ptsCnt;
if (pointer > end) return LoaderResult::SizeCorruption;
if (ptr > end) return LoaderResult::SizeCorruption;
shape->appendPath(cmds, cmdCnt, pts, ptsCnt);
return LoaderResult::Success;
}
static LoaderResult _parseShapeFill(const char *pointer, const char *end, Fill **fillOutside)
static LoaderResult _parseShapeFill(const char *ptr, const char *end, Fill **fillOutside)
{
unique_ptr<Fill> fillGrad;
while (pointer < end)
{
auto block = _readTvgBlock(pointer);
if (block.blockEnd > end) return LoaderResult::SizeCorruption;
while (ptr < end) {
auto block = _readTvgBlock(ptr);
if (block.end > end) return LoaderResult::SizeCorruption;
switch (block.type)
{
case TVG_FILL_RADIAL_GRADIENT_INDICATOR:
{ // radial gradient
switch (block.type) {
case TVG_FILL_RADIAL_GRADIENT_INDICATOR: {
if (block.length != 3 * sizeof(float)) return LoaderResult::SizeCorruption;
const char* pointer = block.data;
auto ptr = block.data;
float x, y, radius;
_read_tvg_float(&x, pointer);
pointer += sizeof(float);
_read_tvg_float(&y, pointer);
pointer += sizeof(float);
_read_tvg_float(&radius, pointer);
_read_tvg_float(&x, ptr);
ptr += sizeof(float);
_read_tvg_float(&y, ptr);
ptr += sizeof(float);
_read_tvg_float(&radius, ptr);
auto fillGradRadial = RadialGradient::gen();
fillGradRadial->radial(x, y, radius);
fillGrad = move(fillGradRadial);
break;
}
case TVG_FILL_LINEAR_GRADIENT_INDICATOR:
{ // linear gradient
case TVG_FILL_LINEAR_GRADIENT_INDICATOR: {
if (block.length != 4 * sizeof(float)) return LoaderResult::SizeCorruption;
const char* pointer = block.data;
auto ptr = block.data;
float x1, y1, x2, y2;
_read_tvg_float(&x1, pointer);
pointer += sizeof(float);
_read_tvg_float(&y1, pointer);
pointer += sizeof(float);
_read_tvg_float(&x2, pointer);
pointer += sizeof(float);
_read_tvg_float(&y2, pointer);
_read_tvg_float(&x1, ptr);
ptr += sizeof(float);
_read_tvg_float(&y1, ptr);
ptr += sizeof(float);
_read_tvg_float(&x2, ptr);
ptr += sizeof(float);
_read_tvg_float(&y2, ptr);
auto fillGradLinear = LinearGradient::gen();
fillGradLinear->linear(x1, y1, x2, y2);
fillGrad = move(fillGradLinear);
break;
}
case TVG_FILL_FILLSPREAD_INDICATOR:
{ // fill spread
case TVG_FILL_FILLSPREAD_INDICATOR: {
if (!fillGrad) return LoaderResult::LogicalCorruption;
if (block.length != sizeof(TvgFlag)) return LoaderResult::SizeCorruption;
switch (*block.data)
{
case TVG_FILL_FILLSPREAD_PAD_FLAG:
switch (*block.data) {
case TVG_FILL_FILLSPREAD_PAD_FLAG: {
fillGrad->spread(FillSpread::Pad);
break;
case TVG_FILL_FILLSPREAD_REFLECT_FLAG:
}
case TVG_FILL_FILLSPREAD_REFLECT_FLAG: {
fillGrad->spread(FillSpread::Reflect);
break;
case TVG_FILL_FILLSPREAD_REPEAT_FLAG:
}
case TVG_FILL_FILLSPREAD_REPEAT_FLAG: {
fillGrad->spread(FillSpread::Repeat);
break;
}
}
break;
}
case TVG_FILL_COLORSTOPS_INDICATOR:
{ // color stops
case TVG_FILL_COLORSTOPS_INDICATOR: {
if (!fillGrad) return LoaderResult::LogicalCorruption;
if (block.length == 0 || block.length & 0x07) return LoaderResult::SizeCorruption;
uint32_t stopsCnt = block.length >> 3; // 8 bytes per ColorStop
if (stopsCnt > 1023) return LoaderResult::SizeCorruption;
Fill::ColorStop stops[stopsCnt];
const char* p = block.data;
for (uint32_t i = 0; i < stopsCnt; i++, p += 8)
{
auto p = block.data;
for (uint32_t i = 0; i < stopsCnt; i++, p += 8) {
_read_tvg_float(&stops[i].offset, p);
stops[i].r = p[4];
stops[i].g = p[5];
@ -259,42 +259,38 @@ static LoaderResult _parseShapeFill(const char *pointer, const char *end, Fill *
break;
}
}
pointer = block.blockEnd;
ptr = block.end;
}
*fillOutside = fillGrad.release();
return LoaderResult::Success;
}
static LoaderResult _parseShapeStrokeDashPattern(const char *pointer, const char *end, Shape *shape)
static LoaderResult _parseShapeStrokeDashPattern(const char *ptr, const char *end, Shape *shape)
{
uint32_t dashPatternCnt;
_read_tvg_ui32(&dashPatternCnt, pointer);
pointer += sizeof(uint32_t);
const float* dashPattern = (float*) pointer;
pointer += sizeof(float) * dashPatternCnt;
_read_tvg_ui32(&dashPatternCnt, ptr);
ptr += sizeof(uint32_t);
const float* dashPattern = (float*) ptr;
ptr += sizeof(float) * dashPatternCnt;
if (pointer > end) return LoaderResult::SizeCorruption;
if (ptr > end) return LoaderResult::SizeCorruption;
shape->stroke(dashPattern, dashPatternCnt);
return LoaderResult::Success;
}
static LoaderResult _parseShapeStroke(const char *pointer, const char *end, Shape *shape)
{
while (pointer < end)
{
auto block = _readTvgBlock(pointer);
if (block.blockEnd > end) return LoaderResult::SizeCorruption;
switch (block.type)
{
case TVG_SHAPE_STROKE_CAP_INDICATOR:
{ // stroke cap
static LoaderResult _parseShapeStroke(const char *ptr, const char *end, Shape *shape)
{
while (ptr < end) {
auto block = _readTvgBlock(ptr);
if (block.end > end) return LoaderResult::SizeCorruption;
switch (block.type) {
case TVG_SHAPE_STROKE_CAP_INDICATOR: {
if (block.length != sizeof(TvgFlag)) return LoaderResult::SizeCorruption;
switch (*block.data)
{
switch (*block.data) {
case TVG_SHAPE_STROKE_CAP_SQUARE_FLAG:
shape->stroke(StrokeCap::Square);
break;
@ -307,11 +303,9 @@ static LoaderResult _parseShapeStroke(const char *pointer, const char *end, Shap
}
break;
}
case TVG_SHAPE_STROKE_JOIN_INDICATOR:
{ // stroke join
case TVG_SHAPE_STROKE_JOIN_INDICATOR: {
if (block.length != sizeof(TvgFlag)) return LoaderResult::SizeCorruption;
switch (*block.data)
{
switch (*block.data) {
case TVG_SHAPE_STROKE_JOIN_BEVEL_FLAG:
shape->stroke(StrokeJoin::Bevel);
break;
@ -324,77 +318,65 @@ static LoaderResult _parseShapeStroke(const char *pointer, const char *end, Shap
}
break;
}
case TVG_SHAPE_STROKE_WIDTH_INDICATOR:
{ // stroke width
case TVG_SHAPE_STROKE_WIDTH_INDICATOR: {
if (block.length != sizeof(float)) return LoaderResult::SizeCorruption;
float width;
_read_tvg_float(&width, block.data);
shape->stroke(width);
break;
}
case TVG_SHAPE_STROKE_COLOR_INDICATOR:
{ // stroke color
case TVG_SHAPE_STROKE_COLOR_INDICATOR: {
if (block.length != 4) return LoaderResult::SizeCorruption;
shape->stroke(block.data[0], block.data[1], block.data[2], block.data[3]);
break;
}
case TVG_SHAPE_STROKE_FILL_INDICATOR:
{ // stroke fill
case TVG_SHAPE_STROKE_FILL_INDICATOR: {
Fill* fill;
auto result = _parseShapeFill(block.data, block.blockEnd, &fill);
auto result = _parseShapeFill(block.data, block.end, &fill);
if (result != LoaderResult::Success) return result;
shape->stroke(unique_ptr < Fill > (fill));
break;
}
case TVG_SHAPE_STROKE_DASHPTRN_INDICATOR:
{ // dashed stroke
auto result = _parseShapeStrokeDashPattern(block.data, block.blockEnd, shape);
case TVG_SHAPE_STROKE_DASHPTRN_INDICATOR: {
auto result = _parseShapeStrokeDashPattern(block.data, block.end, shape);
if (result != LoaderResult::Success) return result;
break;
}
}
pointer = block.blockEnd;
ptr = block.end;
}
return LoaderResult::Success;
}
static LoaderResult _parseShapeProperty(tvgBlock block, Shape *shape)
{
switch (block.type)
{
case TVG_SHAPE_PATH_INDICATOR:
{ // path
auto result = _parseShapePath(block.data, block.blockEnd, shape);
switch (block.type) {
case TVG_SHAPE_PATH_INDICATOR: {
auto result = _parseShapePath(block.data, block.end, shape);
if (result != LoaderResult::Success) return result;
break;
}
case TVG_SHAPE_STROKE_INDICATOR:
{ // stroke section
auto result = _parseShapeStroke(block.data, block.blockEnd, shape);
case TVG_SHAPE_STROKE_INDICATOR: {
auto result = _parseShapeStroke(block.data, block.end, shape);
if (result != LoaderResult::Success) return result;
break;
}
case TVG_SHAPE_FILL_INDICATOR:
{ // fill (gradient)
case TVG_SHAPE_FILL_INDICATOR: {
Fill* fill;
auto result = _parseShapeFill(block.data, block.blockEnd, &fill);
auto result = _parseShapeFill(block.data, block.end, &fill);
if (result != LoaderResult::Success) return result;
shape->fill(unique_ptr < Fill > (fill));
break;
}
case TVG_SHAPE_COLOR_INDICATOR:
{ // color
case TVG_SHAPE_COLOR_INDICATOR: {
if (block.length != 4) return LoaderResult::SizeCorruption;
shape->fill(block.data[0], block.data[1], block.data[2], block.data[3]);
break;
}
case TVG_SHAPE_FILLRULE_INDICATOR:
{ // fill rule
case TVG_SHAPE_FILLRULE_INDICATOR: {
if (block.length != sizeof(TvgFlag)) return LoaderResult::SizeCorruption;
switch (*block.data)
{
switch (*block.data) {
case TVG_SHAPE_FILLRULE_WINDING_FLAG:
shape->fill(FillRule::Winding);
break;
@ -404,36 +386,30 @@ static LoaderResult _parseShapeProperty(tvgBlock block, Shape *shape)
}
break;
}
default:
{
return LoaderResult::InvalidType;
}
default: return LoaderResult::InvalidType;
}
return LoaderResult::Success;
}
// Picture
static LoaderResult _parsePicture(tvgBlock block, Picture *picture)
{
switch (block.type)
{
case TVG_RAW_IMAGE_BEGIN_INDICATOR:
{
switch (block.type) {
case TVG_RAW_IMAGE_BEGIN_INDICATOR: {
if (block.length < 2*sizeof(uint32_t)) return LoaderResult::SizeCorruption;
const char* pointer = block.data;
const char* ptr = block.data;
uint32_t w, h;
_read_tvg_ui32(&w, pointer);
pointer += sizeof(uint32_t);
_read_tvg_ui32(&h, pointer);
pointer += sizeof(uint32_t);
_read_tvg_ui32(&w, ptr);
ptr += sizeof(uint32_t);
_read_tvg_ui32(&h, ptr);
ptr += sizeof(uint32_t);
uint32_t size = w * h * sizeof(uint32_t);
if (block.length != 2*sizeof(uint32_t) + size) return LoaderResult::SizeCorruption;
uint32_t* pixels = (uint32_t*) pointer;
uint32_t* pixels = (uint32_t*) ptr;
picture->load(pixels, w, h, true);
return LoaderResult::Success;
}
@ -452,97 +428,87 @@ static LoaderResult _parsePicture(tvgBlock block, Picture *picture)
static LoaderResult _parsePaint(tvgBlock base_block, Paint **paint)
{
switch (base_block.type)
{
case TVG_SCENE_BEGIN_INDICATOR:
{
switch (base_block.type) {
case TVG_SCENE_BEGIN_INDICATOR: {
auto s = Scene::gen();
const char* pointer = base_block.data;
while (pointer < base_block.blockEnd)
{
auto block = _readTvgBlock(pointer);
if (block.blockEnd > base_block.blockEnd) return LoaderResult::SizeCorruption;
auto ptr = base_block.data;
while (ptr < base_block.end) {
auto block = _readTvgBlock(ptr);
if (block.end > base_block.end) return LoaderResult::SizeCorruption;
auto result = _parseSceneProperty(block, s.get());
if (result == LoaderResult::InvalidType) result = _parsePaintProperty(block, s.get());
if (result > LoaderResult::Success)
{
// LOG: tvg parsing error
if (result > LoaderResult::Success) {
#ifdef THORVG_LOG_ENABLED
printf("TVG_LOADER: Loading scene error[type: 0x%02x]: %d\n", (int) block.type, (int) result);
#endif
return result;
}
pointer = block.blockEnd;
ptr = block.end;
}
*paint = s.release();
break;
}
case TVG_SHAPE_BEGIN_INDICATOR:
{
case TVG_SHAPE_BEGIN_INDICATOR: {
auto s = Shape::gen();
const char* pointer = base_block.data;
while (pointer < base_block.blockEnd)
{
auto block = _readTvgBlock(pointer);
if (block.blockEnd > base_block.blockEnd) return LoaderResult::SizeCorruption;
auto ptr = base_block.data;
while (ptr < base_block.end) {
auto block = _readTvgBlock(ptr);
if (block.end > base_block.end) return LoaderResult::SizeCorruption;
auto result = _parseShapeProperty(block, s.get());
if (result == LoaderResult::InvalidType) result = _parsePaintProperty(block, s.get());
if (result > LoaderResult::Success)
{
// LOG: tvg parsing error
if (result > LoaderResult::Success) {
#ifdef THORVG_LOG_ENABLED
printf("TVG_LOADER: Loading shape error[type: 0x%02x]: %d\n", (int) block.type, (int) result);
#endif
return result;
}
pointer = block.blockEnd;
ptr = block.end;
}
*paint = s.release();
break;
}
case TVG_PICTURE_BEGIN_INDICATOR:
{
case TVG_PICTURE_BEGIN_INDICATOR: {
auto s = Picture::gen();
const char* pointer = base_block.data;
while (pointer < base_block.blockEnd)
{
auto block = _readTvgBlock(pointer);
if (block.blockEnd > base_block.blockEnd) return LoaderResult::SizeCorruption;
auto ptr = base_block.data;
while (ptr < base_block.end) {
auto block = _readTvgBlock(ptr);
if (block.end > base_block.end) return LoaderResult::SizeCorruption;
auto result = _parsePicture(block, s.get());
if (result == LoaderResult::InvalidType) result = _parsePaintProperty(block, s.get());
if (result > LoaderResult::Success)
{
// LOG: tvg parsing error
if (result > LoaderResult::Success) {
#ifdef THORVG_LOG_ENABLED
printf("TVG_LOADER: Loading picture error[type: 0x%02x]: %d\n", (int) block.type, (int) result);
#endif
return result;
}
pointer = block.blockEnd;
ptr = block.end;
}
*paint = s.release();
break;
}
default:
return LoaderResult::InvalidType;
default: return LoaderResult::InvalidType;
}
return LoaderResult::Success;
}
unique_ptr<Scene> tvgParseTvgFile(const char *pointer, uint32_t size)
/************************************************************************/
/* External Class Implementation */
/************************************************************************/
unique_ptr<Scene> tvgLoadTvgData(const char *ptr, uint32_t size)
{
const char* end = pointer + size;
if (!_readTvgHeader(&pointer) || pointer >= end)
{
// LOG: Header is improper
auto end = ptr + size;
if (!_readTvgHeader(&ptr) || ptr >= end) {
#ifdef THORVG_LOG_ENABLED
printf("TVG_LOADER: Header is improper.\n");
printf("TVG_LOADER: Invalid TVG Data!\n");
#endif
return nullptr;
}
@ -551,10 +517,10 @@ unique_ptr<Scene> tvgParseTvgFile(const char *pointer, uint32_t size)
if (!scene) return nullptr;
Paint* paint;
while (pointer < end)
{
auto block = _readTvgBlock(pointer);
if (block.blockEnd > end) return nullptr;
while (ptr < end) {
auto block = _readTvgBlock(ptr);
if (block.end > end) return nullptr;
auto result = _parsePaint(block, &paint);
if (result > LoaderResult::Success) return nullptr;
@ -563,13 +529,8 @@ unique_ptr<Scene> tvgParseTvgFile(const char *pointer, uint32_t size)
return nullptr;
}
}
pointer = block.blockEnd;
ptr = block.end;
}
// LOG: File parsed correctly
#ifdef THORVG_LOG_ENABLED
printf("TVG_LOADER: File parsed correctly.\n");
#endif
return move(scene);
}

View file

@ -24,8 +24,8 @@
#define _TVG_TVG_LOAD_PARSER_H_
#include "tvgCommon.h"
#include "tvgTvgHelper.h"
#include "tvgBinaryDesc.h"
unique_ptr<Scene> tvgParseTvgFile(const char *pointer, uint32_t size);
unique_ptr<Scene> tvgLoadTvgData(const char *ptr, uint32_t size);
#endif //_TVG_TVG_LOAD_PARSER_H_

View file

@ -21,48 +21,50 @@
*/
#include <fstream>
#include <string.h>
#include "tvgLoaderMgr.h"
#include "tvgTvgLoader.h"
#include "tvgTvgLoadParser.h"
/************************************************************************/
/* Internal Class Implementation */
/************************************************************************/
void TvgLoader::clearBuffer()
{
free(buffer);
size = 0;
buffer = nullptr;
pointer = nullptr;
}
/************************************************************************/
/* External Class Implementation */
/************************************************************************/
TvgLoader::~TvgLoader()
{
close();
}
void TvgLoader::clearBuffer()
{
size = 0;
free(buffer);
buffer = nullptr;
pointer = nullptr;
}
bool TvgLoader::open(const string &path)
{
//TODO: verify memory leak if open() is called multiple times.
ifstream f;
f.open(path, ifstream::in | ifstream::binary | ifstream::ate);
if (!f.is_open())
{
#ifdef THORVG_LOG_ENABLED
printf("TVG_LOADER: Failed to open file\n");
#endif
return false;
}
if (!f.is_open()) return false;
size = f.tellg();
f.seekg(0, ifstream::beg);
buffer = (char*) malloc(size);
if (!buffer)
{
buffer = (char*)malloc(size);
if (!buffer) {
size = 0;
f.close();
#ifdef THORVG_LOG_ENABLED
printf("TVG_LOADER: Failed to alloc buffer\n");
#endif
return false;
}
@ -77,13 +79,20 @@ bool TvgLoader::open(const string &path)
pointer = buffer;
//FIXME: verify TVG format here.
return true;
}
bool TvgLoader::open(const char *data, uint32_t size)
{
//TODO: verify memory leak if open() is called multiple times.
pointer = data;
size = size;
//FIXME: verify TVG format here.
return true;
}
@ -106,15 +115,8 @@ bool TvgLoader::close()
void TvgLoader::run(unsigned tid)
{
if (root) root.reset();
root = tvgParseTvgFile(pointer, size);
if (!root)
{
#ifdef THORVG_LOG_ENABLED
printf("TVG_LOADER: File parsing error\n");
#endif
clearBuffer();
}
root = tvgLoadTvgData(pointer, size);
if (!root) clearBuffer();
}
unique_ptr<Scene> TvgLoader::scene()

View file

@ -23,7 +23,6 @@
#ifndef _TVG_TVG_LOADER_H_
#define _TVG_TVG_LOADER_H_
#include "tvgLoader.h"
#include "tvgTaskScheduler.h"
class TvgLoader : public Loader, public Task
@ -33,14 +32,13 @@ public:
const char* pointer = nullptr;
uint32_t size = 0;
unique_ptr<Scene> root;
unique_ptr<Scene> root = nullptr;
~TvgLoader();
using Loader::open;
bool open(const string &path) override;
bool open(const char *data, uint32_t size) override;
bool read() override;
bool close() override;