Skip to content

Commit

Permalink
Add stub Fontations SkTypeface backend
Browse files Browse the repository at this point in the history
Preparation for using Rust code to fill the actual functionality. At the
moment, this backend can draw a single outline, emulating drawing the
capital H from Roboto Regular, and emulating Roboto Regular font
metrics.

The code is to a large extent taken from TestTypeface code in
tools/fonts but is intended to be filled and replaced with Rust logic from
src/ports/fontations/* in forthcoming CLs.

Define build flag use_fontations for GN and bazel, add a bazel alias
--with_fontations for enabling building of this backend.

Add a GM test (for the GN build) which directly instantiates this
typeface and draws three instances of the H glyphs at different sizes.

Bug: skia:14257
Change-Id: I6460e70b2dac8665e4d7f7171bad9b43b8d93c84
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/662076
Reviewed-by: Kevin Lubick <[email protected]>
Reviewed-by: Ben Wagner <[email protected]>
Commit-Queue: Dominik Röttsches <[email protected]>
  • Loading branch information
drott authored and SkCQ committed Apr 14, 2023
1 parent fcb72b8 commit 1f8bee3
Show file tree
Hide file tree
Showing 10 changed files with 294 additions and 0 deletions.
1 change: 1 addition & 0 deletions .bazelrc
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ build --flag_alias=enable_vma=//src/gpu:use_vulkan_memory_allocator
build --flag_alias=with_default_global_memory_pool=//src/lazy:use_default_global_memory_pool
build --flag_alias=with_no_global_memory_pool=no//src/lazy:use_default_global_memory_pool
build --flag_alias=with_harfbuzz=//bazel/common_config_settings:use_harfbuzz
build --flag_alias=with_fontations=//bazel/common_config_settings:use_fontations
build --flag_alias=with_no_harfbuzz=no//bazel/common_config_settings:use_harfbuzz
build --flag_alias=with_icu=//bazel/common_config_settings:use_icu
build --flag_alias=with_no_icu=no//bazel/common_config_settings:use_icu
Expand Down
15 changes: 15 additions & 0 deletions BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -1388,6 +1388,14 @@ optional("typeface_freetype") {
]
}

optional("typeface_fontations") {
enabled = skia_use_fontations
sources = [
"src/ports/SkTypeface_fontations.cpp",
"src/ports/SkTypeface_fontations.h",
]
}

optional("webp_decode") {
enabled = skia_use_libwebp_decode
public_defines = [ "SK_CODEC_DECODES_WEBP" ]
Expand Down Expand Up @@ -1639,6 +1647,10 @@ skia_component("skia") {
defines += [ "SK_ENABLE_SPIRV_VALIDATION" ]
}

if (skia_use_fontations) {
deps += [ ":typeface_fontations" ]
}

if (skia_include_multiframe_procs) {
sources += [ "tools/SkSharingProc.cpp" ]
}
Expand Down Expand Up @@ -2215,6 +2227,9 @@ if (skia_enable_tools) {
if (!skia_enable_ganesh) {
sources -= ganesh_gm_sources
}
if (skia_use_fontations) {
sources += fontations_gm_sources
}
deps = [
":etc1",
":flags",
Expand Down
5 changes: 5 additions & 0 deletions bazel/common_config_settings/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,11 @@ bool_flag(
default = False,
)

bool_flag(
name = "use_fontations",
default = False,
)

bool_flag(
name = "use_icu",
default = False,
Expand Down
75 changes: 75 additions & 0 deletions gm/fontations.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*
* Copyright 2023 Google Inc.
*
* 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/SkRefCnt.h"
#include "include/core/SkTypeface.h"
#include "src/ports/SkTypeface_fontations.h"

namespace skiagm {

namespace {
const SkScalar kTextSizes[] = {12, 18, 30, 120};

} // namespace

class FontationsTypefaceGM : public GM {
public:
FontationsTypefaceGM() { this->setBGColor(SK_ColorWHITE); }

protected:
void onOnceBeforeDraw() override { fTypeface = sk_sp<SkTypeface>(new SkTypeface_Fontations()); }

SkString onShortName() override { return SkString("typeface_fontations"); }

SkISize onISize() override { return SkISize::Make(400, 200); }

DrawResult onDraw(SkCanvas* canvas, SkString* errorMsg) override {
SkPaint paint;
paint.setColor(SK_ColorBLACK);

if (!fTypeface) {
*errorMsg = "Unable to initialize typeface.";
return DrawResult::kSkip;
}

SkFont font(fTypeface);
uint16_t glyphs[] = {1, 1, 1};
SkScalar x = 100;
SkScalar y = 150;

for (SkScalar textSize : kTextSizes) {
font.setSize(textSize);
y += font.getSpacing();

/* Draw origin marker as a green dot. */
paint.setColor(SK_ColorGREEN);
canvas->drawRect(SkRect::MakeXYWH(x, y, 2, 2), paint);
paint.setColor(SK_ColorBLACK);

canvas->drawSimpleText(glyphs,
sizeof(uint16_t) * std::size(glyphs),
SkTextEncoding::kGlyphID,
x,
y,
font,
paint);
}

return DrawResult::kOk;
}

private:
using INHERITED = GM;

sk_sp<SkTypeface> fTypeface;
};

DEF_GM(return new FontationsTypefaceGM();)

} // namespace skiagm
2 changes: 2 additions & 0 deletions gn/gm.gni
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,8 @@ gm_sources = [

gl_gm_sources = [ "$_gm/rectangletexture.cpp" ]

fontations_gm_sources = [ "$_gm/fontations.cpp" ]

ganesh_gm_sources = [
"$_gm/aarecteffect.cpp",
"$_gm/attributes.cpp",
Expand Down
1 change: 1 addition & 0 deletions gn/skia.gni
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ declare_args() {
skia_use_ffmpeg = false
skia_use_fixed_gamma_text = is_android
skia_use_fontconfig = is_linux
skia_use_fontations = false
skia_use_fonthost_mac = is_mac || is_ios
skia_use_freetype = is_android || is_fuchsia || is_linux || is_wasm
skia_use_harfbuzz = true
Expand Down
1 change: 1 addition & 0 deletions src/core/SkGlyph.h
Original file line number Diff line number Diff line change
Expand Up @@ -554,6 +554,7 @@ class SkGlyph {
friend class SkTestScalerContext;
friend class SkTestSVGScalerContext;
friend class SkUserScalerContext;
friend class SkFontationsScalerContext;
friend class TestSVGTypeface;
friend class TestTypeface;
friend class SkGlyphTestPeer;
Expand Down
20 changes: 20 additions & 0 deletions src/ports/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,16 @@ skia_filegroup(
],
)

skia_filegroup(
name = "typeface_fontations",
srcs = select({
"//bazel/common_config_settings:use_fontations_true": [
"SkTypeface_fontations.cpp",
],
"//conditions:default": [],
}),
)

# There can only be one FontMgr Factory, but multiple different types of FontMgr compiled into
# a single build.
skia_filegroup(
Expand Down Expand Up @@ -257,6 +267,7 @@ skia_filegroup(
":malloc",
":osfile",
":skdebug",
":typeface_fontations",
],
visibility = ["//src:__pkg__"],
)
Expand All @@ -281,6 +292,11 @@ skia_filegroup(
"SkFontConfigTypeface.h",
],
"//conditions:default": [],
}) + select({
"//bazel/common_config_settings:use_fontations_true": [
"SkTypeface_fontations.h",
],
"//conditions:default": [],
}),
visibility = ["//src:__pkg__"],
)
Expand Down Expand Up @@ -324,6 +340,10 @@ skia_cc_deps(
}) + select({
"//bazel/common_config_settings:uses_android_fontmgr": ["@expat"],
"//conditions:default": [],
}) + select({
"//bazel/common_config_settings:use_fontations_true": [
],
"//conditions:default": [],
}),
)

Expand Down
112 changes: 112 additions & 0 deletions src/ports/SkTypeface_fontations.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
/*
* Copyright 2023 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/SkFontMetrics.h"
#include "src/core/SkFontPriv.h"
#include "src/ports/SkTypeface_fontations.h"

namespace {
/* Placeholder glyph example until we extract paths through fontations, representing the capital H
* from Roboto Regular. */
void drawCapitalH(SkPath* path) {
path->setFillType(SkPathFillType::kWinding);
path->moveTo(1096, -0);
path->lineTo(1096, -673);
path->lineTo(362, -673);
path->lineTo(362, -0);
path->lineTo(169, -0);
path->lineTo(169, -1456);
path->lineTo(362, -1456);
path->lineTo(362, -830);
path->lineTo(1096, -830);
path->lineTo(1096, -1456);
path->lineTo(1288, -1456);
path->lineTo(1288, -0);
path->lineTo(1096, -0);
path->close();
}

constexpr SkScalar capitalHAdvance = 1461;
}

int SkTypeface_Fontations::onGetUPEM() const { return 2048; }

void SkTypeface_Fontations::onCharsToGlyphs(const SkUnichar* chars,
int count,
SkGlyphID glyphs[]) const {
sk_bzero(glyphs, count * sizeof(glyphs[0]));
}

void SkTypeface_Fontations::onFilterRec(SkScalerContextRec* rec) const {
rec->setHinting(SkFontHinting::kNone);
}

class SkFontationsScalerContext : public SkScalerContext {
public:
SkFontationsScalerContext(sk_sp<SkTypeface_Fontations> face,
const SkScalerContextEffects& effects,
const SkDescriptor* desc)
: SkScalerContext(std::move(face), effects, desc) {
fRec.getSingleMatrix(&fMatrix);
this->forceGenerateImageFromPath();
}

protected:

bool generateAdvance(SkGlyph* glyph) override {
const SkVector advance = fMatrix.mapXY(capitalHAdvance / getTypeface()->getUnitsPerEm(),
SkFloatToScalar(0.f));
glyph->fAdvanceX = SkScalarToFloat(advance.fX);
glyph->fAdvanceY = SkScalarToFloat(advance.fY);
return true;
}

void generateMetrics(SkGlyph* glyph, SkArenaAlloc*) override {
glyph->fMaskFormat = fRec.fMaskFormat;
glyph->zeroMetrics();
this->generateAdvance(glyph);
// Always generates from paths, so SkScalerContext::makeGlyph will figure the bounds.
}

void generateImage(const SkGlyph&) override { SK_ABORT("Should have generated from path."); }

bool generatePath(const SkGlyph& glyph, SkPath* path) override {
drawCapitalH(path);
SkMatrix scaled = fMatrix.preScale(1.0f / getTypeface()->getUnitsPerEm(),
1.0f / getTypeface()->getUnitsPerEm());
*path = path->makeTransform(scaled);
return true;
}

void generateFontMetrics(SkFontMetrics* metrics) override {
/* Hard-coded Roboto Regular metrics, to be replaced with Fontations calls. */
metrics->fTop = -2163.f / getTypeface()->getUnitsPerEm();
metrics->fAscent = -2146.f / getTypeface()->getUnitsPerEm();
metrics->fDescent = 555.f / getTypeface()->getUnitsPerEm();
metrics->fBottom = 555.f / getTypeface()->getUnitsPerEm();
metrics->fLeading = 0;
metrics->fAvgCharWidth = 0;
metrics->fMaxCharWidth = 0;
metrics->fXMin = -1825.f / getTypeface()->getUnitsPerEm();
metrics->fXMax = 4188.f / getTypeface()->getUnitsPerEm();
metrics->fXHeight = -1082.f / getTypeface()->getUnitsPerEm();
metrics->fCapHeight = -1456.f / getTypeface()->getUnitsPerEm();
metrics->fFlags = 0;

SkFontPriv::ScaleFontMetrics(metrics, fMatrix.getScaleY());
}

private:
SkMatrix fMatrix;
};

std::unique_ptr<SkScalerContext> SkTypeface_Fontations::onCreateScalerContext(
const SkScalerContextEffects& effects, const SkDescriptor* desc) const
{
return std::make_unique<SkFontationsScalerContext>(
sk_ref_sp(const_cast<SkTypeface_Fontations*>(this)), effects, desc);
}
62 changes: 62 additions & 0 deletions src/ports/SkTypeface_fontations.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
* Copyright 2023 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/

#ifndef SkTypeface_Fontations_DEFINED
#define SkTypeface_Fontations_DEFINED

#include "include/core/SkStream.h"
#include "include/core/SkTypeface.h"
#include "src/core/SkAdvancedTypefaceMetrics.h"
#include "src/core/SkScalerContext.h"

/** SkTypeface implementation based on Google Fonts Fontations Rust libraries. */
class SkTypeface_Fontations : public SkTypeface {
public:
static sk_sp<SkTypeface> Make() { return sk_sp<SkTypeface>(new SkTypeface_Fontations); }
SkTypeface_Fontations() : SkTypeface(SkFontStyle(), true) {}

protected:

std::unique_ptr<SkStreamAsset> onOpenStream(int* ttcIndex) const override { return nullptr; }
sk_sp<SkTypeface> onMakeClone(const SkFontArguments& args) const override {
return sk_ref_sp(this);
}
std::unique_ptr<SkScalerContext> onCreateScalerContext(const SkScalerContextEffects& effects,
const SkDescriptor* desc) const override;
void onFilterRec(SkScalerContextRec*) const override;
std::unique_ptr<SkAdvancedTypefaceMetrics> onGetAdvancedMetrics() const override {
return nullptr;
}
void onGetFontDescriptor(SkFontDescriptor*, bool*) const override {}
void onCharsToGlyphs(const SkUnichar* chars, int count, SkGlyphID glyphs[]) const override;
int onCountGlyphs() const override { return 1; }
void getPostScriptGlyphNames(SkString*) const override {}
void getGlyphToUnicodeMap(SkUnichar*) const override {}
int onGetUPEM() const override;
class EmptyLocalizedStrings : public SkTypeface::LocalizedStrings {
public:
bool next(SkTypeface::LocalizedString*) override { return false; }
};
void onGetFamilyName(SkString* familyName) const override { familyName->reset(); }
bool onGetPostScriptName(SkString*) const override { return false; }
SkTypeface::LocalizedStrings* onCreateFamilyNameIterator() const override {
return new EmptyLocalizedStrings;
}
bool onGlyphMaskNeedsCurrentColor() const override { return false; }
int onGetVariationDesignPosition(SkFontArguments::VariationPosition::Coordinate coordinates[],
int coordinateCount) const override {
return 0;
}
int onGetVariationDesignParameters(SkFontParameters::Variation::Axis parameters[],
int parameterCount) const override {
return 0;
}
int onGetTableTags(SkFontTableTag tags[]) const override { return 0; }
size_t onGetTableData(SkFontTableTag, size_t, size_t, void*) const override { return 0; }
};

#endif // SkTypeface_Fontations_DEFINED

0 comments on commit 1f8bee3

Please sign in to comment.