Try out scalar picture sizes
This paves the way for removing the 'fTile' parameter from SkPictureShader (although that should be a different CL). If we like this we could also move to providing an entire cull SkRect.
R=reed@google.com, mtklein@google.com, fmalita@google.com, fmalita@chromium.org
Author: robertphillips@google.com
Review URL: https://codereview.chromium.org/513983002
diff --git a/src/core/SkBBoxRecord.cpp b/src/core/SkBBoxRecord.cpp
index 5837a88..5fe42f9 100644
--- a/src/core/SkBBoxRecord.cpp
+++ b/src/core/SkBBoxRecord.cpp
@@ -313,8 +313,7 @@
void SkBBoxRecord::onDrawPicture(const SkPicture* picture, const SkMatrix* matrix,
const SkPaint* paint) {
- SkRect bounds = SkRect::MakeWH(SkIntToScalar(picture->width()),
- SkIntToScalar(picture->height()));
+ SkRect bounds = picture->cullRect();
// todo: wonder if we should allow passing an optional matrix to transformBounds so we don't
// end up transforming the rect twice.
if (matrix) {
diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp
index 16459b0..2b08a94 100644
--- a/src/core/SkCanvas.cpp
+++ b/src/core/SkCanvas.cpp
@@ -2445,7 +2445,7 @@
}
}
- SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->width(), picture->height());
+ SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->cullRect());
picture->draw(this);
}
@@ -2549,16 +2549,16 @@
///////////////////////////////////////////////////////////////////////////////
SkAutoCanvasMatrixPaint::SkAutoCanvasMatrixPaint(SkCanvas* canvas, const SkMatrix* matrix,
- const SkPaint* paint, int width, int height)
+ const SkPaint* paint, const SkRect& bounds)
: fCanvas(canvas)
, fSaveCount(canvas->getSaveCount())
{
if (NULL != paint) {
- SkRect bounds = SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height));
+ SkRect newBounds = bounds;
if (matrix) {
- matrix->mapRect(&bounds);
+ matrix->mapRect(&newBounds);
}
- canvas->saveLayer(&bounds, paint);
+ canvas->saveLayer(&newBounds, paint);
} else if (NULL != matrix) {
canvas->save();
}
diff --git a/src/core/SkCanvasPriv.h b/src/core/SkCanvasPriv.h
index 9f66baa..dfae154 100644
--- a/src/core/SkCanvasPriv.h
+++ b/src/core/SkCanvasPriv.h
@@ -12,7 +12,7 @@
class SkAutoCanvasMatrixPaint : SkNoncopyable {
public:
- SkAutoCanvasMatrixPaint(SkCanvas*, const SkMatrix*, const SkPaint*, int width, int height);
+ SkAutoCanvasMatrixPaint(SkCanvas*, const SkMatrix*, const SkPaint*, const SkRect& bounds);
~SkAutoCanvasMatrixPaint();
private:
diff --git a/src/core/SkPicture.cpp b/src/core/SkPicture.cpp
index e958f96..92551d3 100644
--- a/src/core/SkPicture.cpp
+++ b/src/core/SkPicture.cpp
@@ -262,11 +262,11 @@
#endif
// fRecord OK
-SkPicture::SkPicture(int width, int height,
+SkPicture::SkPicture(SkScalar width, SkScalar height,
const SkPictureRecord& record,
bool deepCopyOps)
- : fWidth(width)
- , fHeight(height)
+ : fCullWidth(width)
+ , fCullHeight(height)
, fAnalysis() {
this->needsNewGenID();
@@ -277,10 +277,11 @@
// Create an SkPictureData-backed SkPicture from an SkRecord.
// This for compatibility with serialization code only. This is not cheap.
-static SkPicture* backport(const SkRecord& src, int width, int height) {
+static SkPicture* backport(const SkRecord& src, const SkRect& cullRect) {
SkPictureRecorder recorder;
SkRecordDraw(src,
- recorder.DEPRECATED_beginRecording(width, height), NULL/*bbh*/, NULL/*callback*/);
+ recorder.DEPRECATED_beginRecording(cullRect.width(), cullRect.height()),
+ NULL/*bbh*/, NULL/*callback*/);
return recorder.endRecording();
}
@@ -351,7 +352,7 @@
// If the query contains the whole picture, don't bother with the BBH.
SkRect clipBounds = { 0, 0, 0, 0 };
(void)canvas->getClipBounds(&clipBounds);
- const bool useBBH = !clipBounds.contains(SkRect::MakeWH(this->width(), this->height()));
+ const bool useBBH = !clipBounds.contains(this->cullRect());
if (NULL != fData.get()) {
SkPicturePlayback playback(this);
@@ -392,7 +393,32 @@
// Check magic bytes.
SkPictInfo info;
SkASSERT(sizeof(kMagic) == sizeof(info.fMagic));
- if (!stream->read(&info, sizeof(info)) || !IsValidPictInfo(info)) {
+
+ if (!stream->read(&info.fMagic, sizeof(kMagic))) {
+ return false;
+ }
+
+ info.fVersion = stream->readU32();
+
+#ifndef V35_COMPATIBILITY_CODE
+ if (info.fVersion < 35) {
+ info.fCullRect.fLeft = 0;
+ info.fCullRect.fTop = 0;
+ info.fCullRect.fRight = SkIntToScalar(stream->readU32());
+ info.fCullRect.fBottom = SkIntToScalar(stream->readU32());
+ } else {
+#endif
+ info.fCullRect.fLeft = stream->readScalar();
+ info.fCullRect.fTop = stream->readScalar();
+ info.fCullRect.fRight = stream->readScalar();
+ info.fCullRect.fBottom = stream->readScalar();
+#ifndef V35_COMPATIBILITY_CODE
+ }
+#endif
+
+ info.fFlags = stream->readU32();
+
+ if (!IsValidPictInfo(info)) {
return false;
}
@@ -403,11 +429,33 @@
}
// fRecord OK
-bool SkPicture::InternalOnly_BufferIsSKP(SkReadBuffer& buffer, SkPictInfo* pInfo) {
+bool SkPicture::InternalOnly_BufferIsSKP(SkReadBuffer* buffer, SkPictInfo* pInfo) {
// Check magic bytes.
SkPictInfo info;
SkASSERT(sizeof(kMagic) == sizeof(info.fMagic));
- if (!buffer.readByteArray(&info, sizeof(info)) || !IsValidPictInfo(info)) {
+
+ if (!buffer->readByteArray(&info.fMagic, sizeof(kMagic))) {
+ return false;
+ }
+
+ info.fVersion = buffer->readUInt();
+
+#ifndef V35_COMPATIBILITY_CODE
+ if (info.fVersion < 35) {
+ info.fCullRect.fLeft = 0;
+ info.fCullRect.fTop = 0;
+ info.fCullRect.fRight = SkIntToScalar(buffer->readUInt());
+ info.fCullRect.fBottom = SkIntToScalar(buffer->readUInt());
+ } else {
+#endif
+ buffer->readRect(&info.fCullRect);
+#ifndef V35_COMPATIBILITY_CODE
+ }
+#endif
+
+ info.fFlags = buffer->readUInt();
+
+ if (!IsValidPictInfo(info)) {
return false;
}
@@ -418,19 +466,20 @@
}
// fRecord OK
-SkPicture::SkPicture(SkPictureData* data, int width, int height)
+SkPicture::SkPicture(SkPictureData* data, SkScalar width, SkScalar height)
: fData(data)
- , fWidth(width)
- , fHeight(height)
+ , fCullWidth(width)
+ , fCullHeight(height)
, fAnalysis() {
this->needsNewGenID();
}
SkPicture* SkPicture::Forwardport(const SkPicture& src) {
SkAutoTDelete<SkRecord> record(SkNEW(SkRecord));
- SkRecorder canvas(record.get(), src.width(), src.height());
+ SkRecorder canvas(record.get(), src.cullRect().width(), src.cullRect().height());
src.draw(&canvas);
- return SkNEW_ARGS(SkPicture, (src.width(), src.height(), record.detach(), NULL/*bbh*/));
+ return SkNEW_ARGS(SkPicture, (src.cullRect().width(), src.cullRect().height(),
+ record.detach(), NULL/*bbh*/));
}
// fRecord OK
@@ -447,7 +496,7 @@
if (NULL == data) {
return NULL;
}
- const SkPicture src(data, info.fWidth, info.fHeight);
+ const SkPicture src(data, info.fCullRect.width(), info.fCullRect.height());
return Forwardport(src);
}
@@ -458,7 +507,7 @@
SkPicture* SkPicture::CreateFromBuffer(SkReadBuffer& buffer) {
SkPictInfo info;
- if (!InternalOnly_BufferIsSKP(buffer, &info)) {
+ if (!InternalOnly_BufferIsSKP(&buffer, &info)) {
return NULL;
}
@@ -468,7 +517,7 @@
if (NULL == data) {
return NULL;
}
- const SkPicture src(data, info.fWidth, info.fHeight);
+ const SkPicture src(data, info.fCullRect.width(), info.fCullRect.height());
return Forwardport(src);
}
@@ -484,8 +533,7 @@
// Set picture info after magic bytes in the header
info->fVersion = CURRENT_PICTURE_VERSION;
- info->fWidth = fWidth;
- info->fHeight = fHeight;
+ info->fCullRect = this->cullRect();
info->fFlags = SkPictInfo::kCrossProcess_Flag;
// TODO: remove this flag, since we're always float (now)
info->fFlags |= SkPictInfo::kScalarIsFloat_Flag;
@@ -502,13 +550,14 @@
// If we're a new-format picture, backport to old format for serialization.
SkAutoTDelete<SkPicture> oldFormat;
if (NULL == data && NULL != fRecord.get()) {
- oldFormat.reset(backport(*fRecord, fWidth, fHeight));
+ oldFormat.reset(backport(*fRecord, this->cullRect()));
data = oldFormat->fData.get();
SkASSERT(NULL != data);
}
SkPictInfo info;
this->createHeader(&info);
+ SkASSERT(sizeof(SkPictInfo) == 32);
stream->write(&info, sizeof(info));
if (NULL != data) {
@@ -526,14 +575,17 @@
// If we're a new-format picture, backport to old format for serialization.
SkAutoTDelete<SkPicture> oldFormat;
if (NULL == data && NULL != fRecord.get()) {
- oldFormat.reset(backport(*fRecord, fWidth, fHeight));
+ oldFormat.reset(backport(*fRecord, this->cullRect()));
data = oldFormat->fData.get();
SkASSERT(NULL != data);
}
SkPictInfo info;
this->createHeader(&info);
- buffer.writeByteArray(&info, sizeof(info));
+ buffer.writeByteArray(&info.fMagic, sizeof(info.fMagic));
+ buffer.writeUInt(info.fVersion);
+ buffer.writeRect(info.fCullRect);
+ buffer.writeUInt(info.fFlags);
if (NULL != data) {
buffer.writeBool(true);
@@ -605,9 +657,9 @@
}
// fRecord OK
-SkPicture::SkPicture(int width, int height, SkRecord* record, SkBBoxHierarchy* bbh)
- : fWidth(width)
- , fHeight(height)
+SkPicture::SkPicture(SkScalar width, SkScalar height, SkRecord* record, SkBBoxHierarchy* bbh)
+ : fCullWidth(width)
+ , fCullHeight(height)
, fRecord(record)
, fBBH(SkSafeRef(bbh))
, fAnalysis(*record) {
diff --git a/src/core/SkPictureData.h b/src/core/SkPictureData.h
index a5f1ae0..019bfb2 100644
--- a/src/core/SkPictureData.h
+++ b/src/core/SkPictureData.h
@@ -37,8 +37,7 @@
char fMagic[8];
uint32_t fVersion;
- uint32_t fWidth;
- uint32_t fHeight;
+ SkRect fCullRect;
uint32_t fFlags;
};
diff --git a/src/core/SkPictureRecorder.cpp b/src/core/SkPictureRecorder.cpp
index d90f885..fadb937 100644
--- a/src/core/SkPictureRecorder.cpp
+++ b/src/core/SkPictureRecorder.cpp
@@ -17,7 +17,7 @@
SkPictureRecorder::~SkPictureRecorder() {}
-SkCanvas* SkPictureRecorder::beginRecording(int width, int height,
+SkCanvas* SkPictureRecorder::beginRecording(SkScalar width, SkScalar height,
SkBBHFactory* bbhFactory /* = NULL */,
uint32_t recordFlags /* = 0 */) {
#ifdef SK_PICTURE_USE_SK_RECORD
@@ -27,11 +27,11 @@
#endif
}
-SkCanvas* SkPictureRecorder::DEPRECATED_beginRecording(int width, int height,
+SkCanvas* SkPictureRecorder::DEPRECATED_beginRecording(SkScalar width, SkScalar height,
SkBBHFactory* bbhFactory /* = NULL */,
uint32_t recordFlags /* = 0 */) {
- fWidth = width;
- fHeight = height;
+ fCullWidth = width;
+ fCullHeight = height;
const SkISize size = SkISize::Make(width, height);
@@ -49,10 +49,10 @@
return this->getRecordingCanvas();
}
-SkCanvas* SkPictureRecorder::EXPERIMENTAL_beginRecording(int width, int height,
+SkCanvas* SkPictureRecorder::EXPERIMENTAL_beginRecording(SkScalar width, SkScalar height,
SkBBHFactory* bbhFactory /* = NULL */) {
- fWidth = width;
- fHeight = height;
+ fCullWidth = width;
+ fCullHeight = height;
if (NULL != bbhFactory) {
fBBH.reset((*bbhFactory)(width, height));
@@ -75,13 +75,15 @@
SkPicture* picture = NULL;
if (NULL != fRecord.get()) {
- picture = SkNEW_ARGS(SkPicture, (fWidth, fHeight, fRecord.detach(), fBBH.get()));
+ picture = SkNEW_ARGS(SkPicture, (fCullWidth, fCullHeight,
+ fRecord.detach(), fBBH.get()));
}
if (NULL != fPictureRecord.get()) {
fPictureRecord->endRecording();
const bool deepCopyOps = false;
- picture = SkNEW_ARGS(SkPicture, (fWidth, fHeight, *fPictureRecord.get(), deepCopyOps));
+ picture = SkNEW_ARGS(SkPicture, (fCullWidth, fCullHeight,
+ *fPictureRecord.get(), deepCopyOps));
}
return picture;
@@ -104,7 +106,8 @@
if (NULL != fPictureRecord.get()) {
const bool deepCopyOps = true;
- SkPicture picture(fWidth, fHeight, *fPictureRecord.get(), deepCopyOps);
+ SkPicture picture(fCullWidth, fCullHeight,
+ *fPictureRecord.get(), deepCopyOps);
picture.draw(canvas);
}
}
diff --git a/src/core/SkPictureShader.cpp b/src/core/SkPictureShader.cpp
index 3e0eb65..73ab170 100644
--- a/src/core/SkPictureShader.cpp
+++ b/src/core/SkPictureShader.cpp
@@ -22,10 +22,9 @@
const SkMatrix* localMatrix, const SkRect* tile)
: INHERITED(localMatrix)
, fPicture(SkRef(picture))
+ , fTile(NULL != tile ? *tile : picture->cullRect())
, fTmx(tmx)
, fTmy(tmy) {
- fTile = tile ? *tile : SkRect::MakeWH(SkIntToScalar(picture->width()),
- SkIntToScalar(picture->height()));
}
#ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING
@@ -43,8 +42,7 @@
SkPictureShader* SkPictureShader::Create(const SkPicture* picture, TileMode tmx, TileMode tmy,
const SkMatrix* localMatrix, const SkRect* tile) {
- if (!picture || 0 == picture->width() || 0 == picture->height()
- || (NULL != tile && tile->isEmpty())) {
+ if (!picture || picture->cullRect().isEmpty() || (NULL != tile && tile->isEmpty())) {
return NULL;
}
return SkNEW_ARGS(SkPictureShader, (picture, tmx, tmy, localMatrix, tile));
@@ -70,7 +68,7 @@
}
SkShader* SkPictureShader::refBitmapShader(const SkMatrix& matrix, const SkMatrix* localM) const {
- SkASSERT(fPicture && fPicture->width() > 0 && fPicture->height() > 0);
+ SkASSERT(fPicture && !fPicture->cullRect().isEmpty());
SkMatrix m;
m.setConcat(matrix, this->getLocalMatrix());
@@ -201,9 +199,11 @@
"clamp", "repeat", "mirror"
};
- str->appendf("PictureShader: [%d:%d] ",
- fPicture ? fPicture->width() : 0,
- fPicture ? fPicture->height() : 0);
+ str->appendf("PictureShader: [%f:%f:%f:%f] ",
+ fPicture ? fPicture->cullRect().fLeft : 0,
+ fPicture ? fPicture->cullRect().fTop : 0,
+ fPicture ? fPicture->cullRect().fRight : 0,
+ fPicture ? fPicture->cullRect().fBottom : 0);
str->appendf("(%s, %s)", gTileModeName[fTmx], gTileModeName[fTmy]);
diff --git a/src/core/SkRecordDraw.cpp b/src/core/SkRecordDraw.cpp
index 7985e2b..0117ade 100644
--- a/src/core/SkRecordDraw.cpp
+++ b/src/core/SkRecordDraw.cpp
@@ -321,7 +321,7 @@
}
Bounds bounds(const DrawPicture& op) const {
- SkRect dst = SkRect::MakeWH(op.picture->width(), op.picture->height());
+ SkRect dst = op.picture->cullRect();
if (op.matrix) {
op.matrix->mapRect(&dst);
}