diff --git a/font-codegen/src/fields.rs b/font-codegen/src/fields.rs index ae9b6bbf6..c653ad053 100644 --- a/font-codegen/src/fields.rs +++ b/font-codegen/src/fields.rs @@ -1053,9 +1053,15 @@ impl FieldType { pub(crate) fn cooked_type_tokens(&self) -> &syn::Ident { match &self { FieldType::Offset { typ, .. } | FieldType::Scalar { typ } => typ, - FieldType::Other { typ } => typ - .get_ident() - .expect("non-trivial custom types never cooked"), + FieldType::Other { typ } => { + match typ.get_ident() { + Some(ident) => ident, + None => { + eprintln!("What do I do with {:#?}", self); + panic!("Oh no"); + } + } + }, FieldType::Array { .. } | FieldType::ComputedArray { .. } | FieldType::VarLenArray(_) => { diff --git a/font-codegen/src/parsing.rs b/font-codegen/src/parsing.rs index 7fe15410c..f49bcc822 100644 --- a/font-codegen/src/parsing.rs +++ b/font-codegen/src/parsing.rs @@ -2,14 +2,14 @@ use std::collections::HashMap; -use proc_macro2::{Span, TokenStream}; +use proc_macro2::{Span, TokenStream, Ident, Punct}; use quote::{quote, ToTokens}; use syn::{ braced, bracketed, parenthesized, parse::{Parse, ParseStream}, punctuated::Punctuated, spanned::Spanned, - token, Attribute, Token, + token, Attribute, Token }; pub(crate) struct Items { @@ -283,6 +283,10 @@ pub(crate) enum FieldType { }, ComputedArray(CustomArray), VarLenArray(CustomArray), + SizedArray { + typ: syn::Ident, + len: syn::Ident, + } } /// A representation shared between computed & varlen arrays @@ -587,6 +591,24 @@ impl Parse for Field { impl Parse for FieldType { fn parse(input: ParseStream) -> syn::Result { + if input.peek(token::Bracket) { + // An array. It should be Ident, Punct(;), Ident + let content; + bracketed!(content in input); + + let array_type: Ident = content.parse()?; + let punct = content.parse::()?; + if punct.as_char() != ';' { + return Err(syn::Error::new(punct.span(), "Invalid separator")); + } + let array_len: Ident = content.parse()?; + + // Should be no further content + if !content.is_empty() { + return Err(syn::Error::new(content.span(), "Unexpected content")); + } + return Ok(FieldType::SizedArray { typ: array_type, len: array_len }); + } if input.lookahead1().peek(token::Bracket) { let content; bracketed!(content in input); diff --git a/read-fonts/generated/generated_cmap.rs b/read-fonts/generated/generated_cmap.rs index bdd927b1d..e69de29bb 100644 --- a/read-fonts/generated/generated_cmap.rs +++ b/read-fonts/generated/generated_cmap.rs @@ -1,1796 +0,0 @@ -// 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::*; - -/// [cmap](https://docs.microsoft.com/en-us/typography/opentype/spec/cmap#overview) -#[derive(Debug, Clone, Copy)] -#[doc(hidden)] -pub struct CmapMarker { - encoding_records_byte_len: usize, -} - -impl CmapMarker { - fn version_byte_range(&self) -> Range { - let start = 0; - start..start + u16::RAW_BYTE_LEN - } - fn num_tables_byte_range(&self) -> Range { - let start = self.version_byte_range().end; - start..start + u16::RAW_BYTE_LEN - } - fn encoding_records_byte_range(&self) -> Range { - let start = self.num_tables_byte_range().end; - start..start + self.encoding_records_byte_len - } -} - -impl<'a> FontRead<'a> for Cmap<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - let num_tables: u16 = cursor.read()?; - let encoding_records_byte_len = num_tables as usize * EncodingRecord::RAW_BYTE_LEN; - cursor.advance_by(encoding_records_byte_len); - cursor.finish(CmapMarker { - encoding_records_byte_len, - }) - } -} - -/// [cmap](https://docs.microsoft.com/en-us/typography/opentype/spec/cmap#overview) -pub type Cmap<'a> = TableRef<'a, CmapMarker>; - -impl<'a> Cmap<'a> { - /// Table version number (0). - pub fn version(&self) -> u16 { - let range = self.shape.version_byte_range(); - self.data.read_at(range.start).unwrap() - } - - /// Number of encoding tables that follow. - 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 = "traversal")] -impl<'a> SomeTable<'a> for Cmap<'a> { - fn type_name(&self) -> &str { - "Cmap" - } - fn get_field(&self, idx: usize) -> Option> { - 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 = "traversal")] -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) - } -} - -/// [Encoding Record](https://docs.microsoft.com/en-us/typography/opentype/spec/cmap#encoding-records-and-encodings) -#[derive(Clone, Debug)] -#[repr(C)] -#[repr(packed)] -pub struct EncodingRecord { - /// Platform ID. - pub platform_id: BigEndian, - /// Platform-specific encoding ID. - pub encoding_id: BigEndian, - /// Byte offset from beginning of table to the subtable for this - /// encoding. - pub subtable_offset: BigEndian, -} - -impl EncodingRecord { - /// Platform ID. - pub fn platform_id(&self) -> PlatformId { - self.platform_id.get() - } - - /// Platform-specific encoding ID. - pub fn encoding_id(&self) -> u16 { - self.encoding_id.get() - } - - /// Byte offset from beginning of table to the subtable for this - /// encoding. - pub fn subtable_offset(&self) -> Offset32 { - self.subtable_offset.get() - } - - /// Attempt to resolve [`subtable_offset`][Self::subtable_offset]. - pub fn subtable<'a>(&self, data: FontData<'a>) -> Result, 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 = "traversal")] -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, PartialEq, Eq)] -#[repr(u16)] -pub enum PlatformId { - Unicode = 0, - Macintosh = 1, - ISO = 2, - Windows = 3, - Custom = 4, - Unknown, -} - -impl PlatformId { - #[doc = r" Create from a raw scalar."] - #[doc = r""] - #[doc = r" This will never fail; unknown values will be mapped to the `Unknown` variant"] - 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 = ::Raw; - fn to_raw(self) -> Self::Raw { - (self as u16).to_raw() - } - fn from_raw(raw: Self::Raw) -> Self { - let t = ::from_raw(raw); - Self::new(t) - } -} - -#[cfg(feature = "traversal")] -impl<'a> From for FieldType<'a> { - fn from(src: PlatformId) -> FieldType<'a> { - (src as u16).into() - } -} - -/// The different cmap subtable formats. -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> FontRead<'a> for CmapSubtable<'a> { - fn read(data: FontData<'a>) -> Result { - let format: u16 = data.read_at(0)?; - 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 = "traversal")] -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 = "traversal")] -impl<'a> std::fmt::Debug for CmapSubtable<'a> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - self.dyn_inner().fmt(f) - } -} - -#[cfg(feature = "traversal")] -impl<'a> SomeTable<'a> for CmapSubtable<'a> { - fn type_name(&self) -> &str { - self.dyn_inner().type_name() - } - fn get_field(&self, idx: usize) -> Option> { - self.dyn_inner().get_field(idx) - } -} - -impl Format for Cmap0Marker { - const FORMAT: u16 = 0; -} - -/// [cmap Format 0](https://docs.microsoft.com/en-us/typography/opentype/spec/cmap#format-0-byte-encoding-table): Byte encoding table -#[derive(Debug, Clone, Copy)] -#[doc(hidden)] -pub struct Cmap0Marker { - glyph_id_array_byte_len: usize, -} - -impl Cmap0Marker { - fn format_byte_range(&self) -> Range { - let start = 0; - start..start + u16::RAW_BYTE_LEN - } - fn length_byte_range(&self) -> Range { - let start = self.format_byte_range().end; - start..start + u16::RAW_BYTE_LEN - } - fn language_byte_range(&self) -> Range { - let start = self.length_byte_range().end; - start..start + u16::RAW_BYTE_LEN - } - fn glyph_id_array_byte_range(&self) -> Range { - 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 { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - let glyph_id_array_byte_len = 256 * u8::RAW_BYTE_LEN; - cursor.advance_by(glyph_id_array_byte_len); - cursor.finish(Cmap0Marker { - glyph_id_array_byte_len, - }) - } -} - -/// [cmap Format 0](https://docs.microsoft.com/en-us/typography/opentype/spec/cmap#format-0-byte-encoding-table): Byte encoding table -pub type Cmap0<'a> = TableRef<'a, Cmap0Marker>; - -impl<'a> Cmap0<'a> { - /// Format number is set to 0. - pub fn format(&self) -> u16 { - let range = self.shape.format_byte_range(); - self.data.read_at(range.start).unwrap() - } - - /// This is the length in bytes of the subtable. - pub fn length(&self) -> u16 { - let range = self.shape.length_byte_range(); - self.data.read_at(range.start).unwrap() - } - - /// For requirements on use of the language field, see “Use of - /// the language field in 'cmap' subtables” in this document. - pub fn language(&self) -> u16 { - let range = self.shape.language_byte_range(); - self.data.read_at(range.start).unwrap() - } - - /// An array that maps character codes to glyph index values. - pub fn glyph_id_array(&self) -> &'a [BigEndian] { - let range = self.shape.glyph_id_array_byte_range(); - self.data.read_array(range).unwrap() - } -} - -#[cfg(feature = "traversal")] -impl<'a> SomeTable<'a> for Cmap0<'a> { - fn type_name(&self) -> &str { - "Cmap0" - } - fn get_field(&self, idx: usize) -> Option> { - 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 = "traversal")] -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 for Cmap2Marker { - const FORMAT: u16 = 2; -} - -/// [cmap Format 2](https://docs.microsoft.com/en-us/typography/opentype/spec/cmap#format-2-high-byte-mapping-through-table): High-byte mapping through table -#[derive(Debug, Clone, Copy)] -#[doc(hidden)] -pub struct Cmap2Marker { - sub_header_keys_byte_len: usize, -} - -impl Cmap2Marker { - fn format_byte_range(&self) -> Range { - let start = 0; - start..start + u16::RAW_BYTE_LEN - } - fn length_byte_range(&self) -> Range { - let start = self.format_byte_range().end; - start..start + u16::RAW_BYTE_LEN - } - fn language_byte_range(&self) -> Range { - let start = self.length_byte_range().end; - start..start + u16::RAW_BYTE_LEN - } - fn sub_header_keys_byte_range(&self) -> Range { - 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 { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - let sub_header_keys_byte_len = 256 * u16::RAW_BYTE_LEN; - cursor.advance_by(sub_header_keys_byte_len); - cursor.finish(Cmap2Marker { - sub_header_keys_byte_len, - }) - } -} - -/// [cmap Format 2](https://docs.microsoft.com/en-us/typography/opentype/spec/cmap#format-2-high-byte-mapping-through-table): High-byte mapping through table -pub type Cmap2<'a> = TableRef<'a, Cmap2Marker>; - -impl<'a> Cmap2<'a> { - /// Format number is set to 2. - pub fn format(&self) -> u16 { - let range = self.shape.format_byte_range(); - self.data.read_at(range.start).unwrap() - } - - /// This is the length in bytes of the subtable. - pub fn length(&self) -> u16 { - let range = self.shape.length_byte_range(); - self.data.read_at(range.start).unwrap() - } - - /// For requirements on use of the language field, see “Use of - /// the language field in 'cmap' subtables” in this document. - pub fn language(&self) -> u16 { - let range = self.shape.language_byte_range(); - self.data.read_at(range.start).unwrap() - } - - /// Array that maps high bytes to subHeaders: value is subHeader - /// index × 8. - pub fn sub_header_keys(&self) -> &'a [BigEndian] { - let range = self.shape.sub_header_keys_byte_range(); - self.data.read_array(range).unwrap() - } -} - -#[cfg(feature = "traversal")] -impl<'a> SomeTable<'a> for Cmap2<'a> { - fn type_name(&self) -> &str { - "Cmap2" - } - fn get_field(&self, idx: usize) -> Option> { - 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 = "traversal")] -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) - } -} - -/// Part of [Cmap2] -#[derive(Clone, Debug)] -#[repr(C)] -#[repr(packed)] -pub struct SubHeader { - /// First valid low byte for this SubHeader. - pub first_code: BigEndian, - /// Number of valid low bytes for this SubHeader. - pub entry_count: BigEndian, - /// See text below. - pub id_delta: BigEndian, - /// See text below. - pub id_range_offset: BigEndian, -} - -impl SubHeader { - /// First valid low byte for this SubHeader. - pub fn first_code(&self) -> u16 { - self.first_code.get() - } - - /// Number of valid low bytes for this SubHeader. - pub fn entry_count(&self) -> u16 { - self.entry_count.get() - } - - /// See text below. - pub fn id_delta(&self) -> i16 { - self.id_delta.get() - } - - /// See text below. - 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 = "traversal")] -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 for Cmap4Marker { - const FORMAT: u16 = 4; -} - -/// [cmap Format 4](https://docs.microsoft.com/en-us/typography/opentype/spec/cmap#format-4-segment-mapping-to-delta-values): Segment mapping to delta values -#[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 { - fn format_byte_range(&self) -> Range { - let start = 0; - start..start + u16::RAW_BYTE_LEN - } - fn length_byte_range(&self) -> Range { - let start = self.format_byte_range().end; - start..start + u16::RAW_BYTE_LEN - } - fn language_byte_range(&self) -> Range { - let start = self.length_byte_range().end; - start..start + u16::RAW_BYTE_LEN - } - fn seg_count_x2_byte_range(&self) -> Range { - let start = self.language_byte_range().end; - start..start + u16::RAW_BYTE_LEN - } - fn search_range_byte_range(&self) -> Range { - let start = self.seg_count_x2_byte_range().end; - start..start + u16::RAW_BYTE_LEN - } - fn entry_selector_byte_range(&self) -> Range { - let start = self.search_range_byte_range().end; - start..start + u16::RAW_BYTE_LEN - } - fn range_shift_byte_range(&self) -> Range { - let start = self.entry_selector_byte_range().end; - start..start + u16::RAW_BYTE_LEN - } - fn end_code_byte_range(&self) -> Range { - let start = self.range_shift_byte_range().end; - start..start + self.end_code_byte_len - } - fn reserved_pad_byte_range(&self) -> Range { - let start = self.end_code_byte_range().end; - start..start + u16::RAW_BYTE_LEN - } - fn start_code_byte_range(&self) -> Range { - let start = self.reserved_pad_byte_range().end; - start..start + self.start_code_byte_len - } - fn id_delta_byte_range(&self) -> Range { - let start = self.start_code_byte_range().end; - start..start + self.id_delta_byte_len - } - fn id_range_offsets_byte_range(&self) -> Range { - let start = self.id_delta_byte_range().end; - start..start + self.id_range_offsets_byte_len - } - fn glyph_id_array_byte_range(&self) -> Range { - 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 { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - let seg_count_x2: u16 = cursor.read()?; - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - let end_code_byte_len = seg_count_x2 as usize / 2 * u16::RAW_BYTE_LEN; - cursor.advance_by(end_code_byte_len); - cursor.advance::(); - let start_code_byte_len = seg_count_x2 as usize / 2 * u16::RAW_BYTE_LEN; - cursor.advance_by(start_code_byte_len); - let id_delta_byte_len = seg_count_x2 as usize / 2 * i16::RAW_BYTE_LEN; - cursor.advance_by(id_delta_byte_len); - let id_range_offsets_byte_len = seg_count_x2 as usize / 2 * u16::RAW_BYTE_LEN; - cursor.advance_by(id_range_offsets_byte_len); - let glyph_id_array_byte_len = cursor.remaining_bytes(); - 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, - }) - } -} - -/// [cmap Format 4](https://docs.microsoft.com/en-us/typography/opentype/spec/cmap#format-4-segment-mapping-to-delta-values): Segment mapping to delta values -pub type Cmap4<'a> = TableRef<'a, Cmap4Marker>; - -impl<'a> Cmap4<'a> { - /// Format number is set to 4. - pub fn format(&self) -> u16 { - let range = self.shape.format_byte_range(); - self.data.read_at(range.start).unwrap() - } - - /// This is the length in bytes of the subtable. - pub fn length(&self) -> u16 { - let range = self.shape.length_byte_range(); - self.data.read_at(range.start).unwrap() - } - - /// For requirements on use of the language field, see “Use of - /// the language field in 'cmap' subtables” in this document. - pub fn language(&self) -> u16 { - let range = self.shape.language_byte_range(); - self.data.read_at(range.start).unwrap() - } - - /// 2 × segCount. - pub fn seg_count_x2(&self) -> u16 { - let range = self.shape.seg_count_x2_byte_range(); - self.data.read_at(range.start).unwrap() - } - - /// Maximum power of 2 less than or equal to segCount, times 2 - /// ((2**floor(log2(segCount))) * 2, where “**” is an - /// exponentiation operator) - pub fn search_range(&self) -> u16 { - let range = self.shape.search_range_byte_range(); - self.data.read_at(range.start).unwrap() - } - - /// Log2 of the maximum power of 2 less than or equal to numTables - /// (log2(searchRange/2), which is equal to floor(log2(segCount))) - pub fn entry_selector(&self) -> u16 { - let range = self.shape.entry_selector_byte_range(); - self.data.read_at(range.start).unwrap() - } - - /// segCount times 2, minus searchRange ((segCount * 2) - - /// searchRange) - pub fn range_shift(&self) -> u16 { - let range = self.shape.range_shift_byte_range(); - self.data.read_at(range.start).unwrap() - } - - /// End characterCode for each segment, last=0xFFFF. - pub fn end_code(&self) -> &'a [BigEndian] { - let range = self.shape.end_code_byte_range(); - self.data.read_array(range).unwrap() - } - - /// Start character code for each segment. - pub fn start_code(&self) -> &'a [BigEndian] { - let range = self.shape.start_code_byte_range(); - self.data.read_array(range).unwrap() - } - - /// Delta for all character codes in segment. - pub fn id_delta(&self) -> &'a [BigEndian] { - let range = self.shape.id_delta_byte_range(); - self.data.read_array(range).unwrap() - } - - /// Offsets into glyphIdArray or 0 - pub fn id_range_offsets(&self) -> &'a [BigEndian] { - let range = self.shape.id_range_offsets_byte_range(); - self.data.read_array(range).unwrap() - } - - /// Glyph index array (arbitrary length) - pub fn glyph_id_array(&self) -> &'a [BigEndian] { - let range = self.shape.glyph_id_array_byte_range(); - self.data.read_array(range).unwrap() - } -} - -#[cfg(feature = "traversal")] -impl<'a> SomeTable<'a> for Cmap4<'a> { - fn type_name(&self) -> &str { - "Cmap4" - } - fn get_field(&self, idx: usize) -> Option> { - 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 = "traversal")] -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 for Cmap6Marker { - const FORMAT: u16 = 6; -} - -/// [cmap Format 6](https://docs.microsoft.com/en-us/typography/opentype/spec/cmap#format-6-trimmed-table-mapping): Trimmed table mapping -#[derive(Debug, Clone, Copy)] -#[doc(hidden)] -pub struct Cmap6Marker { - glyph_id_array_byte_len: usize, -} - -impl Cmap6Marker { - fn format_byte_range(&self) -> Range { - let start = 0; - start..start + u16::RAW_BYTE_LEN - } - fn length_byte_range(&self) -> Range { - let start = self.format_byte_range().end; - start..start + u16::RAW_BYTE_LEN - } - fn language_byte_range(&self) -> Range { - let start = self.length_byte_range().end; - start..start + u16::RAW_BYTE_LEN - } - fn first_code_byte_range(&self) -> Range { - let start = self.language_byte_range().end; - start..start + u16::RAW_BYTE_LEN - } - fn entry_count_byte_range(&self) -> Range { - let start = self.first_code_byte_range().end; - start..start + u16::RAW_BYTE_LEN - } - fn glyph_id_array_byte_range(&self) -> Range { - 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 { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - let entry_count: u16 = cursor.read()?; - let glyph_id_array_byte_len = entry_count as usize * u16::RAW_BYTE_LEN; - cursor.advance_by(glyph_id_array_byte_len); - cursor.finish(Cmap6Marker { - glyph_id_array_byte_len, - }) - } -} - -/// [cmap Format 6](https://docs.microsoft.com/en-us/typography/opentype/spec/cmap#format-6-trimmed-table-mapping): Trimmed table mapping -pub type Cmap6<'a> = TableRef<'a, Cmap6Marker>; - -impl<'a> Cmap6<'a> { - /// Format number is set to 6. - pub fn format(&self) -> u16 { - let range = self.shape.format_byte_range(); - self.data.read_at(range.start).unwrap() - } - - /// This is the length in bytes of the subtable. - pub fn length(&self) -> u16 { - let range = self.shape.length_byte_range(); - self.data.read_at(range.start).unwrap() - } - - /// For requirements on use of the language field, see “Use of - /// the language field in 'cmap' subtables” in this document. - pub fn language(&self) -> u16 { - let range = self.shape.language_byte_range(); - self.data.read_at(range.start).unwrap() - } - - /// First character code of subrange. - pub fn first_code(&self) -> u16 { - let range = self.shape.first_code_byte_range(); - self.data.read_at(range.start).unwrap() - } - - /// Number of character codes in subrange. - pub fn entry_count(&self) -> u16 { - let range = self.shape.entry_count_byte_range(); - self.data.read_at(range.start).unwrap() - } - - /// Array of glyph index values for character codes in the range. - pub fn glyph_id_array(&self) -> &'a [BigEndian] { - let range = self.shape.glyph_id_array_byte_range(); - self.data.read_array(range).unwrap() - } -} - -#[cfg(feature = "traversal")] -impl<'a> SomeTable<'a> for Cmap6<'a> { - fn type_name(&self) -> &str { - "Cmap6" - } - fn get_field(&self, idx: usize) -> Option> { - 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 = "traversal")] -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 for Cmap8Marker { - const FORMAT: u16 = 8; -} - -/// [cmap Format 8](https://docs.microsoft.com/en-us/typography/opentype/spec/cmap#format-8-mixed-16-bit-and-32-bit-coverage): mixed 16-bit and 32-bit coverage -#[derive(Debug, Clone, Copy)] -#[doc(hidden)] -pub struct Cmap8Marker { - is32_byte_len: usize, - groups_byte_len: usize, -} - -impl Cmap8Marker { - fn format_byte_range(&self) -> Range { - let start = 0; - start..start + u16::RAW_BYTE_LEN - } - fn reserved_byte_range(&self) -> Range { - let start = self.format_byte_range().end; - start..start + u16::RAW_BYTE_LEN - } - fn length_byte_range(&self) -> Range { - let start = self.reserved_byte_range().end; - start..start + u32::RAW_BYTE_LEN - } - fn language_byte_range(&self) -> Range { - let start = self.length_byte_range().end; - start..start + u32::RAW_BYTE_LEN - } - fn is32_byte_range(&self) -> Range { - let start = self.language_byte_range().end; - start..start + self.is32_byte_len - } - fn num_groups_byte_range(&self) -> Range { - let start = self.is32_byte_range().end; - start..start + u32::RAW_BYTE_LEN - } - fn groups_byte_range(&self) -> Range { - 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 { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - let is32_byte_len = 8192 * u8::RAW_BYTE_LEN; - cursor.advance_by(is32_byte_len); - let num_groups: u32 = cursor.read()?; - let groups_byte_len = num_groups as usize * SequentialMapGroup::RAW_BYTE_LEN; - cursor.advance_by(groups_byte_len); - cursor.finish(Cmap8Marker { - is32_byte_len, - groups_byte_len, - }) - } -} - -/// [cmap Format 8](https://docs.microsoft.com/en-us/typography/opentype/spec/cmap#format-8-mixed-16-bit-and-32-bit-coverage): mixed 16-bit and 32-bit coverage -pub type Cmap8<'a> = TableRef<'a, Cmap8Marker>; - -impl<'a> Cmap8<'a> { - /// Subtable format; set to 8. - pub fn format(&self) -> u16 { - let range = self.shape.format_byte_range(); - self.data.read_at(range.start).unwrap() - } - - /// Byte length of this subtable (including the header) - pub fn length(&self) -> u32 { - let range = self.shape.length_byte_range(); - self.data.read_at(range.start).unwrap() - } - - /// For requirements on use of the language field, see “Use of - /// the language field in 'cmap' subtables” in this document. - pub fn language(&self) -> u32 { - let range = self.shape.language_byte_range(); - self.data.read_at(range.start).unwrap() - } - - /// Tightly packed array of bits (8K bytes total) indicating - /// whether the particular 16-bit (index) value is the start of a - /// 32-bit character code - pub fn is32(&self) -> &'a [BigEndian] { - let range = self.shape.is32_byte_range(); - self.data.read_array(range).unwrap() - } - - /// Number of groupings which follow - pub fn num_groups(&self) -> u32 { - let range = self.shape.num_groups_byte_range(); - self.data.read_at(range.start).unwrap() - } - - /// Array of SequentialMapGroup records. - pub fn groups(&self) -> &'a [SequentialMapGroup] { - let range = self.shape.groups_byte_range(); - self.data.read_array(range).unwrap() - } -} - -#[cfg(feature = "traversal")] -impl<'a> SomeTable<'a> for Cmap8<'a> { - fn type_name(&self) -> &str { - "Cmap8" - } - fn get_field(&self, idx: usize) -> Option> { - 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 = "traversal")] -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) - } -} - -/// Used in [Cmap8] and [Cmap12] -#[derive(Clone, Debug)] -#[repr(C)] -#[repr(packed)] -pub struct SequentialMapGroup { - /// First character code in this group; note that if this group is - /// for one or more 16-bit character codes (which is determined - /// from the is32 array), this 32-bit value will have the high - /// 16-bits set to zero - pub start_char_code: BigEndian, - /// Last character code in this group; same condition as listed - /// above for the startCharCode - pub end_char_code: BigEndian, - /// Glyph index corresponding to the starting character code - pub start_glyph_id: BigEndian, -} - -impl SequentialMapGroup { - /// First character code in this group; note that if this group is - /// for one or more 16-bit character codes (which is determined - /// from the is32 array), this 32-bit value will have the high - /// 16-bits set to zero - pub fn start_char_code(&self) -> u32 { - self.start_char_code.get() - } - - /// Last character code in this group; same condition as listed - /// above for the startCharCode - pub fn end_char_code(&self) -> u32 { - self.end_char_code.get() - } - - /// Glyph index corresponding to the starting character code - 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 = "traversal")] -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 for Cmap10Marker { - const FORMAT: u16 = 10; -} - -/// [cmap Format 10](https://docs.microsoft.com/en-us/typography/opentype/spec/cmap#format-10-trimmed-array): Tr -#[derive(Debug, Clone, Copy)] -#[doc(hidden)] -pub struct Cmap10Marker { - glyph_id_array_byte_len: usize, -} - -impl Cmap10Marker { - fn format_byte_range(&self) -> Range { - let start = 0; - start..start + u16::RAW_BYTE_LEN - } - fn reserved_byte_range(&self) -> Range { - let start = self.format_byte_range().end; - start..start + u16::RAW_BYTE_LEN - } - fn length_byte_range(&self) -> Range { - let start = self.reserved_byte_range().end; - start..start + u32::RAW_BYTE_LEN - } - fn language_byte_range(&self) -> Range { - let start = self.length_byte_range().end; - start..start + u32::RAW_BYTE_LEN - } - fn start_char_code_byte_range(&self) -> Range { - let start = self.language_byte_range().end; - start..start + u32::RAW_BYTE_LEN - } - fn num_chars_byte_range(&self) -> Range { - let start = self.start_char_code_byte_range().end; - start..start + u32::RAW_BYTE_LEN - } - fn glyph_id_array_byte_range(&self) -> Range { - 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 { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - let glyph_id_array_byte_len = cursor.remaining_bytes(); - cursor.advance_by(glyph_id_array_byte_len); - cursor.finish(Cmap10Marker { - glyph_id_array_byte_len, - }) - } -} - -/// [cmap Format 10](https://docs.microsoft.com/en-us/typography/opentype/spec/cmap#format-10-trimmed-array): Tr -pub type Cmap10<'a> = TableRef<'a, Cmap10Marker>; - -impl<'a> Cmap10<'a> { - /// Subtable format; set to 10. - pub fn format(&self) -> u16 { - let range = self.shape.format_byte_range(); - self.data.read_at(range.start).unwrap() - } - - /// Byte length of this subtable (including the header) - pub fn length(&self) -> u32 { - let range = self.shape.length_byte_range(); - self.data.read_at(range.start).unwrap() - } - - /// For requirements on use of the language field, see “Use of - /// the language field in 'cmap' subtables” in this document. - pub fn language(&self) -> u32 { - let range = self.shape.language_byte_range(); - self.data.read_at(range.start).unwrap() - } - - /// First character code covered - pub fn start_char_code(&self) -> u32 { - let range = self.shape.start_char_code_byte_range(); - self.data.read_at(range.start).unwrap() - } - - /// Number of character codes covered - pub fn num_chars(&self) -> u32 { - let range = self.shape.num_chars_byte_range(); - self.data.read_at(range.start).unwrap() - } - - /// Array of glyph indices for the character codes covered - pub fn glyph_id_array(&self) -> &'a [BigEndian] { - let range = self.shape.glyph_id_array_byte_range(); - self.data.read_array(range).unwrap() - } -} - -#[cfg(feature = "traversal")] -impl<'a> SomeTable<'a> for Cmap10<'a> { - fn type_name(&self) -> &str { - "Cmap10" - } - fn get_field(&self, idx: usize) -> Option> { - 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 = "traversal")] -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 for Cmap12Marker { - const FORMAT: u16 = 12; -} - -/// [cmap Format 12](https://docs.microsoft.com/en-us/typography/opentype/spec/cmap#format-12-segmented-coverage): Segmented coverage -#[derive(Debug, Clone, Copy)] -#[doc(hidden)] -pub struct Cmap12Marker { - groups_byte_len: usize, -} - -impl Cmap12Marker { - fn format_byte_range(&self) -> Range { - let start = 0; - start..start + u16::RAW_BYTE_LEN - } - fn reserved_byte_range(&self) -> Range { - let start = self.format_byte_range().end; - start..start + u16::RAW_BYTE_LEN - } - fn length_byte_range(&self) -> Range { - let start = self.reserved_byte_range().end; - start..start + u32::RAW_BYTE_LEN - } - fn language_byte_range(&self) -> Range { - let start = self.length_byte_range().end; - start..start + u32::RAW_BYTE_LEN - } - fn num_groups_byte_range(&self) -> Range { - let start = self.language_byte_range().end; - start..start + u32::RAW_BYTE_LEN - } - fn groups_byte_range(&self) -> Range { - 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 { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - let num_groups: u32 = cursor.read()?; - let groups_byte_len = num_groups as usize * SequentialMapGroup::RAW_BYTE_LEN; - cursor.advance_by(groups_byte_len); - cursor.finish(Cmap12Marker { groups_byte_len }) - } -} - -/// [cmap Format 12](https://docs.microsoft.com/en-us/typography/opentype/spec/cmap#format-12-segmented-coverage): Segmented coverage -pub type Cmap12<'a> = TableRef<'a, Cmap12Marker>; - -impl<'a> Cmap12<'a> { - /// Subtable format; set to 12. - pub fn format(&self) -> u16 { - let range = self.shape.format_byte_range(); - self.data.read_at(range.start).unwrap() - } - - /// Byte length of this subtable (including the header) - pub fn length(&self) -> u32 { - let range = self.shape.length_byte_range(); - self.data.read_at(range.start).unwrap() - } - - /// For requirements on use of the language field, see “Use of - /// the language field in 'cmap' subtables” in this document. - pub fn language(&self) -> u32 { - let range = self.shape.language_byte_range(); - self.data.read_at(range.start).unwrap() - } - - /// Number of groupings which follow - pub fn num_groups(&self) -> u32 { - let range = self.shape.num_groups_byte_range(); - self.data.read_at(range.start).unwrap() - } - - /// Array of SequentialMapGroup records. - pub fn groups(&self) -> &'a [SequentialMapGroup] { - let range = self.shape.groups_byte_range(); - self.data.read_array(range).unwrap() - } -} - -#[cfg(feature = "traversal")] -impl<'a> SomeTable<'a> for Cmap12<'a> { - fn type_name(&self) -> &str { - "Cmap12" - } - fn get_field(&self, idx: usize) -> Option> { - 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 = "traversal")] -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 for Cmap13Marker { - const FORMAT: u16 = 13; -} - -/// [cmap Format 13](https://docs.microsoft.com/en-us/typography/opentype/spec/cmap#format-13-many-to-one-range-mappings): Many-to-one range mappings -#[derive(Debug, Clone, Copy)] -#[doc(hidden)] -pub struct Cmap13Marker { - groups_byte_len: usize, -} - -impl Cmap13Marker { - fn format_byte_range(&self) -> Range { - let start = 0; - start..start + u16::RAW_BYTE_LEN - } - fn reserved_byte_range(&self) -> Range { - let start = self.format_byte_range().end; - start..start + u16::RAW_BYTE_LEN - } - fn length_byte_range(&self) -> Range { - let start = self.reserved_byte_range().end; - start..start + u32::RAW_BYTE_LEN - } - fn language_byte_range(&self) -> Range { - let start = self.length_byte_range().end; - start..start + u32::RAW_BYTE_LEN - } - fn num_groups_byte_range(&self) -> Range { - let start = self.language_byte_range().end; - start..start + u32::RAW_BYTE_LEN - } - fn groups_byte_range(&self) -> Range { - 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 { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - let num_groups: u32 = cursor.read()?; - let groups_byte_len = num_groups as usize * ConstantMapGroup::RAW_BYTE_LEN; - cursor.advance_by(groups_byte_len); - cursor.finish(Cmap13Marker { groups_byte_len }) - } -} - -/// [cmap Format 13](https://docs.microsoft.com/en-us/typography/opentype/spec/cmap#format-13-many-to-one-range-mappings): Many-to-one range mappings -pub type Cmap13<'a> = TableRef<'a, Cmap13Marker>; - -impl<'a> Cmap13<'a> { - /// Subtable format; set to 13. - pub fn format(&self) -> u16 { - let range = self.shape.format_byte_range(); - self.data.read_at(range.start).unwrap() - } - - /// Byte length of this subtable (including the header) - pub fn length(&self) -> u32 { - let range = self.shape.length_byte_range(); - self.data.read_at(range.start).unwrap() - } - - /// For requirements on use of the language field, see “Use of - /// the language field in 'cmap' subtables” in this document. - pub fn language(&self) -> u32 { - let range = self.shape.language_byte_range(); - self.data.read_at(range.start).unwrap() - } - - /// Number of groupings which follow - pub fn num_groups(&self) -> u32 { - let range = self.shape.num_groups_byte_range(); - self.data.read_at(range.start).unwrap() - } - - /// Array of ConstantMapGroup records. - pub fn groups(&self) -> &'a [ConstantMapGroup] { - let range = self.shape.groups_byte_range(); - self.data.read_array(range).unwrap() - } -} - -#[cfg(feature = "traversal")] -impl<'a> SomeTable<'a> for Cmap13<'a> { - fn type_name(&self) -> &str { - "Cmap13" - } - fn get_field(&self, idx: usize) -> Option> { - 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 = "traversal")] -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) - } -} - -/// Part of [Cmap13] -#[derive(Clone, Debug)] -#[repr(C)] -#[repr(packed)] -pub struct ConstantMapGroup { - /// First character code in this group - pub start_char_code: BigEndian, - /// Last character code in this group - pub end_char_code: BigEndian, - /// Glyph index to be used for all the characters in the group’s - /// range. - pub glyph_id: BigEndian, -} - -impl ConstantMapGroup { - /// First character code in this group - pub fn start_char_code(&self) -> u32 { - self.start_char_code.get() - } - - /// Last character code in this group - pub fn end_char_code(&self) -> u32 { - self.end_char_code.get() - } - - /// Glyph index to be used for all the characters in the group’s - /// range. - 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 = "traversal")] -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 for Cmap14Marker { - const FORMAT: u16 = 14; -} - -/// [cmap Format 14](https://docs.microsoft.com/en-us/typography/opentype/spec/cmap#format-14-unicode-variation-sequences): Unicode Variation Sequences -#[derive(Debug, Clone, Copy)] -#[doc(hidden)] -pub struct Cmap14Marker { - var_selector_byte_len: usize, -} - -impl Cmap14Marker { - fn format_byte_range(&self) -> Range { - let start = 0; - start..start + u16::RAW_BYTE_LEN - } - fn length_byte_range(&self) -> Range { - let start = self.format_byte_range().end; - start..start + u32::RAW_BYTE_LEN - } - fn num_var_selector_records_byte_range(&self) -> Range { - let start = self.length_byte_range().end; - start..start + u32::RAW_BYTE_LEN - } - fn var_selector_byte_range(&self) -> Range { - 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 { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - let num_var_selector_records: u32 = cursor.read()?; - let var_selector_byte_len = - num_var_selector_records as usize * VariationSelector::RAW_BYTE_LEN; - cursor.advance_by(var_selector_byte_len); - cursor.finish(Cmap14Marker { - var_selector_byte_len, - }) - } -} - -/// [cmap Format 14](https://docs.microsoft.com/en-us/typography/opentype/spec/cmap#format-14-unicode-variation-sequences): Unicode Variation Sequences -pub type Cmap14<'a> = TableRef<'a, Cmap14Marker>; - -impl<'a> Cmap14<'a> { - /// Subtable format. Set to 14. - pub fn format(&self) -> u16 { - let range = self.shape.format_byte_range(); - self.data.read_at(range.start).unwrap() - } - - /// Byte length of this subtable (including this header) - pub fn length(&self) -> u32 { - let range = self.shape.length_byte_range(); - self.data.read_at(range.start).unwrap() - } - - /// Number of variation Selector Records - 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() - } - - /// Array of VariationSelector records. - pub fn var_selector(&self) -> &'a [VariationSelector] { - let range = self.shape.var_selector_byte_range(); - self.data.read_array(range).unwrap() - } -} - -#[cfg(feature = "traversal")] -impl<'a> SomeTable<'a> for Cmap14<'a> { - fn type_name(&self) -> &str { - "Cmap14" - } - fn get_field(&self, idx: usize) -> Option> { - 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 = "traversal")] -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) - } -} - -/// Part of [Cmap14] -#[derive(Clone, Debug)] -#[repr(C)] -#[repr(packed)] -pub struct VariationSelector { - /// Variation selector - pub var_selector: BigEndian, - /// Offset from the start of the format 14 subtable to Default UVS - /// Table. May be 0. - pub default_uvs_offset: BigEndian, - /// Offset from the start of the format 14 subtable to Non-Default - /// UVS Table. May be 0. - pub non_default_uvs_offset: BigEndian, -} - -impl VariationSelector { - /// Variation selector - pub fn var_selector(&self) -> Uint24 { - self.var_selector.get() - } - - /// Offset from the start of the format 14 subtable to Default UVS - /// Table. May be 0. - pub fn default_uvs_offset(&self) -> Offset32 { - self.default_uvs_offset.get() - } - - /// Offset from the start of the format 14 subtable to Non-Default - /// UVS Table. May be 0. - pub fn non_default_uvs_offset(&self) -> Offset32 { - self.non_default_uvs_offset.get() - } -} - -impl FixedSize for VariationSelector { - const RAW_BYTE_LEN: usize = - Uint24::RAW_BYTE_LEN + Offset32::RAW_BYTE_LEN + Offset32::RAW_BYTE_LEN; -} - -#[cfg(feature = "traversal")] -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::unknown_offset(self.default_uvs_offset()), - )), - 2usize => Some(Field::new( - "non_default_uvs_offset", - FieldType::unknown_offset(self.non_default_uvs_offset()), - )), - _ => None, - }), - data, - } - } -} - -/// [Default UVS table](https://docs.microsoft.com/en-us/typography/opentype/spec/cmap#default-uvs-table) -#[derive(Debug, Clone, Copy)] -#[doc(hidden)] -pub struct DefaultUvsMarker { - ranges_byte_len: usize, -} - -impl DefaultUvsMarker { - fn num_unicode_value_ranges_byte_range(&self) -> Range { - let start = 0; - start..start + u32::RAW_BYTE_LEN - } - fn ranges_byte_range(&self) -> Range { - 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 { - let mut cursor = data.cursor(); - let num_unicode_value_ranges: u32 = cursor.read()?; - let ranges_byte_len = num_unicode_value_ranges as usize * UnicodeRange::RAW_BYTE_LEN; - cursor.advance_by(ranges_byte_len); - cursor.finish(DefaultUvsMarker { ranges_byte_len }) - } -} - -/// [Default UVS table](https://docs.microsoft.com/en-us/typography/opentype/spec/cmap#default-uvs-table) -pub type DefaultUvs<'a> = TableRef<'a, DefaultUvsMarker>; - -impl<'a> DefaultUvs<'a> { - /// Number of Unicode character ranges. - 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() - } - - /// Array of UnicodeRange records. - pub fn ranges(&self) -> &'a [UnicodeRange] { - let range = self.shape.ranges_byte_range(); - self.data.read_array(range).unwrap() - } -} - -#[cfg(feature = "traversal")] -impl<'a> SomeTable<'a> for DefaultUvs<'a> { - fn type_name(&self) -> &str { - "DefaultUvs" - } - fn get_field(&self, idx: usize) -> Option> { - 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 = "traversal")] -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) - } -} - -/// Part of [Cmap14] -#[derive(Clone, Debug)] -#[repr(C)] -#[repr(packed)] -pub struct UVSMapping { - /// Base Unicode value of the UVS - pub unicode_value: BigEndian, - /// Glyph ID of the UVS - pub glyph_id: BigEndian, -} - -impl UVSMapping { - /// Base Unicode value of the UVS - pub fn unicode_value(&self) -> Uint24 { - self.unicode_value.get() - } - - /// Glyph ID of the UVS - 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 = "traversal")] -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, - } - } -} - -/// Part of [Cmap14] -#[derive(Clone, Debug)] -#[repr(C)] -#[repr(packed)] -pub struct UnicodeRange { - /// First value in this range - pub start_unicode_value: BigEndian, - /// Number of additional values in this range - pub additional_count: BigEndian, -} - -impl UnicodeRange { - /// First value in this range - pub fn start_unicode_value(&self) -> Uint24 { - self.start_unicode_value.get() - } - - /// Number of additional values in this range - pub fn additional_count(&self) -> u8 { - self.additional_count.get() - } -} - -impl FixedSize for UnicodeRange { - const RAW_BYTE_LEN: usize = Uint24::RAW_BYTE_LEN + u8::RAW_BYTE_LEN; -} - -#[cfg(feature = "traversal")] -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, - } - } -} diff --git a/resources/codegen_inputs/cmap.rs b/resources/codegen_inputs/cmap.rs index 5fa602779..ccf507be0 100644 --- a/resources/codegen_inputs/cmap.rs +++ b/resources/codegen_inputs/cmap.rs @@ -5,10 +5,8 @@ table Cmap { /// Table version number (0). version: BigEndian, /// Number of encoding tables that follow. - #[compile(array_len($encoding_records))] num_tables: BigEndian, - #[count($num_tables)] - encoding_records: [EncodingRecord], + encoding_records: [EncodingRecord; num_tables], } /// [Encoding Record](https://docs.microsoft.com/en-us/typography/opentype/spec/cmap#encoding-records-and-encodings)