SkAAClip.cpp revision 1d3ab12b82e1fa16a0d6b6b9cc1c0290b45cbca9
1e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com/* 2e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com * Copyright 2011 Google Inc. 3e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com * 4e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com * Use of this source code is governed by a BSD-style license that can be 5e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com * found in the LICENSE file. 6e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com */ 7e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 8e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com#include "SkAAClip.h" 9b906daf112416c1698a79cf51aa70fe11aa19d0aherb#include "SkAtomics.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" 1434f7e47a3593911d03307a08e5af625b218ceec3reed@google.com#include "SkUtils.h" 15e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 16045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comclass AutoAAClipValidate { 17045e62d715f5ee9b03deb5af3c750f8318096179reed@google.compublic: 18045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com AutoAAClipValidate(const SkAAClip& clip) : fClip(clip) { 19045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fClip.validate(); 20045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 21045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com ~AutoAAClipValidate() { 22045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fClip.validate(); 23045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 24045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comprivate: 25045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const SkAAClip& fClip; 26045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com}; 27045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 28045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com#ifdef SK_DEBUG 29045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com #define AUTO_AACLIP_VALIDATE(clip) AutoAAClipValidate acv(clip) 30045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com#else 31045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com #define AUTO_AACLIP_VALIDATE(clip) 32045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com#endif 33045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 34045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com/////////////////////////////////////////////////////////////////////////////// 35045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 361c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com#define kMaxInt32 0x7FFFFFFF 371c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com 384b7d6730898abc9e02d1e12c2fd732945f4c1ab4commit-bot@chromium.org#ifdef SK_DEBUG 39e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comstatic inline bool x_in_rect(int x, const SkIRect& rect) { 40e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return (unsigned)(x - rect.fLeft) < (unsigned)rect.width(); 41e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 424b7d6730898abc9e02d1e12c2fd732945f4c1ab4commit-bot@chromium.org#endif 43e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 44e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comstatic inline bool y_in_rect(int y, const SkIRect& rect) { 45e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return (unsigned)(y - rect.fTop) < (unsigned)rect.height(); 46e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 47e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 48e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com/* 49e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com * Data runs are packed [count, alpha] 50e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com */ 51e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 52e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comstruct SkAAClip::YOffset { 53e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int32_t fY; 54e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com uint32_t fOffset; 55e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}; 56e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 57e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comstruct SkAAClip::RunHead { 58e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int32_t fRefCnt; 59e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int32_t fRowCount; 60493c65f1aa0864857c21b2be096740a17ef1430ascroggo@google.com size_t fDataSize; 61fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 62e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com YOffset* yoffsets() { 63e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return (YOffset*)((char*)this + sizeof(RunHead)); 64e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 65e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const YOffset* yoffsets() const { 66e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return (const YOffset*)((const char*)this + sizeof(RunHead)); 67e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 68e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com uint8_t* data() { 69e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return (uint8_t*)(this->yoffsets() + fRowCount); 70e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 71e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const uint8_t* data() const { 72e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return (const uint8_t*)(this->yoffsets() + fRowCount); 73e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 74e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 75e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com static RunHead* Alloc(int rowCount, size_t dataSize) { 76e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com size_t size = sizeof(RunHead) + rowCount * sizeof(YOffset) + dataSize; 77e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com RunHead* head = (RunHead*)sk_malloc_throw(size); 78e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com head->fRefCnt = 1; 79e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com head->fRowCount = rowCount; 80e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com head->fDataSize = dataSize; 81e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return head; 82e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 83045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 84045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com static int ComputeRowSizeForWidth(int width) { 85045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com // 2 bytes per segment, where each segment can store up to 255 for count 86045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com int segments = 0; 87045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com while (width > 0) { 88045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com segments += 1; 89045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com int n = SkMin32(width, 255); 90045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com width -= n; 91045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 92045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return segments * 2; // each segment is row[0] + row[1] (n + alpha) 93045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 94045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 95045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com static RunHead* AllocRect(const SkIRect& bounds) { 96045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(!bounds.isEmpty()); 97045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com int width = bounds.width(); 98045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com size_t rowSize = ComputeRowSizeForWidth(width); 99045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com RunHead* head = RunHead::Alloc(1, rowSize); 100045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com YOffset* yoff = head->yoffsets(); 101045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com yoff->fY = bounds.height() - 1; 102045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com yoff->fOffset = 0; 103045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com uint8_t* row = head->data(); 104045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com while (width > 0) { 105045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com int n = SkMin32(width, 255); 106045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com row[0] = n; 107045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com row[1] = 0xFF; 108045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com width -= n; 109045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com row += 2; 110045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 111045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return head; 112045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 113e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}; 114e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 115322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comclass SkAAClip::Iter { 116322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.compublic: 117322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com Iter(const SkAAClip&); 118322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 119322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com bool done() const { return fDone; } 1201c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com int top() const { return fTop; } 1211c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com int bottom() const { return fBottom; } 1221c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com const uint8_t* data() const { return fData; } 123322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com void next(); 124322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 125322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comprivate: 126322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com const YOffset* fCurrYOff; 127322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com const YOffset* fStopYOff; 128322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com const uint8_t* fData; 129322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 130322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com int fTop, fBottom; 131322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com bool fDone; 132322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com}; 133322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 134322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comSkAAClip::Iter::Iter(const SkAAClip& clip) { 135322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com if (clip.isEmpty()) { 136322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com fDone = true; 1371c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fTop = fBottom = clip.fBounds.fBottom; 13896fcdcc219d2a0d3579719b84b28bede76efba64halcanary fData = nullptr; 13996fcdcc219d2a0d3579719b84b28bede76efba64halcanary fCurrYOff = nullptr; 14096fcdcc219d2a0d3579719b84b28bede76efba64halcanary fStopYOff = nullptr; 141322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return; 142322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 143fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 144322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com const RunHead* head = clip.fRunHead; 145322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com fCurrYOff = head->yoffsets(); 146322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com fStopYOff = fCurrYOff + head->fRowCount; 147322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com fData = head->data() + fCurrYOff->fOffset; 148322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 149322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com // setup first value 150322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com fTop = clip.fBounds.fTop; 151322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com fBottom = clip.fBounds.fTop + fCurrYOff->fY + 1; 152322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com fDone = false; 153322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com} 154322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 155322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comvoid SkAAClip::Iter::next() { 1561c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (!fDone) { 1571c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com const YOffset* prev = fCurrYOff; 1581c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com const YOffset* curr = prev + 1; 1591c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com SkASSERT(curr <= fStopYOff); 160322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 161322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com fTop = fBottom; 1621c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (curr >= fStopYOff) { 1631c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fDone = true; 1641c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fBottom = kMaxInt32; 16596fcdcc219d2a0d3579719b84b28bede76efba64halcanary fData = nullptr; 1661c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } else { 1671c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fBottom += curr->fY - prev->fY; 1681c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fData += curr->fOffset - prev->fOffset; 1691c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fCurrYOff = curr; 1701c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } 171322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 172322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com} 173322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 174045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com#ifdef SK_DEBUG 175c90419199525141a5b98091f856e359bf9daf5b1reed@google.com// assert we're exactly width-wide, and then return the number of bytes used 176045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comstatic size_t compute_row_length(const uint8_t row[], int width) { 177045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const uint8_t* origRow = row; 178045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com while (width > 0) { 179045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com int n = row[0]; 180c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(n > 0); 181045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(n <= width); 182045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com row += 2; 183045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com width -= n; 184045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 185045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(0 == width); 186045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return row - origRow; 187045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com} 188045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 189045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comvoid SkAAClip::validate() const { 19096fcdcc219d2a0d3579719b84b28bede76efba64halcanary if (nullptr == fRunHead) { 191045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(fBounds.isEmpty()); 192045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return; 193045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 194d7ec12e41cce090ec0b2e68e995ea511d33c9967reed SkASSERT(!fBounds.isEmpty()); 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} 2226d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper 2236d42d9c7ff1c3d7ab4de032d5451aed02f746c43humperstatic void dump_one_row(const uint8_t* SK_RESTRICT row, 2246d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper int width, int leading_num) { 2256d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper if (leading_num) { 2266d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper SkDebugf( "%03d ", leading_num ); 2276d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper } 2286d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper while (width > 0) { 2296d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper int n = row[0]; 2306d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper int val = row[1]; 2316d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper char out = '.'; 2326d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper if (val == 0xff) { 2336d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper out = '*'; 2346d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper } else if (val > 0) { 2356d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper out = '+'; 2366d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper } 2376d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper for (int i = 0 ; i < n ; i++) { 2386d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper SkDebugf( "%c", out ); 2396d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper } 2406d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper row += 2; 2416d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper width -= n; 2426d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper } 2436d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper SkDebugf( "\n" ); 2446d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper} 2456d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper 2466d42d9c7ff1c3d7ab4de032d5451aed02f746c43humpervoid SkAAClip::debug(bool compress_y) const { 2476d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper Iter iter(*this); 2486d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper const int width = fBounds.width(); 2496d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper 2506d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper int y = fBounds.fTop; 2516d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper while (!iter.done()) { 2526d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper if (compress_y) { 2536d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper dump_one_row(iter.data(), width, iter.bottom() - iter.top() + 1); 2546d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper } else { 2556d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper do { 2566d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper dump_one_row(iter.data(), width, 0); 2576d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper } while (++y < iter.bottom()); 2586d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper } 2596d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper iter.next(); 2606d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper } 2616d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper} 262045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com#endif 263045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 264045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com/////////////////////////////////////////////////////////////////////////////// 265045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 266768fee8b6e9ae0a849ed45ab377fc9079b5db11erobertphillips@google.com// Count the number of zeros on the left and right edges of the passed in 267768fee8b6e9ae0a849ed45ab377fc9079b5db11erobertphillips@google.com// RLE row. If 'row' is all zeros return 'width' in both variables. 268c90419199525141a5b98091f856e359bf9daf5b1reed@google.comstatic void count_left_right_zeros(const uint8_t* row, int width, 269c90419199525141a5b98091f856e359bf9daf5b1reed@google.com int* leftZ, int* riteZ) { 270c90419199525141a5b98091f856e359bf9daf5b1reed@google.com int zeros = 0; 271c90419199525141a5b98091f856e359bf9daf5b1reed@google.com do { 272c90419199525141a5b98091f856e359bf9daf5b1reed@google.com if (row[1]) { 273c90419199525141a5b98091f856e359bf9daf5b1reed@google.com break; 274c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 275c90419199525141a5b98091f856e359bf9daf5b1reed@google.com int n = row[0]; 276c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(n > 0); 277c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(n <= width); 278c90419199525141a5b98091f856e359bf9daf5b1reed@google.com zeros += n; 279c90419199525141a5b98091f856e359bf9daf5b1reed@google.com row += 2; 280c90419199525141a5b98091f856e359bf9daf5b1reed@google.com width -= n; 281c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } while (width > 0); 282c90419199525141a5b98091f856e359bf9daf5b1reed@google.com *leftZ = zeros; 283c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 284768fee8b6e9ae0a849ed45ab377fc9079b5db11erobertphillips@google.com if (0 == width) { 285768fee8b6e9ae0a849ed45ab377fc9079b5db11erobertphillips@google.com // this line is completely empty return 'width' in both variables 286768fee8b6e9ae0a849ed45ab377fc9079b5db11erobertphillips@google.com *riteZ = *leftZ; 287768fee8b6e9ae0a849ed45ab377fc9079b5db11erobertphillips@google.com return; 288768fee8b6e9ae0a849ed45ab377fc9079b5db11erobertphillips@google.com } 289768fee8b6e9ae0a849ed45ab377fc9079b5db11erobertphillips@google.com 290c90419199525141a5b98091f856e359bf9daf5b1reed@google.com zeros = 0; 291c90419199525141a5b98091f856e359bf9daf5b1reed@google.com while (width > 0) { 292c90419199525141a5b98091f856e359bf9daf5b1reed@google.com int n = row[0]; 293c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(n > 0); 294c90419199525141a5b98091f856e359bf9daf5b1reed@google.com if (0 == row[1]) { 295c90419199525141a5b98091f856e359bf9daf5b1reed@google.com zeros += n; 296c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } else { 297c90419199525141a5b98091f856e359bf9daf5b1reed@google.com zeros = 0; 298c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 299c90419199525141a5b98091f856e359bf9daf5b1reed@google.com row += 2; 300c90419199525141a5b98091f856e359bf9daf5b1reed@google.com width -= n; 301c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 302c90419199525141a5b98091f856e359bf9daf5b1reed@google.com *riteZ = zeros; 303c90419199525141a5b98091f856e359bf9daf5b1reed@google.com} 304c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 305c90419199525141a5b98091f856e359bf9daf5b1reed@google.com#ifdef SK_DEBUG 306c90419199525141a5b98091f856e359bf9daf5b1reed@google.comstatic void test_count_left_right_zeros() { 307c90419199525141a5b98091f856e359bf9daf5b1reed@google.com static bool gOnce; 308c90419199525141a5b98091f856e359bf9daf5b1reed@google.com if (gOnce) { 309c90419199525141a5b98091f856e359bf9daf5b1reed@google.com return; 310c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 311c90419199525141a5b98091f856e359bf9daf5b1reed@google.com gOnce = true; 312c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 313c90419199525141a5b98091f856e359bf9daf5b1reed@google.com const uint8_t data0[] = { 0, 0, 10, 0xFF }; 314c90419199525141a5b98091f856e359bf9daf5b1reed@google.com const uint8_t data1[] = { 0, 0, 5, 0xFF, 2, 0, 3, 0xFF }; 315c90419199525141a5b98091f856e359bf9daf5b1reed@google.com const uint8_t data2[] = { 7, 0, 5, 0, 2, 0, 3, 0xFF }; 316c90419199525141a5b98091f856e359bf9daf5b1reed@google.com const uint8_t data3[] = { 0, 5, 5, 0xFF, 2, 0, 3, 0 }; 317c90419199525141a5b98091f856e359bf9daf5b1reed@google.com const uint8_t data4[] = { 2, 3, 2, 0, 5, 0xFF, 3, 0 }; 318768fee8b6e9ae0a849ed45ab377fc9079b5db11erobertphillips@google.com const uint8_t data5[] = { 10, 10, 10, 0 }; 319c90419199525141a5b98091f856e359bf9daf5b1reed@google.com const uint8_t data6[] = { 2, 2, 2, 0, 2, 0xFF, 2, 0, 2, 0xFF, 2, 0 }; 320c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 321c90419199525141a5b98091f856e359bf9daf5b1reed@google.com const uint8_t* array[] = { 322c90419199525141a5b98091f856e359bf9daf5b1reed@google.com data0, data1, data2, data3, data4, data5, data6 323c90419199525141a5b98091f856e359bf9daf5b1reed@google.com }; 324c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 325c90419199525141a5b98091f856e359bf9daf5b1reed@google.com for (size_t i = 0; i < SK_ARRAY_COUNT(array); ++i) { 326c90419199525141a5b98091f856e359bf9daf5b1reed@google.com const uint8_t* data = array[i]; 327c90419199525141a5b98091f856e359bf9daf5b1reed@google.com const int expectedL = *data++; 328c90419199525141a5b98091f856e359bf9daf5b1reed@google.com const int expectedR = *data++; 329c90419199525141a5b98091f856e359bf9daf5b1reed@google.com int L = 12345, R = 12345; 330c90419199525141a5b98091f856e359bf9daf5b1reed@google.com count_left_right_zeros(data, 10, &L, &R); 331c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(expectedL == L); 332c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(expectedR == R); 333c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 334c90419199525141a5b98091f856e359bf9daf5b1reed@google.com} 335c90419199525141a5b98091f856e359bf9daf5b1reed@google.com#endif 336c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 337c90419199525141a5b98091f856e359bf9daf5b1reed@google.com// modify row in place, trimming off (zeros) from the left and right sides. 338c90419199525141a5b98091f856e359bf9daf5b1reed@google.com// return the number of bytes that were completely eliminated from the left 339c90419199525141a5b98091f856e359bf9daf5b1reed@google.comstatic int trim_row_left_right(uint8_t* row, int width, int leftZ, int riteZ) { 340c90419199525141a5b98091f856e359bf9daf5b1reed@google.com int trim = 0; 341c90419199525141a5b98091f856e359bf9daf5b1reed@google.com while (leftZ > 0) { 342c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(0 == row[1]); 343c90419199525141a5b98091f856e359bf9daf5b1reed@google.com int n = row[0]; 344c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(n > 0); 345c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(n <= width); 346c90419199525141a5b98091f856e359bf9daf5b1reed@google.com width -= n; 347c90419199525141a5b98091f856e359bf9daf5b1reed@google.com row += 2; 348c90419199525141a5b98091f856e359bf9daf5b1reed@google.com if (n > leftZ) { 349c90419199525141a5b98091f856e359bf9daf5b1reed@google.com row[-2] = n - leftZ; 350c90419199525141a5b98091f856e359bf9daf5b1reed@google.com break; 351c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 352c90419199525141a5b98091f856e359bf9daf5b1reed@google.com trim += 2; 353c90419199525141a5b98091f856e359bf9daf5b1reed@google.com leftZ -= n; 354c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(leftZ >= 0); 355c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 356c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 357c90419199525141a5b98091f856e359bf9daf5b1reed@google.com if (riteZ) { 358c90419199525141a5b98091f856e359bf9daf5b1reed@google.com // walk row to the end, and then we'll back up to trim riteZ 359c90419199525141a5b98091f856e359bf9daf5b1reed@google.com while (width > 0) { 360c90419199525141a5b98091f856e359bf9daf5b1reed@google.com int n = row[0]; 361c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(n <= width); 362c90419199525141a5b98091f856e359bf9daf5b1reed@google.com width -= n; 363c90419199525141a5b98091f856e359bf9daf5b1reed@google.com row += 2; 364c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 365c90419199525141a5b98091f856e359bf9daf5b1reed@google.com // now skip whole runs of zeros 366c90419199525141a5b98091f856e359bf9daf5b1reed@google.com do { 367c90419199525141a5b98091f856e359bf9daf5b1reed@google.com row -= 2; 368c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(0 == row[1]); 369c90419199525141a5b98091f856e359bf9daf5b1reed@google.com int n = row[0]; 370c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(n > 0); 371c90419199525141a5b98091f856e359bf9daf5b1reed@google.com if (n > riteZ) { 372c90419199525141a5b98091f856e359bf9daf5b1reed@google.com row[0] = n - riteZ; 373c90419199525141a5b98091f856e359bf9daf5b1reed@google.com break; 374c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 375c90419199525141a5b98091f856e359bf9daf5b1reed@google.com riteZ -= n; 376c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(riteZ >= 0); 377c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } while (riteZ > 0); 378c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 379fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 380c90419199525141a5b98091f856e359bf9daf5b1reed@google.com return trim; 381c90419199525141a5b98091f856e359bf9daf5b1reed@google.com} 382c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 383c90419199525141a5b98091f856e359bf9daf5b1reed@google.com#ifdef SK_DEBUG 384c90419199525141a5b98091f856e359bf9daf5b1reed@google.com// assert that this row is exactly this width 385c5507bfe2d54e411ef6eb83452b8cbfbae009610reed@google.comstatic void assert_row_width(const uint8_t* row, int width) { 386c90419199525141a5b98091f856e359bf9daf5b1reed@google.com while (width > 0) { 387c90419199525141a5b98091f856e359bf9daf5b1reed@google.com int n = row[0]; 388c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(n > 0); 389c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(n <= width); 390c90419199525141a5b98091f856e359bf9daf5b1reed@google.com width -= n; 391c90419199525141a5b98091f856e359bf9daf5b1reed@google.com row += 2; 392c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 393c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(0 == width); 394c90419199525141a5b98091f856e359bf9daf5b1reed@google.com} 395c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 396c90419199525141a5b98091f856e359bf9daf5b1reed@google.comstatic void test_trim_row_left_right() { 397c90419199525141a5b98091f856e359bf9daf5b1reed@google.com static bool gOnce; 398c90419199525141a5b98091f856e359bf9daf5b1reed@google.com if (gOnce) { 399c90419199525141a5b98091f856e359bf9daf5b1reed@google.com return; 400c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 401c90419199525141a5b98091f856e359bf9daf5b1reed@google.com gOnce = true; 402fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 403c90419199525141a5b98091f856e359bf9daf5b1reed@google.com uint8_t data0[] = { 0, 0, 0, 10, 10, 0xFF }; 404c90419199525141a5b98091f856e359bf9daf5b1reed@google.com uint8_t data1[] = { 2, 0, 0, 10, 5, 0, 2, 0, 3, 0xFF }; 405c90419199525141a5b98091f856e359bf9daf5b1reed@google.com uint8_t data2[] = { 5, 0, 2, 10, 5, 0, 2, 0, 3, 0xFF }; 406c90419199525141a5b98091f856e359bf9daf5b1reed@google.com uint8_t data3[] = { 6, 0, 2, 10, 5, 0, 2, 0, 3, 0xFF }; 407c90419199525141a5b98091f856e359bf9daf5b1reed@google.com uint8_t data4[] = { 0, 0, 0, 10, 2, 0, 2, 0xFF, 2, 0, 2, 0xFF, 2, 0 }; 408c90419199525141a5b98091f856e359bf9daf5b1reed@google.com uint8_t data5[] = { 1, 0, 0, 10, 2, 0, 2, 0xFF, 2, 0, 2, 0xFF, 2, 0 }; 409c90419199525141a5b98091f856e359bf9daf5b1reed@google.com uint8_t data6[] = { 0, 1, 0, 10, 2, 0, 2, 0xFF, 2, 0, 2, 0xFF, 2, 0 }; 410c90419199525141a5b98091f856e359bf9daf5b1reed@google.com uint8_t data7[] = { 1, 1, 0, 10, 2, 0, 2, 0xFF, 2, 0, 2, 0xFF, 2, 0 }; 411c90419199525141a5b98091f856e359bf9daf5b1reed@google.com uint8_t data8[] = { 2, 2, 2, 10, 2, 0, 2, 0xFF, 2, 0, 2, 0xFF, 2, 0 }; 412c90419199525141a5b98091f856e359bf9daf5b1reed@google.com uint8_t data9[] = { 5, 2, 4, 10, 2, 0, 2, 0, 2, 0, 2, 0xFF, 2, 0 }; 413c90419199525141a5b98091f856e359bf9daf5b1reed@google.com uint8_t data10[] ={ 74, 0, 4, 150, 9, 0, 65, 0, 76, 0xFF }; 414fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 415c90419199525141a5b98091f856e359bf9daf5b1reed@google.com uint8_t* array[] = { 416c90419199525141a5b98091f856e359bf9daf5b1reed@google.com data0, data1, data2, data3, data4, 417c90419199525141a5b98091f856e359bf9daf5b1reed@google.com data5, data6, data7, data8, data9, 418c90419199525141a5b98091f856e359bf9daf5b1reed@google.com data10 419c90419199525141a5b98091f856e359bf9daf5b1reed@google.com }; 420fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 421c90419199525141a5b98091f856e359bf9daf5b1reed@google.com for (size_t i = 0; i < SK_ARRAY_COUNT(array); ++i) { 422c90419199525141a5b98091f856e359bf9daf5b1reed@google.com uint8_t* data = array[i]; 423c90419199525141a5b98091f856e359bf9daf5b1reed@google.com const int trimL = *data++; 424c90419199525141a5b98091f856e359bf9daf5b1reed@google.com const int trimR = *data++; 425c90419199525141a5b98091f856e359bf9daf5b1reed@google.com const int expectedSkip = *data++; 426c90419199525141a5b98091f856e359bf9daf5b1reed@google.com const int origWidth = *data++; 427c90419199525141a5b98091f856e359bf9daf5b1reed@google.com assert_row_width(data, origWidth); 428c90419199525141a5b98091f856e359bf9daf5b1reed@google.com int skip = trim_row_left_right(data, origWidth, trimL, trimR); 429c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(expectedSkip == skip); 430c90419199525141a5b98091f856e359bf9daf5b1reed@google.com int expectedWidth = origWidth - trimL - trimR; 431c90419199525141a5b98091f856e359bf9daf5b1reed@google.com assert_row_width(data + skip, expectedWidth); 432c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 433c90419199525141a5b98091f856e359bf9daf5b1reed@google.com} 434c90419199525141a5b98091f856e359bf9daf5b1reed@google.com#endif 435c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 436c90419199525141a5b98091f856e359bf9daf5b1reed@google.combool SkAAClip::trimLeftRight() { 437c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkDEBUGCODE(test_trim_row_left_right();) 438c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 439c90419199525141a5b98091f856e359bf9daf5b1reed@google.com if (this->isEmpty()) { 440c90419199525141a5b98091f856e359bf9daf5b1reed@google.com return false; 441c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 442fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 443c90419199525141a5b98091f856e359bf9daf5b1reed@google.com AUTO_AACLIP_VALIDATE(*this); 444c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 445c90419199525141a5b98091f856e359bf9daf5b1reed@google.com const int width = fBounds.width(); 446c90419199525141a5b98091f856e359bf9daf5b1reed@google.com RunHead* head = fRunHead; 447c90419199525141a5b98091f856e359bf9daf5b1reed@google.com YOffset* yoff = head->yoffsets(); 448c90419199525141a5b98091f856e359bf9daf5b1reed@google.com YOffset* stop = yoff + head->fRowCount; 449c90419199525141a5b98091f856e359bf9daf5b1reed@google.com uint8_t* base = head->data(); 450c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 451768fee8b6e9ae0a849ed45ab377fc9079b5db11erobertphillips@google.com // After this loop, 'leftZeros' & 'rightZeros' will contain the minimum 452768fee8b6e9ae0a849ed45ab377fc9079b5db11erobertphillips@google.com // number of zeros on the left and right of the clip. This information 453768fee8b6e9ae0a849ed45ab377fc9079b5db11erobertphillips@google.com // can be used to shrink the bounding box. 454c90419199525141a5b98091f856e359bf9daf5b1reed@google.com int leftZeros = width; 455c90419199525141a5b98091f856e359bf9daf5b1reed@google.com int riteZeros = width; 456c90419199525141a5b98091f856e359bf9daf5b1reed@google.com while (yoff < stop) { 457c90419199525141a5b98091f856e359bf9daf5b1reed@google.com int L, R; 458c90419199525141a5b98091f856e359bf9daf5b1reed@google.com count_left_right_zeros(base + yoff->fOffset, width, &L, &R); 459768fee8b6e9ae0a849ed45ab377fc9079b5db11erobertphillips@google.com SkASSERT(L + R < width || (L == width && R == width)); 460c90419199525141a5b98091f856e359bf9daf5b1reed@google.com if (L < leftZeros) { 461c90419199525141a5b98091f856e359bf9daf5b1reed@google.com leftZeros = L; 462c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 463c90419199525141a5b98091f856e359bf9daf5b1reed@google.com if (R < riteZeros) { 464c90419199525141a5b98091f856e359bf9daf5b1reed@google.com riteZeros = R; 465c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 466c90419199525141a5b98091f856e359bf9daf5b1reed@google.com if (0 == (leftZeros | riteZeros)) { 467c90419199525141a5b98091f856e359bf9daf5b1reed@google.com // no trimming to do 468c90419199525141a5b98091f856e359bf9daf5b1reed@google.com return true; 469c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 470c90419199525141a5b98091f856e359bf9daf5b1reed@google.com yoff += 1; 471c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 472c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 473c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(leftZeros || riteZeros); 474768fee8b6e9ae0a849ed45ab377fc9079b5db11erobertphillips@google.com if (width == leftZeros) { 475768fee8b6e9ae0a849ed45ab377fc9079b5db11erobertphillips@google.com SkASSERT(width == riteZeros); 476c90419199525141a5b98091f856e359bf9daf5b1reed@google.com return this->setEmpty(); 477c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 478c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 479c90419199525141a5b98091f856e359bf9daf5b1reed@google.com this->validate(); 480c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 481c90419199525141a5b98091f856e359bf9daf5b1reed@google.com fBounds.fLeft += leftZeros; 482c90419199525141a5b98091f856e359bf9daf5b1reed@google.com fBounds.fRight -= riteZeros; 483c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(!fBounds.isEmpty()); 484c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 485c90419199525141a5b98091f856e359bf9daf5b1reed@google.com // For now we don't realloc the storage (for time), we just shrink in place 486c90419199525141a5b98091f856e359bf9daf5b1reed@google.com // This means we don't have to do any memmoves either, since we can just 487c90419199525141a5b98091f856e359bf9daf5b1reed@google.com // play tricks with the yoff->fOffset for each row 488c90419199525141a5b98091f856e359bf9daf5b1reed@google.com yoff = head->yoffsets(); 489c90419199525141a5b98091f856e359bf9daf5b1reed@google.com while (yoff < stop) { 490c90419199525141a5b98091f856e359bf9daf5b1reed@google.com uint8_t* row = base + yoff->fOffset; 491c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkDEBUGCODE((void)compute_row_length(row, width);) 492c90419199525141a5b98091f856e359bf9daf5b1reed@google.com yoff->fOffset += trim_row_left_right(row, width, leftZeros, riteZeros); 493c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkDEBUGCODE((void)compute_row_length(base + yoff->fOffset, width - leftZeros - riteZeros);) 494c90419199525141a5b98091f856e359bf9daf5b1reed@google.com yoff += 1; 495c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 496c90419199525141a5b98091f856e359bf9daf5b1reed@google.com return true; 497c90419199525141a5b98091f856e359bf9daf5b1reed@google.com} 498c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 499c90419199525141a5b98091f856e359bf9daf5b1reed@google.comstatic bool row_is_all_zeros(const uint8_t* row, int width) { 500c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(width > 0); 501c90419199525141a5b98091f856e359bf9daf5b1reed@google.com do { 502c90419199525141a5b98091f856e359bf9daf5b1reed@google.com if (row[1]) { 503c90419199525141a5b98091f856e359bf9daf5b1reed@google.com return false; 504c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 505c90419199525141a5b98091f856e359bf9daf5b1reed@google.com int n = row[0]; 506c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(n <= width); 507c90419199525141a5b98091f856e359bf9daf5b1reed@google.com width -= n; 508c90419199525141a5b98091f856e359bf9daf5b1reed@google.com row += 2; 509c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } while (width > 0); 510c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(0 == width); 511c90419199525141a5b98091f856e359bf9daf5b1reed@google.com return true; 512c90419199525141a5b98091f856e359bf9daf5b1reed@google.com} 513c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 514c90419199525141a5b98091f856e359bf9daf5b1reed@google.combool SkAAClip::trimTopBottom() { 515c90419199525141a5b98091f856e359bf9daf5b1reed@google.com if (this->isEmpty()) { 516c90419199525141a5b98091f856e359bf9daf5b1reed@google.com return false; 517c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 518c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 519d6040f6f2fcb11fddad5d92b3cb7255e90931bccreed@google.com this->validate(); 520d6040f6f2fcb11fddad5d92b3cb7255e90931bccreed@google.com 521c90419199525141a5b98091f856e359bf9daf5b1reed@google.com const int width = fBounds.width(); 522c90419199525141a5b98091f856e359bf9daf5b1reed@google.com RunHead* head = fRunHead; 523c90419199525141a5b98091f856e359bf9daf5b1reed@google.com YOffset* yoff = head->yoffsets(); 524c90419199525141a5b98091f856e359bf9daf5b1reed@google.com YOffset* stop = yoff + head->fRowCount; 525c90419199525141a5b98091f856e359bf9daf5b1reed@google.com const uint8_t* base = head->data(); 526c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 527c90419199525141a5b98091f856e359bf9daf5b1reed@google.com // Look to trim away empty rows from the top. 528c90419199525141a5b98091f856e359bf9daf5b1reed@google.com // 529c90419199525141a5b98091f856e359bf9daf5b1reed@google.com int skip = 0; 530c90419199525141a5b98091f856e359bf9daf5b1reed@google.com while (yoff < stop) { 531c90419199525141a5b98091f856e359bf9daf5b1reed@google.com const uint8_t* data = base + yoff->fOffset; 532c90419199525141a5b98091f856e359bf9daf5b1reed@google.com if (!row_is_all_zeros(data, width)) { 533c90419199525141a5b98091f856e359bf9daf5b1reed@google.com break; 534c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 535c90419199525141a5b98091f856e359bf9daf5b1reed@google.com skip += 1; 536c90419199525141a5b98091f856e359bf9daf5b1reed@google.com yoff += 1; 537c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 538c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(skip <= head->fRowCount); 539c90419199525141a5b98091f856e359bf9daf5b1reed@google.com if (skip == head->fRowCount) { 540c90419199525141a5b98091f856e359bf9daf5b1reed@google.com return this->setEmpty(); 541c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 542c90419199525141a5b98091f856e359bf9daf5b1reed@google.com if (skip > 0) { 543c90419199525141a5b98091f856e359bf9daf5b1reed@google.com // adjust fRowCount and fBounds.fTop, and slide all the data up 544c90419199525141a5b98091f856e359bf9daf5b1reed@google.com // as we remove [skip] number of YOffset entries 545c90419199525141a5b98091f856e359bf9daf5b1reed@google.com yoff = head->yoffsets(); 546c90419199525141a5b98091f856e359bf9daf5b1reed@google.com int dy = yoff[skip - 1].fY + 1; 547c90419199525141a5b98091f856e359bf9daf5b1reed@google.com for (int i = skip; i < head->fRowCount; ++i) { 548c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(yoff[i].fY >= dy); 549c90419199525141a5b98091f856e359bf9daf5b1reed@google.com yoff[i].fY -= dy; 550c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 551c90419199525141a5b98091f856e359bf9daf5b1reed@google.com YOffset* dst = head->yoffsets(); 552c90419199525141a5b98091f856e359bf9daf5b1reed@google.com size_t size = head->fRowCount * sizeof(YOffset) + head->fDataSize; 553c90419199525141a5b98091f856e359bf9daf5b1reed@google.com memmove(dst, dst + skip, size - skip * sizeof(YOffset)); 554c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 555c90419199525141a5b98091f856e359bf9daf5b1reed@google.com fBounds.fTop += dy; 556c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(!fBounds.isEmpty()); 557c90419199525141a5b98091f856e359bf9daf5b1reed@google.com head->fRowCount -= skip; 558c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(head->fRowCount > 0); 559fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 560d6040f6f2fcb11fddad5d92b3cb7255e90931bccreed@google.com this->validate(); 561d6040f6f2fcb11fddad5d92b3cb7255e90931bccreed@google.com // need to reset this after the memmove 562d6040f6f2fcb11fddad5d92b3cb7255e90931bccreed@google.com base = head->data(); 563c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 564c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 565c90419199525141a5b98091f856e359bf9daf5b1reed@google.com // Look to trim away empty rows from the bottom. 566c90419199525141a5b98091f856e359bf9daf5b1reed@google.com // We know that we have at least one non-zero row, so we can just walk 567c90419199525141a5b98091f856e359bf9daf5b1reed@google.com // backwards without checking for running past the start. 568c90419199525141a5b98091f856e359bf9daf5b1reed@google.com // 569c90419199525141a5b98091f856e359bf9daf5b1reed@google.com stop = yoff = head->yoffsets() + head->fRowCount; 570c90419199525141a5b98091f856e359bf9daf5b1reed@google.com do { 571c90419199525141a5b98091f856e359bf9daf5b1reed@google.com yoff -= 1; 572c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } while (row_is_all_zeros(base + yoff->fOffset, width)); 573a8c7f7702fb4bbedb615031bc653c5cd161a038ecommit-bot@chromium.org skip = SkToInt(stop - yoff - 1); 574c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(skip >= 0 && skip < head->fRowCount); 575c90419199525141a5b98091f856e359bf9daf5b1reed@google.com if (skip > 0) { 576c90419199525141a5b98091f856e359bf9daf5b1reed@google.com // removing from the bottom is easier than from the top, as we don't 577c90419199525141a5b98091f856e359bf9daf5b1reed@google.com // have to adjust any of the Y values, we just have to trim the array 578c90419199525141a5b98091f856e359bf9daf5b1reed@google.com memmove(stop - skip, stop, head->fDataSize); 579c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 580c90419199525141a5b98091f856e359bf9daf5b1reed@google.com fBounds.fBottom = fBounds.fTop + yoff->fY + 1; 581c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(!fBounds.isEmpty()); 582c90419199525141a5b98091f856e359bf9daf5b1reed@google.com head->fRowCount -= skip; 583c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(head->fRowCount > 0); 584c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 585d6040f6f2fcb11fddad5d92b3cb7255e90931bccreed@google.com this->validate(); 586c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 587c90419199525141a5b98091f856e359bf9daf5b1reed@google.com return true; 588c90419199525141a5b98091f856e359bf9daf5b1reed@google.com} 589c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 590045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com// can't validate before we're done, since trimming is part of the process of 591045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com// making us valid after the Builder. Since we build from top to bottom, its 592045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com// possible our fBounds.fBottom is bigger than our last scanline of data, so 593045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com// we trim fBounds.fBottom back up. 594045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com// 595045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com// TODO: check for duplicates in X and Y to further compress our data 596045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com// 597045e62d715f5ee9b03deb5af3c750f8318096179reed@google.combool SkAAClip::trimBounds() { 598045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (this->isEmpty()) { 599045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return false; 600045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 601045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 602045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const RunHead* head = fRunHead; 603045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const YOffset* yoff = head->yoffsets(); 604045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 605045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(head->fRowCount > 0); 606045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const YOffset& lastY = yoff[head->fRowCount - 1]; 607045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(lastY.fY + 1 <= fBounds.height()); 608045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fBounds.fBottom = fBounds.fTop + lastY.fY + 1; 609045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(lastY.fY + 1 == fBounds.height()); 610c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(!fBounds.isEmpty()); 611c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 612c90419199525141a5b98091f856e359bf9daf5b1reed@google.com return this->trimTopBottom() && this->trimLeftRight(); 613045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com} 614045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 615e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com/////////////////////////////////////////////////////////////////////////////// 616e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 617e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comvoid SkAAClip::freeRuns() { 61847ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com if (fRunHead) { 619e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(fRunHead->fRefCnt >= 1); 620e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (1 == sk_atomic_dec(&fRunHead->fRefCnt)) { 621e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com sk_free(fRunHead); 622e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 623e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 624e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 625e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 626e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comSkAAClip::SkAAClip() { 627e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fBounds.setEmpty(); 62896fcdcc219d2a0d3579719b84b28bede76efba64halcanary fRunHead = nullptr; 629e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 630e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 631e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comSkAAClip::SkAAClip(const SkAAClip& src) { 632045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkDEBUGCODE(fBounds.setEmpty();) // need this for validate 63396fcdcc219d2a0d3579719b84b28bede76efba64halcanary fRunHead = nullptr; 634e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com *this = src; 635e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 636e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 637e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comSkAAClip::~SkAAClip() { 638e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com this->freeRuns(); 639e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 640e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 641e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comSkAAClip& SkAAClip::operator=(const SkAAClip& src) { 642045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com AUTO_AACLIP_VALIDATE(*this); 643045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com src.validate(); 644045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 645e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (this != &src) { 646e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com this->freeRuns(); 647e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fBounds = src.fBounds; 648e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fRunHead = src.fRunHead; 64947ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com if (fRunHead) { 650e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com sk_atomic_inc(&fRunHead->fRefCnt); 651e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 652e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 653e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return *this; 654e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 655e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 656e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.combool operator==(const SkAAClip& a, const SkAAClip& b) { 657045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com a.validate(); 658045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com b.validate(); 659045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 660e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (&a == &b) { 661e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return true; 662e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 663e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (a.fBounds != b.fBounds) { 664e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return false; 665e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 666fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 667e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const SkAAClip::RunHead* ah = a.fRunHead; 668e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const SkAAClip::RunHead* bh = b.fRunHead; 669fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 670e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com // this catches empties and rects being equal 671e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (ah == bh) { 672e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return true; 673e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 674e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 675e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com // now we insist that both are complex (but different ptrs) 67647ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com if (!a.fRunHead || !b.fRunHead) { 677e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return false; 678e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 679e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 680e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return ah->fRowCount == bh->fRowCount && 681e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com ah->fDataSize == bh->fDataSize && 682e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com !memcmp(ah->data(), bh->data(), ah->fDataSize); 683e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 684e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 685e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comvoid SkAAClip::swap(SkAAClip& other) { 686045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com AUTO_AACLIP_VALIDATE(*this); 687045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com other.validate(); 688045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 689e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkTSwap(fBounds, other.fBounds); 690e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkTSwap(fRunHead, other.fRunHead); 691e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 692e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 693322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.combool SkAAClip::set(const SkAAClip& src) { 694322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com *this = src; 695322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return !this->isEmpty(); 696322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com} 697322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 698e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.combool SkAAClip::setEmpty() { 699e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com this->freeRuns(); 700e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fBounds.setEmpty(); 70196fcdcc219d2a0d3579719b84b28bede76efba64halcanary fRunHead = nullptr; 702e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return false; 703e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 704e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 705e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.combool SkAAClip::setRect(const SkIRect& bounds) { 706e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (bounds.isEmpty()) { 707e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return this->setEmpty(); 708e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 70947ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com 710045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com AUTO_AACLIP_VALIDATE(*this); 71147ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com 712045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com#if 0 71347ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com SkRect r; 71447ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com r.set(bounds); 71547ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com SkPath path; 71647ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com path.addRect(r); 71747ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com return this->setPath(path); 718045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com#else 719045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com this->freeRuns(); 720045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fBounds = bounds; 721045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fRunHead = RunHead::AllocRect(bounds); 722045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(!this->isEmpty()); 723045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return true; 724045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com#endif 725e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 726e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 727202ab2a5cabaf25a1e6ec47c0003da3213a79864reedbool SkAAClip::isRect() const { 728202ab2a5cabaf25a1e6ec47c0003da3213a79864reed if (this->isEmpty()) { 729202ab2a5cabaf25a1e6ec47c0003da3213a79864reed return false; 730202ab2a5cabaf25a1e6ec47c0003da3213a79864reed } 731202ab2a5cabaf25a1e6ec47c0003da3213a79864reed 732202ab2a5cabaf25a1e6ec47c0003da3213a79864reed const RunHead* head = fRunHead; 733202ab2a5cabaf25a1e6ec47c0003da3213a79864reed if (head->fRowCount != 1) { 734202ab2a5cabaf25a1e6ec47c0003da3213a79864reed return false; 735202ab2a5cabaf25a1e6ec47c0003da3213a79864reed } 736202ab2a5cabaf25a1e6ec47c0003da3213a79864reed const YOffset* yoff = head->yoffsets(); 737202ab2a5cabaf25a1e6ec47c0003da3213a79864reed if (yoff->fY != fBounds.fBottom - 1) { 738202ab2a5cabaf25a1e6ec47c0003da3213a79864reed return false; 739202ab2a5cabaf25a1e6ec47c0003da3213a79864reed } 740202ab2a5cabaf25a1e6ec47c0003da3213a79864reed 741202ab2a5cabaf25a1e6ec47c0003da3213a79864reed const uint8_t* row = head->data() + yoff->fOffset; 742202ab2a5cabaf25a1e6ec47c0003da3213a79864reed int width = fBounds.width(); 743202ab2a5cabaf25a1e6ec47c0003da3213a79864reed do { 744202ab2a5cabaf25a1e6ec47c0003da3213a79864reed if (row[1] != 0xFF) { 745202ab2a5cabaf25a1e6ec47c0003da3213a79864reed return false; 746202ab2a5cabaf25a1e6ec47c0003da3213a79864reed } 747202ab2a5cabaf25a1e6ec47c0003da3213a79864reed int n = row[0]; 748202ab2a5cabaf25a1e6ec47c0003da3213a79864reed SkASSERT(n <= width); 749202ab2a5cabaf25a1e6ec47c0003da3213a79864reed width -= n; 750202ab2a5cabaf25a1e6ec47c0003da3213a79864reed row += 2; 751202ab2a5cabaf25a1e6ec47c0003da3213a79864reed } while (width > 0); 752202ab2a5cabaf25a1e6ec47c0003da3213a79864reed return true; 753202ab2a5cabaf25a1e6ec47c0003da3213a79864reed} 754202ab2a5cabaf25a1e6ec47c0003da3213a79864reed 755f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.combool SkAAClip::setRect(const SkRect& r, bool doAA) { 756e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (r.isEmpty()) { 757e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return this->setEmpty(); 758e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 759e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 760045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com AUTO_AACLIP_VALIDATE(*this); 761045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 762045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com // TODO: special case this 763045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 764e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkPath path; 765e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com path.addRect(r); 76696fcdcc219d2a0d3579719b84b28bede76efba64halcanary return this->setPath(path, nullptr, doAA); 767f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com} 768f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com 769a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.comstatic void append_run(SkTDArray<uint8_t>& array, uint8_t value, int count) { 770a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com SkASSERT(count >= 0); 771a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com while (count > 0) { 772a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com int n = count; 773a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com if (n > 255) { 774a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com n = 255; 775a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com } 776a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com uint8_t* data = array.append(2); 777a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com data[0] = n; 778a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com data[1] = value; 779a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com count -= n; 780a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com } 781a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com} 782a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com 783f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.combool SkAAClip::setRegion(const SkRegion& rgn) { 784f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com if (rgn.isEmpty()) { 785f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com return this->setEmpty(); 786f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com } 787f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com if (rgn.isRect()) { 788f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com return this->setRect(rgn.getBounds()); 789f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com } 790a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com 791a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com#if 0 792f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com SkAAClip clip; 793f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com SkRegion::Iterator iter(rgn); 794f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com for (; !iter.done(); iter.next()) { 795f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com clip.op(iter.rect(), SkRegion::kUnion_Op); 796f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com } 797f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com this->swap(clip); 7983771a030b0b6686b0ec81359774836cc376ea3f4reed@google.com return !this->isEmpty(); 799fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com#else 800a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com const SkIRect& bounds = rgn.getBounds(); 801a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com const int offsetX = bounds.fLeft; 802a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com const int offsetY = bounds.fTop; 803a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com 804a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com SkTDArray<YOffset> yArray; 805a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com SkTDArray<uint8_t> xArray; 806a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com 807a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com yArray.setReserve(SkMin32(bounds.height(), 1024)); 808a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com xArray.setReserve(SkMin32(bounds.width() * 128, 64 * 1024)); 809a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com 810a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com SkRegion::Iterator iter(rgn); 811a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com int prevRight = 0; 812a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com int prevBot = 0; 81396fcdcc219d2a0d3579719b84b28bede76efba64halcanary YOffset* currY = nullptr; 814a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com 815a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com for (; !iter.done(); iter.next()) { 816a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com const SkIRect& r = iter.rect(); 817a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com SkASSERT(bounds.contains(r)); 818a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com 819a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com int bot = r.fBottom - offsetY; 820a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com SkASSERT(bot >= prevBot); 821a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com if (bot > prevBot) { 822a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com if (currY) { 823a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com // flush current row 824a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com append_run(xArray, 0, bounds.width() - prevRight); 825a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com } 826a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com // did we introduce an empty-gap from the prev row? 827a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com int top = r.fTop - offsetY; 828a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com if (top > prevBot) { 829a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com currY = yArray.append(); 830a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com currY->fY = top - 1; 831a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com currY->fOffset = xArray.count(); 832a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com append_run(xArray, 0, bounds.width()); 833a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com } 834a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com // create a new record for this Y value 835a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com currY = yArray.append(); 836a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com currY->fY = bot - 1; 837a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com currY->fOffset = xArray.count(); 838a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com prevRight = 0; 839a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com prevBot = bot; 840a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com } 841a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com 842a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com int x = r.fLeft - offsetX; 843a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com append_run(xArray, 0, x - prevRight); 844a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com 845a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com int w = r.fRight - r.fLeft; 846a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com append_run(xArray, 0xFF, w); 847a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com prevRight = x + w; 848a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com SkASSERT(prevRight <= bounds.width()); 849a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com } 850a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com // flush last row 851a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com append_run(xArray, 0, bounds.width() - prevRight); 852a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com 853a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com // now pack everything into a RunHead 854a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com RunHead* head = RunHead::Alloc(yArray.count(), xArray.bytes()); 855a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com memcpy(head->yoffsets(), yArray.begin(), yArray.bytes()); 856a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com memcpy(head->data(), xArray.begin(), xArray.bytes()); 857a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com 858a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com this->setEmpty(); 859a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com fBounds = bounds; 860a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com fRunHead = head; 861a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com this->validate(); 862a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com return true; 863a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com#endif 864e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 865e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 866e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com/////////////////////////////////////////////////////////////////////////////// 867e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 868e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comconst uint8_t* SkAAClip::findRow(int y, int* lastYForRow) const { 86947ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com SkASSERT(fRunHead); 870e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 871e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (!y_in_rect(y, fBounds)) { 87296fcdcc219d2a0d3579719b84b28bede76efba64halcanary return nullptr; 873e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 874e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com y -= fBounds.y(); // our yoffs values are relative to the top 875e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 876e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const YOffset* yoff = fRunHead->yoffsets(); 877e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com while (yoff->fY < y) { 878e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com yoff += 1; 879e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(yoff - fRunHead->yoffsets() < fRunHead->fRowCount); 880e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 881e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 882e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (lastYForRow) { 883045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com *lastYForRow = fBounds.y() + yoff->fY; 884e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 885e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return fRunHead->data() + yoff->fOffset; 886e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 887e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 888e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comconst uint8_t* SkAAClip::findX(const uint8_t data[], int x, int* initialCount) const { 889e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(x_in_rect(x, fBounds)); 890e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com x -= fBounds.x(); 891e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 892e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com // first skip up to X 893e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com for (;;) { 894e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int n = data[0]; 895e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (x < n) { 896a4c6e4d6d3a4010df8dd2b04314675e4c201133breed@google.com if (initialCount) { 897a4c6e4d6d3a4010df8dd2b04314675e4c201133breed@google.com *initialCount = n - x; 898a4c6e4d6d3a4010df8dd2b04314675e4c201133breed@google.com } 899e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com break; 900e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 901e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com data += 2; 902e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com x -= n; 903e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 904e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return data; 905e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 906e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 907e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.combool SkAAClip::quickContains(int left, int top, int right, int bottom) const { 908e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (this->isEmpty()) { 909e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return false; 910e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 911e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (!fBounds.contains(left, top, right, bottom)) { 912e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return false; 913e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 914322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com#if 0 915e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (this->isRect()) { 916e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return true; 917e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 918322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com#endif 919e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 920a4c6e4d6d3a4010df8dd2b04314675e4c201133breed@google.com int lastY SK_INIT_TO_AVOID_WARNING; 921e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const uint8_t* row = this->findRow(top, &lastY); 922e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (lastY < bottom) { 923e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return false; 924e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 925e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com // now just need to check in X 926045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com int count; 927045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com row = this->findX(row, left, &count); 928045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com#if 0 929045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return count >= (right - left) && 0xFF == row[1]; 930045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com#else 931045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com int rectWidth = right - left; 932045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com while (0xFF == row[1]) { 933045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (count >= rectWidth) { 934045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return true; 935045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 936045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com rectWidth -= count; 937045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com row += 2; 938045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com count = row[0]; 939045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 940045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return false; 941045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com#endif 942e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 943e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 944e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com/////////////////////////////////////////////////////////////////////////////// 945e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 946e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comclass SkAAClip::Builder { 947e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkIRect fBounds; 948e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com struct Row { 949e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int fY; 950e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int fWidth; 951e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkTDArray<uint8_t>* fData; 952e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com }; 953e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkTDArray<Row> fRows; 954e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com Row* fCurrRow; 955e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int fPrevY; 956e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int fWidth; 957209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com int fMinY; 958e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 959e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.compublic: 960e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com Builder(const SkIRect& bounds) : fBounds(bounds) { 961e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fPrevY = -1; 962e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fWidth = bounds.width(); 96396fcdcc219d2a0d3579719b84b28bede76efba64halcanary fCurrRow = nullptr; 964209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com fMinY = bounds.fTop; 965e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 966e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 967e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com ~Builder() { 968e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com Row* row = fRows.begin(); 969e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com Row* stop = fRows.end(); 970e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com while (row < stop) { 971e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com delete row->fData; 972e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com row += 1; 973e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 974e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 975e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 976322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com const SkIRect& getBounds() const { return fBounds; } 977322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 978e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com void addRun(int x, int y, U8CPU alpha, int count) { 979e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(count > 0); 980e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(fBounds.contains(x, y)); 981e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(fBounds.contains(x + count - 1, y)); 982fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 983e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com x -= fBounds.left(); 984e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com y -= fBounds.top(); 985fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 986e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com Row* row = fCurrRow; 987e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (y != fPrevY) { 988e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(y > fPrevY); 989e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fPrevY = y; 990e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com row = this->flushRow(true); 991e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com row->fY = y; 992e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com row->fWidth = 0; 993e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(row->fData); 994e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(0 == row->fData->count()); 995e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fCurrRow = row; 996e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 997e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 998e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(row->fWidth <= x); 999e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(row->fWidth < fBounds.width()); 1000e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1001e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkTDArray<uint8_t>& data = *row->fData; 1002e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1003e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int gap = x - row->fWidth; 1004e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (gap) { 1005e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com AppendRun(data, 0, gap); 1006e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com row->fWidth += gap; 1007e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(row->fWidth < fBounds.width()); 1008e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1009e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1010e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com AppendRun(data, alpha, count); 1011e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com row->fWidth += count; 1012e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(row->fWidth <= fBounds.width()); 1013e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1014e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 101549eac192faa35159752525b23345563252721c64tomhudson@google.com void addColumn(int x, int y, U8CPU alpha, int height) { 101649eac192faa35159752525b23345563252721c64tomhudson@google.com SkASSERT(fBounds.contains(x, y + height - 1)); 101749eac192faa35159752525b23345563252721c64tomhudson@google.com 101849eac192faa35159752525b23345563252721c64tomhudson@google.com this->addRun(x, y, alpha, 1); 101949eac192faa35159752525b23345563252721c64tomhudson@google.com this->flushRowH(fCurrRow); 102049eac192faa35159752525b23345563252721c64tomhudson@google.com y -= fBounds.fTop; 102149eac192faa35159752525b23345563252721c64tomhudson@google.com SkASSERT(y == fCurrRow->fY); 102249eac192faa35159752525b23345563252721c64tomhudson@google.com fCurrRow->fY = y + height - 1; 102349eac192faa35159752525b23345563252721c64tomhudson@google.com } 1024fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 10259154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com void addRectRun(int x, int y, int width, int height) { 10269154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com SkASSERT(fBounds.contains(x + width - 1, y + height - 1)); 10279154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com this->addRun(x, y, 0xFF, width); 10289154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com 1029a89c77b5cafcc13d76cb07c3240e48705cb30d8freed@google.com // we assum the rect must be all we'll see for these scanlines 10309154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com // so we ensure our row goes all the way to our right 10319154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com this->flushRowH(fCurrRow); 10329154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com 10339154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com y -= fBounds.fTop; 10349154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com SkASSERT(y == fCurrRow->fY); 10359154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com fCurrRow->fY = y + height - 1; 10369154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com } 10379154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com 103849eac192faa35159752525b23345563252721c64tomhudson@google.com void addAntiRectRun(int x, int y, int width, int height, 103949eac192faa35159752525b23345563252721c64tomhudson@google.com SkAlpha leftAlpha, SkAlpha rightAlpha) { 10402add0ffdaab4c33ca6702c81533c88c7b5ca7294liyuqian // According to SkBlitter.cpp, no matter whether leftAlpha is 0 or positive, 10412add0ffdaab4c33ca6702c81533c88c7b5ca7294liyuqian // we should always consider [x, x+1] as the left-most column and [x+1, x+1+width] 10422add0ffdaab4c33ca6702c81533c88c7b5ca7294liyuqian // as the rect with full alpha. 10432add0ffdaab4c33ca6702c81533c88c7b5ca7294liyuqian SkASSERT(fBounds.contains(x + width + (rightAlpha > 0 ? 1 : 0), 104449eac192faa35159752525b23345563252721c64tomhudson@google.com y + height - 1)); 104549eac192faa35159752525b23345563252721c64tomhudson@google.com SkASSERT(width >= 0); 104649eac192faa35159752525b23345563252721c64tomhudson@google.com 104749eac192faa35159752525b23345563252721c64tomhudson@google.com // Conceptually we're always adding 3 runs, but we should 104849eac192faa35159752525b23345563252721c64tomhudson@google.com // merge or omit them if possible. 104949eac192faa35159752525b23345563252721c64tomhudson@google.com if (leftAlpha == 0xFF) { 105049eac192faa35159752525b23345563252721c64tomhudson@google.com width++; 105149eac192faa35159752525b23345563252721c64tomhudson@google.com } else if (leftAlpha > 0) { 105249eac192faa35159752525b23345563252721c64tomhudson@google.com this->addRun(x++, y, leftAlpha, 1); 10532add0ffdaab4c33ca6702c81533c88c7b5ca7294liyuqian } else { 10542add0ffdaab4c33ca6702c81533c88c7b5ca7294liyuqian // leftAlpha is 0, ignore the left column 10552add0ffdaab4c33ca6702c81533c88c7b5ca7294liyuqian x++; 105649eac192faa35159752525b23345563252721c64tomhudson@google.com } 105749eac192faa35159752525b23345563252721c64tomhudson@google.com if (rightAlpha == 0xFF) { 105849eac192faa35159752525b23345563252721c64tomhudson@google.com width++; 105949eac192faa35159752525b23345563252721c64tomhudson@google.com } 106049eac192faa35159752525b23345563252721c64tomhudson@google.com if (width > 0) { 106149eac192faa35159752525b23345563252721c64tomhudson@google.com this->addRun(x, y, 0xFF, width); 106249eac192faa35159752525b23345563252721c64tomhudson@google.com } 106349eac192faa35159752525b23345563252721c64tomhudson@google.com if (rightAlpha > 0 && rightAlpha < 255) { 106449eac192faa35159752525b23345563252721c64tomhudson@google.com this->addRun(x + width, y, rightAlpha, 1); 106549eac192faa35159752525b23345563252721c64tomhudson@google.com } 106649eac192faa35159752525b23345563252721c64tomhudson@google.com 106749eac192faa35159752525b23345563252721c64tomhudson@google.com // we assume the rect must be all we'll see for these scanlines 106849eac192faa35159752525b23345563252721c64tomhudson@google.com // so we ensure our row goes all the way to our right 106949eac192faa35159752525b23345563252721c64tomhudson@google.com this->flushRowH(fCurrRow); 107049eac192faa35159752525b23345563252721c64tomhudson@google.com 107149eac192faa35159752525b23345563252721c64tomhudson@google.com y -= fBounds.fTop; 107249eac192faa35159752525b23345563252721c64tomhudson@google.com SkASSERT(y == fCurrRow->fY); 107349eac192faa35159752525b23345563252721c64tomhudson@google.com fCurrRow->fY = y + height - 1; 107449eac192faa35159752525b23345563252721c64tomhudson@google.com } 107549eac192faa35159752525b23345563252721c64tomhudson@google.com 1076045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com bool finish(SkAAClip* target) { 1077e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com this->flushRow(false); 1078e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1079e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const Row* row = fRows.begin(); 1080e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const Row* stop = fRows.end(); 1081e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1082fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com size_t dataSize = 0; 1083e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com while (row < stop) { 1084e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com dataSize += row->fData->count(); 1085e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com row += 1; 1086e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1087e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1088045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (0 == dataSize) { 1089045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return target->setEmpty(); 1090045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1091045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1092209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com SkASSERT(fMinY >= fBounds.fTop); 1093209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com SkASSERT(fMinY < fBounds.fBottom); 1094209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com int adjustY = fMinY - fBounds.fTop; 1095209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com fBounds.fTop = fMinY; 1096209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com 1097e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com RunHead* head = RunHead::Alloc(fRows.count(), dataSize); 1098e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com YOffset* yoffset = head->yoffsets(); 1099e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com uint8_t* data = head->data(); 1100e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com uint8_t* baseData = data; 1101e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1102e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com row = fRows.begin(); 1103c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkDEBUGCODE(int prevY = row->fY - 1;) 1104e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com while (row < stop) { 1105c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(prevY < row->fY); // must be monotonic 1106c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkDEBUGCODE(prevY = row->fY); 1107c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 1108209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com yoffset->fY = row->fY - adjustY; 1109a8c7f7702fb4bbedb615031bc653c5cd161a038ecommit-bot@chromium.org yoffset->fOffset = SkToU32(data - baseData); 1110e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com yoffset += 1; 1111fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1112e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com size_t n = row->fData->count(); 1113e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com memcpy(data, row->fData->begin(), n); 1114c90419199525141a5b98091f856e359bf9daf5b1reed@google.com#ifdef SK_DEBUG 1115f74ad8c91aef4f328dbcbcebae9e436c00a35140tomhudson@google.com size_t bytesNeeded = compute_row_length(data, fBounds.width()); 1116c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(bytesNeeded == n); 1117c90419199525141a5b98091f856e359bf9daf5b1reed@google.com#endif 1118e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com data += n; 1119fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1120e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com row += 1; 1121e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1122e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1123045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com target->freeRuns(); 1124045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com target->fBounds = fBounds; 1125045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com target->fRunHead = head; 1126045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return target->trimBounds(); 1127e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1128e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1129e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com void dump() { 1130e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com this->validate(); 1131e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int y; 1132e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com for (y = 0; y < fRows.count(); ++y) { 1133e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const Row& row = fRows[y]; 1134e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkDebugf("Y:%3d W:%3d", row.fY, row.fWidth); 1135e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const SkTDArray<uint8_t>& data = *row.fData; 1136e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int count = data.count(); 1137e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(!(count & 1)); 1138e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const uint8_t* ptr = data.begin(); 1139e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com for (int x = 0; x < count; x += 2) { 1140e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkDebugf(" [%3d:%02X]", ptr[0], ptr[1]); 1141e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com ptr += 2; 1142e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1143e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkDebugf("\n"); 1144e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1145e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1146e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1147e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com void validate() { 1148e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com#ifdef SK_DEBUG 1149803eceb6afd13f07416df0b4a9bb714e9370f081caryclark@google.com if (false) { // avoid bit rot, suppress warning 1150803eceb6afd13f07416df0b4a9bb714e9370f081caryclark@google.com test_count_left_right_zeros(); 1151803eceb6afd13f07416df0b4a9bb714e9370f081caryclark@google.com } 1152e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int prevY = -1; 1153e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com for (int i = 0; i < fRows.count(); ++i) { 1154e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const Row& row = fRows[i]; 1155e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(prevY < row.fY); 1156e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(fWidth == row.fWidth); 1157e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int count = row.fData->count(); 1158e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const uint8_t* ptr = row.fData->begin(); 1159e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(!(count & 1)); 1160e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int w = 0; 1161e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com for (int x = 0; x < count; x += 2) { 1162d6040f6f2fcb11fddad5d92b3cb7255e90931bccreed@google.com int n = ptr[0]; 1163d6040f6f2fcb11fddad5d92b3cb7255e90931bccreed@google.com SkASSERT(n > 0); 1164d6040f6f2fcb11fddad5d92b3cb7255e90931bccreed@google.com w += n; 1165e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(w <= fWidth); 1166e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com ptr += 2; 1167e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1168e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(w == fWidth); 1169e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com prevY = row.fY; 1170e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1171e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com#endif 1172e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1173e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1174209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com // only called by BuilderBlitter 1175209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com void setMinY(int y) { 1176209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com fMinY = y; 1177209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com } 1178209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com 1179e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comprivate: 11809154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com void flushRowH(Row* row) { 11819154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com // flush current row if needed 11829154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com if (row->fWidth < fWidth) { 11839154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com AppendRun(*row->fData, 0, fWidth - row->fWidth); 11849154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com row->fWidth = fWidth; 11859154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com } 11869154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com } 1187209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com 1188e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com Row* flushRow(bool readyForAnother) { 118996fcdcc219d2a0d3579719b84b28bede76efba64halcanary Row* next = nullptr; 1190e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int count = fRows.count(); 1191e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (count > 0) { 11929154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com this->flushRowH(&fRows[count - 1]); 1193e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1194e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (count > 1) { 1195e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com // are our last two runs the same? 1196e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com Row* prev = &fRows[count - 2]; 1197e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com Row* curr = &fRows[count - 1]; 1198e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(prev->fWidth == fWidth); 1199e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(curr->fWidth == fWidth); 1200e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (*prev->fData == *curr->fData) { 1201e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com prev->fY = curr->fY; 1202e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (readyForAnother) { 1203e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com curr->fData->rewind(); 1204e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com next = curr; 1205e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } else { 1206e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com delete curr->fData; 1207e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fRows.removeShuffle(count - 1); 1208e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1209e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } else { 1210e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (readyForAnother) { 1211e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com next = fRows.append(); 1212e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com next->fData = new SkTDArray<uint8_t>; 1213e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1214e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1215e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } else { 1216e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (readyForAnother) { 1217e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com next = fRows.append(); 1218e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com next->fData = new SkTDArray<uint8_t>; 1219e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1220e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1221e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return next; 1222e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1223e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1224e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com static void AppendRun(SkTDArray<uint8_t>& data, U8CPU alpha, int count) { 1225e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com do { 1226e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int n = count; 1227e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (n > 255) { 1228e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com n = 255; 1229e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1230e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com uint8_t* ptr = data.append(2); 1231e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com ptr[0] = n; 1232e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com ptr[1] = alpha; 1233e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com count -= n; 1234e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } while (count > 0); 1235e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1236e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}; 1237e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1238e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comclass SkAAClip::BuilderBlitter : public SkBlitter { 123980cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com int fLastY; 124080cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com 124180cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com /* 124280cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com If we see a gap of 1 or more empty scanlines while building in Y-order, 124380cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com we inject an explicit empty scanline (alpha==0) 1244fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 124580cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com See AAClipTest.cpp : test_path_with_hole() 124680cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com */ 124780cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com void checkForYGap(int y) { 124880cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com SkASSERT(y >= fLastY); 124980cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com if (fLastY > -SK_MaxS32) { 125080cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com int gap = y - fLastY; 125180cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com if (gap > 1) { 125280cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com fBuilder->addRun(fLeft, y - 1, 0, fRight - fLeft); 125380cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com } 125480cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com } 125580cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com fLastY = y; 125680cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com } 125780cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com 1258e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.compublic: 125980cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com 1260e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com BuilderBlitter(Builder* builder) { 1261e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fBuilder = builder; 12621778564c75de5799d45126984f8faafd03523100reed@google.com fLeft = builder->getBounds().fLeft; 12631778564c75de5799d45126984f8faafd03523100reed@google.com fRight = builder->getBounds().fRight; 1264209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com fMinY = SK_MaxS32; 126580cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com fLastY = -SK_MaxS32; // sentinel 1266209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com } 1267209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com 1268209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com void finish() { 1269209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com if (fMinY < SK_MaxS32) { 1270209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com fBuilder->setMinY(fMinY); 1271209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com } 1272e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1273e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 127449eac192faa35159752525b23345563252721c64tomhudson@google.com /** 127549eac192faa35159752525b23345563252721c64tomhudson@google.com Must evaluate clips in scan-line order, so don't want to allow blitV(), 127649eac192faa35159752525b23345563252721c64tomhudson@google.com but an AAClip can be clipped down to a single pixel wide, so we 127749eac192faa35159752525b23345563252721c64tomhudson@google.com must support it (given AntiRect semantics: minimum width is 2). 127849eac192faa35159752525b23345563252721c64tomhudson@google.com Instead we'll rely on the runtime asserts to guarantee Y monotonicity; 127949eac192faa35159752525b23345563252721c64tomhudson@google.com any failure cases that misses may have minor artifacts. 128049eac192faa35159752525b23345563252721c64tomhudson@google.com */ 128136352bf5e38f45a70ee4f4fc132a38048d38206dmtklein void blitV(int x, int y, int height, SkAlpha alpha) override { 12822add0ffdaab4c33ca6702c81533c88c7b5ca7294liyuqian if (height == 1) { 12832add0ffdaab4c33ca6702c81533c88c7b5ca7294liyuqian // We're still in scan-line order if height is 1 12842add0ffdaab4c33ca6702c81533c88c7b5ca7294liyuqian // This is useful for Analytic AA 12852add0ffdaab4c33ca6702c81533c88c7b5ca7294liyuqian const SkAlpha alphas[2] = {alpha, 0}; 12862add0ffdaab4c33ca6702c81533c88c7b5ca7294liyuqian const int16_t runs[2] = {1, 0}; 12872add0ffdaab4c33ca6702c81533c88c7b5ca7294liyuqian this->blitAntiH(x, y, alphas, runs); 12882add0ffdaab4c33ca6702c81533c88c7b5ca7294liyuqian } else { 12892add0ffdaab4c33ca6702c81533c88c7b5ca7294liyuqian this->recordMinY(y); 12902add0ffdaab4c33ca6702c81533c88c7b5ca7294liyuqian fBuilder->addColumn(x, y, alpha, height); 12912add0ffdaab4c33ca6702c81533c88c7b5ca7294liyuqian fLastY = y + height - 1; 12922add0ffdaab4c33ca6702c81533c88c7b5ca7294liyuqian } 129349eac192faa35159752525b23345563252721c64tomhudson@google.com } 1294045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 129536352bf5e38f45a70ee4f4fc132a38048d38206dmtklein void blitRect(int x, int y, int width, int height) override { 12969154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com this->recordMinY(y); 129780cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com this->checkForYGap(y); 12989154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com fBuilder->addRectRun(x, y, width, height); 1299302b861338a626014153cc7368c54edbc646cfe5reed@google.com fLastY = y + height - 1; 1300562a2ac95b8cd8b359574f8c4d6300b0475938dbreed@google.com } 1301045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 130249eac192faa35159752525b23345563252721c64tomhudson@google.com virtual void blitAntiRect(int x, int y, int width, int height, 130336352bf5e38f45a70ee4f4fc132a38048d38206dmtklein SkAlpha leftAlpha, SkAlpha rightAlpha) override { 130449eac192faa35159752525b23345563252721c64tomhudson@google.com this->recordMinY(y); 1305302b861338a626014153cc7368c54edbc646cfe5reed@google.com this->checkForYGap(y); 130649eac192faa35159752525b23345563252721c64tomhudson@google.com fBuilder->addAntiRectRun(x, y, width, height, leftAlpha, rightAlpha); 1307302b861338a626014153cc7368c54edbc646cfe5reed@google.com fLastY = y + height - 1; 130849eac192faa35159752525b23345563252721c64tomhudson@google.com } 130949eac192faa35159752525b23345563252721c64tomhudson@google.com 131036352bf5e38f45a70ee4f4fc132a38048d38206dmtklein void blitMask(const SkMask&, const SkIRect& clip) override 1311e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com { unexpected(); } 1312e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 131341e010cb901c0da9066c4df562030808c9ccd7f8reed const SkPixmap* justAnOpaqueColor(uint32_t*) override { 131496fcdcc219d2a0d3579719b84b28bede76efba64halcanary return nullptr; 1315e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1316e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 131736352bf5e38f45a70ee4f4fc132a38048d38206dmtklein void blitH(int x, int y, int width) override { 1318209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com this->recordMinY(y); 131980cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com this->checkForYGap(y); 1320e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fBuilder->addRun(x, y, 0xFF, width); 1321e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1322e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1323e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com virtual void blitAntiH(int x, int y, const SkAlpha alpha[], 132436352bf5e38f45a70ee4f4fc132a38048d38206dmtklein const int16_t runs[]) override { 1325209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com this->recordMinY(y); 132680cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com this->checkForYGap(y); 1327e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com for (;;) { 1328e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int count = *runs; 1329e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (count <= 0) { 1330e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return; 1331e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 13321778564c75de5799d45126984f8faafd03523100reed@google.com 13331778564c75de5799d45126984f8faafd03523100reed@google.com // The supersampler's buffer can be the width of the device, so 13341d3ab12b82e1fa16a0d6b6b9cc1c0290b45cbca9liyuqian // we may have to trim the run to our bounds. Previously, we assert that 13351d3ab12b82e1fa16a0d6b6b9cc1c0290b45cbca9liyuqian // the extra spans are always alpha==0. 13361d3ab12b82e1fa16a0d6b6b9cc1c0290b45cbca9liyuqian // However, the analytic AA is too sensitive to precision errors 13371d3ab12b82e1fa16a0d6b6b9cc1c0290b45cbca9liyuqian // so it may have extra spans with very tiny alpha because after several 13381d3ab12b82e1fa16a0d6b6b9cc1c0290b45cbca9liyuqian // arithmatic operations, the edge may bleed the path boundary a little bit. 13391d3ab12b82e1fa16a0d6b6b9cc1c0290b45cbca9liyuqian // Therefore, instead of always asserting alpha==0, we assert alpha < 0x10. 13401778564c75de5799d45126984f8faafd03523100reed@google.com int localX = x; 13411778564c75de5799d45126984f8faafd03523100reed@google.com int localCount = count; 13421778564c75de5799d45126984f8faafd03523100reed@google.com if (x < fLeft) { 13431d3ab12b82e1fa16a0d6b6b9cc1c0290b45cbca9liyuqian SkASSERT(0x10 > *alpha); 13441778564c75de5799d45126984f8faafd03523100reed@google.com int gap = fLeft - x; 13451778564c75de5799d45126984f8faafd03523100reed@google.com SkASSERT(gap <= count); 13461778564c75de5799d45126984f8faafd03523100reed@google.com localX += gap; 13471778564c75de5799d45126984f8faafd03523100reed@google.com localCount -= gap; 13481778564c75de5799d45126984f8faafd03523100reed@google.com } 13491778564c75de5799d45126984f8faafd03523100reed@google.com int right = x + count; 13501778564c75de5799d45126984f8faafd03523100reed@google.com if (right > fRight) { 13511d3ab12b82e1fa16a0d6b6b9cc1c0290b45cbca9liyuqian SkASSERT(0x10 > *alpha); 13521778564c75de5799d45126984f8faafd03523100reed@google.com localCount -= right - fRight; 13531778564c75de5799d45126984f8faafd03523100reed@google.com SkASSERT(localCount >= 0); 13541778564c75de5799d45126984f8faafd03523100reed@google.com } 1355fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 13561778564c75de5799d45126984f8faafd03523100reed@google.com if (localCount) { 13571778564c75de5799d45126984f8faafd03523100reed@google.com fBuilder->addRun(localX, y, *alpha, localCount); 13581778564c75de5799d45126984f8faafd03523100reed@google.com } 1359820e80ad6390e120d4991a5280d0452ec87beaebbsalomon@google.com // Next run 1360e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com runs += count; 1361e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com alpha += count; 1362e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com x += count; 1363e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1364e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1365e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1366e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comprivate: 1367e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com Builder* fBuilder; 13681778564c75de5799d45126984f8faafd03523100reed@google.com int fLeft; // cache of builder's bounds' left edge 13691778564c75de5799d45126984f8faafd03523100reed@google.com int fRight; 1370209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com int fMinY; 1371209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com 1372209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com /* 1373209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com * We track this, in case the scan converter skipped some number of 1374209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com * scanlines at the (relative to the bounds it was given). This allows 1375209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com * the builder, during its finish, to trip its bounds down to the "real" 1376209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com * top. 1377209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com */ 1378209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com void recordMinY(int y) { 1379209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com if (y < fMinY) { 1380209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com fMinY = y; 1381209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com } 1382209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com } 1383e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1384e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com void unexpected() { 1385e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkDebugf("---- did not expect to get called here"); 1386e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com sk_throw(); 1387e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1388e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}; 1389e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1390f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.combool SkAAClip::setPath(const SkPath& path, const SkRegion* clip, bool doAA) { 1391045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com AUTO_AACLIP_VALIDATE(*this); 1392045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1393322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com if (clip && clip->isEmpty()) { 1394e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return this->setEmpty(); 1395e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1396e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1397e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkIRect ibounds; 1398322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com path.getBounds().roundOut(&ibounds); 1399e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1400322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com SkRegion tmpClip; 140196fcdcc219d2a0d3579719b84b28bede76efba64halcanary if (nullptr == clip) { 1402322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com tmpClip.setRect(ibounds); 1403322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com clip = &tmpClip; 1404322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1405fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1406045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (path.isInverseFillType()) { 1407045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com ibounds = clip->getBounds(); 1408045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } else { 1409322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com if (ibounds.isEmpty() || !ibounds.intersect(clip->getBounds())) { 1410e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return this->setEmpty(); 1411e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1412e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1413e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1414e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com Builder builder(ibounds); 1415e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com BuilderBlitter blitter(&builder); 1416e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1417f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com if (doAA) { 14182add0ffdaab4c33ca6702c81533c88c7b5ca7294liyuqian if (gSkUseAnalyticAA.load()) { 14192add0ffdaab4c33ca6702c81533c88c7b5ca7294liyuqian SkScan::AAAFillPath(path, *clip, &blitter, true); 14202add0ffdaab4c33ca6702c81533c88c7b5ca7294liyuqian } else { 14212add0ffdaab4c33ca6702c81533c88c7b5ca7294liyuqian SkScan::AntiFillPath(path, *clip, &blitter, true); 14222add0ffdaab4c33ca6702c81533c88c7b5ca7294liyuqian } 1423f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com } else { 1424f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com SkScan::FillPath(path, *clip, &blitter); 1425f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com } 1426e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1427209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com blitter.finish(); 1428045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return builder.finish(this); 1429e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 1430e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1431e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com/////////////////////////////////////////////////////////////////////////////// 1432e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1433322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comtypedef void (*RowProc)(SkAAClip::Builder&, int bottom, 1434322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com const uint8_t* rowA, const SkIRect& rectA, 1435322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com const uint8_t* rowB, const SkIRect& rectB); 1436322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1437322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comtypedef U8CPU (*AlphaProc)(U8CPU alphaA, U8CPU alphaB); 1438322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1439322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comstatic U8CPU sectAlphaProc(U8CPU alphaA, U8CPU alphaB) { 1440322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com // Multiply 1441322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return SkMulDiv255Round(alphaA, alphaB); 1442322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com} 1443322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1444322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comstatic U8CPU unionAlphaProc(U8CPU alphaA, U8CPU alphaB) { 1445322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com // SrcOver 1446322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return alphaA + alphaB - SkMulDiv255Round(alphaA, alphaB); 1447322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com} 1448322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1449322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comstatic U8CPU diffAlphaProc(U8CPU alphaA, U8CPU alphaB) { 1450322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com // SrcOut 1451322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return SkMulDiv255Round(alphaA, 0xFF - alphaB); 1452322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com} 1453322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1454322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comstatic U8CPU xorAlphaProc(U8CPU alphaA, U8CPU alphaB) { 1455322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com // XOR 1456322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return alphaA + alphaB - 2 * SkMulDiv255Round(alphaA, alphaB); 1457322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com} 1458322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1459322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comstatic AlphaProc find_alpha_proc(SkRegion::Op op) { 1460322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com switch (op) { 1461322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com case SkRegion::kIntersect_Op: 1462322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return sectAlphaProc; 1463322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com case SkRegion::kDifference_Op: 1464322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return diffAlphaProc; 1465322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com case SkRegion::kUnion_Op: 1466322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return unionAlphaProc; 1467322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com case SkRegion::kXOR_Op: 1468322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return xorAlphaProc; 1469322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com default: 14700c00f21fee3f5cfa3aa7e5d46ff94cb8cf340451tomhudson@google.com SkDEBUGFAIL("unexpected region op"); 1471322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return sectAlphaProc; 1472322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1473322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com} 1474322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1475322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comclass RowIter { 1476322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.compublic: 1477322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com RowIter(const uint8_t* row, const SkIRect& bounds) { 1478322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com fRow = row; 1479322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com fLeft = bounds.fLeft; 1480322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com fBoundsRight = bounds.fRight; 14811c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (row) { 14821c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fRight = bounds.fLeft + row[0]; 14831c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com SkASSERT(fRight <= fBoundsRight); 14841c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fAlpha = row[1]; 14851c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fDone = false; 14861c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } else { 14871c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fDone = true; 14881c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fRight = kMaxInt32; 14891c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fAlpha = 0; 14901c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } 1491322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1492322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1493322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com bool done() const { return fDone; } 14941c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com int left() const { return fLeft; } 14951c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com int right() const { return fRight; } 14961c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com U8CPU alpha() const { return fAlpha; } 1497322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com void next() { 14981c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (!fDone) { 1499322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com fLeft = fRight; 15001c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (fRight == fBoundsRight) { 15011c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fDone = true; 15021c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fRight = kMaxInt32; 15031c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fAlpha = 0; 15041c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } else { 15051c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fRow += 2; 15061c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fRight += fRow[0]; 15071c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fAlpha = fRow[1]; 15081c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com SkASSERT(fRight <= fBoundsRight); 15091c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } 1510322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1511322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1512322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1513322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comprivate: 1514322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com const uint8_t* fRow; 1515322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com int fLeft; 1516322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com int fRight; 1517322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com int fBoundsRight; 1518322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com bool fDone; 15191c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com uint8_t fAlpha; 1520322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com}; 1521322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 15221c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.comstatic void adjust_row(RowIter& iter, int& leftA, int& riteA, int rite) { 15231c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (rite == riteA) { 15241c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com iter.next(); 15251c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com leftA = iter.left(); 15261c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com riteA = iter.right(); 1527322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1528322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com} 1529322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1530803eceb6afd13f07416df0b4a9bb714e9370f081caryclark@google.com#if 0 // UNUSED 15311c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.comstatic bool intersect(int& min, int& max, int boundsMin, int boundsMax) { 15321c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com SkASSERT(min < max); 15331c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com SkASSERT(boundsMin < boundsMax); 15341c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (min >= boundsMax || max <= boundsMin) { 15351c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com return false; 15361c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } 15371c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (min < boundsMin) { 15381c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com min = boundsMin; 15391c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } 15401c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (max > boundsMax) { 15411c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com max = boundsMax; 15421c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } 15431c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com return true; 15441c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com} 1545803eceb6afd13f07416df0b4a9bb714e9370f081caryclark@google.com#endif 15461c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com 1547322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comstatic void operatorX(SkAAClip::Builder& builder, int lastY, 1548322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com RowIter& iterA, RowIter& iterB, 1549322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com AlphaProc proc, const SkIRect& bounds) { 1550322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com int leftA = iterA.left(); 1551322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com int riteA = iterA.right(); 1552322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com int leftB = iterB.left(); 1553322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com int riteB = iterB.right(); 1554322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 15551c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com int prevRite = bounds.fLeft; 15561c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com 15571c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com do { 1558322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com U8CPU alphaA = 0; 1559322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com U8CPU alphaB = 0; 1560322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com int left, rite; 1561fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 15621c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (leftA < leftB) { 1563322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com left = leftA; 1564322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com alphaA = iterA.alpha(); 15651c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (riteA <= leftB) { 15661c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com rite = riteA; 15671c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } else { 15681c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com rite = leftA = leftB; 15691c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } 15701c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } else if (leftB < leftA) { 1571322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com left = leftB; 1572322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com alphaB = iterB.alpha(); 15731c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (riteB <= leftA) { 15741c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com rite = riteB; 15751c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } else { 15761c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com rite = leftB = leftA; 15771c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } 1578322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } else { 15791c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com left = leftA; // or leftB, since leftA == leftB 15801c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com rite = leftA = leftB = SkMin32(riteA, riteB); 1581322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com alphaA = iterA.alpha(); 1582322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com alphaB = iterB.alpha(); 1583322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1584322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1585322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com if (left >= bounds.fRight) { 1586322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com break; 1587322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 158834f7e47a3593911d03307a08e5af625b218ceec3reed@google.com if (rite > bounds.fRight) { 158934f7e47a3593911d03307a08e5af625b218ceec3reed@google.com rite = bounds.fRight; 159034f7e47a3593911d03307a08e5af625b218ceec3reed@google.com } 159134f7e47a3593911d03307a08e5af625b218ceec3reed@google.com 1592322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com if (left >= bounds.fLeft) { 15931c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com SkASSERT(rite > left); 1594322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com builder.addRun(left, lastY, proc(alphaA, alphaB), rite - left); 15951c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com prevRite = rite; 1596322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 15971c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com 15981c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com adjust_row(iterA, leftA, riteA, rite); 15991c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com adjust_row(iterB, leftB, riteB, rite); 16001c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } while (!iterA.done() || !iterB.done()); 16011c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com 16021c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (prevRite < bounds.fRight) { 16031c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com builder.addRun(prevRite, lastY, 0, bounds.fRight - prevRite); 1604322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1605322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com} 1606322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 16071c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.comstatic void adjust_iter(SkAAClip::Iter& iter, int& topA, int& botA, int bot) { 16081c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (bot == botA) { 16091c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com iter.next(); 16101c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com topA = botA; 16111c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com SkASSERT(botA == iter.top()); 16121c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com botA = iter.bottom(); 1613322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1614322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com} 1615322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1616322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comstatic void operateY(SkAAClip::Builder& builder, const SkAAClip& A, 1617322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com const SkAAClip& B, SkRegion::Op op) { 1618322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com AlphaProc proc = find_alpha_proc(op); 1619322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com const SkIRect& bounds = builder.getBounds(); 1620322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1621322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com SkAAClip::Iter iterA(A); 1622322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com SkAAClip::Iter iterB(B); 1623322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1624322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com SkASSERT(!iterA.done()); 1625322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com int topA = iterA.top(); 1626322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com int botA = iterA.bottom(); 1627322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com SkASSERT(!iterB.done()); 1628322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com int topB = iterB.top(); 1629322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com int botB = iterB.bottom(); 1630322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 16311c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com do { 163296fcdcc219d2a0d3579719b84b28bede76efba64halcanary const uint8_t* rowA = nullptr; 163396fcdcc219d2a0d3579719b84b28bede76efba64halcanary const uint8_t* rowB = nullptr; 1634322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com int top, bot; 16351c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com 16361c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (topA < topB) { 1637322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com top = topA; 1638322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com rowA = iterA.data(); 16391c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (botA <= topB) { 16401c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com bot = botA; 16411c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } else { 16421c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com bot = topA = topB; 16431c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } 1644fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 16451c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } else if (topB < topA) { 1646322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com top = topB; 1647322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com rowB = iterB.data(); 16481c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (botB <= topA) { 16491c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com bot = botB; 16501c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } else { 16511c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com bot = topB = topA; 16521c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } 1653322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } else { 16541c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com top = topA; // or topB, since topA == topB 16551c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com bot = topA = topB = SkMin32(botA, botB); 1656322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com rowA = iterA.data(); 1657322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com rowB = iterB.data(); 1658322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1659322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1660322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com if (top >= bounds.fBottom) { 1661322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com break; 1662322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 166334f7e47a3593911d03307a08e5af625b218ceec3reed@google.com 166434f7e47a3593911d03307a08e5af625b218ceec3reed@google.com if (bot > bounds.fBottom) { 166534f7e47a3593911d03307a08e5af625b218ceec3reed@google.com bot = bounds.fBottom; 166634f7e47a3593911d03307a08e5af625b218ceec3reed@google.com } 166734f7e47a3593911d03307a08e5af625b218ceec3reed@google.com SkASSERT(top < bot); 166834f7e47a3593911d03307a08e5af625b218ceec3reed@google.com 16691c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (!rowA && !rowB) { 16701c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com builder.addRun(bounds.fLeft, bot - 1, 0, bounds.width()); 16711c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } else if (top >= bounds.fTop) { 16721c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com SkASSERT(bot <= bounds.fBottom); 16731c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com RowIter rowIterA(rowA, rowA ? A.getBounds() : bounds); 16741c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com RowIter rowIterB(rowB, rowB ? B.getBounds() : bounds); 1675322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com operatorX(builder, bot - 1, rowIterA, rowIterB, proc, bounds); 1676322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1677322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 16781c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com adjust_iter(iterA, topA, botA, bot); 16791c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com adjust_iter(iterB, topB, botB, bot); 16801c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } while (!iterA.done() || !iterB.done()); 1681322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com} 1682322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1683322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.combool SkAAClip::op(const SkAAClip& clipAOrig, const SkAAClip& clipBOrig, 1684322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com SkRegion::Op op) { 1685045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com AUTO_AACLIP_VALIDATE(*this); 1686fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1687322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com if (SkRegion::kReplace_Op == op) { 1688322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return this->set(clipBOrig); 1689322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1690fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1691322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com const SkAAClip* clipA = &clipAOrig; 1692322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com const SkAAClip* clipB = &clipBOrig; 1693fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1694322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com if (SkRegion::kReverseDifference_Op == op) { 1695322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com SkTSwap(clipA, clipB); 1696322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com op = SkRegion::kDifference_Op; 1697322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1698322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1699322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com bool a_empty = clipA->isEmpty(); 1700322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com bool b_empty = clipB->isEmpty(); 1701322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1702322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com SkIRect bounds; 1703322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com switch (op) { 1704322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com case SkRegion::kDifference_Op: 1705322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com if (a_empty) { 1706322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return this->setEmpty(); 1707322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1708322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com if (b_empty || !SkIRect::Intersects(clipA->fBounds, clipB->fBounds)) { 1709322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return this->set(*clipA); 1710322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1711322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com bounds = clipA->fBounds; 1712322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com break; 1713fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1714322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com case SkRegion::kIntersect_Op: 1715322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com if ((a_empty | b_empty) || !bounds.intersect(clipA->fBounds, 1716322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com clipB->fBounds)) { 1717322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return this->setEmpty(); 1718322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1719322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com break; 1720fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1721322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com case SkRegion::kUnion_Op: 1722322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com case SkRegion::kXOR_Op: 1723322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com if (a_empty) { 1724322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return this->set(*clipB); 1725322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1726322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com if (b_empty) { 1727322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return this->set(*clipA); 1728322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1729322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com bounds = clipA->fBounds; 1730322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com bounds.join(clipB->fBounds); 1731322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com break; 1732322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1733322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com default: 17340c00f21fee3f5cfa3aa7e5d46ff94cb8cf340451tomhudson@google.com SkDEBUGFAIL("unknown region op"); 1735322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return !this->isEmpty(); 1736322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1737322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1738322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com SkASSERT(SkIRect::Intersects(bounds, clipB->fBounds)); 1739322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com SkASSERT(SkIRect::Intersects(bounds, clipB->fBounds)); 1740322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1741322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com Builder builder(bounds); 1742322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com operateY(builder, *clipA, *clipB, op); 1743045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1744045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return builder.finish(this); 1745e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 1746e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1747045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com/* 1748045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com * It can be expensive to build a local aaclip before applying the op, so 1749045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com * we first see if we can restrict the bounds of new rect to our current 1750045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com * bounds, or note that the new rect subsumes our current clip. 1751045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com */ 1752045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1753045e62d715f5ee9b03deb5af3c750f8318096179reed@google.combool SkAAClip::op(const SkIRect& rOrig, SkRegion::Op op) { 1754045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkIRect rStorage; 1755045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const SkIRect* r = &rOrig; 1756045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1757045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com switch (op) { 1758045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com case SkRegion::kIntersect_Op: 1759045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (!rStorage.intersect(rOrig, fBounds)) { 1760045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com // no overlap, so we're empty 1761045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return this->setEmpty(); 1762045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1763045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (rStorage == fBounds) { 1764045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com // we were wholly inside the rect, no change 1765045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return !this->isEmpty(); 1766045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1767045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (this->quickContains(rStorage)) { 1768045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com // the intersection is wholly inside us, we're a rect 1769045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return this->setRect(rStorage); 1770045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1771045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com r = &rStorage; // use the intersected bounds 1772045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com break; 1773045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com case SkRegion::kDifference_Op: 1774045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com break; 1775045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com case SkRegion::kUnion_Op: 1776045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (rOrig.contains(fBounds)) { 1777045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return this->setRect(rOrig); 1778045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1779045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com break; 1780045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com default: 1781045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com break; 1782045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1783045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 178447ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com SkAAClip clip; 1785045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com clip.setRect(*r); 178647ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com return this->op(*this, clip, op); 178747ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com} 178847ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com 1789045e62d715f5ee9b03deb5af3c750f8318096179reed@google.combool SkAAClip::op(const SkRect& rOrig, SkRegion::Op op, bool doAA) { 1790045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkRect rStorage, boundsStorage; 1791045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const SkRect* r = &rOrig; 1792fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1793045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com boundsStorage.set(fBounds); 1794045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com switch (op) { 1795045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com case SkRegion::kIntersect_Op: 1796045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com case SkRegion::kDifference_Op: 1797045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (!rStorage.intersect(rOrig, boundsStorage)) { 1798e56513d2a9eebabf93d7824eebf9e64441c485bareed@google.com if (SkRegion::kIntersect_Op == op) { 1799e56513d2a9eebabf93d7824eebf9e64441c485bareed@google.com return this->setEmpty(); 1800e56513d2a9eebabf93d7824eebf9e64441c485bareed@google.com } else { // kDifference 1801e56513d2a9eebabf93d7824eebf9e64441c485bareed@google.com return !this->isEmpty(); 1802e56513d2a9eebabf93d7824eebf9e64441c485bareed@google.com } 1803045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1804045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com r = &rStorage; // use the intersected bounds 1805045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com break; 1806045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com case SkRegion::kUnion_Op: 1807045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (rOrig.contains(boundsStorage)) { 1808045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return this->setRect(rOrig); 1809045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1810045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com break; 1811045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com default: 1812045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com break; 1813045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1814fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 181547ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com SkAAClip clip; 1816045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com clip.setRect(*r, doAA); 181747ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com return this->op(*this, clip, op); 181847ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com} 181947ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com 182047ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.combool SkAAClip::op(const SkAAClip& clip, SkRegion::Op op) { 182147ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com return this->op(*this, clip, op); 182247ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com} 182347ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com 1824e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com/////////////////////////////////////////////////////////////////////////////// 1825045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1826045e62d715f5ee9b03deb5af3c750f8318096179reed@google.combool SkAAClip::translate(int dx, int dy, SkAAClip* dst) const { 182796fcdcc219d2a0d3579719b84b28bede76efba64halcanary if (nullptr == dst) { 1828045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return !this->isEmpty(); 1829045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1830fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1831045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (this->isEmpty()) { 1832045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return dst->setEmpty(); 1833045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1834fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1835045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (this != dst) { 1836045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com sk_atomic_inc(&fRunHead->fRefCnt); 183719224c3d7903921ca86c856cc42adb31fc3164a9tomhudson@google.com dst->freeRuns(); 1838045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com dst->fRunHead = fRunHead; 1839045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com dst->fBounds = fBounds; 1840045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1841045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com dst->fBounds.offset(dx, dy); 1842045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return true; 1843045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com} 1844045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1845045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comstatic void expand_row_to_mask(uint8_t* SK_RESTRICT mask, 1846045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const uint8_t* SK_RESTRICT row, 1847045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com int width) { 1848045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com while (width > 0) { 1849045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com int n = row[0]; 1850045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(width >= n); 1851045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com memset(mask, row[1], n); 1852045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com mask += n; 1853045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com row += 2; 1854045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com width -= n; 1855045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1856a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com SkASSERT(0 == width); 1857045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com} 1858045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1859045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comvoid SkAAClip::copyToMask(SkMask* mask) const { 1860045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com mask->fFormat = SkMask::kA8_Format; 1861045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (this->isEmpty()) { 1862045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com mask->fBounds.setEmpty(); 186396fcdcc219d2a0d3579719b84b28bede76efba64halcanary mask->fImage = nullptr; 1864045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com mask->fRowBytes = 0; 1865045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return; 1866045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1867fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1868045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com mask->fBounds = fBounds; 1869045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com mask->fRowBytes = fBounds.width(); 1870045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com size_t size = mask->computeImageSize(); 1871045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com mask->fImage = SkMask::AllocImage(size); 1872fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1873045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com Iter iter(*this); 1874045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com uint8_t* dst = mask->fImage; 1875045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const int width = fBounds.width(); 1876fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1877045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com int y = fBounds.fTop; 1878045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com while (!iter.done()) { 1879045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com do { 1880045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com expand_row_to_mask(dst, iter.data(), width); 1881045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com dst += mask->fRowBytes; 1882045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } while (++y < iter.bottom()); 1883045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com iter.next(); 1884045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1885045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com} 1886045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1887045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com/////////////////////////////////////////////////////////////////////////////// 1888e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com/////////////////////////////////////////////////////////////////////////////// 1889e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1890e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comstatic void expandToRuns(const uint8_t* SK_RESTRICT data, int initialCount, int width, 1891e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int16_t* SK_RESTRICT runs, SkAlpha* SK_RESTRICT aa) { 1892e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com // we don't read our initial n from data, since the caller may have had to 1893e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com // clip it, hence the initialCount parameter. 1894e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int n = initialCount; 1895e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com for (;;) { 1896e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (n > width) { 1897e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com n = width; 1898e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1899e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(n > 0); 1900e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com runs[0] = n; 1901e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com runs += n; 1902e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1903e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com aa[0] = data[1]; 1904e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com aa += n; 1905fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1906e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com data += 2; 1907e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com width -= n; 1908e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (0 == width) { 1909e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com break; 1910e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1911e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com // load the next count 1912e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com n = data[0]; 1913e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1914e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com runs[0] = 0; // sentinel 1915e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 1916e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1917e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comSkAAClipBlitter::~SkAAClipBlitter() { 1918045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com sk_free(fScanlineScratch); 1919e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 1920e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1921e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comvoid SkAAClipBlitter::ensureRunsAndAA() { 192296fcdcc219d2a0d3579719b84b28bede76efba64halcanary if (nullptr == fScanlineScratch) { 1923e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com // add 1 so we can store the terminating run count of 0 1924e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int count = fAAClipBounds.width() + 1; 1925045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com // we use this either for fRuns + fAA, or a scaline of a mask 1926045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com // which may be as deep as 32bits 1927045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fScanlineScratch = sk_malloc_throw(count * sizeof(SkPMColor)); 1928045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fRuns = (int16_t*)fScanlineScratch; 1929e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fAA = (SkAlpha*)(fRuns + count); 1930e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1931e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 1932e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1933e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comvoid SkAAClipBlitter::blitH(int x, int y, int width) { 1934e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(width > 0); 1935e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(fAAClipBounds.contains(x, y)); 1936e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(fAAClipBounds.contains(x + width - 1, y)); 1937e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1938a4c6e4d6d3a4010df8dd2b04314675e4c201133breed@google.com const uint8_t* row = fAAClip->findRow(y); 1939e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int initialCount; 1940e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com row = fAAClip->findX(row, x, &initialCount); 1941e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1942e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (initialCount >= width) { 1943e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkAlpha alpha = row[1]; 1944e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (0 == alpha) { 1945e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return; 1946e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1947e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (0xFF == alpha) { 1948e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fBlitter->blitH(x, y, width); 1949e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return; 1950e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1951e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1952e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1953e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com this->ensureRunsAndAA(); 1954e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com expandToRuns(row, initialCount, width, fRuns, fAA); 1955e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1956e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fBlitter->blitAntiH(x, y, fAA, fRuns); 1957e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 1958e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1959e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comstatic void merge(const uint8_t* SK_RESTRICT row, int rowN, 1960e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const SkAlpha* SK_RESTRICT srcAA, 1961e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const int16_t* SK_RESTRICT srcRuns, 1962e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkAlpha* SK_RESTRICT dstAA, 1963e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int16_t* SK_RESTRICT dstRuns, 1964e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int width) { 1965e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkDEBUGCODE(int accumulated = 0;) 1966e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int srcN = srcRuns[0]; 1967045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com // do we need this check? 1968045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (0 == srcN) { 1969045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return; 1970045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1971045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1972e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com for (;;) { 1973e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(rowN > 0); 1974e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(srcN > 0); 1975e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1976e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com unsigned newAlpha = SkMulDiv255Round(srcAA[0], row[1]); 1977e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int minN = SkMin32(srcN, rowN); 1978e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com dstRuns[0] = minN; 1979e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com dstRuns += minN; 1980e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com dstAA[0] = newAlpha; 1981e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com dstAA += minN; 1982e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1983e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (0 == (srcN -= minN)) { 1984e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com srcN = srcRuns[0]; // refresh 1985e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com srcRuns += srcN; 1986e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com srcAA += srcN; 1987e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com srcN = srcRuns[0]; // reload 1988045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (0 == srcN) { 1989045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com break; 1990045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1991e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1992e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (0 == (rowN -= minN)) { 1993e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com row += 2; 1994e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com rowN = row[0]; // reload 1995e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1996fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1997e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkDEBUGCODE(accumulated += minN;) 1998e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(accumulated <= width); 1999e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 200034f7e47a3593911d03307a08e5af625b218ceec3reed@google.com dstRuns[0] = 0; 2001e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 2002e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 2003e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comvoid SkAAClipBlitter::blitAntiH(int x, int y, const SkAlpha aa[], 2004e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const int16_t runs[]) { 2005a4c6e4d6d3a4010df8dd2b04314675e4c201133breed@google.com 2006a4c6e4d6d3a4010df8dd2b04314675e4c201133breed@google.com const uint8_t* row = fAAClip->findRow(y); 2007e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int initialCount; 2008e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com row = fAAClip->findX(row, x, &initialCount); 2009e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 2010e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com this->ensureRunsAndAA(); 2011e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 2012e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com merge(row, initialCount, aa, runs, fAA, fRuns, fAAClipBounds.width()); 2013e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fBlitter->blitAntiH(x, y, fAA, fRuns); 2014e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 2015e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 2016e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comvoid SkAAClipBlitter::blitV(int x, int y, int height, SkAlpha alpha) { 2017e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (fAAClip->quickContains(x, y, x + 1, y + height)) { 2018e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fBlitter->blitV(x, y, height, alpha); 2019e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return; 2020e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 2021e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 2022045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com for (;;) { 2023a4c6e4d6d3a4010df8dd2b04314675e4c201133breed@google.com int lastY SK_INIT_TO_AVOID_WARNING; 2024e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const uint8_t* row = fAAClip->findRow(y, &lastY); 2025045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com int dy = lastY - y + 1; 2026045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (dy > height) { 2027045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com dy = height; 2028045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 2029045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com height -= dy; 2030045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 2031a4c6e4d6d3a4010df8dd2b04314675e4c201133breed@google.com row = fAAClip->findX(row, x); 2032e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkAlpha newAlpha = SkMulDiv255Round(alpha, row[1]); 2033e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (newAlpha) { 2034045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fBlitter->blitV(x, y, dy, newAlpha); 2035045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 2036045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(height >= 0); 2037045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (height <= 0) { 2038045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com break; 2039e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 2040e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com y = lastY + 1; 2041045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 2042e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 2043e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 2044e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comvoid SkAAClipBlitter::blitRect(int x, int y, int width, int height) { 2045e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (fAAClip->quickContains(x, y, x + width, y + height)) { 2046e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fBlitter->blitRect(x, y, width, height); 2047e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return; 2048e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 2049e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 2050e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com while (--height >= 0) { 2051e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com this->blitH(x, y, width); 2052e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com y += 1; 2053e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 2054e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 2055e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 2056045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comtypedef void (*MergeAAProc)(const void* src, int width, const uint8_t* row, 2057045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com int initialRowCount, void* dst); 2058045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 2059045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comstatic void small_memcpy(void* dst, const void* src, size_t n) { 2060045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com memcpy(dst, src, n); 2061e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 2062e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 2063045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comstatic void small_bzero(void* dst, size_t n) { 2064045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com sk_bzero(dst, n); 2065e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 2066e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 2067045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comstatic inline uint8_t mergeOne(uint8_t value, unsigned alpha) { 2068045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return SkMulDiv255Round(value, alpha); 2069045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com} 2070d54d3fc82456f8789b3e4dff40faeb7b670bcf4breed 2071045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comstatic inline uint16_t mergeOne(uint16_t value, unsigned alpha) { 2072045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com unsigned r = SkGetPackedR16(value); 2073045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com unsigned g = SkGetPackedG16(value); 2074045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com unsigned b = SkGetPackedB16(value); 2075045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return SkPackRGB16(SkMulDiv255Round(r, alpha), 2076803eceb6afd13f07416df0b4a9bb714e9370f081caryclark@google.com SkMulDiv255Round(g, alpha), 2077803eceb6afd13f07416df0b4a9bb714e9370f081caryclark@google.com SkMulDiv255Round(b, alpha)); 2078045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com} 2079322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 20809449616020a58043a49f0342679bf095918792a6herbtemplate <typename T> 20819449616020a58043a49f0342679bf095918792a6herbvoid mergeT(const void* inSrc, int srcN, const uint8_t* SK_RESTRICT row, int rowN, void* inDst) { 20829449616020a58043a49f0342679bf095918792a6herb const T* SK_RESTRICT src = static_cast<const T*>(inSrc); 20839449616020a58043a49f0342679bf095918792a6herb T* SK_RESTRICT dst = static_cast<T*>(inDst); 2084045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com for (;;) { 2085045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(rowN > 0); 2086045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(srcN > 0); 2087fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 2088045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com int n = SkMin32(rowN, srcN); 2089045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com unsigned rowA = row[1]; 2090045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (0xFF == rowA) { 2091045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com small_memcpy(dst, src, n * sizeof(T)); 2092045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } else if (0 == rowA) { 2093045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com small_bzero(dst, n * sizeof(T)); 2094045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } else { 2095045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com for (int i = 0; i < n; ++i) { 2096045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com dst[i] = mergeOne(src[i], rowA); 2097045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 2098045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 2099fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 2100045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (0 == (srcN -= n)) { 2101045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com break; 2102045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 2103fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 2104045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com src += n; 2105045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com dst += n; 2106fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 2107045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(rowN == n); 2108045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com row += 2; 2109045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com rowN = row[0]; 21101c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } 2111045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com} 21121c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com 2113045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comstatic MergeAAProc find_merge_aa_proc(SkMask::Format format) { 2114045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com switch (format) { 2115045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com case SkMask::kBW_Format: 21160c00f21fee3f5cfa3aa7e5d46ff94cb8cf340451tomhudson@google.com SkDEBUGFAIL("unsupported"); 211796fcdcc219d2a0d3579719b84b28bede76efba64halcanary return nullptr; 2118045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com case SkMask::kA8_Format: 21199449616020a58043a49f0342679bf095918792a6herb case SkMask::k3D_Format: 21209449616020a58043a49f0342679bf095918792a6herb return mergeT<uint8_t> ; 21219449616020a58043a49f0342679bf095918792a6herb case SkMask::kLCD16_Format: 21229449616020a58043a49f0342679bf095918792a6herb return mergeT<uint16_t>; 2123045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com default: 21240c00f21fee3f5cfa3aa7e5d46ff94cb8cf340451tomhudson@google.com SkDEBUGFAIL("unsupported"); 212596fcdcc219d2a0d3579719b84b28bede76efba64halcanary return nullptr; 21261c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } 2127045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com} 21281c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com 2129045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comstatic U8CPU bit2byte(int bitInAByte) { 2130045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(bitInAByte <= 0xFF); 2131045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com // negation turns any non-zero into 0xFFFFFF??, so we just shift down 2132045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com // some value >= 8 to get a full FF value 2133045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return -bitInAByte >> 8; 21341c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com} 21351c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com 2136045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comstatic void upscaleBW2A8(SkMask* dstMask, const SkMask& srcMask) { 2137045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(SkMask::kBW_Format == srcMask.fFormat); 2138045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(SkMask::kA8_Format == dstMask->fFormat); 2139045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 2140045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const int width = srcMask.fBounds.width(); 2141045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const int height = srcMask.fBounds.height(); 2142045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 2143045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const uint8_t* SK_RESTRICT src = (const uint8_t*)srcMask.fImage; 2144045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const size_t srcRB = srcMask.fRowBytes; 2145045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com uint8_t* SK_RESTRICT dst = (uint8_t*)dstMask->fImage; 2146045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const size_t dstRB = dstMask->fRowBytes; 2147045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 2148045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const int wholeBytes = width >> 3; 2149045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const int leftOverBits = width & 7; 2150045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 2151045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com for (int y = 0; y < height; ++y) { 2152045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com uint8_t* SK_RESTRICT d = dst; 2153045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com for (int i = 0; i < wholeBytes; ++i) { 2154045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com int srcByte = src[i]; 2155045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com d[0] = bit2byte(srcByte & (1 << 7)); 2156045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com d[1] = bit2byte(srcByte & (1 << 6)); 2157045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com d[2] = bit2byte(srcByte & (1 << 5)); 2158045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com d[3] = bit2byte(srcByte & (1 << 4)); 2159045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com d[4] = bit2byte(srcByte & (1 << 3)); 2160045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com d[5] = bit2byte(srcByte & (1 << 2)); 2161045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com d[6] = bit2byte(srcByte & (1 << 1)); 2162045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com d[7] = bit2byte(srcByte & (1 << 0)); 2163045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com d += 8; 2164045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 2165045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (leftOverBits) { 2166045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com int srcByte = src[wholeBytes]; 2167045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com for (int x = 0; x < leftOverBits; ++x) { 2168045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com *d++ = bit2byte(srcByte & 0x80); 2169045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com srcByte <<= 1; 2170045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 2171045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 2172045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com src += srcRB; 2173045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com dst += dstRB; 2174322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 2175322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com} 2176322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 2177045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comvoid SkAAClipBlitter::blitMask(const SkMask& origMask, const SkIRect& clip) { 2178045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(fAAClip->getBounds().contains(clip)); 2179045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 2180045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (fAAClip->quickContains(clip)) { 2181045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fBlitter->blitMask(origMask, clip); 2182322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return; 2183322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 2184322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 2185045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const SkMask* mask = &origMask; 2186322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 2187045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com // if we're BW, we need to upscale to A8 (ugh) 2188045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkMask grayMask; 2189045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (SkMask::kBW_Format == origMask.fFormat) { 2190045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com grayMask.fFormat = SkMask::kA8_Format; 2191045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com grayMask.fBounds = origMask.fBounds; 2192045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com grayMask.fRowBytes = origMask.fBounds.width(); 2193045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com size_t size = grayMask.computeImageSize(); 2194045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com grayMask.fImage = (uint8_t*)fGrayMaskScratch.reset(size, 2195045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkAutoMalloc::kReuse_OnShrink); 2196322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 2197045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com upscaleBW2A8(&grayMask, origMask); 2198045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com mask = &grayMask; 2199322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 2200045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 2201045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com this->ensureRunsAndAA(); 2202045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 2203045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com // HACK -- we are devolving 3D into A8, need to copy the rest of the 3D 2204045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com // data into a temp block to support it better (ugh) 2205045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 2206045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const void* src = mask->getAddr(clip.fLeft, clip.fTop); 2207045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const size_t srcRB = mask->fRowBytes; 2208045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const int width = clip.width(); 2209045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com MergeAAProc mergeProc = find_merge_aa_proc(mask->fFormat); 2210045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 2211045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkMask rowMask; 2212045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com rowMask.fFormat = SkMask::k3D_Format == mask->fFormat ? SkMask::kA8_Format : mask->fFormat; 2213045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com rowMask.fBounds.fLeft = clip.fLeft; 2214045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com rowMask.fBounds.fRight = clip.fRight; 2215045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com rowMask.fRowBytes = mask->fRowBytes; // doesn't matter, since our height==1 2216045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com rowMask.fImage = (uint8_t*)fScanlineScratch; 2217045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 2218045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com int y = clip.fTop; 2219045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const int stopY = y + clip.height(); 2220045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 2221045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com do { 2222a4c6e4d6d3a4010df8dd2b04314675e4c201133breed@google.com int localStopY SK_INIT_TO_AVOID_WARNING; 2223045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const uint8_t* row = fAAClip->findRow(y, &localStopY); 2224045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com // findRow returns last Y, not stop, so we add 1 2225045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com localStopY = SkMin32(localStopY + 1, stopY); 2226045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 2227045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com int initialCount; 2228045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com row = fAAClip->findX(row, clip.fLeft, &initialCount); 2229045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com do { 2230045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com mergeProc(src, width, row, initialCount, rowMask.fImage); 2231045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com rowMask.fBounds.fTop = y; 2232045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com rowMask.fBounds.fBottom = y + 1; 2233045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fBlitter->blitMask(rowMask, rowMask.fBounds); 2234045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com src = (const void*)((const char*)src + srcRB); 2235045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } while (++y < localStopY); 2236045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } while (y < stopY); 2237045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com} 2238045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 223941e010cb901c0da9066c4df562030808c9ccd7f8reedconst SkPixmap* SkAAClipBlitter::justAnOpaqueColor(uint32_t* value) { 224096fcdcc219d2a0d3579719b84b28bede76efba64halcanary return nullptr; 2241322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com} 2242