diff --git a/src/savers/tvg/tvgTvgSaver.cpp b/src/savers/tvg/tvgTvgSaver.cpp index 26a2e9d2..21d3f12a 100644 --- a/src/savers/tvg/tvgTvgSaver.cpp +++ b/src/savers/tvg/tvgTvgSaver.cpp @@ -444,13 +444,14 @@ TvgBinCounter TvgSaver::serializeFill(const Fill* fill, TvgBinTag tag, const Mat } -TvgBinCounter TvgSaver::serializeStroke(const Shape* shape, const Matrix* pTransform) +TvgBinCounter TvgSaver::serializeStroke(const Shape* shape, const Matrix* pTransform, bool preTransform) { writeTag(TVG_TAG_SHAPE_STROKE); reserveCount(); //width auto width = shape->strokeWidth(); + if (preTransform) width *= pTransform->e11; //we know x/y scaling factors are same. auto cnt = writeTagProperty(TVG_TAG_SHAPE_STROKE_WIDTH, SIZE(width), &width); //cap @@ -490,7 +491,7 @@ TvgBinCounter TvgSaver::serializeStroke(const Shape* shape, const Matrix* pTrans } -TvgBinCounter TvgSaver::serializePath(const Shape* shape, const Matrix* pTransform) +TvgBinCounter TvgSaver::serializePath(const Shape* shape, const Matrix& transform, bool preTransform) { const PathCommand* cmds = nullptr; auto cmdCnt = shape->pathCommands(&cmds); @@ -514,14 +515,13 @@ TvgBinCounter TvgSaver::serializePath(const Shape* shape, const Matrix* pTransfo cnt += writeData(outCmds, SIZE(outCmds)); //transform? - auto transform = const_cast(shape)->transform(); - if (pTransform) transform = _multiply(pTransform, &transform); - - if (fabs(transform.e11 - 1) > FLT_EPSILON || fabs(transform.e12) > FLT_EPSILON || fabs(transform.e13) > FLT_EPSILON || - fabs(transform.e21) > FLT_EPSILON || fabs(transform.e22 - 1) > FLT_EPSILON || fabs(transform.e23) > FLT_EPSILON || - fabs(transform.e31) > FLT_EPSILON || fabs(transform.e32) > FLT_EPSILON || fabs(transform.e33 - 1) > FLT_EPSILON) { - auto p = const_cast(pts); - for (uint32_t i = 0; i < ptsCnt; ++i) _multiply(p++, transform); + if (preTransform) { + if (fabs(transform.e11 - 1) > FLT_EPSILON || fabs(transform.e12) > FLT_EPSILON || fabs(transform.e13) > FLT_EPSILON || + fabs(transform.e21) > FLT_EPSILON || fabs(transform.e22 - 1) > FLT_EPSILON || fabs(transform.e23) > FLT_EPSILON || + fabs(transform.e31) > FLT_EPSILON || fabs(transform.e32) > FLT_EPSILON || fabs(transform.e33 - 1) > FLT_EPSILON) { + auto p = const_cast(pts); + for (uint32_t i = 0; i < ptsCnt; ++i) _multiply(p++, transform); + } } cnt += writeData(pts, ptsCnt * SIZE(pts[0])); @@ -545,12 +545,18 @@ TvgBinCounter TvgSaver::serializeShape(const Shape* shape, const Matrix* pTransf if (auto flag = static_cast(shape->fillRule())) cnt = writeTagProperty(TVG_TAG_SHAPE_FILLRULE, SIZE(TvgBinFlag), &flag); + + bool preTransform = true; + //stroke if (shape->strokeWidth() > 0) { + //We can't apply pre-transformation if the stroke has the irregular scaling per directions or it has dash. + if (abs(transform.e11 - transform.e22) > FLT_EPSILON || shape->strokeDash(nullptr) > 0) preTransform = false; + uint8_t color[4] = {0, 0, 0, 0}; shape->strokeColor(color, color + 1, color + 2, color + 3); auto fill = shape->strokeFill(); - if (fill || color[3] > 0) cnt += serializeStroke(shape, &transform); + if (fill || color[3] > 0) cnt += serializeStroke(shape, &transform, preTransform); } //fill @@ -562,7 +568,9 @@ TvgBinCounter TvgSaver::serializeShape(const Shape* shape, const Matrix* pTransf if (color[3] > 0) cnt += writeTagProperty(TVG_TAG_SHAPE_COLOR, SIZE(color), color); } - cnt += serializePath(shape, pTransform); + cnt += serializePath(shape, transform, preTransform); + + if (!preTransform) cnt += writeTransform(transform); cnt += serializePaint(shape, pTransform); writeReservedCount(cnt); diff --git a/src/savers/tvg/tvgTvgSaver.h b/src/savers/tvg/tvgTvgSaver.h index 155f3500..8839f3c6 100644 --- a/src/savers/tvg/tvgTvgSaver.h +++ b/src/savers/tvg/tvgTvgSaver.h @@ -58,8 +58,8 @@ private: TvgBinCounter serializePicture(const Picture* picture, const Matrix* pTransform); TvgBinCounter serializePaint(const Paint* paint, const Matrix* pTransform); TvgBinCounter serializeFill(const Fill* fill, TvgBinTag tag, const Matrix* pTransform); - TvgBinCounter serializeStroke(const Shape* shape, const Matrix* pTransform); - TvgBinCounter serializePath(const Shape* shape, const Matrix* pTransform); + TvgBinCounter serializeStroke(const Shape* shape, const Matrix* pTransform, bool preTransform); + TvgBinCounter serializePath(const Shape* shape, const Matrix& transform, bool preTransform); TvgBinCounter serializeComposite(const Paint* cmpTarget, CompositeMethod cmpMethod, const Matrix* pTransform); TvgBinCounter serializeChildren(Iterator* it, const Matrix* transform, bool reserved); TvgBinCounter serializeChild(const Paint* parent, const Paint* child, const Matrix* pTransform);