summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2023-03-04 20:30:47 +0100
committerAndreas Kling <kling@serenityos.org>2023-03-06 10:52:55 +0100
commitbca35bee6d207ae99ea8bb87ecaaca42504567e0 (patch)
treea93aef86683a1fb071104ee0ac9a5543e0620f29
parente6131e45e269f48f09cb993a67e63a00267005ec (diff)
downloadserenity-bca35bee6d207ae99ea8bb87ecaaca42504567e0.zip
LibGfx/OpenType: Add scaffolding for CBDT and CBLC tables
-rw-r--r--Userland/Libraries/LibGfx/Font/OpenType/Font.cpp25
-rw-r--r--Userland/Libraries/LibGfx/Font/OpenType/Font.h21
-rw-r--r--Userland/Libraries/LibGfx/Font/OpenType/Tables.h134
3 files changed, 177 insertions, 3 deletions
diff --git a/Userland/Libraries/LibGfx/Font/OpenType/Font.cpp b/Userland/Libraries/LibGfx/Font/OpenType/Font.cpp
index b8b9730809..4ad4debe58 100644
--- a/Userland/Libraries/LibGfx/Font/OpenType/Font.cpp
+++ b/Userland/Libraries/LibGfx/Font/OpenType/Font.cpp
@@ -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
diff --git a/Userland/Libraries/LibGfx/Font/OpenType/Font.h b/Userland/Libraries/LibGfx/Font/OpenType/Font.h
index 86abc00b44..7f798d1ae2 100644
--- a/Userland/Libraries/LibGfx/Font/OpenType/Font.h
+++ b/Userland/Libraries/LibGfx/Font/OpenType/Font.h
@@ -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.
diff --git a/Userland/Libraries/LibGfx/Font/OpenType/Tables.h b/Userland/Libraries/LibGfx/Font/OpenType/Tables.h
index 8d26665f6a..8cc69fc7bc 100644
--- a/Userland/Libraries/LibGfx/Font/OpenType/Tables.h
+++ b/Userland/Libraries/LibGfx/Font/OpenType/Tables.h
@@ -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;
+};
+
}