Index: src/core/SkScan_AntiPath.cpp |
diff --git a/src/core/SkScan_AntiPath.cpp b/src/core/SkScan_AntiPath.cpp |
index e5c67a958af2ef2069ff7ec1fff2a75e402a3e39..0943646ce846c0d1d3f91a12fc320039caa28223 100644 |
--- a/src/core/SkScan_AntiPath.cpp |
+++ b/src/core/SkScan_AntiPath.cpp |
@@ -108,7 +108,7 @@ public: |
virtual ~SuperBlitter() { |
this->flush(); |
- sk_free(fRuns.fRuns); |
+ sk_free(fRunsBuffer); |
} |
/// Once fRuns contains a complete supersampled row, flush() blits |
@@ -123,31 +123,56 @@ public: |
virtual void blitRect(int x, int y, int width, int height) SK_OVERRIDE; |
private: |
+ // The next three variables are used to track a circular buffer that |
+ // contains the values used in SkAlphaRuns. These variables should only |
+ // ever be updated in advanceRuns(), and fRuns should always point to |
+ // a valid SkAlphaRuns... |
+ int fRunsToBuffer; |
+ void* fRunsBuffer; |
+ int fCurrentRun; |
SkAlphaRuns fRuns; |
+ |
+ // extra one to store the zero at the end |
+ int getRunsSz() const { return (fWidth + 1 + (fWidth + 2)/2) * sizeof(int16_t); } |
+ |
+ // This function updates the fRuns variable to point to the next buffer space |
+ // with adequate storage for a SkAlphaRuns. It mostly just advances fCurrentRun |
+ // and resets fRuns to point to an empty scanline. |
+ void advanceRuns() { |
+ const size_t kRunsSz = this->getRunsSz(); |
+ fCurrentRun = (fCurrentRun + 1) % fRunsToBuffer; |
+ fRuns.fRuns = reinterpret_cast<int16_t*>( |
+ reinterpret_cast<uint8_t*>(fRunsBuffer) + fCurrentRun * kRunsSz); |
+ fRuns.fAlpha = reinterpret_cast<SkAlpha*>(fRuns.fRuns + fWidth + 1); |
+ fRuns.reset(fWidth); |
+ } |
+ |
int fOffsetX; |
}; |
SuperBlitter::SuperBlitter(SkBlitter* realBlitter, const SkIRect& ir, |
const SkRegion& clip) |
: BaseSuperBlitter(realBlitter, ir, clip) { |
- const int width = fWidth; |
+ fRunsToBuffer = realBlitter->requestRowsPreserved(); |
+ fRunsBuffer = sk_malloc_throw(fRunsToBuffer * this->getRunsSz()); |
+ fCurrentRun = -1; |
- // extra one to store the zero at the end |
- fRuns.fRuns = (int16_t*)sk_malloc_throw((width + 1 + (width + 2)/2) * sizeof(int16_t)); |
- fRuns.fAlpha = (uint8_t*)(fRuns.fRuns + width + 1); |
- fRuns.reset(width); |
+ this->advanceRuns(); |
fOffsetX = 0; |
} |
void SuperBlitter::flush() { |
if (fCurrIY >= fTop) { |
+ |
+ SkASSERT(fCurrentRun < fRunsToBuffer); |
if (!fRuns.empty()) { |
- // SkDEBUGCODE(fRuns.dump();) |
+ // SkDEBUGCODE(fRuns.dump();) |
fRealBlitter->blitAntiH(fLeft, fCurrIY, fRuns.fAlpha, fRuns.fRuns); |
- fRuns.reset(fWidth); |
+ this->advanceRuns(); |
fOffsetX = 0; |
} |
+ |
fCurrIY = fTop - 1; |
SkDEBUGCODE(fCurrX = -1;) |
} |