skia2/gm/userfont.cpp
Ben Wagner 81eabce6a3 SkCustomTypefaceBuilder to set SkFontStyle
Allow the user of SkCustomTypefaceBuilder to set the SkFontStyle of the
resulting SkTypeface. This allows users to build font families.

Fix the Font_flatten test to actually work (instead of relying on the
magic behavior of nullptr for SkTypeface), add a test with the custom
typeface, and reduce the number of times the inner loop runs from
302,400 times to 4,032 times so that the test finishes in a reasonable
amount of time.

Bug: skia:10630
Change-Id: I0b5e939552ee4a9a1249eefbb7a7279a59b38e5a
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/311596
Commit-Queue: Ben Wagner <bungeman@google.com>
Reviewed-by: Xiao Yu <xster@google.com>
Reviewed-by: Mike Klein <mtklein@google.com>
2020-08-19 00:09:55 +00:00

122 lines
3.5 KiB
C++

/*
* 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<SkTypeface> 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);
}
builder.setFontStyle(font.getTypefaceOrDefault()->fontStyle());
// 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<SkTypeface> round_trip(sk_sp<SkTypeface> tf) {
auto data = tf->serialize();
SkMemoryStream stream(data->data(), data->size());
return SkTypeface::MakeDeserialize(&stream);
}
class UserFontGM : public skiagm::GM {
sk_sp<SkTypeface> fTF;
public:
UserFontGM() {}
void onOnceBeforeDraw() override {
fTF = make_tf();
// test serialization
fTF = round_trip(fTF);
}
static sk_sp<SkTextBlob> make_blob(sk_sp<SkTypeface> 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<SkTypeface> 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;)