diff options
author | Andreas Kling <kling@serenityos.org> | 2023-03-04 20:30:47 +0100 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2023-03-06 10:52:55 +0100 |
commit | bca35bee6d207ae99ea8bb87ecaaca42504567e0 (patch) | |
tree | a93aef86683a1fb071104ee0ac9a5543e0620f29 | |
parent | e6131e45e269f48f09cb993a67e63a00267005ec (diff) | |
download | serenity-bca35bee6d207ae99ea8bb87ecaaca42504567e0.zip |
LibGfx/OpenType: Add scaffolding for CBDT and CBLC tables
-rw-r--r-- | Userland/Libraries/LibGfx/Font/OpenType/Font.cpp | 25 | ||||
-rw-r--r-- | Userland/Libraries/LibGfx/Font/OpenType/Font.h | 21 | ||||
-rw-r--r-- | Userland/Libraries/LibGfx/Font/OpenType/Tables.h | 134 |
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; +}; + } |