1
0
Fork 0
mirror of https://github.com/LadybirdBrowser/ladybird.git synced 2025-06-08 05:27:14 +09:00

LibGfx+LibWeb: Update definitions of supported font formats and features

Based very scientifically on what's listed here:
https://harfbuzz.github.io/what-does-harfbuzz-do.html

I've moved the code into LibGfx because including a HarfBuzz header
directly from LibWeb is a little unpleasant. But the Gfx::FontTech enum
follows the CSS definitions for font features for simplicity.

TrueType collections are supported. SVG and Embedded OpenType are not,
but they're not widely supported by other browsers so that's fine.

Most of the features are completely supported by HarfBuzz, so we can
just return true. Graphite support is optional (and it appears we use a
build of HarfBuzz without it) but there's a define we can check.
Incremental Font Transfer is a whole separate thing that we definitely
don't support yet.
This commit is contained in:
Sam Atkins 2025-06-03 15:48:24 +01:00
parent ea101c6336
commit 5a1c73d7e2
Notes: github-actions[bot] 2025-06-05 11:39:09 +00:00
6 changed files with 155 additions and 32 deletions

View file

@ -14,6 +14,7 @@ set(SOURCES
Font/Font.cpp
Font/FontData.cpp
Font/FontDatabase.cpp
Font/FontSupport.cpp
Font/PathFontProvider.cpp
Font/Typeface.cpp
Font/TypefaceSkia.cpp

View file

@ -0,0 +1,84 @@
/*
* Copyright (c) 2025, Sam Atkins <sam@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibGfx/Font/FontSupport.h>
#include <harfbuzz/hb.h>
namespace Gfx {
bool font_format_is_supported(FontFormat const format)
{
// FIXME: Determine these automatically.
switch (format) {
case FontFormat::EmbeddedOpenType:
return false;
case FontFormat::OpenType:
return true;
case FontFormat::SVG:
return false;
case FontFormat::TrueType:
return true;
case FontFormat::TrueTypeCollection:
return true;
case FontFormat::WOFF:
return true;
case FontFormat::WOFF2:
return true;
}
return false;
}
bool font_tech_is_supported(FontTech const font_tech)
{
// https://drafts.csswg.org/css-fonts-4/#font-tech-definitions
// FIXME: Determine these automatically.
switch (font_tech) {
case FontTech::FeaturesOpentype:
// GSUB and GPOS, supported by HarfBuzz
return true;
case FontTech::FeaturesAat:
// morx and kerx, supported by HarfBuzz
return true;
case FontTech::FeaturesGraphite:
// Silf, Glat , Gloc , Feat and Sill. HarfBuzz may or may not be built with support for it.
#if HB_HAS_GRAPHITE
return true;
#else
return false;
#endif
case FontTech::Variations:
// avar, cvar, fvar, gvar, HVAR, MVAR, STAT, and VVAR, supported by HarfBuzz
return true;
case FontTech::ColorColrv0:
case FontTech::ColorColrv1:
// COLR, supported by HarfBuzz
return true;
case FontTech::ColorSvg:
// SVG, supported by HarfBuzz
return true;
case FontTech::ColorSbix:
// sbix, supported by HarfBuzz
return true;
case FontTech::ColorCbdt:
// CBDT, supported by HarfBuzz
return true;
case FontTech::Palettes:
// CPAL, supported by HarfBuzz
return true;
case FontTech::Incremental:
// Incremental Font Transfer: https://w3c.github.io/IFT/Overview.html
return false;
// https://drafts.csswg.org/css-fonts-5/#font-tech-definitions
case FontTech::Avar2:
// avar version 2, supported by HarfBuzz
return true;
}
return false;
}
}

View file

@ -0,0 +1,41 @@
/*
* Copyright (c) 2025, Sam Atkins <sam@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/Types.h>
namespace Gfx {
enum class FontFormat : u8 {
EmbeddedOpenType,
OpenType,
SVG,
TrueType,
TrueTypeCollection,
WOFF,
WOFF2,
};
enum class FontTech : u8 {
Avar2,
ColorCbdt,
ColorColrv0,
ColorColrv1,
ColorSbix,
ColorSvg,
FeaturesAat,
FeaturesGraphite,
FeaturesOpentype,
Incremental,
Palettes,
Variations,
};
bool font_format_is_supported(FontFormat);
bool font_tech_is_supported(FontTech);
}

View file

@ -8,6 +8,7 @@
#include <AK/ByteBuffer.h>
#include <LibCore/Promise.h>
#include <LibGC/Heap.h>
#include <LibGfx/Font/FontSupport.h>
#include <LibGfx/Font/Typeface.h>
#include <LibGfx/Font/WOFF/Loader.h>
#include <LibGfx/Font/WOFF2/Loader.h>
@ -516,54 +517,52 @@ GC::Ref<WebIDL::Promise> FontFace::load()
bool font_format_is_supported(FlyString const& name)
{
// https://drafts.csswg.org/css-fonts-4/#font-format-definitions
// FIXME: Determine this automatically somehow?
if (name.equals_ignoring_ascii_case("collection"sv))
return false;
return Gfx::font_format_is_supported(Gfx::FontFormat::TrueTypeCollection);
if (name.equals_ignoring_ascii_case("embedded-opentype"sv))
return false;
return Gfx::font_format_is_supported(Gfx::FontFormat::EmbeddedOpenType);
if (name.equals_ignoring_ascii_case("opentype"sv))
return true;
return Gfx::font_format_is_supported(Gfx::FontFormat::OpenType);
if (name.equals_ignoring_ascii_case("svg"sv))
return false;
return Gfx::font_format_is_supported(Gfx::FontFormat::SVG);
if (name.equals_ignoring_ascii_case("truetype"sv))
return true;
return Gfx::font_format_is_supported(Gfx::FontFormat::TrueType);
if (name.equals_ignoring_ascii_case("woff"sv))
return true;
return Gfx::font_format_is_supported(Gfx::FontFormat::WOFF);
if (name.equals_ignoring_ascii_case("woff2"sv))
return true;
return Gfx::font_format_is_supported(Gfx::FontFormat::WOFF2);
return false;
}
bool font_tech_is_supported(FontTech font_tech)
{
// https://drafts.csswg.org/css-fonts-4/#font-tech-definitions
// FIXME: Determine this automatically somehow?
switch (font_tech) {
case FontTech::FeaturesOpentype:
return true;
return Gfx::font_tech_is_supported(Gfx::FontTech::FeaturesOpentype);
case FontTech::FeaturesAat:
return false;
return Gfx::font_tech_is_supported(Gfx::FontTech::FeaturesAat);
case FontTech::FeaturesGraphite:
return false;
return Gfx::font_tech_is_supported(Gfx::FontTech::FeaturesGraphite);
case FontTech::Variations:
return true;
return Gfx::font_tech_is_supported(Gfx::FontTech::Variations);
case FontTech::ColorColrv0:
return true;
return Gfx::font_tech_is_supported(Gfx::FontTech::ColorColrv0);
case FontTech::ColorColrv1:
return true;
return Gfx::font_tech_is_supported(Gfx::FontTech::ColorColrv1);
case FontTech::ColorSvg:
return false;
return Gfx::font_tech_is_supported(Gfx::FontTech::ColorSvg);
case FontTech::ColorSbix:
return false;
return Gfx::font_tech_is_supported(Gfx::FontTech::ColorSbix);
case FontTech::ColorCbdt:
return false;
return Gfx::font_tech_is_supported(Gfx::FontTech::ColorCbdt);
case FontTech::Palettes:
return false;
return Gfx::font_tech_is_supported(Gfx::FontTech::Palettes);
case FontTech::Incremental:
return false;
return Gfx::font_tech_is_supported(Gfx::FontTech::Incremental);
// https://drafts.csswg.org/css-fonts-5/#font-tech-definitions
case FontTech::Avar2:
return false;
return Gfx::font_tech_is_supported(Gfx::FontTech::Avar2);
}
return false;
}

View file

@ -2,21 +2,20 @@ Harness status: OK
Found 35 tests
33 Pass
2 Fail
35 Pass
Pass Check that src: url("foo.ttf") is valid
Pass Check that src: url("foo.ttf"), url("bar.ttf") is valid
Pass Check that src: url("foo.ttf") format() is invalid
Pass Check that src: url("foo.ttf") dummy() is invalid
Pass Check that src: url("foo.ttf") format("woff") dummy() is invalid
Pass Check that src: url("foo.ttf") dummy() format("woff") is invalid
Fail Check that src: url("foo.ttf") format("collection") is valid
Pass Check that src: url("foo.ttf") format("collection") is valid
Pass Check that src: url("foo.ttf") format("opentype") is valid
Pass Check that src: url("foo.ttf") format("truetype") is valid
Pass Check that src: url("foo.ttf") format("woff") is valid
Pass Check that src: url("foo.ttf") format("woff2") is valid
Pass Check that src: url("foo.ttf") format("opentype", "truetype") is invalid
Fail Check that src: url("foo.ttf") format(collection) is valid
Pass Check that src: url("foo.ttf") format(collection) is valid
Pass Check that src: url("foo.ttf") format(opentype) is valid
Pass Check that src: url("foo.ttf") format(truetype) is valid
Pass Check that src: url("foo.ttf") format(woff) is valid

View file

@ -2,22 +2,21 @@ Harness status: OK
Found 39 tests
34 Pass
5 Fail
39 Pass
Pass Check that src: url("foo.ttf") is valid
Pass Check that src: url("foo.ttf") tech() is invalid
Pass Check that src: url("foo.ttf") tech(features-opentype) is valid
Fail Check that src: url("foo.ttf") tech(features-aat) is valid
Pass Check that src: url("foo.ttf") tech(features-aat) is valid
Pass Check that src: url("foo.ttf") tech(color-COLRv0) is valid
Pass Check that src: url("foo.ttf") tech(color-COLRv1) is valid
Fail Check that src: url("foo.ttf") tech(color-sbix) is valid
Fail Check that src: url("foo.ttf") tech(color-CBDT) is valid
Pass Check that src: url("foo.ttf") tech(color-sbix) is valid
Pass Check that src: url("foo.ttf") tech(color-CBDT) is valid
Pass Check that src: url("foo.ttf") tech(variations) is valid
Fail Check that src: url("foo.ttf") tech(palettes) is valid
Pass Check that src: url("foo.ttf") tech(palettes) is valid
Pass Check that src: url("foo.ttf") tech("features-opentype") is invalid
Pass Check that src: url("foo.ttf") tech("color-COLRv0") is invalid
Pass Check that src: url("foo.ttf") tech("variations") is invalid
Fail Check that src: url("foo.ttf") tech(features-opentype, color-COLRv0, variations, palettes) is valid
Pass Check that src: url("foo.ttf") tech(features-opentype, color-COLRv0, variations, palettes) is valid
Pass Check that src: url("foo.ttf") tech(features-opentype color-COLRv0 variations palettes) is invalid
Pass Check that src: url("foo.ttf") tech(feature-opentype) is invalid
Pass Check that src: url("foo.ttf") tech(feature-aat) is invalid