SkAAClip.cpp revision 80cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39b
1e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 2e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com/* 3e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com * Copyright 2011 Google Inc. 4e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com * 5e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com * Use of this source code is governed by a BSD-style license that can be 6e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com * found in the LICENSE file. 7e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com */ 8e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 9e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com#include "SkAAClip.h" 10e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com#include "SkBlitter.h" 11045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com#include "SkColorPriv.h" 12e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com#include "SkPath.h" 13e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com#include "SkScan.h" 14e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com#include "SkThread.h" 1534f7e47a3593911d03307a08e5af625b218ceec3reed@google.com#include "SkUtils.h" 16e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 17045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comclass AutoAAClipValidate { 18045e62d715f5ee9b03deb5af3c750f8318096179reed@google.compublic: 19045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com AutoAAClipValidate(const SkAAClip& clip) : fClip(clip) { 20045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fClip.validate(); 21045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 22045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com ~AutoAAClipValidate() { 23045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fClip.validate(); 24045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 25045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comprivate: 26045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const SkAAClip& fClip; 27045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com}; 28045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 29045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com#ifdef SK_DEBUG 30045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com #define AUTO_AACLIP_VALIDATE(clip) AutoAAClipValidate acv(clip) 31045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com#else 32045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com #define AUTO_AACLIP_VALIDATE(clip) 33045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com#endif 34045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 35045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com/////////////////////////////////////////////////////////////////////////////// 36045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 371c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com#define kMaxInt32 0x7FFFFFFF 381c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com 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} 42e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 43e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comstatic inline bool y_in_rect(int y, const SkIRect& rect) { 44e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return (unsigned)(y - rect.fTop) < (unsigned)rect.height(); 45e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 46e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 47e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com/* 48e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com * Data runs are packed [count, alpha] 49e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com */ 50e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 51e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comstruct SkAAClip::YOffset { 52e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int32_t fY; 53e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com uint32_t fOffset; 54e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}; 55e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 56e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comstruct SkAAClip::RunHead { 57e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int32_t fRefCnt; 58e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int32_t fRowCount; 59e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int32_t fDataSize; 60e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 61e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com YOffset* yoffsets() { 62e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return (YOffset*)((char*)this + sizeof(RunHead)); 63e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 64e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const YOffset* yoffsets() const { 65e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return (const YOffset*)((const char*)this + sizeof(RunHead)); 66e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 67e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com uint8_t* data() { 68e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return (uint8_t*)(this->yoffsets() + fRowCount); 69e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 70e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const uint8_t* data() const { 71e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return (const uint8_t*)(this->yoffsets() + fRowCount); 72e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 73e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 74e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com static RunHead* Alloc(int rowCount, size_t dataSize) { 75e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com size_t size = sizeof(RunHead) + rowCount * sizeof(YOffset) + dataSize; 76e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com RunHead* head = (RunHead*)sk_malloc_throw(size); 77e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com head->fRefCnt = 1; 78e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com head->fRowCount = rowCount; 79e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com head->fDataSize = dataSize; 80e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return head; 81e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 82045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 83045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com static int ComputeRowSizeForWidth(int width) { 84045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com // 2 bytes per segment, where each segment can store up to 255 for count 85045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com int segments = 0; 86045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com while (width > 0) { 87045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com segments += 1; 88045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com int n = SkMin32(width, 255); 89045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com width -= n; 90045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 91045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return segments * 2; // each segment is row[0] + row[1] (n + alpha) 92045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 93045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 94045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com static RunHead* AllocRect(const SkIRect& bounds) { 95045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(!bounds.isEmpty()); 96045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com int width = bounds.width(); 97045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com size_t rowSize = ComputeRowSizeForWidth(width); 98045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com RunHead* head = RunHead::Alloc(1, rowSize); 99045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com YOffset* yoff = head->yoffsets(); 100045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com yoff->fY = bounds.height() - 1; 101045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com yoff->fOffset = 0; 102045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com uint8_t* row = head->data(); 103045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com while (width > 0) { 104045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com int n = SkMin32(width, 255); 105045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com row[0] = n; 106045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com row[1] = 0xFF; 107045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com width -= n; 108045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com row += 2; 109045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 110045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return head; 111045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 112e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}; 113e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 114322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comclass SkAAClip::Iter { 115322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.compublic: 116322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com Iter(const SkAAClip&); 117322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 118322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com bool done() const { return fDone; } 1191c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com int top() const { return fTop; } 1201c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com int bottom() const { return fBottom; } 1211c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com const uint8_t* data() const { return fData; } 122322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com void next(); 123322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 124322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comprivate: 125322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com const YOffset* fCurrYOff; 126322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com const YOffset* fStopYOff; 127322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com const uint8_t* fData; 128322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 129322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com int fTop, fBottom; 130322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com bool fDone; 131322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com}; 132322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 133322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comSkAAClip::Iter::Iter(const SkAAClip& clip) { 134322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com if (clip.isEmpty()) { 135322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com fDone = true; 1361c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fTop = fBottom = clip.fBounds.fBottom; 1371c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fData = NULL; 138322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return; 139322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 140322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 141322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com const RunHead* head = clip.fRunHead; 142322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com fCurrYOff = head->yoffsets(); 143322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com fStopYOff = fCurrYOff + head->fRowCount; 144322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com fData = head->data() + fCurrYOff->fOffset; 145322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 146322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com // setup first value 147322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com fTop = clip.fBounds.fTop; 148322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com fBottom = clip.fBounds.fTop + fCurrYOff->fY + 1; 149322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com fDone = false; 150322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com} 151322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 152322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comvoid SkAAClip::Iter::next() { 1531c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (!fDone) { 1541c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com const YOffset* prev = fCurrYOff; 1551c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com const YOffset* curr = prev + 1; 1561c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com SkASSERT(curr <= fStopYOff); 157322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 158322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com fTop = fBottom; 1591c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (curr >= fStopYOff) { 1601c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fDone = true; 1611c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fBottom = kMaxInt32; 1621c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fData = NULL; 1631c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } else { 1641c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fBottom += curr->fY - prev->fY; 1651c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fData += curr->fOffset - prev->fOffset; 1661c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fCurrYOff = curr; 1671c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } 168322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 169322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com} 170322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 171045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com#ifdef SK_DEBUG 172c90419199525141a5b98091f856e359bf9daf5b1reed@google.com// assert we're exactly width-wide, and then return the number of bytes used 173045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comstatic size_t compute_row_length(const uint8_t row[], int width) { 174045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const uint8_t* origRow = row; 175045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com while (width > 0) { 176045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com int n = row[0]; 177c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(n > 0); 178045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(n <= width); 179045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com row += 2; 180045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com width -= n; 181045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 182045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(0 == width); 183045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return row - origRow; 184045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com} 185045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 186045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comvoid SkAAClip::validate() const { 187045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (NULL == fRunHead) { 188045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(fBounds.isEmpty()); 189045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return; 190045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 191045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 192045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const RunHead* head = fRunHead; 193045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(head->fRefCnt > 0); 194045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(head->fRowCount > 0); 195045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(head->fDataSize > 0); 196045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 197045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const YOffset* yoff = head->yoffsets(); 198045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const YOffset* ystop = yoff + head->fRowCount; 199c90419199525141a5b98091f856e359bf9daf5b1reed@google.com const int lastY = fBounds.height() - 1; 200c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 201c90419199525141a5b98091f856e359bf9daf5b1reed@google.com // Y and offset must be monotonic 202c90419199525141a5b98091f856e359bf9daf5b1reed@google.com int prevY = -1; 203c90419199525141a5b98091f856e359bf9daf5b1reed@google.com int32_t prevOffset = -1; 204045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com while (yoff < ystop) { 205c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(prevY < yoff->fY); 206c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(yoff->fY <= lastY); 207c90419199525141a5b98091f856e359bf9daf5b1reed@google.com prevY = yoff->fY; 208c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(prevOffset < (int32_t)yoff->fOffset); 209c90419199525141a5b98091f856e359bf9daf5b1reed@google.com prevOffset = yoff->fOffset; 210c90419199525141a5b98091f856e359bf9daf5b1reed@google.com const uint8_t* row = head->data() + yoff->fOffset; 211045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com size_t rowLength = compute_row_length(row, fBounds.width()); 212f74ad8c91aef4f328dbcbcebae9e436c00a35140tomhudson@google.com SkASSERT(yoff->fOffset + rowLength <= (size_t) head->fDataSize); 213c90419199525141a5b98091f856e359bf9daf5b1reed@google.com yoff += 1; 214045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 215045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com // check the last entry; 216045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com --yoff; 217c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(yoff->fY == lastY); 218045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com} 219045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com#endif 220045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 221045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com/////////////////////////////////////////////////////////////////////////////// 222045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 223c90419199525141a5b98091f856e359bf9daf5b1reed@google.comstatic void count_left_right_zeros(const uint8_t* row, int width, 224c90419199525141a5b98091f856e359bf9daf5b1reed@google.com int* leftZ, int* riteZ) { 225c90419199525141a5b98091f856e359bf9daf5b1reed@google.com int zeros = 0; 226c90419199525141a5b98091f856e359bf9daf5b1reed@google.com do { 227c90419199525141a5b98091f856e359bf9daf5b1reed@google.com if (row[1]) { 228c90419199525141a5b98091f856e359bf9daf5b1reed@google.com break; 229c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 230c90419199525141a5b98091f856e359bf9daf5b1reed@google.com int n = row[0]; 231c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(n > 0); 232c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(n <= width); 233c90419199525141a5b98091f856e359bf9daf5b1reed@google.com zeros += n; 234c90419199525141a5b98091f856e359bf9daf5b1reed@google.com row += 2; 235c90419199525141a5b98091f856e359bf9daf5b1reed@google.com width -= n; 236c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } while (width > 0); 237c90419199525141a5b98091f856e359bf9daf5b1reed@google.com *leftZ = zeros; 238c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 239c90419199525141a5b98091f856e359bf9daf5b1reed@google.com zeros = 0; 240c90419199525141a5b98091f856e359bf9daf5b1reed@google.com while (width > 0) { 241c90419199525141a5b98091f856e359bf9daf5b1reed@google.com int n = row[0]; 242c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(n > 0); 243c90419199525141a5b98091f856e359bf9daf5b1reed@google.com if (0 == row[1]) { 244c90419199525141a5b98091f856e359bf9daf5b1reed@google.com zeros += n; 245c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } else { 246c90419199525141a5b98091f856e359bf9daf5b1reed@google.com zeros = 0; 247c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 248c90419199525141a5b98091f856e359bf9daf5b1reed@google.com row += 2; 249c90419199525141a5b98091f856e359bf9daf5b1reed@google.com width -= n; 250c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 251c90419199525141a5b98091f856e359bf9daf5b1reed@google.com *riteZ = zeros; 252c90419199525141a5b98091f856e359bf9daf5b1reed@google.com} 253c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 254c90419199525141a5b98091f856e359bf9daf5b1reed@google.com#ifdef SK_DEBUG 255c90419199525141a5b98091f856e359bf9daf5b1reed@google.comstatic void test_count_left_right_zeros() { 256c90419199525141a5b98091f856e359bf9daf5b1reed@google.com static bool gOnce; 257c90419199525141a5b98091f856e359bf9daf5b1reed@google.com if (gOnce) { 258c90419199525141a5b98091f856e359bf9daf5b1reed@google.com return; 259c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 260c90419199525141a5b98091f856e359bf9daf5b1reed@google.com gOnce = true; 261c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 262c90419199525141a5b98091f856e359bf9daf5b1reed@google.com const uint8_t data0[] = { 0, 0, 10, 0xFF }; 263c90419199525141a5b98091f856e359bf9daf5b1reed@google.com const uint8_t data1[] = { 0, 0, 5, 0xFF, 2, 0, 3, 0xFF }; 264c90419199525141a5b98091f856e359bf9daf5b1reed@google.com const uint8_t data2[] = { 7, 0, 5, 0, 2, 0, 3, 0xFF }; 265c90419199525141a5b98091f856e359bf9daf5b1reed@google.com const uint8_t data3[] = { 0, 5, 5, 0xFF, 2, 0, 3, 0 }; 266c90419199525141a5b98091f856e359bf9daf5b1reed@google.com const uint8_t data4[] = { 2, 3, 2, 0, 5, 0xFF, 3, 0 }; 267c90419199525141a5b98091f856e359bf9daf5b1reed@google.com const uint8_t data5[] = { 10, 0, 10, 0 }; 268c90419199525141a5b98091f856e359bf9daf5b1reed@google.com const uint8_t data6[] = { 2, 2, 2, 0, 2, 0xFF, 2, 0, 2, 0xFF, 2, 0 }; 269c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 270c90419199525141a5b98091f856e359bf9daf5b1reed@google.com const uint8_t* array[] = { 271c90419199525141a5b98091f856e359bf9daf5b1reed@google.com data0, data1, data2, data3, data4, data5, data6 272c90419199525141a5b98091f856e359bf9daf5b1reed@google.com }; 273c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 274c90419199525141a5b98091f856e359bf9daf5b1reed@google.com for (size_t i = 0; i < SK_ARRAY_COUNT(array); ++i) { 275c90419199525141a5b98091f856e359bf9daf5b1reed@google.com const uint8_t* data = array[i]; 276c90419199525141a5b98091f856e359bf9daf5b1reed@google.com const int expectedL = *data++; 277c90419199525141a5b98091f856e359bf9daf5b1reed@google.com const int expectedR = *data++; 278c90419199525141a5b98091f856e359bf9daf5b1reed@google.com int L = 12345, R = 12345; 279c90419199525141a5b98091f856e359bf9daf5b1reed@google.com count_left_right_zeros(data, 10, &L, &R); 280c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(expectedL == L); 281c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(expectedR == R); 282c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 283c90419199525141a5b98091f856e359bf9daf5b1reed@google.com} 284c90419199525141a5b98091f856e359bf9daf5b1reed@google.com#endif 285c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 286c90419199525141a5b98091f856e359bf9daf5b1reed@google.com// modify row in place, trimming off (zeros) from the left and right sides. 287c90419199525141a5b98091f856e359bf9daf5b1reed@google.com// return the number of bytes that were completely eliminated from the left 288c90419199525141a5b98091f856e359bf9daf5b1reed@google.comstatic int trim_row_left_right(uint8_t* row, int width, int leftZ, int riteZ) { 289c90419199525141a5b98091f856e359bf9daf5b1reed@google.com int trim = 0; 290c90419199525141a5b98091f856e359bf9daf5b1reed@google.com while (leftZ > 0) { 291c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(0 == row[1]); 292c90419199525141a5b98091f856e359bf9daf5b1reed@google.com int n = row[0]; 293c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(n > 0); 294c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(n <= width); 295c90419199525141a5b98091f856e359bf9daf5b1reed@google.com width -= n; 296c90419199525141a5b98091f856e359bf9daf5b1reed@google.com row += 2; 297c90419199525141a5b98091f856e359bf9daf5b1reed@google.com if (n > leftZ) { 298c90419199525141a5b98091f856e359bf9daf5b1reed@google.com row[-2] = n - leftZ; 299c90419199525141a5b98091f856e359bf9daf5b1reed@google.com break; 300c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 301c90419199525141a5b98091f856e359bf9daf5b1reed@google.com trim += 2; 302c90419199525141a5b98091f856e359bf9daf5b1reed@google.com leftZ -= n; 303c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(leftZ >= 0); 304c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 305c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 306c90419199525141a5b98091f856e359bf9daf5b1reed@google.com if (riteZ) { 307c90419199525141a5b98091f856e359bf9daf5b1reed@google.com // walk row to the end, and then we'll back up to trim riteZ 308c90419199525141a5b98091f856e359bf9daf5b1reed@google.com while (width > 0) { 309c90419199525141a5b98091f856e359bf9daf5b1reed@google.com int n = row[0]; 310c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(n <= width); 311c90419199525141a5b98091f856e359bf9daf5b1reed@google.com width -= n; 312c90419199525141a5b98091f856e359bf9daf5b1reed@google.com row += 2; 313c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 314c90419199525141a5b98091f856e359bf9daf5b1reed@google.com // now skip whole runs of zeros 315c90419199525141a5b98091f856e359bf9daf5b1reed@google.com do { 316c90419199525141a5b98091f856e359bf9daf5b1reed@google.com row -= 2; 317c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(0 == row[1]); 318c90419199525141a5b98091f856e359bf9daf5b1reed@google.com int n = row[0]; 319c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(n > 0); 320c90419199525141a5b98091f856e359bf9daf5b1reed@google.com if (n > riteZ) { 321c90419199525141a5b98091f856e359bf9daf5b1reed@google.com row[0] = n - riteZ; 322c90419199525141a5b98091f856e359bf9daf5b1reed@google.com break; 323c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 324c90419199525141a5b98091f856e359bf9daf5b1reed@google.com riteZ -= n; 325c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(riteZ >= 0); 326c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } while (riteZ > 0); 327c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 328c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 329c90419199525141a5b98091f856e359bf9daf5b1reed@google.com return trim; 330c90419199525141a5b98091f856e359bf9daf5b1reed@google.com} 331c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 332c90419199525141a5b98091f856e359bf9daf5b1reed@google.com#ifdef SK_DEBUG 333c90419199525141a5b98091f856e359bf9daf5b1reed@google.com// assert that this row is exactly this width 334c5507bfe2d54e411ef6eb83452b8cbfbae009610reed@google.comstatic void assert_row_width(const uint8_t* row, int width) { 335c90419199525141a5b98091f856e359bf9daf5b1reed@google.com while (width > 0) { 336c90419199525141a5b98091f856e359bf9daf5b1reed@google.com int n = row[0]; 337c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(n > 0); 338c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(n <= width); 339c90419199525141a5b98091f856e359bf9daf5b1reed@google.com width -= n; 340c90419199525141a5b98091f856e359bf9daf5b1reed@google.com row += 2; 341c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 342c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(0 == width); 343c90419199525141a5b98091f856e359bf9daf5b1reed@google.com} 344c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 345c90419199525141a5b98091f856e359bf9daf5b1reed@google.comstatic void test_trim_row_left_right() { 346c90419199525141a5b98091f856e359bf9daf5b1reed@google.com static bool gOnce; 347c90419199525141a5b98091f856e359bf9daf5b1reed@google.com if (gOnce) { 348c90419199525141a5b98091f856e359bf9daf5b1reed@google.com return; 349c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 350c90419199525141a5b98091f856e359bf9daf5b1reed@google.com gOnce = true; 351c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 352c90419199525141a5b98091f856e359bf9daf5b1reed@google.com uint8_t data0[] = { 0, 0, 0, 10, 10, 0xFF }; 353c90419199525141a5b98091f856e359bf9daf5b1reed@google.com uint8_t data1[] = { 2, 0, 0, 10, 5, 0, 2, 0, 3, 0xFF }; 354c90419199525141a5b98091f856e359bf9daf5b1reed@google.com uint8_t data2[] = { 5, 0, 2, 10, 5, 0, 2, 0, 3, 0xFF }; 355c90419199525141a5b98091f856e359bf9daf5b1reed@google.com uint8_t data3[] = { 6, 0, 2, 10, 5, 0, 2, 0, 3, 0xFF }; 356c90419199525141a5b98091f856e359bf9daf5b1reed@google.com uint8_t data4[] = { 0, 0, 0, 10, 2, 0, 2, 0xFF, 2, 0, 2, 0xFF, 2, 0 }; 357c90419199525141a5b98091f856e359bf9daf5b1reed@google.com uint8_t data5[] = { 1, 0, 0, 10, 2, 0, 2, 0xFF, 2, 0, 2, 0xFF, 2, 0 }; 358c90419199525141a5b98091f856e359bf9daf5b1reed@google.com uint8_t data6[] = { 0, 1, 0, 10, 2, 0, 2, 0xFF, 2, 0, 2, 0xFF, 2, 0 }; 359c90419199525141a5b98091f856e359bf9daf5b1reed@google.com uint8_t data7[] = { 1, 1, 0, 10, 2, 0, 2, 0xFF, 2, 0, 2, 0xFF, 2, 0 }; 360c90419199525141a5b98091f856e359bf9daf5b1reed@google.com uint8_t data8[] = { 2, 2, 2, 10, 2, 0, 2, 0xFF, 2, 0, 2, 0xFF, 2, 0 }; 361c90419199525141a5b98091f856e359bf9daf5b1reed@google.com uint8_t data9[] = { 5, 2, 4, 10, 2, 0, 2, 0, 2, 0, 2, 0xFF, 2, 0 }; 362c90419199525141a5b98091f856e359bf9daf5b1reed@google.com uint8_t data10[] ={ 74, 0, 4, 150, 9, 0, 65, 0, 76, 0xFF }; 363c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 364c90419199525141a5b98091f856e359bf9daf5b1reed@google.com uint8_t* array[] = { 365c90419199525141a5b98091f856e359bf9daf5b1reed@google.com data0, data1, data2, data3, data4, 366c90419199525141a5b98091f856e359bf9daf5b1reed@google.com data5, data6, data7, data8, data9, 367c90419199525141a5b98091f856e359bf9daf5b1reed@google.com data10 368c90419199525141a5b98091f856e359bf9daf5b1reed@google.com }; 369c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 370c90419199525141a5b98091f856e359bf9daf5b1reed@google.com for (size_t i = 0; i < SK_ARRAY_COUNT(array); ++i) { 371c90419199525141a5b98091f856e359bf9daf5b1reed@google.com uint8_t* data = array[i]; 372c90419199525141a5b98091f856e359bf9daf5b1reed@google.com const int trimL = *data++; 373c90419199525141a5b98091f856e359bf9daf5b1reed@google.com const int trimR = *data++; 374c90419199525141a5b98091f856e359bf9daf5b1reed@google.com const int expectedSkip = *data++; 375c90419199525141a5b98091f856e359bf9daf5b1reed@google.com const int origWidth = *data++; 376c90419199525141a5b98091f856e359bf9daf5b1reed@google.com assert_row_width(data, origWidth); 377c90419199525141a5b98091f856e359bf9daf5b1reed@google.com int skip = trim_row_left_right(data, origWidth, trimL, trimR); 378c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(expectedSkip == skip); 379c90419199525141a5b98091f856e359bf9daf5b1reed@google.com int expectedWidth = origWidth - trimL - trimR; 380c90419199525141a5b98091f856e359bf9daf5b1reed@google.com assert_row_width(data + skip, expectedWidth); 381c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 382c90419199525141a5b98091f856e359bf9daf5b1reed@google.com} 383c90419199525141a5b98091f856e359bf9daf5b1reed@google.com#endif 384c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 385c90419199525141a5b98091f856e359bf9daf5b1reed@google.combool SkAAClip::trimLeftRight() { 386c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkDEBUGCODE(test_trim_row_left_right();) 387c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 388c90419199525141a5b98091f856e359bf9daf5b1reed@google.com if (this->isEmpty()) { 389c90419199525141a5b98091f856e359bf9daf5b1reed@google.com return false; 390c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 391c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 392c90419199525141a5b98091f856e359bf9daf5b1reed@google.com AUTO_AACLIP_VALIDATE(*this); 393c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 394c90419199525141a5b98091f856e359bf9daf5b1reed@google.com const int width = fBounds.width(); 395c90419199525141a5b98091f856e359bf9daf5b1reed@google.com RunHead* head = fRunHead; 396c90419199525141a5b98091f856e359bf9daf5b1reed@google.com YOffset* yoff = head->yoffsets(); 397c90419199525141a5b98091f856e359bf9daf5b1reed@google.com YOffset* stop = yoff + head->fRowCount; 398c90419199525141a5b98091f856e359bf9daf5b1reed@google.com uint8_t* base = head->data(); 399c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 400c90419199525141a5b98091f856e359bf9daf5b1reed@google.com int leftZeros = width; 401c90419199525141a5b98091f856e359bf9daf5b1reed@google.com int riteZeros = width; 402c90419199525141a5b98091f856e359bf9daf5b1reed@google.com while (yoff < stop) { 403c90419199525141a5b98091f856e359bf9daf5b1reed@google.com int L, R; 404c90419199525141a5b98091f856e359bf9daf5b1reed@google.com count_left_right_zeros(base + yoff->fOffset, width, &L, &R); 405c90419199525141a5b98091f856e359bf9daf5b1reed@google.com if (L < leftZeros) { 406c90419199525141a5b98091f856e359bf9daf5b1reed@google.com leftZeros = L; 407c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 408c90419199525141a5b98091f856e359bf9daf5b1reed@google.com if (R < riteZeros) { 409c90419199525141a5b98091f856e359bf9daf5b1reed@google.com riteZeros = R; 410c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 411c90419199525141a5b98091f856e359bf9daf5b1reed@google.com if (0 == (leftZeros | riteZeros)) { 412c90419199525141a5b98091f856e359bf9daf5b1reed@google.com // no trimming to do 413c90419199525141a5b98091f856e359bf9daf5b1reed@google.com return true; 414c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 415c90419199525141a5b98091f856e359bf9daf5b1reed@google.com yoff += 1; 416c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 417c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 418c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(leftZeros || riteZeros); 419c90419199525141a5b98091f856e359bf9daf5b1reed@google.com if (width == (leftZeros + riteZeros)) { 420c90419199525141a5b98091f856e359bf9daf5b1reed@google.com return this->setEmpty(); 421c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 422c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 423c90419199525141a5b98091f856e359bf9daf5b1reed@google.com this->validate(); 424c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 425c90419199525141a5b98091f856e359bf9daf5b1reed@google.com fBounds.fLeft += leftZeros; 426c90419199525141a5b98091f856e359bf9daf5b1reed@google.com fBounds.fRight -= riteZeros; 427c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(!fBounds.isEmpty()); 428c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 429c90419199525141a5b98091f856e359bf9daf5b1reed@google.com // For now we don't realloc the storage (for time), we just shrink in place 430c90419199525141a5b98091f856e359bf9daf5b1reed@google.com // This means we don't have to do any memmoves either, since we can just 431c90419199525141a5b98091f856e359bf9daf5b1reed@google.com // play tricks with the yoff->fOffset for each row 432c90419199525141a5b98091f856e359bf9daf5b1reed@google.com yoff = head->yoffsets(); 433c90419199525141a5b98091f856e359bf9daf5b1reed@google.com while (yoff < stop) { 434c90419199525141a5b98091f856e359bf9daf5b1reed@google.com uint8_t* row = base + yoff->fOffset; 435c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkDEBUGCODE((void)compute_row_length(row, width);) 436c90419199525141a5b98091f856e359bf9daf5b1reed@google.com yoff->fOffset += trim_row_left_right(row, width, leftZeros, riteZeros); 437c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkDEBUGCODE((void)compute_row_length(base + yoff->fOffset, width - leftZeros - riteZeros);) 438c90419199525141a5b98091f856e359bf9daf5b1reed@google.com yoff += 1; 439c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 440c90419199525141a5b98091f856e359bf9daf5b1reed@google.com return true; 441c90419199525141a5b98091f856e359bf9daf5b1reed@google.com} 442c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 443c90419199525141a5b98091f856e359bf9daf5b1reed@google.comstatic bool row_is_all_zeros(const uint8_t* row, int width) { 444c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(width > 0); 445c90419199525141a5b98091f856e359bf9daf5b1reed@google.com do { 446c90419199525141a5b98091f856e359bf9daf5b1reed@google.com if (row[1]) { 447c90419199525141a5b98091f856e359bf9daf5b1reed@google.com return false; 448c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 449c90419199525141a5b98091f856e359bf9daf5b1reed@google.com int n = row[0]; 450c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(n <= width); 451c90419199525141a5b98091f856e359bf9daf5b1reed@google.com width -= n; 452c90419199525141a5b98091f856e359bf9daf5b1reed@google.com row += 2; 453c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } while (width > 0); 454c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(0 == width); 455c90419199525141a5b98091f856e359bf9daf5b1reed@google.com return true; 456c90419199525141a5b98091f856e359bf9daf5b1reed@google.com} 457c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 458c90419199525141a5b98091f856e359bf9daf5b1reed@google.combool SkAAClip::trimTopBottom() { 459c90419199525141a5b98091f856e359bf9daf5b1reed@google.com if (this->isEmpty()) { 460c90419199525141a5b98091f856e359bf9daf5b1reed@google.com return false; 461c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 462c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 463d6040f6f2fcb11fddad5d92b3cb7255e90931bccreed@google.com this->validate(); 464d6040f6f2fcb11fddad5d92b3cb7255e90931bccreed@google.com 465c90419199525141a5b98091f856e359bf9daf5b1reed@google.com const int width = fBounds.width(); 466c90419199525141a5b98091f856e359bf9daf5b1reed@google.com RunHead* head = fRunHead; 467c90419199525141a5b98091f856e359bf9daf5b1reed@google.com YOffset* yoff = head->yoffsets(); 468c90419199525141a5b98091f856e359bf9daf5b1reed@google.com YOffset* stop = yoff + head->fRowCount; 469c90419199525141a5b98091f856e359bf9daf5b1reed@google.com const uint8_t* base = head->data(); 470c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 471c90419199525141a5b98091f856e359bf9daf5b1reed@google.com // Look to trim away empty rows from the top. 472c90419199525141a5b98091f856e359bf9daf5b1reed@google.com // 473c90419199525141a5b98091f856e359bf9daf5b1reed@google.com int skip = 0; 474c90419199525141a5b98091f856e359bf9daf5b1reed@google.com while (yoff < stop) { 475c90419199525141a5b98091f856e359bf9daf5b1reed@google.com const uint8_t* data = base + yoff->fOffset; 476c90419199525141a5b98091f856e359bf9daf5b1reed@google.com if (!row_is_all_zeros(data, width)) { 477c90419199525141a5b98091f856e359bf9daf5b1reed@google.com break; 478c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 479c90419199525141a5b98091f856e359bf9daf5b1reed@google.com skip += 1; 480c90419199525141a5b98091f856e359bf9daf5b1reed@google.com yoff += 1; 481c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 482c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(skip <= head->fRowCount); 483c90419199525141a5b98091f856e359bf9daf5b1reed@google.com if (skip == head->fRowCount) { 484c90419199525141a5b98091f856e359bf9daf5b1reed@google.com return this->setEmpty(); 485c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 486c90419199525141a5b98091f856e359bf9daf5b1reed@google.com if (skip > 0) { 487c90419199525141a5b98091f856e359bf9daf5b1reed@google.com // adjust fRowCount and fBounds.fTop, and slide all the data up 488c90419199525141a5b98091f856e359bf9daf5b1reed@google.com // as we remove [skip] number of YOffset entries 489c90419199525141a5b98091f856e359bf9daf5b1reed@google.com yoff = head->yoffsets(); 490c90419199525141a5b98091f856e359bf9daf5b1reed@google.com int dy = yoff[skip - 1].fY + 1; 491c90419199525141a5b98091f856e359bf9daf5b1reed@google.com for (int i = skip; i < head->fRowCount; ++i) { 492c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(yoff[i].fY >= dy); 493c90419199525141a5b98091f856e359bf9daf5b1reed@google.com yoff[i].fY -= dy; 494c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 495c90419199525141a5b98091f856e359bf9daf5b1reed@google.com YOffset* dst = head->yoffsets(); 496c90419199525141a5b98091f856e359bf9daf5b1reed@google.com size_t size = head->fRowCount * sizeof(YOffset) + head->fDataSize; 497c90419199525141a5b98091f856e359bf9daf5b1reed@google.com memmove(dst, dst + skip, size - skip * sizeof(YOffset)); 498c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 499c90419199525141a5b98091f856e359bf9daf5b1reed@google.com fBounds.fTop += dy; 500c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(!fBounds.isEmpty()); 501c90419199525141a5b98091f856e359bf9daf5b1reed@google.com head->fRowCount -= skip; 502c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(head->fRowCount > 0); 503d6040f6f2fcb11fddad5d92b3cb7255e90931bccreed@google.com 504d6040f6f2fcb11fddad5d92b3cb7255e90931bccreed@google.com this->validate(); 505d6040f6f2fcb11fddad5d92b3cb7255e90931bccreed@google.com // need to reset this after the memmove 506d6040f6f2fcb11fddad5d92b3cb7255e90931bccreed@google.com base = head->data(); 507c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 508c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 509c90419199525141a5b98091f856e359bf9daf5b1reed@google.com // Look to trim away empty rows from the bottom. 510c90419199525141a5b98091f856e359bf9daf5b1reed@google.com // We know that we have at least one non-zero row, so we can just walk 511c90419199525141a5b98091f856e359bf9daf5b1reed@google.com // backwards without checking for running past the start. 512c90419199525141a5b98091f856e359bf9daf5b1reed@google.com // 513c90419199525141a5b98091f856e359bf9daf5b1reed@google.com stop = yoff = head->yoffsets() + head->fRowCount; 514c90419199525141a5b98091f856e359bf9daf5b1reed@google.com do { 515c90419199525141a5b98091f856e359bf9daf5b1reed@google.com yoff -= 1; 516c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } while (row_is_all_zeros(base + yoff->fOffset, width)); 517c90419199525141a5b98091f856e359bf9daf5b1reed@google.com skip = stop - yoff - 1; 518c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(skip >= 0 && skip < head->fRowCount); 519c90419199525141a5b98091f856e359bf9daf5b1reed@google.com if (skip > 0) { 520c90419199525141a5b98091f856e359bf9daf5b1reed@google.com // removing from the bottom is easier than from the top, as we don't 521c90419199525141a5b98091f856e359bf9daf5b1reed@google.com // have to adjust any of the Y values, we just have to trim the array 522c90419199525141a5b98091f856e359bf9daf5b1reed@google.com memmove(stop - skip, stop, head->fDataSize); 523c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 524c90419199525141a5b98091f856e359bf9daf5b1reed@google.com fBounds.fBottom = fBounds.fTop + yoff->fY + 1; 525c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(!fBounds.isEmpty()); 526c90419199525141a5b98091f856e359bf9daf5b1reed@google.com head->fRowCount -= skip; 527c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(head->fRowCount > 0); 528c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 529d6040f6f2fcb11fddad5d92b3cb7255e90931bccreed@google.com this->validate(); 530c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 531c90419199525141a5b98091f856e359bf9daf5b1reed@google.com return true; 532c90419199525141a5b98091f856e359bf9daf5b1reed@google.com} 533c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 534045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com// can't validate before we're done, since trimming is part of the process of 535045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com// making us valid after the Builder. Since we build from top to bottom, its 536045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com// possible our fBounds.fBottom is bigger than our last scanline of data, so 537045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com// we trim fBounds.fBottom back up. 538045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com// 539045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com// TODO: check for duplicates in X and Y to further compress our data 540045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com// 541045e62d715f5ee9b03deb5af3c750f8318096179reed@google.combool SkAAClip::trimBounds() { 542045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (this->isEmpty()) { 543045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return false; 544045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 545045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 546045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const RunHead* head = fRunHead; 547045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const YOffset* yoff = head->yoffsets(); 548045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 549045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(head->fRowCount > 0); 550045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const YOffset& lastY = yoff[head->fRowCount - 1]; 551045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(lastY.fY + 1 <= fBounds.height()); 552045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fBounds.fBottom = fBounds.fTop + lastY.fY + 1; 553045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(lastY.fY + 1 == fBounds.height()); 554c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(!fBounds.isEmpty()); 555c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 556c90419199525141a5b98091f856e359bf9daf5b1reed@google.com return this->trimTopBottom() && this->trimLeftRight(); 557045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com} 558045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 559e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com/////////////////////////////////////////////////////////////////////////////// 560e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 561e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comvoid SkAAClip::freeRuns() { 56247ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com if (fRunHead) { 563e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(fRunHead->fRefCnt >= 1); 564e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (1 == sk_atomic_dec(&fRunHead->fRefCnt)) { 565e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com sk_free(fRunHead); 566e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 567e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 568e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 569e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 570e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comSkAAClip::SkAAClip() { 571e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fBounds.setEmpty(); 57247ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com fRunHead = NULL; 573e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 574e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 575e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comSkAAClip::SkAAClip(const SkAAClip& src) { 576045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkDEBUGCODE(fBounds.setEmpty();) // need this for validate 57747ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com fRunHead = NULL; 578e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com *this = src; 579e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 580e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 581e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comSkAAClip::~SkAAClip() { 582e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com this->freeRuns(); 583e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 584e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 585e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comSkAAClip& SkAAClip::operator=(const SkAAClip& src) { 586045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com AUTO_AACLIP_VALIDATE(*this); 587045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com src.validate(); 588045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 589e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (this != &src) { 590e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com this->freeRuns(); 591e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fBounds = src.fBounds; 592e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fRunHead = src.fRunHead; 59347ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com if (fRunHead) { 594e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com sk_atomic_inc(&fRunHead->fRefCnt); 595e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 596e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 597e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return *this; 598e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 599e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 600e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.combool operator==(const SkAAClip& a, const SkAAClip& b) { 601045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com a.validate(); 602045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com b.validate(); 603045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 604e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (&a == &b) { 605e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return true; 606e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 607e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (a.fBounds != b.fBounds) { 608e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return false; 609e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 610e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 611e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const SkAAClip::RunHead* ah = a.fRunHead; 612e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const SkAAClip::RunHead* bh = b.fRunHead; 613e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 614e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com // this catches empties and rects being equal 615e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (ah == bh) { 616e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return true; 617e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 618e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 619e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com // now we insist that both are complex (but different ptrs) 62047ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com if (!a.fRunHead || !b.fRunHead) { 621e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return false; 622e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 623e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 624e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return ah->fRowCount == bh->fRowCount && 625e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com ah->fDataSize == bh->fDataSize && 626e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com !memcmp(ah->data(), bh->data(), ah->fDataSize); 627e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 628e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 629e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comvoid SkAAClip::swap(SkAAClip& other) { 630045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com AUTO_AACLIP_VALIDATE(*this); 631045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com other.validate(); 632045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 633e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkTSwap(fBounds, other.fBounds); 634e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkTSwap(fRunHead, other.fRunHead); 635e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 636e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 637322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.combool SkAAClip::set(const SkAAClip& src) { 638322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com *this = src; 639322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return !this->isEmpty(); 640322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com} 641322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 642e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.combool SkAAClip::setEmpty() { 643e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com this->freeRuns(); 644e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fBounds.setEmpty(); 64547ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com fRunHead = NULL; 646e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return false; 647e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 648e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 649e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.combool SkAAClip::setRect(const SkIRect& bounds) { 650e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (bounds.isEmpty()) { 651e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return this->setEmpty(); 652e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 65347ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com 654045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com AUTO_AACLIP_VALIDATE(*this); 65547ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com 656045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com#if 0 65747ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com SkRect r; 65847ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com r.set(bounds); 65947ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com SkPath path; 66047ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com path.addRect(r); 66147ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com return this->setPath(path); 662045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com#else 663045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com this->freeRuns(); 664045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fBounds = bounds; 665045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fRunHead = RunHead::AllocRect(bounds); 666045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(!this->isEmpty()); 667045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return true; 668045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com#endif 669e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 670e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 671f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.combool SkAAClip::setRect(const SkRect& r, bool doAA) { 672e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (r.isEmpty()) { 673e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return this->setEmpty(); 674e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 675e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 676045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com AUTO_AACLIP_VALIDATE(*this); 677045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 678045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com // TODO: special case this 679045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 680e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkPath path; 681e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com path.addRect(r); 682f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com return this->setPath(path, NULL, doAA); 683f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com} 684f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com 685a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.comstatic void append_run(SkTDArray<uint8_t>& array, uint8_t value, int count) { 686a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com SkASSERT(count >= 0); 687a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com while (count > 0) { 688a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com int n = count; 689a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com if (n > 255) { 690a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com n = 255; 691a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com } 692a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com uint8_t* data = array.append(2); 693a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com data[0] = n; 694a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com data[1] = value; 695a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com count -= n; 696a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com } 697a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com} 698a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com 699f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.combool SkAAClip::setRegion(const SkRegion& rgn) { 700f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com if (rgn.isEmpty()) { 701f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com return this->setEmpty(); 702f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com } 703f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com if (rgn.isRect()) { 704f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com return this->setRect(rgn.getBounds()); 705f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com } 706a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com 707a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com#if 0 708f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com SkAAClip clip; 709f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com SkRegion::Iterator iter(rgn); 710f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com for (; !iter.done(); iter.next()) { 711f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com clip.op(iter.rect(), SkRegion::kUnion_Op); 712f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com } 713f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com this->swap(clip); 7143771a030b0b6686b0ec81359774836cc376ea3f4reed@google.com return !this->isEmpty(); 715a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com#else 716a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com const SkIRect& bounds = rgn.getBounds(); 717a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com const int offsetX = bounds.fLeft; 718a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com const int offsetY = bounds.fTop; 719a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com 720a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com SkTDArray<YOffset> yArray; 721a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com SkTDArray<uint8_t> xArray; 722a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com 723a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com yArray.setReserve(SkMin32(bounds.height(), 1024)); 724a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com xArray.setReserve(SkMin32(bounds.width() * 128, 64 * 1024)); 725a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com 726a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com SkRegion::Iterator iter(rgn); 727a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com int prevRight = 0; 728a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com int prevBot = 0; 729a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com YOffset* currY = NULL; 730a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com 731a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com for (; !iter.done(); iter.next()) { 732a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com const SkIRect& r = iter.rect(); 733a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com SkASSERT(bounds.contains(r)); 734a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com 735a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com int bot = r.fBottom - offsetY; 736a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com SkASSERT(bot >= prevBot); 737a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com if (bot > prevBot) { 738a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com if (currY) { 739a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com // flush current row 740a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com append_run(xArray, 0, bounds.width() - prevRight); 741a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com } 742a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com // did we introduce an empty-gap from the prev row? 743a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com int top = r.fTop - offsetY; 744a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com if (top > prevBot) { 745a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com currY = yArray.append(); 746a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com currY->fY = top - 1; 747a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com currY->fOffset = xArray.count(); 748a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com append_run(xArray, 0, bounds.width()); 749a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com } 750a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com // create a new record for this Y value 751a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com currY = yArray.append(); 752a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com currY->fY = bot - 1; 753a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com currY->fOffset = xArray.count(); 754a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com prevRight = 0; 755a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com prevBot = bot; 756a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com } 757a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com 758a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com int x = r.fLeft - offsetX; 759a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com append_run(xArray, 0, x - prevRight); 760a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com 761a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com int w = r.fRight - r.fLeft; 762a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com append_run(xArray, 0xFF, w); 763a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com prevRight = x + w; 764a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com SkASSERT(prevRight <= bounds.width()); 765a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com } 766a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com // flush last row 767a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com append_run(xArray, 0, bounds.width() - prevRight); 768a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com 769a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com // now pack everything into a RunHead 770a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com RunHead* head = RunHead::Alloc(yArray.count(), xArray.bytes()); 771a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com memcpy(head->yoffsets(), yArray.begin(), yArray.bytes()); 772a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com memcpy(head->data(), xArray.begin(), xArray.bytes()); 773a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com 774a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com this->setEmpty(); 775a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com fBounds = bounds; 776a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com fRunHead = head; 777a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com this->validate(); 778a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com return true; 779a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com#endif 780e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 781e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 782e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com/////////////////////////////////////////////////////////////////////////////// 783e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 784e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comconst uint8_t* SkAAClip::findRow(int y, int* lastYForRow) const { 78547ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com SkASSERT(fRunHead); 786e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 787e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (!y_in_rect(y, fBounds)) { 788e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return NULL; 789e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 790e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com y -= fBounds.y(); // our yoffs values are relative to the top 791e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 792e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const YOffset* yoff = fRunHead->yoffsets(); 793e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com while (yoff->fY < y) { 794e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com yoff += 1; 795e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(yoff - fRunHead->yoffsets() < fRunHead->fRowCount); 796e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 797e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 798e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (lastYForRow) { 799045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com *lastYForRow = fBounds.y() + yoff->fY; 800e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 801e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return fRunHead->data() + yoff->fOffset; 802e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 803e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 804e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comconst uint8_t* SkAAClip::findX(const uint8_t data[], int x, int* initialCount) const { 805e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(x_in_rect(x, fBounds)); 806e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com x -= fBounds.x(); 807e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 808e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com // first skip up to X 809e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com for (;;) { 810e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int n = data[0]; 811e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (x < n) { 812e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com *initialCount = n - x; 813e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com break; 814e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 815e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com data += 2; 816e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com x -= n; 817e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 818e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return data; 819e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 820e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 821e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.combool SkAAClip::quickContains(int left, int top, int right, int bottom) const { 822e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (this->isEmpty()) { 823e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return false; 824e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 825e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (!fBounds.contains(left, top, right, bottom)) { 826e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return false; 827e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 828322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com#if 0 829e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (this->isRect()) { 830e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return true; 831e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 832322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com#endif 833e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 834e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int lastY; 835e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const uint8_t* row = this->findRow(top, &lastY); 836e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (lastY < bottom) { 837e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return false; 838e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 839e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com // now just need to check in X 840045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com int count; 841045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com row = this->findX(row, left, &count); 842045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com#if 0 843045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return count >= (right - left) && 0xFF == row[1]; 844045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com#else 845045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com int rectWidth = right - left; 846045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com while (0xFF == row[1]) { 847045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (count >= rectWidth) { 848045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return true; 849045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 850045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com rectWidth -= count; 851045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com row += 2; 852045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com count = row[0]; 853045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 854045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return false; 855045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com#endif 856e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 857e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 858e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com/////////////////////////////////////////////////////////////////////////////// 859e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 860e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comclass SkAAClip::Builder { 861e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkIRect fBounds; 862e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com struct Row { 863e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int fY; 864e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int fWidth; 865e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkTDArray<uint8_t>* fData; 866e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com }; 867e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkTDArray<Row> fRows; 868e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com Row* fCurrRow; 869e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int fPrevY; 870e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int fWidth; 871209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com int fMinY; 872e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 873e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.compublic: 874e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com Builder(const SkIRect& bounds) : fBounds(bounds) { 875e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fPrevY = -1; 876e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fWidth = bounds.width(); 877e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fCurrRow = NULL; 878209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com fMinY = bounds.fTop; 879e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 880e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 881e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com ~Builder() { 882e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com Row* row = fRows.begin(); 883e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com Row* stop = fRows.end(); 884e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com while (row < stop) { 885e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com delete row->fData; 886e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com row += 1; 887e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 888e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 889e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 890322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com const SkIRect& getBounds() const { return fBounds; } 891322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 892e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com void addRun(int x, int y, U8CPU alpha, int count) { 893e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(count > 0); 894e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(fBounds.contains(x, y)); 895e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(fBounds.contains(x + count - 1, y)); 89680cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com 897e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com x -= fBounds.left(); 898e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com y -= fBounds.top(); 89980cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com 900e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com Row* row = fCurrRow; 901e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (y != fPrevY) { 902e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(y > fPrevY); 903e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fPrevY = y; 904e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com row = this->flushRow(true); 905e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com row->fY = y; 906e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com row->fWidth = 0; 907e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(row->fData); 908e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(0 == row->fData->count()); 909e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fCurrRow = row; 910e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 911e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 912e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(row->fWidth <= x); 913e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(row->fWidth < fBounds.width()); 914e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 915e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkTDArray<uint8_t>& data = *row->fData; 916e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 917e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int gap = x - row->fWidth; 918e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (gap) { 919e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com AppendRun(data, 0, gap); 920e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com row->fWidth += gap; 921e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(row->fWidth < fBounds.width()); 922e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 923e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 924e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com AppendRun(data, alpha, count); 925e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com row->fWidth += count; 926e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(row->fWidth <= fBounds.width()); 927e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 928e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 92949eac192faa35159752525b23345563252721c64tomhudson@google.com void addColumn(int x, int y, U8CPU alpha, int height) { 93049eac192faa35159752525b23345563252721c64tomhudson@google.com SkASSERT(fBounds.contains(x, y + height - 1)); 93149eac192faa35159752525b23345563252721c64tomhudson@google.com 93249eac192faa35159752525b23345563252721c64tomhudson@google.com this->addRun(x, y, alpha, 1); 93349eac192faa35159752525b23345563252721c64tomhudson@google.com this->flushRowH(fCurrRow); 93449eac192faa35159752525b23345563252721c64tomhudson@google.com y -= fBounds.fTop; 93549eac192faa35159752525b23345563252721c64tomhudson@google.com SkASSERT(y == fCurrRow->fY); 93649eac192faa35159752525b23345563252721c64tomhudson@google.com fCurrRow->fY = y + height - 1; 93749eac192faa35159752525b23345563252721c64tomhudson@google.com } 93849eac192faa35159752525b23345563252721c64tomhudson@google.com 9399154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com void addRectRun(int x, int y, int width, int height) { 9409154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com SkASSERT(fBounds.contains(x + width - 1, y + height - 1)); 9419154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com this->addRun(x, y, 0xFF, width); 9429154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com 943a89c77b5cafcc13d76cb07c3240e48705cb30d8freed@google.com // we assum the rect must be all we'll see for these scanlines 9449154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com // so we ensure our row goes all the way to our right 9459154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com this->flushRowH(fCurrRow); 9469154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com 9479154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com y -= fBounds.fTop; 9489154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com SkASSERT(y == fCurrRow->fY); 9499154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com fCurrRow->fY = y + height - 1; 9509154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com } 9519154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com 95249eac192faa35159752525b23345563252721c64tomhudson@google.com void addAntiRectRun(int x, int y, int width, int height, 95349eac192faa35159752525b23345563252721c64tomhudson@google.com SkAlpha leftAlpha, SkAlpha rightAlpha) { 95449eac192faa35159752525b23345563252721c64tomhudson@google.com SkASSERT(fBounds.contains(x + width - 1 + 95549eac192faa35159752525b23345563252721c64tomhudson@google.com (leftAlpha > 0 ? 1 : 0) + (rightAlpha > 0 ? 1 : 0), 95649eac192faa35159752525b23345563252721c64tomhudson@google.com y + height - 1)); 95749eac192faa35159752525b23345563252721c64tomhudson@google.com SkASSERT(width >= 0); 95849eac192faa35159752525b23345563252721c64tomhudson@google.com 95949eac192faa35159752525b23345563252721c64tomhudson@google.com // Conceptually we're always adding 3 runs, but we should 96049eac192faa35159752525b23345563252721c64tomhudson@google.com // merge or omit them if possible. 96149eac192faa35159752525b23345563252721c64tomhudson@google.com if (leftAlpha == 0xFF) { 96249eac192faa35159752525b23345563252721c64tomhudson@google.com width++; 96349eac192faa35159752525b23345563252721c64tomhudson@google.com } else if (leftAlpha > 0) { 96449eac192faa35159752525b23345563252721c64tomhudson@google.com this->addRun(x++, y, leftAlpha, 1); 96549eac192faa35159752525b23345563252721c64tomhudson@google.com } 96649eac192faa35159752525b23345563252721c64tomhudson@google.com if (rightAlpha == 0xFF) { 96749eac192faa35159752525b23345563252721c64tomhudson@google.com width++; 96849eac192faa35159752525b23345563252721c64tomhudson@google.com } 96949eac192faa35159752525b23345563252721c64tomhudson@google.com if (width > 0) { 97049eac192faa35159752525b23345563252721c64tomhudson@google.com this->addRun(x, y, 0xFF, width); 97149eac192faa35159752525b23345563252721c64tomhudson@google.com } 97249eac192faa35159752525b23345563252721c64tomhudson@google.com if (rightAlpha > 0 && rightAlpha < 255) { 97349eac192faa35159752525b23345563252721c64tomhudson@google.com this->addRun(x + width, y, rightAlpha, 1); 97449eac192faa35159752525b23345563252721c64tomhudson@google.com } 97549eac192faa35159752525b23345563252721c64tomhudson@google.com 97649eac192faa35159752525b23345563252721c64tomhudson@google.com // we assume the rect must be all we'll see for these scanlines 97749eac192faa35159752525b23345563252721c64tomhudson@google.com // so we ensure our row goes all the way to our right 97849eac192faa35159752525b23345563252721c64tomhudson@google.com this->flushRowH(fCurrRow); 97949eac192faa35159752525b23345563252721c64tomhudson@google.com 98049eac192faa35159752525b23345563252721c64tomhudson@google.com y -= fBounds.fTop; 98149eac192faa35159752525b23345563252721c64tomhudson@google.com SkASSERT(y == fCurrRow->fY); 98249eac192faa35159752525b23345563252721c64tomhudson@google.com fCurrRow->fY = y + height - 1; 98349eac192faa35159752525b23345563252721c64tomhudson@google.com } 98449eac192faa35159752525b23345563252721c64tomhudson@google.com 985045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com bool finish(SkAAClip* target) { 986e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com this->flushRow(false); 987e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 988e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const Row* row = fRows.begin(); 989e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const Row* stop = fRows.end(); 990e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 991e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com size_t dataSize = 0; 992e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com while (row < stop) { 993e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com dataSize += row->fData->count(); 994e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com row += 1; 995e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 996e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 997045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (0 == dataSize) { 998045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return target->setEmpty(); 999045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1000045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1001209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com SkASSERT(fMinY >= fBounds.fTop); 1002209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com SkASSERT(fMinY < fBounds.fBottom); 1003209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com int adjustY = fMinY - fBounds.fTop; 1004209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com fBounds.fTop = fMinY; 1005209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com 1006e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com RunHead* head = RunHead::Alloc(fRows.count(), dataSize); 1007e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com YOffset* yoffset = head->yoffsets(); 1008e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com uint8_t* data = head->data(); 1009e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com uint8_t* baseData = data; 1010e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1011e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com row = fRows.begin(); 1012c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkDEBUGCODE(int prevY = row->fY - 1;) 1013e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com while (row < stop) { 1014c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(prevY < row->fY); // must be monotonic 1015c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkDEBUGCODE(prevY = row->fY); 1016c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 1017209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com yoffset->fY = row->fY - adjustY; 1018e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com yoffset->fOffset = data - baseData; 1019e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com yoffset += 1; 1020e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1021e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com size_t n = row->fData->count(); 1022e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com memcpy(data, row->fData->begin(), n); 1023c90419199525141a5b98091f856e359bf9daf5b1reed@google.com#ifdef SK_DEBUG 1024f74ad8c91aef4f328dbcbcebae9e436c00a35140tomhudson@google.com size_t bytesNeeded = compute_row_length(data, fBounds.width()); 1025c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(bytesNeeded == n); 1026c90419199525141a5b98091f856e359bf9daf5b1reed@google.com#endif 1027e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com data += n; 1028e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1029e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com row += 1; 1030e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1031e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1032045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com target->freeRuns(); 1033045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com target->fBounds = fBounds; 1034045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com target->fRunHead = head; 1035045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return target->trimBounds(); 1036e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1037e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1038e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com void dump() { 1039e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com this->validate(); 1040e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int y; 1041e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com for (y = 0; y < fRows.count(); ++y) { 1042e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const Row& row = fRows[y]; 1043e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkDebugf("Y:%3d W:%3d", row.fY, row.fWidth); 1044e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const SkTDArray<uint8_t>& data = *row.fData; 1045e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int count = data.count(); 1046e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(!(count & 1)); 1047e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const uint8_t* ptr = data.begin(); 1048e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com for (int x = 0; x < count; x += 2) { 1049e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkDebugf(" [%3d:%02X]", ptr[0], ptr[1]); 1050e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com ptr += 2; 1051e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1052e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkDebugf("\n"); 1053e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1054e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1055e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1056e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com void validate() { 1057e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com#ifdef SK_DEBUG 1058e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int prevY = -1; 1059e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com for (int i = 0; i < fRows.count(); ++i) { 1060e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const Row& row = fRows[i]; 1061e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(prevY < row.fY); 1062e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(fWidth == row.fWidth); 1063e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int count = row.fData->count(); 1064e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const uint8_t* ptr = row.fData->begin(); 1065e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(!(count & 1)); 1066e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int w = 0; 1067e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com for (int x = 0; x < count; x += 2) { 1068d6040f6f2fcb11fddad5d92b3cb7255e90931bccreed@google.com int n = ptr[0]; 1069d6040f6f2fcb11fddad5d92b3cb7255e90931bccreed@google.com SkASSERT(n > 0); 1070d6040f6f2fcb11fddad5d92b3cb7255e90931bccreed@google.com w += n; 1071e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(w <= fWidth); 1072e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com ptr += 2; 1073e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1074e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(w == fWidth); 1075e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com prevY = row.fY; 1076e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1077e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com#endif 1078e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1079e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1080209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com // only called by BuilderBlitter 1081209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com void setMinY(int y) { 1082209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com fMinY = y; 1083209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com } 1084209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com 1085e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comprivate: 10869154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com void flushRowH(Row* row) { 10879154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com // flush current row if needed 10889154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com if (row->fWidth < fWidth) { 10899154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com AppendRun(*row->fData, 0, fWidth - row->fWidth); 10909154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com row->fWidth = fWidth; 10919154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com } 10929154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com } 1093209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com 1094e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com Row* flushRow(bool readyForAnother) { 1095e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com Row* next = NULL; 1096e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int count = fRows.count(); 1097e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (count > 0) { 10989154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com this->flushRowH(&fRows[count - 1]); 1099e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1100e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (count > 1) { 1101e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com // are our last two runs the same? 1102e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com Row* prev = &fRows[count - 2]; 1103e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com Row* curr = &fRows[count - 1]; 1104e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(prev->fWidth == fWidth); 1105e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(curr->fWidth == fWidth); 1106e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (*prev->fData == *curr->fData) { 1107e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com prev->fY = curr->fY; 1108e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (readyForAnother) { 1109e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com curr->fData->rewind(); 1110e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com next = curr; 1111e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } else { 1112e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com delete curr->fData; 1113e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fRows.removeShuffle(count - 1); 1114e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1115e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } else { 1116e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (readyForAnother) { 1117e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com next = fRows.append(); 1118e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com next->fData = new SkTDArray<uint8_t>; 1119e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1120e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1121e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } else { 1122e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (readyForAnother) { 1123e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com next = fRows.append(); 1124e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com next->fData = new SkTDArray<uint8_t>; 1125e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1126e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1127e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return next; 1128e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1129e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1130e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com static void AppendRun(SkTDArray<uint8_t>& data, U8CPU alpha, int count) { 1131e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com do { 1132e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int n = count; 1133e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (n > 255) { 1134e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com n = 255; 1135e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1136e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com uint8_t* ptr = data.append(2); 1137e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com ptr[0] = n; 1138e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com ptr[1] = alpha; 1139e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com count -= n; 1140e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } while (count > 0); 1141e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1142e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}; 1143e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1144e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comclass SkAAClip::BuilderBlitter : public SkBlitter { 114580cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com int fLastY; 114680cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com 114780cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com /* 114880cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com If we see a gap of 1 or more empty scanlines while building in Y-order, 114980cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com we inject an explicit empty scanline (alpha==0) 115080cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com 115180cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com See AAClipTest.cpp : test_path_with_hole() 115280cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com */ 115380cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com void checkForYGap(int y) { 115480cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com SkASSERT(y >= fLastY); 115580cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com if (fLastY > -SK_MaxS32) { 115680cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com int gap = y - fLastY; 115780cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com if (gap > 1) { 115880cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com fBuilder->addRun(fLeft, y - 1, 0, fRight - fLeft); 115980cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com } 116080cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com } 116180cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com fLastY = y; 116280cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com } 116380cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com 1164e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.compublic: 116580cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com 1166e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com BuilderBlitter(Builder* builder) { 1167e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fBuilder = builder; 11681778564c75de5799d45126984f8faafd03523100reed@google.com fLeft = builder->getBounds().fLeft; 11691778564c75de5799d45126984f8faafd03523100reed@google.com fRight = builder->getBounds().fRight; 1170209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com fMinY = SK_MaxS32; 117180cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com fLastY = -SK_MaxS32; // sentinel 1172209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com } 1173209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com 1174209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com void finish() { 1175209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com if (fMinY < SK_MaxS32) { 1176209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com fBuilder->setMinY(fMinY); 1177209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com } 1178e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1179e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 118049eac192faa35159752525b23345563252721c64tomhudson@google.com /** 118149eac192faa35159752525b23345563252721c64tomhudson@google.com Must evaluate clips in scan-line order, so don't want to allow blitV(), 118249eac192faa35159752525b23345563252721c64tomhudson@google.com but an AAClip can be clipped down to a single pixel wide, so we 118349eac192faa35159752525b23345563252721c64tomhudson@google.com must support it (given AntiRect semantics: minimum width is 2). 118449eac192faa35159752525b23345563252721c64tomhudson@google.com Instead we'll rely on the runtime asserts to guarantee Y monotonicity; 118549eac192faa35159752525b23345563252721c64tomhudson@google.com any failure cases that misses may have minor artifacts. 118649eac192faa35159752525b23345563252721c64tomhudson@google.com */ 118749eac192faa35159752525b23345563252721c64tomhudson@google.com virtual void blitV(int x, int y, int height, SkAlpha alpha) SK_OVERRIDE { 118849eac192faa35159752525b23345563252721c64tomhudson@google.com this->recordMinY(y); 118949eac192faa35159752525b23345563252721c64tomhudson@google.com fBuilder->addColumn(x, y, alpha, height); 119049eac192faa35159752525b23345563252721c64tomhudson@google.com } 1191045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1192562a2ac95b8cd8b359574f8c4d6300b0475938dbreed@google.com virtual void blitRect(int x, int y, int width, int height) SK_OVERRIDE { 11939154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com this->recordMinY(y); 119480cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com this->checkForYGap(y); 11959154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com fBuilder->addRectRun(x, y, width, height); 1196562a2ac95b8cd8b359574f8c4d6300b0475938dbreed@google.com } 1197045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 119849eac192faa35159752525b23345563252721c64tomhudson@google.com virtual void blitAntiRect(int x, int y, int width, int height, 119949eac192faa35159752525b23345563252721c64tomhudson@google.com SkAlpha leftAlpha, SkAlpha rightAlpha) SK_OVERRIDE { 120049eac192faa35159752525b23345563252721c64tomhudson@google.com this->recordMinY(y); 120149eac192faa35159752525b23345563252721c64tomhudson@google.com fBuilder->addAntiRectRun(x, y, width, height, leftAlpha, rightAlpha); 120249eac192faa35159752525b23345563252721c64tomhudson@google.com } 120349eac192faa35159752525b23345563252721c64tomhudson@google.com 1204e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com virtual void blitMask(const SkMask&, const SkIRect& clip) SK_OVERRIDE 1205e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com { unexpected(); } 1206e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1207e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com virtual const SkBitmap* justAnOpaqueColor(uint32_t*) SK_OVERRIDE { 12083771a030b0b6686b0ec81359774836cc376ea3f4reed@google.com return NULL; 1209e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1210e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1211e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com virtual void blitH(int x, int y, int width) SK_OVERRIDE { 1212209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com this->recordMinY(y); 121380cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com this->checkForYGap(y); 1214e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fBuilder->addRun(x, y, 0xFF, width); 1215e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1216e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1217e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com virtual void blitAntiH(int x, int y, const SkAlpha alpha[], 1218e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const int16_t runs[]) SK_OVERRIDE { 1219209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com this->recordMinY(y); 122080cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com this->checkForYGap(y); 1221e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com for (;;) { 1222e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int count = *runs; 1223e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (count <= 0) { 1224e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return; 1225e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 12261778564c75de5799d45126984f8faafd03523100reed@google.com 12271778564c75de5799d45126984f8faafd03523100reed@google.com // The supersampler's buffer can be the width of the device, so 12281778564c75de5799d45126984f8faafd03523100reed@google.com // we may have to trim the run to our bounds. If so, we assert that 12291778564c75de5799d45126984f8faafd03523100reed@google.com // the extra spans are always alpha==0 12301778564c75de5799d45126984f8faafd03523100reed@google.com int localX = x; 12311778564c75de5799d45126984f8faafd03523100reed@google.com int localCount = count; 12321778564c75de5799d45126984f8faafd03523100reed@google.com if (x < fLeft) { 12331778564c75de5799d45126984f8faafd03523100reed@google.com SkASSERT(0 == *alpha); 12341778564c75de5799d45126984f8faafd03523100reed@google.com int gap = fLeft - x; 12351778564c75de5799d45126984f8faafd03523100reed@google.com SkASSERT(gap <= count); 12361778564c75de5799d45126984f8faafd03523100reed@google.com localX += gap; 12371778564c75de5799d45126984f8faafd03523100reed@google.com localCount -= gap; 12381778564c75de5799d45126984f8faafd03523100reed@google.com } 12391778564c75de5799d45126984f8faafd03523100reed@google.com int right = x + count; 12401778564c75de5799d45126984f8faafd03523100reed@google.com if (right > fRight) { 12411778564c75de5799d45126984f8faafd03523100reed@google.com SkASSERT(0 == *alpha); 12421778564c75de5799d45126984f8faafd03523100reed@google.com localCount -= right - fRight; 12431778564c75de5799d45126984f8faafd03523100reed@google.com SkASSERT(localCount >= 0); 12441778564c75de5799d45126984f8faafd03523100reed@google.com } 12451778564c75de5799d45126984f8faafd03523100reed@google.com 12461778564c75de5799d45126984f8faafd03523100reed@google.com if (localCount) { 12471778564c75de5799d45126984f8faafd03523100reed@google.com fBuilder->addRun(localX, y, *alpha, localCount); 12481778564c75de5799d45126984f8faafd03523100reed@google.com } 1249820e80ad6390e120d4991a5280d0452ec87beaebbsalomon@google.com // Next run 1250e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com runs += count; 1251e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com alpha += count; 1252e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com x += count; 1253e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1254e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1255e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1256e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comprivate: 1257e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com Builder* fBuilder; 12581778564c75de5799d45126984f8faafd03523100reed@google.com int fLeft; // cache of builder's bounds' left edge 12591778564c75de5799d45126984f8faafd03523100reed@google.com int fRight; 1260209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com int fMinY; 1261209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com 1262209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com /* 1263209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com * We track this, in case the scan converter skipped some number of 1264209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com * scanlines at the (relative to the bounds it was given). This allows 1265209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com * the builder, during its finish, to trip its bounds down to the "real" 1266209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com * top. 1267209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com */ 1268209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com void recordMinY(int y) { 1269209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com if (y < fMinY) { 1270209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com fMinY = y; 1271209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com } 1272209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com } 1273e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1274e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com void unexpected() { 1275e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkDebugf("---- did not expect to get called here"); 1276e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com sk_throw(); 1277e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1278e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}; 1279e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1280f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.combool SkAAClip::setPath(const SkPath& path, const SkRegion* clip, bool doAA) { 1281045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com AUTO_AACLIP_VALIDATE(*this); 1282045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1283322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com if (clip && clip->isEmpty()) { 1284e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return this->setEmpty(); 1285e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1286e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1287e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkIRect ibounds; 1288322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com path.getBounds().roundOut(&ibounds); 1289e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1290322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com SkRegion tmpClip; 1291322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com if (NULL == clip) { 1292322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com tmpClip.setRect(ibounds); 1293322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com clip = &tmpClip; 1294322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1295322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1296045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (path.isInverseFillType()) { 1297045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com ibounds = clip->getBounds(); 1298045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } else { 1299322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com if (ibounds.isEmpty() || !ibounds.intersect(clip->getBounds())) { 1300e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return this->setEmpty(); 1301e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1302e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1303e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1304e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com Builder builder(ibounds); 1305e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com BuilderBlitter blitter(&builder); 1306e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1307f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com if (doAA) { 1308f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com SkScan::AntiFillPath(path, *clip, &blitter, true); 1309f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com } else { 1310f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com SkScan::FillPath(path, *clip, &blitter); 1311f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com } 1312e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1313209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com blitter.finish(); 1314045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return builder.finish(this); 1315e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 1316e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1317e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com/////////////////////////////////////////////////////////////////////////////// 1318e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1319322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comtypedef void (*RowProc)(SkAAClip::Builder&, int bottom, 1320322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com const uint8_t* rowA, const SkIRect& rectA, 1321322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com const uint8_t* rowB, const SkIRect& rectB); 1322322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1323322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comstatic void sectRowProc(SkAAClip::Builder& builder, int bottom, 1324322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com const uint8_t* rowA, const SkIRect& rectA, 1325322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com const uint8_t* rowB, const SkIRect& rectB) { 1326322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1327322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com} 1328322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1329322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comtypedef U8CPU (*AlphaProc)(U8CPU alphaA, U8CPU alphaB); 1330322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1331322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comstatic U8CPU sectAlphaProc(U8CPU alphaA, U8CPU alphaB) { 1332322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com // Multiply 1333322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return SkMulDiv255Round(alphaA, alphaB); 1334322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com} 1335322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1336322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comstatic U8CPU unionAlphaProc(U8CPU alphaA, U8CPU alphaB) { 1337322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com // SrcOver 1338322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return alphaA + alphaB - SkMulDiv255Round(alphaA, alphaB); 1339322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com} 1340322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1341322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comstatic U8CPU diffAlphaProc(U8CPU alphaA, U8CPU alphaB) { 1342322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com // SrcOut 1343322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return SkMulDiv255Round(alphaA, 0xFF - alphaB); 1344322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com} 1345322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1346322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comstatic U8CPU xorAlphaProc(U8CPU alphaA, U8CPU alphaB) { 1347322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com // XOR 1348322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return alphaA + alphaB - 2 * SkMulDiv255Round(alphaA, alphaB); 1349322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com} 1350322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1351322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comstatic AlphaProc find_alpha_proc(SkRegion::Op op) { 1352322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com switch (op) { 1353322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com case SkRegion::kIntersect_Op: 1354322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return sectAlphaProc; 1355322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com case SkRegion::kDifference_Op: 1356322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return diffAlphaProc; 1357322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com case SkRegion::kUnion_Op: 1358322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return unionAlphaProc; 1359322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com case SkRegion::kXOR_Op: 1360322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return xorAlphaProc; 1361322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com default: 13620c00f21fee3f5cfa3aa7e5d46ff94cb8cf340451tomhudson@google.com SkDEBUGFAIL("unexpected region op"); 1363322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return sectAlphaProc; 1364322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1365322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com} 1366322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1367322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comstatic const uint8_t gEmptyRow[] = { 1368322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 1369322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 1370322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 1371322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 1372322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 1373322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 1374322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 1375322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 1376322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com}; 1377322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1378322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comclass RowIter { 1379322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.compublic: 1380322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com RowIter(const uint8_t* row, const SkIRect& bounds) { 1381322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com fRow = row; 1382322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com fLeft = bounds.fLeft; 1383322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com fBoundsRight = bounds.fRight; 13841c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (row) { 13851c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fRight = bounds.fLeft + row[0]; 13861c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com SkASSERT(fRight <= fBoundsRight); 13871c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fAlpha = row[1]; 13881c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fDone = false; 13891c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } else { 13901c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fDone = true; 13911c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fRight = kMaxInt32; 13921c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fAlpha = 0; 13931c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } 1394322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1395322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1396322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com bool done() const { return fDone; } 13971c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com int left() const { return fLeft; } 13981c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com int right() const { return fRight; } 13991c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com U8CPU alpha() const { return fAlpha; } 1400322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com void next() { 14011c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (!fDone) { 1402322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com fLeft = fRight; 14031c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (fRight == fBoundsRight) { 14041c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fDone = true; 14051c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fRight = kMaxInt32; 14061c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fAlpha = 0; 14071c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } else { 14081c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fRow += 2; 14091c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fRight += fRow[0]; 14101c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fAlpha = fRow[1]; 14111c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com SkASSERT(fRight <= fBoundsRight); 14121c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } 1413322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1414322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1415322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1416322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comprivate: 1417322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com const uint8_t* fRow; 1418322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com int fLeft; 1419322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com int fRight; 1420322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com int fBoundsRight; 1421322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com bool fDone; 14221c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com uint8_t fAlpha; 1423322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com}; 1424322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 14251c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.comstatic void adjust_row(RowIter& iter, int& leftA, int& riteA, int rite) { 14261c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (rite == riteA) { 14271c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com iter.next(); 14281c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com leftA = iter.left(); 14291c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com riteA = iter.right(); 1430322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1431322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com} 1432322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 14331c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.comstatic bool intersect(int& min, int& max, int boundsMin, int boundsMax) { 14341c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com SkASSERT(min < max); 14351c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com SkASSERT(boundsMin < boundsMax); 14361c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (min >= boundsMax || max <= boundsMin) { 14371c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com return false; 14381c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } 14391c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (min < boundsMin) { 14401c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com min = boundsMin; 14411c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } 14421c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (max > boundsMax) { 14431c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com max = boundsMax; 14441c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } 14451c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com return true; 14461c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com} 14471c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com 1448322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comstatic void operatorX(SkAAClip::Builder& builder, int lastY, 1449322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com RowIter& iterA, RowIter& iterB, 1450322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com AlphaProc proc, const SkIRect& bounds) { 1451322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com int leftA = iterA.left(); 1452322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com int riteA = iterA.right(); 1453322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com int leftB = iterB.left(); 1454322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com int riteB = iterB.right(); 1455322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 14561c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com int prevRite = bounds.fLeft; 14571c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com 14581c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com do { 1459322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com U8CPU alphaA = 0; 1460322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com U8CPU alphaB = 0; 1461322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com int left, rite; 14621c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com 14631c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (leftA < leftB) { 1464322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com left = leftA; 1465322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com alphaA = iterA.alpha(); 14661c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (riteA <= leftB) { 14671c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com rite = riteA; 14681c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } else { 14691c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com rite = leftA = leftB; 14701c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } 14711c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } else if (leftB < leftA) { 1472322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com left = leftB; 1473322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com alphaB = iterB.alpha(); 14741c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (riteB <= leftA) { 14751c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com rite = riteB; 14761c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } else { 14771c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com rite = leftB = leftA; 14781c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } 1479322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } else { 14801c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com left = leftA; // or leftB, since leftA == leftB 14811c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com rite = leftA = leftB = SkMin32(riteA, riteB); 1482322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com alphaA = iterA.alpha(); 1483322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com alphaB = iterB.alpha(); 1484322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1485322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1486322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com if (left >= bounds.fRight) { 1487322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com break; 1488322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 148934f7e47a3593911d03307a08e5af625b218ceec3reed@google.com if (rite > bounds.fRight) { 149034f7e47a3593911d03307a08e5af625b218ceec3reed@google.com rite = bounds.fRight; 149134f7e47a3593911d03307a08e5af625b218ceec3reed@google.com } 149234f7e47a3593911d03307a08e5af625b218ceec3reed@google.com 1493322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com if (left >= bounds.fLeft) { 14941c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com SkASSERT(rite > left); 1495322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com builder.addRun(left, lastY, proc(alphaA, alphaB), rite - left); 14961c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com prevRite = rite; 1497322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 14981c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com 14991c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com adjust_row(iterA, leftA, riteA, rite); 15001c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com adjust_row(iterB, leftB, riteB, rite); 15011c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } while (!iterA.done() || !iterB.done()); 15021c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com 15031c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (prevRite < bounds.fRight) { 15041c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com builder.addRun(prevRite, lastY, 0, bounds.fRight - prevRite); 1505322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1506322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com} 1507322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 15081c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.comstatic void adjust_iter(SkAAClip::Iter& iter, int& topA, int& botA, int bot) { 15091c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (bot == botA) { 15101c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com iter.next(); 15111c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com topA = botA; 15121c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com SkASSERT(botA == iter.top()); 15131c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com botA = iter.bottom(); 1514322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1515322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com} 1516322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1517322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comstatic void operateY(SkAAClip::Builder& builder, const SkAAClip& A, 1518322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com const SkAAClip& B, SkRegion::Op op) { 1519322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com AlphaProc proc = find_alpha_proc(op); 1520322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com const SkIRect& bounds = builder.getBounds(); 1521322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1522322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com SkAAClip::Iter iterA(A); 1523322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com SkAAClip::Iter iterB(B); 1524322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1525322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com SkASSERT(!iterA.done()); 1526322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com int topA = iterA.top(); 1527322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com int botA = iterA.bottom(); 1528322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com SkASSERT(!iterB.done()); 1529322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com int topB = iterB.top(); 1530322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com int botB = iterB.bottom(); 1531322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 15321c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com do { 15331c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com const uint8_t* rowA = NULL; 15341c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com const uint8_t* rowB = NULL; 1535322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com int top, bot; 15361c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com 15371c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (topA < topB) { 1538322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com top = topA; 1539322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com rowA = iterA.data(); 15401c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (botA <= topB) { 15411c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com bot = botA; 15421c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } else { 15431c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com bot = topA = topB; 15441c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } 15451c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com 15461c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } else if (topB < topA) { 1547322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com top = topB; 1548322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com rowB = iterB.data(); 15491c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (botB <= topA) { 15501c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com bot = botB; 15511c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } else { 15521c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com bot = topB = topA; 15531c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } 1554322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } else { 15551c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com top = topA; // or topB, since topA == topB 15561c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com bot = topA = topB = SkMin32(botA, botB); 1557322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com rowA = iterA.data(); 1558322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com rowB = iterB.data(); 1559322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1560322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1561322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com if (top >= bounds.fBottom) { 1562322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com break; 1563322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 156434f7e47a3593911d03307a08e5af625b218ceec3reed@google.com 156534f7e47a3593911d03307a08e5af625b218ceec3reed@google.com if (bot > bounds.fBottom) { 156634f7e47a3593911d03307a08e5af625b218ceec3reed@google.com bot = bounds.fBottom; 156734f7e47a3593911d03307a08e5af625b218ceec3reed@google.com } 156834f7e47a3593911d03307a08e5af625b218ceec3reed@google.com SkASSERT(top < bot); 156934f7e47a3593911d03307a08e5af625b218ceec3reed@google.com 15701c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (!rowA && !rowB) { 15711c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com builder.addRun(bounds.fLeft, bot - 1, 0, bounds.width()); 15721c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } else if (top >= bounds.fTop) { 15731c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com SkASSERT(bot <= bounds.fBottom); 15741c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com RowIter rowIterA(rowA, rowA ? A.getBounds() : bounds); 15751c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com RowIter rowIterB(rowB, rowB ? B.getBounds() : bounds); 1576322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com operatorX(builder, bot - 1, rowIterA, rowIterB, proc, bounds); 1577322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1578322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 15791c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com adjust_iter(iterA, topA, botA, bot); 15801c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com adjust_iter(iterB, topB, botB, bot); 15811c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } while (!iterA.done() || !iterB.done()); 1582322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com} 1583322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1584322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.combool SkAAClip::op(const SkAAClip& clipAOrig, const SkAAClip& clipBOrig, 1585322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com SkRegion::Op op) { 1586045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com AUTO_AACLIP_VALIDATE(*this); 1587045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1588322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com if (SkRegion::kReplace_Op == op) { 1589322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return this->set(clipBOrig); 1590322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1591322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1592322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com const SkAAClip* clipA = &clipAOrig; 1593322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com const SkAAClip* clipB = &clipBOrig; 1594322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1595322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com if (SkRegion::kReverseDifference_Op == op) { 1596322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com SkTSwap(clipA, clipB); 1597322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com op = SkRegion::kDifference_Op; 1598322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1599322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1600322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com bool a_empty = clipA->isEmpty(); 1601322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com bool b_empty = clipB->isEmpty(); 1602322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1603322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com SkIRect bounds; 1604322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com switch (op) { 1605322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com case SkRegion::kDifference_Op: 1606322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com if (a_empty) { 1607322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return this->setEmpty(); 1608322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1609322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com if (b_empty || !SkIRect::Intersects(clipA->fBounds, clipB->fBounds)) { 1610322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return this->set(*clipA); 1611322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1612322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com bounds = clipA->fBounds; 1613322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com break; 1614322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1615322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com case SkRegion::kIntersect_Op: 1616322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com if ((a_empty | b_empty) || !bounds.intersect(clipA->fBounds, 1617322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com clipB->fBounds)) { 1618322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return this->setEmpty(); 1619322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1620322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com break; 1621322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1622322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com case SkRegion::kUnion_Op: 1623322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com case SkRegion::kXOR_Op: 1624322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com if (a_empty) { 1625322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return this->set(*clipB); 1626322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1627322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com if (b_empty) { 1628322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return this->set(*clipA); 1629322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1630322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com bounds = clipA->fBounds; 1631322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com bounds.join(clipB->fBounds); 1632322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com break; 1633322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1634322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com default: 16350c00f21fee3f5cfa3aa7e5d46ff94cb8cf340451tomhudson@google.com SkDEBUGFAIL("unknown region op"); 1636322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return !this->isEmpty(); 1637322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1638322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1639322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com SkASSERT(SkIRect::Intersects(bounds, clipB->fBounds)); 1640322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com SkASSERT(SkIRect::Intersects(bounds, clipB->fBounds)); 1641322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1642322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com Builder builder(bounds); 1643322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com operateY(builder, *clipA, *clipB, op); 1644045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1645045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return builder.finish(this); 1646e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 1647e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1648045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com/* 1649045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com * It can be expensive to build a local aaclip before applying the op, so 1650045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com * we first see if we can restrict the bounds of new rect to our current 1651045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com * bounds, or note that the new rect subsumes our current clip. 1652045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com */ 1653045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1654045e62d715f5ee9b03deb5af3c750f8318096179reed@google.combool SkAAClip::op(const SkIRect& rOrig, SkRegion::Op op) { 1655045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkIRect rStorage; 1656045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const SkIRect* r = &rOrig; 1657045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1658045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com switch (op) { 1659045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com case SkRegion::kIntersect_Op: 1660045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (!rStorage.intersect(rOrig, fBounds)) { 1661045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com // no overlap, so we're empty 1662045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return this->setEmpty(); 1663045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1664045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (rStorage == fBounds) { 1665045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com // we were wholly inside the rect, no change 1666045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return !this->isEmpty(); 1667045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1668045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (this->quickContains(rStorage)) { 1669045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com // the intersection is wholly inside us, we're a rect 1670045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return this->setRect(rStorage); 1671045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1672045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com r = &rStorage; // use the intersected bounds 1673045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com break; 1674045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com case SkRegion::kDifference_Op: 1675045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com break; 1676045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com case SkRegion::kUnion_Op: 1677045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (rOrig.contains(fBounds)) { 1678045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return this->setRect(rOrig); 1679045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1680045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com break; 1681045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com default: 1682045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com break; 1683045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1684045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 168547ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com SkAAClip clip; 1686045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com clip.setRect(*r); 168747ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com return this->op(*this, clip, op); 168847ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com} 168947ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com 1690045e62d715f5ee9b03deb5af3c750f8318096179reed@google.combool SkAAClip::op(const SkRect& rOrig, SkRegion::Op op, bool doAA) { 1691045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkRect rStorage, boundsStorage; 1692045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const SkRect* r = &rOrig; 1693045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1694045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com boundsStorage.set(fBounds); 1695045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com switch (op) { 1696045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com case SkRegion::kIntersect_Op: 1697045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com case SkRegion::kDifference_Op: 1698045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (!rStorage.intersect(rOrig, boundsStorage)) { 1699045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return this->setEmpty(); 1700045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1701045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com r = &rStorage; // use the intersected bounds 1702045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com break; 1703045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com case SkRegion::kUnion_Op: 1704045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (rOrig.contains(boundsStorage)) { 1705045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return this->setRect(rOrig); 1706045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1707045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com break; 1708045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com default: 1709045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com break; 1710045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1711045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 171247ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com SkAAClip clip; 1713045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com clip.setRect(*r, doAA); 171447ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com return this->op(*this, clip, op); 171547ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com} 171647ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com 171747ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.combool SkAAClip::op(const SkAAClip& clip, SkRegion::Op op) { 171847ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com return this->op(*this, clip, op); 171947ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com} 172047ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com 1721e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com/////////////////////////////////////////////////////////////////////////////// 1722045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1723045e62d715f5ee9b03deb5af3c750f8318096179reed@google.combool SkAAClip::translate(int dx, int dy, SkAAClip* dst) const { 1724045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (NULL == dst) { 1725045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return !this->isEmpty(); 1726045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1727045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1728045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (this->isEmpty()) { 1729045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return dst->setEmpty(); 1730045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1731045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1732045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (this != dst) { 1733045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com sk_atomic_inc(&fRunHead->fRefCnt); 1734045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com dst->fRunHead = fRunHead; 1735045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com dst->fBounds = fBounds; 1736045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1737045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com dst->fBounds.offset(dx, dy); 1738045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return true; 1739045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com} 1740045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1741045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comstatic void expand_row_to_mask(uint8_t* SK_RESTRICT mask, 1742045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const uint8_t* SK_RESTRICT row, 1743045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com int width) { 1744045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com while (width > 0) { 1745045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com int n = row[0]; 1746045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(width >= n); 1747045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com memset(mask, row[1], n); 1748045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com mask += n; 1749045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com row += 2; 1750045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com width -= n; 1751045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1752a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com SkASSERT(0 == width); 1753045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com} 1754045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1755045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comvoid SkAAClip::copyToMask(SkMask* mask) const { 1756045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com mask->fFormat = SkMask::kA8_Format; 1757045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (this->isEmpty()) { 1758045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com mask->fBounds.setEmpty(); 1759045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com mask->fImage = NULL; 1760045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com mask->fRowBytes = 0; 1761045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return; 1762045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1763045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1764045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com mask->fBounds = fBounds; 1765045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com mask->fRowBytes = fBounds.width(); 1766045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com size_t size = mask->computeImageSize(); 1767045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com mask->fImage = SkMask::AllocImage(size); 1768045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1769045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com Iter iter(*this); 1770045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com uint8_t* dst = mask->fImage; 1771045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const int width = fBounds.width(); 1772045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1773045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com int y = fBounds.fTop; 1774045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com while (!iter.done()) { 1775045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com do { 1776045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com expand_row_to_mask(dst, iter.data(), width); 1777045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com dst += mask->fRowBytes; 1778045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } while (++y < iter.bottom()); 1779045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com iter.next(); 1780045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1781045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com} 1782045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1783045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com/////////////////////////////////////////////////////////////////////////////// 1784e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com/////////////////////////////////////////////////////////////////////////////// 1785e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1786e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comstatic void expandToRuns(const uint8_t* SK_RESTRICT data, int initialCount, int width, 1787e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int16_t* SK_RESTRICT runs, SkAlpha* SK_RESTRICT aa) { 1788e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com // we don't read our initial n from data, since the caller may have had to 1789e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com // clip it, hence the initialCount parameter. 1790e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int n = initialCount; 1791e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com for (;;) { 1792e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (n > width) { 1793e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com n = width; 1794e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1795e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(n > 0); 1796e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com runs[0] = n; 1797e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com runs += n; 1798e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1799e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com aa[0] = data[1]; 1800e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com aa += n; 1801e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1802e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com data += 2; 1803e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com width -= n; 1804e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (0 == width) { 1805e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com break; 1806e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1807e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com // load the next count 1808e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com n = data[0]; 1809e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1810e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com runs[0] = 0; // sentinel 1811e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 1812e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1813e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comSkAAClipBlitter::~SkAAClipBlitter() { 1814045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com sk_free(fScanlineScratch); 1815e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 1816e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1817e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comvoid SkAAClipBlitter::ensureRunsAndAA() { 1818045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (NULL == fScanlineScratch) { 1819e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com // add 1 so we can store the terminating run count of 0 1820e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int count = fAAClipBounds.width() + 1; 1821045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com // we use this either for fRuns + fAA, or a scaline of a mask 1822045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com // which may be as deep as 32bits 1823045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fScanlineScratch = sk_malloc_throw(count * sizeof(SkPMColor)); 1824045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fRuns = (int16_t*)fScanlineScratch; 1825e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fAA = (SkAlpha*)(fRuns + count); 1826e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1827e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 1828e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1829e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comvoid SkAAClipBlitter::blitH(int x, int y, int width) { 1830e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(width > 0); 1831e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(fAAClipBounds.contains(x, y)); 1832e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(fAAClipBounds.contains(x + width - 1, y)); 1833e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1834e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int lastY; 1835e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const uint8_t* row = fAAClip->findRow(y, &lastY); 1836e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int initialCount; 1837e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com row = fAAClip->findX(row, x, &initialCount); 1838e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1839e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (initialCount >= width) { 1840e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkAlpha alpha = row[1]; 1841e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (0 == alpha) { 1842e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return; 1843e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1844e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (0xFF == alpha) { 1845e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fBlitter->blitH(x, y, width); 1846e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return; 1847e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1848e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1849e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1850e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com this->ensureRunsAndAA(); 1851e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com expandToRuns(row, initialCount, width, fRuns, fAA); 1852e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1853e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fBlitter->blitAntiH(x, y, fAA, fRuns); 1854e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 1855e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1856e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comstatic void merge(const uint8_t* SK_RESTRICT row, int rowN, 1857e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const SkAlpha* SK_RESTRICT srcAA, 1858e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const int16_t* SK_RESTRICT srcRuns, 1859e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkAlpha* SK_RESTRICT dstAA, 1860e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int16_t* SK_RESTRICT dstRuns, 1861e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int width) { 1862e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkDEBUGCODE(int accumulated = 0;) 1863e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int srcN = srcRuns[0]; 1864045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com // do we need this check? 1865045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (0 == srcN) { 1866045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return; 1867045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1868045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1869e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com for (;;) { 1870e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(rowN > 0); 1871e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(srcN > 0); 1872e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1873e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com unsigned newAlpha = SkMulDiv255Round(srcAA[0], row[1]); 1874e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int minN = SkMin32(srcN, rowN); 1875e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com dstRuns[0] = minN; 1876e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com dstRuns += minN; 1877e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com dstAA[0] = newAlpha; 1878e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com dstAA += minN; 1879e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1880e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (0 == (srcN -= minN)) { 1881e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com srcN = srcRuns[0]; // refresh 1882e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com srcRuns += srcN; 1883e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com srcAA += srcN; 1884e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com srcN = srcRuns[0]; // reload 1885045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (0 == srcN) { 1886045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com break; 1887045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1888e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1889e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (0 == (rowN -= minN)) { 1890e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com row += 2; 1891e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com rowN = row[0]; // reload 1892e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1893e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1894e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkDEBUGCODE(accumulated += minN;) 1895e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(accumulated <= width); 1896e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 189734f7e47a3593911d03307a08e5af625b218ceec3reed@google.com dstRuns[0] = 0; 1898e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 1899e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1900e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comvoid SkAAClipBlitter::blitAntiH(int x, int y, const SkAlpha aa[], 1901e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const int16_t runs[]) { 1902e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int lastY; 1903e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const uint8_t* row = fAAClip->findRow(y, &lastY); 1904e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int initialCount; 1905e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com row = fAAClip->findX(row, x, &initialCount); 1906e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1907e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com this->ensureRunsAndAA(); 1908e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1909e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com merge(row, initialCount, aa, runs, fAA, fRuns, fAAClipBounds.width()); 1910e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fBlitter->blitAntiH(x, y, fAA, fRuns); 1911e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 1912e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1913e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comvoid SkAAClipBlitter::blitV(int x, int y, int height, SkAlpha alpha) { 1914e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (fAAClip->quickContains(x, y, x + 1, y + height)) { 1915e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fBlitter->blitV(x, y, height, alpha); 1916e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return; 1917e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1918e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1919045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com for (;;) { 1920e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int lastY; 1921e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const uint8_t* row = fAAClip->findRow(y, &lastY); 1922045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com int dy = lastY - y + 1; 1923045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (dy > height) { 1924045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com dy = height; 1925045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1926045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com height -= dy; 1927045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1928e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int initialCount; 1929e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com row = fAAClip->findX(row, x, &initialCount); 1930e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkAlpha newAlpha = SkMulDiv255Round(alpha, row[1]); 1931e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (newAlpha) { 1932045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fBlitter->blitV(x, y, dy, newAlpha); 1933045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1934045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(height >= 0); 1935045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (height <= 0) { 1936045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com break; 1937e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1938e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com y = lastY + 1; 1939045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1940e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 1941e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1942e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comvoid SkAAClipBlitter::blitRect(int x, int y, int width, int height) { 1943e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (fAAClip->quickContains(x, y, x + width, y + height)) { 1944e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fBlitter->blitRect(x, y, width, height); 1945e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return; 1946e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1947e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1948e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com while (--height >= 0) { 1949e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com this->blitH(x, y, width); 1950e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com y += 1; 1951e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1952e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 1953e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1954045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comtypedef void (*MergeAAProc)(const void* src, int width, const uint8_t* row, 1955045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com int initialRowCount, void* dst); 1956045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1957045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comstatic void small_memcpy(void* dst, const void* src, size_t n) { 1958045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com memcpy(dst, src, n); 1959e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 1960e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1961045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comstatic void small_bzero(void* dst, size_t n) { 1962045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com sk_bzero(dst, n); 1963e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 1964e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1965045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comstatic inline uint8_t mergeOne(uint8_t value, unsigned alpha) { 1966045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return SkMulDiv255Round(value, alpha); 1967045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com} 1968045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comstatic inline uint16_t mergeOne(uint16_t value, unsigned alpha) { 1969045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com unsigned r = SkGetPackedR16(value); 1970045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com unsigned g = SkGetPackedG16(value); 1971045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com unsigned b = SkGetPackedB16(value); 1972045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return SkPackRGB16(SkMulDiv255Round(r, alpha), 1973045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkMulDiv255Round(r, alpha), 1974045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkMulDiv255Round(r, alpha)); 1975045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com} 1976045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comstatic inline SkPMColor mergeOne(SkPMColor value, unsigned alpha) { 1977045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com unsigned a = SkGetPackedA32(value); 1978045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com unsigned r = SkGetPackedR32(value); 1979045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com unsigned g = SkGetPackedG32(value); 1980045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com unsigned b = SkGetPackedB32(value); 1981045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return SkPackARGB32(SkMulDiv255Round(a, alpha), 1982045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkMulDiv255Round(r, alpha), 1983045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkMulDiv255Round(g, alpha), 1984045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkMulDiv255Round(b, alpha)); 1985045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com} 1986322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1987045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comtemplate <typename T> void mergeT(const T* SK_RESTRICT src, int srcN, 1988045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const uint8_t* SK_RESTRICT row, int rowN, 1989045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com T* SK_RESTRICT dst) { 1990045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkDEBUGCODE(int accumulated = 0;) 1991045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com for (;;) { 1992045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(rowN > 0); 1993045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(srcN > 0); 1994045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1995045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com int n = SkMin32(rowN, srcN); 1996045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com unsigned rowA = row[1]; 1997045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (0xFF == rowA) { 1998045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com small_memcpy(dst, src, n * sizeof(T)); 1999045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } else if (0 == rowA) { 2000045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com small_bzero(dst, n * sizeof(T)); 2001045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } else { 2002045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com for (int i = 0; i < n; ++i) { 2003045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com dst[i] = mergeOne(src[i], rowA); 2004045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 2005045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 2006045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 2007045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (0 == (srcN -= n)) { 2008045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com break; 2009045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 2010045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 2011045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com src += n; 2012045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com dst += n; 2013045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 2014045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(rowN == n); 2015045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com row += 2; 2016045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com rowN = row[0]; 20171c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } 2018045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com} 20191c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com 2020045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comstatic MergeAAProc find_merge_aa_proc(SkMask::Format format) { 2021045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com switch (format) { 2022045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com case SkMask::kBW_Format: 20230c00f21fee3f5cfa3aa7e5d46ff94cb8cf340451tomhudson@google.com SkDEBUGFAIL("unsupported"); 2024045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return NULL; 2025045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com case SkMask::kA8_Format: 2026045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com case SkMask::k3D_Format: { 2027045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com void (*proc8)(const uint8_t*, int, const uint8_t*, int, uint8_t*) = mergeT; 2028045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return (MergeAAProc)proc8; 2029045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 2030045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com case SkMask::kLCD16_Format: { 2031045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com void (*proc16)(const uint16_t*, int, const uint8_t*, int, uint16_t*) = mergeT; 2032045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return (MergeAAProc)proc16; 2033045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 2034045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com case SkMask::kLCD32_Format: { 2035045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com void (*proc32)(const SkPMColor*, int, const uint8_t*, int, SkPMColor*) = mergeT; 2036045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return (MergeAAProc)proc32; 2037045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 2038045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com default: 20390c00f21fee3f5cfa3aa7e5d46ff94cb8cf340451tomhudson@google.com SkDEBUGFAIL("unsupported"); 2040045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return NULL; 20411c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } 2042045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com} 20431c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com 2044045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comstatic U8CPU bit2byte(int bitInAByte) { 2045045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(bitInAByte <= 0xFF); 2046045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com // negation turns any non-zero into 0xFFFFFF??, so we just shift down 2047045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com // some value >= 8 to get a full FF value 2048045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return -bitInAByte >> 8; 20491c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com} 20501c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com 2051045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comstatic void upscaleBW2A8(SkMask* dstMask, const SkMask& srcMask) { 2052045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(SkMask::kBW_Format == srcMask.fFormat); 2053045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(SkMask::kA8_Format == dstMask->fFormat); 2054045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 2055045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const int width = srcMask.fBounds.width(); 2056045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const int height = srcMask.fBounds.height(); 2057045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 2058045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const uint8_t* SK_RESTRICT src = (const uint8_t*)srcMask.fImage; 2059045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const size_t srcRB = srcMask.fRowBytes; 2060045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com uint8_t* SK_RESTRICT dst = (uint8_t*)dstMask->fImage; 2061045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const size_t dstRB = dstMask->fRowBytes; 2062045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 2063045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const int wholeBytes = width >> 3; 2064045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const int leftOverBits = width & 7; 2065045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 2066045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com for (int y = 0; y < height; ++y) { 2067045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com uint8_t* SK_RESTRICT d = dst; 2068045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com for (int i = 0; i < wholeBytes; ++i) { 2069045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com int srcByte = src[i]; 2070045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com d[0] = bit2byte(srcByte & (1 << 7)); 2071045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com d[1] = bit2byte(srcByte & (1 << 6)); 2072045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com d[2] = bit2byte(srcByte & (1 << 5)); 2073045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com d[3] = bit2byte(srcByte & (1 << 4)); 2074045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com d[4] = bit2byte(srcByte & (1 << 3)); 2075045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com d[5] = bit2byte(srcByte & (1 << 2)); 2076045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com d[6] = bit2byte(srcByte & (1 << 1)); 2077045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com d[7] = bit2byte(srcByte & (1 << 0)); 2078045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com d += 8; 2079045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 2080045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (leftOverBits) { 2081045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com int srcByte = src[wholeBytes]; 2082045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com for (int x = 0; x < leftOverBits; ++x) { 2083045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com *d++ = bit2byte(srcByte & 0x80); 2084045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com srcByte <<= 1; 2085045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 2086045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 2087045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com src += srcRB; 2088045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com dst += dstRB; 2089322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 2090322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com} 2091322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 2092045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comvoid SkAAClipBlitter::blitMask(const SkMask& origMask, const SkIRect& clip) { 2093045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(fAAClip->getBounds().contains(clip)); 2094045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 2095045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (fAAClip->quickContains(clip)) { 2096045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fBlitter->blitMask(origMask, clip); 2097322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return; 2098322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 2099322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 2100045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const SkMask* mask = &origMask; 2101322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 2102045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com // if we're BW, we need to upscale to A8 (ugh) 2103045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkMask grayMask; 2104045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com grayMask.fImage = NULL; 2105045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (SkMask::kBW_Format == origMask.fFormat) { 2106045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com grayMask.fFormat = SkMask::kA8_Format; 2107045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com grayMask.fBounds = origMask.fBounds; 2108045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com grayMask.fRowBytes = origMask.fBounds.width(); 2109045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com size_t size = grayMask.computeImageSize(); 2110045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com grayMask.fImage = (uint8_t*)fGrayMaskScratch.reset(size, 2111045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkAutoMalloc::kReuse_OnShrink); 2112322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 2113045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com upscaleBW2A8(&grayMask, origMask); 2114045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com mask = &grayMask; 2115322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 2116045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 2117045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com this->ensureRunsAndAA(); 2118045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 2119045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com // HACK -- we are devolving 3D into A8, need to copy the rest of the 3D 2120045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com // data into a temp block to support it better (ugh) 2121045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 2122045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const void* src = mask->getAddr(clip.fLeft, clip.fTop); 2123045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const size_t srcRB = mask->fRowBytes; 2124045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const int width = clip.width(); 2125045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com MergeAAProc mergeProc = find_merge_aa_proc(mask->fFormat); 2126045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 2127045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkMask rowMask; 2128045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com rowMask.fFormat = SkMask::k3D_Format == mask->fFormat ? SkMask::kA8_Format : mask->fFormat; 2129045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com rowMask.fBounds.fLeft = clip.fLeft; 2130045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com rowMask.fBounds.fRight = clip.fRight; 2131045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com rowMask.fRowBytes = mask->fRowBytes; // doesn't matter, since our height==1 2132045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com rowMask.fImage = (uint8_t*)fScanlineScratch; 2133045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 2134045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com int y = clip.fTop; 2135045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const int stopY = y + clip.height(); 2136045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 2137045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com do { 2138045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com int localStopY; 2139045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const uint8_t* row = fAAClip->findRow(y, &localStopY); 2140045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com // findRow returns last Y, not stop, so we add 1 2141045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com localStopY = SkMin32(localStopY + 1, stopY); 2142045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 2143045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com int initialCount; 2144045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com row = fAAClip->findX(row, clip.fLeft, &initialCount); 2145045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com do { 2146045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com mergeProc(src, width, row, initialCount, rowMask.fImage); 2147045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com rowMask.fBounds.fTop = y; 2148045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com rowMask.fBounds.fBottom = y + 1; 2149045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fBlitter->blitMask(rowMask, rowMask.fBounds); 2150045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com src = (const void*)((const char*)src + srcRB); 2151045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } while (++y < localStopY); 2152045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } while (y < stopY); 2153045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com} 2154045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 2155045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comconst SkBitmap* SkAAClipBlitter::justAnOpaqueColor(uint32_t* value) { 2156045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return NULL; 2157322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com} 2158322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 2159