From 64fea7580d238cd976c3542d75b71b675bb29f26 Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Wed, 21 Jul 2021 13:56:50 +0900 Subject: [PATCH] tvg format: code refactoring #10 keep neat & clean code, revise to tvg style naming convention. --- src/examples/images/test.tvg | Bin 317203 -> 317203 bytes src/lib/tvgBinaryDesc.h | 9 +- src/lib/tvgSaverImpl.h | 320 ++++++++++++++++++++++--------------------- 3 files changed, 173 insertions(+), 156 deletions(-) diff --git a/src/examples/images/test.tvg b/src/examples/images/test.tvg index d4c4ed0f033c7ec536c8770751a4e8688308503b..df8e13c3e8d1356bb3ef561e0ffc500ebcdc49bb 100644 GIT binary patch delta 33 ocmbQdPI&S-0|Nt-My^&a##Sz-RxakPTr8Z|0kyFSk^lez delta 33 ocmbQdPI&S-0|Nu2My^&a##Sz-RxakPTr8Z|0kw|_kN^Mx diff --git a/src/lib/tvgBinaryDesc.h b/src/lib/tvgBinaryDesc.h index 4c65d38..793d48f 100644 --- a/src/lib/tvgBinaryDesc.h +++ b/src/lib/tvgBinaryDesc.h @@ -22,14 +22,17 @@ #ifndef _TVG_BINARY_DESC_H_ #define _TVG_BINARY_DESC_H_ -//TODO: Need to consider whether uin8_t is enough size for extension... +/* TODO: Need to consider whether uin8_t is enough size for extension... + Rather than optimal data, we can use enough size and data compress? */ /* Data types, do not change data types once Tvg Format is officially released, That would occur the abi break. */ + using TvgBinByte = uint8_t; -using TvgBinTag = uint8_t; using TvgBinCounter = uint32_t; -using TvgBinFlag = uint8_t; +using TvgBinTag = TvgBinByte; +using TvgBinFlag = TvgBinByte; + //Header #define TVG_HEADER_SIGNATURE "ThorVG" diff --git a/src/lib/tvgSaverImpl.h b/src/lib/tvgSaverImpl.h index 7504cdd..9a83312 100644 --- a/src/lib/tvgSaverImpl.h +++ b/src/lib/tvgSaverImpl.h @@ -30,6 +30,14 @@ #define SIZE(A) sizeof(A) +/************************************************************************/ +/* Internal Class Implementation */ +/************************************************************************/ + +static inline TvgBinCounter SERIAL_DONE(TvgBinCounter cnt) +{ + return SIZE(TvgBinTag) + SIZE(TvgBinCounter) + cnt; +} struct Saver::Impl { @@ -50,7 +58,7 @@ struct Saver::Impl return true; } - bool bufferToFile(const std::string& path) + bool flushTo(const std::string& path) { FILE* fp = fopen(path.c_str(), "w+"); if (!fp) return false; @@ -77,289 +85,295 @@ struct Saver::Impl return true; } - void writeMemberIndicator(TvgBinTag ind) + void writeTag(TvgBinTag tag) { buffer.grow(SIZE(TvgBinTag)); - memcpy(buffer.ptr(), &ind, SIZE(TvgBinTag)); + memcpy(buffer.ptr(), &tag, SIZE(TvgBinTag)); buffer.count += SIZE(TvgBinTag); } - void writeMemberDataSize(TvgBinCounter byteCnt) + void writeCount(TvgBinCounter cnt) { buffer.grow(SIZE(TvgBinCounter)); - memcpy(buffer.ptr(), &byteCnt, SIZE(TvgBinCounter)); + memcpy(buffer.ptr(), &cnt, SIZE(TvgBinCounter)); buffer.count += SIZE(TvgBinCounter); } - void writeMemberDataSizeAt(TvgBinCounter byteCnt) + void writeReservedCount(TvgBinCounter cnt) { - memcpy(buffer.ptr() - byteCnt - SIZE(TvgBinCounter), &byteCnt, SIZE(TvgBinCounter)); + memcpy(buffer.ptr() - cnt - SIZE(TvgBinCounter), &cnt, SIZE(TvgBinCounter)); } - void skipInBufferMemberDataSize() + void reserveCount() { buffer.grow(SIZE(TvgBinCounter)); buffer.count += SIZE(TvgBinCounter); } - TvgBinCounter writeMemberData(const void* data, TvgBinCounter byteCnt) + TvgBinCounter writeData(const void* data, TvgBinCounter cnt) { - buffer.grow(byteCnt); - memcpy(buffer.ptr(), data, byteCnt); - buffer.count += byteCnt; + buffer.grow(cnt); + memcpy(buffer.ptr(), data, cnt); + buffer.count += cnt; - return byteCnt; + return cnt; } - TvgBinCounter writeMember(TvgBinTag ind, TvgBinCounter byteCnt, const void* data) + TvgBinCounter writeTagProperty(TvgBinTag tag, TvgBinCounter cnt, const void* data) { - TvgBinCounter blockByteCnt = SIZE(TvgBinTag) + SIZE(TvgBinCounter) + byteCnt; + TvgBinCounter growCnt = SERIAL_DONE(cnt); - buffer.grow(blockByteCnt); + buffer.grow(growCnt); auto ptr = buffer.ptr(); - memcpy(ptr, &ind, SIZE(TvgBinTag)); - ptr += SIZE(TvgBinTag); - memcpy(ptr, &byteCnt, SIZE(TvgBinCounter)); + *ptr = tag; + ++ptr; + + memcpy(ptr, &cnt, SIZE(TvgBinCounter)); ptr += SIZE(TvgBinCounter); - memcpy(ptr, data, byteCnt); - ptr += byteCnt; - buffer.count += blockByteCnt; + memcpy(ptr, data, cnt); + ptr += cnt; - return blockByteCnt; + buffer.count += growCnt; + + return growCnt; } TvgBinCounter serializePaint(const Paint* paint) { - TvgBinCounter paintDataByteCnt = 0; + TvgBinCounter cnt = 0; + //opacity auto opacity = paint->opacity(); if (opacity < 255) { - paintDataByteCnt += writeMember(TVG_TAG_PAINT_OPACITY, sizeof(opacity), &opacity); + cnt += writeTagProperty(TVG_TAG_PAINT_OPACITY, sizeof(opacity), &opacity); } + //transform auto m = const_cast(paint)->transform(); if (fabs(m.e11 - 1) > FLT_EPSILON || fabs(m.e12) > FLT_EPSILON || fabs(m.e13) > FLT_EPSILON || fabs(m.e21) > FLT_EPSILON || fabs(m.e22 - 1) > FLT_EPSILON || fabs(m.e23) > FLT_EPSILON || fabs(m.e31) > FLT_EPSILON || fabs(m.e32) > FLT_EPSILON || fabs(m.e33 - 1) > FLT_EPSILON) { - paintDataByteCnt += writeMember(TVG_TAG_PAINT_TRANSFORM, sizeof(m), &m); + cnt += writeTagProperty(TVG_TAG_PAINT_TRANSFORM, sizeof(m), &m); } + //composite const Paint* cmpTarget = nullptr; auto cmpMethod = paint->composite(&cmpTarget); if (cmpMethod != CompositeMethod::None && cmpTarget) { - paintDataByteCnt += serializeComposite(cmpTarget, cmpMethod); + cnt += serializeComposite(cmpTarget, cmpMethod); } - return paintDataByteCnt; + return cnt; } - TvgBinCounter serialize(const Scene* scene) + TvgBinCounter serializeScene(const Scene* scene) { - writeMemberIndicator(TVG_TAG_CLASS_SCENE); - skipInBufferMemberDataSize(); + writeTag(TVG_TAG_CLASS_SCENE); + reserveCount(); - auto sceneDataByteCnt = serializeChildren(scene); - sceneDataByteCnt += serializePaint(scene); + auto cnt = serializeChildren(scene) + serializePaint(scene); - writeMemberDataSizeAt(sceneDataByteCnt); + writeReservedCount(cnt); - return SIZE(TvgBinTag) + SIZE(TvgBinCounter) + sceneDataByteCnt; + return SERIAL_DONE(cnt); } - TvgBinCounter serializeShapeFill(const Fill* f, TvgBinTag fillTvgBinFlag) + TvgBinCounter serializeFill(const Fill* fill, TvgBinTag tag) { - TvgBinCounter fillDataByteCnt = 0; const Fill::ColorStop* stops = nullptr; - auto stopsCnt = f->colorStops(&stops); + auto stopsCnt = fill->colorStops(&stops); if (!stops || stopsCnt == 0) return 0; - writeMemberIndicator(fillTvgBinFlag); - skipInBufferMemberDataSize(); + writeTag(tag); + reserveCount(); - if (f->id() == TVG_CLASS_ID_RADIAL) { - float argRadial[3]; - auto radGrad = static_cast(f); - radGrad->radial(argRadial, argRadial + 1,argRadial + 2); - fillDataByteCnt += writeMember(TVG_TAG_FILL_RADIAL_GRADIENT, sizeof(argRadial), argRadial); - } - else { - float argLinear[4]; - auto linGrad = static_cast(f); - linGrad->linear(argLinear, argLinear + 1, argLinear + 2, argLinear + 3); - fillDataByteCnt += writeMember(TVG_TAG_FILL_LINEAR_GRADIENT, sizeof(argLinear), argLinear); + TvgBinCounter cnt = 0; + + //radial fill + if (fill->id() == TVG_CLASS_ID_RADIAL) { + float args[3]; + static_cast(fill)->radial(args, args + 1,args + 2); + cnt += writeTagProperty(TVG_TAG_FILL_RADIAL_GRADIENT, sizeof(args), args); + //linear fill + } else { + float args[4]; + static_cast(fill)->linear(args, args + 1, args + 2, args + 3); + cnt += writeTagProperty(TVG_TAG_FILL_LINEAR_GRADIENT, sizeof(args), args); } - auto flag = static_cast(f->spread()); - fillDataByteCnt += writeMember(TVG_TAG_FILL_FILLSPREAD, SIZE(TvgBinFlag), &flag); - fillDataByteCnt += writeMember(TVG_TAG_FILL_COLORSTOPS, stopsCnt * sizeof(stops), stops); + auto flag = static_cast(fill->spread()); + cnt += writeTagProperty(TVG_TAG_FILL_FILLSPREAD, SIZE(TvgBinFlag), &flag); + cnt += writeTagProperty(TVG_TAG_FILL_COLORSTOPS, stopsCnt * sizeof(stops), stops); - writeMemberDataSizeAt(fillDataByteCnt); + writeReservedCount(cnt); - return SIZE(TvgBinTag) + SIZE(TvgBinCounter) + fillDataByteCnt; + return SERIAL_DONE(cnt); } - TvgBinCounter serializeShapeStroke(const Shape* shape) + TvgBinCounter serializeStroke(const Shape* shape) { - TvgBinCounter strokeDataByteCnt = 0; - TvgBinFlag flag; + writeTag(TVG_TAG_SHAPE_STROKE); + reserveCount(); - writeMemberIndicator(TVG_TAG_SHAPE_STROKE); - skipInBufferMemberDataSize(); - - flag = static_cast(shape->strokeCap()); - strokeDataByteCnt += writeMember(TVG_TAG_SHAPE_STROKE_CAP, SIZE(TvgBinFlag), &flag); + //cap + auto flag = static_cast(shape->strokeCap()); + auto cnt = writeTagProperty(TVG_TAG_SHAPE_STROKE_CAP, SIZE(TvgBinFlag), &flag); + //join flag = static_cast(shape->strokeJoin()); - strokeDataByteCnt += writeMember(TVG_TAG_SHAPE_STROKE_JOIN, SIZE(TvgBinFlag), &flag); + cnt += writeTagProperty(TVG_TAG_SHAPE_STROKE_JOIN, SIZE(TvgBinFlag), &flag); - float width = shape->strokeWidth(); - strokeDataByteCnt += writeMember(TVG_TAG_SHAPE_STROKE_WIDTH, sizeof(width), &width); + //width + auto width = shape->strokeWidth(); + cnt += writeTagProperty(TVG_TAG_SHAPE_STROKE_WIDTH, sizeof(width), &width); + //fill if (auto fill = shape->strokeFill()) { - strokeDataByteCnt += serializeShapeFill(fill, TVG_TAG_SHAPE_STROKE_FILL); + cnt += serializeFill(fill, TVG_TAG_SHAPE_STROKE_FILL); } else { uint8_t color[4] = {0, 0, 0, 0}; shape->strokeColor(color, color + 1, color + 2, color + 3); - strokeDataByteCnt += writeMember(TVG_TAG_SHAPE_STROKE_COLOR, sizeof(color), &color); + cnt += writeTagProperty(TVG_TAG_SHAPE_STROKE_COLOR, sizeof(color), &color); } + //dash const float* dashPattern = nullptr; - uint32_t dashCnt = shape->strokeDash(&dashPattern); + auto dashCnt = shape->strokeDash(&dashPattern); if (dashPattern && dashCnt > 0) { - TvgBinCounter dashCntByteCnt = sizeof(dashCnt); - TvgBinCounter dashPtrnByteCnt = dashCnt * sizeof(dashPattern[0]); - - writeMemberIndicator(TVG_TAG_SHAPE_STROKE_DASHPTRN); - writeMemberDataSize(dashCntByteCnt + dashPtrnByteCnt); - strokeDataByteCnt += writeMemberData(&dashCnt, dashCntByteCnt); - strokeDataByteCnt += writeMemberData(dashPattern, dashPtrnByteCnt); - strokeDataByteCnt += SIZE(TvgBinTag) + SIZE(TvgBinCounter); + TvgBinCounter dashCntSize = sizeof(dashCnt); + TvgBinCounter dashPtrnSize = dashCnt * sizeof(dashPattern[0]); + + writeTag(TVG_TAG_SHAPE_STROKE_DASHPTRN); + writeCount(dashCntSize + dashPtrnSize); + cnt += writeData(&dashCnt, dashCntSize); + cnt += writeData(dashPattern, dashPtrnSize); + cnt += SIZE(TvgBinTag) + SIZE(TvgBinCounter); } - writeMemberDataSizeAt(strokeDataByteCnt); + writeReservedCount(cnt); - return SIZE(TvgBinTag) + SIZE(TvgBinCounter) + strokeDataByteCnt; + return SERIAL_DONE(cnt); } - TvgBinCounter serializeShapePath(const Shape* shape) + TvgBinCounter serializePath(const Shape* shape) { const PathCommand* cmds = nullptr; - uint32_t cmdCnt = shape->pathCommands(&cmds); + auto cmdCnt = shape->pathCommands(&cmds); const Point* pts = nullptr; - uint32_t ptsCnt = shape->pathCoords(&pts); - - if (!cmds || !pts || !cmdCnt || !ptsCnt) return 0; + auto ptsCnt = shape->pathCoords(&pts); - TvgBinCounter pathDataByteCnt = 0; + if (!cmds || !pts || cmdCnt == 0 || ptsCnt == 0) return 0; - writeMemberIndicator(TVG_TAG_SHAPE_PATH); - skipInBufferMemberDataSize(); + writeTag(TVG_TAG_SHAPE_PATH); + reserveCount(); - pathDataByteCnt += writeMemberData(&cmdCnt, sizeof(cmdCnt)); - pathDataByteCnt += writeMemberData(&ptsCnt, sizeof(ptsCnt)); - pathDataByteCnt += writeMemberData(cmds, cmdCnt * sizeof(cmds[0])); - pathDataByteCnt += writeMemberData(pts, ptsCnt * sizeof(pts[0])); + auto cnt = writeData(&cmdCnt, sizeof(cmdCnt)); + cnt += writeData(&ptsCnt, sizeof(ptsCnt)); + cnt += writeData(cmds, cmdCnt * sizeof(cmds[0])); + cnt += writeData(pts, ptsCnt * sizeof(pts[0])); - writeMemberDataSizeAt(pathDataByteCnt); + writeReservedCount(cnt); - return SIZE(TvgBinTag) + SIZE(TvgBinCounter) + pathDataByteCnt; + return SERIAL_DONE(cnt); } - TvgBinCounter serialize(const Shape* shape) + TvgBinCounter serializeShape(const Shape* shape) { - writeMemberIndicator(TVG_TAG_CLASS_SHAPE); - skipInBufferMemberDataSize(); + writeTag(TVG_TAG_CLASS_SHAPE); + reserveCount(); - auto ruleTvgBinFlag = (shape->fillRule() == FillRule::EvenOdd) ? TVG_FLAG_SHAPE_FILLRULE_EVENODD : TVG_FLAG_SHAPE_FILLRULE_WINDING; - auto shapeDataByteCnt = writeMember(TVG_TAG_SHAPE_FILLRULE, SIZE(TvgBinFlag), &ruleTvgBinFlag); + //fill rule + auto flag = (shape->fillRule() == FillRule::EvenOdd) ? TVG_FLAG_SHAPE_FILLRULE_EVENODD : TVG_FLAG_SHAPE_FILLRULE_WINDING; + auto cnt = writeTagProperty(TVG_TAG_SHAPE_FILLRULE, SIZE(TvgBinFlag), &flag); - if (shape->strokeWidth() > 0) shapeDataByteCnt += serializeShapeStroke(shape); + //stroke + if (shape->strokeWidth() > 0) cnt += serializeStroke(shape); + //fill if (auto fill = shape->fill()) { - shapeDataByteCnt += serializeShapeFill(fill, TVG_TAG_SHAPE_FILL); + cnt += serializeFill(fill, TVG_TAG_SHAPE_FILL); } else { uint8_t color[4] = {0, 0, 0, 0}; shape->fillColor(color, color + 1, color + 2, color + 3); - shapeDataByteCnt += writeMember(TVG_TAG_SHAPE_COLOR, sizeof(color), color); + cnt += writeTagProperty(TVG_TAG_SHAPE_COLOR, sizeof(color), color); } - shapeDataByteCnt += serializeShapePath(shape); - shapeDataByteCnt += serializePaint(shape); + cnt += serializePath(shape); + cnt += serializePaint(shape); - writeMemberDataSizeAt(shapeDataByteCnt); + writeReservedCount(cnt); - return SIZE(TvgBinTag) + SIZE(TvgBinCounter) + shapeDataByteCnt; + return SERIAL_DONE(cnt); } - TvgBinCounter serialize(const Picture* picture) + TvgBinCounter serializePicture(const Picture* picture) { - auto pixels = picture->data(); - - TvgBinCounter pictureDataByteCnt = 0; - - writeMemberIndicator(TVG_TAG_CLASS_PICTURE); - skipInBufferMemberDataSize(); - - if (pixels) { - //TODO - loader expects uints - float vw, vh; - picture->viewbox(nullptr, nullptr, &vw, &vh); - - uint32_t w = static_cast(vw); - uint32_t h = static_cast(vh); - TvgBinCounter wByteCnt = sizeof(w); // same as h size - TvgBinCounter pixelsByteCnt = w * h * sizeof(pixels[0]); - - writeMemberIndicator(TVG_TAG_PICTURE_RAW_IMAGE); - writeMemberDataSize(2 * wByteCnt + pixelsByteCnt); - pictureDataByteCnt += writeMemberData(&w, wByteCnt); - pictureDataByteCnt += writeMemberData(&h, wByteCnt); - pictureDataByteCnt += writeMemberData(pixels, pixelsByteCnt); - pictureDataByteCnt += SIZE(TvgBinTag) + SIZE(TvgBinCounter); + writeTag(TVG_TAG_CLASS_PICTURE); + reserveCount(); + + TvgBinCounter cnt = 0; + + //Bitmap Image + if (auto pixels = picture->data()) { + //TODO: Loader expects uints + float fw, fh; + picture->size(&fw, &fh); + + auto w = static_cast(fw); + auto h = static_cast(fh); + TvgBinCounter sizeCnt = sizeof(w); + TvgBinCounter imgSize = w * h * sizeof(pixels[0]); + + writeTag(TVG_TAG_PICTURE_RAW_IMAGE); + writeCount(2 * sizeCnt + imgSize); + + cnt += writeData(&w, sizeCnt); + cnt += writeData(&h, sizeCnt); + cnt += writeData(pixels, imgSize); + cnt += SIZE(TvgBinTag) + SIZE(TvgBinCounter); + //Vector Image } else { - pictureDataByteCnt += serializeChildren(picture); + cnt += serializeChildren(picture); } - pictureDataByteCnt += serializePaint(picture); + cnt += serializePaint(picture); - writeMemberDataSizeAt(pictureDataByteCnt); + writeReservedCount(cnt); - return SIZE(TvgBinTag) + SIZE(TvgBinCounter) + pictureDataByteCnt; + return SERIAL_DONE(cnt); } TvgBinCounter serializeComposite(const Paint* cmpTarget, CompositeMethod cmpMethod) { - TvgBinCounter cmpDataByteCnt = 0; + writeTag(TVG_TAG_PAINT_CMP_TARGET); + reserveCount(); - writeMemberIndicator(TVG_TAG_PAINT_CMP_TARGET); - skipInBufferMemberDataSize(); + auto flag = static_cast(cmpMethod); + auto cnt = writeTagProperty(TVG_TAG_PAINT_CMP_METHOD, SIZE(TvgBinFlag), &flag); - auto cmpMethodTvgBinFlag = static_cast(cmpMethod); - cmpDataByteCnt += writeMember(TVG_TAG_PAINT_CMP_METHOD, SIZE(TvgBinFlag), &cmpMethodTvgBinFlag); + cnt += serialize(cmpTarget); - cmpDataByteCnt += serialize(cmpTarget); + writeReservedCount(cnt); - writeMemberDataSizeAt(cmpDataByteCnt); - - return SIZE(TvgBinTag) + SIZE(TvgBinCounter) + cmpDataByteCnt; + return SERIAL_DONE(cnt); } TvgBinCounter serializeChildren(const Paint* paint) { - TvgBinCounter dataByteCnt = 0; - auto it = paint->pImpl->iterator(); + if (!it) return 0; - while (auto p = it->next()) { - dataByteCnt += serialize(p); - } + TvgBinCounter cnt = 0; + + while (auto p = it->next()) + cnt += serialize(p); delete(it); - return dataByteCnt; + return cnt; } TvgBinCounter serialize(const Paint* paint) @@ -367,9 +381,9 @@ struct Saver::Impl if (!paint) return 0; switch (paint->id()) { - case TVG_CLASS_ID_SHAPE: return serialize(static_cast(paint)); - case TVG_CLASS_ID_SCENE: return serialize(static_cast(paint)); - case TVG_CLASS_ID_PICTURE: return serialize(static_cast(paint)); + case TVG_CLASS_ID_SHAPE: return serializeShape(static_cast(paint)); + case TVG_CLASS_ID_SCENE: return serializeScene(static_cast(paint)); + case TVG_CLASS_ID_PICTURE: return serializePicture(static_cast(paint)); } return 0; @@ -386,7 +400,7 @@ struct Saver::Impl if (!writeHeader()) return false; if (serialize(paint) == 0) return false; - if (!bufferToFile(path)) return false; + if (!flushTo(path)) return false; return true; } -- 2.7.4