#[allow(unused_imports)]
use crate::codegen_prelude::*;
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct CmapMarker {
encoding_records_byte_len: usize,
}
impl CmapMarker {
pub fn version_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + u16::RAW_BYTE_LEN
}
pub fn num_tables_byte_range(&self) -> Range<usize> {
let start = self.version_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn encoding_records_byte_range(&self) -> Range<usize> {
let start = self.num_tables_byte_range().end;
start..start + self.encoding_records_byte_len
}
}
impl TopLevelTable for Cmap<'_> {
const TAG: Tag = Tag::new(b"cmap");
}
impl<'a> FontRead<'a> for Cmap<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
cursor.advance::<u16>();
let num_tables: u16 = cursor.read()?;
let encoding_records_byte_len = (num_tables as usize)
.checked_mul(EncodingRecord::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(encoding_records_byte_len);
cursor.finish(CmapMarker {
encoding_records_byte_len,
})
}
}
pub type Cmap<'a> = TableRef<'a, CmapMarker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> Cmap<'a> {
pub fn version(&self) -> u16 {
let range = self.shape.version_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn num_tables(&self) -> u16 {
let range = self.shape.num_tables_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn encoding_records(&self) -> &'a [EncodingRecord] {
let range = self.shape.encoding_records_byte_range();
self.data.read_array(range).unwrap()
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for Cmap<'a> {
fn type_name(&self) -> &str {
"Cmap"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("version", self.version())),
1usize => Some(Field::new("num_tables", self.num_tables())),
2usize => Some(Field::new(
"encoding_records",
traversal::FieldType::array_of_records(
stringify!(EncodingRecord),
self.encoding_records(),
self.offset_data(),
),
)),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for Cmap<'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 EncodingRecord {
pub platform_id: BigEndian<PlatformId>,
pub encoding_id: BigEndian<u16>,
pub subtable_offset: BigEndian<Offset32>,
}
impl EncodingRecord {
pub fn platform_id(&self) -> PlatformId {
self.platform_id.get()
}
pub fn encoding_id(&self) -> u16 {
self.encoding_id.get()
}
pub fn subtable_offset(&self) -> Offset32 {
self.subtable_offset.get()
}
pub fn subtable<'a>(&self, data: FontData<'a>) -> Result<CmapSubtable<'a>, ReadError> {
self.subtable_offset().resolve(data)
}
}
impl FixedSize for EncodingRecord {
const RAW_BYTE_LEN: usize =
PlatformId::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + Offset32::RAW_BYTE_LEN;
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeRecord<'a> for EncodingRecord {
fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
RecordResolver {
name: "EncodingRecord",
get_field: Box::new(move |idx, _data| match idx {
0usize => Some(Field::new("platform_id", self.platform_id())),
1usize => Some(Field::new("encoding_id", self.encoding_id())),
2usize => Some(Field::new(
"subtable_offset",
FieldType::offset(self.subtable_offset(), self.subtable(_data)),
)),
_ => None,
}),
data,
}
}
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash, PartialOrd, Ord)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[repr(u16)]
#[allow(clippy::manual_non_exhaustive)]
pub enum PlatformId {
#[default]
Unicode = 0,
Macintosh = 1,
ISO = 2,
Windows = 3,
Custom = 4,
#[doc(hidden)]
Unknown,
}
impl PlatformId {
pub fn new(raw: u16) -> Self {
match raw {
0 => Self::Unicode,
1 => Self::Macintosh,
2 => Self::ISO,
3 => Self::Windows,
4 => Self::Custom,
_ => Self::Unknown,
}
}
}
impl font_types::Scalar for PlatformId {
type Raw = <u16 as font_types::Scalar>::Raw;
fn to_raw(self) -> Self::Raw {
(self as u16).to_raw()
}
fn from_raw(raw: Self::Raw) -> Self {
let t = <u16>::from_raw(raw);
Self::new(t)
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> From<PlatformId> for FieldType<'a> {
fn from(src: PlatformId) -> FieldType<'a> {
(src as u16).into()
}
}
#[derive(Clone)]
pub enum CmapSubtable<'a> {
Format0(Cmap0<'a>),
Format2(Cmap2<'a>),
Format4(Cmap4<'a>),
Format6(Cmap6<'a>),
Format8(Cmap8<'a>),
Format10(Cmap10<'a>),
Format12(Cmap12<'a>),
Format13(Cmap13<'a>),
Format14(Cmap14<'a>),
}
impl<'a> CmapSubtable<'a> {
pub fn offset_data(&self) -> FontData<'a> {
match self {
Self::Format0(item) => item.offset_data(),
Self::Format2(item) => item.offset_data(),
Self::Format4(item) => item.offset_data(),
Self::Format6(item) => item.offset_data(),
Self::Format8(item) => item.offset_data(),
Self::Format10(item) => item.offset_data(),
Self::Format12(item) => item.offset_data(),
Self::Format13(item) => item.offset_data(),
Self::Format14(item) => item.offset_data(),
}
}
pub fn format(&self) -> u16 {
match self {
Self::Format0(item) => item.format(),
Self::Format2(item) => item.format(),
Self::Format4(item) => item.format(),
Self::Format6(item) => item.format(),
Self::Format8(item) => item.format(),
Self::Format10(item) => item.format(),
Self::Format12(item) => item.format(),
Self::Format13(item) => item.format(),
Self::Format14(item) => item.format(),
}
}
}
impl<'a> FontRead<'a> for CmapSubtable<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let format: u16 = data.read_at(0usize)?;
match format {
Cmap0Marker::FORMAT => Ok(Self::Format0(FontRead::read(data)?)),
Cmap2Marker::FORMAT => Ok(Self::Format2(FontRead::read(data)?)),
Cmap4Marker::FORMAT => Ok(Self::Format4(FontRead::read(data)?)),
Cmap6Marker::FORMAT => Ok(Self::Format6(FontRead::read(data)?)),
Cmap8Marker::FORMAT => Ok(Self::Format8(FontRead::read(data)?)),
Cmap10Marker::FORMAT => Ok(Self::Format10(FontRead::read(data)?)),
Cmap12Marker::FORMAT => Ok(Self::Format12(FontRead::read(data)?)),
Cmap13Marker::FORMAT => Ok(Self::Format13(FontRead::read(data)?)),
Cmap14Marker::FORMAT => Ok(Self::Format14(FontRead::read(data)?)),
other => Err(ReadError::InvalidFormat(other.into())),
}
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> CmapSubtable<'a> {
fn dyn_inner<'b>(&'b self) -> &'b dyn SomeTable<'a> {
match self {
Self::Format0(table) => table,
Self::Format2(table) => table,
Self::Format4(table) => table,
Self::Format6(table) => table,
Self::Format8(table) => table,
Self::Format10(table) => table,
Self::Format12(table) => table,
Self::Format13(table) => table,
Self::Format14(table) => table,
}
}
}
#[cfg(feature = "experimental_traverse")]
impl std::fmt::Debug for CmapSubtable<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.dyn_inner().fmt(f)
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for CmapSubtable<'a> {
fn type_name(&self) -> &str {
self.dyn_inner().type_name()
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
self.dyn_inner().get_field(idx)
}
}
impl Format<u16> for Cmap0Marker {
const FORMAT: u16 = 0;
}
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct Cmap0Marker {
glyph_id_array_byte_len: usize,
}
impl Cmap0Marker {
pub fn format_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + u16::RAW_BYTE_LEN
}
pub fn length_byte_range(&self) -> Range<usize> {
let start = self.format_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn language_byte_range(&self) -> Range<usize> {
let start = self.length_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn glyph_id_array_byte_range(&self) -> Range<usize> {
let start = self.language_byte_range().end;
start..start + self.glyph_id_array_byte_len
}
}
impl<'a> FontRead<'a> for Cmap0<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
cursor.advance::<u16>();
cursor.advance::<u16>();
cursor.advance::<u16>();
let glyph_id_array_byte_len = (256_usize)
.checked_mul(u8::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(glyph_id_array_byte_len);
cursor.finish(Cmap0Marker {
glyph_id_array_byte_len,
})
}
}
pub type Cmap0<'a> = TableRef<'a, Cmap0Marker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> Cmap0<'a> {
pub fn format(&self) -> u16 {
let range = self.shape.format_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn length(&self) -> u16 {
let range = self.shape.length_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn language(&self) -> u16 {
let range = self.shape.language_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn glyph_id_array(&self) -> &'a [u8] {
let range = self.shape.glyph_id_array_byte_range();
self.data.read_array(range).unwrap()
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for Cmap0<'a> {
fn type_name(&self) -> &str {
"Cmap0"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("format", self.format())),
1usize => Some(Field::new("length", self.length())),
2usize => Some(Field::new("language", self.language())),
3usize => Some(Field::new("glyph_id_array", self.glyph_id_array())),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for Cmap0<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}
impl Format<u16> for Cmap2Marker {
const FORMAT: u16 = 2;
}
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct Cmap2Marker {
sub_header_keys_byte_len: usize,
}
impl Cmap2Marker {
pub fn format_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + u16::RAW_BYTE_LEN
}
pub fn length_byte_range(&self) -> Range<usize> {
let start = self.format_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn language_byte_range(&self) -> Range<usize> {
let start = self.length_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn sub_header_keys_byte_range(&self) -> Range<usize> {
let start = self.language_byte_range().end;
start..start + self.sub_header_keys_byte_len
}
}
impl<'a> FontRead<'a> for Cmap2<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
cursor.advance::<u16>();
cursor.advance::<u16>();
cursor.advance::<u16>();
let sub_header_keys_byte_len = (256_usize)
.checked_mul(u16::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(sub_header_keys_byte_len);
cursor.finish(Cmap2Marker {
sub_header_keys_byte_len,
})
}
}
pub type Cmap2<'a> = TableRef<'a, Cmap2Marker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> Cmap2<'a> {
pub fn format(&self) -> u16 {
let range = self.shape.format_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn length(&self) -> u16 {
let range = self.shape.length_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn language(&self) -> u16 {
let range = self.shape.language_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn sub_header_keys(&self) -> &'a [BigEndian<u16>] {
let range = self.shape.sub_header_keys_byte_range();
self.data.read_array(range).unwrap()
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for Cmap2<'a> {
fn type_name(&self) -> &str {
"Cmap2"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("format", self.format())),
1usize => Some(Field::new("length", self.length())),
2usize => Some(Field::new("language", self.language())),
3usize => Some(Field::new("sub_header_keys", self.sub_header_keys())),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for Cmap2<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
#[repr(C)]
#[repr(packed)]
pub struct SubHeader {
pub first_code: BigEndian<u16>,
pub entry_count: BigEndian<u16>,
pub id_delta: BigEndian<i16>,
pub id_range_offset: BigEndian<u16>,
}
impl SubHeader {
pub fn first_code(&self) -> u16 {
self.first_code.get()
}
pub fn entry_count(&self) -> u16 {
self.entry_count.get()
}
pub fn id_delta(&self) -> i16 {
self.id_delta.get()
}
pub fn id_range_offset(&self) -> u16 {
self.id_range_offset.get()
}
}
impl FixedSize for SubHeader {
const RAW_BYTE_LEN: usize =
u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + i16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN;
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeRecord<'a> for SubHeader {
fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
RecordResolver {
name: "SubHeader",
get_field: Box::new(move |idx, _data| match idx {
0usize => Some(Field::new("first_code", self.first_code())),
1usize => Some(Field::new("entry_count", self.entry_count())),
2usize => Some(Field::new("id_delta", self.id_delta())),
3usize => Some(Field::new("id_range_offset", self.id_range_offset())),
_ => None,
}),
data,
}
}
}
impl Format<u16> for Cmap4Marker {
const FORMAT: u16 = 4;
}
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct Cmap4Marker {
end_code_byte_len: usize,
start_code_byte_len: usize,
id_delta_byte_len: usize,
id_range_offsets_byte_len: usize,
glyph_id_array_byte_len: usize,
}
impl Cmap4Marker {
pub fn format_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + u16::RAW_BYTE_LEN
}
pub fn length_byte_range(&self) -> Range<usize> {
let start = self.format_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn language_byte_range(&self) -> Range<usize> {
let start = self.length_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn seg_count_x2_byte_range(&self) -> Range<usize> {
let start = self.language_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn search_range_byte_range(&self) -> Range<usize> {
let start = self.seg_count_x2_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn entry_selector_byte_range(&self) -> Range<usize> {
let start = self.search_range_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn range_shift_byte_range(&self) -> Range<usize> {
let start = self.entry_selector_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn end_code_byte_range(&self) -> Range<usize> {
let start = self.range_shift_byte_range().end;
start..start + self.end_code_byte_len
}
pub fn reserved_pad_byte_range(&self) -> Range<usize> {
let start = self.end_code_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn start_code_byte_range(&self) -> Range<usize> {
let start = self.reserved_pad_byte_range().end;
start..start + self.start_code_byte_len
}
pub fn id_delta_byte_range(&self) -> Range<usize> {
let start = self.start_code_byte_range().end;
start..start + self.id_delta_byte_len
}
pub fn id_range_offsets_byte_range(&self) -> Range<usize> {
let start = self.id_delta_byte_range().end;
start..start + self.id_range_offsets_byte_len
}
pub fn glyph_id_array_byte_range(&self) -> Range<usize> {
let start = self.id_range_offsets_byte_range().end;
start..start + self.glyph_id_array_byte_len
}
}
impl<'a> FontRead<'a> for Cmap4<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
cursor.advance::<u16>();
cursor.advance::<u16>();
cursor.advance::<u16>();
let seg_count_x2: u16 = cursor.read()?;
cursor.advance::<u16>();
cursor.advance::<u16>();
cursor.advance::<u16>();
let end_code_byte_len = (transforms::half(seg_count_x2))
.checked_mul(u16::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(end_code_byte_len);
cursor.advance::<u16>();
let start_code_byte_len = (transforms::half(seg_count_x2))
.checked_mul(u16::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(start_code_byte_len);
let id_delta_byte_len = (transforms::half(seg_count_x2))
.checked_mul(i16::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(id_delta_byte_len);
let id_range_offsets_byte_len = (transforms::half(seg_count_x2))
.checked_mul(u16::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(id_range_offsets_byte_len);
let glyph_id_array_byte_len =
cursor.remaining_bytes() / u16::RAW_BYTE_LEN * u16::RAW_BYTE_LEN;
cursor.advance_by(glyph_id_array_byte_len);
cursor.finish(Cmap4Marker {
end_code_byte_len,
start_code_byte_len,
id_delta_byte_len,
id_range_offsets_byte_len,
glyph_id_array_byte_len,
})
}
}
pub type Cmap4<'a> = TableRef<'a, Cmap4Marker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> Cmap4<'a> {
pub fn format(&self) -> u16 {
let range = self.shape.format_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn length(&self) -> u16 {
let range = self.shape.length_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn language(&self) -> u16 {
let range = self.shape.language_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn seg_count_x2(&self) -> u16 {
let range = self.shape.seg_count_x2_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn search_range(&self) -> u16 {
let range = self.shape.search_range_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn entry_selector(&self) -> u16 {
let range = self.shape.entry_selector_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn range_shift(&self) -> u16 {
let range = self.shape.range_shift_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn end_code(&self) -> &'a [BigEndian<u16>] {
let range = self.shape.end_code_byte_range();
self.data.read_array(range).unwrap()
}
pub fn start_code(&self) -> &'a [BigEndian<u16>] {
let range = self.shape.start_code_byte_range();
self.data.read_array(range).unwrap()
}
pub fn id_delta(&self) -> &'a [BigEndian<i16>] {
let range = self.shape.id_delta_byte_range();
self.data.read_array(range).unwrap()
}
pub fn id_range_offsets(&self) -> &'a [BigEndian<u16>] {
let range = self.shape.id_range_offsets_byte_range();
self.data.read_array(range).unwrap()
}
pub fn glyph_id_array(&self) -> &'a [BigEndian<u16>] {
let range = self.shape.glyph_id_array_byte_range();
self.data.read_array(range).unwrap()
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for Cmap4<'a> {
fn type_name(&self) -> &str {
"Cmap4"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("format", self.format())),
1usize => Some(Field::new("length", self.length())),
2usize => Some(Field::new("language", self.language())),
3usize => Some(Field::new("seg_count_x2", self.seg_count_x2())),
4usize => Some(Field::new("search_range", self.search_range())),
5usize => Some(Field::new("entry_selector", self.entry_selector())),
6usize => Some(Field::new("range_shift", self.range_shift())),
7usize => Some(Field::new("end_code", self.end_code())),
8usize => Some(Field::new("start_code", self.start_code())),
9usize => Some(Field::new("id_delta", self.id_delta())),
10usize => Some(Field::new("id_range_offsets", self.id_range_offsets())),
11usize => Some(Field::new("glyph_id_array", self.glyph_id_array())),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for Cmap4<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}
impl Format<u16> for Cmap6Marker {
const FORMAT: u16 = 6;
}
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct Cmap6Marker {
glyph_id_array_byte_len: usize,
}
impl Cmap6Marker {
pub fn format_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + u16::RAW_BYTE_LEN
}
pub fn length_byte_range(&self) -> Range<usize> {
let start = self.format_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn language_byte_range(&self) -> Range<usize> {
let start = self.length_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn first_code_byte_range(&self) -> Range<usize> {
let start = self.language_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn entry_count_byte_range(&self) -> Range<usize> {
let start = self.first_code_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn glyph_id_array_byte_range(&self) -> Range<usize> {
let start = self.entry_count_byte_range().end;
start..start + self.glyph_id_array_byte_len
}
}
impl<'a> FontRead<'a> for Cmap6<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
cursor.advance::<u16>();
cursor.advance::<u16>();
cursor.advance::<u16>();
cursor.advance::<u16>();
let entry_count: u16 = cursor.read()?;
let glyph_id_array_byte_len = (entry_count as usize)
.checked_mul(u16::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(glyph_id_array_byte_len);
cursor.finish(Cmap6Marker {
glyph_id_array_byte_len,
})
}
}
pub type Cmap6<'a> = TableRef<'a, Cmap6Marker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> Cmap6<'a> {
pub fn format(&self) -> u16 {
let range = self.shape.format_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn length(&self) -> u16 {
let range = self.shape.length_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn language(&self) -> u16 {
let range = self.shape.language_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn first_code(&self) -> u16 {
let range = self.shape.first_code_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn entry_count(&self) -> u16 {
let range = self.shape.entry_count_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn glyph_id_array(&self) -> &'a [BigEndian<u16>] {
let range = self.shape.glyph_id_array_byte_range();
self.data.read_array(range).unwrap()
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for Cmap6<'a> {
fn type_name(&self) -> &str {
"Cmap6"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("format", self.format())),
1usize => Some(Field::new("length", self.length())),
2usize => Some(Field::new("language", self.language())),
3usize => Some(Field::new("first_code", self.first_code())),
4usize => Some(Field::new("entry_count", self.entry_count())),
5usize => Some(Field::new("glyph_id_array", self.glyph_id_array())),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for Cmap6<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}
impl Format<u16> for Cmap8Marker {
const FORMAT: u16 = 8;
}
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct Cmap8Marker {
is32_byte_len: usize,
groups_byte_len: usize,
}
impl Cmap8Marker {
pub fn format_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + u16::RAW_BYTE_LEN
}
pub fn reserved_byte_range(&self) -> Range<usize> {
let start = self.format_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn length_byte_range(&self) -> Range<usize> {
let start = self.reserved_byte_range().end;
start..start + u32::RAW_BYTE_LEN
}
pub fn language_byte_range(&self) -> Range<usize> {
let start = self.length_byte_range().end;
start..start + u32::RAW_BYTE_LEN
}
pub fn is32_byte_range(&self) -> Range<usize> {
let start = self.language_byte_range().end;
start..start + self.is32_byte_len
}
pub fn num_groups_byte_range(&self) -> Range<usize> {
let start = self.is32_byte_range().end;
start..start + u32::RAW_BYTE_LEN
}
pub fn groups_byte_range(&self) -> Range<usize> {
let start = self.num_groups_byte_range().end;
start..start + self.groups_byte_len
}
}
impl<'a> FontRead<'a> for Cmap8<'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 is32_byte_len = (8192_usize)
.checked_mul(u8::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(is32_byte_len);
let num_groups: u32 = cursor.read()?;
let groups_byte_len = (num_groups as usize)
.checked_mul(SequentialMapGroup::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(groups_byte_len);
cursor.finish(Cmap8Marker {
is32_byte_len,
groups_byte_len,
})
}
}
pub type Cmap8<'a> = TableRef<'a, Cmap8Marker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> Cmap8<'a> {
pub fn format(&self) -> u16 {
let range = self.shape.format_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn length(&self) -> u32 {
let range = self.shape.length_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn language(&self) -> u32 {
let range = self.shape.language_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn is32(&self) -> &'a [u8] {
let range = self.shape.is32_byte_range();
self.data.read_array(range).unwrap()
}
pub fn num_groups(&self) -> u32 {
let range = self.shape.num_groups_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn groups(&self) -> &'a [SequentialMapGroup] {
let range = self.shape.groups_byte_range();
self.data.read_array(range).unwrap()
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for Cmap8<'a> {
fn type_name(&self) -> &str {
"Cmap8"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("format", self.format())),
1usize => Some(Field::new("length", self.length())),
2usize => Some(Field::new("language", self.language())),
3usize => Some(Field::new("is32", self.is32())),
4usize => Some(Field::new("num_groups", self.num_groups())),
5usize => Some(Field::new(
"groups",
traversal::FieldType::array_of_records(
stringify!(SequentialMapGroup),
self.groups(),
self.offset_data(),
),
)),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for Cmap8<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
#[repr(C)]
#[repr(packed)]
pub struct SequentialMapGroup {
pub start_char_code: BigEndian<u32>,
pub end_char_code: BigEndian<u32>,
pub start_glyph_id: BigEndian<u32>,
}
impl SequentialMapGroup {
pub fn start_char_code(&self) -> u32 {
self.start_char_code.get()
}
pub fn end_char_code(&self) -> u32 {
self.end_char_code.get()
}
pub fn start_glyph_id(&self) -> u32 {
self.start_glyph_id.get()
}
}
impl FixedSize for SequentialMapGroup {
const RAW_BYTE_LEN: usize = u32::RAW_BYTE_LEN + u32::RAW_BYTE_LEN + u32::RAW_BYTE_LEN;
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeRecord<'a> for SequentialMapGroup {
fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
RecordResolver {
name: "SequentialMapGroup",
get_field: Box::new(move |idx, _data| match idx {
0usize => Some(Field::new("start_char_code", self.start_char_code())),
1usize => Some(Field::new("end_char_code", self.end_char_code())),
2usize => Some(Field::new("start_glyph_id", self.start_glyph_id())),
_ => None,
}),
data,
}
}
}
impl Format<u16> for Cmap10Marker {
const FORMAT: u16 = 10;
}
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct Cmap10Marker {
glyph_id_array_byte_len: usize,
}
impl Cmap10Marker {
pub fn format_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + u16::RAW_BYTE_LEN
}
pub fn reserved_byte_range(&self) -> Range<usize> {
let start = self.format_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn length_byte_range(&self) -> Range<usize> {
let start = self.reserved_byte_range().end;
start..start + u32::RAW_BYTE_LEN
}
pub fn language_byte_range(&self) -> Range<usize> {
let start = self.length_byte_range().end;
start..start + u32::RAW_BYTE_LEN
}
pub fn start_char_code_byte_range(&self) -> Range<usize> {
let start = self.language_byte_range().end;
start..start + u32::RAW_BYTE_LEN
}
pub fn num_chars_byte_range(&self) -> Range<usize> {
let start = self.start_char_code_byte_range().end;
start..start + u32::RAW_BYTE_LEN
}
pub fn glyph_id_array_byte_range(&self) -> Range<usize> {
let start = self.num_chars_byte_range().end;
start..start + self.glyph_id_array_byte_len
}
}
impl<'a> FontRead<'a> for Cmap10<'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>();
cursor.advance::<u32>();
cursor.advance::<u32>();
let glyph_id_array_byte_len =
cursor.remaining_bytes() / u16::RAW_BYTE_LEN * u16::RAW_BYTE_LEN;
cursor.advance_by(glyph_id_array_byte_len);
cursor.finish(Cmap10Marker {
glyph_id_array_byte_len,
})
}
}
pub type Cmap10<'a> = TableRef<'a, Cmap10Marker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> Cmap10<'a> {
pub fn format(&self) -> u16 {
let range = self.shape.format_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn length(&self) -> u32 {
let range = self.shape.length_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn language(&self) -> u32 {
let range = self.shape.language_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn start_char_code(&self) -> u32 {
let range = self.shape.start_char_code_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn num_chars(&self) -> u32 {
let range = self.shape.num_chars_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn glyph_id_array(&self) -> &'a [BigEndian<u16>] {
let range = self.shape.glyph_id_array_byte_range();
self.data.read_array(range).unwrap()
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for Cmap10<'a> {
fn type_name(&self) -> &str {
"Cmap10"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("format", self.format())),
1usize => Some(Field::new("length", self.length())),
2usize => Some(Field::new("language", self.language())),
3usize => Some(Field::new("start_char_code", self.start_char_code())),
4usize => Some(Field::new("num_chars", self.num_chars())),
5usize => Some(Field::new("glyph_id_array", self.glyph_id_array())),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for Cmap10<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}
impl Format<u16> for Cmap12Marker {
const FORMAT: u16 = 12;
}
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct Cmap12Marker {
groups_byte_len: usize,
}
impl Cmap12Marker {
pub fn format_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + u16::RAW_BYTE_LEN
}
pub fn reserved_byte_range(&self) -> Range<usize> {
let start = self.format_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn length_byte_range(&self) -> Range<usize> {
let start = self.reserved_byte_range().end;
start..start + u32::RAW_BYTE_LEN
}
pub fn language_byte_range(&self) -> Range<usize> {
let start = self.length_byte_range().end;
start..start + u32::RAW_BYTE_LEN
}
pub fn num_groups_byte_range(&self) -> Range<usize> {
let start = self.language_byte_range().end;
start..start + u32::RAW_BYTE_LEN
}
pub fn groups_byte_range(&self) -> Range<usize> {
let start = self.num_groups_byte_range().end;
start..start + self.groups_byte_len
}
}
impl<'a> FontRead<'a> for Cmap12<'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 num_groups: u32 = cursor.read()?;
let groups_byte_len = (num_groups as usize)
.checked_mul(SequentialMapGroup::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(groups_byte_len);
cursor.finish(Cmap12Marker { groups_byte_len })
}
}
pub type Cmap12<'a> = TableRef<'a, Cmap12Marker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> Cmap12<'a> {
pub fn format(&self) -> u16 {
let range = self.shape.format_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn length(&self) -> u32 {
let range = self.shape.length_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn language(&self) -> u32 {
let range = self.shape.language_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn num_groups(&self) -> u32 {
let range = self.shape.num_groups_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn groups(&self) -> &'a [SequentialMapGroup] {
let range = self.shape.groups_byte_range();
self.data.read_array(range).unwrap()
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for Cmap12<'a> {
fn type_name(&self) -> &str {
"Cmap12"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("format", self.format())),
1usize => Some(Field::new("length", self.length())),
2usize => Some(Field::new("language", self.language())),
3usize => Some(Field::new("num_groups", self.num_groups())),
4usize => Some(Field::new(
"groups",
traversal::FieldType::array_of_records(
stringify!(SequentialMapGroup),
self.groups(),
self.offset_data(),
),
)),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for Cmap12<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}
impl Format<u16> for Cmap13Marker {
const FORMAT: u16 = 13;
}
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct Cmap13Marker {
groups_byte_len: usize,
}
impl Cmap13Marker {
pub fn format_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + u16::RAW_BYTE_LEN
}
pub fn reserved_byte_range(&self) -> Range<usize> {
let start = self.format_byte_range().end;
start..start + u16::RAW_BYTE_LEN
}
pub fn length_byte_range(&self) -> Range<usize> {
let start = self.reserved_byte_range().end;
start..start + u32::RAW_BYTE_LEN
}
pub fn language_byte_range(&self) -> Range<usize> {
let start = self.length_byte_range().end;
start..start + u32::RAW_BYTE_LEN
}
pub fn num_groups_byte_range(&self) -> Range<usize> {
let start = self.language_byte_range().end;
start..start + u32::RAW_BYTE_LEN
}
pub fn groups_byte_range(&self) -> Range<usize> {
let start = self.num_groups_byte_range().end;
start..start + self.groups_byte_len
}
}
impl<'a> FontRead<'a> for Cmap13<'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 num_groups: u32 = cursor.read()?;
let groups_byte_len = (num_groups as usize)
.checked_mul(ConstantMapGroup::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(groups_byte_len);
cursor.finish(Cmap13Marker { groups_byte_len })
}
}
pub type Cmap13<'a> = TableRef<'a, Cmap13Marker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> Cmap13<'a> {
pub fn format(&self) -> u16 {
let range = self.shape.format_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn length(&self) -> u32 {
let range = self.shape.length_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn language(&self) -> u32 {
let range = self.shape.language_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn num_groups(&self) -> u32 {
let range = self.shape.num_groups_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn groups(&self) -> &'a [ConstantMapGroup] {
let range = self.shape.groups_byte_range();
self.data.read_array(range).unwrap()
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for Cmap13<'a> {
fn type_name(&self) -> &str {
"Cmap13"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("format", self.format())),
1usize => Some(Field::new("length", self.length())),
2usize => Some(Field::new("language", self.language())),
3usize => Some(Field::new("num_groups", self.num_groups())),
4usize => Some(Field::new(
"groups",
traversal::FieldType::array_of_records(
stringify!(ConstantMapGroup),
self.groups(),
self.offset_data(),
),
)),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for Cmap13<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
#[repr(C)]
#[repr(packed)]
pub struct ConstantMapGroup {
pub start_char_code: BigEndian<u32>,
pub end_char_code: BigEndian<u32>,
pub glyph_id: BigEndian<u32>,
}
impl ConstantMapGroup {
pub fn start_char_code(&self) -> u32 {
self.start_char_code.get()
}
pub fn end_char_code(&self) -> u32 {
self.end_char_code.get()
}
pub fn glyph_id(&self) -> u32 {
self.glyph_id.get()
}
}
impl FixedSize for ConstantMapGroup {
const RAW_BYTE_LEN: usize = u32::RAW_BYTE_LEN + u32::RAW_BYTE_LEN + u32::RAW_BYTE_LEN;
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeRecord<'a> for ConstantMapGroup {
fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
RecordResolver {
name: "ConstantMapGroup",
get_field: Box::new(move |idx, _data| match idx {
0usize => Some(Field::new("start_char_code", self.start_char_code())),
1usize => Some(Field::new("end_char_code", self.end_char_code())),
2usize => Some(Field::new("glyph_id", self.glyph_id())),
_ => None,
}),
data,
}
}
}
impl Format<u16> for Cmap14Marker {
const FORMAT: u16 = 14;
}
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct Cmap14Marker {
var_selector_byte_len: usize,
}
impl Cmap14Marker {
pub fn format_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + u16::RAW_BYTE_LEN
}
pub fn length_byte_range(&self) -> Range<usize> {
let start = self.format_byte_range().end;
start..start + u32::RAW_BYTE_LEN
}
pub fn num_var_selector_records_byte_range(&self) -> Range<usize> {
let start = self.length_byte_range().end;
start..start + u32::RAW_BYTE_LEN
}
pub fn var_selector_byte_range(&self) -> Range<usize> {
let start = self.num_var_selector_records_byte_range().end;
start..start + self.var_selector_byte_len
}
}
impl<'a> FontRead<'a> for Cmap14<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
cursor.advance::<u16>();
cursor.advance::<u32>();
let num_var_selector_records: u32 = cursor.read()?;
let var_selector_byte_len = (num_var_selector_records as usize)
.checked_mul(VariationSelector::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(var_selector_byte_len);
cursor.finish(Cmap14Marker {
var_selector_byte_len,
})
}
}
pub type Cmap14<'a> = TableRef<'a, Cmap14Marker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> Cmap14<'a> {
pub fn format(&self) -> u16 {
let range = self.shape.format_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn length(&self) -> u32 {
let range = self.shape.length_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn num_var_selector_records(&self) -> u32 {
let range = self.shape.num_var_selector_records_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn var_selector(&self) -> &'a [VariationSelector] {
let range = self.shape.var_selector_byte_range();
self.data.read_array(range).unwrap()
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for Cmap14<'a> {
fn type_name(&self) -> &str {
"Cmap14"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("format", self.format())),
1usize => Some(Field::new("length", self.length())),
2usize => Some(Field::new(
"num_var_selector_records",
self.num_var_selector_records(),
)),
3usize => Some(Field::new(
"var_selector",
traversal::FieldType::array_of_records(
stringify!(VariationSelector),
self.var_selector(),
self.offset_data(),
),
)),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for Cmap14<'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 VariationSelector {
pub var_selector: BigEndian<Uint24>,
pub default_uvs_offset: BigEndian<Nullable<Offset32>>,
pub non_default_uvs_offset: BigEndian<Nullable<Offset32>>,
}
impl VariationSelector {
pub fn var_selector(&self) -> Uint24 {
self.var_selector.get()
}
pub fn default_uvs_offset(&self) -> Nullable<Offset32> {
self.default_uvs_offset.get()
}
pub fn default_uvs<'a>(&self, data: FontData<'a>) -> Option<Result<DefaultUvs<'a>, ReadError>> {
self.default_uvs_offset().resolve(data)
}
pub fn non_default_uvs_offset(&self) -> Nullable<Offset32> {
self.non_default_uvs_offset.get()
}
pub fn non_default_uvs<'a>(
&self,
data: FontData<'a>,
) -> Option<Result<NonDefaultUvs<'a>, ReadError>> {
self.non_default_uvs_offset().resolve(data)
}
}
impl FixedSize for VariationSelector {
const RAW_BYTE_LEN: usize =
Uint24::RAW_BYTE_LEN + Offset32::RAW_BYTE_LEN + Offset32::RAW_BYTE_LEN;
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeRecord<'a> for VariationSelector {
fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
RecordResolver {
name: "VariationSelector",
get_field: Box::new(move |idx, _data| match idx {
0usize => Some(Field::new("var_selector", self.var_selector())),
1usize => Some(Field::new(
"default_uvs_offset",
FieldType::offset(self.default_uvs_offset(), self.default_uvs(_data)),
)),
2usize => Some(Field::new(
"non_default_uvs_offset",
FieldType::offset(self.non_default_uvs_offset(), self.non_default_uvs(_data)),
)),
_ => None,
}),
data,
}
}
}
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct DefaultUvsMarker {
ranges_byte_len: usize,
}
impl DefaultUvsMarker {
pub fn num_unicode_value_ranges_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + u32::RAW_BYTE_LEN
}
pub fn ranges_byte_range(&self) -> Range<usize> {
let start = self.num_unicode_value_ranges_byte_range().end;
start..start + self.ranges_byte_len
}
}
impl<'a> FontRead<'a> for DefaultUvs<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
let num_unicode_value_ranges: u32 = cursor.read()?;
let ranges_byte_len = (num_unicode_value_ranges as usize)
.checked_mul(UnicodeRange::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(ranges_byte_len);
cursor.finish(DefaultUvsMarker { ranges_byte_len })
}
}
pub type DefaultUvs<'a> = TableRef<'a, DefaultUvsMarker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> DefaultUvs<'a> {
pub fn num_unicode_value_ranges(&self) -> u32 {
let range = self.shape.num_unicode_value_ranges_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn ranges(&self) -> &'a [UnicodeRange] {
let range = self.shape.ranges_byte_range();
self.data.read_array(range).unwrap()
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for DefaultUvs<'a> {
fn type_name(&self) -> &str {
"DefaultUvs"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new(
"num_unicode_value_ranges",
self.num_unicode_value_ranges(),
)),
1usize => Some(Field::new(
"ranges",
traversal::FieldType::array_of_records(
stringify!(UnicodeRange),
self.ranges(),
self.offset_data(),
),
)),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for DefaultUvs<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}
#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct NonDefaultUvsMarker {
uvs_mapping_byte_len: usize,
}
impl NonDefaultUvsMarker {
pub fn num_uvs_mappings_byte_range(&self) -> Range<usize> {
let start = 0;
start..start + u32::RAW_BYTE_LEN
}
pub fn uvs_mapping_byte_range(&self) -> Range<usize> {
let start = self.num_uvs_mappings_byte_range().end;
start..start + self.uvs_mapping_byte_len
}
}
impl<'a> FontRead<'a> for NonDefaultUvs<'a> {
fn read(data: FontData<'a>) -> Result<Self, ReadError> {
let mut cursor = data.cursor();
let num_uvs_mappings: u32 = cursor.read()?;
let uvs_mapping_byte_len = (num_uvs_mappings as usize)
.checked_mul(UvsMapping::RAW_BYTE_LEN)
.ok_or(ReadError::OutOfBounds)?;
cursor.advance_by(uvs_mapping_byte_len);
cursor.finish(NonDefaultUvsMarker {
uvs_mapping_byte_len,
})
}
}
pub type NonDefaultUvs<'a> = TableRef<'a, NonDefaultUvsMarker>;
#[allow(clippy::needless_lifetimes)]
impl<'a> NonDefaultUvs<'a> {
pub fn num_uvs_mappings(&self) -> u32 {
let range = self.shape.num_uvs_mappings_byte_range();
self.data.read_at(range.start).unwrap()
}
pub fn uvs_mapping(&self) -> &'a [UvsMapping] {
let range = self.shape.uvs_mapping_byte_range();
self.data.read_array(range).unwrap()
}
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeTable<'a> for NonDefaultUvs<'a> {
fn type_name(&self) -> &str {
"NonDefaultUvs"
}
fn get_field(&self, idx: usize) -> Option<Field<'a>> {
match idx {
0usize => Some(Field::new("num_uvs_mappings", self.num_uvs_mappings())),
1usize => Some(Field::new(
"uvs_mapping",
traversal::FieldType::array_of_records(
stringify!(UvsMapping),
self.uvs_mapping(),
self.offset_data(),
),
)),
_ => None,
}
}
}
#[cfg(feature = "experimental_traverse")]
#[allow(clippy::needless_lifetimes)]
impl<'a> std::fmt::Debug for NonDefaultUvs<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(self as &dyn SomeTable<'a>).fmt(f)
}
}
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
#[repr(C)]
#[repr(packed)]
pub struct UvsMapping {
pub unicode_value: BigEndian<Uint24>,
pub glyph_id: BigEndian<u16>,
}
impl UvsMapping {
pub fn unicode_value(&self) -> Uint24 {
self.unicode_value.get()
}
pub fn glyph_id(&self) -> u16 {
self.glyph_id.get()
}
}
impl FixedSize for UvsMapping {
const RAW_BYTE_LEN: usize = Uint24::RAW_BYTE_LEN + u16::RAW_BYTE_LEN;
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeRecord<'a> for UvsMapping {
fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
RecordResolver {
name: "UvsMapping",
get_field: Box::new(move |idx, _data| match idx {
0usize => Some(Field::new("unicode_value", self.unicode_value())),
1usize => Some(Field::new("glyph_id", self.glyph_id())),
_ => None,
}),
data,
}
}
}
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
#[repr(C)]
#[repr(packed)]
pub struct UnicodeRange {
pub start_unicode_value: BigEndian<Uint24>,
pub additional_count: u8,
}
impl UnicodeRange {
pub fn start_unicode_value(&self) -> Uint24 {
self.start_unicode_value.get()
}
pub fn additional_count(&self) -> u8 {
self.additional_count
}
}
impl FixedSize for UnicodeRange {
const RAW_BYTE_LEN: usize = Uint24::RAW_BYTE_LEN + u8::RAW_BYTE_LEN;
}
#[cfg(feature = "experimental_traverse")]
impl<'a> SomeRecord<'a> for UnicodeRange {
fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
RecordResolver {
name: "UnicodeRange",
get_field: Box::new(move |idx, _data| match idx {
0usize => Some(Field::new(
"start_unicode_value",
self.start_unicode_value(),
)),
1usize => Some(Field::new("additional_count", self.additional_count())),
_ => None,
}),
data,
}
}
}