diff options
author | reed <reed@google.com> | 2015-04-14 10:40:44 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-04-14 10:40:44 -0700 |
commit | 5dc6b7d1a8bc591d62366ff83c434ff74f3e10fc (patch) | |
tree | 25b4f701bfc2b56e28a2ed03cd5a0eecc2aefba9 /src/core/SkScan_Hairline.cpp | |
parent | b5de630d10982c0e650b842fe15cee2eb9efabbd (diff) |
change hairline procs to take array of points
BUG=skia:
Review URL: https://codereview.chromium.org/1085883002
Diffstat (limited to 'src/core/SkScan_Hairline.cpp')
-rw-r--r-- | src/core/SkScan_Hairline.cpp | 199 |
1 files changed, 102 insertions, 97 deletions
diff --git a/src/core/SkScan_Hairline.cpp b/src/core/SkScan_Hairline.cpp index 8cce57b8c9..0f2308b1f7 100644 --- a/src/core/SkScan_Hairline.cpp +++ b/src/core/SkScan_Hairline.cpp @@ -40,102 +40,105 @@ static bool canConvertFDot6ToFixed(SkFDot6 x) { } #endif -void SkScan::HairLineRgn(SkPoint pt0, SkPoint pt1, const SkRegion* clip, SkBlitter* blitter) { +void SkScan::HairLineRgn(const SkPoint array[], int arrayCount, const SkRegion* clip, + SkBlitter* origBlitter) { SkBlitterClipper clipper; - SkRect r; SkIRect clipR, ptsR; - SkPoint pts[2] = { pt0, pt1 }; - // We have to pre-clip the line to fit in a SkFixed, so we just chop - // the line. TODO find a way to actually draw beyond that range. - { - SkRect fixedBounds; - const SkScalar max = SkIntToScalar(32767); - fixedBounds.set(-max, -max, max, max); - if (!SkLineClipper::IntersectLine(pts, fixedBounds, pts)) { - return; - } - } + const SkScalar max = SkIntToScalar(32767); + const SkRect fixedBounds = SkRect::MakeLTRB(-max, -max, max, max); + SkRect clipBounds; if (clip) { - // Perform a clip in scalar space, so we catch huge values which might - // be missed after we convert to SkFDot6 (overflow) - r.set(clip->getBounds()); - if (!SkLineClipper::IntersectLine(pts, r, pts)) { - return; - } + clipBounds.set(clip->getBounds()); } - SkFDot6 x0 = SkScalarToFDot6(pts[0].fX); - SkFDot6 y0 = SkScalarToFDot6(pts[0].fY); - SkFDot6 x1 = SkScalarToFDot6(pts[1].fX); - SkFDot6 y1 = SkScalarToFDot6(pts[1].fY); + for (int i = 0; i < arrayCount - 1; ++i) { + SkBlitter* blitter = origBlitter; - SkASSERT(canConvertFDot6ToFixed(x0)); - SkASSERT(canConvertFDot6ToFixed(y0)); - SkASSERT(canConvertFDot6ToFixed(x1)); - SkASSERT(canConvertFDot6ToFixed(y1)); + SkPoint pts[2]; - if (clip) { - // now perform clipping again, as the rounding to dot6 can wiggle us - // our rects are really dot6 rects, but since we've already used - // lineclipper, we know they will fit in 32bits (26.6) - const SkIRect& bounds = clip->getBounds(); - - clipR.set(SkIntToFDot6(bounds.fLeft), SkIntToFDot6(bounds.fTop), - SkIntToFDot6(bounds.fRight), SkIntToFDot6(bounds.fBottom)); - ptsR.set(x0, y0, x1, y1); - ptsR.sort(); - - // outset the right and bottom, to account for how hairlines are - // actually drawn, which may hit the pixel to the right or below of - // the coordinate - ptsR.fRight += SK_FDot6One; - ptsR.fBottom += SK_FDot6One; - - if (!SkIRect::Intersects(ptsR, clipR)) { - return; - } - if (clip->isRect() && clipR.contains(ptsR)) { - clip = NULL; - } else { - blitter = clipper.apply(blitter, clip); + // We have to pre-clip the line to fit in a SkFixed, so we just chop + // the line. TODO find a way to actually draw beyond that range. + if (!SkLineClipper::IntersectLine(&array[i], fixedBounds, pts)) { + continue; } - } - SkFDot6 dx = x1 - x0; - SkFDot6 dy = y1 - y0; - - if (SkAbs32(dx) > SkAbs32(dy)) { // mostly horizontal - if (x0 > x1) { // we want to go left-to-right - SkTSwap<SkFDot6>(x0, x1); - SkTSwap<SkFDot6>(y0, y1); + // Perform a clip in scalar space, so we catch huge values which might + // be missed after we convert to SkFDot6 (overflow) + if (clip && !SkLineClipper::IntersectLine(pts, clipBounds, pts)) { + continue; } - int ix0 = SkFDot6Round(x0); - int ix1 = SkFDot6Round(x1); - if (ix0 == ix1) {// too short to draw - return; + + SkFDot6 x0 = SkScalarToFDot6(pts[0].fX); + SkFDot6 y0 = SkScalarToFDot6(pts[0].fY); + SkFDot6 x1 = SkScalarToFDot6(pts[1].fX); + SkFDot6 y1 = SkScalarToFDot6(pts[1].fY); + + SkASSERT(canConvertFDot6ToFixed(x0)); + SkASSERT(canConvertFDot6ToFixed(y0)); + SkASSERT(canConvertFDot6ToFixed(x1)); + SkASSERT(canConvertFDot6ToFixed(y1)); + + if (clip) { + // now perform clipping again, as the rounding to dot6 can wiggle us + // our rects are really dot6 rects, but since we've already used + // lineclipper, we know they will fit in 32bits (26.6) + const SkIRect& bounds = clip->getBounds(); + + clipR.set(SkIntToFDot6(bounds.fLeft), SkIntToFDot6(bounds.fTop), + SkIntToFDot6(bounds.fRight), SkIntToFDot6(bounds.fBottom)); + ptsR.set(x0, y0, x1, y1); + ptsR.sort(); + + // outset the right and bottom, to account for how hairlines are + // actually drawn, which may hit the pixel to the right or below of + // the coordinate + ptsR.fRight += SK_FDot6One; + ptsR.fBottom += SK_FDot6One; + + if (!SkIRect::Intersects(ptsR, clipR)) { + continue; + } + if (!clip->isRect() || !clipR.contains(ptsR)) { + blitter = clipper.apply(origBlitter, clip); + } } - SkFixed slope = SkFixedDiv(dy, dx); - SkFixed startY = SkFDot6ToFixed(y0) + (slope * ((32 - x0) & 63) >> 6); + SkFDot6 dx = x1 - x0; + SkFDot6 dy = y1 - y0; - horiline(ix0, ix1, startY, slope, blitter); - } else { // mostly vertical - if (y0 > y1) { // we want to go top-to-bottom - SkTSwap<SkFDot6>(x0, x1); - SkTSwap<SkFDot6>(y0, y1); - } - int iy0 = SkFDot6Round(y0); - int iy1 = SkFDot6Round(y1); - if (iy0 == iy1) { // too short to draw - return; - } + if (SkAbs32(dx) > SkAbs32(dy)) { // mostly horizontal + if (x0 > x1) { // we want to go left-to-right + SkTSwap<SkFDot6>(x0, x1); + SkTSwap<SkFDot6>(y0, y1); + } + int ix0 = SkFDot6Round(x0); + int ix1 = SkFDot6Round(x1); + if (ix0 == ix1) {// too short to draw + continue; + } - SkFixed slope = SkFixedDiv(dx, dy); - SkFixed startX = SkFDot6ToFixed(x0) + (slope * ((32 - y0) & 63) >> 6); + SkFixed slope = SkFixedDiv(dy, dx); + SkFixed startY = SkFDot6ToFixed(y0) + (slope * ((32 - x0) & 63) >> 6); - vertline(iy0, iy1, startX, slope, blitter); + horiline(ix0, ix1, startY, slope, blitter); + } else { // mostly vertical + if (y0 > y1) { // we want to go top-to-bottom + SkTSwap<SkFDot6>(x0, x1); + SkTSwap<SkFDot6>(y0, y1); + } + int iy0 = SkFDot6Round(y0); + int iy1 = SkFDot6Round(y1); + if (iy0 == iy1) { // too short to draw + continue; + } + + SkFixed slope = SkFixedDiv(dx, dy); + SkFixed startX = SkFDot6ToFixed(x0) + (slope * ((32 - y0) & 63) >> 6); + + vertline(iy0, iy1, startX, slope, blitter); + } } } @@ -209,10 +212,8 @@ static int compute_int_quad_dist(const SkPoint pts[3]) { } } -typedef void (*LineProc)(SkPoint, SkPoint, const SkRegion*, SkBlitter*); - static void hairquad(const SkPoint pts[3], const SkRegion* clip, - SkBlitter* blitter, int level, LineProc lineproc) { + SkBlitter* blitter, int level, SkScan::HairRgnProc lineproc) { if (level > 0) { SkPoint tmp[5]; @@ -220,12 +221,13 @@ static void hairquad(const SkPoint pts[3], const SkRegion* clip, hairquad(tmp, clip, blitter, level - 1, lineproc); hairquad(&tmp[2], clip, blitter, level - 1, lineproc); } else { - lineproc(pts[0], pts[2], clip, blitter); + SkPoint tmp[] = { pts[0], pts[2] }; + lineproc(tmp, 2, clip, blitter); } } static void haircubic(const SkPoint pts[4], const SkRegion* clip, - SkBlitter* blitter, int level, LineProc lineproc) { + SkBlitter* blitter, int level, SkScan::HairRgnProc lineproc) { if (level > 0) { SkPoint tmp[7]; @@ -233,7 +235,8 @@ static void haircubic(const SkPoint pts[4], const SkRegion* clip, haircubic(tmp, clip, blitter, level - 1, lineproc); haircubic(&tmp[3], clip, blitter, level - 1, lineproc); } else { - lineproc(pts[0], pts[3], clip, blitter); + SkPoint tmp[] = { pts[0], pts[3] }; + lineproc(tmp, 2, clip, blitter); } } @@ -256,7 +259,7 @@ static int compute_quad_level(const SkPoint pts[3]) { } static void hair_path(const SkPath& path, const SkRasterClip& rclip, SkBlitter* blitter, - LineProc lineproc) { + SkScan::HairRgnProc lineproc) { if (path.isEmpty()) { return; } @@ -291,7 +294,7 @@ static void hair_path(const SkPath& path, const SkRasterClip& rclip, SkBlitter* case SkPath::kMove_Verb: break; case SkPath::kLine_Verb: - lineproc(pts[0], pts[1], clip, blitter); + lineproc(pts, 2, clip, blitter); break; case SkPath::kQuad_Verb: hairquad(pts, clip, blitter, compute_quad_level(pts), lineproc); @@ -364,14 +367,15 @@ void SkScan::FrameRect(const SkRect& r, const SkPoint& strokeSize, SkScan::FillRect(tmp, clip, blitter); } -void SkScan::HairLine(SkPoint p0, SkPoint p1, const SkRasterClip& clip, SkBlitter* blitter) { +void SkScan::HairLine(const SkPoint pts[], int count, const SkRasterClip& clip, + SkBlitter* blitter) { if (clip.isBW()) { - HairLineRgn(p0, p1, &clip.bwRgn(), blitter); + HairLineRgn(pts, count, &clip.bwRgn(), blitter); } else { const SkRegion* clipRgn = NULL; + SkRect r; - r.set(p0.fX, p0.fY, p1.fX, p1.fY); - r.sort(); + r.set(pts, count); r.outset(SK_ScalarHalf, SK_ScalarHalf); SkAAClipBlitterWrapper wrap; @@ -380,18 +384,19 @@ void SkScan::HairLine(SkPoint p0, SkPoint p1, const SkRasterClip& clip, SkBlitte blitter = wrap.getBlitter(); clipRgn = &wrap.getRgn(); } - HairLineRgn(p0, p1, clipRgn, blitter); + HairLineRgn(pts, count, clipRgn, blitter); } } -void SkScan::AntiHairLine(SkPoint p0, SkPoint p1, const SkRasterClip& clip, SkBlitter* blitter) { +void SkScan::AntiHairLine(const SkPoint pts[], int count, const SkRasterClip& clip, + SkBlitter* blitter) { if (clip.isBW()) { - AntiHairLineRgn(p0, p1, &clip.bwRgn(), blitter); + AntiHairLineRgn(pts, count, &clip.bwRgn(), blitter); } else { const SkRegion* clipRgn = NULL; + SkRect r; - r.set(p0.fX, p0.fY, p1.fX, p1.fY); - r.sort(); + r.set(pts, count); SkAAClipBlitterWrapper wrap; if (!clip.quickContains(r.roundOut().makeOutset(1, 1))) { @@ -399,6 +404,6 @@ void SkScan::AntiHairLine(SkPoint p0, SkPoint p1, const SkRasterClip& clip, SkBl blitter = wrap.getBlitter(); clipRgn = &wrap.getRgn(); } - AntiHairLineRgn(p0, p1, clipRgn, blitter); + AntiHairLineRgn(pts, count, clipRgn, blitter); } } |