change hairline procs to take array of points
authorreed <reed@google.com>
Tue, 14 Apr 2015 17:40:44 +0000 (10:40 -0700)
committerCommit bot <commit-bot@chromium.org>
Tue, 14 Apr 2015 17:40:44 +0000 (10:40 -0700)
BUG=skia:

Review URL: https://codereview.chromium.org/1085883002

src/core/SkDraw.cpp
src/core/SkScan.h
src/core/SkScan_Antihair.cpp
src/core/SkScan_Hairline.cpp

index 636eaa6..878dca5 100644 (file)
@@ -381,15 +381,13 @@ static void bw_pt_hair_proc(const PtProcRec& rec, const SkPoint devPts[],
 static void bw_line_hair_proc(const PtProcRec& rec, const SkPoint devPts[],
                               int count, SkBlitter* blitter) {
     for (int i = 0; i < count; i += 2) {
-        SkScan::HairLine(devPts[i], devPts[i+1], *rec.fRC, blitter);
+        SkScan::HairLine(&devPts[i], 2, *rec.fRC, blitter);
     }
 }
 
 static void bw_poly_hair_proc(const PtProcRec& rec, const SkPoint devPts[],
                               int count, SkBlitter* blitter) {
-    for (int i = 0; i < count - 1; i++) {
-        SkScan::HairLine(devPts[i], devPts[i+1], *rec.fRC, blitter);
-    }
+    SkScan::HairLine(devPts, count, *rec.fRC, blitter);
 }
 
 // aa versions
@@ -397,15 +395,13 @@ static void bw_poly_hair_proc(const PtProcRec& rec, const SkPoint devPts[],
 static void aa_line_hair_proc(const PtProcRec& rec, const SkPoint devPts[],
                               int count, SkBlitter* blitter) {
     for (int i = 0; i < count; i += 2) {
-        SkScan::AntiHairLine(devPts[i], devPts[i+1], *rec.fRC, blitter);
+        SkScan::AntiHairLine(&devPts[i], 2, *rec.fRC, blitter);
     }
 }
 
 static void aa_poly_hair_proc(const PtProcRec& rec, const SkPoint devPts[],
                               int count, SkBlitter* blitter) {
-    for (int i = 0; i < count - 1; i++) {
-        SkScan::AntiHairLine(devPts[i], devPts[i+1], *rec.fRC, blitter);
-    }
+    SkScan::AntiHairLine(devPts, count, *rec.fRC, blitter);
 }
 
 // square procs (strokeWidth > 0 but matrix is square-scale (sx == sy)
@@ -1876,9 +1872,7 @@ void SkDraw::drawPosText(const char text[], size_t byteLength,
 
 ///////////////////////////////////////////////////////////////////////////////
 
-typedef void (*HairProc)(SkPoint, SkPoint, const SkRasterClip&, SkBlitter*);
-
-static HairProc ChooseHairProc(bool doAntiAlias) {
+static SkScan::HairRCProc ChooseHairProc(bool doAntiAlias) {
     return doAntiAlias ? SkScan::AntiHairLine : SkScan::HairLine;
 }
 
@@ -2144,12 +2138,13 @@ void SkDraw::drawVertices(SkCanvas::VertexMode vmode, int count,
         }
     } else {
         // no colors[] and no texture, stroke hairlines with paint's color.
-        HairProc hairProc = ChooseHairProc(paint.isAntiAlias());
+        SkScan::HairRCProc hairProc = ChooseHairProc(paint.isAntiAlias());
         const SkRasterClip& clip = *fRC;
         while (vertProc(&state)) {
-            hairProc(devVerts[state.f0], devVerts[state.f1], clip, blitter.get());
-            hairProc(devVerts[state.f1], devVerts[state.f2], clip, blitter.get());
-            hairProc(devVerts[state.f2], devVerts[state.f0], clip, blitter.get());
+            SkPoint array[] = {
+                devVerts[state.f0], devVerts[state.f1], devVerts[state.f2], devVerts[state.f0]
+            };
+            hairProc(array, 4, clip, blitter.get());
         }
     }
 }
index 96c58c5..ef44873 100644 (file)
@@ -24,6 +24,15 @@ typedef SkIRect SkXRect;
 
 class SkScan {
 public:
+    /*
+     *  Draws count-1 line segments, one at a time:
+     *      line(pts[0], pts[1])
+     *      line(pts[1], pts[2])
+     *      line(......, pts[count - 1])
+     */
+    typedef void (*HairRgnProc)(const SkPoint[], int count, const SkRegion*, SkBlitter*);
+    typedef void (*HairRCProc)(const SkPoint[], int count, const SkRasterClip&, SkBlitter*);
+
     static void FillPath(const SkPath&, const SkIRect&, SkBlitter*);
 
     ///////////////////////////////////////////////////////////////////////////
@@ -41,8 +50,8 @@ public:
     static void AntiFrameRect(const SkRect&, const SkPoint& strokeSize,
                               const SkRasterClip&, SkBlitter*);
     static void FillTriangle(const SkPoint pts[], const SkRasterClip&, SkBlitter*);
-    static void HairLine(SkPoint, SkPoint, const SkRasterClip&, SkBlitter*);
-    static void AntiHairLine(SkPoint, SkPoint, const SkRasterClip&, SkBlitter*);
+    static void HairLine(const SkPoint[], int count, const SkRasterClip&, SkBlitter*);
+    static void AntiHairLine(const SkPoint[], int count, const SkRasterClip&, SkBlitter*);
     static void HairRect(const SkRect&, const SkRasterClip&, SkBlitter*);
     static void AntiHairRect(const SkRect&, const SkRasterClip&, SkBlitter*);
     static void HairPath(const SkPath&, const SkRasterClip&, SkBlitter*);
@@ -64,8 +73,8 @@ private:
 
     static void AntiFrameRect(const SkRect&, const SkPoint& strokeSize,
                               const SkRegion*, SkBlitter*);
-    static void HairLineRgn(SkPoint, SkPoint, const SkRegion*, SkBlitter*);
-    static void AntiHairLineRgn(SkPoint, SkPoint, const SkRegion*, SkBlitter*);
+    static void HairLineRgn(const SkPoint[], int count, const SkRegion*, SkBlitter*);
+    static void AntiHairLineRgn(const SkPoint[], int count, const SkRegion*, SkBlitter*);
 };
 
 /** Assign an SkXRect from a SkIRect, by promoting the src rect's coordinates
index c48ad2c..3073434 100644 (file)
@@ -588,7 +588,8 @@ static void do_anti_hairline(SkFDot6 x0, SkFDot6 y0, SkFDot6 x1, SkFDot6 y1,
     }
 }
 
-void SkScan::AntiHairLineRgn(SkPoint pt0, SkPoint pt1, const SkRegion* clip, SkBlitter* blitter) {
+void SkScan::AntiHairLineRgn(const SkPoint array[], int arrayCount, const SkRegion* clip,
+                             SkBlitter* blitter) {
     if (clip && clip->isEmpty()) {
         return;
     }
@@ -599,86 +600,83 @@ void SkScan::AntiHairLineRgn(SkPoint pt0, SkPoint pt1, const SkRegion* clip, SkB
     build_gamma_table();
 #endif
 
-    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) {
-        SkRect clipBounds;
         clipBounds.set(clip->getBounds());
         /*  We perform integral clipping later on, but we do a scalar clip first
-            to ensure that our coordinates are expressible in fixed/integers.
-
-            antialiased hairlines can draw up to 1/2 of a pixel outside of
-            their bounds, so we need to outset the clip before calling the
-            clipper. To make the numerics safer, we outset by a whole pixel,
-            since the 1/2 pixel boundary is important to the antihair blitter,
-            we don't want to risk numerical fate by chopping on that edge.
+         to ensure that our coordinates are expressible in fixed/integers.
+         
+         antialiased hairlines can draw up to 1/2 of a pixel outside of
+         their bounds, so we need to outset the clip before calling the
+         clipper. To make the numerics safer, we outset by a whole pixel,
+         since the 1/2 pixel boundary is important to the antihair blitter,
+         we don't want to risk numerical fate by chopping on that edge.
          */
         clipBounds.outset(SK_Scalar1, SK_Scalar1);
-
-        if (!SkLineClipper::IntersectLine(pts, clipBounds, pts)) {
-            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);
+    for (int i = 0; i < arrayCount - 1; ++i) {
+        SkPoint pts[2];
 
-    if (clip) {
-        SkFDot6 left = SkMin32(x0, x1);
-        SkFDot6 top = SkMin32(y0, y1);
-        SkFDot6 right = SkMax32(x0, x1);
-        SkFDot6 bottom = SkMax32(y0, y1);
-        SkIRect ir;
-
-        ir.set( SkFDot6Floor(left) - 1,
-                SkFDot6Floor(top) - 1,
-                SkFDot6Ceil(right) + 1,
-                SkFDot6Ceil(bottom) + 1);
-
-        if (clip->quickReject(ir)) {
-            return;
+        // 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;
+        }
+
+        if (clip && !SkLineClipper::IntersectLine(pts, clipBounds, pts)) {
+            continue;
         }
-        if (!clip->quickContains(ir)) {
-            SkRegion::Cliperator iter(*clip, ir);
-            const SkIRect*       r = &iter.rect();
 
-            while (!iter.done()) {
-                do_anti_hairline(x0, y0, x1, y1, r, blitter);
-                iter.next();
+        SkFDot6 x0 = SkScalarToFDot6(pts[0].fX);
+        SkFDot6 y0 = SkScalarToFDot6(pts[0].fY);
+        SkFDot6 x1 = SkScalarToFDot6(pts[1].fX);
+        SkFDot6 y1 = SkScalarToFDot6(pts[1].fY);
+
+        if (clip) {
+            SkFDot6 left = SkMin32(x0, x1);
+            SkFDot6 top = SkMin32(y0, y1);
+            SkFDot6 right = SkMax32(x0, x1);
+            SkFDot6 bottom = SkMax32(y0, y1);
+            SkIRect ir;
+
+            ir.set( SkFDot6Floor(left) - 1,
+                    SkFDot6Floor(top) - 1,
+                    SkFDot6Ceil(right) + 1,
+                    SkFDot6Ceil(bottom) + 1);
+
+            if (clip->quickReject(ir)) {
+                continue;
             }
-            return;
+            if (!clip->quickContains(ir)) {
+                SkRegion::Cliperator iter(*clip, ir);
+                const SkIRect*       r = &iter.rect();
+
+                while (!iter.done()) {
+                    do_anti_hairline(x0, y0, x1, y1, r, blitter);
+                    iter.next();
+                }
+                continue;
+            }
+            // fall through to no-clip case
         }
-        // fall through to no-clip case
+        do_anti_hairline(x0, y0, x1, y1, NULL, blitter);
     }
-    do_anti_hairline(x0, y0, x1, y1, NULL, blitter);
 }
 
 void SkScan::AntiHairRect(const SkRect& rect, const SkRasterClip& clip,
                           SkBlitter* blitter) {
-    SkPoint p0, p1;
-
-    p0.set(rect.fLeft, rect.fTop);
-    p1.set(rect.fRight, rect.fTop);
-    SkScan::AntiHairLine(p0, p1, clip, blitter);
-    p0.set(rect.fRight, rect.fBottom);
-    SkScan::AntiHairLine(p0, p1, clip, blitter);
-    p1.set(rect.fLeft, rect.fBottom);
-    SkScan::AntiHairLine(p0, p1, clip, blitter);
-    p0.set(rect.fLeft, rect.fTop);
-    SkScan::AntiHairLine(p0, p1, clip, blitter);
+    SkPoint pts[5];
+
+    pts[0].set(rect.fLeft, rect.fTop);
+    pts[1].set(rect.fRight, rect.fTop);
+    pts[2].set(rect.fRight, rect.fBottom);
+    pts[3].set(rect.fLeft, rect.fBottom);
+    pts[4] = pts[0];
+    SkScan::AntiHairLine(pts, 5, clip, blitter);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
index 8cce57b..0f2308b 100644 (file)
@@ -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);
     }
 }