SkAAClip.cpp revision f74ad8c91aef4f328dbcbcebae9e436c00a35140
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 685f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.combool SkAAClip::setRegion(const SkRegion& rgn) { 686f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com if (rgn.isEmpty()) { 687f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com return this->setEmpty(); 688f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com } 689f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com if (rgn.isRect()) { 690f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com return this->setRect(rgn.getBounds()); 691f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com } 692f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com 693f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com SkAAClip clip; 694f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com SkRegion::Iterator iter(rgn); 695f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com for (; !iter.done(); iter.next()) { 696f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com clip.op(iter.rect(), SkRegion::kUnion_Op); 697f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com } 698f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com this->swap(clip); 6993771a030b0b6686b0ec81359774836cc376ea3f4reed@google.com return !this->isEmpty(); 700e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 701e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 702e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com/////////////////////////////////////////////////////////////////////////////// 703e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 704e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comconst uint8_t* SkAAClip::findRow(int y, int* lastYForRow) const { 70547ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com SkASSERT(fRunHead); 706e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 707e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (!y_in_rect(y, fBounds)) { 708e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return NULL; 709e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 710e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com y -= fBounds.y(); // our yoffs values are relative to the top 711e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 712e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const YOffset* yoff = fRunHead->yoffsets(); 713e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com while (yoff->fY < y) { 714e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com yoff += 1; 715e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(yoff - fRunHead->yoffsets() < fRunHead->fRowCount); 716e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 717e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 718e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (lastYForRow) { 719045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com *lastYForRow = fBounds.y() + yoff->fY; 720e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 721e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return fRunHead->data() + yoff->fOffset; 722e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 723e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 724e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comconst uint8_t* SkAAClip::findX(const uint8_t data[], int x, int* initialCount) const { 725e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(x_in_rect(x, fBounds)); 726e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com x -= fBounds.x(); 727e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 728e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com // first skip up to X 729e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com for (;;) { 730e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int n = data[0]; 731e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (x < n) { 732e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com *initialCount = n - x; 733e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com break; 734e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 735e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com data += 2; 736e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com x -= n; 737e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 738e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return data; 739e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 740e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 741e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.combool SkAAClip::quickContains(int left, int top, int right, int bottom) const { 742e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (this->isEmpty()) { 743e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return false; 744e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 745e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (!fBounds.contains(left, top, right, bottom)) { 746e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return false; 747e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 748322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com#if 0 749e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (this->isRect()) { 750e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return true; 751e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 752322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com#endif 753e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 754e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int lastY; 755e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const uint8_t* row = this->findRow(top, &lastY); 756e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (lastY < bottom) { 757e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return false; 758e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 759e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com // now just need to check in X 760045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com int count; 761045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com row = this->findX(row, left, &count); 762045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com#if 0 763045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return count >= (right - left) && 0xFF == row[1]; 764045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com#else 765045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com int rectWidth = right - left; 766045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com while (0xFF == row[1]) { 767045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (count >= rectWidth) { 768045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return true; 769045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 770045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com rectWidth -= count; 771045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com row += 2; 772045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com count = row[0]; 773045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 774045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return false; 775045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com#endif 776e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 777e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 778e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com/////////////////////////////////////////////////////////////////////////////// 779e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 780e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comclass SkAAClip::Builder { 781e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkIRect fBounds; 782e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com struct Row { 783e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int fY; 784e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int fWidth; 785e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkTDArray<uint8_t>* fData; 786e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com }; 787e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkTDArray<Row> fRows; 788e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com Row* fCurrRow; 789e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int fPrevY; 790e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int fWidth; 791209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com int fMinY; 792e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 793e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.compublic: 794e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com Builder(const SkIRect& bounds) : fBounds(bounds) { 795e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fPrevY = -1; 796e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fWidth = bounds.width(); 797e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fCurrRow = NULL; 798209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com fMinY = bounds.fTop; 799e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 800e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 801e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com ~Builder() { 802e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com Row* row = fRows.begin(); 803e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com Row* stop = fRows.end(); 804e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com while (row < stop) { 805e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com delete row->fData; 806e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com row += 1; 807e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 808e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 809e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 810322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com const SkIRect& getBounds() const { return fBounds; } 811322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 812e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com void addRun(int x, int y, U8CPU alpha, int count) { 813e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(count > 0); 814e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(fBounds.contains(x, y)); 815e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(fBounds.contains(x + count - 1, y)); 816e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 817e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com x -= fBounds.left(); 818e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com y -= fBounds.top(); 819e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 820e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com Row* row = fCurrRow; 821e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (y != fPrevY) { 822e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(y > fPrevY); 823e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fPrevY = y; 824e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com row = this->flushRow(true); 825e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com row->fY = y; 826e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com row->fWidth = 0; 827e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(row->fData); 828e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(0 == row->fData->count()); 829e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fCurrRow = row; 830e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 831e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 832e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(row->fWidth <= x); 833e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(row->fWidth < fBounds.width()); 834e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 835e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkTDArray<uint8_t>& data = *row->fData; 836e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 837e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int gap = x - row->fWidth; 838e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (gap) { 839e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com AppendRun(data, 0, gap); 840e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com row->fWidth += gap; 841e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(row->fWidth < fBounds.width()); 842e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 843e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 844e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com AppendRun(data, alpha, count); 845e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com row->fWidth += count; 846e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(row->fWidth <= fBounds.width()); 847e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 848e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 8499154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com void addRectRun(int x, int y, int width, int height) { 8509154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com SkASSERT(fBounds.contains(x + width - 1, y + height - 1)); 8519154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com this->addRun(x, y, 0xFF, width); 8529154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com 8539154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com // we assum the rect must be all we'll see for these scanlines 8549154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com // so we ensure our row goes all the way to our right 8559154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com this->flushRowH(fCurrRow); 8569154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com 8579154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com y -= fBounds.fTop; 8589154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com SkASSERT(y == fCurrRow->fY); 8599154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com fCurrRow->fY = y + height - 1; 8609154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com } 8619154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com 862045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com bool finish(SkAAClip* target) { 863e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com this->flushRow(false); 864e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 865e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const Row* row = fRows.begin(); 866e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const Row* stop = fRows.end(); 867e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 868e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com size_t dataSize = 0; 869e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com while (row < stop) { 870e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com dataSize += row->fData->count(); 871e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com row += 1; 872e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 873e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 874045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (0 == dataSize) { 875045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return target->setEmpty(); 876045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 877045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 878209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com SkASSERT(fMinY >= fBounds.fTop); 879209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com SkASSERT(fMinY < fBounds.fBottom); 880209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com int adjustY = fMinY - fBounds.fTop; 881209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com fBounds.fTop = fMinY; 882209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com 883e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com RunHead* head = RunHead::Alloc(fRows.count(), dataSize); 884e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com YOffset* yoffset = head->yoffsets(); 885e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com uint8_t* data = head->data(); 886e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com uint8_t* baseData = data; 887e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 888e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com row = fRows.begin(); 889c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkDEBUGCODE(int prevY = row->fY - 1;) 890e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com while (row < stop) { 891c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(prevY < row->fY); // must be monotonic 892c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkDEBUGCODE(prevY = row->fY); 893c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 894209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com yoffset->fY = row->fY - adjustY; 895e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com yoffset->fOffset = data - baseData; 896e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com yoffset += 1; 897e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 898e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com size_t n = row->fData->count(); 899e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com memcpy(data, row->fData->begin(), n); 900c90419199525141a5b98091f856e359bf9daf5b1reed@google.com#ifdef SK_DEBUG 901f74ad8c91aef4f328dbcbcebae9e436c00a35140tomhudson@google.com size_t bytesNeeded = compute_row_length(data, fBounds.width()); 902c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(bytesNeeded == n); 903c90419199525141a5b98091f856e359bf9daf5b1reed@google.com#endif 904e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com data += n; 905e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 906e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com row += 1; 907e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 908e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 909045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com target->freeRuns(); 910045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com target->fBounds = fBounds; 911045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com target->fRunHead = head; 912045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return target->trimBounds(); 913e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 914e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 915e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com void dump() { 916e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com this->validate(); 917e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int y; 918e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com for (y = 0; y < fRows.count(); ++y) { 919e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const Row& row = fRows[y]; 920e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkDebugf("Y:%3d W:%3d", row.fY, row.fWidth); 921e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const SkTDArray<uint8_t>& data = *row.fData; 922e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int count = data.count(); 923e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(!(count & 1)); 924e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const uint8_t* ptr = data.begin(); 925e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com for (int x = 0; x < count; x += 2) { 926e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkDebugf(" [%3d:%02X]", ptr[0], ptr[1]); 927e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com ptr += 2; 928e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 929e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkDebugf("\n"); 930e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 931e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 932e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 933e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com void validate() { 934e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com#ifdef SK_DEBUG 935e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int prevY = -1; 936e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com for (int i = 0; i < fRows.count(); ++i) { 937e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const Row& row = fRows[i]; 938e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(prevY < row.fY); 939e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(fWidth == row.fWidth); 940e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int count = row.fData->count(); 941e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const uint8_t* ptr = row.fData->begin(); 942e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(!(count & 1)); 943e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int w = 0; 944e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com for (int x = 0; x < count; x += 2) { 945d6040f6f2fcb11fddad5d92b3cb7255e90931bccreed@google.com int n = ptr[0]; 946d6040f6f2fcb11fddad5d92b3cb7255e90931bccreed@google.com SkASSERT(n > 0); 947d6040f6f2fcb11fddad5d92b3cb7255e90931bccreed@google.com w += n; 948e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(w <= fWidth); 949e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com ptr += 2; 950e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 951e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(w == fWidth); 952e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com prevY = row.fY; 953e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 954e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com#endif 955e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 956e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 957209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com // only called by BuilderBlitter 958209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com void setMinY(int y) { 959209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com fMinY = y; 960209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com } 961209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com 962e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comprivate: 9639154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com void flushRowH(Row* row) { 9649154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com // flush current row if needed 9659154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com if (row->fWidth < fWidth) { 9669154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com AppendRun(*row->fData, 0, fWidth - row->fWidth); 9679154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com row->fWidth = fWidth; 9689154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com } 9699154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com } 970209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com 971e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com Row* flushRow(bool readyForAnother) { 972e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com Row* next = NULL; 973e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int count = fRows.count(); 974e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (count > 0) { 9759154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com this->flushRowH(&fRows[count - 1]); 976e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 977e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (count > 1) { 978e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com // are our last two runs the same? 979e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com Row* prev = &fRows[count - 2]; 980e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com Row* curr = &fRows[count - 1]; 981e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(prev->fWidth == fWidth); 982e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(curr->fWidth == fWidth); 983e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (*prev->fData == *curr->fData) { 984e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com prev->fY = curr->fY; 985e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (readyForAnother) { 986e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com curr->fData->rewind(); 987e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com next = curr; 988e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } else { 989e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com delete curr->fData; 990e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fRows.removeShuffle(count - 1); 991e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 992e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } else { 993e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (readyForAnother) { 994e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com next = fRows.append(); 995e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com next->fData = new SkTDArray<uint8_t>; 996e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 997e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 998e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } else { 999e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (readyForAnother) { 1000e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com next = fRows.append(); 1001e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com next->fData = new SkTDArray<uint8_t>; 1002e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1003e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1004e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return next; 1005e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1006e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1007e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com static void AppendRun(SkTDArray<uint8_t>& data, U8CPU alpha, int count) { 1008e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com do { 1009e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int n = count; 1010e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (n > 255) { 1011e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com n = 255; 1012e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1013e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com uint8_t* ptr = data.append(2); 1014e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com ptr[0] = n; 1015e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com ptr[1] = alpha; 1016e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com count -= n; 1017e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } while (count > 0); 1018e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1019e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}; 1020e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1021e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comclass SkAAClip::BuilderBlitter : public SkBlitter { 1022e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.compublic: 1023e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com BuilderBlitter(Builder* builder) { 1024e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fBuilder = builder; 10251778564c75de5799d45126984f8faafd03523100reed@google.com fLeft = builder->getBounds().fLeft; 10261778564c75de5799d45126984f8faafd03523100reed@google.com fRight = builder->getBounds().fRight; 1027209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com fMinY = SK_MaxS32; 1028209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com } 1029209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com 1030209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com void finish() { 1031209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com if (fMinY < SK_MaxS32) { 1032209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com fBuilder->setMinY(fMinY); 1033209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com } 1034e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1035e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1036e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com virtual void blitV(int x, int y, int height, SkAlpha alpha) SK_OVERRIDE 1037e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com { unexpected(); } 1038045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1039562a2ac95b8cd8b359574f8c4d6300b0475938dbreed@google.com virtual void blitRect(int x, int y, int width, int height) SK_OVERRIDE { 10409154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com this->recordMinY(y); 10419154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com fBuilder->addRectRun(x, y, width, height); 1042562a2ac95b8cd8b359574f8c4d6300b0475938dbreed@google.com } 1043045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1044e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com virtual void blitMask(const SkMask&, const SkIRect& clip) SK_OVERRIDE 1045e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com { unexpected(); } 1046e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1047e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com virtual const SkBitmap* justAnOpaqueColor(uint32_t*) SK_OVERRIDE { 10483771a030b0b6686b0ec81359774836cc376ea3f4reed@google.com return NULL; 1049e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1050e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1051e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com virtual void blitH(int x, int y, int width) SK_OVERRIDE { 1052209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com this->recordMinY(y); 1053e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fBuilder->addRun(x, y, 0xFF, width); 1054e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1055e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1056e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com virtual void blitAntiH(int x, int y, const SkAlpha alpha[], 1057e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const int16_t runs[]) SK_OVERRIDE { 1058209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com this->recordMinY(y); 1059e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com for (;;) { 1060e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int count = *runs; 1061e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (count <= 0) { 1062e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return; 1063e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 10641778564c75de5799d45126984f8faafd03523100reed@google.com 10651778564c75de5799d45126984f8faafd03523100reed@google.com // The supersampler's buffer can be the width of the device, so 10661778564c75de5799d45126984f8faafd03523100reed@google.com // we may have to trim the run to our bounds. If so, we assert that 10671778564c75de5799d45126984f8faafd03523100reed@google.com // the extra spans are always alpha==0 10681778564c75de5799d45126984f8faafd03523100reed@google.com int localX = x; 10691778564c75de5799d45126984f8faafd03523100reed@google.com int localCount = count; 10701778564c75de5799d45126984f8faafd03523100reed@google.com if (x < fLeft) { 10711778564c75de5799d45126984f8faafd03523100reed@google.com SkASSERT(0 == *alpha); 10721778564c75de5799d45126984f8faafd03523100reed@google.com int gap = fLeft - x; 10731778564c75de5799d45126984f8faafd03523100reed@google.com SkASSERT(gap <= count); 10741778564c75de5799d45126984f8faafd03523100reed@google.com localX += gap; 10751778564c75de5799d45126984f8faafd03523100reed@google.com localCount -= gap; 10761778564c75de5799d45126984f8faafd03523100reed@google.com } 10771778564c75de5799d45126984f8faafd03523100reed@google.com int right = x + count; 10781778564c75de5799d45126984f8faafd03523100reed@google.com if (right > fRight) { 10791778564c75de5799d45126984f8faafd03523100reed@google.com SkASSERT(0 == *alpha); 10801778564c75de5799d45126984f8faafd03523100reed@google.com localCount -= right - fRight; 10811778564c75de5799d45126984f8faafd03523100reed@google.com SkASSERT(localCount >= 0); 10821778564c75de5799d45126984f8faafd03523100reed@google.com } 10831778564c75de5799d45126984f8faafd03523100reed@google.com 10841778564c75de5799d45126984f8faafd03523100reed@google.com if (localCount) { 10851778564c75de5799d45126984f8faafd03523100reed@google.com fBuilder->addRun(localX, y, *alpha, localCount); 10861778564c75de5799d45126984f8faafd03523100reed@google.com } 1087820e80ad6390e120d4991a5280d0452ec87beaebbsalomon@google.com // Next run 1088e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com runs += count; 1089e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com alpha += count; 1090e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com x += count; 1091e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1092e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1093e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1094e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comprivate: 1095e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com Builder* fBuilder; 10961778564c75de5799d45126984f8faafd03523100reed@google.com int fLeft; // cache of builder's bounds' left edge 10971778564c75de5799d45126984f8faafd03523100reed@google.com int fRight; 1098209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com int fMinY; 1099209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com 1100209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com /* 1101209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com * We track this, in case the scan converter skipped some number of 1102209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com * scanlines at the (relative to the bounds it was given). This allows 1103209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com * the builder, during its finish, to trip its bounds down to the "real" 1104209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com * top. 1105209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com */ 1106209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com void recordMinY(int y) { 1107209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com if (y < fMinY) { 1108209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com fMinY = y; 1109209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com } 1110209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com } 1111e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1112e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com void unexpected() { 1113e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkDebugf("---- did not expect to get called here"); 1114e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com sk_throw(); 1115e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1116e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}; 1117e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1118f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.combool SkAAClip::setPath(const SkPath& path, const SkRegion* clip, bool doAA) { 1119045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com AUTO_AACLIP_VALIDATE(*this); 1120045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1121322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com if (clip && clip->isEmpty()) { 1122e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return this->setEmpty(); 1123e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1124e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1125e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkIRect ibounds; 1126322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com path.getBounds().roundOut(&ibounds); 1127e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1128322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com SkRegion tmpClip; 1129322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com if (NULL == clip) { 1130322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com tmpClip.setRect(ibounds); 1131322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com clip = &tmpClip; 1132322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1133322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1134045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (path.isInverseFillType()) { 1135045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com ibounds = clip->getBounds(); 1136045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } else { 1137322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com if (ibounds.isEmpty() || !ibounds.intersect(clip->getBounds())) { 1138e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return this->setEmpty(); 1139e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1140e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1141e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1142e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com Builder builder(ibounds); 1143e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com BuilderBlitter blitter(&builder); 1144e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1145f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com if (doAA) { 1146f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com SkScan::AntiFillPath(path, *clip, &blitter, true); 1147f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com } else { 1148f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com SkScan::FillPath(path, *clip, &blitter); 1149f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com } 1150e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1151209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com blitter.finish(); 1152045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return builder.finish(this); 1153e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 1154e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1155e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com/////////////////////////////////////////////////////////////////////////////// 1156e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1157322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comtypedef void (*RowProc)(SkAAClip::Builder&, int bottom, 1158322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com const uint8_t* rowA, const SkIRect& rectA, 1159322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com const uint8_t* rowB, const SkIRect& rectB); 1160322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1161322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comstatic void sectRowProc(SkAAClip::Builder& builder, int bottom, 1162322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com const uint8_t* rowA, const SkIRect& rectA, 1163322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com const uint8_t* rowB, const SkIRect& rectB) { 1164322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1165322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com} 1166322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1167322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comtypedef U8CPU (*AlphaProc)(U8CPU alphaA, U8CPU alphaB); 1168322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1169322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comstatic U8CPU sectAlphaProc(U8CPU alphaA, U8CPU alphaB) { 1170322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com // Multiply 1171322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return SkMulDiv255Round(alphaA, alphaB); 1172322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com} 1173322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1174322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comstatic U8CPU unionAlphaProc(U8CPU alphaA, U8CPU alphaB) { 1175322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com // SrcOver 1176322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return alphaA + alphaB - SkMulDiv255Round(alphaA, alphaB); 1177322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com} 1178322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1179322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comstatic U8CPU diffAlphaProc(U8CPU alphaA, U8CPU alphaB) { 1180322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com // SrcOut 1181322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return SkMulDiv255Round(alphaA, 0xFF - alphaB); 1182322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com} 1183322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1184322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comstatic U8CPU xorAlphaProc(U8CPU alphaA, U8CPU alphaB) { 1185322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com // XOR 1186322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return alphaA + alphaB - 2 * SkMulDiv255Round(alphaA, alphaB); 1187322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com} 1188322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1189322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comstatic AlphaProc find_alpha_proc(SkRegion::Op op) { 1190322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com switch (op) { 1191322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com case SkRegion::kIntersect_Op: 1192322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return sectAlphaProc; 1193322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com case SkRegion::kDifference_Op: 1194322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return diffAlphaProc; 1195322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com case SkRegion::kUnion_Op: 1196322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return unionAlphaProc; 1197322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com case SkRegion::kXOR_Op: 1198322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return xorAlphaProc; 1199322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com default: 1200322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com SkASSERT(!"unexpected region op"); 1201322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return sectAlphaProc; 1202322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1203322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com} 1204322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1205322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comstatic const uint8_t gEmptyRow[] = { 1206322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 1207322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 1208322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 1209322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 1210322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 1211322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 1212322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 1213322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 1214322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com}; 1215322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1216322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comclass RowIter { 1217322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.compublic: 1218322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com RowIter(const uint8_t* row, const SkIRect& bounds) { 1219322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com fRow = row; 1220322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com fLeft = bounds.fLeft; 1221322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com fBoundsRight = bounds.fRight; 12221c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (row) { 12231c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fRight = bounds.fLeft + row[0]; 12241c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com SkASSERT(fRight <= fBoundsRight); 12251c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fAlpha = row[1]; 12261c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fDone = false; 12271c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } else { 12281c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fDone = true; 12291c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fRight = kMaxInt32; 12301c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fAlpha = 0; 12311c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } 1232322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1233322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1234322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com bool done() const { return fDone; } 12351c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com int left() const { return fLeft; } 12361c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com int right() const { return fRight; } 12371c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com U8CPU alpha() const { return fAlpha; } 1238322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com void next() { 12391c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (!fDone) { 1240322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com fLeft = fRight; 12411c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (fRight == fBoundsRight) { 12421c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fDone = true; 12431c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fRight = kMaxInt32; 12441c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fAlpha = 0; 12451c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } else { 12461c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fRow += 2; 12471c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fRight += fRow[0]; 12481c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fAlpha = fRow[1]; 12491c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com SkASSERT(fRight <= fBoundsRight); 12501c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } 1251322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1252322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1253322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1254322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comprivate: 1255322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com const uint8_t* fRow; 1256322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com int fLeft; 1257322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com int fRight; 1258322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com int fBoundsRight; 1259322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com bool fDone; 12601c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com uint8_t fAlpha; 1261322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com}; 1262322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 12631c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.comstatic void adjust_row(RowIter& iter, int& leftA, int& riteA, int rite) { 12641c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (rite == riteA) { 12651c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com iter.next(); 12661c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com leftA = iter.left(); 12671c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com riteA = iter.right(); 1268322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1269322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com} 1270322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 12711c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.comstatic bool intersect(int& min, int& max, int boundsMin, int boundsMax) { 12721c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com SkASSERT(min < max); 12731c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com SkASSERT(boundsMin < boundsMax); 12741c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (min >= boundsMax || max <= boundsMin) { 12751c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com return false; 12761c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } 12771c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (min < boundsMin) { 12781c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com min = boundsMin; 12791c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } 12801c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (max > boundsMax) { 12811c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com max = boundsMax; 12821c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } 12831c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com return true; 12841c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com} 12851c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com 1286322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comstatic void operatorX(SkAAClip::Builder& builder, int lastY, 1287322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com RowIter& iterA, RowIter& iterB, 1288322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com AlphaProc proc, const SkIRect& bounds) { 1289322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com int leftA = iterA.left(); 1290322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com int riteA = iterA.right(); 1291322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com int leftB = iterB.left(); 1292322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com int riteB = iterB.right(); 1293322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 12941c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com int prevRite = bounds.fLeft; 12951c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com 12961c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com do { 1297322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com U8CPU alphaA = 0; 1298322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com U8CPU alphaB = 0; 1299322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com int left, rite; 13001c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com 13011c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (leftA < leftB) { 1302322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com left = leftA; 1303322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com alphaA = iterA.alpha(); 13041c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (riteA <= leftB) { 13051c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com rite = riteA; 13061c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } else { 13071c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com rite = leftA = leftB; 13081c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } 13091c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } else if (leftB < leftA) { 1310322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com left = leftB; 1311322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com alphaB = iterB.alpha(); 13121c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (riteB <= leftA) { 13131c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com rite = riteB; 13141c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } else { 13151c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com rite = leftB = leftA; 13161c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } 1317322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } else { 13181c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com left = leftA; // or leftB, since leftA == leftB 13191c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com rite = leftA = leftB = SkMin32(riteA, riteB); 1320322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com alphaA = iterA.alpha(); 1321322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com alphaB = iterB.alpha(); 1322322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1323322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1324322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com if (left >= bounds.fRight) { 1325322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com break; 1326322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 132734f7e47a3593911d03307a08e5af625b218ceec3reed@google.com if (rite > bounds.fRight) { 132834f7e47a3593911d03307a08e5af625b218ceec3reed@google.com rite = bounds.fRight; 132934f7e47a3593911d03307a08e5af625b218ceec3reed@google.com } 133034f7e47a3593911d03307a08e5af625b218ceec3reed@google.com 1331322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com if (left >= bounds.fLeft) { 13321c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com SkASSERT(rite > left); 1333322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com builder.addRun(left, lastY, proc(alphaA, alphaB), rite - left); 13341c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com prevRite = rite; 1335322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 13361c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com 13371c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com adjust_row(iterA, leftA, riteA, rite); 13381c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com adjust_row(iterB, leftB, riteB, rite); 13391c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } while (!iterA.done() || !iterB.done()); 13401c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com 13411c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (prevRite < bounds.fRight) { 13421c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com builder.addRun(prevRite, lastY, 0, bounds.fRight - prevRite); 1343322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1344322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com} 1345322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 13461c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.comstatic void adjust_iter(SkAAClip::Iter& iter, int& topA, int& botA, int bot) { 13471c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (bot == botA) { 13481c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com iter.next(); 13491c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com topA = botA; 13501c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com SkASSERT(botA == iter.top()); 13511c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com botA = iter.bottom(); 1352322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1353322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com} 1354322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1355322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comstatic void operateY(SkAAClip::Builder& builder, const SkAAClip& A, 1356322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com const SkAAClip& B, SkRegion::Op op) { 1357322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com AlphaProc proc = find_alpha_proc(op); 1358322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com const SkIRect& bounds = builder.getBounds(); 1359322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1360322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com SkAAClip::Iter iterA(A); 1361322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com SkAAClip::Iter iterB(B); 1362322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1363322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com SkASSERT(!iterA.done()); 1364322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com int topA = iterA.top(); 1365322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com int botA = iterA.bottom(); 1366322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com SkASSERT(!iterB.done()); 1367322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com int topB = iterB.top(); 1368322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com int botB = iterB.bottom(); 1369322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 13701c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com do { 13711c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com const uint8_t* rowA = NULL; 13721c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com const uint8_t* rowB = NULL; 1373322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com int top, bot; 13741c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com 13751c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (topA < topB) { 1376322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com top = topA; 1377322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com rowA = iterA.data(); 13781c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (botA <= topB) { 13791c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com bot = botA; 13801c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } else { 13811c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com bot = topA = topB; 13821c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } 13831c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com 13841c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } else if (topB < topA) { 1385322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com top = topB; 1386322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com rowB = iterB.data(); 13871c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (botB <= topA) { 13881c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com bot = botB; 13891c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } else { 13901c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com bot = topB = topA; 13911c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } 1392322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } else { 13931c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com top = topA; // or topB, since topA == topB 13941c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com bot = topA = topB = SkMin32(botA, botB); 1395322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com rowA = iterA.data(); 1396322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com rowB = iterB.data(); 1397322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1398322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1399322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com if (top >= bounds.fBottom) { 1400322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com break; 1401322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 140234f7e47a3593911d03307a08e5af625b218ceec3reed@google.com 140334f7e47a3593911d03307a08e5af625b218ceec3reed@google.com if (bot > bounds.fBottom) { 140434f7e47a3593911d03307a08e5af625b218ceec3reed@google.com bot = bounds.fBottom; 140534f7e47a3593911d03307a08e5af625b218ceec3reed@google.com } 140634f7e47a3593911d03307a08e5af625b218ceec3reed@google.com SkASSERT(top < bot); 140734f7e47a3593911d03307a08e5af625b218ceec3reed@google.com 14081c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (!rowA && !rowB) { 14091c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com builder.addRun(bounds.fLeft, bot - 1, 0, bounds.width()); 14101c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } else if (top >= bounds.fTop) { 14111c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com SkASSERT(bot <= bounds.fBottom); 14121c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com RowIter rowIterA(rowA, rowA ? A.getBounds() : bounds); 14131c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com RowIter rowIterB(rowB, rowB ? B.getBounds() : bounds); 1414322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com operatorX(builder, bot - 1, rowIterA, rowIterB, proc, bounds); 1415322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1416322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 14171c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com adjust_iter(iterA, topA, botA, bot); 14181c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com adjust_iter(iterB, topB, botB, bot); 14191c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } while (!iterA.done() || !iterB.done()); 1420322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com} 1421322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1422322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.combool SkAAClip::op(const SkAAClip& clipAOrig, const SkAAClip& clipBOrig, 1423322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com SkRegion::Op op) { 1424045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com AUTO_AACLIP_VALIDATE(*this); 1425045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1426322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com if (SkRegion::kReplace_Op == op) { 1427322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return this->set(clipBOrig); 1428322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1429322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1430322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com const SkAAClip* clipA = &clipAOrig; 1431322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com const SkAAClip* clipB = &clipBOrig; 1432322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1433322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com if (SkRegion::kReverseDifference_Op == op) { 1434322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com SkTSwap(clipA, clipB); 1435322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com op = SkRegion::kDifference_Op; 1436322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1437322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1438322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com bool a_empty = clipA->isEmpty(); 1439322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com bool b_empty = clipB->isEmpty(); 1440322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1441322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com SkIRect bounds; 1442322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com switch (op) { 1443322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com case SkRegion::kDifference_Op: 1444322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com if (a_empty) { 1445322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return this->setEmpty(); 1446322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1447322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com if (b_empty || !SkIRect::Intersects(clipA->fBounds, clipB->fBounds)) { 1448322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return this->set(*clipA); 1449322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1450322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com bounds = clipA->fBounds; 1451322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com break; 1452322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1453322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com case SkRegion::kIntersect_Op: 1454322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com if ((a_empty | b_empty) || !bounds.intersect(clipA->fBounds, 1455322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com clipB->fBounds)) { 1456322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return this->setEmpty(); 1457322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1458322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com break; 1459322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1460322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com case SkRegion::kUnion_Op: 1461322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com case SkRegion::kXOR_Op: 1462322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com if (a_empty) { 1463322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return this->set(*clipB); 1464322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1465322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com if (b_empty) { 1466322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return this->set(*clipA); 1467322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1468322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com bounds = clipA->fBounds; 1469322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com bounds.join(clipB->fBounds); 1470322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com break; 1471322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1472322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com default: 1473322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com SkASSERT(!"unknown region op"); 1474322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return !this->isEmpty(); 1475322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1476322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1477322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com SkASSERT(SkIRect::Intersects(bounds, clipB->fBounds)); 1478322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com SkASSERT(SkIRect::Intersects(bounds, clipB->fBounds)); 1479322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1480322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com Builder builder(bounds); 1481322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com operateY(builder, *clipA, *clipB, op); 1482045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1483045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return builder.finish(this); 1484e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 1485e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1486045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com/* 1487045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com * It can be expensive to build a local aaclip before applying the op, so 1488045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com * we first see if we can restrict the bounds of new rect to our current 1489045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com * bounds, or note that the new rect subsumes our current clip. 1490045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com */ 1491045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1492045e62d715f5ee9b03deb5af3c750f8318096179reed@google.combool SkAAClip::op(const SkIRect& rOrig, SkRegion::Op op) { 1493045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkIRect rStorage; 1494045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const SkIRect* r = &rOrig; 1495045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1496045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com switch (op) { 1497045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com case SkRegion::kIntersect_Op: 1498045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (!rStorage.intersect(rOrig, fBounds)) { 1499045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com // no overlap, so we're empty 1500045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return this->setEmpty(); 1501045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1502045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (rStorage == fBounds) { 1503045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com // we were wholly inside the rect, no change 1504045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return !this->isEmpty(); 1505045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1506045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (this->quickContains(rStorage)) { 1507045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com // the intersection is wholly inside us, we're a rect 1508045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return this->setRect(rStorage); 1509045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1510045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com r = &rStorage; // use the intersected bounds 1511045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com break; 1512045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com case SkRegion::kDifference_Op: 1513045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com break; 1514045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com case SkRegion::kUnion_Op: 1515045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (rOrig.contains(fBounds)) { 1516045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return this->setRect(rOrig); 1517045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1518045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com break; 1519045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com default: 1520045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com break; 1521045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1522045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 152347ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com SkAAClip clip; 1524045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com clip.setRect(*r); 152547ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com return this->op(*this, clip, op); 152647ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com} 152747ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com 1528045e62d715f5ee9b03deb5af3c750f8318096179reed@google.combool SkAAClip::op(const SkRect& rOrig, SkRegion::Op op, bool doAA) { 1529045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkRect rStorage, boundsStorage; 1530045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const SkRect* r = &rOrig; 1531045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1532045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com boundsStorage.set(fBounds); 1533045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com switch (op) { 1534045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com case SkRegion::kIntersect_Op: 1535045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com case SkRegion::kDifference_Op: 1536045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (!rStorage.intersect(rOrig, boundsStorage)) { 1537045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return this->setEmpty(); 1538045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1539045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com r = &rStorage; // use the intersected bounds 1540045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com break; 1541045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com case SkRegion::kUnion_Op: 1542045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (rOrig.contains(boundsStorage)) { 1543045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return this->setRect(rOrig); 1544045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1545045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com break; 1546045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com default: 1547045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com break; 1548045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1549045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 155047ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com SkAAClip clip; 1551045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com clip.setRect(*r, doAA); 155247ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com return this->op(*this, clip, op); 155347ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com} 155447ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com 155547ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.combool SkAAClip::op(const SkAAClip& clip, SkRegion::Op op) { 155647ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com return this->op(*this, clip, op); 155747ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com} 155847ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com 1559e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com/////////////////////////////////////////////////////////////////////////////// 1560045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1561045e62d715f5ee9b03deb5af3c750f8318096179reed@google.combool SkAAClip::translate(int dx, int dy, SkAAClip* dst) const { 1562045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (NULL == dst) { 1563045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return !this->isEmpty(); 1564045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1565045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1566045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (this->isEmpty()) { 1567045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return dst->setEmpty(); 1568045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1569045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1570045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (this != dst) { 1571045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com sk_atomic_inc(&fRunHead->fRefCnt); 1572045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com dst->fRunHead = fRunHead; 1573045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com dst->fBounds = fBounds; 1574045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1575045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com dst->fBounds.offset(dx, dy); 1576045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return true; 1577045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com} 1578045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1579045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comstatic void expand_row_to_mask(uint8_t* SK_RESTRICT mask, 1580045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const uint8_t* SK_RESTRICT row, 1581045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com int width) { 1582045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com while (width > 0) { 1583045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com int n = row[0]; 1584045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(width >= n); 1585045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com memset(mask, row[1], n); 1586045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com mask += n; 1587045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com row += 2; 1588045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com width -= n; 1589045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1590045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com} 1591045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1592045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comvoid SkAAClip::copyToMask(SkMask* mask) const { 1593045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com mask->fFormat = SkMask::kA8_Format; 1594045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (this->isEmpty()) { 1595045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com mask->fBounds.setEmpty(); 1596045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com mask->fImage = NULL; 1597045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com mask->fRowBytes = 0; 1598045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return; 1599045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1600045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1601045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com mask->fBounds = fBounds; 1602045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com mask->fRowBytes = fBounds.width(); 1603045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com size_t size = mask->computeImageSize(); 1604045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com mask->fImage = SkMask::AllocImage(size); 1605045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1606045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com Iter iter(*this); 1607045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com uint8_t* dst = mask->fImage; 1608045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const int width = fBounds.width(); 1609045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1610045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com int y = fBounds.fTop; 1611045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com while (!iter.done()) { 1612045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com do { 1613045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com expand_row_to_mask(dst, iter.data(), width); 1614045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com dst += mask->fRowBytes; 1615045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } while (++y < iter.bottom()); 1616045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com iter.next(); 1617045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1618045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com} 1619045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1620045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com/////////////////////////////////////////////////////////////////////////////// 1621e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com/////////////////////////////////////////////////////////////////////////////// 1622e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1623e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comstatic void expandToRuns(const uint8_t* SK_RESTRICT data, int initialCount, int width, 1624e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int16_t* SK_RESTRICT runs, SkAlpha* SK_RESTRICT aa) { 1625e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com // we don't read our initial n from data, since the caller may have had to 1626e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com // clip it, hence the initialCount parameter. 1627e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int n = initialCount; 1628e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com for (;;) { 1629e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (n > width) { 1630e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com n = width; 1631e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1632e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(n > 0); 1633e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com runs[0] = n; 1634e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com runs += n; 1635e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1636e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com aa[0] = data[1]; 1637e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com aa += n; 1638e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1639e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com data += 2; 1640e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com width -= n; 1641e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (0 == width) { 1642e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com break; 1643e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1644e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com // load the next count 1645e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com n = data[0]; 1646e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1647e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com runs[0] = 0; // sentinel 1648e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 1649e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1650e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comSkAAClipBlitter::~SkAAClipBlitter() { 1651045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com sk_free(fScanlineScratch); 1652e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 1653e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1654e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comvoid SkAAClipBlitter::ensureRunsAndAA() { 1655045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (NULL == fScanlineScratch) { 1656e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com // add 1 so we can store the terminating run count of 0 1657e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int count = fAAClipBounds.width() + 1; 1658045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com // we use this either for fRuns + fAA, or a scaline of a mask 1659045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com // which may be as deep as 32bits 1660045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fScanlineScratch = sk_malloc_throw(count * sizeof(SkPMColor)); 1661045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fRuns = (int16_t*)fScanlineScratch; 1662e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fAA = (SkAlpha*)(fRuns + count); 1663e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1664e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 1665e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1666e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comvoid SkAAClipBlitter::blitH(int x, int y, int width) { 1667e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(width > 0); 1668e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(fAAClipBounds.contains(x, y)); 1669e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(fAAClipBounds.contains(x + width - 1, y)); 1670e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1671e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int lastY; 1672e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const uint8_t* row = fAAClip->findRow(y, &lastY); 1673e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int initialCount; 1674e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com row = fAAClip->findX(row, x, &initialCount); 1675e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1676e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (initialCount >= width) { 1677e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkAlpha alpha = row[1]; 1678e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (0 == alpha) { 1679e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return; 1680e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1681e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (0xFF == alpha) { 1682e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fBlitter->blitH(x, y, width); 1683e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return; 1684e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1685e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1686e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1687e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com this->ensureRunsAndAA(); 1688e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com expandToRuns(row, initialCount, width, fRuns, fAA); 1689e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1690e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fBlitter->blitAntiH(x, y, fAA, fRuns); 1691e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 1692e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1693e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comstatic void merge(const uint8_t* SK_RESTRICT row, int rowN, 1694e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const SkAlpha* SK_RESTRICT srcAA, 1695e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const int16_t* SK_RESTRICT srcRuns, 1696e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkAlpha* SK_RESTRICT dstAA, 1697e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int16_t* SK_RESTRICT dstRuns, 1698e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int width) { 1699e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkDEBUGCODE(int accumulated = 0;) 1700e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int srcN = srcRuns[0]; 1701045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com // do we need this check? 1702045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (0 == srcN) { 1703045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return; 1704045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1705045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1706e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com for (;;) { 1707e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(rowN > 0); 1708e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(srcN > 0); 1709e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1710e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com unsigned newAlpha = SkMulDiv255Round(srcAA[0], row[1]); 1711e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int minN = SkMin32(srcN, rowN); 1712e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com dstRuns[0] = minN; 1713e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com dstRuns += minN; 1714e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com dstAA[0] = newAlpha; 1715e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com dstAA += minN; 1716e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1717e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (0 == (srcN -= minN)) { 1718e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com srcN = srcRuns[0]; // refresh 1719e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com srcRuns += srcN; 1720e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com srcAA += srcN; 1721e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com srcN = srcRuns[0]; // reload 1722045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (0 == srcN) { 1723045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com break; 1724045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1725e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1726e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (0 == (rowN -= minN)) { 1727e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com row += 2; 1728e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com rowN = row[0]; // reload 1729e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1730e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1731e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkDEBUGCODE(accumulated += minN;) 1732e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(accumulated <= width); 1733e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 173434f7e47a3593911d03307a08e5af625b218ceec3reed@google.com dstRuns[0] = 0; 1735e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 1736e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1737e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comvoid SkAAClipBlitter::blitAntiH(int x, int y, const SkAlpha aa[], 1738e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const int16_t runs[]) { 1739e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int lastY; 1740e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const uint8_t* row = fAAClip->findRow(y, &lastY); 1741e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int initialCount; 1742e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com row = fAAClip->findX(row, x, &initialCount); 1743e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1744e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com this->ensureRunsAndAA(); 1745e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1746e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com merge(row, initialCount, aa, runs, fAA, fRuns, fAAClipBounds.width()); 1747e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fBlitter->blitAntiH(x, y, fAA, fRuns); 1748e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 1749e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1750e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comvoid SkAAClipBlitter::blitV(int x, int y, int height, SkAlpha alpha) { 1751e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (fAAClip->quickContains(x, y, x + 1, y + height)) { 1752e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fBlitter->blitV(x, y, height, alpha); 1753e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return; 1754e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1755e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1756045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com for (;;) { 1757e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int lastY; 1758e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const uint8_t* row = fAAClip->findRow(y, &lastY); 1759045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com int dy = lastY - y + 1; 1760045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (dy > height) { 1761045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com dy = height; 1762045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1763045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com height -= dy; 1764045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1765e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int initialCount; 1766e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com row = fAAClip->findX(row, x, &initialCount); 1767e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkAlpha newAlpha = SkMulDiv255Round(alpha, row[1]); 1768e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (newAlpha) { 1769045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fBlitter->blitV(x, y, dy, newAlpha); 1770045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1771045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(height >= 0); 1772045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (height <= 0) { 1773045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com break; 1774e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1775e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com y = lastY + 1; 1776045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1777e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 1778e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1779e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comvoid SkAAClipBlitter::blitRect(int x, int y, int width, int height) { 1780e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (fAAClip->quickContains(x, y, x + width, y + height)) { 1781e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fBlitter->blitRect(x, y, width, height); 1782e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return; 1783e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1784e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1785e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com while (--height >= 0) { 1786e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com this->blitH(x, y, width); 1787e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com y += 1; 1788e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1789e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 1790e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1791045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comtypedef void (*MergeAAProc)(const void* src, int width, const uint8_t* row, 1792045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com int initialRowCount, void* dst); 1793045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1794045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comstatic void small_memcpy(void* dst, const void* src, size_t n) { 1795045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com memcpy(dst, src, n); 1796e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 1797e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1798045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comstatic void small_bzero(void* dst, size_t n) { 1799045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com sk_bzero(dst, n); 1800e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 1801e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1802045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comstatic inline uint8_t mergeOne(uint8_t value, unsigned alpha) { 1803045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return SkMulDiv255Round(value, alpha); 1804045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com} 1805045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comstatic inline uint16_t mergeOne(uint16_t value, unsigned alpha) { 1806045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com unsigned r = SkGetPackedR16(value); 1807045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com unsigned g = SkGetPackedG16(value); 1808045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com unsigned b = SkGetPackedB16(value); 1809045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return SkPackRGB16(SkMulDiv255Round(r, alpha), 1810045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkMulDiv255Round(r, alpha), 1811045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkMulDiv255Round(r, alpha)); 1812045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com} 1813045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comstatic inline SkPMColor mergeOne(SkPMColor value, unsigned alpha) { 1814045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com unsigned a = SkGetPackedA32(value); 1815045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com unsigned r = SkGetPackedR32(value); 1816045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com unsigned g = SkGetPackedG32(value); 1817045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com unsigned b = SkGetPackedB32(value); 1818045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return SkPackARGB32(SkMulDiv255Round(a, alpha), 1819045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkMulDiv255Round(r, alpha), 1820045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkMulDiv255Round(g, alpha), 1821045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkMulDiv255Round(b, alpha)); 1822045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com} 1823322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1824045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comtemplate <typename T> void mergeT(const T* SK_RESTRICT src, int srcN, 1825045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const uint8_t* SK_RESTRICT row, int rowN, 1826045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com T* SK_RESTRICT dst) { 1827045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkDEBUGCODE(int accumulated = 0;) 1828045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com for (;;) { 1829045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(rowN > 0); 1830045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(srcN > 0); 1831045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1832045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com int n = SkMin32(rowN, srcN); 1833045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com unsigned rowA = row[1]; 1834045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (0xFF == rowA) { 1835045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com small_memcpy(dst, src, n * sizeof(T)); 1836045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } else if (0 == rowA) { 1837045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com small_bzero(dst, n * sizeof(T)); 1838045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } else { 1839045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com for (int i = 0; i < n; ++i) { 1840045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com dst[i] = mergeOne(src[i], rowA); 1841045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1842045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1843045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1844045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (0 == (srcN -= n)) { 1845045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com break; 1846045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1847045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1848045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com src += n; 1849045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com dst += n; 1850045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1851045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(rowN == n); 1852045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com row += 2; 1853045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com rowN = row[0]; 18541c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } 1855045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com} 18561c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com 1857045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comstatic MergeAAProc find_merge_aa_proc(SkMask::Format format) { 1858045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com switch (format) { 1859045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com case SkMask::kBW_Format: 1860045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(!"unsupported"); 1861045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return NULL; 1862045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com case SkMask::kA8_Format: 1863045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com case SkMask::k3D_Format: { 1864045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com void (*proc8)(const uint8_t*, int, const uint8_t*, int, uint8_t*) = mergeT; 1865045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return (MergeAAProc)proc8; 1866045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1867045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com case SkMask::kLCD16_Format: { 1868045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com void (*proc16)(const uint16_t*, int, const uint8_t*, int, uint16_t*) = mergeT; 1869045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return (MergeAAProc)proc16; 1870045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1871045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com case SkMask::kLCD32_Format: { 1872045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com void (*proc32)(const SkPMColor*, int, const uint8_t*, int, SkPMColor*) = mergeT; 1873045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return (MergeAAProc)proc32; 1874045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1875045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com default: 1876045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(!"unsupported"); 1877045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return NULL; 18781c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } 1879045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com} 18801c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com 1881045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comstatic U8CPU bit2byte(int bitInAByte) { 1882045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(bitInAByte <= 0xFF); 1883045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com // negation turns any non-zero into 0xFFFFFF??, so we just shift down 1884045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com // some value >= 8 to get a full FF value 1885045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return -bitInAByte >> 8; 18861c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com} 18871c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com 1888045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comstatic void upscaleBW2A8(SkMask* dstMask, const SkMask& srcMask) { 1889045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(SkMask::kBW_Format == srcMask.fFormat); 1890045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(SkMask::kA8_Format == dstMask->fFormat); 1891045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1892045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const int width = srcMask.fBounds.width(); 1893045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const int height = srcMask.fBounds.height(); 1894045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1895045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const uint8_t* SK_RESTRICT src = (const uint8_t*)srcMask.fImage; 1896045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const size_t srcRB = srcMask.fRowBytes; 1897045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com uint8_t* SK_RESTRICT dst = (uint8_t*)dstMask->fImage; 1898045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const size_t dstRB = dstMask->fRowBytes; 1899045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1900045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const int wholeBytes = width >> 3; 1901045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const int leftOverBits = width & 7; 1902045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1903045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com for (int y = 0; y < height; ++y) { 1904045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com uint8_t* SK_RESTRICT d = dst; 1905045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com for (int i = 0; i < wholeBytes; ++i) { 1906045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com int srcByte = src[i]; 1907045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com d[0] = bit2byte(srcByte & (1 << 7)); 1908045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com d[1] = bit2byte(srcByte & (1 << 6)); 1909045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com d[2] = bit2byte(srcByte & (1 << 5)); 1910045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com d[3] = bit2byte(srcByte & (1 << 4)); 1911045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com d[4] = bit2byte(srcByte & (1 << 3)); 1912045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com d[5] = bit2byte(srcByte & (1 << 2)); 1913045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com d[6] = bit2byte(srcByte & (1 << 1)); 1914045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com d[7] = bit2byte(srcByte & (1 << 0)); 1915045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com d += 8; 1916045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1917045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (leftOverBits) { 1918045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com int srcByte = src[wholeBytes]; 1919045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com for (int x = 0; x < leftOverBits; ++x) { 1920045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com *d++ = bit2byte(srcByte & 0x80); 1921045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com srcByte <<= 1; 1922045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1923045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1924045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com src += srcRB; 1925045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com dst += dstRB; 1926322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1927322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com} 1928322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1929045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comvoid SkAAClipBlitter::blitMask(const SkMask& origMask, const SkIRect& clip) { 1930045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(fAAClip->getBounds().contains(clip)); 1931045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1932045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (fAAClip->quickContains(clip)) { 1933045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fBlitter->blitMask(origMask, clip); 1934322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return; 1935322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1936322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1937045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const SkMask* mask = &origMask; 1938322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1939045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com // if we're BW, we need to upscale to A8 (ugh) 1940045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkMask grayMask; 1941045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com grayMask.fImage = NULL; 1942045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (SkMask::kBW_Format == origMask.fFormat) { 1943045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com grayMask.fFormat = SkMask::kA8_Format; 1944045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com grayMask.fBounds = origMask.fBounds; 1945045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com grayMask.fRowBytes = origMask.fBounds.width(); 1946045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com size_t size = grayMask.computeImageSize(); 1947045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com grayMask.fImage = (uint8_t*)fGrayMaskScratch.reset(size, 1948045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkAutoMalloc::kReuse_OnShrink); 1949322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1950045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com upscaleBW2A8(&grayMask, origMask); 1951045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com mask = &grayMask; 1952322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1953045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1954045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com this->ensureRunsAndAA(); 1955045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1956045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com // HACK -- we are devolving 3D into A8, need to copy the rest of the 3D 1957045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com // data into a temp block to support it better (ugh) 1958045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1959045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const void* src = mask->getAddr(clip.fLeft, clip.fTop); 1960045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const size_t srcRB = mask->fRowBytes; 1961045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const int width = clip.width(); 1962045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com MergeAAProc mergeProc = find_merge_aa_proc(mask->fFormat); 1963045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1964045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkMask rowMask; 1965045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com rowMask.fFormat = SkMask::k3D_Format == mask->fFormat ? SkMask::kA8_Format : mask->fFormat; 1966045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com rowMask.fBounds.fLeft = clip.fLeft; 1967045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com rowMask.fBounds.fRight = clip.fRight; 1968045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com rowMask.fRowBytes = mask->fRowBytes; // doesn't matter, since our height==1 1969045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com rowMask.fImage = (uint8_t*)fScanlineScratch; 1970045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1971045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com int y = clip.fTop; 1972045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const int stopY = y + clip.height(); 1973045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1974045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com do { 1975045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com int localStopY; 1976045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const uint8_t* row = fAAClip->findRow(y, &localStopY); 1977045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com // findRow returns last Y, not stop, so we add 1 1978045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com localStopY = SkMin32(localStopY + 1, stopY); 1979045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1980045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com int initialCount; 1981045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com row = fAAClip->findX(row, clip.fLeft, &initialCount); 1982045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com do { 1983045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com mergeProc(src, width, row, initialCount, rowMask.fImage); 1984045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com rowMask.fBounds.fTop = y; 1985045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com rowMask.fBounds.fBottom = y + 1; 1986045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fBlitter->blitMask(rowMask, rowMask.fBounds); 1987045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com src = (const void*)((const char*)src + srcRB); 1988045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } while (++y < localStopY); 1989045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } while (y < stopY); 1990045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com} 1991045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1992045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comconst SkBitmap* SkAAClipBlitter::justAnOpaqueColor(uint32_t* value) { 1993045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return NULL; 1994322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com} 1995322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1996