Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(160)

Unified Diff: src/core/SkPictureRecord.cpp

Issue 12545009: Adding option in SkPicture to record device-space bounds of draw commands. (Closed) Base URL: http://skia.googlecode.com/svn/trunk/
Patch Set: Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« src/core/SkPicture.cpp ('K') | « src/core/SkPictureRecord.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/core/SkPictureRecord.cpp
===================================================================
--- src/core/SkPictureRecord.cpp (revision 8010)
+++ src/core/SkPictureRecord.cpp (working copy)
@@ -30,6 +30,7 @@
INHERITED(device),
fBoundingHierarchy(NULL),
fStateTree(NULL),
+ fLastDrawRejected(false),
fFlattenableHeap(HEAP_BLOCK_SIZE),
fMatrices(&fFlattenableHeap),
fPaints(&fFlattenableHeap),
@@ -62,10 +63,30 @@
///////////////////////////////////////////////////////////////////////////////
+bool SkPictureRecord::canRecordBounds(DrawType op) {
+ SkASSERT(op != DRAW_POS_TEXT_TOP_BOTTOM); // Should never be used when encoding bounds
+ SkASSERT(op != DRAW_POS_TEXT_H_TOP_BOTTOM);
+ return
+ op == DRAW_BITMAP ||
+ op == DRAW_BITMAP_MATRIX ||
+ op == DRAW_BITMAP_NINE ||
+ op == DRAW_BITMAP_RECT_TO_RECT ||
+ op == DRAW_OVAL ||
+ op == DRAW_PATH ||
+ op == DRAW_POINTS ||
+ op == DRAW_POS_TEXT ||
+ op == DRAW_POS_TEXT_H ||
+ op == DRAW_RECT ||
+ op == DRAW_RRECT ||
+ op == DRAW_TEXT ||
+ op == DRAW_TEXT_ON_PATH ||
+ op == DRAW_VERTICES;
+}
+
// Return the offset of the paint inside a given op's byte stream. A zero
// return value means there is no paint (and you really shouldn't be calling
// this method)
-static inline uint32_t getPaintOffset(DrawType op, uint32_t opSize) {
+static inline uint32_t getPaintOffset(DrawType op, uint32_t opSize, bool recordBounds) {
// These offsets are where the paint would be if the op size doesn't overflow
static const uint8_t gPaintOffsets[LAST_DRAWTYPE_ENUM + 1] = {
0, // UNUSED - no paint
@@ -116,6 +137,9 @@
// after the op code
overflow = sizeof(uint32_t);
}
+ if (recordBounds && SkPictureRecord::canRecordBounds(op)) {
+ overflow += sizeof(SkIRect);
+ }
if (SAVE_LAYER == op) {
static const uint32_t kSaveLayerNoBoundsPaintOffset = 2 * kUInt32Size;
@@ -146,6 +170,7 @@
// op + flags
uint32_t size = 2 * kUInt32Size;
uint32_t initialOffset = this->addDraw(SAVE, &size);
+ SkASSERT(kInvalidOffset != initialOffset);
addInt(flags);
validate(initialOffset, size);
@@ -169,8 +194,9 @@
SkASSERT(kSaveLayerNoBoundsSize == size || kSaveLayerWithBoundsSize == size);
uint32_t initialOffset = this->addDraw(SAVE_LAYER, &size);
+ SkASSERT(kInvalidOffset != initialOffset);
addRectPtr(bounds);
- SkASSERT(initialOffset+getPaintOffset(SAVE_LAYER, size) == fWriter.size());
+ SkASSERT(initialOffset + getPaintOffset(SAVE_LAYER, size, false) == fWriter.size());
addPaintPtr(paint);
addInt(flags);
@@ -235,7 +261,7 @@
* where the saveLayer's color can be moved into the drawBitmap*'s paint
*/
static bool remove_save_layer1(SkWriter32* writer, int32_t offset,
- SkPaintDictionary* paintDict) {
+ SkPaintDictionary* paintDict, bool recordBounds) {
#ifdef SK_IGNORE_PICTURE_RECORD_SAVE_LAYER_OPT
return false;
@@ -283,8 +309,8 @@
return false; // something else between the dbm* and the restore
}
- uint32_t dbmPaintOffset = getPaintOffset(op, dbmSize);
- uint32_t slPaintOffset = getPaintOffset(SAVE_LAYER, saveLayerSize);
+ uint32_t dbmPaintOffset = getPaintOffset(op, dbmSize, recordBounds);
+ uint32_t slPaintOffset = getPaintOffset(SAVE_LAYER, saveLayerSize, false);
// we have a match, now we need to get the paints involved
int dbmPaintId = *((int32_t*)writer->peek32(dbmOffset+dbmPaintOffset));
@@ -418,7 +444,8 @@
uint32_t initialOffset, size;
if (!collapseSaveClipRestore(&fWriter, fRestoreOffsetStack.top()) &&
- !remove_save_layer1(&fWriter, fRestoreOffsetStack.top(), &fPaints)) {
+ !remove_save_layer1(&fWriter, fRestoreOffsetStack.top(), &fPaints,
robertphillips 2013/03/06 23:02:02 SkToBool?
+ 0 != (fRecordFlags & SkPicture::kRecordBounds_RecordingFlag))) {
fillRestoreOffsetPlaceholdersForCurrentStackLevel((uint32_t)fWriter.size());
// op
size = 1 * kUInt32Size;
@@ -434,6 +461,55 @@
return this->INHERITED::restore();
}
+uint32_t SkPictureRecord::addDrawWithBounds(DrawType drawType, uint32_t* size,
+ const SkPaint* paint, const SkRect* localBounds) {
+ SkASSERT(canRecordBounds(drawType));
+
+ SkIRect clippedDevBounds;
+ if (recordBounds()) {
+ SkIRect devClipBounds;
+ if (!this->getClipDeviceBounds(&devClipBounds)) {
robertphillips 2013/03/06 23:02:02 Comment here about this optimization and why it is
+ fLastDrawRejected = true;
+ return 0;
+ }
+ if (NULL == localBounds || (NULL != paint && !paint->canComputeFastBounds())) {
+ clippedDevBounds = devClipBounds;
+ } else {
+ SkRect paintBounds;
+ SkRect rectifiedBounds = *localBounds;
+ rectifiedBounds.sort();
+ if (NULL != paint) {
+ if (drawType == DRAW_POINTS) {
+ paintBounds = paint->computeFastStrokeBounds(rectifiedBounds, &paintBounds);
+ } else {
+ paintBounds = paint->computeFastBounds(rectifiedBounds, &paintBounds);
+ }
+ } else {
+ paintBounds = *localBounds;
+ }
+ if (paintBounds.isEmpty()) {
+ fLastDrawRejected = true;
+ return 0;
+ }
+ SkRect devBounds;
+ this->getTotalMatrix().mapRect(&devBounds, paintBounds);
+ devBounds.roundOut(&clippedDevBounds);
+ if (!clippedDevBounds.intersect(devClipBounds)) {
+ fLastDrawRejected = true;
+ return 0;
+ }
+ }
+ *size += sizeof(SkIRect);
+ }
+
+ uint32_t offset = addDraw(drawType, size);
+
+ if (recordBounds()) {
+ fWriter.write(&clippedDevBounds, sizeof(clippedDevBounds));
+ }
+ return offset;
+}
+
bool SkPictureRecord::translate(SkScalar dx, SkScalar dy) {
// op + dx + dy
uint32_t size = 1 * kUInt32Size + 2 * sizeof(SkScalar);
@@ -660,7 +736,7 @@
// op + paint index
uint32_t size = 2 * kUInt32Size;
uint32_t initialOffset = this->addDraw(DRAW_PAINT, &size);
- SkASSERT(initialOffset+getPaintOffset(DRAW_PAINT, size) == fWriter.size());
+ SkASSERT(initialOffset + getPaintOffset(DRAW_PAINT, size, false) == fWriter.size());
addPaint(paint);
validate(initialOffset, size);
}
@@ -669,8 +745,18 @@
const SkPaint& paint) {
// op + paint index + mode + count + point data
uint32_t size = 4 * kUInt32Size + count * sizeof(SkPoint);
- uint32_t initialOffset = this->addDraw(DRAW_POINTS, &size);
- SkASSERT(initialOffset+getPaintOffset(DRAW_POINTS, size) == fWriter.size());
+ uint32_t initialOffset;
+ if (recordBounds()) {
+ SkRect bbox;
+ bbox.set(pts, count);
+ initialOffset = this->addDrawWithBounds(DRAW_POINTS, &size, &paint, &bbox);
robertphillips 2013/03/06 23:02:02 Could fLastDrawRejected be passed in as a paramete
Justin Novosad 2013/03/07 14:41:42 It could, but I need to have as a member anyways b
+ if (fLastDrawRejected) {
+ return;
+ }
+ } else {
+ initialOffset = this->addDraw(DRAW_POINTS, &size);
+ }
robertphillips 2013/03/06 23:02:02 this->recordBounds()? Also in following changes to
+ SkASSERT(initialOffset + getPaintOffset(DRAW_POINTS, size, recordBounds()) == fWriter.size());
addPaint(paint);
addInt(mode);
addInt(count);
@@ -681,8 +767,16 @@
void SkPictureRecord::drawOval(const SkRect& oval, const SkPaint& paint) {
// op + paint index + rect
uint32_t size = 2 * kUInt32Size + sizeof(oval);
- uint32_t initialOffset = this->addDraw(DRAW_OVAL, &size);
- SkASSERT(initialOffset+getPaintOffset(DRAW_OVAL, size) == fWriter.size());
+ uint32_t initialOffset;
+ if (recordBounds()) {
+ initialOffset = this->addDrawWithBounds(DRAW_OVAL, &size, &paint, &oval);
+ if (fLastDrawRejected) {
+ return;
+ }
+ } else {
+ initialOffset = this->addDraw(DRAW_OVAL, &size);
+ }
+ SkASSERT(initialOffset + getPaintOffset(DRAW_OVAL, size, recordBounds()) == fWriter.size());
addPaint(paint);
addRect(oval);
validate(initialOffset, size);
@@ -691,45 +785,60 @@
void SkPictureRecord::drawRect(const SkRect& rect, const SkPaint& paint) {
// op + paint index + rect
uint32_t size = 2 * kUInt32Size + sizeof(rect);
- uint32_t initialOffset = this->addDraw(DRAW_RECT, &size);
- SkASSERT(initialOffset+getPaintOffset(DRAW_RECT, size) == fWriter.size());
+ uint32_t initialOffset;
+ if (recordBounds()) {
+ initialOffset = this->addDrawWithBounds(DRAW_RECT, &size, &paint, &rect);
+ if (fLastDrawRejected) {
+ return;
+ }
+ } else {
+ initialOffset = this->addDraw(DRAW_RECT, &size);
+ }
+ SkASSERT(initialOffset + getPaintOffset(DRAW_RECT, size, recordBounds()) == fWriter.size());
addPaint(paint);
addRect(rect);
validate(initialOffset, size);
}
void SkPictureRecord::drawRRect(const SkRRect& rrect, const SkPaint& paint) {
- uint32_t initialOffset, size;
if (rrect.isRect()) {
- // op + paint index + rect
- size = 2 * kUInt32Size + sizeof(SkRect);
- initialOffset = this->addDraw(DRAW_RECT, &size);
- SkASSERT(initialOffset+getPaintOffset(DRAW_RECT, size) == fWriter.size());
- addPaint(paint);
- addRect(rrect.getBounds());
+ this->drawRect(rrect.getBounds(), paint);
} else if (rrect.isOval()) {
- // op + paint index + rect
- size = 2 * kUInt32Size + sizeof(SkRect);
- initialOffset = this->addDraw(DRAW_OVAL, &size);
- SkASSERT(initialOffset+getPaintOffset(DRAW_OVAL, size) == fWriter.size());
- addPaint(paint);
- addRect(rrect.getBounds());
+ this->drawOval(rrect.getBounds(), paint);
} else {
// op + paint index + rrect
+ uint32_t initialOffset, size;
size = 2 * kUInt32Size + SkRRect::kSizeInMemory;
- initialOffset = this->addDraw(DRAW_RRECT, &size);
- SkASSERT(initialOffset+getPaintOffset(DRAW_RRECT, size) == fWriter.size());
+ if (recordBounds()) {
robertphillips 2013/03/06 23:02:02 What do you think about modifying addDraw to alway
Justin Novosad 2013/03/07 14:41:42 Well, I also want to avoid computing the bounds th
+ initialOffset = this->addDrawWithBounds(DRAW_RRECT, &size, &paint, &rrect.getBounds());
+ if (fLastDrawRejected) {
+ return;
+ }
+ } else {
+ initialOffset = this->addDraw(DRAW_RRECT, &size);
+ }
+ SkASSERT(initialOffset + getPaintOffset(DRAW_RRECT, size, recordBounds()) \
+ == fWriter.size());
addPaint(paint);
addRRect(rrect);
+ validate(initialOffset, size);
}
- validate(initialOffset, size);
}
void SkPictureRecord::drawPath(const SkPath& path, const SkPaint& paint) {
// op + paint index + path index
uint32_t size = 3 * kUInt32Size;
- uint32_t initialOffset = this->addDraw(DRAW_PATH, &size);
- SkASSERT(initialOffset+getPaintOffset(DRAW_PATH, size) == fWriter.size());
+ const SkRect* bounds = path.isInverseFillType() ? NULL : &path.getBounds();
+ uint32_t initialOffset;
+ if (recordBounds()) {
+ initialOffset = this->addDrawWithBounds(DRAW_PATH, &size, &paint, bounds);
+ if (fLastDrawRejected) {
+ return;
+ }
+ } else {
+ initialOffset = this->addDraw(DRAW_PATH, &size);
+ }
+ SkASSERT(initialOffset + getPaintOffset(DRAW_PATH, size, recordBounds()) == fWriter.size());
addPaint(paint);
addPath(path);
validate(initialOffset, size);
@@ -739,8 +848,17 @@
const SkPaint* paint = NULL) {
// op + paint index + bitmap index + left + top
uint32_t size = 3 * kUInt32Size + 2 * sizeof(SkScalar);
- uint32_t initialOffset = this->addDraw(DRAW_BITMAP, &size);
- SkASSERT(initialOffset+getPaintOffset(DRAW_BITMAP, size) == fWriter.size());
+ SkRect bounds = SkRect::MakeXYWH(left, top, bitmap.width(), bitmap.height());
+ uint32_t initialOffset;
+ if (recordBounds()) {
+ initialOffset = this->addDrawWithBounds(DRAW_BITMAP, &size, paint, &bounds);
+ if (fLastDrawRejected) {
+ return;
+ }
+ } else {
+ initialOffset = this->addDraw(DRAW_BITMAP, &size);
+ }
+ SkASSERT(initialOffset + getPaintOffset(DRAW_BITMAP, size, recordBounds()) == fWriter.size());
addPaintPtr(paint);
addBitmap(bitmap);
addScalar(left);
@@ -757,8 +875,17 @@
}
size += sizeof(dst); // + rect
- uint32_t initialOffset = this->addDraw(DRAW_BITMAP_RECT_TO_RECT, &size);
- SkASSERT(initialOffset+getPaintOffset(DRAW_BITMAP_RECT_TO_RECT, size) == fWriter.size());
+ uint32_t initialOffset;
+ if (recordBounds()) {
+ initialOffset = this->addDrawWithBounds(DRAW_BITMAP_RECT_TO_RECT, &size, paint, &dst);
+ if (fLastDrawRejected) {
+ return;
+ }
+ } else {
+ initialOffset = this->addDraw(DRAW_BITMAP_RECT_TO_RECT, &size);
+ }
+ SkASSERT(initialOffset + getPaintOffset(DRAW_BITMAP_RECT_TO_RECT, size, recordBounds()) \
+ == fWriter.size());
addPaintPtr(paint);
addBitmap(bitmap);
addRectPtr(src); // may be null
@@ -770,8 +897,19 @@
const SkPaint* paint) {
// id + paint index + bitmap index + matrix index
uint32_t size = 4 * kUInt32Size;
- uint32_t initialOffset = this->addDraw(DRAW_BITMAP_MATRIX, &size);
- SkASSERT(initialOffset+getPaintOffset(DRAW_BITMAP_MATRIX, size) == fWriter.size());
+ uint32_t initialOffset;
+ if (recordBounds()) {
+ SkRect bounds = SkRect::MakeWH(bitmap.width(), bitmap.height());
+ matrix.mapRect(&bounds);
+ initialOffset = this->addDrawWithBounds(DRAW_BITMAP_MATRIX, &size, paint, &bounds);
+ if (fLastDrawRejected) {
+ return;
+ }
+ } else {
+ initialOffset = this->addDraw(DRAW_BITMAP_MATRIX, &size);
+ }
+ SkASSERT(initialOffset + getPaintOffset(DRAW_BITMAP_MATRIX, size, recordBounds()) \
+ == fWriter.size());
addPaintPtr(paint);
addBitmap(bitmap);
addMatrix(matrix);
@@ -782,8 +920,17 @@
const SkRect& dst, const SkPaint* paint) {
// op + paint index + bitmap id + center + dst rect
uint32_t size = 3 * kUInt32Size + sizeof(center) + sizeof(dst);
- uint32_t initialOffset = this->addDraw(DRAW_BITMAP_NINE, &size);
- SkASSERT(initialOffset+getPaintOffset(DRAW_BITMAP_NINE, size) == fWriter.size());
+ uint32_t initialOffset;
+ if (recordBounds()) {
+ initialOffset = this->addDrawWithBounds(DRAW_BITMAP_NINE, &size, paint, &dst);
+ if (fLastDrawRejected) {
+ return;
+ }
+ } else {
+ initialOffset = this->addDraw(DRAW_BITMAP_NINE, &size);
+ }
+ SkASSERT(initialOffset + getPaintOffset(DRAW_BITMAP_NINE, size, recordBounds()) == \
+ fWriter.size());
addPaintPtr(paint);
addBitmap(bitmap);
addIRect(center);
@@ -792,11 +939,13 @@
}
void SkPictureRecord::drawSprite(const SkBitmap& bitmap, int left, int top,
- const SkPaint* paint = NULL) {
+ const SkPaint* paint) {
// op + paint index + bitmap index + left + top
uint32_t size = 5 * kUInt32Size;
- uint32_t initialOffset = this->addDraw(DRAW_SPRITE, &size);
- SkASSERT(initialOffset+getPaintOffset(DRAW_SPRITE, size) == fWriter.size());
+ uint32_t initialOffset;
+ // Note: Bounds encoding not supported.
+ initialOffset = this->addDraw(DRAW_SPRITE, &size);
+ SkASSERT(initialOffset + getPaintOffset(DRAW_SPRITE, size, false) == fWriter.size());
addPaintPtr(paint);
addBitmap(bitmap);
addInt(left);
@@ -831,7 +980,8 @@
void SkPictureRecord::drawText(const void* text, size_t byteLength, SkScalar x,
SkScalar y, const SkPaint& paint) {
robertphillips 2013/03/06 23:02:02 // We disallow DRAW_TEXT_TOP_BOTTOM when saving bo
- bool fast = !paint.isVerticalText() && paint.canComputeFastBounds();
+ bool fast = !paint.isVerticalText() && paint.canComputeFastBounds() &&
+ (fRecordFlags & SkPicture::kRecordBounds_RecordingFlag) == 0;
// op + paint index + length + 'length' worth of chars + x + y
uint32_t size = 3 * kUInt32Size + SkAlign4(byteLength) + 2 * sizeof(SkScalar);
@@ -840,8 +990,57 @@
}
DrawType op = fast ? DRAW_TEXT_TOP_BOTTOM : DRAW_TEXT;
- uint32_t initialOffset = this->addDraw(op, &size);
- SkASSERT(initialOffset+getPaintOffset(op, size) == fWriter.size());
+ uint32_t initialOffset;
+ if (recordBounds()) {
+ SkRect bbox;
+ paint.measureText(text, byteLength, &bbox);
+ SkPaint::FontMetrics metrics;
+ paint.getFontMetrics(&metrics);
+
+ // Vertical and aligned text need to be offset
+ if (paint.isVerticalText()) {
+ SkScalar h = bbox.fBottom - bbox.fTop;
+ if (paint.getTextAlign() == SkPaint::kCenter_Align) {
+ bbox.fTop -= h / 2;
+ bbox.fBottom -= h / 2;
+ }
+ // Pad top and bottom with max extents from FontMetrics
+ bbox.fBottom += metrics.fBottom;
+ bbox.fTop += metrics.fTop;
+ } else {
+ SkScalar w = bbox.fRight - bbox.fLeft;
+ if (paint.getTextAlign() == SkPaint::kCenter_Align) {
+ bbox.fLeft -= w / 2;
+ bbox.fRight -= w / 2;
+ } else if (paint.getTextAlign() == SkPaint::kRight_Align) {
+ bbox.fLeft -= w;
+ bbox.fRight -= w;
+ }
+ // Set vertical bounds to max extents from font metrics
+ bbox.fTop = metrics.fTop;
+ bbox.fBottom = metrics.fBottom;
+ }
+
+ // Pad horizontal bounds on each side by half of max vertical extents (this is sort of
+ // arbitrary, but seems to produce reasonable results, if there were a way of getting max
+ // glyph X-extents to pad by, that may be better here, but FontMetrics fXMin and fXMax seem
+ // incorrect on most platforms (too small in Linux, never even set in Windows).
+ SkScalar pad = (metrics.fBottom - metrics.fTop) / 2;
+ bbox.fLeft -= pad;
+ bbox.fRight += pad;
+
+ bbox.fLeft += x;
+ bbox.fRight += x;
+ bbox.fTop += y;
+ bbox.fBottom += y;
+ initialOffset = this->addDrawWithBounds(op, &size, &paint, &bbox);
+ if (fLastDrawRejected) {
+ return;
+ }
+ } else {
+ initialOffset = this->addDraw(op, &size);
+ }
+ SkASSERT(initialOffset + getPaintOffset(op, size, recordBounds()) == fWriter.size());
const SkFlatData* flatPaintData = addPaint(paint);
SkASSERT(flatPaintData);
addText(text, byteLength);
@@ -877,7 +1076,8 @@
}
}
- bool fastBounds = !paint.isVerticalText() && paint.canComputeFastBounds();
+ bool fastBounds = !paint.isVerticalText() && paint.canComputeFastBounds() &&
+ (fRecordFlags & SkPicture::kRecordBounds_RecordingFlag) == 0;
bool fast = canUseDrawH && fastBounds;
// op + paint index + length + 'length' worth of data + num points
@@ -906,8 +1106,27 @@
} else {
op = DRAW_POS_TEXT;
}
- uint32_t initialOffset = this->addDraw(op, &size);
- SkASSERT(initialOffset+getPaintOffset(op, size) == fWriter.size());
+ uint32_t initialOffset;
+ if (recordBounds()) {
+ SkRect bbox;
+ bbox.set(pos, paint.countText(text, byteLength));
+ SkPaint::FontMetrics metrics;
+ paint.getFontMetrics(&metrics);
+ bbox.fTop += metrics.fTop;
+ bbox.fBottom += metrics.fBottom;
+
+ // pad on left and right by half of max vertical glyph extents
+ SkScalar pad = (metrics.fTop - metrics.fBottom) / 2;
+ bbox.fLeft += pad;
+ bbox.fRight -= pad;
+ initialOffset = this->addDrawWithBounds(op, &size, &paint, &bbox);
+ if (fLastDrawRejected) {
+ return;
+ }
+ } else {
+ initialOffset = this->addDraw(op, &size);
+ }
+ SkASSERT(initialOffset + getPaintOffset(op, size, recordBounds()) == fWriter.size());
const SkFlatData* flatPaintData = addPaint(paint);
SkASSERT(flatPaintData);
addText(text, byteLength);
@@ -944,7 +1163,8 @@
if (0 == points)
return;
- bool fast = !paint.isVerticalText() && paint.canComputeFastBounds();
+ bool fast = !paint.isVerticalText() && paint.canComputeFastBounds() &&
+ (fRecordFlags & SkPicture::kRecordBounds_RecordingFlag) == 0;
// op + paint index + length + 'length' worth of data + num points
uint32_t size = 3 * kUInt32Size + SkAlign4(byteLength) + 1 * kUInt32Size;
@@ -954,8 +1174,41 @@
// + y + the actual points
size += 1 * kUInt32Size + points * sizeof(SkScalar);
- uint32_t initialOffset = this->addDraw(fast ? DRAW_POS_TEXT_H_TOP_BOTTOM : DRAW_POS_TEXT_H,
- &size);
+ uint32_t initialOffset;
+ if (recordBounds()) {
+ size_t numChars = paint.countText(text, byteLength);
+ SkRect bbox;
+ bbox.fLeft = xpos[0];
+ bbox.fRight = xpos[numChars - 1];
+ // if we had a guarantee that these will be monotonically increasing, this could be sped up
+ for (size_t i = 1; i < numChars; ++i) {
+ if (xpos[i] < bbox.fLeft) {
+ bbox.fLeft = xpos[i];
+ }
+ if (xpos[i] > bbox.fRight) {
+ bbox.fRight = xpos[i];
+ }
+ }
+ SkPaint::FontMetrics metrics;
+ paint.getFontMetrics(&metrics);
+
+ // pad horizontally by max glyph height
+ SkScalar pad = (metrics.fTop - metrics.fBottom);
+ bbox.fLeft += pad;
+ bbox.fRight -= pad;
+
+ bbox.fTop = metrics.fTop + constY;
+ bbox.fBottom = metrics.fBottom + constY;
+ initialOffset = this->addDrawWithBounds(DRAW_POS_TEXT_H, &size, &paint, &bbox);
+ if (fLastDrawRejected) {
+ return;
+ }
+ } else {
+ initialOffset = this->addDraw(fast ? DRAW_POS_TEXT_H_TOP_BOTTOM : DRAW_POS_TEXT_H,
+ &size);
+ }
+ SkASSERT(initialOffset + getPaintOffset(DRAW_TEXT_ON_PATH, size, recordBounds()) \
+ == fWriter.size());
const SkFlatData* flatPaintData = addPaint(paint);
SkASSERT(flatPaintData);
addText(text, byteLength);
@@ -981,8 +1234,26 @@
const SkPaint& paint) {
// op + paint index + length + 'length' worth of data + path index + matrix index
uint32_t size = 3 * kUInt32Size + SkAlign4(byteLength) + 2 * kUInt32Size;
- uint32_t initialOffset = this->addDraw(DRAW_TEXT_ON_PATH, &size);
- SkASSERT(initialOffset+getPaintOffset(DRAW_TEXT_ON_PATH, size) == fWriter.size());
+ uint32_t initialOffset;
+ if (recordBounds()) {
+ SkRect bbox = path.getBounds();
+ SkPaint::FontMetrics metrics;
+ paint.getFontMetrics(&metrics);
+ // pad out all sides by the max glyph height above baseline
+ SkScalar pad = metrics.fTop;
+ bbox.fLeft += pad;
+ bbox.fRight -= pad;
+ bbox.fTop += pad;
+ bbox.fBottom -= pad;
+ initialOffset = this->addDrawWithBounds(DRAW_TEXT_ON_PATH, &size, &paint, &bbox);
+ if (fLastDrawRejected) {
+ return;
+ }
+ } else {
+ initialOffset = this->addDraw(DRAW_TEXT_ON_PATH, &size);
+ }
+ SkASSERT(initialOffset + getPaintOffset(DRAW_TEXT_ON_PATH, size, recordBounds()) \
+ == fWriter.size());
addPaint(paint);
addText(text, byteLength);
addPath(path);
@@ -1027,8 +1298,19 @@
size += 1 * kUInt32Size + SkAlign4(indexCount * sizeof(uint16_t));
}
- uint32_t initialOffset = this->addDraw(DRAW_VERTICES, &size);
- SkASSERT(initialOffset+getPaintOffset(DRAW_VERTICES, size) == fWriter.size());
+ uint32_t initialOffset;
+ if (recordBounds()) {
+ SkRect bbox;
+ bbox.set(vertices, vertexCount);
+ initialOffset = this->addDrawWithBounds(DRAW_VERTICES, &size, &paint, &bbox);
+ if (fLastDrawRejected) {
+ return;
+ }
+ } else {
+ initialOffset = this->addDraw(DRAW_VERTICES, &size);
+ }
+ SkASSERT(initialOffset + getPaintOffset(DRAW_VERTICES, size, recordBounds()) \
+ == fWriter.size());
addPaint(paint);
addInt(flags);
addInt(vmode);
« src/core/SkPicture.cpp ('K') | « src/core/SkPictureRecord.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698