Reland "Another fix for dash line thickness."

This is a reland of bf1904fd48

Fix for case of scaling matrix and update GM to use a scaling
matrix.

Original change's description:
> Another fix for dash line thickness.
>
> Use the device space offset from the dash centerline for
> antialiasing in y direction.
>
> Bug: chromium:1049028
>
> Change-Id: Ib6363579680d05cbf1fe34795695422baeca7065
> Reviewed-on: https://skia-review.googlesource.com/c/skia/+/288764
> Reviewed-by: Greg Daniel <egdaniel@google.com>
> Commit-Queue: Brian Salomon <bsalomon@google.com>

Bug: chromium:1049028
Change-Id: I6d2b04f9cf5de302c41045c2e2494cee43092d9a
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/288976
Reviewed-by: Greg Daniel <egdaniel@google.com>
Commit-Queue: Brian Salomon <bsalomon@google.com>
This commit is contained in:
Brian Salomon 2020-05-08 15:32:28 -04:00 committed by Skia Commit-Bot
parent c74db7998b
commit 518fd4d9d0
2 changed files with 48 additions and 32 deletions

View File

@ -585,20 +585,26 @@ DEF_SIMPLE_GM(dash_line_zero_off_interval, canvas, 160, 330) {
}
}
DEF_SIMPLE_GM(thin_aa_dash_lines, canvas, 110, 110) {
DEF_SIMPLE_GM(thin_aa_dash_lines, canvas, 330, 110) {
SkPaint paint;
static constexpr SkScalar kIntervals[] = {10, 5};
static constexpr SkScalar kScale = 100.f;
static constexpr SkScalar kIntervals[] = {10/kScale, 5/kScale};
paint.setPathEffect(SkDashPathEffect::Make(kIntervals, SK_ARRAY_COUNT(kIntervals), 0.f));
paint.setAntiAlias(true);
paint.setStrokeWidth(0.25f);
paint.setStrokeWidth(0.25f/kScale);
// substep moves the subpixel offset every iteration.
static constexpr SkScalar kSubstep = 0.05f;
static constexpr SkScalar kSubstep = 0.05f/kScale;
// We will draw a grid of horiz/vertical lines that pass through each other's off intervals.
static constexpr SkScalar kStep = kIntervals[0] + kIntervals[1];
canvas->scale(kScale, kScale);
canvas->translate(kIntervals[1], kIntervals[1]);
for (SkScalar x = -.5f*kIntervals[1]; x < 105; x += (kStep + kSubstep)) {
canvas->drawLine({x, 0}, {x, 100}, paint);
canvas->drawLine({0, x}, {100, x}, paint);
for (auto c : {SkPaint::kButt_Cap, SkPaint::kSquare_Cap, SkPaint::kRound_Cap}) {
paint.setStrokeCap(c);
for (SkScalar x = -.5f*kIntervals[1]; x < 105/kScale; x += (kStep + kSubstep)) {
canvas->drawLine({x, 0}, {x, 100/kScale}, paint);
canvas->drawLine({0, x}, {100/kScale, x}, paint);
}
canvas->translate(110/kScale, 0);
}
}

View File

@ -152,13 +152,24 @@ enum DashCap {
kNonRound_DashCap,
};
static void setup_dashed_rect(const SkRect& rect, GrVertexWriter& vertices, const SkMatrix& matrix,
SkScalar offset, SkScalar bloatX, SkScalar bloatY, SkScalar len,
SkScalar stroke, SkScalar startInterval, SkScalar endInterval,
SkScalar strokeWidth, DashCap cap) {
static void setup_dashed_rect(const SkRect& rect,
GrVertexWriter& vertices,
const SkMatrix& matrix,
SkScalar offset,
SkScalar bloatX,
SkScalar len,
SkScalar startInterval,
SkScalar endInterval,
SkScalar strokeWidth,
SkScalar perpScale,
DashCap cap) {
SkScalar intervalLength = startInterval + endInterval;
SkRect dashRect = { offset - bloatX, -stroke - bloatY,
offset + len + bloatX, stroke + bloatY };
// 'dashRect' gets interpolated over the rendered 'rect'. For y we want the perpendicular signed
// distance from the stroke center line in device space. 'perpScale' is the scale factor applied
// to the y dimension of 'rect' isolated from 'matrix'.
SkScalar halfDevRectHeight = rect.height()*perpScale/2.f;
SkRect dashRect = { offset - bloatX, -halfDevRectHeight,
offset + len + bloatX, halfDevRectHeight};
if (kRound_DashCap == cap) {
SkScalar radius = SkScalarHalf(strokeWidth) - 0.5f;
@ -318,9 +329,8 @@ private:
SkScalar fStartOffset;
SkScalar fStrokeWidth;
SkScalar fLineLength;
SkScalar fHalfDevStroke;
SkScalar fDevBloatX;
SkScalar fDevBloatY;
SkScalar fPerpendicularScale;
bool fLineDone;
bool fHasStartRect;
bool fHasEndRect;
@ -596,8 +606,7 @@ private:
draw.fStartOffset = startOffset;
draw.fDevBloatX = devBloatX;
draw.fDevBloatY = devBloatY;
draw.fHalfDevStroke = halfDevStroke;
draw.fPerpendicularScale = args.fPerpendicularScale;
draw.fStrokeWidth = strokeWidth;
draw.fHasStartRect = hasStartRect;
draw.fLineDone = lineDone;
@ -620,11 +629,12 @@ private:
if (!draws[i].fLineDone) {
if (fullDash) {
setup_dashed_rect(
rects[rectIndex], vertices, geom.fSrcRotInv,
draws[i].fStartOffset, draws[i].fDevBloatX, draws[i].fDevBloatY,
draws[i].fLineLength, draws[i].fHalfDevStroke, draws[i].fIntervals[0],
draws[i].fIntervals[1], draws[i].fStrokeWidth, capType);
setup_dashed_rect(rects[rectIndex], vertices, geom.fSrcRotInv,
draws[i].fStartOffset, draws[i].fDevBloatX,
draws[i].fLineLength, draws[i].fIntervals[0],
draws[i].fIntervals[1], draws[i].fStrokeWidth,
draws[i].fPerpendicularScale,
capType);
} else {
vertices.writeQuad(GrQuad::MakeFromRect(rects[rectIndex], geom.fSrcRotInv));
}
@ -633,11 +643,11 @@ private:
if (draws[i].fHasStartRect) {
if (fullDash) {
setup_dashed_rect(
rects[rectIndex], vertices, geom.fSrcRotInv,
draws[i].fStartOffset, draws[i].fDevBloatX, draws[i].fDevBloatY,
draws[i].fIntervals[0], draws[i].fHalfDevStroke, draws[i].fIntervals[0],
draws[i].fIntervals[1], draws[i].fStrokeWidth, capType);
setup_dashed_rect(rects[rectIndex], vertices, geom.fSrcRotInv,
draws[i].fStartOffset, draws[i].fDevBloatX,
draws[i].fIntervals[0], draws[i].fIntervals[0],
draws[i].fIntervals[1], draws[i].fStrokeWidth,
draws[i].fPerpendicularScale, capType);
} else {
vertices.writeQuad(GrQuad::MakeFromRect(rects[rectIndex], geom.fSrcRotInv));
}
@ -646,11 +656,11 @@ private:
if (draws[i].fHasEndRect) {
if (fullDash) {
setup_dashed_rect(
rects[rectIndex], vertices, geom.fSrcRotInv,
draws[i].fStartOffset, draws[i].fDevBloatX, draws[i].fDevBloatY,
draws[i].fIntervals[0], draws[i].fHalfDevStroke, draws[i].fIntervals[0],
draws[i].fIntervals[1], draws[i].fStrokeWidth, capType);
setup_dashed_rect(rects[rectIndex], vertices, geom.fSrcRotInv,
draws[i].fStartOffset, draws[i].fDevBloatX,
draws[i].fIntervals[0], draws[i].fIntervals[0],
draws[i].fIntervals[1], draws[i].fStrokeWidth,
draws[i].fPerpendicularScale, capType);
} else {
vertices.writeQuad(GrQuad::MakeFromRect(rects[rectIndex], geom.fSrcRotInv));
}