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 26class RectanizerView : public SampleView { 27public: 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 53protected: 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 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 133private: 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 149 const char* getRectanizerName() const { 150 if (fCurRectanizer == fRectanizers[0]) { 151 return "Pow2"; 152 } else { 153 return "Skyline"; 154 } 155 } 156 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 168 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 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////////////////////////////////////////////////////////////////////////////// 195static SkView* MyFactory() { return new RectanizerView; } 196static SkViewRegister reg(MyFactory); 197 198#endif 199