| 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);
|
| }
|
| }
|
|
|