1e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com/* 2e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com * Copyright 2011 Google Inc. 3e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com * 4e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com * Use of this source code is governed by a BSD-style license that can be 5e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com * found in the LICENSE file. 6e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com */ 7e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 8e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com#include "SkAAClip.h" 9b906daf112416c1698a79cf51aa70fe11aa19d0aherb#include "SkAtomics.h" 10e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com#include "SkBlitter.h" 11a4083c97d48e8a4f88e2797d7363f141e3d42553Cary Clark#include "SkColorData.h" 129fc53624a09f6d3378b0a540832571dc1c31fbcdMike Reed#include "SkRectPriv.h" 13e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com#include "SkPath.h" 14e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com#include "SkScan.h" 1534f7e47a3593911d03307a08e5af625b218ceec3reed@google.com#include "SkUtils.h" 16e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 17045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comclass AutoAAClipValidate { 18045e62d715f5ee9b03deb5af3c750f8318096179reed@google.compublic: 19045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com AutoAAClipValidate(const SkAAClip& clip) : fClip(clip) { 20045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fClip.validate(); 21045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 22045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com ~AutoAAClipValidate() { 23045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fClip.validate(); 24045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 25045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comprivate: 26045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const SkAAClip& fClip; 27045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com}; 28045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 29045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com#ifdef SK_DEBUG 30045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com #define AUTO_AACLIP_VALIDATE(clip) AutoAAClipValidate acv(clip) 31045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com#else 32045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com #define AUTO_AACLIP_VALIDATE(clip) 33045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com#endif 34045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 35045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com/////////////////////////////////////////////////////////////////////////////// 36045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 371c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com#define kMaxInt32 0x7FFFFFFF 381c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com 394b7d6730898abc9e02d1e12c2fd732945f4c1ab4commit-bot@chromium.org#ifdef SK_DEBUG 40e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comstatic inline bool x_in_rect(int x, const SkIRect& rect) { 41e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return (unsigned)(x - rect.fLeft) < (unsigned)rect.width(); 42e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 434b7d6730898abc9e02d1e12c2fd732945f4c1ab4commit-bot@chromium.org#endif 44e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 45e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comstatic inline bool y_in_rect(int y, const SkIRect& rect) { 46e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return (unsigned)(y - rect.fTop) < (unsigned)rect.height(); 47e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 48e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 49e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com/* 50e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com * Data runs are packed [count, alpha] 51e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com */ 52e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 53e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comstruct SkAAClip::YOffset { 54e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int32_t fY; 55e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com uint32_t fOffset; 56e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}; 57e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 58e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comstruct SkAAClip::RunHead { 59e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int32_t fRefCnt; 60e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int32_t fRowCount; 61493c65f1aa0864857c21b2be096740a17ef1430ascroggo@google.com size_t fDataSize; 62fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 63e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com YOffset* yoffsets() { 64e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return (YOffset*)((char*)this + sizeof(RunHead)); 65e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 66e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const YOffset* yoffsets() const { 67e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return (const YOffset*)((const char*)this + sizeof(RunHead)); 68e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 69e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com uint8_t* data() { 70e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return (uint8_t*)(this->yoffsets() + fRowCount); 71e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 72e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const uint8_t* data() const { 73e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return (const uint8_t*)(this->yoffsets() + fRowCount); 74e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 75e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 76e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com static RunHead* Alloc(int rowCount, size_t dataSize) { 77e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com size_t size = sizeof(RunHead) + rowCount * sizeof(YOffset) + dataSize; 78e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com RunHead* head = (RunHead*)sk_malloc_throw(size); 79e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com head->fRefCnt = 1; 80e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com head->fRowCount = rowCount; 81e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com head->fDataSize = dataSize; 82e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return head; 83e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 84045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 85045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com static int ComputeRowSizeForWidth(int width) { 86045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com // 2 bytes per segment, where each segment can store up to 255 for count 87045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com int segments = 0; 88045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com while (width > 0) { 89045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com segments += 1; 90045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com int n = SkMin32(width, 255); 91045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com width -= n; 92045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 93045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return segments * 2; // each segment is row[0] + row[1] (n + alpha) 94045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 95045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 96045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com static RunHead* AllocRect(const SkIRect& bounds) { 97045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(!bounds.isEmpty()); 98045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com int width = bounds.width(); 99045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com size_t rowSize = ComputeRowSizeForWidth(width); 100045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com RunHead* head = RunHead::Alloc(1, rowSize); 101045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com YOffset* yoff = head->yoffsets(); 102045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com yoff->fY = bounds.height() - 1; 103045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com yoff->fOffset = 0; 104045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com uint8_t* row = head->data(); 105045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com while (width > 0) { 106045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com int n = SkMin32(width, 255); 107045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com row[0] = n; 108045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com row[1] = 0xFF; 109045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com width -= n; 110045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com row += 2; 111045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 112045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return head; 113045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 114e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}; 115e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 116322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comclass SkAAClip::Iter { 117322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.compublic: 118322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com Iter(const SkAAClip&); 119322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 120322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com bool done() const { return fDone; } 1211c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com int top() const { return fTop; } 1221c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com int bottom() const { return fBottom; } 1231c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com const uint8_t* data() const { return fData; } 124322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com void next(); 125322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 126322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comprivate: 127322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com const YOffset* fCurrYOff; 128322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com const YOffset* fStopYOff; 129322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com const uint8_t* fData; 130322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 131322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com int fTop, fBottom; 132322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com bool fDone; 133322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com}; 134322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 135322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comSkAAClip::Iter::Iter(const SkAAClip& clip) { 136322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com if (clip.isEmpty()) { 137322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com fDone = true; 1381c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fTop = fBottom = clip.fBounds.fBottom; 13996fcdcc219d2a0d3579719b84b28bede76efba64halcanary fData = nullptr; 14096fcdcc219d2a0d3579719b84b28bede76efba64halcanary fCurrYOff = nullptr; 14196fcdcc219d2a0d3579719b84b28bede76efba64halcanary fStopYOff = nullptr; 142322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return; 143322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 144fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 145322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com const RunHead* head = clip.fRunHead; 146322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com fCurrYOff = head->yoffsets(); 147322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com fStopYOff = fCurrYOff + head->fRowCount; 148322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com fData = head->data() + fCurrYOff->fOffset; 149322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 150322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com // setup first value 151322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com fTop = clip.fBounds.fTop; 152322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com fBottom = clip.fBounds.fTop + fCurrYOff->fY + 1; 153322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com fDone = false; 154322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com} 155322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 156322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comvoid SkAAClip::Iter::next() { 1571c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (!fDone) { 1581c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com const YOffset* prev = fCurrYOff; 1591c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com const YOffset* curr = prev + 1; 1601c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com SkASSERT(curr <= fStopYOff); 161322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 162322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com fTop = fBottom; 1631c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (curr >= fStopYOff) { 1641c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fDone = true; 1651c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fBottom = kMaxInt32; 16696fcdcc219d2a0d3579719b84b28bede76efba64halcanary fData = nullptr; 1671c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } else { 1681c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fBottom += curr->fY - prev->fY; 1691c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fData += curr->fOffset - prev->fOffset; 1701c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fCurrYOff = curr; 1711c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } 172322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 173322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com} 174322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 175045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com#ifdef SK_DEBUG 176c90419199525141a5b98091f856e359bf9daf5b1reed@google.com// assert we're exactly width-wide, and then return the number of bytes used 177045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comstatic size_t compute_row_length(const uint8_t row[], int width) { 178045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const uint8_t* origRow = row; 179045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com while (width > 0) { 180045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com int n = row[0]; 181c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(n > 0); 182045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(n <= width); 183045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com row += 2; 184045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com width -= n; 185045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 186045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(0 == width); 187045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return row - origRow; 188045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com} 189045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 190045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comvoid SkAAClip::validate() const { 19196fcdcc219d2a0d3579719b84b28bede76efba64halcanary if (nullptr == fRunHead) { 192045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(fBounds.isEmpty()); 193045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return; 194045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 195d7ec12e41cce090ec0b2e68e995ea511d33c9967reed SkASSERT(!fBounds.isEmpty()); 196045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 197045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const RunHead* head = fRunHead; 198045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(head->fRefCnt > 0); 199045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(head->fRowCount > 0); 200045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 201045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const YOffset* yoff = head->yoffsets(); 202045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const YOffset* ystop = yoff + head->fRowCount; 203c90419199525141a5b98091f856e359bf9daf5b1reed@google.com const int lastY = fBounds.height() - 1; 204c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 205c90419199525141a5b98091f856e359bf9daf5b1reed@google.com // Y and offset must be monotonic 206c90419199525141a5b98091f856e359bf9daf5b1reed@google.com int prevY = -1; 207c90419199525141a5b98091f856e359bf9daf5b1reed@google.com int32_t prevOffset = -1; 208045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com while (yoff < ystop) { 209c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(prevY < yoff->fY); 210c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(yoff->fY <= lastY); 211c90419199525141a5b98091f856e359bf9daf5b1reed@google.com prevY = yoff->fY; 212c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(prevOffset < (int32_t)yoff->fOffset); 213c90419199525141a5b98091f856e359bf9daf5b1reed@google.com prevOffset = yoff->fOffset; 214c90419199525141a5b98091f856e359bf9daf5b1reed@google.com const uint8_t* row = head->data() + yoff->fOffset; 215045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com size_t rowLength = compute_row_length(row, fBounds.width()); 216493c65f1aa0864857c21b2be096740a17ef1430ascroggo@google.com SkASSERT(yoff->fOffset + rowLength <= head->fDataSize); 217c90419199525141a5b98091f856e359bf9daf5b1reed@google.com yoff += 1; 218045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 219045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com // check the last entry; 220045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com --yoff; 221c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(yoff->fY == lastY); 222045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com} 2236d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper 2246d42d9c7ff1c3d7ab4de032d5451aed02f746c43humperstatic void dump_one_row(const uint8_t* SK_RESTRICT row, 2256d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper int width, int leading_num) { 2266d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper if (leading_num) { 2276d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper SkDebugf( "%03d ", leading_num ); 2286d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper } 2296d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper while (width > 0) { 2306d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper int n = row[0]; 2316d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper int val = row[1]; 2326d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper char out = '.'; 2336d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper if (val == 0xff) { 2346d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper out = '*'; 2356d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper } else if (val > 0) { 2366d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper out = '+'; 2376d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper } 2386d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper for (int i = 0 ; i < n ; i++) { 2396d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper SkDebugf( "%c", out ); 2406d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper } 2416d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper row += 2; 2426d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper width -= n; 2436d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper } 2446d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper SkDebugf( "\n" ); 2456d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper} 2466d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper 2476d42d9c7ff1c3d7ab4de032d5451aed02f746c43humpervoid SkAAClip::debug(bool compress_y) const { 2486d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper Iter iter(*this); 2496d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper const int width = fBounds.width(); 2506d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper 2516d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper int y = fBounds.fTop; 2526d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper while (!iter.done()) { 2536d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper if (compress_y) { 2546d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper dump_one_row(iter.data(), width, iter.bottom() - iter.top() + 1); 2556d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper } else { 2566d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper do { 2576d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper dump_one_row(iter.data(), width, 0); 2586d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper } while (++y < iter.bottom()); 2596d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper } 2606d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper iter.next(); 2616d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper } 2626d42d9c7ff1c3d7ab4de032d5451aed02f746c43humper} 263045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com#endif 264045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 265045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com/////////////////////////////////////////////////////////////////////////////// 266045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 267768fee8b6e9ae0a849ed45ab377fc9079b5db11erobertphillips@google.com// Count the number of zeros on the left and right edges of the passed in 268768fee8b6e9ae0a849ed45ab377fc9079b5db11erobertphillips@google.com// RLE row. If 'row' is all zeros return 'width' in both variables. 269c90419199525141a5b98091f856e359bf9daf5b1reed@google.comstatic void count_left_right_zeros(const uint8_t* row, int width, 270c90419199525141a5b98091f856e359bf9daf5b1reed@google.com int* leftZ, int* riteZ) { 271c90419199525141a5b98091f856e359bf9daf5b1reed@google.com int zeros = 0; 272c90419199525141a5b98091f856e359bf9daf5b1reed@google.com do { 273c90419199525141a5b98091f856e359bf9daf5b1reed@google.com if (row[1]) { 274c90419199525141a5b98091f856e359bf9daf5b1reed@google.com break; 275c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 276c90419199525141a5b98091f856e359bf9daf5b1reed@google.com int n = row[0]; 277c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(n > 0); 278c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(n <= width); 279c90419199525141a5b98091f856e359bf9daf5b1reed@google.com zeros += n; 280c90419199525141a5b98091f856e359bf9daf5b1reed@google.com row += 2; 281c90419199525141a5b98091f856e359bf9daf5b1reed@google.com width -= n; 282c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } while (width > 0); 283c90419199525141a5b98091f856e359bf9daf5b1reed@google.com *leftZ = zeros; 284c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 285768fee8b6e9ae0a849ed45ab377fc9079b5db11erobertphillips@google.com if (0 == width) { 286768fee8b6e9ae0a849ed45ab377fc9079b5db11erobertphillips@google.com // this line is completely empty return 'width' in both variables 287768fee8b6e9ae0a849ed45ab377fc9079b5db11erobertphillips@google.com *riteZ = *leftZ; 288768fee8b6e9ae0a849ed45ab377fc9079b5db11erobertphillips@google.com return; 289768fee8b6e9ae0a849ed45ab377fc9079b5db11erobertphillips@google.com } 290768fee8b6e9ae0a849ed45ab377fc9079b5db11erobertphillips@google.com 291c90419199525141a5b98091f856e359bf9daf5b1reed@google.com zeros = 0; 292c90419199525141a5b98091f856e359bf9daf5b1reed@google.com while (width > 0) { 293c90419199525141a5b98091f856e359bf9daf5b1reed@google.com int n = row[0]; 294c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(n > 0); 295c90419199525141a5b98091f856e359bf9daf5b1reed@google.com if (0 == row[1]) { 296c90419199525141a5b98091f856e359bf9daf5b1reed@google.com zeros += n; 297c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } else { 298c90419199525141a5b98091f856e359bf9daf5b1reed@google.com zeros = 0; 299c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 300c90419199525141a5b98091f856e359bf9daf5b1reed@google.com row += 2; 301c90419199525141a5b98091f856e359bf9daf5b1reed@google.com width -= n; 302c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 303c90419199525141a5b98091f856e359bf9daf5b1reed@google.com *riteZ = zeros; 304c90419199525141a5b98091f856e359bf9daf5b1reed@google.com} 305c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 306c90419199525141a5b98091f856e359bf9daf5b1reed@google.com#ifdef SK_DEBUG 307c90419199525141a5b98091f856e359bf9daf5b1reed@google.comstatic void test_count_left_right_zeros() { 308c90419199525141a5b98091f856e359bf9daf5b1reed@google.com static bool gOnce; 309c90419199525141a5b98091f856e359bf9daf5b1reed@google.com if (gOnce) { 310c90419199525141a5b98091f856e359bf9daf5b1reed@google.com return; 311c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 312c90419199525141a5b98091f856e359bf9daf5b1reed@google.com gOnce = true; 313c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 314c90419199525141a5b98091f856e359bf9daf5b1reed@google.com const uint8_t data0[] = { 0, 0, 10, 0xFF }; 315c90419199525141a5b98091f856e359bf9daf5b1reed@google.com const uint8_t data1[] = { 0, 0, 5, 0xFF, 2, 0, 3, 0xFF }; 316c90419199525141a5b98091f856e359bf9daf5b1reed@google.com const uint8_t data2[] = { 7, 0, 5, 0, 2, 0, 3, 0xFF }; 317c90419199525141a5b98091f856e359bf9daf5b1reed@google.com const uint8_t data3[] = { 0, 5, 5, 0xFF, 2, 0, 3, 0 }; 318c90419199525141a5b98091f856e359bf9daf5b1reed@google.com const uint8_t data4[] = { 2, 3, 2, 0, 5, 0xFF, 3, 0 }; 319768fee8b6e9ae0a849ed45ab377fc9079b5db11erobertphillips@google.com const uint8_t data5[] = { 10, 10, 10, 0 }; 320c90419199525141a5b98091f856e359bf9daf5b1reed@google.com const uint8_t data6[] = { 2, 2, 2, 0, 2, 0xFF, 2, 0, 2, 0xFF, 2, 0 }; 321c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 322c90419199525141a5b98091f856e359bf9daf5b1reed@google.com const uint8_t* array[] = { 323c90419199525141a5b98091f856e359bf9daf5b1reed@google.com data0, data1, data2, data3, data4, data5, data6 324c90419199525141a5b98091f856e359bf9daf5b1reed@google.com }; 325c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 326c90419199525141a5b98091f856e359bf9daf5b1reed@google.com for (size_t i = 0; i < SK_ARRAY_COUNT(array); ++i) { 327c90419199525141a5b98091f856e359bf9daf5b1reed@google.com const uint8_t* data = array[i]; 328c90419199525141a5b98091f856e359bf9daf5b1reed@google.com const int expectedL = *data++; 329c90419199525141a5b98091f856e359bf9daf5b1reed@google.com const int expectedR = *data++; 330c90419199525141a5b98091f856e359bf9daf5b1reed@google.com int L = 12345, R = 12345; 331c90419199525141a5b98091f856e359bf9daf5b1reed@google.com count_left_right_zeros(data, 10, &L, &R); 332c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(expectedL == L); 333c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(expectedR == R); 334c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 335c90419199525141a5b98091f856e359bf9daf5b1reed@google.com} 336c90419199525141a5b98091f856e359bf9daf5b1reed@google.com#endif 337c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 338c90419199525141a5b98091f856e359bf9daf5b1reed@google.com// modify row in place, trimming off (zeros) from the left and right sides. 339c90419199525141a5b98091f856e359bf9daf5b1reed@google.com// return the number of bytes that were completely eliminated from the left 340c90419199525141a5b98091f856e359bf9daf5b1reed@google.comstatic int trim_row_left_right(uint8_t* row, int width, int leftZ, int riteZ) { 341c90419199525141a5b98091f856e359bf9daf5b1reed@google.com int trim = 0; 342c90419199525141a5b98091f856e359bf9daf5b1reed@google.com while (leftZ > 0) { 343c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(0 == row[1]); 344c90419199525141a5b98091f856e359bf9daf5b1reed@google.com int n = row[0]; 345c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(n > 0); 346c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(n <= width); 347c90419199525141a5b98091f856e359bf9daf5b1reed@google.com width -= n; 348c90419199525141a5b98091f856e359bf9daf5b1reed@google.com row += 2; 349c90419199525141a5b98091f856e359bf9daf5b1reed@google.com if (n > leftZ) { 350c90419199525141a5b98091f856e359bf9daf5b1reed@google.com row[-2] = n - leftZ; 351c90419199525141a5b98091f856e359bf9daf5b1reed@google.com break; 352c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 353c90419199525141a5b98091f856e359bf9daf5b1reed@google.com trim += 2; 354c90419199525141a5b98091f856e359bf9daf5b1reed@google.com leftZ -= n; 355c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(leftZ >= 0); 356c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 357c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 358c90419199525141a5b98091f856e359bf9daf5b1reed@google.com if (riteZ) { 359c90419199525141a5b98091f856e359bf9daf5b1reed@google.com // walk row to the end, and then we'll back up to trim riteZ 360c90419199525141a5b98091f856e359bf9daf5b1reed@google.com while (width > 0) { 361c90419199525141a5b98091f856e359bf9daf5b1reed@google.com int n = row[0]; 362c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(n <= width); 363c90419199525141a5b98091f856e359bf9daf5b1reed@google.com width -= n; 364c90419199525141a5b98091f856e359bf9daf5b1reed@google.com row += 2; 365c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 366c90419199525141a5b98091f856e359bf9daf5b1reed@google.com // now skip whole runs of zeros 367c90419199525141a5b98091f856e359bf9daf5b1reed@google.com do { 368c90419199525141a5b98091f856e359bf9daf5b1reed@google.com row -= 2; 369c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(0 == row[1]); 370c90419199525141a5b98091f856e359bf9daf5b1reed@google.com int n = row[0]; 371c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(n > 0); 372c90419199525141a5b98091f856e359bf9daf5b1reed@google.com if (n > riteZ) { 373c90419199525141a5b98091f856e359bf9daf5b1reed@google.com row[0] = n - riteZ; 374c90419199525141a5b98091f856e359bf9daf5b1reed@google.com break; 375c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 376c90419199525141a5b98091f856e359bf9daf5b1reed@google.com riteZ -= n; 377c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(riteZ >= 0); 378c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } while (riteZ > 0); 379c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 380fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 381c90419199525141a5b98091f856e359bf9daf5b1reed@google.com return trim; 382c90419199525141a5b98091f856e359bf9daf5b1reed@google.com} 383c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 384c90419199525141a5b98091f856e359bf9daf5b1reed@google.com#ifdef SK_DEBUG 385c90419199525141a5b98091f856e359bf9daf5b1reed@google.com// assert that this row is exactly this width 386c5507bfe2d54e411ef6eb83452b8cbfbae009610reed@google.comstatic void assert_row_width(const uint8_t* row, int width) { 387c90419199525141a5b98091f856e359bf9daf5b1reed@google.com while (width > 0) { 388c90419199525141a5b98091f856e359bf9daf5b1reed@google.com int n = row[0]; 389c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(n > 0); 390c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(n <= width); 391c90419199525141a5b98091f856e359bf9daf5b1reed@google.com width -= n; 392c90419199525141a5b98091f856e359bf9daf5b1reed@google.com row += 2; 393c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 394c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(0 == width); 395c90419199525141a5b98091f856e359bf9daf5b1reed@google.com} 396c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 397c90419199525141a5b98091f856e359bf9daf5b1reed@google.comstatic void test_trim_row_left_right() { 398c90419199525141a5b98091f856e359bf9daf5b1reed@google.com static bool gOnce; 399c90419199525141a5b98091f856e359bf9daf5b1reed@google.com if (gOnce) { 400c90419199525141a5b98091f856e359bf9daf5b1reed@google.com return; 401c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 402c90419199525141a5b98091f856e359bf9daf5b1reed@google.com gOnce = true; 403fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 404c90419199525141a5b98091f856e359bf9daf5b1reed@google.com uint8_t data0[] = { 0, 0, 0, 10, 10, 0xFF }; 405c90419199525141a5b98091f856e359bf9daf5b1reed@google.com uint8_t data1[] = { 2, 0, 0, 10, 5, 0, 2, 0, 3, 0xFF }; 406c90419199525141a5b98091f856e359bf9daf5b1reed@google.com uint8_t data2[] = { 5, 0, 2, 10, 5, 0, 2, 0, 3, 0xFF }; 407c90419199525141a5b98091f856e359bf9daf5b1reed@google.com uint8_t data3[] = { 6, 0, 2, 10, 5, 0, 2, 0, 3, 0xFF }; 408c90419199525141a5b98091f856e359bf9daf5b1reed@google.com uint8_t data4[] = { 0, 0, 0, 10, 2, 0, 2, 0xFF, 2, 0, 2, 0xFF, 2, 0 }; 409c90419199525141a5b98091f856e359bf9daf5b1reed@google.com uint8_t data5[] = { 1, 0, 0, 10, 2, 0, 2, 0xFF, 2, 0, 2, 0xFF, 2, 0 }; 410c90419199525141a5b98091f856e359bf9daf5b1reed@google.com uint8_t data6[] = { 0, 1, 0, 10, 2, 0, 2, 0xFF, 2, 0, 2, 0xFF, 2, 0 }; 411c90419199525141a5b98091f856e359bf9daf5b1reed@google.com uint8_t data7[] = { 1, 1, 0, 10, 2, 0, 2, 0xFF, 2, 0, 2, 0xFF, 2, 0 }; 412c90419199525141a5b98091f856e359bf9daf5b1reed@google.com uint8_t data8[] = { 2, 2, 2, 10, 2, 0, 2, 0xFF, 2, 0, 2, 0xFF, 2, 0 }; 413c90419199525141a5b98091f856e359bf9daf5b1reed@google.com uint8_t data9[] = { 5, 2, 4, 10, 2, 0, 2, 0, 2, 0, 2, 0xFF, 2, 0 }; 414c90419199525141a5b98091f856e359bf9daf5b1reed@google.com uint8_t data10[] ={ 74, 0, 4, 150, 9, 0, 65, 0, 76, 0xFF }; 415fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 416c90419199525141a5b98091f856e359bf9daf5b1reed@google.com uint8_t* array[] = { 417c90419199525141a5b98091f856e359bf9daf5b1reed@google.com data0, data1, data2, data3, data4, 418c90419199525141a5b98091f856e359bf9daf5b1reed@google.com data5, data6, data7, data8, data9, 419c90419199525141a5b98091f856e359bf9daf5b1reed@google.com data10 420c90419199525141a5b98091f856e359bf9daf5b1reed@google.com }; 421fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 422c90419199525141a5b98091f856e359bf9daf5b1reed@google.com for (size_t i = 0; i < SK_ARRAY_COUNT(array); ++i) { 423c90419199525141a5b98091f856e359bf9daf5b1reed@google.com uint8_t* data = array[i]; 424c90419199525141a5b98091f856e359bf9daf5b1reed@google.com const int trimL = *data++; 425c90419199525141a5b98091f856e359bf9daf5b1reed@google.com const int trimR = *data++; 426c90419199525141a5b98091f856e359bf9daf5b1reed@google.com const int expectedSkip = *data++; 427c90419199525141a5b98091f856e359bf9daf5b1reed@google.com const int origWidth = *data++; 428c90419199525141a5b98091f856e359bf9daf5b1reed@google.com assert_row_width(data, origWidth); 429c90419199525141a5b98091f856e359bf9daf5b1reed@google.com int skip = trim_row_left_right(data, origWidth, trimL, trimR); 430c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(expectedSkip == skip); 431c90419199525141a5b98091f856e359bf9daf5b1reed@google.com int expectedWidth = origWidth - trimL - trimR; 432c90419199525141a5b98091f856e359bf9daf5b1reed@google.com assert_row_width(data + skip, expectedWidth); 433c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 434c90419199525141a5b98091f856e359bf9daf5b1reed@google.com} 435c90419199525141a5b98091f856e359bf9daf5b1reed@google.com#endif 436c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 437c90419199525141a5b98091f856e359bf9daf5b1reed@google.combool SkAAClip::trimLeftRight() { 438c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkDEBUGCODE(test_trim_row_left_right();) 439c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 440c90419199525141a5b98091f856e359bf9daf5b1reed@google.com if (this->isEmpty()) { 441c90419199525141a5b98091f856e359bf9daf5b1reed@google.com return false; 442c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 443fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 444c90419199525141a5b98091f856e359bf9daf5b1reed@google.com AUTO_AACLIP_VALIDATE(*this); 445c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 446c90419199525141a5b98091f856e359bf9daf5b1reed@google.com const int width = fBounds.width(); 447c90419199525141a5b98091f856e359bf9daf5b1reed@google.com RunHead* head = fRunHead; 448c90419199525141a5b98091f856e359bf9daf5b1reed@google.com YOffset* yoff = head->yoffsets(); 449c90419199525141a5b98091f856e359bf9daf5b1reed@google.com YOffset* stop = yoff + head->fRowCount; 450c90419199525141a5b98091f856e359bf9daf5b1reed@google.com uint8_t* base = head->data(); 451c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 452768fee8b6e9ae0a849ed45ab377fc9079b5db11erobertphillips@google.com // After this loop, 'leftZeros' & 'rightZeros' will contain the minimum 453768fee8b6e9ae0a849ed45ab377fc9079b5db11erobertphillips@google.com // number of zeros on the left and right of the clip. This information 454768fee8b6e9ae0a849ed45ab377fc9079b5db11erobertphillips@google.com // can be used to shrink the bounding box. 455c90419199525141a5b98091f856e359bf9daf5b1reed@google.com int leftZeros = width; 456c90419199525141a5b98091f856e359bf9daf5b1reed@google.com int riteZeros = width; 457c90419199525141a5b98091f856e359bf9daf5b1reed@google.com while (yoff < stop) { 458c90419199525141a5b98091f856e359bf9daf5b1reed@google.com int L, R; 459c90419199525141a5b98091f856e359bf9daf5b1reed@google.com count_left_right_zeros(base + yoff->fOffset, width, &L, &R); 460768fee8b6e9ae0a849ed45ab377fc9079b5db11erobertphillips@google.com SkASSERT(L + R < width || (L == width && R == width)); 461c90419199525141a5b98091f856e359bf9daf5b1reed@google.com if (L < leftZeros) { 462c90419199525141a5b98091f856e359bf9daf5b1reed@google.com leftZeros = L; 463c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 464c90419199525141a5b98091f856e359bf9daf5b1reed@google.com if (R < riteZeros) { 465c90419199525141a5b98091f856e359bf9daf5b1reed@google.com riteZeros = R; 466c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 467c90419199525141a5b98091f856e359bf9daf5b1reed@google.com if (0 == (leftZeros | riteZeros)) { 468c90419199525141a5b98091f856e359bf9daf5b1reed@google.com // no trimming to do 469c90419199525141a5b98091f856e359bf9daf5b1reed@google.com return true; 470c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 471c90419199525141a5b98091f856e359bf9daf5b1reed@google.com yoff += 1; 472c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 473c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 474c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(leftZeros || riteZeros); 475768fee8b6e9ae0a849ed45ab377fc9079b5db11erobertphillips@google.com if (width == leftZeros) { 476768fee8b6e9ae0a849ed45ab377fc9079b5db11erobertphillips@google.com SkASSERT(width == riteZeros); 477c90419199525141a5b98091f856e359bf9daf5b1reed@google.com return this->setEmpty(); 478c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 479c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 480c90419199525141a5b98091f856e359bf9daf5b1reed@google.com this->validate(); 481c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 482c90419199525141a5b98091f856e359bf9daf5b1reed@google.com fBounds.fLeft += leftZeros; 483c90419199525141a5b98091f856e359bf9daf5b1reed@google.com fBounds.fRight -= riteZeros; 484c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(!fBounds.isEmpty()); 485c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 486c90419199525141a5b98091f856e359bf9daf5b1reed@google.com // For now we don't realloc the storage (for time), we just shrink in place 487c90419199525141a5b98091f856e359bf9daf5b1reed@google.com // This means we don't have to do any memmoves either, since we can just 488c90419199525141a5b98091f856e359bf9daf5b1reed@google.com // play tricks with the yoff->fOffset for each row 489c90419199525141a5b98091f856e359bf9daf5b1reed@google.com yoff = head->yoffsets(); 490c90419199525141a5b98091f856e359bf9daf5b1reed@google.com while (yoff < stop) { 491c90419199525141a5b98091f856e359bf9daf5b1reed@google.com uint8_t* row = base + yoff->fOffset; 492c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkDEBUGCODE((void)compute_row_length(row, width);) 493c90419199525141a5b98091f856e359bf9daf5b1reed@google.com yoff->fOffset += trim_row_left_right(row, width, leftZeros, riteZeros); 494c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkDEBUGCODE((void)compute_row_length(base + yoff->fOffset, width - leftZeros - riteZeros);) 495c90419199525141a5b98091f856e359bf9daf5b1reed@google.com yoff += 1; 496c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 497c90419199525141a5b98091f856e359bf9daf5b1reed@google.com return true; 498c90419199525141a5b98091f856e359bf9daf5b1reed@google.com} 499c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 500c90419199525141a5b98091f856e359bf9daf5b1reed@google.comstatic bool row_is_all_zeros(const uint8_t* row, int width) { 501c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(width > 0); 502c90419199525141a5b98091f856e359bf9daf5b1reed@google.com do { 503c90419199525141a5b98091f856e359bf9daf5b1reed@google.com if (row[1]) { 504c90419199525141a5b98091f856e359bf9daf5b1reed@google.com return false; 505c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 506c90419199525141a5b98091f856e359bf9daf5b1reed@google.com int n = row[0]; 507c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(n <= width); 508c90419199525141a5b98091f856e359bf9daf5b1reed@google.com width -= n; 509c90419199525141a5b98091f856e359bf9daf5b1reed@google.com row += 2; 510c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } while (width > 0); 511c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(0 == width); 512c90419199525141a5b98091f856e359bf9daf5b1reed@google.com return true; 513c90419199525141a5b98091f856e359bf9daf5b1reed@google.com} 514c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 515c90419199525141a5b98091f856e359bf9daf5b1reed@google.combool SkAAClip::trimTopBottom() { 516c90419199525141a5b98091f856e359bf9daf5b1reed@google.com if (this->isEmpty()) { 517c90419199525141a5b98091f856e359bf9daf5b1reed@google.com return false; 518c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 519c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 520d6040f6f2fcb11fddad5d92b3cb7255e90931bccreed@google.com this->validate(); 521d6040f6f2fcb11fddad5d92b3cb7255e90931bccreed@google.com 522c90419199525141a5b98091f856e359bf9daf5b1reed@google.com const int width = fBounds.width(); 523c90419199525141a5b98091f856e359bf9daf5b1reed@google.com RunHead* head = fRunHead; 524c90419199525141a5b98091f856e359bf9daf5b1reed@google.com YOffset* yoff = head->yoffsets(); 525c90419199525141a5b98091f856e359bf9daf5b1reed@google.com YOffset* stop = yoff + head->fRowCount; 526c90419199525141a5b98091f856e359bf9daf5b1reed@google.com const uint8_t* base = head->data(); 527c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 528c90419199525141a5b98091f856e359bf9daf5b1reed@google.com // Look to trim away empty rows from the top. 529c90419199525141a5b98091f856e359bf9daf5b1reed@google.com // 530c90419199525141a5b98091f856e359bf9daf5b1reed@google.com int skip = 0; 531c90419199525141a5b98091f856e359bf9daf5b1reed@google.com while (yoff < stop) { 532c90419199525141a5b98091f856e359bf9daf5b1reed@google.com const uint8_t* data = base + yoff->fOffset; 533c90419199525141a5b98091f856e359bf9daf5b1reed@google.com if (!row_is_all_zeros(data, width)) { 534c90419199525141a5b98091f856e359bf9daf5b1reed@google.com break; 535c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 536c90419199525141a5b98091f856e359bf9daf5b1reed@google.com skip += 1; 537c90419199525141a5b98091f856e359bf9daf5b1reed@google.com yoff += 1; 538c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 539c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(skip <= head->fRowCount); 540c90419199525141a5b98091f856e359bf9daf5b1reed@google.com if (skip == head->fRowCount) { 541c90419199525141a5b98091f856e359bf9daf5b1reed@google.com return this->setEmpty(); 542c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 543c90419199525141a5b98091f856e359bf9daf5b1reed@google.com if (skip > 0) { 544c90419199525141a5b98091f856e359bf9daf5b1reed@google.com // adjust fRowCount and fBounds.fTop, and slide all the data up 545c90419199525141a5b98091f856e359bf9daf5b1reed@google.com // as we remove [skip] number of YOffset entries 546c90419199525141a5b98091f856e359bf9daf5b1reed@google.com yoff = head->yoffsets(); 547c90419199525141a5b98091f856e359bf9daf5b1reed@google.com int dy = yoff[skip - 1].fY + 1; 548c90419199525141a5b98091f856e359bf9daf5b1reed@google.com for (int i = skip; i < head->fRowCount; ++i) { 549c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(yoff[i].fY >= dy); 550c90419199525141a5b98091f856e359bf9daf5b1reed@google.com yoff[i].fY -= dy; 551c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 552c90419199525141a5b98091f856e359bf9daf5b1reed@google.com YOffset* dst = head->yoffsets(); 553c90419199525141a5b98091f856e359bf9daf5b1reed@google.com size_t size = head->fRowCount * sizeof(YOffset) + head->fDataSize; 554c90419199525141a5b98091f856e359bf9daf5b1reed@google.com memmove(dst, dst + skip, size - skip * sizeof(YOffset)); 555c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 556c90419199525141a5b98091f856e359bf9daf5b1reed@google.com fBounds.fTop += dy; 557c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(!fBounds.isEmpty()); 558c90419199525141a5b98091f856e359bf9daf5b1reed@google.com head->fRowCount -= skip; 559c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(head->fRowCount > 0); 560fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 561d6040f6f2fcb11fddad5d92b3cb7255e90931bccreed@google.com this->validate(); 562d6040f6f2fcb11fddad5d92b3cb7255e90931bccreed@google.com // need to reset this after the memmove 563d6040f6f2fcb11fddad5d92b3cb7255e90931bccreed@google.com base = head->data(); 564c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 565c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 566c90419199525141a5b98091f856e359bf9daf5b1reed@google.com // Look to trim away empty rows from the bottom. 567c90419199525141a5b98091f856e359bf9daf5b1reed@google.com // We know that we have at least one non-zero row, so we can just walk 568c90419199525141a5b98091f856e359bf9daf5b1reed@google.com // backwards without checking for running past the start. 569c90419199525141a5b98091f856e359bf9daf5b1reed@google.com // 570c90419199525141a5b98091f856e359bf9daf5b1reed@google.com stop = yoff = head->yoffsets() + head->fRowCount; 571c90419199525141a5b98091f856e359bf9daf5b1reed@google.com do { 572c90419199525141a5b98091f856e359bf9daf5b1reed@google.com yoff -= 1; 573c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } while (row_is_all_zeros(base + yoff->fOffset, width)); 574a8c7f7702fb4bbedb615031bc653c5cd161a038ecommit-bot@chromium.org skip = SkToInt(stop - yoff - 1); 575c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(skip >= 0 && skip < head->fRowCount); 576c90419199525141a5b98091f856e359bf9daf5b1reed@google.com if (skip > 0) { 577c90419199525141a5b98091f856e359bf9daf5b1reed@google.com // removing from the bottom is easier than from the top, as we don't 578c90419199525141a5b98091f856e359bf9daf5b1reed@google.com // have to adjust any of the Y values, we just have to trim the array 579c90419199525141a5b98091f856e359bf9daf5b1reed@google.com memmove(stop - skip, stop, head->fDataSize); 580c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 581c90419199525141a5b98091f856e359bf9daf5b1reed@google.com fBounds.fBottom = fBounds.fTop + yoff->fY + 1; 582c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(!fBounds.isEmpty()); 583c90419199525141a5b98091f856e359bf9daf5b1reed@google.com head->fRowCount -= skip; 584c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(head->fRowCount > 0); 585c90419199525141a5b98091f856e359bf9daf5b1reed@google.com } 586d6040f6f2fcb11fddad5d92b3cb7255e90931bccreed@google.com this->validate(); 587c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 588c90419199525141a5b98091f856e359bf9daf5b1reed@google.com return true; 589c90419199525141a5b98091f856e359bf9daf5b1reed@google.com} 590c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 591045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com// can't validate before we're done, since trimming is part of the process of 592045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com// making us valid after the Builder. Since we build from top to bottom, its 593045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com// possible our fBounds.fBottom is bigger than our last scanline of data, so 594045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com// we trim fBounds.fBottom back up. 595045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com// 596045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com// TODO: check for duplicates in X and Y to further compress our data 597045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com// 598045e62d715f5ee9b03deb5af3c750f8318096179reed@google.combool SkAAClip::trimBounds() { 599045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (this->isEmpty()) { 600045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return false; 601045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 602045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 603045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const RunHead* head = fRunHead; 604045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const YOffset* yoff = head->yoffsets(); 605045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 606045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(head->fRowCount > 0); 607045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const YOffset& lastY = yoff[head->fRowCount - 1]; 608045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(lastY.fY + 1 <= fBounds.height()); 609045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fBounds.fBottom = fBounds.fTop + lastY.fY + 1; 610045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(lastY.fY + 1 == fBounds.height()); 611c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(!fBounds.isEmpty()); 612c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 613c90419199525141a5b98091f856e359bf9daf5b1reed@google.com return this->trimTopBottom() && this->trimLeftRight(); 614045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com} 615045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 616e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com/////////////////////////////////////////////////////////////////////////////// 617e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 618e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comvoid SkAAClip::freeRuns() { 61947ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com if (fRunHead) { 620e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(fRunHead->fRefCnt >= 1); 621e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (1 == sk_atomic_dec(&fRunHead->fRefCnt)) { 622e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com sk_free(fRunHead); 623e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 624e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 625e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 626e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 627e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comSkAAClip::SkAAClip() { 628e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fBounds.setEmpty(); 62996fcdcc219d2a0d3579719b84b28bede76efba64halcanary fRunHead = nullptr; 630e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 631e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 632e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comSkAAClip::SkAAClip(const SkAAClip& src) { 633045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkDEBUGCODE(fBounds.setEmpty();) // need this for validate 63496fcdcc219d2a0d3579719b84b28bede76efba64halcanary fRunHead = nullptr; 635e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com *this = src; 636e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 637e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 638e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comSkAAClip::~SkAAClip() { 639e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com this->freeRuns(); 640e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 641e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 642e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comSkAAClip& SkAAClip::operator=(const SkAAClip& src) { 643045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com AUTO_AACLIP_VALIDATE(*this); 644045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com src.validate(); 645045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 646e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (this != &src) { 647e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com this->freeRuns(); 648e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fBounds = src.fBounds; 649e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fRunHead = src.fRunHead; 65047ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com if (fRunHead) { 651e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com sk_atomic_inc(&fRunHead->fRefCnt); 652e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 653e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 654e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return *this; 655e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 656e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 657e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.combool operator==(const SkAAClip& a, const SkAAClip& b) { 658045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com a.validate(); 659045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com b.validate(); 660045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 661e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (&a == &b) { 662e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return true; 663e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 664e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (a.fBounds != b.fBounds) { 665e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return false; 666e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 667fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 668e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const SkAAClip::RunHead* ah = a.fRunHead; 669e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const SkAAClip::RunHead* bh = b.fRunHead; 670fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 671e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com // this catches empties and rects being equal 672e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (ah == bh) { 673e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return true; 674e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 675e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 676e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com // now we insist that both are complex (but different ptrs) 67747ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com if (!a.fRunHead || !b.fRunHead) { 678e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return false; 679e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 680e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 681e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return ah->fRowCount == bh->fRowCount && 682e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com ah->fDataSize == bh->fDataSize && 683e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com !memcmp(ah->data(), bh->data(), ah->fDataSize); 684e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 685e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 686e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comvoid SkAAClip::swap(SkAAClip& other) { 687045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com AUTO_AACLIP_VALIDATE(*this); 688045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com other.validate(); 689045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 690e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkTSwap(fBounds, other.fBounds); 691e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkTSwap(fRunHead, other.fRunHead); 692e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 693e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 694322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.combool SkAAClip::set(const SkAAClip& src) { 695322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com *this = src; 696322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return !this->isEmpty(); 697322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com} 698322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 699e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.combool SkAAClip::setEmpty() { 700e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com this->freeRuns(); 701e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fBounds.setEmpty(); 70296fcdcc219d2a0d3579719b84b28bede76efba64halcanary fRunHead = nullptr; 703e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return false; 704e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 705e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 706e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.combool SkAAClip::setRect(const SkIRect& bounds) { 707a766ca9af12e1175cfb01f4b516802da9197ba78Mike Reed if (bounds.isEmpty()) { 708e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return this->setEmpty(); 709e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 71047ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com 711045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com AUTO_AACLIP_VALIDATE(*this); 71247ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com 713045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com#if 0 71447ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com SkRect r; 71547ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com r.set(bounds); 71647ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com SkPath path; 71747ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com path.addRect(r); 71847ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com return this->setPath(path); 719045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com#else 720045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com this->freeRuns(); 721045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fBounds = bounds; 722045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fRunHead = RunHead::AllocRect(bounds); 723045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(!this->isEmpty()); 724045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return true; 725045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com#endif 726e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 727e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 728202ab2a5cabaf25a1e6ec47c0003da3213a79864reedbool SkAAClip::isRect() const { 729202ab2a5cabaf25a1e6ec47c0003da3213a79864reed if (this->isEmpty()) { 730202ab2a5cabaf25a1e6ec47c0003da3213a79864reed return false; 731202ab2a5cabaf25a1e6ec47c0003da3213a79864reed } 732202ab2a5cabaf25a1e6ec47c0003da3213a79864reed 733202ab2a5cabaf25a1e6ec47c0003da3213a79864reed const RunHead* head = fRunHead; 734202ab2a5cabaf25a1e6ec47c0003da3213a79864reed if (head->fRowCount != 1) { 735202ab2a5cabaf25a1e6ec47c0003da3213a79864reed return false; 736202ab2a5cabaf25a1e6ec47c0003da3213a79864reed } 737202ab2a5cabaf25a1e6ec47c0003da3213a79864reed const YOffset* yoff = head->yoffsets(); 738202ab2a5cabaf25a1e6ec47c0003da3213a79864reed if (yoff->fY != fBounds.fBottom - 1) { 739202ab2a5cabaf25a1e6ec47c0003da3213a79864reed return false; 740202ab2a5cabaf25a1e6ec47c0003da3213a79864reed } 741202ab2a5cabaf25a1e6ec47c0003da3213a79864reed 742202ab2a5cabaf25a1e6ec47c0003da3213a79864reed const uint8_t* row = head->data() + yoff->fOffset; 743202ab2a5cabaf25a1e6ec47c0003da3213a79864reed int width = fBounds.width(); 744202ab2a5cabaf25a1e6ec47c0003da3213a79864reed do { 745202ab2a5cabaf25a1e6ec47c0003da3213a79864reed if (row[1] != 0xFF) { 746202ab2a5cabaf25a1e6ec47c0003da3213a79864reed return false; 747202ab2a5cabaf25a1e6ec47c0003da3213a79864reed } 748202ab2a5cabaf25a1e6ec47c0003da3213a79864reed int n = row[0]; 749202ab2a5cabaf25a1e6ec47c0003da3213a79864reed SkASSERT(n <= width); 750202ab2a5cabaf25a1e6ec47c0003da3213a79864reed width -= n; 751202ab2a5cabaf25a1e6ec47c0003da3213a79864reed row += 2; 752202ab2a5cabaf25a1e6ec47c0003da3213a79864reed } while (width > 0); 753202ab2a5cabaf25a1e6ec47c0003da3213a79864reed return true; 754202ab2a5cabaf25a1e6ec47c0003da3213a79864reed} 755202ab2a5cabaf25a1e6ec47c0003da3213a79864reed 756f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.combool SkAAClip::setRect(const SkRect& r, bool doAA) { 757e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (r.isEmpty()) { 758e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return this->setEmpty(); 759e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 760e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 761045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com AUTO_AACLIP_VALIDATE(*this); 762045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 763045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com // TODO: special case this 764045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 765e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkPath path; 766e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com path.addRect(r); 76796fcdcc219d2a0d3579719b84b28bede76efba64halcanary return this->setPath(path, nullptr, doAA); 768f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com} 769f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com 770a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.comstatic void append_run(SkTDArray<uint8_t>& array, uint8_t value, int count) { 771a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com SkASSERT(count >= 0); 772a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com while (count > 0) { 773a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com int n = count; 774a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com if (n > 255) { 775a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com n = 255; 776a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com } 777a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com uint8_t* data = array.append(2); 778a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com data[0] = n; 779a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com data[1] = value; 780a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com count -= n; 781a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com } 782a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com} 783a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com 784f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.combool SkAAClip::setRegion(const SkRegion& rgn) { 785f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com if (rgn.isEmpty()) { 786f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com return this->setEmpty(); 787f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com } 788f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com if (rgn.isRect()) { 789f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com return this->setRect(rgn.getBounds()); 790f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com } 791a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com 792a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com#if 0 793f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com SkAAClip clip; 794f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com SkRegion::Iterator iter(rgn); 795f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com for (; !iter.done(); iter.next()) { 796f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com clip.op(iter.rect(), SkRegion::kUnion_Op); 797f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com } 798f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com this->swap(clip); 7993771a030b0b6686b0ec81359774836cc376ea3f4reed@google.com return !this->isEmpty(); 800fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com#else 801a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com const SkIRect& bounds = rgn.getBounds(); 802a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com const int offsetX = bounds.fLeft; 803a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com const int offsetY = bounds.fTop; 804a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com 805a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com SkTDArray<YOffset> yArray; 806a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com SkTDArray<uint8_t> xArray; 807a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com 808a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com yArray.setReserve(SkMin32(bounds.height(), 1024)); 809e06739531b5067564c2ce90c35522c6590162e29Mike Reed xArray.setReserve(SkMin32(bounds.width(), 512) * 128); 810a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com 811a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com SkRegion::Iterator iter(rgn); 812a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com int prevRight = 0; 813a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com int prevBot = 0; 81496fcdcc219d2a0d3579719b84b28bede76efba64halcanary YOffset* currY = nullptr; 815a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com 816a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com for (; !iter.done(); iter.next()) { 817a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com const SkIRect& r = iter.rect(); 818a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com SkASSERT(bounds.contains(r)); 819a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com 820a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com int bot = r.fBottom - offsetY; 821a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com SkASSERT(bot >= prevBot); 822a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com if (bot > prevBot) { 823a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com if (currY) { 824a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com // flush current row 825a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com append_run(xArray, 0, bounds.width() - prevRight); 826a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com } 827a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com // did we introduce an empty-gap from the prev row? 828a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com int top = r.fTop - offsetY; 829a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com if (top > prevBot) { 830a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com currY = yArray.append(); 831a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com currY->fY = top - 1; 832a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com currY->fOffset = xArray.count(); 833a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com append_run(xArray, 0, bounds.width()); 834a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com } 835a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com // create a new record for this Y value 836a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com currY = yArray.append(); 837a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com currY->fY = bot - 1; 838a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com currY->fOffset = xArray.count(); 839a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com prevRight = 0; 840a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com prevBot = bot; 841a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com } 842a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com 843a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com int x = r.fLeft - offsetX; 844a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com append_run(xArray, 0, x - prevRight); 845a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com 846a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com int w = r.fRight - r.fLeft; 847a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com append_run(xArray, 0xFF, w); 848a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com prevRight = x + w; 849a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com SkASSERT(prevRight <= bounds.width()); 850a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com } 851a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com // flush last row 852a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com append_run(xArray, 0, bounds.width() - prevRight); 853a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com 854a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com // now pack everything into a RunHead 855a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com RunHead* head = RunHead::Alloc(yArray.count(), xArray.bytes()); 856a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com memcpy(head->yoffsets(), yArray.begin(), yArray.bytes()); 857a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com memcpy(head->data(), xArray.begin(), xArray.bytes()); 858a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com 859a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com this->setEmpty(); 860a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com fBounds = bounds; 861a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com fRunHead = head; 862a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com this->validate(); 863a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com return true; 864a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com#endif 865e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 866e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 867e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com/////////////////////////////////////////////////////////////////////////////// 868e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 869e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comconst uint8_t* SkAAClip::findRow(int y, int* lastYForRow) const { 87047ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com SkASSERT(fRunHead); 871e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 872e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (!y_in_rect(y, fBounds)) { 87396fcdcc219d2a0d3579719b84b28bede76efba64halcanary return nullptr; 874e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 875e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com y -= fBounds.y(); // our yoffs values are relative to the top 876e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 877e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const YOffset* yoff = fRunHead->yoffsets(); 878e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com while (yoff->fY < y) { 879e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com yoff += 1; 880e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(yoff - fRunHead->yoffsets() < fRunHead->fRowCount); 881e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 882e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 883e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (lastYForRow) { 884045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com *lastYForRow = fBounds.y() + yoff->fY; 885e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 886e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return fRunHead->data() + yoff->fOffset; 887e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 888e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 889e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comconst uint8_t* SkAAClip::findX(const uint8_t data[], int x, int* initialCount) const { 890e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(x_in_rect(x, fBounds)); 891e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com x -= fBounds.x(); 892e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 893e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com // first skip up to X 894e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com for (;;) { 895e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int n = data[0]; 896e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (x < n) { 897a4c6e4d6d3a4010df8dd2b04314675e4c201133breed@google.com if (initialCount) { 898a4c6e4d6d3a4010df8dd2b04314675e4c201133breed@google.com *initialCount = n - x; 899a4c6e4d6d3a4010df8dd2b04314675e4c201133breed@google.com } 900e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com break; 901e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 902e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com data += 2; 903e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com x -= n; 904e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 905e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return data; 906e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 907e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 908e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.combool SkAAClip::quickContains(int left, int top, int right, int bottom) const { 909e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (this->isEmpty()) { 910e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return false; 911e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 912e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (!fBounds.contains(left, top, right, bottom)) { 913e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return false; 914e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 915322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com#if 0 916e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (this->isRect()) { 917e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return true; 918e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 919322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com#endif 920e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 921a4c6e4d6d3a4010df8dd2b04314675e4c201133breed@google.com int lastY SK_INIT_TO_AVOID_WARNING; 922e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const uint8_t* row = this->findRow(top, &lastY); 923e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (lastY < bottom) { 924e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return false; 925e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 926e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com // now just need to check in X 927045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com int count; 928045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com row = this->findX(row, left, &count); 929045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com#if 0 930045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return count >= (right - left) && 0xFF == row[1]; 931045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com#else 932045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com int rectWidth = right - left; 933045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com while (0xFF == row[1]) { 934045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (count >= rectWidth) { 935045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return true; 936045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 937045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com rectWidth -= count; 938045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com row += 2; 939045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com count = row[0]; 940045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 941045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return false; 942045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com#endif 943e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 944e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 945e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com/////////////////////////////////////////////////////////////////////////////// 946e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 947e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comclass SkAAClip::Builder { 948e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkIRect fBounds; 949e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com struct Row { 950e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int fY; 951e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int fWidth; 952e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkTDArray<uint8_t>* fData; 953e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com }; 954e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkTDArray<Row> fRows; 955e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com Row* fCurrRow; 956e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int fPrevY; 957e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int fWidth; 958209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com int fMinY; 959e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 960e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.compublic: 961e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com Builder(const SkIRect& bounds) : fBounds(bounds) { 962e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fPrevY = -1; 963e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fWidth = bounds.width(); 96496fcdcc219d2a0d3579719b84b28bede76efba64halcanary fCurrRow = nullptr; 965209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com fMinY = bounds.fTop; 966e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 967e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 968e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com ~Builder() { 969e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com Row* row = fRows.begin(); 970e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com Row* stop = fRows.end(); 971e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com while (row < stop) { 972e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com delete row->fData; 973e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com row += 1; 974e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 975e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 976e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 977322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com const SkIRect& getBounds() const { return fBounds; } 978322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 979e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com void addRun(int x, int y, U8CPU alpha, int count) { 980e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(count > 0); 981e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(fBounds.contains(x, y)); 982e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(fBounds.contains(x + count - 1, y)); 983fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 984e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com x -= fBounds.left(); 985e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com y -= fBounds.top(); 986fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 987e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com Row* row = fCurrRow; 988e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (y != fPrevY) { 989e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(y > fPrevY); 990e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fPrevY = y; 991e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com row = this->flushRow(true); 992e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com row->fY = y; 993e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com row->fWidth = 0; 994e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(row->fData); 995e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(0 == row->fData->count()); 996e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fCurrRow = row; 997e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 998e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 999e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(row->fWidth <= x); 1000e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(row->fWidth < fBounds.width()); 1001e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1002e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkTDArray<uint8_t>& data = *row->fData; 1003e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1004e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int gap = x - row->fWidth; 1005e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (gap) { 1006e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com AppendRun(data, 0, gap); 1007e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com row->fWidth += gap; 1008e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(row->fWidth < fBounds.width()); 1009e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1010e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1011e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com AppendRun(data, alpha, count); 1012e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com row->fWidth += count; 1013e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(row->fWidth <= fBounds.width()); 1014e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1015e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 101649eac192faa35159752525b23345563252721c64tomhudson@google.com void addColumn(int x, int y, U8CPU alpha, int height) { 101749eac192faa35159752525b23345563252721c64tomhudson@google.com SkASSERT(fBounds.contains(x, y + height - 1)); 101849eac192faa35159752525b23345563252721c64tomhudson@google.com 101949eac192faa35159752525b23345563252721c64tomhudson@google.com this->addRun(x, y, alpha, 1); 102049eac192faa35159752525b23345563252721c64tomhudson@google.com this->flushRowH(fCurrRow); 102149eac192faa35159752525b23345563252721c64tomhudson@google.com y -= fBounds.fTop; 102249eac192faa35159752525b23345563252721c64tomhudson@google.com SkASSERT(y == fCurrRow->fY); 102349eac192faa35159752525b23345563252721c64tomhudson@google.com fCurrRow->fY = y + height - 1; 102449eac192faa35159752525b23345563252721c64tomhudson@google.com } 1025fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 10269154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com void addRectRun(int x, int y, int width, int height) { 10279154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com SkASSERT(fBounds.contains(x + width - 1, y + height - 1)); 10289154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com this->addRun(x, y, 0xFF, width); 10299154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com 1030a89c77b5cafcc13d76cb07c3240e48705cb30d8freed@google.com // we assum the rect must be all we'll see for these scanlines 10319154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com // so we ensure our row goes all the way to our right 10329154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com this->flushRowH(fCurrRow); 10339154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com 10349154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com y -= fBounds.fTop; 10359154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com SkASSERT(y == fCurrRow->fY); 10369154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com fCurrRow->fY = y + height - 1; 10379154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com } 10389154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com 103949eac192faa35159752525b23345563252721c64tomhudson@google.com void addAntiRectRun(int x, int y, int width, int height, 104049eac192faa35159752525b23345563252721c64tomhudson@google.com SkAlpha leftAlpha, SkAlpha rightAlpha) { 10412add0ffdaab4c33ca6702c81533c88c7b5ca7294liyuqian // According to SkBlitter.cpp, no matter whether leftAlpha is 0 or positive, 10422add0ffdaab4c33ca6702c81533c88c7b5ca7294liyuqian // we should always consider [x, x+1] as the left-most column and [x+1, x+1+width] 10432add0ffdaab4c33ca6702c81533c88c7b5ca7294liyuqian // as the rect with full alpha. 10442add0ffdaab4c33ca6702c81533c88c7b5ca7294liyuqian SkASSERT(fBounds.contains(x + width + (rightAlpha > 0 ? 1 : 0), 104549eac192faa35159752525b23345563252721c64tomhudson@google.com y + height - 1)); 104649eac192faa35159752525b23345563252721c64tomhudson@google.com SkASSERT(width >= 0); 104749eac192faa35159752525b23345563252721c64tomhudson@google.com 104849eac192faa35159752525b23345563252721c64tomhudson@google.com // Conceptually we're always adding 3 runs, but we should 104949eac192faa35159752525b23345563252721c64tomhudson@google.com // merge or omit them if possible. 105049eac192faa35159752525b23345563252721c64tomhudson@google.com if (leftAlpha == 0xFF) { 105149eac192faa35159752525b23345563252721c64tomhudson@google.com width++; 105249eac192faa35159752525b23345563252721c64tomhudson@google.com } else if (leftAlpha > 0) { 105349eac192faa35159752525b23345563252721c64tomhudson@google.com this->addRun(x++, y, leftAlpha, 1); 10542add0ffdaab4c33ca6702c81533c88c7b5ca7294liyuqian } else { 10552add0ffdaab4c33ca6702c81533c88c7b5ca7294liyuqian // leftAlpha is 0, ignore the left column 10562add0ffdaab4c33ca6702c81533c88c7b5ca7294liyuqian x++; 105749eac192faa35159752525b23345563252721c64tomhudson@google.com } 105849eac192faa35159752525b23345563252721c64tomhudson@google.com if (rightAlpha == 0xFF) { 105949eac192faa35159752525b23345563252721c64tomhudson@google.com width++; 106049eac192faa35159752525b23345563252721c64tomhudson@google.com } 106149eac192faa35159752525b23345563252721c64tomhudson@google.com if (width > 0) { 106249eac192faa35159752525b23345563252721c64tomhudson@google.com this->addRun(x, y, 0xFF, width); 106349eac192faa35159752525b23345563252721c64tomhudson@google.com } 106449eac192faa35159752525b23345563252721c64tomhudson@google.com if (rightAlpha > 0 && rightAlpha < 255) { 106549eac192faa35159752525b23345563252721c64tomhudson@google.com this->addRun(x + width, y, rightAlpha, 1); 106649eac192faa35159752525b23345563252721c64tomhudson@google.com } 106749eac192faa35159752525b23345563252721c64tomhudson@google.com 106849eac192faa35159752525b23345563252721c64tomhudson@google.com // we assume the rect must be all we'll see for these scanlines 106949eac192faa35159752525b23345563252721c64tomhudson@google.com // so we ensure our row goes all the way to our right 107049eac192faa35159752525b23345563252721c64tomhudson@google.com this->flushRowH(fCurrRow); 107149eac192faa35159752525b23345563252721c64tomhudson@google.com 107249eac192faa35159752525b23345563252721c64tomhudson@google.com y -= fBounds.fTop; 107349eac192faa35159752525b23345563252721c64tomhudson@google.com SkASSERT(y == fCurrRow->fY); 107449eac192faa35159752525b23345563252721c64tomhudson@google.com fCurrRow->fY = y + height - 1; 107549eac192faa35159752525b23345563252721c64tomhudson@google.com } 107649eac192faa35159752525b23345563252721c64tomhudson@google.com 1077045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com bool finish(SkAAClip* target) { 1078e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com this->flushRow(false); 1079e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1080e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const Row* row = fRows.begin(); 1081e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const Row* stop = fRows.end(); 1082e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1083fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com size_t dataSize = 0; 1084e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com while (row < stop) { 1085e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com dataSize += row->fData->count(); 1086e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com row += 1; 1087e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1088e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1089045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (0 == dataSize) { 1090045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return target->setEmpty(); 1091045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1092045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1093209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com SkASSERT(fMinY >= fBounds.fTop); 1094209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com SkASSERT(fMinY < fBounds.fBottom); 1095209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com int adjustY = fMinY - fBounds.fTop; 1096209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com fBounds.fTop = fMinY; 1097209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com 1098e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com RunHead* head = RunHead::Alloc(fRows.count(), dataSize); 1099e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com YOffset* yoffset = head->yoffsets(); 1100e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com uint8_t* data = head->data(); 1101e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com uint8_t* baseData = data; 1102e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1103e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com row = fRows.begin(); 1104c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkDEBUGCODE(int prevY = row->fY - 1;) 1105e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com while (row < stop) { 1106c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(prevY < row->fY); // must be monotonic 1107c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkDEBUGCODE(prevY = row->fY); 1108c90419199525141a5b98091f856e359bf9daf5b1reed@google.com 1109209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com yoffset->fY = row->fY - adjustY; 1110a8c7f7702fb4bbedb615031bc653c5cd161a038ecommit-bot@chromium.org yoffset->fOffset = SkToU32(data - baseData); 1111e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com yoffset += 1; 1112fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1113e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com size_t n = row->fData->count(); 1114e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com memcpy(data, row->fData->begin(), n); 1115c90419199525141a5b98091f856e359bf9daf5b1reed@google.com#ifdef SK_DEBUG 1116f74ad8c91aef4f328dbcbcebae9e436c00a35140tomhudson@google.com size_t bytesNeeded = compute_row_length(data, fBounds.width()); 1117c90419199525141a5b98091f856e359bf9daf5b1reed@google.com SkASSERT(bytesNeeded == n); 1118c90419199525141a5b98091f856e359bf9daf5b1reed@google.com#endif 1119e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com data += n; 1120fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1121e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com row += 1; 1122e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1123e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1124045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com target->freeRuns(); 1125045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com target->fBounds = fBounds; 1126045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com target->fRunHead = head; 1127045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return target->trimBounds(); 1128e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1129e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1130e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com void dump() { 1131e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com this->validate(); 1132e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int y; 1133e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com for (y = 0; y < fRows.count(); ++y) { 1134e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const Row& row = fRows[y]; 1135e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkDebugf("Y:%3d W:%3d", row.fY, row.fWidth); 1136e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const SkTDArray<uint8_t>& data = *row.fData; 1137e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int count = data.count(); 1138e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(!(count & 1)); 1139e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const uint8_t* ptr = data.begin(); 1140e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com for (int x = 0; x < count; x += 2) { 1141e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkDebugf(" [%3d:%02X]", ptr[0], ptr[1]); 1142e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com ptr += 2; 1143e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1144e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkDebugf("\n"); 1145e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1146e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1147e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1148e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com void validate() { 1149e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com#ifdef SK_DEBUG 1150803eceb6afd13f07416df0b4a9bb714e9370f081caryclark@google.com if (false) { // avoid bit rot, suppress warning 1151803eceb6afd13f07416df0b4a9bb714e9370f081caryclark@google.com test_count_left_right_zeros(); 1152803eceb6afd13f07416df0b4a9bb714e9370f081caryclark@google.com } 1153e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int prevY = -1; 1154e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com for (int i = 0; i < fRows.count(); ++i) { 1155e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const Row& row = fRows[i]; 1156e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(prevY < row.fY); 1157e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(fWidth == row.fWidth); 1158e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int count = row.fData->count(); 1159e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const uint8_t* ptr = row.fData->begin(); 1160e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(!(count & 1)); 1161e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int w = 0; 1162e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com for (int x = 0; x < count; x += 2) { 1163d6040f6f2fcb11fddad5d92b3cb7255e90931bccreed@google.com int n = ptr[0]; 1164d6040f6f2fcb11fddad5d92b3cb7255e90931bccreed@google.com SkASSERT(n > 0); 1165d6040f6f2fcb11fddad5d92b3cb7255e90931bccreed@google.com w += n; 1166e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(w <= fWidth); 1167e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com ptr += 2; 1168e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1169e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(w == fWidth); 1170e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com prevY = row.fY; 1171e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1172e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com#endif 1173e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1174e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1175209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com // only called by BuilderBlitter 1176209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com void setMinY(int y) { 1177209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com fMinY = y; 1178209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com } 1179209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com 1180e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comprivate: 11819154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com void flushRowH(Row* row) { 11829154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com // flush current row if needed 11839154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com if (row->fWidth < fWidth) { 11849154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com AppendRun(*row->fData, 0, fWidth - row->fWidth); 11859154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com row->fWidth = fWidth; 11869154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com } 11879154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com } 1188209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com 1189e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com Row* flushRow(bool readyForAnother) { 119096fcdcc219d2a0d3579719b84b28bede76efba64halcanary Row* next = nullptr; 1191e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int count = fRows.count(); 1192e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (count > 0) { 11939154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com this->flushRowH(&fRows[count - 1]); 1194e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1195e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (count > 1) { 1196e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com // are our last two runs the same? 1197e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com Row* prev = &fRows[count - 2]; 1198e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com Row* curr = &fRows[count - 1]; 1199e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(prev->fWidth == fWidth); 1200e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(curr->fWidth == fWidth); 1201e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (*prev->fData == *curr->fData) { 1202e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com prev->fY = curr->fY; 1203e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (readyForAnother) { 1204e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com curr->fData->rewind(); 1205e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com next = curr; 1206e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } else { 1207e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com delete curr->fData; 1208e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fRows.removeShuffle(count - 1); 1209e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1210e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } else { 1211e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (readyForAnother) { 1212e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com next = fRows.append(); 1213e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com next->fData = new SkTDArray<uint8_t>; 1214e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1215e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1216e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } else { 1217e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (readyForAnother) { 1218e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com next = fRows.append(); 1219e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com next->fData = new SkTDArray<uint8_t>; 1220e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1221e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1222e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return next; 1223e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1224e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1225e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com static void AppendRun(SkTDArray<uint8_t>& data, U8CPU alpha, int count) { 1226e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com do { 1227e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int n = count; 1228e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (n > 255) { 1229e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com n = 255; 1230e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1231e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com uint8_t* ptr = data.append(2); 1232e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com ptr[0] = n; 1233e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com ptr[1] = alpha; 1234e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com count -= n; 1235e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } while (count > 0); 1236e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1237e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}; 1238e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1239e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comclass SkAAClip::BuilderBlitter : public SkBlitter { 124080cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com int fLastY; 124180cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com 124280cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com /* 124380cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com If we see a gap of 1 or more empty scanlines while building in Y-order, 124480cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com we inject an explicit empty scanline (alpha==0) 1245fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 124680cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com See AAClipTest.cpp : test_path_with_hole() 124780cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com */ 124880cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com void checkForYGap(int y) { 124980cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com SkASSERT(y >= fLastY); 125080cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com if (fLastY > -SK_MaxS32) { 125180cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com int gap = y - fLastY; 125280cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com if (gap > 1) { 125380cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com fBuilder->addRun(fLeft, y - 1, 0, fRight - fLeft); 125480cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com } 125580cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com } 125680cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com fLastY = y; 125780cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com } 125880cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com 1259e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.compublic: 126080cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com 1261e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com BuilderBlitter(Builder* builder) { 1262e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fBuilder = builder; 12631778564c75de5799d45126984f8faafd03523100reed@google.com fLeft = builder->getBounds().fLeft; 12641778564c75de5799d45126984f8faafd03523100reed@google.com fRight = builder->getBounds().fRight; 1265209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com fMinY = SK_MaxS32; 126680cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com fLastY = -SK_MaxS32; // sentinel 1267209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com } 1268209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com 1269209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com void finish() { 1270209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com if (fMinY < SK_MaxS32) { 1271209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com fBuilder->setMinY(fMinY); 1272209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com } 1273e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1274e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 127549eac192faa35159752525b23345563252721c64tomhudson@google.com /** 127649eac192faa35159752525b23345563252721c64tomhudson@google.com Must evaluate clips in scan-line order, so don't want to allow blitV(), 127749eac192faa35159752525b23345563252721c64tomhudson@google.com but an AAClip can be clipped down to a single pixel wide, so we 127849eac192faa35159752525b23345563252721c64tomhudson@google.com must support it (given AntiRect semantics: minimum width is 2). 127949eac192faa35159752525b23345563252721c64tomhudson@google.com Instead we'll rely on the runtime asserts to guarantee Y monotonicity; 128049eac192faa35159752525b23345563252721c64tomhudson@google.com any failure cases that misses may have minor artifacts. 128149eac192faa35159752525b23345563252721c64tomhudson@google.com */ 128236352bf5e38f45a70ee4f4fc132a38048d38206dmtklein void blitV(int x, int y, int height, SkAlpha alpha) override { 12832add0ffdaab4c33ca6702c81533c88c7b5ca7294liyuqian if (height == 1) { 12842add0ffdaab4c33ca6702c81533c88c7b5ca7294liyuqian // We're still in scan-line order if height is 1 12852add0ffdaab4c33ca6702c81533c88c7b5ca7294liyuqian // This is useful for Analytic AA 12862add0ffdaab4c33ca6702c81533c88c7b5ca7294liyuqian const SkAlpha alphas[2] = {alpha, 0}; 12872add0ffdaab4c33ca6702c81533c88c7b5ca7294liyuqian const int16_t runs[2] = {1, 0}; 12882add0ffdaab4c33ca6702c81533c88c7b5ca7294liyuqian this->blitAntiH(x, y, alphas, runs); 12892add0ffdaab4c33ca6702c81533c88c7b5ca7294liyuqian } else { 12902add0ffdaab4c33ca6702c81533c88c7b5ca7294liyuqian this->recordMinY(y); 12912add0ffdaab4c33ca6702c81533c88c7b5ca7294liyuqian fBuilder->addColumn(x, y, alpha, height); 12922add0ffdaab4c33ca6702c81533c88c7b5ca7294liyuqian fLastY = y + height - 1; 12932add0ffdaab4c33ca6702c81533c88c7b5ca7294liyuqian } 129449eac192faa35159752525b23345563252721c64tomhudson@google.com } 1295045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 129636352bf5e38f45a70ee4f4fc132a38048d38206dmtklein void blitRect(int x, int y, int width, int height) override { 12979154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com this->recordMinY(y); 129880cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com this->checkForYGap(y); 12999154eb08ec1f0d51688a6eb55c54111cf6ec5fbbreed@google.com fBuilder->addRectRun(x, y, width, height); 1300302b861338a626014153cc7368c54edbc646cfe5reed@google.com fLastY = y + height - 1; 1301562a2ac95b8cd8b359574f8c4d6300b0475938dbreed@google.com } 1302045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 130349eac192faa35159752525b23345563252721c64tomhudson@google.com virtual void blitAntiRect(int x, int y, int width, int height, 130436352bf5e38f45a70ee4f4fc132a38048d38206dmtklein SkAlpha leftAlpha, SkAlpha rightAlpha) override { 130549eac192faa35159752525b23345563252721c64tomhudson@google.com this->recordMinY(y); 1306302b861338a626014153cc7368c54edbc646cfe5reed@google.com this->checkForYGap(y); 130749eac192faa35159752525b23345563252721c64tomhudson@google.com fBuilder->addAntiRectRun(x, y, width, height, leftAlpha, rightAlpha); 1308302b861338a626014153cc7368c54edbc646cfe5reed@google.com fLastY = y + height - 1; 130949eac192faa35159752525b23345563252721c64tomhudson@google.com } 131049eac192faa35159752525b23345563252721c64tomhudson@google.com 131136352bf5e38f45a70ee4f4fc132a38048d38206dmtklein void blitMask(const SkMask&, const SkIRect& clip) override 1312e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com { unexpected(); } 1313e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 131441e010cb901c0da9066c4df562030808c9ccd7f8reed const SkPixmap* justAnOpaqueColor(uint32_t*) override { 131596fcdcc219d2a0d3579719b84b28bede76efba64halcanary return nullptr; 1316e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1317e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 131836352bf5e38f45a70ee4f4fc132a38048d38206dmtklein void blitH(int x, int y, int width) override { 1319209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com this->recordMinY(y); 132080cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com this->checkForYGap(y); 1321e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fBuilder->addRun(x, y, 0xFF, width); 1322e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1323e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1324e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com virtual void blitAntiH(int x, int y, const SkAlpha alpha[], 132536352bf5e38f45a70ee4f4fc132a38048d38206dmtklein const int16_t runs[]) override { 1326209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com this->recordMinY(y); 132780cdb9a2139bdc6cb15b5bfb06ed9fc3e33bb39breed@google.com this->checkForYGap(y); 1328e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com for (;;) { 1329e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int count = *runs; 1330e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (count <= 0) { 1331e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return; 1332e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 13331778564c75de5799d45126984f8faafd03523100reed@google.com 13341778564c75de5799d45126984f8faafd03523100reed@google.com // The supersampler's buffer can be the width of the device, so 13351d3ab12b82e1fa16a0d6b6b9cc1c0290b45cbca9liyuqian // we may have to trim the run to our bounds. Previously, we assert that 13361d3ab12b82e1fa16a0d6b6b9cc1c0290b45cbca9liyuqian // the extra spans are always alpha==0. 13371d3ab12b82e1fa16a0d6b6b9cc1c0290b45cbca9liyuqian // However, the analytic AA is too sensitive to precision errors 13381d3ab12b82e1fa16a0d6b6b9cc1c0290b45cbca9liyuqian // so it may have extra spans with very tiny alpha because after several 13391d3ab12b82e1fa16a0d6b6b9cc1c0290b45cbca9liyuqian // arithmatic operations, the edge may bleed the path boundary a little bit. 13401d3ab12b82e1fa16a0d6b6b9cc1c0290b45cbca9liyuqian // Therefore, instead of always asserting alpha==0, we assert alpha < 0x10. 13411778564c75de5799d45126984f8faafd03523100reed@google.com int localX = x; 13421778564c75de5799d45126984f8faafd03523100reed@google.com int localCount = count; 13431778564c75de5799d45126984f8faafd03523100reed@google.com if (x < fLeft) { 13441d3ab12b82e1fa16a0d6b6b9cc1c0290b45cbca9liyuqian SkASSERT(0x10 > *alpha); 13451778564c75de5799d45126984f8faafd03523100reed@google.com int gap = fLeft - x; 13461778564c75de5799d45126984f8faafd03523100reed@google.com SkASSERT(gap <= count); 13471778564c75de5799d45126984f8faafd03523100reed@google.com localX += gap; 13481778564c75de5799d45126984f8faafd03523100reed@google.com localCount -= gap; 13491778564c75de5799d45126984f8faafd03523100reed@google.com } 13501778564c75de5799d45126984f8faafd03523100reed@google.com int right = x + count; 13511778564c75de5799d45126984f8faafd03523100reed@google.com if (right > fRight) { 13521d3ab12b82e1fa16a0d6b6b9cc1c0290b45cbca9liyuqian SkASSERT(0x10 > *alpha); 13531778564c75de5799d45126984f8faafd03523100reed@google.com localCount -= right - fRight; 13541778564c75de5799d45126984f8faafd03523100reed@google.com SkASSERT(localCount >= 0); 13551778564c75de5799d45126984f8faafd03523100reed@google.com } 1356fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 13571778564c75de5799d45126984f8faafd03523100reed@google.com if (localCount) { 13581778564c75de5799d45126984f8faafd03523100reed@google.com fBuilder->addRun(localX, y, *alpha, localCount); 13591778564c75de5799d45126984f8faafd03523100reed@google.com } 1360820e80ad6390e120d4991a5280d0452ec87beaebbsalomon@google.com // Next run 1361e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com runs += count; 1362e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com alpha += count; 1363e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com x += count; 1364e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1365e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1366e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1367e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comprivate: 1368e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com Builder* fBuilder; 13691778564c75de5799d45126984f8faafd03523100reed@google.com int fLeft; // cache of builder's bounds' left edge 13701778564c75de5799d45126984f8faafd03523100reed@google.com int fRight; 1371209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com int fMinY; 1372209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com 1373209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com /* 1374209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com * We track this, in case the scan converter skipped some number of 1375209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com * scanlines at the (relative to the bounds it was given). This allows 1376209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com * the builder, during its finish, to trip its bounds down to the "real" 1377209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com * top. 1378209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com */ 1379209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com void recordMinY(int y) { 1380209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com if (y < fMinY) { 1381209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com fMinY = y; 1382209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com } 1383209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com } 1384e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1385e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com void unexpected() { 13867ca9a74fef3296cdf1385785b5e817e963bb4c35Ben Wagner SK_ABORT("---- did not expect to get called here"); 1387e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1388e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com}; 1389e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1390f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.combool SkAAClip::setPath(const SkPath& path, const SkRegion* clip, bool doAA) { 1391045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com AUTO_AACLIP_VALIDATE(*this); 1392045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1393322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com if (clip && clip->isEmpty()) { 1394e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return this->setEmpty(); 1395e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1396e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1397e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkIRect ibounds; 1398322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com path.getBounds().roundOut(&ibounds); 1399e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1400322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com SkRegion tmpClip; 140196fcdcc219d2a0d3579719b84b28bede76efba64halcanary if (nullptr == clip) { 1402322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com tmpClip.setRect(ibounds); 1403322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com clip = &tmpClip; 1404322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1405fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1406ca85fc3159e9735b8e589bbc5b736a34affb12b5Yuqian Li // Since we assert that the BuilderBlitter will never blit outside the intersection 1407ca85fc3159e9735b8e589bbc5b736a34affb12b5Yuqian Li // of clip and ibounds, we create this snugClip to be that intersection and send it 1408ca85fc3159e9735b8e589bbc5b736a34affb12b5Yuqian Li // to the scan-converter. 1409ca85fc3159e9735b8e589bbc5b736a34affb12b5Yuqian Li SkRegion snugClip(*clip); 1410ca85fc3159e9735b8e589bbc5b736a34affb12b5Yuqian Li 1411045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (path.isInverseFillType()) { 1412045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com ibounds = clip->getBounds(); 1413045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } else { 1414322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com if (ibounds.isEmpty() || !ibounds.intersect(clip->getBounds())) { 1415e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return this->setEmpty(); 1416e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1417ca85fc3159e9735b8e589bbc5b736a34affb12b5Yuqian Li snugClip.op(ibounds, SkRegion::kIntersect_Op); 1418e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1419e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1420e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com Builder builder(ibounds); 1421e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com BuilderBlitter blitter(&builder); 1422e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1423f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com if (doAA) { 14247d99dad70b97a534a6e23e9c74d914b5eb17ff1eYuqian Li SkScan::AntiFillPath(path, snugClip, &blitter, true); 1425f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com } else { 1426ca85fc3159e9735b8e589bbc5b736a34affb12b5Yuqian Li SkScan::FillPath(path, snugClip, &blitter); 1427f3c1da1e977a0e02535af71749fe9e92665ed51ereed@google.com } 1428e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1429209c41511eb0d06f8c19f8fb1fc0393c502a1b18reed@google.com blitter.finish(); 1430045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return builder.finish(this); 1431e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 1432e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1433e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com/////////////////////////////////////////////////////////////////////////////// 1434e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1435322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comtypedef void (*RowProc)(SkAAClip::Builder&, int bottom, 1436322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com const uint8_t* rowA, const SkIRect& rectA, 1437322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com const uint8_t* rowB, const SkIRect& rectB); 1438322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1439322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comtypedef U8CPU (*AlphaProc)(U8CPU alphaA, U8CPU alphaB); 1440322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1441322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comstatic U8CPU sectAlphaProc(U8CPU alphaA, U8CPU alphaB) { 1442322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com // Multiply 1443322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return SkMulDiv255Round(alphaA, alphaB); 1444322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com} 1445322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1446322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comstatic U8CPU unionAlphaProc(U8CPU alphaA, U8CPU alphaB) { 1447322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com // SrcOver 1448322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return alphaA + alphaB - SkMulDiv255Round(alphaA, alphaB); 1449322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com} 1450322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1451322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comstatic U8CPU diffAlphaProc(U8CPU alphaA, U8CPU alphaB) { 1452322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com // SrcOut 1453322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return SkMulDiv255Round(alphaA, 0xFF - alphaB); 1454322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com} 1455322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1456322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comstatic U8CPU xorAlphaProc(U8CPU alphaA, U8CPU alphaB) { 1457322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com // XOR 1458322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return alphaA + alphaB - 2 * SkMulDiv255Round(alphaA, alphaB); 1459322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com} 1460322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1461322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comstatic AlphaProc find_alpha_proc(SkRegion::Op op) { 1462322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com switch (op) { 1463322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com case SkRegion::kIntersect_Op: 1464322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return sectAlphaProc; 1465322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com case SkRegion::kDifference_Op: 1466322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return diffAlphaProc; 1467322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com case SkRegion::kUnion_Op: 1468322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return unionAlphaProc; 1469322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com case SkRegion::kXOR_Op: 1470322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return xorAlphaProc; 1471322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com default: 14720c00f21fee3f5cfa3aa7e5d46ff94cb8cf340451tomhudson@google.com SkDEBUGFAIL("unexpected region op"); 1473322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return sectAlphaProc; 1474322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1475322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com} 1476322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1477322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comclass RowIter { 1478322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.compublic: 1479322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com RowIter(const uint8_t* row, const SkIRect& bounds) { 1480322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com fRow = row; 1481322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com fLeft = bounds.fLeft; 1482322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com fBoundsRight = bounds.fRight; 14831c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (row) { 14841c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fRight = bounds.fLeft + row[0]; 14851c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com SkASSERT(fRight <= fBoundsRight); 14861c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fAlpha = row[1]; 14871c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fDone = false; 14881c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } else { 14891c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fDone = true; 14901c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fRight = kMaxInt32; 14911c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fAlpha = 0; 14921c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } 1493322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1494322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1495322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com bool done() const { return fDone; } 14961c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com int left() const { return fLeft; } 14971c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com int right() const { return fRight; } 14981c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com U8CPU alpha() const { return fAlpha; } 1499322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com void next() { 15001c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (!fDone) { 1501322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com fLeft = fRight; 15021c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (fRight == fBoundsRight) { 15031c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fDone = true; 15041c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fRight = kMaxInt32; 15051c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fAlpha = 0; 15061c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } else { 15071c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fRow += 2; 15081c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fRight += fRow[0]; 15091c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com fAlpha = fRow[1]; 15101c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com SkASSERT(fRight <= fBoundsRight); 15111c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } 1512322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1513322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1514322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1515322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comprivate: 1516322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com const uint8_t* fRow; 1517322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com int fLeft; 1518322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com int fRight; 1519322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com int fBoundsRight; 1520322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com bool fDone; 15211c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com uint8_t fAlpha; 1522322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com}; 1523322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 15241c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.comstatic void adjust_row(RowIter& iter, int& leftA, int& riteA, int rite) { 15251c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (rite == riteA) { 15261c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com iter.next(); 15271c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com leftA = iter.left(); 15281c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com riteA = iter.right(); 1529322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1530322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com} 1531322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1532803eceb6afd13f07416df0b4a9bb714e9370f081caryclark@google.com#if 0 // UNUSED 15331c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.comstatic bool intersect(int& min, int& max, int boundsMin, int boundsMax) { 15341c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com SkASSERT(min < max); 15351c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com SkASSERT(boundsMin < boundsMax); 15361c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (min >= boundsMax || max <= boundsMin) { 15371c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com return false; 15381c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } 15391c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (min < boundsMin) { 15401c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com min = boundsMin; 15411c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } 15421c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (max > boundsMax) { 15431c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com max = boundsMax; 15441c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } 15451c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com return true; 15461c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com} 1547803eceb6afd13f07416df0b4a9bb714e9370f081caryclark@google.com#endif 15481c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com 1549322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comstatic void operatorX(SkAAClip::Builder& builder, int lastY, 1550322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com RowIter& iterA, RowIter& iterB, 1551322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com AlphaProc proc, const SkIRect& bounds) { 1552322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com int leftA = iterA.left(); 1553322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com int riteA = iterA.right(); 1554322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com int leftB = iterB.left(); 1555322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com int riteB = iterB.right(); 1556322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 15571c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com int prevRite = bounds.fLeft; 15581c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com 15591c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com do { 1560322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com U8CPU alphaA = 0; 1561322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com U8CPU alphaB = 0; 1562322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com int left, rite; 1563fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 15641c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (leftA < leftB) { 1565322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com left = leftA; 1566322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com alphaA = iterA.alpha(); 15671c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (riteA <= leftB) { 15681c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com rite = riteA; 15691c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } else { 15701c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com rite = leftA = leftB; 15711c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } 15721c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } else if (leftB < leftA) { 1573322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com left = leftB; 1574322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com alphaB = iterB.alpha(); 15751c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (riteB <= leftA) { 15761c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com rite = riteB; 15771c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } else { 15781c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com rite = leftB = leftA; 15791c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } 1580322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } else { 15811c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com left = leftA; // or leftB, since leftA == leftB 15821c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com rite = leftA = leftB = SkMin32(riteA, riteB); 1583322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com alphaA = iterA.alpha(); 1584322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com alphaB = iterB.alpha(); 1585322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1586322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1587322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com if (left >= bounds.fRight) { 1588322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com break; 1589322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 159034f7e47a3593911d03307a08e5af625b218ceec3reed@google.com if (rite > bounds.fRight) { 159134f7e47a3593911d03307a08e5af625b218ceec3reed@google.com rite = bounds.fRight; 159234f7e47a3593911d03307a08e5af625b218ceec3reed@google.com } 159334f7e47a3593911d03307a08e5af625b218ceec3reed@google.com 1594322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com if (left >= bounds.fLeft) { 15951c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com SkASSERT(rite > left); 1596322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com builder.addRun(left, lastY, proc(alphaA, alphaB), rite - left); 15971c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com prevRite = rite; 1598322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 15991c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com 16001c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com adjust_row(iterA, leftA, riteA, rite); 16011c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com adjust_row(iterB, leftB, riteB, rite); 16021c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } while (!iterA.done() || !iterB.done()); 16031c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com 16041c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (prevRite < bounds.fRight) { 16051c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com builder.addRun(prevRite, lastY, 0, bounds.fRight - prevRite); 1606322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1607322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com} 1608322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 16091c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.comstatic void adjust_iter(SkAAClip::Iter& iter, int& topA, int& botA, int bot) { 16101c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (bot == botA) { 16111c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com iter.next(); 16121c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com topA = botA; 16131c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com SkASSERT(botA == iter.top()); 16141c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com botA = iter.bottom(); 1615322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1616322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com} 1617322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1618322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.comstatic void operateY(SkAAClip::Builder& builder, const SkAAClip& A, 1619322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com const SkAAClip& B, SkRegion::Op op) { 1620322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com AlphaProc proc = find_alpha_proc(op); 1621322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com const SkIRect& bounds = builder.getBounds(); 1622322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1623322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com SkAAClip::Iter iterA(A); 1624322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com SkAAClip::Iter iterB(B); 1625322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1626322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com SkASSERT(!iterA.done()); 1627322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com int topA = iterA.top(); 1628322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com int botA = iterA.bottom(); 1629322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com SkASSERT(!iterB.done()); 1630322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com int topB = iterB.top(); 1631322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com int botB = iterB.bottom(); 1632322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 16331c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com do { 163496fcdcc219d2a0d3579719b84b28bede76efba64halcanary const uint8_t* rowA = nullptr; 163596fcdcc219d2a0d3579719b84b28bede76efba64halcanary const uint8_t* rowB = nullptr; 1636322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com int top, bot; 16371c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com 16381c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (topA < topB) { 1639322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com top = topA; 1640322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com rowA = iterA.data(); 16411c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (botA <= topB) { 16421c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com bot = botA; 16431c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } else { 16441c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com bot = topA = topB; 16451c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } 1646fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 16471c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } else if (topB < topA) { 1648322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com top = topB; 1649322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com rowB = iterB.data(); 16501c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (botB <= topA) { 16511c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com bot = botB; 16521c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } else { 16531c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com bot = topB = topA; 16541c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } 1655322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } else { 16561c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com top = topA; // or topB, since topA == topB 16571c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com bot = topA = topB = SkMin32(botA, botB); 1658322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com rowA = iterA.data(); 1659322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com rowB = iterB.data(); 1660322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1661322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1662322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com if (top >= bounds.fBottom) { 1663322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com break; 1664322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 166534f7e47a3593911d03307a08e5af625b218ceec3reed@google.com 166634f7e47a3593911d03307a08e5af625b218ceec3reed@google.com if (bot > bounds.fBottom) { 166734f7e47a3593911d03307a08e5af625b218ceec3reed@google.com bot = bounds.fBottom; 166834f7e47a3593911d03307a08e5af625b218ceec3reed@google.com } 166934f7e47a3593911d03307a08e5af625b218ceec3reed@google.com SkASSERT(top < bot); 167034f7e47a3593911d03307a08e5af625b218ceec3reed@google.com 16711c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com if (!rowA && !rowB) { 16721c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com builder.addRun(bounds.fLeft, bot - 1, 0, bounds.width()); 16731c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } else if (top >= bounds.fTop) { 16741c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com SkASSERT(bot <= bounds.fBottom); 16751c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com RowIter rowIterA(rowA, rowA ? A.getBounds() : bounds); 16761c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com RowIter rowIterB(rowB, rowB ? B.getBounds() : bounds); 1677322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com operatorX(builder, bot - 1, rowIterA, rowIterB, proc, bounds); 1678322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1679322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 16801c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com adjust_iter(iterA, topA, botA, bot); 16811c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com adjust_iter(iterB, topB, botB, bot); 16821c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } while (!iterA.done() || !iterB.done()); 1683322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com} 1684322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1685322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.combool SkAAClip::op(const SkAAClip& clipAOrig, const SkAAClip& clipBOrig, 1686322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com SkRegion::Op op) { 1687045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com AUTO_AACLIP_VALIDATE(*this); 1688fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1689322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com if (SkRegion::kReplace_Op == op) { 1690322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return this->set(clipBOrig); 1691322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1692fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1693322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com const SkAAClip* clipA = &clipAOrig; 1694322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com const SkAAClip* clipB = &clipBOrig; 1695fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1696322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com if (SkRegion::kReverseDifference_Op == op) { 1697322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com SkTSwap(clipA, clipB); 1698322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com op = SkRegion::kDifference_Op; 1699322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1700322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1701322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com bool a_empty = clipA->isEmpty(); 1702322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com bool b_empty = clipB->isEmpty(); 1703322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1704322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com SkIRect bounds; 1705322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com switch (op) { 1706322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com case SkRegion::kDifference_Op: 1707322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com if (a_empty) { 1708322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return this->setEmpty(); 1709322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1710322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com if (b_empty || !SkIRect::Intersects(clipA->fBounds, clipB->fBounds)) { 1711322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return this->set(*clipA); 1712322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1713322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com bounds = clipA->fBounds; 1714322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com break; 1715fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1716322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com case SkRegion::kIntersect_Op: 1717322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com if ((a_empty | b_empty) || !bounds.intersect(clipA->fBounds, 1718322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com clipB->fBounds)) { 1719322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return this->setEmpty(); 1720322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1721322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com break; 1722fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1723322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com case SkRegion::kUnion_Op: 1724322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com case SkRegion::kXOR_Op: 1725322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com if (a_empty) { 1726322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return this->set(*clipB); 1727322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1728322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com if (b_empty) { 1729322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return this->set(*clipA); 1730322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1731322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com bounds = clipA->fBounds; 1732322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com bounds.join(clipB->fBounds); 1733322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com break; 1734322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1735322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com default: 17360c00f21fee3f5cfa3aa7e5d46ff94cb8cf340451tomhudson@google.com SkDEBUGFAIL("unknown region op"); 1737322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return !this->isEmpty(); 1738322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 1739322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1740322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com SkASSERT(SkIRect::Intersects(bounds, clipB->fBounds)); 1741322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com SkASSERT(SkIRect::Intersects(bounds, clipB->fBounds)); 1742322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 1743322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com Builder builder(bounds); 1744322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com operateY(builder, *clipA, *clipB, op); 1745045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1746045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return builder.finish(this); 1747e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 1748e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1749045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com/* 1750045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com * It can be expensive to build a local aaclip before applying the op, so 1751045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com * we first see if we can restrict the bounds of new rect to our current 1752045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com * bounds, or note that the new rect subsumes our current clip. 1753045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com */ 1754045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1755045e62d715f5ee9b03deb5af3c750f8318096179reed@google.combool SkAAClip::op(const SkIRect& rOrig, SkRegion::Op op) { 1756045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkIRect rStorage; 1757045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const SkIRect* r = &rOrig; 1758045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1759045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com switch (op) { 1760045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com case SkRegion::kIntersect_Op: 1761045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (!rStorage.intersect(rOrig, fBounds)) { 1762045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com // no overlap, so we're empty 1763045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return this->setEmpty(); 1764045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1765045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (rStorage == fBounds) { 1766045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com // we were wholly inside the rect, no change 1767045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return !this->isEmpty(); 1768045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1769045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (this->quickContains(rStorage)) { 1770045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com // the intersection is wholly inside us, we're a rect 1771045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return this->setRect(rStorage); 1772045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1773045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com r = &rStorage; // use the intersected bounds 1774045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com break; 1775045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com case SkRegion::kDifference_Op: 1776045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com break; 1777045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com case SkRegion::kUnion_Op: 1778045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (rOrig.contains(fBounds)) { 1779045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return this->setRect(rOrig); 1780045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1781045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com break; 1782045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com default: 1783045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com break; 1784045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1785045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 178647ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com SkAAClip clip; 1787045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com clip.setRect(*r); 178847ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com return this->op(*this, clip, op); 178947ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com} 179047ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com 1791045e62d715f5ee9b03deb5af3c750f8318096179reed@google.combool SkAAClip::op(const SkRect& rOrig, SkRegion::Op op, bool doAA) { 1792045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkRect rStorage, boundsStorage; 1793045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const SkRect* r = &rOrig; 1794fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1795045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com boundsStorage.set(fBounds); 1796045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com switch (op) { 1797045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com case SkRegion::kIntersect_Op: 1798045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com case SkRegion::kDifference_Op: 1799045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (!rStorage.intersect(rOrig, boundsStorage)) { 1800e56513d2a9eebabf93d7824eebf9e64441c485bareed@google.com if (SkRegion::kIntersect_Op == op) { 1801e56513d2a9eebabf93d7824eebf9e64441c485bareed@google.com return this->setEmpty(); 1802e56513d2a9eebabf93d7824eebf9e64441c485bareed@google.com } else { // kDifference 1803e56513d2a9eebabf93d7824eebf9e64441c485bareed@google.com return !this->isEmpty(); 1804e56513d2a9eebabf93d7824eebf9e64441c485bareed@google.com } 1805045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1806045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com r = &rStorage; // use the intersected bounds 1807045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com break; 1808045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com case SkRegion::kUnion_Op: 1809045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (rOrig.contains(boundsStorage)) { 1810045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return this->setRect(rOrig); 1811045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1812045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com break; 1813045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com default: 1814045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com break; 1815045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1816fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 181747ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com SkAAClip clip; 1818045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com clip.setRect(*r, doAA); 181947ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com return this->op(*this, clip, op); 182047ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com} 182147ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com 182247ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.combool SkAAClip::op(const SkAAClip& clip, SkRegion::Op op) { 182347ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com return this->op(*this, clip, op); 182447ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com} 182547ac84edafc6f26e2146ab10363e2043c5af0e62reed@google.com 1826e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com/////////////////////////////////////////////////////////////////////////////// 1827045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1828045e62d715f5ee9b03deb5af3c750f8318096179reed@google.combool SkAAClip::translate(int dx, int dy, SkAAClip* dst) const { 182996fcdcc219d2a0d3579719b84b28bede76efba64halcanary if (nullptr == dst) { 1830045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return !this->isEmpty(); 1831045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1832fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1833045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (this->isEmpty()) { 1834045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return dst->setEmpty(); 1835045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1836fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1837045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (this != dst) { 1838045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com sk_atomic_inc(&fRunHead->fRefCnt); 183919224c3d7903921ca86c856cc42adb31fc3164a9tomhudson@google.com dst->freeRuns(); 1840045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com dst->fRunHead = fRunHead; 1841045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com dst->fBounds = fBounds; 1842045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1843045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com dst->fBounds.offset(dx, dy); 1844045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return true; 1845045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com} 1846045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1847045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comstatic void expand_row_to_mask(uint8_t* SK_RESTRICT mask, 1848045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const uint8_t* SK_RESTRICT row, 1849045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com int width) { 1850045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com while (width > 0) { 1851045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com int n = row[0]; 1852045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(width >= n); 1853045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com memset(mask, row[1], n); 1854045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com mask += n; 1855045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com row += 2; 1856045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com width -= n; 1857045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1858a069c8ff9abf00efed85ca0a2df37a7a7f30390ereed@google.com SkASSERT(0 == width); 1859045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com} 1860045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1861045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comvoid SkAAClip::copyToMask(SkMask* mask) const { 1862045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com mask->fFormat = SkMask::kA8_Format; 1863045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (this->isEmpty()) { 1864045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com mask->fBounds.setEmpty(); 186596fcdcc219d2a0d3579719b84b28bede76efba64halcanary mask->fImage = nullptr; 1866045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com mask->fRowBytes = 0; 1867045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return; 1868045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1869fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1870045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com mask->fBounds = fBounds; 1871045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com mask->fRowBytes = fBounds.width(); 1872045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com size_t size = mask->computeImageSize(); 1873045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com mask->fImage = SkMask::AllocImage(size); 1874fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1875045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com Iter iter(*this); 1876045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com uint8_t* dst = mask->fImage; 1877045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const int width = fBounds.width(); 1878fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1879045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com int y = fBounds.fTop; 1880045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com while (!iter.done()) { 1881045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com do { 1882045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com expand_row_to_mask(dst, iter.data(), width); 1883045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com dst += mask->fRowBytes; 1884045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } while (++y < iter.bottom()); 1885045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com iter.next(); 1886045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1887045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com} 1888045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1889045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com/////////////////////////////////////////////////////////////////////////////// 1890e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com/////////////////////////////////////////////////////////////////////////////// 1891e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1892e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comstatic void expandToRuns(const uint8_t* SK_RESTRICT data, int initialCount, int width, 1893e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int16_t* SK_RESTRICT runs, SkAlpha* SK_RESTRICT aa) { 1894e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com // we don't read our initial n from data, since the caller may have had to 1895e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com // clip it, hence the initialCount parameter. 1896e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int n = initialCount; 1897e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com for (;;) { 1898e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (n > width) { 1899e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com n = width; 1900e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1901e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(n > 0); 1902e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com runs[0] = n; 1903e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com runs += n; 1904e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1905e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com aa[0] = data[1]; 1906e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com aa += n; 1907fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1908e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com data += 2; 1909e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com width -= n; 1910e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (0 == width) { 1911e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com break; 1912e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1913e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com // load the next count 1914e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com n = data[0]; 1915e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1916e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com runs[0] = 0; // sentinel 1917e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 1918e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1919e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comSkAAClipBlitter::~SkAAClipBlitter() { 1920045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com sk_free(fScanlineScratch); 1921e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 1922e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1923e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comvoid SkAAClipBlitter::ensureRunsAndAA() { 192496fcdcc219d2a0d3579719b84b28bede76efba64halcanary if (nullptr == fScanlineScratch) { 1925e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com // add 1 so we can store the terminating run count of 0 1926e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int count = fAAClipBounds.width() + 1; 1927045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com // we use this either for fRuns + fAA, or a scaline of a mask 1928045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com // which may be as deep as 32bits 1929045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fScanlineScratch = sk_malloc_throw(count * sizeof(SkPMColor)); 1930045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fRuns = (int16_t*)fScanlineScratch; 1931e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fAA = (SkAlpha*)(fRuns + count); 1932e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1933e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 1934e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1935e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comvoid SkAAClipBlitter::blitH(int x, int y, int width) { 1936e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(width > 0); 1937e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(fAAClipBounds.contains(x, y)); 1938e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(fAAClipBounds.contains(x + width - 1, y)); 1939e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1940a4c6e4d6d3a4010df8dd2b04314675e4c201133breed@google.com const uint8_t* row = fAAClip->findRow(y); 1941e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int initialCount; 1942e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com row = fAAClip->findX(row, x, &initialCount); 1943e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1944e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (initialCount >= width) { 1945e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkAlpha alpha = row[1]; 1946e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (0 == alpha) { 1947e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return; 1948e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1949e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (0xFF == alpha) { 1950e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fBlitter->blitH(x, y, width); 1951e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return; 1952e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1953e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1954e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1955e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com this->ensureRunsAndAA(); 1956e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com expandToRuns(row, initialCount, width, fRuns, fAA); 1957e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1958e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fBlitter->blitAntiH(x, y, fAA, fRuns); 1959e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 1960e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1961e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comstatic void merge(const uint8_t* SK_RESTRICT row, int rowN, 1962e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const SkAlpha* SK_RESTRICT srcAA, 1963e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const int16_t* SK_RESTRICT srcRuns, 1964e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkAlpha* SK_RESTRICT dstAA, 1965e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int16_t* SK_RESTRICT dstRuns, 1966e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int width) { 1967e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkDEBUGCODE(int accumulated = 0;) 1968e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int srcN = srcRuns[0]; 1969045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com // do we need this check? 1970045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (0 == srcN) { 1971045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return; 1972045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1973045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1974e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com for (;;) { 1975e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(rowN > 0); 1976e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(srcN > 0); 1977e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1978e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com unsigned newAlpha = SkMulDiv255Round(srcAA[0], row[1]); 1979e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int minN = SkMin32(srcN, rowN); 1980e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com dstRuns[0] = minN; 1981e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com dstRuns += minN; 1982e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com dstAA[0] = newAlpha; 1983e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com dstAA += minN; 1984e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 1985e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (0 == (srcN -= minN)) { 1986e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com srcN = srcRuns[0]; // refresh 1987e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com srcRuns += srcN; 1988e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com srcAA += srcN; 1989e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com srcN = srcRuns[0]; // reload 1990045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (0 == srcN) { 1991045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com break; 1992045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1993e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1994e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (0 == (rowN -= minN)) { 1995e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com row += 2; 1996e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com rowN = row[0]; // reload 1997e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 1998fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1999e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkDEBUGCODE(accumulated += minN;) 2000e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkASSERT(accumulated <= width); 2001e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 200234f7e47a3593911d03307a08e5af625b218ceec3reed@google.com dstRuns[0] = 0; 2003e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 2004e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 2005e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comvoid SkAAClipBlitter::blitAntiH(int x, int y, const SkAlpha aa[], 2006e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const int16_t runs[]) { 2007a4c6e4d6d3a4010df8dd2b04314675e4c201133breed@google.com 2008a4c6e4d6d3a4010df8dd2b04314675e4c201133breed@google.com const uint8_t* row = fAAClip->findRow(y); 2009e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com int initialCount; 2010e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com row = fAAClip->findX(row, x, &initialCount); 2011e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 2012e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com this->ensureRunsAndAA(); 2013e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 2014e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com merge(row, initialCount, aa, runs, fAA, fRuns, fAAClipBounds.width()); 2015e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fBlitter->blitAntiH(x, y, fAA, fRuns); 2016e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 2017e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 2018e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comvoid SkAAClipBlitter::blitV(int x, int y, int height, SkAlpha alpha) { 2019e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (fAAClip->quickContains(x, y, x + 1, y + height)) { 2020e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fBlitter->blitV(x, y, height, alpha); 2021e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return; 2022e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 2023e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 2024045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com for (;;) { 2025a4c6e4d6d3a4010df8dd2b04314675e4c201133breed@google.com int lastY SK_INIT_TO_AVOID_WARNING; 2026e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com const uint8_t* row = fAAClip->findRow(y, &lastY); 2027045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com int dy = lastY - y + 1; 2028045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (dy > height) { 2029045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com dy = height; 2030045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 2031045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com height -= dy; 2032045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 2033a4c6e4d6d3a4010df8dd2b04314675e4c201133breed@google.com row = fAAClip->findX(row, x); 2034e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com SkAlpha newAlpha = SkMulDiv255Round(alpha, row[1]); 2035e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (newAlpha) { 2036045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fBlitter->blitV(x, y, dy, newAlpha); 2037045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 2038045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(height >= 0); 2039045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (height <= 0) { 2040045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com break; 2041e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 2042e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com y = lastY + 1; 2043045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 2044e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 2045e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 2046e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.comvoid SkAAClipBlitter::blitRect(int x, int y, int width, int height) { 2047e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com if (fAAClip->quickContains(x, y, x + width, y + height)) { 2048e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com fBlitter->blitRect(x, y, width, height); 2049e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com return; 2050e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 2051e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 2052e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com while (--height >= 0) { 2053e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com this->blitH(x, y, width); 2054e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com y += 1; 2055e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com } 2056e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 2057e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 2058045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comtypedef void (*MergeAAProc)(const void* src, int width, const uint8_t* row, 2059045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com int initialRowCount, void* dst); 2060045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 2061045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comstatic void small_memcpy(void* dst, const void* src, size_t n) { 2062045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com memcpy(dst, src, n); 2063e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 2064e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 2065045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comstatic void small_bzero(void* dst, size_t n) { 2066045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com sk_bzero(dst, n); 2067e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com} 2068e36707a4a82a4dea7d480d969220f3ed223305dcreed@google.com 2069045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comstatic inline uint8_t mergeOne(uint8_t value, unsigned alpha) { 2070045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return SkMulDiv255Round(value, alpha); 2071045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com} 2072d54d3fc82456f8789b3e4dff40faeb7b670bcf4breed 2073045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comstatic inline uint16_t mergeOne(uint16_t value, unsigned alpha) { 2074045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com unsigned r = SkGetPackedR16(value); 2075045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com unsigned g = SkGetPackedG16(value); 2076045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com unsigned b = SkGetPackedB16(value); 2077045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return SkPackRGB16(SkMulDiv255Round(r, alpha), 2078803eceb6afd13f07416df0b4a9bb714e9370f081caryclark@google.com SkMulDiv255Round(g, alpha), 2079803eceb6afd13f07416df0b4a9bb714e9370f081caryclark@google.com SkMulDiv255Round(b, alpha)); 2080045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com} 2081322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 20829449616020a58043a49f0342679bf095918792a6herbtemplate <typename T> 20839449616020a58043a49f0342679bf095918792a6herbvoid mergeT(const void* inSrc, int srcN, const uint8_t* SK_RESTRICT row, int rowN, void* inDst) { 20849449616020a58043a49f0342679bf095918792a6herb const T* SK_RESTRICT src = static_cast<const T*>(inSrc); 20859449616020a58043a49f0342679bf095918792a6herb T* SK_RESTRICT dst = static_cast<T*>(inDst); 2086045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com for (;;) { 2087045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(rowN > 0); 2088045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(srcN > 0); 2089fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 2090045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com int n = SkMin32(rowN, srcN); 2091045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com unsigned rowA = row[1]; 2092045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (0xFF == rowA) { 2093045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com small_memcpy(dst, src, n * sizeof(T)); 2094045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } else if (0 == rowA) { 2095045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com small_bzero(dst, n * sizeof(T)); 2096045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } else { 2097045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com for (int i = 0; i < n; ++i) { 2098045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com dst[i] = mergeOne(src[i], rowA); 2099045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 2100045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 2101fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 2102045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (0 == (srcN -= n)) { 2103045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com break; 2104045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 2105fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 2106045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com src += n; 2107045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com dst += n; 2108fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 2109045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(rowN == n); 2110045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com row += 2; 2111045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com rowN = row[0]; 21121c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } 2113045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com} 21141c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com 2115045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comstatic MergeAAProc find_merge_aa_proc(SkMask::Format format) { 2116045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com switch (format) { 2117045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com case SkMask::kBW_Format: 21180c00f21fee3f5cfa3aa7e5d46ff94cb8cf340451tomhudson@google.com SkDEBUGFAIL("unsupported"); 211996fcdcc219d2a0d3579719b84b28bede76efba64halcanary return nullptr; 2120045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com case SkMask::kA8_Format: 21219449616020a58043a49f0342679bf095918792a6herb case SkMask::k3D_Format: 21229449616020a58043a49f0342679bf095918792a6herb return mergeT<uint8_t> ; 21239449616020a58043a49f0342679bf095918792a6herb case SkMask::kLCD16_Format: 21249449616020a58043a49f0342679bf095918792a6herb return mergeT<uint16_t>; 2125045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com default: 21260c00f21fee3f5cfa3aa7e5d46ff94cb8cf340451tomhudson@google.com SkDEBUGFAIL("unsupported"); 212796fcdcc219d2a0d3579719b84b28bede76efba64halcanary return nullptr; 21281c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com } 2129045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com} 21301c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com 2131045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comstatic U8CPU bit2byte(int bitInAByte) { 2132045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(bitInAByte <= 0xFF); 2133045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com // negation turns any non-zero into 0xFFFFFF??, so we just shift down 2134045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com // some value >= 8 to get a full FF value 2135045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return -bitInAByte >> 8; 21361c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com} 21371c04bf97b6245b55ac58c2f3902f8ca95ca91c3dreed@google.com 2138045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comstatic void upscaleBW2A8(SkMask* dstMask, const SkMask& srcMask) { 2139045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(SkMask::kBW_Format == srcMask.fFormat); 2140045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(SkMask::kA8_Format == dstMask->fFormat); 2141045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 2142045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const int width = srcMask.fBounds.width(); 2143045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const int height = srcMask.fBounds.height(); 2144045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 2145045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const uint8_t* SK_RESTRICT src = (const uint8_t*)srcMask.fImage; 2146045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const size_t srcRB = srcMask.fRowBytes; 2147045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com uint8_t* SK_RESTRICT dst = (uint8_t*)dstMask->fImage; 2148045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const size_t dstRB = dstMask->fRowBytes; 2149045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 2150045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const int wholeBytes = width >> 3; 2151045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const int leftOverBits = width & 7; 2152045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 2153045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com for (int y = 0; y < height; ++y) { 2154045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com uint8_t* SK_RESTRICT d = dst; 2155045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com for (int i = 0; i < wholeBytes; ++i) { 2156045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com int srcByte = src[i]; 2157045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com d[0] = bit2byte(srcByte & (1 << 7)); 2158045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com d[1] = bit2byte(srcByte & (1 << 6)); 2159045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com d[2] = bit2byte(srcByte & (1 << 5)); 2160045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com d[3] = bit2byte(srcByte & (1 << 4)); 2161045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com d[4] = bit2byte(srcByte & (1 << 3)); 2162045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com d[5] = bit2byte(srcByte & (1 << 2)); 2163045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com d[6] = bit2byte(srcByte & (1 << 1)); 2164045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com d[7] = bit2byte(srcByte & (1 << 0)); 2165045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com d += 8; 2166045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 2167045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (leftOverBits) { 2168045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com int srcByte = src[wholeBytes]; 2169045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com for (int x = 0; x < leftOverBits; ++x) { 2170045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com *d++ = bit2byte(srcByte & 0x80); 2171045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com srcByte <<= 1; 2172045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 2173045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 2174045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com src += srcRB; 2175045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com dst += dstRB; 2176322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 2177322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com} 2178322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 2179045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comvoid SkAAClipBlitter::blitMask(const SkMask& origMask, const SkIRect& clip) { 2180045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(fAAClip->getBounds().contains(clip)); 2181045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 2182045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (fAAClip->quickContains(clip)) { 2183045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fBlitter->blitMask(origMask, clip); 2184322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com return; 2185322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 2186322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 2187045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const SkMask* mask = &origMask; 2188322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 2189045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com // if we're BW, we need to upscale to A8 (ugh) 2190045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkMask grayMask; 2191045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (SkMask::kBW_Format == origMask.fFormat) { 2192045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com grayMask.fFormat = SkMask::kA8_Format; 2193045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com grayMask.fBounds = origMask.fBounds; 2194045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com grayMask.fRowBytes = origMask.fBounds.width(); 2195045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com size_t size = grayMask.computeImageSize(); 2196045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com grayMask.fImage = (uint8_t*)fGrayMaskScratch.reset(size, 2197045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkAutoMalloc::kReuse_OnShrink); 2198322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com 2199045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com upscaleBW2A8(&grayMask, origMask); 2200045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com mask = &grayMask; 2201322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com } 2202045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 2203045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com this->ensureRunsAndAA(); 2204045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 2205045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com // HACK -- we are devolving 3D into A8, need to copy the rest of the 3D 2206045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com // data into a temp block to support it better (ugh) 2207045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 2208045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const void* src = mask->getAddr(clip.fLeft, clip.fTop); 2209045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const size_t srcRB = mask->fRowBytes; 2210045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const int width = clip.width(); 2211045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com MergeAAProc mergeProc = find_merge_aa_proc(mask->fFormat); 2212045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 2213045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkMask rowMask; 2214045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com rowMask.fFormat = SkMask::k3D_Format == mask->fFormat ? SkMask::kA8_Format : mask->fFormat; 2215045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com rowMask.fBounds.fLeft = clip.fLeft; 2216045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com rowMask.fBounds.fRight = clip.fRight; 2217045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com rowMask.fRowBytes = mask->fRowBytes; // doesn't matter, since our height==1 2218045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com rowMask.fImage = (uint8_t*)fScanlineScratch; 2219045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 2220045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com int y = clip.fTop; 2221045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const int stopY = y + clip.height(); 2222045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 2223045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com do { 2224a4c6e4d6d3a4010df8dd2b04314675e4c201133breed@google.com int localStopY SK_INIT_TO_AVOID_WARNING; 2225045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const uint8_t* row = fAAClip->findRow(y, &localStopY); 2226045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com // findRow returns last Y, not stop, so we add 1 2227045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com localStopY = SkMin32(localStopY + 1, stopY); 2228045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 2229045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com int initialCount; 2230045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com row = fAAClip->findX(row, clip.fLeft, &initialCount); 2231045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com do { 2232045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com mergeProc(src, width, row, initialCount, rowMask.fImage); 2233045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com rowMask.fBounds.fTop = y; 2234045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com rowMask.fBounds.fBottom = y + 1; 2235045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fBlitter->blitMask(rowMask, rowMask.fBounds); 2236045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com src = (const void*)((const char*)src + srcRB); 2237045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } while (++y < localStopY); 2238045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } while (y < stopY); 2239045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com} 2240045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 224141e010cb901c0da9066c4df562030808c9ccd7f8reedconst SkPixmap* SkAAClipBlitter::justAnOpaqueColor(uint32_t* value) { 224296fcdcc219d2a0d3579719b84b28bede76efba64halcanary return nullptr; 2243322878907f6c5c5fb8abdbce7d348a3cd66ff2fareed@google.com} 2244