SkAAClip.cpp revision d7ec12e41cce090ec0b2e68e995ea511d33c9967
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) { 104049eac192faa35159752525b23345563252721c64tomhudson@google.com SkASSERT(fBounds.contains(x + width - 1 + 104149eac192faa35159752525b23345563252721c64tomhudson@google.com (leftAlpha > 0 ? 1 : 0) + (rightAlpha > 0 ? 1 : 0), 104249eac192faa35159752525b23345563252721c64tomhudson@google.com y + height - 1)); 104349eac192faa35159752525b23345563252721c64tomhudson@google.com SkASSERT(width >= 0); 104449eac192faa35159752525b23345563252721c64tomhudson@google.com 104549eac192faa35159752525b23345563252721c64tomhudson@google.com // Conceptually we're always adding 3 runs, but we should 104649eac192faa35159752525b23345563252721c64tomhudson@google.com // merge or omit them if possible. 104749eac192faa35159752525b23345563252721c64tomhudson@google.com if (leftAlpha == 0xFF) { 104849eac192faa35159752525b23345563252721c64tomhudson@google.com width++; 104949eac192faa35159752525b23345563252721c64tomhudson@google.com } else if (leftAlpha > 0) { 105049eac192faa35159752525b23345563252721c64tomhudson@google.com this->addRun(x++, y, leftAlpha, 1); 105149eac192faa35159752525b23345563252721c64tomhudson@google.com } 105249eac192faa35159752525b23345563252721c64tomhudson@google.com if (rightAlpha == 0xFF) { 105349eac192faa35159752525b23345563252721c64tomhudson@google.com width++; 105449eac192faa35159752525b23345563252721c64tomhudson@google.com } 105549eac192faa35159752525b23345563252721c64tomhudson@google.com if (width > 0) { 105649eac192faa35159752525b23345563252721c64tomhudson@google.com this->addRun(x, y, 0xFF, width); 105749eac192faa35159752525b23345563252721c64tomhudson@google.com } 105849eac192faa35159752525b23345563252721c64tomhudson@google.com if (rightAlpha > 0 && rightAlpha < 255) { 105949eac192faa35159752525b23345563252721c64tomhudson@google.com this->addRun(x + width, y, rightAlpha, 1); 106049eac192faa35159752525b23345563252721c64tomhudson@google.com } 106149eac192faa35159752525b23345563252721c64tomhudson@google.com 106249eac192faa35159752525b23345563252721c64tomhudson@google.com // we assume the rect must be all we'll see for these scanlines 106349eac192faa35159752525b23345563252721c64tomhudson@google.com // so we ensure our row goes all the way to our right 106449eac192faa35159752525b23345563252721c64tomhudson@google.com this->flushRowH(fCurrRow); 106549eac192faa35159752525b23345563252721c64tomhudson@google.com 106649eac192faa35159752525b23345563252721c64tomhudson@google.com y -= fBounds.fTop; 106749eac192faa35159752525b23345563252721c64tomhudson@google.com SkASSERT(y == fCurrRow->fY); 106849eac192faa35159752525b23345563252721c64tomhudson@google.com fCurrRow->fY = y + height - 1; 106949eac192faa35159752525b23345563252721c64tomhudson@google.com } 107049eac192faa35159752525b23345563252721c64tomhudson@google.com 1071045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com bool finish(SkAAClip* target) { 1072e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com this->flushRow(false); 1073e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1074e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const Row* row = fRows.begin(); 1075e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const Row* stop = fRows.end(); 1076e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1077fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com size_t dataSize = 0; 1078e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com while (row < stop) { 1079e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com dataSize += row->fData->count(); 1080e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com row += 1; 1081e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1082e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1083045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (0 == dataSize) { 1084045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return target->setEmpty(); 1085045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1086045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1087209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com SkASSERT(fMinY >= fBounds.fTop); 1088209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com SkASSERT(fMinY < fBounds.fBottom); 1089209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com int adjustY = fMinY - fBounds.fTop; 1090209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com fBounds.fTop = fMinY; 1091209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com 1092e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com RunHead* head = RunHead::Alloc(fRows.count(), dataSize); 1093e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com YOffset* yoffset = head->yoffsets(); 1094e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com uint8_t* data = head->data(); 1095e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com uint8_t* baseData = data; 1096e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1097e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com row = fRows.begin(); 1098c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkDEBUGCODE(int prevY = row->fY - 1;) 1099e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com while (row < stop) { 1100c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(prevY < row->fY); // must be monotonic 1101c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkDEBUGCODE(prevY = row->fY); 1102c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 1103209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com yoffset->fY = row->fY - adjustY; 1104a8c7f7702fb4bbedb615031bc653c5cd161a038ecommit-bot@chromium.org yoffset->fOffset = SkToU32(data - baseData); 1105e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com yoffset += 1; 1106fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1107e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com size_t n = row->fData->count(); 1108e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com memcpy(data, row->fData->begin(), n); 1109c90419199525141a5b98091f856e359bf9daf5b1reed@google.com#ifdef SK_DEBUG 1110f74ad8c91aef4f328dbcbcebae9e436c00a35140tomhudson@google.com size_t bytesNeeded = compute_row_length(data, fBounds.width()); 1111c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(bytesNeeded == n); 1112c90419199525141a5b98091f856e359bf9daf5b1reed@google.com#endif 1113e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com data += n; 1114fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1115e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com row += 1; 1116e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1117e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1118045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com target->freeRuns(); 1119045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com target->fBounds = fBounds; 1120045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com target->fRunHead = head; 1121045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return target->trimBounds(); 1122e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1123e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1124e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com void dump() { 1125e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com this->validate(); 1126e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int y; 1127e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com for (y = 0; y < fRows.count(); ++y) { 1128e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const Row& row = fRows[y]; 1129e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkDebugf("Y:%3d W:%3d", row.fY, row.fWidth); 1130e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const SkTDArray<uint8_t>& data = *row.fData; 1131e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int count = data.count(); 1132e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(!(count & 1)); 1133e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const uint8_t* ptr = data.begin(); 1134e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com for (int x = 0; x < count; x += 2) { 1135e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkDebugf(" [%3d:%02X]", ptr[0], ptr[1]); 1136e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com ptr += 2; 1137e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1138e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkDebugf("\n"); 1139e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1140e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1141e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1142e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com void validate() { 1143e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com#ifdef SK_DEBUG 1144803eceb6afd13f07416df0b4a9bb714e9370f081caryclark@google.com if (false) { // avoid bit rot, suppress warning 1145803eceb6afd13f07416df0b4a9bb714e9370f081caryclark@google.com test_count_left_right_zeros(); 1146803eceb6afd13f07416df0b4a9bb714e9370f081caryclark@google.com } 1147e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int prevY = -1; 1148e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com for (int i = 0; i < fRows.count(); ++i) { 1149e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const Row& row = fRows[i]; 1150e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(prevY < row.fY); 1151e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(fWidth == row.fWidth); 1152e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int count = row.fData->count(); 1153e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const uint8_t* ptr = row.fData->begin(); 1154e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(!(count & 1)); 1155e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int w = 0; 1156e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com for (int x = 0; x < count; x += 2) { 1157d6040f6f2fcb11fddad5d92b3cb7255e90931bccreed@google.com int n = ptr[0]; 1158d6040f6f2fcb11fddad5d92b3cb7255e90931bccreed@google.com SkASSERT(n > 0); 1159d6040f6f2fcb11fddad5d92b3cb7255e90931bccreed@google.com w += n; 1160e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(w <= fWidth); 1161e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com ptr += 2; 1162e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1163e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(w == fWidth); 1164e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com prevY = row.fY; 1165e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1166e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com#endif 1167e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1168e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1169209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com // only called by BuilderBlitter 1170209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com void setMinY(int y) { 1171209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com fMinY = y; 1172209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com } 1173209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com 1174e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comprivate: 11759154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com void flushRowH(Row* row) { 11769154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com // flush current row if needed 11779154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com if (row->fWidth < fWidth) { 11789154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com AppendRun(*row->fData, 0, fWidth - row->fWidth); 11799154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com row->fWidth = fWidth; 11809154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com } 11819154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com } 1182209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com 1183e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com Row* flushRow(bool readyForAnother) { 118496fcdcc219d2a0d3579719b84b28bede76efba64halcanary Row* next = nullptr; 1185e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int count = fRows.count(); 1186e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (count > 0) { 11879154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com this->flushRowH(&fRows[count - 1]); 1188e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1189e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (count > 1) { 1190e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com // are our last two runs the same? 1191e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com Row* prev = &fRows[count - 2]; 1192e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com Row* curr = &fRows[count - 1]; 1193e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(prev->fWidth == fWidth); 1194e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(curr->fWidth == fWidth); 1195e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (*prev->fData == *curr->fData) { 1196e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com prev->fY = curr->fY; 1197e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (readyForAnother) { 1198e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com curr->fData->rewind(); 1199e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com next = curr; 1200e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } else { 1201e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com delete curr->fData; 1202e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fRows.removeShuffle(count - 1); 1203e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1204e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } else { 1205e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (readyForAnother) { 1206e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com next = fRows.append(); 1207e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com next->fData = new SkTDArray<uint8_t>; 1208e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1209e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1210e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } else { 1211e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (readyForAnother) { 1212e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com next = fRows.append(); 1213e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com next->fData = new SkTDArray<uint8_t>; 1214e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1215e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1216e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return next; 1217e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1218e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1219e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com static void AppendRun(SkTDArray<uint8_t>& data, U8CPU alpha, int count) { 1220e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com do { 1221e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int n = count; 1222e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (n > 255) { 1223e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com n = 255; 1224e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1225e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com uint8_t* ptr = data.append(2); 1226e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com ptr[0] = n; 1227e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com ptr[1] = alpha; 1228e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com count -= n; 1229e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } while (count > 0); 1230e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1231e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}; 1232e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1233e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comclass SkAAClip::BuilderBlitter : public SkBlitter { 123480cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com int fLastY; 123580cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com 123680cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com /* 123780cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com If we see a gap of 1 or more empty scanlines while building in Y-order, 123880cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com we inject an explicit empty scanline (alpha==0) 1239fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 124080cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com See AAClipTest.cpp : test_path_with_hole() 124180cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com */ 124280cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com void checkForYGap(int y) { 124380cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com SkASSERT(y >= fLastY); 124480cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com if (fLastY > -SK_MaxS32) { 124580cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com int gap = y - fLastY; 124680cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com if (gap > 1) { 124780cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com fBuilder->addRun(fLeft, y - 1, 0, fRight - fLeft); 124880cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com } 124980cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com } 125080cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com fLastY = y; 125180cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com } 125280cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com 1253e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.compublic: 125480cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com 1255e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com BuilderBlitter(Builder* builder) { 1256e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fBuilder = builder; 12571778564c75de5799d45126984f8faafd03523100reed@google.com fLeft = builder->getBounds().fLeft; 12581778564c75de5799d45126984f8faafd03523100reed@google.com fRight = builder->getBounds().fRight; 1259209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com fMinY = SK_MaxS32; 126080cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com fLastY = -SK_MaxS32; // sentinel 1261209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com } 1262209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com 1263209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com void finish() { 1264209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com if (fMinY < SK_MaxS32) { 1265209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com fBuilder->setMinY(fMinY); 1266209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com } 1267e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1268e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 126949eac192faa35159752525b23345563252721c64tomhudson@google.com /** 127049eac192faa35159752525b23345563252721c64tomhudson@google.com Must evaluate clips in scan-line order, so don't want to allow blitV(), 127149eac192faa35159752525b23345563252721c64tomhudson@google.com but an AAClip can be clipped down to a single pixel wide, so we 127249eac192faa35159752525b23345563252721c64tomhudson@google.com must support it (given AntiRect semantics: minimum width is 2). 127349eac192faa35159752525b23345563252721c64tomhudson@google.com Instead we'll rely on the runtime asserts to guarantee Y monotonicity; 127449eac192faa35159752525b23345563252721c64tomhudson@google.com any failure cases that misses may have minor artifacts. 127549eac192faa35159752525b23345563252721c64tomhudson@google.com */ 127636352bf5e38f45a70ee4f4fc132a38048d38206dmtklein void blitV(int x, int y, int height, SkAlpha alpha) override { 127749eac192faa35159752525b23345563252721c64tomhudson@google.com this->recordMinY(y); 127849eac192faa35159752525b23345563252721c64tomhudson@google.com fBuilder->addColumn(x, y, alpha, height); 12799b0da23f0af145ffd9795b4b55b9527ac050d0b0reed@google.com fLastY = y + height - 1; 128049eac192faa35159752525b23345563252721c64tomhudson@google.com } 1281045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 128236352bf5e38f45a70ee4f4fc132a38048d38206dmtklein void blitRect(int x, int y, int width, int height) override { 12839154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com this->recordMinY(y); 128480cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com this->checkForYGap(y); 12859154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com fBuilder->addRectRun(x, y, width, height); 1286302b861338a626014153cc7368c54edbc646cfe5reed@google.com fLastY = y + height - 1; 1287562a2ac95b8cd8b359574f8c4d6300b0475938dbreed@google.com } 1288045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 128949eac192faa35159752525b23345563252721c64tomhudson@google.com virtual void blitAntiRect(int x, int y, int width, int height, 129036352bf5e38f45a70ee4f4fc132a38048d38206dmtklein SkAlpha leftAlpha, SkAlpha rightAlpha) override { 129149eac192faa35159752525b23345563252721c64tomhudson@google.com this->recordMinY(y); 1292302b861338a626014153cc7368c54edbc646cfe5reed@google.com this->checkForYGap(y); 129349eac192faa35159752525b23345563252721c64tomhudson@google.com fBuilder->addAntiRectRun(x, y, width, height, leftAlpha, rightAlpha); 1294302b861338a626014153cc7368c54edbc646cfe5reed@google.com fLastY = y + height - 1; 129549eac192faa35159752525b23345563252721c64tomhudson@google.com } 129649eac192faa35159752525b23345563252721c64tomhudson@google.com 129736352bf5e38f45a70ee4f4fc132a38048d38206dmtklein void blitMask(const SkMask&, const SkIRect& clip) override 1298e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com { unexpected(); } 1299e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 130041e010cb901c0da9066c4df562030808c9ccd7f8reed const SkPixmap* justAnOpaqueColor(uint32_t*) override { 130196fcdcc219d2a0d3579719b84b28bede76efba64halcanary return nullptr; 1302e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1303e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 130436352bf5e38f45a70ee4f4fc132a38048d38206dmtklein void blitH(int x, int y, int width) override { 1305209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com this->recordMinY(y); 130680cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com this->checkForYGap(y); 1307e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fBuilder->addRun(x, y, 0xFF, width); 1308e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1309e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1310e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com virtual void blitAntiH(int x, int y, const SkAlpha alpha[], 131136352bf5e38f45a70ee4f4fc132a38048d38206dmtklein const int16_t runs[]) override { 1312209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com this->recordMinY(y); 131380cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com this->checkForYGap(y); 1314e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com for (;;) { 1315e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int count = *runs; 1316e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (count <= 0) { 1317e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return; 1318e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 13191778564c75de5799d45126984f8faafd03523100reed@google.com 13201778564c75de5799d45126984f8faafd03523100reed@google.com // The supersampler's buffer can be the width of the device, so 13211778564c75de5799d45126984f8faafd03523100reed@google.com // we may have to trim the run to our bounds. If so, we assert that 13221778564c75de5799d45126984f8faafd03523100reed@google.com // the extra spans are always alpha==0 13231778564c75de5799d45126984f8faafd03523100reed@google.com int localX = x; 13241778564c75de5799d45126984f8faafd03523100reed@google.com int localCount = count; 13251778564c75de5799d45126984f8faafd03523100reed@google.com if (x < fLeft) { 13261778564c75de5799d45126984f8faafd03523100reed@google.com SkASSERT(0 == *alpha); 13271778564c75de5799d45126984f8faafd03523100reed@google.com int gap = fLeft - x; 13281778564c75de5799d45126984f8faafd03523100reed@google.com SkASSERT(gap <= count); 13291778564c75de5799d45126984f8faafd03523100reed@google.com localX += gap; 13301778564c75de5799d45126984f8faafd03523100reed@google.com localCount -= gap; 13311778564c75de5799d45126984f8faafd03523100reed@google.com } 13321778564c75de5799d45126984f8faafd03523100reed@google.com int right = x + count; 13331778564c75de5799d45126984f8faafd03523100reed@google.com if (right > fRight) { 13341778564c75de5799d45126984f8faafd03523100reed@google.com SkASSERT(0 == *alpha); 13351778564c75de5799d45126984f8faafd03523100reed@google.com localCount -= right - fRight; 13361778564c75de5799d45126984f8faafd03523100reed@google.com SkASSERT(localCount >= 0); 13371778564c75de5799d45126984f8faafd03523100reed@google.com } 1338fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 13391778564c75de5799d45126984f8faafd03523100reed@google.com if (localCount) { 13401778564c75de5799d45126984f8faafd03523100reed@google.com fBuilder->addRun(localX, y, *alpha, localCount); 13411778564c75de5799d45126984f8faafd03523100reed@google.com } 1342820e80ad6390e120d4991a5280d0452ec87beaebbsalomon@google.com // Next run 1343e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com runs += count; 1344e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com alpha += count; 1345e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com x += count; 1346e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1347e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1348e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1349e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comprivate: 1350e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com Builder* fBuilder; 13511778564c75de5799d45126984f8faafd03523100reed@google.com int fLeft; // cache of builder's bounds' left edge 13521778564c75de5799d45126984f8faafd03523100reed@google.com int fRight; 1353209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com int fMinY; 1354209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com 1355209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com /* 1356209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com * We track this, in case the scan converter skipped some number of 1357209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com * scanlines at the (relative to the bounds it was given). This allows 1358209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com * the builder, during its finish, to trip its bounds down to the "real" 1359209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com * top. 1360209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com */ 1361209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com void recordMinY(int y) { 1362209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com if (y < fMinY) { 1363209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com fMinY = y; 1364209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com } 1365209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com } 1366e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1367e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com void unexpected() { 1368e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkDebugf("---- did not expect to get called here"); 1369e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com sk_throw(); 1370e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1371e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}; 1372e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1373f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.combool SkAAClip::setPath(const SkPath& path, const SkRegion* clip, bool doAA) { 1374045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com AUTO_AACLIP_VALIDATE(*this); 1375045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1376322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com if (clip && clip->isEmpty()) { 1377e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return this->setEmpty(); 1378e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1379e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1380e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkIRect ibounds; 1381322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com path.getBounds().roundOut(&ibounds); 1382e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1383322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com SkRegion tmpClip; 138496fcdcc219d2a0d3579719b84b28bede76efba64halcanary if (nullptr == clip) { 1385322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com tmpClip.setRect(ibounds); 1386322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com clip = &tmpClip; 1387322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1388fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1389045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (path.isInverseFillType()) { 1390045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com ibounds = clip->getBounds(); 1391045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } else { 1392322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com if (ibounds.isEmpty() || !ibounds.intersect(clip->getBounds())) { 1393e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return this->setEmpty(); 1394e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1395e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1396e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1397e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com Builder builder(ibounds); 1398e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com BuilderBlitter blitter(&builder); 1399e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1400f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com if (doAA) { 1401f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com SkScan::AntiFillPath(path, *clip, &blitter, true); 1402f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com } else { 1403f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com SkScan::FillPath(path, *clip, &blitter); 1404f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com } 1405e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1406209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com blitter.finish(); 1407045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return builder.finish(this); 1408e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 1409e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1410e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com/////////////////////////////////////////////////////////////////////////////// 1411e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1412322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comtypedef void (*RowProc)(SkAAClip::Builder&, int bottom, 1413322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com const uint8_t* rowA, const SkIRect& rectA, 1414322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com const uint8_t* rowB, const SkIRect& rectB); 1415322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1416322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comtypedef U8CPU (*AlphaProc)(U8CPU alphaA, U8CPU alphaB); 1417322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1418322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comstatic U8CPU sectAlphaProc(U8CPU alphaA, U8CPU alphaB) { 1419322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com // Multiply 1420322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return SkMulDiv255Round(alphaA, alphaB); 1421322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com} 1422322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1423322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comstatic U8CPU unionAlphaProc(U8CPU alphaA, U8CPU alphaB) { 1424322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com // SrcOver 1425322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return alphaA + alphaB - SkMulDiv255Round(alphaA, alphaB); 1426322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com} 1427322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1428322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comstatic U8CPU diffAlphaProc(U8CPU alphaA, U8CPU alphaB) { 1429322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com // SrcOut 1430322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return SkMulDiv255Round(alphaA, 0xFF - alphaB); 1431322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com} 1432322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1433322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comstatic U8CPU xorAlphaProc(U8CPU alphaA, U8CPU alphaB) { 1434322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com // XOR 1435322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return alphaA + alphaB - 2 * SkMulDiv255Round(alphaA, alphaB); 1436322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com} 1437322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1438322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comstatic AlphaProc find_alpha_proc(SkRegion::Op op) { 1439322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com switch (op) { 1440322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com case SkRegion::kIntersect_Op: 1441322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return sectAlphaProc; 1442322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com case SkRegion::kDifference_Op: 1443322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return diffAlphaProc; 1444322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com case SkRegion::kUnion_Op: 1445322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return unionAlphaProc; 1446322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com case SkRegion::kXOR_Op: 1447322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return xorAlphaProc; 1448322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com default: 14490c00f21fee3f5cfa3aa7e5d46ff94cb8cf340451tomhudson@google.com SkDEBUGFAIL("unexpected region op"); 1450322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return sectAlphaProc; 1451322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1452322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com} 1453322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1454322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comclass RowIter { 1455322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.compublic: 1456322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com RowIter(const uint8_t* row, const SkIRect& bounds) { 1457322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com fRow = row; 1458322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com fLeft = bounds.fLeft; 1459322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com fBoundsRight = bounds.fRight; 14601c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (row) { 14611c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fRight = bounds.fLeft + row[0]; 14621c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com SkASSERT(fRight <= fBoundsRight); 14631c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fAlpha = row[1]; 14641c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fDone = false; 14651c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } else { 14661c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fDone = true; 14671c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fRight = kMaxInt32; 14681c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fAlpha = 0; 14691c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } 1470322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1471322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1472322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com bool done() const { return fDone; } 14731c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com int left() const { return fLeft; } 14741c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com int right() const { return fRight; } 14751c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com U8CPU alpha() const { return fAlpha; } 1476322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com void next() { 14771c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (!fDone) { 1478322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com fLeft = fRight; 14791c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (fRight == fBoundsRight) { 14801c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fDone = true; 14811c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fRight = kMaxInt32; 14821c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fAlpha = 0; 14831c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } else { 14841c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fRow += 2; 14851c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fRight += fRow[0]; 14861c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fAlpha = fRow[1]; 14871c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com SkASSERT(fRight <= fBoundsRight); 14881c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } 1489322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1490322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1491322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1492322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comprivate: 1493322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com const uint8_t* fRow; 1494322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com int fLeft; 1495322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com int fRight; 1496322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com int fBoundsRight; 1497322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com bool fDone; 14981c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com uint8_t fAlpha; 1499322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com}; 1500322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 15011c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.comstatic void adjust_row(RowIter& iter, int& leftA, int& riteA, int rite) { 15021c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (rite == riteA) { 15031c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com iter.next(); 15041c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com leftA = iter.left(); 15051c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com riteA = iter.right(); 1506322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1507322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com} 1508322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1509803eceb6afd13f07416df0b4a9bb714e9370f081caryclark@google.com#if 0 // UNUSED 15101c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.comstatic bool intersect(int& min, int& max, int boundsMin, int boundsMax) { 15111c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com SkASSERT(min < max); 15121c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com SkASSERT(boundsMin < boundsMax); 15131c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (min >= boundsMax || max <= boundsMin) { 15141c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com return false; 15151c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } 15161c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (min < boundsMin) { 15171c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com min = boundsMin; 15181c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } 15191c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (max > boundsMax) { 15201c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com max = boundsMax; 15211c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } 15221c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com return true; 15231c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com} 1524803eceb6afd13f07416df0b4a9bb714e9370f081caryclark@google.com#endif 15251c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com 1526322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comstatic void operatorX(SkAAClip::Builder& builder, int lastY, 1527322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com RowIter& iterA, RowIter& iterB, 1528322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com AlphaProc proc, const SkIRect& bounds) { 1529322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com int leftA = iterA.left(); 1530322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com int riteA = iterA.right(); 1531322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com int leftB = iterB.left(); 1532322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com int riteB = iterB.right(); 1533322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 15341c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com int prevRite = bounds.fLeft; 15351c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com 15361c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com do { 1537322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com U8CPU alphaA = 0; 1538322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com U8CPU alphaB = 0; 1539322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com int left, rite; 1540fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 15411c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (leftA < leftB) { 1542322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com left = leftA; 1543322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com alphaA = iterA.alpha(); 15441c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (riteA <= leftB) { 15451c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com rite = riteA; 15461c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } else { 15471c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com rite = leftA = leftB; 15481c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } 15491c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } else if (leftB < leftA) { 1550322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com left = leftB; 1551322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com alphaB = iterB.alpha(); 15521c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (riteB <= leftA) { 15531c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com rite = riteB; 15541c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } else { 15551c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com rite = leftB = leftA; 15561c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } 1557322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } else { 15581c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com left = leftA; // or leftB, since leftA == leftB 15591c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com rite = leftA = leftB = SkMin32(riteA, riteB); 1560322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com alphaA = iterA.alpha(); 1561322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com alphaB = iterB.alpha(); 1562322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1563322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1564322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com if (left >= bounds.fRight) { 1565322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com break; 1566322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 156734f7e47a3593911d03307a08e5af625b218ceec3reed@google.com if (rite > bounds.fRight) { 156834f7e47a3593911d03307a08e5af625b218ceec3reed@google.com rite = bounds.fRight; 156934f7e47a3593911d03307a08e5af625b218ceec3reed@google.com } 157034f7e47a3593911d03307a08e5af625b218ceec3reed@google.com 1571322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com if (left >= bounds.fLeft) { 15721c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com SkASSERT(rite > left); 1573322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com builder.addRun(left, lastY, proc(alphaA, alphaB), rite - left); 15741c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com prevRite = rite; 1575322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 15761c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com 15771c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com adjust_row(iterA, leftA, riteA, rite); 15781c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com adjust_row(iterB, leftB, riteB, rite); 15791c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } while (!iterA.done() || !iterB.done()); 15801c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com 15811c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (prevRite < bounds.fRight) { 15821c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com builder.addRun(prevRite, lastY, 0, bounds.fRight - prevRite); 1583322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1584322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com} 1585322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 15861c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.comstatic void adjust_iter(SkAAClip::Iter& iter, int& topA, int& botA, int bot) { 15871c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (bot == botA) { 15881c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com iter.next(); 15891c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com topA = botA; 15901c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com SkASSERT(botA == iter.top()); 15911c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com botA = iter.bottom(); 1592322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1593322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com} 1594322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1595322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comstatic void operateY(SkAAClip::Builder& builder, const SkAAClip& A, 1596322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com const SkAAClip& B, SkRegion::Op op) { 1597322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com AlphaProc proc = find_alpha_proc(op); 1598322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com const SkIRect& bounds = builder.getBounds(); 1599322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1600322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com SkAAClip::Iter iterA(A); 1601322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com SkAAClip::Iter iterB(B); 1602322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1603322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com SkASSERT(!iterA.done()); 1604322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com int topA = iterA.top(); 1605322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com int botA = iterA.bottom(); 1606322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com SkASSERT(!iterB.done()); 1607322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com int topB = iterB.top(); 1608322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com int botB = iterB.bottom(); 1609322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 16101c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com do { 161196fcdcc219d2a0d3579719b84b28bede76efba64halcanary const uint8_t* rowA = nullptr; 161296fcdcc219d2a0d3579719b84b28bede76efba64halcanary const uint8_t* rowB = nullptr; 1613322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com int top, bot; 16141c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com 16151c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (topA < topB) { 1616322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com top = topA; 1617322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com rowA = iterA.data(); 16181c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (botA <= topB) { 16191c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com bot = botA; 16201c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } else { 16211c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com bot = topA = topB; 16221c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } 1623fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 16241c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } else if (topB < topA) { 1625322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com top = topB; 1626322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com rowB = iterB.data(); 16271c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (botB <= topA) { 16281c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com bot = botB; 16291c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } else { 16301c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com bot = topB = topA; 16311c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } 1632322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } else { 16331c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com top = topA; // or topB, since topA == topB 16341c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com bot = topA = topB = SkMin32(botA, botB); 1635322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com rowA = iterA.data(); 1636322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com rowB = iterB.data(); 1637322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1638322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1639322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com if (top >= bounds.fBottom) { 1640322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com break; 1641322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 164234f7e47a3593911d03307a08e5af625b218ceec3reed@google.com 164334f7e47a3593911d03307a08e5af625b218ceec3reed@google.com if (bot > bounds.fBottom) { 164434f7e47a3593911d03307a08e5af625b218ceec3reed@google.com bot = bounds.fBottom; 164534f7e47a3593911d03307a08e5af625b218ceec3reed@google.com } 164634f7e47a3593911d03307a08e5af625b218ceec3reed@google.com SkASSERT(top < bot); 164734f7e47a3593911d03307a08e5af625b218ceec3reed@google.com 16481c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (!rowA && !rowB) { 16491c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com builder.addRun(bounds.fLeft, bot - 1, 0, bounds.width()); 16501c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } else if (top >= bounds.fTop) { 16511c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com SkASSERT(bot <= bounds.fBottom); 16521c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com RowIter rowIterA(rowA, rowA ? A.getBounds() : bounds); 16531c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com RowIter rowIterB(rowB, rowB ? B.getBounds() : bounds); 1654322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com operatorX(builder, bot - 1, rowIterA, rowIterB, proc, bounds); 1655322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1656322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 16571c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com adjust_iter(iterA, topA, botA, bot); 16581c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com adjust_iter(iterB, topB, botB, bot); 16591c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } while (!iterA.done() || !iterB.done()); 1660322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com} 1661322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1662322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.combool SkAAClip::op(const SkAAClip& clipAOrig, const SkAAClip& clipBOrig, 1663322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com SkRegion::Op op) { 1664045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com AUTO_AACLIP_VALIDATE(*this); 1665fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1666322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com if (SkRegion::kReplace_Op == op) { 1667322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return this->set(clipBOrig); 1668322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1669fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1670322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com const SkAAClip* clipA = &clipAOrig; 1671322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com const SkAAClip* clipB = &clipBOrig; 1672fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1673322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com if (SkRegion::kReverseDifference_Op == op) { 1674322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com SkTSwap(clipA, clipB); 1675322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com op = SkRegion::kDifference_Op; 1676322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1677322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1678322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com bool a_empty = clipA->isEmpty(); 1679322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com bool b_empty = clipB->isEmpty(); 1680322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1681322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com SkIRect bounds; 1682322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com switch (op) { 1683322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com case SkRegion::kDifference_Op: 1684322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com if (a_empty) { 1685322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return this->setEmpty(); 1686322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1687322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com if (b_empty || !SkIRect::Intersects(clipA->fBounds, clipB->fBounds)) { 1688322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return this->set(*clipA); 1689322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1690322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com bounds = clipA->fBounds; 1691322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com break; 1692fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1693322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com case SkRegion::kIntersect_Op: 1694322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com if ((a_empty | b_empty) || !bounds.intersect(clipA->fBounds, 1695322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com clipB->fBounds)) { 1696322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return this->setEmpty(); 1697322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1698322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com break; 1699fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1700322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com case SkRegion::kUnion_Op: 1701322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com case SkRegion::kXOR_Op: 1702322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com if (a_empty) { 1703322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return this->set(*clipB); 1704322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1705322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com if (b_empty) { 1706322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return this->set(*clipA); 1707322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1708322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com bounds = clipA->fBounds; 1709322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com bounds.join(clipB->fBounds); 1710322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com break; 1711322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1712322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com default: 17130c00f21fee3f5cfa3aa7e5d46ff94cb8cf340451tomhudson@google.com SkDEBUGFAIL("unknown region op"); 1714322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return !this->isEmpty(); 1715322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1716322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1717322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com SkASSERT(SkIRect::Intersects(bounds, clipB->fBounds)); 1718322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com SkASSERT(SkIRect::Intersects(bounds, clipB->fBounds)); 1719322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1720322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com Builder builder(bounds); 1721322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com operateY(builder, *clipA, *clipB, op); 1722045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1723045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return builder.finish(this); 1724e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 1725e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1726045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com/* 1727045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com * It can be expensive to build a local aaclip before applying the op, so 1728045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com * we first see if we can restrict the bounds of new rect to our current 1729045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com * bounds, or note that the new rect subsumes our current clip. 1730045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com */ 1731045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1732045e62d715f5ee9b03deb5af3c750f8318096179reed@google.combool SkAAClip::op(const SkIRect& rOrig, SkRegion::Op op) { 1733045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkIRect rStorage; 1734045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const SkIRect* r = &rOrig; 1735045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1736045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com switch (op) { 1737045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com case SkRegion::kIntersect_Op: 1738045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (!rStorage.intersect(rOrig, fBounds)) { 1739045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com // no overlap, so we're empty 1740045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return this->setEmpty(); 1741045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1742045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (rStorage == fBounds) { 1743045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com // we were wholly inside the rect, no change 1744045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return !this->isEmpty(); 1745045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1746045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (this->quickContains(rStorage)) { 1747045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com // the intersection is wholly inside us, we're a rect 1748045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return this->setRect(rStorage); 1749045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1750045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com r = &rStorage; // use the intersected bounds 1751045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com break; 1752045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com case SkRegion::kDifference_Op: 1753045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com break; 1754045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com case SkRegion::kUnion_Op: 1755045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (rOrig.contains(fBounds)) { 1756045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return this->setRect(rOrig); 1757045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1758045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com break; 1759045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com default: 1760045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com break; 1761045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1762045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 176347ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com SkAAClip clip; 1764045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com clip.setRect(*r); 176547ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com return this->op(*this, clip, op); 176647ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com} 176747ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com 1768045e62d715f5ee9b03deb5af3c750f8318096179reed@google.combool SkAAClip::op(const SkRect& rOrig, SkRegion::Op op, bool doAA) { 1769045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkRect rStorage, boundsStorage; 1770045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const SkRect* r = &rOrig; 1771fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1772045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com boundsStorage.set(fBounds); 1773045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com switch (op) { 1774045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com case SkRegion::kIntersect_Op: 1775045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com case SkRegion::kDifference_Op: 1776045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (!rStorage.intersect(rOrig, boundsStorage)) { 1777e56513d2a9eebabf93d7824eebf9e64441c485bareed@google.com if (SkRegion::kIntersect_Op == op) { 1778e56513d2a9eebabf93d7824eebf9e64441c485bareed@google.com return this->setEmpty(); 1779e56513d2a9eebabf93d7824eebf9e64441c485bareed@google.com } else { // kDifference 1780e56513d2a9eebabf93d7824eebf9e64441c485bareed@google.com return !this->isEmpty(); 1781e56513d2a9eebabf93d7824eebf9e64441c485bareed@google.com } 1782045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1783045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com r = &rStorage; // use the intersected bounds 1784045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com break; 1785045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com case SkRegion::kUnion_Op: 1786045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (rOrig.contains(boundsStorage)) { 1787045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return this->setRect(rOrig); 1788045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1789045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com break; 1790045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com default: 1791045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com break; 1792045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1793fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 179447ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com SkAAClip clip; 1795045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com clip.setRect(*r, doAA); 179647ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com return this->op(*this, clip, op); 179747ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com} 179847ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com 179947ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.combool SkAAClip::op(const SkAAClip& clip, SkRegion::Op op) { 180047ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com return this->op(*this, clip, op); 180147ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com} 180247ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com 1803e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com/////////////////////////////////////////////////////////////////////////////// 1804045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1805045e62d715f5ee9b03deb5af3c750f8318096179reed@google.combool SkAAClip::translate(int dx, int dy, SkAAClip* dst) const { 180696fcdcc219d2a0d3579719b84b28bede76efba64halcanary if (nullptr == dst) { 1807045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return !this->isEmpty(); 1808045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1809fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1810045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (this->isEmpty()) { 1811045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return dst->setEmpty(); 1812045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1813fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1814045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (this != dst) { 1815045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com sk_atomic_inc(&fRunHead->fRefCnt); 181619224c3d7903921ca86c856cc42adb31fc3164a9tomhudson@google.com dst->freeRuns(); 1817045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com dst->fRunHead = fRunHead; 1818045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com dst->fBounds = fBounds; 1819045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1820045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com dst->fBounds.offset(dx, dy); 1821045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return true; 1822045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com} 1823045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1824045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comstatic void expand_row_to_mask(uint8_t* SK_RESTRICT mask, 1825045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const uint8_t* SK_RESTRICT row, 1826045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com int width) { 1827045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com while (width > 0) { 1828045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com int n = row[0]; 1829045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(width >= n); 1830045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com memset(mask, row[1], n); 1831045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com mask += n; 1832045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com row += 2; 1833045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com width -= n; 1834045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1835a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com SkASSERT(0 == width); 1836045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com} 1837045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1838045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comvoid SkAAClip::copyToMask(SkMask* mask) const { 1839045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com mask->fFormat = SkMask::kA8_Format; 1840045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (this->isEmpty()) { 1841045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com mask->fBounds.setEmpty(); 184296fcdcc219d2a0d3579719b84b28bede76efba64halcanary mask->fImage = nullptr; 1843045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com mask->fRowBytes = 0; 1844045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return; 1845045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1846fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1847045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com mask->fBounds = fBounds; 1848045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com mask->fRowBytes = fBounds.width(); 1849045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com size_t size = mask->computeImageSize(); 1850045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com mask->fImage = SkMask::AllocImage(size); 1851fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1852045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com Iter iter(*this); 1853045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com uint8_t* dst = mask->fImage; 1854045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const int width = fBounds.width(); 1855fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1856045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com int y = fBounds.fTop; 1857045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com while (!iter.done()) { 1858045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com do { 1859045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com expand_row_to_mask(dst, iter.data(), width); 1860045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com dst += mask->fRowBytes; 1861045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } while (++y < iter.bottom()); 1862045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com iter.next(); 1863045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1864045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com} 1865045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1866045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com/////////////////////////////////////////////////////////////////////////////// 1867e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com/////////////////////////////////////////////////////////////////////////////// 1868e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1869e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comstatic void expandToRuns(const uint8_t* SK_RESTRICT data, int initialCount, int width, 1870e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int16_t* SK_RESTRICT runs, SkAlpha* SK_RESTRICT aa) { 1871e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com // we don't read our initial n from data, since the caller may have had to 1872e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com // clip it, hence the initialCount parameter. 1873e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int n = initialCount; 1874e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com for (;;) { 1875e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (n > width) { 1876e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com n = width; 1877e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1878e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(n > 0); 1879e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com runs[0] = n; 1880e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com runs += n; 1881e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1882e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com aa[0] = data[1]; 1883e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com aa += n; 1884fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1885e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com data += 2; 1886e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com width -= n; 1887e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (0 == width) { 1888e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com break; 1889e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1890e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com // load the next count 1891e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com n = data[0]; 1892e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1893e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com runs[0] = 0; // sentinel 1894e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 1895e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1896e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comSkAAClipBlitter::~SkAAClipBlitter() { 1897045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com sk_free(fScanlineScratch); 1898e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 1899e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1900e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comvoid SkAAClipBlitter::ensureRunsAndAA() { 190196fcdcc219d2a0d3579719b84b28bede76efba64halcanary if (nullptr == fScanlineScratch) { 1902e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com // add 1 so we can store the terminating run count of 0 1903e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int count = fAAClipBounds.width() + 1; 1904045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com // we use this either for fRuns + fAA, or a scaline of a mask 1905045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com // which may be as deep as 32bits 1906045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fScanlineScratch = sk_malloc_throw(count * sizeof(SkPMColor)); 1907045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fRuns = (int16_t*)fScanlineScratch; 1908e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fAA = (SkAlpha*)(fRuns + count); 1909e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1910e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 1911e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1912e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comvoid SkAAClipBlitter::blitH(int x, int y, int width) { 1913e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(width > 0); 1914e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(fAAClipBounds.contains(x, y)); 1915e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(fAAClipBounds.contains(x + width - 1, y)); 1916e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1917a4c6e4d6d3a4010df8dd2b04314675e4c201133breed@google.com const uint8_t* row = fAAClip->findRow(y); 1918e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int initialCount; 1919e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com row = fAAClip->findX(row, x, &initialCount); 1920e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1921e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (initialCount >= width) { 1922e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkAlpha alpha = row[1]; 1923e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (0 == alpha) { 1924e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return; 1925e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1926e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (0xFF == alpha) { 1927e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fBlitter->blitH(x, y, width); 1928e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return; 1929e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1930e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1931e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1932e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com this->ensureRunsAndAA(); 1933e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com expandToRuns(row, initialCount, width, fRuns, fAA); 1934e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1935e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fBlitter->blitAntiH(x, y, fAA, fRuns); 1936e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 1937e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1938e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comstatic void merge(const uint8_t* SK_RESTRICT row, int rowN, 1939e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const SkAlpha* SK_RESTRICT srcAA, 1940e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const int16_t* SK_RESTRICT srcRuns, 1941e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkAlpha* SK_RESTRICT dstAA, 1942e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int16_t* SK_RESTRICT dstRuns, 1943e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int width) { 1944e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkDEBUGCODE(int accumulated = 0;) 1945e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int srcN = srcRuns[0]; 1946045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com // do we need this check? 1947045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (0 == srcN) { 1948045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return; 1949045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1950045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1951e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com for (;;) { 1952e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(rowN > 0); 1953e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(srcN > 0); 1954e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1955e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com unsigned newAlpha = SkMulDiv255Round(srcAA[0], row[1]); 1956e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int minN = SkMin32(srcN, rowN); 1957e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com dstRuns[0] = minN; 1958e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com dstRuns += minN; 1959e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com dstAA[0] = newAlpha; 1960e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com dstAA += minN; 1961e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1962e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (0 == (srcN -= minN)) { 1963e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com srcN = srcRuns[0]; // refresh 1964e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com srcRuns += srcN; 1965e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com srcAA += srcN; 1966e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com srcN = srcRuns[0]; // reload 1967045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (0 == srcN) { 1968045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com break; 1969045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1970e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1971e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (0 == (rowN -= minN)) { 1972e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com row += 2; 1973e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com rowN = row[0]; // reload 1974e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1975fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1976e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkDEBUGCODE(accumulated += minN;) 1977e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(accumulated <= width); 1978e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 197934f7e47a3593911d03307a08e5af625b218ceec3reed@google.com dstRuns[0] = 0; 1980e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 1981e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1982e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comvoid SkAAClipBlitter::blitAntiH(int x, int y, const SkAlpha aa[], 1983e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const int16_t runs[]) { 1984a4c6e4d6d3a4010df8dd2b04314675e4c201133breed@google.com 1985a4c6e4d6d3a4010df8dd2b04314675e4c201133breed@google.com const uint8_t* row = fAAClip->findRow(y); 1986e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int initialCount; 1987e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com row = fAAClip->findX(row, x, &initialCount); 1988e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1989e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com this->ensureRunsAndAA(); 1990e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1991e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com merge(row, initialCount, aa, runs, fAA, fRuns, fAAClipBounds.width()); 1992e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fBlitter->blitAntiH(x, y, fAA, fRuns); 1993e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 1994e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1995e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comvoid SkAAClipBlitter::blitV(int x, int y, int height, SkAlpha alpha) { 1996e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (fAAClip->quickContains(x, y, x + 1, y + height)) { 1997e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fBlitter->blitV(x, y, height, alpha); 1998e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return; 1999e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 2000e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 2001045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com for (;;) { 2002a4c6e4d6d3a4010df8dd2b04314675e4c201133breed@google.com int lastY SK_INIT_TO_AVOID_WARNING; 2003e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const uint8_t* row = fAAClip->findRow(y, &lastY); 2004045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com int dy = lastY - y + 1; 2005045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (dy > height) { 2006045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com dy = height; 2007045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 2008045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com height -= dy; 2009045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 2010a4c6e4d6d3a4010df8dd2b04314675e4c201133breed@google.com row = fAAClip->findX(row, x); 2011e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkAlpha newAlpha = SkMulDiv255Round(alpha, row[1]); 2012e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (newAlpha) { 2013045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fBlitter->blitV(x, y, dy, newAlpha); 2014045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 2015045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(height >= 0); 2016045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (height <= 0) { 2017045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com break; 2018e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 2019e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com y = lastY + 1; 2020045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 2021e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 2022e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 2023e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comvoid SkAAClipBlitter::blitRect(int x, int y, int width, int height) { 2024e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (fAAClip->quickContains(x, y, x + width, y + height)) { 2025e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fBlitter->blitRect(x, y, width, height); 2026e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return; 2027e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 2028e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 2029e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com while (--height >= 0) { 2030e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com this->blitH(x, y, width); 2031e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com y += 1; 2032e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 2033e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 2034e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 2035045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comtypedef void (*MergeAAProc)(const void* src, int width, const uint8_t* row, 2036045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com int initialRowCount, void* dst); 2037045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 2038045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comstatic void small_memcpy(void* dst, const void* src, size_t n) { 2039045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com memcpy(dst, src, n); 2040e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 2041e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 2042045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comstatic void small_bzero(void* dst, size_t n) { 2043045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com sk_bzero(dst, n); 2044e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 2045e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 2046045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comstatic inline uint8_t mergeOne(uint8_t value, unsigned alpha) { 2047045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return SkMulDiv255Round(value, alpha); 2048045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com} 2049d54d3fc82456f8789b3e4dff40faeb7b670bcf4breed 2050045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comstatic inline uint16_t mergeOne(uint16_t value, unsigned alpha) { 2051045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com unsigned r = SkGetPackedR16(value); 2052045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com unsigned g = SkGetPackedG16(value); 2053045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com unsigned b = SkGetPackedB16(value); 2054045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return SkPackRGB16(SkMulDiv255Round(r, alpha), 2055803eceb6afd13f07416df0b4a9bb714e9370f081caryclark@google.com SkMulDiv255Round(g, alpha), 2056803eceb6afd13f07416df0b4a9bb714e9370f081caryclark@google.com SkMulDiv255Round(b, alpha)); 2057045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com} 2058322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 20599449616020a58043a49f0342679bf095918792a6herbtemplate <typename T> 20609449616020a58043a49f0342679bf095918792a6herbvoid mergeT(const void* inSrc, int srcN, const uint8_t* SK_RESTRICT row, int rowN, void* inDst) { 20619449616020a58043a49f0342679bf095918792a6herb const T* SK_RESTRICT src = static_cast<const T*>(inSrc); 20629449616020a58043a49f0342679bf095918792a6herb T* SK_RESTRICT dst = static_cast<T*>(inDst); 2063045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com for (;;) { 2064045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(rowN > 0); 2065045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(srcN > 0); 2066fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 2067045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com int n = SkMin32(rowN, srcN); 2068045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com unsigned rowA = row[1]; 2069045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (0xFF == rowA) { 2070045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com small_memcpy(dst, src, n * sizeof(T)); 2071045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } else if (0 == rowA) { 2072045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com small_bzero(dst, n * sizeof(T)); 2073045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } else { 2074045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com for (int i = 0; i < n; ++i) { 2075045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com dst[i] = mergeOne(src[i], rowA); 2076045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 2077045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 2078fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 2079045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (0 == (srcN -= n)) { 2080045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com break; 2081045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 2082fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 2083045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com src += n; 2084045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com dst += n; 2085fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 2086045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(rowN == n); 2087045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com row += 2; 2088045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com rowN = row[0]; 20891c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } 2090045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com} 20911c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com 2092045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comstatic MergeAAProc find_merge_aa_proc(SkMask::Format format) { 2093045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com switch (format) { 2094045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com case SkMask::kBW_Format: 20950c00f21fee3f5cfa3aa7e5d46ff94cb8cf340451tomhudson@google.com SkDEBUGFAIL("unsupported"); 209696fcdcc219d2a0d3579719b84b28bede76efba64halcanary return nullptr; 2097045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com case SkMask::kA8_Format: 20989449616020a58043a49f0342679bf095918792a6herb case SkMask::k3D_Format: 20999449616020a58043a49f0342679bf095918792a6herb return mergeT<uint8_t> ; 21009449616020a58043a49f0342679bf095918792a6herb case SkMask::kLCD16_Format: 21019449616020a58043a49f0342679bf095918792a6herb return mergeT<uint16_t>; 2102045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com default: 21030c00f21fee3f5cfa3aa7e5d46ff94cb8cf340451tomhudson@google.com SkDEBUGFAIL("unsupported"); 210496fcdcc219d2a0d3579719b84b28bede76efba64halcanary return nullptr; 21051c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } 2106045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com} 21071c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com 2108045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comstatic U8CPU bit2byte(int bitInAByte) { 2109045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(bitInAByte <= 0xFF); 2110045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com // negation turns any non-zero into 0xFFFFFF??, so we just shift down 2111045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com // some value >= 8 to get a full FF value 2112045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return -bitInAByte >> 8; 21131c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com} 21141c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com 2115045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comstatic void upscaleBW2A8(SkMask* dstMask, const SkMask& srcMask) { 2116045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(SkMask::kBW_Format == srcMask.fFormat); 2117045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(SkMask::kA8_Format == dstMask->fFormat); 2118045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 2119045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const int width = srcMask.fBounds.width(); 2120045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const int height = srcMask.fBounds.height(); 2121045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 2122045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const uint8_t* SK_RESTRICT src = (const uint8_t*)srcMask.fImage; 2123045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const size_t srcRB = srcMask.fRowBytes; 2124045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com uint8_t* SK_RESTRICT dst = (uint8_t*)dstMask->fImage; 2125045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const size_t dstRB = dstMask->fRowBytes; 2126045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 2127045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const int wholeBytes = width >> 3; 2128045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const int leftOverBits = width & 7; 2129045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 2130045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com for (int y = 0; y < height; ++y) { 2131045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com uint8_t* SK_RESTRICT d = dst; 2132045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com for (int i = 0; i < wholeBytes; ++i) { 2133045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com int srcByte = src[i]; 2134045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com d[0] = bit2byte(srcByte & (1 << 7)); 2135045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com d[1] = bit2byte(srcByte & (1 << 6)); 2136045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com d[2] = bit2byte(srcByte & (1 << 5)); 2137045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com d[3] = bit2byte(srcByte & (1 << 4)); 2138045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com d[4] = bit2byte(srcByte & (1 << 3)); 2139045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com d[5] = bit2byte(srcByte & (1 << 2)); 2140045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com d[6] = bit2byte(srcByte & (1 << 1)); 2141045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com d[7] = bit2byte(srcByte & (1 << 0)); 2142045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com d += 8; 2143045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 2144045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (leftOverBits) { 2145045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com int srcByte = src[wholeBytes]; 2146045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com for (int x = 0; x < leftOverBits; ++x) { 2147045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com *d++ = bit2byte(srcByte & 0x80); 2148045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com srcByte <<= 1; 2149045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 2150045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 2151045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com src += srcRB; 2152045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com dst += dstRB; 2153322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 2154322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com} 2155322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 2156045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comvoid SkAAClipBlitter::blitMask(const SkMask& origMask, const SkIRect& clip) { 2157045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(fAAClip->getBounds().contains(clip)); 2158045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 2159045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (fAAClip->quickContains(clip)) { 2160045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fBlitter->blitMask(origMask, clip); 2161322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return; 2162322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 2163322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 2164045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const SkMask* mask = &origMask; 2165322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 2166045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com // if we're BW, we need to upscale to A8 (ugh) 2167045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkMask grayMask; 2168045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (SkMask::kBW_Format == origMask.fFormat) { 2169045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com grayMask.fFormat = SkMask::kA8_Format; 2170045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com grayMask.fBounds = origMask.fBounds; 2171045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com grayMask.fRowBytes = origMask.fBounds.width(); 2172045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com size_t size = grayMask.computeImageSize(); 2173045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com grayMask.fImage = (uint8_t*)fGrayMaskScratch.reset(size, 2174045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkAutoMalloc::kReuse_OnShrink); 2175322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 2176045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com upscaleBW2A8(&grayMask, origMask); 2177045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com mask = &grayMask; 2178322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 2179045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 2180045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com this->ensureRunsAndAA(); 2181045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 2182045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com // HACK -- we are devolving 3D into A8, need to copy the rest of the 3D 2183045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com // data into a temp block to support it better (ugh) 2184045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 2185045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const void* src = mask->getAddr(clip.fLeft, clip.fTop); 2186045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const size_t srcRB = mask->fRowBytes; 2187045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const int width = clip.width(); 2188045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com MergeAAProc mergeProc = find_merge_aa_proc(mask->fFormat); 2189045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 2190045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkMask rowMask; 2191045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com rowMask.fFormat = SkMask::k3D_Format == mask->fFormat ? SkMask::kA8_Format : mask->fFormat; 2192045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com rowMask.fBounds.fLeft = clip.fLeft; 2193045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com rowMask.fBounds.fRight = clip.fRight; 2194045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com rowMask.fRowBytes = mask->fRowBytes; // doesn't matter, since our height==1 2195045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com rowMask.fImage = (uint8_t*)fScanlineScratch; 2196045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 2197045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com int y = clip.fTop; 2198045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const int stopY = y + clip.height(); 2199045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 2200045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com do { 2201a4c6e4d6d3a4010df8dd2b04314675e4c201133breed@google.com int localStopY SK_INIT_TO_AVOID_WARNING; 2202045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const uint8_t* row = fAAClip->findRow(y, &localStopY); 2203045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com // findRow returns last Y, not stop, so we add 1 2204045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com localStopY = SkMin32(localStopY + 1, stopY); 2205045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 2206045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com int initialCount; 2207045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com row = fAAClip->findX(row, clip.fLeft, &initialCount); 2208045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com do { 2209045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com mergeProc(src, width, row, initialCount, rowMask.fImage); 2210045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com rowMask.fBounds.fTop = y; 2211045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com rowMask.fBounds.fBottom = y + 1; 2212045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fBlitter->blitMask(rowMask, rowMask.fBounds); 2213045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com src = (const void*)((const char*)src + srcRB); 2214045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } while (++y < localStopY); 2215045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } while (y < stopY); 2216045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com} 2217045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 221841e010cb901c0da9066c4df562030808c9ccd7f8reedconst SkPixmap* SkAAClipBlitter::justAnOpaqueColor(uint32_t* value) { 221996fcdcc219d2a0d3579719b84b28bede76efba64halcanary return nullptr; 2220322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com} 2221