Index: gm/multipicturedraw.cpp |
diff --git a/gm/multipicturedraw.cpp b/gm/multipicturedraw.cpp |
index 11756a79a7a4276388160ac17df929653a84800c..eeb5909288e2793bb5ea8eaedbd819611d294566 100644 |
--- a/gm/multipicturedraw.cpp |
+++ b/gm/multipicturedraw.cpp |
@@ -13,6 +13,7 @@ |
#include "SkSurface.h" |
static const SkScalar kRoot3Over2 = 0.86602545f; // sin(60) |
+static const SkScalar kRoot3 = 1.73205081f; |
static const int kHexSide = 30; |
static const int kNumHexX = 6; |
@@ -20,6 +21,9 @@ static const int kNumHexY = 6; |
static const int kPicWidth = kNumHexX * kHexSide; |
static const int kPicHeight = SkScalarCeilToInt((kNumHexY - 0.5f) * 2 * kHexSide * kRoot3Over2); |
static const SkScalar kInset = 20.0f; |
+static const int kNumPictures = 3; |
+ |
+static const int kTriSide = 40; |
// Create a hexagon centered at (originX, originY) |
static SkPath make_hex_path(SkScalar originX, SkScalar originY) { |
@@ -37,7 +41,7 @@ static SkPath make_hex_path(SkScalar originX, SkScalar originY) { |
// Make a picture that is a tiling of the plane with stroked hexagons where |
// each hexagon is in its own layer. The layers are to exercise Ganesh's |
// layer hoisting. |
-static const SkPicture* make_picture(SkColor fillColor) { |
+static const SkPicture* make_hex_plane_picture(SkColor fillColor) { |
// Create a hexagon with its center at the origin |
SkPath hex = make_hex_path(0, 0); |
@@ -76,6 +80,93 @@ static const SkPicture* make_picture(SkColor fillColor) { |
return recorder.endRecording(); |
} |
+// Make an equilateral triangle path with its top corner at (originX, originY) |
+static SkPath make_tri_path(SkScalar originX, SkScalar originY) { |
+ SkPath tri; |
+ tri.moveTo(originX, originY); |
+ tri.rLineTo(SkScalarHalf(kTriSide), 1.5f * kTriSide / kRoot3); |
+ tri.rLineTo(-kTriSide, 0); |
+ tri.close(); |
+ return tri; |
+} |
+ |
+static const SkPicture* make_tri_picture() { |
+ SkPath tri = make_tri_path(0, 0); |
+ |
+ SkPaint fill; |
+ fill.setStyle(SkPaint::kFill_Style); |
+ fill.setColor(SK_ColorLTGRAY);; |
+ |
+ SkPaint stroke; |
+ stroke.setStyle(SkPaint::kStroke_Style); |
+ stroke.setStrokeWidth(3); |
+ |
+ SkPictureRecorder recorder; |
+ |
+ SkCanvas* canvas = recorder.beginRecording(SkIntToScalar(kPicWidth), |
+ SkIntToScalar(kPicHeight)); |
+ // The saveLayer/restore block is to exercise layer hoisting |
+ canvas->saveLayer(NULL, NULL); |
+ canvas->drawPath(tri, fill); |
+ canvas->drawPath(tri, stroke); |
+ canvas->restore(); |
+ |
+ return recorder.endRecording(); |
+} |
+ |
+static const SkPicture* make_sub_picture(const SkPicture* tri) { |
+ SkPictureRecorder recorder; |
+ |
+ SkCanvas* canvas = recorder.beginRecording(SkIntToScalar(kPicWidth), |
+ SkIntToScalar(kPicHeight)); |
+ |
+ canvas->scale(1.0f/2.0f, 1.0f/2.0f); |
+ |
+ canvas->drawPicture(tri); |
+ |
+ canvas->save(); |
+ canvas->translate(SkScalarHalf(kTriSide), 1.5f * kTriSide / kRoot3); |
+ canvas->drawPicture(tri); |
+ canvas->restore(); |
+ |
+ canvas->save(); |
+ canvas->translate(-SkScalarHalf(kTriSide), 1.5f * kTriSide / kRoot3); |
+ canvas->drawPicture(tri); |
+ canvas->restore(); |
+ |
+ return recorder.endRecording(); |
+} |
+ |
+// Create a Sierpinkski-like picture that starts with a top row with a picture |
+// that just contains a triangle. Subsequent rows take the prior row's picture, |
+// shrinks it and replicates it 3 times then draws and appropriate number of |
+// copies of it. |
+static const SkPicture* make_sierpinski_picture() { |
+ SkAutoTUnref<const SkPicture> pic(make_tri_picture()); |
+ |
+ SkPictureRecorder recorder; |
+ |
+ SkCanvas* canvas = recorder.beginRecording(SkIntToScalar(kPicWidth), |
+ SkIntToScalar(kPicHeight)); |
+ |
+ static const int kNumLevels = 4; |
+ for (int i = 0; i < kNumLevels; ++i) { |
+ canvas->save(); |
+ canvas->translate(-i*kTriSide / 2.0f, 0); |
+ for (int j = 0; j < i+1; ++j) { |
+ canvas->drawPicture(pic); |
+ canvas->translate(SkIntToScalar(kTriSide), 0); |
+ } |
+ canvas->restore(); |
+ |
+ pic.reset(make_sub_picture(pic)); |
+ |
+ canvas->translate(0, 1.5f * kTriSide / kRoot3); |
+ } |
+ |
+ return recorder.endRecording(); |
+} |
+ |
static SkSurface* create_compat_surface(SkCanvas* canvas, int width, int height) { |
SkImageInfo info = SkImageInfo::MakeN32Premul(width, height); |
@@ -101,15 +192,15 @@ public: |
SkPaint* fPaint; |
}; |
-typedef void (*PFContentMtd)(SkCanvas* canvas, const SkPicture* pictures[2]); |
+typedef void (*PFContentMtd)(SkCanvas* canvas, const SkPicture* pictures[kNumPictures]); |
// Just a single picture with no clip |
-static void no_clip(SkCanvas* canvas, const SkPicture* pictures[2]) { |
+static void no_clip(SkCanvas* canvas, const SkPicture* pictures[kNumPictures]) { |
canvas->drawPicture(pictures[0]); |
} |
// Two pictures with a rect clip on the second one |
-static void rect_clip(SkCanvas* canvas, const SkPicture* pictures[2]) { |
+static void rect_clip(SkCanvas* canvas, const SkPicture* pictures[kNumPictures]) { |
canvas->drawPicture(pictures[0]); |
SkRect rect = pictures[0]->cullRect(); |
@@ -121,7 +212,7 @@ static void rect_clip(SkCanvas* canvas, const SkPicture* pictures[2]) { |
} |
// Two pictures with a round rect clip on the second one |
-static void rrect_clip(SkCanvas* canvas, const SkPicture* pictures[2]) { |
+static void rrect_clip(SkCanvas* canvas, const SkPicture* pictures[kNumPictures]) { |
canvas->drawPicture(pictures[0]); |
SkRect rect = pictures[0]->cullRect(); |
@@ -136,7 +227,7 @@ static void rrect_clip(SkCanvas* canvas, const SkPicture* pictures[2]) { |
} |
// Two pictures with a clip path on the second one |
-static void path_clip(SkCanvas* canvas, const SkPicture* pictures[2]) { |
+static void path_clip(SkCanvas* canvas, const SkPicture* pictures[kNumPictures]) { |
canvas->drawPicture(pictures[0]); |
// Create a hexagon centered on the middle of the hex grid |
@@ -148,7 +239,7 @@ static void path_clip(SkCanvas* canvas, const SkPicture* pictures[2]) { |
} |
// Two pictures with an inverse clip path on the second one |
-static void invpath_clip(SkCanvas* canvas, const SkPicture* pictures[2]) { |
+static void invpath_clip(SkCanvas* canvas, const SkPicture* pictures[kNumPictures]) { |
canvas->drawPicture(pictures[0]); |
// Create a hexagon centered on the middle of the hex grid |
@@ -160,16 +251,29 @@ static void invpath_clip(SkCanvas* canvas, const SkPicture* pictures[2]) { |
canvas->drawPicture(pictures[1]); |
} |
+// Reuse a single base (triangular) picture a _lot_ (rotated, scaled and translated). |
+static void sierpinski(SkCanvas* canvas, const SkPicture* pictures[kNumPictures]) { |
+ canvas->save(); |
+ canvas->translate(kPicWidth / 2.0f, 0.0f); |
+ canvas->drawPicture(pictures[2]); |
+ |
+ canvas->rotate(180.0f); |
+ canvas->translate(0.0f, -SkIntToScalar(kPicHeight)); |
+ canvas->drawPicture(pictures[2]); |
+ canvas->restore(); |
+} |
+ |
static const PFContentMtd gContentMthds[] = { |
no_clip, |
rect_clip, |
rrect_clip, |
path_clip, |
- invpath_clip |
+ invpath_clip, |
+ sierpinski |
}; |
static void create_content(SkMultiPictureDraw* mpd, PFContentMtd pfGen, |
- const SkPicture* pictures[2], |
+ const SkPicture* pictures[kNumPictures], |
SkCanvas* dest, const SkMatrix& xform) { |
SkAutoTUnref<SkPicture> composite; |
@@ -188,13 +292,13 @@ static void create_content(SkMultiPictureDraw* mpd, PFContentMtd pfGen, |
} |
typedef void(*PFLayoutMtd)(SkCanvas* finalCanvas, SkMultiPictureDraw* mpd, |
- PFContentMtd pfGen, const SkPicture* pictures[2], |
+ PFContentMtd pfGen, const SkPicture* pictures[kNumPictures], |
SkTArray<ComposeStep>* composeSteps); |
// Draw the content into a single canvas |
static void simple(SkCanvas* finalCanvas, SkMultiPictureDraw* mpd, |
PFContentMtd pfGen, |
- const SkPicture* pictures[2], |
+ const SkPicture* pictures[kNumPictures], |
SkTArray<ComposeStep> *composeSteps) { |
ComposeStep& step = composeSteps->push_back(); |
@@ -209,7 +313,7 @@ static void simple(SkCanvas* finalCanvas, SkMultiPictureDraw* mpd, |
// Draw the content into multiple canvases/tiles |
static void tiled(SkCanvas* finalCanvas, SkMultiPictureDraw* mpd, |
PFContentMtd pfGen, |
- const SkPicture* pictures[2], |
+ const SkPicture* pictures[kNumPictures], |
SkTArray<ComposeStep> *composeSteps) { |
static const int kNumTilesX = 2; |
static const int kNumTilesY = 2; |
@@ -264,8 +368,9 @@ namespace skiagm { |
kRRectClipMulti_Content, |
kPathClipMulti_Content, |
kInvPathClipMulti_Content, |
+ kSierpinski_Content, |
- kLast_Content = kInvPathClipMulti_Content |
+ kLast_Content = kSierpinski_Content |
}; |
static const int kContentCnt = kLast_Content + 1; |
@@ -283,22 +388,26 @@ namespace skiagm { |
SkASSERT(SK_ARRAY_COUNT(gLayoutMthds) == kLayoutCnt); |
SkASSERT(SK_ARRAY_COUNT(gContentMthds) == kContentCnt); |
- fPictures[0] = fPictures[1] = NULL; |
+ for (int i = 0; i < kNumPictures; ++i) { |
+ fPictures[i] = NULL; |
+ } |
} |
virtual ~MultiPictureDraw() { |
- SkSafeUnref(fPictures[0]); |
- SkSafeUnref(fPictures[1]); |
+ for (int i = 0; i < kNumPictures; ++i) { |
+ SkSafeUnref(fPictures[i]); |
+ } |
} |
protected: |
Content fContent; |
Layout fLayout; |
- const SkPicture* fPictures[2]; |
+ const SkPicture* fPictures[kNumPictures]; |
virtual void onOnceBeforeDraw() SK_OVERRIDE { |
- fPictures[0] = make_picture(SK_ColorWHITE); |
- fPictures[1] = make_picture(SK_ColorGRAY); |
+ fPictures[0] = make_hex_plane_picture(SK_ColorWHITE); |
+ fPictures[1] = make_hex_plane_picture(SK_ColorGRAY); |
+ fPictures[2] = SkRef(make_sierpinski_picture()); |
} |
virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE { |
@@ -326,7 +435,7 @@ namespace skiagm { |
virtual SkString onShortName() SK_OVERRIDE { |
static const char* gContentNames[] = { |
- "noclip", "rectclip", "rrectclip", "pathclip", "invpathclip" |
+ "noclip", "rectclip", "rrectclip", "pathclip", "invpathclip", "sierpinski" |
}; |
static const char* gLayoutNames[] = { "simple", "tiled" }; |
@@ -357,6 +466,8 @@ namespace skiagm { |
MultiPictureDraw::kSimple_Layout));) |
DEF_GM(return SkNEW_ARGS(MultiPictureDraw, (MultiPictureDraw::kInvPathClipMulti_Content, |
MultiPictureDraw::kSimple_Layout));) |
+ DEF_GM(return SkNEW_ARGS(MultiPictureDraw, (MultiPictureDraw::kSierpinski_Content, |
+ MultiPictureDraw::kSimple_Layout));) |
DEF_GM(return SkNEW_ARGS(MultiPictureDraw, (MultiPictureDraw::kNoClipSingle_Content, |
MultiPictureDraw::kTiled_Layout));) |
@@ -368,4 +479,6 @@ namespace skiagm { |
MultiPictureDraw::kTiled_Layout));) |
DEF_GM(return SkNEW_ARGS(MultiPictureDraw, (MultiPictureDraw::kInvPathClipMulti_Content, |
MultiPictureDraw::kTiled_Layout));) |
+ DEF_GM(return SkNEW_ARGS(MultiPictureDraw, (MultiPictureDraw::kSierpinski_Content, |
+ MultiPictureDraw::kTiled_Layout));) |
} |