aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar reed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-12-07 17:14:40 +0000
committerGravatar reed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-12-07 17:14:40 +0000
commit4595426b553c0c721f41aa14d598caa5d9940207 (patch)
tree0f5d52324d947a15f08fec5ff58d2775f7c28813 /src
parent8f30fb7dfafe9d1954d73458a88d50060085abb2 (diff)
cache fontmetrics in picture-record
Review URL: https://codereview.appspot.com/6908049 git-svn-id: http://skia.googlecode.com/svn/trunk@6706 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src')
-rw-r--r--src/core/SkPictureFlat.cpp1
-rw-r--r--src/core/SkPictureFlat.h29
-rw-r--r--src/core/SkPictureRecord.cpp49
-rw-r--r--src/core/SkPictureRecord.h7
4 files changed, 63 insertions, 23 deletions
diff --git a/src/core/SkPictureFlat.cpp b/src/core/SkPictureFlat.cpp
index 8f6e0895d7..e104a402bc 100644
--- a/src/core/SkPictureFlat.cpp
+++ b/src/core/SkPictureFlat.cpp
@@ -120,6 +120,7 @@ SkFlatData* SkFlatData::Create(SkFlatController* controller, const void* obj,
SkFlatData* result = (SkFlatData*) controller->allocThrow(allocSize);
result->fIndex = index;
+ result->fTopBot[0] = result->fTopBot[1] = 0; // initial to sentinel values
result->fFlatSize = size;
// put the serialized contents into the data section of the new allocation
diff --git a/src/core/SkPictureFlat.h b/src/core/SkPictureFlat.h
index a00596fed0..429236150b 100644
--- a/src/core/SkPictureFlat.h
+++ b/src/core/SkPictureFlat.h
@@ -329,9 +329,34 @@ public:
return !memcmp(a.dataToCompare(), b.dataToCompare(), N);
}
+ // returns true if fTopBot[] has been recorded
+ bool isTopBotValid() const {
+ return fTopBot[0] < fTopBot[1];
+ }
+
+ // 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() {
+ SkASSERT(!this->isTopBotValid());
+ return fTopBot;
+ }
+
+ // return the topbot[] after it has been recorded
+ const SkScalar* topBot() const {
+ SkASSERT(this->isTopBotValid());
+ return fTopBot;
+ }
+
private:
+ // This is *not* part of the key for search/sort
int fIndex;
+ // Cache of paint's FontMetrics fTop,fBottom
+ // initialied to [0,0] as a sentinel that they have not been recorded yet
+ //
+ // This is *not* part of the key for search/sort
+ SkScalar fTopBot[2];
+
// From here down is the data we look at in the search/sort. We always begin
// with the checksum and then length.
uint32_t fChecksum;
@@ -621,6 +646,10 @@ 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 270eee5bd4..b62b5b94da 100644
--- a/src/core/SkPictureRecord.cpp
+++ b/src/core/SkPictureRecord.cpp
@@ -473,19 +473,30 @@ void SkPictureRecord::drawSprite(const SkBitmap& bitmap, int left, int top,
validate();
}
-void SkPictureRecord::addFontMetricsTopBottom(const SkPaint& paint,
- SkScalar minY, SkScalar maxY) {
+// Return fontmetrics.fTop,fBottom in topbot[0,1], after they have been
+// tweaked by paint.computeFastBounds().
+//
+static void computeFontMetricsTopBottom(const SkPaint& paint, SkScalar topbot[2]) {
SkPaint::FontMetrics metrics;
paint.getFontMetrics(&metrics);
SkRect bounds;
// construct a rect so we can see any adjustments from the paint.
// we use 0,1 for left,right, just so the rect isn't empty
- bounds.set(0, metrics.fTop + minY,
- SK_Scalar1, metrics.fBottom + maxY);
+ bounds.set(0, metrics.fTop, SK_Scalar1, metrics.fBottom);
(void)paint.computeFastBounds(bounds, &bounds);
- // now record the top and bottom
- addScalar(bounds.fTop);
- addScalar(bounds.fBottom);
+ topbot[0] = bounds.fTop;
+ topbot[1] = bounds.fBottom;
+}
+
+void SkPictureRecord::addFontMetricsTopBottom(const SkPaint& paint, int index,
+ SkScalar minY, SkScalar maxY) {
+ SkFlatData* flat = fPaints.writableFlatData(index);
+ if (!flat->isTopBotValid()) {
+ computeFontMetricsTopBottom(paint, flat->writableTopBot());
+ SkASSERT(flat->isTopBotValid());
+ }
+ addScalar(flat->topBot()[0] + minY);
+ addScalar(flat->topBot()[1] + maxY);
}
void SkPictureRecord::drawText(const void* text, size_t byteLength, SkScalar x,
@@ -493,12 +504,12 @@ 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);
- addPaint(paint);
+ int paintIndex = addPaint(paint);
addText(text, byteLength);
addScalar(x);
addScalar(y);
if (fast) {
- addFontMetricsTopBottom(paint, y, y);
+ addFontMetricsTopBottom(paint, paintIndex - 1, y, y);
}
validate();
}
@@ -539,7 +550,7 @@ void SkPictureRecord::drawPosText(const void* text, size_t byteLength,
} else {
addDraw(DRAW_POS_TEXT);
}
- addPaint(paint);
+ int paintIndex = addPaint(paint);
addText(text, byteLength);
addInt(points);
@@ -548,7 +559,7 @@ void SkPictureRecord::drawPosText(const void* text, size_t byteLength,
#endif
if (canUseDrawH) {
if (fast) {
- addFontMetricsTopBottom(paint, pos[0].fY, pos[0].fY);
+ addFontMetricsTopBottom(paint, paintIndex - 1, pos[0].fY, pos[0].fY);
}
addScalar(pos[0].fY);
SkScalar* xptr = (SkScalar*)fWriter.reserve(points * sizeof(SkScalar));
@@ -558,7 +569,7 @@ void SkPictureRecord::drawPosText(const void* text, size_t byteLength,
else {
fWriter.writeMul4(pos, points * sizeof(SkPoint));
if (fastBounds) {
- addFontMetricsTopBottom(paint, minY, maxY);
+ addFontMetricsTopBottom(paint, paintIndex - 1, minY, maxY);
}
}
#ifdef SK_DEBUG_SIZE
@@ -578,7 +589,7 @@ 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);
- addPaint(paint);
+ int paintIndex = this->addPaint(paint);
addText(text, byteLength);
addInt(points);
@@ -586,7 +597,7 @@ void SkPictureRecord::drawPosTextH(const void* text, size_t byteLength,
size_t start = fWriter.size();
#endif
if (fast) {
- addFontMetricsTopBottom(paint, constY, constY);
+ addFontMetricsTopBottom(paint, paintIndex - 1, constY, constY);
}
addScalar(constY);
fWriter.writeMul4(xpos, points * sizeof(SkScalar));
@@ -673,12 +684,10 @@ void SkPictureRecord::addMatrixPtr(const SkMatrix* matrix) {
this->addInt(matrix ? fMatrices.find(*matrix) : 0);
}
-void SkPictureRecord::addPaint(const SkPaint& paint) {
- addPaintPtr(&paint);
-}
-
-void SkPictureRecord::addPaintPtr(const SkPaint* paint) {
- this->addInt(paint ? fPaints.find(*paint) : 0);
+int SkPictureRecord::addPaintPtr(const SkPaint* paint) {
+ int index = paint ? fPaints.find(*paint) : 0;
+ this->addInt(index);
+ return index;
}
void SkPictureRecord::addPath(const SkPath& path) {
diff --git a/src/core/SkPictureRecord.h b/src/core/SkPictureRecord.h
index 77e011416f..77a6b04fc7 100644
--- a/src/core/SkPictureRecord.h
+++ b/src/core/SkPictureRecord.h
@@ -72,7 +72,8 @@ public:
virtual void drawData(const void*, size_t) SK_OVERRIDE;
virtual bool isDrawingToLayer() const SK_OVERRIDE;
- void addFontMetricsTopBottom(const SkPaint& paint, SkScalar minY, SkScalar maxY);
+ void addFontMetricsTopBottom(const SkPaint& paint, int paintIndex,
+ SkScalar minY, SkScalar maxY);
const SkTDArray<SkPicture* >& getPictureRefs() const {
return fPictureRefs;
@@ -118,8 +119,8 @@ private:
void addBitmap(const SkBitmap& bitmap);
void addMatrix(const SkMatrix& matrix);
void addMatrixPtr(const SkMatrix* matrix);
- void addPaint(const SkPaint& paint);
- void addPaintPtr(const SkPaint* paint);
+ int addPaint(const SkPaint& paint) { return this->addPaintPtr(&paint); }
+ int addPaintPtr(const SkPaint* paint);
void addPath(const SkPath& path);
void addPicture(SkPicture& picture);
void addPoint(const SkPoint& point);