tvg_saver: fix the incorrect stroke transformation

Saver tries to pre-transfom to skip the matrix data,
but it missed the case - transformed stroking,

we skip it also only when xy scaling factors are same excluding the dash properties,
because scaled of the stroking is depent on the engines,
we have no idea of the proper input data in advance.

@Issues: https://github.com/Samsung/thorvg/issues/773
This commit is contained in:
Hermet Park 2021-09-07 14:34:04 +09:00 committed by Mira Grudzinska
parent b421660676
commit f1d9f691cc
2 changed files with 22 additions and 14 deletions

View file

@ -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,15 +515,14 @@ TvgBinCounter TvgSaver::serializePath(const Shape* shape, const Matrix* pTransfo
cnt += writeData(outCmds, SIZE(outCmds));
//transform?
auto transform = const_cast<Shape*>(shape)->transform();
if (pTransform) transform = _multiply(pTransform, &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<Point*>(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<TvgBinFlag>(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);

View file

@ -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);