From: reed Date: Tue, 14 Apr 2015 17:40:44 +0000 (-0700) Subject: change hairline procs to take array of points X-Git-Tag: accepted/tizen/5.0/unified/20181102.025319~2788 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=5dc6b7d1a8bc591d62366ff83c434ff74f3e10fc;p=platform%2Fupstream%2FlibSkiaSharp.git change hairline procs to take array of points BUG=skia: Review URL: https://codereview.chromium.org/1085883002 --- diff --git a/src/core/SkDraw.cpp b/src/core/SkDraw.cpp index 636eaa6..878dca5 100644 --- a/src/core/SkDraw.cpp +++ b/src/core/SkDraw.cpp @@ -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()); } } } diff --git a/src/core/SkScan.h b/src/core/SkScan.h index 96c58c5..ef44873 100644 --- a/src/core/SkScan.h +++ b/src/core/SkScan.h @@ -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 diff --git a/src/core/SkScan_Antihair.cpp b/src/core/SkScan_Antihair.cpp index c48ad2c..3073434 100644 --- a/src/core/SkScan_Antihair.cpp +++ b/src/core/SkScan_Antihair.cpp @@ -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); } /////////////////////////////////////////////////////////////////////////////// diff --git a/src/core/SkScan_Hairline.cpp b/src/core/SkScan_Hairline.cpp index 8cce57b..0f2308b 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(x0, x1); - SkTSwap(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(x0, x1); - SkTSwap(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(x0, x1); + SkTSwap(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(x0, x1); + SkTSwap(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); } }