| Index: gm/variedtext.cpp
|
| diff --git a/gm/variedtext.cpp b/gm/variedtext.cpp
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..e174796780513c48b8f6ecfeea83be7fdecd94d9
|
| --- /dev/null
|
| +++ b/gm/variedtext.cpp
|
| @@ -0,0 +1,169 @@
|
| +/*
|
| + * 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 "SkCanvas.h"
|
| +#include "SkPath.h"
|
| +#include "SkTypeface.h"
|
| +#include "SkRandom.h"
|
| +
|
| +/**
|
| + * Draws text with random parameters. The text draws each get their own clip rect. It is also
|
| + * used as a bench to measure how well the GPU backend batches text draws.
|
| + */
|
| +
|
| +class VariedTextGM : public skiagm::GM {
|
| +public:
|
| + VariedTextGM(bool effectiveClip, bool lcd)
|
| + : fEffectiveClip(effectiveClip)
|
| + , fLCD(lcd) {
|
| + memset(fTypefacesToUnref, 0, sizeof(fTypefacesToUnref));
|
| + }
|
| +
|
| + ~VariedTextGM() {
|
| + for (size_t i = 0; i < SK_ARRAY_COUNT(fTypefacesToUnref); ++i) {
|
| + SkSafeUnref(fTypefacesToUnref[i]);
|
| + }
|
| + }
|
| +
|
| +protected:
|
| + virtual SkString onShortName() SK_OVERRIDE {
|
| + SkString name("varied_text");
|
| + if (fEffectiveClip) {
|
| + name.append("_clipped");
|
| + } else {
|
| + name.append("_ignorable_clip");
|
| + }
|
| + if (fLCD) {
|
| + name.append("_lcd");
|
| + } else {
|
| + name.append("_no_lcd");
|
| + }
|
| + return name;
|
| + }
|
| +
|
| + virtual SkISize onISize() SK_OVERRIDE {
|
| + return SkISize::Make(640, 480);
|
| + }
|
| +
|
| + virtual void onOnceBeforeDraw() SK_OVERRIDE {
|
| + fPaint.setAntiAlias(true);
|
| + fPaint.setLCDRenderText(fLCD);
|
| +
|
| + SkISize size = this->getISize();
|
| + SkScalar w = SkIntToScalar(size.fWidth);
|
| + SkScalar h = SkIntToScalar(size.fHeight);
|
| +
|
| + SK_COMPILE_ASSERT(4 == SK_ARRAY_COUNT(fTypefacesToUnref), typeface_cnt);
|
| + fTypefacesToUnref[0] = SkTypeface::CreateFromName("sans-serif", SkTypeface::kNormal);
|
| + fTypefacesToUnref[1] = SkTypeface::CreateFromName("sans-serif", SkTypeface::kBold);
|
| + fTypefacesToUnref[2] = SkTypeface::CreateFromName("serif", SkTypeface::kNormal);
|
| + fTypefacesToUnref[3] = SkTypeface::CreateFromName("serif", SkTypeface::kBold);
|
| +
|
| + SkRandom random;
|
| + for (int i = 0; i < kCnt; ++i) {
|
| + int length = random.nextRangeU(kMinLength, kMaxLength);
|
| + char text[kMaxLength];
|
| + for (int j = 0; j < length; ++j) {
|
| + text[j] = (char)random.nextRangeU('!', 'z');
|
| + }
|
| + fStrings[i].set(text, length);
|
| +
|
| + fColors[i] = random.nextU();
|
| + fColors[i] |= 0xFF000000;
|
| +
|
| + static const SkScalar kMinPtSize = 8.f;
|
| + static const SkScalar kMaxPtSize = 32.f;
|
| +
|
| + fPtSizes[i] = random.nextRangeScalar(kMinPtSize, kMaxPtSize);
|
| +
|
| + fTypefaces[i] = fTypefacesToUnref[
|
| + random.nextULessThan(SK_ARRAY_COUNT(fTypefacesToUnref))];
|
| +
|
| + SkRect r;
|
| + fPaint.setColor(fColors[i]);
|
| + fPaint.setTypeface(fTypefaces[i]);
|
| + fPaint.setTextSize(fPtSizes[i]);
|
| +
|
| + fPaint.measureText(fStrings[i].c_str(), fStrings[i].size(), &r);
|
| + // safeRect is set of x,y positions where we can draw the string without hitting
|
| + // the GM's border.
|
| + SkRect safeRect = SkRect::MakeLTRB(-r.fLeft, -r.fTop, w - r.fRight, h - r.fBottom);
|
| + if (safeRect.isEmpty()) {
|
| + // If we don't fit then just don't worry about how we get cliped to the device
|
| + // border.
|
| + safeRect = SkRect::MakeWH(w, h);
|
| + }
|
| + fPositions[i].fX = random.nextRangeScalar(safeRect.fLeft, safeRect.fRight);
|
| + fPositions[i].fY = random.nextRangeScalar(safeRect.fTop, safeRect.fBottom);
|
| +
|
| + fClipRects[i] = r;
|
| + fClipRects[i].offset(fPositions[i].fX, fPositions[i].fY);
|
| + fClipRects[i].outset(2.f, 2.f);
|
| +
|
| + if (fEffectiveClip) {
|
| + fClipRects[i].fRight -= 0.25f * fClipRects[i].width();
|
| + }
|
| + }
|
| + }
|
| +
|
| + virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
|
| + for (int i = 0; i < kCnt; ++i) {
|
| + fPaint.setColor(fColors[i]);
|
| + fPaint.setTextSize(fPtSizes[i]);
|
| + fPaint.setTypeface(fTypefaces[i]);
|
| +
|
| + canvas->save();
|
| + canvas->clipRect(fClipRects[i]);
|
| + canvas->translate(fPositions[i].fX, fPositions[i].fY);
|
| + canvas->drawText(fStrings[i].c_str(), fStrings[i].size(), 0, 0, fPaint);
|
| + canvas->restore();
|
| + }
|
| +
|
| + // Visualize the clips, but not in bench mode.
|
| + if (kBench_Mode != this->getMode()) {
|
| + SkPaint wirePaint;
|
| + wirePaint.setAntiAlias(true);
|
| + wirePaint.setStrokeWidth(0);
|
| + wirePaint.setStyle(SkPaint::kStroke_Style);
|
| + for (int i = 0; i < kCnt; ++i) {
|
| + canvas->drawRect(fClipRects[i], wirePaint);
|
| + }
|
| + }
|
| + }
|
| +
|
| + virtual uint32_t onGetFlags() const SK_OVERRIDE {
|
| + // The aa hairline stroked rects used to visualize the clip draw slightly differently in
|
| + // quilt mode in dm.
|
| + return kAsBench_Flag | kSkipTiled_Flag;
|
| + }
|
| +
|
| +private:
|
| + static const int kCnt = 30;
|
| + static const int kMinLength = 15;
|
| + static const int kMaxLength = 40;
|
| +
|
| + bool fEffectiveClip;
|
| + bool fLCD;
|
| + SkTypeface* fTypefacesToUnref[4];
|
| + SkPaint fPaint;
|
| +
|
| + // precomputed for each text draw
|
| + SkString fStrings[kCnt];
|
| + SkColor fColors[kCnt];
|
| + SkScalar fPtSizes[kCnt];
|
| + SkTypeface* fTypefaces[kCnt];
|
| + SkPoint fPositions[kCnt];
|
| + SkRect fClipRects[kCnt];
|
| +
|
| + typedef skiagm::GM INHERITED;
|
| +};
|
| +
|
| +DEF_GM( return SkNEW(VariedTextGM(false, false)); )
|
| +DEF_GM( return SkNEW(VariedTextGM(true, false)); )
|
| +DEF_GM( return SkNEW(VariedTextGM(false, true)); )
|
| +DEF_GM( return SkNEW(VariedTextGM(true, true)); )
|
|
|