LibGfx/OpenType: Add scaffolding for CBDT and CBLC tables

This commit is contained in:
Andreas Kling 2023-03-04 20:30:47 +01:00
parent e6131e45e2
commit bca35bee6d
Notes: sideshowbarker 2024-07-17 01:06:10 +09:00
3 changed files with 177 additions and 3 deletions

View file

@ -1,6 +1,6 @@
/*
* Copyright (c) 2020, Srimanta Barua <srimanta.barua1@gmail.com>
* Copyright (c) 2021-2022, Andreas Kling <kling@serenityos.org>
* Copyright (c) 2021-2023, Andreas Kling <kling@serenityos.org>
* Copyright (c) 2022, Jelle Raaijmakers <jelle@gmta.nl>
*
* SPDX-License-Identifier: BSD-2-Clause
@ -409,6 +409,8 @@ ErrorOr<NonnullRefPtr<Font>> Font::try_load_from_offset(ReadonlyBytes buffer, u3
Optional<Kern> opt_kern = {};
Optional<Fpgm> opt_fpgm = {};
Optional<Prep> opt_prep = {};
Optional<CBLC> cblc;
Optional<CBDT> cbdt;
auto num_tables = be_u16(buffer.offset_pointer(offset + (u32)Offsets::NumTables));
if (buffer.size() < offset + (u32)Sizes::OffsetTable + num_tables * (u32)Sizes::TableRecord)
@ -453,6 +455,10 @@ ErrorOr<NonnullRefPtr<Font>> Font::try_load_from_offset(ReadonlyBytes buffer, u3
opt_fpgm_slice = buffer_here;
} else if (tag == tag_from_str("prep")) {
opt_prep_slice = buffer_here;
} else if (tag == tag_from_str("CBLC")) {
cblc = TRY(CBLC::from_slice(buffer_here));
} else if (tag == tag_from_str("CBDT")) {
cbdt = TRY(CBDT::from_slice(buffer_here));
}
}
@ -537,7 +543,22 @@ ErrorOr<NonnullRefPtr<Font>> Font::try_load_from_offset(ReadonlyBytes buffer, u3
}
}
return adopt_ref(*new Font(move(buffer), move(head), move(name), move(hhea), move(maxp), move(hmtx), move(cmap), move(loca), move(glyf), move(os2), move(kern), move(fpgm), move(prep)));
return adopt_ref(*new Font(
move(buffer),
move(head),
move(name),
move(hhea),
move(maxp),
move(hmtx),
move(cmap),
move(loca),
move(glyf),
move(os2),
move(kern),
move(fpgm),
move(prep),
move(cblc),
move(cbdt)));
}
Gfx::ScaledFontMetrics Font::metrics([[maybe_unused]] float x_scale, float y_scale) const

View file

@ -59,7 +59,22 @@ private:
static ErrorOr<NonnullRefPtr<Font>> try_load_from_offset(ReadonlyBytes, unsigned index = 0);
Font(ReadonlyBytes bytes, Head&& head, Name&& name, Hhea&& hhea, Maxp&& maxp, Hmtx&& hmtx, Cmap&& cmap, Optional<Loca>&& loca, Optional<Glyf>&& glyf, Optional<OS2> os2, Optional<Kern>&& kern, Optional<Fpgm> fpgm, Optional<Prep> prep)
Font(
ReadonlyBytes bytes,
Head&& head,
Name&& name,
Hhea&& hhea,
Maxp&& maxp,
Hmtx&& hmtx,
Cmap&& cmap,
Optional<Loca>&& loca,
Optional<Glyf>&& glyf,
Optional<OS2> os2,
Optional<Kern>&& kern,
Optional<Fpgm> fpgm,
Optional<Prep> prep,
Optional<CBLC> cblc,
Optional<CBDT> cbdt)
: m_buffer(move(bytes))
, m_head(move(head))
, m_name(move(name))
@ -73,6 +88,8 @@ private:
, m_kern(move(kern))
, m_fpgm(move(fpgm))
, m_prep(move(prep))
, m_cblc(move(cblc))
, m_cbdt(move(cbdt))
{
}
@ -93,6 +110,8 @@ private:
Optional<Kern> m_kern;
Optional<Fpgm> m_fpgm;
Optional<Prep> m_prep;
Optional<CBLC> m_cblc;
Optional<CBDT> m_cbdt;
// This cache stores information per code point.
// It's segmented into pages with data about 256 code points each.

View file

@ -37,6 +37,7 @@ using FWord = BigEndian<i16>;
using UFWord = BigEndian<u16>;
using Tag = BigEndian<u32>;
using Offset16 = BigEndian<u16>;
using Offset32 = BigEndian<u32>;
// https://learn.microsoft.com/en-us/typography/opentype/spec/head
// head: Font Header Table
@ -399,4 +400,137 @@ private:
FixedArray<size_t> m_subtable_offsets;
};
// https://learn.microsoft.com/en-us/typography/opentype/spec/eblc
// EBLC — Embedded Bitmap Location Table
class EBLC {
public:
// https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#sbitlinemetrics-record
struct SbitLineMetrics {
i8 ascender {};
i8 descender {};
u8 width_max {};
i8 caret_slope_numerator {};
i8 caret_slope_denominator {};
i8 caret_offset {};
i8 min_origin_sb {};
i8 min_advance_sb {};
i8 max_before_bl {};
i8 min_after_bl {};
i8 pad1 {};
i8 pad2 {};
};
// https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#indexsubtablearray
struct IndexSubTableArray {
BigEndian<u16> first_glyph_index;
BigEndian<u16> last_glyph_index;
Offset32 additional_offset_to_index_subtable;
};
// https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#indexsubheader
struct IndexSubHeader {
BigEndian<u16> index_format;
BigEndian<u16> image_format;
Offset32 image_data_offset;
};
// https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#indexsubtable1-variable-metrics-glyphs-with-4-byte-offsets
// IndexSubTable1: variable-metrics glyphs with 4-byte offsets
struct IndexSubTable1 {
IndexSubHeader header;
Offset32 sbit_offsets[];
};
};
// https://learn.microsoft.com/en-us/typography/opentype/spec/cblc
// CBLC — Color Bitmap Location Table
class CBLC {
public:
// https://learn.microsoft.com/en-us/typography/opentype/spec/cblc#bitmapsize-record
struct BitmapSize {
Offset32 index_subtable_array_offset;
BigEndian<u32> index_tables_size;
BigEndian<u32> number_of_index_subtables;
BigEndian<u32> color_ref;
EBLC::SbitLineMetrics hori;
EBLC::SbitLineMetrics vert;
BigEndian<u16> start_glyph_index;
BigEndian<u16> end_glyph_index;
u8 ppem_x {};
u8 ppem_y {};
u8 bit_depth {};
i8 flags {};
};
// https://learn.microsoft.com/en-us/typography/opentype/spec/cblc#cblcheader
struct CblcHeader {
BigEndian<u16> major_version;
BigEndian<u16> minor_version;
BigEndian<u32> num_sizes;
BitmapSize bitmap_sizes[];
};
CblcHeader const& header() const { return *bit_cast<CblcHeader const*>(m_slice.data()); }
ReadonlySpan<BitmapSize> bitmap_sizes() const { return { header().bitmap_sizes, header().num_sizes }; }
Optional<BitmapSize const&> bitmap_size_for_glyph_id(u32 glyph_id) const;
static ErrorOr<CBLC> from_slice(ReadonlyBytes);
ReadonlyBytes bytes() const { return m_slice; }
Optional<EBLC::IndexSubHeader const&> index_subtable_for_glyph_id(u32 glyph_id, u16& first_glyph_index, u16& last_glyph_index) const;
private:
explicit CBLC(ReadonlyBytes slice)
: m_slice(slice)
{
}
ReadonlyBytes m_slice;
};
// https://learn.microsoft.com/en-us/typography/opentype/spec/ebdt
// EBDT — Embedded Bitmap Data Table
class EBDT {
public:
// https://learn.microsoft.com/en-us/typography/opentype/spec/ebdt#smallglyphmetrics
struct SmallGlyphMetrics {
u8 height {};
u8 width {};
i8 bearing_x {};
i8 bearing_y {};
u8 advance {};
};
};
// https://learn.microsoft.com/en-us/typography/opentype/spec/cbdt
// CBDT — Color Bitmap Data Table
class CBDT {
public:
// https://learn.microsoft.com/en-us/typography/opentype/spec/cbdt#table-structure
struct CbdtHeader {
BigEndian<u16> major_version;
BigEndian<u16> minor_version;
};
// https://learn.microsoft.com/en-us/typography/opentype/spec/cbdt#format-17-small-metrics-png-image-data
struct Format17 {
EBDT::SmallGlyphMetrics glyph_metrics;
BigEndian<u32> data_len;
u8 data[];
};
static ErrorOr<CBDT> from_slice(ReadonlyBytes);
ReadonlyBytes bytes() const { return m_slice; }
CbdtHeader const& header() const { return *bit_cast<CbdtHeader const*>(m_slice.data()); }
private:
explicit CBDT(ReadonlyBytes slice)
: m_slice(slice)
{
}
ReadonlyBytes m_slice;
};
}