1e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 2e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com/* 3e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com * Copyright 2011 Google Inc. 4e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com * 5e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com * Use of this source code is governed by a BSD-style license that can be 6e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com * found in the LICENSE file. 7e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com */ 8e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 9e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com#include "SkAAClip.h" 10e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com#include "SkBlitter.h" 11045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com#include "SkColorPriv.h" 12e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com#include "SkPath.h" 13e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com#include "SkScan.h" 14e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com#include "SkThread.h" 1534f7e47a3593911d03307a08e5af625b218ceec3reed@google.com#include "SkUtils.h" 16e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 17045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comclass AutoAAClipValidate { 18045e62d715f5ee9b03deb5af3c750f8318096179reed@google.compublic: 19045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com AutoAAClipValidate(const SkAAClip& clip) : fClip(clip) { 20045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fClip.validate(); 21045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 22045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com ~AutoAAClipValidate() { 23045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fClip.validate(); 24045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 25045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comprivate: 26045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const SkAAClip& fClip; 27045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com}; 28045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 29045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com#ifdef SK_DEBUG 30045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com #define AUTO_AACLIP_VALIDATE(clip) AutoAAClipValidate acv(clip) 31045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com#else 32045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com #define AUTO_AACLIP_VALIDATE(clip) 33045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com#endif 34045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 35045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com/////////////////////////////////////////////////////////////////////////////// 36045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 371c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com#define kMaxInt32 0x7FFFFFFF 381c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com 394b7d6730898abc9e02d1e12c2fd732945f4c1ab4commit-bot@chromium.org#ifdef SK_DEBUG 40e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comstatic inline bool x_in_rect(int x, const SkIRect& rect) { 41e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return (unsigned)(x - rect.fLeft) < (unsigned)rect.width(); 42e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 434b7d6730898abc9e02d1e12c2fd732945f4c1ab4commit-bot@chromium.org#endif 44e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 45e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comstatic inline bool y_in_rect(int y, const SkIRect& rect) { 46e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return (unsigned)(y - rect.fTop) < (unsigned)rect.height(); 47e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 48e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 49e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com/* 50e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com * Data runs are packed [count, alpha] 51e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com */ 52e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 53e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comstruct SkAAClip::YOffset { 54e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int32_t fY; 55e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com uint32_t fOffset; 56e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}; 57e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 58e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comstruct SkAAClip::RunHead { 59e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int32_t fRefCnt; 60e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int32_t fRowCount; 61493c65f1aa0864857c21b2be096740a17ef1430ascroggo@google.com size_t fDataSize; 62fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 63e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com YOffset* yoffsets() { 64e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return (YOffset*)((char*)this + sizeof(RunHead)); 65e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 66e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const YOffset* yoffsets() const { 67e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return (const YOffset*)((const char*)this + sizeof(RunHead)); 68e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 69e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com uint8_t* data() { 70e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return (uint8_t*)(this->yoffsets() + fRowCount); 71e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 72e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const uint8_t* data() const { 73e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return (const uint8_t*)(this->yoffsets() + fRowCount); 74e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 75e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 76e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com static RunHead* Alloc(int rowCount, size_t dataSize) { 77e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com size_t size = sizeof(RunHead) + rowCount * sizeof(YOffset) + dataSize; 78e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com RunHead* head = (RunHead*)sk_malloc_throw(size); 79e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com head->fRefCnt = 1; 80e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com head->fRowCount = rowCount; 81e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com head->fDataSize = dataSize; 82e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return head; 83e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 84045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 85045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com static int ComputeRowSizeForWidth(int width) { 86045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com // 2 bytes per segment, where each segment can store up to 255 for count 87045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com int segments = 0; 88045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com while (width > 0) { 89045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com segments += 1; 90045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com int n = SkMin32(width, 255); 91045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com width -= n; 92045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 93045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return segments * 2; // each segment is row[0] + row[1] (n + alpha) 94045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 95045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 96045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com static RunHead* AllocRect(const SkIRect& bounds) { 97045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(!bounds.isEmpty()); 98045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com int width = bounds.width(); 99045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com size_t rowSize = ComputeRowSizeForWidth(width); 100045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com RunHead* head = RunHead::Alloc(1, rowSize); 101045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com YOffset* yoff = head->yoffsets(); 102045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com yoff->fY = bounds.height() - 1; 103045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com yoff->fOffset = 0; 104045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com uint8_t* row = head->data(); 105045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com while (width > 0) { 106045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com int n = SkMin32(width, 255); 107045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com row[0] = n; 108045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com row[1] = 0xFF; 109045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com width -= n; 110045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com row += 2; 111045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 112045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return head; 113045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 114e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}; 115e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 116322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comclass SkAAClip::Iter { 117322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.compublic: 118322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com Iter(const SkAAClip&); 119322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 120322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com bool done() const { return fDone; } 1211c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com int top() const { return fTop; } 1221c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com int bottom() const { return fBottom; } 1231c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com const uint8_t* data() const { return fData; } 124322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com void next(); 125322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 126322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comprivate: 127322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com const YOffset* fCurrYOff; 128322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com const YOffset* fStopYOff; 129322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com const uint8_t* fData; 130322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 131322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com int fTop, fBottom; 132322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com bool fDone; 133322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com}; 134322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 135322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comSkAAClip::Iter::Iter(const SkAAClip& clip) { 136322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com if (clip.isEmpty()) { 137322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com fDone = true; 1381c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fTop = fBottom = clip.fBounds.fBottom; 1391c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fData = NULL; 1406c035f6c873d02d3cf46ecf67b6d9c2af3c374d8commit-bot@chromium.org fCurrYOff = NULL; 141a4c6e4d6d3a4010df8dd2b04314675e4c201133breed@google.com fStopYOff = NULL; 142322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return; 143322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 144fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 145322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com const RunHead* head = clip.fRunHead; 146322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com fCurrYOff = head->yoffsets(); 147322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com fStopYOff = fCurrYOff + head->fRowCount; 148322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com fData = head->data() + fCurrYOff->fOffset; 149322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 150322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com // setup first value 151322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com fTop = clip.fBounds.fTop; 152322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com fBottom = clip.fBounds.fTop + fCurrYOff->fY + 1; 153322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com fDone = false; 154322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com} 155322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 156322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comvoid SkAAClip::Iter::next() { 1571c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (!fDone) { 1581c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com const YOffset* prev = fCurrYOff; 1591c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com const YOffset* curr = prev + 1; 1601c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com SkASSERT(curr <= fStopYOff); 161322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 162322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com fTop = fBottom; 1631c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (curr >= fStopYOff) { 1641c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fDone = true; 1651c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fBottom = kMaxInt32; 1661c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fData = NULL; 1671c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } else { 1681c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fBottom += curr->fY - prev->fY; 1691c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fData += curr->fOffset - prev->fOffset; 1701c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fCurrYOff = curr; 1711c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } 172322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 173322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com} 174322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 175045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com#ifdef SK_DEBUG 176c90419199525141a5b98091f856e359bf9daf5b1reed@google.com// assert we're exactly width-wide, and then return the number of bytes used 177045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comstatic size_t compute_row_length(const uint8_t row[], int width) { 178045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const uint8_t* origRow = row; 179045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com while (width > 0) { 180045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com int n = row[0]; 181c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(n > 0); 182045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(n <= width); 183045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com row += 2; 184045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com width -= n; 185045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 186045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(0 == width); 187045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return row - origRow; 188045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com} 189045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 190045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comvoid SkAAClip::validate() const { 191045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (NULL == fRunHead) { 192045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(fBounds.isEmpty()); 193045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return; 194045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 195045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 196045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const RunHead* head = fRunHead; 197045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(head->fRefCnt > 0); 198045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(head->fRowCount > 0); 199045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 200045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const YOffset* yoff = head->yoffsets(); 201045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const YOffset* ystop = yoff + head->fRowCount; 202c90419199525141a5b98091f856e359bf9daf5b1reed@google.com const int lastY = fBounds.height() - 1; 203c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 204c90419199525141a5b98091f856e359bf9daf5b1reed@google.com // Y and offset must be monotonic 205c90419199525141a5b98091f856e359bf9daf5b1reed@google.com int prevY = -1; 206c90419199525141a5b98091f856e359bf9daf5b1reed@google.com int32_t prevOffset = -1; 207045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com while (yoff < ystop) { 208c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(prevY < yoff->fY); 209c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(yoff->fY <= lastY); 210c90419199525141a5b98091f856e359bf9daf5b1reed@google.com prevY = yoff->fY; 211c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(prevOffset < (int32_t)yoff->fOffset); 212c90419199525141a5b98091f856e359bf9daf5b1reed@google.com prevOffset = yoff->fOffset; 213c90419199525141a5b98091f856e359bf9daf5b1reed@google.com const uint8_t* row = head->data() + yoff->fOffset; 214045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com size_t rowLength = compute_row_length(row, fBounds.width()); 215493c65f1aa0864857c21b2be096740a17ef1430ascroggo@google.com SkASSERT(yoff->fOffset + rowLength <= head->fDataSize); 216c90419199525141a5b98091f856e359bf9daf5b1reed@google.com yoff += 1; 217045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 218045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com // check the last entry; 219045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com --yoff; 220c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(yoff->fY == lastY); 221045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com} 222045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com#endif 223045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 224045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com/////////////////////////////////////////////////////////////////////////////// 225045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 226768fee8b6e9ae0a849ed45ab377fc9079b5db11erobertphillips@google.com// Count the number of zeros on the left and right edges of the passed in 227768fee8b6e9ae0a849ed45ab377fc9079b5db11erobertphillips@google.com// RLE row. If 'row' is all zeros return 'width' in both variables. 228c90419199525141a5b98091f856e359bf9daf5b1reed@google.comstatic void count_left_right_zeros(const uint8_t* row, int width, 229c90419199525141a5b98091f856e359bf9daf5b1reed@google.com int* leftZ, int* riteZ) { 230c90419199525141a5b98091f856e359bf9daf5b1reed@google.com int zeros = 0; 231c90419199525141a5b98091f856e359bf9daf5b1reed@google.com do { 232c90419199525141a5b98091f856e359bf9daf5b1reed@google.com if (row[1]) { 233c90419199525141a5b98091f856e359bf9daf5b1reed@google.com break; 234c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 235c90419199525141a5b98091f856e359bf9daf5b1reed@google.com int n = row[0]; 236c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(n > 0); 237c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(n <= width); 238c90419199525141a5b98091f856e359bf9daf5b1reed@google.com zeros += n; 239c90419199525141a5b98091f856e359bf9daf5b1reed@google.com row += 2; 240c90419199525141a5b98091f856e359bf9daf5b1reed@google.com width -= n; 241c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } while (width > 0); 242c90419199525141a5b98091f856e359bf9daf5b1reed@google.com *leftZ = zeros; 243c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 244768fee8b6e9ae0a849ed45ab377fc9079b5db11erobertphillips@google.com if (0 == width) { 245768fee8b6e9ae0a849ed45ab377fc9079b5db11erobertphillips@google.com // this line is completely empty return 'width' in both variables 246768fee8b6e9ae0a849ed45ab377fc9079b5db11erobertphillips@google.com *riteZ = *leftZ; 247768fee8b6e9ae0a849ed45ab377fc9079b5db11erobertphillips@google.com return; 248768fee8b6e9ae0a849ed45ab377fc9079b5db11erobertphillips@google.com } 249768fee8b6e9ae0a849ed45ab377fc9079b5db11erobertphillips@google.com 250c90419199525141a5b98091f856e359bf9daf5b1reed@google.com zeros = 0; 251c90419199525141a5b98091f856e359bf9daf5b1reed@google.com while (width > 0) { 252c90419199525141a5b98091f856e359bf9daf5b1reed@google.com int n = row[0]; 253c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(n > 0); 254c90419199525141a5b98091f856e359bf9daf5b1reed@google.com if (0 == row[1]) { 255c90419199525141a5b98091f856e359bf9daf5b1reed@google.com zeros += n; 256c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } else { 257c90419199525141a5b98091f856e359bf9daf5b1reed@google.com zeros = 0; 258c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 259c90419199525141a5b98091f856e359bf9daf5b1reed@google.com row += 2; 260c90419199525141a5b98091f856e359bf9daf5b1reed@google.com width -= n; 261c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 262c90419199525141a5b98091f856e359bf9daf5b1reed@google.com *riteZ = zeros; 263c90419199525141a5b98091f856e359bf9daf5b1reed@google.com} 264c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 265c90419199525141a5b98091f856e359bf9daf5b1reed@google.com#ifdef SK_DEBUG 266c90419199525141a5b98091f856e359bf9daf5b1reed@google.comstatic void test_count_left_right_zeros() { 267c90419199525141a5b98091f856e359bf9daf5b1reed@google.com static bool gOnce; 268c90419199525141a5b98091f856e359bf9daf5b1reed@google.com if (gOnce) { 269c90419199525141a5b98091f856e359bf9daf5b1reed@google.com return; 270c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 271c90419199525141a5b98091f856e359bf9daf5b1reed@google.com gOnce = true; 272c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 273c90419199525141a5b98091f856e359bf9daf5b1reed@google.com const uint8_t data0[] = { 0, 0, 10, 0xFF }; 274c90419199525141a5b98091f856e359bf9daf5b1reed@google.com const uint8_t data1[] = { 0, 0, 5, 0xFF, 2, 0, 3, 0xFF }; 275c90419199525141a5b98091f856e359bf9daf5b1reed@google.com const uint8_t data2[] = { 7, 0, 5, 0, 2, 0, 3, 0xFF }; 276c90419199525141a5b98091f856e359bf9daf5b1reed@google.com const uint8_t data3[] = { 0, 5, 5, 0xFF, 2, 0, 3, 0 }; 277c90419199525141a5b98091f856e359bf9daf5b1reed@google.com const uint8_t data4[] = { 2, 3, 2, 0, 5, 0xFF, 3, 0 }; 278768fee8b6e9ae0a849ed45ab377fc9079b5db11erobertphillips@google.com const uint8_t data5[] = { 10, 10, 10, 0 }; 279c90419199525141a5b98091f856e359bf9daf5b1reed@google.com const uint8_t data6[] = { 2, 2, 2, 0, 2, 0xFF, 2, 0, 2, 0xFF, 2, 0 }; 280c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 281c90419199525141a5b98091f856e359bf9daf5b1reed@google.com const uint8_t* array[] = { 282c90419199525141a5b98091f856e359bf9daf5b1reed@google.com data0, data1, data2, data3, data4, data5, data6 283c90419199525141a5b98091f856e359bf9daf5b1reed@google.com }; 284c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 285c90419199525141a5b98091f856e359bf9daf5b1reed@google.com for (size_t i = 0; i < SK_ARRAY_COUNT(array); ++i) { 286c90419199525141a5b98091f856e359bf9daf5b1reed@google.com const uint8_t* data = array[i]; 287c90419199525141a5b98091f856e359bf9daf5b1reed@google.com const int expectedL = *data++; 288c90419199525141a5b98091f856e359bf9daf5b1reed@google.com const int expectedR = *data++; 289c90419199525141a5b98091f856e359bf9daf5b1reed@google.com int L = 12345, R = 12345; 290c90419199525141a5b98091f856e359bf9daf5b1reed@google.com count_left_right_zeros(data, 10, &L, &R); 291c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(expectedL == L); 292c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(expectedR == R); 293c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 294c90419199525141a5b98091f856e359bf9daf5b1reed@google.com} 295c90419199525141a5b98091f856e359bf9daf5b1reed@google.com#endif 296c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 297c90419199525141a5b98091f856e359bf9daf5b1reed@google.com// modify row in place, trimming off (zeros) from the left and right sides. 298c90419199525141a5b98091f856e359bf9daf5b1reed@google.com// return the number of bytes that were completely eliminated from the left 299c90419199525141a5b98091f856e359bf9daf5b1reed@google.comstatic int trim_row_left_right(uint8_t* row, int width, int leftZ, int riteZ) { 300c90419199525141a5b98091f856e359bf9daf5b1reed@google.com int trim = 0; 301c90419199525141a5b98091f856e359bf9daf5b1reed@google.com while (leftZ > 0) { 302c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(0 == row[1]); 303c90419199525141a5b98091f856e359bf9daf5b1reed@google.com int n = row[0]; 304c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(n > 0); 305c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(n <= width); 306c90419199525141a5b98091f856e359bf9daf5b1reed@google.com width -= n; 307c90419199525141a5b98091f856e359bf9daf5b1reed@google.com row += 2; 308c90419199525141a5b98091f856e359bf9daf5b1reed@google.com if (n > leftZ) { 309c90419199525141a5b98091f856e359bf9daf5b1reed@google.com row[-2] = n - leftZ; 310c90419199525141a5b98091f856e359bf9daf5b1reed@google.com break; 311c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 312c90419199525141a5b98091f856e359bf9daf5b1reed@google.com trim += 2; 313c90419199525141a5b98091f856e359bf9daf5b1reed@google.com leftZ -= n; 314c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(leftZ >= 0); 315c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 316c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 317c90419199525141a5b98091f856e359bf9daf5b1reed@google.com if (riteZ) { 318c90419199525141a5b98091f856e359bf9daf5b1reed@google.com // walk row to the end, and then we'll back up to trim riteZ 319c90419199525141a5b98091f856e359bf9daf5b1reed@google.com while (width > 0) { 320c90419199525141a5b98091f856e359bf9daf5b1reed@google.com int n = row[0]; 321c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(n <= width); 322c90419199525141a5b98091f856e359bf9daf5b1reed@google.com width -= n; 323c90419199525141a5b98091f856e359bf9daf5b1reed@google.com row += 2; 324c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 325c90419199525141a5b98091f856e359bf9daf5b1reed@google.com // now skip whole runs of zeros 326c90419199525141a5b98091f856e359bf9daf5b1reed@google.com do { 327c90419199525141a5b98091f856e359bf9daf5b1reed@google.com row -= 2; 328c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(0 == row[1]); 329c90419199525141a5b98091f856e359bf9daf5b1reed@google.com int n = row[0]; 330c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(n > 0); 331c90419199525141a5b98091f856e359bf9daf5b1reed@google.com if (n > riteZ) { 332c90419199525141a5b98091f856e359bf9daf5b1reed@google.com row[0] = n - riteZ; 333c90419199525141a5b98091f856e359bf9daf5b1reed@google.com break; 334c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 335c90419199525141a5b98091f856e359bf9daf5b1reed@google.com riteZ -= n; 336c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(riteZ >= 0); 337c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } while (riteZ > 0); 338c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 339fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 340c90419199525141a5b98091f856e359bf9daf5b1reed@google.com return trim; 341c90419199525141a5b98091f856e359bf9daf5b1reed@google.com} 342c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 343c90419199525141a5b98091f856e359bf9daf5b1reed@google.com#ifdef SK_DEBUG 344c90419199525141a5b98091f856e359bf9daf5b1reed@google.com// assert that this row is exactly this width 345c5507bfe2d54e411ef6eb83452b8cbfbae009610reed@google.comstatic void assert_row_width(const uint8_t* row, int width) { 346c90419199525141a5b98091f856e359bf9daf5b1reed@google.com while (width > 0) { 347c90419199525141a5b98091f856e359bf9daf5b1reed@google.com int n = row[0]; 348c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(n > 0); 349c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(n <= width); 350c90419199525141a5b98091f856e359bf9daf5b1reed@google.com width -= n; 351c90419199525141a5b98091f856e359bf9daf5b1reed@google.com row += 2; 352c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 353c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(0 == width); 354c90419199525141a5b98091f856e359bf9daf5b1reed@google.com} 355c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 356c90419199525141a5b98091f856e359bf9daf5b1reed@google.comstatic void test_trim_row_left_right() { 357c90419199525141a5b98091f856e359bf9daf5b1reed@google.com static bool gOnce; 358c90419199525141a5b98091f856e359bf9daf5b1reed@google.com if (gOnce) { 359c90419199525141a5b98091f856e359bf9daf5b1reed@google.com return; 360c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 361c90419199525141a5b98091f856e359bf9daf5b1reed@google.com gOnce = true; 362fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 363c90419199525141a5b98091f856e359bf9daf5b1reed@google.com uint8_t data0[] = { 0, 0, 0, 10, 10, 0xFF }; 364c90419199525141a5b98091f856e359bf9daf5b1reed@google.com uint8_t data1[] = { 2, 0, 0, 10, 5, 0, 2, 0, 3, 0xFF }; 365c90419199525141a5b98091f856e359bf9daf5b1reed@google.com uint8_t data2[] = { 5, 0, 2, 10, 5, 0, 2, 0, 3, 0xFF }; 366c90419199525141a5b98091f856e359bf9daf5b1reed@google.com uint8_t data3[] = { 6, 0, 2, 10, 5, 0, 2, 0, 3, 0xFF }; 367c90419199525141a5b98091f856e359bf9daf5b1reed@google.com uint8_t data4[] = { 0, 0, 0, 10, 2, 0, 2, 0xFF, 2, 0, 2, 0xFF, 2, 0 }; 368c90419199525141a5b98091f856e359bf9daf5b1reed@google.com uint8_t data5[] = { 1, 0, 0, 10, 2, 0, 2, 0xFF, 2, 0, 2, 0xFF, 2, 0 }; 369c90419199525141a5b98091f856e359bf9daf5b1reed@google.com uint8_t data6[] = { 0, 1, 0, 10, 2, 0, 2, 0xFF, 2, 0, 2, 0xFF, 2, 0 }; 370c90419199525141a5b98091f856e359bf9daf5b1reed@google.com uint8_t data7[] = { 1, 1, 0, 10, 2, 0, 2, 0xFF, 2, 0, 2, 0xFF, 2, 0 }; 371c90419199525141a5b98091f856e359bf9daf5b1reed@google.com uint8_t data8[] = { 2, 2, 2, 10, 2, 0, 2, 0xFF, 2, 0, 2, 0xFF, 2, 0 }; 372c90419199525141a5b98091f856e359bf9daf5b1reed@google.com uint8_t data9[] = { 5, 2, 4, 10, 2, 0, 2, 0, 2, 0, 2, 0xFF, 2, 0 }; 373c90419199525141a5b98091f856e359bf9daf5b1reed@google.com uint8_t data10[] ={ 74, 0, 4, 150, 9, 0, 65, 0, 76, 0xFF }; 374fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 375c90419199525141a5b98091f856e359bf9daf5b1reed@google.com uint8_t* array[] = { 376c90419199525141a5b98091f856e359bf9daf5b1reed@google.com data0, data1, data2, data3, data4, 377c90419199525141a5b98091f856e359bf9daf5b1reed@google.com data5, data6, data7, data8, data9, 378c90419199525141a5b98091f856e359bf9daf5b1reed@google.com data10 379c90419199525141a5b98091f856e359bf9daf5b1reed@google.com }; 380fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 381c90419199525141a5b98091f856e359bf9daf5b1reed@google.com for (size_t i = 0; i < SK_ARRAY_COUNT(array); ++i) { 382c90419199525141a5b98091f856e359bf9daf5b1reed@google.com uint8_t* data = array[i]; 383c90419199525141a5b98091f856e359bf9daf5b1reed@google.com const int trimL = *data++; 384c90419199525141a5b98091f856e359bf9daf5b1reed@google.com const int trimR = *data++; 385c90419199525141a5b98091f856e359bf9daf5b1reed@google.com const int expectedSkip = *data++; 386c90419199525141a5b98091f856e359bf9daf5b1reed@google.com const int origWidth = *data++; 387c90419199525141a5b98091f856e359bf9daf5b1reed@google.com assert_row_width(data, origWidth); 388c90419199525141a5b98091f856e359bf9daf5b1reed@google.com int skip = trim_row_left_right(data, origWidth, trimL, trimR); 389c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(expectedSkip == skip); 390c90419199525141a5b98091f856e359bf9daf5b1reed@google.com int expectedWidth = origWidth - trimL - trimR; 391c90419199525141a5b98091f856e359bf9daf5b1reed@google.com assert_row_width(data + skip, expectedWidth); 392c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 393c90419199525141a5b98091f856e359bf9daf5b1reed@google.com} 394c90419199525141a5b98091f856e359bf9daf5b1reed@google.com#endif 395c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 396c90419199525141a5b98091f856e359bf9daf5b1reed@google.combool SkAAClip::trimLeftRight() { 397c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkDEBUGCODE(test_trim_row_left_right();) 398c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 399c90419199525141a5b98091f856e359bf9daf5b1reed@google.com if (this->isEmpty()) { 400c90419199525141a5b98091f856e359bf9daf5b1reed@google.com return false; 401c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 402fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 403c90419199525141a5b98091f856e359bf9daf5b1reed@google.com AUTO_AACLIP_VALIDATE(*this); 404c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 405c90419199525141a5b98091f856e359bf9daf5b1reed@google.com const int width = fBounds.width(); 406c90419199525141a5b98091f856e359bf9daf5b1reed@google.com RunHead* head = fRunHead; 407c90419199525141a5b98091f856e359bf9daf5b1reed@google.com YOffset* yoff = head->yoffsets(); 408c90419199525141a5b98091f856e359bf9daf5b1reed@google.com YOffset* stop = yoff + head->fRowCount; 409c90419199525141a5b98091f856e359bf9daf5b1reed@google.com uint8_t* base = head->data(); 410c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 411768fee8b6e9ae0a849ed45ab377fc9079b5db11erobertphillips@google.com // After this loop, 'leftZeros' & 'rightZeros' will contain the minimum 412768fee8b6e9ae0a849ed45ab377fc9079b5db11erobertphillips@google.com // number of zeros on the left and right of the clip. This information 413768fee8b6e9ae0a849ed45ab377fc9079b5db11erobertphillips@google.com // can be used to shrink the bounding box. 414c90419199525141a5b98091f856e359bf9daf5b1reed@google.com int leftZeros = width; 415c90419199525141a5b98091f856e359bf9daf5b1reed@google.com int riteZeros = width; 416c90419199525141a5b98091f856e359bf9daf5b1reed@google.com while (yoff < stop) { 417c90419199525141a5b98091f856e359bf9daf5b1reed@google.com int L, R; 418c90419199525141a5b98091f856e359bf9daf5b1reed@google.com count_left_right_zeros(base + yoff->fOffset, width, &L, &R); 419768fee8b6e9ae0a849ed45ab377fc9079b5db11erobertphillips@google.com SkASSERT(L + R < width || (L == width && R == width)); 420c90419199525141a5b98091f856e359bf9daf5b1reed@google.com if (L < leftZeros) { 421c90419199525141a5b98091f856e359bf9daf5b1reed@google.com leftZeros = L; 422c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 423c90419199525141a5b98091f856e359bf9daf5b1reed@google.com if (R < riteZeros) { 424c90419199525141a5b98091f856e359bf9daf5b1reed@google.com riteZeros = R; 425c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 426c90419199525141a5b98091f856e359bf9daf5b1reed@google.com if (0 == (leftZeros | riteZeros)) { 427c90419199525141a5b98091f856e359bf9daf5b1reed@google.com // no trimming to do 428c90419199525141a5b98091f856e359bf9daf5b1reed@google.com return true; 429c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 430c90419199525141a5b98091f856e359bf9daf5b1reed@google.com yoff += 1; 431c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 432c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 433c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(leftZeros || riteZeros); 434768fee8b6e9ae0a849ed45ab377fc9079b5db11erobertphillips@google.com if (width == leftZeros) { 435768fee8b6e9ae0a849ed45ab377fc9079b5db11erobertphillips@google.com SkASSERT(width == riteZeros); 436c90419199525141a5b98091f856e359bf9daf5b1reed@google.com return this->setEmpty(); 437c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 438c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 439c90419199525141a5b98091f856e359bf9daf5b1reed@google.com this->validate(); 440c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 441c90419199525141a5b98091f856e359bf9daf5b1reed@google.com fBounds.fLeft += leftZeros; 442c90419199525141a5b98091f856e359bf9daf5b1reed@google.com fBounds.fRight -= riteZeros; 443c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(!fBounds.isEmpty()); 444c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 445c90419199525141a5b98091f856e359bf9daf5b1reed@google.com // For now we don't realloc the storage (for time), we just shrink in place 446c90419199525141a5b98091f856e359bf9daf5b1reed@google.com // This means we don't have to do any memmoves either, since we can just 447c90419199525141a5b98091f856e359bf9daf5b1reed@google.com // play tricks with the yoff->fOffset for each row 448c90419199525141a5b98091f856e359bf9daf5b1reed@google.com yoff = head->yoffsets(); 449c90419199525141a5b98091f856e359bf9daf5b1reed@google.com while (yoff < stop) { 450c90419199525141a5b98091f856e359bf9daf5b1reed@google.com uint8_t* row = base + yoff->fOffset; 451c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkDEBUGCODE((void)compute_row_length(row, width);) 452c90419199525141a5b98091f856e359bf9daf5b1reed@google.com yoff->fOffset += trim_row_left_right(row, width, leftZeros, riteZeros); 453c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkDEBUGCODE((void)compute_row_length(base + yoff->fOffset, width - leftZeros - riteZeros);) 454c90419199525141a5b98091f856e359bf9daf5b1reed@google.com yoff += 1; 455c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 456c90419199525141a5b98091f856e359bf9daf5b1reed@google.com return true; 457c90419199525141a5b98091f856e359bf9daf5b1reed@google.com} 458c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 459c90419199525141a5b98091f856e359bf9daf5b1reed@google.comstatic bool row_is_all_zeros(const uint8_t* row, int width) { 460c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(width > 0); 461c90419199525141a5b98091f856e359bf9daf5b1reed@google.com do { 462c90419199525141a5b98091f856e359bf9daf5b1reed@google.com if (row[1]) { 463c90419199525141a5b98091f856e359bf9daf5b1reed@google.com return false; 464c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 465c90419199525141a5b98091f856e359bf9daf5b1reed@google.com int n = row[0]; 466c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(n <= width); 467c90419199525141a5b98091f856e359bf9daf5b1reed@google.com width -= n; 468c90419199525141a5b98091f856e359bf9daf5b1reed@google.com row += 2; 469c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } while (width > 0); 470c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(0 == width); 471c90419199525141a5b98091f856e359bf9daf5b1reed@google.com return true; 472c90419199525141a5b98091f856e359bf9daf5b1reed@google.com} 473c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 474c90419199525141a5b98091f856e359bf9daf5b1reed@google.combool SkAAClip::trimTopBottom() { 475c90419199525141a5b98091f856e359bf9daf5b1reed@google.com if (this->isEmpty()) { 476c90419199525141a5b98091f856e359bf9daf5b1reed@google.com return false; 477c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 478c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 479d6040f6f2fcb11fddad5d92b3cb7255e90931bccreed@google.com this->validate(); 480d6040f6f2fcb11fddad5d92b3cb7255e90931bccreed@google.com 481c90419199525141a5b98091f856e359bf9daf5b1reed@google.com const int width = fBounds.width(); 482c90419199525141a5b98091f856e359bf9daf5b1reed@google.com RunHead* head = fRunHead; 483c90419199525141a5b98091f856e359bf9daf5b1reed@google.com YOffset* yoff = head->yoffsets(); 484c90419199525141a5b98091f856e359bf9daf5b1reed@google.com YOffset* stop = yoff + head->fRowCount; 485c90419199525141a5b98091f856e359bf9daf5b1reed@google.com const uint8_t* base = head->data(); 486c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 487c90419199525141a5b98091f856e359bf9daf5b1reed@google.com // Look to trim away empty rows from the top. 488c90419199525141a5b98091f856e359bf9daf5b1reed@google.com // 489c90419199525141a5b98091f856e359bf9daf5b1reed@google.com int skip = 0; 490c90419199525141a5b98091f856e359bf9daf5b1reed@google.com while (yoff < stop) { 491c90419199525141a5b98091f856e359bf9daf5b1reed@google.com const uint8_t* data = base + yoff->fOffset; 492c90419199525141a5b98091f856e359bf9daf5b1reed@google.com if (!row_is_all_zeros(data, width)) { 493c90419199525141a5b98091f856e359bf9daf5b1reed@google.com break; 494c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 495c90419199525141a5b98091f856e359bf9daf5b1reed@google.com skip += 1; 496c90419199525141a5b98091f856e359bf9daf5b1reed@google.com yoff += 1; 497c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 498c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(skip <= head->fRowCount); 499c90419199525141a5b98091f856e359bf9daf5b1reed@google.com if (skip == head->fRowCount) { 500c90419199525141a5b98091f856e359bf9daf5b1reed@google.com return this->setEmpty(); 501c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 502c90419199525141a5b98091f856e359bf9daf5b1reed@google.com if (skip > 0) { 503c90419199525141a5b98091f856e359bf9daf5b1reed@google.com // adjust fRowCount and fBounds.fTop, and slide all the data up 504c90419199525141a5b98091f856e359bf9daf5b1reed@google.com // as we remove [skip] number of YOffset entries 505c90419199525141a5b98091f856e359bf9daf5b1reed@google.com yoff = head->yoffsets(); 506c90419199525141a5b98091f856e359bf9daf5b1reed@google.com int dy = yoff[skip - 1].fY + 1; 507c90419199525141a5b98091f856e359bf9daf5b1reed@google.com for (int i = skip; i < head->fRowCount; ++i) { 508c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(yoff[i].fY >= dy); 509c90419199525141a5b98091f856e359bf9daf5b1reed@google.com yoff[i].fY -= dy; 510c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 511c90419199525141a5b98091f856e359bf9daf5b1reed@google.com YOffset* dst = head->yoffsets(); 512c90419199525141a5b98091f856e359bf9daf5b1reed@google.com size_t size = head->fRowCount * sizeof(YOffset) + head->fDataSize; 513c90419199525141a5b98091f856e359bf9daf5b1reed@google.com memmove(dst, dst + skip, size - skip * sizeof(YOffset)); 514c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 515c90419199525141a5b98091f856e359bf9daf5b1reed@google.com fBounds.fTop += dy; 516c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(!fBounds.isEmpty()); 517c90419199525141a5b98091f856e359bf9daf5b1reed@google.com head->fRowCount -= skip; 518c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(head->fRowCount > 0); 519fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 520d6040f6f2fcb11fddad5d92b3cb7255e90931bccreed@google.com this->validate(); 521d6040f6f2fcb11fddad5d92b3cb7255e90931bccreed@google.com // need to reset this after the memmove 522d6040f6f2fcb11fddad5d92b3cb7255e90931bccreed@google.com base = head->data(); 523c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 524c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 525c90419199525141a5b98091f856e359bf9daf5b1reed@google.com // Look to trim away empty rows from the bottom. 526c90419199525141a5b98091f856e359bf9daf5b1reed@google.com // We know that we have at least one non-zero row, so we can just walk 527c90419199525141a5b98091f856e359bf9daf5b1reed@google.com // backwards without checking for running past the start. 528c90419199525141a5b98091f856e359bf9daf5b1reed@google.com // 529c90419199525141a5b98091f856e359bf9daf5b1reed@google.com stop = yoff = head->yoffsets() + head->fRowCount; 530c90419199525141a5b98091f856e359bf9daf5b1reed@google.com do { 531c90419199525141a5b98091f856e359bf9daf5b1reed@google.com yoff -= 1; 532c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } while (row_is_all_zeros(base + yoff->fOffset, width)); 533a8c7f7702fb4bbedb615031bc653c5cd161a038ecommit-bot@chromium.org skip = SkToInt(stop - yoff - 1); 534c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(skip >= 0 && skip < head->fRowCount); 535c90419199525141a5b98091f856e359bf9daf5b1reed@google.com if (skip > 0) { 536c90419199525141a5b98091f856e359bf9daf5b1reed@google.com // removing from the bottom is easier than from the top, as we don't 537c90419199525141a5b98091f856e359bf9daf5b1reed@google.com // have to adjust any of the Y values, we just have to trim the array 538c90419199525141a5b98091f856e359bf9daf5b1reed@google.com memmove(stop - skip, stop, head->fDataSize); 539c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 540c90419199525141a5b98091f856e359bf9daf5b1reed@google.com fBounds.fBottom = fBounds.fTop + yoff->fY + 1; 541c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(!fBounds.isEmpty()); 542c90419199525141a5b98091f856e359bf9daf5b1reed@google.com head->fRowCount -= skip; 543c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(head->fRowCount > 0); 544c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 545d6040f6f2fcb11fddad5d92b3cb7255e90931bccreed@google.com this->validate(); 546c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 547c90419199525141a5b98091f856e359bf9daf5b1reed@google.com return true; 548c90419199525141a5b98091f856e359bf9daf5b1reed@google.com} 549c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 550045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com// can't validate before we're done, since trimming is part of the process of 551045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com// making us valid after the Builder. Since we build from top to bottom, its 552045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com// possible our fBounds.fBottom is bigger than our last scanline of data, so 553045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com// we trim fBounds.fBottom back up. 554045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com// 555045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com// TODO: check for duplicates in X and Y to further compress our data 556045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com// 557045e62d715f5ee9b03deb5af3c750f8318096179reed@google.combool SkAAClip::trimBounds() { 558045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (this->isEmpty()) { 559045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return false; 560045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 561045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 562045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const RunHead* head = fRunHead; 563045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const YOffset* yoff = head->yoffsets(); 564045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 565045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(head->fRowCount > 0); 566045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const YOffset& lastY = yoff[head->fRowCount - 1]; 567045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(lastY.fY + 1 <= fBounds.height()); 568045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fBounds.fBottom = fBounds.fTop + lastY.fY + 1; 569045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(lastY.fY + 1 == fBounds.height()); 570c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(!fBounds.isEmpty()); 571c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 572c90419199525141a5b98091f856e359bf9daf5b1reed@google.com return this->trimTopBottom() && this->trimLeftRight(); 573045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com} 574045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 575e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com/////////////////////////////////////////////////////////////////////////////// 576e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 577e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comvoid SkAAClip::freeRuns() { 57847ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com if (fRunHead) { 579e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(fRunHead->fRefCnt >= 1); 580e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (1 == sk_atomic_dec(&fRunHead->fRefCnt)) { 581e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com sk_free(fRunHead); 582e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 583e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 584e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 585e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 586e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comSkAAClip::SkAAClip() { 587e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fBounds.setEmpty(); 58847ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com fRunHead = NULL; 589e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 590e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 591e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comSkAAClip::SkAAClip(const SkAAClip& src) { 592045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkDEBUGCODE(fBounds.setEmpty();) // need this for validate 59347ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com fRunHead = NULL; 594e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com *this = src; 595e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 596e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 597e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comSkAAClip::~SkAAClip() { 598e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com this->freeRuns(); 599e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 600e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 601e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comSkAAClip& SkAAClip::operator=(const SkAAClip& src) { 602045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com AUTO_AACLIP_VALIDATE(*this); 603045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com src.validate(); 604045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 605e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (this != &src) { 606e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com this->freeRuns(); 607e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fBounds = src.fBounds; 608e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fRunHead = src.fRunHead; 60947ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com if (fRunHead) { 610e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com sk_atomic_inc(&fRunHead->fRefCnt); 611e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 612e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 613e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return *this; 614e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 615e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 616e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.combool operator==(const SkAAClip& a, const SkAAClip& b) { 617045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com a.validate(); 618045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com b.validate(); 619045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 620e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (&a == &b) { 621e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return true; 622e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 623e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (a.fBounds != b.fBounds) { 624e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return false; 625e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 626fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 627e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const SkAAClip::RunHead* ah = a.fRunHead; 628e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const SkAAClip::RunHead* bh = b.fRunHead; 629fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 630e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com // this catches empties and rects being equal 631e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (ah == bh) { 632e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return true; 633e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 634e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 635e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com // now we insist that both are complex (but different ptrs) 63647ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com if (!a.fRunHead || !b.fRunHead) { 637e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return false; 638e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 639e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 640e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return ah->fRowCount == bh->fRowCount && 641e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com ah->fDataSize == bh->fDataSize && 642e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com !memcmp(ah->data(), bh->data(), ah->fDataSize); 643e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 644e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 645e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comvoid SkAAClip::swap(SkAAClip& other) { 646045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com AUTO_AACLIP_VALIDATE(*this); 647045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com other.validate(); 648045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 649e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkTSwap(fBounds, other.fBounds); 650e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkTSwap(fRunHead, other.fRunHead); 651e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 652e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 653322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.combool SkAAClip::set(const SkAAClip& src) { 654322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com *this = src; 655322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return !this->isEmpty(); 656322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com} 657322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 658e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.combool SkAAClip::setEmpty() { 659e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com this->freeRuns(); 660e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fBounds.setEmpty(); 66147ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com fRunHead = NULL; 662e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return false; 663e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 664e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 665e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.combool SkAAClip::setRect(const SkIRect& bounds) { 666e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (bounds.isEmpty()) { 667e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return this->setEmpty(); 668e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 66947ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com 670045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com AUTO_AACLIP_VALIDATE(*this); 67147ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com 672045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com#if 0 67347ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com SkRect r; 67447ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com r.set(bounds); 67547ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com SkPath path; 67647ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com path.addRect(r); 67747ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com return this->setPath(path); 678045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com#else 679045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com this->freeRuns(); 680045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fBounds = bounds; 681045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fRunHead = RunHead::AllocRect(bounds); 682045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(!this->isEmpty()); 683045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return true; 684045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com#endif 685e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 686e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 687f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.combool SkAAClip::setRect(const SkRect& r, bool doAA) { 688e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (r.isEmpty()) { 689e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return this->setEmpty(); 690e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 691e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 692045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com AUTO_AACLIP_VALIDATE(*this); 693045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 694045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com // TODO: special case this 695045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 696e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkPath path; 697e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com path.addRect(r); 698f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com return this->setPath(path, NULL, doAA); 699f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com} 700f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com 701a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.comstatic void append_run(SkTDArray<uint8_t>& array, uint8_t value, int count) { 702a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com SkASSERT(count >= 0); 703a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com while (count > 0) { 704a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com int n = count; 705a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com if (n > 255) { 706a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com n = 255; 707a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com } 708a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com uint8_t* data = array.append(2); 709a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com data[0] = n; 710a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com data[1] = value; 711a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com count -= n; 712a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com } 713a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com} 714a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com 715f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.combool SkAAClip::setRegion(const SkRegion& rgn) { 716f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com if (rgn.isEmpty()) { 717f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com return this->setEmpty(); 718f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com } 719f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com if (rgn.isRect()) { 720f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com return this->setRect(rgn.getBounds()); 721f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com } 722a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com 723a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com#if 0 724f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com SkAAClip clip; 725f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com SkRegion::Iterator iter(rgn); 726f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com for (; !iter.done(); iter.next()) { 727f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com clip.op(iter.rect(), SkRegion::kUnion_Op); 728f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com } 729f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com this->swap(clip); 7303771a030b0b6686b0ec81359774836cc376ea3f4reed@google.com return !this->isEmpty(); 731fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com#else 732a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com const SkIRect& bounds = rgn.getBounds(); 733a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com const int offsetX = bounds.fLeft; 734a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com const int offsetY = bounds.fTop; 735a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com 736a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com SkTDArray<YOffset> yArray; 737a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com SkTDArray<uint8_t> xArray; 738a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com 739a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com yArray.setReserve(SkMin32(bounds.height(), 1024)); 740a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com xArray.setReserve(SkMin32(bounds.width() * 128, 64 * 1024)); 741a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com 742a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com SkRegion::Iterator iter(rgn); 743a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com int prevRight = 0; 744a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com int prevBot = 0; 745a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com YOffset* currY = NULL; 746a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com 747a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com for (; !iter.done(); iter.next()) { 748a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com const SkIRect& r = iter.rect(); 749a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com SkASSERT(bounds.contains(r)); 750a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com 751a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com int bot = r.fBottom - offsetY; 752a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com SkASSERT(bot >= prevBot); 753a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com if (bot > prevBot) { 754a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com if (currY) { 755a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com // flush current row 756a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com append_run(xArray, 0, bounds.width() - prevRight); 757a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com } 758a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com // did we introduce an empty-gap from the prev row? 759a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com int top = r.fTop - offsetY; 760a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com if (top > prevBot) { 761a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com currY = yArray.append(); 762a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com currY->fY = top - 1; 763a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com currY->fOffset = xArray.count(); 764a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com append_run(xArray, 0, bounds.width()); 765a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com } 766a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com // create a new record for this Y value 767a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com currY = yArray.append(); 768a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com currY->fY = bot - 1; 769a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com currY->fOffset = xArray.count(); 770a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com prevRight = 0; 771a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com prevBot = bot; 772a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com } 773a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com 774a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com int x = r.fLeft - offsetX; 775a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com append_run(xArray, 0, x - prevRight); 776a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com 777a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com int w = r.fRight - r.fLeft; 778a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com append_run(xArray, 0xFF, w); 779a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com prevRight = x + w; 780a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com SkASSERT(prevRight <= bounds.width()); 781a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com } 782a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com // flush last row 783a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com append_run(xArray, 0, bounds.width() - prevRight); 784a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com 785a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com // now pack everything into a RunHead 786a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com RunHead* head = RunHead::Alloc(yArray.count(), xArray.bytes()); 787a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com memcpy(head->yoffsets(), yArray.begin(), yArray.bytes()); 788a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com memcpy(head->data(), xArray.begin(), xArray.bytes()); 789a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com 790a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com this->setEmpty(); 791a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com fBounds = bounds; 792a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com fRunHead = head; 793a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com this->validate(); 794a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com return true; 795a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com#endif 796e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 797e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 798e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com/////////////////////////////////////////////////////////////////////////////// 799e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 800e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comconst uint8_t* SkAAClip::findRow(int y, int* lastYForRow) const { 80147ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com SkASSERT(fRunHead); 802e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 803e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (!y_in_rect(y, fBounds)) { 804e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return NULL; 805e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 806e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com y -= fBounds.y(); // our yoffs values are relative to the top 807e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 808e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const YOffset* yoff = fRunHead->yoffsets(); 809e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com while (yoff->fY < y) { 810e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com yoff += 1; 811e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(yoff - fRunHead->yoffsets() < fRunHead->fRowCount); 812e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 813e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 814e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (lastYForRow) { 815045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com *lastYForRow = fBounds.y() + yoff->fY; 816e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 817e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return fRunHead->data() + yoff->fOffset; 818e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 819e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 820e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comconst uint8_t* SkAAClip::findX(const uint8_t data[], int x, int* initialCount) const { 821e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(x_in_rect(x, fBounds)); 822e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com x -= fBounds.x(); 823e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 824e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com // first skip up to X 825e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com for (;;) { 826e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int n = data[0]; 827e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (x < n) { 828a4c6e4d6d3a4010df8dd2b04314675e4c201133breed@google.com if (initialCount) { 829a4c6e4d6d3a4010df8dd2b04314675e4c201133breed@google.com *initialCount = n - x; 830a4c6e4d6d3a4010df8dd2b04314675e4c201133breed@google.com } 831e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com break; 832e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 833e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com data += 2; 834e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com x -= n; 835e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 836e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return data; 837e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 838e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 839e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.combool SkAAClip::quickContains(int left, int top, int right, int bottom) const { 840e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (this->isEmpty()) { 841e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return false; 842e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 843e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (!fBounds.contains(left, top, right, bottom)) { 844e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return false; 845e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 846322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com#if 0 847e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (this->isRect()) { 848e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return true; 849e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 850322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com#endif 851e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 852a4c6e4d6d3a4010df8dd2b04314675e4c201133breed@google.com int lastY SK_INIT_TO_AVOID_WARNING; 853e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const uint8_t* row = this->findRow(top, &lastY); 854e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (lastY < bottom) { 855e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return false; 856e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 857e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com // now just need to check in X 858045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com int count; 859045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com row = this->findX(row, left, &count); 860045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com#if 0 861045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return count >= (right - left) && 0xFF == row[1]; 862045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com#else 863045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com int rectWidth = right - left; 864045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com while (0xFF == row[1]) { 865045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (count >= rectWidth) { 866045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return true; 867045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 868045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com rectWidth -= count; 869045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com row += 2; 870045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com count = row[0]; 871045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 872045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return false; 873045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com#endif 874e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 875e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 876e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com/////////////////////////////////////////////////////////////////////////////// 877e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 878e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comclass SkAAClip::Builder { 879e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkIRect fBounds; 880e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com struct Row { 881e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int fY; 882e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int fWidth; 883e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkTDArray<uint8_t>* fData; 884e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com }; 885e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkTDArray<Row> fRows; 886e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com Row* fCurrRow; 887e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int fPrevY; 888e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int fWidth; 889209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com int fMinY; 890e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 891e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.compublic: 892e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com Builder(const SkIRect& bounds) : fBounds(bounds) { 893e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fPrevY = -1; 894e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fWidth = bounds.width(); 895e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fCurrRow = NULL; 896209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com fMinY = bounds.fTop; 897e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 898e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 899e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com ~Builder() { 900e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com Row* row = fRows.begin(); 901e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com Row* stop = fRows.end(); 902e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com while (row < stop) { 903e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com delete row->fData; 904e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com row += 1; 905e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 906e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 907e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 908322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com const SkIRect& getBounds() const { return fBounds; } 909322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 910e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com void addRun(int x, int y, U8CPU alpha, int count) { 911e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(count > 0); 912e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(fBounds.contains(x, y)); 913e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(fBounds.contains(x + count - 1, y)); 914fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 915e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com x -= fBounds.left(); 916e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com y -= fBounds.top(); 917fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 918e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com Row* row = fCurrRow; 919e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (y != fPrevY) { 920e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(y > fPrevY); 921e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fPrevY = y; 922e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com row = this->flushRow(true); 923e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com row->fY = y; 924e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com row->fWidth = 0; 925e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(row->fData); 926e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(0 == row->fData->count()); 927e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fCurrRow = row; 928e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 929e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 930e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(row->fWidth <= x); 931e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(row->fWidth < fBounds.width()); 932e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 933e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkTDArray<uint8_t>& data = *row->fData; 934e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 935e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int gap = x - row->fWidth; 936e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (gap) { 937e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com AppendRun(data, 0, gap); 938e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com row->fWidth += gap; 939e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(row->fWidth < fBounds.width()); 940e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 941e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 942e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com AppendRun(data, alpha, count); 943e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com row->fWidth += count; 944e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(row->fWidth <= fBounds.width()); 945e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 946e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 94749eac192faa35159752525b23345563252721c64tomhudson@google.com void addColumn(int x, int y, U8CPU alpha, int height) { 94849eac192faa35159752525b23345563252721c64tomhudson@google.com SkASSERT(fBounds.contains(x, y + height - 1)); 94949eac192faa35159752525b23345563252721c64tomhudson@google.com 95049eac192faa35159752525b23345563252721c64tomhudson@google.com this->addRun(x, y, alpha, 1); 95149eac192faa35159752525b23345563252721c64tomhudson@google.com this->flushRowH(fCurrRow); 95249eac192faa35159752525b23345563252721c64tomhudson@google.com y -= fBounds.fTop; 95349eac192faa35159752525b23345563252721c64tomhudson@google.com SkASSERT(y == fCurrRow->fY); 95449eac192faa35159752525b23345563252721c64tomhudson@google.com fCurrRow->fY = y + height - 1; 95549eac192faa35159752525b23345563252721c64tomhudson@google.com } 956fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 9579154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com void addRectRun(int x, int y, int width, int height) { 9589154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com SkASSERT(fBounds.contains(x + width - 1, y + height - 1)); 9599154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com this->addRun(x, y, 0xFF, width); 9609154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com 961a89c77b5cafcc13d76cb07c3240e48705cb30d8freed@google.com // we assum the rect must be all we'll see for these scanlines 9629154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com // so we ensure our row goes all the way to our right 9639154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com this->flushRowH(fCurrRow); 9649154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com 9659154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com y -= fBounds.fTop; 9669154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com SkASSERT(y == fCurrRow->fY); 9679154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com fCurrRow->fY = y + height - 1; 9689154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com } 9699154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com 97049eac192faa35159752525b23345563252721c64tomhudson@google.com void addAntiRectRun(int x, int y, int width, int height, 97149eac192faa35159752525b23345563252721c64tomhudson@google.com SkAlpha leftAlpha, SkAlpha rightAlpha) { 97249eac192faa35159752525b23345563252721c64tomhudson@google.com SkASSERT(fBounds.contains(x + width - 1 + 97349eac192faa35159752525b23345563252721c64tomhudson@google.com (leftAlpha > 0 ? 1 : 0) + (rightAlpha > 0 ? 1 : 0), 97449eac192faa35159752525b23345563252721c64tomhudson@google.com y + height - 1)); 97549eac192faa35159752525b23345563252721c64tomhudson@google.com SkASSERT(width >= 0); 97649eac192faa35159752525b23345563252721c64tomhudson@google.com 97749eac192faa35159752525b23345563252721c64tomhudson@google.com // Conceptually we're always adding 3 runs, but we should 97849eac192faa35159752525b23345563252721c64tomhudson@google.com // merge or omit them if possible. 97949eac192faa35159752525b23345563252721c64tomhudson@google.com if (leftAlpha == 0xFF) { 98049eac192faa35159752525b23345563252721c64tomhudson@google.com width++; 98149eac192faa35159752525b23345563252721c64tomhudson@google.com } else if (leftAlpha > 0) { 98249eac192faa35159752525b23345563252721c64tomhudson@google.com this->addRun(x++, y, leftAlpha, 1); 98349eac192faa35159752525b23345563252721c64tomhudson@google.com } 98449eac192faa35159752525b23345563252721c64tomhudson@google.com if (rightAlpha == 0xFF) { 98549eac192faa35159752525b23345563252721c64tomhudson@google.com width++; 98649eac192faa35159752525b23345563252721c64tomhudson@google.com } 98749eac192faa35159752525b23345563252721c64tomhudson@google.com if (width > 0) { 98849eac192faa35159752525b23345563252721c64tomhudson@google.com this->addRun(x, y, 0xFF, width); 98949eac192faa35159752525b23345563252721c64tomhudson@google.com } 99049eac192faa35159752525b23345563252721c64tomhudson@google.com if (rightAlpha > 0 && rightAlpha < 255) { 99149eac192faa35159752525b23345563252721c64tomhudson@google.com this->addRun(x + width, y, rightAlpha, 1); 99249eac192faa35159752525b23345563252721c64tomhudson@google.com } 99349eac192faa35159752525b23345563252721c64tomhudson@google.com 99449eac192faa35159752525b23345563252721c64tomhudson@google.com // we assume the rect must be all we'll see for these scanlines 99549eac192faa35159752525b23345563252721c64tomhudson@google.com // so we ensure our row goes all the way to our right 99649eac192faa35159752525b23345563252721c64tomhudson@google.com this->flushRowH(fCurrRow); 99749eac192faa35159752525b23345563252721c64tomhudson@google.com 99849eac192faa35159752525b23345563252721c64tomhudson@google.com y -= fBounds.fTop; 99949eac192faa35159752525b23345563252721c64tomhudson@google.com SkASSERT(y == fCurrRow->fY); 100049eac192faa35159752525b23345563252721c64tomhudson@google.com fCurrRow->fY = y + height - 1; 100149eac192faa35159752525b23345563252721c64tomhudson@google.com } 100249eac192faa35159752525b23345563252721c64tomhudson@google.com 1003045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com bool finish(SkAAClip* target) { 1004e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com this->flushRow(false); 1005e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1006e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const Row* row = fRows.begin(); 1007e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const Row* stop = fRows.end(); 1008e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1009fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com size_t dataSize = 0; 1010e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com while (row < stop) { 1011e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com dataSize += row->fData->count(); 1012e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com row += 1; 1013e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1014e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1015045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (0 == dataSize) { 1016045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return target->setEmpty(); 1017045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1018045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1019209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com SkASSERT(fMinY >= fBounds.fTop); 1020209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com SkASSERT(fMinY < fBounds.fBottom); 1021209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com int adjustY = fMinY - fBounds.fTop; 1022209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com fBounds.fTop = fMinY; 1023209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com 1024e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com RunHead* head = RunHead::Alloc(fRows.count(), dataSize); 1025e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com YOffset* yoffset = head->yoffsets(); 1026e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com uint8_t* data = head->data(); 1027e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com uint8_t* baseData = data; 1028e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1029e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com row = fRows.begin(); 1030c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkDEBUGCODE(int prevY = row->fY - 1;) 1031e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com while (row < stop) { 1032c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(prevY < row->fY); // must be monotonic 1033c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkDEBUGCODE(prevY = row->fY); 1034c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 1035209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com yoffset->fY = row->fY - adjustY; 1036a8c7f7702fb4bbedb615031bc653c5cd161a038ecommit-bot@chromium.org yoffset->fOffset = SkToU32(data - baseData); 1037e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com yoffset += 1; 1038fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1039e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com size_t n = row->fData->count(); 1040e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com memcpy(data, row->fData->begin(), n); 1041c90419199525141a5b98091f856e359bf9daf5b1reed@google.com#ifdef SK_DEBUG 1042f74ad8c91aef4f328dbcbcebae9e436c00a35140tomhudson@google.com size_t bytesNeeded = compute_row_length(data, fBounds.width()); 1043c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(bytesNeeded == n); 1044c90419199525141a5b98091f856e359bf9daf5b1reed@google.com#endif 1045e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com data += n; 1046fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1047e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com row += 1; 1048e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1049e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1050045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com target->freeRuns(); 1051045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com target->fBounds = fBounds; 1052045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com target->fRunHead = head; 1053045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return target->trimBounds(); 1054e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1055e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1056e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com void dump() { 1057e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com this->validate(); 1058e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int y; 1059e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com for (y = 0; y < fRows.count(); ++y) { 1060e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const Row& row = fRows[y]; 1061e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkDebugf("Y:%3d W:%3d", row.fY, row.fWidth); 1062e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const SkTDArray<uint8_t>& data = *row.fData; 1063e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int count = data.count(); 1064e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(!(count & 1)); 1065e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const uint8_t* ptr = data.begin(); 1066e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com for (int x = 0; x < count; x += 2) { 1067e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkDebugf(" [%3d:%02X]", ptr[0], ptr[1]); 1068e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com ptr += 2; 1069e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1070e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkDebugf("\n"); 1071e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1072e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1073e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1074e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com void validate() { 1075e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com#ifdef SK_DEBUG 1076803eceb6afd13f07416df0b4a9bb714e9370f081caryclark@google.com if (false) { // avoid bit rot, suppress warning 1077803eceb6afd13f07416df0b4a9bb714e9370f081caryclark@google.com test_count_left_right_zeros(); 1078803eceb6afd13f07416df0b4a9bb714e9370f081caryclark@google.com } 1079e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int prevY = -1; 1080e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com for (int i = 0; i < fRows.count(); ++i) { 1081e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const Row& row = fRows[i]; 1082e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(prevY < row.fY); 1083e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(fWidth == row.fWidth); 1084e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int count = row.fData->count(); 1085e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const uint8_t* ptr = row.fData->begin(); 1086e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(!(count & 1)); 1087e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int w = 0; 1088e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com for (int x = 0; x < count; x += 2) { 1089d6040f6f2fcb11fddad5d92b3cb7255e90931bccreed@google.com int n = ptr[0]; 1090d6040f6f2fcb11fddad5d92b3cb7255e90931bccreed@google.com SkASSERT(n > 0); 1091d6040f6f2fcb11fddad5d92b3cb7255e90931bccreed@google.com w += n; 1092e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(w <= fWidth); 1093e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com ptr += 2; 1094e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1095e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(w == fWidth); 1096e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com prevY = row.fY; 1097e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1098e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com#endif 1099e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1100e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1101209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com // only called by BuilderBlitter 1102209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com void setMinY(int y) { 1103209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com fMinY = y; 1104209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com } 1105209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com 1106e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comprivate: 11079154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com void flushRowH(Row* row) { 11089154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com // flush current row if needed 11099154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com if (row->fWidth < fWidth) { 11109154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com AppendRun(*row->fData, 0, fWidth - row->fWidth); 11119154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com row->fWidth = fWidth; 11129154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com } 11139154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com } 1114209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com 1115e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com Row* flushRow(bool readyForAnother) { 1116e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com Row* next = NULL; 1117e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int count = fRows.count(); 1118e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (count > 0) { 11199154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com this->flushRowH(&fRows[count - 1]); 1120e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1121e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (count > 1) { 1122e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com // are our last two runs the same? 1123e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com Row* prev = &fRows[count - 2]; 1124e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com Row* curr = &fRows[count - 1]; 1125e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(prev->fWidth == fWidth); 1126e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(curr->fWidth == fWidth); 1127e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (*prev->fData == *curr->fData) { 1128e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com prev->fY = curr->fY; 1129e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (readyForAnother) { 1130e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com curr->fData->rewind(); 1131e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com next = curr; 1132e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } else { 1133e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com delete curr->fData; 1134e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fRows.removeShuffle(count - 1); 1135e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1136e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } else { 1137e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (readyForAnother) { 1138e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com next = fRows.append(); 1139e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com next->fData = new SkTDArray<uint8_t>; 1140e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1141e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1142e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } else { 1143e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (readyForAnother) { 1144e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com next = fRows.append(); 1145e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com next->fData = new SkTDArray<uint8_t>; 1146e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1147e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1148e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return next; 1149e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1150e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1151e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com static void AppendRun(SkTDArray<uint8_t>& data, U8CPU alpha, int count) { 1152e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com do { 1153e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int n = count; 1154e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (n > 255) { 1155e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com n = 255; 1156e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1157e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com uint8_t* ptr = data.append(2); 1158e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com ptr[0] = n; 1159e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com ptr[1] = alpha; 1160e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com count -= n; 1161e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } while (count > 0); 1162e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1163e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}; 1164e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1165e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comclass SkAAClip::BuilderBlitter : public SkBlitter { 116680cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com int fLastY; 116780cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com 116880cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com /* 116980cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com If we see a gap of 1 or more empty scanlines while building in Y-order, 117080cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com we inject an explicit empty scanline (alpha==0) 1171fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 117280cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com See AAClipTest.cpp : test_path_with_hole() 117380cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com */ 117480cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com void checkForYGap(int y) { 117580cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com SkASSERT(y >= fLastY); 117680cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com if (fLastY > -SK_MaxS32) { 117780cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com int gap = y - fLastY; 117880cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com if (gap > 1) { 117980cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com fBuilder->addRun(fLeft, y - 1, 0, fRight - fLeft); 118080cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com } 118180cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com } 118280cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com fLastY = y; 118380cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com } 118480cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com 1185e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.compublic: 118680cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com 1187e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com BuilderBlitter(Builder* builder) { 1188e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fBuilder = builder; 11891778564c75de5799d45126984f8faafd03523100reed@google.com fLeft = builder->getBounds().fLeft; 11901778564c75de5799d45126984f8faafd03523100reed@google.com fRight = builder->getBounds().fRight; 1191209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com fMinY = SK_MaxS32; 119280cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com fLastY = -SK_MaxS32; // sentinel 1193209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com } 1194209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com 1195209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com void finish() { 1196209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com if (fMinY < SK_MaxS32) { 1197209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com fBuilder->setMinY(fMinY); 1198209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com } 1199e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1200e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 120149eac192faa35159752525b23345563252721c64tomhudson@google.com /** 120249eac192faa35159752525b23345563252721c64tomhudson@google.com Must evaluate clips in scan-line order, so don't want to allow blitV(), 120349eac192faa35159752525b23345563252721c64tomhudson@google.com but an AAClip can be clipped down to a single pixel wide, so we 120449eac192faa35159752525b23345563252721c64tomhudson@google.com must support it (given AntiRect semantics: minimum width is 2). 120549eac192faa35159752525b23345563252721c64tomhudson@google.com Instead we'll rely on the runtime asserts to guarantee Y monotonicity; 120649eac192faa35159752525b23345563252721c64tomhudson@google.com any failure cases that misses may have minor artifacts. 120749eac192faa35159752525b23345563252721c64tomhudson@google.com */ 120849eac192faa35159752525b23345563252721c64tomhudson@google.com virtual void blitV(int x, int y, int height, SkAlpha alpha) SK_OVERRIDE { 120949eac192faa35159752525b23345563252721c64tomhudson@google.com this->recordMinY(y); 121049eac192faa35159752525b23345563252721c64tomhudson@google.com fBuilder->addColumn(x, y, alpha, height); 12119b0da23f0af145ffd9795b4b55b9527ac050d0b0reed@google.com fLastY = y + height - 1; 121249eac192faa35159752525b23345563252721c64tomhudson@google.com } 1213045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1214562a2ac95b8cd8b359574f8c4d6300b0475938dbreed@google.com virtual void blitRect(int x, int y, int width, int height) SK_OVERRIDE { 12159154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com this->recordMinY(y); 121680cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com this->checkForYGap(y); 12179154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com fBuilder->addRectRun(x, y, width, height); 1218302b861338a626014153cc7368c54edbc646cfe5reed@google.com fLastY = y + height - 1; 1219562a2ac95b8cd8b359574f8c4d6300b0475938dbreed@google.com } 1220045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 122149eac192faa35159752525b23345563252721c64tomhudson@google.com virtual void blitAntiRect(int x, int y, int width, int height, 122249eac192faa35159752525b23345563252721c64tomhudson@google.com SkAlpha leftAlpha, SkAlpha rightAlpha) SK_OVERRIDE { 122349eac192faa35159752525b23345563252721c64tomhudson@google.com this->recordMinY(y); 1224302b861338a626014153cc7368c54edbc646cfe5reed@google.com this->checkForYGap(y); 122549eac192faa35159752525b23345563252721c64tomhudson@google.com fBuilder->addAntiRectRun(x, y, width, height, leftAlpha, rightAlpha); 1226302b861338a626014153cc7368c54edbc646cfe5reed@google.com fLastY = y + height - 1; 122749eac192faa35159752525b23345563252721c64tomhudson@google.com } 122849eac192faa35159752525b23345563252721c64tomhudson@google.com 1229e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com virtual void blitMask(const SkMask&, const SkIRect& clip) SK_OVERRIDE 1230e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com { unexpected(); } 1231e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1232e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com virtual const SkBitmap* justAnOpaqueColor(uint32_t*) SK_OVERRIDE { 12333771a030b0b6686b0ec81359774836cc376ea3f4reed@google.com return NULL; 1234e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1235e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1236e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com virtual void blitH(int x, int y, int width) SK_OVERRIDE { 1237209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com this->recordMinY(y); 123880cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com this->checkForYGap(y); 1239e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fBuilder->addRun(x, y, 0xFF, width); 1240e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1241e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1242e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com virtual void blitAntiH(int x, int y, const SkAlpha alpha[], 1243e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const int16_t runs[]) SK_OVERRIDE { 1244209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com this->recordMinY(y); 124580cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com this->checkForYGap(y); 1246e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com for (;;) { 1247e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int count = *runs; 1248e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (count <= 0) { 1249e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return; 1250e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 12511778564c75de5799d45126984f8faafd03523100reed@google.com 12521778564c75de5799d45126984f8faafd03523100reed@google.com // The supersampler's buffer can be the width of the device, so 12531778564c75de5799d45126984f8faafd03523100reed@google.com // we may have to trim the run to our bounds. If so, we assert that 12541778564c75de5799d45126984f8faafd03523100reed@google.com // the extra spans are always alpha==0 12551778564c75de5799d45126984f8faafd03523100reed@google.com int localX = x; 12561778564c75de5799d45126984f8faafd03523100reed@google.com int localCount = count; 12571778564c75de5799d45126984f8faafd03523100reed@google.com if (x < fLeft) { 12581778564c75de5799d45126984f8faafd03523100reed@google.com SkASSERT(0 == *alpha); 12591778564c75de5799d45126984f8faafd03523100reed@google.com int gap = fLeft - x; 12601778564c75de5799d45126984f8faafd03523100reed@google.com SkASSERT(gap <= count); 12611778564c75de5799d45126984f8faafd03523100reed@google.com localX += gap; 12621778564c75de5799d45126984f8faafd03523100reed@google.com localCount -= gap; 12631778564c75de5799d45126984f8faafd03523100reed@google.com } 12641778564c75de5799d45126984f8faafd03523100reed@google.com int right = x + count; 12651778564c75de5799d45126984f8faafd03523100reed@google.com if (right > fRight) { 12661778564c75de5799d45126984f8faafd03523100reed@google.com SkASSERT(0 == *alpha); 12671778564c75de5799d45126984f8faafd03523100reed@google.com localCount -= right - fRight; 12681778564c75de5799d45126984f8faafd03523100reed@google.com SkASSERT(localCount >= 0); 12691778564c75de5799d45126984f8faafd03523100reed@google.com } 1270fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 12711778564c75de5799d45126984f8faafd03523100reed@google.com if (localCount) { 12721778564c75de5799d45126984f8faafd03523100reed@google.com fBuilder->addRun(localX, y, *alpha, localCount); 12731778564c75de5799d45126984f8faafd03523100reed@google.com } 1274820e80ad6390e120d4991a5280d0452ec87beaebbsalomon@google.com // Next run 1275e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com runs += count; 1276e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com alpha += count; 1277e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com x += count; 1278e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1279e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1280e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1281e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comprivate: 1282e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com Builder* fBuilder; 12831778564c75de5799d45126984f8faafd03523100reed@google.com int fLeft; // cache of builder's bounds' left edge 12841778564c75de5799d45126984f8faafd03523100reed@google.com int fRight; 1285209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com int fMinY; 1286209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com 1287209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com /* 1288209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com * We track this, in case the scan converter skipped some number of 1289209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com * scanlines at the (relative to the bounds it was given). This allows 1290209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com * the builder, during its finish, to trip its bounds down to the "real" 1291209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com * top. 1292209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com */ 1293209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com void recordMinY(int y) { 1294209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com if (y < fMinY) { 1295209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com fMinY = y; 1296209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com } 1297209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com } 1298e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1299e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com void unexpected() { 1300e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkDebugf("---- did not expect to get called here"); 1301e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com sk_throw(); 1302e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1303e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}; 1304e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1305f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.combool SkAAClip::setPath(const SkPath& path, const SkRegion* clip, bool doAA) { 1306045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com AUTO_AACLIP_VALIDATE(*this); 1307045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1308322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com if (clip && clip->isEmpty()) { 1309e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return this->setEmpty(); 1310e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1311e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1312e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkIRect ibounds; 1313322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com path.getBounds().roundOut(&ibounds); 1314e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1315322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com SkRegion tmpClip; 1316322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com if (NULL == clip) { 1317322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com tmpClip.setRect(ibounds); 1318322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com clip = &tmpClip; 1319322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1320fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1321045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (path.isInverseFillType()) { 1322045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com ibounds = clip->getBounds(); 1323045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } else { 1324322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com if (ibounds.isEmpty() || !ibounds.intersect(clip->getBounds())) { 1325e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return this->setEmpty(); 1326e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1327e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1328e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1329e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com Builder builder(ibounds); 1330e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com BuilderBlitter blitter(&builder); 1331e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1332f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com if (doAA) { 1333f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com SkScan::AntiFillPath(path, *clip, &blitter, true); 1334f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com } else { 1335f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com SkScan::FillPath(path, *clip, &blitter); 1336f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com } 1337e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1338209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com blitter.finish(); 1339045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return builder.finish(this); 1340e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 1341e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1342e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com/////////////////////////////////////////////////////////////////////////////// 1343e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1344322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comtypedef void (*RowProc)(SkAAClip::Builder&, int bottom, 1345322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com const uint8_t* rowA, const SkIRect& rectA, 1346322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com const uint8_t* rowB, const SkIRect& rectB); 1347322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1348322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comtypedef U8CPU (*AlphaProc)(U8CPU alphaA, U8CPU alphaB); 1349322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1350322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comstatic U8CPU sectAlphaProc(U8CPU alphaA, U8CPU alphaB) { 1351322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com // Multiply 1352322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return SkMulDiv255Round(alphaA, alphaB); 1353322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com} 1354322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1355322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comstatic U8CPU unionAlphaProc(U8CPU alphaA, U8CPU alphaB) { 1356322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com // SrcOver 1357322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return alphaA + alphaB - SkMulDiv255Round(alphaA, alphaB); 1358322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com} 1359322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1360322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comstatic U8CPU diffAlphaProc(U8CPU alphaA, U8CPU alphaB) { 1361322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com // SrcOut 1362322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return SkMulDiv255Round(alphaA, 0xFF - alphaB); 1363322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com} 1364322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1365322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comstatic U8CPU xorAlphaProc(U8CPU alphaA, U8CPU alphaB) { 1366322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com // XOR 1367322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return alphaA + alphaB - 2 * SkMulDiv255Round(alphaA, alphaB); 1368322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com} 1369322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1370322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comstatic AlphaProc find_alpha_proc(SkRegion::Op op) { 1371322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com switch (op) { 1372322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com case SkRegion::kIntersect_Op: 1373322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return sectAlphaProc; 1374322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com case SkRegion::kDifference_Op: 1375322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return diffAlphaProc; 1376322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com case SkRegion::kUnion_Op: 1377322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return unionAlphaProc; 1378322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com case SkRegion::kXOR_Op: 1379322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return xorAlphaProc; 1380322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com default: 13810c00f21fee3f5cfa3aa7e5d46ff94cb8cf340451tomhudson@google.com SkDEBUGFAIL("unexpected region op"); 1382322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return sectAlphaProc; 1383322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1384322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com} 1385322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1386322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comclass RowIter { 1387322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.compublic: 1388322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com RowIter(const uint8_t* row, const SkIRect& bounds) { 1389322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com fRow = row; 1390322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com fLeft = bounds.fLeft; 1391322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com fBoundsRight = bounds.fRight; 13921c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (row) { 13931c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fRight = bounds.fLeft + row[0]; 13941c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com SkASSERT(fRight <= fBoundsRight); 13951c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fAlpha = row[1]; 13961c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fDone = false; 13971c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } else { 13981c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fDone = true; 13991c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fRight = kMaxInt32; 14001c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fAlpha = 0; 14011c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } 1402322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1403322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1404322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com bool done() const { return fDone; } 14051c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com int left() const { return fLeft; } 14061c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com int right() const { return fRight; } 14071c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com U8CPU alpha() const { return fAlpha; } 1408322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com void next() { 14091c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (!fDone) { 1410322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com fLeft = fRight; 14111c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (fRight == fBoundsRight) { 14121c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fDone = true; 14131c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fRight = kMaxInt32; 14141c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fAlpha = 0; 14151c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } else { 14161c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fRow += 2; 14171c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fRight += fRow[0]; 14181c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fAlpha = fRow[1]; 14191c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com SkASSERT(fRight <= fBoundsRight); 14201c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } 1421322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1422322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1423322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1424322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comprivate: 1425322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com const uint8_t* fRow; 1426322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com int fLeft; 1427322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com int fRight; 1428322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com int fBoundsRight; 1429322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com bool fDone; 14301c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com uint8_t fAlpha; 1431322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com}; 1432322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 14331c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.comstatic void adjust_row(RowIter& iter, int& leftA, int& riteA, int rite) { 14341c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (rite == riteA) { 14351c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com iter.next(); 14361c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com leftA = iter.left(); 14371c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com riteA = iter.right(); 1438322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1439322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com} 1440322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1441803eceb6afd13f07416df0b4a9bb714e9370f081caryclark@google.com#if 0 // UNUSED 14421c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.comstatic bool intersect(int& min, int& max, int boundsMin, int boundsMax) { 14431c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com SkASSERT(min < max); 14441c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com SkASSERT(boundsMin < boundsMax); 14451c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (min >= boundsMax || max <= boundsMin) { 14461c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com return false; 14471c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } 14481c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (min < boundsMin) { 14491c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com min = boundsMin; 14501c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } 14511c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (max > boundsMax) { 14521c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com max = boundsMax; 14531c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } 14541c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com return true; 14551c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com} 1456803eceb6afd13f07416df0b4a9bb714e9370f081caryclark@google.com#endif 14571c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com 1458322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comstatic void operatorX(SkAAClip::Builder& builder, int lastY, 1459322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com RowIter& iterA, RowIter& iterB, 1460322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com AlphaProc proc, const SkIRect& bounds) { 1461322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com int leftA = iterA.left(); 1462322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com int riteA = iterA.right(); 1463322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com int leftB = iterB.left(); 1464322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com int riteB = iterB.right(); 1465322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 14661c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com int prevRite = bounds.fLeft; 14671c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com 14681c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com do { 1469322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com U8CPU alphaA = 0; 1470322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com U8CPU alphaB = 0; 1471322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com int left, rite; 1472fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 14731c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (leftA < leftB) { 1474322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com left = leftA; 1475322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com alphaA = iterA.alpha(); 14761c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (riteA <= leftB) { 14771c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com rite = riteA; 14781c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } else { 14791c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com rite = leftA = leftB; 14801c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } 14811c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } else if (leftB < leftA) { 1482322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com left = leftB; 1483322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com alphaB = iterB.alpha(); 14841c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (riteB <= leftA) { 14851c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com rite = riteB; 14861c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } else { 14871c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com rite = leftB = leftA; 14881c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } 1489322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } else { 14901c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com left = leftA; // or leftB, since leftA == leftB 14911c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com rite = leftA = leftB = SkMin32(riteA, riteB); 1492322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com alphaA = iterA.alpha(); 1493322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com alphaB = iterB.alpha(); 1494322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1495322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1496322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com if (left >= bounds.fRight) { 1497322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com break; 1498322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 149934f7e47a3593911d03307a08e5af625b218ceec3reed@google.com if (rite > bounds.fRight) { 150034f7e47a3593911d03307a08e5af625b218ceec3reed@google.com rite = bounds.fRight; 150134f7e47a3593911d03307a08e5af625b218ceec3reed@google.com } 150234f7e47a3593911d03307a08e5af625b218ceec3reed@google.com 1503322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com if (left >= bounds.fLeft) { 15041c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com SkASSERT(rite > left); 1505322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com builder.addRun(left, lastY, proc(alphaA, alphaB), rite - left); 15061c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com prevRite = rite; 1507322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 15081c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com 15091c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com adjust_row(iterA, leftA, riteA, rite); 15101c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com adjust_row(iterB, leftB, riteB, rite); 15111c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } while (!iterA.done() || !iterB.done()); 15121c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com 15131c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (prevRite < bounds.fRight) { 15141c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com builder.addRun(prevRite, lastY, 0, bounds.fRight - prevRite); 1515322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1516322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com} 1517322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 15181c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.comstatic void adjust_iter(SkAAClip::Iter& iter, int& topA, int& botA, int bot) { 15191c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (bot == botA) { 15201c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com iter.next(); 15211c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com topA = botA; 15221c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com SkASSERT(botA == iter.top()); 15231c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com botA = iter.bottom(); 1524322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1525322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com} 1526322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1527322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comstatic void operateY(SkAAClip::Builder& builder, const SkAAClip& A, 1528322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com const SkAAClip& B, SkRegion::Op op) { 1529322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com AlphaProc proc = find_alpha_proc(op); 1530322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com const SkIRect& bounds = builder.getBounds(); 1531322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1532322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com SkAAClip::Iter iterA(A); 1533322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com SkAAClip::Iter iterB(B); 1534322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1535322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com SkASSERT(!iterA.done()); 1536322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com int topA = iterA.top(); 1537322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com int botA = iterA.bottom(); 1538322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com SkASSERT(!iterB.done()); 1539322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com int topB = iterB.top(); 1540322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com int botB = iterB.bottom(); 1541322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 15421c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com do { 15431c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com const uint8_t* rowA = NULL; 15441c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com const uint8_t* rowB = NULL; 1545322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com int top, bot; 15461c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com 15471c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (topA < topB) { 1548322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com top = topA; 1549322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com rowA = iterA.data(); 15501c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (botA <= topB) { 15511c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com bot = botA; 15521c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } else { 15531c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com bot = topA = topB; 15541c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } 1555fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 15561c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } else if (topB < topA) { 1557322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com top = topB; 1558322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com rowB = iterB.data(); 15591c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (botB <= topA) { 15601c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com bot = botB; 15611c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } else { 15621c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com bot = topB = topA; 15631c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } 1564322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } else { 15651c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com top = topA; // or topB, since topA == topB 15661c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com bot = topA = topB = SkMin32(botA, botB); 1567322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com rowA = iterA.data(); 1568322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com rowB = iterB.data(); 1569322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1570322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1571322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com if (top >= bounds.fBottom) { 1572322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com break; 1573322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 157434f7e47a3593911d03307a08e5af625b218ceec3reed@google.com 157534f7e47a3593911d03307a08e5af625b218ceec3reed@google.com if (bot > bounds.fBottom) { 157634f7e47a3593911d03307a08e5af625b218ceec3reed@google.com bot = bounds.fBottom; 157734f7e47a3593911d03307a08e5af625b218ceec3reed@google.com } 157834f7e47a3593911d03307a08e5af625b218ceec3reed@google.com SkASSERT(top < bot); 157934f7e47a3593911d03307a08e5af625b218ceec3reed@google.com 15801c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (!rowA && !rowB) { 15811c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com builder.addRun(bounds.fLeft, bot - 1, 0, bounds.width()); 15821c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } else if (top >= bounds.fTop) { 15831c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com SkASSERT(bot <= bounds.fBottom); 15841c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com RowIter rowIterA(rowA, rowA ? A.getBounds() : bounds); 15851c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com RowIter rowIterB(rowB, rowB ? B.getBounds() : bounds); 1586322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com operatorX(builder, bot - 1, rowIterA, rowIterB, proc, bounds); 1587322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1588322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 15891c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com adjust_iter(iterA, topA, botA, bot); 15901c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com adjust_iter(iterB, topB, botB, bot); 15911c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } while (!iterA.done() || !iterB.done()); 1592322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com} 1593322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1594322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.combool SkAAClip::op(const SkAAClip& clipAOrig, const SkAAClip& clipBOrig, 1595322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com SkRegion::Op op) { 1596045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com AUTO_AACLIP_VALIDATE(*this); 1597fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1598322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com if (SkRegion::kReplace_Op == op) { 1599322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return this->set(clipBOrig); 1600322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1601fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1602322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com const SkAAClip* clipA = &clipAOrig; 1603322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com const SkAAClip* clipB = &clipBOrig; 1604fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1605322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com if (SkRegion::kReverseDifference_Op == op) { 1606322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com SkTSwap(clipA, clipB); 1607322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com op = SkRegion::kDifference_Op; 1608322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1609322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1610322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com bool a_empty = clipA->isEmpty(); 1611322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com bool b_empty = clipB->isEmpty(); 1612322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1613322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com SkIRect bounds; 1614322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com switch (op) { 1615322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com case SkRegion::kDifference_Op: 1616322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com if (a_empty) { 1617322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return this->setEmpty(); 1618322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1619322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com if (b_empty || !SkIRect::Intersects(clipA->fBounds, clipB->fBounds)) { 1620322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return this->set(*clipA); 1621322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1622322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com bounds = clipA->fBounds; 1623322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com break; 1624fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1625322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com case SkRegion::kIntersect_Op: 1626322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com if ((a_empty | b_empty) || !bounds.intersect(clipA->fBounds, 1627322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com clipB->fBounds)) { 1628322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return this->setEmpty(); 1629322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1630322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com break; 1631fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1632322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com case SkRegion::kUnion_Op: 1633322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com case SkRegion::kXOR_Op: 1634322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com if (a_empty) { 1635322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return this->set(*clipB); 1636322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1637322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com if (b_empty) { 1638322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return this->set(*clipA); 1639322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1640322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com bounds = clipA->fBounds; 1641322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com bounds.join(clipB->fBounds); 1642322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com break; 1643322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1644322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com default: 16450c00f21fee3f5cfa3aa7e5d46ff94cb8cf340451tomhudson@google.com SkDEBUGFAIL("unknown region op"); 1646322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return !this->isEmpty(); 1647322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1648322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1649322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com SkASSERT(SkIRect::Intersects(bounds, clipB->fBounds)); 1650322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com SkASSERT(SkIRect::Intersects(bounds, clipB->fBounds)); 1651322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1652322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com Builder builder(bounds); 1653322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com operateY(builder, *clipA, *clipB, op); 1654045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1655045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return builder.finish(this); 1656e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 1657e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1658045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com/* 1659045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com * It can be expensive to build a local aaclip before applying the op, so 1660045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com * we first see if we can restrict the bounds of new rect to our current 1661045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com * bounds, or note that the new rect subsumes our current clip. 1662045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com */ 1663045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1664045e62d715f5ee9b03deb5af3c750f8318096179reed@google.combool SkAAClip::op(const SkIRect& rOrig, SkRegion::Op op) { 1665045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkIRect rStorage; 1666045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const SkIRect* r = &rOrig; 1667045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1668045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com switch (op) { 1669045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com case SkRegion::kIntersect_Op: 1670045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (!rStorage.intersect(rOrig, fBounds)) { 1671045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com // no overlap, so we're empty 1672045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return this->setEmpty(); 1673045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1674045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (rStorage == fBounds) { 1675045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com // we were wholly inside the rect, no change 1676045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return !this->isEmpty(); 1677045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1678045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (this->quickContains(rStorage)) { 1679045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com // the intersection is wholly inside us, we're a rect 1680045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return this->setRect(rStorage); 1681045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1682045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com r = &rStorage; // use the intersected bounds 1683045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com break; 1684045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com case SkRegion::kDifference_Op: 1685045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com break; 1686045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com case SkRegion::kUnion_Op: 1687045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (rOrig.contains(fBounds)) { 1688045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return this->setRect(rOrig); 1689045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1690045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com break; 1691045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com default: 1692045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com break; 1693045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1694045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 169547ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com SkAAClip clip; 1696045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com clip.setRect(*r); 169747ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com return this->op(*this, clip, op); 169847ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com} 169947ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com 1700045e62d715f5ee9b03deb5af3c750f8318096179reed@google.combool SkAAClip::op(const SkRect& rOrig, SkRegion::Op op, bool doAA) { 1701045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkRect rStorage, boundsStorage; 1702045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const SkRect* r = &rOrig; 1703fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1704045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com boundsStorage.set(fBounds); 1705045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com switch (op) { 1706045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com case SkRegion::kIntersect_Op: 1707045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com case SkRegion::kDifference_Op: 1708045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (!rStorage.intersect(rOrig, boundsStorage)) { 1709e56513d2a9eebabf93d7824eebf9e64441c485bareed@google.com if (SkRegion::kIntersect_Op == op) { 1710e56513d2a9eebabf93d7824eebf9e64441c485bareed@google.com return this->setEmpty(); 1711e56513d2a9eebabf93d7824eebf9e64441c485bareed@google.com } else { // kDifference 1712e56513d2a9eebabf93d7824eebf9e64441c485bareed@google.com return !this->isEmpty(); 1713e56513d2a9eebabf93d7824eebf9e64441c485bareed@google.com } 1714045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1715045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com r = &rStorage; // use the intersected bounds 1716045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com break; 1717045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com case SkRegion::kUnion_Op: 1718045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (rOrig.contains(boundsStorage)) { 1719045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return this->setRect(rOrig); 1720045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1721045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com break; 1722045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com default: 1723045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com break; 1724045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1725fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 172647ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com SkAAClip clip; 1727045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com clip.setRect(*r, doAA); 172847ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com return this->op(*this, clip, op); 172947ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com} 173047ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com 173147ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.combool SkAAClip::op(const SkAAClip& clip, SkRegion::Op op) { 173247ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com return this->op(*this, clip, op); 173347ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com} 173447ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com 1735e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com/////////////////////////////////////////////////////////////////////////////// 1736045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1737045e62d715f5ee9b03deb5af3c750f8318096179reed@google.combool SkAAClip::translate(int dx, int dy, SkAAClip* dst) const { 1738045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (NULL == dst) { 1739045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return !this->isEmpty(); 1740045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1741fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1742045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (this->isEmpty()) { 1743045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return dst->setEmpty(); 1744045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1745fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1746045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (this != dst) { 1747045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com sk_atomic_inc(&fRunHead->fRefCnt); 174819224c3d7903921ca86c856cc42adb31fc3164a9tomhudson@google.com dst->freeRuns(); 1749045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com dst->fRunHead = fRunHead; 1750045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com dst->fBounds = fBounds; 1751045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1752045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com dst->fBounds.offset(dx, dy); 1753045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return true; 1754045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com} 1755045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1756045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comstatic void expand_row_to_mask(uint8_t* SK_RESTRICT mask, 1757045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const uint8_t* SK_RESTRICT row, 1758045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com int width) { 1759045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com while (width > 0) { 1760045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com int n = row[0]; 1761045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(width >= n); 1762045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com memset(mask, row[1], n); 1763045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com mask += n; 1764045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com row += 2; 1765045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com width -= n; 1766045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1767a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com SkASSERT(0 == width); 1768045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com} 1769045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1770045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comvoid SkAAClip::copyToMask(SkMask* mask) const { 1771045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com mask->fFormat = SkMask::kA8_Format; 1772045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (this->isEmpty()) { 1773045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com mask->fBounds.setEmpty(); 1774045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com mask->fImage = NULL; 1775045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com mask->fRowBytes = 0; 1776045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return; 1777045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1778fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1779045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com mask->fBounds = fBounds; 1780045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com mask->fRowBytes = fBounds.width(); 1781045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com size_t size = mask->computeImageSize(); 1782045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com mask->fImage = SkMask::AllocImage(size); 1783fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1784045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com Iter iter(*this); 1785045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com uint8_t* dst = mask->fImage; 1786045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const int width = fBounds.width(); 1787fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1788045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com int y = fBounds.fTop; 1789045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com while (!iter.done()) { 1790045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com do { 1791045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com expand_row_to_mask(dst, iter.data(), width); 1792045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com dst += mask->fRowBytes; 1793045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } while (++y < iter.bottom()); 1794045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com iter.next(); 1795045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1796045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com} 1797045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1798045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com/////////////////////////////////////////////////////////////////////////////// 1799e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com/////////////////////////////////////////////////////////////////////////////// 1800e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1801e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comstatic void expandToRuns(const uint8_t* SK_RESTRICT data, int initialCount, int width, 1802e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int16_t* SK_RESTRICT runs, SkAlpha* SK_RESTRICT aa) { 1803e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com // we don't read our initial n from data, since the caller may have had to 1804e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com // clip it, hence the initialCount parameter. 1805e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int n = initialCount; 1806e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com for (;;) { 1807e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (n > width) { 1808e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com n = width; 1809e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1810e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(n > 0); 1811e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com runs[0] = n; 1812e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com runs += n; 1813e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1814e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com aa[0] = data[1]; 1815e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com aa += n; 1816fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1817e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com data += 2; 1818e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com width -= n; 1819e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (0 == width) { 1820e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com break; 1821e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1822e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com // load the next count 1823e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com n = data[0]; 1824e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1825e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com runs[0] = 0; // sentinel 1826e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 1827e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1828e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comSkAAClipBlitter::~SkAAClipBlitter() { 1829045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com sk_free(fScanlineScratch); 1830e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 1831e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1832e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comvoid SkAAClipBlitter::ensureRunsAndAA() { 1833045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (NULL == fScanlineScratch) { 1834e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com // add 1 so we can store the terminating run count of 0 1835e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int count = fAAClipBounds.width() + 1; 1836045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com // we use this either for fRuns + fAA, or a scaline of a mask 1837045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com // which may be as deep as 32bits 1838045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fScanlineScratch = sk_malloc_throw(count * sizeof(SkPMColor)); 1839045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fRuns = (int16_t*)fScanlineScratch; 1840e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fAA = (SkAlpha*)(fRuns + count); 1841e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1842e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 1843e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1844e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comvoid SkAAClipBlitter::blitH(int x, int y, int width) { 1845e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(width > 0); 1846e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(fAAClipBounds.contains(x, y)); 1847e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(fAAClipBounds.contains(x + width - 1, y)); 1848e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1849a4c6e4d6d3a4010df8dd2b04314675e4c201133breed@google.com const uint8_t* row = fAAClip->findRow(y); 1850e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int initialCount; 1851e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com row = fAAClip->findX(row, x, &initialCount); 1852e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1853e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (initialCount >= width) { 1854e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkAlpha alpha = row[1]; 1855e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (0 == alpha) { 1856e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return; 1857e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1858e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (0xFF == alpha) { 1859e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fBlitter->blitH(x, y, width); 1860e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return; 1861e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1862e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1863e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1864e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com this->ensureRunsAndAA(); 1865e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com expandToRuns(row, initialCount, width, fRuns, fAA); 1866e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1867e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fBlitter->blitAntiH(x, y, fAA, fRuns); 1868e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 1869e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1870e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comstatic void merge(const uint8_t* SK_RESTRICT row, int rowN, 1871e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const SkAlpha* SK_RESTRICT srcAA, 1872e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const int16_t* SK_RESTRICT srcRuns, 1873e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkAlpha* SK_RESTRICT dstAA, 1874e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int16_t* SK_RESTRICT dstRuns, 1875e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int width) { 1876e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkDEBUGCODE(int accumulated = 0;) 1877e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int srcN = srcRuns[0]; 1878045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com // do we need this check? 1879045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (0 == srcN) { 1880045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return; 1881045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1882045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1883e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com for (;;) { 1884e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(rowN > 0); 1885e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(srcN > 0); 1886e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1887e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com unsigned newAlpha = SkMulDiv255Round(srcAA[0], row[1]); 1888e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int minN = SkMin32(srcN, rowN); 1889e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com dstRuns[0] = minN; 1890e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com dstRuns += minN; 1891e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com dstAA[0] = newAlpha; 1892e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com dstAA += minN; 1893e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1894e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (0 == (srcN -= minN)) { 1895e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com srcN = srcRuns[0]; // refresh 1896e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com srcRuns += srcN; 1897e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com srcAA += srcN; 1898e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com srcN = srcRuns[0]; // reload 1899045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (0 == srcN) { 1900045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com break; 1901045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1902e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1903e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (0 == (rowN -= minN)) { 1904e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com row += 2; 1905e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com rowN = row[0]; // reload 1906e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1907fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1908e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkDEBUGCODE(accumulated += minN;) 1909e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(accumulated <= width); 1910e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 191134f7e47a3593911d03307a08e5af625b218ceec3reed@google.com dstRuns[0] = 0; 1912e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 1913e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1914e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comvoid SkAAClipBlitter::blitAntiH(int x, int y, const SkAlpha aa[], 1915e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const int16_t runs[]) { 1916a4c6e4d6d3a4010df8dd2b04314675e4c201133breed@google.com 1917a4c6e4d6d3a4010df8dd2b04314675e4c201133breed@google.com const uint8_t* row = fAAClip->findRow(y); 1918e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int initialCount; 1919e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com row = fAAClip->findX(row, x, &initialCount); 1920e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1921e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com this->ensureRunsAndAA(); 1922e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1923e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com merge(row, initialCount, aa, runs, fAA, fRuns, fAAClipBounds.width()); 1924e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fBlitter->blitAntiH(x, y, fAA, fRuns); 1925e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 1926e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1927e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comvoid SkAAClipBlitter::blitV(int x, int y, int height, SkAlpha alpha) { 1928e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (fAAClip->quickContains(x, y, x + 1, y + height)) { 1929e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fBlitter->blitV(x, y, height, alpha); 1930e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return; 1931e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1932e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1933045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com for (;;) { 1934a4c6e4d6d3a4010df8dd2b04314675e4c201133breed@google.com int lastY SK_INIT_TO_AVOID_WARNING; 1935e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const uint8_t* row = fAAClip->findRow(y, &lastY); 1936045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com int dy = lastY - y + 1; 1937045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (dy > height) { 1938045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com dy = height; 1939045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1940045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com height -= dy; 1941045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1942a4c6e4d6d3a4010df8dd2b04314675e4c201133breed@google.com row = fAAClip->findX(row, x); 1943e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkAlpha newAlpha = SkMulDiv255Round(alpha, row[1]); 1944e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (newAlpha) { 1945045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fBlitter->blitV(x, y, dy, newAlpha); 1946045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1947045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(height >= 0); 1948045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (height <= 0) { 1949045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com break; 1950e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1951e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com y = lastY + 1; 1952045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1953e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 1954e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1955e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comvoid SkAAClipBlitter::blitRect(int x, int y, int width, int height) { 1956e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (fAAClip->quickContains(x, y, x + width, y + height)) { 1957e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fBlitter->blitRect(x, y, width, height); 1958e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return; 1959e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1960e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1961e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com while (--height >= 0) { 1962e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com this->blitH(x, y, width); 1963e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com y += 1; 1964e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1965e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 1966e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1967045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comtypedef void (*MergeAAProc)(const void* src, int width, const uint8_t* row, 1968045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com int initialRowCount, void* dst); 1969045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1970045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comstatic void small_memcpy(void* dst, const void* src, size_t n) { 1971045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com memcpy(dst, src, n); 1972e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 1973e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1974045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comstatic void small_bzero(void* dst, size_t n) { 1975045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com sk_bzero(dst, n); 1976e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 1977e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1978045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comstatic inline uint8_t mergeOne(uint8_t value, unsigned alpha) { 1979045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return SkMulDiv255Round(value, alpha); 1980045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com} 1981045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comstatic inline uint16_t mergeOne(uint16_t value, unsigned alpha) { 1982045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com unsigned r = SkGetPackedR16(value); 1983045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com unsigned g = SkGetPackedG16(value); 1984045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com unsigned b = SkGetPackedB16(value); 1985045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return SkPackRGB16(SkMulDiv255Round(r, alpha), 1986803eceb6afd13f07416df0b4a9bb714e9370f081caryclark@google.com SkMulDiv255Round(g, alpha), 1987803eceb6afd13f07416df0b4a9bb714e9370f081caryclark@google.com SkMulDiv255Round(b, alpha)); 1988045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com} 1989045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comstatic inline SkPMColor mergeOne(SkPMColor value, unsigned alpha) { 1990045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com unsigned a = SkGetPackedA32(value); 1991045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com unsigned r = SkGetPackedR32(value); 1992045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com unsigned g = SkGetPackedG32(value); 1993045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com unsigned b = SkGetPackedB32(value); 1994045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return SkPackARGB32(SkMulDiv255Round(a, alpha), 1995045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkMulDiv255Round(r, alpha), 1996045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkMulDiv255Round(g, alpha), 1997045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkMulDiv255Round(b, alpha)); 1998045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com} 1999322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 2000045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comtemplate <typename T> void mergeT(const T* SK_RESTRICT src, int srcN, 2001045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const uint8_t* SK_RESTRICT row, int rowN, 2002045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com T* SK_RESTRICT dst) { 2003045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com for (;;) { 2004045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(rowN > 0); 2005045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(srcN > 0); 2006fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 2007045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com int n = SkMin32(rowN, srcN); 2008045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com unsigned rowA = row[1]; 2009045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (0xFF == rowA) { 2010045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com small_memcpy(dst, src, n * sizeof(T)); 2011045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } else if (0 == rowA) { 2012045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com small_bzero(dst, n * sizeof(T)); 2013045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } else { 2014045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com for (int i = 0; i < n; ++i) { 2015045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com dst[i] = mergeOne(src[i], rowA); 2016045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 2017045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 2018fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 2019045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (0 == (srcN -= n)) { 2020045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com break; 2021045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 2022fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 2023045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com src += n; 2024045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com dst += n; 2025fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 2026045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(rowN == n); 2027045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com row += 2; 2028045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com rowN = row[0]; 20291c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } 2030045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com} 20311c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com 2032045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comstatic MergeAAProc find_merge_aa_proc(SkMask::Format format) { 2033045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com switch (format) { 2034045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com case SkMask::kBW_Format: 20350c00f21fee3f5cfa3aa7e5d46ff94cb8cf340451tomhudson@google.com SkDEBUGFAIL("unsupported"); 2036045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return NULL; 2037045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com case SkMask::kA8_Format: 2038045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com case SkMask::k3D_Format: { 2039045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com void (*proc8)(const uint8_t*, int, const uint8_t*, int, uint8_t*) = mergeT; 2040045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return (MergeAAProc)proc8; 2041045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 2042045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com case SkMask::kLCD16_Format: { 2043045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com void (*proc16)(const uint16_t*, int, const uint8_t*, int, uint16_t*) = mergeT; 2044045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return (MergeAAProc)proc16; 2045045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 2046045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com case SkMask::kLCD32_Format: { 2047045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com void (*proc32)(const SkPMColor*, int, const uint8_t*, int, SkPMColor*) = mergeT; 2048045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return (MergeAAProc)proc32; 2049045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 2050045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com default: 20510c00f21fee3f5cfa3aa7e5d46ff94cb8cf340451tomhudson@google.com SkDEBUGFAIL("unsupported"); 2052045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return NULL; 20531c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } 2054045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com} 20551c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com 2056045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comstatic U8CPU bit2byte(int bitInAByte) { 2057045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(bitInAByte <= 0xFF); 2058045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com // negation turns any non-zero into 0xFFFFFF??, so we just shift down 2059045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com // some value >= 8 to get a full FF value 2060045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return -bitInAByte >> 8; 20611c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com} 20621c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com 2063045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comstatic void upscaleBW2A8(SkMask* dstMask, const SkMask& srcMask) { 2064045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(SkMask::kBW_Format == srcMask.fFormat); 2065045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(SkMask::kA8_Format == dstMask->fFormat); 2066045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 2067045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const int width = srcMask.fBounds.width(); 2068045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const int height = srcMask.fBounds.height(); 2069045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 2070045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const uint8_t* SK_RESTRICT src = (const uint8_t*)srcMask.fImage; 2071045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const size_t srcRB = srcMask.fRowBytes; 2072045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com uint8_t* SK_RESTRICT dst = (uint8_t*)dstMask->fImage; 2073045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const size_t dstRB = dstMask->fRowBytes; 2074045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 2075045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const int wholeBytes = width >> 3; 2076045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const int leftOverBits = width & 7; 2077045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 2078045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com for (int y = 0; y < height; ++y) { 2079045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com uint8_t* SK_RESTRICT d = dst; 2080045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com for (int i = 0; i < wholeBytes; ++i) { 2081045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com int srcByte = src[i]; 2082045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com d[0] = bit2byte(srcByte & (1 << 7)); 2083045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com d[1] = bit2byte(srcByte & (1 << 6)); 2084045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com d[2] = bit2byte(srcByte & (1 << 5)); 2085045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com d[3] = bit2byte(srcByte & (1 << 4)); 2086045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com d[4] = bit2byte(srcByte & (1 << 3)); 2087045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com d[5] = bit2byte(srcByte & (1 << 2)); 2088045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com d[6] = bit2byte(srcByte & (1 << 1)); 2089045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com d[7] = bit2byte(srcByte & (1 << 0)); 2090045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com d += 8; 2091045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 2092045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (leftOverBits) { 2093045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com int srcByte = src[wholeBytes]; 2094045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com for (int x = 0; x < leftOverBits; ++x) { 2095045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com *d++ = bit2byte(srcByte & 0x80); 2096045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com srcByte <<= 1; 2097045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 2098045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 2099045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com src += srcRB; 2100045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com dst += dstRB; 2101322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 2102322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com} 2103322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 2104045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comvoid SkAAClipBlitter::blitMask(const SkMask& origMask, const SkIRect& clip) { 2105045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(fAAClip->getBounds().contains(clip)); 2106045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 2107045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (fAAClip->quickContains(clip)) { 2108045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fBlitter->blitMask(origMask, clip); 2109322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return; 2110322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 2111322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 2112045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const SkMask* mask = &origMask; 2113322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 2114045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com // if we're BW, we need to upscale to A8 (ugh) 2115045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkMask grayMask; 2116045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com grayMask.fImage = NULL; 2117045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (SkMask::kBW_Format == origMask.fFormat) { 2118045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com grayMask.fFormat = SkMask::kA8_Format; 2119045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com grayMask.fBounds = origMask.fBounds; 2120045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com grayMask.fRowBytes = origMask.fBounds.width(); 2121045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com size_t size = grayMask.computeImageSize(); 2122045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com grayMask.fImage = (uint8_t*)fGrayMaskScratch.reset(size, 2123045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkAutoMalloc::kReuse_OnShrink); 2124322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 2125045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com upscaleBW2A8(&grayMask, origMask); 2126045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com mask = &grayMask; 2127322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 2128045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 2129045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com this->ensureRunsAndAA(); 2130045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 2131045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com // HACK -- we are devolving 3D into A8, need to copy the rest of the 3D 2132045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com // data into a temp block to support it better (ugh) 2133045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 2134045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const void* src = mask->getAddr(clip.fLeft, clip.fTop); 2135045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const size_t srcRB = mask->fRowBytes; 2136045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const int width = clip.width(); 2137045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com MergeAAProc mergeProc = find_merge_aa_proc(mask->fFormat); 2138045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 2139045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkMask rowMask; 2140045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com rowMask.fFormat = SkMask::k3D_Format == mask->fFormat ? SkMask::kA8_Format : mask->fFormat; 2141045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com rowMask.fBounds.fLeft = clip.fLeft; 2142045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com rowMask.fBounds.fRight = clip.fRight; 2143045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com rowMask.fRowBytes = mask->fRowBytes; // doesn't matter, since our height==1 2144045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com rowMask.fImage = (uint8_t*)fScanlineScratch; 2145045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 2146045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com int y = clip.fTop; 2147045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const int stopY = y + clip.height(); 2148045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 2149045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com do { 2150a4c6e4d6d3a4010df8dd2b04314675e4c201133breed@google.com int localStopY SK_INIT_TO_AVOID_WARNING; 2151045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const uint8_t* row = fAAClip->findRow(y, &localStopY); 2152045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com // findRow returns last Y, not stop, so we add 1 2153045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com localStopY = SkMin32(localStopY + 1, stopY); 2154045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 2155045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com int initialCount; 2156045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com row = fAAClip->findX(row, clip.fLeft, &initialCount); 2157045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com do { 2158045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com mergeProc(src, width, row, initialCount, rowMask.fImage); 2159045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com rowMask.fBounds.fTop = y; 2160045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com rowMask.fBounds.fBottom = y + 1; 2161045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fBlitter->blitMask(rowMask, rowMask.fBounds); 2162045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com src = (const void*)((const char*)src + srcRB); 2163045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } while (++y < localStopY); 2164045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } while (y < stopY); 2165045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com} 2166045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 2167045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comconst SkBitmap* SkAAClipBlitter::justAnOpaqueColor(uint32_t* value) { 2168045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return NULL; 2169322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com} 2170