skia2/samplecode/SampleRectanizer.cpp
Hal Canary f107a2fd01 SkUTF
Create new header and namespace, `SkUTF` where we are putting all of our
robust, well documented UTF-8, UTF-16, and UTF-32 functions:
`SkUTF::{Count,Next,To}UTF{8,16,32}()`.

SkUTF.h and SkUTF.cpp do not depend on the rest of Skia and are suitable
for re-use in other modules.

Some of the old UTF-{8,16} functions still live in SkUtils.h; their use
will be phased out in future CLs.

Also added more unit testing and cleaned up old tests.

Removed functions that were unused outside of tests or used only once.

Change-Id: Iaa59b8705abccf9c4ba082f855da368a0bad8380
Reviewed-on: https://skia-review.googlesource.com/143306
Reviewed-by: Ben Wagner <bungeman@google.com>
Commit-Queue: Hal Canary <halcanary@google.com>
2018-07-31 20:11:19 +00:00

194 lines
6.5 KiB
C++

/*
* 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[SkUTF::kMaxBytesInUTF8Sequence];
size_t size = SkUTF::ToUTF8(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