1639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com/* 21304bb25aa3b0baa61fc2e2900fabcef88801b59caryclark@google.com * Copyright 2011 Google Inc. 3639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com * 41304bb25aa3b0baa61fc2e2900fabcef88801b59caryclark@google.com * Use of this source code is governed by a BSD-style license that can be 51304bb25aa3b0baa61fc2e2900fabcef88801b59caryclark@google.com * found in the LICENSE file. 6639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com */ 7639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com#include "SkAntiEdge.h" 8639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com#include "SkPoint.h" 9639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 101915fd09f3b60eb907f5ab155e8379b589e2bae1reed@google.com/** Returns the signed fraction of a SkFixed 111915fd09f3b60eb907f5ab155e8379b589e2bae1reed@google.com */ 121915fd09f3b60eb907f5ab155e8379b589e2bae1reed@google.comstatic inline SkFixed SkFixedFraction(SkFixed x) 131915fd09f3b60eb907f5ab155e8379b589e2bae1reed@google.com{ 141915fd09f3b60eb907f5ab155e8379b589e2bae1reed@google.com SkFixed mask = x >> 31 << 16; 151915fd09f3b60eb907f5ab155e8379b589e2bae1reed@google.com return (x & 0xFFFF) | mask; 161915fd09f3b60eb907f5ab155e8379b589e2bae1reed@google.com} 171915fd09f3b60eb907f5ab155e8379b589e2bae1reed@google.com 18639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.comvoid SkAntiEdge::pointOnLine(SkFixed x, SkFixed y) { 19639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com float x0 = SkFixedToFloat(x); 20639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com float y0 = SkFixedToFloat(y); 21639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com float x1 = SkFixedToFloat(fFirstX); 22639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com float y1 = SkFixedToFloat(fFirstY); 23639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com float x2 = SkFixedToFloat(fLastX); 24639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com float y2 = SkFixedToFloat(fLastY); 25639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com float numer = (x2 - x1) * (y1 - y0) - (x1 - x0) * (y2 - y1); 26639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com float denom = (x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1); 27639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com double dist = fabs(numer) / sqrt(denom); 28639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkAssertResult(dist < 0.01); 29639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com} 30639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 31639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.comvoid SkAntiEdge::pointInLine(SkFixed x, SkFixed y) { 32639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com if (y == SK_MaxS32) { 33639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com return; 34639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 35639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com pointOnLine(x, y); 36639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkAssertResult(y >= fFirstY && y <= fLastY); 37639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com} 38639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 39639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.comvoid SkAntiEdge::validate() { 40639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com pointOnLine(fWalkX, fY); 41639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com pointOnLine(fX, fWalkY); 42639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com} 43639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 44639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.combool SkAntiEdge::setLine(const SkPoint& p0, const SkPoint& p1) { 45639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com fFirstY = SkScalarToFixed(p0.fY); 46639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com fLastY = SkScalarToFixed(p1.fY); 47639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com if (fFirstY == fLastY) { 48639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com return false; 49d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com } 50639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com fFirstX = SkScalarToFixed(p0.fX); 51639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com fLastX = SkScalarToFixed(p1.fX); 52639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com if (fFirstY > fLastY) { 53639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkTSwap(fFirstX, fLastX); 54639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkTSwap(fFirstY, fLastY); 55639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com fWinding = -1; 56639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } else { 57639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com fWinding = 1; 58639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 59639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkFixed dx = fLastX - fFirstX; 60639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com fDXFlipped = dx < 0; 61639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkFixed dy = fLastY - fFirstY; 62639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com fDX = SkFixedDiv(dx, dy); 63639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com fDY = dx == 0 ? SK_MaxS32 : SkFixedDiv(dy, SkFixedAbs(dx)); 64639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com fLink = NULL; 65639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com fLinkSet = false; 66639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com return true; 67639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com} 68639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 69639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.comvoid SkAntiEdge::calcLine() { 70639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkFixed yStartFrac = SkFixedFraction(fFirstY); 71639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com if (fDXFlipped) { 72639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkFixed vert = SK_Fixed1 - yStartFrac; // distance from y start to x-axis 73639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com fX0 = fFirstX + SkFixedMul(fDX, vert); 74639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkFixed backupX = fFirstX + SkFixedMul(vert, fDX); // x cell to back up to 75639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkFixed cellX = SkIntToFixed(SkFixedFloor(backupX)); 76639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkFixed endX = SkIntToFixed(SkFixedFloor(fLastX)); 77639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com if (cellX < endX) { 78639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com cellX = endX; 79639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 80639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkFixed distX = fFirstX - cellX; // to y-axis 81639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com fY0 = fFirstY + SkFixedMul(fDY, distX); 82639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkFixed rowBottom = SkIntToFixed(SkFixedCeil(fFirstY + 1)); 83639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com if (fLastY > rowBottom) { 84639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com fPartialY = 0; 85639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com fX = fX0; 86639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com fY = rowBottom; 87639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } else { 88639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com fPartialY = SkFixedFraction(fLastY); 89639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com fX = fLastX; 90639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com fY = fLastY; 91639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 92639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } else { 93639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com fPartialY = yStartFrac; 94639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com fX0 = fFirstX - SkFixedMul(fDX, yStartFrac); 95639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com fY0 = fFirstY; 96639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com if (fDY != SK_MaxS32) { 97639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkFixed xStartFrac = SkFixedFraction(fFirstX); 98639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com fY0 -= SkFixedMul(fDY, xStartFrac); 99639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 100639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com fX = fFirstX; 101639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com fY = fFirstY; 102639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 103639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com fWalkX = fX; 104639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com fWalkY = fY; 105639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com fFinished = false; 106639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com} 107639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 108639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.comstatic SkFixed SkFixedAddPin(SkFixed a, SkFixed b) { 109639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkFixed result = a + b; 110639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com if (((a ^ ~b) & (a ^ result)) >= 0) { // one positive, one negative 111639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com return result; // or all three same sign 112639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 113639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com return a < 0 ? -SK_FixedMax : SK_FixedMax; 114639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com} 115639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 116639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com// edge is increasing in x and y 117639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.comuint16_t SkAntiEdge::advanceX(SkFixed left) { 118639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com validate(); 119639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkFixed x = SkFixedAddPin(fX0, fDX); 120639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkFixed wy = SkIntToFixed(SkFixedFloor(fWalkY + SK_Fixed1)); 121639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com pointOnLine(x, wy); 122639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkFixed partial = SK_Fixed1 - fPartialY; 123639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkFixed bottomPartial = wy - fLastY; 124639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com if (bottomPartial > 0) { 125639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com partial -= bottomPartial; 126639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 127639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com if (x > fLastX) { 128639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com x = fLastX; 129639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com wy = fLastY; 130639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 131639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com uint16_t coverage; 132639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com if (left >= x) { 133639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com fFinished = true; 134639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com coverage = partial - 1; // walker is to the right of edge 135639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } else { 136639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkFixed y = SkFixedAddPin(fY0, fDY); 137639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkFixed wx = SkIntToFixed(SkFixedFloor(fWalkX + SK_Fixed1)); 138639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com if (fDY != SK_MaxS32) { 139639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com pointOnLine(wx, y); 140639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 141639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com if (y > fLastY) { 142639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com y = fLastY; 143639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com wx = fLastX; 144639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 145639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com bool topCorner = fWalkX <= fX; 146639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com bool bottomCorner = x <= wx; 147639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com bool halfPlane = !(topCorner ^ bottomCorner); 148639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com if (halfPlane) { 149639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com if (x - SkIntToFixed(SkFixedFloor(fX)) <= SK_Fixed1) { 150639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com coverage = ~((fX + x) >> 1); // avg of fx, fx+dx 151639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com fFinished = true; 152639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com if (x >= left + SK_Fixed1) { 153639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com fWalkX = wx; 154639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com fY = fY0 = y; 155639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 156639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } else { 157639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkAssertResult(y - SkIntToFixed(SkFixedFloor(fY)) <= SK_Fixed1); 158639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com coverage = ((fY + y) >> 1); 159639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com fFinished = y == fLastY; 160639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com fWalkX = wx; 161639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com fY = fY0 = y; 162639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 163639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com coverage = coverage * partial >> 16; 164639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } else if (topCorner) { 165639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkFixed xDiff = wx - fX; 166639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkAssertResult(xDiff >= 0); 167639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkAssertResult(xDiff <= SK_Fixed1); 168639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkFixed yDiff = y - fWalkY; 169639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com // This may be a very small negative number if error accumulates 170639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com // FIXME: for now, try setting it to zero in that case. 171639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com if (yDiff < 0) { 172639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com fX = fX0 = SkIntToFixed(SkFixedCeil(fX)); 173639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com yDiff = 0; 174639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 175639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkAssertResult(yDiff >= 0); 176639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkAssertResult(yDiff <= SK_Fixed1); 177639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com int xCoverage = xDiff >> 1; // throw away 1 bit so multiply 178639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com int yCoverage = yDiff >> 1; // stays in range 179639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com int triangle = xCoverage * yCoverage; // 30 bits 180639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkFixed bottomPartial = y - fLastY; 181639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com fFinished = bottomPartial >= 0; 182639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com if (fFinished) { 183639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com yCoverage = bottomPartial >> 1; 184639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com xCoverage = (wx - fLastX) >> 1; 185639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com triangle -= xCoverage * yCoverage; 186639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 187639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com coverage = triangle >> 15; 188639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com fWalkX = wx; 189639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com fY = fY0 = y; 190639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } else { 191639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkAssertResult(bottomCorner); 192639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkFixed xDiff = x - fWalkX; 193639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkAssertResult(xDiff >= 0); 194639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkAssertResult(xDiff <= SK_Fixed1); 195639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkFixed yDiff = wy - fY; 196639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkAssertResult(yDiff >= 0); 197639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkAssertResult(yDiff <= SK_Fixed1); 198d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com int xCoverage = xDiff >> 1; // throw away 1 bit so multiply 199639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com int yCoverage = yDiff >> 1; // stays in range 200639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com int triangle = xCoverage * yCoverage >> 15; 201639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com coverage = partial - 1 - triangle; 202639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com fFinished = true; 203639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 204639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 205639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com validate(); 206639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com return coverage; 207639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com} 208639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 209639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com// edge is increasing in x, but decreasing in y 210639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.comuint16_t SkAntiEdge::advanceFlippedX(SkFixed left) { 211639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com validate(); 212639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkFixed x = SkFixedAddPin(fX0, -fDX); 213639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkFixed wy = SkIntToFixed(SkFixedFloor(fWalkY - 1)); 214639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com pointOnLine(x, wy); 215639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkFixed partial = fPartialY ? fPartialY : SK_Fixed1; 216639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkFixed topPartial = fFirstY - wy; 217639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com if (topPartial > 0) { 218639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com partial -= topPartial; 219639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 220639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com if (x > fFirstX) { 221639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com x = fFirstX; 222639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com wy = fFirstY; 223639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 224639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com uint16_t coverage; 225639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com if (left >= x) { 226639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com fFinished = true; 227639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com coverage = partial - 1; // walker is to the right of edge 228639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } else { 229639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkFixed y = SkFixedAddPin(fY0, -fDY); 230639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkFixed wx = SkIntToFixed(SkFixedFloor(fWalkX + SK_Fixed1)); 231639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com pointOnLine(wx, y); 232639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com if (y < fFirstY) { 233639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com y = fFirstY; 234639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com wx = fFirstX; 235639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 236639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com bool bottomCorner = fWalkX <= fX; 237639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com bool topCorner = x <= wx; 238639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com bool halfPlane = !(topCorner ^ bottomCorner); 239639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com if (halfPlane) { 240639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com if (x - SkIntToFixed(SkFixedFloor(fX)) <= SK_Fixed1) { 241639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com coverage = ~((fX + x) >> 1); // avg of fx, fx+dx 242639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com fFinished = true; 243639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } else { 244639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkAssertResult(y - SkIntToFixed(SkFixedFloor(fY)) <= SK_Fixed1); 245639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com coverage = ~((fY + y) >> 1); 246639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com fFinished = y == fY; 247639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com fWalkX = wx; 248639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com fY = fY0 = y; 249639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 250639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com coverage = coverage * partial >> 16; 251639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } else if (bottomCorner) { 252639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkFixed xDiff = wx - fX; 253639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkAssertResult(xDiff >= 0); 254639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkAssertResult(xDiff <= SK_Fixed1); 255639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkFixed yDiff = fWalkY - y; 256639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkAssertResult(yDiff >= 0); 257639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkAssertResult(yDiff <= SK_Fixed1); 258639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com int xCoverage = xDiff >> 1; // throw away 1 bit so multiply 259639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com int yCoverage = yDiff >> 1; // stays in range 260639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com int triangle = xCoverage * yCoverage; // 30 bits 261639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkFixed bottomPartial = fFirstY - y; 262639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com fFinished = bottomPartial >= 0; 263639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com if (fFinished) { 264639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com yCoverage = bottomPartial >> 1; 265639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com xCoverage = (wx - fFirstX) >> 1; 266639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com triangle -= xCoverage * yCoverage; 267639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 268639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com coverage = triangle >> 15; 269639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com fWalkX = wx; 270639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com fY = fY0 = y; 271639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } else { 272639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkAssertResult(topCorner); 273639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkFixed xDiff = x - fWalkX; 274639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkAssertResult(xDiff >= 0); 275639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkAssertResult(xDiff <= SK_Fixed1); 276639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkFixed yDiff = fY - wy; 277639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkAssertResult(yDiff >= 0); 278639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkAssertResult(yDiff <= SK_Fixed1); 279d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com int xCoverage = xDiff >> 1; // throw away 1 bit so multiply 280639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com int yCoverage = yDiff >> 1; // stays in range 281639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com int triangle = xCoverage * yCoverage >> 15; 282639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com coverage = partial - 1 - triangle; 283639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com fFinished = true; 284639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 285639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 286639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com validate(); 287639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com return coverage; 288639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com} 289639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 290639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.comvoid SkAntiEdge::advanceY(SkFixed top) { 291639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com validate(); 292639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com fX0 = SkFixedAddPin(fX0, fDX); 293639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com fPartialY = 0; 294639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com if (fDXFlipped) { 295639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com if (fX0 < fLastX) { 296639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com fWalkX = fX = fLastX; 297639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } else { 298639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com fWalkX = fX = fX0; 299639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 300639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkFixed bottom = top + SK_Fixed1; 301639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com if (bottom > fLastY) { 302639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com bottom = fLastY; 303639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 304639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkFixed vert = bottom - fFirstY; // distance from y start to x-axis 305639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkFixed backupX = fFirstX + SkFixedMul(vert, fDX); // x cell to back up to 306639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkFixed distX = fFirstX - SkIntToFixed(SkFixedFloor(backupX)); // to y-axis 307639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com fY0 = fFirstY + SkFixedMul(fDY, distX); 308639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 309639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com fY = top + SK_Fixed1; 310639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com if (fY > fLastY) { 311639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com fY = fLastY; 312639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 313639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com if (fLastY < top + SK_Fixed1) { 314639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com fPartialY = SkFixedFraction(fLastY); 315639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 316639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } else { 317639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com if (fX0 > fLastX) { 318639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com fX0 = fLastX; 319639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 320639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com fX = fX0; 321639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 322639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com fWalkY = SkIntToFixed(SkFixedFloor(fWalkY + SK_Fixed1)); 323639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com if (fWalkY > fLastY) { 324639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com fWalkY = fLastY; 325639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 326639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com validate(); 327639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com fFinished = false; 328639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com} 329639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 330639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.comint SkAntiEdgeBuilder::build(const SkPoint pts[], int count) { 331639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkAntiEdge* edge = fEdges.append(); 332639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com for (int index = 0; index < count; ++index) { 333639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com if (edge->setLine(pts[index], pts[(index + 1) % count])) { 334639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com edge = fEdges.append(); 335639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 336639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 337639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com int result = fEdges.count(); 338639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com fEdges.setCount(--result); 339639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com if (result > 0) { 340639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com sk_bzero(&fHeadEdge, sizeof(fHeadEdge)); 341639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com sk_bzero(&fTailEdge, sizeof(fTailEdge)); 342639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com for (int index = 0; index < result; ++index) { 343639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com *fList.append() = &fEdges[index]; 344639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 345639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 346639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com return result; 347639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com} 348639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 349639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.comvoid SkAntiEdgeBuilder::calc() { 350639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com for (SkAntiEdge* active = fEdges.begin(); active != fEdges.end(); ++active) { 351639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com active->calcLine(); 352639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 353639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com // compute winding sum for edges 354639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkAntiEdge* first = fHeadEdge.fNext; 355639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkAntiEdge* active; 356639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkAntiEdge* listTop = first; 357639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com for (active = first; active != &fTailEdge; active = active->fNext) { 358639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com active->fWindingSum = active->fWinding; 359639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com while (listTop->fLastY < active->fFirstY) { 360639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com listTop = listTop->fNext; 361639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 362639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com for (SkAntiEdge* check = listTop; check->fFirstY <= active->fFirstY; check = check->fNext) { 363639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com if (check == active) { 364639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com continue; 365639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 366639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com if (check->fLastY <= active->fFirstY) { 367639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com continue; 368639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 369639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com if (check->fFirstX > active->fFirstX) { 370639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com continue; 371639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 372639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com if (check->fFirstX == active->fFirstX && check->fDX > active->fDX) { 373639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com continue; 374639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 375639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com active->fWindingSum += check->fWinding; 376639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 377639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 378639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com} 379639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 380639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.comextern "C" { 381639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com static int edge_compare(const void* a, const void* b) { 382639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com const SkAntiEdge* edgea = *(const SkAntiEdge**)a; 383639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com const SkAntiEdge* edgeb = *(const SkAntiEdge**)b; 384639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 385639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com int valuea = edgea->fFirstY; 386639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com int valueb = edgeb->fFirstY; 387639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 388639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com if (valuea == valueb) { 389639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com valuea = edgea->fFirstX; 390639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com valueb = edgeb->fFirstX; 391639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 392d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com 393639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com if (valuea == valueb) { 394639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com valuea = edgea->fDX; 395639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com valueb = edgeb->fDX; 396639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 397639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 398639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com return valuea - valueb; 399639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 400639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com} 401639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 402639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.comvoid SkAntiEdgeBuilder::sort(SkTDArray<SkAntiEdge*>& listOfEdges) { 403639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkAntiEdge** list = listOfEdges.begin(); 404639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com int count = listOfEdges.count(); 405639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com qsort(list, count, sizeof(SkAntiEdge*), edge_compare); 406639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 407639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com // link the edges in sorted order 408639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com for (int i = 1; i < count; i++) { 409639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com list[i - 1]->fNext = list[i]; 410639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com list[i]->fPrev = list[i - 1]; 411639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 412639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com} 413639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 414639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com#define kEDGE_HEAD_XY SK_MinS32 415639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com#define kEDGE_TAIL_XY SK_MaxS32 416639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 417639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.comvoid SkAntiEdgeBuilder::sort() { 418639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com sort(fList); 419639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkAntiEdge* last = fList.end()[-1]; 420639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com fHeadEdge.fNext = fList[0]; 421639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com fHeadEdge.fFirstX = fHeadEdge.fFirstY = fHeadEdge.fWalkY = fHeadEdge.fLastY = kEDGE_HEAD_XY; 422639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com fList[0]->fPrev = &fHeadEdge; 423639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 424639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com fTailEdge.fPrev = last; 425639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com fTailEdge.fFirstX = fTailEdge.fFirstY = fTailEdge.fWalkY = fTailEdge.fLastY = kEDGE_TAIL_XY; 426639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com last->fNext = &fTailEdge; 427639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com} 428639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 429639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.comstatic inline void remove_edge(SkAntiEdge* edge) { 430639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com edge->fPrev->fNext = edge->fNext; 431639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com edge->fNext->fPrev = edge->fPrev; 432639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com} 433639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 434639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.comstatic inline void swap_edges(SkAntiEdge* prev, SkAntiEdge* next) { 435639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkASSERT(prev->fNext == next && next->fPrev == prev); 436639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 437639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com // remove prev from the list 438639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com prev->fPrev->fNext = next; 439639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com next->fPrev = prev->fPrev; 440639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 441639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com // insert prev after next 442639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com prev->fNext = next->fNext; 443639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com next->fNext->fPrev = prev; 444639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com next->fNext = prev; 445639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com prev->fPrev = next; 446639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com} 447639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 448639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.comstatic void backward_insert_edge_based_on_x(SkAntiEdge* edge SkDECLAREPARAM(int, y)) { 449639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkFixed x = edge->fFirstX; 450639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 451639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com for (;;) { 452639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkAntiEdge* prev = edge->fPrev; 453639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 454639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com // add 1 to curr_y since we may have added new edges (built from curves) 455639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com // that start on the next scanline 456639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkASSERT(prev && SkFixedFloor(prev->fWalkY - prev->fDXFlipped) <= y + 1); 457639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 458639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com if (prev->fFirstX <= x) { 459639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com break; 460639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 461639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com swap_edges(prev, edge); 462639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 463639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com} 464639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 465639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.comstatic void insert_new_edges(SkAntiEdge* newEdge, SkFixed curr_y) { 466639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com int y = SkFixedFloor(curr_y); 467639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com if (SkFixedFloor(newEdge->fWalkY - newEdge->fDXFlipped) < y) { 468639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com return; 469639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 470639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com while (SkFixedFloor(newEdge->fWalkY - newEdge->fDXFlipped) == y) { 471639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkAntiEdge* next = newEdge->fNext; 472639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com backward_insert_edge_based_on_x(newEdge SkPARAM(y)); 473639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com newEdge = next; 474639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 475639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com} 476639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 477639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.comstatic int find_active_edges(int y, SkAntiEdge** activeLeft, 478639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkAntiEdge** activeLast) { 479639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkAntiEdge* first = *activeLeft; 480639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkFixed bottom = first->fLastY; 481639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkAntiEdge* active = first->fNext; 482639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com first->fLinkSet = false; 483639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkFixed yLimit = SkIntToFixed(y + 1); // limiting pixel edge 484639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com for ( ; active->fWalkY != kEDGE_TAIL_XY; active = active->fNext) { 485639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com active->fLinkSet = false; 486639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com if (yLimit <= active->fWalkY - active->fDXFlipped) { 487639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com break; 488639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 489639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com if ((*activeLeft)->fWalkX > active->fWalkX) { 490639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com *activeLeft = active; 491639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 492639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com if (bottom > active->fLastY) { 493639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com bottom = active->fLastY; 494639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 495639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 496639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com *activeLast = active; 497639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com return SkFixedCeil(bottom); 498639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com} 499639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 500639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com// All edges are oriented to increase in y. Link edges with common tops and 501639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com// bottoms so the links can share their winding sum. 502639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.comvoid SkAntiEdgeBuilder::link() { 503639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkAntiEdge* tail = fEdges.end(); 504639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com // look for links forwards and backwards 505639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkAntiEdge* prev = fEdges.begin(); 506639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkAntiEdge* active; 507639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com for (active = prev + 1; active != tail; ++active) { 508639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com if (prev->fWinding == active->fWinding) { 509639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com if (prev->fLastX == active->fFirstX && prev->fLastY == active->fFirstY) { 510639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com prev->fLink = active; 511639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com active->fLinkSet = true; 512639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } else if (active->fLastX == prev->fFirstX && active->fLastY == prev->fFirstY) { 513639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com active->fLink = prev; 514639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com prev->fLinkSet = true; 515639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 516639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 517639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com prev = active; 518639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 519639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com // look for stragglers 520639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com prev = fEdges.begin() - 1; 521639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com do { 522639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com do { 523639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com if (++prev == tail) { 524639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com return; 525639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 526639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } while (prev->fLinkSet || NULL != prev->fLink); 527639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com for (active = prev + 1; active != tail; ++active) { 528639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com if (active->fLinkSet || NULL != active->fLink) { 529639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com continue; 530639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 531639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com if (prev->fWinding != active->fWinding) { 532639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com continue; 533639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 534639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com if (prev->fLastX == active->fFirstX && prev->fLastY == active->fFirstY) { 535639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com prev->fLink = active; 536639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com active->fLinkSet = true; 537639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com break; 538639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 539639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com if (active->fLastX == prev->fFirstX && active->fLastY == prev->fFirstY) { 540639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com active->fLink = prev; 541639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com prev->fLinkSet = true; 542639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com break; 543639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 544639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 545639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } while (true); 546639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com} 547639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 548639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.comvoid SkAntiEdgeBuilder::split(SkAntiEdge* edge, SkFixed y) { 549639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkPoint upperPoint = {edge->fFirstX, edge->fFirstY}; 550639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkPoint midPoint = {edge->fFirstX + SkMulDiv(y - edge->fFirstY, 551639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com edge->fLastX - edge->fFirstX, edge->fLastY - edge->fFirstY), y}; 552639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkPoint lowerPoint = {edge->fLastX, edge->fLastY}; 553639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com int8_t winding = edge->fWinding; 554639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com edge->setLine(upperPoint, midPoint); 555639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com edge->fWinding = winding; 556639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkAntiEdge* lower = fEdges.append(); 557639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com lower->setLine(midPoint, lowerPoint); 558639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com lower->fWinding = winding; 559639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com insert_new_edges(lower, y); 560639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com} 561639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 562639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com// An edge computes pixel coverage by considering the integral winding value 563639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com// to its left. If an edge is enclosed by fractional winding, split it. 564639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com// FIXME: This is also a good time to find crossing edges and split them, too. 565639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.comvoid SkAntiEdgeBuilder::split() { 566639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com // create a new set of edges that describe the whole link 567639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkTDArray<SkAntiEdge> links; 568639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkAntiEdge* first = fHeadEdge.fNext; 569639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkAntiEdge* active; 570639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com for (active = first; active != &fTailEdge; active = active->fNext) { 571639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com if (active->fLinkSet || NULL == active->fLink) { 572639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com continue; 573639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 574639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkAntiEdge* link = links.append(); 575639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com link->fFirstX = active->fFirstX; 576639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com link->fFirstY = active->fFirstY; 577639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkAntiEdge* linkEnd; 578639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkAntiEdge* next = active; 579639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com do { 580639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com linkEnd = next; 581639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com next = next->fLink; 582639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } while (NULL != next); 583639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com link->fLastX = linkEnd->fLastX; 584639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com link->fLastY = linkEnd->fLastY; 585639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 586639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com // create a list of all edges, links and singletons 587639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkTDArray<SkAntiEdge*> list; 588639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com for (active = links.begin(); active != links.end(); ++active) { 589639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com *list.append() = active; 590639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 591639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com for (active = first; active != &fTailEdge; active = active->fNext) { 592639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com if (!active->fLinkSet && NULL == active->fLink) { 593639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkAntiEdge* link = links.append(); 594639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com link->fFirstX = active->fFirstX; 595639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com link->fFirstY = active->fFirstY; 596639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com link->fLastX = active->fLastX; 597639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com link->fLastY = active->fLastY; 598639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com *list.append() = link; 599639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 600639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 601639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkAntiEdge tail; 602639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com tail.fFirstY = tail.fLastY = kEDGE_TAIL_XY; 603639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com *list.append() = &tail; 604639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com sort(list); 605639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com // walk the list, splitting edges partially occluded on the left 606639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkAntiEdge* listTop = list[0]; 607639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com for (active = first; active != &fTailEdge; active = active->fNext) { 608639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com while (listTop->fLastY < active->fFirstY) { 609639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com listTop = listTop->fNext; 610639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 611639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com for (SkAntiEdge* check = listTop; check->fFirstY < active->fLastY; check = check->fNext) { 612639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com if (check->fFirstX > active->fFirstX) { 613639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com continue; 614639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 615639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com if (check->fFirstX == active->fFirstX && check->fDX > active->fDX) { 616639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com continue; 617639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 618639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com if (check->fFirstY > active->fFirstY) { 619639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com split(active, check->fFirstY); 620639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 621639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com if (check->fLastY < active->fLastY) { 622639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com split(active, check->fLastY); 623639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 624639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 625639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 626639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com} 627639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 628639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.comstatic inline uint8_t coverage_to_8(int coverage) { 629639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com uint16_t x = coverage < 0 ? 0 : coverage > 0xFFFF ? 0xFFFF : coverage; 630639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com // for values 0x7FFF and smaller, add (0x7F - high byte) and trunc 631639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com // for values 0x8000 and larger, subtract (high byte - 0x80) and trunc 632639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com return (x + 0x7f + (x >> 15) - (x >> 8)) >> 8; 633639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com} 634639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 635639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.comvoid SkAntiEdgeBuilder::walk(uint8_t* result, int rowBytes, int height) { 636639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkAntiEdge* first = fHeadEdge.fNext; 637639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkFixed top = first->fWalkY - first->fDXFlipped; 638639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com int y = SkFixedFloor(top); 639639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com do { 640639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkAntiEdge* activeLeft = first; 641639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkAntiEdge* activeLast, * active; 642639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com int yLast = find_active_edges(y, &activeLeft, &activeLast); 643639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com while (y < yLast) { 644639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkAssertResult(y >= 0); 645639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkAssertResult(y < height); 646639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkFixed left = activeLeft->fWalkX; 647639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com int x = SkFixedFloor(left); 648639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com uint8_t* resultPtr = &result[y * rowBytes + x]; 649639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com bool finished; 650639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com do { 651639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com left = SkIntToFixed(x); 652639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkAssertResult(x >= 0); 653639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com // SkAssertResult(x < pixelCol); 654639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com if (x >= rowBytes) { // FIXME: cumulative error in fX += fDX 655639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com break; // fails to set fFinished early enough 656639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } // see test 6 (dy<dx) 657639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com finished = true; 658639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com int coverage = 0; 659639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com for (active = first; active != activeLast; active = active->fNext) { 660639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com if (left + SK_Fixed1 <= active->fX) { 661639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com finished = false; 662639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com continue; // walker is to the left of edge 663639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 664639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com int cover = active->fDXFlipped ? 665639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com active->advanceFlippedX(left) : active->advanceX(left); 666639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com if (0 == active->fWindingSum) { 667639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com cover = -cover; 668639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 669639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com coverage += cover; 670639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com finished &= active->fFinished; 671639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 672639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com uint8_t old = *resultPtr; 673639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com uint8_t pix = coverage_to_8(coverage); 674d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com uint8_t blend = old > pix ? old : pix; 675639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com *resultPtr++ = blend; 676639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com ++x; 677639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } while (!finished); 678639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com ++y; 679639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com top = SkIntToFixed(y); 680639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkFixed topLimit = top + SK_Fixed1; 681639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkFixed xSort = -SK_FixedMax; 682639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com for (active = first; active != activeLast; active = active->fNext) { 683639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com if (xSort > active->fX || topLimit > active->fLastY) { 684639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com yLast = y; // recompute bottom after all Ys are advanced 685639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 686639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com xSort = active->fX; 687639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com if (active->fWalkY < active->fLastY) { 688639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com active->advanceY(top); 689639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 690639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 691639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com for (active = first; active != activeLast; ) { 692639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkAntiEdge* next = active->fNext; 693639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com if (top >= active->fLastY) { 694639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com remove_edge(active); 695639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 696639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com active = next; 697639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 698639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com first = fHeadEdge.fNext; 699639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 700639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkAntiEdge* prev = activeLast->fPrev; 701639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com if (prev != &fHeadEdge) { 702639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com insert_new_edges(prev, top); 703639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com first = fHeadEdge.fNext; 704639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 705639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } while (first->fWalkY < kEDGE_TAIL_XY); 706639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com} 707639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 708639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.comvoid SkAntiEdgeBuilder::process(const SkPoint* points, int ptCount, 709639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com uint8_t* result, int pixelCol, int pixelRow) { 710639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com if (ptCount < 3) { 711639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com return; 712639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 713639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com int count = build(points, ptCount); 714639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com if (count == 0) { 715639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com return; 716639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 717639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkAssertResult(count > 1); 718639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com link(); 719639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com sort(); 720639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com split(); 721639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com calc(); 722639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com walk(result, pixelCol, pixelRow); 723639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com} 724639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 725639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com//////////////////////////////////////////////////////////////////////////////// 726639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 727639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.comint test3by3_test; 728639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 729639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com// input is a rectangle 730639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.comstatic void test_3_by_3() { 731639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com const int pixelRow = 3; 732639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com const int pixelCol = 3; 733639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com const int ptCount = 4; 734639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com const int pixelCount = pixelRow * pixelCol; 735639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com const SkPoint tests[][ptCount] = { 736639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com {{2.0f, 1.0f}, {1.0f, 1.0f}, {1.0f, 2.0f}, {2.0f, 2.0f}}, // 0: full rect 737639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com {{2.5f, 1.0f}, {1.5f, 1.0f}, {1.5f, 2.0f}, {2.5f, 2.0f}}, // 1: y edge 738639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com {{2.0f, 1.5f}, {1.0f, 1.5f}, {1.0f, 2.5f}, {2.0f, 2.5f}}, // 2: x edge 739639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com {{2.5f, 1.5f}, {1.5f, 1.5f}, {1.5f, 2.5f}, {2.5f, 2.5f}}, // 3: x/y edge 740639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com {{2.8f, 0.2f}, {0.2f, 0.2f}, {0.2f, 2.8f}, {2.8f, 2.8f}}, // 4: large 741639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com {{1.8f, 1.2f}, {1.2f, 1.2f}, {1.2f, 1.8f}, {1.8f, 1.8f}}, // 5: small 742639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com {{0.0f, 0.0f}, {0.0f, 1.0f}, {3.0f, 2.0f}, {3.0f, 1.0f}}, // 6: dy<dx 743639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com {{3.0f, 0.0f}, {0.0f, 1.0f}, {0.0f, 2.0f}, {3.0f, 1.0f}}, // 7: dy<-dx 744639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com {{1.0f, 0.0f}, {0.0f, 0.0f}, {1.0f, 3.0f}, {2.0f, 3.0f}}, // 8: dy>dx 745639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com {{2.0f, 0.0f}, {1.0f, 0.0f}, {0.0f, 3.0f}, {1.0f, 3.0f}}, // 9: dy>-dx 746639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com {{0.5f, 0.5f}, {0.5f, 1.5f}, {2.5f, 2.5f}, {2.5f, 1.5f}}, // 10: dy<dx 2 747639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com {{2.5f, 0.5f}, {0.5f, 1.5f}, {0.5f, 2.5f}, {2.5f, 1.5f}}, // 11: dy<-dx 2 748639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com {{0.0f, 0.0f}, {2.0f, 0.0f}, {2.0f, 2.0f}, {0.0f, 2.0f}}, // 12: 2x2 749639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com {{0.0f, 0.0f}, {3.0f, 0.0f}, {3.0f, 3.0f}, {0.0f, 3.0f}}, // 13: 3x3 750639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com {{1.75f, 0.25f}, {2.75f, 1.25f}, {1.25f, 2.75f}, {0.25f, 1.75f}}, // 14 751639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com {{2.25f, 0.25f}, {2.75f, 0.75f}, {0.75f, 2.75f}, {0.25f, 2.25f}}, // 15 752639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com {{0.25f, 0.75f}, {0.75f, 0.25f}, {2.75f, 2.25f}, {2.25f, 2.75f}}, // 16 753639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com {{1.25f, 0.50f}, {1.75f, 0.25f}, {2.75f, 2.25f}, {2.25f, 2.50f}}, // 17 754639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com {{1.00f, 0.75f}, {2.00f, 0.50f}, {2.00f, 1.50f}, {1.00f, 1.75f}}, // 18 755639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com {{1.00f, 0.50f}, {2.00f, 0.75f}, {2.00f, 1.75f}, {1.00f, 1.50f}}, // 19 756639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com {{1.00f, 0.75f}, {1.00f, 1.75f}, {2.00f, 1.50f}, {2.00f, 0.50f}}, // 20 757639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com {{1.00f, 0.50f}, {1.00f, 1.50f}, {2.00f, 1.75f}, {2.00f, 0.75f}}, // 21 758639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com }; 759639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com const uint8_t results[][pixelCount] = { 760639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com {0x00, 0x00, 0x00, // 0: 1 pixel rect 761639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 0x00, 0xFF, 0x00, 762639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 0x00, 0x00, 0x00}, 763639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com {0x00, 0x00, 0x00, // 1: y edge 764639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 0x00, 0x7F, 0x80, 765639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 0x00, 0x00, 0x00}, 766639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com {0x00, 0x00, 0x00, // 2: x edge 767639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 0x00, 0x7F, 0x00, 768639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 0x00, 0x7F, 0x00}, 769639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com {0x00, 0x00, 0x00, // 3: x/y edge 770639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 0x00, 0x40, 0x40, 771639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 0x00, 0x40, 0x40}, 772639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com {0xA3, 0xCC, 0xA3, // 4: large 773639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 0xCC, 0xFF, 0xCC, 774639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 0xA3, 0xCC, 0xA3}, 775639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com {0x00, 0x00, 0x00, // 5: small 776639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 0x00, 0x5C, 0x00, 777639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 0x00, 0x00, 0x00}, 778639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com {0xD5, 0x80, 0x2B, // 6: dy<dx 779639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 0x2A, 0x7F, 0xD4, 780639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 0x00, 0x00, 0x00}, 781639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com {0x2B, 0x80, 0xD5, // 7: dy<-dx 782639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 0xD4, 0x7F, 0x2A, 783639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 0x00, 0x00, 0x00}, 784639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com {0xD5, 0x2A, 0x00, // 8: dy>dx 785639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 0x80, 0x7F, 0x00, 786639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 0x2B, 0xD4, 0x00}, 787639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com {0x2A, 0xD5, 0x00, // 9: dy>-dx 788639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 0x7F, 0x80, 0x00, 789639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 0xD4, 0x2B, 0x00}, 790639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com {0x30, 0x10, 0x00, // 10: dy<dx 2 791639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 0x50, 0xDF, 0x50, 792639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 0x00, 0x10, 0x30}, 793639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com {0x00, 0x10, 0x30, // 11: dy<-dx 2 794639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 0x50, 0xDF, 0x50, 795639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 0x30, 0x10, 0x00}, 796639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com {0xFF, 0xFF, 0x00, // 12: 2x2 797639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 0xFF, 0xFF, 0x00, 798639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 0x00, 0x00, 0x00}, 799639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com {0xFF, 0xFF, 0xFF, // 13: 3x3 800639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 0xFF, 0xFF, 0xFF, 801639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 0xFF, 0xFF, 0xFF}, 802639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com {0x00, 0x70, 0x20, // 14 803639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 0x70, 0xFF, 0x70, 804639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 0x20, 0x70, 0x00}, 805639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com {0x00, 0x20, 0x60, // 15 806639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 0x20, 0xBF, 0x20, 807639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 0x60, 0x20, 0x00}, 808639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com {0x60, 0x20, 0x00, // 16 809639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 0x20, 0xBF, 0x20, 810639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 0x00, 0x20, 0x60}, 811639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com {0x00, 0x60, 0x04, // 17 812639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 0x00, 0x40, 0x60, 813639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 0x00, 0x00, 0x3C}, 814639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com {0x00, 0x60, 0x00, // 18 815639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 0x00, 0x9F, 0x00, 816639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 0x00, 0x00, 0x00}, 817639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com {0x00, 0x60, 0x00, // 19 818639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 0x00, 0x9F, 0x00, 819639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 0x00, 0x00, 0x00}, 820639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com {0x00, 0x60, 0x00, // 20 821639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 0x00, 0x9F, 0x00, 822639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 0x00, 0x00, 0x00}, 823639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com {0x00, 0x60, 0x00, // 21 824639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 0x00, 0x9F, 0x00, 825639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 0x00, 0x00, 0x00}, 826639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com }; 827639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com const int testCount = sizeof(tests) / sizeof(tests[0]); 828639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkAssertResult(testCount == sizeof(results) / sizeof(results[0])); 829639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com int testFirst = test3by3_test < 0 ? 0 : test3by3_test; 830639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com int testLast = test3by3_test < 0 ? testCount : test3by3_test + 1; 831639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com for (int testIndex = testFirst; testIndex < testLast; ++testIndex) { 832639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com uint8_t result[pixelRow][pixelCol]; 833639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com sk_bzero(result, sizeof(result)); 834639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com const SkPoint* rect = tests[testIndex]; 835639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkAntiEdgeBuilder builder; 836639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com builder.process(rect, ptCount, result[0], pixelCol, pixelRow); 837639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkAssertResult(memcmp(results[testIndex], result[0], pixelCount) == 0); 838639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 839639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com} 840639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 841639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com// input has arbitrary number of points 842639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.comstatic void test_arbitrary_3_by_3() { 843639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com const int pixelRow = 3; 844639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com const int pixelCol = 3; 845639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com const int pixelCount = pixelRow * pixelCol; 846639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com const SkPoint t1[] = { {1,1}, {2,1}, {2,1.5f}, {1,1.5f}, {1,2}, {2,2}, 847639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com {2,1.5f}, {1,1.5f}, {1,1} }; 848639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com const SkPoint* tests[] = { t1 }; 849639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com size_t testPts[] = { sizeof(t1) / sizeof(t1[0]) }; 850639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com const uint8_t results[][pixelCount] = { 851639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com {0x00, 0x00, 0x00, // 0: 1 pixel rect 852639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 0x00, 0xFF, 0x00, 853639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 0x00, 0x00, 0x00}, 854639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com }; 855639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com const int testCount = sizeof(tests) / sizeof(tests[0]); 856639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkAssertResult(testCount == sizeof(results) / sizeof(results[0])); 857639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com int testFirst = test3by3_test < 0 ? 0 : test3by3_test; 858639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com int testLast = test3by3_test < 0 ? testCount : test3by3_test + 1; 859639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com for (int testIndex = testFirst; testIndex < testLast; ++testIndex) { 860639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com uint8_t result[pixelRow][pixelCol]; 861639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com sk_bzero(result, sizeof(result)); 862639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com const SkPoint* pts = tests[testIndex]; 863639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com size_t ptCount = testPts[testIndex]; 864639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkAntiEdgeBuilder builder; 865639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com builder.process(pts, ptCount, result[0], pixelCol, pixelRow); 866639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkAssertResult(memcmp(results[testIndex], result[0], pixelCount) == 0); 867639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 868639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com} 869639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 870639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com#include "SkRect.h" 871639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com#include "SkPath.h" 872639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 873639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.comint testsweep_test; 874639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 875639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.comstatic void create_sweep(uint8_t* result, int pixelRow, int pixelCol, SkScalar rectWidth) { 876639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com const int ptCount = 4; 877639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkRect refRect = {pixelCol / 2 - rectWidth / 2, 5, 878639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com pixelCol / 2 + rectWidth / 2, pixelRow / 2 - 5}; 879639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkPath refPath; 880639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com refPath.addRect(refRect); 881639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkScalar angleFirst = testsweep_test < 0 ? 0 : testsweep_test; 882639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkScalar angleLast = testsweep_test < 0 ? 360 : testsweep_test + 1; 883639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com for (SkScalar angle = angleFirst; angle < angleLast; angle += 12) { 884639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkPath rotPath; 885639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkMatrix matrix; 886639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com matrix.setRotate(angle, SkIntToScalar(pixelCol) / 2, 887639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkIntToScalar(pixelRow) / 2); 888639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com refPath.transform(matrix, &rotPath); 889639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkPoint rect[ptCount], temp[2]; 890639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkPath::Iter iter(rotPath, false); 891639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com int index = 0; 892639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com for (;;) { 893639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkPath::Verb verb = iter.next(temp); 894639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com if (verb == SkPath::kMove_Verb) { 895639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com continue; 896639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 897639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com if (verb == SkPath::kClose_Verb) { 898639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com break; 899639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 900639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkAssertResult(SkPath::kLine_Verb == verb); 901639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com rect[index++] = temp[0]; 902639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 903639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkAntiEdgeBuilder builder; 904639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com builder.process(rect, ptCount, result, pixelCol, pixelRow); 905639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 906639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com} 907639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 908639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.comstatic void create_horz(uint8_t* result, int pixelRow, int pixelCol) { 909639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com const int ptCount = 4; 910639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com for (SkScalar x = 0; x < 100; x += 5) { 911639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkPoint rect[ptCount]; 912639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com rect[0].fX = 0; rect[0].fY = x; 913639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com rect[1].fX = 100; rect[1].fY = x; 914639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com rect[2].fX = 100; rect[2].fY = x + x / 50; 915639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com rect[3].fX = 0; rect[3].fY = x + x / 50; 916639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkAntiEdgeBuilder builder; 917639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com builder.process(rect, ptCount, result, pixelCol, pixelRow); 918639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 919639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com} 920639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 921639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.comstatic void create_vert(uint8_t* result, int pixelRow, int pixelCol) { 922639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com const int ptCount = 4; 923639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com for (SkScalar x = 0; x < 100; x += 5) { 924639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkPoint rect[ptCount]; 925639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com rect[0].fY = 0; rect[0].fX = x; 926639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com rect[1].fY = 100; rect[1].fX = x; 927639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com rect[2].fY = 100; rect[2].fX = x + x / 50; 928639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com rect[3].fY = 0; rect[3].fX = x + x / 50; 929639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkAntiEdgeBuilder builder; 930639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com builder.process(rect, ptCount, result, pixelCol, pixelRow); 931639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 932639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com} 933639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 934639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.comstatic void create_angle(uint8_t* result, int pixelRow, int pixelCol, SkScalar angle) { 935639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com const int ptCount = 4; 936639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkRect refRect = {25, 25, 125, 125}; 937639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkPath refPath; 938639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com for (SkScalar x = 30; x < 125; x += 5) { 939639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com refRect.fTop = x; 940639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com refRect.fBottom = x + (x - 25) / 50; 941639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com refPath.addRect(refRect); 942639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 943639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkPath rotPath; 944639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkMatrix matrix; 945639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com matrix.setRotate(angle, 75, 75); 946639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com refPath.transform(matrix, &rotPath); 947639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkPath::Iter iter(rotPath, false); 948639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com for (SkScalar x = 30; x < 125; x += 5) { 949639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkPoint rect[ptCount], temp[2]; 950639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com int index = 0; 951639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com for (;;) { 952639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkPath::Verb verb = iter.next(temp); 953639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com if (verb == SkPath::kMove_Verb) { 954639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com continue; 955639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 956639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com if (verb == SkPath::kClose_Verb) { 957639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com break; 958639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 959639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkAssertResult(SkPath::kLine_Verb == verb); 960639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com rect[index++] = temp[0]; 961639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 962639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com // if ((x == 30 || x == 75) && angle == 12) continue; 963639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkAntiEdgeBuilder builder; 964639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com builder.process(rect, ptCount, result, pixelCol, pixelRow); 965639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 966639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com} 967639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 968639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.comstatic void test_sweep() { 969639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com const int pixelRow = 100; 970639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com const int pixelCol = 100; 971639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com uint8_t result[pixelRow][pixelCol]; 972639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com sk_bzero(result, sizeof(result)); 973639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com create_sweep(result[0], pixelRow, pixelCol, 1); 974639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com} 975639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 976639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.comstatic void test_horz() { 977639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com const int pixelRow = 100; 978639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com const int pixelCol = 100; 979639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com uint8_t result[pixelRow][pixelCol]; 980639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com sk_bzero(result, sizeof(result)); 981639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com create_horz(result[0], pixelRow, pixelCol); 982639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com} 983639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 984639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.comstatic void test_vert() { 985639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com const int pixelRow = 100; 986639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com const int pixelCol = 100; 987639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com uint8_t result[pixelRow][pixelCol]; 988639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com sk_bzero(result, sizeof(result)); 989639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com create_vert(result[0], pixelRow, pixelCol); 990639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com} 991639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 992639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.comstatic void test_angle(SkScalar angle) { 993639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com const int pixelRow = 150; 994639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com const int pixelCol = 150; 995639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com uint8_t result[pixelRow][pixelCol]; 996639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com sk_bzero(result, sizeof(result)); 997639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com create_angle(result[0], pixelRow, pixelCol, angle); 998639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com} 999639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 1000639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com#include "SkBitmap.h" 1001639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 1002639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.comvoid CreateSweep(SkBitmap* sweep, SkScalar rectWidth) { 1003639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com const int pixelRow = 100; 1004639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com const int pixelCol = 100; 1005639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com sweep->setConfig(SkBitmap::kA8_Config, pixelCol, pixelRow); 1006639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com sweep->allocPixels(); 1007dbfac8a72393eaf01670aeb3244de0e18d8faf98junov@google.com sweep->eraseColor(SK_ColorTRANSPARENT); 1008639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com sweep->lockPixels(); 1009639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com void* pixels = sweep->getPixels(); 1010639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com create_sweep((uint8_t*) pixels, pixelRow, pixelCol, rectWidth); 1011639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com sweep->unlockPixels(); 1012639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com} 1013639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 1014639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.comvoid CreateHorz(SkBitmap* sweep) { 1015639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com const int pixelRow = 100; 1016639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com const int pixelCol = 100; 1017639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com sweep->setConfig(SkBitmap::kA8_Config, pixelCol, pixelRow); 1018639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com sweep->allocPixels(); 1019dbfac8a72393eaf01670aeb3244de0e18d8faf98junov@google.com sweep->eraseColor(SK_ColorTRANSPARENT); 1020639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com sweep->lockPixels(); 1021639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com void* pixels = sweep->getPixels(); 1022639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com create_horz((uint8_t*) pixels, pixelRow, pixelCol); 1023639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com sweep->unlockPixels(); 1024639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com} 1025639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 1026639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.comvoid CreateVert(SkBitmap* sweep) { 1027639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com const int pixelRow = 100; 1028639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com const int pixelCol = 100; 1029639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com sweep->setConfig(SkBitmap::kA8_Config, pixelCol, pixelRow); 1030639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com sweep->allocPixels(); 1031dbfac8a72393eaf01670aeb3244de0e18d8faf98junov@google.com sweep->eraseColor(SK_ColorTRANSPARENT); 1032639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com sweep->lockPixels(); 1033639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com void* pixels = sweep->getPixels(); 1034639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com create_vert((uint8_t*) pixels, pixelRow, pixelCol); 1035639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com sweep->unlockPixels(); 1036639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com} 1037639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 1038639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.comvoid CreateAngle(SkBitmap* sweep, SkScalar angle) { 1039639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com const int pixelRow = 150; 1040639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com const int pixelCol = 150; 1041639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com sweep->setConfig(SkBitmap::kA8_Config, pixelCol, pixelRow); 1042639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com sweep->allocPixels(); 1043dbfac8a72393eaf01670aeb3244de0e18d8faf98junov@google.com sweep->eraseColor(SK_ColorTRANSPARENT); 1044639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com sweep->lockPixels(); 1045639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com void* pixels = sweep->getPixels(); 1046639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com create_angle((uint8_t*) pixels, pixelRow, pixelCol, angle); 1047639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com sweep->unlockPixels(); 1048639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com} 1049639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 1050639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com#include "SkCanvas.h" 1051639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 1052639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.comstatic void testPng() { 1053639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkBitmap device; 1054639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com device.setConfig(SkBitmap::kARGB_8888_Config, 4, 4); 1055639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com device.allocPixels(); 1056639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com device.eraseColor(0xFFFFFFFF); 105782ba677e1729a2557f6115a724c9f793fd9bf162reed@google.com 105882ba677e1729a2557f6115a724c9f793fd9bf162reed@google.com SkCanvas canvas(device); 1059639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com canvas.drawARGB(167, 0, 0, 0); 106082ba677e1729a2557f6115a724c9f793fd9bf162reed@google.com 1061639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com device.lockPixels(); 1062639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com unsigned char* pixels = (unsigned char*) device.getPixels(); 1063639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com SkDebugf("%02x%02x%02x%02x", pixels[3], pixels[2], pixels[1], pixels[0]); 1064639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com} 1065639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com 1066639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.comvoid SkAntiEdge_Test() { 1067639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com testPng(); 1068639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com test_arbitrary_3_by_3(); 1069639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com test_angle(12); 1070639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com#if 0 1071639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com test3by3_test = 18; 1072639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com#else 1073639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com test3by3_test = -1; 1074639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com#endif 1075639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com#if 0 1076639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com testsweep_test = 7 * 12; 1077639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com#else 1078639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com testsweep_test = -1; 1079639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com#endif 1080639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com if (testsweep_test == -1) { 1081639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com test_3_by_3(); 1082639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com } 1083639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com test_sweep(); 1084639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com test_horz(); 1085639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com test_vert(); 1086639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com} 1087