Index: gm/textblobmixedsizes.cpp |
diff --git a/gm/textblobmixedsizes.cpp b/gm/textblobmixedsizes.cpp |
new file mode 100644 |
index 0000000000000000000000000000000000000000..9d91b6125c92981aa7ef28b919f9747ea7a585fe |
--- /dev/null |
+++ b/gm/textblobmixedsizes.cpp |
@@ -0,0 +1,191 @@ |
+/* |
+ * Copyright 2015 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 "Resources.h" |
+#include "SkBlurMask.h" |
+#include "SkBlurMaskFilter.h" |
+#include "SkCanvas.h" |
+#include "SkGradientShader.h" |
+#include "SkImage.h" |
+#include "SkRandom.h" |
+#include "SkStream.h" |
+#include "SkSurface.h" |
+#include "SkTextBlob.h" |
+#include "SkTypeface.h" |
+ |
+namespace skiagm { |
+class TextBlobMixedSizes : public GM { |
+public: |
+ // This gm tests that textblobs of mixed sizes with a large glyph will render properly |
+ TextBlobMixedSizes(bool useDFT) : fUseDFT(useDFT) {} |
+ |
+protected: |
+ void onOnceBeforeDraw() override { |
+ SkAutoTUnref<SkTypeface> typeface(GetResourceAsTypeface("/fonts/HangingS.ttf")); |
+ SkTextBlobBuilder builder; |
+ |
+ // make textblob. To stress distance fields, we choose sizes appropriately |
+ SkPaint paint; |
+ paint.setAntiAlias(true); |
+ paint.setSubpixelText(true); |
+ paint.setLCDRenderText(true); |
+ paint.setTypeface(typeface); |
+ |
+ const char* text = "Sk"; |
+ |
+ // extra large |
+ paint.setTextSize(262); |
+ |
+ sk_tool_utils::add_to_text_blob(&builder, text, paint, 0, 0); |
+ |
+ // large |
+ SkRect bounds; |
+ paint.measureText(text, strlen(text), &bounds); |
+ SkScalar yOffset = bounds.height(); |
+ paint.setTextSize(162); |
+ |
+ sk_tool_utils::add_to_text_blob(&builder, text, paint, 0, yOffset); |
+ |
+ // Medium |
+ paint.measureText(text, strlen(text), &bounds); |
+ yOffset += bounds.height(); |
+ paint.setTextSize(72); |
+ |
+ sk_tool_utils::add_to_text_blob(&builder, text, paint, 0, yOffset); |
+ |
+ // Small |
+ paint.measureText(text, strlen(text), &bounds); |
+ yOffset += bounds.height(); |
+ paint.setTextSize(32); |
+ |
+ sk_tool_utils::add_to_text_blob(&builder, text, paint, 0, yOffset); |
+ |
+ // micro (will fall out of distance field text even if distance field text is enabled) |
+ paint.measureText(text, strlen(text), &bounds); |
+ yOffset += bounds.height(); |
+ paint.setTextSize(14); |
+ |
+ sk_tool_utils::add_to_text_blob(&builder, text, paint, 0, yOffset); |
+ |
+ // build |
+ fBlob.reset(builder.build()); |
+ } |
+ |
+ SkString onShortName() override { |
+ SkString name("textblobmixedsizes"); |
+ if (fUseDFT) { |
+ name.appendf("_df"); |
+ } |
+ return name; |
+ } |
+ |
+ SkISize onISize() override { |
+ return SkISize::Make(kWidth, kHeight); |
+ } |
+ |
+ void onDraw(SkCanvas* inputCanvas) override { |
+ SkCanvas* canvas = inputCanvas; |
+ SkAutoTUnref<SkSurface> surface; |
+ if (fUseDFT) { |
+#if SK_SUPPORT_GPU |
+ // Create a new Canvas to enable DFT |
+ GrContext* ctx = inputCanvas->getGrContext(); |
+ SkImageInfo info = SkImageInfo::MakeN32Premul(onISize()); |
+ SkSurfaceProps props(SkSurfaceProps::kUseDistanceFieldFonts_Flag, |
+ SkSurfaceProps::kLegacyFontHost_InitType); |
+ surface.reset(SkSurface::NewRenderTarget(ctx, SkSurface::kNo_Budgeted, info, 0, |
+ &props)); |
+ canvas = surface.get() ? surface->getCanvas() : inputCanvas; |
+ // init our new canvas with the old canvas's matrix |
+ canvas->setMatrix(inputCanvas->getTotalMatrix()); |
+#endif |
+ } |
+ canvas->drawColor(sk_tool_utils::color_to_565(SK_ColorWHITE)); |
+ |
+ SkRect bounds = fBlob->bounds(); |
+ |
+ static const int kPadX = SkScalarFloorToInt(bounds.width() / 3); |
+ static const int kPadY = SkScalarFloorToInt(bounds.height() / 3); |
+ |
+ int rowCount = 0; |
+ canvas->translate(SkIntToScalar(kPadX), SkIntToScalar(kPadY)); |
+ canvas->save(); |
+ SkRandom random; |
+ |
+ SkPaint paint; |
+ if (!fUseDFT) { |
+ paint.setColor(sk_tool_utils::color_to_565(SK_ColorWHITE)); |
+ } |
+ paint.setAntiAlias(false); |
+ |
+ static const SkScalar kSigma = SkBlurMask::ConvertRadiusToSigma(SkIntToScalar(8)); |
+ |
+ // setup blur paint |
+ SkPaint blurPaint(paint); |
+ blurPaint.setColor(sk_tool_utils::color_to_565(SK_ColorBLACK)); |
+ SkAutoTUnref<SkMaskFilter> mf(SkBlurMaskFilter::Create(kNormal_SkBlurStyle, kSigma)); |
+ blurPaint.setMaskFilter(mf); |
+ |
+ for (int i = 0; i < 4; i++) { |
+ canvas->save(); |
+ switch (i % 2) { |
+ case 0: |
+ canvas->rotate(random.nextF() * 45.f); |
+ break; |
+ case 1: |
+ canvas->rotate(-random.nextF() * 45.f); |
+ break; |
+ } |
+ if (!fUseDFT) { |
+ canvas->drawTextBlob(fBlob, 0, 0, blurPaint); |
+ } |
+ canvas->drawTextBlob(fBlob, 0, 0, paint); |
+ canvas->restore(); |
+ canvas->translate(bounds.width() + SK_Scalar1 * kPadX, 0); |
+ ++rowCount; |
+ if ((bounds.width() + 2 * kPadX) * rowCount > kWidth) { |
+ canvas->restore(); |
+ canvas->translate(0, bounds.height() + SK_Scalar1 * kPadY); |
+ canvas->save(); |
+ rowCount = 0; |
+ } |
+ } |
+ canvas->restore(); |
+ |
+#if SK_SUPPORT_GPU |
+ // render offscreen buffer |
+ if (surface) { |
+ SkAutoCanvasRestore acr(inputCanvas, true); |
+ // since we prepended this matrix already, we blit using identity |
+ inputCanvas->resetMatrix(); |
+ SkImage* image = surface->newImageSnapshot(); |
+ inputCanvas->drawImage(image, 0, 0, NULL); |
+ image->unref(); |
+ } |
+#endif |
+ } |
+ |
+private: |
+ SkAutoTUnref<const SkTextBlob> fBlob; |
+ |
+ static const int kWidth = 2000; |
+ static const int kHeight = 2000; |
+ |
+ bool fUseDFT; |
+ |
+ typedef GM INHERITED; |
+}; |
+ |
+////////////////////////////////////////////////////////////////////////////// |
+ |
+DEF_GM( return SkNEW_ARGS(TextBlobMixedSizes, (false)); ) |
+#if SK_SUPPORT_GPU |
+DEF_GM( return SkNEW_ARGS(TextBlobMixedSizes, (true)); ) |
+#endif |
+} |