/* * 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 "include/core/SkCanvas.h" #include "include/core/SkColorFilter.h" #include "include/core/SkColorPriv.h" #include "include/core/SkFont.h" #include "include/core/SkImage.h" #include "include/core/SkTime.h" #include "include/core/SkTypeface.h" #include "include/utils/SkRandom.h" #include "samplecode/Sample.h" #include "src/utils/SkUTF.h" #if SK_SUPPORT_GPU #include "include/gpu/GrDirectContext.h" #include "src/gpu/ganesh/GrDirectContextPriv.h" using MaskFormat = skgpu::MaskFormat; #endif SkRandom gRand; static void DrawTheText(SkCanvas* canvas, const char text[], size_t length, SkScalar x, SkScalar y, const SkFont& font, const SkPaint& paint) { SkFont f(font); f.setSubpixel(true); canvas->drawSimpleText(text, length, SkTextEncoding::kUTF8, x, y, f, paint); } // This sample demonstrates the cache behavior of bitmap vs. distance field text // It renders variously sized text with an animated scale and rotation. // Specifically one should: // use 'D' to toggle between bitmap and distance field fonts // use '2' to toggle between scaling the image by 2x // -- this feature boosts the rendering out of the small point-size // SDF-text special case (which falls back to bitmap fonts for small points) class AnimatedTextView : public Sample { float fScale = 1; float fScaleInc = 0.1f; float fRotation = 0; int fSizeScale = 1; SkString name() override { return SkString("AnimatedText"); } bool onChar(SkUnichar uni) override { if ('2' == uni) { if (fSizeScale == 2) { fSizeScale = 1; } else { fSizeScale = 2; } return true; } return false; } void onDrawContent(SkCanvas* canvas) override { SkFont font(SkTypeface::MakeFromFile("/skimages/samplefont.ttf")); SkPaint paint; paint.setAntiAlias(true); canvas->save(); #if SK_SUPPORT_GPU auto direct = GrAsDirectContext(canvas->recordingContext()); if (direct) { SkSamplingOptions sampling(SkFilterMode::kLinear, SkMipmapMode::kNearest); sk_sp image = direct->priv().testingOnly_getFontAtlasImage(MaskFormat::kA8); const SkRect rect = SkRect::MakeXYWH(512.0f, 10.0f, 512.0f, 512.0f); canvas->drawImageRect(image.get(), rect, rect, sampling, &paint, SkCanvas::kFast_SrcRectConstraint); } #endif canvas->translate(180, 180); canvas->rotate(fRotation); canvas->scale(fScale, fScale); canvas->translate(-180, -180); const char* text = "Hamburgefons"; size_t length = strlen(text); SkScalar y = SkIntToScalar(0); for (int i = 12; i <= 26; i++) { font.setSize(SkIntToScalar(i*fSizeScale)); y += font.getSpacing(); DrawTheText(canvas, text, length, SkIntToScalar(110), y, font, paint); } canvas->restore(); font.setSize(16); } bool onAnimate(double nanos) override { // TODO: use nanos // We add noise to the scale and rotation animations to // keep the font atlas from falling into a steady state fRotation += (1.0f + gRand.nextRangeF(-0.1f, 0.1f)); fScale += (fScaleInc + gRand.nextRangeF(-0.025f, 0.025f)); if (fScale >= 2.0f) { fScaleInc = -0.1f; } else if (fScale <= 1.0f) { fScaleInc = 0.1f; } return true; } }; DEF_SAMPLE( return new AnimatedTextView(); )