/* * Copyright 2020 Google LLC * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "gm/gm.h" #include "include/core/SkCanvas.h" #include "include/core/SkFont.h" #include "include/core/SkPaint.h" #include "include/core/SkPath.h" #include "include/core/SkSize.h" #include "include/core/SkString.h" #include "include/utils/SkCustomTypeface.h" #include "tools/Resources.h" static sk_sp make_tf() { SkCustomTypefaceBuilder builder; SkFont font; const float upem = font.getTypefaceOrDefault()->getUnitsPerEm(); // request a big size, to improve precision at the fontscaler level font.setSize(upem); font.setHinting(SkFontHinting::kNone); // so we can scale our paths back down to 1-point const SkMatrix scale = SkMatrix::Scale(1.0f/upem, 1.0f/upem); { SkFontMetrics metrics; font.getMetrics(&metrics); builder.setMetrics(metrics, 1.0f/upem); } // Steal the first 128 chars from the default font for (SkGlyphID index = 0; index <= 127; ++index) { SkGlyphID glyph = font.unicharToGlyph(index); SkScalar width; font.getWidths(&glyph, 1, &width); SkPath path; font.getPath(glyph, &path); // we use the charcode to be our glyph index, since we have no cmap table builder.setGlyph(index, width/upem, path.makeTransform(scale)); } return builder.detach(); } #include "include/core/SkTextBlob.h" static sk_sp round_trip(sk_sp tf) { auto data = tf->serialize(); SkMemoryStream stream(data->data(), data->size()); return SkTypeface::MakeDeserialize(&stream); } class UserFontGM : public skiagm::GM { sk_sp fTF; public: UserFontGM() {} void onOnceBeforeDraw() override { fTF = make_tf(); // test serialization fTF = round_trip(fTF); } static sk_sp make_blob(sk_sp tf, float size, float* spacing) { SkFont font(tf); font.setSize(size); font.setEdging(SkFont::Edging::kAntiAlias); *spacing = font.getMetrics(nullptr); return SkTextBlob::MakeFromString("Typeface", font); } bool runAsBench() const override { return true; } SkString onShortName() override { return SkString("user_typeface"); } SkISize onISize() override { return {810, 452}; } void onDraw(SkCanvas* canvas) override { auto waterfall = [&](sk_sp tf) { SkPaint paint; paint.setAntiAlias(true); float spacing; float x = 20, y = 16; for (float size = 9; size <= 100; size *= 1.25f) { auto blob = make_blob(tf, size, &spacing); // shared baseline if (tf == nullptr) { paint.setColor(0xFFDDDDDD); canvas->drawRect({0, y, 810, y+1}, paint); } paint.setColor(0xFFCCCCCC); paint.setStyle(SkPaint::kStroke_Style); canvas->drawRect(blob->bounds().makeOffset(x, y), paint); paint.setStyle(SkPaint::kFill_Style); paint.setColor(SK_ColorBLACK); canvas->drawTextBlob(blob, x, y, paint); y += SkScalarRoundToInt(spacing * 1.25f + 2); } }; waterfall(nullptr); canvas->translate(400, 0); waterfall(fTF); } }; DEF_GM(return new UserFontGM;)