Add Sample slide for Rectanizers

R=jvanverth@google.com, bsalomon@google.com

Author: robertphillips@google.com

Review URL: https://codereview.chromium.org/303263005
diff --git a/samplecode/SampleRectanizer.cpp b/samplecode/SampleRectanizer.cpp
new file mode 100644
index 0000000..fcb1cdb
--- /dev/null
+++ b/samplecode/SampleRectanizer.cpp
@@ -0,0 +1,198 @@
+/*
+ * 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 "gm.h"
+#include "SampleCode.h"
+#include "SkRandom.h"
+#include "SkUtils.h"
+#if SK_SUPPORT_GPU
+#include "GrRectanizer_pow2.h"
+#include "GrRectanizer_skyline.h"
+
+
+// This slide visualizes the various GrRectanizer-derived classes behavior
+// for various input sets
+//  'j' will cycle through the various rectanizers
+//          Pow2 -> GrRectanizerPow2
+//          Skyline -> GrRectanizerSkyline
+//  'h' will cycle through the various rect sets
+//          Rand -> random rects from 2-256
+//          Pow2Rand -> random power of 2 sized rects from 2-256
+//          SmallPow2 -> 128x128 rects
+class RectanizerView : public SampleView {
+public:
+    RectanizerView()
+        : fCurRandRect(0) {
+        for (int i = 0; i < 3; ++i) {
+           fRects[i].setReserve(kNumRandRects);
+        }
+        fRectLocations.setReserve(kNumRandRects);
+
+        SkRandom random;
+        for (int i = 0; i < kNumRandRects; ++i) {
+            *fRects[0].append() = SkISize::Make(random.nextRangeU(kMinRectSize, kMaxRectSize),
+                                                random.nextRangeU(kMinRectSize, kMaxRectSize));
+            *fRects[1].append() = SkISize::Make(
+                        GrNextPow2(random.nextRangeU(kMinRectSize, kMaxRectSize)),
+                        GrNextPow2(random.nextRangeU(kMinRectSize, kMaxRectSize)));
+            *fRects[2].append() = SkISize::Make(128, 128);
+            *fRectLocations.append() = GrIPoint16::Make(0, 0);
+        }
+
+        fCurRects = &fRects[0];
+
+        fRectanizers[0] = new GrRectanizerPow2(kWidth, kHeight);
+        fRectanizers[1] = new GrRectanizerSkyline(kWidth, kHeight);
+        fCurRectanizer = fRectanizers[0];
+    }
+
+protected:
+    virtual bool onQuery(SkEvent* evt) SK_OVERRIDE {
+        if (SampleCode::TitleQ(*evt)) {
+            SampleCode::TitleR(evt, "Rectanizer");
+            return true;
+        }
+        SkUnichar uni;
+        if (SampleCode::CharQ(*evt, &uni)) {
+            char utf8[kMaxBytesInUTF8Sequence];
+            size_t size = SkUTF8_FromUnichar(uni, utf8);
+            // Only consider events for single char keys
+            if (1 == size) {
+                switch (utf8[0]) {
+                case kCycleRectanizerKey:
+                    this->cycleRectanizer();
+                    return true;
+                case kCycleRectsKey:
+                    this->cycleRects();
+                    return true;
+                default:
+                    break;
+                }
+            }
+        }
+        return this->INHERITED::onQuery(evt);
+    }
+
+    virtual void onDrawContent(SkCanvas* canvas) SK_OVERRIDE {
+        if (fCurRandRect < kNumRandRects) {
+            if (fCurRectanizer->addRect((*fCurRects)[fCurRandRect].fWidth,
+                                        (*fCurRects)[fCurRandRect].fHeight,
+                                        &fRectLocations[fCurRandRect])) {
+                ++fCurRandRect;
+            }
+        }
+
+        SkPaint blackBigFont;
+        blackBigFont.setTextSize(20);
+        SkPaint blackStroke;
+        blackStroke.setStyle(SkPaint::kStroke_Style);
+        SkPaint redFill;
+        redFill.setColor(SK_ColorRED);
+
+        SkRect r = SkRect::MakeWH(SkIntToScalar(kWidth), SkIntToScalar(kHeight));
+
+        canvas->clear(SK_ColorWHITE);
+        canvas->drawRect(r, blackStroke);
+
+        long totArea = 0;
+        for (int i = 0; i < fCurRandRect; ++i) {
+            r = SkRect::MakeXYWH(SkIntToScalar(fRectLocations[i].fX), 
+                                 SkIntToScalar(fRectLocations[i].fY),
+                                 SkIntToScalar((*fCurRects)[i].fWidth),
+                                 SkIntToScalar((*fCurRects)[i].fHeight));
+            canvas->drawRect(r, redFill);
+            canvas->drawRect(r, blackStroke);
+            totArea += (*fCurRects)[i].fWidth * (*fCurRects)[i].fHeight;
+        }
+
+        SkString str;
+
+        str.printf("%s-%s: tot Area: %ld %%full: %.2f (%.2f) numTextures: %d/%d",
+                   this->getRectanizerName(),
+                   this->getRectsName(),
+                   totArea,
+                   100.0f * fCurRectanizer->percentFull(),
+                   100.0f * totArea / ((float)kWidth*kHeight),
+                   fCurRandRect,
+                   kNumRandRects);
+        canvas->drawText(str.c_str(), str.size(), 50, kHeight + 50, blackBigFont);
+
+        str.printf("Press \'j\' to toggle rectanizer");
+        canvas->drawText(str.c_str(), str.size(), 50, kHeight + 100, blackBigFont);
+
+        str.printf("Press \'h\' to toggle rects");
+        canvas->drawText(str.c_str(), str.size(), 50, kHeight + 150, blackBigFont);
+
+        this->inval(NULL);
+    }
+
+private:
+    static const int kWidth = 1024;
+    static const int kHeight = 1024;
+    static const int kNumRandRects = 200;
+    static const char kCycleRectanizerKey = 'j';
+    static const char kCycleRectsKey = 'h';
+    static const int kMinRectSize = 2;
+    static const int kMaxRectSize = 256;
+
+    int                   fCurRandRect;
+    SkTDArray<SkISize>    fRects[3];
+    SkTDArray<SkISize>*   fCurRects;
+    SkTDArray<GrIPoint16> fRectLocations;
+    GrRectanizer*         fRectanizers[2];
+    GrRectanizer*         fCurRectanizer;
+
+    const char* getRectanizerName() const {
+        if (fCurRectanizer == fRectanizers[0]) {
+            return "Pow2";
+        } else {
+            return "Skyline";
+        }
+    }
+
+    void cycleRectanizer() {
+        if (fCurRectanizer == fRectanizers[0]) {
+            fCurRectanizer = fRectanizers[1];
+        } else {
+            fCurRectanizer = fRectanizers[0];
+        }
+
+        fCurRectanizer->reset();
+        fCurRandRect = 0;
+    }
+
+    const char* getRectsName() const {
+        if (fCurRects == &fRects[0]) {
+            return "Rand";
+        } else if (fCurRects == &fRects[1]) {
+            return "Pow2Rand";
+        } else {
+            return "SmallPow2";
+        }
+    }
+
+    void cycleRects() {
+        if (fCurRects == &fRects[0]) {
+            fCurRects = &fRects[1];
+        } else if (fCurRects == &fRects[1]) {
+            fCurRects = &fRects[2];
+        } else {
+            fCurRects = &fRects[0];
+        }
+
+        fCurRectanizer->reset();
+        fCurRandRect = 0;
+    }
+
+    typedef SampleView INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+static SkView* MyFactory() { return new RectanizerView; }
+static SkViewRegister reg(MyFactory);
+
+#endif