LibGfx+LibWeb: Remove typeface classes for WOFF fonts

This change removes wrappers inherited from Gfx::Typeface for WOFF and
WOFF2 fonts. The only purpose they served is owning of ttf ByteBuffer
produced by decoding a WOFF/WOFF2 font. Now new FontData class is
responsible for holding ByteBuffer when a font is constructed from
non-externally owned memory.
This commit is contained in:
Aliaksandr Kalenik 2024-07-22 14:03:58 +03:00 committed by Andreas Kling
parent 2497f43989
commit 2ead999f2b
Notes: github-actions[bot] 2024-07-22 13:05:57 +00:00
19 changed files with 154 additions and 150 deletions

View file

@ -4,12 +4,12 @@
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibGfx/Font/WOFF/Typeface.h>
#include <LibGfx/Font/WOFF/Loader.h>
#include <stddef.h>
extern "C" int LLVMFuzzerTestOneInput(u8 const* data, size_t size)
{
AK::set_debug_enabled(false);
(void)WOFF::Typeface::try_load_from_externally_owned_memory({ data, size });
(void)WOFF::try_load_from_externally_owned_memory({ data, size });
return 0;
}

View file

@ -4,12 +4,12 @@
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibGfx/Font/WOFF2/Typeface.h>
#include <LibGfx/Font/WOFF2/Loader.h>
#include <stddef.h>
extern "C" int LLVMFuzzerTestOneInput(u8 const* data, size_t size)
{
AK::set_debug_enabled(false);
(void)WOFF2::Typeface::try_load_from_externally_owned_memory({ data, size });
(void)WOFF2::try_load_from_externally_owned_memory({ data, size });
return 0;
}

View file

@ -4,7 +4,7 @@
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibGfx/Font/WOFF/Typeface.h>
#include <LibGfx/Font/WOFF/Loader.h>
#include <LibTest/TestCase.h>
#define TEST_INPUT(x) ("test-inputs/" x)
@ -17,7 +17,7 @@ TEST_CASE(malformed_woff)
for (auto test_input : test_inputs) {
auto file = MUST(Core::MappedFile::map(test_input));
auto font_or_error = WOFF::Typeface::try_load_from_externally_owned_memory(file->bytes());
auto font_or_error = WOFF::try_load_from_externally_owned_memory(file->bytes());
EXPECT(font_or_error.is_error());
}
}

View file

@ -4,7 +4,7 @@
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibGfx/Font/WOFF2/Typeface.h>
#include <LibGfx/Font/WOFF2/Loader.h>
#include <LibTest/TestCase.h>
#define TEST_INPUT(x) ("test-inputs/" x)
@ -12,7 +12,7 @@
TEST_CASE(tolerate_incorrect_sfnt_size)
{
auto file = MUST(Core::MappedFile::map(TEST_INPUT("woff2/incorrect_sfnt_size.woff2"sv)));
auto font = TRY_OR_FAIL(WOFF2::Typeface::try_load_from_externally_owned_memory(file->bytes()));
auto font = TRY_OR_FAIL(WOFF2::try_load_from_externally_owned_memory(file->bytes()));
EXPECT_EQ(font->family(), "Test"_string);
EXPECT_EQ(font->glyph_count(), 4u);
}
@ -26,7 +26,7 @@ TEST_CASE(malformed_woff2)
for (auto test_input : test_inputs) {
auto file = MUST(Core::MappedFile::map(test_input));
auto font_or_error = WOFF2::Typeface::try_load_from_externally_owned_memory(file->bytes());
auto font_or_error = WOFF2::try_load_from_externally_owned_memory(file->bytes());
EXPECT(font_or_error.is_error());
}
}

View file

@ -9,6 +9,7 @@ set(SOURCES
FontCascadeList.cpp
Font/Emoji.cpp
Font/Font.cpp
Font/FontData.cpp
Font/FontDatabase.cpp
Font/OpenType/Cmap.cpp
Font/OpenType/Glyf.cpp
@ -17,8 +18,8 @@ set(SOURCES
Font/OpenType/Typeface.cpp
Font/ScaledFont.cpp
Font/Typeface.cpp
Font/WOFF/Typeface.cpp
Font/WOFF2/Typeface.cpp
Font/WOFF/Loader.cpp
Font/WOFF2/Loader.cpp
GradientPainting.cpp
ICC/BinaryWriter.cpp
ICC/Enums.cpp

View file

@ -0,0 +1,40 @@
/*
* Copyright (c) 2024, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibGfx/Font/FontData.h>
namespace Gfx {
NonnullOwnPtr<FontData> FontData::create_from_byte_buffer(ByteBuffer&& byte_buffer)
{
return adopt_own(*new FontData(move(byte_buffer)));
}
NonnullOwnPtr<FontData> FontData::create_from_resource(Core::Resource const& resource)
{
return adopt_own(*new FontData(resource));
}
ReadonlyBytes FontData::bytes() const
{
return m_data.visit(
[&](ByteBuffer const& byte_buffer) { return byte_buffer.bytes(); },
[&](Core::Resource const& resource) {
return resource.data();
});
}
FontData::FontData(ByteBuffer&& byte_buffer)
: m_data(move(byte_buffer))
{
}
FontData::FontData(NonnullRefPtr<Core::Resource> resource)
: m_data(move(resource))
{
}
}

View file

@ -0,0 +1,31 @@
/*
* Copyright (c) 2024, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/HashMap.h>
#include <AK/Noncopyable.h>
#include <AK/RefCounted.h>
#include <LibCore/Resource.h>
#include <LibGfx/Forward.h>
namespace Gfx {
class FontData {
public:
static NonnullOwnPtr<FontData> create_from_byte_buffer(ByteBuffer&&);
static NonnullOwnPtr<FontData> create_from_resource(Core::Resource const&);
ReadonlyBytes bytes() const;
private:
FontData(ByteBuffer&& byte_buffer);
FontData(NonnullRefPtr<Core::Resource> resource);
Variant<ByteBuffer, NonnullRefPtr<Core::Resource>> m_data;
};
}

View file

@ -13,7 +13,7 @@
#include <LibGfx/Font/FontDatabase.h>
#include <LibGfx/Font/OpenType/Typeface.h>
#include <LibGfx/Font/ScaledFont.h>
#include <LibGfx/Font/WOFF/Typeface.h>
#include <LibGfx/Font/WOFF/Loader.h>
namespace Gfx {
@ -52,7 +52,7 @@ void FontDatabase::load_all_fonts_from_uri(StringView uri)
family.append(font);
}
} else if (path.has_extension(".woff"sv)) {
if (auto font_or_error = WOFF::Typeface::try_load_from_resource(resource); !font_or_error.is_error()) {
if (auto font_or_error = WOFF::try_load_from_resource(resource); !font_or_error.is_error()) {
auto font = font_or_error.release_value();
auto& family = m_private->typeface_by_family.ensure(font->family(), [] {
return Vector<NonnullRefPtr<Typeface>> {};

View file

@ -152,8 +152,14 @@ float be_fword(u8 const* ptr)
ErrorOr<NonnullRefPtr<Typeface>> Typeface::try_load_from_resource(Core::Resource const& resource, unsigned index)
{
auto font = TRY(try_load_from_externally_owned_memory(resource.data(), { .index = index }));
font->m_resource = resource;
auto font_data = Gfx::FontData::create_from_resource(resource);
return try_load_from_font_data(move(font_data), { .index = index });
}
ErrorOr<NonnullRefPtr<Typeface>> Typeface::try_load_from_font_data(NonnullOwnPtr<Gfx::FontData> font_data, Options options)
{
auto font = TRY(try_load_from_externally_owned_memory(font_data->bytes(), move(options)));
font->m_font_data = move(font_data);
return font;
}

View file

@ -51,6 +51,7 @@ class Typeface : public Gfx::Typeface {
public:
using Options = FontOptions;
static ErrorOr<NonnullRefPtr<Typeface>> try_load_from_resource(Core::Resource const&, unsigned index = 0);
static ErrorOr<NonnullRefPtr<Typeface>> try_load_from_font_data(NonnullOwnPtr<Gfx::FontData>, Options options = {});
static ErrorOr<NonnullRefPtr<Typeface>> try_load_from_externally_owned_memory(ReadonlyBytes bytes, Options options = {});
virtual Gfx::ScaledFontMetrics metrics(float x_scale, float y_scale) const override;
@ -144,7 +145,7 @@ private:
{
}
RefPtr<Core::Resource> m_resource;
OwnPtr<Gfx::FontData> m_font_data;
// These are stateful wrappers around non-owning slices
Head m_head;

View file

@ -10,6 +10,7 @@
#include <AK/Noncopyable.h>
#include <AK/RefCounted.h>
#include <LibGfx/Font/Font.h>
#include <LibGfx/Font/FontData.h>
#include <LibGfx/Forward.h>
#include <LibGfx/Path.h>

View file

@ -7,11 +7,10 @@
#include <AK/ByteBuffer.h>
#include <AK/IntegralMath.h>
#include <AK/MemoryStream.h>
#include <LibCompress/Zlib.h>
#include <LibCore/Resource.h>
#include <LibGfx/Font/OpenType/Typeface.h>
#include <LibGfx/Font/WOFF/Typeface.h>
#include <LibGfx/Font/WOFF/Loader.h>
namespace WOFF {
@ -69,12 +68,12 @@ static u16 pow_2_less_than_or_equal(u16 x)
return 1 << (sizeof(u16) * 8 - count_leading_zeroes_safe<u16>(x - 1));
}
ErrorOr<NonnullRefPtr<Typeface>> Typeface::try_load_from_resource(Core::Resource const& resource, unsigned index)
ErrorOr<NonnullRefPtr<OpenType::Typeface>> try_load_from_resource(Core::Resource const& resource, unsigned index)
{
return try_load_from_externally_owned_memory(resource.data(), index);
}
ErrorOr<NonnullRefPtr<Typeface>> Typeface::try_load_from_externally_owned_memory(ReadonlyBytes buffer, unsigned int index)
ErrorOr<NonnullRefPtr<OpenType::Typeface>> try_load_from_externally_owned_memory(ReadonlyBytes buffer, unsigned int index)
{
FixedMemoryStream stream(buffer);
auto header = TRY(stream.read_value<Header>());
@ -158,9 +157,8 @@ ErrorOr<NonnullRefPtr<Typeface>> Typeface::try_load_from_externally_owned_memory
if (header.total_sfnt_size != expected_total_sfnt_size)
return Error::from_string_literal("Invalid WOFF total sfnt size");
auto input_font = TRY(OpenType::Typeface::try_load_from_externally_owned_memory(font_buffer.bytes(), { .index = index }));
auto font = adopt_ref(*new Typeface(input_font, move(font_buffer)));
return font;
auto font_data = Gfx::FontData::create_from_byte_buffer(move(font_buffer));
return TRY(OpenType::Typeface::try_load_from_font_data(move(font_data), { .index = index }));
}
}

View file

@ -0,0 +1,19 @@
/*
* Copyright (c) 2022, the SerenityOS developers.
* Copyright (c) 2023, Andreas Kling <kling@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/OwnPtr.h>
#include <AK/RefCounted.h>
#include <LibGfx/Font/OpenType/Typeface.h>
namespace WOFF {
ErrorOr<NonnullRefPtr<OpenType::Typeface>> try_load_from_resource(Core::Resource const&, unsigned index = 0);
ErrorOr<NonnullRefPtr<OpenType::Typeface>> try_load_from_externally_owned_memory(ReadonlyBytes bytes, unsigned index = 0);
}

View file

@ -1,56 +0,0 @@
/*
* Copyright (c) 2022, the SerenityOS developers.
* Copyright (c) 2023, Andreas Kling <kling@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/ByteString.h>
#include <AK/Noncopyable.h>
#include <AK/OwnPtr.h>
#include <AK/RefCounted.h>
#include <LibCore/MappedFile.h>
#include <LibGfx/Bitmap.h>
#include <LibGfx/Font/Typeface.h>
namespace WOFF {
class Typeface : public Gfx::Typeface {
AK_MAKE_NONCOPYABLE(Typeface);
public:
static ErrorOr<NonnullRefPtr<Typeface>> try_load_from_resource(Core::Resource const&, unsigned index = 0);
static ErrorOr<NonnullRefPtr<Typeface>> try_load_from_externally_owned_memory(ReadonlyBytes bytes, unsigned index = 0);
virtual Gfx::ScaledFontMetrics metrics(float x_scale, float y_scale) const override { return m_input_font->metrics(x_scale, y_scale); }
virtual Gfx::ScaledGlyphMetrics glyph_metrics(u32 glyph_id, float x_scale, float y_scale, float point_width, float point_height) const override { return m_input_font->glyph_metrics(glyph_id, x_scale, y_scale, point_width, point_height); }
virtual float glyph_advance(u32 glyph_id, float x_scale, float y_scale, float point_width, float point_height) const override { return m_input_font->glyph_advance(glyph_id, x_scale, y_scale, point_width, point_height); }
virtual float glyphs_horizontal_kerning(u32 left_glyph_id, u32 right_glyph_id, float x_scale) const override { return m_input_font->glyphs_horizontal_kerning(left_glyph_id, right_glyph_id, x_scale); }
virtual RefPtr<Gfx::Bitmap> rasterize_glyph(u32 glyph_id, float x_scale, float y_scale, Gfx::GlyphSubpixelOffset subpixel_offset) const override { return m_input_font->rasterize_glyph(glyph_id, x_scale, y_scale, subpixel_offset); }
virtual bool append_glyph_path_to(Gfx::Path& path, u32 glyph_id, float x_scale, float y_scale) const override { return m_input_font->append_glyph_path_to(path, glyph_id, x_scale, y_scale); }
virtual u32 glyph_count() const override { return m_input_font->glyph_count(); }
virtual u16 units_per_em() const override { return m_input_font->units_per_em(); }
virtual u32 glyph_id_for_code_point(u32 code_point) const override { return m_input_font->glyph_id_for_code_point(code_point); }
virtual String family() const override { return m_input_font->family(); }
virtual String variant() const override { return m_input_font->variant(); }
virtual u16 weight() const override { return m_input_font->weight(); }
virtual u16 width() const override { return m_input_font->width(); }
virtual u8 slope() const override { return m_input_font->slope(); }
virtual bool is_fixed_width() const override { return m_input_font->is_fixed_width(); }
virtual bool has_color_bitmaps() const override { return m_input_font->has_color_bitmaps(); }
private:
Typeface(NonnullRefPtr<Gfx::Typeface const> input_font, ByteBuffer input_font_buffer)
: m_input_font_buffer(move(input_font_buffer))
, m_input_font(move(input_font))
{
}
ByteBuffer m_input_font_buffer;
NonnullRefPtr<Gfx::Typeface const> m_input_font;
};
}

View file

@ -6,7 +6,7 @@
#define AK_DONT_REPLACE_STD
#include <LibGfx/Font/OpenType/Typeface.h>
#include <LibGfx/Font/WOFF2/Typeface.h>
#include <LibGfx/Font/WOFF2/Loader.h>
#include <woff2/decode.h>
namespace WOFF2 {
@ -54,7 +54,7 @@ private:
ByteBuffer& m_buffer;
};
ErrorOr<NonnullRefPtr<Typeface>> Typeface::try_load_from_externally_owned_memory(ReadonlyBytes bytes)
ErrorOr<NonnullRefPtr<OpenType::Typeface>> try_load_from_externally_owned_memory(ReadonlyBytes bytes)
{
auto ttf_buffer = TRY(ByteBuffer::create_uninitialized(0));
auto output = WOFF2ByteBufferOut { ttf_buffer };
@ -62,8 +62,10 @@ ErrorOr<NonnullRefPtr<Typeface>> Typeface::try_load_from_externally_owned_memory
if (!result) {
return Error::from_string_literal("Failed to convert the WOFF2 font to TTF");
}
auto input_font = TRY(OpenType::Typeface::try_load_from_externally_owned_memory(ttf_buffer.bytes()));
return adopt_ref(*new Typeface(input_font, move(ttf_buffer)));
auto font_data = Gfx::FontData::create_from_byte_buffer(move(ttf_buffer));
auto input_font = TRY(OpenType::Typeface::try_load_from_font_data(move(font_data)));
return input_font;
}
}

View file

@ -0,0 +1,18 @@
/*
* Copyright (c) 2022, Luke Wilde <lukew@serenityos.org>
* Copyright (c) 2023, Andreas Kling <kling@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/OwnPtr.h>
#include <AK/RefCounted.h>
#include <LibGfx/Font/OpenType/Typeface.h>
namespace WOFF2 {
ErrorOr<NonnullRefPtr<OpenType::Typeface>> try_load_from_externally_owned_memory(ReadonlyBytes);
}

View file

@ -1,57 +0,0 @@
/*
* Copyright (c) 2022, Luke Wilde <lukew@serenityos.org>
* Copyright (c) 2023, Andreas Kling <kling@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/Noncopyable.h>
#include <AK/OwnPtr.h>
#include <AK/RefCounted.h>
#include <AK/Stream.h>
#include <AK/String.h>
#include <LibGfx/Bitmap.h>
#include <LibGfx/Font/Typeface.h>
namespace WOFF2 {
class Typeface : public Gfx::Typeface {
AK_MAKE_NONCOPYABLE(Typeface);
public:
static ErrorOr<NonnullRefPtr<Typeface>> try_load_from_externally_owned_memory(ReadonlyBytes);
virtual Gfx::ScaledFontMetrics metrics(float x_scale, float y_scale) const override { return m_input_font->metrics(x_scale, y_scale); }
virtual Gfx::ScaledGlyphMetrics glyph_metrics(u32 glyph_id, float x_scale, float y_scale, float point_width, float point_height) const override { return m_input_font->glyph_metrics(glyph_id, x_scale, y_scale, point_width, point_height); }
virtual float glyph_advance(u32 glyph_id, float x_scale, float y_scale, float point_width, float point_height) const override { return m_input_font->glyph_advance(glyph_id, x_scale, y_scale, point_width, point_height); }
virtual float glyphs_horizontal_kerning(u32 left_glyph_id, u32 right_glyph_id, float x_scale) const override { return m_input_font->glyphs_horizontal_kerning(left_glyph_id, right_glyph_id, x_scale); }
virtual RefPtr<Gfx::Bitmap> rasterize_glyph(u32 glyph_id, float x_scale, float y_scale, Gfx::GlyphSubpixelOffset subpixel_offset) const override
{
return m_input_font->rasterize_glyph(glyph_id, x_scale, y_scale, subpixel_offset);
}
virtual bool append_glyph_path_to(Gfx::Path& path, u32 glyph_id, float x_scale, float y_scale) const override { return m_input_font->append_glyph_path_to(path, glyph_id, x_scale, y_scale); }
virtual u32 glyph_count() const override { return m_input_font->glyph_count(); }
virtual u16 units_per_em() const override { return m_input_font->units_per_em(); }
virtual u32 glyph_id_for_code_point(u32 code_point) const override { return m_input_font->glyph_id_for_code_point(code_point); }
virtual String family() const override { return m_input_font->family(); }
virtual String variant() const override { return m_input_font->variant(); }
virtual u16 weight() const override { return m_input_font->weight(); }
virtual u16 width() const override { return m_input_font->width(); }
virtual u8 slope() const override { return m_input_font->slope(); }
virtual bool is_fixed_width() const override { return m_input_font->is_fixed_width(); }
virtual bool has_color_bitmaps() const override { return m_input_font->has_color_bitmaps(); }
private:
Typeface(NonnullRefPtr<Gfx::Typeface> input_font, ByteBuffer input_font_buffer)
: m_input_font_buffer(move(input_font_buffer))
, m_input_font(move(input_font))
{
}
ByteBuffer m_input_font_buffer;
NonnullRefPtr<Gfx::Typeface> m_input_font;
};
}

View file

@ -7,8 +7,8 @@
#include <LibCore/Promise.h>
#include <LibGfx/Font/OpenType/Typeface.h>
#include <LibGfx/Font/Typeface.h>
#include <LibGfx/Font/WOFF/Typeface.h>
#include <LibGfx/Font/WOFF2/Typeface.h>
#include <LibGfx/Font/WOFF/Loader.h>
#include <LibGfx/Font/WOFF2/Loader.h>
#include <LibJS/Heap/Heap.h>
#include <LibJS/Runtime/ArrayBuffer.h>
#include <LibJS/Runtime/Realm.h>
@ -40,12 +40,12 @@ static NonnullRefPtr<Core::Promise<NonnullRefPtr<Gfx::Typeface>>> load_vector_fo
promise->resolve(ttf.release_value());
return;
}
auto woff = WOFF::Typeface::try_load_from_externally_owned_memory(data);
auto woff = WOFF::try_load_from_externally_owned_memory(data);
if (!woff.is_error()) {
promise->resolve(woff.release_value());
return;
}
auto woff2 = WOFF2::Typeface::try_load_from_externally_owned_memory(data);
auto woff2 = WOFF2::try_load_from_externally_owned_memory(data);
if (!woff2.is_error()) {
promise->resolve(woff2.release_value());
return;

View file

@ -22,8 +22,8 @@
#include <LibGfx/Font/OpenType/Typeface.h>
#include <LibGfx/Font/ScaledFont.h>
#include <LibGfx/Font/Typeface.h>
#include <LibGfx/Font/WOFF/Typeface.h>
#include <LibGfx/Font/WOFF2/Typeface.h>
#include <LibGfx/Font/WOFF/Loader.h>
#include <LibGfx/Font/WOFF2/Loader.h>
#include <LibWeb/Animations/AnimationEffect.h>
#include <LibWeb/Animations/DocumentTimeline.h>
#include <LibWeb/CSS/AnimationEvent.h>
@ -172,12 +172,12 @@ ErrorOr<NonnullRefPtr<Gfx::Typeface>> FontLoader::try_load_font()
}
}
if (mime_type == "font/woff"sv || mime_type == "application/font-woff"sv) {
if (auto result = WOFF::Typeface::try_load_from_externally_owned_memory(resource()->encoded_data()); !result.is_error()) {
if (auto result = WOFF::try_load_from_externally_owned_memory(resource()->encoded_data()); !result.is_error()) {
return result;
}
}
if (mime_type == "font/woff2"sv || mime_type == "application/font-woff2"sv) {
if (auto result = WOFF2::Typeface::try_load_from_externally_owned_memory(resource()->encoded_data()); !result.is_error()) {
if (auto result = WOFF2::try_load_from_externally_owned_memory(resource()->encoded_data()); !result.is_error()) {
return result;
}
}
@ -186,10 +186,10 @@ ErrorOr<NonnullRefPtr<Gfx::Typeface>> FontLoader::try_load_font()
auto ttf = OpenType::Typeface::try_load_from_externally_owned_memory(resource()->encoded_data());
if (!ttf.is_error())
return ttf.release_value();
auto woff = WOFF::Typeface::try_load_from_externally_owned_memory(resource()->encoded_data());
auto woff = WOFF::try_load_from_externally_owned_memory(resource()->encoded_data());
if (!woff.is_error())
return woff.release_value();
auto woff2 = WOFF2::Typeface::try_load_from_externally_owned_memory(resource()->encoded_data());
auto woff2 = WOFF2::try_load_from_externally_owned_memory(resource()->encoded_data());
if (!woff2.is_error())
return woff2.release_value();
return Error::from_string_literal("Automatic format detection failed");