1662 lines
53 KiB
Rust
1662 lines
53 KiB
Rust
// THIS FILE IS AUTOGENERATED.
|
|
// Any changes to this file will be overwritten.
|
|
// For more information about how codegen works, see font-codegen/README.md
|
|
|
|
#[allow(unused_imports)]
|
|
use crate::codegen_prelude::*;
|
|
|
|
/// [BitmapSize](https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#bitmapsize-record) record.
|
|
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
|
|
#[repr(C)]
|
|
#[repr(packed)]
|
|
pub struct BitmapSize {
|
|
/// Offset to IndexSubtableList, from beginning of EBLC/CBLC.
|
|
pub index_subtable_list_offset: BigEndian<u32>,
|
|
/// Total size in bytes of the IndexSubtableList including its array of IndexSubtables.
|
|
pub index_subtable_list_size: BigEndian<u32>,
|
|
/// Number of IndexSubtables in the IndexSubtableList.
|
|
pub number_of_index_subtables: BigEndian<u32>,
|
|
/// Not used; set to 0.
|
|
pub color_ref: BigEndian<u32>,
|
|
/// Line metrics for text rendered horizontally.
|
|
pub hori: SbitLineMetrics,
|
|
/// Line metrics for text rendered vertically.
|
|
pub vert: SbitLineMetrics,
|
|
/// Lowest glyph index for this size.
|
|
pub start_glyph_index: BigEndian<GlyphId16>,
|
|
/// Highest glyph index for this size.
|
|
pub end_glyph_index: BigEndian<GlyphId16>,
|
|
/// Horizontal pixels per em.
|
|
pub ppem_x: u8,
|
|
/// Vertical pixels per em.
|
|
pub ppem_y: u8,
|
|
/// The Microsoft rasterizer v.1.7 or greater supports the following
|
|
/// bitDepth values, as described below: 1, 2, 4, and 8 (and 32 for CBLC).
|
|
pub bit_depth: u8,
|
|
/// Vertical or horizontal.
|
|
pub flags: BigEndian<BitmapFlags>,
|
|
}
|
|
|
|
impl BitmapSize {
|
|
/// Offset to IndexSubtableList, from beginning of EBLC/CBLC.
|
|
pub fn index_subtable_list_offset(&self) -> u32 {
|
|
self.index_subtable_list_offset.get()
|
|
}
|
|
|
|
/// Total size in bytes of the IndexSubtableList including its array of IndexSubtables.
|
|
pub fn index_subtable_list_size(&self) -> u32 {
|
|
self.index_subtable_list_size.get()
|
|
}
|
|
|
|
/// Number of IndexSubtables in the IndexSubtableList.
|
|
pub fn number_of_index_subtables(&self) -> u32 {
|
|
self.number_of_index_subtables.get()
|
|
}
|
|
|
|
/// Not used; set to 0.
|
|
pub fn color_ref(&self) -> u32 {
|
|
self.color_ref.get()
|
|
}
|
|
|
|
/// Line metrics for text rendered horizontally.
|
|
pub fn hori(&self) -> &SbitLineMetrics {
|
|
&self.hori
|
|
}
|
|
|
|
/// Line metrics for text rendered vertically.
|
|
pub fn vert(&self) -> &SbitLineMetrics {
|
|
&self.vert
|
|
}
|
|
|
|
/// Lowest glyph index for this size.
|
|
pub fn start_glyph_index(&self) -> GlyphId16 {
|
|
self.start_glyph_index.get()
|
|
}
|
|
|
|
/// Highest glyph index for this size.
|
|
pub fn end_glyph_index(&self) -> GlyphId16 {
|
|
self.end_glyph_index.get()
|
|
}
|
|
|
|
/// Horizontal pixels per em.
|
|
pub fn ppem_x(&self) -> u8 {
|
|
self.ppem_x
|
|
}
|
|
|
|
/// Vertical pixels per em.
|
|
pub fn ppem_y(&self) -> u8 {
|
|
self.ppem_y
|
|
}
|
|
|
|
/// The Microsoft rasterizer v.1.7 or greater supports the following
|
|
/// bitDepth values, as described below: 1, 2, 4, and 8 (and 32 for CBLC).
|
|
pub fn bit_depth(&self) -> u8 {
|
|
self.bit_depth
|
|
}
|
|
|
|
/// Vertical or horizontal.
|
|
pub fn flags(&self) -> BitmapFlags {
|
|
self.flags.get()
|
|
}
|
|
}
|
|
|
|
impl FixedSize for BitmapSize {
|
|
const RAW_BYTE_LEN: usize = u32::RAW_BYTE_LEN
|
|
+ u32::RAW_BYTE_LEN
|
|
+ u32::RAW_BYTE_LEN
|
|
+ u32::RAW_BYTE_LEN
|
|
+ SbitLineMetrics::RAW_BYTE_LEN
|
|
+ SbitLineMetrics::RAW_BYTE_LEN
|
|
+ GlyphId16::RAW_BYTE_LEN
|
|
+ GlyphId16::RAW_BYTE_LEN
|
|
+ u8::RAW_BYTE_LEN
|
|
+ u8::RAW_BYTE_LEN
|
|
+ u8::RAW_BYTE_LEN
|
|
+ BitmapFlags::RAW_BYTE_LEN;
|
|
}
|
|
|
|
#[cfg(feature = "experimental_traverse")]
|
|
impl<'a> SomeRecord<'a> for BitmapSize {
|
|
fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
|
|
RecordResolver {
|
|
name: "BitmapSize",
|
|
get_field: Box::new(move |idx, _data| match idx {
|
|
0usize => Some(Field::new(
|
|
"index_subtable_list_offset",
|
|
self.index_subtable_list_offset(),
|
|
)),
|
|
1usize => Some(Field::new(
|
|
"index_subtable_list_size",
|
|
self.index_subtable_list_size(),
|
|
)),
|
|
2usize => Some(Field::new(
|
|
"number_of_index_subtables",
|
|
self.number_of_index_subtables(),
|
|
)),
|
|
3usize => Some(Field::new("color_ref", self.color_ref())),
|
|
4usize => Some(Field::new("hori", self.hori().traversal_type(_data))),
|
|
5usize => Some(Field::new("vert", self.vert().traversal_type(_data))),
|
|
6usize => Some(Field::new("start_glyph_index", self.start_glyph_index())),
|
|
7usize => Some(Field::new("end_glyph_index", self.end_glyph_index())),
|
|
8usize => Some(Field::new("ppem_x", self.ppem_x())),
|
|
9usize => Some(Field::new("ppem_y", self.ppem_y())),
|
|
10usize => Some(Field::new("bit_depth", self.bit_depth())),
|
|
11usize => Some(Field::new("flags", self.flags())),
|
|
_ => None,
|
|
}),
|
|
data,
|
|
}
|
|
}
|
|
}
|
|
|
|
/// [SbitLineMetrics](https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#sbitlinemetrics-record) record.
|
|
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
|
|
#[repr(C)]
|
|
#[repr(packed)]
|
|
pub struct SbitLineMetrics {
|
|
pub ascender: BigEndian<i8>,
|
|
pub descender: BigEndian<i8>,
|
|
pub width_max: u8,
|
|
pub caret_slope_numerator: BigEndian<i8>,
|
|
pub caret_slope_denominator: u8,
|
|
pub caret_offset: BigEndian<i8>,
|
|
pub min_origin_sb: BigEndian<i8>,
|
|
pub min_advance_sb: BigEndian<i8>,
|
|
pub max_before_bl: BigEndian<i8>,
|
|
pub min_after_bl: BigEndian<i8>,
|
|
pub pad1: BigEndian<i8>,
|
|
pub pad2: BigEndian<i8>,
|
|
}
|
|
|
|
impl SbitLineMetrics {
|
|
pub fn ascender(&self) -> i8 {
|
|
self.ascender.get()
|
|
}
|
|
|
|
pub fn descender(&self) -> i8 {
|
|
self.descender.get()
|
|
}
|
|
|
|
pub fn width_max(&self) -> u8 {
|
|
self.width_max
|
|
}
|
|
|
|
pub fn caret_slope_numerator(&self) -> i8 {
|
|
self.caret_slope_numerator.get()
|
|
}
|
|
|
|
pub fn caret_slope_denominator(&self) -> u8 {
|
|
self.caret_slope_denominator
|
|
}
|
|
|
|
pub fn caret_offset(&self) -> i8 {
|
|
self.caret_offset.get()
|
|
}
|
|
|
|
pub fn min_origin_sb(&self) -> i8 {
|
|
self.min_origin_sb.get()
|
|
}
|
|
|
|
pub fn min_advance_sb(&self) -> i8 {
|
|
self.min_advance_sb.get()
|
|
}
|
|
|
|
pub fn max_before_bl(&self) -> i8 {
|
|
self.max_before_bl.get()
|
|
}
|
|
|
|
pub fn min_after_bl(&self) -> i8 {
|
|
self.min_after_bl.get()
|
|
}
|
|
|
|
pub fn pad1(&self) -> i8 {
|
|
self.pad1.get()
|
|
}
|
|
|
|
pub fn pad2(&self) -> i8 {
|
|
self.pad2.get()
|
|
}
|
|
}
|
|
|
|
impl FixedSize for SbitLineMetrics {
|
|
const RAW_BYTE_LEN: usize = i8::RAW_BYTE_LEN
|
|
+ i8::RAW_BYTE_LEN
|
|
+ u8::RAW_BYTE_LEN
|
|
+ i8::RAW_BYTE_LEN
|
|
+ u8::RAW_BYTE_LEN
|
|
+ i8::RAW_BYTE_LEN
|
|
+ i8::RAW_BYTE_LEN
|
|
+ i8::RAW_BYTE_LEN
|
|
+ i8::RAW_BYTE_LEN
|
|
+ i8::RAW_BYTE_LEN
|
|
+ i8::RAW_BYTE_LEN
|
|
+ i8::RAW_BYTE_LEN;
|
|
}
|
|
|
|
#[cfg(feature = "experimental_traverse")]
|
|
impl<'a> SomeRecord<'a> for SbitLineMetrics {
|
|
fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
|
|
RecordResolver {
|
|
name: "SbitLineMetrics",
|
|
get_field: Box::new(move |idx, _data| match idx {
|
|
0usize => Some(Field::new("ascender", self.ascender())),
|
|
1usize => Some(Field::new("descender", self.descender())),
|
|
2usize => Some(Field::new("width_max", self.width_max())),
|
|
3usize => Some(Field::new(
|
|
"caret_slope_numerator",
|
|
self.caret_slope_numerator(),
|
|
)),
|
|
4usize => Some(Field::new(
|
|
"caret_slope_denominator",
|
|
self.caret_slope_denominator(),
|
|
)),
|
|
5usize => Some(Field::new("caret_offset", self.caret_offset())),
|
|
6usize => Some(Field::new("min_origin_sb", self.min_origin_sb())),
|
|
7usize => Some(Field::new("min_advance_sb", self.min_advance_sb())),
|
|
8usize => Some(Field::new("max_before_bl", self.max_before_bl())),
|
|
9usize => Some(Field::new("min_after_bl", self.min_after_bl())),
|
|
10usize => Some(Field::new("pad1", self.pad1())),
|
|
11usize => Some(Field::new("pad2", self.pad2())),
|
|
_ => None,
|
|
}),
|
|
data,
|
|
}
|
|
}
|
|
}
|
|
|
|
/// [Bitmap flags](https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#bitmap-flags).
|
|
#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash, bytemuck :: AnyBitPattern)]
|
|
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
|
#[repr(transparent)]
|
|
pub struct BitmapFlags {
|
|
bits: u8,
|
|
}
|
|
|
|
impl BitmapFlags {
|
|
/// Horizontal
|
|
pub const HORIZONTAL_METRICS: Self = Self { bits: 0x01 };
|
|
|
|
/// Vertical
|
|
pub const VERTICAL_METRICS: Self = Self { bits: 0x02 };
|
|
}
|
|
|
|
impl BitmapFlags {
|
|
/// Returns an empty set of flags.
|
|
#[inline]
|
|
pub const fn empty() -> Self {
|
|
Self { bits: 0 }
|
|
}
|
|
|
|
/// Returns the set containing all flags.
|
|
#[inline]
|
|
pub const fn all() -> Self {
|
|
Self {
|
|
bits: Self::HORIZONTAL_METRICS.bits | Self::VERTICAL_METRICS.bits,
|
|
}
|
|
}
|
|
|
|
/// Returns the raw value of the flags currently stored.
|
|
#[inline]
|
|
pub const fn bits(&self) -> u8 {
|
|
self.bits
|
|
}
|
|
|
|
/// Convert from underlying bit representation, unless that
|
|
/// representation contains bits that do not correspond to a flag.
|
|
#[inline]
|
|
pub const fn from_bits(bits: u8) -> Option<Self> {
|
|
if (bits & !Self::all().bits()) == 0 {
|
|
Some(Self { bits })
|
|
} else {
|
|
None
|
|
}
|
|
}
|
|
|
|
/// Convert from underlying bit representation, dropping any bits
|
|
/// that do not correspond to flags.
|
|
#[inline]
|
|
pub const fn from_bits_truncate(bits: u8) -> Self {
|
|
Self {
|
|
bits: bits & Self::all().bits,
|
|
}
|
|
}
|
|
|
|
/// Returns `true` if no flags are currently stored.
|
|
#[inline]
|
|
pub const fn is_empty(&self) -> bool {
|
|
self.bits() == Self::empty().bits()
|
|
}
|
|
|
|
/// Returns `true` if there are flags common to both `self` and `other`.
|
|
#[inline]
|
|
pub const fn intersects(&self, other: Self) -> bool {
|
|
!(Self {
|
|
bits: self.bits & other.bits,
|
|
})
|
|
.is_empty()
|
|
}
|
|
|
|
/// Returns `true` if all of the flags in `other` are contained within `self`.
|
|
#[inline]
|
|
pub const fn contains(&self, other: Self) -> bool {
|
|
(self.bits & other.bits) == other.bits
|
|
}
|
|
|
|
/// Inserts the specified flags in-place.
|
|
#[inline]
|
|
pub fn insert(&mut self, other: Self) {
|
|
self.bits |= other.bits;
|
|
}
|
|
|
|
/// Removes the specified flags in-place.
|
|
#[inline]
|
|
pub fn remove(&mut self, other: Self) {
|
|
self.bits &= !other.bits;
|
|
}
|
|
|
|
/// Toggles the specified flags in-place.
|
|
#[inline]
|
|
pub fn toggle(&mut self, other: Self) {
|
|
self.bits ^= other.bits;
|
|
}
|
|
|
|
/// Returns the intersection between the flags in `self` and
|
|
/// `other`.
|
|
///
|
|
/// Specifically, the returned set contains only the flags which are
|
|
/// present in *both* `self` *and* `other`.
|
|
///
|
|
/// This is equivalent to using the `&` operator (e.g.
|
|
/// [`ops::BitAnd`]), as in `flags & other`.
|
|
///
|
|
/// [`ops::BitAnd`]: https://doc.rust-lang.org/std/ops/trait.BitAnd.html
|
|
#[inline]
|
|
#[must_use]
|
|
pub const fn intersection(self, other: Self) -> Self {
|
|
Self {
|
|
bits: self.bits & other.bits,
|
|
}
|
|
}
|
|
|
|
/// Returns the union of between the flags in `self` and `other`.
|
|
///
|
|
/// Specifically, the returned set contains all flags which are
|
|
/// present in *either* `self` *or* `other`, including any which are
|
|
/// present in both.
|
|
///
|
|
/// This is equivalent to using the `|` operator (e.g.
|
|
/// [`ops::BitOr`]), as in `flags | other`.
|
|
///
|
|
/// [`ops::BitOr`]: https://doc.rust-lang.org/std/ops/trait.BitOr.html
|
|
#[inline]
|
|
#[must_use]
|
|
pub const fn union(self, other: Self) -> Self {
|
|
Self {
|
|
bits: self.bits | other.bits,
|
|
}
|
|
}
|
|
|
|
/// Returns the difference between the flags in `self` and `other`.
|
|
///
|
|
/// Specifically, the returned set contains all flags present in
|
|
/// `self`, except for the ones present in `other`.
|
|
///
|
|
/// It is also conceptually equivalent to the "bit-clear" operation:
|
|
/// `flags & !other` (and this syntax is also supported).
|
|
///
|
|
/// This is equivalent to using the `-` operator (e.g.
|
|
/// [`ops::Sub`]), as in `flags - other`.
|
|
///
|
|
/// [`ops::Sub`]: https://doc.rust-lang.org/std/ops/trait.Sub.html
|
|
#[inline]
|
|
#[must_use]
|
|
pub const fn difference(self, other: Self) -> Self {
|
|
Self {
|
|
bits: self.bits & !other.bits,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl std::ops::BitOr for BitmapFlags {
|
|
type Output = Self;
|
|
|
|
/// Returns the union of the two sets of flags.
|
|
#[inline]
|
|
fn bitor(self, other: BitmapFlags) -> Self {
|
|
Self {
|
|
bits: self.bits | other.bits,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl std::ops::BitOrAssign for BitmapFlags {
|
|
/// Adds the set of flags.
|
|
#[inline]
|
|
fn bitor_assign(&mut self, other: Self) {
|
|
self.bits |= other.bits;
|
|
}
|
|
}
|
|
|
|
impl std::ops::BitXor for BitmapFlags {
|
|
type Output = Self;
|
|
|
|
/// Returns the left flags, but with all the right flags toggled.
|
|
#[inline]
|
|
fn bitxor(self, other: Self) -> Self {
|
|
Self {
|
|
bits: self.bits ^ other.bits,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl std::ops::BitXorAssign for BitmapFlags {
|
|
/// Toggles the set of flags.
|
|
#[inline]
|
|
fn bitxor_assign(&mut self, other: Self) {
|
|
self.bits ^= other.bits;
|
|
}
|
|
}
|
|
|
|
impl std::ops::BitAnd for BitmapFlags {
|
|
type Output = Self;
|
|
|
|
/// Returns the intersection between the two sets of flags.
|
|
#[inline]
|
|
fn bitand(self, other: Self) -> Self {
|
|
Self {
|
|
bits: self.bits & other.bits,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl std::ops::BitAndAssign for BitmapFlags {
|
|
/// Disables all flags disabled in the set.
|
|
#[inline]
|
|
fn bitand_assign(&mut self, other: Self) {
|
|
self.bits &= other.bits;
|
|
}
|
|
}
|
|
|
|
impl std::ops::Sub for BitmapFlags {
|
|
type Output = Self;
|
|
|
|
/// Returns the set difference of the two sets of flags.
|
|
#[inline]
|
|
fn sub(self, other: Self) -> Self {
|
|
Self {
|
|
bits: self.bits & !other.bits,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl std::ops::SubAssign for BitmapFlags {
|
|
/// Disables all flags enabled in the set.
|
|
#[inline]
|
|
fn sub_assign(&mut self, other: Self) {
|
|
self.bits &= !other.bits;
|
|
}
|
|
}
|
|
|
|
impl std::ops::Not for BitmapFlags {
|
|
type Output = Self;
|
|
|
|
/// Returns the complement of this set of flags.
|
|
#[inline]
|
|
fn not(self) -> Self {
|
|
Self { bits: !self.bits } & Self::all()
|
|
}
|
|
}
|
|
|
|
impl std::fmt::Debug for BitmapFlags {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
|
let members: &[(&str, Self)] = &[
|
|
("HORIZONTAL_METRICS", Self::HORIZONTAL_METRICS),
|
|
("VERTICAL_METRICS", Self::VERTICAL_METRICS),
|
|
];
|
|
let mut first = true;
|
|
for (name, value) in members {
|
|
if self.contains(*value) {
|
|
if !first {
|
|
f.write_str(" | ")?;
|
|
}
|
|
first = false;
|
|
f.write_str(name)?;
|
|
}
|
|
}
|
|
if first {
|
|
f.write_str("(empty)")?;
|
|
}
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
impl std::fmt::Binary for BitmapFlags {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
|
std::fmt::Binary::fmt(&self.bits, f)
|
|
}
|
|
}
|
|
|
|
impl std::fmt::Octal for BitmapFlags {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
|
std::fmt::Octal::fmt(&self.bits, f)
|
|
}
|
|
}
|
|
|
|
impl std::fmt::LowerHex for BitmapFlags {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
|
std::fmt::LowerHex::fmt(&self.bits, f)
|
|
}
|
|
}
|
|
|
|
impl std::fmt::UpperHex for BitmapFlags {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
|
std::fmt::UpperHex::fmt(&self.bits, f)
|
|
}
|
|
}
|
|
|
|
impl font_types::Scalar for BitmapFlags {
|
|
type Raw = <u8 as font_types::Scalar>::Raw;
|
|
fn to_raw(self) -> Self::Raw {
|
|
self.bits().to_raw()
|
|
}
|
|
fn from_raw(raw: Self::Raw) -> Self {
|
|
let t = <u8>::from_raw(raw);
|
|
Self::from_bits_truncate(t)
|
|
}
|
|
}
|
|
|
|
#[cfg(feature = "experimental_traverse")]
|
|
impl<'a> From<BitmapFlags> for FieldType<'a> {
|
|
fn from(src: BitmapFlags) -> FieldType<'a> {
|
|
src.bits().into()
|
|
}
|
|
}
|
|
|
|
/// [BigGlyphMetrics](https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#bigglyphmetrics) record.
|
|
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
|
|
#[repr(C)]
|
|
#[repr(packed)]
|
|
pub struct BigGlyphMetrics {
|
|
/// Number of rows of data.
|
|
pub height: u8,
|
|
/// Number of columns of data.
|
|
pub width: u8,
|
|
/// Distance in pixels from the horizontal origin to the left edge of the bitmap.
|
|
pub hori_bearing_x: BigEndian<i8>,
|
|
/// Distance in pixels from the horizontal origin to the top edge of the bitmap.
|
|
pub hori_bearing_y: BigEndian<i8>,
|
|
/// Horizontal advance width in pixels.
|
|
pub hori_advance: u8,
|
|
/// Distance in pixels from the vertical origin to the left edge of the bitmap.
|
|
pub vert_bearing_x: BigEndian<i8>,
|
|
/// Distance in pixels from the vertical origin to the top edge of the bitmap.
|
|
pub vert_bearing_y: BigEndian<i8>,
|
|
/// Vertical advance width in pixels.
|
|
pub vert_advance: u8,
|
|
}
|
|
|
|
impl BigGlyphMetrics {
|
|
/// Number of rows of data.
|
|
pub fn height(&self) -> u8 {
|
|
self.height
|
|
}
|
|
|
|
/// Number of columns of data.
|
|
pub fn width(&self) -> u8 {
|
|
self.width
|
|
}
|
|
|
|
/// Distance in pixels from the horizontal origin to the left edge of the bitmap.
|
|
pub fn hori_bearing_x(&self) -> i8 {
|
|
self.hori_bearing_x.get()
|
|
}
|
|
|
|
/// Distance in pixels from the horizontal origin to the top edge of the bitmap.
|
|
pub fn hori_bearing_y(&self) -> i8 {
|
|
self.hori_bearing_y.get()
|
|
}
|
|
|
|
/// Horizontal advance width in pixels.
|
|
pub fn hori_advance(&self) -> u8 {
|
|
self.hori_advance
|
|
}
|
|
|
|
/// Distance in pixels from the vertical origin to the left edge of the bitmap.
|
|
pub fn vert_bearing_x(&self) -> i8 {
|
|
self.vert_bearing_x.get()
|
|
}
|
|
|
|
/// Distance in pixels from the vertical origin to the top edge of the bitmap.
|
|
pub fn vert_bearing_y(&self) -> i8 {
|
|
self.vert_bearing_y.get()
|
|
}
|
|
|
|
/// Vertical advance width in pixels.
|
|
pub fn vert_advance(&self) -> u8 {
|
|
self.vert_advance
|
|
}
|
|
}
|
|
|
|
impl FixedSize for BigGlyphMetrics {
|
|
const RAW_BYTE_LEN: usize = u8::RAW_BYTE_LEN
|
|
+ u8::RAW_BYTE_LEN
|
|
+ i8::RAW_BYTE_LEN
|
|
+ i8::RAW_BYTE_LEN
|
|
+ u8::RAW_BYTE_LEN
|
|
+ i8::RAW_BYTE_LEN
|
|
+ i8::RAW_BYTE_LEN
|
|
+ u8::RAW_BYTE_LEN;
|
|
}
|
|
|
|
#[cfg(feature = "experimental_traverse")]
|
|
impl<'a> SomeRecord<'a> for BigGlyphMetrics {
|
|
fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
|
|
RecordResolver {
|
|
name: "BigGlyphMetrics",
|
|
get_field: Box::new(move |idx, _data| match idx {
|
|
0usize => Some(Field::new("height", self.height())),
|
|
1usize => Some(Field::new("width", self.width())),
|
|
2usize => Some(Field::new("hori_bearing_x", self.hori_bearing_x())),
|
|
3usize => Some(Field::new("hori_bearing_y", self.hori_bearing_y())),
|
|
4usize => Some(Field::new("hori_advance", self.hori_advance())),
|
|
5usize => Some(Field::new("vert_bearing_x", self.vert_bearing_x())),
|
|
6usize => Some(Field::new("vert_bearing_y", self.vert_bearing_y())),
|
|
7usize => Some(Field::new("vert_advance", self.vert_advance())),
|
|
_ => None,
|
|
}),
|
|
data,
|
|
}
|
|
}
|
|
}
|
|
|
|
/// [SmallGlyphMetrics](https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#smallglyphmetrics) record.
|
|
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
|
|
#[repr(C)]
|
|
#[repr(packed)]
|
|
pub struct SmallGlyphMetrics {
|
|
/// Number of rows of data.
|
|
pub height: u8,
|
|
/// Number of columns of data.
|
|
pub width: u8,
|
|
/// Distance in pixels from the horizontal origin to the left edge of the bitmap (for horizontal text); or distance in pixels from the vertical origin to the top edge of the bitmap (for vertical text).
|
|
pub bearing_x: BigEndian<i8>,
|
|
/// Distance in pixels from the horizontal origin to the top edge of the bitmap (for horizontal text); or distance in pixels from the vertical origin to the left edge of the bitmap (for vertical text).
|
|
pub bearing_y: BigEndian<i8>,
|
|
/// Horizontal or vertical advance width in pixels.
|
|
pub advance: u8,
|
|
}
|
|
|
|
impl SmallGlyphMetrics {
|
|
/// Number of rows of data.
|
|
pub fn height(&self) -> u8 {
|
|
self.height
|
|
}
|
|
|
|
/// Number of columns of data.
|
|
pub fn width(&self) -> u8 {
|
|
self.width
|
|
}
|
|
|
|
/// Distance in pixels from the horizontal origin to the left edge of the bitmap (for horizontal text); or distance in pixels from the vertical origin to the top edge of the bitmap (for vertical text).
|
|
pub fn bearing_x(&self) -> i8 {
|
|
self.bearing_x.get()
|
|
}
|
|
|
|
/// Distance in pixels from the horizontal origin to the top edge of the bitmap (for horizontal text); or distance in pixels from the vertical origin to the left edge of the bitmap (for vertical text).
|
|
pub fn bearing_y(&self) -> i8 {
|
|
self.bearing_y.get()
|
|
}
|
|
|
|
/// Horizontal or vertical advance width in pixels.
|
|
pub fn advance(&self) -> u8 {
|
|
self.advance
|
|
}
|
|
}
|
|
|
|
impl FixedSize for SmallGlyphMetrics {
|
|
const RAW_BYTE_LEN: usize = u8::RAW_BYTE_LEN
|
|
+ u8::RAW_BYTE_LEN
|
|
+ i8::RAW_BYTE_LEN
|
|
+ i8::RAW_BYTE_LEN
|
|
+ u8::RAW_BYTE_LEN;
|
|
}
|
|
|
|
#[cfg(feature = "experimental_traverse")]
|
|
impl<'a> SomeRecord<'a> for SmallGlyphMetrics {
|
|
fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
|
|
RecordResolver {
|
|
name: "SmallGlyphMetrics",
|
|
get_field: Box::new(move |idx, _data| match idx {
|
|
0usize => Some(Field::new("height", self.height())),
|
|
1usize => Some(Field::new("width", self.width())),
|
|
2usize => Some(Field::new("bearing_x", self.bearing_x())),
|
|
3usize => Some(Field::new("bearing_y", self.bearing_y())),
|
|
4usize => Some(Field::new("advance", self.advance())),
|
|
_ => None,
|
|
}),
|
|
data,
|
|
}
|
|
}
|
|
}
|
|
|
|
/// [IndexSubtableList](https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#indexsubtablelist) table.
|
|
#[derive(Debug, Clone, Copy)]
|
|
#[doc(hidden)]
|
|
pub struct IndexSubtableListMarker {
|
|
index_subtable_records_byte_len: usize,
|
|
}
|
|
|
|
impl IndexSubtableListMarker {
|
|
pub fn index_subtable_records_byte_range(&self) -> Range<usize> {
|
|
let start = 0;
|
|
start..start + self.index_subtable_records_byte_len
|
|
}
|
|
}
|
|
|
|
impl MinByteRange for IndexSubtableListMarker {
|
|
fn min_byte_range(&self) -> Range<usize> {
|
|
0..self.index_subtable_records_byte_range().end
|
|
}
|
|
}
|
|
|
|
impl ReadArgs for IndexSubtableList<'_> {
|
|
type Args = u32;
|
|
}
|
|
|
|
impl<'a> FontReadWithArgs<'a> for IndexSubtableList<'a> {
|
|
fn read_with_args(data: FontData<'a>, args: &u32) -> Result<Self, ReadError> {
|
|
let number_of_index_subtables = *args;
|
|
let mut cursor = data.cursor();
|
|
let index_subtable_records_byte_len = (number_of_index_subtables as usize)
|
|
.checked_mul(IndexSubtableRecord::RAW_BYTE_LEN)
|
|
.ok_or(ReadError::OutOfBounds)?;
|
|
cursor.advance_by(index_subtable_records_byte_len);
|
|
cursor.finish(IndexSubtableListMarker {
|
|
index_subtable_records_byte_len,
|
|
})
|
|
}
|
|
}
|
|
|
|
impl<'a> IndexSubtableList<'a> {
|
|
/// A constructor that requires additional arguments.
|
|
///
|
|
/// This type requires some external state in order to be
|
|
/// parsed.
|
|
pub fn read(data: FontData<'a>, number_of_index_subtables: u32) -> Result<Self, ReadError> {
|
|
let args = number_of_index_subtables;
|
|
Self::read_with_args(data, &args)
|
|
}
|
|
}
|
|
|
|
/// [IndexSubtableList](https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#indexsubtablelist) table.
|
|
pub type IndexSubtableList<'a> = TableRef<'a, IndexSubtableListMarker>;
|
|
|
|
#[allow(clippy::needless_lifetimes)]
|
|
impl<'a> IndexSubtableList<'a> {
|
|
/// Array of IndexSubtableRecords.
|
|
pub fn index_subtable_records(&self) -> &'a [IndexSubtableRecord] {
|
|
let range = self.shape.index_subtable_records_byte_range();
|
|
self.data.read_array(range).unwrap()
|
|
}
|
|
}
|
|
|
|
#[cfg(feature = "experimental_traverse")]
|
|
impl<'a> SomeTable<'a> for IndexSubtableList<'a> {
|
|
fn type_name(&self) -> &str {
|
|
"IndexSubtableList"
|
|
}
|
|
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
|
|
match idx {
|
|
0usize => Some(Field::new(
|
|
"index_subtable_records",
|
|
traversal::FieldType::array_of_records(
|
|
stringify!(IndexSubtableRecord),
|
|
self.index_subtable_records(),
|
|
self.offset_data(),
|
|
),
|
|
)),
|
|
_ => None,
|
|
}
|
|
}
|
|
}
|
|
|
|
#[cfg(feature = "experimental_traverse")]
|
|
#[allow(clippy::needless_lifetimes)]
|
|
impl<'a> std::fmt::Debug for IndexSubtableList<'a> {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
(self as &dyn SomeTable<'a>).fmt(f)
|
|
}
|
|
}
|
|
|
|
#[derive(Clone, Debug, Copy, bytemuck :: AnyBitPattern)]
|
|
#[repr(C)]
|
|
#[repr(packed)]
|
|
pub struct IndexSubtableRecord {
|
|
/// First glyph ID of this range.
|
|
pub first_glyph_index: BigEndian<GlyphId16>,
|
|
/// Last glyph ID of this range (inclusive).
|
|
pub last_glyph_index: BigEndian<GlyphId16>,
|
|
/// Offset to an IndexSubtable from the start of the IndexSubtableList.
|
|
pub index_subtable_offset: BigEndian<Offset32>,
|
|
}
|
|
|
|
impl IndexSubtableRecord {
|
|
/// First glyph ID of this range.
|
|
pub fn first_glyph_index(&self) -> GlyphId16 {
|
|
self.first_glyph_index.get()
|
|
}
|
|
|
|
/// Last glyph ID of this range (inclusive).
|
|
pub fn last_glyph_index(&self) -> GlyphId16 {
|
|
self.last_glyph_index.get()
|
|
}
|
|
|
|
/// Offset to an IndexSubtable from the start of the IndexSubtableList.
|
|
pub fn index_subtable_offset(&self) -> Offset32 {
|
|
self.index_subtable_offset.get()
|
|
}
|
|
|
|
/// Offset to an IndexSubtable from the start of the IndexSubtableList.
|
|
///
|
|
/// The `data` argument should be retrieved from the parent table
|
|
/// By calling its `offset_data` method.
|
|
pub fn index_subtable<'a>(&self, data: FontData<'a>) -> Result<IndexSubtable<'a>, ReadError> {
|
|
let args = (self.last_glyph_index(), self.first_glyph_index());
|
|
self.index_subtable_offset().resolve_with_args(data, &args)
|
|
}
|
|
}
|
|
|
|
impl FixedSize for IndexSubtableRecord {
|
|
const RAW_BYTE_LEN: usize =
|
|
GlyphId16::RAW_BYTE_LEN + GlyphId16::RAW_BYTE_LEN + Offset32::RAW_BYTE_LEN;
|
|
}
|
|
|
|
#[cfg(feature = "experimental_traverse")]
|
|
impl<'a> SomeRecord<'a> for IndexSubtableRecord {
|
|
fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
|
|
RecordResolver {
|
|
name: "IndexSubtableRecord",
|
|
get_field: Box::new(move |idx, _data| match idx {
|
|
0usize => Some(Field::new("first_glyph_index", self.first_glyph_index())),
|
|
1usize => Some(Field::new("last_glyph_index", self.last_glyph_index())),
|
|
2usize => Some(Field::new(
|
|
"index_subtable_offset",
|
|
FieldType::offset(self.index_subtable_offset(), self.index_subtable(_data)),
|
|
)),
|
|
_ => None,
|
|
}),
|
|
data,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Format<u16> for IndexSubtable1Marker {
|
|
const FORMAT: u16 = 1;
|
|
}
|
|
|
|
/// [IndexSubTable1](https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#indexsubtable1-variable-metrics-glyphs-with-4-byte-offsets): variable-metrics glyphs with 4-byte offsets.
|
|
#[derive(Debug, Clone, Copy)]
|
|
#[doc(hidden)]
|
|
pub struct IndexSubtable1Marker {
|
|
sbit_offsets_byte_len: usize,
|
|
}
|
|
|
|
impl IndexSubtable1Marker {
|
|
pub fn index_format_byte_range(&self) -> Range<usize> {
|
|
let start = 0;
|
|
start..start + u16::RAW_BYTE_LEN
|
|
}
|
|
|
|
pub fn image_format_byte_range(&self) -> Range<usize> {
|
|
let start = self.index_format_byte_range().end;
|
|
start..start + u16::RAW_BYTE_LEN
|
|
}
|
|
|
|
pub fn image_data_offset_byte_range(&self) -> Range<usize> {
|
|
let start = self.image_format_byte_range().end;
|
|
start..start + u32::RAW_BYTE_LEN
|
|
}
|
|
|
|
pub fn sbit_offsets_byte_range(&self) -> Range<usize> {
|
|
let start = self.image_data_offset_byte_range().end;
|
|
start..start + self.sbit_offsets_byte_len
|
|
}
|
|
}
|
|
|
|
impl MinByteRange for IndexSubtable1Marker {
|
|
fn min_byte_range(&self) -> Range<usize> {
|
|
0..self.sbit_offsets_byte_range().end
|
|
}
|
|
}
|
|
|
|
impl ReadArgs for IndexSubtable1<'_> {
|
|
type Args = (GlyphId16, GlyphId16);
|
|
}
|
|
|
|
impl<'a> FontReadWithArgs<'a> for IndexSubtable1<'a> {
|
|
fn read_with_args(
|
|
data: FontData<'a>,
|
|
args: &(GlyphId16, GlyphId16),
|
|
) -> Result<Self, ReadError> {
|
|
let (last_glyph_index, first_glyph_index) = *args;
|
|
let mut cursor = data.cursor();
|
|
cursor.advance::<u16>();
|
|
cursor.advance::<u16>();
|
|
cursor.advance::<u32>();
|
|
let sbit_offsets_byte_len =
|
|
(transforms::subtract_add_two(last_glyph_index, first_glyph_index))
|
|
.checked_mul(u32::RAW_BYTE_LEN)
|
|
.ok_or(ReadError::OutOfBounds)?;
|
|
cursor.advance_by(sbit_offsets_byte_len);
|
|
cursor.finish(IndexSubtable1Marker {
|
|
sbit_offsets_byte_len,
|
|
})
|
|
}
|
|
}
|
|
|
|
impl<'a> IndexSubtable1<'a> {
|
|
/// A constructor that requires additional arguments.
|
|
///
|
|
/// This type requires some external state in order to be
|
|
/// parsed.
|
|
pub fn read(
|
|
data: FontData<'a>,
|
|
last_glyph_index: GlyphId16,
|
|
first_glyph_index: GlyphId16,
|
|
) -> Result<Self, ReadError> {
|
|
let args = (last_glyph_index, first_glyph_index);
|
|
Self::read_with_args(data, &args)
|
|
}
|
|
}
|
|
|
|
/// [IndexSubTable1](https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#indexsubtable1-variable-metrics-glyphs-with-4-byte-offsets): variable-metrics glyphs with 4-byte offsets.
|
|
pub type IndexSubtable1<'a> = TableRef<'a, IndexSubtable1Marker>;
|
|
|
|
#[allow(clippy::needless_lifetimes)]
|
|
impl<'a> IndexSubtable1<'a> {
|
|
/// Format of this IndexSubTable.
|
|
pub fn index_format(&self) -> u16 {
|
|
let range = self.shape.index_format_byte_range();
|
|
self.data.read_at(range.start).unwrap()
|
|
}
|
|
|
|
/// Format of EBDT image data.
|
|
pub fn image_format(&self) -> u16 {
|
|
let range = self.shape.image_format_byte_range();
|
|
self.data.read_at(range.start).unwrap()
|
|
}
|
|
|
|
/// Offset to image data in EBDT table.
|
|
pub fn image_data_offset(&self) -> u32 {
|
|
let range = self.shape.image_data_offset_byte_range();
|
|
self.data.read_at(range.start).unwrap()
|
|
}
|
|
|
|
pub fn sbit_offsets(&self) -> &'a [BigEndian<u32>] {
|
|
let range = self.shape.sbit_offsets_byte_range();
|
|
self.data.read_array(range).unwrap()
|
|
}
|
|
}
|
|
|
|
#[cfg(feature = "experimental_traverse")]
|
|
impl<'a> SomeTable<'a> for IndexSubtable1<'a> {
|
|
fn type_name(&self) -> &str {
|
|
"IndexSubtable1"
|
|
}
|
|
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
|
|
match idx {
|
|
0usize => Some(Field::new("index_format", self.index_format())),
|
|
1usize => Some(Field::new("image_format", self.image_format())),
|
|
2usize => Some(Field::new("image_data_offset", self.image_data_offset())),
|
|
3usize => Some(Field::new("sbit_offsets", self.sbit_offsets())),
|
|
_ => None,
|
|
}
|
|
}
|
|
}
|
|
|
|
#[cfg(feature = "experimental_traverse")]
|
|
#[allow(clippy::needless_lifetimes)]
|
|
impl<'a> std::fmt::Debug for IndexSubtable1<'a> {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
(self as &dyn SomeTable<'a>).fmt(f)
|
|
}
|
|
}
|
|
|
|
impl Format<u16> for IndexSubtable2Marker {
|
|
const FORMAT: u16 = 2;
|
|
}
|
|
|
|
/// [IndexSubTable2](https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#indexsubtable2-all-glyphs-have-identical-metrics): all glyphs have identical metrics.
|
|
#[derive(Debug, Clone, Copy)]
|
|
#[doc(hidden)]
|
|
pub struct IndexSubtable2Marker {
|
|
big_metrics_byte_len: usize,
|
|
}
|
|
|
|
impl IndexSubtable2Marker {
|
|
pub fn index_format_byte_range(&self) -> Range<usize> {
|
|
let start = 0;
|
|
start..start + u16::RAW_BYTE_LEN
|
|
}
|
|
|
|
pub fn image_format_byte_range(&self) -> Range<usize> {
|
|
let start = self.index_format_byte_range().end;
|
|
start..start + u16::RAW_BYTE_LEN
|
|
}
|
|
|
|
pub fn image_data_offset_byte_range(&self) -> Range<usize> {
|
|
let start = self.image_format_byte_range().end;
|
|
start..start + u32::RAW_BYTE_LEN
|
|
}
|
|
|
|
pub fn image_size_byte_range(&self) -> Range<usize> {
|
|
let start = self.image_data_offset_byte_range().end;
|
|
start..start + u32::RAW_BYTE_LEN
|
|
}
|
|
|
|
pub fn big_metrics_byte_range(&self) -> Range<usize> {
|
|
let start = self.image_size_byte_range().end;
|
|
start..start + self.big_metrics_byte_len
|
|
}
|
|
}
|
|
|
|
impl MinByteRange for IndexSubtable2Marker {
|
|
fn min_byte_range(&self) -> Range<usize> {
|
|
0..self.big_metrics_byte_range().end
|
|
}
|
|
}
|
|
|
|
impl<'a> FontRead<'a> for IndexSubtable2<'a> {
|
|
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
|
|
let mut cursor = data.cursor();
|
|
cursor.advance::<u16>();
|
|
cursor.advance::<u16>();
|
|
cursor.advance::<u32>();
|
|
cursor.advance::<u32>();
|
|
let big_metrics_byte_len = BigGlyphMetrics::RAW_BYTE_LEN;
|
|
cursor.advance_by(big_metrics_byte_len);
|
|
cursor.finish(IndexSubtable2Marker {
|
|
big_metrics_byte_len,
|
|
})
|
|
}
|
|
}
|
|
|
|
/// [IndexSubTable2](https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#indexsubtable2-all-glyphs-have-identical-metrics): all glyphs have identical metrics.
|
|
pub type IndexSubtable2<'a> = TableRef<'a, IndexSubtable2Marker>;
|
|
|
|
#[allow(clippy::needless_lifetimes)]
|
|
impl<'a> IndexSubtable2<'a> {
|
|
/// Format of this IndexSubTable.
|
|
pub fn index_format(&self) -> u16 {
|
|
let range = self.shape.index_format_byte_range();
|
|
self.data.read_at(range.start).unwrap()
|
|
}
|
|
|
|
/// Format of EBDT image data.
|
|
pub fn image_format(&self) -> u16 {
|
|
let range = self.shape.image_format_byte_range();
|
|
self.data.read_at(range.start).unwrap()
|
|
}
|
|
|
|
/// Offset to image data in EBDT table.
|
|
pub fn image_data_offset(&self) -> u32 {
|
|
let range = self.shape.image_data_offset_byte_range();
|
|
self.data.read_at(range.start).unwrap()
|
|
}
|
|
|
|
/// All the glyphs are of the same size.
|
|
pub fn image_size(&self) -> u32 {
|
|
let range = self.shape.image_size_byte_range();
|
|
self.data.read_at(range.start).unwrap()
|
|
}
|
|
|
|
/// All glyphs have the same metrics; glyph data may be compressed, byte-aligned, or bit-aligned.
|
|
pub fn big_metrics(&self) -> &'a [BigGlyphMetrics] {
|
|
let range = self.shape.big_metrics_byte_range();
|
|
self.data.read_array(range).unwrap()
|
|
}
|
|
}
|
|
|
|
#[cfg(feature = "experimental_traverse")]
|
|
impl<'a> SomeTable<'a> for IndexSubtable2<'a> {
|
|
fn type_name(&self) -> &str {
|
|
"IndexSubtable2"
|
|
}
|
|
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
|
|
match idx {
|
|
0usize => Some(Field::new("index_format", self.index_format())),
|
|
1usize => Some(Field::new("image_format", self.image_format())),
|
|
2usize => Some(Field::new("image_data_offset", self.image_data_offset())),
|
|
3usize => Some(Field::new("image_size", self.image_size())),
|
|
4usize => Some(Field::new(
|
|
"big_metrics",
|
|
traversal::FieldType::array_of_records(
|
|
stringify!(BigGlyphMetrics),
|
|
self.big_metrics(),
|
|
self.offset_data(),
|
|
),
|
|
)),
|
|
_ => None,
|
|
}
|
|
}
|
|
}
|
|
|
|
#[cfg(feature = "experimental_traverse")]
|
|
#[allow(clippy::needless_lifetimes)]
|
|
impl<'a> std::fmt::Debug for IndexSubtable2<'a> {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
(self as &dyn SomeTable<'a>).fmt(f)
|
|
}
|
|
}
|
|
|
|
impl Format<u16> for IndexSubtable3Marker {
|
|
const FORMAT: u16 = 3;
|
|
}
|
|
|
|
/// [IndexSubTable3](https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#indexsubtable3-variable-metrics-glyphs-with-2-byte-offsets): variable-metrics glyphs with 2-byte offsets.
|
|
#[derive(Debug, Clone, Copy)]
|
|
#[doc(hidden)]
|
|
pub struct IndexSubtable3Marker {
|
|
sbit_offsets_byte_len: usize,
|
|
}
|
|
|
|
impl IndexSubtable3Marker {
|
|
pub fn index_format_byte_range(&self) -> Range<usize> {
|
|
let start = 0;
|
|
start..start + u16::RAW_BYTE_LEN
|
|
}
|
|
|
|
pub fn image_format_byte_range(&self) -> Range<usize> {
|
|
let start = self.index_format_byte_range().end;
|
|
start..start + u16::RAW_BYTE_LEN
|
|
}
|
|
|
|
pub fn image_data_offset_byte_range(&self) -> Range<usize> {
|
|
let start = self.image_format_byte_range().end;
|
|
start..start + u32::RAW_BYTE_LEN
|
|
}
|
|
|
|
pub fn sbit_offsets_byte_range(&self) -> Range<usize> {
|
|
let start = self.image_data_offset_byte_range().end;
|
|
start..start + self.sbit_offsets_byte_len
|
|
}
|
|
}
|
|
|
|
impl MinByteRange for IndexSubtable3Marker {
|
|
fn min_byte_range(&self) -> Range<usize> {
|
|
0..self.sbit_offsets_byte_range().end
|
|
}
|
|
}
|
|
|
|
impl ReadArgs for IndexSubtable3<'_> {
|
|
type Args = (GlyphId16, GlyphId16);
|
|
}
|
|
|
|
impl<'a> FontReadWithArgs<'a> for IndexSubtable3<'a> {
|
|
fn read_with_args(
|
|
data: FontData<'a>,
|
|
args: &(GlyphId16, GlyphId16),
|
|
) -> Result<Self, ReadError> {
|
|
let (last_glyph_index, first_glyph_index) = *args;
|
|
let mut cursor = data.cursor();
|
|
cursor.advance::<u16>();
|
|
cursor.advance::<u16>();
|
|
cursor.advance::<u32>();
|
|
let sbit_offsets_byte_len =
|
|
(transforms::subtract_add_two(last_glyph_index, first_glyph_index))
|
|
.checked_mul(u16::RAW_BYTE_LEN)
|
|
.ok_or(ReadError::OutOfBounds)?;
|
|
cursor.advance_by(sbit_offsets_byte_len);
|
|
cursor.finish(IndexSubtable3Marker {
|
|
sbit_offsets_byte_len,
|
|
})
|
|
}
|
|
}
|
|
|
|
impl<'a> IndexSubtable3<'a> {
|
|
/// A constructor that requires additional arguments.
|
|
///
|
|
/// This type requires some external state in order to be
|
|
/// parsed.
|
|
pub fn read(
|
|
data: FontData<'a>,
|
|
last_glyph_index: GlyphId16,
|
|
first_glyph_index: GlyphId16,
|
|
) -> Result<Self, ReadError> {
|
|
let args = (last_glyph_index, first_glyph_index);
|
|
Self::read_with_args(data, &args)
|
|
}
|
|
}
|
|
|
|
/// [IndexSubTable3](https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#indexsubtable3-variable-metrics-glyphs-with-2-byte-offsets): variable-metrics glyphs with 2-byte offsets.
|
|
pub type IndexSubtable3<'a> = TableRef<'a, IndexSubtable3Marker>;
|
|
|
|
#[allow(clippy::needless_lifetimes)]
|
|
impl<'a> IndexSubtable3<'a> {
|
|
/// Format of this IndexSubTable.
|
|
pub fn index_format(&self) -> u16 {
|
|
let range = self.shape.index_format_byte_range();
|
|
self.data.read_at(range.start).unwrap()
|
|
}
|
|
|
|
/// Format of EBDT image data.
|
|
pub fn image_format(&self) -> u16 {
|
|
let range = self.shape.image_format_byte_range();
|
|
self.data.read_at(range.start).unwrap()
|
|
}
|
|
|
|
/// Offset to image data in EBDT table.
|
|
pub fn image_data_offset(&self) -> u32 {
|
|
let range = self.shape.image_data_offset_byte_range();
|
|
self.data.read_at(range.start).unwrap()
|
|
}
|
|
|
|
pub fn sbit_offsets(&self) -> &'a [BigEndian<u16>] {
|
|
let range = self.shape.sbit_offsets_byte_range();
|
|
self.data.read_array(range).unwrap()
|
|
}
|
|
}
|
|
|
|
#[cfg(feature = "experimental_traverse")]
|
|
impl<'a> SomeTable<'a> for IndexSubtable3<'a> {
|
|
fn type_name(&self) -> &str {
|
|
"IndexSubtable3"
|
|
}
|
|
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
|
|
match idx {
|
|
0usize => Some(Field::new("index_format", self.index_format())),
|
|
1usize => Some(Field::new("image_format", self.image_format())),
|
|
2usize => Some(Field::new("image_data_offset", self.image_data_offset())),
|
|
3usize => Some(Field::new("sbit_offsets", self.sbit_offsets())),
|
|
_ => None,
|
|
}
|
|
}
|
|
}
|
|
|
|
#[cfg(feature = "experimental_traverse")]
|
|
#[allow(clippy::needless_lifetimes)]
|
|
impl<'a> std::fmt::Debug for IndexSubtable3<'a> {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
(self as &dyn SomeTable<'a>).fmt(f)
|
|
}
|
|
}
|
|
|
|
impl Format<u16> for IndexSubtable4Marker {
|
|
const FORMAT: u16 = 4;
|
|
}
|
|
|
|
/// [IndexSubTable4](https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#indexsubtable3-variable-metrics-glyphs-with-2-byte-offsets): variable-metrics glyphs with sparse glyph codes.
|
|
#[derive(Debug, Clone, Copy)]
|
|
#[doc(hidden)]
|
|
pub struct IndexSubtable4Marker {
|
|
glyph_array_byte_len: usize,
|
|
}
|
|
|
|
impl IndexSubtable4Marker {
|
|
pub fn index_format_byte_range(&self) -> Range<usize> {
|
|
let start = 0;
|
|
start..start + u16::RAW_BYTE_LEN
|
|
}
|
|
|
|
pub fn image_format_byte_range(&self) -> Range<usize> {
|
|
let start = self.index_format_byte_range().end;
|
|
start..start + u16::RAW_BYTE_LEN
|
|
}
|
|
|
|
pub fn image_data_offset_byte_range(&self) -> Range<usize> {
|
|
let start = self.image_format_byte_range().end;
|
|
start..start + u32::RAW_BYTE_LEN
|
|
}
|
|
|
|
pub fn num_glyphs_byte_range(&self) -> Range<usize> {
|
|
let start = self.image_data_offset_byte_range().end;
|
|
start..start + u32::RAW_BYTE_LEN
|
|
}
|
|
|
|
pub fn glyph_array_byte_range(&self) -> Range<usize> {
|
|
let start = self.num_glyphs_byte_range().end;
|
|
start..start + self.glyph_array_byte_len
|
|
}
|
|
}
|
|
|
|
impl MinByteRange for IndexSubtable4Marker {
|
|
fn min_byte_range(&self) -> Range<usize> {
|
|
0..self.glyph_array_byte_range().end
|
|
}
|
|
}
|
|
|
|
impl<'a> FontRead<'a> for IndexSubtable4<'a> {
|
|
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
|
|
let mut cursor = data.cursor();
|
|
cursor.advance::<u16>();
|
|
cursor.advance::<u16>();
|
|
cursor.advance::<u32>();
|
|
let num_glyphs: u32 = cursor.read()?;
|
|
let glyph_array_byte_len = (transforms::add(num_glyphs, 1_usize))
|
|
.checked_mul(GlyphIdOffsetPair::RAW_BYTE_LEN)
|
|
.ok_or(ReadError::OutOfBounds)?;
|
|
cursor.advance_by(glyph_array_byte_len);
|
|
cursor.finish(IndexSubtable4Marker {
|
|
glyph_array_byte_len,
|
|
})
|
|
}
|
|
}
|
|
|
|
/// [IndexSubTable4](https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#indexsubtable3-variable-metrics-glyphs-with-2-byte-offsets): variable-metrics glyphs with sparse glyph codes.
|
|
pub type IndexSubtable4<'a> = TableRef<'a, IndexSubtable4Marker>;
|
|
|
|
#[allow(clippy::needless_lifetimes)]
|
|
impl<'a> IndexSubtable4<'a> {
|
|
/// Format of this IndexSubTable.
|
|
pub fn index_format(&self) -> u16 {
|
|
let range = self.shape.index_format_byte_range();
|
|
self.data.read_at(range.start).unwrap()
|
|
}
|
|
|
|
/// Format of EBDT image data.
|
|
pub fn image_format(&self) -> u16 {
|
|
let range = self.shape.image_format_byte_range();
|
|
self.data.read_at(range.start).unwrap()
|
|
}
|
|
|
|
/// Offset to image data in EBDT table.
|
|
pub fn image_data_offset(&self) -> u32 {
|
|
let range = self.shape.image_data_offset_byte_range();
|
|
self.data.read_at(range.start).unwrap()
|
|
}
|
|
|
|
/// Array length.
|
|
pub fn num_glyphs(&self) -> u32 {
|
|
let range = self.shape.num_glyphs_byte_range();
|
|
self.data.read_at(range.start).unwrap()
|
|
}
|
|
|
|
/// One per glyph.
|
|
pub fn glyph_array(&self) -> &'a [GlyphIdOffsetPair] {
|
|
let range = self.shape.glyph_array_byte_range();
|
|
self.data.read_array(range).unwrap()
|
|
}
|
|
}
|
|
|
|
#[cfg(feature = "experimental_traverse")]
|
|
impl<'a> SomeTable<'a> for IndexSubtable4<'a> {
|
|
fn type_name(&self) -> &str {
|
|
"IndexSubtable4"
|
|
}
|
|
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
|
|
match idx {
|
|
0usize => Some(Field::new("index_format", self.index_format())),
|
|
1usize => Some(Field::new("image_format", self.image_format())),
|
|
2usize => Some(Field::new("image_data_offset", self.image_data_offset())),
|
|
3usize => Some(Field::new("num_glyphs", self.num_glyphs())),
|
|
4usize => Some(Field::new(
|
|
"glyph_array",
|
|
traversal::FieldType::array_of_records(
|
|
stringify!(GlyphIdOffsetPair),
|
|
self.glyph_array(),
|
|
self.offset_data(),
|
|
),
|
|
)),
|
|
_ => None,
|
|
}
|
|
}
|
|
}
|
|
|
|
#[cfg(feature = "experimental_traverse")]
|
|
#[allow(clippy::needless_lifetimes)]
|
|
impl<'a> std::fmt::Debug for IndexSubtable4<'a> {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
(self as &dyn SomeTable<'a>).fmt(f)
|
|
}
|
|
}
|
|
|
|
/// [GlyphIdOffsetPair](https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#glyphidoffsetpair-record) record.
|
|
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
|
|
#[repr(C)]
|
|
#[repr(packed)]
|
|
pub struct GlyphIdOffsetPair {
|
|
/// Glyph ID of glyph present.
|
|
pub glyph_id: BigEndian<GlyphId16>,
|
|
/// Location in EBDT.
|
|
pub sbit_offset: BigEndian<u16>,
|
|
}
|
|
|
|
impl GlyphIdOffsetPair {
|
|
/// Glyph ID of glyph present.
|
|
pub fn glyph_id(&self) -> GlyphId16 {
|
|
self.glyph_id.get()
|
|
}
|
|
|
|
/// Location in EBDT.
|
|
pub fn sbit_offset(&self) -> u16 {
|
|
self.sbit_offset.get()
|
|
}
|
|
}
|
|
|
|
impl FixedSize for GlyphIdOffsetPair {
|
|
const RAW_BYTE_LEN: usize = GlyphId16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN;
|
|
}
|
|
|
|
#[cfg(feature = "experimental_traverse")]
|
|
impl<'a> SomeRecord<'a> for GlyphIdOffsetPair {
|
|
fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
|
|
RecordResolver {
|
|
name: "GlyphIdOffsetPair",
|
|
get_field: Box::new(move |idx, _data| match idx {
|
|
0usize => Some(Field::new("glyph_id", self.glyph_id())),
|
|
1usize => Some(Field::new("sbit_offset", self.sbit_offset())),
|
|
_ => None,
|
|
}),
|
|
data,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Format<u16> for IndexSubtable5Marker {
|
|
const FORMAT: u16 = 5;
|
|
}
|
|
|
|
/// [IndexSubTable5](https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#indexsubtable5-constant-metrics-glyphs-with-sparse-glyph-codes): constant-metrics glyphs with sparse glyph codes
|
|
#[derive(Debug, Clone, Copy)]
|
|
#[doc(hidden)]
|
|
pub struct IndexSubtable5Marker {
|
|
big_metrics_byte_len: usize,
|
|
glyph_array_byte_len: usize,
|
|
}
|
|
|
|
impl IndexSubtable5Marker {
|
|
pub fn index_format_byte_range(&self) -> Range<usize> {
|
|
let start = 0;
|
|
start..start + u16::RAW_BYTE_LEN
|
|
}
|
|
|
|
pub fn image_format_byte_range(&self) -> Range<usize> {
|
|
let start = self.index_format_byte_range().end;
|
|
start..start + u16::RAW_BYTE_LEN
|
|
}
|
|
|
|
pub fn image_data_offset_byte_range(&self) -> Range<usize> {
|
|
let start = self.image_format_byte_range().end;
|
|
start..start + u32::RAW_BYTE_LEN
|
|
}
|
|
|
|
pub fn image_size_byte_range(&self) -> Range<usize> {
|
|
let start = self.image_data_offset_byte_range().end;
|
|
start..start + u32::RAW_BYTE_LEN
|
|
}
|
|
|
|
pub fn big_metrics_byte_range(&self) -> Range<usize> {
|
|
let start = self.image_size_byte_range().end;
|
|
start..start + self.big_metrics_byte_len
|
|
}
|
|
|
|
pub fn num_glyphs_byte_range(&self) -> Range<usize> {
|
|
let start = self.big_metrics_byte_range().end;
|
|
start..start + u32::RAW_BYTE_LEN
|
|
}
|
|
|
|
pub fn glyph_array_byte_range(&self) -> Range<usize> {
|
|
let start = self.num_glyphs_byte_range().end;
|
|
start..start + self.glyph_array_byte_len
|
|
}
|
|
}
|
|
|
|
impl MinByteRange for IndexSubtable5Marker {
|
|
fn min_byte_range(&self) -> Range<usize> {
|
|
0..self.glyph_array_byte_range().end
|
|
}
|
|
}
|
|
|
|
impl<'a> FontRead<'a> for IndexSubtable5<'a> {
|
|
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
|
|
let mut cursor = data.cursor();
|
|
cursor.advance::<u16>();
|
|
cursor.advance::<u16>();
|
|
cursor.advance::<u32>();
|
|
cursor.advance::<u32>();
|
|
let big_metrics_byte_len = BigGlyphMetrics::RAW_BYTE_LEN;
|
|
cursor.advance_by(big_metrics_byte_len);
|
|
let num_glyphs: u32 = cursor.read()?;
|
|
let glyph_array_byte_len = (num_glyphs as usize)
|
|
.checked_mul(GlyphId16::RAW_BYTE_LEN)
|
|
.ok_or(ReadError::OutOfBounds)?;
|
|
cursor.advance_by(glyph_array_byte_len);
|
|
cursor.finish(IndexSubtable5Marker {
|
|
big_metrics_byte_len,
|
|
glyph_array_byte_len,
|
|
})
|
|
}
|
|
}
|
|
|
|
/// [IndexSubTable5](https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#indexsubtable5-constant-metrics-glyphs-with-sparse-glyph-codes): constant-metrics glyphs with sparse glyph codes
|
|
pub type IndexSubtable5<'a> = TableRef<'a, IndexSubtable5Marker>;
|
|
|
|
#[allow(clippy::needless_lifetimes)]
|
|
impl<'a> IndexSubtable5<'a> {
|
|
/// Format of this IndexSubTable.
|
|
pub fn index_format(&self) -> u16 {
|
|
let range = self.shape.index_format_byte_range();
|
|
self.data.read_at(range.start).unwrap()
|
|
}
|
|
|
|
/// Format of EBDT image data.
|
|
pub fn image_format(&self) -> u16 {
|
|
let range = self.shape.image_format_byte_range();
|
|
self.data.read_at(range.start).unwrap()
|
|
}
|
|
|
|
/// Offset to image data in EBDT table.
|
|
pub fn image_data_offset(&self) -> u32 {
|
|
let range = self.shape.image_data_offset_byte_range();
|
|
self.data.read_at(range.start).unwrap()
|
|
}
|
|
|
|
/// All glyphs have the same data size.
|
|
pub fn image_size(&self) -> u32 {
|
|
let range = self.shape.image_size_byte_range();
|
|
self.data.read_at(range.start).unwrap()
|
|
}
|
|
|
|
/// All glyphs have the same metrics.
|
|
pub fn big_metrics(&self) -> &'a [BigGlyphMetrics] {
|
|
let range = self.shape.big_metrics_byte_range();
|
|
self.data.read_array(range).unwrap()
|
|
}
|
|
|
|
/// Array length.
|
|
pub fn num_glyphs(&self) -> u32 {
|
|
let range = self.shape.num_glyphs_byte_range();
|
|
self.data.read_at(range.start).unwrap()
|
|
}
|
|
|
|
/// One per glyph, sorted by glyhph ID.
|
|
pub fn glyph_array(&self) -> &'a [BigEndian<GlyphId16>] {
|
|
let range = self.shape.glyph_array_byte_range();
|
|
self.data.read_array(range).unwrap()
|
|
}
|
|
}
|
|
|
|
#[cfg(feature = "experimental_traverse")]
|
|
impl<'a> SomeTable<'a> for IndexSubtable5<'a> {
|
|
fn type_name(&self) -> &str {
|
|
"IndexSubtable5"
|
|
}
|
|
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
|
|
match idx {
|
|
0usize => Some(Field::new("index_format", self.index_format())),
|
|
1usize => Some(Field::new("image_format", self.image_format())),
|
|
2usize => Some(Field::new("image_data_offset", self.image_data_offset())),
|
|
3usize => Some(Field::new("image_size", self.image_size())),
|
|
4usize => Some(Field::new(
|
|
"big_metrics",
|
|
traversal::FieldType::array_of_records(
|
|
stringify!(BigGlyphMetrics),
|
|
self.big_metrics(),
|
|
self.offset_data(),
|
|
),
|
|
)),
|
|
5usize => Some(Field::new("num_glyphs", self.num_glyphs())),
|
|
6usize => Some(Field::new("glyph_array", self.glyph_array())),
|
|
_ => None,
|
|
}
|
|
}
|
|
}
|
|
|
|
#[cfg(feature = "experimental_traverse")]
|
|
#[allow(clippy::needless_lifetimes)]
|
|
impl<'a> std::fmt::Debug for IndexSubtable5<'a> {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
(self as &dyn SomeTable<'a>).fmt(f)
|
|
}
|
|
}
|
|
|
|
/// [EbdtComponent](https://learn.microsoft.com/en-us/typography/opentype/spec/ebdt#ebdtcomponent-record) record.
|
|
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
|
|
#[repr(C)]
|
|
#[repr(packed)]
|
|
pub struct BdtComponent {
|
|
/// Component glyph ID.
|
|
pub glyph_id: BigEndian<GlyphId16>,
|
|
/// Position of component left.
|
|
pub x_offset: BigEndian<i8>,
|
|
/// Position of component top.
|
|
pub y_offset: BigEndian<i8>,
|
|
}
|
|
|
|
impl BdtComponent {
|
|
/// Component glyph ID.
|
|
pub fn glyph_id(&self) -> GlyphId16 {
|
|
self.glyph_id.get()
|
|
}
|
|
|
|
/// Position of component left.
|
|
pub fn x_offset(&self) -> i8 {
|
|
self.x_offset.get()
|
|
}
|
|
|
|
/// Position of component top.
|
|
pub fn y_offset(&self) -> i8 {
|
|
self.y_offset.get()
|
|
}
|
|
}
|
|
|
|
impl FixedSize for BdtComponent {
|
|
const RAW_BYTE_LEN: usize = GlyphId16::RAW_BYTE_LEN + i8::RAW_BYTE_LEN + i8::RAW_BYTE_LEN;
|
|
}
|
|
|
|
#[cfg(feature = "experimental_traverse")]
|
|
impl<'a> SomeRecord<'a> for BdtComponent {
|
|
fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
|
|
RecordResolver {
|
|
name: "BdtComponent",
|
|
get_field: Box::new(move |idx, _data| match idx {
|
|
0usize => Some(Field::new("glyph_id", self.glyph_id())),
|
|
1usize => Some(Field::new("x_offset", self.x_offset())),
|
|
2usize => Some(Field::new("y_offset", self.y_offset())),
|
|
_ => None,
|
|
}),
|
|
data,
|
|
}
|
|
}
|
|
}
|