mirror of
https://github.com/thorvg/thorvg.git
synced 2025-07-28 17:15:57 +00:00
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:
parent
b421660676
commit
f1d9f691cc
2 changed files with 22 additions and 14 deletions
|
@ -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);
|
writeTag(TVG_TAG_SHAPE_STROKE);
|
||||||
reserveCount();
|
reserveCount();
|
||||||
|
|
||||||
//width
|
//width
|
||||||
auto width = shape->strokeWidth();
|
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);
|
auto cnt = writeTagProperty(TVG_TAG_SHAPE_STROKE_WIDTH, SIZE(width), &width);
|
||||||
|
|
||||||
//cap
|
//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;
|
const PathCommand* cmds = nullptr;
|
||||||
auto cmdCnt = shape->pathCommands(&cmds);
|
auto cmdCnt = shape->pathCommands(&cmds);
|
||||||
|
@ -514,14 +515,13 @@ TvgBinCounter TvgSaver::serializePath(const Shape* shape, const Matrix* pTransfo
|
||||||
cnt += writeData(outCmds, SIZE(outCmds));
|
cnt += writeData(outCmds, SIZE(outCmds));
|
||||||
|
|
||||||
//transform?
|
//transform?
|
||||||
auto transform = const_cast<Shape*>(shape)->transform();
|
if (preTransform) {
|
||||||
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 ||
|
||||||
if (fabs(transform.e11 - 1) > FLT_EPSILON || fabs(transform.e12) > FLT_EPSILON || fabs(transform.e13) > FLT_EPSILON ||
|
fabs(transform.e31) > FLT_EPSILON || fabs(transform.e32) > FLT_EPSILON || fabs(transform.e33 - 1) > FLT_EPSILON) {
|
||||||
fabs(transform.e21) > FLT_EPSILON || fabs(transform.e22 - 1) > FLT_EPSILON || fabs(transform.e23) > FLT_EPSILON ||
|
auto p = const_cast<Point*>(pts);
|
||||||
fabs(transform.e31) > FLT_EPSILON || fabs(transform.e32) > FLT_EPSILON || fabs(transform.e33 - 1) > FLT_EPSILON) {
|
for (uint32_t i = 0; i < ptsCnt; ++i) _multiply(p++, transform);
|
||||||
auto p = const_cast<Point*>(pts);
|
}
|
||||||
for (uint32_t i = 0; i < ptsCnt; ++i) _multiply(p++, transform);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cnt += writeData(pts, ptsCnt * SIZE(pts[0]));
|
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()))
|
if (auto flag = static_cast<TvgBinFlag>(shape->fillRule()))
|
||||||
cnt = writeTagProperty(TVG_TAG_SHAPE_FILLRULE, SIZE(TvgBinFlag), &flag);
|
cnt = writeTagProperty(TVG_TAG_SHAPE_FILLRULE, SIZE(TvgBinFlag), &flag);
|
||||||
|
|
||||||
|
|
||||||
|
bool preTransform = true;
|
||||||
|
|
||||||
//stroke
|
//stroke
|
||||||
if (shape->strokeWidth() > 0) {
|
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};
|
uint8_t color[4] = {0, 0, 0, 0};
|
||||||
shape->strokeColor(color, color + 1, color + 2, color + 3);
|
shape->strokeColor(color, color + 1, color + 2, color + 3);
|
||||||
auto fill = shape->strokeFill();
|
auto fill = shape->strokeFill();
|
||||||
if (fill || color[3] > 0) cnt += serializeStroke(shape, &transform);
|
if (fill || color[3] > 0) cnt += serializeStroke(shape, &transform, preTransform);
|
||||||
}
|
}
|
||||||
|
|
||||||
//fill
|
//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);
|
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);
|
cnt += serializePaint(shape, pTransform);
|
||||||
|
|
||||||
writeReservedCount(cnt);
|
writeReservedCount(cnt);
|
||||||
|
|
|
@ -58,8 +58,8 @@ private:
|
||||||
TvgBinCounter serializePicture(const Picture* picture, const Matrix* pTransform);
|
TvgBinCounter serializePicture(const Picture* picture, const Matrix* pTransform);
|
||||||
TvgBinCounter serializePaint(const Paint* paint, const Matrix* pTransform);
|
TvgBinCounter serializePaint(const Paint* paint, const Matrix* pTransform);
|
||||||
TvgBinCounter serializeFill(const Fill* fill, TvgBinTag tag, const Matrix* pTransform);
|
TvgBinCounter serializeFill(const Fill* fill, TvgBinTag tag, const Matrix* pTransform);
|
||||||
TvgBinCounter serializeStroke(const Shape* shape, const Matrix* pTransform);
|
TvgBinCounter serializeStroke(const Shape* shape, const Matrix* pTransform, bool preTransform);
|
||||||
TvgBinCounter serializePath(const Shape* shape, const Matrix* pTransform);
|
TvgBinCounter serializePath(const Shape* shape, const Matrix& transform, bool preTransform);
|
||||||
TvgBinCounter serializeComposite(const Paint* cmpTarget, CompositeMethod cmpMethod, const Matrix* pTransform);
|
TvgBinCounter serializeComposite(const Paint* cmpTarget, CompositeMethod cmpMethod, const Matrix* pTransform);
|
||||||
TvgBinCounter serializeChildren(Iterator* it, const Matrix* transform, bool reserved);
|
TvgBinCounter serializeChildren(Iterator* it, const Matrix* transform, bool reserved);
|
||||||
TvgBinCounter serializeChild(const Paint* parent, const Paint* child, const Matrix* pTransform);
|
TvgBinCounter serializeChild(const Paint* parent, const Paint* child, const Matrix* pTransform);
|
||||||
|
|
Loading…
Add table
Reference in a new issue