aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--gm/optimizations.cpp420
-rw-r--r--gyp/core.gypi6
-rw-r--r--gyp/gmslides.gypi1
-rw-r--r--gyp/tests.gypi1
-rw-r--r--include/core/SkPicture.h21
-rw-r--r--include/core/SkPictureRecorder.h8
-rw-r--r--src/core/SkBBoxHierarchyRecord.cpp132
-rw-r--r--src/core/SkBBoxHierarchyRecord.h47
-rw-r--r--src/core/SkBBoxRecord.cpp380
-rw-r--r--src/core/SkBBoxRecord.h96
-rw-r--r--src/core/SkPicture.cpp23
-rw-r--r--src/core/SkPictureData.cpp23
-rw-r--r--src/core/SkPictureData.h15
-rw-r--r--src/core/SkPicturePlayback.cpp86
-rw-r--r--src/core/SkPicturePlayback.h25
-rw-r--r--src/core/SkPictureRecord.cpp592
-rw-r--r--src/core/SkPictureRecord.h44
-rw-r--r--src/core/SkPictureRecorder.cpp22
-rw-r--r--src/core/SkPictureStateTree.cpp218
-rw-r--r--src/core/SkPictureStateTree.h162
-rw-r--r--tests/PictureStateTreeTest.cpp123
-rw-r--r--tests/RecordingXfermodeTest.cpp129
22 files changed, 83 insertions, 2491 deletions
diff --git a/gm/optimizations.cpp b/gm/optimizations.cpp
deleted file mode 100644
index 85ce3e9d94..0000000000
--- a/gm/optimizations.cpp
+++ /dev/null
@@ -1,420 +0,0 @@
-/*
- * Copyright 2013 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "gm.h"
-#include "SkDebugCanvas.h"
-#include "SkPictureFlat.h"
-#include "SkPictureRecorder.h"
-
-#define WARN(msg) \
- SkDebugf("%s:%d: %s\n", __FILE__, __LINE__, msg);
-
-// Do the commands in 'input' match the supplied pattern? Note: this is a pretty
-// heavy-weight operation since we are drawing the picture into a debug canvas
-// to extract the commands.
-static bool check_pattern(SkPicture& input, const SkTDArray<DrawType> &pattern) {
- SkDebugCanvas debugCanvas(SkScalarCeilToInt(input.cullRect().width()),
- SkScalarCeilToInt(input.cullRect().height()));
- input.playback(&debugCanvas);
-
- if (pattern.count() != debugCanvas.getSize()) {
- return false;
- }
-
- for (int i = 0; i < pattern.count(); ++i) {
- if (pattern[i] != debugCanvas.getDrawCommandAt(i)->getType()) {
- return false;
- }
- }
-
- return true;
-}
-
-// construct the pattern removed by the SkPictureRecord::remove_save_layer1
-// optimization, i.e.:
-// SAVE_LAYER
-// DRAW_BITMAP|DRAW_BITMAP_MATRIX|DRAW_BITMAP_NINE|DRAW_BITMAP_RECT_TO_RECT
-// RESTORE
-//
-// saveLayerHasPaint - control if the saveLayer has a paint (the optimization
-// takes a different path if this is false)
-// dbmr2rHasPaint - control if the dbmr2r has a paint (the optimization
-// takes a different path if this is false)
-// colorsMatch - control if the saveLayer and dbmr2r paint colors
-// match (the optimization will fail if they do not)
-static SkPicture* create_save_layer_opt_1(SkTDArray<DrawType>* preOptPattern,
- SkTDArray<DrawType>* postOptPattern,
- const SkBitmap& checkerBoard,
- bool saveLayerHasPaint,
- bool dbmr2rHasPaint,
- bool colorsMatch) {
- // Create the pattern that should trigger the optimization
- preOptPattern->setCount(5);
- (*preOptPattern)[0] = SAVE;
- (*preOptPattern)[1] = SAVE_LAYER;
- (*preOptPattern)[2] = DRAW_BITMAP_RECT_TO_RECT;
- (*preOptPattern)[3] = RESTORE;
- (*preOptPattern)[4] = RESTORE;
-
- if (colorsMatch) {
- // Create the pattern that should appear after the optimization
- postOptPattern->setCount(5);
- (*postOptPattern)[0] = SAVE; // extra save/restore added by extra draw
- (*postOptPattern)[1] = SAVE;
- (*postOptPattern)[2] = DRAW_BITMAP_RECT_TO_RECT;
- (*postOptPattern)[3] = RESTORE;
- (*postOptPattern)[4] = RESTORE;
- } else {
- // Create the pattern that appears if the optimization doesn't fire
- postOptPattern->setCount(7);
- (*postOptPattern)[0] = SAVE; // extra save/restore added by extra draw
- (*postOptPattern)[1] = SAVE;
- (*postOptPattern)[2] = SAVE_LAYER;
- (*postOptPattern)[3] = DRAW_BITMAP_RECT_TO_RECT;
- (*postOptPattern)[4] = RESTORE;
- (*postOptPattern)[5] = RESTORE;
- (*postOptPattern)[6] = RESTORE;
- }
-
- SkPictureRecorder recorder;
-
- SkCanvas* canvas = recorder.DEPRECATED_beginRecording(100, 100, NULL, 0);
- // have to disable the optimizations while generating the picture
- recorder.internalOnly_EnableOpts(false);
-
- SkPaint saveLayerPaint;
- saveLayerPaint.setColor(0xCC000000);
-
- // saveLayer's 'bounds' parameter must be NULL for this optimization
- if (saveLayerHasPaint) {
- canvas->saveLayer(NULL, &saveLayerPaint);
- } else {
- canvas->saveLayer(NULL, NULL);
- }
-
- SkRect rect = { 10, 10, 90, 90 };
-
- // The dbmr2r's paint must be opaque
- SkPaint dbmr2rPaint;
- if (colorsMatch) {
- dbmr2rPaint.setColor(0xFF000000);
- } else {
- dbmr2rPaint.setColor(0xFFFF0000);
- }
-
- if (dbmr2rHasPaint) {
- canvas->drawBitmapRectToRect(checkerBoard, NULL, rect, &dbmr2rPaint);
- } else {
- canvas->drawBitmapRectToRect(checkerBoard, NULL, rect, NULL);
- }
- canvas->restore();
-
- return recorder.endRecording();
-}
-
-// straight-ahead version that is seen in the skps
-static SkPicture* create_save_layer_opt_1_v1(SkTDArray<DrawType>* preOptPattern,
- SkTDArray<DrawType>* postOptPattern,
- const SkBitmap& checkerBoard) {
- return create_save_layer_opt_1(preOptPattern, postOptPattern, checkerBoard,
- true, // saveLayer has a paint
- true, // dbmr2r has a paint
- true); // and the colors match
-}
-
-// alternate version that should still succeed
-static SkPicture* create_save_layer_opt_1_v2(SkTDArray<DrawType>* preOptPattern,
- SkTDArray<DrawType>* postOptPattern,
- const SkBitmap& checkerBoard) {
- return create_save_layer_opt_1(preOptPattern, postOptPattern, checkerBoard,
- false, // saveLayer doesn't have a paint!
- true, // dbmr2r has a paint
- true); // color matching not really applicable
-}
-
-// alternate version that should still succeed
-static SkPicture* create_save_layer_opt_1_v3(SkTDArray<DrawType>* preOptPattern,
- SkTDArray<DrawType>* postOptPattern,
- const SkBitmap& checkerBoard) {
- return create_save_layer_opt_1(preOptPattern, postOptPattern, checkerBoard,
- true, // saveLayer has a paint
- false, // dbmr2r doesn't have a paint!
- true); // color matching not really applicable
-}
-
-// version in which the optimization fails b.c. the colors don't match
-static SkPicture* create_save_layer_opt_1_v4(SkTDArray<DrawType>* preOptPattern,
- SkTDArray<DrawType>* postOptPattern,
- const SkBitmap& checkerBoard) {
- return create_save_layer_opt_1(preOptPattern, postOptPattern, checkerBoard,
- true, // saveLayer has a paint
- true, // dbmr2r has a paint
- false); // and the colors don't match!
-}
-
-// construct the pattern removed by the SkPictureRecord::remove_save_layer2
-// optimization, i.e.:
-// SAVE_LAYER (with NULL == bounds)
-// SAVE
-// CLIP_RECT
-// DRAW_BITMAP|DRAW_BITMAP_MATRIX|DRAW_BITMAP_NINE|DRAW_BITMAP_RECT_TO_RECT
-// RESTORE
-// RESTORE
-//
-// saveLayerHasPaint - control if the saveLayer has a paint (the optimization
-// takes a different path if this is false)
-// dbmr2rHasPaint - control if the dbmr2r has a paint (the optimization
-// takes a different path if this is false)
-// colorsMatch - control if the saveLayer and dbmr2r paint colors
-// match (the optimization will fail if they do not)
-static SkPicture* create_save_layer_opt_2(SkTDArray<DrawType>* preOptPattern,
- SkTDArray<DrawType>* postOptPattern,
- const SkBitmap& checkerBoard,
- bool saveLayerHasPaint,
- bool dbmr2rHasPaint,
- bool colorsMatch) {
- // Create the pattern that should trigger the optimization
- preOptPattern->setCount(8);
- (*preOptPattern)[0] = SAVE;
- (*preOptPattern)[1] = SAVE_LAYER;
- (*preOptPattern)[2] = SAVE;
- (*preOptPattern)[3] = CLIP_RECT;
- (*preOptPattern)[4] = DRAW_BITMAP_RECT_TO_RECT;
- (*preOptPattern)[5] = RESTORE;
- (*preOptPattern)[6] = RESTORE;
- (*preOptPattern)[7] = RESTORE;
-
- if (colorsMatch) {
- // Create the pattern that should appear after the optimization
- postOptPattern->setCount(8);
- (*postOptPattern)[0] = SAVE; // extra save/restore added by extra draw
- (*postOptPattern)[1] = SAVE;
- (*postOptPattern)[2] = SAVE;
- (*postOptPattern)[3] = CLIP_RECT;
- (*postOptPattern)[4] = DRAW_BITMAP_RECT_TO_RECT;
- (*postOptPattern)[5] = RESTORE;
- (*postOptPattern)[6] = RESTORE;
- (*postOptPattern)[7] = RESTORE;
- } else {
- // Create the pattern that appears if the optimization doesn't fire
- postOptPattern->setCount(10);
- (*postOptPattern)[0] = SAVE; // extra save/restore added by extra draw
- (*postOptPattern)[1] = SAVE;
- (*postOptPattern)[2] = SAVE_LAYER;
- (*postOptPattern)[3] = SAVE;
- (*postOptPattern)[4] = CLIP_RECT;
- (*postOptPattern)[5] = DRAW_BITMAP_RECT_TO_RECT;
- (*postOptPattern)[6] = RESTORE;
- (*postOptPattern)[7] = RESTORE;
- (*postOptPattern)[8] = RESTORE;
- (*postOptPattern)[9] = RESTORE;
- }
-
- SkPictureRecorder recorder;
-
- SkCanvas* canvas = recorder.DEPRECATED_beginRecording(100, 100, NULL, 0);
- // have to disable the optimizations while generating the picture
- recorder.internalOnly_EnableOpts(false);
-
- SkPaint saveLayerPaint;
- saveLayerPaint.setColor(0xCC000000);
-
- // saveLayer's 'bounds' parameter must be NULL for this optimization
- if (saveLayerHasPaint) {
- canvas->saveLayer(NULL, &saveLayerPaint);
- } else {
- canvas->saveLayer(NULL, NULL);
- }
-
- canvas->save();
-
- SkRect rect = { 10, 10, 90, 90 };
- canvas->clipRect(rect);
-
- // The dbmr2r's paint must be opaque
- SkPaint dbmr2rPaint;
- if (colorsMatch) {
- dbmr2rPaint.setColor(0xFF000000);
- } else {
- dbmr2rPaint.setColor(0xFFFF0000);
- }
-
- if (dbmr2rHasPaint) {
- canvas->drawBitmapRectToRect(checkerBoard, NULL, rect, &dbmr2rPaint);
- } else {
- canvas->drawBitmapRectToRect(checkerBoard, NULL, rect, NULL);
- }
- canvas->restore();
- canvas->restore();
-
- return recorder.endRecording();
-}
-
-// straight-ahead version that is seen in the skps
-static SkPicture* create_save_layer_opt_2_v1(SkTDArray<DrawType>* preOptPattern,
- SkTDArray<DrawType>* postOptPattern,
- const SkBitmap& checkerBoard) {
- return create_save_layer_opt_2(preOptPattern, postOptPattern, checkerBoard,
- true, // saveLayer has a paint
- true, // dbmr2r has a paint
- true); // and the colors match
-}
-
-// alternate version that should still succeed
-static SkPicture* create_save_layer_opt_2_v2(SkTDArray<DrawType>* preOptPattern,
- SkTDArray<DrawType>* postOptPattern,
- const SkBitmap& checkerBoard) {
- return create_save_layer_opt_2(preOptPattern, postOptPattern, checkerBoard,
- false, // saveLayer doesn't have a paint!
- true, // dbmr2r has a paint
- true); // color matching not really applicable
-}
-
-// alternate version that should still succeed
-static SkPicture* create_save_layer_opt_2_v3(SkTDArray<DrawType>* preOptPattern,
- SkTDArray<DrawType>* postOptPattern,
- const SkBitmap& checkerBoard) {
- return create_save_layer_opt_2(preOptPattern, postOptPattern, checkerBoard,
- true, // saveLayer has a paint
- false, // dbmr2r doesn't have a paint!
- true); // color matching not really applicable
-}
-
-// version in which the optimization fails b.c. the colors don't match
-static SkPicture* create_save_layer_opt_2_v4(SkTDArray<DrawType>* preOptPattern,
- SkTDArray<DrawType>* postOptPattern,
- const SkBitmap& checkerBoard) {
- return create_save_layer_opt_2(preOptPattern, postOptPattern, checkerBoard,
- true, // saveLayer has a paint
- true, // dbmr2r has a paint
- false); // and the colors don't match!
-}
-
-// As our .skp optimizations get folded into the captured skps our code will
-// no longer be locally exercised. This GM manually constructs the patterns
-// our optimizations will remove to test them. It acts as both a GM and a unit
-// test
-class OptimizationsGM : public skiagm::GM {
-public:
- OptimizationsGM() {
- this->makeCheckerboard();
- }
-
- static const int kWidth = 800;
- static const int kHeight = 800;
-
-protected:
- uint32_t onGetFlags() const SK_OVERRIDE {
- // One optimization changes the color drawn slightly in a 565 target.
- // We've decided it's innocuous, so we disable this GM when targeting 565.
- // Revisit this if we get finer-grained control: it'd be nice to keep drawing directly.
- // For more, see skia:1994.
- return skiagm::GM::kSkip565_Flag;
- }
-
- SkString onShortName() {
- return SkString("optimizations");
- }
-
- SkISize onISize() { return SkISize::Make(kWidth, kHeight); }
-
- typedef SkPicture* (*PFCreateOpt)(SkTDArray<DrawType> *preOptPattern,
- SkTDArray<DrawType> *postOptPattern,
- const SkBitmap& checkerBoard);
-
- virtual void onDraw(SkCanvas* canvas) {
-
- PFCreateOpt gOpts[] = {
- create_save_layer_opt_1_v1,
- create_save_layer_opt_1_v2,
- create_save_layer_opt_1_v3,
- create_save_layer_opt_1_v4,
- create_save_layer_opt_2_v1,
- create_save_layer_opt_2_v2,
- create_save_layer_opt_2_v3,
- create_save_layer_opt_2_v4,
- };
-
- SkTDArray<DrawType> prePattern, postPattern;
- SkScalar xPos = 0, yPos = 0;
-
- for (size_t i = 0; i < SK_ARRAY_COUNT(gOpts); ++i) {
- SkAutoTUnref<SkPicture> pre((*gOpts[i])(&prePattern, &postPattern, fCheckerboard));
-
- if (!(check_pattern(*pre, prePattern))) {
- WARN("Pre optimization pattern mismatch");
- SkASSERT(0);
- }
-
- canvas->save();
- canvas->translate(xPos, yPos);
- pre->playback(canvas);
- xPos += pre->cullRect().width();
- canvas->restore();
-
- // re-render the 'pre' picture and thus 'apply' the optimization
- SkPictureRecorder recorder;
-
- SkCanvas* recordCanvas =
- recorder.DEPRECATED_beginRecording(pre->cullRect().width(),
- pre->cullRect().height(),
- NULL, 0);
-
- pre->playback(recordCanvas);
-
- SkAutoTUnref<SkPicture> post(recorder.endRecording());
-
- if (!(check_pattern(*post, postPattern))) {
- WARN("Post optimization pattern mismatch");
- SkASSERT(0);
- }
-
- canvas->save();
- canvas->translate(xPos, yPos);
- post->playback(canvas);
- xPos += post->cullRect().width();
- canvas->restore();
-
- if (xPos >= kWidth) {
- // start a new line
- xPos = 0;
- yPos += post->cullRect().height();
- }
-
- // TODO: we could also render the pre and post pictures to bitmaps
- // and manually compare them in this method
- }
- }
-
-private:
- void makeCheckerboard() {
- static const unsigned int kCheckerboardWidth = 16;
- static const unsigned int kCheckerboardHeight = 16;
-
- fCheckerboard.allocN32Pixels(kCheckerboardWidth, kCheckerboardHeight);
- for (unsigned int y = 0; y < kCheckerboardHeight; y += 2) {
- SkPMColor* scanline = fCheckerboard.getAddr32(0, y);
- for (unsigned int x = 0; x < kCheckerboardWidth; x += 2) {
- *scanline++ = 0xFFFFFFFF;
- *scanline++ = 0xFF000000;
- }
- scanline = fCheckerboard.getAddr32(0, y + 1);
- for (unsigned int x = 0; x < kCheckerboardWidth; x += 2) {
- *scanline++ = 0xFF000000;
- *scanline++ = 0xFFFFFFFF;
- }
- }
- }
-
- SkBitmap fCheckerboard;
-
- typedef skiagm::GM INHERITED;
-};
-
-//////////////////////////////////////////////////////////////////////////////
-
-DEF_GM( return new OptimizationsGM; )
diff --git a/gyp/core.gypi b/gyp/core.gypi
index 6907d346cc..49027a91f2 100644
--- a/gyp/core.gypi
+++ b/gyp/core.gypi
@@ -14,10 +14,6 @@
'<(skia_src_path)/core/SkAntiRun.h',
'<(skia_src_path)/core/SkBBHFactory.cpp',
'<(skia_src_path)/core/SkBBoxHierarchy.h',
- '<(skia_src_path)/core/SkBBoxRecord.cpp',
- '<(skia_src_path)/core/SkBBoxRecord.h',
- '<(skia_src_path)/core/SkBBoxHierarchyRecord.cpp',
- '<(skia_src_path)/core/SkBBoxHierarchyRecord.h',
'<(skia_src_path)/core/SkBitmap.cpp',
'<(skia_src_path)/core/SkBitmapCache.cpp',
'<(skia_src_path)/core/SkBitmapDevice.cpp',
@@ -141,8 +137,6 @@
'<(skia_src_path)/core/SkPictureRecorder.cpp',
'<(skia_src_path)/core/SkPictureShader.cpp',
'<(skia_src_path)/core/SkPictureShader.h',
- '<(skia_src_path)/core/SkPictureStateTree.cpp',
- '<(skia_src_path)/core/SkPictureStateTree.h',
'<(skia_src_path)/core/SkPixelRef.cpp',
'<(skia_src_path)/core/SkPoint.cpp',
'<(skia_src_path)/core/SkProcSpriteBlitter.cpp',
diff --git a/gyp/gmslides.gypi b/gyp/gmslides.gypi
index 04301f4cf9..557cc4aa4b 100644
--- a/gyp/gmslides.gypi
+++ b/gyp/gmslides.gypi
@@ -127,7 +127,6 @@
'../gm/ninepatchstretch.cpp',
'../gm/nonclosedpaths.cpp',
'../gm/offsetimagefilter.cpp',
- '../gm/optimizations.cpp',
'../gm/ovals.cpp',
'../gm/patch.cpp',
'../gm/patchgrid.cpp',
diff --git a/gyp/tests.gypi b/gyp/tests.gypi
index a3197220ef..f50dc295cd 100644
--- a/gyp/tests.gypi
+++ b/gyp/tests.gypi
@@ -155,7 +155,6 @@
'../tests/PathTest.cpp',
'../tests/PathUtilsTest.cpp',
'../tests/PictureShaderTest.cpp',
- '../tests/PictureStateTreeTest.cpp',
'../tests/PictureTest.cpp',
'../tests/PixelRefTest.cpp',
'../tests/PointTest.cpp',
diff --git a/include/core/SkPicture.h b/include/core/SkPicture.h
index c41709d4be..6e785d43da 100644
--- a/include/core/SkPicture.h
+++ b/include/core/SkPicture.h
@@ -253,8 +253,7 @@ private:
mutable uint32_t fUniqueID;
- // TODO: make SkPictureData const when clone method goes away
- SkAutoTDelete<SkPictureData> fData;
+ SkAutoTDelete<const SkPictureData> fData;
const SkScalar fCullWidth;
const SkScalar fCullHeight;
mutable SkAutoTUnref<const AccelData> fAccelData;
@@ -270,30 +269,14 @@ private:
SkPicture(SkScalar width, SkScalar height, const SkPictureRecord& record, bool deepCopyOps);
- // An OperationList encapsulates a set of operation offsets into the picture byte
- // stream along with the CTMs needed for those operation.
- class OperationList : ::SkNoncopyable {
- public:
- // The following three entry points should only be accessed if
- // 'valid' returns true.
- int numOps() const { return fOps.count(); }
- // The offset in the picture of the operation to execute.
- uint32_t offset(int index) const;
- // The CTM that must be installed for the operation to behave correctly
- const SkMatrix& matrix(int index) const;
-
- SkTDArray<void*> fOps;
- };
-
void createHeader(SkPictInfo* info) const;
static bool IsValidPictInfo(const SkPictInfo& info);
- friend class SkPictureData; // to access OperationList
friend class SkPictureRecorder; // just for SkPicture-based constructor
friend class SkGpuDevice; // for fData access
friend class GrLayerHoister; // access to fRecord
friend class CollectLayers; // access to fRecord
- friend class SkPicturePlayback; // to get fData & OperationList
+ friend class SkPicturePlayback; // to get fData
friend void GrRecordReplaceDraw(const SkPicture* picture,
SkCanvas* canvas,
const GrReplacements* replacements,
diff --git a/include/core/SkPictureRecorder.h b/include/core/SkPictureRecorder.h
index 7951e5d396..8f3afb3a76 100644
--- a/include/core/SkPictureRecorder.h
+++ b/include/core/SkPictureRecorder.h
@@ -72,14 +72,6 @@ public:
*/
SkPicture* endRecording();
- /** Enable/disable all the picture recording optimizations (i.e.,
- those in SkPictureRecord). It is mainly intended for testing the
- existing optimizations (i.e., to actually have the pattern
- appear in an .skp we have to disable the optimization). Call right
- after 'beginRecording'.
- */
- void internalOnly_EnableOpts(bool enableOpts);
-
private:
void reset();
diff --git a/src/core/SkBBoxHierarchyRecord.cpp b/src/core/SkBBoxHierarchyRecord.cpp
deleted file mode 100644
index a9cd05d85f..0000000000
--- a/src/core/SkBBoxHierarchyRecord.cpp
+++ /dev/null
@@ -1,132 +0,0 @@
-
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "SkBBoxHierarchyRecord.h"
-#include "SkPictureStateTree.h"
-
-SkBBoxHierarchyRecord::SkBBoxHierarchyRecord(const SkISize& size,
- uint32_t recordFlags,
- SkBBoxHierarchy* h)
- : INHERITED(size, recordFlags) {
- fStateTree = SkNEW(SkPictureStateTree);
- fBoundingHierarchy = h;
- fBoundingHierarchy->ref();
- fBoundingHierarchy->setClient(this);
-}
-
-void SkBBoxHierarchyRecord::handleBBox(const SkRect& bounds) {
- SkPictureStateTree::Draw* draw = fStateTree->appendDraw(this->writeStream().bytesWritten());
- fBoundingHierarchy->insert(draw, bounds, true);
-}
-
-void SkBBoxHierarchyRecord::willSave() {
- fStateTree->appendSave();
- this->INHERITED::willSave();
-}
-
-SkCanvas::SaveLayerStrategy SkBBoxHierarchyRecord::willSaveLayer(const SkRect* bounds,
- const SkPaint* paint,
- SaveFlags flags) {
- // For now, assume all filters affect transparent black.
- // FIXME: This could be made less conservative as an optimization.
- bool paintAffectsTransparentBlack = paint &&
- ((paint->getImageFilter()) ||
- (paint->getColorFilter()));
- bool needToHandleBBox = paintAffectsTransparentBlack;
- if (!needToHandleBBox && paint) {
- // Unusual Xfermodes require us to process a saved layer
- // even with operations outisde the clip.
- // For example, DstIn is used by masking layers.
- // https://code.google.com/p/skia/issues/detail?id=1291
- SkXfermode* xfermode = paint->getXfermode();
- SkXfermode::Mode mode;
- // SrcOver is the common case with a NULL xfermode, so we should
- // make that the fast path and bypass the mode extraction and test.
- if (xfermode && xfermode->asMode(&mode)) {
- switch (mode) {
- case SkXfermode::kClear_Mode:
- case SkXfermode::kSrc_Mode:
- case SkXfermode::kSrcIn_Mode:
- case SkXfermode::kDstIn_Mode:
- case SkXfermode::kSrcOut_Mode:
- case SkXfermode::kDstATop_Mode:
- case SkXfermode::kModulate_Mode:
- needToHandleBBox = true;
- break;
- default:
- break;
- }
- }
- }
-
- SkRect drawBounds;
- if (needToHandleBBox) {
- SkIRect deviceBounds;
- this->getClipDeviceBounds(&deviceBounds);
- drawBounds.set(deviceBounds);
- }
- fStateTree->appendSaveLayer(this->writeStream().bytesWritten());
- SkCanvas::SaveLayerStrategy strategy = this->INHERITED::willSaveLayer(bounds, paint, flags);
- if (needToHandleBBox) {
- this->handleBBox(drawBounds);
- this->addNoOp();
- }
- return strategy;
-}
-
-void SkBBoxHierarchyRecord::willRestore() {
- fStateTree->appendRestore();
- this->INHERITED::willRestore();
-}
-
-void SkBBoxHierarchyRecord::didConcat(const SkMatrix& matrix) {
- fStateTree->appendTransform(getTotalMatrix());
- INHERITED::didConcat(matrix);
-}
-
-void SkBBoxHierarchyRecord::didSetMatrix(const SkMatrix& matrix) {
- fStateTree->appendTransform(getTotalMatrix());
- INHERITED::didSetMatrix(matrix);
-}
-
-void SkBBoxHierarchyRecord::onClipRect(const SkRect& rect,
- SkRegion::Op op,
- ClipEdgeStyle edgeStyle) {
- fStateTree->appendClip(this->writeStream().bytesWritten());
- this->INHERITED::onClipRect(rect, op, edgeStyle);
-}
-
-void SkBBoxHierarchyRecord::onClipRegion(const SkRegion& region,
- SkRegion::Op op) {
- fStateTree->appendClip(this->writeStream().bytesWritten());
- this->INHERITED::onClipRegion(region, op);
-}
-
-void SkBBoxHierarchyRecord::onClipPath(const SkPath& path,
- SkRegion::Op op,
- ClipEdgeStyle edgeStyle) {
- fStateTree->appendClip(this->writeStream().bytesWritten());
- this->INHERITED::onClipPath(path, op, edgeStyle);
-}
-
-void SkBBoxHierarchyRecord::onClipRRect(const SkRRect& rrect,
- SkRegion::Op op,
- ClipEdgeStyle edgeStyle) {
- fStateTree->appendClip(this->writeStream().bytesWritten());
- this->INHERITED::onClipRRect(rrect, op, edgeStyle);
-}
-
-bool SkBBoxHierarchyRecord::shouldRewind(void* data) {
- // SkBBoxHierarchy::rewindInserts is called by SkPicture after the
- // SkPicture has rewound its command stream. To match that rewind in the
- // BBH, we rewind all draws that reference commands that were recorded
- // past the point to which the SkPicture has rewound, which is given by
- // writeStream().bytesWritten().
- SkPictureStateTree::Draw* draw = static_cast<SkPictureStateTree::Draw*>(data);
- return draw->fOffset >= writeStream().bytesWritten();
-}
diff --git a/src/core/SkBBoxHierarchyRecord.h b/src/core/SkBBoxHierarchyRecord.h
deleted file mode 100644
index 7db82d8369..0000000000
--- a/src/core/SkBBoxHierarchyRecord.h
+++ /dev/null
@@ -1,47 +0,0 @@
-
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef SkRTreeCanvas_DEFINED
-#define SkRTreeCanvas_DEFINED
-
-#include "SkBBoxHierarchy.h"
-#include "SkBBoxRecord.h"
-
-/**
- * This records bounding box information into an SkBBoxHierarchy, and clip/transform information
- * into an SkPictureStateTree to allow for efficient culling and correct playback of draws.
- */
-class SkBBoxHierarchyRecord : public SkBBoxRecord, public SkBBoxHierarchyClient {
-public:
- /** This will take a ref of h */
- SkBBoxHierarchyRecord(const SkISize& size, uint32_t recordFlags, SkBBoxHierarchy* h);
- virtual ~SkBBoxHierarchyRecord() { };
-
- virtual void handleBBox(const SkRect& bounds) SK_OVERRIDE;
-
- // Implementation of the SkBBoxHierarchyClient interface
- virtual bool shouldRewind(void* data) SK_OVERRIDE;
-
-protected:
- virtual void willSave() SK_OVERRIDE;
- virtual SaveLayerStrategy willSaveLayer(const SkRect*, const SkPaint*, SaveFlags) SK_OVERRIDE;
- virtual void willRestore() SK_OVERRIDE;
-
- virtual void didConcat(const SkMatrix&) SK_OVERRIDE;
- virtual void didSetMatrix(const SkMatrix&) SK_OVERRIDE;
-
- virtual void onClipRect(const SkRect&, SkRegion::Op, ClipEdgeStyle) SK_OVERRIDE;
- virtual void onClipRRect(const SkRRect&, SkRegion::Op, ClipEdgeStyle) SK_OVERRIDE;
- virtual void onClipPath(const SkPath&, SkRegion::Op, ClipEdgeStyle) SK_OVERRIDE;
- virtual void onClipRegion(const SkRegion&, SkRegion::Op) SK_OVERRIDE;
-
-private:
- typedef SkBBoxRecord INHERITED;
-};
-
-#endif
diff --git a/src/core/SkBBoxRecord.cpp b/src/core/SkBBoxRecord.cpp
deleted file mode 100644
index 5fe42f99d6..0000000000
--- a/src/core/SkBBoxRecord.cpp
+++ /dev/null
@@ -1,380 +0,0 @@
-
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "SkBBoxRecord.h"
-#include "SkPatchUtils.h"
-
-#include "SkTextBlob.h"
-
-SkBBoxRecord::~SkBBoxRecord() {
- fSaveStack.deleteAll();
-}
-
-void SkBBoxRecord::drawOval(const SkRect& rect, const SkPaint& paint) {
- if (this->transformBounds(rect, &paint)) {
- INHERITED::drawOval(rect, paint);
- }
-}
-
-void SkBBoxRecord::drawRRect(const SkRRect& rrect, const SkPaint& paint) {
- if (this->transformBounds(rrect.rect(), &paint)) {
- INHERITED::drawRRect(rrect, paint);
- }
-}
-
-void SkBBoxRecord::drawRect(const SkRect& rect, const SkPaint& paint) {
- if (this->transformBounds(rect, &paint)) {
- INHERITED::drawRect(rect, paint);
- }
-}
-
-void SkBBoxRecord::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
- const SkPaint& paint) {
- if (this->transformBounds(outer.rect(), &paint)) {
- this->INHERITED::onDrawDRRect(outer, inner, paint);
- }
-}
-
-void SkBBoxRecord::drawPath(const SkPath& path, const SkPaint& paint) {
- if (path.isInverseFillType()) {
- // If path is inverse filled, use the current clip bounds as the
- // path's device-space bounding box.
- SkIRect clipBounds;
- if (this->getClipDeviceBounds(&clipBounds)) {
- this->handleBBox(SkRect::Make(clipBounds));
- INHERITED::drawPath(path, paint);
- }
- } else if (this->transformBounds(path.getBounds(), &paint)) {
- INHERITED::drawPath(path, paint);
- }
-}
-
-void SkBBoxRecord::drawPoints(PointMode mode, size_t count, const SkPoint pts[],
- const SkPaint& paint) {
- SkRect bbox;
- bbox.set(pts, SkToInt(count));
- // Small min width value, just to ensure hairline point bounding boxes aren't empty.
- // Even though we know hairline primitives are drawn one pixel wide, we do not use a
- // minimum of 1 because the playback scale factor is unknown at record time. Later
- // outsets will take care of adding additional padding for antialiasing and rounding out
- // to integer device coordinates, guaranteeing that the rasterized pixels will be included
- // in the computed bounds.
- // Note: The device coordinate outset in SkBBoxHierarchyRecord::handleBBox is currently
- // done in the recording coordinate space, which is wrong.
- // http://code.google.com/p/skia/issues/detail?id=1021
- static const SkScalar kMinWidth = 0.01f;
- SkScalar halfStrokeWidth = SkMaxScalar(paint.getStrokeWidth(), kMinWidth) / 2;
- bbox.outset(halfStrokeWidth, halfStrokeWidth);
- if (this->transformBounds(bbox, &paint)) {
- INHERITED::drawPoints(mode, count, pts, paint);
- }
-}
-
-void SkBBoxRecord::drawPaint(const SkPaint& paint) {
- SkRect bbox;
- if (this->getClipBounds(&bbox)) {
- if (this->transformBounds(bbox, &paint)) {
- INHERITED::drawPaint(paint);
- }
- }
-}
-
-void SkBBoxRecord::clear(SkColor color) {
- SkISize size = this->getDeviceSize();
- SkRect bbox = {0, 0, SkIntToScalar(size.width()), SkIntToScalar(size.height())};
- this->handleBBox(bbox);
- INHERITED::clear(color);
-}
-
-void SkBBoxRecord::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
- const SkPaint& paint) {
- 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;
- if (this->transformBounds(bbox, &paint)) {
- INHERITED::onDrawText(text, byteLength, x, y, paint);
- }
-}
-
-void SkBBoxRecord::drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top,
- const SkPaint* paint) {
- SkRect bbox = {left, top, left + bitmap.width(), top + bitmap.height()};
- if (this->transformBounds(bbox, paint)) {
- INHERITED::drawBitmap(bitmap, left, top, paint);
- }
-}
-
-void SkBBoxRecord::drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src,
- const SkRect& dst, const SkPaint* paint,
- DrawBitmapRectFlags flags) {
- if (this->transformBounds(dst, paint)) {
- INHERITED::drawBitmapRectToRect(bitmap, src, dst, paint, flags);
- }
-}
-
-void SkBBoxRecord::drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& mat,
- const SkPaint* paint) {
- SkMatrix m = mat;
- SkRect bbox = {0, 0, SkIntToScalar(bitmap.width()), SkIntToScalar(bitmap.height())};
- m.mapRect(&bbox);
- if (this->transformBounds(bbox, paint)) {
- INHERITED::drawBitmapMatrix(bitmap, mat, paint);
- }
-}
-
-void SkBBoxRecord::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
- const SkRect& dst, const SkPaint* paint) {
- if (this->transformBounds(dst, paint)) {
- INHERITED::drawBitmapNine(bitmap, center, dst, paint);
- }
-}
-
-// Hack to work-around https://code.google.com/p/chromium/issues/detail?id=373785
-// This logic assums that 'pad' is enough to add to the left and right to account for
-// big glyphs. For the font in question (a logo font) the glyphs is much wider than just
-// the pointsize (approx 3x wider).
-// As a temp work-around, we scale-up pad.
-// A more correct fix might be to add fontmetrics.fMaxX, but we don't have that value in hand
-// at the moment, and (possibly) the value in the font may not be accurate (but who knows).
-//
-static SkScalar hack_373785_amend_pad(SkScalar pad) {
- return pad * 4;
-}
-
-void SkBBoxRecord::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
- const SkPaint& paint) {
- 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;
- pad = hack_373785_amend_pad(pad);
- bbox.fLeft += pad;
- bbox.fRight -= pad;
-
- if (this->transformBounds(bbox, &paint)) {
- INHERITED::onDrawPosText(text, byteLength, pos, paint);
- }
-}
-
-void SkBBoxRecord::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
- SkScalar constY, const SkPaint& paint) {
- size_t numChars = paint.countText(text, byteLength);
- if (numChars == 0) {
- return;
- }
-
- const SkFlatData* flatPaintData = this->getFlatPaintData(paint);
- WriteTopBot(paint, *flatPaintData);
-
- SkScalar top = flatPaintData->topBot()[0];
- SkScalar bottom = flatPaintData->topBot()[1];
- SkScalar pad = top - bottom;
-
- SkRect bbox;
- bbox.fLeft = SK_ScalarMax;
- bbox.fRight = SK_ScalarMin;
-
- for (size_t i = 0; i < numChars; ++i) {
- if (xpos[i] < bbox.fLeft) {
- bbox.fLeft = xpos[i];
- }
- if (xpos[i] > bbox.fRight) {
- bbox.fRight = xpos[i];
- }
- }
-
- // pad horizontally by max glyph height
- pad = hack_373785_amend_pad(pad);
- bbox.fLeft += pad;
- bbox.fRight -= pad;
-
- bbox.fTop = top + constY;
- bbox.fBottom = bottom + constY;
-
- if (!this->transformBounds(bbox, &paint)) {
- return;
- }
- // This is the equivalent of calling:
- // INHERITED::drawPosTextH(text, byteLength, xpos, constY, paint);
- // but we filled our flat paint beforehand so that we could get font metrics.
- drawPosTextHImpl(text, byteLength, xpos, constY, paint, flatPaintData);
-}
-
-void SkBBoxRecord::drawSprite(const SkBitmap& bitmap, int left, int top,
- const SkPaint* paint) {
- SkRect bbox;
- bbox.set(SkIRect::MakeXYWH(left, top, bitmap.width(), bitmap.height()));
- this->handleBBox(bbox); // directly call handleBBox, matrix is ignored
- INHERITED::drawSprite(bitmap, left, top, paint);
-}
-
-void SkBBoxRecord::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
- const SkMatrix* matrix, const SkPaint& paint) {
- 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;
-
- if (this->transformBounds(bbox, &paint)) {
- INHERITED::onDrawTextOnPath(text, byteLength, path, matrix, paint);
- }
-}
-
-void SkBBoxRecord::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
- const SkPaint& paint) {
- SkRect bbox = blob->bounds();
- bbox.offset(x, y);
- // FIXME: implement implicit blob bounds!
- if (bbox.isEmpty()) {
- this->getClipBounds(&bbox);
- }
-
- if (this->transformBounds(bbox, &paint)) {
- INHERITED::onDrawTextBlob(blob, x, y, paint);
- }
-}
-
-void SkBBoxRecord::drawVertices(VertexMode mode, int vertexCount,
- const SkPoint vertices[], const SkPoint texs[],
- const SkColor colors[], SkXfermode* xfer,
- const uint16_t indices[], int indexCount,
- const SkPaint& paint) {
- SkRect bbox;
- bbox.set(vertices, vertexCount);
- if (this->transformBounds(bbox, &paint)) {
- INHERITED::drawVertices(mode, vertexCount, vertices, texs,
- colors, xfer, indices, indexCount, paint);
- }
-}
-
-void SkBBoxRecord::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
- const SkPoint texCoords[4], SkXfermode* xmode,
- const SkPaint& paint) {
- SkRect bbox;
- bbox.set(cubics, SkPatchUtils::kNumCtrlPts);
- if (this->transformBounds(bbox, &paint)) {
- INHERITED::onDrawPatch(cubics, colors, texCoords, xmode, paint);
- }
-}
-
-void SkBBoxRecord::onDrawPicture(const SkPicture* picture, const SkMatrix* matrix,
- const SkPaint* paint) {
- 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) {
- matrix->mapRect(&bounds);
- }
- if (this->transformBounds(bounds, paint)) {
- this->INHERITED::onDrawPicture(picture, matrix, paint);
- }
-}
-
-void SkBBoxRecord::willSave() {
- fSaveStack.push(NULL);
- this->INHERITED::willSave();
-}
-
-SkCanvas::SaveLayerStrategy SkBBoxRecord::willSaveLayer(const SkRect* bounds,
- const SkPaint* paint,
- SaveFlags flags) {
- // Image filters can affect the effective bounds of primitives drawn inside saveLayer().
- // Copy the paint so we can compute the modified bounds in transformBounds().
- fSaveStack.push(paint && paint->getImageFilter() ? new SkPaint(*paint) : NULL);
- return this->INHERITED::willSaveLayer(bounds, paint, flags);
-}
-
-void SkBBoxRecord::willRestore() {
- delete fSaveStack.top();
- fSaveStack.pop();
- this->INHERITED::willRestore();
-}
-
-bool SkBBoxRecord::transformBounds(const SkRect& bounds, const SkPaint* paint) {
- SkRect outBounds = bounds;
- outBounds.sort();
-
- if (paint) {
- // account for stroking, path effects, shadows, etc
- if (paint->canComputeFastBounds()) {
- SkRect temp;
- outBounds = paint->computeFastBounds(outBounds, &temp);
- } else {
- // set bounds to current clip
- if (!this->getClipBounds(&outBounds)) {
- // current clip is empty
- return false;
- }
- }
- }
-
- for (int i = fSaveStack.count() - 1; i >= 0; --i) {
- const SkPaint* paint = fSaveStack.getAt(i);
- if (paint && paint->canComputeFastBounds()) {
- SkRect temp;
- outBounds = paint->computeFastBounds(outBounds, &temp);
- }
- }
-
- if (!outBounds.isEmpty() && !this->quickReject(outBounds)) {
- this->getTotalMatrix().mapRect(&outBounds);
- this->handleBBox(outBounds);
- return true;
- }
-
- return false;
-}
diff --git a/src/core/SkBBoxRecord.h b/src/core/SkBBoxRecord.h
deleted file mode 100644
index 4833452e73..0000000000
--- a/src/core/SkBBoxRecord.h
+++ /dev/null
@@ -1,96 +0,0 @@
-
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef SkBBoxRecord_DEFINED
-#define SkBBoxRecord_DEFINED
-
-#include "SkPictureRecord.h"
-#include "SkTDArray.h"
-
-/**
- * This is an abstract SkPictureRecord subclass that intercepts draw calls and computes an
- * axis-aligned bounding box for each draw that it sees, subclasses implement handleBBox()
- * which will be called every time we get a new bounding box.
- */
-class SkBBoxRecord : public SkPictureRecord {
-public:
-
- SkBBoxRecord(const SkISize& size, uint32_t recordFlags)
- : INHERITED(size, recordFlags) {
- }
- virtual ~SkBBoxRecord();
-
- /**
- * This is called each time we get a bounding box, it will be axis-aligned,
- * in device coordinates, and expanded to include stroking, shadows, etc.
- */
- virtual void handleBBox(const SkRect& bbox) = 0;
-
- virtual void drawOval(const SkRect& rect, const SkPaint& paint) SK_OVERRIDE;
- virtual void drawRRect(const SkRRect& rrect, const SkPaint& paint) SK_OVERRIDE;
- virtual void drawRect(const SkRect& rect, const SkPaint& paint) SK_OVERRIDE;
- virtual void drawPath(const SkPath& path, const SkPaint& paint) SK_OVERRIDE;
- virtual void drawPoints(PointMode mode, size_t count, const SkPoint pts[],
- const SkPaint& paint) SK_OVERRIDE;
- virtual void drawPaint(const SkPaint& paint) SK_OVERRIDE;
- virtual void clear(SkColor) SK_OVERRIDE;
- virtual void drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top,
- const SkPaint* paint = NULL) SK_OVERRIDE;
- virtual void drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src,
- const SkRect& dst, const SkPaint* paint,
- DrawBitmapRectFlags flags) SK_OVERRIDE;
- virtual void drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& mat,
- const SkPaint* paint) SK_OVERRIDE;
- virtual void drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
- const SkRect& dst, const SkPaint* paint) SK_OVERRIDE;
- virtual void drawSprite(const SkBitmap& bitmap, int left, int top,
- const SkPaint* paint) SK_OVERRIDE;
- virtual void drawVertices(VertexMode mode, int vertexCount,
- const SkPoint vertices[], const SkPoint texs[],
- const SkColor colors[], SkXfermode* xfer,
- const uint16_t indices[], int indexCount,
- const SkPaint& paint) SK_OVERRIDE;
-
-protected:
- virtual void onDrawDRRect(const SkRRect&, const SkRRect&, const SkPaint&) SK_OVERRIDE;
- virtual void onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
- const SkPaint&) SK_OVERRIDE;
- virtual void onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
- const SkPaint&) SK_OVERRIDE;
- virtual void onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
- SkScalar constY, const SkPaint&) SK_OVERRIDE;
- virtual void onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
- const SkMatrix* matrix, const SkPaint&) SK_OVERRIDE;
- virtual void onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
- const SkPaint& paint) SK_OVERRIDE;
- virtual void onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
- const SkPoint texCoords[4], SkXfermode* xmode,
- const SkPaint& paint) SK_OVERRIDE;
- virtual void onDrawPicture(const SkPicture*, const SkMatrix*, const SkPaint*) SK_OVERRIDE;
- virtual void willSave() SK_OVERRIDE;
- virtual SaveLayerStrategy willSaveLayer(const SkRect*, const SkPaint*, SaveFlags) SK_OVERRIDE;
- virtual void willRestore() SK_OVERRIDE;
-
-private:
- /**
- * Takes a bounding box in current canvas view space, accounts for stroking and effects, and
- * computes an axis-aligned bounding box in device coordinates, then passes it to handleBBox()
- * returns false if the draw is completely clipped out, and may safely be ignored.
- **/
- bool transformBounds(const SkRect& bounds, const SkPaint* paint);
-
- /**
- * Paints from currently-active saveLayers that need to be applied to bounding boxes of all
- * primitives drawn inside them. We own these pointers.
- **/
- SkTDArray<const SkPaint*> fSaveStack;
-
- typedef SkPictureRecord INHERITED;
-};
-
-#endif
diff --git a/src/core/SkPicture.cpp b/src/core/SkPicture.cpp
index 10bbbcedb3..def67e6571 100644
--- a/src/core/SkPicture.cpp
+++ b/src/core/SkPicture.cpp
@@ -12,7 +12,6 @@
#include "SkPicturePlayback.h"
#include "SkPictureRecord.h"
#include "SkPictureRecorder.h"
-#include "SkPictureStateTree.h"
#include "SkBitmapDevice.h"
#include "SkCanvas.h"
@@ -32,7 +31,6 @@
#include "SkReader32.h"
#include "SkWriter32.h"
#include "SkRTree.h"
-#include "SkBBoxHierarchyRecord.h"
#if SK_SUPPORT_GPU
#include "GrContext.h"
@@ -307,32 +305,21 @@ SkPicture::AccelData::Domain SkPicture::AccelData::GenerateDomain() {
///////////////////////////////////////////////////////////////////////////////
-uint32_t SkPicture::OperationList::offset(int index) const {
- SkASSERT(index < fOps.count());
- return ((SkPictureStateTree::Draw*)fOps[index])->fOffset;
-}
-
-const SkMatrix& SkPicture::OperationList::matrix(int index) const {
- SkASSERT(index < fOps.count());
- return *((SkPictureStateTree::Draw*)fOps[index])->fMatrix;
-}
-
// fRecord OK
void SkPicture::playback(SkCanvas* canvas, SkDrawPictureCallback* callback) const {
SkASSERT(canvas);
SkASSERT(fData.get() || fRecord.get());
- // 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(this->cullRect());
-
if (fData.get()) {
SkPicturePlayback playback(this);
- playback.setUseBBH(useBBH);
playback.draw(canvas, callback);
}
if (fRecord.get()) {
+ // 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(this->cullRect());
+
SkRecordDraw(*fRecord, canvas, useBBH ? fBBH.get() : NULL, callback);
}
}
diff --git a/src/core/SkPictureData.cpp b/src/core/SkPictureData.cpp
index 877c3f4c33..896c2e6bf3 100644
--- a/src/core/SkPictureData.cpp
+++ b/src/core/SkPictureData.cpp
@@ -46,17 +46,8 @@ SkPictureData::SkPictureData(const SkPictureRecord& record,
fOpData = record.opData(deepCopyOps);
- fBoundingHierarchy = record.fBoundingHierarchy;
- fStateTree = record.fStateTree;
-
- SkSafeRef(fBoundingHierarchy);
- SkSafeRef(fStateTree);
fContentInfo.set(record.fContentInfo);
- if (fBoundingHierarchy) {
- fBoundingHierarchy->flushDeferredInserts();
- }
-
// copy over the refcnt dictionary to our reader
record.fFlattenableHeap.setupPlaybacks();
@@ -98,8 +89,6 @@ void SkPictureData::init() {
fTextBlobCount = 0;
fOpData = NULL;
fFactoryPlayback = NULL;
- fBoundingHierarchy = NULL;
- fStateTree = NULL;
}
SkPictureData::~SkPictureData() {
@@ -107,8 +96,6 @@ SkPictureData::~SkPictureData() {
SkSafeUnref(fBitmaps);
SkSafeUnref(fPaints);
- SkSafeUnref(fBoundingHierarchy);
- SkSafeUnref(fStateTree);
for (int i = 0; i < fPictureCount; i++) {
fPictureRefs[i]->unref();
@@ -578,16 +565,6 @@ bool SkPictureData::parseBuffer(SkReadBuffer& buffer) {
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
-const SkPicture::OperationList* SkPictureData::getActiveOps(const SkRect& query) const {
- if (NULL == fStateTree || NULL == fBoundingHierarchy) {
- return NULL;
- }
-
- SkPicture::OperationList* activeOps = SkNEW(SkPicture::OperationList);
- fBoundingHierarchy->search(query, &(activeOps->fOps));
- return activeOps;
-}
-
#if SK_SUPPORT_GPU
bool SkPictureData::suitableForGpuRasterization(GrContext* context, const char **reason,
int sampleCount) const {
diff --git a/src/core/SkPictureData.h b/src/core/SkPictureData.h
index b875151b50..02529938ab 100644
--- a/src/core/SkPictureData.h
+++ b/src/core/SkPictureData.h
@@ -13,7 +13,6 @@
#include "SkPicture.h"
#include "SkPictureContentInfo.h"
#include "SkPictureFlat.h"
-#include "SkPictureStateTree.h"
class SkData;
class SkPictureRecord;
@@ -24,7 +23,6 @@ class SkBBoxHierarchy;
class SkMatrix;
class SkPaint;
class SkPath;
-class SkPictureStateTree;
class SkReadBuffer;
class SkTextBlob;
@@ -67,8 +65,6 @@ public:
virtual ~SkPictureData();
- const SkPicture::OperationList* getActiveOps(const SkRect& queryRect) const;
-
void serialize(SkWStream*, SkPicture::EncodeBitmap) const;
void flatten(SkWriteBuffer&) const;
@@ -123,14 +119,6 @@ public:
return fTextBlobRefs[index - 1];
}
- void initIterator(SkPictureStateTree::Iterator* iter,
- const SkTDArray<void*>& draws,
- SkCanvas* canvas) const {
- if (fStateTree) {
- fStateTree->initIterator(iter, draws, canvas);
- }
- }
-
#if SK_SUPPORT_GPU
/**
* sampleCount is the number of samples-per-pixel or zero if non-MSAA.
@@ -175,9 +163,6 @@ private:
const SkTextBlob** fTextBlobRefs;
int fTextBlobCount;
- SkBBoxHierarchy* fBoundingHierarchy;
- SkPictureStateTree* fStateTree;
-
SkPictureContentInfo fContentInfo;
SkTypefacePlayback fTFPlayback;
diff --git a/src/core/SkPicturePlayback.cpp b/src/core/SkPicturePlayback.cpp
index 308ce9ec3f..661115e41a 100644
--- a/src/core/SkPicturePlayback.cpp
+++ b/src/core/SkPicturePlayback.cpp
@@ -10,7 +10,6 @@
#include "SkPictureData.h"
#include "SkPicturePlayback.h"
#include "SkPictureRecord.h"
-#include "SkPictureStateTree.h"
#include "SkReader32.h"
#include "SkTextBlob.h"
#include "SkTDArray.h"
@@ -66,84 +65,12 @@ static SkBitmap shallow_copy(const SkBitmap& bitmap) {
return bitmap;
}
-const SkPicture::OperationList* SkPicturePlayback::getActiveOps(const SkCanvas* canvas) {
-
- if (fUseBBH) {
- SkRect clipBounds;
- if (canvas->getClipBounds(&clipBounds)) {
- return fPictureData->getActiveOps(clipBounds);
- }
- }
-
- return NULL;
-}
-
-// Initialize the state tree iterator. Return false if there is nothing left to draw.
-bool SkPicturePlayback::initIterator(SkPictureStateTree::Iterator* iter,
- SkCanvas* canvas,
- const SkPicture::OperationList *activeOpsList) {
-
- if (activeOpsList) {
- if (0 == activeOpsList->numOps()) {
- return false; // nothing to draw
- }
-
- fPictureData->initIterator(iter, activeOpsList->fOps, canvas);
- }
-
- return true;
-}
-
-// If 'iter' is valid use it to skip forward through the picture.
-void SkPicturePlayback::StepIterator(SkPictureStateTree::Iterator* iter, SkReader32* reader) {
- if (iter->isValid()) {
- uint32_t skipTo = iter->nextDraw();
- if (SkPictureStateTree::Iterator::kDrawComplete == skipTo) {
- reader->setOffset(reader->size()); // skip to end
- } else {
- reader->setOffset(skipTo);
- }
- }
-}
-
-// Update the iterator and state tree to catch up with the skipped ops.
-void SkPicturePlayback::SkipIterTo(SkPictureStateTree::Iterator* iter,
- SkReader32* reader,
- uint32_t skipTo) {
- SkASSERT(skipTo <= reader->size());
- SkASSERT(reader->offset() <= skipTo); // should only be skipping forward
-
- if (iter->isValid()) {
- // If using a bounding box hierarchy, advance the state tree
- // iterator until at or after skipTo
- uint32_t adjustedSkipTo;
- do {
- adjustedSkipTo = iter->nextDraw();
- } while (adjustedSkipTo < skipTo);
- skipTo = adjustedSkipTo;
- }
- if (SkPictureStateTree::Iterator::kDrawComplete == skipTo) {
- reader->setOffset(reader->size()); // skip to end
- } else {
- reader->setOffset(skipTo);
- }
-}
-
void SkPicturePlayback::draw(SkCanvas* canvas, SkDrawPictureCallback* callback) {
AutoResetOpID aroi(this);
SkASSERT(0 == fCurOffset);
- SkAutoTDelete<const SkPicture::OperationList> activeOpsList(this->getActiveOps(canvas));
- SkPictureStateTree::Iterator it;
-
- if (!this->initIterator(&it, canvas, activeOpsList.get())) {
- return; // nothing to draw
- }
-
SkReader32 reader(fPictureData->opData()->bytes(), fPictureData->opData()->size());
- StepIterator(&it, &reader);
-
// Record this, so we can concat w/ it if we encounter a setMatrix()
SkMatrix initialMatrix = canvas->getTotalMatrix();
@@ -157,15 +84,8 @@ void SkPicturePlayback::draw(SkCanvas* canvas, SkDrawPictureCallback* callback)
fCurOffset = reader.offset();
uint32_t size;
DrawType op = ReadOpAndSize(&reader, &size);
- if (NOOP == op) {
- // NOOPs are to be ignored - do not propagate them any further
- SkipIterTo(&it, &reader, fCurOffset + size);
- continue;
- }
this->handleOp(&reader, op, size, canvas, initialMatrix);
-
- StepIterator(&it, &reader);
}
}
@@ -175,6 +95,10 @@ void SkPicturePlayback::handleOp(SkReader32* reader,
SkCanvas* canvas,
const SkMatrix& initialMatrix) {
switch (op) {
+ case NOOP: {
+ SkASSERT(size >= 4);
+ reader->skip(size - 4);
+ } break;
case CLIP_PATH: {
const SkPath& path = fPictureData->getPath(reader);
uint32_t packed = reader->readInt();
@@ -518,7 +442,7 @@ void SkPicturePlayback::handleOp(SkReader32* reader,
canvas->translate(dx, dy);
} break;
default:
- SkASSERT(0);
+ SkASSERTF(false, "Unknown draw type: %d", op);
}
}
diff --git a/src/core/SkPicturePlayback.h b/src/core/SkPicturePlayback.h
index cdfa8efe18..9e5db08c63 100644
--- a/src/core/SkPicturePlayback.h
+++ b/src/core/SkPicturePlayback.h
@@ -9,7 +9,6 @@
#define SkPicturePlayback_DEFINED
#include "SkPictureFlat.h" // for DrawType
-#include "SkPictureStateTree.h"
class SkBitmap;
class SkCanvas;
@@ -18,14 +17,11 @@ class SkPaint;
class SkPictureData;
// The basic picture playback class replays the provided picture into a canvas.
-// If the picture was generated with a BBH it is used to accelerate drawing
-// unless disabled via setUseBBH.
class SkPicturePlayback : SkNoncopyable {
public:
SkPicturePlayback(const SkPicture* picture)
: fPictureData(picture->fData.get())
- , fCurOffset(0)
- , fUseBBH(true) {
+ , fCurOffset(0) {
}
virtual ~SkPicturePlayback() { }
@@ -37,31 +33,18 @@ public:
size_t curOpID() const { return fCurOffset; }
void resetOpID() { fCurOffset = 0; }
- // TODO: remove setUseBBH after cleaning up GrGatherCanvas
- void setUseBBH(bool useBBH) { fUseBBH = useBBH; }
-
protected:
const SkPictureData* fPictureData;
// The offset of the current operation when within the draw method
size_t fCurOffset;
- bool fUseBBH;
-
- void handleOp(SkReader32* reader,
- DrawType op,
- uint32_t size,
+ void handleOp(SkReader32* reader,
+ DrawType op,
+ uint32_t size,
SkCanvas* canvas,
const SkMatrix& initialMatrix);
- const SkPicture::OperationList* getActiveOps(const SkCanvas* canvas);
- bool initIterator(SkPictureStateTree::Iterator* iter,
- SkCanvas* canvas,
- const SkPicture::OperationList *activeOpsList);
- static void StepIterator(SkPictureStateTree::Iterator* iter, SkReader32* reader);
- static void SkipIterTo(SkPictureStateTree::Iterator* iter,
- SkReader32* reader, uint32_t skipTo);
-
static DrawType ReadOpAndSize(SkReader32* reader, uint32_t* size);
class AutoResetOpID {
diff --git a/src/core/SkPictureRecord.cpp b/src/core/SkPictureRecord.cpp
index 5b28468898..16cb3b5a1b 100644
--- a/src/core/SkPictureRecord.cpp
+++ b/src/core/SkPictureRecord.cpp
@@ -6,10 +6,8 @@
*/
#include "SkPictureRecord.h"
-#include "SkBBoxHierarchy.h"
#include "SkDevice.h"
#include "SkPatchUtils.h"
-#include "SkPictureStateTree.h"
#include "SkPixelRef.h"
#include "SkRRect.h"
#include "SkTextBlob.h"
@@ -17,15 +15,6 @@
#define HEAP_BLOCK_SIZE 4096
-// If SK_RECORD_LITERAL_PICTURES is defined, record our inputs as literally as possible.
-// Otherwise, we can be clever and record faster equivalents. kBeClever is normally true.
-static const bool kBeClever =
-#ifdef SK_RECORD_LITERAL_PICTURES
- false;
-#else
- true;
-#endif
-
enum {
// just need a value that save or getSaveCount would never return
kNoInitialSave = -1,
@@ -40,12 +29,9 @@ static const uint32_t kSaveLayerWithBoundsSize = 4 * kUInt32Size + sizeof(SkRect
SkPictureRecord::SkPictureRecord(const SkISize& dimensions, uint32_t flags)
: INHERITED(dimensions.width(), dimensions.height())
- , fBoundingHierarchy(NULL)
- , fStateTree(NULL)
, fFlattenableHeap(HEAP_BLOCK_SIZE)
, fPaints(&fFlattenableHeap)
- , fRecordFlags(flags)
- , fOptsEnabled(kBeClever) {
+ , fRecordFlags(flags) {
fBitmapHeap = SkNEW(SkBitmapHeap);
fFlattenableHeap.setBitmapStorage(fBitmapHeap);
@@ -56,8 +42,6 @@ SkPictureRecord::SkPictureRecord(const SkISize& dimensions, uint32_t flags)
SkPictureRecord::~SkPictureRecord() {
SkSafeUnref(fBitmapHeap);
- SkSafeUnref(fBoundingHierarchy);
- SkSafeUnref(fStateTree);
fFlattenableHeap.setBitmapStorage(NULL);
fPictureRefs.unrefAll();
fTextBlobRefs.unrefAll();
@@ -211,15 +195,7 @@ bool SkPictureRecord::isDrawingToLayer() const {
return fFirstSavedLayerIndex != kNoSavedLayerIndex;
}
-/*
- * Read the op code from 'offset' in 'writer'.
- */
#ifdef SK_DEBUG
-static DrawType peek_op(SkWriter32* writer, size_t offset) {
- return (DrawType)(writer->readTAt<uint32_t>(offset) >> 24);
-}
-#endif
-
/*
* Read the op code from 'offset' in 'writer' and extract the size too.
*/
@@ -234,346 +210,7 @@ static DrawType peek_op_and_size(SkWriter32* writer, size_t offset, uint32_t* si
}
return (DrawType) op;
}
-
-// Is the supplied paint simply a color?
-static bool is_simple(const SkPaint& p) {
- intptr_t orAccum = (intptr_t)p.getPathEffect() |
- (intptr_t)p.getShader() |
- (intptr_t)p.getXfermode() |
- (intptr_t)p.getMaskFilter() |
- (intptr_t)p.getColorFilter() |
- (intptr_t)p.getRasterizer() |
- (intptr_t)p.getLooper() |
- (intptr_t)p.getImageFilter();
- return 0 == orAccum;
-}
-
-// CommandInfos are fed to the 'match' method and filled in with command
-// information.
-struct CommandInfo {
- DrawType fActualOp;
- uint32_t fOffset;
- uint32_t fSize;
-};
-
-/*
- * Attempt to match the provided pattern of commands starting at 'offset'
- * in the byte stream and stopping at the end of the stream. Upon success,
- * return true with all the pattern information filled out in the result
- * array (i.e., actual ops, offsets and sizes).
- * Note this method skips any NOOPs seen in the stream
- */
-static bool match(SkWriter32* writer, uint32_t offset,
- int* pattern, CommandInfo* result, int numCommands) {
- SkASSERT(offset < writer->bytesWritten());
-
- uint32_t curOffset = offset;
- uint32_t curSize = 0;
- int numMatched;
- for (numMatched = 0; numMatched < numCommands && curOffset < writer->bytesWritten(); ++numMatched) {
- DrawType op = peek_op_and_size(writer, curOffset, &curSize);
- while (NOOP == op) {
- curOffset += curSize;
- if (curOffset >= writer->bytesWritten()) {
- return false;
- }
- op = peek_op_and_size(writer, curOffset, &curSize);
- }
-
- if (kDRAW_BITMAP_FLAVOR == pattern[numMatched]) {
- if (DRAW_BITMAP != op && DRAW_BITMAP_MATRIX != op &&
- DRAW_BITMAP_NINE != op && DRAW_BITMAP_RECT_TO_RECT != op) {
- return false;
- }
- } else if (op != pattern[numMatched]) {
- return false;
- }
-
- result[numMatched].fActualOp = op;
- result[numMatched].fOffset = curOffset;
- result[numMatched].fSize = curSize;
-
- curOffset += curSize;
- }
-
- if (numMatched != numCommands) {
- return false;
- }
-
- if (curOffset < writer->bytesWritten()) {
- // Something else between the last command and the end of the stream
- return false;
- }
-
- return true;
-}
-
-// temporarily here to make code review easier
-static bool merge_savelayer_paint_into_drawbitmp(SkWriter32* writer,
- SkPaintDictionary* paintDict,
- const CommandInfo& saveLayerInfo,
- const CommandInfo& dbmInfo);
-
-/*
- * Restore has just been called (but not recorded), look back at the
- * matching save* and see if we are in the configuration:
- * SAVE_LAYER
- * DRAW_BITMAP|DRAW_BITMAP_MATRIX|DRAW_BITMAP_NINE|DRAW_BITMAP_RECT_TO_RECT
- * RESTORE
- * 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) {
- // back up to the save block
- // TODO: add a stack to track save*/restore offsets rather than searching backwards
- while (offset > 0) {
- offset = writer->readTAt<uint32_t>(offset);
- }
-
- int pattern[] = { SAVE_LAYER, kDRAW_BITMAP_FLAVOR, /* RESTORE */ };
- CommandInfo result[SK_ARRAY_COUNT(pattern)];
-
- if (!match(writer, -offset, pattern, result, SK_ARRAY_COUNT(pattern))) {
- return false;
- }
-
- if (kSaveLayerWithBoundsSize == result[0].fSize) {
- // The saveLayer's bound can offset where the dbm is drawn
- return false;
- }
-
- return merge_savelayer_paint_into_drawbitmp(writer, paintDict,
- result[0], result[1]);
-}
-
-/*
- * Convert the command code located at 'offset' to a NOOP. Leave the size
- * field alone so the NOOP can be skipped later.
- */
-static void convert_command_to_noop(SkWriter32* writer, uint32_t offset) {
- uint32_t command = writer->readTAt<uint32_t>(offset);
- writer->overwriteTAt(offset, (command & MASK_24) | (NOOP << 24));
-}
-
-/*
- * Attempt to merge the saveLayer's paint into the drawBitmap*'s paint.
- * Return true on success; false otherwise.
- */
-static bool merge_savelayer_paint_into_drawbitmp(SkWriter32* writer,
- SkPaintDictionary* paintDict,
- const CommandInfo& saveLayerInfo,
- const CommandInfo& dbmInfo) {
- SkASSERT(SAVE_LAYER == saveLayerInfo.fActualOp);
- SkASSERT(DRAW_BITMAP == dbmInfo.fActualOp ||
- DRAW_BITMAP_MATRIX == dbmInfo.fActualOp ||
- DRAW_BITMAP_NINE == dbmInfo.fActualOp ||
- DRAW_BITMAP_RECT_TO_RECT == dbmInfo.fActualOp);
-
- size_t dbmPaintOffset = getPaintOffset(dbmInfo.fActualOp, dbmInfo.fSize);
- size_t slPaintOffset = getPaintOffset(SAVE_LAYER, saveLayerInfo.fSize);
-
- // we have a match, now we need to get the paints involved
- uint32_t dbmPaintId = writer->readTAt<uint32_t>(dbmInfo.fOffset + dbmPaintOffset);
- uint32_t saveLayerPaintId = writer->readTAt<uint32_t>(saveLayerInfo.fOffset + slPaintOffset);
-
- if (0 == saveLayerPaintId) {
- // In this case the saveLayer/restore isn't needed at all - just kill the saveLayer
- // and signal the caller (by returning true) to not add the RESTORE op
- convert_command_to_noop(writer, saveLayerInfo.fOffset);
- return true;
- }
-
- if (0 == dbmPaintId) {
- // In this case just make the DBM* use the saveLayer's paint, kill the saveLayer
- // and signal the caller (by returning true) to not add the RESTORE op
- convert_command_to_noop(writer, saveLayerInfo.fOffset);
- writer->overwriteTAt(dbmInfo.fOffset + dbmPaintOffset, saveLayerPaintId);
- return true;
- }
-
- SkAutoTDelete<SkPaint> saveLayerPaint(paintDict->unflatten(saveLayerPaintId));
- if (NULL == saveLayerPaint.get() || !is_simple(*saveLayerPaint)) {
- return false;
- }
-
- // For this optimization we only fold the saveLayer and drawBitmapRect
- // together if the saveLayer's draw is simple (i.e., no fancy effects) and
- // and the only difference in the colors is that the saveLayer's can have
- // an alpha while the drawBitmapRect's is opaque.
- // TODO: it should be possible to fold them together even if they both
- // have different non-255 alphas
- SkColor layerColor = saveLayerPaint->getColor() | 0xFF000000; // force opaque
-
- SkAutoTDelete<SkPaint> dbmPaint(paintDict->unflatten(dbmPaintId));
- if (NULL == dbmPaint.get() || dbmPaint->getColor() != layerColor || !is_simple(*dbmPaint)) {
- return false;
- }
-
- SkColor newColor = SkColorSetA(dbmPaint->getColor(),
- SkColorGetA(saveLayerPaint->getColor()));
- dbmPaint->setColor(newColor);
-
- const SkFlatData* data = paintDict->findAndReturnFlat(*dbmPaint);
- if (NULL == data) {
- return false;
- }
-
- // kill the saveLayer and alter the DBMR2R's paint to be the modified one
- convert_command_to_noop(writer, saveLayerInfo.fOffset);
- writer->overwriteTAt(dbmInfo.fOffset + dbmPaintOffset, data->index());
- return true;
-}
-
-/*
- * Restore has just been called (but not recorded), look back at the
- * matching save* and see if we are in the configuration:
- * SAVE_LAYER (with NULL == bounds)
- * SAVE
- * CLIP_RECT
- * DRAW_BITMAP|DRAW_BITMAP_MATRIX|DRAW_BITMAP_NINE|DRAW_BITMAP_RECT_TO_RECT
- * RESTORE
- * RESTORE
- * where the saveLayer's color can be moved into the drawBitmap*'s paint
- */
-static bool remove_save_layer2(SkWriter32* writer, int32_t offset,
- SkPaintDictionary* paintDict) {
- // back up to the save block
- // TODO: add a stack to track save*/restore offsets rather than searching backwards
- while (offset > 0) {
- offset = writer->readTAt<uint32_t>(offset);
- }
-
- int pattern[] = { SAVE_LAYER, SAVE, CLIP_RECT, kDRAW_BITMAP_FLAVOR, RESTORE, /* RESTORE */ };
- CommandInfo result[SK_ARRAY_COUNT(pattern)];
-
- if (!match(writer, -offset, pattern, result, SK_ARRAY_COUNT(pattern))) {
- return false;
- }
-
- if (kSaveLayerWithBoundsSize == result[0].fSize) {
- // The saveLayer's bound can offset where the dbm is drawn
- return false;
- }
-
- return merge_savelayer_paint_into_drawbitmp(writer, paintDict,
- result[0], result[3]);
-}
-
-static bool is_drawing_op(DrawType op) {
-
- // FIXME: yuck. convert to a lookup table?
- return (op > CONCAT && op < ROTATE)
- || DRAW_DRRECT == op
- || DRAW_PATCH == op
- || DRAW_PICTURE_MATRIX_PAINT == op
- || DRAW_TEXT_BLOB == op;
-}
-
-/*
- * Restore has just been called (but not recorded), so look back at the
- * matching save(), and see if we can eliminate the pair of them, due to no
- * intervening matrix/clip calls.
- *
- * If so, update the writer and return true, in which case we won't even record
- * the restore() call. If we still need the restore(), return false.
- */
-static bool collapse_save_clip_restore(SkWriter32* writer, int32_t offset,
- SkPaintDictionary* paintDict) {
- int32_t restoreOffset = (int32_t)writer->bytesWritten();
-
- // back up to the save block
- while (offset > 0) {
- offset = writer->readTAt<uint32_t>(offset);
- }
-
- // now offset points to a save
- offset = -offset;
- uint32_t opSize;
- DrawType op = peek_op_and_size(writer, offset, &opSize);
- if (SAVE_LAYER == op) {
- // not ready to cull these out yet (mrr)
- return false;
- }
- SkASSERT(SAVE == op);
- SkASSERT(kSaveSize == opSize);
-
- // Walk forward until we get back to either a draw-verb (abort) or we hit
- // our restore (success).
- int32_t saveOffset = offset;
-
- offset += opSize;
- while (offset < restoreOffset) {
- op = peek_op_and_size(writer, offset, &opSize);
- if (is_drawing_op(op) || (SAVE_LAYER == op)) {
- // drawing verb, abort
- return false;
- }
- offset += opSize;
- }
-
- writer->rewindToOffset(saveOffset);
- return true;
-}
-
-typedef bool (*PictureRecordOptProc)(SkWriter32* writer, int32_t offset,
- SkPaintDictionary* paintDict);
-enum PictureRecordOptType {
- kRewind_OptType, // Optimization rewinds the command stream
- kCollapseSaveLayer_OptType, // Optimization eliminates a save/restore pair
-};
-
-enum PictureRecordOptFlags {
- kSkipIfBBoxHierarchy_Flag = 0x1, // Optimization should be skipped if the
- // SkPicture has a bounding box hierarchy.
- kRescindLastSave_Flag = 0x2,
- kRescindLastSaveLayer_Flag = 0x4,
-};
-
-struct PictureRecordOpt {
- PictureRecordOptProc fProc;
- PictureRecordOptType fType;
- unsigned fFlags;
-};
-/*
- * A list of the optimizations that are tried upon seeing a restore
- * TODO: add a real API for such optimizations
- * Add the ability to fire optimizations on any op (not just RESTORE)
- */
-static const PictureRecordOpt gPictureRecordOpts[] = {
- // 'collapse_save_clip_restore' is skipped if there is a BBoxHierarchy
- // because it is redundant with the state traversal optimization in
- // SkPictureStateTree, and applying the optimization introduces significant
- // record time overhead because it requires rewinding contents that were
- // recorded into the BBoxHierarchy.
- { collapse_save_clip_restore, kRewind_OptType,
- kSkipIfBBoxHierarchy_Flag|kRescindLastSave_Flag },
- { remove_save_layer1, kCollapseSaveLayer_OptType, kRescindLastSaveLayer_Flag },
- { remove_save_layer2, kCollapseSaveLayer_OptType, kRescindLastSaveLayer_Flag }
-};
-
-// This is called after an optimization has been applied to the command stream
-// in order to adjust the contents and state of the bounding box hierarchy and
-// state tree to reflect the optimization.
-static void apply_optimization_to_bbh(PictureRecordOptType opt, SkPictureStateTree* stateTree,
- SkBBoxHierarchy* boundingHierarchy) {
- switch (opt) {
- case kCollapseSaveLayer_OptType:
- if (stateTree) {
- stateTree->saveCollapsed();
- }
- break;
- case kRewind_OptType:
- if (boundingHierarchy) {
- boundingHierarchy->rewindInserts();
- }
- // Note: No need to touch the state tree for this to work correctly.
- // Unused branches do not burden the playback, and pruning the tree
- // would be O(N^2), so it is best to leave it alone.
- break;
- default:
- SkASSERT(0);
- }
-}
+#endif//SK_DEBUG
void SkPictureRecord::willRestore() {
// FIXME: SkDeferredCanvas needs to be refactored to respect
@@ -592,31 +229,7 @@ void SkPictureRecord::willRestore() {
fFirstSavedLayerIndex = kNoSavedLayerIndex;
}
- size_t opt = 0;
- if (fOptsEnabled) {
- for (opt = 0; opt < SK_ARRAY_COUNT(gPictureRecordOpts); ++opt) {
- if (0 != (gPictureRecordOpts[opt].fFlags & kSkipIfBBoxHierarchy_Flag)
- && fBoundingHierarchy) {
- continue;
- }
- if ((*gPictureRecordOpts[opt].fProc)(&fWriter, fRestoreOffsetStack.top(), &fPaints)) {
- // Some optimization fired so don't add the RESTORE
- apply_optimization_to_bbh(gPictureRecordOpts[opt].fType,
- fStateTree, fBoundingHierarchy);
- if (gPictureRecordOpts[opt].fFlags & kRescindLastSave_Flag) {
- fContentInfo.rescindLastSave();
- } else if (gPictureRecordOpts[opt].fFlags & kRescindLastSaveLayer_Flag) {
- fContentInfo.rescindLastSaveLayer();
- }
- break;
- }
- }
- }
-
- if (!fOptsEnabled || SK_ARRAY_COUNT(gPictureRecordOpts) == opt) {
- // No optimization fired so add the RESTORE
- this->recordRestore();
- }
+ this->recordRestore();
fRestoreOffsetStack.pop();
@@ -905,19 +518,13 @@ void SkPictureRecord::drawRect(const SkRect& rect, const SkPaint& paint) {
}
void SkPictureRecord::drawRRect(const SkRRect& rrect, const SkPaint& paint) {
- if (rrect.isRect() && kBeClever) {
- this->SkPictureRecord::drawRect(rrect.getBounds(), paint);
- } else if (rrect.isOval() && kBeClever) {
- this->SkPictureRecord::drawOval(rrect.getBounds(), paint);
- } else {
- // op + paint index + rrect
- size_t size = 2 * kUInt32Size + SkRRect::kSizeInMemory;
- size_t initialOffset = this->addDraw(DRAW_RRECT, &size);
- SkASSERT(initialOffset+getPaintOffset(DRAW_RRECT, size) == fWriter.bytesWritten());
- this->addPaint(paint);
- this->addRRect(rrect);
- this->validate(initialOffset, size);
- }
+ // op + paint index + rrect
+ size_t size = 2 * kUInt32Size + SkRRect::kSizeInMemory;
+ size_t initialOffset = this->addDraw(DRAW_RRECT, &size);
+ SkASSERT(initialOffset+getPaintOffset(DRAW_RRECT, size) == fWriter.bytesWritten());
+ this->addPaint(paint);
+ this->addRRect(rrect);
+ this->validate(initialOffset, size);
}
void SkPictureRecord::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
@@ -946,10 +553,6 @@ void SkPictureRecord::drawPath(const SkPath& path, const SkPaint& paint) {
void SkPictureRecord::drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top,
const SkPaint* paint = NULL) {
- if (bitmap.drawsNothing() && kBeClever) {
- return;
- }
-
// op + paint index + bitmap index + left + top
size_t size = 3 * kUInt32Size + 2 * sizeof(SkScalar);
size_t initialOffset = this->addDraw(DRAW_BITMAP, &size);
@@ -964,10 +567,6 @@ void SkPictureRecord::drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar
void SkPictureRecord::drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src,
const SkRect& dst, const SkPaint* paint,
DrawBitmapRectFlags flags) {
- if (bitmap.drawsNothing() && kBeClever) {
- return;
- }
-
// id + paint index + bitmap index + bool for 'src' + flags
size_t size = 5 * kUInt32Size;
if (src) {
@@ -988,10 +587,6 @@ void SkPictureRecord::drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect*
void SkPictureRecord::drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& matrix,
const SkPaint* paint) {
- if (bitmap.drawsNothing() && kBeClever) {
- return;
- }
-
// id + paint index + bitmap index + matrix
size_t size = 3 * kUInt32Size + matrix.writeToMemory(NULL);
size_t initialOffset = this->addDraw(DRAW_BITMAP_MATRIX, &size);
@@ -1004,10 +599,6 @@ void SkPictureRecord::drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& m
void SkPictureRecord::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
const SkRect& dst, const SkPaint* paint) {
- if (bitmap.drawsNothing() && kBeClever) {
- return;
- }
-
// op + paint index + bitmap id + center + dst rect
size_t size = 3 * kUInt32Size + sizeof(center) + sizeof(dst);
size_t initialOffset = this->addDraw(DRAW_BITMAP_NINE, &size);
@@ -1021,10 +612,6 @@ void SkPictureRecord::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& cent
void SkPictureRecord::drawSprite(const SkBitmap& bitmap, int left, int top,
const SkPaint* paint = NULL) {
- if (bitmap.drawsNothing() && kBeClever) {
- return;
- }
-
// op + paint index + bitmap index + left + top
size_t size = 5 * kUInt32Size;
size_t initialOffset = this->addDraw(DRAW_SPRITE, &size);
@@ -1036,160 +623,52 @@ void SkPictureRecord::drawSprite(const SkBitmap& bitmap, int left, int top,
this->validate(initialOffset, size);
}
-void SkPictureRecord::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, SK_Scalar1, metrics.fBottom);
- (void)paint.computeFastBounds(bounds, &bounds);
- topbot[0] = bounds.fTop;
- topbot[1] = bounds.fBottom;
-}
-
-void SkPictureRecord::addFontMetricsTopBottom(const SkPaint& paint, const SkFlatData& flat,
- SkScalar minY, SkScalar maxY) {
- WriteTopBot(paint, flat);
- this->addScalar(flat.topBot()[0] + minY);
- this->addScalar(flat.topBot()[1] + maxY);
-}
-
void SkPictureRecord::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
const SkPaint& paint) {
- bool fast = !paint.isVerticalText() && paint.canComputeFastBounds() && kBeClever;
-
// op + paint index + length + 'length' worth of chars + x + y
size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + 2 * sizeof(SkScalar);
- if (fast) {
- size += 2 * sizeof(SkScalar); // + top & bottom
- }
- DrawType op = fast ? DRAW_TEXT_TOP_BOTTOM : DRAW_TEXT;
+ DrawType op = DRAW_TEXT;
size_t initialOffset = this->addDraw(op, &size);
SkASSERT(initialOffset+getPaintOffset(op, size) == fWriter.bytesWritten());
- const SkFlatData* flatPaintData = addPaint(paint);
- SkASSERT(flatPaintData);
+ this->addPaint(paint);
this->addText(text, byteLength);
this->addScalar(x);
this->addScalar(y);
- if (fast) {
- this->addFontMetricsTopBottom(paint, *flatPaintData, y, y);
- }
this->validate(initialOffset, size);
}
void SkPictureRecord::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
const SkPaint& paint) {
int points = paint.countText(text, byteLength);
- if (0 == points)
- return;
- bool canUseDrawH = true;
- SkScalar minY = pos[0].fY;
- SkScalar maxY = pos[0].fY;
- // check if the caller really should have used drawPosTextH()
- {
- const SkScalar firstY = pos[0].fY;
- for (int index = 1; index < points; index++) {
- if (pos[index].fY != firstY) {
- canUseDrawH = false;
- if (pos[index].fY < minY) {
- minY = pos[index].fY;
- } else if (pos[index].fY > maxY) {
- maxY = pos[index].fY;
- }
- }
- }
- }
-
- bool fastBounds = !paint.isVerticalText() && paint.canComputeFastBounds() && kBeClever;
- bool fast = canUseDrawH && fastBounds && kBeClever;
+ // op + paint index + length + 'length' worth of data + num points + x&y point data
+ size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + kUInt32Size + points * sizeof(SkPoint);
- // op + paint index + length + 'length' worth of data + num points
- size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + 1 * kUInt32Size;
- if (canUseDrawH) {
- if (fast) {
- size += 2 * sizeof(SkScalar); // + top & bottom
- }
- // + y-pos + actual x-point data
- size += sizeof(SkScalar) + points * sizeof(SkScalar);
- } else {
- // + x&y point data
- size += points * sizeof(SkPoint);
- if (fastBounds) {
- size += 2 * sizeof(SkScalar); // + top & bottom
- }
- }
+ DrawType op = DRAW_POS_TEXT;
- DrawType op;
- if (fast) {
- op = DRAW_POS_TEXT_H_TOP_BOTTOM;
- } else if (canUseDrawH) {
- op = DRAW_POS_TEXT_H;
- } else if (fastBounds) {
- op = DRAW_POS_TEXT_TOP_BOTTOM;
- } else {
- op = DRAW_POS_TEXT;
- }
size_t initialOffset = this->addDraw(op, &size);
SkASSERT(initialOffset+getPaintOffset(op, size) == fWriter.bytesWritten());
- const SkFlatData* flatPaintData = this->addPaint(paint);
- SkASSERT(flatPaintData);
+ this->addPaint(paint);
this->addText(text, byteLength);
this->addInt(points);
-
- if (canUseDrawH) {
- if (fast) {
- this->addFontMetricsTopBottom(paint, *flatPaintData, pos[0].fY, pos[0].fY);
- }
- this->addScalar(pos[0].fY);
- SkScalar* xptr = (SkScalar*)fWriter.reserve(points * sizeof(SkScalar));
- for (int index = 0; index < points; index++)
- *xptr++ = pos[index].fX;
- } else {
- fWriter.writeMul4(pos, points * sizeof(SkPoint));
- if (fastBounds) {
- this->addFontMetricsTopBottom(paint, *flatPaintData, minY, maxY);
- }
- }
+ fWriter.writeMul4(pos, points * sizeof(SkPoint));
this->validate(initialOffset, size);
}
void SkPictureRecord::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
SkScalar constY, const SkPaint& paint) {
- const SkFlatData* flatPaintData = this->getFlatPaintData(paint);
- this->drawPosTextHImpl(text, byteLength, xpos, constY, paint, flatPaintData);
-}
-
-void SkPictureRecord::drawPosTextHImpl(const void* text, size_t byteLength,
- const SkScalar xpos[], SkScalar constY,
- const SkPaint& paint, const SkFlatData* flatPaintData) {
int points = paint.countText(text, byteLength);
- if (0 == points && kBeClever) {
- return;
- }
-
- bool fast = !paint.isVerticalText() && paint.canComputeFastBounds() && kBeClever;
// op + paint index + length + 'length' worth of data + num points
size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + 1 * kUInt32Size;
- if (fast) {
- size += 2 * sizeof(SkScalar); // + top & bottom
- }
// + y + the actual points
size += 1 * kUInt32Size + points * sizeof(SkScalar);
- size_t initialOffset = this->addDraw(fast ? DRAW_POS_TEXT_H_TOP_BOTTOM : DRAW_POS_TEXT_H,
- &size);
- SkASSERT(flatPaintData);
- this->addFlatPaint(flatPaintData);
+ size_t initialOffset = this->addDraw(DRAW_POS_TEXT_H, &size);
+ this->addPaint(paint);
this->addText(text, byteLength);
this->addInt(points);
-
- if (fast) {
- this->addFontMetricsTopBottom(paint, *flatPaintData, constY, constY);
- }
this->addScalar(constY);
fWriter.writeMul4(xpos, points * sizeof(SkScalar));
this->validate(initialOffset, size);
@@ -1331,13 +810,13 @@ void SkPictureRecord::onDrawPatch(const SkPoint cubics[12], const SkColor colors
size += kUInt32Size;
}
}
-
+
size_t initialOffset = this->addDraw(DRAW_PATCH, &size);
SkASSERT(initialOffset+getPaintOffset(DRAW_PATCH, size) == fWriter.bytesWritten());
this->addPaint(paint);
this->addPatch(cubics);
this->addInt(flag);
-
+
// write optional parameters
if (colors) {
fWriter.write(colors, SkPatchUtils::kNumCorners * sizeof(SkColor));
@@ -1409,14 +888,6 @@ void SkPictureRecord::onPopCull() {
uint32_t cullSkipOffset = fCullOffsetStack.top();
fCullOffsetStack.pop();
- // Collapse empty push/pop pairs.
- if ((size_t)(cullSkipOffset + kUInt32Size) == fWriter.bytesWritten() && kBeClever) {
- SkASSERT(fWriter.bytesWritten() >= kPushCullOpSize);
- SkASSERT(PUSH_CULL == peek_op(&fWriter, fWriter.bytesWritten() - kPushCullOpSize));
- fWriter.rewindToOffset(fWriter.bytesWritten() - kPushCullOpSize);
- return;
- }
-
// op only
size_t size = kUInt32Size;
size_t initialOffset = this->addDraw(POP_CULL, &size);
@@ -1447,21 +918,16 @@ void SkPictureRecord::addMatrix(const SkMatrix& matrix) {
fWriter.writeMatrix(matrix);
}
-const SkFlatData* SkPictureRecord::getFlatPaintData(const SkPaint& paint) {
- return fPaints.findAndReturnFlat(paint);
-}
-
-const SkFlatData* SkPictureRecord::addPaintPtr(const SkPaint* paint) {
+void SkPictureRecord::addPaintPtr(const SkPaint* paint) {
fContentInfo.onAddPaintPtr(paint);
- const SkFlatData* data = paint ? getFlatPaintData(*paint) : NULL;
- this->addFlatPaint(data);
- return data;
-}
-
-void SkPictureRecord::addFlatPaint(const SkFlatData* flatPaint) {
- int index = flatPaint ? flatPaint->index() : 0;
- this->addInt(index);
+ if (paint) {
+ const SkFlatData* flat = fPaints.findAndReturnFlat(*paint);
+ SkASSERT(flat && flat->index() != 0);
+ this->addInt(flat->index());
+ } else {
+ this->addInt(0);
+ }
}
int SkPictureRecord::addPathToHeap(const SkPath& path) {
diff --git a/src/core/SkPictureRecord.h b/src/core/SkPictureRecord.h
index f8895c950e..ca2aecd678 100644
--- a/src/core/SkPictureRecord.h
+++ b/src/core/SkPictureRecord.h
@@ -17,9 +17,6 @@
#include "SkTemplates.h"
#include "SkWriter32.h"
-class SkBBoxHierarchy;
-class SkPictureStateTree;
-
// These macros help with packing and unpacking a single byte value and
// a 3 byte value into/out of a uint32_t
#define MASK_24 0x00FFFFFF
@@ -64,9 +61,6 @@ public:
virtual void endCommentGroup() SK_OVERRIDE;
virtual bool isDrawingToLayer() const SK_OVERRIDE;
- void addFontMetricsTopBottom(const SkPaint& paint, const SkFlatData&,
- SkScalar minY, SkScalar maxY);
-
const SkTDArray<const SkPicture* >& getPictureRefs() const {
return fPictureRefs;
}
@@ -108,10 +102,6 @@ public:
void beginRecording();
void endRecording();
- void internalOnly_EnableOpts(bool optsEnabled) {
- fOptsEnabled = optsEnabled;
- }
-
protected:
void addNoOp();
@@ -170,9 +160,8 @@ private:
// The command at 'offset' in the skp uses the specified bitmap
int addBitmap(const SkBitmap& bitmap);
void addMatrix(const SkMatrix& matrix);
- const SkFlatData* addPaint(const SkPaint& paint) { return this->addPaintPtr(&paint); }
- const SkFlatData* addPaintPtr(const SkPaint* paint);
- void addFlatPaint(const SkFlatData* flatPaint);
+ void addPaint(const SkPaint& paint) { this->addPaintPtr(&paint); }
+ void addPaintPtr(const SkPaint* paint);
void addPatch(const SkPoint cubics[12]);
void addPath(const SkPath& path);
void addPicture(const SkPicture* picture);
@@ -220,7 +209,7 @@ protected:
const SkMatrix* matrix, const SkPaint&) SK_OVERRIDE;
virtual void onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
const SkPaint& paint) SK_OVERRIDE;
-
+
virtual void onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
const SkPoint texCoords[4], SkXfermode* xmode,
const SkPaint& paint) SK_OVERRIDE;
@@ -232,27 +221,6 @@ protected:
virtual void onDrawPicture(const SkPicture*, const SkMatrix*, const SkPaint*) SK_OVERRIDE;
- // 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]);
-
- // Make sure that flat has fTopBot written.
- static void WriteTopBot(const SkPaint& paint, const SkFlatData& flat) {
- if (!flat.isTopBotWritten()) {
- ComputeFontMetricsTopBottom(paint, flat.writableTopBot());
- SkASSERT(flat.isTopBotWritten());
- }
- }
- // Will return a cached version when possible.
- const SkFlatData* getFlatPaintData(const SkPaint& paint);
- /**
- * SkBBoxRecord::drawPosTextH gets a flat paint and uses it,
- * then it calls this, using the extra parameter, to avoid duplication.
- */
- void drawPosTextHImpl(const void* text, size_t byteLength,
- const SkScalar xpos[], SkScalar constY,
- const SkPaint& paint, const SkFlatData* flatPaintData);
-
int addPathToHeap(const SkPath& path); // does not write to ops stream
// These entry points allow the writing of matrices, clips, saves &
@@ -269,11 +237,6 @@ protected:
void recordSaveLayer(const SkRect* bounds, const SkPaint* paint, SaveFlags flags);
void recordRestore(bool fillInSkips = true);
- // These are set to NULL in our constructor, but may be changed by
- // subclasses, in which case they will be SkSafeUnref'd in our destructor.
- SkBBoxHierarchy* fBoundingHierarchy;
- SkPictureStateTree* fStateTree;
-
// Allocated in the constructor and managed by this class.
SkBitmapHeap* fBitmapHeap;
@@ -292,7 +255,6 @@ private:
SkTDArray<const SkTextBlob*> fTextBlobRefs;
uint32_t fRecordFlags;
- bool fOptsEnabled;
int fInitialSaveCount;
friend class SkPictureData; // for SkPictureData's SkPictureRecord-based constructor
diff --git a/src/core/SkPictureRecorder.cpp b/src/core/SkPictureRecorder.cpp
index 43111a5c6c..81c39e36f0 100644
--- a/src/core/SkPictureRecorder.cpp
+++ b/src/core/SkPictureRecorder.cpp
@@ -5,7 +5,6 @@
* found in the LICENSE file.
*/
-#include "SkBBoxHierarchyRecord.h"
#include "SkPictureRecord.h"
#include "SkPictureRecorder.h"
#include "SkRecord.h"
@@ -26,20 +25,11 @@ SkCanvas* SkPictureRecorder::beginRecording(SkScalar width, SkScalar height,
SkCanvas* SkPictureRecorder::DEPRECATED_beginRecording(SkScalar width, SkScalar height,
SkBBHFactory* bbhFactory /* = NULL */,
uint32_t recordFlags /* = 0 */) {
+ SkASSERT(!bbhFactory); // No longer suppported with this backend.
+
fCullWidth = width;
fCullHeight = height;
-
- const SkISize size = SkISize::Make(width, height);
-
- if (bbhFactory) {
- // We don't need to hold a ref on the BBH ourselves, but might as well for
- // consistency with EXPERIMENTAL_beginRecording(), which does need to.
- fBBH.reset((*bbhFactory)(width, height));
- SkASSERT(fBBH.get());
- fPictureRecord.reset(SkNEW_ARGS(SkBBoxHierarchyRecord, (size, recordFlags, fBBH.get())));
- } else {
- fPictureRecord.reset(SkNEW_ARGS(SkPictureRecord, (size, recordFlags)));
- }
+ fPictureRecord.reset(SkNEW_ARGS(SkPictureRecord, (SkISize::Make(width, height), recordFlags)));
fPictureRecord->beginRecording();
return this->getRecordingCanvas();
@@ -85,12 +75,6 @@ SkPicture* SkPictureRecorder::endRecording() {
return picture;
}
-void SkPictureRecorder::internalOnly_EnableOpts(bool enableOpts) {
- if (fPictureRecord.get()) {
- fPictureRecord->internalOnly_EnableOpts(enableOpts);
- }
-}
-
void SkPictureRecorder::partialReplay(SkCanvas* canvas) const {
if (NULL == canvas) {
return;
diff --git a/src/core/SkPictureStateTree.cpp b/src/core/SkPictureStateTree.cpp
deleted file mode 100644
index 704a04ebee..0000000000
--- a/src/core/SkPictureStateTree.cpp
+++ /dev/null
@@ -1,218 +0,0 @@
-
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "SkPictureStateTree.h"
-#include "SkCanvas.h"
-
-SkPictureStateTree::SkPictureStateTree()
- : fAlloc(2048)
- , fLastRestoredNode(NULL)
- , fStateStack(sizeof(Draw), 16) {
- fRootMatrix.reset();
- fRoot.fParent = NULL;
- fRoot.fMatrix = &fRootMatrix;
- fRoot.fFlags = Node::kSave_Flag;
- fRoot.fOffset = 0;
- fRoot.fLevel = 0;
- fCurrentState.fNode = &fRoot;
- fCurrentState.fMatrix = &fRootMatrix;
- *static_cast<Draw*>(fStateStack.push_back()) = fCurrentState;
-}
-
-SkPictureStateTree::~SkPictureStateTree() {
-}
-
-SkPictureStateTree::Draw* SkPictureStateTree::appendDraw(size_t offset) {
- Draw* draw = static_cast<Draw*>(fAlloc.allocThrow(sizeof(Draw)));
- *draw = fCurrentState;
- draw->fOffset = SkToU32(offset);
- return draw;
-}
-
-void SkPictureStateTree::appendSave() {
- *static_cast<Draw*>(fStateStack.push_back()) = fCurrentState;
- fCurrentState.fNode->fFlags |= Node::kSave_Flag;
-}
-
-void SkPictureStateTree::appendSaveLayer(size_t offset) {
- *static_cast<Draw*>(fStateStack.push_back()) = fCurrentState;
- this->appendNode(offset);
- fCurrentState.fNode->fFlags |= Node::kSaveLayer_Flag;
-}
-
-void SkPictureStateTree::saveCollapsed() {
- SkASSERT(fLastRestoredNode);
- SkASSERT(SkToBool(fLastRestoredNode->fFlags & \
- (Node::kSaveLayer_Flag | Node::kSave_Flag)));
- SkASSERT(fLastRestoredNode->fParent == fCurrentState.fNode);
- // The structure of the tree is not modified here. We just turn off
- // the save or saveLayer flag to prevent the iterator from making state
- // changing calls on the playback canvas when traversing a save or
- // saveLayerNode node.
- fLastRestoredNode->fFlags = 0;
-}
-
-void SkPictureStateTree::appendRestore() {
- fLastRestoredNode = fCurrentState.fNode;
- fCurrentState = *static_cast<Draw*>(fStateStack.back());
- fStateStack.pop_back();
-}
-
-void SkPictureStateTree::appendTransform(const SkMatrix& trans) {
- SkMatrix* m = static_cast<SkMatrix*>(fAlloc.allocThrow(sizeof(SkMatrix)));
- *m = trans;
- fCurrentState.fMatrix = m;
-}
-
-void SkPictureStateTree::appendClip(size_t offset) {
- this->appendNode(offset);
-}
-
-void SkPictureStateTree::initIterator(SkPictureStateTree::Iterator* iter,
- const SkTDArray<void*>& draws,
- SkCanvas* canvas) {
- iter->init(draws, canvas, &fRoot);
-}
-
-void SkPictureStateTree::appendNode(size_t offset) {
- Node* n = static_cast<Node*>(fAlloc.allocThrow(sizeof(Node)));
- n->fOffset = SkToU32(offset);
- n->fFlags = 0;
- n->fParent = fCurrentState.fNode;
- n->fLevel = fCurrentState.fNode->fLevel + 1;
- n->fMatrix = fCurrentState.fMatrix;
- fCurrentState.fNode = n;
-}
-
-void SkPictureStateTree::Iterator::init(const SkTDArray<void*>& draws, SkCanvas* canvas, Node* root) {
- SkASSERT(!fValid);
- fDraws = &draws;
- fCanvas = canvas;
- fCurrentNode = root;
- fPlaybackMatrix = canvas->getTotalMatrix();
- fCurrentMatrix = NULL;
- fPlaybackIndex = 0;
- fSave = false;
- fValid = true;
-}
-
-void SkPictureStateTree::Iterator::setCurrentMatrix(const SkMatrix* matrix) {
- SkASSERT(matrix);
-
- if (matrix == fCurrentMatrix) {
- return;
- }
-
- // The matrix is in recording space, but we also inherit
- // a playback matrix from out target canvas.
- SkMatrix m = *matrix;
- m.postConcat(fPlaybackMatrix);
- fCanvas->setMatrix(m);
- fCurrentMatrix = matrix;
-}
-
-uint32_t SkPictureStateTree::Iterator::finish() {
- if (fCurrentNode->fFlags & Node::kSaveLayer_Flag) {
- fCanvas->restore();
- }
-
- for (fCurrentNode = fCurrentNode->fParent; fCurrentNode;
- fCurrentNode = fCurrentNode->fParent) {
- // Note: we call restore() twice when both flags are set.
- if (fCurrentNode->fFlags & Node::kSave_Flag) {
- fCanvas->restore();
- }
- if (fCurrentNode->fFlags & Node::kSaveLayer_Flag) {
- fCanvas->restore();
- }
- }
-
- fCanvas->setMatrix(fPlaybackMatrix);
- fCurrentMatrix = NULL;
- return kDrawComplete;
-}
-
-uint32_t SkPictureStateTree::Iterator::nextDraw() {
- SkASSERT(this->isValid());
- if (fPlaybackIndex >= fDraws->count()) {
- return this->finish();
- }
-
- Draw* draw = static_cast<Draw*>((*fDraws)[fPlaybackIndex]);
- Node* targetNode = draw->fNode;
-
- if (fSave) {
- fCanvas->save();
- fSave = false;
- }
-
- if (fCurrentNode != targetNode) {
- // If we're not at the target and we don't have a list of nodes to get there, we need to
- // figure out the path from our current node, to the target
- if (fNodes.count() == 0) {
- // Trace back up to a common ancestor, restoring to get our current state to match that
- // of the ancestor, and saving a list of nodes whose state we need to apply to get to
- // the target (we can restore up to the ancestor immediately, but we'll need to return
- // an offset for each node on the way down to the target, to apply the desired clips and
- // saveLayers, so it may take several draw() calls before the next draw actually occurs)
- Node* tmp = fCurrentNode;
- Node* ancestor = targetNode;
- while (tmp != ancestor) {
- uint16_t currentLevel = tmp->fLevel;
- uint16_t targetLevel = ancestor->fLevel;
- if (currentLevel >= targetLevel) {
- if (tmp != fCurrentNode && tmp->fFlags & Node::kSave_Flag) {
- fCanvas->restore();
- // restore() may change the matrix, so we need to reapply.
- fCurrentMatrix = NULL;
- }
- if (tmp->fFlags & Node::kSaveLayer_Flag) {
- fCanvas->restore();
- // restore() may change the matrix, so we need to reapply.
- fCurrentMatrix = NULL;
- }
- tmp = tmp->fParent;
- }
- if (currentLevel <= targetLevel) {
- fNodes.push(ancestor);
- ancestor = ancestor->fParent;
- }
- }
-
- if (ancestor->fFlags & Node::kSave_Flag) {
- if (fCurrentNode != ancestor) {
- fCanvas->restore();
- // restore() may change the matrix, so we need to reapply.
- fCurrentMatrix = NULL;
- }
- if (targetNode != ancestor) {
- fCanvas->save();
- }
- }
- fCurrentNode = ancestor;
- }
-
- // If we're not at the target node yet, we'll need to return an offset to make the caller
- // apply the next clip or saveLayer.
- if (fCurrentNode != targetNode) {
- uint32_t offset = fNodes.top()->fOffset;
- fCurrentNode = fNodes.top();
- fSave = fCurrentNode != targetNode && fCurrentNode->fFlags & Node::kSave_Flag;
- fNodes.pop();
- this->setCurrentMatrix(fCurrentNode->fMatrix);
- return offset;
- }
- }
-
- // If we got this far, the clip/saveLayer state is all set, so we can proceed to set the matrix
- // for the draw, and return its offset.
- this->setCurrentMatrix(draw->fMatrix);
-
- ++fPlaybackIndex;
- return draw->fOffset;
-}
diff --git a/src/core/SkPictureStateTree.h b/src/core/SkPictureStateTree.h
deleted file mode 100644
index 15bb02f354..0000000000
--- a/src/core/SkPictureStateTree.h
+++ /dev/null
@@ -1,162 +0,0 @@
-
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef SkPictureStateTree_DEFINED
-#define SkPictureStateTree_DEFINED
-
-#include "SkTDArray.h"
-#include "SkChunkAlloc.h"
-#include "SkDeque.h"
-#include "SkMatrix.h"
-#include "SkRefCnt.h"
-
-class SkCanvas;
-
-/**
- * Provides an interface that, given a sequence of draws into an SkPicture with corresponding
- * offsets, allows for playback of an arbitrary subset of the draws (note that Z-order is only
- * guaranteed if the draws are explicitly sorted).
- */
-class SkPictureStateTree : public SkRefCnt {
-private:
- struct Node;
-public:
- SK_DECLARE_INST_COUNT(SkPictureStateTree)
-
- /**
- * A draw call, stores offset into command buffer, a pointer to the matrix, and a pointer to
- * the node in the tree that corresponds to its clip/layer state
- */
- struct Draw {
- SkMatrix* fMatrix;
- Node* fNode;
- uint32_t fOffset;
- bool operator<(const Draw& other) const { return fOffset < other.fOffset; }
- };
-
- class Iterator;
-
- SkPictureStateTree();
- ~SkPictureStateTree();
-
- /**
- * Creates and returns a struct representing a draw at the given offset.
- */
- Draw* appendDraw(size_t offset);
-
- /**
- * Given a list of draws, and a canvas, initialize an iterator that produces the correct
- * sequence of offsets into the command buffer to carry out those calls with correct
- * matrix/clip state. This handles saves/restores, and does all necessary matrix setup.
- */
- void initIterator(SkPictureStateTree::Iterator* iter,
- const SkTDArray<void*>& draws,
- SkCanvas* canvas);
-
- void appendSave();
- void appendSaveLayer(size_t offset);
- void appendRestore();
- void appendTransform(const SkMatrix& trans);
- void appendClip(size_t offset);
-
- /**
- * Call this immediately after an appendRestore call that is associated
- * a save or saveLayer that was removed from the command stream
- * due to a command pattern optimization in SkPicture.
- */
- void saveCollapsed();
-
- /**
- * Playback helper
- */
- class Iterator {
- public:
- /** Returns the next op offset needed to create the drawing state
- required by the queued up draw operation or the offset of the queued
- up draw operation itself. In the latter case, the next draw operation
- will move into the queued up slot.
- It retuns kDrawComplete when done.
- TODO: this might be better named nextOp
- */
- uint32_t nextDraw();
- static const uint32_t kDrawComplete = SK_MaxU32;
- Iterator() : fValid(false) { }
- bool isValid() const { return fValid; }
-
- private:
- void init(const SkTDArray<void*>& draws, SkCanvas* canvas, Node* root);
-
- void setCurrentMatrix(const SkMatrix*);
-
- // The draws this iterator is associated with
- const SkTDArray<void*>* fDraws;
-
- // canvas this is playing into (so we can insert saves/restores as necessary)
- SkCanvas* fCanvas;
-
- // current state node
- Node* fCurrentNode;
-
- // List of nodes whose state we need to apply to reach TargetNode
- SkTDArray<Node*> fNodes;
-
- // The matrix of the canvas we're playing back into
- SkMatrix fPlaybackMatrix;
-
- // Cache of current matrix, so we can avoid redundantly setting it
- const SkMatrix* fCurrentMatrix;
-
- // current position in the array of draws
- int fPlaybackIndex;
- // Whether or not we need to do a save next iteration
- bool fSave;
-
- // Whether or not this is a valid iterator (the default public constructor sets this false)
- bool fValid;
-
- uint32_t finish();
-
- friend class SkPictureStateTree;
- };
-
-private:
-
- void appendNode(size_t offset);
-
- SkChunkAlloc fAlloc;
- // Needed by saveCollapsed() because nodes do not currently store
- // references to their children. If they did, we could just retrieve the
- // last added child.
- Node* fLastRestoredNode;
-
- // The currently active state
- Draw fCurrentState;
- // A stack of states for tracking save/restores
- SkDeque fStateStack;
-
- // Represents a notable piece of state that requires an offset into the command buffer,
- // corresponding to a clip/saveLayer/etc call, to apply.
- struct Node {
- Node* fParent;
- uint32_t fOffset;
- uint16_t fLevel;
- uint16_t fFlags;
- SkMatrix* fMatrix;
- enum Flags {
- kSave_Flag = 0x1,
- kSaveLayer_Flag = 0x2
- };
- };
-
- Node fRoot;
- SkMatrix fRootMatrix;
-
- typedef SkRefCnt INHERITED;
-};
-
-#endif
diff --git a/tests/PictureStateTreeTest.cpp b/tests/PictureStateTreeTest.cpp
deleted file mode 100644
index cb154def96..0000000000
--- a/tests/PictureStateTreeTest.cpp
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Copyright 2014 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "SkBBHFactory.h"
-#include "SkCanvas.h"
-#include "SkPictureRecorder.h"
-#include "SkPictureStateTree.h"
-#include "Test.h"
-
-static SkPicture* draw_scene(SkBBHFactory* bbhFactory) {
- SkPictureRecorder recorder;
- SkCanvas* canvas = recorder.beginRecording(200, 200, bbhFactory, 0);
-
- SkPaint p1, p2;
- p1.setStyle(SkPaint::kFill_Style);
- p1.setARGB(0x80, 0, 0xff, 0);
- p2.setStyle(SkPaint::kFill_Style);
- p2.setARGB(0x80, 0xff, 0, 0);
-
- canvas->drawColor(SK_ColorWHITE);
-
- // This is intended to exercise some tricky SkPictureStateTree code paths when
- // played back with various clips:
- //
- // * cleanup/rewind when the last draw is not at the root of the state tree.
- // * state nodes with both kSave_Flag & kSaveLayer_Flag set.
- // * state tree transitions which implicitly reset the matrix via. restore().
-
- canvas->save();
- canvas->translate(10, 10);
-
- canvas->drawRect(SkRect::MakeWH(100, 50), p1);
- canvas->drawRect(SkRect::MakeWH(50, 100), p2);
-
- SkRect layerBounds = SkRect::MakeXYWH(0, 0, 90, 90);
- canvas->saveLayer(&layerBounds, NULL);
- canvas->save();
- canvas->clipRect(layerBounds);
-
- canvas->save();
- canvas->clipRect(SkRect::MakeWH(25, 25));
- canvas->rotate(90);
- canvas->drawRect(SkRect::MakeWH(100, 50), p1);
- canvas->restore();
-
- canvas->save();
- canvas->clipRect(SkRect::MakeWH(25, 25));
- canvas->save();
- canvas->rotate(90);
- canvas->drawRect(SkRect::MakeWH(50, 100), p2);
- canvas->restore();
- canvas->drawRect(SkRect::MakeWH(100, 50), p1);
- canvas->restore();
- canvas->drawRect(SkRect::MakeXYWH(99, 99, 1, 1), p1);
- canvas->restore();
- canvas->restore();
-
- canvas->restore();
-
- return recorder.endRecording();
-}
-
-static void check_bms(skiatest::Reporter* reporter, const SkBitmap& bm1, const SkBitmap& bm2) {
- SkASSERT(bm1.getSize() == bm2.getSize());
- REPORTER_ASSERT(reporter, 0 == memcmp(bm1.getAddr(0, 0), bm2.getAddr(0, 0), bm1.getSize()));
-}
-
-static void test_reference_picture(skiatest::Reporter* reporter) {
- SkRTreeFactory bbhFactory;
-
- SkAutoTUnref<SkPicture> bbhPicture(draw_scene(&bbhFactory));
- SkAutoTUnref<SkPicture> referencePicture(draw_scene(NULL));
-
- SkBitmap referenceBitmap;
- referenceBitmap.allocN32Pixels(100, 100);
- SkCanvas referenceCanvas(referenceBitmap);
-
- SkBitmap bbhBitmap;
- bbhBitmap.allocN32Pixels(100, 100);
- SkCanvas bbhCanvas(bbhBitmap);
-
- referenceCanvas.drawColor(SK_ColorTRANSPARENT);
- referenceCanvas.drawPicture(referencePicture.get());
- bbhCanvas.drawColor(SK_ColorTRANSPARENT);
- bbhCanvas.drawPicture(bbhPicture.get());
- REPORTER_ASSERT(reporter,
- referenceCanvas.getSaveCount() == bbhCanvas.getSaveCount());
- REPORTER_ASSERT(reporter,
- referenceCanvas.getTotalMatrix() == bbhCanvas.getTotalMatrix());
- check_bms(reporter, referenceBitmap, bbhBitmap);
-
- referenceCanvas.drawColor(SK_ColorTRANSPARENT);
- referenceCanvas.clipRect(SkRect::MakeWH(50, 50));
- referenceCanvas.drawPicture(referencePicture.get());
- bbhCanvas.drawColor(SK_ColorTRANSPARENT);
- bbhCanvas.clipRect(SkRect::MakeWH(50, 50));
- bbhCanvas.drawPicture(bbhPicture.get());
- REPORTER_ASSERT(reporter,
- referenceCanvas.getSaveCount() == bbhCanvas.getSaveCount());
- REPORTER_ASSERT(reporter,
- referenceCanvas.getTotalMatrix() == bbhCanvas.getTotalMatrix());
- check_bms(reporter, referenceBitmap, bbhBitmap);
-
- referenceCanvas.drawColor(SK_ColorTRANSPARENT);
- referenceCanvas.clipRect(SkRect::MakeWH(10, 10));
- referenceCanvas.drawPicture(referencePicture.get());
- bbhCanvas.drawColor(SK_ColorTRANSPARENT);
- bbhCanvas.clipRect(SkRect::MakeWH(10, 10));
- bbhCanvas.drawPicture(bbhPicture.get());
- REPORTER_ASSERT(reporter,
- referenceCanvas.getSaveCount() == bbhCanvas.getSaveCount());
- REPORTER_ASSERT(reporter,
- referenceCanvas.getTotalMatrix() == bbhCanvas.getTotalMatrix());
- check_bms(reporter, referenceBitmap, bbhBitmap);
-}
-
-DEF_TEST(PictureStateTree, reporter) {
- test_reference_picture(reporter);
-}
diff --git a/tests/RecordingXfermodeTest.cpp b/tests/RecordingXfermodeTest.cpp
index 8da81b3680..aa6bf687a1 100644
--- a/tests/RecordingXfermodeTest.cpp
+++ b/tests/RecordingXfermodeTest.cpp
@@ -20,20 +20,17 @@
// This arose from http://crbug.com/401593 which has
// https://code.google.com/p/skia/issues/detail?id=1291 as its root cause.
-
namespace {
class Drawer {
public:
- explicit Drawer()
- : fImageInfo(SkImageInfo::MakeN32Premul(200,100))
- {
- fCircleBM.allocPixels( SkImageInfo::MakeN32Premul(100,100) );
+ explicit Drawer() : fImageInfo(SkImageInfo::MakeN32Premul(200, 100)) {
+ fCircleBM.allocPixels(SkImageInfo::MakeN32Premul(100, 100));
SkCanvas canvas(fCircleBM);
canvas.clear(0xffffffff);
SkPaint circlePaint;
circlePaint.setColor(0xff000000);
- canvas.drawCircle(50,50,50,circlePaint);
+ canvas.drawCircle(50, 50, 50, circlePaint);
}
const SkImageInfo& imageInfo() const { return fImageInfo; }
@@ -48,15 +45,16 @@ class Drawer {
SkPaint layerPaint;
layerPaint.setColor(0xff000000);
layerPaint.setXfermodeMode(mode);
- SkRect canvasRect(SkRect::MakeWH(SkIntToScalar(fImageInfo.width()),SkIntToScalar(fImageInfo.height())));
+ SkRect canvasRect(SkRect::MakeWH(SkIntToScalar(fImageInfo.width()),
+ SkIntToScalar(fImageInfo.height())));
canvas->clipRect(clipRect);
canvas->clear(0xff000000);
- canvas->saveLayer(NULL,&blackPaint);
- canvas->drawRect(canvasRect,greenPaint);
- canvas->saveLayer(NULL,&layerPaint);
- canvas->drawBitmapRect(fCircleBM,SkRect::MakeXYWH(20,20,60,60),&blackPaint);
+ canvas->saveLayer(NULL, &blackPaint);
+ canvas->drawRect(canvasRect, greenPaint);
+ canvas->saveLayer(NULL, &layerPaint);
+ canvas->drawBitmapRect(fCircleBM, SkRect::MakeXYWH(20,20,60,60), &blackPaint);
canvas->restore();
canvas->restore();
}
@@ -69,7 +67,6 @@ class Drawer {
class RecordingStrategy {
public:
virtual ~RecordingStrategy() {}
- virtual void init(const SkImageInfo&) = 0;
virtual const SkBitmap& recordAndReplay(const Drawer& drawer,
const SkRect& intoClip,
SkXfermode::Mode) = 0;
@@ -78,9 +75,7 @@ class RecordingStrategy {
class BitmapBackedCanvasStrategy : public RecordingStrategy {
// This version just draws into a bitmap-backed canvas.
public:
- BitmapBackedCanvasStrategy() {}
-
- virtual void init(const SkImageInfo& imageInfo) {
+ BitmapBackedCanvasStrategy(const SkImageInfo& imageInfo) {
fBitmap.allocPixels(imageInfo);
}
@@ -99,57 +94,15 @@ class BitmapBackedCanvasStrategy : public RecordingStrategy {
SkBitmap fBitmap;
};
-class DeprecatedRecorderStrategy : public RecordingStrategy {
- // This version draws the entire scene into an SkPictureRecorder,
- // using the deprecated recording backend.
- // Then it then replays the scene through a clip rectangle.
- // This backend proved to be buggy.
- public:
- DeprecatedRecorderStrategy() {}
-
- virtual void init(const SkImageInfo& imageInfo) {
- fBitmap.allocPixels(imageInfo);
- fWidth = imageInfo.width();
- fHeight= imageInfo.height();
- }
-
- virtual const SkBitmap& recordAndReplay(const Drawer& drawer,
- const SkRect& intoClip,
- SkXfermode::Mode mode) {
- SkTileGridFactory::TileGridInfo tileGridInfo = { {100,100}, {0,0}, {0,0} };
- SkTileGridFactory factory(tileGridInfo);
- SkPictureRecorder recorder;
- SkRect canvasRect(SkRect::MakeWH(SkIntToScalar(fWidth),SkIntToScalar(fHeight)));
- SkCanvas* canvas = recorder.DEPRECATED_beginRecording( SkIntToScalar(fWidth), SkIntToScalar(fHeight), &factory);
- drawer.draw(canvas, canvasRect, mode);
- SkAutoTDelete<SkPicture> picture(recorder.endRecording());
-
- SkCanvas replayCanvas(fBitmap);
- replayCanvas.clear(0xffffffff);
- replayCanvas.clipRect(intoClip);
- picture->playback(&replayCanvas);
-
- return fBitmap;
- }
-
- private:
- SkBitmap fBitmap;
- int fWidth;
- int fHeight;
-};
-
-class NewRecordingStrategy : public RecordingStrategy {
- // This version draws the entire scene into an SkPictureRecorder,
- // using the new recording backend.
+class PictureStrategy : public RecordingStrategy {
+ // This version draws the entire scene into an SkPictureRecorder.
// Then it then replays the scene through a clip rectangle.
// This backend proved to be buggy.
public:
- NewRecordingStrategy() {}
-
- virtual void init(const SkImageInfo& imageInfo) {
+ PictureStrategy(const SkImageInfo& imageInfo) {
fBitmap.allocPixels(imageInfo);
- fWidth = imageInfo.width();
- fHeight= imageInfo.height();
+ fWidth = imageInfo.width();
+ fHeight = imageInfo.height();
}
virtual const SkBitmap& recordAndReplay(const Drawer& drawer,
@@ -159,8 +112,9 @@ class NewRecordingStrategy : public RecordingStrategy {
SkTileGridFactory factory(tileGridInfo);
SkPictureRecorder recorder;
SkRect canvasRect(SkRect::MakeWH(SkIntToScalar(fWidth),SkIntToScalar(fHeight)));
- SkCanvas* canvas = recorder.EXPERIMENTAL_beginRecording( SkIntToScalar(fWidth), SkIntToScalar(fHeight), &factory);
-
+ SkCanvas* canvas = recorder.beginRecording(SkIntToScalar(fWidth),
+ SkIntToScalar(fHeight),
+ &factory);
drawer.draw(canvas, canvasRect, mode);
SkAutoTDelete<SkPicture> picture(recorder.endRecording());
@@ -177,64 +131,45 @@ class NewRecordingStrategy : public RecordingStrategy {
int fHeight;
};
-}
-
+} // namespace
DEF_TEST(SkRecordingAccuracyXfermode, reporter) {
#define FINEGRAIN 0
-
const Drawer drawer;
- BitmapBackedCanvasStrategy golden; // This is the expected result.
- DeprecatedRecorderStrategy deprecatedRecording;
- NewRecordingStrategy newRecording;
-
- golden.init(drawer.imageInfo());
- deprecatedRecording.init(drawer.imageInfo());
- newRecording.init(drawer.imageInfo());
+ BitmapBackedCanvasStrategy golden(drawer.imageInfo());
+ PictureStrategy picture(drawer.imageInfo());
#if !FINEGRAIN
unsigned numErrors = 0;
SkString errors;
#endif
- for (int iMode = 0; iMode < int(SkXfermode::kLastMode) ; iMode++ ) {
- const SkRect& clip = SkRect::MakeXYWH(100,0,100,100);
+ for (int iMode = 0; iMode < int(SkXfermode::kLastMode); iMode++) {
+ const SkRect& clip = SkRect::MakeXYWH(100, 0, 100, 100);
SkXfermode::Mode mode = SkXfermode::Mode(iMode);
const SkBitmap& goldenBM = golden.recordAndReplay(drawer, clip, mode);
- const SkBitmap& deprecatedBM = deprecatedRecording.recordAndReplay(drawer, clip, mode);
- const SkBitmap& newRecordingBM = newRecording.recordAndReplay(drawer, clip, mode);
+ const SkBitmap& pictureBM = picture.recordAndReplay(drawer, clip, mode);
size_t pixelsSize = goldenBM.getSize();
- REPORTER_ASSERT( reporter, pixelsSize == deprecatedBM.getSize() );
- REPORTER_ASSERT( reporter, pixelsSize == newRecordingBM.getSize() );
+ REPORTER_ASSERT(reporter, pixelsSize == pictureBM.getSize());
// The pixel arrays should match.
#if FINEGRAIN
- REPORTER_ASSERT_MESSAGE( reporter,
- 0==memcmp( goldenBM.getPixels(), deprecatedBM.getPixels(), pixelsSize ),
- "Tiled bitmap is wrong");
- REPORTER_ASSERT_MESSAGE( reporter,
- 0==memcmp( goldenBM.getPixels(), recordingBM.getPixels(), pixelsSize ),
- "SkRecorder bitmap is wrong");
+ REPORTER_ASSERT(reporter,
+ 0 == memcmp(goldenBM.getPixels(), pictureBM.getPixels(), pixelsSize));
#else
- if ( memcmp( goldenBM.getPixels(), deprecatedBM.getPixels(), pixelsSize ) ) {
+ if (memcmp(goldenBM.getPixels(), pictureBM.getPixels(), pixelsSize)) {
numErrors++;
- SkString str;
- str.printf("For SkXfermode %d %s: Deprecated recorder bitmap is wrong\n", iMode, SkXfermode::ModeName(mode));
- errors.append(str);
- }
- if ( memcmp( goldenBM.getPixels(), newRecordingBM.getPixels(), pixelsSize ) ) {
- numErrors++;
- SkString str;
- str.printf("For SkXfermode %d %s: SkPictureRecorder bitmap is wrong\n", iMode, SkXfermode::ModeName(mode));
- errors.append(str);
+ errors.appendf("For SkXfermode %d %s: SkPictureRecorder bitmap is wrong\n",
+ iMode, SkXfermode::ModeName(mode));
}
#endif
}
+
#if !FINEGRAIN
- REPORTER_ASSERT_MESSAGE( reporter, 0==numErrors, errors.c_str() );
+ REPORTER_ASSERT_MESSAGE(reporter, 0 == numErrors, errors.c_str());
#endif
}