aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar junov@chromium.org <junov@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>2013-01-22 17:50:47 +0000
committerGravatar junov@chromium.org <junov@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>2013-01-22 17:50:47 +0000
commitf3b1223e6d52b161dbc59a4119ba6a4161b10a54 (patch)
tree259268d9e718739de4aa3daa0ff12b10ef7b9524 /src
parentb83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6 (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.h54
-rw-r--r--src/core/SkPictureRecord.cpp28
-rw-r--r--src/core/SkPictureRecord.h6
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);