11cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 21cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger/* 31cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Copyright 2006 The Android Open Source Project 41cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * 51cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Use of this source code is governed by a BSD-style license that can be 61cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * found in the LICENSE file. 71cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger */ 81cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 90910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkScan.h" 110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkBlitter.h" 121cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#include "SkRasterClip.h" 130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkFDot6.h" 148e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed#include "SkLineClipper.h" 150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1635e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenbergerstatic void horiline(int x, int stopx, SkFixed fy, SkFixed dy, 1735e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger SkBlitter* blitter) { 180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(x < stopx); 190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project do { 210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project blitter->blitH(x, fy >> 16, 1); 220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fy += dy; 230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } while (++x < stopx); 240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2635e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenbergerstatic void vertline(int y, int stopy, SkFixed fx, SkFixed dx, 2735e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger SkBlitter* blitter) { 280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(y < stopy); 290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project do { 310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project blitter->blitH(fx >> 16, y, 1); 320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fx += dx; 330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } while (++y < stopy); 340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 361cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergervoid SkScan::HairLineRgn(const SkPoint& pt0, const SkPoint& pt1, 371cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger const SkRegion* clip, SkBlitter* blitter) { 380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkBlitterClipper clipper; 398e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed SkRect r; 408e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed SkIRect clipR, ptsR; 418e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed SkPoint pts[2] = { pt0, pt1 }; 428e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed 438e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed if (clip) { 448e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed // Perform a clip in scalar space, so we catch huge values which might 458e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed // be missed after we convert to SkFDot6 (overflow) 468e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed r.set(clip->getBounds()); 478e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed if (!SkLineClipper::IntersectLine(pts, r, pts)) { 488e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed return; 498e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed } 508e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed } 510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 528e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed SkFDot6 x0 = SkScalarToFDot6(pts[0].fX); 538e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed SkFDot6 y0 = SkScalarToFDot6(pts[0].fY); 548e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed SkFDot6 x1 = SkScalarToFDot6(pts[1].fX); 558e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed SkFDot6 y1 = SkScalarToFDot6(pts[1].fY); 568e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed 578e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed if (clip) { 588e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed // now perform clipping again, as the rounding to dot6 can wiggle us 598e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed // our rects are really dot6 rects, but since we've already used 608e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed // lineclipper, we know they will fit in 32bits (26.6) 618e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed const SkIRect& bounds = clip->getBounds(); 628e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed 638e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed clipR.set(SkIntToFDot6(bounds.fLeft), SkIntToFDot6(bounds.fTop), 648e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed SkIntToFDot6(bounds.fRight), SkIntToFDot6(bounds.fBottom)); 658e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed ptsR.set(x0, y0, x1, y1); 668e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed ptsR.sort(); 678e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed 688e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed // outset the right and bottom, to account for how hairlines are 698e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed // actually drawn, which may hit the pixel to the right or below of 708e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed // the coordinate 7187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger ptsR.fRight += SK_FDot6One; 7287b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger ptsR.fBottom += SK_FDot6One; 738e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed 748e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed if (!SkIRect::Intersects(ptsR, clipR)) { 750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return; 768e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed } 778e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed if (clip->isRect() && clipR.contains(ptsR)) { 780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project clip = NULL; 798e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed } else { 800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project blitter = clipper.apply(blitter, clip); 810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkFDot6 dx = x1 - x0; 850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkFDot6 dy = y1 - y0; 860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 8735e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger if (SkAbs32(dx) > SkAbs32(dy)) { // mostly horizontal 8835e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger if (x0 > x1) { // we want to go left-to-right 890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkTSwap<SkFDot6>(x0, x1); 900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkTSwap<SkFDot6>(y0, y1); 910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int ix0 = SkFDot6Round(x0); 930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int ix1 = SkFDot6Round(x1); 9435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger if (ix0 == ix1) {// too short to draw 950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return; 9635e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger } 970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkFixed slope = SkFixedDiv(dy, dx); 990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkFixed startY = SkFDot6ToFixed(y0) + (slope * ((32 - x0) & 63) >> 6); 1000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project horiline(ix0, ix1, startY, slope, blitter); 10235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger } else { // mostly vertical 10335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger if (y0 > y1) { // we want to go top-to-bottom 1040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkTSwap<SkFDot6>(x0, x1); 1050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkTSwap<SkFDot6>(y0, y1); 1060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 1070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int iy0 = SkFDot6Round(y0); 1080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int iy1 = SkFDot6Round(y1); 10935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger if (iy0 == iy1) { // too short to draw 1100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return; 11135e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger } 1120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkFixed slope = SkFixedDiv(dx, dy); 1140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkFixed startX = SkFDot6ToFixed(x0) + (slope * ((32 - y0) & 63) >> 6); 1150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project vertline(iy0, iy1, startX, slope, blitter); 1170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 1180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 1190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project// we don't just draw 4 lines, 'cause that can leave a gap in the bottom-right 1210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project// and double-hit the top-left. 1228e048c19870a898cecdde3b3c0d2d512e6f372c0Mike Reed// TODO: handle huge coordinates on rect (before calling SkScalarToFixed) 1231cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergervoid SkScan::HairRect(const SkRect& rect, const SkRasterClip& clip, 12435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger SkBlitter* blitter) { 1251cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkAAClipBlitterWrapper wrapper; 1260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkBlitterClipper clipper; 1270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkIRect r; 1280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project r.set(SkScalarToFixed(rect.fLeft) >> 16, 1300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalarToFixed(rect.fTop) >> 16, 1310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project (SkScalarToFixed(rect.fRight) >> 16) + 1, 1320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project (SkScalarToFixed(rect.fBottom) >> 16) + 1); 1330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1341cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (clip.quickReject(r)) { 1351cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger return; 1361cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 1371cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (!clip.quickContains(r)) { 1381cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger const SkRegion* clipRgn; 1391cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (clip.isBW()) { 1401cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger clipRgn = &clip.bwRgn(); 1411cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } else { 1421cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger wrapper.init(clip, blitter); 1431cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger clipRgn = &wrapper.getRgn(); 1441cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger blitter = wrapper.getBlitter(); 14535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger } 1461cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger blitter = clipper.apply(blitter, clipRgn); 1470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 1480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int width = r.width(); 1500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int height = r.height(); 1510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 15235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger if ((width | height) == 0) { 1530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return; 15435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger } 15535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger if (width <= 2 || height <= 2) { 1560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project blitter->blitRect(r.fLeft, r.fTop, width, height); 1570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return; 1580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 1590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // if we get here, we know we have 4 segments to draw 1600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project blitter->blitH(r.fLeft, r.fTop, width); // top 1610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project blitter->blitRect(r.fLeft, r.fTop + 1, 1, height - 2); // left 1620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project blitter->blitRect(r.fRight - 1, r.fTop + 1, 1, height - 2); // right 1630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project blitter->blitH(r.fLeft, r.fBottom - 1, width); // bottom 1640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 1650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 16635e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger/////////////////////////////////////////////////////////////////////////////// 1670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkPath.h" 1690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkGeometry.h" 1700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 17135e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenbergerstatic bool quad_too_curvy(const SkPoint pts[3]) { 1720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return true; 1730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 1740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic int compute_int_quad_dist(const SkPoint pts[3]) { 1760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // compute the vector between the control point ([1]) and the middle of the 1770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // line connecting the start and end ([0] and [2]) 1780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar dx = SkScalarHalf(pts[0].fX + pts[2].fX) - pts[1].fX; 1790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar dy = SkScalarHalf(pts[0].fY + pts[2].fY) - pts[1].fY; 1800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // we want everyone to be positive 1810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project dx = SkScalarAbs(dx); 1820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project dy = SkScalarAbs(dy); 1830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // convert to whole pixel values (use ceiling to be conservative) 1840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int idx = SkScalarCeil(dx); 1850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int idy = SkScalarCeil(dy); 1860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // use the cheap approx for distance 1870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (idx > idy) { 1880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return idx + (idy >> 1); 1890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } else { 1900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return idy + (idx >> 1); 1910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 1920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 1930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic void hairquad(const SkPoint pts[3], const SkRegion* clip, SkBlitter* blitter, int level, 1950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project void (*lineproc)(const SkPoint&, const SkPoint&, const SkRegion* clip, SkBlitter*)) 1960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{ 1970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#if 1 1980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (level > 0 && quad_too_curvy(pts)) 1990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project { 2000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkPoint tmp[5]; 2010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkChopQuadAtHalf(pts, tmp); 2030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project hairquad(tmp, clip, blitter, level - 1, lineproc); 2040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project hairquad(&tmp[2], clip, blitter, level - 1, lineproc); 2050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 2060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project else 2070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project lineproc(pts[0], pts[2], clip, blitter); 2080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#else 2090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int count = 1 << level; 2100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const SkScalar dt = SkFixedToScalar(SK_Fixed1 >> level); 2110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar t = dt; 2120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkPoint prevPt = pts[0]; 2130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project for (int i = 1; i < count; i++) { 2140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkPoint nextPt; 2150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkEvalQuadAt(pts, t, &nextPt); 2160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project lineproc(prevPt, nextPt, clip, blitter); 2170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project t += dt; 2180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project prevPt = nextPt; 2190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 2200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // draw the last line explicitly to 1.0, in case t didn't match that exactly 2210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project lineproc(prevPt, pts[2], clip, blitter); 2220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif 2230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 2240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic bool cubic_too_curvy(const SkPoint pts[4]) 2260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{ 2270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return true; 2280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 2290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic void haircubic(const SkPoint pts[4], const SkRegion* clip, SkBlitter* blitter, int level, 2310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project void (*lineproc)(const SkPoint&, const SkPoint&, const SkRegion*, SkBlitter*)) 2320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{ 2330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (level > 0 && cubic_too_curvy(pts)) 2340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project { 2350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkPoint tmp[7]; 2360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkChopCubicAt(pts, tmp, SK_Scalar1/2); 2380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project haircubic(tmp, clip, blitter, level - 1, lineproc); 2390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project haircubic(&tmp[3], clip, blitter, level - 1, lineproc); 2400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 2410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project else 2420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project lineproc(pts[0], pts[3], clip, blitter); 2430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 2440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define kMaxCubicSubdivideLevel 6 2460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define kMaxQuadSubdivideLevel 5 2470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2481cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic void hair_path(const SkPath& path, const SkRasterClip& rclip, SkBlitter* blitter, 2490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project void (*lineproc)(const SkPoint&, const SkPoint&, const SkRegion*, SkBlitter*)) 2500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{ 25135e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger if (path.isEmpty()) { 2520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return; 25335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger } 2540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2551cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkAAClipBlitterWrapper wrap; 2560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const SkIRect* clipR = NULL; 2571cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger const SkRegion* clip = NULL; 2580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2591cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger { 2600e747d6d0a794242bd214fa44a6a179baeadfdf9Mike Reed SkIRect ibounds; 2610e747d6d0a794242bd214fa44a6a179baeadfdf9Mike Reed path.getBounds().roundOut(&ibounds); 2620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project ibounds.inset(-1, -1); 2630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2641cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (rclip.quickReject(ibounds)) { 2650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return; 26635e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger } 2671cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (!rclip.quickContains(ibounds)) { 2681cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger clipR = &rclip.getBounds(); 2691cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (rclip.isBW()) { 2701cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger clip = &rclip.bwRgn(); 2711cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } else { 2721cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger wrap.init(rclip, blitter); 2731cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger blitter = wrap.getBlitter(); 2741cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger clip = &wrap.getRgn(); 2751cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 27635e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger } 2770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 2780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkPath::Iter iter(path, false); 2800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkPoint pts[4]; 2810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkPath::Verb verb; 2820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 28335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger while ((verb = iter.next(pts)) != SkPath::kDone_Verb) { 2840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project switch (verb) { 28535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger case SkPath::kLine_Verb: 28635e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger lineproc(pts[0], pts[1], clip, blitter); 28735e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger break; 28835e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger case SkPath::kQuad_Verb: { 28935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger int d = compute_int_quad_dist(pts); 29035e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger /* quadratics approach the line connecting their start and end points 29135e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger 4x closer with each subdivision, so we compute the number of 29235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger subdivisions to be the minimum need to get that distance to be less 29335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger than a pixel. 29435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger */ 29535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger int level = (33 - SkCLZ(d)) >> 1; 29635e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger // SkDebugf("----- distance %d computedLevel %d\n", d, computedLevel); 29735e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger // sanity check on level (from the previous version) 29835e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger if (level > kMaxQuadSubdivideLevel) { 29935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger level = kMaxQuadSubdivideLevel; 30035e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger } 30135e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger hairquad(pts, clip, blitter, level, lineproc); 30235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger break; 3030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 30435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger case SkPath::kCubic_Verb: 30535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger haircubic(pts, clip, blitter, kMaxCubicSubdivideLevel, lineproc); 30635e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger break; 30735e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger default: 30835e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger break; 3090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 3100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 3110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 3120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 3131cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergervoid SkScan::HairPath(const SkPath& path, const SkRasterClip& clip, 31435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger SkBlitter* blitter) { 3151cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger hair_path(path, clip, blitter, SkScan::HairLineRgn); 3160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 3170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 3181cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergervoid SkScan::AntiHairPath(const SkPath& path, const SkRasterClip& clip, 31935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger SkBlitter* blitter) { 3201cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger hair_path(path, clip, blitter, SkScan::AntiHairLineRgn); 3210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 3220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 32387b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger/////////////////////////////////////////////////////////////////////////////// 3240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 32587b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenbergervoid SkScan::FrameRect(const SkRect& r, const SkPoint& strokeSize, 3261cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger const SkRasterClip& clip, SkBlitter* blitter) { 32787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger SkASSERT(strokeSize.fX >= 0 && strokeSize.fY >= 0); 3280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 32987b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger if (strokeSize.fX < 0 || strokeSize.fY < 0) { 3300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return; 33187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger } 3320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 33387b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger const SkScalar dx = strokeSize.fX; 33487b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger const SkScalar dy = strokeSize.fY; 33587b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger SkScalar rx = SkScalarHalf(dx); 33687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger SkScalar ry = SkScalarHalf(dy); 3370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkRect outer, tmp; 3380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 33987b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger outer.set(r.fLeft - rx, r.fTop - ry, 34087b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger r.fRight + rx, r.fBottom + ry); 3410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 34287b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger if (r.width() <= dx || r.height() <= dx) { 3430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScan::FillRect(outer, clip, blitter); 3440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return; 3450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 3460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 34787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger tmp.set(outer.fLeft, outer.fTop, outer.fRight, outer.fTop + dy); 3480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScan::FillRect(tmp, clip, blitter); 34987b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger tmp.fTop = outer.fBottom - dy; 3500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project tmp.fBottom = outer.fBottom; 3510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScan::FillRect(tmp, clip, blitter); 3520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 35387b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger tmp.set(outer.fLeft, outer.fTop + dy, outer.fLeft + dx, outer.fBottom - dy); 3540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScan::FillRect(tmp, clip, blitter); 35587b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger tmp.fLeft = outer.fRight - dx; 3560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project tmp.fRight = outer.fRight; 3570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScan::FillRect(tmp, clip, blitter); 3580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 3590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 3601cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergervoid SkScan::HairLine(const SkPoint& p0, const SkPoint& p1, 3611cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger const SkRasterClip& clip, SkBlitter* blitter) { 3621cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (clip.isBW()) { 3631cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger HairLineRgn(p0, p1, &clip.bwRgn(), blitter); 3641cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } else { 3651cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger const SkRegion* clipRgn = NULL; 3661cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkRect r; 3671cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkIRect ir; 3681cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger r.set(p0.fX, p0.fY, p1.fX, p1.fY); 3691cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger r.sort(); 3701cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger r.inset(-SK_ScalarHalf, -SK_ScalarHalf); 3711cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger r.roundOut(&ir); 3721cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 3731cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkAAClipBlitterWrapper wrap; 3741cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (!clip.quickContains(ir)) { 3751cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger wrap.init(clip, blitter); 3761cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger blitter = wrap.getBlitter(); 3771cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger clipRgn = &wrap.getRgn(); 3781cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 3791cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger HairLineRgn(p0, p1, clipRgn, blitter); 3801cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 3811cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger} 3821cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 3831cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergervoid SkScan::AntiHairLine(const SkPoint& p0, const SkPoint& p1, 3841cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger const SkRasterClip& clip, SkBlitter* blitter) { 3851cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (clip.isBW()) { 3861cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger AntiHairLineRgn(p0, p1, &clip.bwRgn(), blitter); 3871cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } else { 3881cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger const SkRegion* clipRgn = NULL; 3891cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkRect r; 3901cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkIRect ir; 3911cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger r.set(p0.fX, p0.fY, p1.fX, p1.fY); 3921cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger r.sort(); 3931cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger r.roundOut(&ir); 3941cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger ir.inset(-1, -1); 3951cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 3961cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkAAClipBlitterWrapper wrap; 3971cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (!clip.quickContains(ir)) { 3981cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger wrap.init(clip, blitter); 3991cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger blitter = wrap.getBlitter(); 4001cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger clipRgn = &wrap.getRgn(); 4011cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 4021cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger AntiHairLineRgn(p0, p1, clipRgn, blitter); 4031cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 4041cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger} 405