| /* | 
 |  * 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) | 
 |         , fCurRectanizer(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() = SkIPoint16::Make(0, 0); | 
 |         } | 
 |  | 
 |         fCurRects = &fRects[0]; | 
 |  | 
 |         fRectanizers.push_back( | 
 |             std::unique_ptr<GrRectanizer>(new GrRectanizerPow2(kWidth, kHeight))); | 
 |         fRectanizers.push_back( | 
 |             std::unique_ptr<GrRectanizer>(new GrRectanizerSkyline(kWidth, kHeight))); | 
 |     } | 
 |  | 
 | protected: | 
 |     bool onQuery(SkEvent* evt) 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); | 
 |     } | 
 |  | 
 |     void onDrawContent(SkCanvas* canvas) override { | 
 |         if (fCurRandRect < kNumRandRects) { | 
 |             if (fRectanizers[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 * fRectanizers[fCurRectanizer]->percentFull(), | 
 |                    100.0f * totArea / ((float)kWidth*kHeight), | 
 |                    fCurRandRect, | 
 |                    kNumRandRects); | 
 |         canvas->drawString(str, 50, kHeight + 50, blackBigFont); | 
 |  | 
 |         str.printf("Press \'j\' to toggle rectanizer"); | 
 |         canvas->drawString(str, 50, kHeight + 100, blackBigFont); | 
 |  | 
 |         str.printf("Press \'h\' to toggle rects"); | 
 |         canvas->drawString(str, 50, kHeight + 150, blackBigFont); | 
 |     } | 
 |  | 
 | 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<SkIPoint16>                   fRectLocations; | 
 |     SkTArray<std::unique_ptr<GrRectanizer>> fRectanizers; | 
 |     int                                     fCurRectanizer; | 
 |  | 
 |     const char* getRectanizerName() const { | 
 |         if (!fCurRectanizer) { | 
 |             return "Pow2"; | 
 |         } else { | 
 |             return "Skyline"; | 
 |         } | 
 |     } | 
 |  | 
 |     void cycleRectanizer() { | 
 |         fCurRectanizer = (fCurRectanizer + 1) % fRectanizers.count(); | 
 |  | 
 |         fRectanizers[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]; | 
 |         } | 
 |  | 
 |         fRectanizers[fCurRectanizer]->reset(); | 
 |         fCurRandRect = 0; | 
 |     } | 
 |  | 
 |     typedef SampleView INHERITED; | 
 | }; | 
 |  | 
 | ////////////////////////////////////////////////////////////////////////////// | 
 | static SkView* MyFactory() { return new RectanizerView; } | 
 | static SkViewRegister reg(MyFactory); | 
 |  | 
 | #endif |