diff options
author | junov@chromium.org <junov@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2013-01-22 17:50:47 +0000 |
---|---|---|
committer | junov@chromium.org <junov@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2013-01-22 17:50:47 +0000 |
commit | f3b1223e6d52b161dbc59a4119ba6a4161b10a54 (patch) | |
tree | 259268d9e718739de4aa3daa0ff12b10ef7b9524 /src | |
parent | b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6 (diff) |
Fixing invalid text clipping on SkPicture playback
The bug was caused by an invalid assumption that a flattend object's
index is related to its array index in SkFlatDictionary::fData.
The data in SkFlatDictionary is sorted by flattened data content,
not by index number. Problem was solved by passing down the SkFlatData*
through addPaint, rather than the index value. The bug was causing
SkPictureRecord::addFontMetricsTopBottom to use cached font metrics
from the wrong SkPaint instance.
BUG=https://code.google.com/p/chromium/issues/detail?id=170964
Review URL: https://codereview.appspot.com/7178045
git-svn-id: http://skia.googlecode.com/svn/trunk@7312 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src')
-rw-r--r-- | src/core/SkPictureFlat.h | 54 | ||||
-rw-r--r-- | src/core/SkPictureRecord.cpp | 28 | ||||
-rw-r--r-- | src/core/SkPictureRecord.h | 6 |
3 files changed, 42 insertions, 46 deletions
diff --git a/src/core/SkPictureFlat.h b/src/core/SkPictureFlat.h index c01e9a3724..6354e9fc2a 100644 --- a/src/core/SkPictureFlat.h +++ b/src/core/SkPictureFlat.h @@ -339,7 +339,7 @@ public: // Returns fTopBot array, so it can be passed to a routine to compute them. // For efficiency, we assert that fTopBot have not been recorded yet. - SkScalar* writableTopBot() { + SkScalar* writableTopBot() const { SkASSERT(!this->isTopBotWritten()); return fTopBot; } @@ -355,10 +355,10 @@ private: int fIndex; // Cache of paint's FontMetrics fTop,fBottom - // initialied to [0,0] as a sentinel that they have not been recorded yet + // initialied to [NaN,NaN] as a sentinel that they have not been recorded yet // // This is *not* part of the key for search/sort - SkScalar fTopBot[2]; + mutable SkScalar fTopBot[2]; // marks fTopBot[] as unrecorded void setTopBotUnwritten() { @@ -494,29 +494,6 @@ public: return array; } -protected: - void (*fFlattenProc)(SkOrderedWriteBuffer&, const void*); - void (*fUnflattenProc)(SkOrderedReadBuffer&, void*); - -private: - void unflattenIntoArray(T* array) const { - const int count = fData.count(); - const SkFlatData** iter = fData.begin(); - for (int i = 0; i < count; ++i) { - const SkFlatData* element = iter[i]; - int index = element->index() - 1; - SkASSERT((unsigned)index < (unsigned)count); - element->unflatten(&array[index], fUnflattenProc, - fController->getBitmapHeap(), - fController->getTypefacePlayback()); - } - } - - - SkFlatController * const fController; - int fNextIndex; - SkTDArray<const SkFlatData*> fData; - const SkFlatData* findAndReturnFlat(const T& element) { SkFlatData* flat = SkFlatData::Create(fController, &element, fNextIndex, fFlattenProc); @@ -545,6 +522,27 @@ private: return flat; } +protected: + void (*fFlattenProc)(SkOrderedWriteBuffer&, const void*); + void (*fUnflattenProc)(SkOrderedReadBuffer&, void*); + +private: + void unflattenIntoArray(T* array) const { + const int count = fData.count(); + const SkFlatData** iter = fData.begin(); + for (int i = 0; i < count; ++i) { + const SkFlatData* element = iter[i]; + int index = element->index() - 1; + SkASSERT((unsigned)index < (unsigned)count); + element->unflatten(&array[index], fUnflattenProc, + fController->getBitmapHeap(), + fController->getTypefacePlayback()); + } + } + + SkFlatController * const fController; + int fNextIndex; + SkTDArray<const SkFlatData*> fData; enum { // Determined by trying diff values on picture-recording benchmarks @@ -654,10 +652,6 @@ class SkPaintDictionary : public SkFlatDictionary<SkPaint> { fFlattenProc = &SkFlattenObjectProc<SkPaint>; fUnflattenProc = &SkUnflattenObjectProc<SkPaint>; } - - SkFlatData* writableFlatData(int index) { - return const_cast<SkFlatData*>((*this)[index]); - } }; class SkRegionDictionary : public SkFlatDictionary<SkRegion> { diff --git a/src/core/SkPictureRecord.cpp b/src/core/SkPictureRecord.cpp index 3e481acf07..9b05250ba8 100644 --- a/src/core/SkPictureRecord.cpp +++ b/src/core/SkPictureRecord.cpp @@ -535,9 +535,8 @@ static void computeFontMetricsTopBottom(const SkPaint& paint, SkScalar topbot[2] topbot[1] = bounds.fBottom; } -void SkPictureRecord::addFontMetricsTopBottom(const SkPaint& paint, int index, +void SkPictureRecord::addFontMetricsTopBottom(const SkPaint& paint, const SkFlatData& flat, SkScalar minY, SkScalar maxY) { - SkFlatData* flat = fPaints.writableFlatData(index); if (!flat->isTopBotWritten()) { computeFontMetricsTopBottom(paint, flat->writableTopBot()); SkASSERT(flat->isTopBotWritten()); @@ -551,12 +550,13 @@ void SkPictureRecord::drawText(const void* text, size_t byteLength, SkScalar x, bool fast = !paint.isVerticalText() && paint.canComputeFastBounds(); addDraw(fast ? DRAW_TEXT_TOP_BOTTOM : DRAW_TEXT); - int paintIndex = addPaint(paint); + const SkFlatData* flatPaintData = addPaint(paint); + SkASSERT(flatPaintData); addText(text, byteLength); addScalar(x); addScalar(y); if (fast) { - addFontMetricsTopBottom(paint, paintIndex - 1, y, y); + addFontMetricsTopBottom(paint, *flatPaintData, y, y); } validate(); } @@ -597,7 +597,8 @@ void SkPictureRecord::drawPosText(const void* text, size_t byteLength, } else { addDraw(DRAW_POS_TEXT); } - int paintIndex = addPaint(paint); + const SkFlatData* flatPaintData = addPaint(paint); + SkASSERT(flatPaintData); addText(text, byteLength); addInt(points); @@ -606,7 +607,7 @@ void SkPictureRecord::drawPosText(const void* text, size_t byteLength, #endif if (canUseDrawH) { if (fast) { - addFontMetricsTopBottom(paint, paintIndex - 1, pos[0].fY, pos[0].fY); + addFontMetricsTopBottom(paint, *flatPaintData, pos[0].fY, pos[0].fY); } addScalar(pos[0].fY); SkScalar* xptr = (SkScalar*)fWriter.reserve(points * sizeof(SkScalar)); @@ -616,7 +617,7 @@ void SkPictureRecord::drawPosText(const void* text, size_t byteLength, else { fWriter.writeMul4(pos, points * sizeof(SkPoint)); if (fastBounds) { - addFontMetricsTopBottom(paint, paintIndex - 1, minY, maxY); + addFontMetricsTopBottom(paint, *flatPaintData, minY, maxY); } } #ifdef SK_DEBUG_SIZE @@ -636,7 +637,8 @@ void SkPictureRecord::drawPosTextH(const void* text, size_t byteLength, bool fast = !paint.isVerticalText() && paint.canComputeFastBounds(); addDraw(fast ? DRAW_POS_TEXT_H_TOP_BOTTOM : DRAW_POS_TEXT_H); - int paintIndex = this->addPaint(paint); + const SkFlatData* flatPaintData = addPaint(paint); + SkASSERT(flatPaintData); addText(text, byteLength); addInt(points); @@ -644,7 +646,7 @@ void SkPictureRecord::drawPosTextH(const void* text, size_t byteLength, size_t start = fWriter.size(); #endif if (fast) { - addFontMetricsTopBottom(paint, paintIndex - 1, constY, constY); + addFontMetricsTopBottom(paint, *flatPaintData, constY, constY); } addScalar(constY); fWriter.writeMul4(xpos, points * sizeof(SkScalar)); @@ -731,10 +733,11 @@ void SkPictureRecord::addMatrixPtr(const SkMatrix* matrix) { this->addInt(matrix ? fMatrices.find(*matrix) : 0); } -int SkPictureRecord::addPaintPtr(const SkPaint* paint) { - int index = paint ? fPaints.find(*paint) : 0; +const SkFlatData* SkPictureRecord::addPaintPtr(const SkPaint* paint) { + const SkFlatData* data = paint ? fPaints.findAndReturnFlat(*paint) : NULL; + int index = data ? data->index() : 0; this->addInt(index); - return index; + return data; } void SkPictureRecord::addPath(const SkPath& path) { @@ -950,4 +953,3 @@ void SkPictureRecord::validateRegions() const { } } #endif - diff --git a/src/core/SkPictureRecord.h b/src/core/SkPictureRecord.h index abaa22dd9d..782ee43d95 100644 --- a/src/core/SkPictureRecord.h +++ b/src/core/SkPictureRecord.h @@ -75,7 +75,7 @@ public: virtual void drawData(const void*, size_t) SK_OVERRIDE; virtual bool isDrawingToLayer() const SK_OVERRIDE; - void addFontMetricsTopBottom(const SkPaint& paint, int paintIndex, + void addFontMetricsTopBottom(const SkPaint& paint, const SkFlatData*, SkScalar minY, SkScalar maxY); const SkTDArray<SkPicture* >& getPictureRefs() const { @@ -122,8 +122,8 @@ private: void addBitmap(const SkBitmap& bitmap); void addMatrix(const SkMatrix& matrix); void addMatrixPtr(const SkMatrix* matrix); - int addPaint(const SkPaint& paint) { return this->addPaintPtr(&paint); } - int addPaintPtr(const SkPaint* paint); + const SkFlatData* addPaint(const SkPaint& paint) { return this->addPaintPtr(&paint); } + const SkFlatData* addPaintPtr(const SkPaint* paint); void addPath(const SkPath& path); void addPicture(SkPicture& picture); void addPoint(const SkPoint& point); |