sw_engine: revise scale transform logic.

Basically, stroke width size is linear,

engine couldn't apply scale factor from the matrix which contains 2 dimensional values.

Thus, we can apply it if the scale factor of x/y is identical.

Otherwise, we should transform every stroke points in the stroking process.
That scenario can be improved with another patch.

Change-Id: I070dcf29d2e42f21e182bdf4239781464158ef73
This commit is contained in:
Hermet Park 2020-07-21 20:24:25 +09:00
parent 5dcafb8b89
commit 4d72eeda15
5 changed files with 17 additions and 9 deletions

View file

@ -156,6 +156,7 @@ struct SwStroke
bool firstPt; bool firstPt;
bool openSubPath; bool openSubPath;
bool handleWideStrokes; bool handleWideStrokes;
bool preScaled;
}; };
struct SwDashStroke struct SwDashStroke
@ -259,7 +260,7 @@ bool shapeGenOutline(SwShape& shape, const Shape* sdata, const Matrix* transform
bool shapePrepare(SwShape& shape, const Shape* sdata, const SwSize& clip, const Matrix* transform); bool shapePrepare(SwShape& shape, const Shape* sdata, const SwSize& clip, const Matrix* transform);
bool shapeGenRle(SwShape& shape, const Shape* sdata, const SwSize& clip, bool antiAlias); bool shapeGenRle(SwShape& shape, const Shape* sdata, const SwSize& clip, bool antiAlias);
void shapeDelOutline(SwShape& shape); void shapeDelOutline(SwShape& shape);
void shapeResetStroke(SwShape& shape, const Shape* sdata); void shapeResetStroke(SwShape& shape, const Shape* sdata, const Matrix* transform);
bool shapeGenStrokeRle(SwShape& shape, const Shape* sdata, const Matrix* transform, const SwSize& clip); bool shapeGenStrokeRle(SwShape& shape, const Shape* sdata, const Matrix* transform, const SwSize& clip);
void shapeFree(SwShape& shape); void shapeFree(SwShape& shape);
void shapeDelStroke(SwShape& shape); void shapeDelStroke(SwShape& shape);
@ -267,7 +268,7 @@ bool shapeGenFillColors(SwShape& shape, const Fill* fill, const Matrix* transfor
void shapeResetFill(SwShape& shape); void shapeResetFill(SwShape& shape);
void shapeDelFill(SwShape& shape); void shapeDelFill(SwShape& shape);
void strokeReset(SwStroke& stroke, const Shape* shape); void strokeReset(SwStroke& stroke, const Shape* shape, const Matrix* transform);
bool strokeParseOutline(SwStroke& stroke, const SwOutline& outline); bool strokeParseOutline(SwStroke& stroke, const SwOutline& outline);
SwOutline* strokeExportOutline(SwStroke& stroke); SwOutline* strokeExportOutline(SwStroke& stroke);
void strokeFree(SwStroke* stroke); void strokeFree(SwStroke* stroke);

View file

@ -211,7 +211,7 @@ void* SwRenderer::prepare(const Shape& sdata, void* data, const RenderTransform*
//Stroke //Stroke
if (task->flags & (RenderUpdateFlag::Stroke | RenderUpdateFlag::Transform)) { if (task->flags & (RenderUpdateFlag::Stroke | RenderUpdateFlag::Transform)) {
if (strokeAlpha > 0) { if (strokeAlpha > 0) {
shapeResetStroke(task->shape, task->sdata); shapeResetStroke(task->shape, task->sdata, task->transform);
if (!shapeGenStrokeRle(task->shape, task->sdata, task->transform, task->clip)) return; if (!shapeGenStrokeRle(task->shape, task->sdata, task->transform, task->clip)) return;
} else { } else {
shapeDelStroke(task->shape); shapeDelStroke(task->shape);
@ -257,4 +257,4 @@ SwRenderer* SwRenderer::inst()
return static_cast<SwRenderer*>(RenderInitializer::inst(renderInit)); return static_cast<SwRenderer*>(RenderInitializer::inst(renderInit));
} }
#endif /* _TVG_SW_RENDERER_CPP_ */ #endif /* _TVG_SW_RENDERER_CPP_ */

View file

@ -618,13 +618,13 @@ void shapeDelStroke(SwShape& shape)
} }
void shapeResetStroke(SwShape& shape, const Shape* sdata) void shapeResetStroke(SwShape& shape, const Shape* sdata, const Matrix* transform)
{ {
if (!shape.stroke) shape.stroke = static_cast<SwStroke*>(calloc(1, sizeof(SwStroke))); if (!shape.stroke) shape.stroke = static_cast<SwStroke*>(calloc(1, sizeof(SwStroke)));
auto stroke = shape.stroke; auto stroke = shape.stroke;
assert(stroke); assert(stroke);
strokeReset(*stroke, sdata); strokeReset(*stroke, sdata, transform);
rleFree(shape.strokeRle); rleFree(shape.strokeRle);
shape.strokeRle = nullptr; shape.strokeRle = nullptr;

View file

@ -818,11 +818,18 @@ void strokeFree(SwStroke* stroke)
} }
void strokeReset(SwStroke& stroke, const Shape* sdata) void strokeReset(SwStroke& stroke, const Shape* sdata, const Matrix* transform)
{ {
assert(sdata); assert(sdata);
stroke.width = TO_SWCOORD(sdata->strokeWidth() * 0.5); //If x/y scale factor is identical, we can scale width size simply.
auto scale = 1.0f;
if (transform && fabsf(transform->e11 - transform->e22) < FLT_EPSILON) {
scale = transform->e11;
stroke.preScaled = true;
}
stroke.width = TO_SWCOORD(sdata->strokeWidth() * 0.5 * scale);
stroke.cap = sdata->strokeCap(); stroke.cap = sdata->strokeCap();
//Save line join: it can be temporarily changed when stroking curves... //Save line join: it can be temporarily changed when stroking curves...

View file

@ -32,7 +32,7 @@ enum RenderUpdateFlag {None = 0, Path = 1, Color = 2, Gradient = 4, Stroke = 8,
struct RenderTransform struct RenderTransform
{ {
Matrix m; //3x3 Matrix Elements Matrix m; //3x3 Matrix Elements
float x = 0.0f; float x = 0.0f;
float y = 0.0f; float y = 0.0f;
float degree = 0.0f; //rotation degree float degree = 0.0f; //rotation degree