1 /*
2 * Copyright 2014 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8 #include "gm.h"
9 #include "SampleCode.h"
10 #include "SkRandom.h"
11 #include "SkUtils.h"
12 #if SK_SUPPORT_GPU
13 #include "GrRectanizer_pow2.h"
14 #include "GrRectanizer_skyline.h"
15
16
17 // This slide visualizes the various GrRectanizer-derived classes behavior
18 // for various input sets
19 // 'j' will cycle through the various rectanizers
20 // Pow2 -> GrRectanizerPow2
21 // Skyline -> GrRectanizerSkyline
22 // 'h' will cycle through the various rect sets
23 // Rand -> random rects from 2-256
24 // Pow2Rand -> random power of 2 sized rects from 2-256
25 // SmallPow2 -> 128x128 rects
26 class RectanizerView : public SampleView {
27 public:
RectanizerView()28 RectanizerView()
29 : fCurRandRect(0) {
30 for (int i = 0; i < 3; ++i) {
31 fRects[i].setReserve(kNumRandRects);
32 }
33 fRectLocations.setReserve(kNumRandRects);
34
35 SkRandom random;
36 for (int i = 0; i < kNumRandRects; ++i) {
37 *fRects[0].append() = SkISize::Make(random.nextRangeU(kMinRectSize, kMaxRectSize),
38 random.nextRangeU(kMinRectSize, kMaxRectSize));
39 *fRects[1].append() = SkISize::Make(
40 GrNextPow2(random.nextRangeU(kMinRectSize, kMaxRectSize)),
41 GrNextPow2(random.nextRangeU(kMinRectSize, kMaxRectSize)));
42 *fRects[2].append() = SkISize::Make(128, 128);
43 *fRectLocations.append() = SkIPoint16::Make(0, 0);
44 }
45
46 fCurRects = &fRects[0];
47
48 fRectanizers[0] = new GrRectanizerPow2(kWidth, kHeight);
49 fRectanizers[1] = new GrRectanizerSkyline(kWidth, kHeight);
50 fCurRectanizer = fRectanizers[0];
51 }
52
53 protected:
onQuery(SkEvent * evt)54 bool onQuery(SkEvent* evt) override {
55 if (SampleCode::TitleQ(*evt)) {
56 SampleCode::TitleR(evt, "Rectanizer");
57 return true;
58 }
59 SkUnichar uni;
60 if (SampleCode::CharQ(*evt, &uni)) {
61 char utf8[kMaxBytesInUTF8Sequence];
62 size_t size = SkUTF8_FromUnichar(uni, utf8);
63 // Only consider events for single char keys
64 if (1 == size) {
65 switch (utf8[0]) {
66 case kCycleRectanizerKey:
67 this->cycleRectanizer();
68 return true;
69 case kCycleRectsKey:
70 this->cycleRects();
71 return true;
72 default:
73 break;
74 }
75 }
76 }
77 return this->INHERITED::onQuery(evt);
78 }
79
onDrawContent(SkCanvas * canvas)80 void onDrawContent(SkCanvas* canvas) override {
81 if (fCurRandRect < kNumRandRects) {
82 if (fCurRectanizer->addRect((*fCurRects)[fCurRandRect].fWidth,
83 (*fCurRects)[fCurRandRect].fHeight,
84 &fRectLocations[fCurRandRect])) {
85 ++fCurRandRect;
86 }
87 }
88
89 SkPaint blackBigFont;
90 blackBigFont.setTextSize(20);
91 SkPaint blackStroke;
92 blackStroke.setStyle(SkPaint::kStroke_Style);
93 SkPaint redFill;
94 redFill.setColor(SK_ColorRED);
95
96 SkRect r = SkRect::MakeWH(SkIntToScalar(kWidth), SkIntToScalar(kHeight));
97
98 canvas->clear(SK_ColorWHITE);
99 canvas->drawRect(r, blackStroke);
100
101 long totArea = 0;
102 for (int i = 0; i < fCurRandRect; ++i) {
103 r = SkRect::MakeXYWH(SkIntToScalar(fRectLocations[i].fX),
104 SkIntToScalar(fRectLocations[i].fY),
105 SkIntToScalar((*fCurRects)[i].fWidth),
106 SkIntToScalar((*fCurRects)[i].fHeight));
107 canvas->drawRect(r, redFill);
108 canvas->drawRect(r, blackStroke);
109 totArea += (*fCurRects)[i].fWidth * (*fCurRects)[i].fHeight;
110 }
111
112 SkString str;
113
114 str.printf("%s-%s: tot Area: %ld %%full: %.2f (%.2f) numTextures: %d/%d",
115 this->getRectanizerName(),
116 this->getRectsName(),
117 totArea,
118 100.0f * fCurRectanizer->percentFull(),
119 100.0f * totArea / ((float)kWidth*kHeight),
120 fCurRandRect,
121 kNumRandRects);
122 canvas->drawText(str.c_str(), str.size(), 50, kHeight + 50, blackBigFont);
123
124 str.printf("Press \'j\' to toggle rectanizer");
125 canvas->drawText(str.c_str(), str.size(), 50, kHeight + 100, blackBigFont);
126
127 str.printf("Press \'h\' to toggle rects");
128 canvas->drawText(str.c_str(), str.size(), 50, kHeight + 150, blackBigFont);
129
130 this->inval(nullptr);
131 }
132
133 private:
134 static const int kWidth = 1024;
135 static const int kHeight = 1024;
136 static const int kNumRandRects = 200;
137 static const char kCycleRectanizerKey = 'j';
138 static const char kCycleRectsKey = 'h';
139 static const int kMinRectSize = 2;
140 static const int kMaxRectSize = 256;
141
142 int fCurRandRect;
143 SkTDArray<SkISize> fRects[3];
144 SkTDArray<SkISize>* fCurRects;
145 SkTDArray<SkIPoint16> fRectLocations;
146 GrRectanizer* fRectanizers[2];
147 GrRectanizer* fCurRectanizer;
148
getRectanizerName() const149 const char* getRectanizerName() const {
150 if (fCurRectanizer == fRectanizers[0]) {
151 return "Pow2";
152 } else {
153 return "Skyline";
154 }
155 }
156
cycleRectanizer()157 void cycleRectanizer() {
158 if (fCurRectanizer == fRectanizers[0]) {
159 fCurRectanizer = fRectanizers[1];
160 } else {
161 fCurRectanizer = fRectanizers[0];
162 }
163
164 fCurRectanizer->reset();
165 fCurRandRect = 0;
166 }
167
getRectsName() const168 const char* getRectsName() const {
169 if (fCurRects == &fRects[0]) {
170 return "Rand";
171 } else if (fCurRects == &fRects[1]) {
172 return "Pow2Rand";
173 } else {
174 return "SmallPow2";
175 }
176 }
177
cycleRects()178 void cycleRects() {
179 if (fCurRects == &fRects[0]) {
180 fCurRects = &fRects[1];
181 } else if (fCurRects == &fRects[1]) {
182 fCurRects = &fRects[2];
183 } else {
184 fCurRects = &fRects[0];
185 }
186
187 fCurRectanizer->reset();
188 fCurRandRect = 0;
189 }
190
191 typedef SampleView INHERITED;
192 };
193
194 //////////////////////////////////////////////////////////////////////////////
MyFactory()195 static SkView* MyFactory() { return new RectanizerView; }
196 static SkViewRegister reg(MyFactory);
197
198 #endif
199