Index: src/core/SkScan_Hairline.cpp |
diff --git a/src/core/SkScan_Hairline.cpp b/src/core/SkScan_Hairline.cpp |
index 8cce57b8c97d4869b26fc50503ffa259db55fb4e..0f2308b1f79df7279c5bde4c11585e0430a68e63 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); |
} |
} |