diff --git a/font-codegen/src/fields.rs b/font-codegen/src/fields.rs index e59f41226..693cd4eff 100644 --- a/font-codegen/src/fields.rs +++ b/font-codegen/src/fields.rs @@ -315,7 +315,7 @@ fn if_expression(xform: &IfTransform, add_self: bool) -> TokenStream { } impl Condition { - fn condition_tokens_for_read(&self) -> TokenStream { + pub(crate) fn condition_tokens_for_read(&self) -> TokenStream { match self { Condition::SinceVersion(version) => quote!(version.compatible(#version)), Condition::IfFlag { field, flag } => quote!(#field.contains(#flag)), @@ -323,6 +323,18 @@ impl Condition { } } + pub(crate) fn condition_tokens_for_access(&self) -> TokenStream { + match self { + Condition::SinceVersion(version) => quote!(self.version().compatible(#version)), + Condition::IfFlag { field, flag } => quote!(self.#field().contains(#flag)), + Condition::IfCond { xform } => match xform { + IfTransform::AnyFlag(field, flags) => { + quote!(self.#field().intersects(#(#flags)|*)) + } + }, + } + } + fn condition_tokens_for_write(&self) -> TokenStream { match self { Condition::SinceVersion(version) => quote!(version.compatible(#version)), @@ -690,7 +702,7 @@ impl Field { self.attrs.skip_getter.is_none() } - pub(crate) fn shape_len_expr(&self) -> TokenStream { + pub(crate) fn shape_len_expr(&self, start_expr: TokenStream) -> TokenStream { // is this a scalar/offset? then it's just 'RAW_BYTE_LEN' // is this computed? then it is stored match &self.typ { @@ -702,8 +714,7 @@ impl Field { | FieldType::ComputedArray { .. } | FieldType::VarLenArray(_) => { let len_field = self.shape_byte_len_field_name(); - let try_op = self.is_conditional().then(|| quote!(?)); - quote!(self.#len_field #try_op) + quote!(self.#len_field(#start_expr)) } FieldType::PendingResolution { .. } => panic!("Should have resolved {self:?}"), } @@ -717,7 +728,7 @@ impl Field { result.extend( count .iter_referenced_fields() - .map(|fld| (fld.clone(), NeededWhen::Parse)), + .map(|fld| (fld.clone(), NeededWhen::Both)), ); } if let Some(flds) = self.attrs.conditional.as_ref().map(|c| c.input_field()) { @@ -814,13 +825,13 @@ impl Field { let range_stmt = self.getter_range_stmt(); let mut read_stmt = if let Some(args) = &self.attrs.read_with_args { let get_args = args.to_tokens_for_table_getter(); - quote!( self.data.read_with_args(range, &#get_args).unwrap() ) + quote!(unchecked::read_with_args(self.data, range, &#get_args)) } else if is_var_array { - quote!(VarLenArray::read(self.data.split_off(range.start).unwrap()).unwrap()) + quote!(VarLenArray::read(unchecked::split_off(self.data, range.start)).unwrap()) } else if is_array { - quote!(self.data.read_array(range).unwrap()) + quote!(unchecked::read_array(self.data, range)) } else { - quote!(self.data.read_at(range.start).unwrap()) + quote!(unchecked::read_at(self.data, range.start)) }; if is_versioned { read_stmt = quote!(Some(#read_stmt)); @@ -887,7 +898,7 @@ impl Field { fn getter_range_stmt(&self) -> TokenStream { let shape_range_fn_name = self.shape_byte_range_fn_name(); let try_op = self.is_conditional().then(|| quote!(?)); - quote!( self.shape.#shape_range_fn_name() #try_op ) + quote!( self.#shape_range_fn_name() #try_op ) } fn typed_offset_getter_docs(&self, has_data_arg: bool) -> TokenStream { diff --git a/font-codegen/src/table.rs b/font-codegen/src/table.rs index b92f4b4eb..4711715a1 100644 --- a/font-codegen/src/table.rs +++ b/font-codegen/src/table.rs @@ -9,7 +9,10 @@ use quote::{quote, ToTokens}; use crate::parsing::{Attr, GenericGroup, Item, Items, Phase}; -use super::parsing::{Field, ReferencedFields, Table, TableFormat, TableReadArg, TableReadArgs}; +use super::parsing::{ + Count, CountArg, CountTransform, Field, FieldReadArgs, FieldType, ReferencedFields, Table, + TableFormat, TableReadArg, TableReadArgs, +}; pub(crate) fn generate(item: &Table) -> syn::Result { if item.attrs.write_only.is_some() { @@ -18,40 +21,29 @@ pub(crate) fn generate(item: &Table) -> syn::Result { let docs = &item.attrs.docs; let generic = item.attrs.generic_offset.as_ref(); let generic_with_default = generic.map(|t| quote!(#t = ())); - let phantom_decl = generic.map(|t| quote!(offset_type: std::marker::PhantomData<*const #t>)); let marker_name = item.marker_name(); let raw_name = item.raw_name(); + let shape_byte_len_fns = item.iter_shape_len_fns(); let shape_byte_range_fns = item.iter_shape_byte_fns(); let optional_min_byte_range_trait_impl = item.impl_min_byte_range_trait(); - let shape_fields = item.iter_shape_fields(); - let derive_clone_copy = generic.is_none().then(|| quote!(Clone, Copy)); - let impl_clone_copy = generic.is_some().then(|| { - quote! { - impl<#generic> Clone for #marker_name<#generic> { - fn clone(&self) -> Self { - *self - } - } - - impl<#generic> Copy for #marker_name<#generic> {} - } - }); + let table_ref_args = item + .attrs + .read_args + .as_ref() + .map(|args| args.args_type()) + .unwrap_or_else(|| { + generic + .as_ref() + .map(|t| quote!(std::marker::PhantomData<*const #t>)) + .unwrap_or_else(|| quote!(())) + }); let of_unit_docs = " Replace the specific generic type on this implementation with `()`"; // In the presence of a generic param we only impl FontRead for Name<()>, // and then use into() to convert it to the concrete generic type. let impl_into_generic = generic.as_ref().map(|t| { - let shape_fields = item - .iter_shape_field_names() - .map(|name| quote!(#name: shape.#name)) - .collect::>(); - - let shape_name = if shape_fields.is_empty() { - quote!(..) - } else { - quote!(shape) - }; + let shape_name = quote!(..); quote! { impl<'a> #raw_name<'a, ()> { @@ -59,10 +51,9 @@ pub(crate) fn generate(item: &Table) -> syn::Result { pub(crate) fn into_concrete(self) -> #raw_name<'a, #t> { let TableRef { data, #shape_name} = self; TableRef { - shape: #marker_name { - #( #shape_fields, )* - offset_type: std::marker::PhantomData, - }, data + args: std::marker::PhantomData, + data, + _marker: std::marker::PhantomData, } } } @@ -75,10 +66,9 @@ pub(crate) fn generate(item: &Table) -> syn::Result { pub(crate) fn of_unit_type(&self) -> #raw_name<'a, ()> { let TableRef { data, #shape_name} = self; TableRef { - shape: #marker_name { - #( #shape_fields, )* - offset_type: std::marker::PhantomData, - }, data: *data, + args: std::marker::PhantomData, + data: *data, + _marker: std::marker::PhantomData, } } } @@ -106,33 +96,28 @@ pub(crate) fn generate(item: &Table) -> syn::Result { #optional_format_trait_impl #( #docs )* - #[derive(Debug, #derive_clone_copy)] + #[derive(Debug, Clone, Copy)] #[doc(hidden)] - pub struct #marker_name <#generic_with_default> { - #( #shape_fields, )* - #phantom_decl - } - - impl <#generic> #marker_name <#generic> { - #( #shape_byte_range_fns )* - } - + pub struct #marker_name; #optional_min_byte_range_trait_impl #top_level - #impl_clone_copy - #font_read #impl_into_generic #( #docs )* - pub type #raw_name<'a, #generic> = TableRef<'a, #marker_name<#generic>>; + pub type #raw_name<'a, #generic_with_default> = + TableRef<'a, #marker_name, #table_ref_args>; #[allow(clippy::needless_lifetimes)] impl<'a, #generic> #raw_name<'a, #generic> { + #( #shape_byte_len_fns )* + + #( #shape_byte_range_fns )* + #( #table_ref_getters )* } @@ -142,25 +127,16 @@ pub(crate) fn generate(item: &Table) -> syn::Result { } fn generate_font_read(item: &Table) -> syn::Result { - let marker_name = item.marker_name(); let name = item.raw_name(); - let field_validation_stmts = item.iter_field_validation_stmts(); - let shape_field_names = item.iter_shape_field_names(); let generic = item.attrs.generic_offset.as_ref(); - let phantom = generic.map(|_| quote!(offset_type: std::marker::PhantomData,)); let error_if_phantom_and_read_args = generic.map(|_| { quote!(compile_error!( "ReadWithArgs not implemented for tables with phantom params." );) }); - // the cursor doesn't need to be mut if there are no fields, - // which happens at least once (in glyf)? - let maybe_mut_kw = (!item.fields.fields.is_empty()).then(|| quote!(mut)); - if let Some(read_args) = &item.attrs.read_args { let args_type = read_args.args_type(); - let destructure_pattern = read_args.destructure_pattern(); let constructor_args = read_args.constructor_args(); let args_from_constructor_args = read_args.read_args_from_constructor_args(); Ok(quote! { @@ -171,11 +147,11 @@ fn generate_font_read(item: &Table) -> syn::Result { impl<'a> FontReadWithArgs<'a> for #name<'a> { fn read_with_args(data: FontData<'a>, args: &#args_type) -> Result { - let #destructure_pattern = *args; - let #maybe_mut_kw cursor = data.cursor(); - #( #field_validation_stmts )* - cursor.finish( #marker_name { - #( #shape_field_names, )* + let args = *args; + Ok(TableRef { + args, + data, + _marker: std::marker::PhantomData, }) } } @@ -192,14 +168,17 @@ fn generate_font_read(item: &Table) -> syn::Result { } }) } else { + let args_value = generic + .as_ref() + .map(|_| quote!(std::marker::PhantomData)) + .unwrap_or_else(|| quote!(())); Ok(quote! { impl<'a, #generic> FontRead<'a> for #name<'a, #generic> { fn read(data: FontData<'a>) -> Result { - let #maybe_mut_kw cursor = data.cursor(); - #( #field_validation_stmts )* - cursor.finish( #marker_name { - #( #shape_field_names, )* - #phantom + Ok(TableRef { + args: #args_value, + data, + _marker: std::marker::PhantomData, }) } } @@ -921,19 +900,24 @@ impl Table { std::iter::from_fn(move || { let field = iter.next()?; let fn_name = field.shape_byte_range_fn_name(); - let len_expr = field.shape_len_expr(); + let len_expr = field.shape_len_expr(quote!(start)); // versioned fields have a different signature - if field.attrs.conditional.is_some() { + if let Some(condition) = field.attrs.conditional.as_ref() { + let condition = condition.condition_tokens_for_access(); + let start_expr = prev_field_end_expr.clone(); prev_field_end_expr = quote! { self.#fn_name().map(|range| range.end) .unwrap_or_else(|| #prev_field_end_expr) }; - let start_field_name = field.shape_byte_start_field_name(); return Some(quote! { pub fn #fn_name(&self) -> Option> { - let start = self.#start_field_name?; - Some(start..start + #len_expr) + if #condition { + let start = #start_expr; + Some(start..start + #len_expr) + } else { + None + } } }); } @@ -950,51 +934,213 @@ impl Table { }) } - fn iter_shape_fields(&self) -> impl Iterator + '_ { - self.iter_shape_field_names_and_types() - .into_iter() - .map(|(ident, typ)| quote!( #ident: #typ )) + fn iter_shape_len_fns(&self) -> impl Iterator + '_ { + self.fields.iter().filter_map(|field| { + if !field.has_computed_len() { + return None; + } + let fn_name = field.shape_byte_len_field_name(); + let len_expr = self.byte_len_expr_for_field(field); + Some(quote! { + fn #fn_name(&self, start: usize) -> usize { + let _ = start; + #len_expr + } + }) + }) } - fn iter_shape_field_names(&self) -> impl Iterator + '_ { - self.iter_shape_field_names_and_types() - .into_iter() - .map(|(name, _)| name) - } + fn byte_len_expr_for_field(&self, field: &Field) -> TokenStream { + let read_args = field + .attrs + .read_with_args + .as_deref() + .map(|args| self.field_read_args_expr(args)); - fn iter_shape_field_names_and_types(&self) -> Vec<(syn::Ident, TokenStream)> { - let mut result = Vec::new(); - // if an input arg is needed later, save it in the shape. - if let Some(args) = &self.attrs.read_args { - result.extend( - args.args - .iter() - .filter(|arg| self.fields.referenced_fields.needs_at_runtime(&arg.ident)) - .map(|arg| (arg.ident.clone(), arg.typ.to_token_stream())), - ); + if let FieldType::Struct { typ } = &field.typ { + let read_args = read_args.expect("ComputeSize requires read args"); + return quote!(<#typ as ComputeSize>::compute_size(&#read_args).unwrap()); + } + if let FieldType::PendingResolution { .. } = &field.typ { + panic!("Should have resolved {field:?}") } - for next in self.fields.iter() { - let is_versioned = next.attrs.conditional.is_some(); - let has_computed_len = next.has_computed_len(); - if !(is_versioned || has_computed_len) { - continue; + let count = field + .attrs + .count + .as_deref() + .expect("missing count attribute?"); + match count { + Count::All(_) => { + let remaining = match &field.typ { + FieldType::Array { inner_typ } => { + let inner_typ = inner_typ.cooked_type_tokens(); + quote! { + { + let remaining = self.data.len().saturating_sub(start); + remaining / #inner_typ::RAW_BYTE_LEN * #inner_typ::RAW_BYTE_LEN + } + } + } + _ => quote!(self.data.len().saturating_sub(start)), + }; + remaining } - if is_versioned { - let field_name = next.shape_byte_start_field_name(); - result.push((field_name, quote!(Option))); + other => { + let count_expr = self.count_expr_tokens(other); + let size_expr = match &field.typ { + FieldType::Array { inner_typ } => { + let inner_typ = inner_typ.cooked_type_tokens(); + quote!(#inner_typ::RAW_BYTE_LEN) + } + FieldType::ComputedArray(array) => { + let inner = array.raw_inner_type(); + let read_args = read_args.expect("ComputedArray requires read args"); + quote!(<#inner as ComputeSize>::compute_size(&#read_args).unwrap()) + } + FieldType::VarLenArray(array) => { + let inner = array.raw_inner_type(); + return quote! { + { + let data = self.data.split_off(start).unwrap(); + <#inner as VarSize>::total_len_for_count(data, #count_expr).unwrap() + } + }; + } + _ => unreachable!("count not valid here"), + }; + if let Count::SingleArg(CountArg::Literal(lit)) = other { + if lit.base10_digits() == "1" { + return size_expr; + } + } + quote!((#count_expr).checked_mul(#size_expr).unwrap()) } + } + } - if has_computed_len { - let field_name = next.shape_byte_len_field_name(); - if is_versioned { - result.push((field_name, quote!(Option))); - } else { - result.push((field_name, quote!(usize))); + fn field_read_args_expr(&self, args: &FieldReadArgs) -> TokenStream { + match args.inputs.as_slice() { + [arg] => self.read_arg_expr(arg), + args => { + let args = args.iter().map(|arg| self.read_arg_expr(arg)); + quote!(( #( #args ),* )) + } + } + } + + fn count_arg_expr(&self, arg: &CountArg) -> TokenStream { + match arg { + CountArg::Field(ident) => self.read_arg_expr(ident), + CountArg::Literal(lit) => quote!(#lit), + } + } + + fn count_expr_tokens(&self, count: &Count) -> TokenStream { + match count { + Count::All(_) => unreachable!("'all' count handled separately"), + Count::SingleArg(CountArg::Field(arg)) => { + let arg = self.read_arg_expr(arg); + quote!((#arg) as usize) + } + Count::SingleArg(CountArg::Literal(arg)) => quote!(#arg), + Count::Complicated { args, xform } => { + let args = args + .iter() + .map(|arg| self.count_arg_expr(arg)) + .collect::>(); + match (xform, args.as_slice()) { + (CountTransform::Sub, [a, b]) => { + quote!(transforms::subtract(#a, #b)) + } + (CountTransform::Add, [a, b]) => { + quote!(transforms::add(#a, #b)) + } + (CountTransform::AddMul, [a, b, c]) => { + quote!(transforms::add_multiply(#a, #b, #c)) + } + (CountTransform::MulAdd, [a, b, c]) => { + quote!(transforms::multiply_add(#a, #b, #c)) + } + (CountTransform::Half, [a]) => { + quote!(transforms::half(#a)) + } + (CountTransform::DeltaSetIndexData, [a, b]) => { + quote!(EntryFormat::map_size(#a, #b)) + } + (CountTransform::DeltaValueCount, [a, b, c]) => { + quote!(DeltaFormat::value_count(#a, #b, #c)) + } + (CountTransform::TupleLen, [a, b, c]) => { + quote!(TupleIndex::tuple_len(#a, #b, #c)) + } + (CountTransform::ItemVariationDataLen, [a, b, c]) => { + quote!(ItemVariationData::delta_sets_len(#a, #b, #c)) + } + (CountTransform::BitmapLen, [a]) => { + quote!(transforms::bitmap_len(#a)) + } + (CountTransform::MaxValueBitmapLen, [a]) => { + quote!(transforms::max_value_bitmap_len(#a)) + } + (CountTransform::SubAddTwo, [a, b]) => { + quote!(transforms::subtract_add_two(#a, #b)) + } + (CountTransform::TryInto, [a]) => { + quote!(usize::try_from(#a).unwrap_or_default()) + } + _ => unreachable!("unexpected count transform args"), } - }; + } + } + } + + fn read_arg_expr(&self, ident: &syn::Ident) -> TokenStream { + if let Some(idx) = self.read_arg_index(ident) { + if self.read_args_len() == 1 { + quote!(self.args) + } else { + let idx = syn::Index::from(idx); + quote!(self.args.#idx) + } + } else if self.is_conditional_field(ident) { + quote!(self.#ident().unwrap_or_default()) + } else { + quote!(self.#ident()) } - result + } + + fn read_arg_index(&self, ident: &syn::Ident) -> Option { + self.attrs + .read_args + .as_ref() + .and_then(|args| args.args.iter().position(|arg| arg.ident == *ident)) + } + + fn read_args_len(&self) -> usize { + self.attrs + .read_args + .as_ref() + .map(|args| args.args.len()) + .unwrap_or(0) + } + + fn is_conditional_field(&self, ident: &syn::Ident) -> bool { + self.fields + .iter() + .any(|field| field.name == *ident && field.attrs.conditional.is_some()) + } + + fn iter_shape_fields(&self) -> impl Iterator + '_ { + std::iter::empty() + } + + fn iter_shape_field_names(&self) -> impl Iterator + '_ { + std::iter::empty() + } + + fn iter_shape_field_names_and_types(&self) -> Vec<(syn::Ident, TokenStream)> { + Vec::new() } fn iter_field_validation_stmts(&self) -> impl Iterator + '_ { @@ -1034,11 +1180,12 @@ impl Table { .iter() .filter(|fld| fld.attrs.conditional.is_none()) .last()?; - let name = self.marker_name(); + let name = self.raw_name(); + let generic = self.attrs.generic_offset.as_ref().map(|attr| &attr.attr); let fn_name = field.shape_byte_range_fn_name(); Some(quote! { - impl MinByteRange for #name { + impl<'a, #generic> MinByteRange for #name<'a, #generic> { fn min_byte_range(&self) -> Range { 0..self.#fn_name().end } @@ -1089,13 +1236,21 @@ impl TableReadArgs { &'a self, referenced_fields: &'a ReferencedFields, ) -> impl Iterator + 'a { + let is_single = self.args.len() == 1; self.args .iter() - .filter(|arg| referenced_fields.needs_at_runtime(&arg.ident)) - .map(|TableReadArg { ident, typ }| { + .enumerate() + .filter(|(_, arg)| referenced_fields.needs_at_runtime(&arg.ident)) + .map(move |(idx, TableReadArg { ident, typ })| { + let value_expr = if is_single { + quote!(self.args) + } else { + let idx = syn::Index::from(idx); + quote!(self.args.#idx) + }; quote! { pub(crate) fn #ident(&self) -> #typ { - self.shape.#ident + #value_expr } } }) diff --git a/incremental-font-transfer/src/glyph_keyed.rs b/incremental-font-transfer/src/glyph_keyed.rs index 9045b3dc4..930e3c10c 100644 --- a/incremental-font-transfer/src/glyph_keyed.rs +++ b/incremental-font-transfer/src/glyph_keyed.rs @@ -656,7 +656,7 @@ impl CFFAndCharStrings<'_> { let charstrings = Index1::read(charstrings_data)?; let offset_type = Self::offset_type(charstrings.off_size())?; - let offset_base = charstrings.shape().data_byte_range().start; + let offset_base = charstrings.data_byte_range().start; let charstrings_object_data = charstrings_data .split_off(offset_base) .ok_or(ReadError::OutOfBounds)? @@ -684,7 +684,7 @@ impl CFFAndCharStrings<'_> { let charstrings = Index2::read(charstrings_data)?; let offset_type = Self::offset_type(charstrings.off_size())?; - let offset_base = charstrings.shape().data_byte_range().start; + let offset_base = charstrings.data_byte_range().start; let charstrings_object_data = charstrings_data .split_off(offset_base) .ok_or(ReadError::OutOfBounds)? @@ -883,7 +883,7 @@ impl GlyphDataOffsetArray for Gvar<'_> { let orig_bytes = self.as_bytes(); let orig_size = orig_bytes.len(); - let original_offsets_range = self.shape().glyph_variation_data_offsets_byte_range(); + let original_offsets_range = self.glyph_variation_data_offsets_byte_range(); if new_offset_type == self.offset_type() && offsets.offset_array.len() @@ -940,7 +940,7 @@ impl GlyphDataOffsetArray for Gvar<'_> { let shared_tuples_bytes = shared_tuples .offset_data() .as_bytes() - .get(shared_tuples.shape().tuples_byte_range()) + .get(shared_tuples.tuples_byte_range()) .ok_or_else(|| PatchingError::SerializationError(serializer.error()))?; let shared_tuples_obj = if !shared_tuples_bytes.is_empty() { @@ -965,14 +965,14 @@ impl GlyphDataOffsetArray for Gvar<'_> { // Set up offsets to shared tuples and glyph data. serializer .add_link( - self.shape().shared_tuples_offset_byte_range(), + self.shared_tuples_offset_byte_range(), shared_tuples_obj, OffsetWhence::Head, 0, false, ) .and(serializer.add_link( - self.shape().glyph_variation_data_array_offset_byte_range(), + self.glyph_variation_data_array_offset_byte_range(), glyph_data_obj, OffsetWhence::Head, 0, diff --git a/incremental-font-transfer/src/patchmap.rs b/incremental-font-transfer/src/patchmap.rs index 2b465f9c1..d78a70473 100644 --- a/incremental-font-transfer/src/patchmap.rs +++ b/incremental-font-transfer/src/patchmap.rs @@ -109,7 +109,7 @@ fn add_intersecting_format1_patches( // Step 2: produce final output. let mut applied_entries_indices: HashMap> = Default::default(); - let applied_entries_start_bit_index = map.shape().applied_entries_bitmap_byte_range().start * 8; + let applied_entries_start_bit_index = map.applied_entries_bitmap_byte_range().start * 8; for (index, subset_def) in entries .into_iter() @@ -674,7 +674,7 @@ fn decode_format2_entry<'a>( entries.push(entry); - let consumed_bytes = entry_data.shape().trailing_data_byte_range().end - trailing_data.len(); + let consumed_bytes = entry_data.trailing_data_byte_range().end - trailing_data.len(); Ok((FontData::new(trailing_data), consumed_bytes)) } diff --git a/klippa/src/cblc.rs b/klippa/src/cblc.rs index c213780ca..71bbf5fec 100644 --- a/klippa/src/cblc.rs +++ b/klippa/src/cblc.rs @@ -48,7 +48,7 @@ impl Subset for Cblc<'_> { let bitmapsize_bytes = self .offset_data() .as_bytes() - .get(self.shape().bitmap_sizes_byte_range()) + .get(self.bitmap_sizes_byte_range()) .unwrap(); // cbdt out diff --git a/klippa/src/colr.rs b/klippa/src/colr.rs index 0b5cf943a..3bfdf0d2a 100644 --- a/klippa/src/colr.rs +++ b/klippa/src/colr.rs @@ -534,7 +534,7 @@ impl SubsetTable<'_> for ClipBoxFormat2<'_> { }; // update VarIdxBase s.copy_assign( - start_pos + self.shape().var_index_base_byte_range().start, + start_pos + self.var_index_base_byte_range().start, *new_varidx, ); } @@ -833,7 +833,7 @@ impl SubsetTable<'_> for PaintVarLinearGradient<'_> { return Err(s.set_err(SerializeErrorFlags::SERIALIZE_ERROR_OTHER)); }; // update VarIdxBase - let pos = start_pos + self.shape().var_index_base_byte_range().start; + let pos = start_pos + self.var_index_base_byte_range().start; s.copy_assign(pos, *new_varidx); } Ok(()) @@ -884,7 +884,7 @@ impl SubsetTable<'_> for PaintVarRadialGradient<'_> { return Err(s.set_err(SerializeErrorFlags::SERIALIZE_ERROR_OTHER)); }; // update VarIdxBase - let pos = start_pos + self.shape().var_index_base_byte_range().start; + let pos = start_pos + self.var_index_base_byte_range().start; s.copy_assign(pos, *new_varidx); } Ok(()) @@ -935,7 +935,7 @@ impl SubsetTable<'_> for PaintVarSweepGradient<'_> { return Err(s.set_err(SerializeErrorFlags::SERIALIZE_ERROR_OTHER)); }; // update VarIdxBase - let pos = start_pos + self.shape().var_index_base_byte_range().start; + let pos = start_pos + self.var_index_base_byte_range().start; s.copy_assign(pos, *new_varidx); } Ok(()) @@ -1019,7 +1019,7 @@ impl SubsetTable<'_> for VarAffine2x3<'_> { return Err(s.set_err(SerializeErrorFlags::SERIALIZE_ERROR_OTHER)); }; // update VarIdxBase - let pos = start_pos + self.shape().var_index_base_byte_range().start; + let pos = start_pos + self.var_index_base_byte_range().start; s.copy_assign(pos, *new_varidx); } Ok(()) @@ -1120,7 +1120,7 @@ impl SubsetTable<'_> for PaintVarTranslate<'_> { return Err(s.set_err(SerializeErrorFlags::SERIALIZE_ERROR_OTHER)); }; // update VarIdxBase - let pos = start_pos + self.shape().var_index_base_byte_range().start; + let pos = start_pos + self.var_index_base_byte_range().start; s.copy_assign(pos, *new_varidx); } Ok(()) @@ -1167,7 +1167,7 @@ impl SubsetTable<'_> for PaintVarScale<'_> { return Err(s.set_err(SerializeErrorFlags::SERIALIZE_ERROR_OTHER)); }; // update VarIdxBase - let pos = start_pos + self.shape().var_index_base_byte_range().start; + let pos = start_pos + self.var_index_base_byte_range().start; s.copy_assign(pos, *new_varidx); } Ok(()) @@ -1214,7 +1214,7 @@ impl SubsetTable<'_> for PaintVarScaleAroundCenter<'_> { return Err(s.set_err(SerializeErrorFlags::SERIALIZE_ERROR_OTHER)); }; // update VarIdxBase - let pos = start_pos + self.shape().var_index_base_byte_range().start; + let pos = start_pos + self.var_index_base_byte_range().start; s.copy_assign(pos, *new_varidx); } Ok(()) @@ -1261,7 +1261,7 @@ impl SubsetTable<'_> for PaintVarScaleUniform<'_> { return Err(s.set_err(SerializeErrorFlags::SERIALIZE_ERROR_OTHER)); }; // update VarIdxBase - let pos = start_pos + self.shape().var_index_base_byte_range().start; + let pos = start_pos + self.var_index_base_byte_range().start; s.copy_assign(pos, *new_varidx); } Ok(()) @@ -1308,7 +1308,7 @@ impl SubsetTable<'_> for PaintVarScaleUniformAroundCenter<'_> { return Err(s.set_err(SerializeErrorFlags::SERIALIZE_ERROR_OTHER)); }; // update VarIdxBase - let pos = start_pos + self.shape().var_index_base_byte_range().start; + let pos = start_pos + self.var_index_base_byte_range().start; s.copy_assign(pos, *new_varidx); } Ok(()) @@ -1355,7 +1355,7 @@ impl SubsetTable<'_> for PaintVarRotate<'_> { return Err(s.set_err(SerializeErrorFlags::SERIALIZE_ERROR_OTHER)); }; // update VarIdxBase - let pos = start_pos + self.shape().var_index_base_byte_range().start; + let pos = start_pos + self.var_index_base_byte_range().start; s.copy_assign(pos, *new_varidx); } Ok(()) @@ -1402,7 +1402,7 @@ impl SubsetTable<'_> for PaintVarRotateAroundCenter<'_> { return Err(s.set_err(SerializeErrorFlags::SERIALIZE_ERROR_OTHER)); }; // update VarIdxBase - let pos = start_pos + self.shape().var_index_base_byte_range().start; + let pos = start_pos + self.var_index_base_byte_range().start; s.copy_assign(pos, *new_varidx); } Ok(()) @@ -1449,7 +1449,7 @@ impl SubsetTable<'_> for PaintVarSkew<'_> { return Err(s.set_err(SerializeErrorFlags::SERIALIZE_ERROR_OTHER)); }; // update VarIdxBase - let pos = start_pos + self.shape().var_index_base_byte_range().start; + let pos = start_pos + self.var_index_base_byte_range().start; s.copy_assign(pos, *new_varidx); } Ok(()) @@ -1496,7 +1496,7 @@ impl SubsetTable<'_> for PaintVarSkewAroundCenter<'_> { return Err(s.set_err(SerializeErrorFlags::SERIALIZE_ERROR_OTHER)); }; // update VarIdxBase - let pos = start_pos + self.shape().var_index_base_byte_range().start; + let pos = start_pos + self.var_index_base_byte_range().start; s.copy_assign(pos, *new_varidx); } Ok(()) diff --git a/klippa/src/gvar.rs b/klippa/src/gvar.rs index a27347a1b..cc0b215c0 100644 --- a/klippa/src/gvar.rs +++ b/klippa/src/gvar.rs @@ -88,7 +88,7 @@ fn subset_with_offset_type( //update sharedTuplesOffset, which is of Offset32 type and byte position in gvar is 8..12 s.copy_assign( - gvar.shape().shared_tuples_offset_byte_range().start, + gvar.shared_tuples_offset_byte_range().start, shared_tuples_offset, ); diff --git a/klippa/src/maxp.rs b/klippa/src/maxp.rs index 7fc880216..88920f163 100644 --- a/klippa/src/maxp.rs +++ b/klippa/src/maxp.rs @@ -19,7 +19,7 @@ impl Subset for Maxp<'_> { let num_glyphs = plan.num_output_glyphs.min(0xFFFF) as u16; s.embed_bytes(self.offset_data().as_bytes()) .map_err(|_| SubsetError::SubsetTableError(Maxp::TAG))?; - s.copy_assign(self.shape().num_glyphs_byte_range().start, num_glyphs); + s.copy_assign(self.num_glyphs_byte_range().start, num_glyphs); //drop hints if self.version() == Version16Dot16::VERSION_1_0 @@ -28,33 +28,15 @@ impl Subset for Maxp<'_> { .contains(SubsetFlags::SUBSET_FLAGS_NO_HINTING) { //maxZones - s.copy_assign_from_bytes(self.shape().max_zones_byte_range().unwrap().start, &[0, 1]); + s.copy_assign_from_bytes(self.max_zones_byte_range().unwrap().start, &[0, 1]); //maxTwilightPoints..maxSizeOfInstructions + s.copy_assign(self.max_twilight_points_byte_range().unwrap().start, 0_u16); + s.copy_assign(self.max_storage_byte_range().unwrap().start, 0_u16); + s.copy_assign(self.max_function_defs_byte_range().unwrap().start, 0_u16); + s.copy_assign(self.max_instruction_defs_byte_range().unwrap().start, 0_u16); + s.copy_assign(self.max_stack_elements_byte_range().unwrap().start, 0_u16); s.copy_assign( - self.shape().max_twilight_points_byte_range().unwrap().start, - 0_u16, - ); - s.copy_assign(self.shape().max_storage_byte_range().unwrap().start, 0_u16); - s.copy_assign( - self.shape().max_function_defs_byte_range().unwrap().start, - 0_u16, - ); - s.copy_assign( - self.shape() - .max_instruction_defs_byte_range() - .unwrap() - .start, - 0_u16, - ); - s.copy_assign( - self.shape().max_stack_elements_byte_range().unwrap().start, - 0_u16, - ); - s.copy_assign( - self.shape() - .max_size_of_instructions_byte_range() - .unwrap() - .start, + self.max_size_of_instructions_byte_range().unwrap().start, 0_u16, ); } diff --git a/klippa/src/name.rs b/klippa/src/name.rs index d0dc451f7..a11615a44 100644 --- a/klippa/src/name.rs +++ b/klippa/src/name.rs @@ -80,7 +80,7 @@ fn serialize_name_records( ) -> Result<(), SubsetError> { let data = name.offset_data().as_bytes(); let name_records = name.name_record(); - let name_records_bytes = data.get(name.shape().name_record_byte_range()).unwrap(); + let name_records_bytes = data.get(name.name_record_byte_range()).unwrap(); let storage_start = name.storage_offset() as usize; for idx in retained_name_record_idxes.iter() { let len = s.length(); diff --git a/klippa/src/offset.rs b/klippa/src/offset.rs index 9c34fe299..a27b43743 100644 --- a/klippa/src/offset.rs +++ b/klippa/src/offset.rs @@ -50,11 +50,13 @@ impl SerializeSubset for O { // this is trait is used to copy simple tables only which implemented MinByteRange trait pub(crate) trait SerializeCopy { - fn serialize_copy( + fn serialize_copy( t: &TableRef, s: &mut Serializer, pos: usize, - ) -> Result<(), SerializeErrorFlags>; + ) -> Result<(), SerializeErrorFlags> + where + for<'a> TableRef<'a, T>: MinByteRange; fn serialize_copy_from_bytes( src_bytes: &[u8], @@ -64,11 +66,14 @@ pub(crate) trait SerializeCopy { } impl SerializeCopy for O { - fn serialize_copy( + fn serialize_copy( t: &TableRef, s: &mut Serializer, pos: usize, - ) -> Result<(), SerializeErrorFlags> { + ) -> Result<(), SerializeErrorFlags> + where + for<'a> TableRef<'a, T>: MinByteRange, + { s.push()?; s.embed_bytes(t.min_table_bytes())?; diff --git a/klippa/src/os2.rs b/klippa/src/os2.rs index 9f2417d51..011b1c2f4 100644 --- a/klippa/src/os2.rs +++ b/klippa/src/os2.rs @@ -27,13 +27,13 @@ impl Subset for Os2<'_> { let us_first_char_index: u16 = plan.os2_info.min_cmap_codepoint.min(0xFFFF) as u16; s.copy_assign( - self.shape().us_first_char_index_byte_range().start, + self.us_first_char_index_byte_range().start, us_first_char_index, ); let us_last_char_index: u16 = plan.os2_info.max_cmap_codepoint.min(0xFFFF) as u16; s.copy_assign( - self.shape().us_last_char_index_byte_range().start, + self.us_last_char_index_byte_range().start, us_last_char_index, ); diff --git a/klippa/src/post.rs b/klippa/src/post.rs index a3abb071c..0d284db9f 100644 --- a/klippa/src/post.rs +++ b/klippa/src/post.rs @@ -31,10 +31,7 @@ impl Subset for Post<'_> { .contains(SubsetFlags::SUBSET_FLAGS_GLYPH_NAMES); //version 3 does not have any glyph names if !glyph_names { - s.copy_assign( - self.shape().version_byte_range().start, - Version16Dot16::VERSION_3_0, - ); + s.copy_assign(self.version_byte_range().start, Version16Dot16::VERSION_3_0); } if glyph_names && self.version() == Version16Dot16::VERSION_2_0 { diff --git a/klippa/src/variations.rs b/klippa/src/variations.rs index 723779fc5..6f7fa20e5 100644 --- a/klippa/src/variations.rs +++ b/klippa/src/variations.rs @@ -102,7 +102,7 @@ impl<'a> SubsetTable<'a> for VariationRegionList<'a> { let Some(src_var_regions_bytes) = self .offset_data() .as_bytes() - .get(self.shape().variation_regions_byte_range()) + .get(self.variation_regions_byte_range()) else { return Err(s.set_err(SerializeErrorFlags::SERIALIZE_ERROR_READ_ERROR)); }; diff --git a/read-fonts/generated/font.rs b/read-fonts/generated/font.rs index a74ce537f..6f94e65aa 100644 --- a/read-fonts/generated/font.rs +++ b/read-fonts/generated/font.rs @@ -8,11 +8,36 @@ use crate::codegen_prelude::*; /// The OpenType [Table Directory](https://docs.microsoft.com/en-us/typography/opentype/spec/otff#table-directory) #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct TableDirectoryMarker { - table_records_byte_len: usize, +pub struct TableDirectoryMarker; + +impl<'a> MinByteRange for TableDirectory<'a> { + fn min_byte_range(&self) -> Range { + 0..self.table_records_byte_range().end + } } -impl TableDirectoryMarker { +impl<'a> FontRead<'a> for TableDirectory<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// The OpenType [Table Directory](https://docs.microsoft.com/en-us/typography/opentype/spec/otff#table-directory) +pub type TableDirectory<'a> = TableRef<'a, TableDirectoryMarker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> TableDirectory<'a> { + fn table_records_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.num_tables()) as usize) + .checked_mul(TableRecord::RAW_BYTE_LEN) + .unwrap() + } + pub fn sfnt_version_byte_range(&self) -> Range { let start = 0; start..start + u32::RAW_BYTE_LEN @@ -40,70 +65,40 @@ impl TableDirectoryMarker { pub fn table_records_byte_range(&self) -> Range { let start = self.range_shift_byte_range().end; - start..start + self.table_records_byte_len + start..start + self.table_records_byte_len(start) } -} -impl MinByteRange for TableDirectoryMarker { - fn min_byte_range(&self) -> Range { - 0..self.table_records_byte_range().end - } -} - -impl<'a> FontRead<'a> for TableDirectory<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - let num_tables: u16 = cursor.read()?; - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - let table_records_byte_len = (num_tables as usize) - .checked_mul(TableRecord::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(table_records_byte_len); - cursor.finish(TableDirectoryMarker { - table_records_byte_len, - }) - } -} - -/// The OpenType [Table Directory](https://docs.microsoft.com/en-us/typography/opentype/spec/otff#table-directory) -pub type TableDirectory<'a> = TableRef<'a, TableDirectoryMarker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> TableDirectory<'a> { /// 0x00010000 or 0x4F54544F pub fn sfnt_version(&self) -> u32 { - let range = self.shape.sfnt_version_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.sfnt_version_byte_range(); + unchecked::read_at(self.data, range.start) } /// Number of tables. pub fn num_tables(&self) -> u16 { - let range = self.shape.num_tables_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.num_tables_byte_range(); + unchecked::read_at(self.data, range.start) } pub fn search_range(&self) -> u16 { - let range = self.shape.search_range_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.search_range_byte_range(); + unchecked::read_at(self.data, range.start) } pub fn entry_selector(&self) -> u16 { - let range = self.shape.entry_selector_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.entry_selector_byte_range(); + unchecked::read_at(self.data, range.start) } pub fn range_shift(&self) -> u16 { - let range = self.shape.range_shift_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.range_shift_byte_range(); + unchecked::read_at(self.data, range.start) } /// Table records array—one for each top-level table in the font pub fn table_records(&self) -> &'a [TableRecord] { - let range = self.shape.table_records_byte_range(); - self.data.read_array(range).unwrap() + let range = self.table_records_byte_range(); + unchecked::read_array(self.data, range) } } @@ -202,14 +197,36 @@ impl<'a> SomeRecord<'a> for TableRecord { /// [TTC Header](https://learn.microsoft.com/en-us/typography/opentype/spec/otff#ttc-header) #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct TTCHeaderMarker { - table_directory_offsets_byte_len: usize, - dsig_tag_byte_start: Option, - dsig_length_byte_start: Option, - dsig_offset_byte_start: Option, +pub struct TTCHeaderMarker; + +impl<'a> MinByteRange for TTCHeader<'a> { + fn min_byte_range(&self) -> Range { + 0..self.table_directory_offsets_byte_range().end + } +} + +impl<'a> FontRead<'a> for TTCHeader<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } } -impl TTCHeaderMarker { +/// [TTC Header](https://learn.microsoft.com/en-us/typography/opentype/spec/otff#ttc-header) +pub type TTCHeader<'a> = TableRef<'a, TTCHeaderMarker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> TTCHeader<'a> { + fn table_directory_offsets_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.num_fonts()) as usize) + .checked_mul(u32::RAW_BYTE_LEN) + .unwrap() + } + pub fn ttc_tag_byte_range(&self) -> Range { let start = 0; start..start + Tag::RAW_BYTE_LEN @@ -227,116 +244,86 @@ impl TTCHeaderMarker { pub fn table_directory_offsets_byte_range(&self) -> Range { let start = self.num_fonts_byte_range().end; - start..start + self.table_directory_offsets_byte_len + start..start + self.table_directory_offsets_byte_len(start) } pub fn dsig_tag_byte_range(&self) -> Option> { - let start = self.dsig_tag_byte_start?; - Some(start..start + u32::RAW_BYTE_LEN) + if self.version().compatible((2u16, 0u16)) { + let start = self.table_directory_offsets_byte_range().end; + Some(start..start + u32::RAW_BYTE_LEN) + } else { + None + } } pub fn dsig_length_byte_range(&self) -> Option> { - let start = self.dsig_length_byte_start?; - Some(start..start + u32::RAW_BYTE_LEN) + if self.version().compatible((2u16, 0u16)) { + let start = self + .dsig_tag_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| self.table_directory_offsets_byte_range().end); + Some(start..start + u32::RAW_BYTE_LEN) + } else { + None + } } pub fn dsig_offset_byte_range(&self) -> Option> { - let start = self.dsig_offset_byte_start?; - Some(start..start + u32::RAW_BYTE_LEN) - } -} - -impl MinByteRange for TTCHeaderMarker { - fn min_byte_range(&self) -> Range { - 0..self.table_directory_offsets_byte_range().end - } -} - -impl<'a> FontRead<'a> for TTCHeader<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - let version: MajorMinor = cursor.read()?; - let num_fonts: u32 = cursor.read()?; - let table_directory_offsets_byte_len = (num_fonts as usize) - .checked_mul(u32::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(table_directory_offsets_byte_len); - let dsig_tag_byte_start = version - .compatible((2u16, 0u16)) - .then(|| cursor.position()) - .transpose()?; - version - .compatible((2u16, 0u16)) - .then(|| cursor.advance::()); - let dsig_length_byte_start = version - .compatible((2u16, 0u16)) - .then(|| cursor.position()) - .transpose()?; - version - .compatible((2u16, 0u16)) - .then(|| cursor.advance::()); - let dsig_offset_byte_start = version - .compatible((2u16, 0u16)) - .then(|| cursor.position()) - .transpose()?; - version - .compatible((2u16, 0u16)) - .then(|| cursor.advance::()); - cursor.finish(TTCHeaderMarker { - table_directory_offsets_byte_len, - dsig_tag_byte_start, - dsig_length_byte_start, - dsig_offset_byte_start, - }) + if self.version().compatible((2u16, 0u16)) { + let start = self + .dsig_length_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| { + self.dsig_tag_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| self.table_directory_offsets_byte_range().end) + }); + Some(start..start + u32::RAW_BYTE_LEN) + } else { + None + } } -} -/// [TTC Header](https://learn.microsoft.com/en-us/typography/opentype/spec/otff#ttc-header) -pub type TTCHeader<'a> = TableRef<'a, TTCHeaderMarker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> TTCHeader<'a> { /// Font Collection ID string: \"ttcf\" pub fn ttc_tag(&self) -> Tag { - let range = self.shape.ttc_tag_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.ttc_tag_byte_range(); + unchecked::read_at(self.data, range.start) } /// Major/minor version of the TTC Header pub fn version(&self) -> MajorMinor { - let range = self.shape.version_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.version_byte_range(); + unchecked::read_at(self.data, range.start) } /// Number of fonts in TTC pub fn num_fonts(&self) -> u32 { - let range = self.shape.num_fonts_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.num_fonts_byte_range(); + unchecked::read_at(self.data, range.start) } /// Array of offsets to the TableDirectory for each font from the beginning of the file pub fn table_directory_offsets(&self) -> &'a [BigEndian] { - let range = self.shape.table_directory_offsets_byte_range(); - self.data.read_array(range).unwrap() + let range = self.table_directory_offsets_byte_range(); + unchecked::read_array(self.data, range) } /// Tag indicating that a DSIG table exists, 0x44534947 ('DSIG') (null if no signature) pub fn dsig_tag(&self) -> Option { - let range = self.shape.dsig_tag_byte_range()?; - Some(self.data.read_at(range.start).unwrap()) + let range = self.dsig_tag_byte_range()?; + Some(unchecked::read_at(self.data, range.start)) } /// The length (in bytes) of the DSIG table (null if no signature) pub fn dsig_length(&self) -> Option { - let range = self.shape.dsig_length_byte_range()?; - Some(self.data.read_at(range.start).unwrap()) + let range = self.dsig_length_byte_range()?; + Some(unchecked::read_at(self.data, range.start)) } /// The offset (in bytes) of the DSIG table from the beginning of the TTC file (null if no signature) pub fn dsig_offset(&self) -> Option { - let range = self.shape.dsig_offset_byte_range()?; - Some(self.data.read_at(range.start).unwrap()) + let range = self.dsig_offset_byte_range()?; + Some(unchecked::read_at(self.data, range.start)) } } diff --git a/read-fonts/generated/generated_aat.rs b/read-fonts/generated/generated_aat.rs index 483f13975..cec1579f3 100644 --- a/read-fonts/generated/generated_aat.rs +++ b/read-fonts/generated/generated_aat.rs @@ -110,23 +110,9 @@ impl Format for Lookup0Marker { /// by glyph index. #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct Lookup0Marker { - values_data_byte_len: usize, -} - -impl Lookup0Marker { - pub fn format_byte_range(&self) -> Range { - let start = 0; - start..start + u16::RAW_BYTE_LEN - } - - pub fn values_data_byte_range(&self) -> Range { - let start = self.format_byte_range().end; - start..start + self.values_data_byte_len - } -} +pub struct Lookup0Marker; -impl MinByteRange for Lookup0Marker { +impl<'a> MinByteRange for Lookup0<'a> { fn min_byte_range(&self) -> Range { 0..self.values_data_byte_range().end } @@ -134,32 +120,48 @@ impl MinByteRange for Lookup0Marker { impl<'a> FontRead<'a> for Lookup0<'a> { fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - let values_data_byte_len = cursor.remaining_bytes() / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN; - cursor.advance_by(values_data_byte_len); - cursor.finish(Lookup0Marker { - values_data_byte_len, + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, }) } } /// Simple array format. The lookup data is an array of lookup values, indexed /// by glyph index. -pub type Lookup0<'a> = TableRef<'a, Lookup0Marker>; +pub type Lookup0<'a> = TableRef<'a, Lookup0Marker, ()>; #[allow(clippy::needless_lifetimes)] impl<'a> Lookup0<'a> { + fn values_data_byte_len(&self, start: usize) -> usize { + let _ = start; + { + let remaining = self.data.len().saturating_sub(start); + remaining / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN + } + } + + pub fn format_byte_range(&self) -> Range { + let start = 0; + start..start + u16::RAW_BYTE_LEN + } + + pub fn values_data_byte_range(&self) -> Range { + let start = self.format_byte_range().end; + start..start + self.values_data_byte_len(start) + } + /// 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() + let range = self.format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Values, indexed by glyph index. pub fn values_data(&self) -> &'a [u8] { - let range = self.shape.values_data_byte_range(); - self.data.read_array(range).unwrap() + let range = self.values_data_byte_range(); + unchecked::read_array(self.data, range) } } @@ -194,11 +196,38 @@ impl Format for Lookup2Marker { /// a contiguous range of glyph indexes. #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct Lookup2Marker { - segments_data_byte_len: usize, +pub struct Lookup2Marker; + +impl<'a> MinByteRange for Lookup2<'a> { + fn min_byte_range(&self) -> Range { + 0..self.segments_data_byte_range().end + } } -impl Lookup2Marker { +impl<'a> FontRead<'a> for Lookup2<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// Segment single format. Each non-overlapping segment has a single lookup +/// value that applies to all glyphs in the segment. A segment is defined as +/// a contiguous range of glyph indexes. +pub type Lookup2<'a> = TableRef<'a, Lookup2Marker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> Lookup2<'a> { + fn segments_data_byte_len(&self, start: usize) -> usize { + let _ = start; + (transforms::add_multiply(self.unit_size(), 0_usize, self.n_units())) + .checked_mul(u8::RAW_BYTE_LEN) + .unwrap() + } + pub fn format_byte_range(&self) -> Range { let start = 0; start..start + u16::RAW_BYTE_LEN @@ -231,82 +260,49 @@ impl Lookup2Marker { pub fn segments_data_byte_range(&self) -> Range { let start = self.range_shift_byte_range().end; - start..start + self.segments_data_byte_len + start..start + self.segments_data_byte_len(start) } -} -impl MinByteRange for Lookup2Marker { - fn min_byte_range(&self) -> Range { - 0..self.segments_data_byte_range().end - } -} - -impl<'a> FontRead<'a> for Lookup2<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - let unit_size: u16 = cursor.read()?; - let n_units: u16 = cursor.read()?; - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - let segments_data_byte_len = (transforms::add_multiply(unit_size, 0_usize, n_units)) - .checked_mul(u8::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(segments_data_byte_len); - cursor.finish(Lookup2Marker { - segments_data_byte_len, - }) - } -} - -/// Segment single format. Each non-overlapping segment has a single lookup -/// value that applies to all glyphs in the segment. A segment is defined as -/// a contiguous range of glyph indexes. -pub type Lookup2<'a> = TableRef<'a, Lookup2Marker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> Lookup2<'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() + let range = self.format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Size of a lookup unit for this search in bytes. pub fn unit_size(&self) -> u16 { - let range = self.shape.unit_size_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.unit_size_byte_range(); + unchecked::read_at(self.data, range.start) } /// Number of units of the preceding size to be searched. pub fn n_units(&self) -> u16 { - let range = self.shape.n_units_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.n_units_byte_range(); + unchecked::read_at(self.data, range.start) } /// The value of unitSize times the largest power of 2 that is less than or equal to the value of nUnits. pub fn search_range(&self) -> u16 { - let range = self.shape.search_range_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.search_range_byte_range(); + unchecked::read_at(self.data, range.start) } /// The log base 2 of the largest power of 2 less than or equal to the value of nUnits. pub fn entry_selector(&self) -> u16 { - let range = self.shape.entry_selector_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.entry_selector_byte_range(); + unchecked::read_at(self.data, range.start) } /// The value of unitSize times the difference of the value of nUnits minus the largest power of 2 less than or equal to the value of nUnits. pub fn range_shift(&self) -> u16 { - let range = self.shape.range_shift_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.range_shift_byte_range(); + unchecked::read_at(self.data, range.start) } /// Segments. pub fn segments_data(&self) -> &'a [u8] { - let range = self.shape.segments_data_byte_range(); - self.data.read_array(range).unwrap() + let range = self.segments_data_byte_range(); + unchecked::read_array(self.data, range) } } @@ -346,11 +342,38 @@ impl Format for Lookup4Marker { /// each glyph in the segment gets its own separate lookup value. #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct Lookup4Marker { - segments_byte_len: usize, +pub struct Lookup4Marker; + +impl<'a> MinByteRange for Lookup4<'a> { + fn min_byte_range(&self) -> Range { + 0..self.segments_byte_range().end + } } -impl Lookup4Marker { +impl<'a> FontRead<'a> for Lookup4<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// Segment array format. A segment mapping is performed (as with Format 2), +/// but instead of a single lookup value for all the glyphs in the segment, +/// each glyph in the segment gets its own separate lookup value. +pub type Lookup4<'a> = TableRef<'a, Lookup4Marker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> Lookup4<'a> { + fn segments_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.n_units()) as usize) + .checked_mul(LookupSegment4::RAW_BYTE_LEN) + .unwrap() + } + pub fn format_byte_range(&self) -> Range { let start = 0; start..start + u16::RAW_BYTE_LEN @@ -383,80 +406,49 @@ impl Lookup4Marker { pub fn segments_byte_range(&self) -> Range { let start = self.range_shift_byte_range().end; - start..start + self.segments_byte_len - } -} - -impl MinByteRange for Lookup4Marker { - fn min_byte_range(&self) -> Range { - 0..self.segments_byte_range().end + start..start + self.segments_byte_len(start) } -} - -impl<'a> FontRead<'a> for Lookup4<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - let n_units: u16 = cursor.read()?; - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - let segments_byte_len = (n_units as usize) - .checked_mul(LookupSegment4::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(segments_byte_len); - cursor.finish(Lookup4Marker { segments_byte_len }) - } -} - -/// Segment array format. A segment mapping is performed (as with Format 2), -/// but instead of a single lookup value for all the glyphs in the segment, -/// each glyph in the segment gets its own separate lookup value. -pub type Lookup4<'a> = TableRef<'a, Lookup4Marker>; -#[allow(clippy::needless_lifetimes)] -impl<'a> Lookup4<'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() + let range = self.format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Size of a lookup unit for this search in bytes. pub fn unit_size(&self) -> u16 { - let range = self.shape.unit_size_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.unit_size_byte_range(); + unchecked::read_at(self.data, range.start) } /// Number of units of the preceding size to be searched. pub fn n_units(&self) -> u16 { - let range = self.shape.n_units_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.n_units_byte_range(); + unchecked::read_at(self.data, range.start) } /// The value of unitSize times the largest power of 2 that is less than or equal to the value of nUnits. pub fn search_range(&self) -> u16 { - let range = self.shape.search_range_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.search_range_byte_range(); + unchecked::read_at(self.data, range.start) } /// The log base 2 of the largest power of 2 less than or equal to the value of nUnits. pub fn entry_selector(&self) -> u16 { - let range = self.shape.entry_selector_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.entry_selector_byte_range(); + unchecked::read_at(self.data, range.start) } /// The value of unitSize times the difference of the value of nUnits minus the largest power of 2 less than or equal to the value of nUnits. pub fn range_shift(&self) -> u16 { - let range = self.shape.range_shift_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.range_shift_byte_range(); + unchecked::read_at(self.data, range.start) } /// Segments. pub fn segments(&self) -> &'a [LookupSegment4] { - let range = self.shape.segments_byte_range(); - self.data.read_array(range).unwrap() + let range = self.segments_byte_range(); + unchecked::read_array(self.data, range) } } @@ -552,11 +544,37 @@ impl Format for Lookup6Marker { /// pairs. #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct Lookup6Marker { - entries_data_byte_len: usize, +pub struct Lookup6Marker; + +impl<'a> MinByteRange for Lookup6<'a> { + fn min_byte_range(&self) -> Range { + 0..self.entries_data_byte_range().end + } } -impl Lookup6Marker { +impl<'a> FontRead<'a> for Lookup6<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// Single table format. The lookup data is a sorted list of +/// pairs. +pub type Lookup6<'a> = TableRef<'a, Lookup6Marker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> Lookup6<'a> { + fn entries_data_byte_len(&self, start: usize) -> usize { + let _ = start; + (transforms::add_multiply(self.unit_size(), 0_usize, self.n_units())) + .checked_mul(u8::RAW_BYTE_LEN) + .unwrap() + } + pub fn format_byte_range(&self) -> Range { let start = 0; start..start + u16::RAW_BYTE_LEN @@ -589,81 +607,49 @@ impl Lookup6Marker { pub fn entries_data_byte_range(&self) -> Range { let start = self.range_shift_byte_range().end; - start..start + self.entries_data_byte_len - } -} - -impl MinByteRange for Lookup6Marker { - fn min_byte_range(&self) -> Range { - 0..self.entries_data_byte_range().end + start..start + self.entries_data_byte_len(start) } -} -impl<'a> FontRead<'a> for Lookup6<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - let unit_size: u16 = cursor.read()?; - let n_units: u16 = cursor.read()?; - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - let entries_data_byte_len = (transforms::add_multiply(unit_size, 0_usize, n_units)) - .checked_mul(u8::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(entries_data_byte_len); - cursor.finish(Lookup6Marker { - entries_data_byte_len, - }) - } -} - -/// Single table format. The lookup data is a sorted list of -/// pairs. -pub type Lookup6<'a> = TableRef<'a, Lookup6Marker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> Lookup6<'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() + let range = self.format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Size of a lookup unit for this search in bytes. pub fn unit_size(&self) -> u16 { - let range = self.shape.unit_size_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.unit_size_byte_range(); + unchecked::read_at(self.data, range.start) } /// Number of units of the preceding size to be searched. pub fn n_units(&self) -> u16 { - let range = self.shape.n_units_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.n_units_byte_range(); + unchecked::read_at(self.data, range.start) } /// The value of unitSize times the largest power of 2 that is less than or equal to the value of nUnits. pub fn search_range(&self) -> u16 { - let range = self.shape.search_range_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.search_range_byte_range(); + unchecked::read_at(self.data, range.start) } /// The log base 2 of the largest power of 2 less than or equal to the value of nUnits. pub fn entry_selector(&self) -> u16 { - let range = self.shape.entry_selector_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.entry_selector_byte_range(); + unchecked::read_at(self.data, range.start) } /// The value of unitSize times the difference of the value of nUnits minus the largest power of 2 less than or equal to the value of nUnits. pub fn range_shift(&self) -> u16 { - let range = self.shape.range_shift_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.range_shift_byte_range(); + unchecked::read_at(self.data, range.start) } /// Values, indexed by glyph index. pub fn entries_data(&self) -> &'a [u8] { - let range = self.shape.entries_data_byte_range(); - self.data.read_array(range).unwrap() + let range = self.entries_data_byte_range(); + unchecked::read_array(self.data, range) } } @@ -702,11 +688,37 @@ impl Format for Lookup8Marker { /// indexed by glyph index. #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct Lookup8Marker { - value_array_byte_len: usize, +pub struct Lookup8Marker; + +impl<'a> MinByteRange for Lookup8<'a> { + fn min_byte_range(&self) -> Range { + 0..self.value_array_byte_range().end + } +} + +impl<'a> FontRead<'a> for Lookup8<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } } -impl Lookup8Marker { +/// Trimmed array format. The lookup data is a simple trimmed array +/// indexed by glyph index. +pub type Lookup8<'a> = TableRef<'a, Lookup8Marker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> Lookup8<'a> { + fn value_array_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.glyph_count()) as usize) + .checked_mul(u16::RAW_BYTE_LEN) + .unwrap() + } + pub fn format_byte_range(&self) -> Range { let start = 0; start..start + u16::RAW_BYTE_LEN @@ -724,62 +736,33 @@ impl Lookup8Marker { pub fn value_array_byte_range(&self) -> Range { let start = self.glyph_count_byte_range().end; - start..start + self.value_array_byte_len + start..start + self.value_array_byte_len(start) } -} - -impl MinByteRange for Lookup8Marker { - fn min_byte_range(&self) -> Range { - 0..self.value_array_byte_range().end - } -} - -impl<'a> FontRead<'a> for Lookup8<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - let glyph_count: u16 = cursor.read()?; - let value_array_byte_len = (glyph_count as usize) - .checked_mul(u16::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(value_array_byte_len); - cursor.finish(Lookup8Marker { - value_array_byte_len, - }) - } -} -/// Trimmed array format. The lookup data is a simple trimmed array -/// indexed by glyph index. -pub type Lookup8<'a> = TableRef<'a, Lookup8Marker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> Lookup8<'a> { /// Format number is set to 8. pub fn format(&self) -> u16 { - let range = self.shape.format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.format_byte_range(); + unchecked::read_at(self.data, range.start) } /// First glyph index included in the trimmed array. pub fn first_glyph(&self) -> u16 { - let range = self.shape.first_glyph_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.first_glyph_byte_range(); + unchecked::read_at(self.data, range.start) } /// Total number of glyphs (equivalent to the last glyph minus the value /// of firstGlyph plus 1). pub fn glyph_count(&self) -> u16 { - let range = self.shape.glyph_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.glyph_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// The lookup values (indexed by the glyph index minus the value of /// firstGlyph). Entries in the value array must be two bytes. pub fn value_array(&self) -> &'a [BigEndian] { - let range = self.shape.value_array_byte_range(); - self.data.read_array(range).unwrap() + let range = self.value_array_byte_range(); + unchecked::read_array(self.data, range) } } @@ -815,11 +798,37 @@ impl Format for Lookup10Marker { /// indexed by glyph index. #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct Lookup10Marker { - values_data_byte_len: usize, +pub struct Lookup10Marker; + +impl<'a> MinByteRange for Lookup10<'a> { + fn min_byte_range(&self) -> Range { + 0..self.values_data_byte_range().end + } +} + +impl<'a> FontRead<'a> for Lookup10<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } } -impl Lookup10Marker { +/// Trimmed array format. The lookup data is a simple trimmed array +/// indexed by glyph index. +pub type Lookup10<'a> = TableRef<'a, Lookup10Marker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> Lookup10<'a> { + fn values_data_byte_len(&self, start: usize) -> usize { + let _ = start; + (transforms::add_multiply(self.glyph_count(), 0_usize, self.unit_size())) + .checked_mul(u8::RAW_BYTE_LEN) + .unwrap() + } + pub fn format_byte_range(&self) -> Range { let start = 0; start..start + u16::RAW_BYTE_LEN @@ -842,70 +851,40 @@ impl Lookup10Marker { pub fn values_data_byte_range(&self) -> Range { let start = self.glyph_count_byte_range().end; - start..start + self.values_data_byte_len + start..start + self.values_data_byte_len(start) } -} -impl MinByteRange for Lookup10Marker { - fn min_byte_range(&self) -> Range { - 0..self.values_data_byte_range().end - } -} - -impl<'a> FontRead<'a> for Lookup10<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - let unit_size: u16 = cursor.read()?; - cursor.advance::(); - let glyph_count: u16 = cursor.read()?; - let values_data_byte_len = (transforms::add_multiply(glyph_count, 0_usize, unit_size)) - .checked_mul(u8::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(values_data_byte_len); - cursor.finish(Lookup10Marker { - values_data_byte_len, - }) - } -} - -/// Trimmed array format. The lookup data is a simple trimmed array -/// indexed by glyph index. -pub type Lookup10<'a> = TableRef<'a, Lookup10Marker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> Lookup10<'a> { /// Format number is set to 10. pub fn format(&self) -> u16 { - let range = self.shape.format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Size of a lookup unit for this lookup table in bytes. Allowed values /// are 1, 2, 4, and 8. pub fn unit_size(&self) -> u16 { - let range = self.shape.unit_size_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.unit_size_byte_range(); + unchecked::read_at(self.data, range.start) } /// First glyph index included in the trimmed array. pub fn first_glyph(&self) -> u16 { - let range = self.shape.first_glyph_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.first_glyph_byte_range(); + unchecked::read_at(self.data, range.start) } /// Total number of glyphs (equivalent to the last glyph minus the value /// of firstGlyph plus 1). pub fn glyph_count(&self) -> u16 { - let range = self.shape.glyph_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.glyph_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// The lookup values (indexed by the glyph index minus the value of /// firstGlyph). pub fn values_data(&self) -> &'a [u8] { - let range = self.shape.values_data_byte_range(); - self.data.read_array(range).unwrap() + let range = self.values_data_byte_range(); + unchecked::read_array(self.data, range) } } @@ -937,9 +916,29 @@ impl<'a> std::fmt::Debug for Lookup10<'a> { /// Header for a state table. #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct StateHeaderMarker {} +pub struct StateHeaderMarker; -impl StateHeaderMarker { +impl<'a> MinByteRange for StateHeader<'a> { + fn min_byte_range(&self) -> Range { + 0..self.entry_table_offset_byte_range().end + } +} + +impl<'a> FontRead<'a> for StateHeader<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// Header for a state table. +pub type StateHeader<'a> = TableRef<'a, StateHeaderMarker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> StateHeader<'a> { pub fn state_size_byte_range(&self) -> Range { let start = 0; start..start + u16::RAW_BYTE_LEN @@ -959,41 +958,18 @@ impl StateHeaderMarker { let start = self.state_array_offset_byte_range().end; start..start + Offset16::RAW_BYTE_LEN } -} - -impl MinByteRange for StateHeaderMarker { - fn min_byte_range(&self) -> Range { - 0..self.entry_table_offset_byte_range().end - } -} - -impl<'a> FontRead<'a> for StateHeader<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.finish(StateHeaderMarker {}) - } -} -/// Header for a state table. -pub type StateHeader<'a> = TableRef<'a, StateHeaderMarker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> StateHeader<'a> { /// Size of a state, in bytes. The size is limited to 8 bits, although the /// field is 16 bits for alignment. pub fn state_size(&self) -> u16 { - let range = self.shape.state_size_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.state_size_byte_range(); + unchecked::read_at(self.data, range.start) } /// Byte offset from the beginning of the state table to the class subtable. pub fn class_table_offset(&self) -> Offset16 { - let range = self.shape.class_table_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.class_table_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`class_table_offset`][Self::class_table_offset]. @@ -1004,8 +980,8 @@ impl<'a> StateHeader<'a> { /// Byte offset from the beginning of the state table to the state array. pub fn state_array_offset(&self) -> Offset16 { - let range = self.shape.state_array_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.state_array_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`state_array_offset`][Self::state_array_offset]. @@ -1016,8 +992,8 @@ impl<'a> StateHeader<'a> { /// Byte offset from the beginning of the state table to the entry subtable. pub fn entry_table_offset(&self) -> Offset16 { - let range = self.shape.entry_table_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.entry_table_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`entry_table_offset`][Self::entry_table_offset]. @@ -1063,28 +1039,9 @@ impl<'a> std::fmt::Debug for StateHeader<'a> { /// Maps the glyph indexes of your font into classes. #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct ClassSubtableMarker { - class_array_byte_len: usize, -} +pub struct ClassSubtableMarker; -impl ClassSubtableMarker { - pub fn first_glyph_byte_range(&self) -> Range { - let start = 0; - start..start + u16::RAW_BYTE_LEN - } - - pub fn n_glyphs_byte_range(&self) -> Range { - let start = self.first_glyph_byte_range().end; - start..start + u16::RAW_BYTE_LEN - } - - pub fn class_array_byte_range(&self) -> Range { - let start = self.n_glyphs_byte_range().end; - start..start + self.class_array_byte_len - } -} - -impl MinByteRange for ClassSubtableMarker { +impl<'a> MinByteRange for ClassSubtable<'a> { fn min_byte_range(&self) -> Range { 0..self.class_array_byte_range().end } @@ -1092,41 +1049,58 @@ impl MinByteRange for ClassSubtableMarker { impl<'a> FontRead<'a> for ClassSubtable<'a> { fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - let n_glyphs: u16 = cursor.read()?; - let class_array_byte_len = (n_glyphs as usize) - .checked_mul(u8::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(class_array_byte_len); - cursor.finish(ClassSubtableMarker { - class_array_byte_len, + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, }) } } /// Maps the glyph indexes of your font into classes. -pub type ClassSubtable<'a> = TableRef<'a, ClassSubtableMarker>; +pub type ClassSubtable<'a> = TableRef<'a, ClassSubtableMarker, ()>; #[allow(clippy::needless_lifetimes)] impl<'a> ClassSubtable<'a> { + fn class_array_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.n_glyphs()) as usize) + .checked_mul(u8::RAW_BYTE_LEN) + .unwrap() + } + + pub fn first_glyph_byte_range(&self) -> Range { + let start = 0; + start..start + u16::RAW_BYTE_LEN + } + + pub fn n_glyphs_byte_range(&self) -> Range { + let start = self.first_glyph_byte_range().end; + start..start + u16::RAW_BYTE_LEN + } + + pub fn class_array_byte_range(&self) -> Range { + let start = self.n_glyphs_byte_range().end; + start..start + self.class_array_byte_len(start) + } + /// Glyph index of the first glyph in the class table. pub fn first_glyph(&self) -> u16 { - let range = self.shape.first_glyph_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.first_glyph_byte_range(); + unchecked::read_at(self.data, range.start) } /// Number of glyphs in class table. pub fn n_glyphs(&self) -> u16 { - let range = self.shape.n_glyphs_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.n_glyphs_byte_range(); + unchecked::read_at(self.data, range.start) } /// The class codes (indexed by glyph index minus firstGlyph). Class codes /// range from 0 to the value of stateSize minus 1. pub fn class_array(&self) -> &'a [u8] { - let range = self.shape.class_array_byte_range(); - self.data.read_array(range).unwrap() + let range = self.class_array_byte_range(); + unchecked::read_array(self.data, range) } } @@ -1156,18 +1130,9 @@ impl<'a> std::fmt::Debug for ClassSubtable<'a> { /// Used for the `state_array` and `entry_table` fields in [`StateHeader`]. #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct RawBytesMarker { - data_byte_len: usize, -} +pub struct RawBytesMarker; -impl RawBytesMarker { - pub fn data_byte_range(&self) -> Range { - let start = 0; - start..start + self.data_byte_len - } -} - -impl MinByteRange for RawBytesMarker { +impl<'a> MinByteRange for RawBytes<'a> { fn min_byte_range(&self) -> Range { 0..self.data_byte_range().end } @@ -1175,21 +1140,35 @@ impl MinByteRange for RawBytesMarker { impl<'a> FontRead<'a> for RawBytes<'a> { fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - let data_byte_len = cursor.remaining_bytes() / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN; - cursor.advance_by(data_byte_len); - cursor.finish(RawBytesMarker { data_byte_len }) + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) } } /// Used for the `state_array` and `entry_table` fields in [`StateHeader`]. -pub type RawBytes<'a> = TableRef<'a, RawBytesMarker>; +pub type RawBytes<'a> = TableRef<'a, RawBytesMarker, ()>; #[allow(clippy::needless_lifetimes)] impl<'a> RawBytes<'a> { + fn data_byte_len(&self, start: usize) -> usize { + let _ = start; + { + let remaining = self.data.len().saturating_sub(start); + remaining / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN + } + } + + pub fn data_byte_range(&self) -> Range { + let start = 0; + start..start + self.data_byte_len(start) + } + pub fn data(&self) -> &'a [u8] { - let range = self.shape.data_byte_range(); - self.data.read_array(range).unwrap() + let range = self.data_byte_range(); + unchecked::read_array(self.data, range) } } @@ -1217,9 +1196,29 @@ impl<'a> std::fmt::Debug for RawBytes<'a> { /// Header for an extended state table. #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct StxHeaderMarker {} +pub struct StxHeaderMarker; + +impl<'a> MinByteRange for StxHeader<'a> { + fn min_byte_range(&self) -> Range { + 0..self.entry_table_offset_byte_range().end + } +} -impl StxHeaderMarker { +impl<'a> FontRead<'a> for StxHeader<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// Header for an extended state table. +pub type StxHeader<'a> = TableRef<'a, StxHeaderMarker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> StxHeader<'a> { pub fn n_classes_byte_range(&self) -> Range { let start = 0; start..start + u32::RAW_BYTE_LEN @@ -1239,40 +1238,17 @@ impl StxHeaderMarker { let start = self.state_array_offset_byte_range().end; start..start + Offset32::RAW_BYTE_LEN } -} - -impl MinByteRange for StxHeaderMarker { - fn min_byte_range(&self) -> Range { - 0..self.entry_table_offset_byte_range().end - } -} - -impl<'a> FontRead<'a> for StxHeader<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.finish(StxHeaderMarker {}) - } -} - -/// Header for an extended state table. -pub type StxHeader<'a> = TableRef<'a, StxHeaderMarker>; -#[allow(clippy::needless_lifetimes)] -impl<'a> StxHeader<'a> { /// Number of classes, which is the number of 16-bit entry indices in a single line in the state array. pub fn n_classes(&self) -> u32 { - let range = self.shape.n_classes_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.n_classes_byte_range(); + unchecked::read_at(self.data, range.start) } /// Byte offset from the beginning of the state table to the class subtable. pub fn class_table_offset(&self) -> Offset32 { - let range = self.shape.class_table_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.class_table_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`class_table_offset`][Self::class_table_offset]. @@ -1283,8 +1259,8 @@ impl<'a> StxHeader<'a> { /// Byte offset from the beginning of the state table to the state array. pub fn state_array_offset(&self) -> Offset32 { - let range = self.shape.state_array_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.state_array_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`state_array_offset`][Self::state_array_offset]. @@ -1295,8 +1271,8 @@ impl<'a> StxHeader<'a> { /// Byte offset from the beginning of the state table to the entry subtable. pub fn entry_table_offset(&self) -> Offset32 { - let range = self.shape.entry_table_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.entry_table_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`entry_table_offset`][Self::entry_table_offset]. @@ -1342,18 +1318,9 @@ impl<'a> std::fmt::Debug for StxHeader<'a> { /// Used for the `state_array` in [`StxHeader`]. #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct RawWordsMarker { - data_byte_len: usize, -} +pub struct RawWordsMarker; -impl RawWordsMarker { - pub fn data_byte_range(&self) -> Range { - let start = 0; - start..start + self.data_byte_len - } -} - -impl MinByteRange for RawWordsMarker { +impl<'a> MinByteRange for RawWords<'a> { fn min_byte_range(&self) -> Range { 0..self.data_byte_range().end } @@ -1361,21 +1328,35 @@ impl MinByteRange for RawWordsMarker { impl<'a> FontRead<'a> for RawWords<'a> { fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - let data_byte_len = cursor.remaining_bytes() / u16::RAW_BYTE_LEN * u16::RAW_BYTE_LEN; - cursor.advance_by(data_byte_len); - cursor.finish(RawWordsMarker { data_byte_len }) + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) } } /// Used for the `state_array` in [`StxHeader`]. -pub type RawWords<'a> = TableRef<'a, RawWordsMarker>; +pub type RawWords<'a> = TableRef<'a, RawWordsMarker, ()>; #[allow(clippy::needless_lifetimes)] impl<'a> RawWords<'a> { + fn data_byte_len(&self, start: usize) -> usize { + let _ = start; + { + let remaining = self.data.len().saturating_sub(start); + remaining / u16::RAW_BYTE_LEN * u16::RAW_BYTE_LEN + } + } + + pub fn data_byte_range(&self) -> Range { + let start = 0; + start..start + self.data_byte_len(start) + } + pub fn data(&self) -> &'a [BigEndian] { - let range = self.shape.data_byte_range(); - self.data.read_array(range).unwrap() + let range = self.data_byte_range(); + unchecked::read_array(self.data, range) } } diff --git a/read-fonts/generated/generated_ankr.rs b/read-fonts/generated/generated_ankr.rs index 0a4b42b7f..4e2330ddd 100644 --- a/read-fonts/generated/generated_ankr.rs +++ b/read-fonts/generated/generated_ankr.rs @@ -8,9 +8,34 @@ use crate::codegen_prelude::*; /// The [anchor point](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6ankr.html) table. #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct AnkrMarker {} +pub struct AnkrMarker; -impl AnkrMarker { +impl<'a> MinByteRange for Ankr<'a> { + fn min_byte_range(&self) -> Range { + 0..self.glyph_data_table_offset_byte_range().end + } +} + +impl TopLevelTable for Ankr<'_> { + /// `ankr` + const TAG: Tag = Tag::new(b"ankr"); +} + +impl<'a> FontRead<'a> for Ankr<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// The [anchor point](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6ankr.html) table. +pub type Ankr<'a> = TableRef<'a, AnkrMarker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> Ankr<'a> { pub fn version_byte_range(&self) -> Range { let start = 0; start..start + u16::RAW_BYTE_LEN @@ -30,53 +55,25 @@ impl AnkrMarker { let start = self.lookup_table_offset_byte_range().end; start..start + u32::RAW_BYTE_LEN } -} - -impl MinByteRange for AnkrMarker { - fn min_byte_range(&self) -> Range { - 0..self.glyph_data_table_offset_byte_range().end - } -} - -impl TopLevelTable for Ankr<'_> { - /// `ankr` - const TAG: Tag = Tag::new(b"ankr"); -} - -impl<'a> FontRead<'a> for Ankr<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.finish(AnkrMarker {}) - } -} -/// The [anchor point](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6ankr.html) table. -pub type Ankr<'a> = TableRef<'a, AnkrMarker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> Ankr<'a> { /// Version number (set to zero). pub fn version(&self) -> u16 { - let range = self.shape.version_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.version_byte_range(); + unchecked::read_at(self.data, range.start) } /// Flags (currently unused; set to zero). pub fn flags(&self) -> u16 { - let range = self.shape.flags_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.flags_byte_range(); + unchecked::read_at(self.data, range.start) } /// Offset to the table's lookup table; currently this is always `0x0000000C`. /// /// Lookup values are two byte offsets into the glyph data table. pub fn lookup_table_offset(&self) -> Offset32 { - let range = self.shape.lookup_table_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.lookup_table_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`lookup_table_offset`][Self::lookup_table_offset]. @@ -87,8 +84,8 @@ impl<'a> Ankr<'a> { /// Offset to the glyph data table. pub fn glyph_data_table_offset(&self) -> u32 { - let range = self.shape.glyph_data_table_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.glyph_data_table_offset_byte_range(); + unchecked::read_at(self.data, range.start) } } @@ -124,23 +121,9 @@ impl<'a> std::fmt::Debug for Ankr<'a> { #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct GlyphDataEntryMarker { - anchor_points_byte_len: usize, -} +pub struct GlyphDataEntryMarker; -impl GlyphDataEntryMarker { - pub fn num_points_byte_range(&self) -> Range { - let start = 0; - start..start + u32::RAW_BYTE_LEN - } - - pub fn anchor_points_byte_range(&self) -> Range { - let start = self.num_points_byte_range().end; - start..start + self.anchor_points_byte_len - } -} - -impl MinByteRange for GlyphDataEntryMarker { +impl<'a> MinByteRange for GlyphDataEntry<'a> { fn min_byte_range(&self) -> Range { 0..self.anchor_points_byte_range().end } @@ -148,32 +131,45 @@ impl MinByteRange for GlyphDataEntryMarker { impl<'a> FontRead<'a> for GlyphDataEntry<'a> { fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - let num_points: u32 = cursor.read()?; - let anchor_points_byte_len = (num_points as usize) - .checked_mul(AnchorPoint::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(anchor_points_byte_len); - cursor.finish(GlyphDataEntryMarker { - anchor_points_byte_len, + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, }) } } -pub type GlyphDataEntry<'a> = TableRef<'a, GlyphDataEntryMarker>; +pub type GlyphDataEntry<'a> = TableRef<'a, GlyphDataEntryMarker, ()>; #[allow(clippy::needless_lifetimes)] impl<'a> GlyphDataEntry<'a> { + fn anchor_points_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.num_points()) as usize) + .checked_mul(AnchorPoint::RAW_BYTE_LEN) + .unwrap() + } + + pub fn num_points_byte_range(&self) -> Range { + let start = 0; + start..start + u32::RAW_BYTE_LEN + } + + pub fn anchor_points_byte_range(&self) -> Range { + let start = self.num_points_byte_range().end; + start..start + self.anchor_points_byte_len(start) + } + /// Number of anchor points for this glyph. pub fn num_points(&self) -> u32 { - let range = self.shape.num_points_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.num_points_byte_range(); + unchecked::read_at(self.data, range.start) } /// Individual anchor points. pub fn anchor_points(&self) -> &'a [AnchorPoint] { - let range = self.shape.anchor_points_byte_range(); - self.data.read_array(range).unwrap() + let range = self.anchor_points_byte_range(); + unchecked::read_array(self.data, range) } } diff --git a/read-fonts/generated/generated_avar.rs b/read-fonts/generated/generated_avar.rs index 8d1e74f3e..8e4347548 100644 --- a/read-fonts/generated/generated_avar.rs +++ b/read-fonts/generated/generated_avar.rs @@ -8,13 +8,43 @@ use crate::codegen_prelude::*; /// The [avar (Axis Variations)](https://docs.microsoft.com/en-us/typography/opentype/spec/avar) table #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct AvarMarker { - axis_segment_maps_byte_len: usize, - axis_index_map_offset_byte_start: Option, - var_store_offset_byte_start: Option, +pub struct AvarMarker; + +impl<'a> MinByteRange for Avar<'a> { + fn min_byte_range(&self) -> Range { + 0..self.axis_segment_maps_byte_range().end + } +} + +impl TopLevelTable for Avar<'_> { + /// `avar` + const TAG: Tag = Tag::new(b"avar"); } -impl AvarMarker { +impl<'a> FontRead<'a> for Avar<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// The [avar (Axis Variations)](https://docs.microsoft.com/en-us/typography/opentype/spec/avar) table +pub type Avar<'a> = TableRef<'a, AvarMarker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> Avar<'a> { + fn axis_segment_maps_byte_len(&self, start: usize) -> usize { + let _ = start; + { + let data = self.data.split_off(start).unwrap(); + ::total_len_for_count(data, (self.axis_count()) as usize) + .unwrap() + } + } + pub fn version_byte_range(&self) -> Range { let start = 0; start..start + MajorMinor::RAW_BYTE_LEN @@ -32,92 +62,53 @@ impl AvarMarker { pub fn axis_segment_maps_byte_range(&self) -> Range { let start = self.axis_count_byte_range().end; - start..start + self.axis_segment_maps_byte_len + start..start + self.axis_segment_maps_byte_len(start) } pub fn axis_index_map_offset_byte_range(&self) -> Option> { - let start = self.axis_index_map_offset_byte_start?; - Some(start..start + Offset32::RAW_BYTE_LEN) + if self.version().compatible((2u16, 0u16)) { + let start = self.axis_segment_maps_byte_range().end; + Some(start..start + Offset32::RAW_BYTE_LEN) + } else { + None + } } pub fn var_store_offset_byte_range(&self) -> Option> { - let start = self.var_store_offset_byte_start?; - Some(start..start + Offset32::RAW_BYTE_LEN) - } -} - -impl MinByteRange for AvarMarker { - fn min_byte_range(&self) -> Range { - 0..self.axis_segment_maps_byte_range().end - } -} - -impl TopLevelTable for Avar<'_> { - /// `avar` - const TAG: Tag = Tag::new(b"avar"); -} - -impl<'a> FontRead<'a> for Avar<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - let version: MajorMinor = cursor.read()?; - cursor.advance::(); - let axis_count: u16 = cursor.read()?; - let axis_segment_maps_byte_len = { - let data = cursor.remaining().ok_or(ReadError::OutOfBounds)?; - ::total_len_for_count(data, axis_count as usize)? - }; - cursor.advance_by(axis_segment_maps_byte_len); - let axis_index_map_offset_byte_start = version - .compatible((2u16, 0u16)) - .then(|| cursor.position()) - .transpose()?; - version - .compatible((2u16, 0u16)) - .then(|| cursor.advance::()); - let var_store_offset_byte_start = version - .compatible((2u16, 0u16)) - .then(|| cursor.position()) - .transpose()?; - version - .compatible((2u16, 0u16)) - .then(|| cursor.advance::()); - cursor.finish(AvarMarker { - axis_segment_maps_byte_len, - axis_index_map_offset_byte_start, - var_store_offset_byte_start, - }) + if self.version().compatible((2u16, 0u16)) { + let start = self + .axis_index_map_offset_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| self.axis_segment_maps_byte_range().end); + Some(start..start + Offset32::RAW_BYTE_LEN) + } else { + None + } } -} - -/// The [avar (Axis Variations)](https://docs.microsoft.com/en-us/typography/opentype/spec/avar) table -pub type Avar<'a> = TableRef<'a, AvarMarker>; -#[allow(clippy::needless_lifetimes)] -impl<'a> Avar<'a> { /// Major version number of the axis variations table — set to 1 or 2. /// Minor version number of the axis variations table — set to 0. pub fn version(&self) -> MajorMinor { - let range = self.shape.version_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.version_byte_range(); + unchecked::read_at(self.data, range.start) } /// The number of variation axes for this font. This must be the same number as axisCount in the 'fvar' table. pub fn axis_count(&self) -> u16 { - let range = self.shape.axis_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.axis_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// The segment maps array — one segment map for each axis, in the order of axes specified in the 'fvar' table. pub fn axis_segment_maps(&self) -> VarLenArray<'a, SegmentMaps<'a>> { - let range = self.shape.axis_segment_maps_byte_range(); - VarLenArray::read(self.data.split_off(range.start).unwrap()).unwrap() + let range = self.axis_segment_maps_byte_range(); + VarLenArray::read(unchecked::split_off(self.data, range.start)).unwrap() } /// Offset to DeltaSetIndexMap table (may be NULL). pub fn axis_index_map_offset(&self) -> Option> { - let range = self.shape.axis_index_map_offset_byte_range()?; - Some(self.data.read_at(range.start).unwrap()) + let range = self.axis_index_map_offset_byte_range()?; + Some(unchecked::read_at(self.data, range.start)) } /// Attempt to resolve [`axis_index_map_offset`][Self::axis_index_map_offset]. @@ -128,8 +119,8 @@ impl<'a> Avar<'a> { /// Offset to ItemVariationStore (may be NULL). pub fn var_store_offset(&self) -> Option> { - let range = self.shape.var_store_offset_byte_range()?; - Some(self.data.read_at(range.start).unwrap()) + let range = self.var_store_offset_byte_range()?; + Some(unchecked::read_at(self.data, range.start)) } /// Attempt to resolve [`var_store_offset`][Self::var_store_offset]. diff --git a/read-fonts/generated/generated_base.rs b/read-fonts/generated/generated_base.rs index 4149390e2..3385fb25b 100644 --- a/read-fonts/generated/generated_base.rs +++ b/read-fonts/generated/generated_base.rs @@ -8,33 +8,9 @@ use crate::codegen_prelude::*; /// The [BASE](https://learn.microsoft.com/en-us/typography/opentype/spec/base) (Baseline) table #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct BaseMarker { - item_var_store_offset_byte_start: Option, -} - -impl BaseMarker { - pub fn version_byte_range(&self) -> Range { - let start = 0; - start..start + MajorMinor::RAW_BYTE_LEN - } - - pub fn horiz_axis_offset_byte_range(&self) -> Range { - let start = self.version_byte_range().end; - start..start + Offset16::RAW_BYTE_LEN - } - - pub fn vert_axis_offset_byte_range(&self) -> Range { - let start = self.horiz_axis_offset_byte_range().end; - start..start + Offset16::RAW_BYTE_LEN - } - - pub fn item_var_store_offset_byte_range(&self) -> Option> { - let start = self.item_var_store_offset_byte_start?; - Some(start..start + Offset32::RAW_BYTE_LEN) - } -} +pub struct BaseMarker; -impl MinByteRange for BaseMarker { +impl<'a> MinByteRange for Base<'a> { fn min_byte_range(&self) -> Range { 0..self.vert_axis_offset_byte_range().end } @@ -47,38 +23,53 @@ impl TopLevelTable for Base<'_> { impl<'a> FontRead<'a> for Base<'a> { fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - let version: MajorMinor = cursor.read()?; - cursor.advance::(); - cursor.advance::(); - let item_var_store_offset_byte_start = version - .compatible((1u16, 1u16)) - .then(|| cursor.position()) - .transpose()?; - version - .compatible((1u16, 1u16)) - .then(|| cursor.advance::()); - cursor.finish(BaseMarker { - item_var_store_offset_byte_start, + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, }) } } /// The [BASE](https://learn.microsoft.com/en-us/typography/opentype/spec/base) (Baseline) table -pub type Base<'a> = TableRef<'a, BaseMarker>; +pub type Base<'a> = TableRef<'a, BaseMarker, ()>; #[allow(clippy::needless_lifetimes)] impl<'a> Base<'a> { + pub fn version_byte_range(&self) -> Range { + let start = 0; + start..start + MajorMinor::RAW_BYTE_LEN + } + + pub fn horiz_axis_offset_byte_range(&self) -> Range { + let start = self.version_byte_range().end; + start..start + Offset16::RAW_BYTE_LEN + } + + pub fn vert_axis_offset_byte_range(&self) -> Range { + let start = self.horiz_axis_offset_byte_range().end; + start..start + Offset16::RAW_BYTE_LEN + } + + pub fn item_var_store_offset_byte_range(&self) -> Option> { + if self.version().compatible((1u16, 1u16)) { + let start = self.vert_axis_offset_byte_range().end; + Some(start..start + Offset32::RAW_BYTE_LEN) + } else { + None + } + } + /// (major, minor) Version for the BASE table (1,0) or (1,1) pub fn version(&self) -> MajorMinor { - let range = self.shape.version_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.version_byte_range(); + unchecked::read_at(self.data, range.start) } /// Offset to horizontal Axis table, from beginning of BASE table (may be NULL) pub fn horiz_axis_offset(&self) -> Nullable { - let range = self.shape.horiz_axis_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.horiz_axis_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`horiz_axis_offset`][Self::horiz_axis_offset]. @@ -89,8 +80,8 @@ impl<'a> Base<'a> { /// Offset to vertical Axis table, from beginning of BASE table (may be NULL) pub fn vert_axis_offset(&self) -> Nullable { - let range = self.shape.vert_axis_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.vert_axis_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`vert_axis_offset`][Self::vert_axis_offset]. @@ -101,8 +92,8 @@ impl<'a> Base<'a> { /// Offset to Item Variation Store table, from beginning of BASE table (may be null) pub fn item_var_store_offset(&self) -> Option> { - let range = self.shape.item_var_store_offset_byte_range()?; - Some(self.data.read_at(range.start).unwrap()) + let range = self.item_var_store_offset_byte_range()?; + Some(unchecked::read_at(self.data, range.start)) } /// Attempt to resolve [`item_var_store_offset`][Self::item_var_store_offset]. @@ -149,21 +140,9 @@ impl<'a> std::fmt::Debug for Base<'a> { /// [Axis Table](https://learn.microsoft.com/en-us/typography/opentype/spec/base#axis-tables-horizaxis-and-vertaxis) #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct AxisMarker {} - -impl AxisMarker { - pub fn base_tag_list_offset_byte_range(&self) -> Range { - let start = 0; - start..start + Offset16::RAW_BYTE_LEN - } +pub struct AxisMarker; - pub fn base_script_list_offset_byte_range(&self) -> Range { - let start = self.base_tag_list_offset_byte_range().end; - start..start + Offset16::RAW_BYTE_LEN - } -} - -impl MinByteRange for AxisMarker { +impl<'a> MinByteRange for Axis<'a> { fn min_byte_range(&self) -> Range { 0..self.base_script_list_offset_byte_range().end } @@ -171,23 +150,34 @@ impl MinByteRange for AxisMarker { impl<'a> FontRead<'a> for Axis<'a> { fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.finish(AxisMarker {}) + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) } } /// [Axis Table](https://learn.microsoft.com/en-us/typography/opentype/spec/base#axis-tables-horizaxis-and-vertaxis) -pub type Axis<'a> = TableRef<'a, AxisMarker>; +pub type Axis<'a> = TableRef<'a, AxisMarker, ()>; #[allow(clippy::needless_lifetimes)] impl<'a> Axis<'a> { + pub fn base_tag_list_offset_byte_range(&self) -> Range { + let start = 0; + start..start + Offset16::RAW_BYTE_LEN + } + + pub fn base_script_list_offset_byte_range(&self) -> Range { + let start = self.base_tag_list_offset_byte_range().end; + start..start + Offset16::RAW_BYTE_LEN + } + /// Offset to BaseTagList table, from beginning of Axis table (may /// be NULL) pub fn base_tag_list_offset(&self) -> Nullable { - let range = self.shape.base_tag_list_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.base_tag_list_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`base_tag_list_offset`][Self::base_tag_list_offset]. @@ -198,8 +188,8 @@ impl<'a> Axis<'a> { /// Offset to BaseScriptList table, from beginning of Axis table pub fn base_script_list_offset(&self) -> Offset16 { - let range = self.shape.base_script_list_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.base_script_list_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`base_script_list_offset`][Self::base_script_list_offset]. @@ -240,23 +230,9 @@ impl<'a> std::fmt::Debug for Axis<'a> { /// [BaseTagList Table](https://learn.microsoft.com/en-us/typography/opentype/spec/base#basetaglist-table) #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct BaseTagListMarker { - baseline_tags_byte_len: usize, -} +pub struct BaseTagListMarker; -impl BaseTagListMarker { - pub fn base_tag_count_byte_range(&self) -> Range { - let start = 0; - start..start + u16::RAW_BYTE_LEN - } - - pub fn baseline_tags_byte_range(&self) -> Range { - let start = self.base_tag_count_byte_range().end; - start..start + self.baseline_tags_byte_len - } -} - -impl MinByteRange for BaseTagListMarker { +impl<'a> MinByteRange for BaseTagList<'a> { fn min_byte_range(&self) -> Range { 0..self.baseline_tags_byte_range().end } @@ -264,35 +240,48 @@ impl MinByteRange for BaseTagListMarker { impl<'a> FontRead<'a> for BaseTagList<'a> { fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - let base_tag_count: u16 = cursor.read()?; - let baseline_tags_byte_len = (base_tag_count as usize) - .checked_mul(Tag::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(baseline_tags_byte_len); - cursor.finish(BaseTagListMarker { - baseline_tags_byte_len, + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, }) } } /// [BaseTagList Table](https://learn.microsoft.com/en-us/typography/opentype/spec/base#basetaglist-table) -pub type BaseTagList<'a> = TableRef<'a, BaseTagListMarker>; +pub type BaseTagList<'a> = TableRef<'a, BaseTagListMarker, ()>; #[allow(clippy::needless_lifetimes)] impl<'a> BaseTagList<'a> { + fn baseline_tags_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.base_tag_count()) as usize) + .checked_mul(Tag::RAW_BYTE_LEN) + .unwrap() + } + + pub fn base_tag_count_byte_range(&self) -> Range { + let start = 0; + start..start + u16::RAW_BYTE_LEN + } + + pub fn baseline_tags_byte_range(&self) -> Range { + let start = self.base_tag_count_byte_range().end; + start..start + self.baseline_tags_byte_len(start) + } + /// Number of baseline identification tags in this text direction /// — may be zero (0) pub fn base_tag_count(&self) -> u16 { - let range = self.shape.base_tag_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.base_tag_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Array of 4-byte baseline identification tags — must be in /// alphabetical order pub fn baseline_tags(&self) -> &'a [BigEndian] { - let range = self.shape.baseline_tags_byte_range(); - self.data.read_array(range).unwrap() + let range = self.baseline_tags_byte_range(); + unchecked::read_array(self.data, range) } } @@ -321,23 +310,9 @@ impl<'a> std::fmt::Debug for BaseTagList<'a> { /// [BaseScriptList Table](https://learn.microsoft.com/en-us/typography/opentype/spec/base#basescriptlist-table) #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct BaseScriptListMarker { - base_script_records_byte_len: usize, -} - -impl BaseScriptListMarker { - pub fn base_script_count_byte_range(&self) -> Range { - let start = 0; - start..start + u16::RAW_BYTE_LEN - } - - pub fn base_script_records_byte_range(&self) -> Range { - let start = self.base_script_count_byte_range().end; - start..start + self.base_script_records_byte_len - } -} +pub struct BaseScriptListMarker; -impl MinByteRange for BaseScriptListMarker { +impl<'a> MinByteRange for BaseScriptList<'a> { fn min_byte_range(&self) -> Range { 0..self.base_script_records_byte_range().end } @@ -345,34 +320,47 @@ impl MinByteRange for BaseScriptListMarker { impl<'a> FontRead<'a> for BaseScriptList<'a> { fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - let base_script_count: u16 = cursor.read()?; - let base_script_records_byte_len = (base_script_count as usize) - .checked_mul(BaseScriptRecord::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(base_script_records_byte_len); - cursor.finish(BaseScriptListMarker { - base_script_records_byte_len, + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, }) } } /// [BaseScriptList Table](https://learn.microsoft.com/en-us/typography/opentype/spec/base#basescriptlist-table) -pub type BaseScriptList<'a> = TableRef<'a, BaseScriptListMarker>; +pub type BaseScriptList<'a> = TableRef<'a, BaseScriptListMarker, ()>; #[allow(clippy::needless_lifetimes)] impl<'a> BaseScriptList<'a> { + fn base_script_records_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.base_script_count()) as usize) + .checked_mul(BaseScriptRecord::RAW_BYTE_LEN) + .unwrap() + } + + pub fn base_script_count_byte_range(&self) -> Range { + let start = 0; + start..start + u16::RAW_BYTE_LEN + } + + pub fn base_script_records_byte_range(&self) -> Range { + let start = self.base_script_count_byte_range().end; + start..start + self.base_script_records_byte_len(start) + } + /// Number of BaseScriptRecords defined pub fn base_script_count(&self) -> u16 { - let range = self.shape.base_script_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.base_script_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Array of BaseScriptRecords, in alphabetical order by /// baseScriptTag pub fn base_script_records(&self) -> &'a [BaseScriptRecord] { - let range = self.shape.base_script_records_byte_range(); - self.data.read_array(range).unwrap() + let range = self.base_script_records_byte_range(); + unchecked::read_array(self.data, range) } } @@ -461,11 +449,36 @@ impl<'a> SomeRecord<'a> for BaseScriptRecord { /// [BaseScript Table](https://learn.microsoft.com/en-us/typography/opentype/spec/base#basescript-table) #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct BaseScriptMarker { - base_lang_sys_records_byte_len: usize, +pub struct BaseScriptMarker; + +impl<'a> MinByteRange for BaseScript<'a> { + fn min_byte_range(&self) -> Range { + 0..self.base_lang_sys_records_byte_range().end + } +} + +impl<'a> FontRead<'a> for BaseScript<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } } -impl BaseScriptMarker { +/// [BaseScript Table](https://learn.microsoft.com/en-us/typography/opentype/spec/base#basescript-table) +pub type BaseScript<'a> = TableRef<'a, BaseScriptMarker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> BaseScript<'a> { + fn base_lang_sys_records_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.base_lang_sys_count()) as usize) + .checked_mul(BaseLangSysRecord::RAW_BYTE_LEN) + .unwrap() + } + pub fn base_values_offset_byte_range(&self) -> Range { let start = 0; start..start + Offset16::RAW_BYTE_LEN @@ -483,41 +496,13 @@ impl BaseScriptMarker { pub fn base_lang_sys_records_byte_range(&self) -> Range { let start = self.base_lang_sys_count_byte_range().end; - start..start + self.base_lang_sys_records_byte_len - } -} - -impl MinByteRange for BaseScriptMarker { - fn min_byte_range(&self) -> Range { - 0..self.base_lang_sys_records_byte_range().end + start..start + self.base_lang_sys_records_byte_len(start) } -} -impl<'a> FontRead<'a> for BaseScript<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - let base_lang_sys_count: u16 = cursor.read()?; - let base_lang_sys_records_byte_len = (base_lang_sys_count as usize) - .checked_mul(BaseLangSysRecord::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(base_lang_sys_records_byte_len); - cursor.finish(BaseScriptMarker { - base_lang_sys_records_byte_len, - }) - } -} - -/// [BaseScript Table](https://learn.microsoft.com/en-us/typography/opentype/spec/base#basescript-table) -pub type BaseScript<'a> = TableRef<'a, BaseScriptMarker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> BaseScript<'a> { /// Offset to BaseValues table, from beginning of BaseScript table (may be NULL) pub fn base_values_offset(&self) -> Nullable { - let range = self.shape.base_values_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.base_values_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`base_values_offset`][Self::base_values_offset]. @@ -528,8 +513,8 @@ impl<'a> BaseScript<'a> { /// Offset to MinMax table, from beginning of BaseScript table (may be NULL) pub fn default_min_max_offset(&self) -> Nullable { - let range = self.shape.default_min_max_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.default_min_max_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`default_min_max_offset`][Self::default_min_max_offset]. @@ -540,15 +525,15 @@ impl<'a> BaseScript<'a> { /// Number of BaseLangSysRecords defined — may be zero (0) pub fn base_lang_sys_count(&self) -> u16 { - let range = self.shape.base_lang_sys_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.base_lang_sys_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Array of BaseLangSysRecords, in alphabetical order by /// BaseLangSysTag pub fn base_lang_sys_records(&self) -> &'a [BaseLangSysRecord] { - let range = self.shape.base_lang_sys_records_byte_range(); - self.data.read_array(range).unwrap() + let range = self.base_lang_sys_records_byte_range(); + unchecked::read_array(self.data, range) } } @@ -648,28 +633,9 @@ impl<'a> SomeRecord<'a> for BaseLangSysRecord { /// [BaseValues](https://learn.microsoft.com/en-us/typography/opentype/spec/base#basevalues-table) table #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct BaseValuesMarker { - base_coord_offsets_byte_len: usize, -} +pub struct BaseValuesMarker; -impl BaseValuesMarker { - pub fn default_baseline_index_byte_range(&self) -> Range { - let start = 0; - start..start + u16::RAW_BYTE_LEN - } - - pub fn base_coord_count_byte_range(&self) -> Range { - let start = self.default_baseline_index_byte_range().end; - start..start + u16::RAW_BYTE_LEN - } - - pub fn base_coord_offsets_byte_range(&self) -> Range { - let start = self.base_coord_count_byte_range().end; - start..start + self.base_coord_offsets_byte_len - } -} - -impl MinByteRange for BaseValuesMarker { +impl<'a> MinByteRange for BaseValues<'a> { fn min_byte_range(&self) -> Range { 0..self.base_coord_offsets_byte_range().end } @@ -677,45 +643,62 @@ impl MinByteRange for BaseValuesMarker { impl<'a> FontRead<'a> for BaseValues<'a> { fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - let base_coord_count: u16 = cursor.read()?; - let base_coord_offsets_byte_len = (base_coord_count as usize) - .checked_mul(Offset16::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(base_coord_offsets_byte_len); - cursor.finish(BaseValuesMarker { - base_coord_offsets_byte_len, + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, }) } } /// [BaseValues](https://learn.microsoft.com/en-us/typography/opentype/spec/base#basevalues-table) table -pub type BaseValues<'a> = TableRef<'a, BaseValuesMarker>; +pub type BaseValues<'a> = TableRef<'a, BaseValuesMarker, ()>; #[allow(clippy::needless_lifetimes)] impl<'a> BaseValues<'a> { + fn base_coord_offsets_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.base_coord_count()) as usize) + .checked_mul(Offset16::RAW_BYTE_LEN) + .unwrap() + } + + pub fn default_baseline_index_byte_range(&self) -> Range { + let start = 0; + start..start + u16::RAW_BYTE_LEN + } + + pub fn base_coord_count_byte_range(&self) -> Range { + let start = self.default_baseline_index_byte_range().end; + start..start + u16::RAW_BYTE_LEN + } + + pub fn base_coord_offsets_byte_range(&self) -> Range { + let start = self.base_coord_count_byte_range().end; + start..start + self.base_coord_offsets_byte_len(start) + } + /// Index number of default baseline for this script — equals /// index position of baseline tag in baselineTags array of the /// BaseTagList pub fn default_baseline_index(&self) -> u16 { - let range = self.shape.default_baseline_index_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.default_baseline_index_byte_range(); + unchecked::read_at(self.data, range.start) } /// Number of BaseCoord tables defined — should equal /// baseTagCount in the BaseTagList pub fn base_coord_count(&self) -> u16 { - let range = self.shape.base_coord_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.base_coord_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Array of offsets to BaseCoord tables, from beginning of /// BaseValues table — order matches baselineTags array in the /// BaseTagList pub fn base_coord_offsets(&self) -> &'a [BigEndian] { - let range = self.shape.base_coord_offsets_byte_range(); - self.data.read_array(range).unwrap() + let range = self.base_coord_offsets_byte_range(); + unchecked::read_array(self.data, range) } /// A dynamically resolving wrapper for [`base_coord_offsets`][Self::base_coord_offsets]. @@ -768,11 +751,36 @@ impl<'a> std::fmt::Debug for BaseValues<'a> { /// [MinMax](https://learn.microsoft.com/en-us/typography/opentype/spec/base#minmax-table) table #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct MinMaxMarker { - feat_min_max_records_byte_len: usize, +pub struct MinMaxMarker; + +impl<'a> MinByteRange for MinMax<'a> { + fn min_byte_range(&self) -> Range { + 0..self.feat_min_max_records_byte_range().end + } +} + +impl<'a> FontRead<'a> for MinMax<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } } -impl MinMaxMarker { +/// [MinMax](https://learn.microsoft.com/en-us/typography/opentype/spec/base#minmax-table) table +pub type MinMax<'a> = TableRef<'a, MinMaxMarker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> MinMax<'a> { + fn feat_min_max_records_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.feat_min_max_count()) as usize) + .checked_mul(FeatMinMaxRecord::RAW_BYTE_LEN) + .unwrap() + } + pub fn min_coord_offset_byte_range(&self) -> Range { let start = 0; start..start + Offset16::RAW_BYTE_LEN @@ -790,42 +798,14 @@ impl MinMaxMarker { pub fn feat_min_max_records_byte_range(&self) -> Range { let start = self.feat_min_max_count_byte_range().end; - start..start + self.feat_min_max_records_byte_len - } -} - -impl MinByteRange for MinMaxMarker { - fn min_byte_range(&self) -> Range { - 0..self.feat_min_max_records_byte_range().end - } -} - -impl<'a> FontRead<'a> for MinMax<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - let feat_min_max_count: u16 = cursor.read()?; - let feat_min_max_records_byte_len = (feat_min_max_count as usize) - .checked_mul(FeatMinMaxRecord::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(feat_min_max_records_byte_len); - cursor.finish(MinMaxMarker { - feat_min_max_records_byte_len, - }) + start..start + self.feat_min_max_records_byte_len(start) } -} -/// [MinMax](https://learn.microsoft.com/en-us/typography/opentype/spec/base#minmax-table) table -pub type MinMax<'a> = TableRef<'a, MinMaxMarker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> MinMax<'a> { /// Offset to BaseCoord table that defines the minimum extent /// value, from the beginning of MinMax table (may be NULL) pub fn min_coord_offset(&self) -> Nullable { - let range = self.shape.min_coord_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.min_coord_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`min_coord_offset`][Self::min_coord_offset]. @@ -837,8 +817,8 @@ impl<'a> MinMax<'a> { /// Offset to BaseCoord table that defines maximum extent value, /// from the beginning of MinMax table (may be NULL) pub fn max_coord_offset(&self) -> Nullable { - let range = self.shape.max_coord_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.max_coord_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`max_coord_offset`][Self::max_coord_offset]. @@ -849,15 +829,15 @@ impl<'a> MinMax<'a> { /// Number of FeatMinMaxRecords — may be zero (0) pub fn feat_min_max_count(&self) -> u16 { - let range = self.shape.feat_min_max_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.feat_min_max_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Array of FeatMinMaxRecords, in alphabetical order by /// featureTableTag pub fn feat_min_max_records(&self) -> &'a [FeatMinMaxRecord] { - let range = self.shape.feat_min_max_records_byte_range(); - self.data.read_array(range).unwrap() + let range = self.feat_min_max_records_byte_range(); + unchecked::read_array(self.data, range) } } @@ -1071,21 +1051,9 @@ impl Format for BaseCoordFormat1Marker { /// [BaseCoordFormat1](https://learn.microsoft.com/en-us/typography/opentype/spec/base#basecoord-format-1) #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct BaseCoordFormat1Marker {} +pub struct BaseCoordFormat1Marker; -impl BaseCoordFormat1Marker { - pub fn base_coord_format_byte_range(&self) -> Range { - let start = 0; - start..start + u16::RAW_BYTE_LEN - } - - pub fn coordinate_byte_range(&self) -> Range { - let start = self.base_coord_format_byte_range().end; - start..start + i16::RAW_BYTE_LEN - } -} - -impl MinByteRange for BaseCoordFormat1Marker { +impl<'a> MinByteRange for BaseCoordFormat1<'a> { fn min_byte_range(&self) -> Range { 0..self.coordinate_byte_range().end } @@ -1093,28 +1061,39 @@ impl MinByteRange for BaseCoordFormat1Marker { impl<'a> FontRead<'a> for BaseCoordFormat1<'a> { fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.finish(BaseCoordFormat1Marker {}) + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) } } /// [BaseCoordFormat1](https://learn.microsoft.com/en-us/typography/opentype/spec/base#basecoord-format-1) -pub type BaseCoordFormat1<'a> = TableRef<'a, BaseCoordFormat1Marker>; +pub type BaseCoordFormat1<'a> = TableRef<'a, BaseCoordFormat1Marker, ()>; #[allow(clippy::needless_lifetimes)] impl<'a> BaseCoordFormat1<'a> { + pub fn base_coord_format_byte_range(&self) -> Range { + let start = 0; + start..start + u16::RAW_BYTE_LEN + } + + pub fn coordinate_byte_range(&self) -> Range { + let start = self.base_coord_format_byte_range().end; + start..start + i16::RAW_BYTE_LEN + } + /// Format identifier — format = 1 pub fn base_coord_format(&self) -> u16 { - let range = self.shape.base_coord_format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.base_coord_format_byte_range(); + unchecked::read_at(self.data, range.start) } /// X or Y value, in design units pub fn coordinate(&self) -> i16 { - let range = self.shape.coordinate_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.coordinate_byte_range(); + unchecked::read_at(self.data, range.start) } } @@ -1147,9 +1126,29 @@ impl Format for BaseCoordFormat2Marker { /// [BaseCoordFormat2](https://learn.microsoft.com/en-us/typography/opentype/spec/base#basecoord-format-2) #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct BaseCoordFormat2Marker {} +pub struct BaseCoordFormat2Marker; + +impl<'a> MinByteRange for BaseCoordFormat2<'a> { + fn min_byte_range(&self) -> Range { + 0..self.base_coord_point_byte_range().end + } +} + +impl<'a> FontRead<'a> for BaseCoordFormat2<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// [BaseCoordFormat2](https://learn.microsoft.com/en-us/typography/opentype/spec/base#basecoord-format-2) +pub type BaseCoordFormat2<'a> = TableRef<'a, BaseCoordFormat2Marker, ()>; -impl BaseCoordFormat2Marker { +#[allow(clippy::needless_lifetimes)] +impl<'a> BaseCoordFormat2<'a> { pub fn base_coord_format_byte_range(&self) -> Range { let start = 0; start..start + u16::RAW_BYTE_LEN @@ -1169,52 +1168,29 @@ impl BaseCoordFormat2Marker { let start = self.reference_glyph_byte_range().end; start..start + u16::RAW_BYTE_LEN } -} -impl MinByteRange for BaseCoordFormat2Marker { - fn min_byte_range(&self) -> Range { - 0..self.base_coord_point_byte_range().end - } -} - -impl<'a> FontRead<'a> for BaseCoordFormat2<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.finish(BaseCoordFormat2Marker {}) - } -} - -/// [BaseCoordFormat2](https://learn.microsoft.com/en-us/typography/opentype/spec/base#basecoord-format-2) -pub type BaseCoordFormat2<'a> = TableRef<'a, BaseCoordFormat2Marker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> BaseCoordFormat2<'a> { /// Format identifier — format = 2 pub fn base_coord_format(&self) -> u16 { - let range = self.shape.base_coord_format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.base_coord_format_byte_range(); + unchecked::read_at(self.data, range.start) } /// X or Y value, in design units pub fn coordinate(&self) -> i16 { - let range = self.shape.coordinate_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.coordinate_byte_range(); + unchecked::read_at(self.data, range.start) } /// Glyph ID of control glyph pub fn reference_glyph(&self) -> u16 { - let range = self.shape.reference_glyph_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.reference_glyph_byte_range(); + unchecked::read_at(self.data, range.start) } /// Index of contour point on the reference glyph pub fn base_coord_point(&self) -> u16 { - let range = self.shape.base_coord_point_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.base_coord_point_byte_range(); + unchecked::read_at(self.data, range.start) } } @@ -1249,9 +1225,29 @@ impl Format for BaseCoordFormat3Marker { /// [BaseCoordFormat3](https://learn.microsoft.com/en-us/typography/opentype/spec/base#basecoord-format-3) #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct BaseCoordFormat3Marker {} +pub struct BaseCoordFormat3Marker; -impl BaseCoordFormat3Marker { +impl<'a> MinByteRange for BaseCoordFormat3<'a> { + fn min_byte_range(&self) -> Range { + 0..self.device_offset_byte_range().end + } +} + +impl<'a> FontRead<'a> for BaseCoordFormat3<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// [BaseCoordFormat3](https://learn.microsoft.com/en-us/typography/opentype/spec/base#basecoord-format-3) +pub type BaseCoordFormat3<'a> = TableRef<'a, BaseCoordFormat3Marker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> BaseCoordFormat3<'a> { pub fn base_coord_format_byte_range(&self) -> Range { let start = 0; start..start + u16::RAW_BYTE_LEN @@ -1266,47 +1262,25 @@ impl BaseCoordFormat3Marker { let start = self.coordinate_byte_range().end; start..start + Offset16::RAW_BYTE_LEN } -} - -impl MinByteRange for BaseCoordFormat3Marker { - fn min_byte_range(&self) -> Range { - 0..self.device_offset_byte_range().end - } -} - -impl<'a> FontRead<'a> for BaseCoordFormat3<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.finish(BaseCoordFormat3Marker {}) - } -} -/// [BaseCoordFormat3](https://learn.microsoft.com/en-us/typography/opentype/spec/base#basecoord-format-3) -pub type BaseCoordFormat3<'a> = TableRef<'a, BaseCoordFormat3Marker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> BaseCoordFormat3<'a> { /// Format identifier — format = 3 pub fn base_coord_format(&self) -> u16 { - let range = self.shape.base_coord_format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.base_coord_format_byte_range(); + unchecked::read_at(self.data, range.start) } /// X or Y value, in design units pub fn coordinate(&self) -> i16 { - let range = self.shape.coordinate_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.coordinate_byte_range(); + unchecked::read_at(self.data, range.start) } /// Offset to Device table (non-variable font) / Variation Index /// table (variable font) for X or Y value, from beginning of /// BaseCoord table (may be NULL). pub fn device_offset(&self) -> Nullable { - let range = self.shape.device_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.device_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`device_offset`][Self::device_offset]. diff --git a/read-fonts/generated/generated_bitmap.rs b/read-fonts/generated/generated_bitmap.rs index af2bac926..76a4e727d 100644 --- a/read-fonts/generated/generated_bitmap.rs +++ b/read-fonts/generated/generated_bitmap.rs @@ -742,18 +742,9 @@ impl<'a> SomeRecord<'a> for SmallGlyphMetrics { /// [IndexSubtableList](https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#indexsubtablelist) table. #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct IndexSubtableListMarker { - index_subtable_records_byte_len: usize, -} +pub struct IndexSubtableListMarker; -impl IndexSubtableListMarker { - pub fn index_subtable_records_byte_range(&self) -> Range { - let start = 0; - start..start + self.index_subtable_records_byte_len - } -} - -impl MinByteRange for IndexSubtableListMarker { +impl<'a> MinByteRange for IndexSubtableList<'a> { fn min_byte_range(&self) -> Range { 0..self.index_subtable_records_byte_range().end } @@ -765,14 +756,11 @@ impl ReadArgs for IndexSubtableList<'_> { impl<'a> FontReadWithArgs<'a> for IndexSubtableList<'a> { fn read_with_args(data: FontData<'a>, args: &u32) -> Result { - let number_of_index_subtables = *args; - let mut cursor = data.cursor(); - let index_subtable_records_byte_len = (number_of_index_subtables as usize) - .checked_mul(IndexSubtableRecord::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(index_subtable_records_byte_len); - cursor.finish(IndexSubtableListMarker { - index_subtable_records_byte_len, + let args = *args; + Ok(TableRef { + args, + data, + _marker: std::marker::PhantomData, }) } } @@ -789,14 +777,30 @@ impl<'a> IndexSubtableList<'a> { } /// [IndexSubtableList](https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#indexsubtablelist) table. -pub type IndexSubtableList<'a> = TableRef<'a, IndexSubtableListMarker>; +pub type IndexSubtableList<'a> = TableRef<'a, IndexSubtableListMarker, u32>; #[allow(clippy::needless_lifetimes)] impl<'a> IndexSubtableList<'a> { + fn index_subtable_records_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.args) as usize) + .checked_mul(IndexSubtableRecord::RAW_BYTE_LEN) + .unwrap() + } + + pub fn index_subtable_records_byte_range(&self) -> Range { + let start = 0; + start..start + self.index_subtable_records_byte_len(start) + } + /// Array of IndexSubtableRecords. pub fn index_subtable_records(&self) -> &'a [IndexSubtableRecord] { - let range = self.shape.index_subtable_records_byte_range(); - self.data.read_array(range).unwrap() + let range = self.index_subtable_records_byte_range(); + unchecked::read_array(self.data, range) + } + + pub(crate) fn number_of_index_subtables(&self) -> u32 { + self.args } } @@ -897,33 +901,9 @@ impl Format for IndexSubtable1Marker { /// [IndexSubTable1](https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#indexsubtable1-variable-metrics-glyphs-with-4-byte-offsets): variable-metrics glyphs with 4-byte offsets. #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct IndexSubtable1Marker { - sbit_offsets_byte_len: usize, -} - -impl IndexSubtable1Marker { - pub fn index_format_byte_range(&self) -> Range { - let start = 0; - start..start + u16::RAW_BYTE_LEN - } - - pub fn image_format_byte_range(&self) -> Range { - let start = self.index_format_byte_range().end; - start..start + u16::RAW_BYTE_LEN - } - - pub fn image_data_offset_byte_range(&self) -> Range { - let start = self.image_format_byte_range().end; - start..start + u32::RAW_BYTE_LEN - } - - pub fn sbit_offsets_byte_range(&self) -> Range { - let start = self.image_data_offset_byte_range().end; - start..start + self.sbit_offsets_byte_len - } -} +pub struct IndexSubtable1Marker; -impl MinByteRange for IndexSubtable1Marker { +impl<'a> MinByteRange for IndexSubtable1<'a> { fn min_byte_range(&self) -> Range { 0..self.sbit_offsets_byte_range().end } @@ -938,18 +918,11 @@ impl<'a> FontReadWithArgs<'a> for IndexSubtable1<'a> { data: FontData<'a>, args: &(GlyphId16, GlyphId16), ) -> Result { - let (last_glyph_index, first_glyph_index) = *args; - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - let sbit_offsets_byte_len = - (transforms::subtract_add_two(last_glyph_index, first_glyph_index)) - .checked_mul(u32::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(sbit_offsets_byte_len); - cursor.finish(IndexSubtable1Marker { - sbit_offsets_byte_len, + let args = *args; + Ok(TableRef { + args, + data, + _marker: std::marker::PhantomData, }) } } @@ -970,31 +943,66 @@ impl<'a> IndexSubtable1<'a> { } /// [IndexSubTable1](https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#indexsubtable1-variable-metrics-glyphs-with-4-byte-offsets): variable-metrics glyphs with 4-byte offsets. -pub type IndexSubtable1<'a> = TableRef<'a, IndexSubtable1Marker>; +pub type IndexSubtable1<'a> = TableRef<'a, IndexSubtable1Marker, (GlyphId16, GlyphId16)>; #[allow(clippy::needless_lifetimes)] impl<'a> IndexSubtable1<'a> { + fn sbit_offsets_byte_len(&self, start: usize) -> usize { + let _ = start; + (transforms::subtract_add_two(self.args.0, self.args.1)) + .checked_mul(u32::RAW_BYTE_LEN) + .unwrap() + } + + pub fn index_format_byte_range(&self) -> Range { + let start = 0; + start..start + u16::RAW_BYTE_LEN + } + + pub fn image_format_byte_range(&self) -> Range { + let start = self.index_format_byte_range().end; + start..start + u16::RAW_BYTE_LEN + } + + pub fn image_data_offset_byte_range(&self) -> Range { + let start = self.image_format_byte_range().end; + start..start + u32::RAW_BYTE_LEN + } + + pub fn sbit_offsets_byte_range(&self) -> Range { + let start = self.image_data_offset_byte_range().end; + start..start + self.sbit_offsets_byte_len(start) + } + /// Format of this IndexSubTable. pub fn index_format(&self) -> u16 { - let range = self.shape.index_format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.index_format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Format of EBDT image data. pub fn image_format(&self) -> u16 { - let range = self.shape.image_format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.image_format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Offset to image data in EBDT table. pub fn image_data_offset(&self) -> u32 { - let range = self.shape.image_data_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.image_data_offset_byte_range(); + unchecked::read_at(self.data, range.start) } pub fn sbit_offsets(&self) -> &'a [BigEndian] { - let range = self.shape.sbit_offsets_byte_range(); - self.data.read_array(range).unwrap() + let range = self.sbit_offsets_byte_range(); + unchecked::read_array(self.data, range) + } + + pub(crate) fn last_glyph_index(&self) -> GlyphId16 { + self.args.0 + } + + pub(crate) fn first_glyph_index(&self) -> GlyphId16 { + self.args.1 } } @@ -1029,11 +1037,34 @@ impl Format for IndexSubtable2Marker { /// [IndexSubTable2](https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#indexsubtable2-all-glyphs-have-identical-metrics): all glyphs have identical metrics. #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct IndexSubtable2Marker { - big_metrics_byte_len: usize, +pub struct IndexSubtable2Marker; + +impl<'a> MinByteRange for IndexSubtable2<'a> { + fn min_byte_range(&self) -> Range { + 0..self.big_metrics_byte_range().end + } } -impl IndexSubtable2Marker { +impl<'a> FontRead<'a> for IndexSubtable2<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// [IndexSubTable2](https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#indexsubtable2-all-glyphs-have-identical-metrics): all glyphs have identical metrics. +pub type IndexSubtable2<'a> = TableRef<'a, IndexSubtable2Marker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> IndexSubtable2<'a> { + fn big_metrics_byte_len(&self, start: usize) -> usize { + let _ = start; + BigGlyphMetrics::RAW_BYTE_LEN + } + pub fn index_format_byte_range(&self) -> Range { let start = 0; start..start + u16::RAW_BYTE_LEN @@ -1056,64 +1087,37 @@ impl IndexSubtable2Marker { pub fn big_metrics_byte_range(&self) -> Range { let start = self.image_size_byte_range().end; - start..start + self.big_metrics_byte_len + start..start + self.big_metrics_byte_len(start) } -} - -impl MinByteRange for IndexSubtable2Marker { - fn min_byte_range(&self) -> Range { - 0..self.big_metrics_byte_range().end - } -} - -impl<'a> FontRead<'a> for IndexSubtable2<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - let big_metrics_byte_len = BigGlyphMetrics::RAW_BYTE_LEN; - cursor.advance_by(big_metrics_byte_len); - cursor.finish(IndexSubtable2Marker { - big_metrics_byte_len, - }) - } -} - -/// [IndexSubTable2](https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#indexsubtable2-all-glyphs-have-identical-metrics): all glyphs have identical metrics. -pub type IndexSubtable2<'a> = TableRef<'a, IndexSubtable2Marker>; -#[allow(clippy::needless_lifetimes)] -impl<'a> IndexSubtable2<'a> { /// Format of this IndexSubTable. pub fn index_format(&self) -> u16 { - let range = self.shape.index_format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.index_format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Format of EBDT image data. pub fn image_format(&self) -> u16 { - let range = self.shape.image_format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.image_format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Offset to image data in EBDT table. pub fn image_data_offset(&self) -> u32 { - let range = self.shape.image_data_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.image_data_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// All the glyphs are of the same size. pub fn image_size(&self) -> u32 { - let range = self.shape.image_size_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.image_size_byte_range(); + unchecked::read_at(self.data, range.start) } /// All glyphs have the same metrics; glyph data may be compressed, byte-aligned, or bit-aligned. pub fn big_metrics(&self) -> &'a [BigGlyphMetrics] { - let range = self.shape.big_metrics_byte_range(); - self.data.read_array(range).unwrap() + let range = self.big_metrics_byte_range(); + unchecked::read_array(self.data, range) } } @@ -1156,33 +1160,9 @@ impl Format for IndexSubtable3Marker { /// [IndexSubTable3](https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#indexsubtable3-variable-metrics-glyphs-with-2-byte-offsets): variable-metrics glyphs with 2-byte offsets. #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct IndexSubtable3Marker { - sbit_offsets_byte_len: usize, -} - -impl IndexSubtable3Marker { - pub fn index_format_byte_range(&self) -> Range { - let start = 0; - start..start + u16::RAW_BYTE_LEN - } - - pub fn image_format_byte_range(&self) -> Range { - let start = self.index_format_byte_range().end; - start..start + u16::RAW_BYTE_LEN - } +pub struct IndexSubtable3Marker; - pub fn image_data_offset_byte_range(&self) -> Range { - let start = self.image_format_byte_range().end; - start..start + u32::RAW_BYTE_LEN - } - - pub fn sbit_offsets_byte_range(&self) -> Range { - let start = self.image_data_offset_byte_range().end; - start..start + self.sbit_offsets_byte_len - } -} - -impl MinByteRange for IndexSubtable3Marker { +impl<'a> MinByteRange for IndexSubtable3<'a> { fn min_byte_range(&self) -> Range { 0..self.sbit_offsets_byte_range().end } @@ -1197,18 +1177,11 @@ impl<'a> FontReadWithArgs<'a> for IndexSubtable3<'a> { data: FontData<'a>, args: &(GlyphId16, GlyphId16), ) -> Result { - let (last_glyph_index, first_glyph_index) = *args; - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - let sbit_offsets_byte_len = - (transforms::subtract_add_two(last_glyph_index, first_glyph_index)) - .checked_mul(u16::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(sbit_offsets_byte_len); - cursor.finish(IndexSubtable3Marker { - sbit_offsets_byte_len, + let args = *args; + Ok(TableRef { + args, + data, + _marker: std::marker::PhantomData, }) } } @@ -1229,31 +1202,66 @@ impl<'a> IndexSubtable3<'a> { } /// [IndexSubTable3](https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#indexsubtable3-variable-metrics-glyphs-with-2-byte-offsets): variable-metrics glyphs with 2-byte offsets. -pub type IndexSubtable3<'a> = TableRef<'a, IndexSubtable3Marker>; +pub type IndexSubtable3<'a> = TableRef<'a, IndexSubtable3Marker, (GlyphId16, GlyphId16)>; #[allow(clippy::needless_lifetimes)] impl<'a> IndexSubtable3<'a> { + fn sbit_offsets_byte_len(&self, start: usize) -> usize { + let _ = start; + (transforms::subtract_add_two(self.args.0, self.args.1)) + .checked_mul(u16::RAW_BYTE_LEN) + .unwrap() + } + + pub fn index_format_byte_range(&self) -> Range { + let start = 0; + start..start + u16::RAW_BYTE_LEN + } + + pub fn image_format_byte_range(&self) -> Range { + let start = self.index_format_byte_range().end; + start..start + u16::RAW_BYTE_LEN + } + + pub fn image_data_offset_byte_range(&self) -> Range { + let start = self.image_format_byte_range().end; + start..start + u32::RAW_BYTE_LEN + } + + pub fn sbit_offsets_byte_range(&self) -> Range { + let start = self.image_data_offset_byte_range().end; + start..start + self.sbit_offsets_byte_len(start) + } + /// Format of this IndexSubTable. pub fn index_format(&self) -> u16 { - let range = self.shape.index_format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.index_format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Format of EBDT image data. pub fn image_format(&self) -> u16 { - let range = self.shape.image_format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.image_format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Offset to image data in EBDT table. pub fn image_data_offset(&self) -> u32 { - let range = self.shape.image_data_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.image_data_offset_byte_range(); + unchecked::read_at(self.data, range.start) } pub fn sbit_offsets(&self) -> &'a [BigEndian] { - let range = self.shape.sbit_offsets_byte_range(); - self.data.read_array(range).unwrap() + let range = self.sbit_offsets_byte_range(); + unchecked::read_array(self.data, range) + } + + pub(crate) fn last_glyph_index(&self) -> GlyphId16 { + self.args.0 + } + + pub(crate) fn first_glyph_index(&self) -> GlyphId16 { + self.args.1 } } @@ -1288,11 +1296,36 @@ impl Format for IndexSubtable4Marker { /// [IndexSubTable4](https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#indexsubtable3-variable-metrics-glyphs-with-2-byte-offsets): variable-metrics glyphs with sparse glyph codes. #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct IndexSubtable4Marker { - glyph_array_byte_len: usize, +pub struct IndexSubtable4Marker; + +impl<'a> MinByteRange for IndexSubtable4<'a> { + fn min_byte_range(&self) -> Range { + 0..self.glyph_array_byte_range().end + } } -impl IndexSubtable4Marker { +impl<'a> FontRead<'a> for IndexSubtable4<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// [IndexSubTable4](https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#indexsubtable3-variable-metrics-glyphs-with-2-byte-offsets): variable-metrics glyphs with sparse glyph codes. +pub type IndexSubtable4<'a> = TableRef<'a, IndexSubtable4Marker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> IndexSubtable4<'a> { + fn glyph_array_byte_len(&self, start: usize) -> usize { + let _ = start; + (transforms::add(self.num_glyphs(), 1_usize)) + .checked_mul(GlyphIdOffsetPair::RAW_BYTE_LEN) + .unwrap() + } + pub fn index_format_byte_range(&self) -> Range { let start = 0; start..start + u16::RAW_BYTE_LEN @@ -1315,66 +1348,37 @@ impl IndexSubtable4Marker { pub fn glyph_array_byte_range(&self) -> Range { let start = self.num_glyphs_byte_range().end; - start..start + self.glyph_array_byte_len + start..start + self.glyph_array_byte_len(start) } -} - -impl MinByteRange for IndexSubtable4Marker { - fn min_byte_range(&self) -> Range { - 0..self.glyph_array_byte_range().end - } -} - -impl<'a> FontRead<'a> for IndexSubtable4<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - let num_glyphs: u32 = cursor.read()?; - let glyph_array_byte_len = (transforms::add(num_glyphs, 1_usize)) - .checked_mul(GlyphIdOffsetPair::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(glyph_array_byte_len); - cursor.finish(IndexSubtable4Marker { - glyph_array_byte_len, - }) - } -} -/// [IndexSubTable4](https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#indexsubtable3-variable-metrics-glyphs-with-2-byte-offsets): variable-metrics glyphs with sparse glyph codes. -pub type IndexSubtable4<'a> = TableRef<'a, IndexSubtable4Marker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> IndexSubtable4<'a> { /// Format of this IndexSubTable. pub fn index_format(&self) -> u16 { - let range = self.shape.index_format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.index_format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Format of EBDT image data. pub fn image_format(&self) -> u16 { - let range = self.shape.image_format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.image_format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Offset to image data in EBDT table. pub fn image_data_offset(&self) -> u32 { - let range = self.shape.image_data_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.image_data_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Array length. pub fn num_glyphs(&self) -> u32 { - let range = self.shape.num_glyphs_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.num_glyphs_byte_range(); + unchecked::read_at(self.data, range.start) } /// One per glyph. pub fn glyph_array(&self) -> &'a [GlyphIdOffsetPair] { - let range = self.shape.glyph_array_byte_range(); - self.data.read_array(range).unwrap() + let range = self.glyph_array_byte_range(); + unchecked::read_array(self.data, range) } } @@ -1459,12 +1463,40 @@ impl Format for IndexSubtable5Marker { /// [IndexSubTable5](https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#indexsubtable5-constant-metrics-glyphs-with-sparse-glyph-codes): constant-metrics glyphs with sparse glyph codes #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct IndexSubtable5Marker { - big_metrics_byte_len: usize, - glyph_array_byte_len: usize, +pub struct IndexSubtable5Marker; + +impl<'a> MinByteRange for IndexSubtable5<'a> { + fn min_byte_range(&self) -> Range { + 0..self.glyph_array_byte_range().end + } } -impl IndexSubtable5Marker { +impl<'a> FontRead<'a> for IndexSubtable5<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// [IndexSubTable5](https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#indexsubtable5-constant-metrics-glyphs-with-sparse-glyph-codes): constant-metrics glyphs with sparse glyph codes +pub type IndexSubtable5<'a> = TableRef<'a, IndexSubtable5Marker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> IndexSubtable5<'a> { + fn big_metrics_byte_len(&self, start: usize) -> usize { + let _ = start; + BigGlyphMetrics::RAW_BYTE_LEN + } + fn glyph_array_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.num_glyphs()) as usize) + .checked_mul(GlyphId16::RAW_BYTE_LEN) + .unwrap() + } + pub fn index_format_byte_range(&self) -> Range { let start = 0; start..start + u16::RAW_BYTE_LEN @@ -1487,7 +1519,7 @@ impl IndexSubtable5Marker { pub fn big_metrics_byte_range(&self) -> Range { let start = self.image_size_byte_range().end; - start..start + self.big_metrics_byte_len + start..start + self.big_metrics_byte_len(start) } pub fn num_glyphs_byte_range(&self) -> Range { @@ -1497,82 +1529,49 @@ impl IndexSubtable5Marker { pub fn glyph_array_byte_range(&self) -> Range { let start = self.num_glyphs_byte_range().end; - start..start + self.glyph_array_byte_len - } -} - -impl MinByteRange for IndexSubtable5Marker { - fn min_byte_range(&self) -> Range { - 0..self.glyph_array_byte_range().end + start..start + self.glyph_array_byte_len(start) } -} -impl<'a> FontRead<'a> for IndexSubtable5<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - let big_metrics_byte_len = BigGlyphMetrics::RAW_BYTE_LEN; - cursor.advance_by(big_metrics_byte_len); - let num_glyphs: u32 = cursor.read()?; - let glyph_array_byte_len = (num_glyphs as usize) - .checked_mul(GlyphId16::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(glyph_array_byte_len); - cursor.finish(IndexSubtable5Marker { - big_metrics_byte_len, - glyph_array_byte_len, - }) - } -} - -/// [IndexSubTable5](https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#indexsubtable5-constant-metrics-glyphs-with-sparse-glyph-codes): constant-metrics glyphs with sparse glyph codes -pub type IndexSubtable5<'a> = TableRef<'a, IndexSubtable5Marker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> IndexSubtable5<'a> { /// Format of this IndexSubTable. pub fn index_format(&self) -> u16 { - let range = self.shape.index_format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.index_format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Format of EBDT image data. pub fn image_format(&self) -> u16 { - let range = self.shape.image_format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.image_format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Offset to image data in EBDT table. pub fn image_data_offset(&self) -> u32 { - let range = self.shape.image_data_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.image_data_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// All glyphs have the same data size. pub fn image_size(&self) -> u32 { - let range = self.shape.image_size_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.image_size_byte_range(); + unchecked::read_at(self.data, range.start) } /// All glyphs have the same metrics. pub fn big_metrics(&self) -> &'a [BigGlyphMetrics] { - let range = self.shape.big_metrics_byte_range(); - self.data.read_array(range).unwrap() + let range = self.big_metrics_byte_range(); + unchecked::read_array(self.data, range) } /// Array length. pub fn num_glyphs(&self) -> u32 { - let range = self.shape.num_glyphs_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.num_glyphs_byte_range(); + unchecked::read_at(self.data, range.start) } /// One per glyph, sorted by glyhph ID. pub fn glyph_array(&self) -> &'a [BigEndian] { - let range = self.shape.glyph_array_byte_range(); - self.data.read_array(range).unwrap() + let range = self.glyph_array_byte_range(); + unchecked::read_array(self.data, range) } } diff --git a/read-fonts/generated/generated_cbdt.rs b/read-fonts/generated/generated_cbdt.rs index 900f1ce2f..1c1091705 100644 --- a/read-fonts/generated/generated_cbdt.rs +++ b/read-fonts/generated/generated_cbdt.rs @@ -8,21 +8,9 @@ use crate::codegen_prelude::*; /// The [Color Bitmap Data](https://learn.microsoft.com/en-us/typography/opentype/spec/cbdt) table #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct CbdtMarker {} +pub struct CbdtMarker; -impl CbdtMarker { - pub fn major_version_byte_range(&self) -> Range { - let start = 0; - start..start + u16::RAW_BYTE_LEN - } - - pub fn minor_version_byte_range(&self) -> Range { - let start = self.major_version_byte_range().end; - start..start + u16::RAW_BYTE_LEN - } -} - -impl MinByteRange for CbdtMarker { +impl<'a> MinByteRange for Cbdt<'a> { fn min_byte_range(&self) -> Range { 0..self.minor_version_byte_range().end } @@ -35,28 +23,39 @@ impl TopLevelTable for Cbdt<'_> { impl<'a> FontRead<'a> for Cbdt<'a> { fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.finish(CbdtMarker {}) + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) } } /// The [Color Bitmap Data](https://learn.microsoft.com/en-us/typography/opentype/spec/cbdt) table -pub type Cbdt<'a> = TableRef<'a, CbdtMarker>; +pub type Cbdt<'a> = TableRef<'a, CbdtMarker, ()>; #[allow(clippy::needless_lifetimes)] impl<'a> Cbdt<'a> { + pub fn major_version_byte_range(&self) -> Range { + let start = 0; + start..start + u16::RAW_BYTE_LEN + } + + pub fn minor_version_byte_range(&self) -> Range { + let start = self.major_version_byte_range().end; + start..start + u16::RAW_BYTE_LEN + } + /// Major version of the CBDT table, = 3. pub fn major_version(&self) -> u16 { - let range = self.shape.major_version_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.major_version_byte_range(); + unchecked::read_at(self.data, range.start) } /// Minor version of CBDT table, = 0. pub fn minor_version(&self) -> u16 { - let range = self.shape.minor_version_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.minor_version_byte_range(); + unchecked::read_at(self.data, range.start) } } diff --git a/read-fonts/generated/generated_cblc.rs b/read-fonts/generated/generated_cblc.rs index 33bd528a7..ec48953db 100644 --- a/read-fonts/generated/generated_cblc.rs +++ b/read-fonts/generated/generated_cblc.rs @@ -8,33 +8,9 @@ use crate::codegen_prelude::*; /// The [Color Bitmap Location](https://learn.microsoft.com/en-us/typography/opentype/spec/cblc) table #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct CblcMarker { - bitmap_sizes_byte_len: usize, -} - -impl CblcMarker { - pub fn major_version_byte_range(&self) -> Range { - let start = 0; - start..start + u16::RAW_BYTE_LEN - } - - pub fn minor_version_byte_range(&self) -> Range { - let start = self.major_version_byte_range().end; - start..start + u16::RAW_BYTE_LEN - } +pub struct CblcMarker; - pub fn num_sizes_byte_range(&self) -> Range { - let start = self.minor_version_byte_range().end; - start..start + u32::RAW_BYTE_LEN - } - - pub fn bitmap_sizes_byte_range(&self) -> Range { - let start = self.num_sizes_byte_range().end; - start..start + self.bitmap_sizes_byte_len - } -} - -impl MinByteRange for CblcMarker { +impl<'a> MinByteRange for Cblc<'a> { fn min_byte_range(&self) -> Range { 0..self.bitmap_sizes_byte_range().end } @@ -47,47 +23,68 @@ impl TopLevelTable for Cblc<'_> { impl<'a> FontRead<'a> for Cblc<'a> { fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - let num_sizes: u32 = cursor.read()?; - let bitmap_sizes_byte_len = (num_sizes as usize) - .checked_mul(BitmapSize::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(bitmap_sizes_byte_len); - cursor.finish(CblcMarker { - bitmap_sizes_byte_len, + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, }) } } /// The [Color Bitmap Location](https://learn.microsoft.com/en-us/typography/opentype/spec/cblc) table -pub type Cblc<'a> = TableRef<'a, CblcMarker>; +pub type Cblc<'a> = TableRef<'a, CblcMarker, ()>; #[allow(clippy::needless_lifetimes)] impl<'a> Cblc<'a> { + fn bitmap_sizes_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.num_sizes()) as usize) + .checked_mul(BitmapSize::RAW_BYTE_LEN) + .unwrap() + } + + pub fn major_version_byte_range(&self) -> Range { + let start = 0; + start..start + u16::RAW_BYTE_LEN + } + + pub fn minor_version_byte_range(&self) -> Range { + let start = self.major_version_byte_range().end; + start..start + u16::RAW_BYTE_LEN + } + + pub fn num_sizes_byte_range(&self) -> Range { + let start = self.minor_version_byte_range().end; + start..start + u32::RAW_BYTE_LEN + } + + pub fn bitmap_sizes_byte_range(&self) -> Range { + let start = self.num_sizes_byte_range().end; + start..start + self.bitmap_sizes_byte_len(start) + } + /// Major version of the CBLC table, = 3. pub fn major_version(&self) -> u16 { - let range = self.shape.major_version_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.major_version_byte_range(); + unchecked::read_at(self.data, range.start) } /// Minor version of CBLC table, = 0. pub fn minor_version(&self) -> u16 { - let range = self.shape.minor_version_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.minor_version_byte_range(); + unchecked::read_at(self.data, range.start) } /// Number of BitmapSize records. pub fn num_sizes(&self) -> u32 { - let range = self.shape.num_sizes_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.num_sizes_byte_range(); + unchecked::read_at(self.data, range.start) } /// BitmapSize records array. pub fn bitmap_sizes(&self) -> &'a [BitmapSize] { - let range = self.shape.bitmap_sizes_byte_range(); - self.data.read_array(range).unwrap() + let range = self.bitmap_sizes_byte_range(); + unchecked::read_array(self.data, range) } } diff --git a/read-fonts/generated/generated_cff.rs b/read-fonts/generated/generated_cff.rs index 64668d9ee..44a4145b6 100644 --- a/read-fonts/generated/generated_cff.rs +++ b/read-fonts/generated/generated_cff.rs @@ -8,12 +8,43 @@ use crate::codegen_prelude::*; /// [Compact Font Format](https://learn.microsoft.com/en-us/typography/opentype/spec/cff) table header #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct CffHeaderMarker { - _padding_byte_len: usize, - trailing_data_byte_len: usize, +pub struct CffHeaderMarker; + +impl<'a> MinByteRange for CffHeader<'a> { + fn min_byte_range(&self) -> Range { + 0..self.trailing_data_byte_range().end + } +} + +impl<'a> FontRead<'a> for CffHeader<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } } -impl CffHeaderMarker { +/// [Compact Font Format](https://learn.microsoft.com/en-us/typography/opentype/spec/cff) table header +pub type CffHeader<'a> = TableRef<'a, CffHeaderMarker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> CffHeader<'a> { + fn _padding_byte_len(&self, start: usize) -> usize { + let _ = start; + (transforms::subtract(self.hdr_size(), 4_usize)) + .checked_mul(u8::RAW_BYTE_LEN) + .unwrap() + } + fn trailing_data_byte_len(&self, start: usize) -> usize { + let _ = start; + { + let remaining = self.data.len().saturating_sub(start); + remaining / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN + } + } + pub fn major_byte_range(&self) -> Range { let start = 0; start..start + u8::RAW_BYTE_LEN @@ -36,80 +67,48 @@ impl CffHeaderMarker { pub fn _padding_byte_range(&self) -> Range { let start = self.off_size_byte_range().end; - start..start + self._padding_byte_len + start..start + self._padding_byte_len(start) } pub fn trailing_data_byte_range(&self) -> Range { let start = self._padding_byte_range().end; - start..start + self.trailing_data_byte_len - } -} - -impl MinByteRange for CffHeaderMarker { - fn min_byte_range(&self) -> Range { - 0..self.trailing_data_byte_range().end - } -} - -impl<'a> FontRead<'a> for CffHeader<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - let hdr_size: u8 = cursor.read()?; - cursor.advance::(); - let _padding_byte_len = (transforms::subtract(hdr_size, 4_usize)) - .checked_mul(u8::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(_padding_byte_len); - let trailing_data_byte_len = cursor.remaining_bytes() / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN; - cursor.advance_by(trailing_data_byte_len); - cursor.finish(CffHeaderMarker { - _padding_byte_len, - trailing_data_byte_len, - }) + start..start + self.trailing_data_byte_len(start) } -} -/// [Compact Font Format](https://learn.microsoft.com/en-us/typography/opentype/spec/cff) table header -pub type CffHeader<'a> = TableRef<'a, CffHeaderMarker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> CffHeader<'a> { /// Format major version (starting at 1). pub fn major(&self) -> u8 { - let range = self.shape.major_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.major_byte_range(); + unchecked::read_at(self.data, range.start) } /// Format minor version (starting at 0). pub fn minor(&self) -> u8 { - let range = self.shape.minor_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.minor_byte_range(); + unchecked::read_at(self.data, range.start) } /// Header size (bytes). pub fn hdr_size(&self) -> u8 { - let range = self.shape.hdr_size_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.hdr_size_byte_range(); + unchecked::read_at(self.data, range.start) } /// Absolute offset size. pub fn off_size(&self) -> u8 { - let range = self.shape.off_size_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.off_size_byte_range(); + unchecked::read_at(self.data, range.start) } /// Padding bytes before the start of the Name INDEX. pub fn _padding(&self) -> &'a [u8] { - let range = self.shape._padding_byte_range(); - self.data.read_array(range).unwrap() + let range = self._padding_byte_range(); + unchecked::read_array(self.data, range) } /// Remaining table data. pub fn trailing_data(&self) -> &'a [u8] { - let range = self.shape.trailing_data_byte_range(); - self.data.read_array(range).unwrap() + let range = self.trailing_data_byte_range(); + unchecked::read_array(self.data, range) } } diff --git a/read-fonts/generated/generated_cff2.rs b/read-fonts/generated/generated_cff2.rs index 0bd7bd474..13c2d3c70 100644 --- a/read-fonts/generated/generated_cff2.rs +++ b/read-fonts/generated/generated_cff2.rs @@ -8,13 +8,49 @@ use crate::codegen_prelude::*; /// [Compact Font Format (CFF) version 2](https://learn.microsoft.com/en-us/typography/opentype/spec/cff2) table header #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct Cff2HeaderMarker { - _padding_byte_len: usize, - top_dict_data_byte_len: usize, - trailing_data_byte_len: usize, +pub struct Cff2HeaderMarker; + +impl<'a> MinByteRange for Cff2Header<'a> { + fn min_byte_range(&self) -> Range { + 0..self.trailing_data_byte_range().end + } +} + +impl<'a> FontRead<'a> for Cff2Header<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } } -impl Cff2HeaderMarker { +/// [Compact Font Format (CFF) version 2](https://learn.microsoft.com/en-us/typography/opentype/spec/cff2) table header +pub type Cff2Header<'a> = TableRef<'a, Cff2HeaderMarker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> Cff2Header<'a> { + fn _padding_byte_len(&self, start: usize) -> usize { + let _ = start; + (transforms::subtract(self.header_size(), 5_usize)) + .checked_mul(u8::RAW_BYTE_LEN) + .unwrap() + } + fn top_dict_data_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.top_dict_length()) as usize) + .checked_mul(u8::RAW_BYTE_LEN) + .unwrap() + } + fn trailing_data_byte_len(&self, start: usize) -> usize { + let _ = start; + { + let remaining = self.data.len().saturating_sub(start); + remaining / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN + } + } + pub fn major_version_byte_range(&self) -> Range { let start = 0; start..start + u8::RAW_BYTE_LEN @@ -37,96 +73,59 @@ impl Cff2HeaderMarker { pub fn _padding_byte_range(&self) -> Range { let start = self.top_dict_length_byte_range().end; - start..start + self._padding_byte_len + start..start + self._padding_byte_len(start) } pub fn top_dict_data_byte_range(&self) -> Range { let start = self._padding_byte_range().end; - start..start + self.top_dict_data_byte_len + start..start + self.top_dict_data_byte_len(start) } pub fn trailing_data_byte_range(&self) -> Range { let start = self.top_dict_data_byte_range().end; - start..start + self.trailing_data_byte_len - } -} - -impl MinByteRange for Cff2HeaderMarker { - fn min_byte_range(&self) -> Range { - 0..self.trailing_data_byte_range().end + start..start + self.trailing_data_byte_len(start) } -} -impl<'a> FontRead<'a> for Cff2Header<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - let header_size: u8 = cursor.read()?; - let top_dict_length: u16 = cursor.read()?; - let _padding_byte_len = (transforms::subtract(header_size, 5_usize)) - .checked_mul(u8::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(_padding_byte_len); - let top_dict_data_byte_len = (top_dict_length as usize) - .checked_mul(u8::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(top_dict_data_byte_len); - let trailing_data_byte_len = cursor.remaining_bytes() / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN; - cursor.advance_by(trailing_data_byte_len); - cursor.finish(Cff2HeaderMarker { - _padding_byte_len, - top_dict_data_byte_len, - trailing_data_byte_len, - }) - } -} - -/// [Compact Font Format (CFF) version 2](https://learn.microsoft.com/en-us/typography/opentype/spec/cff2) table header -pub type Cff2Header<'a> = TableRef<'a, Cff2HeaderMarker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> Cff2Header<'a> { /// Format major version (set to 2). pub fn major_version(&self) -> u8 { - let range = self.shape.major_version_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.major_version_byte_range(); + unchecked::read_at(self.data, range.start) } /// Format minor version (set to 0). pub fn minor_version(&self) -> u8 { - let range = self.shape.minor_version_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.minor_version_byte_range(); + unchecked::read_at(self.data, range.start) } /// Header size (bytes). pub fn header_size(&self) -> u8 { - let range = self.shape.header_size_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.header_size_byte_range(); + unchecked::read_at(self.data, range.start) } /// Length of Top DICT structure in bytes. pub fn top_dict_length(&self) -> u16 { - let range = self.shape.top_dict_length_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.top_dict_length_byte_range(); + unchecked::read_at(self.data, range.start) } /// Padding bytes before the start of the Top DICT. pub fn _padding(&self) -> &'a [u8] { - let range = self.shape._padding_byte_range(); - self.data.read_array(range).unwrap() + let range = self._padding_byte_range(); + unchecked::read_array(self.data, range) } /// Data containing the Top DICT. pub fn top_dict_data(&self) -> &'a [u8] { - let range = self.shape.top_dict_data_byte_range(); - self.data.read_array(range).unwrap() + let range = self.top_dict_data_byte_range(); + unchecked::read_array(self.data, range) } /// Remaining table data. pub fn trailing_data(&self) -> &'a [u8] { - let range = self.shape.trailing_data_byte_range(); - self.data.read_array(range).unwrap() + let range = self.trailing_data_byte_range(); + unchecked::read_array(self.data, range) } } diff --git a/read-fonts/generated/generated_cmap.rs b/read-fonts/generated/generated_cmap.rs index b16b8587e..0a99da7bd 100644 --- a/read-fonts/generated/generated_cmap.rs +++ b/read-fonts/generated/generated_cmap.rs @@ -8,28 +8,9 @@ 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 { - pub fn version_byte_range(&self) -> Range { - let start = 0; - start..start + u16::RAW_BYTE_LEN - } - - pub fn num_tables_byte_range(&self) -> Range { - let start = self.version_byte_range().end; - start..start + u16::RAW_BYTE_LEN - } - - pub fn encoding_records_byte_range(&self) -> Range { - let start = self.num_tables_byte_range().end; - start..start + self.encoding_records_byte_len - } -} +pub struct CmapMarker; -impl MinByteRange for CmapMarker { +impl<'a> MinByteRange for Cmap<'a> { fn min_byte_range(&self) -> Range { 0..self.encoding_records_byte_range().end } @@ -42,39 +23,56 @@ impl TopLevelTable for Cmap<'_> { 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) - .checked_mul(EncodingRecord::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(encoding_records_byte_len); - cursor.finish(CmapMarker { - encoding_records_byte_len, + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, }) } } /// [cmap](https://docs.microsoft.com/en-us/typography/opentype/spec/cmap#overview) -pub type Cmap<'a> = TableRef<'a, CmapMarker>; +pub type Cmap<'a> = TableRef<'a, CmapMarker, ()>; #[allow(clippy::needless_lifetimes)] impl<'a> Cmap<'a> { + fn encoding_records_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.num_tables()) as usize) + .checked_mul(EncodingRecord::RAW_BYTE_LEN) + .unwrap() + } + + pub fn version_byte_range(&self) -> Range { + let start = 0; + start..start + u16::RAW_BYTE_LEN + } + + pub fn num_tables_byte_range(&self) -> Range { + let start = self.version_byte_range().end; + start..start + u16::RAW_BYTE_LEN + } + + pub fn encoding_records_byte_range(&self) -> Range { + let start = self.num_tables_byte_range().end; + start..start + self.encoding_records_byte_len(start) + } + /// Table version number (0). pub fn version(&self) -> u16 { - let range = self.shape.version_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.version_byte_range(); + unchecked::read_at(self.data, range.start) } /// 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() + let range = self.num_tables_byte_range(); + unchecked::read_at(self.data, range.start) } pub fn encoding_records(&self) -> &'a [EncodingRecord] { - let range = self.shape.encoding_records_byte_range(); - self.data.read_array(range).unwrap() + let range = self.encoding_records_byte_range(); + unchecked::read_array(self.data, range) } } @@ -345,11 +343,34 @@ impl Format for Cmap0Marker { /// [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, +pub struct Cmap0Marker; + +impl<'a> MinByteRange for Cmap0<'a> { + fn min_byte_range(&self) -> Range { + 0..self.glyph_id_array_byte_range().end + } } -impl Cmap0Marker { +impl<'a> FontRead<'a> for Cmap0<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// [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, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> Cmap0<'a> { + fn glyph_id_array_byte_len(&self, start: usize) -> usize { + let _ = start; + (256_usize).checked_mul(u8::RAW_BYTE_LEN).unwrap() + } + pub fn format_byte_range(&self) -> Range { let start = 0; start..start + u16::RAW_BYTE_LEN @@ -367,60 +388,32 @@ impl Cmap0Marker { pub fn glyph_id_array_byte_range(&self) -> Range { let start = self.language_byte_range().end; - start..start + self.glyph_id_array_byte_len + start..start + self.glyph_id_array_byte_len(start) } -} - -impl MinByteRange for Cmap0Marker { - fn min_byte_range(&self) -> Range { - 0..self.glyph_id_array_byte_range().end - } -} - -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_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, - }) - } -} -/// [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>; - -#[allow(clippy::needless_lifetimes)] -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() + let range = self.format_byte_range(); + unchecked::read_at(self.data, range.start) } /// 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() + let range = self.length_byte_range(); + unchecked::read_at(self.data, range.start) } /// 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() + let range = self.language_byte_range(); + unchecked::read_at(self.data, range.start) } /// An array that maps character codes to glyph index values. pub fn glyph_id_array(&self) -> &'a [u8] { - let range = self.shape.glyph_id_array_byte_range(); - self.data.read_array(range).unwrap() + let range = self.glyph_id_array_byte_range(); + unchecked::read_array(self.data, range) } } @@ -455,11 +448,34 @@ impl Format for Cmap2Marker { /// [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, +pub struct Cmap2Marker; + +impl<'a> MinByteRange for Cmap2<'a> { + fn min_byte_range(&self) -> Range { + 0..self.sub_header_keys_byte_range().end + } } -impl Cmap2Marker { +impl<'a> FontRead<'a> for Cmap2<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// [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, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> Cmap2<'a> { + fn sub_header_keys_byte_len(&self, start: usize) -> usize { + let _ = start; + (256_usize).checked_mul(u16::RAW_BYTE_LEN).unwrap() + } + pub fn format_byte_range(&self) -> Range { let start = 0; start..start + u16::RAW_BYTE_LEN @@ -477,61 +493,33 @@ impl Cmap2Marker { pub fn sub_header_keys_byte_range(&self) -> Range { let start = self.language_byte_range().end; - start..start + self.sub_header_keys_byte_len + start..start + self.sub_header_keys_byte_len(start) } -} -impl MinByteRange for Cmap2Marker { - fn min_byte_range(&self) -> Range { - 0..self.sub_header_keys_byte_range().end - } -} - -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_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, - }) - } -} - -/// [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>; - -#[allow(clippy::needless_lifetimes)] -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() + let range = self.format_byte_range(); + unchecked::read_at(self.data, range.start) } /// 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() + let range = self.length_byte_range(); + unchecked::read_at(self.data, range.start) } /// 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() + let range = self.language_byte_range(); + unchecked::read_at(self.data, range.start) } /// 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() + let range = self.sub_header_keys_byte_range(); + unchecked::read_array(self.data, range) } } @@ -625,15 +613,61 @@ impl Format for Cmap4Marker { /// [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, +pub struct Cmap4Marker; + +impl<'a> MinByteRange for Cmap4<'a> { + fn min_byte_range(&self) -> Range { + 0..self.glyph_id_array_byte_range().end + } } -impl Cmap4Marker { +impl<'a> FontRead<'a> for Cmap4<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// [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, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> Cmap4<'a> { + fn end_code_byte_len(&self, start: usize) -> usize { + let _ = start; + (transforms::half(self.seg_count_x2())) + .checked_mul(u16::RAW_BYTE_LEN) + .unwrap() + } + fn start_code_byte_len(&self, start: usize) -> usize { + let _ = start; + (transforms::half(self.seg_count_x2())) + .checked_mul(u16::RAW_BYTE_LEN) + .unwrap() + } + fn id_delta_byte_len(&self, start: usize) -> usize { + let _ = start; + (transforms::half(self.seg_count_x2())) + .checked_mul(i16::RAW_BYTE_LEN) + .unwrap() + } + fn id_range_offsets_byte_len(&self, start: usize) -> usize { + let _ = start; + (transforms::half(self.seg_count_x2())) + .checked_mul(u16::RAW_BYTE_LEN) + .unwrap() + } + fn glyph_id_array_byte_len(&self, start: usize) -> usize { + let _ = start; + { + let remaining = self.data.len().saturating_sub(start); + remaining / u16::RAW_BYTE_LEN * u16::RAW_BYTE_LEN + } + } + pub fn format_byte_range(&self) -> Range { let start = 0; start..start + u16::RAW_BYTE_LEN @@ -671,7 +705,7 @@ impl Cmap4Marker { pub fn end_code_byte_range(&self) -> Range { let start = self.range_shift_byte_range().end; - start..start + self.end_code_byte_len + start..start + self.end_code_byte_len(start) } pub fn reserved_pad_byte_range(&self) -> Range { @@ -681,151 +715,99 @@ impl Cmap4Marker { pub fn start_code_byte_range(&self) -> Range { let start = self.reserved_pad_byte_range().end; - start..start + self.start_code_byte_len + start..start + self.start_code_byte_len(start) } pub fn id_delta_byte_range(&self) -> Range { let start = self.start_code_byte_range().end; - start..start + self.id_delta_byte_len + start..start + self.id_delta_byte_len(start) } pub fn id_range_offsets_byte_range(&self) -> Range { let start = self.id_delta_byte_range().end; - start..start + self.id_range_offsets_byte_len + start..start + self.id_range_offsets_byte_len(start) } pub 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 + start..start + self.glyph_id_array_byte_len(start) } -} -impl MinByteRange for Cmap4Marker { - fn min_byte_range(&self) -> Range { - 0..self.glyph_id_array_byte_range().end - } -} - -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 = (transforms::half(seg_count_x2)) - .checked_mul(u16::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(end_code_byte_len); - cursor.advance::(); - 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, - }) - } -} - -/// [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>; - -#[allow(clippy::needless_lifetimes)] -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() + let range = self.format_byte_range(); + unchecked::read_at(self.data, range.start) } /// 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() + let range = self.length_byte_range(); + unchecked::read_at(self.data, range.start) } /// 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() + let range = self.language_byte_range(); + unchecked::read_at(self.data, range.start) } /// 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() + let range = self.seg_count_x2_byte_range(); + unchecked::read_at(self.data, range.start) } /// 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() + let range = self.search_range_byte_range(); + unchecked::read_at(self.data, range.start) } /// 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() + let range = self.entry_selector_byte_range(); + unchecked::read_at(self.data, range.start) } /// 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() + let range = self.range_shift_byte_range(); + unchecked::read_at(self.data, range.start) } /// 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() + let range = self.end_code_byte_range(); + unchecked::read_array(self.data, range) } /// 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() + let range = self.start_code_byte_range(); + unchecked::read_array(self.data, range) } /// 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() + let range = self.id_delta_byte_range(); + unchecked::read_array(self.data, range) } /// 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() + let range = self.id_range_offsets_byte_range(); + unchecked::read_array(self.data, range) } /// 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() + let range = self.glyph_id_array_byte_range(); + unchecked::read_array(self.data, range) } } @@ -868,11 +850,36 @@ impl Format for Cmap6Marker { /// [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, +pub struct Cmap6Marker; + +impl<'a> MinByteRange for Cmap6<'a> { + fn min_byte_range(&self) -> Range { + 0..self.glyph_id_array_byte_range().end + } +} + +impl<'a> FontRead<'a> for Cmap6<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } } -impl Cmap6Marker { +/// [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, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> Cmap6<'a> { + fn glyph_id_array_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.entry_count()) as usize) + .checked_mul(u16::RAW_BYTE_LEN) + .unwrap() + } + pub fn format_byte_range(&self) -> Range { let start = 0; start..start + u16::RAW_BYTE_LEN @@ -900,74 +907,44 @@ impl Cmap6Marker { pub fn glyph_id_array_byte_range(&self) -> Range { let start = self.entry_count_byte_range().end; - start..start + self.glyph_id_array_byte_len + start..start + self.glyph_id_array_byte_len(start) } -} - -impl MinByteRange for Cmap6Marker { - fn min_byte_range(&self) -> Range { - 0..self.glyph_id_array_byte_range().end - } -} - -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) - .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, - }) - } -} -/// [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>; - -#[allow(clippy::needless_lifetimes)] -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() + let range = self.format_byte_range(); + unchecked::read_at(self.data, range.start) } /// 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() + let range = self.length_byte_range(); + unchecked::read_at(self.data, range.start) } /// 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() + let range = self.language_byte_range(); + unchecked::read_at(self.data, range.start) } /// 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() + let range = self.first_code_byte_range(); + unchecked::read_at(self.data, range.start) } /// 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() + let range = self.entry_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// 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() + let range = self.glyph_id_array_byte_range(); + unchecked::read_array(self.data, range) } } @@ -1004,12 +981,40 @@ impl Format for Cmap8Marker { /// [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, +pub struct Cmap8Marker; + +impl<'a> MinByteRange for Cmap8<'a> { + fn min_byte_range(&self) -> Range { + 0..self.groups_byte_range().end + } } -impl Cmap8Marker { +impl<'a> FontRead<'a> for Cmap8<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// [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, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> Cmap8<'a> { + fn is32_byte_len(&self, start: usize) -> usize { + let _ = start; + (8192_usize).checked_mul(u8::RAW_BYTE_LEN).unwrap() + } + fn groups_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.num_groups()) as usize) + .checked_mul(SequentialMapGroup::RAW_BYTE_LEN) + .unwrap() + } + pub fn format_byte_range(&self) -> Range { let start = 0; start..start + u16::RAW_BYTE_LEN @@ -1032,7 +1037,7 @@ impl Cmap8Marker { pub fn is32_byte_range(&self) -> Range { let start = self.language_byte_range().end; - start..start + self.is32_byte_len + start..start + self.is32_byte_len(start) } pub fn num_groups_byte_range(&self) -> Range { @@ -1042,81 +1047,46 @@ impl Cmap8Marker { pub fn groups_byte_range(&self) -> Range { let start = self.num_groups_byte_range().end; - start..start + self.groups_byte_len - } -} - -impl MinByteRange for Cmap8Marker { - fn min_byte_range(&self) -> Range { - 0..self.groups_byte_range().end + start..start + self.groups_byte_len(start) } -} - -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_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, - }) - } -} - -/// [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>; -#[allow(clippy::needless_lifetimes)] -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() + let range = self.format_byte_range(); + unchecked::read_at(self.data, range.start) } /// 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() + let range = self.length_byte_range(); + unchecked::read_at(self.data, range.start) } /// 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() + let range = self.language_byte_range(); + unchecked::read_at(self.data, range.start) } /// 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 [u8] { - let range = self.shape.is32_byte_range(); - self.data.read_array(range).unwrap() + let range = self.is32_byte_range(); + unchecked::read_array(self.data, range) } /// 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() + let range = self.num_groups_byte_range(); + unchecked::read_at(self.data, range.start) } /// Array of SequentialMapGroup records. pub fn groups(&self) -> &'a [SequentialMapGroup] { - let range = self.shape.groups_byte_range(); - self.data.read_array(range).unwrap() + let range = self.groups_byte_range(); + unchecked::read_array(self.data, range) } } @@ -1218,11 +1188,36 @@ impl Format for Cmap10Marker { /// [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, +pub struct Cmap10Marker; + +impl<'a> MinByteRange for Cmap10<'a> { + fn min_byte_range(&self) -> Range { + 0..self.glyph_id_array_byte_range().end + } +} + +impl<'a> FontRead<'a> for Cmap10<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } } -impl Cmap10Marker { +/// [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, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> Cmap10<'a> { + fn glyph_id_array_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.num_chars()) as usize) + .checked_mul(u16::RAW_BYTE_LEN) + .unwrap() + } + pub fn format_byte_range(&self) -> Range { let start = 0; start..start + u16::RAW_BYTE_LEN @@ -1255,75 +1250,44 @@ impl Cmap10Marker { pub fn glyph_id_array_byte_range(&self) -> Range { let start = self.num_chars_byte_range().end; - start..start + self.glyph_id_array_byte_len + start..start + self.glyph_id_array_byte_len(start) } -} - -impl MinByteRange for Cmap10Marker { - fn min_byte_range(&self) -> Range { - 0..self.glyph_id_array_byte_range().end - } -} -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::(); - let num_chars: u32 = cursor.read()?; - let glyph_id_array_byte_len = (num_chars as usize) - .checked_mul(u16::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - 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>; - -#[allow(clippy::needless_lifetimes)] -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() + let range = self.format_byte_range(); + unchecked::read_at(self.data, range.start) } /// 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() + let range = self.length_byte_range(); + unchecked::read_at(self.data, range.start) } /// 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() + let range = self.language_byte_range(); + unchecked::read_at(self.data, range.start) } /// 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() + let range = self.start_char_code_byte_range(); + unchecked::read_at(self.data, range.start) } /// 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() + let range = self.num_chars_byte_range(); + unchecked::read_at(self.data, range.start) } /// 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() + let range = self.glyph_id_array_byte_range(); + unchecked::read_array(self.data, range) } } @@ -1360,11 +1324,36 @@ impl Format for Cmap12Marker { /// [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, +pub struct Cmap12Marker; + +impl<'a> MinByteRange for Cmap12<'a> { + fn min_byte_range(&self) -> Range { + 0..self.groups_byte_range().end + } } -impl Cmap12Marker { +impl<'a> FontRead<'a> for Cmap12<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// [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, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> Cmap12<'a> { + fn groups_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.num_groups()) as usize) + .checked_mul(SequentialMapGroup::RAW_BYTE_LEN) + .unwrap() + } + pub fn format_byte_range(&self) -> Range { let start = 0; start..start + u16::RAW_BYTE_LEN @@ -1392,66 +1381,38 @@ impl Cmap12Marker { pub fn groups_byte_range(&self) -> Range { let start = self.num_groups_byte_range().end; - start..start + self.groups_byte_len + start..start + self.groups_byte_len(start) } -} -impl MinByteRange for Cmap12Marker { - fn min_byte_range(&self) -> Range { - 0..self.groups_byte_range().end - } -} - -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) - .checked_mul(SequentialMapGroup::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - 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>; - -#[allow(clippy::needless_lifetimes)] -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() + let range = self.format_byte_range(); + unchecked::read_at(self.data, range.start) } /// 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() + let range = self.length_byte_range(); + unchecked::read_at(self.data, range.start) } /// 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() + let range = self.language_byte_range(); + unchecked::read_at(self.data, range.start) } /// 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() + let range = self.num_groups_byte_range(); + unchecked::read_at(self.data, range.start) } /// Array of SequentialMapGroup records. pub fn groups(&self) -> &'a [SequentialMapGroup] { - let range = self.shape.groups_byte_range(); - self.data.read_array(range).unwrap() + let range = self.groups_byte_range(); + unchecked::read_array(self.data, range) } } @@ -1494,11 +1455,36 @@ impl Format for Cmap13Marker { /// [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, +pub struct Cmap13Marker; + +impl<'a> MinByteRange for Cmap13<'a> { + fn min_byte_range(&self) -> Range { + 0..self.groups_byte_range().end + } } -impl Cmap13Marker { +impl<'a> FontRead<'a> for Cmap13<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// [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, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> Cmap13<'a> { + fn groups_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.num_groups()) as usize) + .checked_mul(ConstantMapGroup::RAW_BYTE_LEN) + .unwrap() + } + pub fn format_byte_range(&self) -> Range { let start = 0; start..start + u16::RAW_BYTE_LEN @@ -1526,66 +1512,38 @@ impl Cmap13Marker { pub fn groups_byte_range(&self) -> Range { let start = self.num_groups_byte_range().end; - start..start + self.groups_byte_len + start..start + self.groups_byte_len(start) } -} - -impl MinByteRange for Cmap13Marker { - fn min_byte_range(&self) -> Range { - 0..self.groups_byte_range().end - } -} - -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) - .checked_mul(ConstantMapGroup::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - 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>; -#[allow(clippy::needless_lifetimes)] -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() + let range = self.format_byte_range(); + unchecked::read_at(self.data, range.start) } /// 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() + let range = self.length_byte_range(); + unchecked::read_at(self.data, range.start) } /// 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() + let range = self.language_byte_range(); + unchecked::read_at(self.data, range.start) } /// 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() + let range = self.num_groups_byte_range(); + unchecked::read_at(self.data, range.start) } /// Array of ConstantMapGroup records. pub fn groups(&self) -> &'a [ConstantMapGroup] { - let range = self.shape.groups_byte_range(); - self.data.read_array(range).unwrap() + let range = self.groups_byte_range(); + unchecked::read_array(self.data, range) } } @@ -1680,11 +1638,36 @@ impl Format for Cmap14Marker { /// [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, +pub struct Cmap14Marker; + +impl<'a> MinByteRange for Cmap14<'a> { + fn min_byte_range(&self) -> Range { + 0..self.var_selector_byte_range().end + } } -impl Cmap14Marker { +impl<'a> FontRead<'a> for Cmap14<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// [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, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> Cmap14<'a> { + fn var_selector_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.num_var_selector_records()) as usize) + .checked_mul(VariationSelector::RAW_BYTE_LEN) + .unwrap() + } + pub fn format_byte_range(&self) -> Range { let start = 0; start..start + u16::RAW_BYTE_LEN @@ -1702,59 +1685,31 @@ impl Cmap14Marker { pub fn var_selector_byte_range(&self) -> Range { let start = self.num_var_selector_records_byte_range().end; - start..start + self.var_selector_byte_len + start..start + self.var_selector_byte_len(start) } -} -impl MinByteRange for Cmap14Marker { - fn min_byte_range(&self) -> Range { - 0..self.var_selector_byte_range().end - } -} - -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) - .checked_mul(VariationSelector::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - 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>; - -#[allow(clippy::needless_lifetimes)] -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() + let range = self.format_byte_range(); + unchecked::read_at(self.data, range.start) } /// 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() + let range = self.length_byte_range(); + unchecked::read_at(self.data, range.start) } /// 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() + let range = self.num_var_selector_records_byte_range(); + unchecked::read_at(self.data, range.start) } /// 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() + let range = self.var_selector_byte_range(); + unchecked::read_array(self.data, range) } } @@ -1877,23 +1832,9 @@ impl<'a> SomeRecord<'a> for VariationSelector { /// [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, -} +pub struct DefaultUvsMarker; -impl DefaultUvsMarker { - pub fn num_unicode_value_ranges_byte_range(&self) -> Range { - let start = 0; - start..start + u32::RAW_BYTE_LEN - } - - pub fn ranges_byte_range(&self) -> Range { - let start = self.num_unicode_value_ranges_byte_range().end; - start..start + self.ranges_byte_len - } -} - -impl MinByteRange for DefaultUvsMarker { +impl<'a> MinByteRange for DefaultUvs<'a> { fn min_byte_range(&self) -> Range { 0..self.ranges_byte_range().end } @@ -1901,31 +1842,46 @@ impl MinByteRange for DefaultUvsMarker { 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) - .checked_mul(UnicodeRange::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(ranges_byte_len); - cursor.finish(DefaultUvsMarker { ranges_byte_len }) + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) } } /// [Default UVS table](https://docs.microsoft.com/en-us/typography/opentype/spec/cmap#default-uvs-table) -pub type DefaultUvs<'a> = TableRef<'a, DefaultUvsMarker>; +pub type DefaultUvs<'a> = TableRef<'a, DefaultUvsMarker, ()>; #[allow(clippy::needless_lifetimes)] impl<'a> DefaultUvs<'a> { + fn ranges_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.num_unicode_value_ranges()) as usize) + .checked_mul(UnicodeRange::RAW_BYTE_LEN) + .unwrap() + } + + pub fn num_unicode_value_ranges_byte_range(&self) -> Range { + let start = 0; + start..start + u32::RAW_BYTE_LEN + } + + pub fn ranges_byte_range(&self) -> Range { + let start = self.num_unicode_value_ranges_byte_range().end; + start..start + self.ranges_byte_len(start) + } + /// 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() + let range = self.num_unicode_value_ranges_byte_range(); + unchecked::read_at(self.data, range.start) } /// Array of UnicodeRange records. pub fn ranges(&self) -> &'a [UnicodeRange] { - let range = self.shape.ranges_byte_range(); - self.data.read_array(range).unwrap() + let range = self.ranges_byte_range(); + unchecked::read_array(self.data, range) } } @@ -1964,23 +1920,9 @@ impl<'a> std::fmt::Debug for DefaultUvs<'a> { /// [Non-Default UVS table](https://learn.microsoft.com/en-us/typography/opentype/spec/cmap#non-default-uvs-table) #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct NonDefaultUvsMarker { - uvs_mapping_byte_len: usize, -} +pub struct NonDefaultUvsMarker; -impl NonDefaultUvsMarker { - pub fn num_uvs_mappings_byte_range(&self) -> Range { - let start = 0; - start..start + u32::RAW_BYTE_LEN - } - - pub fn uvs_mapping_byte_range(&self) -> Range { - let start = self.num_uvs_mappings_byte_range().end; - start..start + self.uvs_mapping_byte_len - } -} - -impl MinByteRange for NonDefaultUvsMarker { +impl<'a> MinByteRange for NonDefaultUvs<'a> { fn min_byte_range(&self) -> Range { 0..self.uvs_mapping_byte_range().end } @@ -1988,31 +1930,44 @@ impl MinByteRange for NonDefaultUvsMarker { impl<'a> FontRead<'a> for NonDefaultUvs<'a> { fn read(data: FontData<'a>) -> Result { - 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, + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, }) } } /// [Non-Default UVS table](https://learn.microsoft.com/en-us/typography/opentype/spec/cmap#non-default-uvs-table) -pub type NonDefaultUvs<'a> = TableRef<'a, NonDefaultUvsMarker>; +pub type NonDefaultUvs<'a> = TableRef<'a, NonDefaultUvsMarker, ()>; #[allow(clippy::needless_lifetimes)] impl<'a> NonDefaultUvs<'a> { + fn uvs_mapping_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.num_uvs_mappings()) as usize) + .checked_mul(UvsMapping::RAW_BYTE_LEN) + .unwrap() + } + + pub fn num_uvs_mappings_byte_range(&self) -> Range { + let start = 0; + start..start + u32::RAW_BYTE_LEN + } + + pub fn uvs_mapping_byte_range(&self) -> Range { + let start = self.num_uvs_mappings_byte_range().end; + start..start + self.uvs_mapping_byte_len(start) + } + pub fn num_uvs_mappings(&self) -> u32 { - let range = self.shape.num_uvs_mappings_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.num_uvs_mappings_byte_range(); + unchecked::read_at(self.data, range.start) } pub fn uvs_mapping(&self) -> &'a [UvsMapping] { - let range = self.shape.uvs_mapping_byte_range(); - self.data.read_array(range).unwrap() + let range = self.uvs_mapping_byte_range(); + unchecked::read_array(self.data, range) } } diff --git a/read-fonts/generated/generated_colr.rs b/read-fonts/generated/generated_colr.rs index ea9417481..8ce5e3fe0 100644 --- a/read-fonts/generated/generated_colr.rs +++ b/read-fonts/generated/generated_colr.rs @@ -8,15 +8,34 @@ use crate::codegen_prelude::*; /// [COLR (Color)](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#colr-header) table #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct ColrMarker { - base_glyph_list_offset_byte_start: Option, - layer_list_offset_byte_start: Option, - clip_list_offset_byte_start: Option, - var_index_map_offset_byte_start: Option, - item_variation_store_offset_byte_start: Option, +pub struct ColrMarker; + +impl<'a> MinByteRange for Colr<'a> { + fn min_byte_range(&self) -> Range { + 0..self.num_layer_records_byte_range().end + } +} + +impl TopLevelTable for Colr<'_> { + /// `COLR` + const TAG: Tag = Tag::new(b"COLR"); +} + +impl<'a> FontRead<'a> for Colr<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } } -impl ColrMarker { +/// [COLR (Color)](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#colr-header) table +pub type Colr<'a> = TableRef<'a, ColrMarker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> Colr<'a> { pub fn version_byte_range(&self) -> Range { let start = 0; start..start + u16::RAW_BYTE_LEN @@ -43,116 +62,102 @@ impl ColrMarker { } pub fn base_glyph_list_offset_byte_range(&self) -> Option> { - let start = self.base_glyph_list_offset_byte_start?; - Some(start..start + Offset32::RAW_BYTE_LEN) + if self.version().compatible(1u16) { + let start = self.num_layer_records_byte_range().end; + Some(start..start + Offset32::RAW_BYTE_LEN) + } else { + None + } } pub fn layer_list_offset_byte_range(&self) -> Option> { - let start = self.layer_list_offset_byte_start?; - Some(start..start + Offset32::RAW_BYTE_LEN) + if self.version().compatible(1u16) { + let start = self + .base_glyph_list_offset_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| self.num_layer_records_byte_range().end); + Some(start..start + Offset32::RAW_BYTE_LEN) + } else { + None + } } pub fn clip_list_offset_byte_range(&self) -> Option> { - let start = self.clip_list_offset_byte_start?; - Some(start..start + Offset32::RAW_BYTE_LEN) + if self.version().compatible(1u16) { + let start = self + .layer_list_offset_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| { + self.base_glyph_list_offset_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| self.num_layer_records_byte_range().end) + }); + Some(start..start + Offset32::RAW_BYTE_LEN) + } else { + None + } } pub fn var_index_map_offset_byte_range(&self) -> Option> { - let start = self.var_index_map_offset_byte_start?; - Some(start..start + Offset32::RAW_BYTE_LEN) + if self.version().compatible(1u16) { + let start = self + .clip_list_offset_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| { + self.layer_list_offset_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| { + self.base_glyph_list_offset_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| self.num_layer_records_byte_range().end) + }) + }); + Some(start..start + Offset32::RAW_BYTE_LEN) + } else { + None + } } pub fn item_variation_store_offset_byte_range(&self) -> Option> { - let start = self.item_variation_store_offset_byte_start?; - Some(start..start + Offset32::RAW_BYTE_LEN) - } -} - -impl MinByteRange for ColrMarker { - fn min_byte_range(&self) -> Range { - 0..self.num_layer_records_byte_range().end - } -} - -impl TopLevelTable for Colr<'_> { - /// `COLR` - const TAG: Tag = Tag::new(b"COLR"); -} - -impl<'a> FontRead<'a> for Colr<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - let version: u16 = cursor.read()?; - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - let base_glyph_list_offset_byte_start = version - .compatible(1u16) - .then(|| cursor.position()) - .transpose()?; - version - .compatible(1u16) - .then(|| cursor.advance::()); - let layer_list_offset_byte_start = version - .compatible(1u16) - .then(|| cursor.position()) - .transpose()?; - version - .compatible(1u16) - .then(|| cursor.advance::()); - let clip_list_offset_byte_start = version - .compatible(1u16) - .then(|| cursor.position()) - .transpose()?; - version - .compatible(1u16) - .then(|| cursor.advance::()); - let var_index_map_offset_byte_start = version - .compatible(1u16) - .then(|| cursor.position()) - .transpose()?; - version - .compatible(1u16) - .then(|| cursor.advance::()); - let item_variation_store_offset_byte_start = version - .compatible(1u16) - .then(|| cursor.position()) - .transpose()?; - version - .compatible(1u16) - .then(|| cursor.advance::()); - cursor.finish(ColrMarker { - base_glyph_list_offset_byte_start, - layer_list_offset_byte_start, - clip_list_offset_byte_start, - var_index_map_offset_byte_start, - item_variation_store_offset_byte_start, - }) + if self.version().compatible(1u16) { + let start = self + .var_index_map_offset_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| { + self.clip_list_offset_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| { + self.layer_list_offset_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| { + self.base_glyph_list_offset_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| self.num_layer_records_byte_range().end) + }) + }) + }); + Some(start..start + Offset32::RAW_BYTE_LEN) + } else { + None + } } -} - -/// [COLR (Color)](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#colr-header) table -pub type Colr<'a> = TableRef<'a, ColrMarker>; -#[allow(clippy::needless_lifetimes)] -impl<'a> Colr<'a> { /// Table version number - set to 0 or 1. pub fn version(&self) -> u16 { - let range = self.shape.version_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.version_byte_range(); + unchecked::read_at(self.data, range.start) } /// Number of BaseGlyph records; may be 0 in a version 1 table. pub fn num_base_glyph_records(&self) -> u16 { - let range = self.shape.num_base_glyph_records_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.num_base_glyph_records_byte_range(); + unchecked::read_at(self.data, range.start) } /// Offset to baseGlyphRecords array (may be NULL). pub fn base_glyph_records_offset(&self) -> Nullable { - let range = self.shape.base_glyph_records_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.base_glyph_records_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`base_glyph_records_offset`][Self::base_glyph_records_offset]. @@ -165,8 +170,8 @@ impl<'a> Colr<'a> { /// Offset to layerRecords array (may be NULL). pub fn layer_records_offset(&self) -> Nullable { - let range = self.shape.layer_records_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.layer_records_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`layer_records_offset`][Self::layer_records_offset]. @@ -178,14 +183,14 @@ impl<'a> Colr<'a> { /// Number of Layer records; may be 0 in a version 1 table. pub fn num_layer_records(&self) -> u16 { - let range = self.shape.num_layer_records_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.num_layer_records_byte_range(); + unchecked::read_at(self.data, range.start) } /// Offset to BaseGlyphList table. pub fn base_glyph_list_offset(&self) -> Option> { - let range = self.shape.base_glyph_list_offset_byte_range()?; - Some(self.data.read_at(range.start).unwrap()) + let range = self.base_glyph_list_offset_byte_range()?; + Some(unchecked::read_at(self.data, range.start)) } /// Attempt to resolve [`base_glyph_list_offset`][Self::base_glyph_list_offset]. @@ -196,8 +201,8 @@ impl<'a> Colr<'a> { /// Offset to LayerList table (may be NULL). pub fn layer_list_offset(&self) -> Option> { - let range = self.shape.layer_list_offset_byte_range()?; - Some(self.data.read_at(range.start).unwrap()) + let range = self.layer_list_offset_byte_range()?; + Some(unchecked::read_at(self.data, range.start)) } /// Attempt to resolve [`layer_list_offset`][Self::layer_list_offset]. @@ -208,8 +213,8 @@ impl<'a> Colr<'a> { /// Offset to ClipList table (may be NULL). pub fn clip_list_offset(&self) -> Option> { - let range = self.shape.clip_list_offset_byte_range()?; - Some(self.data.read_at(range.start).unwrap()) + let range = self.clip_list_offset_byte_range()?; + Some(unchecked::read_at(self.data, range.start)) } /// Attempt to resolve [`clip_list_offset`][Self::clip_list_offset]. @@ -220,8 +225,8 @@ impl<'a> Colr<'a> { /// Offset to DeltaSetIndexMap table (may be NULL). pub fn var_index_map_offset(&self) -> Option> { - let range = self.shape.var_index_map_offset_byte_range()?; - Some(self.data.read_at(range.start).unwrap()) + let range = self.var_index_map_offset_byte_range()?; + Some(unchecked::read_at(self.data, range.start)) } /// Attempt to resolve [`var_index_map_offset`][Self::var_index_map_offset]. @@ -232,8 +237,8 @@ impl<'a> Colr<'a> { /// Offset to ItemVariationStore (may be NULL). pub fn item_variation_store_offset(&self) -> Option> { - let range = self.shape.item_variation_store_offset_byte_range()?; - Some(self.data.read_at(range.start).unwrap()) + let range = self.item_variation_store_offset_byte_range()?; + Some(unchecked::read_at(self.data, range.start)) } /// Attempt to resolve [`item_variation_store_offset`][Self::item_variation_store_offset]. @@ -410,23 +415,9 @@ impl<'a> SomeRecord<'a> for Layer { /// [BaseGlyphList](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#baseglyphlist-layerlist-and-cliplist) table #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct BaseGlyphListMarker { - base_glyph_paint_records_byte_len: usize, -} - -impl BaseGlyphListMarker { - pub fn num_base_glyph_paint_records_byte_range(&self) -> Range { - let start = 0; - start..start + u32::RAW_BYTE_LEN - } - - pub fn base_glyph_paint_records_byte_range(&self) -> Range { - let start = self.num_base_glyph_paint_records_byte_range().end; - start..start + self.base_glyph_paint_records_byte_len - } -} +pub struct BaseGlyphListMarker; -impl MinByteRange for BaseGlyphListMarker { +impl<'a> MinByteRange for BaseGlyphList<'a> { fn min_byte_range(&self) -> Range { 0..self.base_glyph_paint_records_byte_range().end } @@ -434,31 +425,44 @@ impl MinByteRange for BaseGlyphListMarker { impl<'a> FontRead<'a> for BaseGlyphList<'a> { fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - let num_base_glyph_paint_records: u32 = cursor.read()?; - let base_glyph_paint_records_byte_len = (num_base_glyph_paint_records as usize) - .checked_mul(BaseGlyphPaint::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(base_glyph_paint_records_byte_len); - cursor.finish(BaseGlyphListMarker { - base_glyph_paint_records_byte_len, + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, }) } } /// [BaseGlyphList](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#baseglyphlist-layerlist-and-cliplist) table -pub type BaseGlyphList<'a> = TableRef<'a, BaseGlyphListMarker>; +pub type BaseGlyphList<'a> = TableRef<'a, BaseGlyphListMarker, ()>; #[allow(clippy::needless_lifetimes)] impl<'a> BaseGlyphList<'a> { + fn base_glyph_paint_records_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.num_base_glyph_paint_records()) as usize) + .checked_mul(BaseGlyphPaint::RAW_BYTE_LEN) + .unwrap() + } + + pub fn num_base_glyph_paint_records_byte_range(&self) -> Range { + let start = 0; + start..start + u32::RAW_BYTE_LEN + } + + pub fn base_glyph_paint_records_byte_range(&self) -> Range { + let start = self.num_base_glyph_paint_records_byte_range().end; + start..start + self.base_glyph_paint_records_byte_len(start) + } + pub fn num_base_glyph_paint_records(&self) -> u32 { - let range = self.shape.num_base_glyph_paint_records_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.num_base_glyph_paint_records_byte_range(); + unchecked::read_at(self.data, range.start) } pub fn base_glyph_paint_records(&self) -> &'a [BaseGlyphPaint] { - let range = self.shape.base_glyph_paint_records_byte_range(); - self.data.read_array(range).unwrap() + let range = self.base_glyph_paint_records_byte_range(); + unchecked::read_array(self.data, range) } } @@ -550,23 +554,9 @@ impl<'a> SomeRecord<'a> for BaseGlyphPaint { /// [LayerList](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#baseglyphlist-layerlist-and-cliplist) table #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct LayerListMarker { - paint_offsets_byte_len: usize, -} - -impl LayerListMarker { - pub fn num_layers_byte_range(&self) -> Range { - let start = 0; - start..start + u32::RAW_BYTE_LEN - } - - pub fn paint_offsets_byte_range(&self) -> Range { - let start = self.num_layers_byte_range().end; - start..start + self.paint_offsets_byte_len - } -} +pub struct LayerListMarker; -impl MinByteRange for LayerListMarker { +impl<'a> MinByteRange for LayerList<'a> { fn min_byte_range(&self) -> Range { 0..self.paint_offsets_byte_range().end } @@ -574,32 +564,45 @@ impl MinByteRange for LayerListMarker { impl<'a> FontRead<'a> for LayerList<'a> { fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - let num_layers: u32 = cursor.read()?; - let paint_offsets_byte_len = (num_layers as usize) - .checked_mul(Offset32::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(paint_offsets_byte_len); - cursor.finish(LayerListMarker { - paint_offsets_byte_len, + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, }) } } /// [LayerList](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#baseglyphlist-layerlist-and-cliplist) table -pub type LayerList<'a> = TableRef<'a, LayerListMarker>; +pub type LayerList<'a> = TableRef<'a, LayerListMarker, ()>; #[allow(clippy::needless_lifetimes)] impl<'a> LayerList<'a> { + fn paint_offsets_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.num_layers()) as usize) + .checked_mul(Offset32::RAW_BYTE_LEN) + .unwrap() + } + + pub fn num_layers_byte_range(&self) -> Range { + let start = 0; + start..start + u32::RAW_BYTE_LEN + } + + pub fn paint_offsets_byte_range(&self) -> Range { + let start = self.num_layers_byte_range().end; + start..start + self.paint_offsets_byte_len(start) + } + pub fn num_layers(&self) -> u32 { - let range = self.shape.num_layers_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.num_layers_byte_range(); + unchecked::read_at(self.data, range.start) } /// Offsets to Paint tables. pub fn paint_offsets(&self) -> &'a [BigEndian] { - let range = self.shape.paint_offsets_byte_range(); - self.data.read_array(range).unwrap() + let range = self.paint_offsets_byte_range(); + unchecked::read_array(self.data, range) } /// A dynamically resolving wrapper for [`paint_offsets`][Self::paint_offsets]. @@ -648,11 +651,36 @@ impl<'a> std::fmt::Debug for LayerList<'a> { /// [ClipList](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#baseglyphlist-layerlist-and-cliplist) table #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct ClipListMarker { - clips_byte_len: usize, +pub struct ClipListMarker; + +impl<'a> MinByteRange for ClipList<'a> { + fn min_byte_range(&self) -> Range { + 0..self.clips_byte_range().end + } +} + +impl<'a> FontRead<'a> for ClipList<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } } -impl ClipListMarker { +/// [ClipList](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#baseglyphlist-layerlist-and-cliplist) table +pub type ClipList<'a> = TableRef<'a, ClipListMarker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> ClipList<'a> { + fn clips_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.num_clips()) as usize) + .checked_mul(Clip::RAW_BYTE_LEN) + .unwrap() + } + pub fn format_byte_range(&self) -> Range { let start = 0; start..start + u8::RAW_BYTE_LEN @@ -665,50 +693,25 @@ impl ClipListMarker { pub fn clips_byte_range(&self) -> Range { let start = self.num_clips_byte_range().end; - start..start + self.clips_byte_len - } -} - -impl MinByteRange for ClipListMarker { - fn min_byte_range(&self) -> Range { - 0..self.clips_byte_range().end - } -} - -impl<'a> FontRead<'a> for ClipList<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - let num_clips: u32 = cursor.read()?; - let clips_byte_len = (num_clips as usize) - .checked_mul(Clip::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(clips_byte_len); - cursor.finish(ClipListMarker { clips_byte_len }) + start..start + self.clips_byte_len(start) } -} - -/// [ClipList](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#baseglyphlist-layerlist-and-cliplist) table -pub type ClipList<'a> = TableRef<'a, ClipListMarker>; -#[allow(clippy::needless_lifetimes)] -impl<'a> ClipList<'a> { /// Set to 1. pub fn format(&self) -> u8 { - let range = self.shape.format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Number of Clip records. pub fn num_clips(&self) -> u32 { - let range = self.shape.num_clips_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.num_clips_byte_range(); + unchecked::read_at(self.data, range.start) } /// Clip records. Sorted by startGlyphID. pub fn clips(&self) -> &'a [Clip] { - let range = self.shape.clips_byte_range(); - self.data.read_array(range).unwrap() + let range = self.clips_byte_range(); + unchecked::read_array(self.data, range) } } @@ -915,9 +918,29 @@ impl Format for ClipBoxFormat1Marker { /// [ClipBoxFormat1](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#baseglyphlist-layerlist-and-cliplist) record #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct ClipBoxFormat1Marker {} +pub struct ClipBoxFormat1Marker; + +impl<'a> MinByteRange for ClipBoxFormat1<'a> { + fn min_byte_range(&self) -> Range { + 0..self.y_max_byte_range().end + } +} + +impl<'a> FontRead<'a> for ClipBoxFormat1<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// [ClipBoxFormat1](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#baseglyphlist-layerlist-and-cliplist) record +pub type ClipBoxFormat1<'a> = TableRef<'a, ClipBoxFormat1Marker, ()>; -impl ClipBoxFormat1Marker { +#[allow(clippy::needless_lifetimes)] +impl<'a> ClipBoxFormat1<'a> { pub fn format_byte_range(&self) -> Range { let start = 0; start..start + u8::RAW_BYTE_LEN @@ -942,59 +965,35 @@ impl ClipBoxFormat1Marker { let start = self.x_max_byte_range().end; start..start + FWord::RAW_BYTE_LEN } -} - -impl MinByteRange for ClipBoxFormat1Marker { - fn min_byte_range(&self) -> Range { - 0..self.y_max_byte_range().end - } -} - -impl<'a> FontRead<'a> for ClipBoxFormat1<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.finish(ClipBoxFormat1Marker {}) - } -} - -/// [ClipBoxFormat1](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#baseglyphlist-layerlist-and-cliplist) record -pub type ClipBoxFormat1<'a> = TableRef<'a, ClipBoxFormat1Marker>; -#[allow(clippy::needless_lifetimes)] -impl<'a> ClipBoxFormat1<'a> { /// Set to 1. pub fn format(&self) -> u8 { - let range = self.shape.format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Minimum x of clip box. pub fn x_min(&self) -> FWord { - let range = self.shape.x_min_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.x_min_byte_range(); + unchecked::read_at(self.data, range.start) } /// Minimum y of clip box. pub fn y_min(&self) -> FWord { - let range = self.shape.y_min_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.y_min_byte_range(); + unchecked::read_at(self.data, range.start) } /// Maximum x of clip box. pub fn x_max(&self) -> FWord { - let range = self.shape.x_max_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.x_max_byte_range(); + unchecked::read_at(self.data, range.start) } /// Maximum y of clip box. pub fn y_max(&self) -> FWord { - let range = self.shape.y_max_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.y_max_byte_range(); + unchecked::read_at(self.data, range.start) } } @@ -1030,9 +1029,29 @@ impl Format for ClipBoxFormat2Marker { /// [ClipBoxFormat2](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#baseglyphlist-layerlist-and-cliplist) record #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct ClipBoxFormat2Marker {} +pub struct ClipBoxFormat2Marker; + +impl<'a> MinByteRange for ClipBoxFormat2<'a> { + fn min_byte_range(&self) -> Range { + 0..self.var_index_base_byte_range().end + } +} + +impl<'a> FontRead<'a> for ClipBoxFormat2<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// [ClipBoxFormat2](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#baseglyphlist-layerlist-and-cliplist) record +pub type ClipBoxFormat2<'a> = TableRef<'a, ClipBoxFormat2Marker, ()>; -impl ClipBoxFormat2Marker { +#[allow(clippy::needless_lifetimes)] +impl<'a> ClipBoxFormat2<'a> { pub fn format_byte_range(&self) -> Range { let start = 0; start..start + u8::RAW_BYTE_LEN @@ -1062,66 +1081,41 @@ impl ClipBoxFormat2Marker { let start = self.y_max_byte_range().end; start..start + u32::RAW_BYTE_LEN } -} - -impl MinByteRange for ClipBoxFormat2Marker { - fn min_byte_range(&self) -> Range { - 0..self.var_index_base_byte_range().end - } -} - -impl<'a> FontRead<'a> for ClipBoxFormat2<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.finish(ClipBoxFormat2Marker {}) - } -} -/// [ClipBoxFormat2](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#baseglyphlist-layerlist-and-cliplist) record -pub type ClipBoxFormat2<'a> = TableRef<'a, ClipBoxFormat2Marker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> ClipBoxFormat2<'a> { /// Set to 2. pub fn format(&self) -> u8 { - let range = self.shape.format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Minimum x of clip box. For variation, use varIndexBase + 0. pub fn x_min(&self) -> FWord { - let range = self.shape.x_min_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.x_min_byte_range(); + unchecked::read_at(self.data, range.start) } /// Minimum y of clip box. For variation, use varIndexBase + 1. pub fn y_min(&self) -> FWord { - let range = self.shape.y_min_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.y_min_byte_range(); + unchecked::read_at(self.data, range.start) } /// Maximum x of clip box. For variation, use varIndexBase + 2. pub fn x_max(&self) -> FWord { - let range = self.shape.x_max_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.x_max_byte_range(); + unchecked::read_at(self.data, range.start) } /// Maximum y of clip box. For variation, use varIndexBase + 3. pub fn y_max(&self) -> FWord { - let range = self.shape.y_max_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.y_max_byte_range(); + unchecked::read_at(self.data, range.start) } /// Base index into DeltaSetIndexMap. pub fn var_index_base(&self) -> u32 { - let range = self.shape.var_index_base_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.var_index_base_byte_range(); + unchecked::read_at(self.data, range.start) } } @@ -1355,28 +1349,9 @@ impl<'a> SomeRecord<'a> for VarColorStop { /// [ColorLine](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#color-references-colorstop-and-colorline) table #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct ColorLineMarker { - color_stops_byte_len: usize, -} - -impl ColorLineMarker { - pub fn extend_byte_range(&self) -> Range { - let start = 0; - start..start + Extend::RAW_BYTE_LEN - } - - pub fn num_stops_byte_range(&self) -> Range { - let start = self.extend_byte_range().end; - start..start + u16::RAW_BYTE_LEN - } - - pub fn color_stops_byte_range(&self) -> Range { - let start = self.num_stops_byte_range().end; - start..start + self.color_stops_byte_len - } -} +pub struct ColorLineMarker; -impl MinByteRange for ColorLineMarker { +impl<'a> MinByteRange for ColorLine<'a> { fn min_byte_range(&self) -> Range { 0..self.color_stops_byte_range().end } @@ -1384,39 +1359,56 @@ impl MinByteRange for ColorLineMarker { impl<'a> FontRead<'a> for ColorLine<'a> { fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - let num_stops: u16 = cursor.read()?; - let color_stops_byte_len = (num_stops as usize) - .checked_mul(ColorStop::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(color_stops_byte_len); - cursor.finish(ColorLineMarker { - color_stops_byte_len, + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, }) } } /// [ColorLine](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#color-references-colorstop-and-colorline) table -pub type ColorLine<'a> = TableRef<'a, ColorLineMarker>; +pub type ColorLine<'a> = TableRef<'a, ColorLineMarker, ()>; #[allow(clippy::needless_lifetimes)] impl<'a> ColorLine<'a> { + fn color_stops_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.num_stops()) as usize) + .checked_mul(ColorStop::RAW_BYTE_LEN) + .unwrap() + } + + pub fn extend_byte_range(&self) -> Range { + let start = 0; + start..start + Extend::RAW_BYTE_LEN + } + + pub fn num_stops_byte_range(&self) -> Range { + let start = self.extend_byte_range().end; + start..start + u16::RAW_BYTE_LEN + } + + pub fn color_stops_byte_range(&self) -> Range { + let start = self.num_stops_byte_range().end; + start..start + self.color_stops_byte_len(start) + } + /// An Extend enum value. pub fn extend(&self) -> Extend { - let range = self.shape.extend_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.extend_byte_range(); + unchecked::read_at(self.data, range.start) } /// Number of ColorStop records. pub fn num_stops(&self) -> u16 { - let range = self.shape.num_stops_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.num_stops_byte_range(); + unchecked::read_at(self.data, range.start) } pub fn color_stops(&self) -> &'a [ColorStop] { - let range = self.shape.color_stops_byte_range(); - self.data.read_array(range).unwrap() + let range = self.color_stops_byte_range(); + unchecked::read_array(self.data, range) } } @@ -1453,28 +1445,9 @@ impl<'a> std::fmt::Debug for ColorLine<'a> { /// [VarColorLine](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#color-references-colorstop-and-colorline) table #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct VarColorLineMarker { - color_stops_byte_len: usize, -} - -impl VarColorLineMarker { - pub fn extend_byte_range(&self) -> Range { - let start = 0; - start..start + Extend::RAW_BYTE_LEN - } - - pub fn num_stops_byte_range(&self) -> Range { - let start = self.extend_byte_range().end; - start..start + u16::RAW_BYTE_LEN - } - - pub fn color_stops_byte_range(&self) -> Range { - let start = self.num_stops_byte_range().end; - start..start + self.color_stops_byte_len - } -} +pub struct VarColorLineMarker; -impl MinByteRange for VarColorLineMarker { +impl<'a> MinByteRange for VarColorLine<'a> { fn min_byte_range(&self) -> Range { 0..self.color_stops_byte_range().end } @@ -1482,41 +1455,58 @@ impl MinByteRange for VarColorLineMarker { impl<'a> FontRead<'a> for VarColorLine<'a> { fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - let num_stops: u16 = cursor.read()?; - let color_stops_byte_len = (num_stops as usize) - .checked_mul(VarColorStop::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(color_stops_byte_len); - cursor.finish(VarColorLineMarker { - color_stops_byte_len, + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, }) } } /// [VarColorLine](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#color-references-colorstop-and-colorline) table -pub type VarColorLine<'a> = TableRef<'a, VarColorLineMarker>; +pub type VarColorLine<'a> = TableRef<'a, VarColorLineMarker, ()>; #[allow(clippy::needless_lifetimes)] impl<'a> VarColorLine<'a> { - /// An Extend enum value. - pub fn extend(&self) -> Extend { - let range = self.shape.extend_byte_range(); - self.data.read_at(range.start).unwrap() + fn color_stops_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.num_stops()) as usize) + .checked_mul(VarColorStop::RAW_BYTE_LEN) + .unwrap() } - /// Number of ColorStop records. - pub fn num_stops(&self) -> u16 { - let range = self.shape.num_stops_byte_range(); - self.data.read_at(range.start).unwrap() + pub fn extend_byte_range(&self) -> Range { + let start = 0; + start..start + Extend::RAW_BYTE_LEN } - /// Allows for variations. - pub fn color_stops(&self) -> &'a [VarColorStop] { - let range = self.shape.color_stops_byte_range(); - self.data.read_array(range).unwrap() - } + pub fn num_stops_byte_range(&self) -> Range { + let start = self.extend_byte_range().end; + start..start + u16::RAW_BYTE_LEN + } + + pub fn color_stops_byte_range(&self) -> Range { + let start = self.num_stops_byte_range().end; + start..start + self.color_stops_byte_len(start) + } + + /// An Extend enum value. + pub fn extend(&self) -> Extend { + let range = self.extend_byte_range(); + unchecked::read_at(self.data, range.start) + } + + /// Number of ColorStop records. + pub fn num_stops(&self) -> u16 { + let range = self.num_stops_byte_range(); + unchecked::read_at(self.data, range.start) + } + + /// Allows for variations. + pub fn color_stops(&self) -> &'a [VarColorStop] { + let range = self.color_stops_byte_range(); + unchecked::read_array(self.data, range) + } } #[cfg(feature = "experimental_traverse")] @@ -1877,9 +1867,29 @@ impl Format for PaintColrLayersMarker { /// [PaintColrLayers](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#format-1-paintcolrlayers) table #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct PaintColrLayersMarker {} +pub struct PaintColrLayersMarker; + +impl<'a> MinByteRange for PaintColrLayers<'a> { + fn min_byte_range(&self) -> Range { + 0..self.first_layer_index_byte_range().end + } +} + +impl<'a> FontRead<'a> for PaintColrLayers<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} -impl PaintColrLayersMarker { +/// [PaintColrLayers](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#format-1-paintcolrlayers) table +pub type PaintColrLayers<'a> = TableRef<'a, PaintColrLayersMarker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> PaintColrLayers<'a> { pub fn format_byte_range(&self) -> Range { let start = 0; start..start + u8::RAW_BYTE_LEN @@ -1894,45 +1904,23 @@ impl PaintColrLayersMarker { let start = self.num_layers_byte_range().end; start..start + u32::RAW_BYTE_LEN } -} - -impl MinByteRange for PaintColrLayersMarker { - fn min_byte_range(&self) -> Range { - 0..self.first_layer_index_byte_range().end - } -} - -impl<'a> FontRead<'a> for PaintColrLayers<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.finish(PaintColrLayersMarker {}) - } -} - -/// [PaintColrLayers](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#format-1-paintcolrlayers) table -pub type PaintColrLayers<'a> = TableRef<'a, PaintColrLayersMarker>; -#[allow(clippy::needless_lifetimes)] -impl<'a> PaintColrLayers<'a> { /// Set to 1. pub fn format(&self) -> u8 { - let range = self.shape.format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Number of offsets to paint tables to read from LayerList. pub fn num_layers(&self) -> u8 { - let range = self.shape.num_layers_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.num_layers_byte_range(); + unchecked::read_at(self.data, range.start) } /// Index (base 0) into the LayerList. pub fn first_layer_index(&self) -> u32 { - let range = self.shape.first_layer_index_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.first_layer_index_byte_range(); + unchecked::read_at(self.data, range.start) } } @@ -1966,9 +1954,29 @@ impl Format for PaintSolidMarker { /// [PaintSolid](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-2-and-3-paintsolid-paintvarsolid) table #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct PaintSolidMarker {} +pub struct PaintSolidMarker; + +impl<'a> MinByteRange for PaintSolid<'a> { + fn min_byte_range(&self) -> Range { + 0..self.alpha_byte_range().end + } +} + +impl<'a> FontRead<'a> for PaintSolid<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// [PaintSolid](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-2-and-3-paintsolid-paintvarsolid) table +pub type PaintSolid<'a> = TableRef<'a, PaintSolidMarker, ()>; -impl PaintSolidMarker { +#[allow(clippy::needless_lifetimes)] +impl<'a> PaintSolid<'a> { pub fn format_byte_range(&self) -> Range { let start = 0; start..start + u8::RAW_BYTE_LEN @@ -1983,45 +1991,23 @@ impl PaintSolidMarker { let start = self.palette_index_byte_range().end; start..start + F2Dot14::RAW_BYTE_LEN } -} - -impl MinByteRange for PaintSolidMarker { - fn min_byte_range(&self) -> Range { - 0..self.alpha_byte_range().end - } -} - -impl<'a> FontRead<'a> for PaintSolid<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.finish(PaintSolidMarker {}) - } -} - -/// [PaintSolid](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-2-and-3-paintsolid-paintvarsolid) table -pub type PaintSolid<'a> = TableRef<'a, PaintSolidMarker>; -#[allow(clippy::needless_lifetimes)] -impl<'a> PaintSolid<'a> { /// Set to 2. pub fn format(&self) -> u8 { - let range = self.shape.format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Index for a CPAL palette entry. pub fn palette_index(&self) -> u16 { - let range = self.shape.palette_index_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.palette_index_byte_range(); + unchecked::read_at(self.data, range.start) } /// Alpha value. pub fn alpha(&self) -> F2Dot14 { - let range = self.shape.alpha_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.alpha_byte_range(); + unchecked::read_at(self.data, range.start) } } @@ -2055,9 +2041,29 @@ impl Format for PaintVarSolidMarker { /// [PaintVarSolid](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-2-and-3-paintsolid-paintvarsolid) table #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct PaintVarSolidMarker {} +pub struct PaintVarSolidMarker; + +impl<'a> MinByteRange for PaintVarSolid<'a> { + fn min_byte_range(&self) -> Range { + 0..self.var_index_base_byte_range().end + } +} + +impl<'a> FontRead<'a> for PaintVarSolid<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// [PaintVarSolid](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-2-and-3-paintsolid-paintvarsolid) table +pub type PaintVarSolid<'a> = TableRef<'a, PaintVarSolidMarker, ()>; -impl PaintVarSolidMarker { +#[allow(clippy::needless_lifetimes)] +impl<'a> PaintVarSolid<'a> { pub fn format_byte_range(&self) -> Range { let start = 0; start..start + u8::RAW_BYTE_LEN @@ -2077,52 +2083,29 @@ impl PaintVarSolidMarker { let start = self.alpha_byte_range().end; start..start + u32::RAW_BYTE_LEN } -} - -impl MinByteRange for PaintVarSolidMarker { - fn min_byte_range(&self) -> Range { - 0..self.var_index_base_byte_range().end - } -} - -impl<'a> FontRead<'a> for PaintVarSolid<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.finish(PaintVarSolidMarker {}) - } -} - -/// [PaintVarSolid](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-2-and-3-paintsolid-paintvarsolid) table -pub type PaintVarSolid<'a> = TableRef<'a, PaintVarSolidMarker>; -#[allow(clippy::needless_lifetimes)] -impl<'a> PaintVarSolid<'a> { /// Set to 3. pub fn format(&self) -> u8 { - let range = self.shape.format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Index for a CPAL palette entry. pub fn palette_index(&self) -> u16 { - let range = self.shape.palette_index_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.palette_index_byte_range(); + unchecked::read_at(self.data, range.start) } /// Alpha value. For variation, use varIndexBase + 0. pub fn alpha(&self) -> F2Dot14 { - let range = self.shape.alpha_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.alpha_byte_range(); + unchecked::read_at(self.data, range.start) } /// Base index into DeltaSetIndexMap. pub fn var_index_base(&self) -> u32 { - let range = self.shape.var_index_base_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.var_index_base_byte_range(); + unchecked::read_at(self.data, range.start) } } @@ -2157,9 +2140,29 @@ impl Format for PaintLinearGradientMarker { /// [PaintLinearGradient](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-4-and-5-paintlineargradient-paintvarlineargradient) table #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct PaintLinearGradientMarker {} +pub struct PaintLinearGradientMarker; + +impl<'a> MinByteRange for PaintLinearGradient<'a> { + fn min_byte_range(&self) -> Range { + 0..self.y2_byte_range().end + } +} + +impl<'a> FontRead<'a> for PaintLinearGradient<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// [PaintLinearGradient](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-4-and-5-paintlineargradient-paintvarlineargradient) table +pub type PaintLinearGradient<'a> = TableRef<'a, PaintLinearGradientMarker, ()>; -impl PaintLinearGradientMarker { +#[allow(clippy::needless_lifetimes)] +impl<'a> PaintLinearGradient<'a> { pub fn format_byte_range(&self) -> Range { let start = 0; start..start + u8::RAW_BYTE_LEN @@ -2199,44 +2202,17 @@ impl PaintLinearGradientMarker { let start = self.x2_byte_range().end; start..start + FWord::RAW_BYTE_LEN } -} - -impl MinByteRange for PaintLinearGradientMarker { - fn min_byte_range(&self) -> Range { - 0..self.y2_byte_range().end - } -} - -impl<'a> FontRead<'a> for PaintLinearGradient<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.finish(PaintLinearGradientMarker {}) - } -} -/// [PaintLinearGradient](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-4-and-5-paintlineargradient-paintvarlineargradient) table -pub type PaintLinearGradient<'a> = TableRef<'a, PaintLinearGradientMarker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> PaintLinearGradient<'a> { /// Set to 4. pub fn format(&self) -> u8 { - let range = self.shape.format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Offset to ColorLine table. pub fn color_line_offset(&self) -> Offset24 { - let range = self.shape.color_line_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.color_line_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`color_line_offset`][Self::color_line_offset]. @@ -2247,38 +2223,38 @@ impl<'a> PaintLinearGradient<'a> { /// Start point (p₀) x coordinate. pub fn x0(&self) -> FWord { - let range = self.shape.x0_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.x0_byte_range(); + unchecked::read_at(self.data, range.start) } /// Start point (p₀) y coordinate. pub fn y0(&self) -> FWord { - let range = self.shape.y0_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.y0_byte_range(); + unchecked::read_at(self.data, range.start) } /// End point (p₁) x coordinate. pub fn x1(&self) -> FWord { - let range = self.shape.x1_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.x1_byte_range(); + unchecked::read_at(self.data, range.start) } /// End point (p₁) y coordinate. pub fn y1(&self) -> FWord { - let range = self.shape.y1_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.y1_byte_range(); + unchecked::read_at(self.data, range.start) } /// Rotation point (p₂) x coordinate. pub fn x2(&self) -> FWord { - let range = self.shape.x2_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.x2_byte_range(); + unchecked::read_at(self.data, range.start) } /// Rotation point (p₂) y coordinate. pub fn y2(&self) -> FWord { - let range = self.shape.y2_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.y2_byte_range(); + unchecked::read_at(self.data, range.start) } } @@ -2320,9 +2296,29 @@ impl Format for PaintVarLinearGradientMarker { /// [PaintVarLinearGradient](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-4-and-5-paintlineargradient-paintvarlineargradient) table #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct PaintVarLinearGradientMarker {} +pub struct PaintVarLinearGradientMarker; -impl PaintVarLinearGradientMarker { +impl<'a> MinByteRange for PaintVarLinearGradient<'a> { + fn min_byte_range(&self) -> Range { + 0..self.var_index_base_byte_range().end + } +} + +impl<'a> FontRead<'a> for PaintVarLinearGradient<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// [PaintVarLinearGradient](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-4-and-5-paintlineargradient-paintvarlineargradient) table +pub type PaintVarLinearGradient<'a> = TableRef<'a, PaintVarLinearGradientMarker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> PaintVarLinearGradient<'a> { pub fn format_byte_range(&self) -> Range { let start = 0; start..start + u8::RAW_BYTE_LEN @@ -2367,45 +2363,17 @@ impl PaintVarLinearGradientMarker { let start = self.y2_byte_range().end; start..start + u32::RAW_BYTE_LEN } -} - -impl MinByteRange for PaintVarLinearGradientMarker { - fn min_byte_range(&self) -> Range { - 0..self.var_index_base_byte_range().end - } -} - -impl<'a> FontRead<'a> for PaintVarLinearGradient<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.finish(PaintVarLinearGradientMarker {}) - } -} - -/// [PaintVarLinearGradient](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-4-and-5-paintlineargradient-paintvarlineargradient) table -pub type PaintVarLinearGradient<'a> = TableRef<'a, PaintVarLinearGradientMarker>; -#[allow(clippy::needless_lifetimes)] -impl<'a> PaintVarLinearGradient<'a> { /// Set to 5. pub fn format(&self) -> u8 { - let range = self.shape.format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Offset to VarColorLine table. pub fn color_line_offset(&self) -> Offset24 { - let range = self.shape.color_line_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.color_line_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`color_line_offset`][Self::color_line_offset]. @@ -2417,49 +2385,49 @@ impl<'a> PaintVarLinearGradient<'a> { /// Start point (p₀) x coordinate. For variation, use /// varIndexBase + 0. pub fn x0(&self) -> FWord { - let range = self.shape.x0_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.x0_byte_range(); + unchecked::read_at(self.data, range.start) } /// Start point (p₀) y coordinate. For variation, use /// varIndexBase + 1. pub fn y0(&self) -> FWord { - let range = self.shape.y0_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.y0_byte_range(); + unchecked::read_at(self.data, range.start) } /// End point (p₁) x coordinate. For variation, use varIndexBase /// + 2. pub fn x1(&self) -> FWord { - let range = self.shape.x1_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.x1_byte_range(); + unchecked::read_at(self.data, range.start) } /// End point (p₁) y coordinate. For variation, use varIndexBase /// + 3. pub fn y1(&self) -> FWord { - let range = self.shape.y1_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.y1_byte_range(); + unchecked::read_at(self.data, range.start) } /// Rotation point (p₂) x coordinate. For variation, use /// varIndexBase + 4. pub fn x2(&self) -> FWord { - let range = self.shape.x2_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.x2_byte_range(); + unchecked::read_at(self.data, range.start) } /// Rotation point (p₂) y coordinate. For variation, use /// varIndexBase + 5. pub fn y2(&self) -> FWord { - let range = self.shape.y2_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.y2_byte_range(); + unchecked::read_at(self.data, range.start) } /// Base index into DeltaSetIndexMap. pub fn var_index_base(&self) -> u32 { - let range = self.shape.var_index_base_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.var_index_base_byte_range(); + unchecked::read_at(self.data, range.start) } } @@ -2502,9 +2470,29 @@ impl Format for PaintRadialGradientMarker { /// [PaintRadialGradient](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-6-and-7-paintradialgradient-paintvarradialgradient) table #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct PaintRadialGradientMarker {} +pub struct PaintRadialGradientMarker; + +impl<'a> MinByteRange for PaintRadialGradient<'a> { + fn min_byte_range(&self) -> Range { + 0..self.radius1_byte_range().end + } +} + +impl<'a> FontRead<'a> for PaintRadialGradient<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// [PaintRadialGradient](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-6-and-7-paintradialgradient-paintvarradialgradient) table +pub type PaintRadialGradient<'a> = TableRef<'a, PaintRadialGradientMarker, ()>; -impl PaintRadialGradientMarker { +#[allow(clippy::needless_lifetimes)] +impl<'a> PaintRadialGradient<'a> { pub fn format_byte_range(&self) -> Range { let start = 0; start..start + u8::RAW_BYTE_LEN @@ -2544,44 +2532,17 @@ impl PaintRadialGradientMarker { let start = self.y1_byte_range().end; start..start + UfWord::RAW_BYTE_LEN } -} - -impl MinByteRange for PaintRadialGradientMarker { - fn min_byte_range(&self) -> Range { - 0..self.radius1_byte_range().end - } -} - -impl<'a> FontRead<'a> for PaintRadialGradient<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.finish(PaintRadialGradientMarker {}) - } -} - -/// [PaintRadialGradient](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-6-and-7-paintradialgradient-paintvarradialgradient) table -pub type PaintRadialGradient<'a> = TableRef<'a, PaintRadialGradientMarker>; -#[allow(clippy::needless_lifetimes)] -impl<'a> PaintRadialGradient<'a> { /// Set to 6. pub fn format(&self) -> u8 { - let range = self.shape.format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Offset to ColorLine table. pub fn color_line_offset(&self) -> Offset24 { - let range = self.shape.color_line_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.color_line_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`color_line_offset`][Self::color_line_offset]. @@ -2592,38 +2553,38 @@ impl<'a> PaintRadialGradient<'a> { /// Start circle center x coordinate. pub fn x0(&self) -> FWord { - let range = self.shape.x0_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.x0_byte_range(); + unchecked::read_at(self.data, range.start) } /// Start circle center y coordinate. pub fn y0(&self) -> FWord { - let range = self.shape.y0_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.y0_byte_range(); + unchecked::read_at(self.data, range.start) } /// Start circle radius. pub fn radius0(&self) -> UfWord { - let range = self.shape.radius0_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.radius0_byte_range(); + unchecked::read_at(self.data, range.start) } /// End circle center x coordinate. pub fn x1(&self) -> FWord { - let range = self.shape.x1_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.x1_byte_range(); + unchecked::read_at(self.data, range.start) } /// End circle center y coordinate. pub fn y1(&self) -> FWord { - let range = self.shape.y1_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.y1_byte_range(); + unchecked::read_at(self.data, range.start) } /// End circle radius. pub fn radius1(&self) -> UfWord { - let range = self.shape.radius1_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.radius1_byte_range(); + unchecked::read_at(self.data, range.start) } } @@ -2665,9 +2626,29 @@ impl Format for PaintVarRadialGradientMarker { /// [PaintVarRadialGradient](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-6-and-7-paintradialgradient-paintvarradialgradient) table #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct PaintVarRadialGradientMarker {} +pub struct PaintVarRadialGradientMarker; + +impl<'a> MinByteRange for PaintVarRadialGradient<'a> { + fn min_byte_range(&self) -> Range { + 0..self.var_index_base_byte_range().end + } +} + +impl<'a> FontRead<'a> for PaintVarRadialGradient<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// [PaintVarRadialGradient](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-6-and-7-paintradialgradient-paintvarradialgradient) table +pub type PaintVarRadialGradient<'a> = TableRef<'a, PaintVarRadialGradientMarker, ()>; -impl PaintVarRadialGradientMarker { +#[allow(clippy::needless_lifetimes)] +impl<'a> PaintVarRadialGradient<'a> { pub fn format_byte_range(&self) -> Range { let start = 0; start..start + u8::RAW_BYTE_LEN @@ -2712,45 +2693,17 @@ impl PaintVarRadialGradientMarker { let start = self.radius1_byte_range().end; start..start + u32::RAW_BYTE_LEN } -} - -impl MinByteRange for PaintVarRadialGradientMarker { - fn min_byte_range(&self) -> Range { - 0..self.var_index_base_byte_range().end - } -} - -impl<'a> FontRead<'a> for PaintVarRadialGradient<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.finish(PaintVarRadialGradientMarker {}) - } -} - -/// [PaintVarRadialGradient](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-6-and-7-paintradialgradient-paintvarradialgradient) table -pub type PaintVarRadialGradient<'a> = TableRef<'a, PaintVarRadialGradientMarker>; -#[allow(clippy::needless_lifetimes)] -impl<'a> PaintVarRadialGradient<'a> { /// Set to 7. pub fn format(&self) -> u8 { - let range = self.shape.format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Offset to VarColorLine table. pub fn color_line_offset(&self) -> Offset24 { - let range = self.shape.color_line_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.color_line_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`color_line_offset`][Self::color_line_offset]. @@ -2762,47 +2715,47 @@ impl<'a> PaintVarRadialGradient<'a> { /// Start circle center x coordinate. For variation, use /// varIndexBase + 0. pub fn x0(&self) -> FWord { - let range = self.shape.x0_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.x0_byte_range(); + unchecked::read_at(self.data, range.start) } /// Start circle center y coordinate. For variation, use /// varIndexBase + 1. pub fn y0(&self) -> FWord { - let range = self.shape.y0_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.y0_byte_range(); + unchecked::read_at(self.data, range.start) } /// Start circle radius. For variation, use varIndexBase + 2. pub fn radius0(&self) -> UfWord { - let range = self.shape.radius0_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.radius0_byte_range(); + unchecked::read_at(self.data, range.start) } /// End circle center x coordinate. For variation, use varIndexBase /// + 3. pub fn x1(&self) -> FWord { - let range = self.shape.x1_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.x1_byte_range(); + unchecked::read_at(self.data, range.start) } /// End circle center y coordinate. For variation, use varIndexBase /// + 4. pub fn y1(&self) -> FWord { - let range = self.shape.y1_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.y1_byte_range(); + unchecked::read_at(self.data, range.start) } /// End circle radius. For variation, use varIndexBase + 5. pub fn radius1(&self) -> UfWord { - let range = self.shape.radius1_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.radius1_byte_range(); + unchecked::read_at(self.data, range.start) } /// Base index into DeltaSetIndexMap. pub fn var_index_base(&self) -> u32 { - let range = self.shape.var_index_base_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.var_index_base_byte_range(); + unchecked::read_at(self.data, range.start) } } @@ -2845,9 +2798,29 @@ impl Format for PaintSweepGradientMarker { /// [PaintSweepGradient](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-8-and-9-paintsweepgradient-paintvarsweepgradient) table #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct PaintSweepGradientMarker {} +pub struct PaintSweepGradientMarker; + +impl<'a> MinByteRange for PaintSweepGradient<'a> { + fn min_byte_range(&self) -> Range { + 0..self.end_angle_byte_range().end + } +} + +impl<'a> FontRead<'a> for PaintSweepGradient<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// [PaintSweepGradient](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-8-and-9-paintsweepgradient-paintvarsweepgradient) table +pub type PaintSweepGradient<'a> = TableRef<'a, PaintSweepGradientMarker, ()>; -impl PaintSweepGradientMarker { +#[allow(clippy::needless_lifetimes)] +impl<'a> PaintSweepGradient<'a> { pub fn format_byte_range(&self) -> Range { let start = 0; start..start + u8::RAW_BYTE_LEN @@ -2877,42 +2850,17 @@ impl PaintSweepGradientMarker { let start = self.start_angle_byte_range().end; start..start + F2Dot14::RAW_BYTE_LEN } -} -impl MinByteRange for PaintSweepGradientMarker { - fn min_byte_range(&self) -> Range { - 0..self.end_angle_byte_range().end - } -} - -impl<'a> FontRead<'a> for PaintSweepGradient<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.finish(PaintSweepGradientMarker {}) - } -} - -/// [PaintSweepGradient](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-8-and-9-paintsweepgradient-paintvarsweepgradient) table -pub type PaintSweepGradient<'a> = TableRef<'a, PaintSweepGradientMarker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> PaintSweepGradient<'a> { /// Set to 8. pub fn format(&self) -> u8 { - let range = self.shape.format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Offset to ColorLine table. pub fn color_line_offset(&self) -> Offset24 { - let range = self.shape.color_line_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.color_line_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`color_line_offset`][Self::color_line_offset]. @@ -2923,28 +2871,28 @@ impl<'a> PaintSweepGradient<'a> { /// Center x coordinate. pub fn center_x(&self) -> FWord { - let range = self.shape.center_x_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.center_x_byte_range(); + unchecked::read_at(self.data, range.start) } /// Center y coordinate. pub fn center_y(&self) -> FWord { - let range = self.shape.center_y_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.center_y_byte_range(); + unchecked::read_at(self.data, range.start) } /// Start of the angular range of the gradient, 180° in /// counter-clockwise degrees per 1.0 of value. pub fn start_angle(&self) -> F2Dot14 { - let range = self.shape.start_angle_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.start_angle_byte_range(); + unchecked::read_at(self.data, range.start) } /// End of the angular range of the gradient, 180° in /// counter-clockwise degrees per 1.0 of value. pub fn end_angle(&self) -> F2Dot14 { - let range = self.shape.end_angle_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.end_angle_byte_range(); + unchecked::read_at(self.data, range.start) } } @@ -2984,9 +2932,29 @@ impl Format for PaintVarSweepGradientMarker { /// [PaintVarSweepGradient](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-8-and-9-paintsweepgradient-paintvarsweepgradient) table #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct PaintVarSweepGradientMarker {} +pub struct PaintVarSweepGradientMarker; + +impl<'a> MinByteRange for PaintVarSweepGradient<'a> { + fn min_byte_range(&self) -> Range { + 0..self.var_index_base_byte_range().end + } +} + +impl<'a> FontRead<'a> for PaintVarSweepGradient<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} -impl PaintVarSweepGradientMarker { +/// [PaintVarSweepGradient](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-8-and-9-paintsweepgradient-paintvarsweepgradient) table +pub type PaintVarSweepGradient<'a> = TableRef<'a, PaintVarSweepGradientMarker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> PaintVarSweepGradient<'a> { pub fn format_byte_range(&self) -> Range { let start = 0; start..start + u8::RAW_BYTE_LEN @@ -3021,43 +2989,17 @@ impl PaintVarSweepGradientMarker { let start = self.end_angle_byte_range().end; start..start + u32::RAW_BYTE_LEN } -} - -impl MinByteRange for PaintVarSweepGradientMarker { - fn min_byte_range(&self) -> Range { - 0..self.var_index_base_byte_range().end - } -} - -impl<'a> FontRead<'a> for PaintVarSweepGradient<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.finish(PaintVarSweepGradientMarker {}) - } -} - -/// [PaintVarSweepGradient](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-8-and-9-paintsweepgradient-paintvarsweepgradient) table -pub type PaintVarSweepGradient<'a> = TableRef<'a, PaintVarSweepGradientMarker>; -#[allow(clippy::needless_lifetimes)] -impl<'a> PaintVarSweepGradient<'a> { /// Set to 9. pub fn format(&self) -> u8 { - let range = self.shape.format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Offset to VarColorLine table. pub fn color_line_offset(&self) -> Offset24 { - let range = self.shape.color_line_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.color_line_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`color_line_offset`][Self::color_line_offset]. @@ -3068,36 +3010,36 @@ impl<'a> PaintVarSweepGradient<'a> { /// Center x coordinate. For variation, use varIndexBase + 0. pub fn center_x(&self) -> FWord { - let range = self.shape.center_x_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.center_x_byte_range(); + unchecked::read_at(self.data, range.start) } /// Center y coordinate. For variation, use varIndexBase + 1. pub fn center_y(&self) -> FWord { - let range = self.shape.center_y_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.center_y_byte_range(); + unchecked::read_at(self.data, range.start) } /// Start of the angular range of the gradient, 180° in /// counter-clockwise degrees per 1.0 of value. For variation, use /// varIndexBase + 2. pub fn start_angle(&self) -> F2Dot14 { - let range = self.shape.start_angle_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.start_angle_byte_range(); + unchecked::read_at(self.data, range.start) } /// End of the angular range of the gradient, 180° in /// counter-clockwise degrees per 1.0 of value. For variation, use /// varIndexBase + 3. pub fn end_angle(&self) -> F2Dot14 { - let range = self.shape.end_angle_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.end_angle_byte_range(); + unchecked::read_at(self.data, range.start) } /// Base index into DeltaSetIndexMap. pub fn var_index_base(&self) -> u32 { - let range = self.shape.var_index_base_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.var_index_base_byte_range(); + unchecked::read_at(self.data, range.start) } } @@ -3138,9 +3080,29 @@ impl Format for PaintGlyphMarker { /// [PaintGlyph](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#format-10-paintglyph) table #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct PaintGlyphMarker {} +pub struct PaintGlyphMarker; + +impl<'a> MinByteRange for PaintGlyph<'a> { + fn min_byte_range(&self) -> Range { + 0..self.glyph_id_byte_range().end + } +} -impl PaintGlyphMarker { +impl<'a> FontRead<'a> for PaintGlyph<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// [PaintGlyph](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#format-10-paintglyph) table +pub type PaintGlyph<'a> = TableRef<'a, PaintGlyphMarker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> PaintGlyph<'a> { pub fn format_byte_range(&self) -> Range { let start = 0; start..start + u8::RAW_BYTE_LEN @@ -3155,39 +3117,17 @@ impl PaintGlyphMarker { let start = self.paint_offset_byte_range().end; start..start + GlyphId16::RAW_BYTE_LEN } -} - -impl MinByteRange for PaintGlyphMarker { - fn min_byte_range(&self) -> Range { - 0..self.glyph_id_byte_range().end - } -} - -impl<'a> FontRead<'a> for PaintGlyph<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.finish(PaintGlyphMarker {}) - } -} - -/// [PaintGlyph](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#format-10-paintglyph) table -pub type PaintGlyph<'a> = TableRef<'a, PaintGlyphMarker>; -#[allow(clippy::needless_lifetimes)] -impl<'a> PaintGlyph<'a> { /// Set to 10. pub fn format(&self) -> u8 { - let range = self.shape.format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Offset to a Paint table. pub fn paint_offset(&self) -> Offset24 { - let range = self.shape.paint_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.paint_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`paint_offset`][Self::paint_offset]. @@ -3198,8 +3138,8 @@ impl<'a> PaintGlyph<'a> { /// Glyph ID for the source outline. pub fn glyph_id(&self) -> GlyphId16 { - let range = self.shape.glyph_id_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.glyph_id_byte_range(); + unchecked::read_at(self.data, range.start) } } @@ -3236,21 +3176,9 @@ impl Format for PaintColrGlyphMarker { /// [PaintColrGlyph](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#format-11-paintcolrglyph) table #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct PaintColrGlyphMarker {} - -impl PaintColrGlyphMarker { - pub fn format_byte_range(&self) -> Range { - let start = 0; - start..start + u8::RAW_BYTE_LEN - } - - pub fn glyph_id_byte_range(&self) -> Range { - let start = self.format_byte_range().end; - start..start + GlyphId16::RAW_BYTE_LEN - } -} +pub struct PaintColrGlyphMarker; -impl MinByteRange for PaintColrGlyphMarker { +impl<'a> MinByteRange for PaintColrGlyph<'a> { fn min_byte_range(&self) -> Range { 0..self.glyph_id_byte_range().end } @@ -3258,28 +3186,39 @@ impl MinByteRange for PaintColrGlyphMarker { impl<'a> FontRead<'a> for PaintColrGlyph<'a> { fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.finish(PaintColrGlyphMarker {}) + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) } } /// [PaintColrGlyph](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#format-11-paintcolrglyph) table -pub type PaintColrGlyph<'a> = TableRef<'a, PaintColrGlyphMarker>; +pub type PaintColrGlyph<'a> = TableRef<'a, PaintColrGlyphMarker, ()>; #[allow(clippy::needless_lifetimes)] impl<'a> PaintColrGlyph<'a> { + pub fn format_byte_range(&self) -> Range { + let start = 0; + start..start + u8::RAW_BYTE_LEN + } + + pub fn glyph_id_byte_range(&self) -> Range { + let start = self.format_byte_range().end; + start..start + GlyphId16::RAW_BYTE_LEN + } + /// Set to 11. pub fn format(&self) -> u8 { - let range = self.shape.format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Glyph ID for a BaseGlyphList base glyph. pub fn glyph_id(&self) -> GlyphId16 { - let range = self.shape.glyph_id_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.glyph_id_byte_range(); + unchecked::read_at(self.data, range.start) } } @@ -3312,9 +3251,29 @@ impl Format for PaintTransformMarker { /// [PaintTransform](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-12-and-13-painttransform-paintvartransform) table #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct PaintTransformMarker {} +pub struct PaintTransformMarker; + +impl<'a> MinByteRange for PaintTransform<'a> { + fn min_byte_range(&self) -> Range { + 0..self.transform_offset_byte_range().end + } +} + +impl<'a> FontRead<'a> for PaintTransform<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// [PaintTransform](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-12-and-13-painttransform-paintvartransform) table +pub type PaintTransform<'a> = TableRef<'a, PaintTransformMarker, ()>; -impl PaintTransformMarker { +#[allow(clippy::needless_lifetimes)] +impl<'a> PaintTransform<'a> { pub fn format_byte_range(&self) -> Range { let start = 0; start..start + u8::RAW_BYTE_LEN @@ -3329,39 +3288,17 @@ impl PaintTransformMarker { let start = self.paint_offset_byte_range().end; start..start + Offset24::RAW_BYTE_LEN } -} - -impl MinByteRange for PaintTransformMarker { - fn min_byte_range(&self) -> Range { - 0..self.transform_offset_byte_range().end - } -} - -impl<'a> FontRead<'a> for PaintTransform<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.finish(PaintTransformMarker {}) - } -} -/// [PaintTransform](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-12-and-13-painttransform-paintvartransform) table -pub type PaintTransform<'a> = TableRef<'a, PaintTransformMarker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> PaintTransform<'a> { /// Set to 12. pub fn format(&self) -> u8 { - let range = self.shape.format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Offset to a Paint subtable. pub fn paint_offset(&self) -> Offset24 { - let range = self.shape.paint_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.paint_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`paint_offset`][Self::paint_offset]. @@ -3372,8 +3309,8 @@ impl<'a> PaintTransform<'a> { /// Offset to an Affine2x3 table. pub fn transform_offset(&self) -> Offset24 { - let range = self.shape.transform_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.transform_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`transform_offset`][Self::transform_offset]. @@ -3419,9 +3356,29 @@ impl Format for PaintVarTransformMarker { /// [PaintVarTransform](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-12-and-13-painttransform-paintvartransform) table #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct PaintVarTransformMarker {} +pub struct PaintVarTransformMarker; -impl PaintVarTransformMarker { +impl<'a> MinByteRange for PaintVarTransform<'a> { + fn min_byte_range(&self) -> Range { + 0..self.transform_offset_byte_range().end + } +} + +impl<'a> FontRead<'a> for PaintVarTransform<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// [PaintVarTransform](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-12-and-13-painttransform-paintvartransform) table +pub type PaintVarTransform<'a> = TableRef<'a, PaintVarTransformMarker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> PaintVarTransform<'a> { pub fn format_byte_range(&self) -> Range { let start = 0; start..start + u8::RAW_BYTE_LEN @@ -3436,39 +3393,17 @@ impl PaintVarTransformMarker { let start = self.paint_offset_byte_range().end; start..start + Offset24::RAW_BYTE_LEN } -} - -impl MinByteRange for PaintVarTransformMarker { - fn min_byte_range(&self) -> Range { - 0..self.transform_offset_byte_range().end - } -} - -impl<'a> FontRead<'a> for PaintVarTransform<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.finish(PaintVarTransformMarker {}) - } -} - -/// [PaintVarTransform](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-12-and-13-painttransform-paintvartransform) table -pub type PaintVarTransform<'a> = TableRef<'a, PaintVarTransformMarker>; -#[allow(clippy::needless_lifetimes)] -impl<'a> PaintVarTransform<'a> { /// Set to 13. pub fn format(&self) -> u8 { - let range = self.shape.format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Offset to a Paint subtable. pub fn paint_offset(&self) -> Offset24 { - let range = self.shape.paint_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.paint_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`paint_offset`][Self::paint_offset]. @@ -3479,8 +3414,8 @@ impl<'a> PaintVarTransform<'a> { /// Offset to a VarAffine2x3 table. pub fn transform_offset(&self) -> Offset24 { - let range = self.shape.transform_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.transform_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`transform_offset`][Self::transform_offset]. @@ -3522,9 +3457,29 @@ impl<'a> std::fmt::Debug for PaintVarTransform<'a> { /// [Affine2x3](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-12-and-13-painttransform-paintvartransform) record #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct Affine2x3Marker {} +pub struct Affine2x3Marker; + +impl<'a> MinByteRange for Affine2x3<'a> { + fn min_byte_range(&self) -> Range { + 0..self.dy_byte_range().end + } +} + +impl<'a> FontRead<'a> for Affine2x3<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// [Affine2x3](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-12-and-13-painttransform-paintvartransform) record +pub type Affine2x3<'a> = TableRef<'a, Affine2x3Marker, ()>; -impl Affine2x3Marker { +#[allow(clippy::needless_lifetimes)] +impl<'a> Affine2x3<'a> { pub fn xx_byte_range(&self) -> Range { let start = 0; start..start + Fixed::RAW_BYTE_LEN @@ -3554,66 +3509,41 @@ impl Affine2x3Marker { let start = self.dx_byte_range().end; start..start + Fixed::RAW_BYTE_LEN } -} - -impl MinByteRange for Affine2x3Marker { - fn min_byte_range(&self) -> Range { - 0..self.dy_byte_range().end - } -} - -impl<'a> FontRead<'a> for Affine2x3<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.finish(Affine2x3Marker {}) - } -} - -/// [Affine2x3](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-12-and-13-painttransform-paintvartransform) record -pub type Affine2x3<'a> = TableRef<'a, Affine2x3Marker>; -#[allow(clippy::needless_lifetimes)] -impl<'a> Affine2x3<'a> { /// x-component of transformed x-basis vector. pub fn xx(&self) -> Fixed { - let range = self.shape.xx_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.xx_byte_range(); + unchecked::read_at(self.data, range.start) } /// y-component of transformed x-basis vector. pub fn yx(&self) -> Fixed { - let range = self.shape.yx_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.yx_byte_range(); + unchecked::read_at(self.data, range.start) } /// x-component of transformed y-basis vector. pub fn xy(&self) -> Fixed { - let range = self.shape.xy_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.xy_byte_range(); + unchecked::read_at(self.data, range.start) } /// y-component of transformed y-basis vector. pub fn yy(&self) -> Fixed { - let range = self.shape.yy_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.yy_byte_range(); + unchecked::read_at(self.data, range.start) } /// Translation in x direction. pub fn dx(&self) -> Fixed { - let range = self.shape.dx_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.dx_byte_range(); + unchecked::read_at(self.data, range.start) } /// Translation in y direction. pub fn dy(&self) -> Fixed { - let range = self.shape.dy_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.dy_byte_range(); + unchecked::read_at(self.data, range.start) } } @@ -3646,9 +3576,29 @@ impl<'a> std::fmt::Debug for Affine2x3<'a> { /// [VarAffine2x3](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-12-and-13-painttransform-paintvartransform) record #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct VarAffine2x3Marker {} +pub struct VarAffine2x3Marker; + +impl<'a> MinByteRange for VarAffine2x3<'a> { + fn min_byte_range(&self) -> Range { + 0..self.var_index_base_byte_range().end + } +} + +impl<'a> FontRead<'a> for VarAffine2x3<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// [VarAffine2x3](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-12-and-13-painttransform-paintvartransform) record +pub type VarAffine2x3<'a> = TableRef<'a, VarAffine2x3Marker, ()>; -impl VarAffine2x3Marker { +#[allow(clippy::needless_lifetimes)] +impl<'a> VarAffine2x3<'a> { pub fn xx_byte_range(&self) -> Range { let start = 0; start..start + Fixed::RAW_BYTE_LEN @@ -3683,77 +3633,51 @@ impl VarAffine2x3Marker { let start = self.dy_byte_range().end; start..start + u32::RAW_BYTE_LEN } -} - -impl MinByteRange for VarAffine2x3Marker { - fn min_byte_range(&self) -> Range { - 0..self.var_index_base_byte_range().end - } -} - -impl<'a> FontRead<'a> for VarAffine2x3<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.finish(VarAffine2x3Marker {}) - } -} - -/// [VarAffine2x3](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-12-and-13-painttransform-paintvartransform) record -pub type VarAffine2x3<'a> = TableRef<'a, VarAffine2x3Marker>; -#[allow(clippy::needless_lifetimes)] -impl<'a> VarAffine2x3<'a> { /// x-component of transformed x-basis vector. For variation, use /// varIndexBase + 0. pub fn xx(&self) -> Fixed { - let range = self.shape.xx_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.xx_byte_range(); + unchecked::read_at(self.data, range.start) } /// y-component of transformed x-basis vector. For variation, use /// varIndexBase + 1. pub fn yx(&self) -> Fixed { - let range = self.shape.yx_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.yx_byte_range(); + unchecked::read_at(self.data, range.start) } /// x-component of transformed y-basis vector. For variation, use /// varIndexBase + 2. pub fn xy(&self) -> Fixed { - let range = self.shape.xy_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.xy_byte_range(); + unchecked::read_at(self.data, range.start) } /// y-component of transformed y-basis vector. For variation, use /// varIndexBase + 3. pub fn yy(&self) -> Fixed { - let range = self.shape.yy_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.yy_byte_range(); + unchecked::read_at(self.data, range.start) } /// Translation in x direction. For variation, use varIndexBase + 4. pub fn dx(&self) -> Fixed { - let range = self.shape.dx_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.dx_byte_range(); + unchecked::read_at(self.data, range.start) } /// Translation in y direction. For variation, use varIndexBase + 5. pub fn dy(&self) -> Fixed { - let range = self.shape.dy_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.dy_byte_range(); + unchecked::read_at(self.data, range.start) } /// Base index into DeltaSetIndexMap. pub fn var_index_base(&self) -> u32 { - let range = self.shape.var_index_base_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.var_index_base_byte_range(); + unchecked::read_at(self.data, range.start) } } @@ -3791,9 +3715,29 @@ impl Format for PaintTranslateMarker { /// [PaintTranslate](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-14-and-15-painttranslate-paintvartranslate) table #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct PaintTranslateMarker {} +pub struct PaintTranslateMarker; + +impl<'a> MinByteRange for PaintTranslate<'a> { + fn min_byte_range(&self) -> Range { + 0..self.dy_byte_range().end + } +} + +impl<'a> FontRead<'a> for PaintTranslate<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// [PaintTranslate](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-14-and-15-painttranslate-paintvartranslate) table +pub type PaintTranslate<'a> = TableRef<'a, PaintTranslateMarker, ()>; -impl PaintTranslateMarker { +#[allow(clippy::needless_lifetimes)] +impl<'a> PaintTranslate<'a> { pub fn format_byte_range(&self) -> Range { let start = 0; start..start + u8::RAW_BYTE_LEN @@ -3813,40 +3757,17 @@ impl PaintTranslateMarker { let start = self.dx_byte_range().end; start..start + FWord::RAW_BYTE_LEN } -} - -impl MinByteRange for PaintTranslateMarker { - fn min_byte_range(&self) -> Range { - 0..self.dy_byte_range().end - } -} - -impl<'a> FontRead<'a> for PaintTranslate<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.finish(PaintTranslateMarker {}) - } -} -/// [PaintTranslate](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-14-and-15-painttranslate-paintvartranslate) table -pub type PaintTranslate<'a> = TableRef<'a, PaintTranslateMarker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> PaintTranslate<'a> { /// Set to 14. pub fn format(&self) -> u8 { - let range = self.shape.format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Offset to a Paint subtable. pub fn paint_offset(&self) -> Offset24 { - let range = self.shape.paint_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.paint_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`paint_offset`][Self::paint_offset]. @@ -3857,14 +3778,14 @@ impl<'a> PaintTranslate<'a> { /// Translation in x direction. pub fn dx(&self) -> FWord { - let range = self.shape.dx_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.dx_byte_range(); + unchecked::read_at(self.data, range.start) } /// Translation in y direction. pub fn dy(&self) -> FWord { - let range = self.shape.dy_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.dy_byte_range(); + unchecked::read_at(self.data, range.start) } } @@ -3902,13 +3823,33 @@ impl Format for PaintVarTranslateMarker { /// [PaintVarTranslate](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-14-and-15-painttranslate-paintvartranslate) table #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct PaintVarTranslateMarker {} +pub struct PaintVarTranslateMarker; -impl PaintVarTranslateMarker { - pub fn format_byte_range(&self) -> Range { - let start = 0; - start..start + u8::RAW_BYTE_LEN - } +impl<'a> MinByteRange for PaintVarTranslate<'a> { + fn min_byte_range(&self) -> Range { + 0..self.var_index_base_byte_range().end + } +} + +impl<'a> FontRead<'a> for PaintVarTranslate<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// [PaintVarTranslate](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-14-and-15-painttranslate-paintvartranslate) table +pub type PaintVarTranslate<'a> = TableRef<'a, PaintVarTranslateMarker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> PaintVarTranslate<'a> { + pub fn format_byte_range(&self) -> Range { + let start = 0; + start..start + u8::RAW_BYTE_LEN + } pub fn paint_offset_byte_range(&self) -> Range { let start = self.format_byte_range().end; @@ -3929,41 +3870,17 @@ impl PaintVarTranslateMarker { let start = self.dy_byte_range().end; start..start + u32::RAW_BYTE_LEN } -} - -impl MinByteRange for PaintVarTranslateMarker { - fn min_byte_range(&self) -> Range { - 0..self.var_index_base_byte_range().end - } -} - -impl<'a> FontRead<'a> for PaintVarTranslate<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.finish(PaintVarTranslateMarker {}) - } -} - -/// [PaintVarTranslate](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-14-and-15-painttranslate-paintvartranslate) table -pub type PaintVarTranslate<'a> = TableRef<'a, PaintVarTranslateMarker>; -#[allow(clippy::needless_lifetimes)] -impl<'a> PaintVarTranslate<'a> { /// Set to 15. pub fn format(&self) -> u8 { - let range = self.shape.format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Offset to a Paint subtable. pub fn paint_offset(&self) -> Offset24 { - let range = self.shape.paint_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.paint_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`paint_offset`][Self::paint_offset]. @@ -3974,20 +3891,20 @@ impl<'a> PaintVarTranslate<'a> { /// Translation in x direction. For variation, use varIndexBase + 0. pub fn dx(&self) -> FWord { - let range = self.shape.dx_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.dx_byte_range(); + unchecked::read_at(self.data, range.start) } /// Translation in y direction. For variation, use varIndexBase + 1. pub fn dy(&self) -> FWord { - let range = self.shape.dy_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.dy_byte_range(); + unchecked::read_at(self.data, range.start) } /// Base index into DeltaSetIndexMap. pub fn var_index_base(&self) -> u32 { - let range = self.shape.var_index_base_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.var_index_base_byte_range(); + unchecked::read_at(self.data, range.start) } } @@ -4026,9 +3943,29 @@ impl Format for PaintScaleMarker { /// [PaintScale](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-16-to-23-paintscale-and-variant-scaling-formats) table #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct PaintScaleMarker {} +pub struct PaintScaleMarker; + +impl<'a> MinByteRange for PaintScale<'a> { + fn min_byte_range(&self) -> Range { + 0..self.scale_y_byte_range().end + } +} -impl PaintScaleMarker { +impl<'a> FontRead<'a> for PaintScale<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// [PaintScale](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-16-to-23-paintscale-and-variant-scaling-formats) table +pub type PaintScale<'a> = TableRef<'a, PaintScaleMarker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> PaintScale<'a> { pub fn format_byte_range(&self) -> Range { let start = 0; start..start + u8::RAW_BYTE_LEN @@ -4048,40 +3985,17 @@ impl PaintScaleMarker { let start = self.scale_x_byte_range().end; start..start + F2Dot14::RAW_BYTE_LEN } -} - -impl MinByteRange for PaintScaleMarker { - fn min_byte_range(&self) -> Range { - 0..self.scale_y_byte_range().end - } -} -impl<'a> FontRead<'a> for PaintScale<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.finish(PaintScaleMarker {}) - } -} - -/// [PaintScale](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-16-to-23-paintscale-and-variant-scaling-formats) table -pub type PaintScale<'a> = TableRef<'a, PaintScaleMarker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> PaintScale<'a> { /// Set to 16. pub fn format(&self) -> u8 { - let range = self.shape.format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Offset to a Paint subtable. pub fn paint_offset(&self) -> Offset24 { - let range = self.shape.paint_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.paint_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`paint_offset`][Self::paint_offset]. @@ -4092,14 +4006,14 @@ impl<'a> PaintScale<'a> { /// Scale factor in x direction. pub fn scale_x(&self) -> F2Dot14 { - let range = self.shape.scale_x_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.scale_x_byte_range(); + unchecked::read_at(self.data, range.start) } /// Scale factor in y direction. pub fn scale_y(&self) -> F2Dot14 { - let range = self.shape.scale_y_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.scale_y_byte_range(); + unchecked::read_at(self.data, range.start) } } @@ -4137,9 +4051,29 @@ impl Format for PaintVarScaleMarker { /// [PaintVarScale](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-16-to-23-paintscale-and-variant-scaling-formats) table #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct PaintVarScaleMarker {} +pub struct PaintVarScaleMarker; + +impl<'a> MinByteRange for PaintVarScale<'a> { + fn min_byte_range(&self) -> Range { + 0..self.var_index_base_byte_range().end + } +} + +impl<'a> FontRead<'a> for PaintVarScale<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// [PaintVarScale](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-16-to-23-paintscale-and-variant-scaling-formats) table +pub type PaintVarScale<'a> = TableRef<'a, PaintVarScaleMarker, ()>; -impl PaintVarScaleMarker { +#[allow(clippy::needless_lifetimes)] +impl<'a> PaintVarScale<'a> { pub fn format_byte_range(&self) -> Range { let start = 0; start..start + u8::RAW_BYTE_LEN @@ -4164,41 +4098,17 @@ impl PaintVarScaleMarker { let start = self.scale_y_byte_range().end; start..start + u32::RAW_BYTE_LEN } -} - -impl MinByteRange for PaintVarScaleMarker { - fn min_byte_range(&self) -> Range { - 0..self.var_index_base_byte_range().end - } -} - -impl<'a> FontRead<'a> for PaintVarScale<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.finish(PaintVarScaleMarker {}) - } -} - -/// [PaintVarScale](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-16-to-23-paintscale-and-variant-scaling-formats) table -pub type PaintVarScale<'a> = TableRef<'a, PaintVarScaleMarker>; -#[allow(clippy::needless_lifetimes)] -impl<'a> PaintVarScale<'a> { /// Set to 17. pub fn format(&self) -> u8 { - let range = self.shape.format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Offset to a Paint subtable. pub fn paint_offset(&self) -> Offset24 { - let range = self.shape.paint_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.paint_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`paint_offset`][Self::paint_offset]. @@ -4210,21 +4120,21 @@ impl<'a> PaintVarScale<'a> { /// Scale factor in x direction. For variation, use varIndexBase + /// 0. pub fn scale_x(&self) -> F2Dot14 { - let range = self.shape.scale_x_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.scale_x_byte_range(); + unchecked::read_at(self.data, range.start) } /// Scale factor in y direction. For variation, use varIndexBase + /// 1. pub fn scale_y(&self) -> F2Dot14 { - let range = self.shape.scale_y_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.scale_y_byte_range(); + unchecked::read_at(self.data, range.start) } /// Base index into DeltaSetIndexMap. pub fn var_index_base(&self) -> u32 { - let range = self.shape.var_index_base_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.var_index_base_byte_range(); + unchecked::read_at(self.data, range.start) } } @@ -4263,9 +4173,29 @@ impl Format for PaintScaleAroundCenterMarker { /// [PaintScaleAroundCenter](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-16-to-23-paintscale-and-variant-scaling-formats) table #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct PaintScaleAroundCenterMarker {} +pub struct PaintScaleAroundCenterMarker; + +impl<'a> MinByteRange for PaintScaleAroundCenter<'a> { + fn min_byte_range(&self) -> Range { + 0..self.center_y_byte_range().end + } +} + +impl<'a> FontRead<'a> for PaintScaleAroundCenter<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} -impl PaintScaleAroundCenterMarker { +/// [PaintScaleAroundCenter](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-16-to-23-paintscale-and-variant-scaling-formats) table +pub type PaintScaleAroundCenter<'a> = TableRef<'a, PaintScaleAroundCenterMarker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> PaintScaleAroundCenter<'a> { pub fn format_byte_range(&self) -> Range { let start = 0; start..start + u8::RAW_BYTE_LEN @@ -4295,42 +4225,17 @@ impl PaintScaleAroundCenterMarker { let start = self.center_x_byte_range().end; start..start + FWord::RAW_BYTE_LEN } -} - -impl MinByteRange for PaintScaleAroundCenterMarker { - fn min_byte_range(&self) -> Range { - 0..self.center_y_byte_range().end - } -} -impl<'a> FontRead<'a> for PaintScaleAroundCenter<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.finish(PaintScaleAroundCenterMarker {}) - } -} - -/// [PaintScaleAroundCenter](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-16-to-23-paintscale-and-variant-scaling-formats) table -pub type PaintScaleAroundCenter<'a> = TableRef<'a, PaintScaleAroundCenterMarker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> PaintScaleAroundCenter<'a> { /// Set to 18. pub fn format(&self) -> u8 { - let range = self.shape.format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Offset to a Paint subtable. pub fn paint_offset(&self) -> Offset24 { - let range = self.shape.paint_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.paint_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`paint_offset`][Self::paint_offset]. @@ -4341,26 +4246,26 @@ impl<'a> PaintScaleAroundCenter<'a> { /// Scale factor in x direction. pub fn scale_x(&self) -> F2Dot14 { - let range = self.shape.scale_x_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.scale_x_byte_range(); + unchecked::read_at(self.data, range.start) } /// Scale factor in y direction. pub fn scale_y(&self) -> F2Dot14 { - let range = self.shape.scale_y_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.scale_y_byte_range(); + unchecked::read_at(self.data, range.start) } /// x coordinate for the center of scaling. pub fn center_x(&self) -> FWord { - let range = self.shape.center_x_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.center_x_byte_range(); + unchecked::read_at(self.data, range.start) } /// y coordinate for the center of scaling. pub fn center_y(&self) -> FWord { - let range = self.shape.center_y_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.center_y_byte_range(); + unchecked::read_at(self.data, range.start) } } @@ -4400,9 +4305,29 @@ impl Format for PaintVarScaleAroundCenterMarker { /// [PaintVarScaleAroundCenter](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-16-to-23-paintscale-and-variant-scaling-formats) table #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct PaintVarScaleAroundCenterMarker {} +pub struct PaintVarScaleAroundCenterMarker; + +impl<'a> MinByteRange for PaintVarScaleAroundCenter<'a> { + fn min_byte_range(&self) -> Range { + 0..self.var_index_base_byte_range().end + } +} -impl PaintVarScaleAroundCenterMarker { +impl<'a> FontRead<'a> for PaintVarScaleAroundCenter<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// [PaintVarScaleAroundCenter](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-16-to-23-paintscale-and-variant-scaling-formats) table +pub type PaintVarScaleAroundCenter<'a> = TableRef<'a, PaintVarScaleAroundCenterMarker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> PaintVarScaleAroundCenter<'a> { pub fn format_byte_range(&self) -> Range { let start = 0; start..start + u8::RAW_BYTE_LEN @@ -4437,43 +4362,17 @@ impl PaintVarScaleAroundCenterMarker { let start = self.center_y_byte_range().end; start..start + u32::RAW_BYTE_LEN } -} -impl MinByteRange for PaintVarScaleAroundCenterMarker { - fn min_byte_range(&self) -> Range { - 0..self.var_index_base_byte_range().end - } -} - -impl<'a> FontRead<'a> for PaintVarScaleAroundCenter<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.finish(PaintVarScaleAroundCenterMarker {}) - } -} - -/// [PaintVarScaleAroundCenter](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-16-to-23-paintscale-and-variant-scaling-formats) table -pub type PaintVarScaleAroundCenter<'a> = TableRef<'a, PaintVarScaleAroundCenterMarker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> PaintVarScaleAroundCenter<'a> { /// Set to 19. pub fn format(&self) -> u8 { - let range = self.shape.format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Offset to a Paint subtable. pub fn paint_offset(&self) -> Offset24 { - let range = self.shape.paint_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.paint_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`paint_offset`][Self::paint_offset]. @@ -4485,35 +4384,35 @@ impl<'a> PaintVarScaleAroundCenter<'a> { /// Scale factor in x direction. For variation, use varIndexBase + /// 0. pub fn scale_x(&self) -> F2Dot14 { - let range = self.shape.scale_x_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.scale_x_byte_range(); + unchecked::read_at(self.data, range.start) } /// Scale factor in y direction. For variation, use varIndexBase + /// 1. pub fn scale_y(&self) -> F2Dot14 { - let range = self.shape.scale_y_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.scale_y_byte_range(); + unchecked::read_at(self.data, range.start) } /// x coordinate for the center of scaling. For variation, use /// varIndexBase + 2. pub fn center_x(&self) -> FWord { - let range = self.shape.center_x_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.center_x_byte_range(); + unchecked::read_at(self.data, range.start) } /// y coordinate for the center of scaling. For variation, use /// varIndexBase + 3. pub fn center_y(&self) -> FWord { - let range = self.shape.center_y_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.center_y_byte_range(); + unchecked::read_at(self.data, range.start) } /// Base index into DeltaSetIndexMap. pub fn var_index_base(&self) -> u32 { - let range = self.shape.var_index_base_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.var_index_base_byte_range(); + unchecked::read_at(self.data, range.start) } } @@ -4554,9 +4453,29 @@ impl Format for PaintScaleUniformMarker { /// [PaintScaleUniform](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-16-to-23-paintscale-and-variant-scaling-formats) table #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct PaintScaleUniformMarker {} +pub struct PaintScaleUniformMarker; + +impl<'a> MinByteRange for PaintScaleUniform<'a> { + fn min_byte_range(&self) -> Range { + 0..self.scale_byte_range().end + } +} + +impl<'a> FontRead<'a> for PaintScaleUniform<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// [PaintScaleUniform](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-16-to-23-paintscale-and-variant-scaling-formats) table +pub type PaintScaleUniform<'a> = TableRef<'a, PaintScaleUniformMarker, ()>; -impl PaintScaleUniformMarker { +#[allow(clippy::needless_lifetimes)] +impl<'a> PaintScaleUniform<'a> { pub fn format_byte_range(&self) -> Range { let start = 0; start..start + u8::RAW_BYTE_LEN @@ -4571,39 +4490,17 @@ impl PaintScaleUniformMarker { let start = self.paint_offset_byte_range().end; start..start + F2Dot14::RAW_BYTE_LEN } -} - -impl MinByteRange for PaintScaleUniformMarker { - fn min_byte_range(&self) -> Range { - 0..self.scale_byte_range().end - } -} - -impl<'a> FontRead<'a> for PaintScaleUniform<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.finish(PaintScaleUniformMarker {}) - } -} - -/// [PaintScaleUniform](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-16-to-23-paintscale-and-variant-scaling-formats) table -pub type PaintScaleUniform<'a> = TableRef<'a, PaintScaleUniformMarker>; -#[allow(clippy::needless_lifetimes)] -impl<'a> PaintScaleUniform<'a> { /// Set to 20. pub fn format(&self) -> u8 { - let range = self.shape.format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Offset to a Paint subtable. pub fn paint_offset(&self) -> Offset24 { - let range = self.shape.paint_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.paint_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`paint_offset`][Self::paint_offset]. @@ -4614,8 +4511,8 @@ impl<'a> PaintScaleUniform<'a> { /// Scale factor in x and y directions. pub fn scale(&self) -> F2Dot14 { - let range = self.shape.scale_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.scale_byte_range(); + unchecked::read_at(self.data, range.start) } } @@ -4652,9 +4549,29 @@ impl Format for PaintVarScaleUniformMarker { /// [PaintVarScaleUniform](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-16-to-23-paintscale-and-variant-scaling-formats) table #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct PaintVarScaleUniformMarker {} +pub struct PaintVarScaleUniformMarker; + +impl<'a> MinByteRange for PaintVarScaleUniform<'a> { + fn min_byte_range(&self) -> Range { + 0..self.var_index_base_byte_range().end + } +} -impl PaintVarScaleUniformMarker { +impl<'a> FontRead<'a> for PaintVarScaleUniform<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// [PaintVarScaleUniform](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-16-to-23-paintscale-and-variant-scaling-formats) table +pub type PaintVarScaleUniform<'a> = TableRef<'a, PaintVarScaleUniformMarker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> PaintVarScaleUniform<'a> { pub fn format_byte_range(&self) -> Range { let start = 0; start..start + u8::RAW_BYTE_LEN @@ -4674,40 +4591,17 @@ impl PaintVarScaleUniformMarker { let start = self.scale_byte_range().end; start..start + u32::RAW_BYTE_LEN } -} - -impl MinByteRange for PaintVarScaleUniformMarker { - fn min_byte_range(&self) -> Range { - 0..self.var_index_base_byte_range().end - } -} - -impl<'a> FontRead<'a> for PaintVarScaleUniform<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.finish(PaintVarScaleUniformMarker {}) - } -} -/// [PaintVarScaleUniform](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-16-to-23-paintscale-and-variant-scaling-formats) table -pub type PaintVarScaleUniform<'a> = TableRef<'a, PaintVarScaleUniformMarker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> PaintVarScaleUniform<'a> { /// Set to 21. pub fn format(&self) -> u8 { - let range = self.shape.format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Offset to a Paint subtable. pub fn paint_offset(&self) -> Offset24 { - let range = self.shape.paint_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.paint_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`paint_offset`][Self::paint_offset]. @@ -4719,14 +4613,14 @@ impl<'a> PaintVarScaleUniform<'a> { /// Scale factor in x and y directions. For variation, use /// varIndexBase + 0. pub fn scale(&self) -> F2Dot14 { - let range = self.shape.scale_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.scale_byte_range(); + unchecked::read_at(self.data, range.start) } /// Base index into DeltaSetIndexMap. pub fn var_index_base(&self) -> u32 { - let range = self.shape.var_index_base_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.var_index_base_byte_range(); + unchecked::read_at(self.data, range.start) } } @@ -4764,9 +4658,29 @@ impl Format for PaintScaleUniformAroundCenterMarker { /// [PaintScaleUniformAroundCenter](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-16-to-23-paintscale-and-variant-scaling-formats) table #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct PaintScaleUniformAroundCenterMarker {} +pub struct PaintScaleUniformAroundCenterMarker; + +impl<'a> MinByteRange for PaintScaleUniformAroundCenter<'a> { + fn min_byte_range(&self) -> Range { + 0..self.center_y_byte_range().end + } +} -impl PaintScaleUniformAroundCenterMarker { +impl<'a> FontRead<'a> for PaintScaleUniformAroundCenter<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// [PaintScaleUniformAroundCenter](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-16-to-23-paintscale-and-variant-scaling-formats) table +pub type PaintScaleUniformAroundCenter<'a> = TableRef<'a, PaintScaleUniformAroundCenterMarker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> PaintScaleUniformAroundCenter<'a> { pub fn format_byte_range(&self) -> Range { let start = 0; start..start + u8::RAW_BYTE_LEN @@ -4791,41 +4705,17 @@ impl PaintScaleUniformAroundCenterMarker { let start = self.center_x_byte_range().end; start..start + FWord::RAW_BYTE_LEN } -} - -impl MinByteRange for PaintScaleUniformAroundCenterMarker { - fn min_byte_range(&self) -> Range { - 0..self.center_y_byte_range().end - } -} - -impl<'a> FontRead<'a> for PaintScaleUniformAroundCenter<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.finish(PaintScaleUniformAroundCenterMarker {}) - } -} - -/// [PaintScaleUniformAroundCenter](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-16-to-23-paintscale-and-variant-scaling-formats) table -pub type PaintScaleUniformAroundCenter<'a> = TableRef<'a, PaintScaleUniformAroundCenterMarker>; -#[allow(clippy::needless_lifetimes)] -impl<'a> PaintScaleUniformAroundCenter<'a> { /// Set to 22. pub fn format(&self) -> u8 { - let range = self.shape.format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Offset to a Paint subtable. pub fn paint_offset(&self) -> Offset24 { - let range = self.shape.paint_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.paint_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`paint_offset`][Self::paint_offset]. @@ -4836,20 +4726,20 @@ impl<'a> PaintScaleUniformAroundCenter<'a> { /// Scale factor in x and y directions. pub fn scale(&self) -> F2Dot14 { - let range = self.shape.scale_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.scale_byte_range(); + unchecked::read_at(self.data, range.start) } /// x coordinate for the center of scaling. pub fn center_x(&self) -> FWord { - let range = self.shape.center_x_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.center_x_byte_range(); + unchecked::read_at(self.data, range.start) } /// y coordinate for the center of scaling. pub fn center_y(&self) -> FWord { - let range = self.shape.center_y_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.center_y_byte_range(); + unchecked::read_at(self.data, range.start) } } @@ -4888,9 +4778,30 @@ impl Format for PaintVarScaleUniformAroundCenterMarker { /// [PaintVarScaleUniformAroundCenter](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-16-to-23-paintscale-and-variant-scaling-formats) table #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct PaintVarScaleUniformAroundCenterMarker {} +pub struct PaintVarScaleUniformAroundCenterMarker; + +impl<'a> MinByteRange for PaintVarScaleUniformAroundCenter<'a> { + fn min_byte_range(&self) -> Range { + 0..self.var_index_base_byte_range().end + } +} -impl PaintVarScaleUniformAroundCenterMarker { +impl<'a> FontRead<'a> for PaintVarScaleUniformAroundCenter<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// [PaintVarScaleUniformAroundCenter](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-16-to-23-paintscale-and-variant-scaling-formats) table +pub type PaintVarScaleUniformAroundCenter<'a> = + TableRef<'a, PaintVarScaleUniformAroundCenterMarker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> PaintVarScaleUniformAroundCenter<'a> { pub fn format_byte_range(&self) -> Range { let start = 0; start..start + u8::RAW_BYTE_LEN @@ -4920,43 +4831,17 @@ impl PaintVarScaleUniformAroundCenterMarker { let start = self.center_y_byte_range().end; start..start + u32::RAW_BYTE_LEN } -} - -impl MinByteRange for PaintVarScaleUniformAroundCenterMarker { - fn min_byte_range(&self) -> Range { - 0..self.var_index_base_byte_range().end - } -} -impl<'a> FontRead<'a> for PaintVarScaleUniformAroundCenter<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.finish(PaintVarScaleUniformAroundCenterMarker {}) - } -} - -/// [PaintVarScaleUniformAroundCenter](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-16-to-23-paintscale-and-variant-scaling-formats) table -pub type PaintVarScaleUniformAroundCenter<'a> = - TableRef<'a, PaintVarScaleUniformAroundCenterMarker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> PaintVarScaleUniformAroundCenter<'a> { /// Set to 23. pub fn format(&self) -> u8 { - let range = self.shape.format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Offset to a Paint subtable. pub fn paint_offset(&self) -> Offset24 { - let range = self.shape.paint_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.paint_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`paint_offset`][Self::paint_offset]. @@ -4968,28 +4853,28 @@ impl<'a> PaintVarScaleUniformAroundCenter<'a> { /// Scale factor in x and y directions. For variation, use /// varIndexBase + 0. pub fn scale(&self) -> F2Dot14 { - let range = self.shape.scale_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.scale_byte_range(); + unchecked::read_at(self.data, range.start) } /// x coordinate for the center of scaling. For variation, use /// varIndexBase + 1. pub fn center_x(&self) -> FWord { - let range = self.shape.center_x_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.center_x_byte_range(); + unchecked::read_at(self.data, range.start) } /// y coordinate for the center of scaling. For variation, use /// varIndexBase + 2. pub fn center_y(&self) -> FWord { - let range = self.shape.center_y_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.center_y_byte_range(); + unchecked::read_at(self.data, range.start) } /// Base index into DeltaSetIndexMap. pub fn var_index_base(&self) -> u32 { - let range = self.shape.var_index_base_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.var_index_base_byte_range(); + unchecked::read_at(self.data, range.start) } } @@ -5029,9 +4914,29 @@ impl Format for PaintRotateMarker { /// [PaintRotate](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-24-to-27-paintrotate-paintvarrotate-paintrotatearoundcenter-paintvarrotatearoundcenter) table #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct PaintRotateMarker {} +pub struct PaintRotateMarker; + +impl<'a> MinByteRange for PaintRotate<'a> { + fn min_byte_range(&self) -> Range { + 0..self.angle_byte_range().end + } +} + +impl<'a> FontRead<'a> for PaintRotate<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} -impl PaintRotateMarker { +/// [PaintRotate](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-24-to-27-paintrotate-paintvarrotate-paintrotatearoundcenter-paintvarrotatearoundcenter) table +pub type PaintRotate<'a> = TableRef<'a, PaintRotateMarker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> PaintRotate<'a> { pub fn format_byte_range(&self) -> Range { let start = 0; start..start + u8::RAW_BYTE_LEN @@ -5042,43 +4947,21 @@ impl PaintRotateMarker { start..start + Offset24::RAW_BYTE_LEN } - pub fn angle_byte_range(&self) -> Range { - let start = self.paint_offset_byte_range().end; - start..start + F2Dot14::RAW_BYTE_LEN - } -} - -impl MinByteRange for PaintRotateMarker { - fn min_byte_range(&self) -> Range { - 0..self.angle_byte_range().end - } -} - -impl<'a> FontRead<'a> for PaintRotate<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.finish(PaintRotateMarker {}) - } -} - -/// [PaintRotate](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-24-to-27-paintrotate-paintvarrotate-paintrotatearoundcenter-paintvarrotatearoundcenter) table -pub type PaintRotate<'a> = TableRef<'a, PaintRotateMarker>; + pub fn angle_byte_range(&self) -> Range { + let start = self.paint_offset_byte_range().end; + start..start + F2Dot14::RAW_BYTE_LEN + } -#[allow(clippy::needless_lifetimes)] -impl<'a> PaintRotate<'a> { /// Set to 24. pub fn format(&self) -> u8 { - let range = self.shape.format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Offset to a Paint subtable. pub fn paint_offset(&self) -> Offset24 { - let range = self.shape.paint_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.paint_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`paint_offset`][Self::paint_offset]. @@ -5090,8 +4973,8 @@ impl<'a> PaintRotate<'a> { /// Rotation angle, 180° in counter-clockwise degrees per 1.0 of /// value. pub fn angle(&self) -> F2Dot14 { - let range = self.shape.angle_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.angle_byte_range(); + unchecked::read_at(self.data, range.start) } } @@ -5128,9 +5011,29 @@ impl Format for PaintVarRotateMarker { /// [PaintVarRotate](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-24-to-27-paintrotate-paintvarrotate-paintrotatearoundcenter-paintvarrotatearoundcenter) table #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct PaintVarRotateMarker {} +pub struct PaintVarRotateMarker; + +impl<'a> MinByteRange for PaintVarRotate<'a> { + fn min_byte_range(&self) -> Range { + 0..self.var_index_base_byte_range().end + } +} + +impl<'a> FontRead<'a> for PaintVarRotate<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} -impl PaintVarRotateMarker { +/// [PaintVarRotate](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-24-to-27-paintrotate-paintvarrotate-paintrotatearoundcenter-paintvarrotatearoundcenter) table +pub type PaintVarRotate<'a> = TableRef<'a, PaintVarRotateMarker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> PaintVarRotate<'a> { pub fn format_byte_range(&self) -> Range { let start = 0; start..start + u8::RAW_BYTE_LEN @@ -5150,40 +5053,17 @@ impl PaintVarRotateMarker { let start = self.angle_byte_range().end; start..start + u32::RAW_BYTE_LEN } -} - -impl MinByteRange for PaintVarRotateMarker { - fn min_byte_range(&self) -> Range { - 0..self.var_index_base_byte_range().end - } -} - -impl<'a> FontRead<'a> for PaintVarRotate<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.finish(PaintVarRotateMarker {}) - } -} - -/// [PaintVarRotate](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-24-to-27-paintrotate-paintvarrotate-paintrotatearoundcenter-paintvarrotatearoundcenter) table -pub type PaintVarRotate<'a> = TableRef<'a, PaintVarRotateMarker>; -#[allow(clippy::needless_lifetimes)] -impl<'a> PaintVarRotate<'a> { /// Set to 25. pub fn format(&self) -> u8 { - let range = self.shape.format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Offset to a Paint subtable. pub fn paint_offset(&self) -> Offset24 { - let range = self.shape.paint_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.paint_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`paint_offset`][Self::paint_offset]. @@ -5195,14 +5075,14 @@ impl<'a> PaintVarRotate<'a> { /// Rotation angle, 180° in counter-clockwise degrees per 1.0 of /// value. For variation, use varIndexBase + 0. pub fn angle(&self) -> F2Dot14 { - let range = self.shape.angle_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.angle_byte_range(); + unchecked::read_at(self.data, range.start) } /// Base index into DeltaSetIndexMap. pub fn var_index_base(&self) -> u32 { - let range = self.shape.var_index_base_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.var_index_base_byte_range(); + unchecked::read_at(self.data, range.start) } } @@ -5240,9 +5120,29 @@ impl Format for PaintRotateAroundCenterMarker { /// [PaintRotateAroundCenter](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-24-to-27-paintrotate-paintvarrotate-paintrotatearoundcenter-paintvarrotatearoundcenter) table #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct PaintRotateAroundCenterMarker {} +pub struct PaintRotateAroundCenterMarker; + +impl<'a> MinByteRange for PaintRotateAroundCenter<'a> { + fn min_byte_range(&self) -> Range { + 0..self.center_y_byte_range().end + } +} + +impl<'a> FontRead<'a> for PaintRotateAroundCenter<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// [PaintRotateAroundCenter](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-24-to-27-paintrotate-paintvarrotate-paintrotatearoundcenter-paintvarrotatearoundcenter) table +pub type PaintRotateAroundCenter<'a> = TableRef<'a, PaintRotateAroundCenterMarker, ()>; -impl PaintRotateAroundCenterMarker { +#[allow(clippy::needless_lifetimes)] +impl<'a> PaintRotateAroundCenter<'a> { pub fn format_byte_range(&self) -> Range { let start = 0; start..start + u8::RAW_BYTE_LEN @@ -5267,41 +5167,17 @@ impl PaintRotateAroundCenterMarker { let start = self.center_x_byte_range().end; start..start + FWord::RAW_BYTE_LEN } -} - -impl MinByteRange for PaintRotateAroundCenterMarker { - fn min_byte_range(&self) -> Range { - 0..self.center_y_byte_range().end - } -} - -impl<'a> FontRead<'a> for PaintRotateAroundCenter<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.finish(PaintRotateAroundCenterMarker {}) - } -} - -/// [PaintRotateAroundCenter](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-24-to-27-paintrotate-paintvarrotate-paintrotatearoundcenter-paintvarrotatearoundcenter) table -pub type PaintRotateAroundCenter<'a> = TableRef<'a, PaintRotateAroundCenterMarker>; -#[allow(clippy::needless_lifetimes)] -impl<'a> PaintRotateAroundCenter<'a> { /// Set to 26. pub fn format(&self) -> u8 { - let range = self.shape.format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Offset to a Paint subtable. pub fn paint_offset(&self) -> Offset24 { - let range = self.shape.paint_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.paint_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`paint_offset`][Self::paint_offset]. @@ -5313,20 +5189,20 @@ impl<'a> PaintRotateAroundCenter<'a> { /// Rotation angle, 180° in counter-clockwise degrees per 1.0 of /// value. pub fn angle(&self) -> F2Dot14 { - let range = self.shape.angle_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.angle_byte_range(); + unchecked::read_at(self.data, range.start) } /// x coordinate for the center of rotation. pub fn center_x(&self) -> FWord { - let range = self.shape.center_x_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.center_x_byte_range(); + unchecked::read_at(self.data, range.start) } /// y coordinate for the center of rotation. pub fn center_y(&self) -> FWord { - let range = self.shape.center_y_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.center_y_byte_range(); + unchecked::read_at(self.data, range.start) } } @@ -5365,9 +5241,29 @@ impl Format for PaintVarRotateAroundCenterMarker { /// [PaintVarRotateAroundCenter](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-24-to-27-paintrotate-paintvarrotate-paintrotatearoundcenter-paintvarrotatearoundcenter) table #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct PaintVarRotateAroundCenterMarker {} +pub struct PaintVarRotateAroundCenterMarker; + +impl<'a> MinByteRange for PaintVarRotateAroundCenter<'a> { + fn min_byte_range(&self) -> Range { + 0..self.var_index_base_byte_range().end + } +} + +impl<'a> FontRead<'a> for PaintVarRotateAroundCenter<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// [PaintVarRotateAroundCenter](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-24-to-27-paintrotate-paintvarrotate-paintrotatearoundcenter-paintvarrotatearoundcenter) table +pub type PaintVarRotateAroundCenter<'a> = TableRef<'a, PaintVarRotateAroundCenterMarker, ()>; -impl PaintVarRotateAroundCenterMarker { +#[allow(clippy::needless_lifetimes)] +impl<'a> PaintVarRotateAroundCenter<'a> { pub fn format_byte_range(&self) -> Range { let start = 0; start..start + u8::RAW_BYTE_LEN @@ -5397,42 +5293,17 @@ impl PaintVarRotateAroundCenterMarker { let start = self.center_y_byte_range().end; start..start + u32::RAW_BYTE_LEN } -} - -impl MinByteRange for PaintVarRotateAroundCenterMarker { - fn min_byte_range(&self) -> Range { - 0..self.var_index_base_byte_range().end - } -} - -impl<'a> FontRead<'a> for PaintVarRotateAroundCenter<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.finish(PaintVarRotateAroundCenterMarker {}) - } -} - -/// [PaintVarRotateAroundCenter](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-24-to-27-paintrotate-paintvarrotate-paintrotatearoundcenter-paintvarrotatearoundcenter) table -pub type PaintVarRotateAroundCenter<'a> = TableRef<'a, PaintVarRotateAroundCenterMarker>; -#[allow(clippy::needless_lifetimes)] -impl<'a> PaintVarRotateAroundCenter<'a> { /// Set to 27. pub fn format(&self) -> u8 { - let range = self.shape.format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Offset to a Paint subtable. pub fn paint_offset(&self) -> Offset24 { - let range = self.shape.paint_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.paint_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`paint_offset`][Self::paint_offset]. @@ -5444,28 +5315,28 @@ impl<'a> PaintVarRotateAroundCenter<'a> { /// Rotation angle, 180° in counter-clockwise degrees per 1.0 of /// value. For variation, use varIndexBase + 0. pub fn angle(&self) -> F2Dot14 { - let range = self.shape.angle_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.angle_byte_range(); + unchecked::read_at(self.data, range.start) } /// x coordinate for the center of rotation. For variation, use /// varIndexBase + 1. pub fn center_x(&self) -> FWord { - let range = self.shape.center_x_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.center_x_byte_range(); + unchecked::read_at(self.data, range.start) } /// y coordinate for the center of rotation. For variation, use /// varIndexBase + 2. pub fn center_y(&self) -> FWord { - let range = self.shape.center_y_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.center_y_byte_range(); + unchecked::read_at(self.data, range.start) } /// Base index into DeltaSetIndexMap. pub fn var_index_base(&self) -> u32 { - let range = self.shape.var_index_base_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.var_index_base_byte_range(); + unchecked::read_at(self.data, range.start) } } @@ -5505,9 +5376,29 @@ impl Format for PaintSkewMarker { /// [PaintSkew](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-28-to-31-paintskew-paintvarskew-paintskewaroundcenter-paintvarskewaroundcenter) table #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct PaintSkewMarker {} +pub struct PaintSkewMarker; + +impl<'a> MinByteRange for PaintSkew<'a> { + fn min_byte_range(&self) -> Range { + 0..self.y_skew_angle_byte_range().end + } +} + +impl<'a> FontRead<'a> for PaintSkew<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// [PaintSkew](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-28-to-31-paintskew-paintvarskew-paintskewaroundcenter-paintvarskewaroundcenter) table +pub type PaintSkew<'a> = TableRef<'a, PaintSkewMarker, ()>; -impl PaintSkewMarker { +#[allow(clippy::needless_lifetimes)] +impl<'a> PaintSkew<'a> { pub fn format_byte_range(&self) -> Range { let start = 0; start..start + u8::RAW_BYTE_LEN @@ -5527,40 +5418,17 @@ impl PaintSkewMarker { let start = self.x_skew_angle_byte_range().end; start..start + F2Dot14::RAW_BYTE_LEN } -} - -impl MinByteRange for PaintSkewMarker { - fn min_byte_range(&self) -> Range { - 0..self.y_skew_angle_byte_range().end - } -} - -impl<'a> FontRead<'a> for PaintSkew<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.finish(PaintSkewMarker {}) - } -} -/// [PaintSkew](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-28-to-31-paintskew-paintvarskew-paintskewaroundcenter-paintvarskewaroundcenter) table -pub type PaintSkew<'a> = TableRef<'a, PaintSkewMarker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> PaintSkew<'a> { /// Set to 28. pub fn format(&self) -> u8 { - let range = self.shape.format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Offset to a Paint subtable. pub fn paint_offset(&self) -> Offset24 { - let range = self.shape.paint_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.paint_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`paint_offset`][Self::paint_offset]. @@ -5572,15 +5440,15 @@ impl<'a> PaintSkew<'a> { /// Angle of skew in the direction of the x-axis, 180° in /// counter-clockwise degrees per 1.0 of value. pub fn x_skew_angle(&self) -> F2Dot14 { - let range = self.shape.x_skew_angle_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.x_skew_angle_byte_range(); + unchecked::read_at(self.data, range.start) } /// Angle of skew in the direction of the y-axis, 180° in /// counter-clockwise degrees per 1.0 of value. pub fn y_skew_angle(&self) -> F2Dot14 { - let range = self.shape.y_skew_angle_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.y_skew_angle_byte_range(); + unchecked::read_at(self.data, range.start) } } @@ -5618,9 +5486,29 @@ impl Format for PaintVarSkewMarker { /// [PaintVarSkew](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-28-to-31-paintskew-paintvarskew-paintskewaroundcenter-paintvarskewaroundcenter) table #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct PaintVarSkewMarker {} +pub struct PaintVarSkewMarker; + +impl<'a> MinByteRange for PaintVarSkew<'a> { + fn min_byte_range(&self) -> Range { + 0..self.var_index_base_byte_range().end + } +} + +impl<'a> FontRead<'a> for PaintVarSkew<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} -impl PaintVarSkewMarker { +/// [PaintVarSkew](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-28-to-31-paintskew-paintvarskew-paintskewaroundcenter-paintvarskewaroundcenter) table +pub type PaintVarSkew<'a> = TableRef<'a, PaintVarSkewMarker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> PaintVarSkew<'a> { pub fn format_byte_range(&self) -> Range { let start = 0; start..start + u8::RAW_BYTE_LEN @@ -5645,41 +5533,17 @@ impl PaintVarSkewMarker { let start = self.y_skew_angle_byte_range().end; start..start + u32::RAW_BYTE_LEN } -} - -impl MinByteRange for PaintVarSkewMarker { - fn min_byte_range(&self) -> Range { - 0..self.var_index_base_byte_range().end - } -} - -impl<'a> FontRead<'a> for PaintVarSkew<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.finish(PaintVarSkewMarker {}) - } -} - -/// [PaintVarSkew](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-28-to-31-paintskew-paintvarskew-paintskewaroundcenter-paintvarskewaroundcenter) table -pub type PaintVarSkew<'a> = TableRef<'a, PaintVarSkewMarker>; -#[allow(clippy::needless_lifetimes)] -impl<'a> PaintVarSkew<'a> { /// Set to 29. pub fn format(&self) -> u8 { - let range = self.shape.format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Offset to a Paint subtable. pub fn paint_offset(&self) -> Offset24 { - let range = self.shape.paint_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.paint_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`paint_offset`][Self::paint_offset]. @@ -5692,22 +5556,22 @@ impl<'a> PaintVarSkew<'a> { /// counter-clockwise degrees per 1.0 of value. For variation, use /// varIndexBase + 0. pub fn x_skew_angle(&self) -> F2Dot14 { - let range = self.shape.x_skew_angle_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.x_skew_angle_byte_range(); + unchecked::read_at(self.data, range.start) } /// Angle of skew in the direction of the y-axis, 180° in /// counter-clockwise degrees per 1.0 of value. For variation, use /// varIndexBase + 1. pub fn y_skew_angle(&self) -> F2Dot14 { - let range = self.shape.y_skew_angle_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.y_skew_angle_byte_range(); + unchecked::read_at(self.data, range.start) } /// Base index into DeltaSetIndexMap. pub fn var_index_base(&self) -> u32 { - let range = self.shape.var_index_base_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.var_index_base_byte_range(); + unchecked::read_at(self.data, range.start) } } @@ -5746,9 +5610,29 @@ impl Format for PaintSkewAroundCenterMarker { /// [PaintSkewAroundCenter](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-28-to-31-paintskew-paintvarskew-paintskewaroundcenter-paintvarskewaroundcenter) table #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct PaintSkewAroundCenterMarker {} +pub struct PaintSkewAroundCenterMarker; + +impl<'a> MinByteRange for PaintSkewAroundCenter<'a> { + fn min_byte_range(&self) -> Range { + 0..self.center_y_byte_range().end + } +} + +impl<'a> FontRead<'a> for PaintSkewAroundCenter<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// [PaintSkewAroundCenter](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-28-to-31-paintskew-paintvarskew-paintskewaroundcenter-paintvarskewaroundcenter) table +pub type PaintSkewAroundCenter<'a> = TableRef<'a, PaintSkewAroundCenterMarker, ()>; -impl PaintSkewAroundCenterMarker { +#[allow(clippy::needless_lifetimes)] +impl<'a> PaintSkewAroundCenter<'a> { pub fn format_byte_range(&self) -> Range { let start = 0; start..start + u8::RAW_BYTE_LEN @@ -5778,42 +5662,17 @@ impl PaintSkewAroundCenterMarker { let start = self.center_x_byte_range().end; start..start + FWord::RAW_BYTE_LEN } -} - -impl MinByteRange for PaintSkewAroundCenterMarker { - fn min_byte_range(&self) -> Range { - 0..self.center_y_byte_range().end - } -} - -impl<'a> FontRead<'a> for PaintSkewAroundCenter<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.finish(PaintSkewAroundCenterMarker {}) - } -} - -/// [PaintSkewAroundCenter](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-28-to-31-paintskew-paintvarskew-paintskewaroundcenter-paintvarskewaroundcenter) table -pub type PaintSkewAroundCenter<'a> = TableRef<'a, PaintSkewAroundCenterMarker>; -#[allow(clippy::needless_lifetimes)] -impl<'a> PaintSkewAroundCenter<'a> { /// Set to 30. pub fn format(&self) -> u8 { - let range = self.shape.format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Offset to a Paint subtable. pub fn paint_offset(&self) -> Offset24 { - let range = self.shape.paint_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.paint_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`paint_offset`][Self::paint_offset]. @@ -5825,27 +5684,27 @@ impl<'a> PaintSkewAroundCenter<'a> { /// Angle of skew in the direction of the x-axis, 180° in /// counter-clockwise degrees per 1.0 of value. pub fn x_skew_angle(&self) -> F2Dot14 { - let range = self.shape.x_skew_angle_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.x_skew_angle_byte_range(); + unchecked::read_at(self.data, range.start) } /// Angle of skew in the direction of the y-axis, 180° in /// counter-clockwise degrees per 1.0 of value. pub fn y_skew_angle(&self) -> F2Dot14 { - let range = self.shape.y_skew_angle_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.y_skew_angle_byte_range(); + unchecked::read_at(self.data, range.start) } /// x coordinate for the center of rotation. pub fn center_x(&self) -> FWord { - let range = self.shape.center_x_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.center_x_byte_range(); + unchecked::read_at(self.data, range.start) } /// y coordinate for the center of rotation. pub fn center_y(&self) -> FWord { - let range = self.shape.center_y_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.center_y_byte_range(); + unchecked::read_at(self.data, range.start) } } @@ -5885,9 +5744,29 @@ impl Format for PaintVarSkewAroundCenterMarker { /// [PaintVarSkewAroundCenter](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-28-to-31-paintskew-paintvarskew-paintskewaroundcenter-paintvarskewaroundcenter) table #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct PaintVarSkewAroundCenterMarker {} +pub struct PaintVarSkewAroundCenterMarker; + +impl<'a> MinByteRange for PaintVarSkewAroundCenter<'a> { + fn min_byte_range(&self) -> Range { + 0..self.var_index_base_byte_range().end + } +} + +impl<'a> FontRead<'a> for PaintVarSkewAroundCenter<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// [PaintVarSkewAroundCenter](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-28-to-31-paintskew-paintvarskew-paintskewaroundcenter-paintvarskewaroundcenter) table +pub type PaintVarSkewAroundCenter<'a> = TableRef<'a, PaintVarSkewAroundCenterMarker, ()>; -impl PaintVarSkewAroundCenterMarker { +#[allow(clippy::needless_lifetimes)] +impl<'a> PaintVarSkewAroundCenter<'a> { pub fn format_byte_range(&self) -> Range { let start = 0; start..start + u8::RAW_BYTE_LEN @@ -5922,43 +5801,17 @@ impl PaintVarSkewAroundCenterMarker { let start = self.center_y_byte_range().end; start..start + u32::RAW_BYTE_LEN } -} - -impl MinByteRange for PaintVarSkewAroundCenterMarker { - fn min_byte_range(&self) -> Range { - 0..self.var_index_base_byte_range().end - } -} - -impl<'a> FontRead<'a> for PaintVarSkewAroundCenter<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.finish(PaintVarSkewAroundCenterMarker {}) - } -} - -/// [PaintVarSkewAroundCenter](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#formats-28-to-31-paintskew-paintvarskew-paintskewaroundcenter-paintvarskewaroundcenter) table -pub type PaintVarSkewAroundCenter<'a> = TableRef<'a, PaintVarSkewAroundCenterMarker>; -#[allow(clippy::needless_lifetimes)] -impl<'a> PaintVarSkewAroundCenter<'a> { /// Set to 31. pub fn format(&self) -> u8 { - let range = self.shape.format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Offset to a Paint subtable. pub fn paint_offset(&self) -> Offset24 { - let range = self.shape.paint_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.paint_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`paint_offset`][Self::paint_offset]. @@ -5971,36 +5824,36 @@ impl<'a> PaintVarSkewAroundCenter<'a> { /// counter-clockwise degrees per 1.0 of value. For variation, use /// varIndexBase + 0. pub fn x_skew_angle(&self) -> F2Dot14 { - let range = self.shape.x_skew_angle_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.x_skew_angle_byte_range(); + unchecked::read_at(self.data, range.start) } /// Angle of skew in the direction of the y-axis, 180° in /// counter-clockwise degrees per 1.0 of value. For variation, use /// varIndexBase + 1. pub fn y_skew_angle(&self) -> F2Dot14 { - let range = self.shape.y_skew_angle_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.y_skew_angle_byte_range(); + unchecked::read_at(self.data, range.start) } /// x coordinate for the center of rotation. For variation, use /// varIndexBase + 2. pub fn center_x(&self) -> FWord { - let range = self.shape.center_x_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.center_x_byte_range(); + unchecked::read_at(self.data, range.start) } /// y coordinate for the center of rotation. For variation, use /// varIndexBase + 3. pub fn center_y(&self) -> FWord { - let range = self.shape.center_y_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.center_y_byte_range(); + unchecked::read_at(self.data, range.start) } /// Base index into DeltaSetIndexMap. pub fn var_index_base(&self) -> u32 { - let range = self.shape.var_index_base_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.var_index_base_byte_range(); + unchecked::read_at(self.data, range.start) } } @@ -6041,9 +5894,29 @@ impl Format for PaintCompositeMarker { /// [PaintComposite](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#format-32-paintcomposite) table #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct PaintCompositeMarker {} +pub struct PaintCompositeMarker; + +impl<'a> MinByteRange for PaintComposite<'a> { + fn min_byte_range(&self) -> Range { + 0..self.backdrop_paint_offset_byte_range().end + } +} + +impl<'a> FontRead<'a> for PaintComposite<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// [PaintComposite](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#format-32-paintcomposite) table +pub type PaintComposite<'a> = TableRef<'a, PaintCompositeMarker, ()>; -impl PaintCompositeMarker { +#[allow(clippy::needless_lifetimes)] +impl<'a> PaintComposite<'a> { pub fn format_byte_range(&self) -> Range { let start = 0; start..start + u8::RAW_BYTE_LEN @@ -6063,40 +5936,17 @@ impl PaintCompositeMarker { let start = self.composite_mode_byte_range().end; start..start + Offset24::RAW_BYTE_LEN } -} - -impl MinByteRange for PaintCompositeMarker { - fn min_byte_range(&self) -> Range { - 0..self.backdrop_paint_offset_byte_range().end - } -} - -impl<'a> FontRead<'a> for PaintComposite<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.finish(PaintCompositeMarker {}) - } -} -/// [PaintComposite](https://learn.microsoft.com/en-us/typography/opentype/spec/colr#format-32-paintcomposite) table -pub type PaintComposite<'a> = TableRef<'a, PaintCompositeMarker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> PaintComposite<'a> { /// Set to 32. pub fn format(&self) -> u8 { - let range = self.shape.format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Offset to a source Paint table. pub fn source_paint_offset(&self) -> Offset24 { - let range = self.shape.source_paint_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.source_paint_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`source_paint_offset`][Self::source_paint_offset]. @@ -6107,14 +5957,14 @@ impl<'a> PaintComposite<'a> { /// A CompositeMode enumeration value. pub fn composite_mode(&self) -> CompositeMode { - let range = self.shape.composite_mode_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.composite_mode_byte_range(); + unchecked::read_at(self.data, range.start) } /// Offset to a backdrop Paint table. pub fn backdrop_paint_offset(&self) -> Offset24 { - let range = self.shape.backdrop_paint_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.backdrop_paint_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`backdrop_paint_offset`][Self::backdrop_paint_offset]. diff --git a/read-fonts/generated/generated_cpal.rs b/read-fonts/generated/generated_cpal.rs index 0d9d3393e..309ea4ab3 100644 --- a/read-fonts/generated/generated_cpal.rs +++ b/read-fonts/generated/generated_cpal.rs @@ -8,14 +8,41 @@ use crate::codegen_prelude::*; /// [CPAL (Color Palette Table)](https://learn.microsoft.com/en-us/typography/opentype/spec/cpal#palette-table-header) table #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct CpalMarker { - color_record_indices_byte_len: usize, - palette_types_array_offset_byte_start: Option, - palette_labels_array_offset_byte_start: Option, - palette_entry_labels_array_offset_byte_start: Option, +pub struct CpalMarker; + +impl<'a> MinByteRange for Cpal<'a> { + fn min_byte_range(&self) -> Range { + 0..self.color_record_indices_byte_range().end + } +} + +impl TopLevelTable for Cpal<'_> { + /// `CPAL` + const TAG: Tag = Tag::new(b"CPAL"); } -impl CpalMarker { +impl<'a> FontRead<'a> for Cpal<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// [CPAL (Color Palette Table)](https://learn.microsoft.com/en-us/typography/opentype/spec/cpal#palette-table-header) table +pub type Cpal<'a> = TableRef<'a, CpalMarker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> Cpal<'a> { + fn color_record_indices_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.num_palettes()) as usize) + .checked_mul(u16::RAW_BYTE_LEN) + .unwrap() + } + pub fn version_byte_range(&self) -> Range { let start = 0; start..start + u16::RAW_BYTE_LEN @@ -43,112 +70,75 @@ impl CpalMarker { pub fn color_record_indices_byte_range(&self) -> Range { let start = self.color_records_array_offset_byte_range().end; - start..start + self.color_record_indices_byte_len + start..start + self.color_record_indices_byte_len(start) } pub fn palette_types_array_offset_byte_range(&self) -> Option> { - let start = self.palette_types_array_offset_byte_start?; - Some(start..start + Offset32::RAW_BYTE_LEN) + if self.version().compatible(1u16) { + let start = self.color_record_indices_byte_range().end; + Some(start..start + Offset32::RAW_BYTE_LEN) + } else { + None + } } pub fn palette_labels_array_offset_byte_range(&self) -> Option> { - let start = self.palette_labels_array_offset_byte_start?; - Some(start..start + Offset32::RAW_BYTE_LEN) + if self.version().compatible(1u16) { + let start = self + .palette_types_array_offset_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| self.color_record_indices_byte_range().end); + Some(start..start + Offset32::RAW_BYTE_LEN) + } else { + None + } } pub fn palette_entry_labels_array_offset_byte_range(&self) -> Option> { - let start = self.palette_entry_labels_array_offset_byte_start?; - Some(start..start + Offset32::RAW_BYTE_LEN) - } -} - -impl MinByteRange for CpalMarker { - fn min_byte_range(&self) -> Range { - 0..self.color_record_indices_byte_range().end - } -} - -impl TopLevelTable for Cpal<'_> { - /// `CPAL` - const TAG: Tag = Tag::new(b"CPAL"); -} - -impl<'a> FontRead<'a> for Cpal<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - let version: u16 = cursor.read()?; - cursor.advance::(); - let num_palettes: u16 = cursor.read()?; - cursor.advance::(); - cursor.advance::(); - let color_record_indices_byte_len = (num_palettes as usize) - .checked_mul(u16::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(color_record_indices_byte_len); - let palette_types_array_offset_byte_start = version - .compatible(1u16) - .then(|| cursor.position()) - .transpose()?; - version - .compatible(1u16) - .then(|| cursor.advance::()); - let palette_labels_array_offset_byte_start = version - .compatible(1u16) - .then(|| cursor.position()) - .transpose()?; - version - .compatible(1u16) - .then(|| cursor.advance::()); - let palette_entry_labels_array_offset_byte_start = version - .compatible(1u16) - .then(|| cursor.position()) - .transpose()?; - version - .compatible(1u16) - .then(|| cursor.advance::()); - cursor.finish(CpalMarker { - color_record_indices_byte_len, - palette_types_array_offset_byte_start, - palette_labels_array_offset_byte_start, - palette_entry_labels_array_offset_byte_start, - }) + if self.version().compatible(1u16) { + let start = self + .palette_labels_array_offset_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| { + self.palette_types_array_offset_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| self.color_record_indices_byte_range().end) + }); + Some(start..start + Offset32::RAW_BYTE_LEN) + } else { + None + } } -} - -/// [CPAL (Color Palette Table)](https://learn.microsoft.com/en-us/typography/opentype/spec/cpal#palette-table-header) table -pub type Cpal<'a> = TableRef<'a, CpalMarker>; -#[allow(clippy::needless_lifetimes)] -impl<'a> Cpal<'a> { /// Table version number (=0). pub fn version(&self) -> u16 { - let range = self.shape.version_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.version_byte_range(); + unchecked::read_at(self.data, range.start) } /// Number of palette entries in each palette. pub fn num_palette_entries(&self) -> u16 { - let range = self.shape.num_palette_entries_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.num_palette_entries_byte_range(); + unchecked::read_at(self.data, range.start) } /// Number of palettes in the table. pub fn num_palettes(&self) -> u16 { - let range = self.shape.num_palettes_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.num_palettes_byte_range(); + unchecked::read_at(self.data, range.start) } /// Total number of color records, combined for all palettes. pub fn num_color_records(&self) -> u16 { - let range = self.shape.num_color_records_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.num_color_records_byte_range(); + unchecked::read_at(self.data, range.start) } /// Offset from the beginning of CPAL table to the first /// ColorRecord. pub fn color_records_array_offset(&self) -> Nullable { - let range = self.shape.color_records_array_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.color_records_array_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`color_records_array_offset`][Self::color_records_array_offset]. @@ -162,8 +152,8 @@ impl<'a> Cpal<'a> { /// Index of each palette’s first color record in the combined /// color record array. pub fn color_record_indices(&self) -> &'a [BigEndian] { - let range = self.shape.color_record_indices_byte_range(); - self.data.read_array(range).unwrap() + let range = self.color_record_indices_byte_range(); + unchecked::read_array(self.data, range) } /// Offset from the beginning of CPAL table to the [Palette Types Array][]. @@ -172,8 +162,8 @@ impl<'a> Cpal<'a> { /// /// [Palette Types Array]: https://learn.microsoft.com/en-us/typography/opentype/spec/cpal#palette-type-array pub fn palette_types_array_offset(&self) -> Option> { - let range = self.shape.palette_types_array_offset_byte_range()?; - Some(self.data.read_at(range.start).unwrap()) + let range = self.palette_types_array_offset_byte_range()?; + Some(unchecked::read_at(self.data, range.start)) } /// Attempt to resolve [`palette_types_array_offset`][Self::palette_types_array_offset]. @@ -192,8 +182,8 @@ impl<'a> Cpal<'a> { /// /// [Palette Labels Array]: https://learn.microsoft.com/en-us/typography/opentype/spec/cpal#palette-labels-array pub fn palette_labels_array_offset(&self) -> Option> { - let range = self.shape.palette_labels_array_offset_byte_range()?; - Some(self.data.read_at(range.start).unwrap()) + let range = self.palette_labels_array_offset_byte_range()?; + Some(unchecked::read_at(self.data, range.start)) } /// Attempt to resolve [`palette_labels_array_offset`][Self::palette_labels_array_offset]. @@ -214,8 +204,8 @@ impl<'a> Cpal<'a> { /// /// [Palette Entry Labels Array]: https://learn.microsoft.com/en-us/typography/opentype/spec/cpal#palette-entry-label-array pub fn palette_entry_labels_array_offset(&self) -> Option> { - let range = self.shape.palette_entry_labels_array_offset_byte_range()?; - Some(self.data.read_at(range.start).unwrap()) + let range = self.palette_entry_labels_array_offset_byte_range()?; + Some(unchecked::read_at(self.data, range.start)) } /// Attempt to resolve [`palette_entry_labels_array_offset`][Self::palette_entry_labels_array_offset]. diff --git a/read-fonts/generated/generated_cvar.rs b/read-fonts/generated/generated_cvar.rs index 89c6ae2f9..7b868974b 100644 --- a/read-fonts/generated/generated_cvar.rs +++ b/read-fonts/generated/generated_cvar.rs @@ -8,33 +8,9 @@ use crate::codegen_prelude::*; /// The [cvar](https://learn.microsoft.com/en-us/typography/opentype/spec/cvar) table. #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct CvarMarker { - tuple_variation_headers_byte_len: usize, -} - -impl CvarMarker { - pub fn version_byte_range(&self) -> Range { - let start = 0; - start..start + MajorMinor::RAW_BYTE_LEN - } - - pub fn tuple_variation_count_byte_range(&self) -> Range { - let start = self.version_byte_range().end; - start..start + TupleVariationCount::RAW_BYTE_LEN - } - - pub fn data_offset_byte_range(&self) -> Range { - let start = self.tuple_variation_count_byte_range().end; - start..start + Offset16::RAW_BYTE_LEN - } - - pub fn tuple_variation_headers_byte_range(&self) -> Range { - let start = self.data_offset_byte_range().end; - start..start + self.tuple_variation_headers_byte_len - } -} +pub struct CvarMarker; -impl MinByteRange for CvarMarker { +impl<'a> MinByteRange for Cvar<'a> { fn min_byte_range(&self) -> Range { 0..self.tuple_variation_headers_byte_range().end } @@ -47,27 +23,48 @@ impl TopLevelTable for Cvar<'_> { impl<'a> FontRead<'a> for Cvar<'a> { fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - let tuple_variation_headers_byte_len = cursor.remaining_bytes(); - cursor.advance_by(tuple_variation_headers_byte_len); - cursor.finish(CvarMarker { - tuple_variation_headers_byte_len, + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, }) } } /// The [cvar](https://learn.microsoft.com/en-us/typography/opentype/spec/cvar) table. -pub type Cvar<'a> = TableRef<'a, CvarMarker>; +pub type Cvar<'a> = TableRef<'a, CvarMarker, ()>; #[allow(clippy::needless_lifetimes)] impl<'a> Cvar<'a> { + fn tuple_variation_headers_byte_len(&self, start: usize) -> usize { + let _ = start; + self.data.len().saturating_sub(start) + } + + pub fn version_byte_range(&self) -> Range { + let start = 0; + start..start + MajorMinor::RAW_BYTE_LEN + } + + pub fn tuple_variation_count_byte_range(&self) -> Range { + let start = self.version_byte_range().end; + start..start + TupleVariationCount::RAW_BYTE_LEN + } + + pub fn data_offset_byte_range(&self) -> Range { + let start = self.tuple_variation_count_byte_range().end; + start..start + Offset16::RAW_BYTE_LEN + } + + pub fn tuple_variation_headers_byte_range(&self) -> Range { + let start = self.data_offset_byte_range().end; + start..start + self.tuple_variation_headers_byte_len(start) + } + /// Major/minor version number of the CVT variations table — set to (1,0). pub fn version(&self) -> MajorMinor { - let range = self.shape.version_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.version_byte_range(); + unchecked::read_at(self.data, range.start) } /// A packed field. The high 4 bits are flags, and the low 12 bits @@ -75,14 +72,14 @@ impl<'a> Cvar<'a> { /// number of tuple variation tables can be any number between 1 /// and 4095. pub fn tuple_variation_count(&self) -> TupleVariationCount { - let range = self.shape.tuple_variation_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.tuple_variation_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Offset from the start of the 'cvar' table to the serialized data. pub fn data_offset(&self) -> Offset16 { - let range = self.shape.data_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.data_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`data_offset`][Self::data_offset]. @@ -93,8 +90,8 @@ impl<'a> Cvar<'a> { /// Array of tuple variation headers. pub fn tuple_variation_headers(&self) -> VarLenArray<'a, TupleVariationHeader<'a>> { - let range = self.shape.tuple_variation_headers_byte_range(); - VarLenArray::read(self.data.split_off(range.start).unwrap()).unwrap() + let range = self.tuple_variation_headers_byte_range(); + VarLenArray::read(unchecked::split_off(self.data, range.start)).unwrap() } } diff --git a/read-fonts/generated/generated_dsig.rs b/read-fonts/generated/generated_dsig.rs index 715a9fe36..473880bf0 100644 --- a/read-fonts/generated/generated_dsig.rs +++ b/read-fonts/generated/generated_dsig.rs @@ -8,33 +8,9 @@ use crate::codegen_prelude::*; /// [DSIG (Digital Signature Table)](https://docs.microsoft.com/en-us/typography/opentype/spec/dsig#table-structure) table #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct DsigMarker { - signature_records_byte_len: usize, -} - -impl DsigMarker { - pub fn version_byte_range(&self) -> Range { - let start = 0; - start..start + u32::RAW_BYTE_LEN - } - - pub fn num_signatures_byte_range(&self) -> Range { - let start = self.version_byte_range().end; - start..start + u16::RAW_BYTE_LEN - } - - pub fn flags_byte_range(&self) -> Range { - let start = self.num_signatures_byte_range().end; - start..start + PermissionFlags::RAW_BYTE_LEN - } - - pub fn signature_records_byte_range(&self) -> Range { - let start = self.flags_byte_range().end; - start..start + self.signature_records_byte_len - } -} +pub struct DsigMarker; -impl MinByteRange for DsigMarker { +impl<'a> MinByteRange for Dsig<'a> { fn min_byte_range(&self) -> Range { 0..self.signature_records_byte_range().end } @@ -47,47 +23,68 @@ impl TopLevelTable for Dsig<'_> { impl<'a> FontRead<'a> for Dsig<'a> { fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - let num_signatures: u16 = cursor.read()?; - cursor.advance::(); - let signature_records_byte_len = (num_signatures as usize) - .checked_mul(SignatureRecord::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(signature_records_byte_len); - cursor.finish(DsigMarker { - signature_records_byte_len, + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, }) } } /// [DSIG (Digital Signature Table)](https://docs.microsoft.com/en-us/typography/opentype/spec/dsig#table-structure) table -pub type Dsig<'a> = TableRef<'a, DsigMarker>; +pub type Dsig<'a> = TableRef<'a, DsigMarker, ()>; #[allow(clippy::needless_lifetimes)] impl<'a> Dsig<'a> { + fn signature_records_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.num_signatures()) as usize) + .checked_mul(SignatureRecord::RAW_BYTE_LEN) + .unwrap() + } + + pub fn version_byte_range(&self) -> Range { + let start = 0; + start..start + u32::RAW_BYTE_LEN + } + + pub fn num_signatures_byte_range(&self) -> Range { + let start = self.version_byte_range().end; + start..start + u16::RAW_BYTE_LEN + } + + pub fn flags_byte_range(&self) -> Range { + let start = self.num_signatures_byte_range().end; + start..start + PermissionFlags::RAW_BYTE_LEN + } + + pub fn signature_records_byte_range(&self) -> Range { + let start = self.flags_byte_range().end; + start..start + self.signature_records_byte_len(start) + } + /// Version number of the DSIG table (0x00000001) pub fn version(&self) -> u32 { - let range = self.shape.version_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.version_byte_range(); + unchecked::read_at(self.data, range.start) } /// Number of signatures in the table pub fn num_signatures(&self) -> u16 { - let range = self.shape.num_signatures_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.num_signatures_byte_range(); + unchecked::read_at(self.data, range.start) } /// Permission flags pub fn flags(&self) -> PermissionFlags { - let range = self.shape.flags_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.flags_byte_range(); + unchecked::read_at(self.data, range.start) } /// Array of signature records pub fn signature_records(&self) -> &'a [SignatureRecord] { - let range = self.shape.signature_records_byte_range(); - self.data.read_array(range).unwrap() + let range = self.signature_records_byte_range(); + unchecked::read_array(self.data, range) } } @@ -482,11 +479,36 @@ impl<'a> SomeRecord<'a> for SignatureRecord { /// [Signature Block Format 1](https://learn.microsoft.com/en-us/typography/opentype/spec/dsig#table-structure) #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct SignatureBlockFormat1Marker { - signature_byte_len: usize, +pub struct SignatureBlockFormat1Marker; + +impl<'a> MinByteRange for SignatureBlockFormat1<'a> { + fn min_byte_range(&self) -> Range { + 0..self.signature_byte_range().end + } +} + +impl<'a> FontRead<'a> for SignatureBlockFormat1<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } } -impl SignatureBlockFormat1Marker { +/// [Signature Block Format 1](https://learn.microsoft.com/en-us/typography/opentype/spec/dsig#table-structure) +pub type SignatureBlockFormat1<'a> = TableRef<'a, SignatureBlockFormat1Marker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> SignatureBlockFormat1<'a> { + fn signature_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.signature_length()) as usize) + .checked_mul(u8::RAW_BYTE_LEN) + .unwrap() + } + pub fn _reserved1_byte_range(&self) -> Range { let start = 0; start..start + u16::RAW_BYTE_LEN @@ -504,45 +526,19 @@ impl SignatureBlockFormat1Marker { pub fn signature_byte_range(&self) -> Range { let start = self.signature_length_byte_range().end; - start..start + self.signature_byte_len - } -} - -impl MinByteRange for SignatureBlockFormat1Marker { - fn min_byte_range(&self) -> Range { - 0..self.signature_byte_range().end + start..start + self.signature_byte_len(start) } -} -impl<'a> FontRead<'a> for SignatureBlockFormat1<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - let signature_length: u32 = cursor.read()?; - let signature_byte_len = (signature_length as usize) - .checked_mul(u8::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(signature_byte_len); - cursor.finish(SignatureBlockFormat1Marker { signature_byte_len }) - } -} - -/// [Signature Block Format 1](https://learn.microsoft.com/en-us/typography/opentype/spec/dsig#table-structure) -pub type SignatureBlockFormat1<'a> = TableRef<'a, SignatureBlockFormat1Marker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> SignatureBlockFormat1<'a> { /// Length (in bytes) of the PKCS#7 packet in the signature field. pub fn signature_length(&self) -> u32 { - let range = self.shape.signature_length_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.signature_length_byte_range(); + unchecked::read_at(self.data, range.start) } /// PKCS#7 packet pub fn signature(&self) -> &'a [u8] { - let range = self.shape.signature_byte_range(); - self.data.read_array(range).unwrap() + let range = self.signature_byte_range(); + unchecked::read_array(self.data, range) } } diff --git a/read-fonts/generated/generated_ebdt.rs b/read-fonts/generated/generated_ebdt.rs index 5e6a498d9..8a6b34b16 100644 --- a/read-fonts/generated/generated_ebdt.rs +++ b/read-fonts/generated/generated_ebdt.rs @@ -8,21 +8,9 @@ use crate::codegen_prelude::*; /// The [Embedded Bitmap Data](https://learn.microsoft.com/en-us/typography/opentype/spec/ebdt) table #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct EbdtMarker {} +pub struct EbdtMarker; -impl EbdtMarker { - pub fn major_version_byte_range(&self) -> Range { - let start = 0; - start..start + u16::RAW_BYTE_LEN - } - - pub fn minor_version_byte_range(&self) -> Range { - let start = self.major_version_byte_range().end; - start..start + u16::RAW_BYTE_LEN - } -} - -impl MinByteRange for EbdtMarker { +impl<'a> MinByteRange for Ebdt<'a> { fn min_byte_range(&self) -> Range { 0..self.minor_version_byte_range().end } @@ -35,28 +23,39 @@ impl TopLevelTable for Ebdt<'_> { impl<'a> FontRead<'a> for Ebdt<'a> { fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.finish(EbdtMarker {}) + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) } } /// The [Embedded Bitmap Data](https://learn.microsoft.com/en-us/typography/opentype/spec/ebdt) table -pub type Ebdt<'a> = TableRef<'a, EbdtMarker>; +pub type Ebdt<'a> = TableRef<'a, EbdtMarker, ()>; #[allow(clippy::needless_lifetimes)] impl<'a> Ebdt<'a> { + pub fn major_version_byte_range(&self) -> Range { + let start = 0; + start..start + u16::RAW_BYTE_LEN + } + + pub fn minor_version_byte_range(&self) -> Range { + let start = self.major_version_byte_range().end; + start..start + u16::RAW_BYTE_LEN + } + /// Major version of the EBDT table, = 2. pub fn major_version(&self) -> u16 { - let range = self.shape.major_version_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.major_version_byte_range(); + unchecked::read_at(self.data, range.start) } /// Minor version of EBDT table, = 0. pub fn minor_version(&self) -> u16 { - let range = self.shape.minor_version_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.minor_version_byte_range(); + unchecked::read_at(self.data, range.start) } } diff --git a/read-fonts/generated/generated_eblc.rs b/read-fonts/generated/generated_eblc.rs index 332d75244..d5041646f 100644 --- a/read-fonts/generated/generated_eblc.rs +++ b/read-fonts/generated/generated_eblc.rs @@ -8,33 +8,9 @@ use crate::codegen_prelude::*; /// The [Embedded Bitmap Location](https://learn.microsoft.com/en-us/typography/opentype/spec/eblc) table #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct EblcMarker { - bitmap_sizes_byte_len: usize, -} - -impl EblcMarker { - pub fn major_version_byte_range(&self) -> Range { - let start = 0; - start..start + u16::RAW_BYTE_LEN - } - - pub fn minor_version_byte_range(&self) -> Range { - let start = self.major_version_byte_range().end; - start..start + u16::RAW_BYTE_LEN - } +pub struct EblcMarker; - pub fn num_sizes_byte_range(&self) -> Range { - let start = self.minor_version_byte_range().end; - start..start + u32::RAW_BYTE_LEN - } - - pub fn bitmap_sizes_byte_range(&self) -> Range { - let start = self.num_sizes_byte_range().end; - start..start + self.bitmap_sizes_byte_len - } -} - -impl MinByteRange for EblcMarker { +impl<'a> MinByteRange for Eblc<'a> { fn min_byte_range(&self) -> Range { 0..self.bitmap_sizes_byte_range().end } @@ -47,47 +23,68 @@ impl TopLevelTable for Eblc<'_> { impl<'a> FontRead<'a> for Eblc<'a> { fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - let num_sizes: u32 = cursor.read()?; - let bitmap_sizes_byte_len = (num_sizes as usize) - .checked_mul(BitmapSize::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(bitmap_sizes_byte_len); - cursor.finish(EblcMarker { - bitmap_sizes_byte_len, + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, }) } } /// The [Embedded Bitmap Location](https://learn.microsoft.com/en-us/typography/opentype/spec/eblc) table -pub type Eblc<'a> = TableRef<'a, EblcMarker>; +pub type Eblc<'a> = TableRef<'a, EblcMarker, ()>; #[allow(clippy::needless_lifetimes)] impl<'a> Eblc<'a> { + fn bitmap_sizes_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.num_sizes()) as usize) + .checked_mul(BitmapSize::RAW_BYTE_LEN) + .unwrap() + } + + pub fn major_version_byte_range(&self) -> Range { + let start = 0; + start..start + u16::RAW_BYTE_LEN + } + + pub fn minor_version_byte_range(&self) -> Range { + let start = self.major_version_byte_range().end; + start..start + u16::RAW_BYTE_LEN + } + + pub fn num_sizes_byte_range(&self) -> Range { + let start = self.minor_version_byte_range().end; + start..start + u32::RAW_BYTE_LEN + } + + pub fn bitmap_sizes_byte_range(&self) -> Range { + let start = self.num_sizes_byte_range().end; + start..start + self.bitmap_sizes_byte_len(start) + } + /// Major version of the EBLC table, = 2. pub fn major_version(&self) -> u16 { - let range = self.shape.major_version_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.major_version_byte_range(); + unchecked::read_at(self.data, range.start) } /// Minor version of EBLC table, = 0. pub fn minor_version(&self) -> u16 { - let range = self.shape.minor_version_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.minor_version_byte_range(); + unchecked::read_at(self.data, range.start) } /// Number of BitmapSize records. pub fn num_sizes(&self) -> u32 { - let range = self.shape.num_sizes_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.num_sizes_byte_range(); + unchecked::read_at(self.data, range.start) } /// BitmapSize records array. pub fn bitmap_sizes(&self) -> &'a [BitmapSize] { - let range = self.shape.bitmap_sizes_byte_range(); - self.data.read_array(range).unwrap() + let range = self.bitmap_sizes_byte_range(); + unchecked::read_array(self.data, range) } } diff --git a/read-fonts/generated/generated_feat.rs b/read-fonts/generated/generated_feat.rs index 94ccad03f..f2743ab3d 100644 --- a/read-fonts/generated/generated_feat.rs +++ b/read-fonts/generated/generated_feat.rs @@ -8,11 +8,41 @@ use crate::codegen_prelude::*; /// The [feature name](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6feat.html) table. #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct FeatMarker { - names_byte_len: usize, +pub struct FeatMarker; + +impl<'a> MinByteRange for Feat<'a> { + fn min_byte_range(&self) -> Range { + 0..self.names_byte_range().end + } +} + +impl TopLevelTable for Feat<'_> { + /// `feat` + const TAG: Tag = Tag::new(b"feat"); +} + +impl<'a> FontRead<'a> for Feat<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } } -impl FeatMarker { +/// The [feature name](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6feat.html) table. +pub type Feat<'a> = TableRef<'a, FeatMarker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> Feat<'a> { + fn names_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.feature_name_count()) as usize) + .checked_mul(FeatureName::RAW_BYTE_LEN) + .unwrap() + } + pub fn version_byte_range(&self) -> Range { let start = 0; start..start + MajorMinor::RAW_BYTE_LEN @@ -35,58 +65,26 @@ impl FeatMarker { pub fn names_byte_range(&self) -> Range { let start = self._reserved2_byte_range().end; - start..start + self.names_byte_len - } -} - -impl MinByteRange for FeatMarker { - fn min_byte_range(&self) -> Range { - 0..self.names_byte_range().end - } -} - -impl TopLevelTable for Feat<'_> { - /// `feat` - const TAG: Tag = Tag::new(b"feat"); -} - -impl<'a> FontRead<'a> for Feat<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - let feature_name_count: u16 = cursor.read()?; - cursor.advance::(); - cursor.advance::(); - let names_byte_len = (feature_name_count as usize) - .checked_mul(FeatureName::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(names_byte_len); - cursor.finish(FeatMarker { names_byte_len }) + start..start + self.names_byte_len(start) } -} - -/// The [feature name](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6feat.html) table. -pub type Feat<'a> = TableRef<'a, FeatMarker>; -#[allow(clippy::needless_lifetimes)] -impl<'a> Feat<'a> { /// Version number of the feature name table (0x00010000 for the current /// version). pub fn version(&self) -> MajorMinor { - let range = self.shape.version_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.version_byte_range(); + unchecked::read_at(self.data, range.start) } /// The number of entries in the feature name array. pub fn feature_name_count(&self) -> u16 { - let range = self.shape.feature_name_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.feature_name_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// The feature name array, sorted by feature type. pub fn names(&self) -> &'a [FeatureName] { - let range = self.shape.names_byte_range(); - self.data.read_array(range).unwrap() + let range = self.names_byte_range(); + unchecked::read_array(self.data, range) } } @@ -210,18 +208,9 @@ impl<'a> SomeRecord<'a> for FeatureName { #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct SettingNameArrayMarker { - settings_byte_len: usize, -} - -impl SettingNameArrayMarker { - pub fn settings_byte_range(&self) -> Range { - let start = 0; - start..start + self.settings_byte_len - } -} +pub struct SettingNameArrayMarker; -impl MinByteRange for SettingNameArrayMarker { +impl<'a> MinByteRange for SettingNameArray<'a> { fn min_byte_range(&self) -> Range { 0..self.settings_byte_range().end } @@ -233,13 +222,12 @@ impl ReadArgs for SettingNameArray<'_> { impl<'a> FontReadWithArgs<'a> for SettingNameArray<'a> { fn read_with_args(data: FontData<'a>, args: &u16) -> Result { - let n_settings = *args; - let mut cursor = data.cursor(); - let settings_byte_len = (n_settings as usize) - .checked_mul(SettingName::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(settings_byte_len); - cursor.finish(SettingNameArrayMarker { settings_byte_len }) + let args = *args; + Ok(TableRef { + args, + data, + _marker: std::marker::PhantomData, + }) } } @@ -254,14 +242,30 @@ impl<'a> SettingNameArray<'a> { } } -pub type SettingNameArray<'a> = TableRef<'a, SettingNameArrayMarker>; +pub type SettingNameArray<'a> = TableRef<'a, SettingNameArrayMarker, u16>; #[allow(clippy::needless_lifetimes)] impl<'a> SettingNameArray<'a> { + fn settings_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.args) as usize) + .checked_mul(SettingName::RAW_BYTE_LEN) + .unwrap() + } + + pub fn settings_byte_range(&self) -> Range { + let start = 0; + start..start + self.settings_byte_len(start) + } + /// List of setting names for a feature. pub fn settings(&self) -> &'a [SettingName] { - let range = self.shape.settings_byte_range(); - self.data.read_array(range).unwrap() + let range = self.settings_byte_range(); + unchecked::read_array(self.data, range) + } + + pub(crate) fn n_settings(&self) -> u16 { + self.args } } diff --git a/read-fonts/generated/generated_fvar.rs b/read-fonts/generated/generated_fvar.rs index e020392a7..7c32e4015 100644 --- a/read-fonts/generated/generated_fvar.rs +++ b/read-fonts/generated/generated_fvar.rs @@ -8,9 +8,34 @@ use crate::codegen_prelude::*; /// The [fvar (Font Variations)](https://docs.microsoft.com/en-us/typography/opentype/spec/fvar) table #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct FvarMarker {} +pub struct FvarMarker; -impl FvarMarker { +impl<'a> MinByteRange for Fvar<'a> { + fn min_byte_range(&self) -> Range { + 0..self.instance_size_byte_range().end + } +} + +impl TopLevelTable for Fvar<'_> { + /// `fvar` + const TAG: Tag = Tag::new(b"fvar"); +} + +impl<'a> FontRead<'a> for Fvar<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// The [fvar (Font Variations)](https://docs.microsoft.com/en-us/typography/opentype/spec/fvar) table +pub type Fvar<'a> = TableRef<'a, FvarMarker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> Fvar<'a> { pub fn version_byte_range(&self) -> Range { let start = 0; start..start + MajorMinor::RAW_BYTE_LEN @@ -45,50 +70,19 @@ impl FvarMarker { let start = self.instance_count_byte_range().end; start..start + u16::RAW_BYTE_LEN } -} - -impl MinByteRange for FvarMarker { - fn min_byte_range(&self) -> Range { - 0..self.instance_size_byte_range().end - } -} - -impl TopLevelTable for Fvar<'_> { - /// `fvar` - const TAG: Tag = Tag::new(b"fvar"); -} - -impl<'a> FontRead<'a> for Fvar<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.finish(FvarMarker {}) - } -} -/// The [fvar (Font Variations)](https://docs.microsoft.com/en-us/typography/opentype/spec/fvar) table -pub type Fvar<'a> = TableRef<'a, FvarMarker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> Fvar<'a> { /// Major version number of the font variations table — set to 1. /// Minor version number of the font variations table — set to 0. pub fn version(&self) -> MajorMinor { - let range = self.shape.version_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.version_byte_range(); + unchecked::read_at(self.data, range.start) } /// Offset in bytes from the beginning of the table to the start of the VariationAxisRecord array. The /// InstanceRecord array directly follows. pub fn axis_instance_arrays_offset(&self) -> Offset16 { - let range = self.shape.axis_instance_arrays_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.axis_instance_arrays_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`axis_instance_arrays_offset`][Self::axis_instance_arrays_offset]. @@ -105,26 +99,26 @@ impl<'a> Fvar<'a> { /// The number of variation axes in the font (the number of records in the axes array). pub fn axis_count(&self) -> u16 { - let range = self.shape.axis_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.axis_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// The size in bytes of each VariationAxisRecord — set to 20 (0x0014) for this version. pub fn axis_size(&self) -> u16 { - let range = self.shape.axis_size_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.axis_size_byte_range(); + unchecked::read_at(self.data, range.start) } /// The number of named instances defined in the font (the number of records in the instances array). pub fn instance_count(&self) -> u16 { - let range = self.shape.instance_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.instance_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// The size in bytes of each InstanceRecord — set to either axisCount * sizeof(Fixed) + 4, or to axisCount * sizeof(Fixed) + 6. pub fn instance_size(&self) -> u16 { - let range = self.shape.instance_size_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.instance_size_byte_range(); + unchecked::read_at(self.data, range.start) } } @@ -163,26 +157,9 @@ impl<'a> std::fmt::Debug for Fvar<'a> { /// Shim table to handle combined axis and instance arrays. #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct AxisInstanceArraysMarker { - axis_count: u16, - instance_size: u16, - axes_byte_len: usize, - instances_byte_len: usize, -} - -impl AxisInstanceArraysMarker { - pub fn axes_byte_range(&self) -> Range { - let start = 0; - start..start + self.axes_byte_len - } +pub struct AxisInstanceArraysMarker; - pub fn instances_byte_range(&self) -> Range { - let start = self.axes_byte_range().end; - start..start + self.instances_byte_len - } -} - -impl MinByteRange for AxisInstanceArraysMarker { +impl<'a> MinByteRange for AxisInstanceArrays<'a> { fn min_byte_range(&self) -> Range { 0..self.instances_byte_range().end } @@ -194,24 +171,11 @@ impl ReadArgs for AxisInstanceArrays<'_> { impl<'a> FontReadWithArgs<'a> for AxisInstanceArrays<'a> { fn read_with_args(data: FontData<'a>, args: &(u16, u16, u16)) -> Result { - let (axis_count, instance_count, instance_size) = *args; - let mut cursor = data.cursor(); - let axes_byte_len = (axis_count as usize) - .checked_mul(VariationAxisRecord::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(axes_byte_len); - let instances_byte_len = (instance_count as usize) - .checked_mul(::compute_size(&( - axis_count, - instance_size, - ))?) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(instances_byte_len); - cursor.finish(AxisInstanceArraysMarker { - axis_count, - instance_size, - axes_byte_len, - instances_byte_len, + let args = *args; + Ok(TableRef { + args, + data, + _marker: std::marker::PhantomData, }) } } @@ -233,30 +197,57 @@ impl<'a> AxisInstanceArrays<'a> { } /// Shim table to handle combined axis and instance arrays. -pub type AxisInstanceArrays<'a> = TableRef<'a, AxisInstanceArraysMarker>; +pub type AxisInstanceArrays<'a> = TableRef<'a, AxisInstanceArraysMarker, (u16, u16, u16)>; #[allow(clippy::needless_lifetimes)] impl<'a> AxisInstanceArrays<'a> { + fn axes_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.args.0) as usize) + .checked_mul(VariationAxisRecord::RAW_BYTE_LEN) + .unwrap() + } + fn instances_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.args.1) as usize) + .checked_mul( + ::compute_size(&(self.args.0, self.args.2)).unwrap(), + ) + .unwrap() + } + + pub fn axes_byte_range(&self) -> Range { + let start = 0; + start..start + self.axes_byte_len(start) + } + + pub fn instances_byte_range(&self) -> Range { + let start = self.axes_byte_range().end; + start..start + self.instances_byte_len(start) + } + /// Variation axis record array. pub fn axes(&self) -> &'a [VariationAxisRecord] { - let range = self.shape.axes_byte_range(); - self.data.read_array(range).unwrap() + let range = self.axes_byte_range(); + unchecked::read_array(self.data, range) } /// Instance record array. pub fn instances(&self) -> ComputedArray<'a, InstanceRecord<'a>> { - let range = self.shape.instances_byte_range(); - self.data - .read_with_args(range, &(self.axis_count(), self.instance_size())) - .unwrap() + let range = self.instances_byte_range(); + unchecked::read_with_args(self.data, range, &(self.axis_count(), self.instance_size())) } pub(crate) fn axis_count(&self) -> u16 { - self.shape.axis_count + self.args.0 + } + + pub(crate) fn instance_count(&self) -> u16 { + self.args.1 } pub(crate) fn instance_size(&self) -> u16 { - self.shape.instance_size + self.args.2 } } diff --git a/read-fonts/generated/generated_gasp.rs b/read-fonts/generated/generated_gasp.rs index 866bc8773..989f35eea 100644 --- a/read-fonts/generated/generated_gasp.rs +++ b/read-fonts/generated/generated_gasp.rs @@ -8,28 +8,9 @@ use crate::codegen_prelude::*; /// [gasp](https://learn.microsoft.com/en-us/typography/opentype/spec/gasp#gasp-table-formats) #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct GaspMarker { - gasp_ranges_byte_len: usize, -} - -impl GaspMarker { - pub fn version_byte_range(&self) -> Range { - let start = 0; - start..start + u16::RAW_BYTE_LEN - } - - pub fn num_ranges_byte_range(&self) -> Range { - let start = self.version_byte_range().end; - start..start + u16::RAW_BYTE_LEN - } +pub struct GaspMarker; - pub fn gasp_ranges_byte_range(&self) -> Range { - let start = self.num_ranges_byte_range().end; - start..start + self.gasp_ranges_byte_len - } -} - -impl MinByteRange for GaspMarker { +impl<'a> MinByteRange for Gasp<'a> { fn min_byte_range(&self) -> Range { 0..self.gasp_ranges_byte_range().end } @@ -42,40 +23,57 @@ impl TopLevelTable for Gasp<'_> { impl<'a> FontRead<'a> for Gasp<'a> { fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - let num_ranges: u16 = cursor.read()?; - let gasp_ranges_byte_len = (num_ranges as usize) - .checked_mul(GaspRange::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(gasp_ranges_byte_len); - cursor.finish(GaspMarker { - gasp_ranges_byte_len, + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, }) } } /// [gasp](https://learn.microsoft.com/en-us/typography/opentype/spec/gasp#gasp-table-formats) -pub type Gasp<'a> = TableRef<'a, GaspMarker>; +pub type Gasp<'a> = TableRef<'a, GaspMarker, ()>; #[allow(clippy::needless_lifetimes)] impl<'a> Gasp<'a> { + fn gasp_ranges_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.num_ranges()) as usize) + .checked_mul(GaspRange::RAW_BYTE_LEN) + .unwrap() + } + + pub fn version_byte_range(&self) -> Range { + let start = 0; + start..start + u16::RAW_BYTE_LEN + } + + pub fn num_ranges_byte_range(&self) -> Range { + let start = self.version_byte_range().end; + start..start + u16::RAW_BYTE_LEN + } + + pub fn gasp_ranges_byte_range(&self) -> Range { + let start = self.num_ranges_byte_range().end; + start..start + self.gasp_ranges_byte_len(start) + } + /// Version number (set to 1) pub fn version(&self) -> u16 { - let range = self.shape.version_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.version_byte_range(); + unchecked::read_at(self.data, range.start) } /// Number of records to follow pub fn num_ranges(&self) -> u16 { - let range = self.shape.num_ranges_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.num_ranges_byte_range(); + unchecked::read_at(self.data, range.start) } /// Sorted by ppem pub fn gasp_ranges(&self) -> &'a [GaspRange] { - let range = self.shape.gasp_ranges_byte_range(); - self.data.read_array(range).unwrap() + let range = self.gasp_ranges_byte_range(); + unchecked::read_array(self.data, range) } } diff --git a/read-fonts/generated/generated_gdef.rs b/read-fonts/generated/generated_gdef.rs index 165c68cfd..a234ab2dd 100644 --- a/read-fonts/generated/generated_gdef.rs +++ b/read-fonts/generated/generated_gdef.rs @@ -8,12 +8,34 @@ use crate::codegen_prelude::*; /// [GDEF](https://docs.microsoft.com/en-us/typography/opentype/spec/gdef#gdef-header) 1.0 #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct GdefMarker { - mark_glyph_sets_def_offset_byte_start: Option, - item_var_store_offset_byte_start: Option, +pub struct GdefMarker; + +impl<'a> MinByteRange for Gdef<'a> { + fn min_byte_range(&self) -> Range { + 0..self.mark_attach_class_def_offset_byte_range().end + } +} + +impl TopLevelTable for Gdef<'_> { + /// `GDEF` + const TAG: Tag = Tag::new(b"GDEF"); } -impl GdefMarker { +impl<'a> FontRead<'a> for Gdef<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// [GDEF](https://docs.microsoft.com/en-us/typography/opentype/spec/gdef#gdef-header) 1.0 +pub type Gdef<'a> = TableRef<'a, GdefMarker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> Gdef<'a> { pub fn version_byte_range(&self) -> Range { let start = 0; start..start + MajorMinor::RAW_BYTE_LEN @@ -40,72 +62,37 @@ impl GdefMarker { } pub fn mark_glyph_sets_def_offset_byte_range(&self) -> Option> { - let start = self.mark_glyph_sets_def_offset_byte_start?; - Some(start..start + Offset16::RAW_BYTE_LEN) + if self.version().compatible((1u16, 2u16)) { + let start = self.mark_attach_class_def_offset_byte_range().end; + Some(start..start + Offset16::RAW_BYTE_LEN) + } else { + None + } } pub fn item_var_store_offset_byte_range(&self) -> Option> { - let start = self.item_var_store_offset_byte_start?; - Some(start..start + Offset32::RAW_BYTE_LEN) - } -} - -impl MinByteRange for GdefMarker { - fn min_byte_range(&self) -> Range { - 0..self.mark_attach_class_def_offset_byte_range().end - } -} - -impl TopLevelTable for Gdef<'_> { - /// `GDEF` - const TAG: Tag = Tag::new(b"GDEF"); -} - -impl<'a> FontRead<'a> for Gdef<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - let version: MajorMinor = cursor.read()?; - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - let mark_glyph_sets_def_offset_byte_start = version - .compatible((1u16, 2u16)) - .then(|| cursor.position()) - .transpose()?; - version - .compatible((1u16, 2u16)) - .then(|| cursor.advance::()); - let item_var_store_offset_byte_start = version - .compatible((1u16, 3u16)) - .then(|| cursor.position()) - .transpose()?; - version - .compatible((1u16, 3u16)) - .then(|| cursor.advance::()); - cursor.finish(GdefMarker { - mark_glyph_sets_def_offset_byte_start, - item_var_store_offset_byte_start, - }) + if self.version().compatible((1u16, 3u16)) { + let start = self + .mark_glyph_sets_def_offset_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| self.mark_attach_class_def_offset_byte_range().end); + Some(start..start + Offset32::RAW_BYTE_LEN) + } else { + None + } } -} -/// [GDEF](https://docs.microsoft.com/en-us/typography/opentype/spec/gdef#gdef-header) 1.0 -pub type Gdef<'a> = TableRef<'a, GdefMarker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> Gdef<'a> { /// The major/minor version of the GDEF table pub fn version(&self) -> MajorMinor { - let range = self.shape.version_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.version_byte_range(); + unchecked::read_at(self.data, range.start) } /// Offset to class definition table for glyph type, from beginning /// of GDEF header (may be NULL) pub fn glyph_class_def_offset(&self) -> Nullable { - let range = self.shape.glyph_class_def_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.glyph_class_def_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`glyph_class_def_offset`][Self::glyph_class_def_offset]. @@ -117,8 +104,8 @@ impl<'a> Gdef<'a> { /// Offset to attachment point list table, from beginning of GDEF /// header (may be NULL) pub fn attach_list_offset(&self) -> Nullable { - let range = self.shape.attach_list_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.attach_list_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`attach_list_offset`][Self::attach_list_offset]. @@ -130,8 +117,8 @@ impl<'a> Gdef<'a> { /// Offset to ligature caret list table, from beginning of GDEF /// header (may be NULL) pub fn lig_caret_list_offset(&self) -> Nullable { - let range = self.shape.lig_caret_list_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.lig_caret_list_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`lig_caret_list_offset`][Self::lig_caret_list_offset]. @@ -143,8 +130,8 @@ impl<'a> Gdef<'a> { /// Offset to class definition table for mark attachment type, from /// beginning of GDEF header (may be NULL) pub fn mark_attach_class_def_offset(&self) -> Nullable { - let range = self.shape.mark_attach_class_def_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.mark_attach_class_def_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`mark_attach_class_def_offset`][Self::mark_attach_class_def_offset]. @@ -156,8 +143,8 @@ impl<'a> Gdef<'a> { /// Offset to the table of mark glyph set definitions, from /// beginning of GDEF header (may be NULL) pub fn mark_glyph_sets_def_offset(&self) -> Option> { - let range = self.shape.mark_glyph_sets_def_offset_byte_range()?; - Some(self.data.read_at(range.start).unwrap()) + let range = self.mark_glyph_sets_def_offset_byte_range()?; + Some(unchecked::read_at(self.data, range.start)) } /// Attempt to resolve [`mark_glyph_sets_def_offset`][Self::mark_glyph_sets_def_offset]. @@ -169,8 +156,8 @@ impl<'a> Gdef<'a> { /// Offset to the Item Variation Store table, from beginning of /// GDEF header (may be NULL) pub fn item_var_store_offset(&self) -> Option> { - let range = self.shape.item_var_store_offset_byte_range()?; - Some(self.data.read_at(range.start).unwrap()) + let range = self.item_var_store_offset_byte_range()?; + Some(unchecked::read_at(self.data, range.start)) } /// Attempt to resolve [`item_var_store_offset`][Self::item_var_store_offset]. @@ -284,28 +271,9 @@ impl<'a> From for FieldType<'a> { /// [Attachment Point List Table](https://docs.microsoft.com/en-us/typography/opentype/spec/gdef#attachment-point-list-table) #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct AttachListMarker { - attach_point_offsets_byte_len: usize, -} +pub struct AttachListMarker; -impl AttachListMarker { - pub fn coverage_offset_byte_range(&self) -> Range { - let start = 0; - start..start + Offset16::RAW_BYTE_LEN - } - - pub fn glyph_count_byte_range(&self) -> Range { - let start = self.coverage_offset_byte_range().end; - start..start + u16::RAW_BYTE_LEN - } - - pub fn attach_point_offsets_byte_range(&self) -> Range { - let start = self.glyph_count_byte_range().end; - start..start + self.attach_point_offsets_byte_len - } -} - -impl MinByteRange for AttachListMarker { +impl<'a> MinByteRange for AttachList<'a> { fn min_byte_range(&self) -> Range { 0..self.attach_point_offsets_byte_range().end } @@ -313,28 +281,45 @@ impl MinByteRange for AttachListMarker { impl<'a> FontRead<'a> for AttachList<'a> { fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - let glyph_count: u16 = cursor.read()?; - let attach_point_offsets_byte_len = (glyph_count as usize) - .checked_mul(Offset16::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(attach_point_offsets_byte_len); - cursor.finish(AttachListMarker { - attach_point_offsets_byte_len, + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, }) } } /// [Attachment Point List Table](https://docs.microsoft.com/en-us/typography/opentype/spec/gdef#attachment-point-list-table) -pub type AttachList<'a> = TableRef<'a, AttachListMarker>; +pub type AttachList<'a> = TableRef<'a, AttachListMarker, ()>; #[allow(clippy::needless_lifetimes)] impl<'a> AttachList<'a> { + fn attach_point_offsets_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.glyph_count()) as usize) + .checked_mul(Offset16::RAW_BYTE_LEN) + .unwrap() + } + + pub fn coverage_offset_byte_range(&self) -> Range { + let start = 0; + start..start + Offset16::RAW_BYTE_LEN + } + + pub fn glyph_count_byte_range(&self) -> Range { + let start = self.coverage_offset_byte_range().end; + start..start + u16::RAW_BYTE_LEN + } + + pub fn attach_point_offsets_byte_range(&self) -> Range { + let start = self.glyph_count_byte_range().end; + start..start + self.attach_point_offsets_byte_len(start) + } + /// Offset to Coverage table - from beginning of AttachList table pub fn coverage_offset(&self) -> Offset16 { - let range = self.shape.coverage_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.coverage_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`coverage_offset`][Self::coverage_offset]. @@ -345,15 +330,15 @@ impl<'a> AttachList<'a> { /// Number of glyphs with attachment points pub fn glyph_count(&self) -> u16 { - let range = self.shape.glyph_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.glyph_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Array of offsets to AttachPoint tables-from beginning of /// AttachList table-in Coverage Index order pub fn attach_point_offsets(&self) -> &'a [BigEndian] { - let range = self.shape.attach_point_offsets_byte_range(); - self.data.read_array(range).unwrap() + let range = self.attach_point_offsets_byte_range(); + unchecked::read_array(self.data, range) } /// A dynamically resolving wrapper for [`attach_point_offsets`][Self::attach_point_offsets]. @@ -406,23 +391,9 @@ impl<'a> std::fmt::Debug for AttachList<'a> { /// Part of [AttachList] #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct AttachPointMarker { - point_indices_byte_len: usize, -} - -impl AttachPointMarker { - pub fn point_count_byte_range(&self) -> Range { - let start = 0; - start..start + u16::RAW_BYTE_LEN - } +pub struct AttachPointMarker; - pub fn point_indices_byte_range(&self) -> Range { - let start = self.point_count_byte_range().end; - start..start + self.point_indices_byte_len - } -} - -impl MinByteRange for AttachPointMarker { +impl<'a> MinByteRange for AttachPoint<'a> { fn min_byte_range(&self) -> Range { 0..self.point_indices_byte_range().end } @@ -430,33 +401,46 @@ impl MinByteRange for AttachPointMarker { impl<'a> FontRead<'a> for AttachPoint<'a> { fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - let point_count: u16 = cursor.read()?; - let point_indices_byte_len = (point_count as usize) - .checked_mul(u16::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(point_indices_byte_len); - cursor.finish(AttachPointMarker { - point_indices_byte_len, + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, }) } } /// Part of [AttachList] -pub type AttachPoint<'a> = TableRef<'a, AttachPointMarker>; +pub type AttachPoint<'a> = TableRef<'a, AttachPointMarker, ()>; #[allow(clippy::needless_lifetimes)] impl<'a> AttachPoint<'a> { + fn point_indices_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.point_count()) as usize) + .checked_mul(u16::RAW_BYTE_LEN) + .unwrap() + } + + pub fn point_count_byte_range(&self) -> Range { + let start = 0; + start..start + u16::RAW_BYTE_LEN + } + + pub fn point_indices_byte_range(&self) -> Range { + let start = self.point_count_byte_range().end; + start..start + self.point_indices_byte_len(start) + } + /// Number of attachment points on this glyph pub fn point_count(&self) -> u16 { - let range = self.shape.point_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.point_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Array of contour point indices -in increasing numerical order pub fn point_indices(&self) -> &'a [BigEndian] { - let range = self.shape.point_indices_byte_range(); - self.data.read_array(range).unwrap() + let range = self.point_indices_byte_range(); + unchecked::read_array(self.data, range) } } @@ -485,28 +469,9 @@ impl<'a> std::fmt::Debug for AttachPoint<'a> { /// [Ligature Caret List Table](https://docs.microsoft.com/en-us/typography/opentype/spec/gdef#ligature-caret-list-table) #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct LigCaretListMarker { - lig_glyph_offsets_byte_len: usize, -} +pub struct LigCaretListMarker; -impl LigCaretListMarker { - pub fn coverage_offset_byte_range(&self) -> Range { - let start = 0; - start..start + Offset16::RAW_BYTE_LEN - } - - pub fn lig_glyph_count_byte_range(&self) -> Range { - let start = self.coverage_offset_byte_range().end; - start..start + u16::RAW_BYTE_LEN - } - - pub fn lig_glyph_offsets_byte_range(&self) -> Range { - let start = self.lig_glyph_count_byte_range().end; - start..start + self.lig_glyph_offsets_byte_len - } -} - -impl MinByteRange for LigCaretListMarker { +impl<'a> MinByteRange for LigCaretList<'a> { fn min_byte_range(&self) -> Range { 0..self.lig_glyph_offsets_byte_range().end } @@ -514,28 +479,45 @@ impl MinByteRange for LigCaretListMarker { impl<'a> FontRead<'a> for LigCaretList<'a> { fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - let lig_glyph_count: u16 = cursor.read()?; - let lig_glyph_offsets_byte_len = (lig_glyph_count as usize) - .checked_mul(Offset16::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(lig_glyph_offsets_byte_len); - cursor.finish(LigCaretListMarker { - lig_glyph_offsets_byte_len, + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, }) } } /// [Ligature Caret List Table](https://docs.microsoft.com/en-us/typography/opentype/spec/gdef#ligature-caret-list-table) -pub type LigCaretList<'a> = TableRef<'a, LigCaretListMarker>; +pub type LigCaretList<'a> = TableRef<'a, LigCaretListMarker, ()>; #[allow(clippy::needless_lifetimes)] impl<'a> LigCaretList<'a> { + fn lig_glyph_offsets_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.lig_glyph_count()) as usize) + .checked_mul(Offset16::RAW_BYTE_LEN) + .unwrap() + } + + pub fn coverage_offset_byte_range(&self) -> Range { + let start = 0; + start..start + Offset16::RAW_BYTE_LEN + } + + pub fn lig_glyph_count_byte_range(&self) -> Range { + let start = self.coverage_offset_byte_range().end; + start..start + u16::RAW_BYTE_LEN + } + + pub fn lig_glyph_offsets_byte_range(&self) -> Range { + let start = self.lig_glyph_count_byte_range().end; + start..start + self.lig_glyph_offsets_byte_len(start) + } + /// Offset to Coverage table - from beginning of LigCaretList table pub fn coverage_offset(&self) -> Offset16 { - let range = self.shape.coverage_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.coverage_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`coverage_offset`][Self::coverage_offset]. @@ -546,15 +528,15 @@ impl<'a> LigCaretList<'a> { /// Number of ligature glyphs pub fn lig_glyph_count(&self) -> u16 { - let range = self.shape.lig_glyph_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.lig_glyph_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Array of offsets to LigGlyph tables, from beginning of /// LigCaretList table —in Coverage Index order pub fn lig_glyph_offsets(&self) -> &'a [BigEndian] { - let range = self.shape.lig_glyph_offsets_byte_range(); - self.data.read_array(range).unwrap() + let range = self.lig_glyph_offsets_byte_range(); + unchecked::read_array(self.data, range) } /// A dynamically resolving wrapper for [`lig_glyph_offsets`][Self::lig_glyph_offsets]. @@ -607,23 +589,9 @@ impl<'a> std::fmt::Debug for LigCaretList<'a> { /// [Ligature Glyph Table](https://docs.microsoft.com/en-us/typography/opentype/spec/gdef#ligature-glyph-table) #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct LigGlyphMarker { - caret_value_offsets_byte_len: usize, -} +pub struct LigGlyphMarker; -impl LigGlyphMarker { - pub fn caret_count_byte_range(&self) -> Range { - let start = 0; - start..start + u16::RAW_BYTE_LEN - } - - pub fn caret_value_offsets_byte_range(&self) -> Range { - let start = self.caret_count_byte_range().end; - start..start + self.caret_value_offsets_byte_len - } -} - -impl MinByteRange for LigGlyphMarker { +impl<'a> MinByteRange for LigGlyph<'a> { fn min_byte_range(&self) -> Range { 0..self.caret_value_offsets_byte_range().end } @@ -631,34 +599,47 @@ impl MinByteRange for LigGlyphMarker { impl<'a> FontRead<'a> for LigGlyph<'a> { fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - let caret_count: u16 = cursor.read()?; - let caret_value_offsets_byte_len = (caret_count as usize) - .checked_mul(Offset16::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(caret_value_offsets_byte_len); - cursor.finish(LigGlyphMarker { - caret_value_offsets_byte_len, + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, }) } } /// [Ligature Glyph Table](https://docs.microsoft.com/en-us/typography/opentype/spec/gdef#ligature-glyph-table) -pub type LigGlyph<'a> = TableRef<'a, LigGlyphMarker>; +pub type LigGlyph<'a> = TableRef<'a, LigGlyphMarker, ()>; #[allow(clippy::needless_lifetimes)] impl<'a> LigGlyph<'a> { + fn caret_value_offsets_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.caret_count()) as usize) + .checked_mul(Offset16::RAW_BYTE_LEN) + .unwrap() + } + + pub fn caret_count_byte_range(&self) -> Range { + let start = 0; + start..start + u16::RAW_BYTE_LEN + } + + pub fn caret_value_offsets_byte_range(&self) -> Range { + let start = self.caret_count_byte_range().end; + start..start + self.caret_value_offsets_byte_len(start) + } + /// Number of CaretValue tables for this ligature (components - 1) pub fn caret_count(&self) -> u16 { - let range = self.shape.caret_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.caret_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Array of offsets to CaretValue tables, from beginning of /// LigGlyph table — in increasing coordinate order pub fn caret_value_offsets(&self) -> &'a [BigEndian] { - let range = self.shape.caret_value_offsets_byte_range(); - self.data.read_array(range).unwrap() + let range = self.caret_value_offsets_byte_range(); + unchecked::read_array(self.data, range) } /// A dynamically resolving wrapper for [`caret_value_offsets`][Self::caret_value_offsets]. @@ -789,21 +770,9 @@ impl Format for CaretValueFormat1Marker { /// [CaretValue Format 1](https://docs.microsoft.com/en-us/typography/opentype/spec/gdef#caretvalue-format-1) #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct CaretValueFormat1Marker {} +pub struct CaretValueFormat1Marker; -impl CaretValueFormat1Marker { - pub fn caret_value_format_byte_range(&self) -> Range { - let start = 0; - start..start + u16::RAW_BYTE_LEN - } - - pub fn coordinate_byte_range(&self) -> Range { - let start = self.caret_value_format_byte_range().end; - start..start + i16::RAW_BYTE_LEN - } -} - -impl MinByteRange for CaretValueFormat1Marker { +impl<'a> MinByteRange for CaretValueFormat1<'a> { fn min_byte_range(&self) -> Range { 0..self.coordinate_byte_range().end } @@ -811,28 +780,39 @@ impl MinByteRange for CaretValueFormat1Marker { impl<'a> FontRead<'a> for CaretValueFormat1<'a> { fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.finish(CaretValueFormat1Marker {}) + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) } } /// [CaretValue Format 1](https://docs.microsoft.com/en-us/typography/opentype/spec/gdef#caretvalue-format-1) -pub type CaretValueFormat1<'a> = TableRef<'a, CaretValueFormat1Marker>; +pub type CaretValueFormat1<'a> = TableRef<'a, CaretValueFormat1Marker, ()>; #[allow(clippy::needless_lifetimes)] impl<'a> CaretValueFormat1<'a> { + pub fn caret_value_format_byte_range(&self) -> Range { + let start = 0; + start..start + u16::RAW_BYTE_LEN + } + + pub fn coordinate_byte_range(&self) -> Range { + let start = self.caret_value_format_byte_range().end; + start..start + i16::RAW_BYTE_LEN + } + /// Format identifier: format = 1 pub fn caret_value_format(&self) -> u16 { - let range = self.shape.caret_value_format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.caret_value_format_byte_range(); + unchecked::read_at(self.data, range.start) } /// X or Y value, in design units pub fn coordinate(&self) -> i16 { - let range = self.shape.coordinate_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.coordinate_byte_range(); + unchecked::read_at(self.data, range.start) } } @@ -865,21 +845,9 @@ impl Format for CaretValueFormat2Marker { /// [CaretValue Format 2](https://docs.microsoft.com/en-us/typography/opentype/spec/gdef#caretvalue-format-2) #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct CaretValueFormat2Marker {} +pub struct CaretValueFormat2Marker; -impl CaretValueFormat2Marker { - pub fn caret_value_format_byte_range(&self) -> Range { - let start = 0; - start..start + u16::RAW_BYTE_LEN - } - - pub fn caret_value_point_index_byte_range(&self) -> Range { - let start = self.caret_value_format_byte_range().end; - start..start + u16::RAW_BYTE_LEN - } -} - -impl MinByteRange for CaretValueFormat2Marker { +impl<'a> MinByteRange for CaretValueFormat2<'a> { fn min_byte_range(&self) -> Range { 0..self.caret_value_point_index_byte_range().end } @@ -887,28 +855,39 @@ impl MinByteRange for CaretValueFormat2Marker { impl<'a> FontRead<'a> for CaretValueFormat2<'a> { fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.finish(CaretValueFormat2Marker {}) + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) } } /// [CaretValue Format 2](https://docs.microsoft.com/en-us/typography/opentype/spec/gdef#caretvalue-format-2) -pub type CaretValueFormat2<'a> = TableRef<'a, CaretValueFormat2Marker>; +pub type CaretValueFormat2<'a> = TableRef<'a, CaretValueFormat2Marker, ()>; #[allow(clippy::needless_lifetimes)] impl<'a> CaretValueFormat2<'a> { + pub fn caret_value_format_byte_range(&self) -> Range { + let start = 0; + start..start + u16::RAW_BYTE_LEN + } + + pub fn caret_value_point_index_byte_range(&self) -> Range { + let start = self.caret_value_format_byte_range().end; + start..start + u16::RAW_BYTE_LEN + } + /// Format identifier: format = 2 pub fn caret_value_format(&self) -> u16 { - let range = self.shape.caret_value_format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.caret_value_format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Contour point index on glyph pub fn caret_value_point_index(&self) -> u16 { - let range = self.shape.caret_value_point_index_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.caret_value_point_index_byte_range(); + unchecked::read_at(self.data, range.start) } } @@ -944,9 +923,29 @@ impl Format for CaretValueFormat3Marker { /// [CaretValue Format 3](https://docs.microsoft.com/en-us/typography/opentype/spec/gdef#caretvalue-format-3) #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct CaretValueFormat3Marker {} +pub struct CaretValueFormat3Marker; -impl CaretValueFormat3Marker { +impl<'a> MinByteRange for CaretValueFormat3<'a> { + fn min_byte_range(&self) -> Range { + 0..self.device_offset_byte_range().end + } +} + +impl<'a> FontRead<'a> for CaretValueFormat3<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// [CaretValue Format 3](https://docs.microsoft.com/en-us/typography/opentype/spec/gdef#caretvalue-format-3) +pub type CaretValueFormat3<'a> = TableRef<'a, CaretValueFormat3Marker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> CaretValueFormat3<'a> { pub fn caret_value_format_byte_range(&self) -> Range { let start = 0; start..start + u16::RAW_BYTE_LEN @@ -961,47 +960,25 @@ impl CaretValueFormat3Marker { let start = self.coordinate_byte_range().end; start..start + Offset16::RAW_BYTE_LEN } -} - -impl MinByteRange for CaretValueFormat3Marker { - fn min_byte_range(&self) -> Range { - 0..self.device_offset_byte_range().end - } -} - -impl<'a> FontRead<'a> for CaretValueFormat3<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.finish(CaretValueFormat3Marker {}) - } -} - -/// [CaretValue Format 3](https://docs.microsoft.com/en-us/typography/opentype/spec/gdef#caretvalue-format-3) -pub type CaretValueFormat3<'a> = TableRef<'a, CaretValueFormat3Marker>; -#[allow(clippy::needless_lifetimes)] -impl<'a> CaretValueFormat3<'a> { /// Format identifier-format = 3 pub fn caret_value_format(&self) -> u16 { - let range = self.shape.caret_value_format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.caret_value_format_byte_range(); + unchecked::read_at(self.data, range.start) } /// X or Y value, in design units pub fn coordinate(&self) -> i16 { - let range = self.shape.coordinate_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.coordinate_byte_range(); + unchecked::read_at(self.data, range.start) } /// Offset to Device table (non-variable font) / Variation Index /// table (variable font) for X or Y value-from beginning of /// CaretValue table pub fn device_offset(&self) -> Offset16 { - let range = self.shape.device_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.device_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`device_offset`][Self::device_offset]. @@ -1044,28 +1021,9 @@ impl Format for MarkGlyphSetsMarker { /// [Mark Glyph Sets Table](https://docs.microsoft.com/en-us/typography/opentype/spec/gdef#mark-glyph-sets-table) #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct MarkGlyphSetsMarker { - coverage_offsets_byte_len: usize, -} +pub struct MarkGlyphSetsMarker; -impl MarkGlyphSetsMarker { - pub fn format_byte_range(&self) -> Range { - let start = 0; - start..start + u16::RAW_BYTE_LEN - } - - pub fn mark_glyph_set_count_byte_range(&self) -> Range { - let start = self.format_byte_range().end; - start..start + u16::RAW_BYTE_LEN - } - - pub fn coverage_offsets_byte_range(&self) -> Range { - let start = self.mark_glyph_set_count_byte_range().end; - start..start + self.coverage_offsets_byte_len - } -} - -impl MinByteRange for MarkGlyphSetsMarker { +impl<'a> MinByteRange for MarkGlyphSets<'a> { fn min_byte_range(&self) -> Range { 0..self.coverage_offsets_byte_range().end } @@ -1073,41 +1031,58 @@ impl MinByteRange for MarkGlyphSetsMarker { impl<'a> FontRead<'a> for MarkGlyphSets<'a> { fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - let mark_glyph_set_count: u16 = cursor.read()?; - let coverage_offsets_byte_len = (mark_glyph_set_count as usize) - .checked_mul(Offset32::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(coverage_offsets_byte_len); - cursor.finish(MarkGlyphSetsMarker { - coverage_offsets_byte_len, + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, }) } } /// [Mark Glyph Sets Table](https://docs.microsoft.com/en-us/typography/opentype/spec/gdef#mark-glyph-sets-table) -pub type MarkGlyphSets<'a> = TableRef<'a, MarkGlyphSetsMarker>; +pub type MarkGlyphSets<'a> = TableRef<'a, MarkGlyphSetsMarker, ()>; #[allow(clippy::needless_lifetimes)] impl<'a> MarkGlyphSets<'a> { + fn coverage_offsets_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.mark_glyph_set_count()) as usize) + .checked_mul(Offset32::RAW_BYTE_LEN) + .unwrap() + } + + pub fn format_byte_range(&self) -> Range { + let start = 0; + start..start + u16::RAW_BYTE_LEN + } + + pub fn mark_glyph_set_count_byte_range(&self) -> Range { + let start = self.format_byte_range().end; + start..start + u16::RAW_BYTE_LEN + } + + pub fn coverage_offsets_byte_range(&self) -> Range { + let start = self.mark_glyph_set_count_byte_range().end; + start..start + self.coverage_offsets_byte_len(start) + } + /// Format identifier == 1 pub fn format(&self) -> u16 { - let range = self.shape.format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Number of mark glyph sets defined pub fn mark_glyph_set_count(&self) -> u16 { - let range = self.shape.mark_glyph_set_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.mark_glyph_set_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Array of offsets to mark glyph set coverage tables, from the /// start of the MarkGlyphSets table. pub fn coverage_offsets(&self) -> &'a [BigEndian] { - let range = self.shape.coverage_offsets_byte_range(); - self.data.read_array(range).unwrap() + let range = self.coverage_offsets_byte_range(); + unchecked::read_array(self.data, range) } /// A dynamically resolving wrapper for [`coverage_offsets`][Self::coverage_offsets]. diff --git a/read-fonts/generated/generated_glyf.rs b/read-fonts/generated/generated_glyf.rs index 4015b6bc6..581bb794c 100644 --- a/read-fonts/generated/generated_glyf.rs +++ b/read-fonts/generated/generated_glyf.rs @@ -8,9 +8,7 @@ use crate::codegen_prelude::*; /// The [glyf (Glyph Data)](https://docs.microsoft.com/en-us/typography/opentype/spec/glyf) table #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct GlyfMarker {} - -impl GlyfMarker {} +pub struct GlyfMarker; impl TopLevelTable for Glyf<'_> { /// `glyf` @@ -19,13 +17,16 @@ impl TopLevelTable for Glyf<'_> { impl<'a> FontRead<'a> for Glyf<'a> { fn read(data: FontData<'a>) -> Result { - let cursor = data.cursor(); - cursor.finish(GlyfMarker {}) + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) } } /// The [glyf (Glyph Data)](https://docs.microsoft.com/en-us/typography/opentype/spec/glyf) table -pub type Glyf<'a> = TableRef<'a, GlyfMarker>; +pub type Glyf<'a> = TableRef<'a, GlyfMarker, ()>; #[allow(clippy::needless_lifetimes)] impl<'a> Glyf<'a> {} @@ -56,13 +57,49 @@ impl<'a> std::fmt::Debug for Glyf<'a> { /// The [Glyph Header](https://docs.microsoft.com/en-us/typography/opentype/spec/glyf#glyph-headers) #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct SimpleGlyphMarker { - end_pts_of_contours_byte_len: usize, - instructions_byte_len: usize, - glyph_data_byte_len: usize, +pub struct SimpleGlyphMarker; + +impl<'a> MinByteRange for SimpleGlyph<'a> { + fn min_byte_range(&self) -> Range { + 0..self.glyph_data_byte_range().end + } } -impl SimpleGlyphMarker { +impl<'a> FontRead<'a> for SimpleGlyph<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// The [Glyph Header](https://docs.microsoft.com/en-us/typography/opentype/spec/glyf#glyph-headers) +pub type SimpleGlyph<'a> = TableRef<'a, SimpleGlyphMarker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> SimpleGlyph<'a> { + fn end_pts_of_contours_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.number_of_contours()) as usize) + .checked_mul(u16::RAW_BYTE_LEN) + .unwrap() + } + fn instructions_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.instruction_length()) as usize) + .checked_mul(u8::RAW_BYTE_LEN) + .unwrap() + } + fn glyph_data_byte_len(&self, start: usize) -> usize { + let _ = start; + { + let remaining = self.data.len().saturating_sub(start); + remaining / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN + } + } + pub fn number_of_contours_byte_range(&self) -> Range { let start = 0; start..start + i16::RAW_BYTE_LEN @@ -90,7 +127,7 @@ impl SimpleGlyphMarker { pub fn end_pts_of_contours_byte_range(&self) -> Range { let start = self.y_max_byte_range().end; - start..start + self.end_pts_of_contours_byte_len + start..start + self.end_pts_of_contours_byte_len(start) } pub fn instruction_length_byte_range(&self) -> Range { @@ -100,110 +137,71 @@ impl SimpleGlyphMarker { pub fn instructions_byte_range(&self) -> Range { let start = self.instruction_length_byte_range().end; - start..start + self.instructions_byte_len + start..start + self.instructions_byte_len(start) } pub fn glyph_data_byte_range(&self) -> Range { let start = self.instructions_byte_range().end; - start..start + self.glyph_data_byte_len - } -} - -impl MinByteRange for SimpleGlyphMarker { - fn min_byte_range(&self) -> Range { - 0..self.glyph_data_byte_range().end + start..start + self.glyph_data_byte_len(start) } -} - -impl<'a> FontRead<'a> for SimpleGlyph<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - let number_of_contours: i16 = cursor.read()?; - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - let end_pts_of_contours_byte_len = (number_of_contours as usize) - .checked_mul(u16::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(end_pts_of_contours_byte_len); - let instruction_length: u16 = cursor.read()?; - let instructions_byte_len = (instruction_length as usize) - .checked_mul(u8::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(instructions_byte_len); - let glyph_data_byte_len = cursor.remaining_bytes() / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN; - cursor.advance_by(glyph_data_byte_len); - cursor.finish(SimpleGlyphMarker { - end_pts_of_contours_byte_len, - instructions_byte_len, - glyph_data_byte_len, - }) - } -} -/// The [Glyph Header](https://docs.microsoft.com/en-us/typography/opentype/spec/glyf#glyph-headers) -pub type SimpleGlyph<'a> = TableRef<'a, SimpleGlyphMarker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> SimpleGlyph<'a> { /// If the number of contours is greater than or equal to zero, /// this is a simple glyph. If negative, this is a composite glyph /// — the value -1 should be used for composite glyphs. pub fn number_of_contours(&self) -> i16 { - let range = self.shape.number_of_contours_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.number_of_contours_byte_range(); + unchecked::read_at(self.data, range.start) } /// Minimum x for coordinate data. pub fn x_min(&self) -> i16 { - let range = self.shape.x_min_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.x_min_byte_range(); + unchecked::read_at(self.data, range.start) } /// Minimum y for coordinate data. pub fn y_min(&self) -> i16 { - let range = self.shape.y_min_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.y_min_byte_range(); + unchecked::read_at(self.data, range.start) } /// Maximum x for coordinate data. pub fn x_max(&self) -> i16 { - let range = self.shape.x_max_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.x_max_byte_range(); + unchecked::read_at(self.data, range.start) } /// Maximum y for coordinate data. pub fn y_max(&self) -> i16 { - let range = self.shape.y_max_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.y_max_byte_range(); + unchecked::read_at(self.data, range.start) } /// Array of point indices for the last point of each contour, /// in increasing numeric order pub fn end_pts_of_contours(&self) -> &'a [BigEndian] { - let range = self.shape.end_pts_of_contours_byte_range(); - self.data.read_array(range).unwrap() + let range = self.end_pts_of_contours_byte_range(); + unchecked::read_array(self.data, range) } /// Total number of bytes for instructions. If instructionLength is /// zero, no instructions are present for this glyph, and this /// field is followed directly by the flags field. pub fn instruction_length(&self) -> u16 { - let range = self.shape.instruction_length_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.instruction_length_byte_range(); + unchecked::read_at(self.data, range.start) } /// Array of instruction byte code for the glyph. pub fn instructions(&self) -> &'a [u8] { - let range = self.shape.instructions_byte_range(); - self.data.read_array(range).unwrap() + let range = self.instructions_byte_range(); + unchecked::read_array(self.data, range) } /// the raw data for flags & x/y coordinates pub fn glyph_data(&self) -> &'a [u8] { - let range = self.shape.glyph_data_byte_range(); - self.data.read_array(range).unwrap() + let range = self.glyph_data_byte_range(); + unchecked::read_array(self.data, range) } } @@ -640,11 +638,37 @@ impl<'a> From for FieldType<'a> { /// [CompositeGlyph](https://docs.microsoft.com/en-us/typography/opentype/spec/glyf#glyph-headers) #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct CompositeGlyphMarker { - component_data_byte_len: usize, +pub struct CompositeGlyphMarker; + +impl<'a> MinByteRange for CompositeGlyph<'a> { + fn min_byte_range(&self) -> Range { + 0..self.component_data_byte_range().end + } } -impl CompositeGlyphMarker { +impl<'a> FontRead<'a> for CompositeGlyph<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// [CompositeGlyph](https://docs.microsoft.com/en-us/typography/opentype/spec/glyf#glyph-headers) +pub type CompositeGlyph<'a> = TableRef<'a, CompositeGlyphMarker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> CompositeGlyph<'a> { + fn component_data_byte_len(&self, start: usize) -> usize { + let _ = start; + { + let remaining = self.data.len().saturating_sub(start); + remaining / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN + } + } + pub fn number_of_contours_byte_range(&self) -> Range { let start = 0; start..start + i16::RAW_BYTE_LEN @@ -672,75 +696,46 @@ impl CompositeGlyphMarker { pub fn component_data_byte_range(&self) -> Range { let start = self.y_max_byte_range().end; - start..start + self.component_data_byte_len - } -} - -impl MinByteRange for CompositeGlyphMarker { - fn min_byte_range(&self) -> Range { - 0..self.component_data_byte_range().end - } -} - -impl<'a> FontRead<'a> for CompositeGlyph<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - let component_data_byte_len = - cursor.remaining_bytes() / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN; - cursor.advance_by(component_data_byte_len); - cursor.finish(CompositeGlyphMarker { - component_data_byte_len, - }) + start..start + self.component_data_byte_len(start) } -} -/// [CompositeGlyph](https://docs.microsoft.com/en-us/typography/opentype/spec/glyf#glyph-headers) -pub type CompositeGlyph<'a> = TableRef<'a, CompositeGlyphMarker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> CompositeGlyph<'a> { /// If the number of contours is greater than or equal to zero, /// this is a simple glyph. If negative, this is a composite glyph /// — the value -1 should be used for composite glyphs. pub fn number_of_contours(&self) -> i16 { - let range = self.shape.number_of_contours_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.number_of_contours_byte_range(); + unchecked::read_at(self.data, range.start) } /// Minimum x for coordinate data. pub fn x_min(&self) -> i16 { - let range = self.shape.x_min_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.x_min_byte_range(); + unchecked::read_at(self.data, range.start) } /// Minimum y for coordinate data. pub fn y_min(&self) -> i16 { - let range = self.shape.y_min_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.y_min_byte_range(); + unchecked::read_at(self.data, range.start) } /// Maximum x for coordinate data. pub fn x_max(&self) -> i16 { - let range = self.shape.x_max_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.x_max_byte_range(); + unchecked::read_at(self.data, range.start) } /// Maximum y for coordinate data. pub fn y_max(&self) -> i16 { - let range = self.shape.y_max_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.y_max_byte_range(); + unchecked::read_at(self.data, range.start) } /// component flag /// glyph index of component pub fn component_data(&self) -> &'a [u8] { - let range = self.shape.component_data_byte_range(); - self.data.read_array(range).unwrap() + let range = self.component_data_byte_range(); + unchecked::read_array(self.data, range) } } diff --git a/read-fonts/generated/generated_gpos.rs b/read-fonts/generated/generated_gpos.rs index 477632528..20f0f4b94 100644 --- a/read-fonts/generated/generated_gpos.rs +++ b/read-fonts/generated/generated_gpos.rs @@ -9,11 +9,35 @@ use crate::codegen_prelude::*; /// [GPOS Version 1.0](https://docs.microsoft.com/en-us/typography/opentype/spec/gpos#gpos-header) #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct GposMarker { - feature_variations_offset_byte_start: Option, +pub struct GposMarker; + +impl<'a> MinByteRange for Gpos<'a> { + fn min_byte_range(&self) -> Range { + 0..self.lookup_list_offset_byte_range().end + } +} + +impl TopLevelTable for Gpos<'_> { + /// `GPOS` + const TAG: Tag = Tag::new(b"GPOS"); +} + +impl<'a> FontRead<'a> for Gpos<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } } -impl GposMarker { +/// [Class Definition Table Format 1](https://docs.microsoft.com/en-us/typography/opentype/spec/chapter2#class-definition-table-format-1) +/// [GPOS Version 1.0](https://docs.microsoft.com/en-us/typography/opentype/spec/gpos#gpos-header) +pub type Gpos<'a> = TableRef<'a, GposMarker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> Gpos<'a> { pub fn version_byte_range(&self) -> Range { let start = 0; start..start + MajorMinor::RAW_BYTE_LEN @@ -35,58 +59,24 @@ impl GposMarker { } pub fn feature_variations_offset_byte_range(&self) -> Option> { - let start = self.feature_variations_offset_byte_start?; - Some(start..start + Offset32::RAW_BYTE_LEN) - } -} - -impl MinByteRange for GposMarker { - fn min_byte_range(&self) -> Range { - 0..self.lookup_list_offset_byte_range().end - } -} - -impl TopLevelTable for Gpos<'_> { - /// `GPOS` - const TAG: Tag = Tag::new(b"GPOS"); -} - -impl<'a> FontRead<'a> for Gpos<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - let version: MajorMinor = cursor.read()?; - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - let feature_variations_offset_byte_start = version - .compatible((1u16, 1u16)) - .then(|| cursor.position()) - .transpose()?; - version - .compatible((1u16, 1u16)) - .then(|| cursor.advance::()); - cursor.finish(GposMarker { - feature_variations_offset_byte_start, - }) + if self.version().compatible((1u16, 1u16)) { + let start = self.lookup_list_offset_byte_range().end; + Some(start..start + Offset32::RAW_BYTE_LEN) + } else { + None + } } -} - -/// [Class Definition Table Format 1](https://docs.microsoft.com/en-us/typography/opentype/spec/chapter2#class-definition-table-format-1) -/// [GPOS Version 1.0](https://docs.microsoft.com/en-us/typography/opentype/spec/gpos#gpos-header) -pub type Gpos<'a> = TableRef<'a, GposMarker>; -#[allow(clippy::needless_lifetimes)] -impl<'a> Gpos<'a> { /// The major and minor version of the GPOS table, as a tuple (u16, u16) pub fn version(&self) -> MajorMinor { - let range = self.shape.version_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.version_byte_range(); + unchecked::read_at(self.data, range.start) } /// Offset to ScriptList table, from beginning of GPOS table pub fn script_list_offset(&self) -> Offset16 { - let range = self.shape.script_list_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.script_list_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`script_list_offset`][Self::script_list_offset]. @@ -97,8 +87,8 @@ impl<'a> Gpos<'a> { /// Offset to FeatureList table, from beginning of GPOS table pub fn feature_list_offset(&self) -> Offset16 { - let range = self.shape.feature_list_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.feature_list_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`feature_list_offset`][Self::feature_list_offset]. @@ -109,8 +99,8 @@ impl<'a> Gpos<'a> { /// Offset to LookupList table, from beginning of GPOS table pub fn lookup_list_offset(&self) -> Offset16 { - let range = self.shape.lookup_list_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.lookup_list_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`lookup_list_offset`][Self::lookup_list_offset]. @@ -120,8 +110,8 @@ impl<'a> Gpos<'a> { } pub fn feature_variations_offset(&self) -> Option> { - let range = self.shape.feature_variations_offset_byte_range()?; - Some(self.data.read_at(range.start).unwrap()) + let range = self.feature_variations_offset_byte_range()?; + Some(unchecked::read_at(self.data, range.start)) } /// Attempt to resolve [`feature_variations_offset`][Self::feature_variations_offset]. @@ -704,9 +694,29 @@ impl Format for AnchorFormat1Marker { /// [Anchor Table Format 1](https://docs.microsoft.com/en-us/typography/opentype/spec/gpos#anchor-table-format-1-design-units): Design Units #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct AnchorFormat1Marker {} +pub struct AnchorFormat1Marker; + +impl<'a> MinByteRange for AnchorFormat1<'a> { + fn min_byte_range(&self) -> Range { + 0..self.y_coordinate_byte_range().end + } +} + +impl<'a> FontRead<'a> for AnchorFormat1<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// [Anchor Table Format 1](https://docs.microsoft.com/en-us/typography/opentype/spec/gpos#anchor-table-format-1-design-units): Design Units +pub type AnchorFormat1<'a> = TableRef<'a, AnchorFormat1Marker, ()>; -impl AnchorFormat1Marker { +#[allow(clippy::needless_lifetimes)] +impl<'a> AnchorFormat1<'a> { pub fn anchor_format_byte_range(&self) -> Range { let start = 0; start..start + u16::RAW_BYTE_LEN @@ -721,45 +731,23 @@ impl AnchorFormat1Marker { let start = self.x_coordinate_byte_range().end; start..start + i16::RAW_BYTE_LEN } -} - -impl MinByteRange for AnchorFormat1Marker { - fn min_byte_range(&self) -> Range { - 0..self.y_coordinate_byte_range().end - } -} - -impl<'a> FontRead<'a> for AnchorFormat1<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.finish(AnchorFormat1Marker {}) - } -} - -/// [Anchor Table Format 1](https://docs.microsoft.com/en-us/typography/opentype/spec/gpos#anchor-table-format-1-design-units): Design Units -pub type AnchorFormat1<'a> = TableRef<'a, AnchorFormat1Marker>; -#[allow(clippy::needless_lifetimes)] -impl<'a> AnchorFormat1<'a> { /// Format identifier, = 1 pub fn anchor_format(&self) -> u16 { - let range = self.shape.anchor_format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.anchor_format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Horizontal value, in design units pub fn x_coordinate(&self) -> i16 { - let range = self.shape.x_coordinate_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.x_coordinate_byte_range(); + unchecked::read_at(self.data, range.start) } /// Vertical value, in design units pub fn y_coordinate(&self) -> i16 { - let range = self.shape.y_coordinate_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.y_coordinate_byte_range(); + unchecked::read_at(self.data, range.start) } } @@ -793,9 +781,29 @@ impl Format for AnchorFormat2Marker { /// [Anchor Table Format 2](https://docs.microsoft.com/en-us/typography/opentype/spec/gpos#anchor-table-format-2-design-units-plus-contour-point): Design Units Plus Contour Point #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct AnchorFormat2Marker {} +pub struct AnchorFormat2Marker; + +impl<'a> MinByteRange for AnchorFormat2<'a> { + fn min_byte_range(&self) -> Range { + 0..self.anchor_point_byte_range().end + } +} + +impl<'a> FontRead<'a> for AnchorFormat2<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// [Anchor Table Format 2](https://docs.microsoft.com/en-us/typography/opentype/spec/gpos#anchor-table-format-2-design-units-plus-contour-point): Design Units Plus Contour Point +pub type AnchorFormat2<'a> = TableRef<'a, AnchorFormat2Marker, ()>; -impl AnchorFormat2Marker { +#[allow(clippy::needless_lifetimes)] +impl<'a> AnchorFormat2<'a> { pub fn anchor_format_byte_range(&self) -> Range { let start = 0; start..start + u16::RAW_BYTE_LEN @@ -815,52 +823,29 @@ impl AnchorFormat2Marker { let start = self.y_coordinate_byte_range().end; start..start + u16::RAW_BYTE_LEN } -} - -impl MinByteRange for AnchorFormat2Marker { - fn min_byte_range(&self) -> Range { - 0..self.anchor_point_byte_range().end - } -} - -impl<'a> FontRead<'a> for AnchorFormat2<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.finish(AnchorFormat2Marker {}) - } -} - -/// [Anchor Table Format 2](https://docs.microsoft.com/en-us/typography/opentype/spec/gpos#anchor-table-format-2-design-units-plus-contour-point): Design Units Plus Contour Point -pub type AnchorFormat2<'a> = TableRef<'a, AnchorFormat2Marker>; -#[allow(clippy::needless_lifetimes)] -impl<'a> AnchorFormat2<'a> { /// Format identifier, = 2 pub fn anchor_format(&self) -> u16 { - let range = self.shape.anchor_format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.anchor_format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Horizontal value, in design units pub fn x_coordinate(&self) -> i16 { - let range = self.shape.x_coordinate_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.x_coordinate_byte_range(); + unchecked::read_at(self.data, range.start) } /// Vertical value, in design units pub fn y_coordinate(&self) -> i16 { - let range = self.shape.y_coordinate_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.y_coordinate_byte_range(); + unchecked::read_at(self.data, range.start) } /// Index to glyph contour point pub fn anchor_point(&self) -> u16 { - let range = self.shape.anchor_point_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.anchor_point_byte_range(); + unchecked::read_at(self.data, range.start) } } @@ -895,9 +880,29 @@ impl Format for AnchorFormat3Marker { /// [Anchor Table Format 3](https://docs.microsoft.com/en-us/typography/opentype/spec/gpos#anchor-table-format-3-design-units-plus-device-or-variationindex-tables): Design Units Plus Device or VariationIndex Tables #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct AnchorFormat3Marker {} +pub struct AnchorFormat3Marker; + +impl<'a> MinByteRange for AnchorFormat3<'a> { + fn min_byte_range(&self) -> Range { + 0..self.y_device_offset_byte_range().end + } +} + +impl<'a> FontRead<'a> for AnchorFormat3<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// [Anchor Table Format 3](https://docs.microsoft.com/en-us/typography/opentype/spec/gpos#anchor-table-format-3-design-units-plus-device-or-variationindex-tables): Design Units Plus Device or VariationIndex Tables +pub type AnchorFormat3<'a> = TableRef<'a, AnchorFormat3Marker, ()>; -impl AnchorFormat3Marker { +#[allow(clippy::needless_lifetimes)] +impl<'a> AnchorFormat3<'a> { pub fn anchor_format_byte_range(&self) -> Range { let start = 0; start..start + u16::RAW_BYTE_LEN @@ -922,55 +927,31 @@ impl AnchorFormat3Marker { let start = self.x_device_offset_byte_range().end; start..start + Offset16::RAW_BYTE_LEN } -} - -impl MinByteRange for AnchorFormat3Marker { - fn min_byte_range(&self) -> Range { - 0..self.y_device_offset_byte_range().end - } -} - -impl<'a> FontRead<'a> for AnchorFormat3<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.finish(AnchorFormat3Marker {}) - } -} - -/// [Anchor Table Format 3](https://docs.microsoft.com/en-us/typography/opentype/spec/gpos#anchor-table-format-3-design-units-plus-device-or-variationindex-tables): Design Units Plus Device or VariationIndex Tables -pub type AnchorFormat3<'a> = TableRef<'a, AnchorFormat3Marker>; -#[allow(clippy::needless_lifetimes)] -impl<'a> AnchorFormat3<'a> { /// Format identifier, = 3 pub fn anchor_format(&self) -> u16 { - let range = self.shape.anchor_format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.anchor_format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Horizontal value, in design units pub fn x_coordinate(&self) -> i16 { - let range = self.shape.x_coordinate_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.x_coordinate_byte_range(); + unchecked::read_at(self.data, range.start) } /// Vertical value, in design units pub fn y_coordinate(&self) -> i16 { - let range = self.shape.y_coordinate_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.y_coordinate_byte_range(); + unchecked::read_at(self.data, range.start) } /// Offset to Device table (non-variable font) / VariationIndex /// table (variable font) for X coordinate, from beginning of /// Anchor table (may be NULL) pub fn x_device_offset(&self) -> Nullable { - let range = self.shape.x_device_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.x_device_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`x_device_offset`][Self::x_device_offset]. @@ -983,8 +964,8 @@ impl<'a> AnchorFormat3<'a> { /// table (variable font) for Y coordinate, from beginning of /// Anchor table (may be NULL) pub fn y_device_offset(&self) -> Nullable { - let range = self.shape.y_device_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.y_device_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`y_device_offset`][Self::y_device_offset]. @@ -1028,23 +1009,9 @@ impl<'a> std::fmt::Debug for AnchorFormat3<'a> { /// [Mark Array Table](https://docs.microsoft.com/en-us/typography/opentype/spec/gpos#mark-array-table) #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct MarkArrayMarker { - mark_records_byte_len: usize, -} +pub struct MarkArrayMarker; -impl MarkArrayMarker { - pub fn mark_count_byte_range(&self) -> Range { - let start = 0; - start..start + u16::RAW_BYTE_LEN - } - - pub fn mark_records_byte_range(&self) -> Range { - let start = self.mark_count_byte_range().end; - start..start + self.mark_records_byte_len - } -} - -impl MinByteRange for MarkArrayMarker { +impl<'a> MinByteRange for MarkArray<'a> { fn min_byte_range(&self) -> Range { 0..self.mark_records_byte_range().end } @@ -1052,34 +1019,47 @@ impl MinByteRange for MarkArrayMarker { impl<'a> FontRead<'a> for MarkArray<'a> { fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - let mark_count: u16 = cursor.read()?; - let mark_records_byte_len = (mark_count as usize) - .checked_mul(MarkRecord::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(mark_records_byte_len); - cursor.finish(MarkArrayMarker { - mark_records_byte_len, + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, }) } } /// [Mark Array Table](https://docs.microsoft.com/en-us/typography/opentype/spec/gpos#mark-array-table) -pub type MarkArray<'a> = TableRef<'a, MarkArrayMarker>; +pub type MarkArray<'a> = TableRef<'a, MarkArrayMarker, ()>; #[allow(clippy::needless_lifetimes)] impl<'a> MarkArray<'a> { + fn mark_records_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.mark_count()) as usize) + .checked_mul(MarkRecord::RAW_BYTE_LEN) + .unwrap() + } + + pub fn mark_count_byte_range(&self) -> Range { + let start = 0; + start..start + u16::RAW_BYTE_LEN + } + + pub fn mark_records_byte_range(&self) -> Range { + let start = self.mark_count_byte_range().end; + start..start + self.mark_records_byte_len(start) + } + /// Number of MarkRecords pub fn mark_count(&self) -> u16 { - let range = self.shape.mark_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.mark_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Array of MarkRecords, ordered by corresponding glyphs in the /// associated mark Coverage table. pub fn mark_records(&self) -> &'a [MarkRecord] { - let range = self.shape.mark_records_byte_range(); - self.data.read_array(range).unwrap() + let range = self.mark_records_byte_range(); + unchecked::read_array(self.data, range) } } @@ -1260,11 +1240,34 @@ impl Format for SinglePosFormat1Marker { /// [Single Adjustment Positioning Format 1](https://docs.microsoft.com/en-us/typography/opentype/spec/gpos#single-adjustment-positioning-format-1-single-positioning-value): Single Positioning Value #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct SinglePosFormat1Marker { - value_record_byte_len: usize, +pub struct SinglePosFormat1Marker; + +impl<'a> MinByteRange for SinglePosFormat1<'a> { + fn min_byte_range(&self) -> Range { + 0..self.value_record_byte_range().end + } +} + +impl<'a> FontRead<'a> for SinglePosFormat1<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } } -impl SinglePosFormat1Marker { +/// [Single Adjustment Positioning Format 1](https://docs.microsoft.com/en-us/typography/opentype/spec/gpos#single-adjustment-positioning-format-1-single-positioning-value): Single Positioning Value +pub type SinglePosFormat1<'a> = TableRef<'a, SinglePosFormat1Marker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> SinglePosFormat1<'a> { + fn value_record_byte_len(&self, start: usize) -> usize { + let _ = start; + ::compute_size(&self.value_format()).unwrap() + } + pub fn pos_format_byte_range(&self) -> Range { let start = 0; start..start + u16::RAW_BYTE_LEN @@ -1282,45 +1285,19 @@ impl SinglePosFormat1Marker { pub fn value_record_byte_range(&self) -> Range { let start = self.value_format_byte_range().end; - start..start + self.value_record_byte_len - } -} - -impl MinByteRange for SinglePosFormat1Marker { - fn min_byte_range(&self) -> Range { - 0..self.value_record_byte_range().end - } -} - -impl<'a> FontRead<'a> for SinglePosFormat1<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - let value_format: ValueFormat = cursor.read()?; - let value_record_byte_len = ::compute_size(&value_format)?; - cursor.advance_by(value_record_byte_len); - cursor.finish(SinglePosFormat1Marker { - value_record_byte_len, - }) + start..start + self.value_record_byte_len(start) } -} - -/// [Single Adjustment Positioning Format 1](https://docs.microsoft.com/en-us/typography/opentype/spec/gpos#single-adjustment-positioning-format-1-single-positioning-value): Single Positioning Value -pub type SinglePosFormat1<'a> = TableRef<'a, SinglePosFormat1Marker>; -#[allow(clippy::needless_lifetimes)] -impl<'a> SinglePosFormat1<'a> { /// Format identifier: format = 1 pub fn pos_format(&self) -> u16 { - let range = self.shape.pos_format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.pos_format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Offset to Coverage table, from beginning of SinglePos subtable. pub fn coverage_offset(&self) -> Offset16 { - let range = self.shape.coverage_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.coverage_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`coverage_offset`][Self::coverage_offset]. @@ -1331,17 +1308,15 @@ impl<'a> SinglePosFormat1<'a> { /// Defines the types of data in the ValueRecord. pub fn value_format(&self) -> ValueFormat { - let range = self.shape.value_format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.value_format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Defines positioning value(s) — applied to all glyphs in the /// Coverage table. pub fn value_record(&self) -> ValueRecord { - let range = self.shape.value_record_byte_range(); - self.data - .read_with_args(range, &self.value_format()) - .unwrap() + let range = self.value_record_byte_range(); + unchecked::read_with_args(self.data, range, &self.value_format()) } } @@ -1382,11 +1357,36 @@ impl Format for SinglePosFormat2Marker { /// [Single Adjustment Positioning Format 2](https://docs.microsoft.com/en-us/typography/opentype/spec/gpos#single-adjustment-positioning-format-2-array-of-positioning-values): Array of Positioning Values #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct SinglePosFormat2Marker { - value_records_byte_len: usize, +pub struct SinglePosFormat2Marker; + +impl<'a> MinByteRange for SinglePosFormat2<'a> { + fn min_byte_range(&self) -> Range { + 0..self.value_records_byte_range().end + } +} + +impl<'a> FontRead<'a> for SinglePosFormat2<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } } -impl SinglePosFormat2Marker { +/// [Single Adjustment Positioning Format 2](https://docs.microsoft.com/en-us/typography/opentype/spec/gpos#single-adjustment-positioning-format-2-array-of-positioning-values): Array of Positioning Values +pub type SinglePosFormat2<'a> = TableRef<'a, SinglePosFormat2Marker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> SinglePosFormat2<'a> { + fn value_records_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.value_count()) as usize) + .checked_mul(::compute_size(&self.value_format()).unwrap()) + .unwrap() + } + pub fn pos_format_byte_range(&self) -> Range { let start = 0; start..start + u16::RAW_BYTE_LEN @@ -1409,48 +1409,19 @@ impl SinglePosFormat2Marker { pub fn value_records_byte_range(&self) -> Range { let start = self.value_count_byte_range().end; - start..start + self.value_records_byte_len + start..start + self.value_records_byte_len(start) } -} - -impl MinByteRange for SinglePosFormat2Marker { - fn min_byte_range(&self) -> Range { - 0..self.value_records_byte_range().end - } -} - -impl<'a> FontRead<'a> for SinglePosFormat2<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - let value_format: ValueFormat = cursor.read()?; - let value_count: u16 = cursor.read()?; - let value_records_byte_len = (value_count as usize) - .checked_mul(::compute_size(&value_format)?) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(value_records_byte_len); - cursor.finish(SinglePosFormat2Marker { - value_records_byte_len, - }) - } -} - -/// [Single Adjustment Positioning Format 2](https://docs.microsoft.com/en-us/typography/opentype/spec/gpos#single-adjustment-positioning-format-2-array-of-positioning-values): Array of Positioning Values -pub type SinglePosFormat2<'a> = TableRef<'a, SinglePosFormat2Marker>; -#[allow(clippy::needless_lifetimes)] -impl<'a> SinglePosFormat2<'a> { /// Format identifier: format = 2 pub fn pos_format(&self) -> u16 { - let range = self.shape.pos_format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.pos_format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Offset to Coverage table, from beginning of SinglePos subtable. pub fn coverage_offset(&self) -> Offset16 { - let range = self.shape.coverage_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.coverage_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`coverage_offset`][Self::coverage_offset]. @@ -1461,23 +1432,21 @@ impl<'a> SinglePosFormat2<'a> { /// Defines the types of data in the ValueRecords. pub fn value_format(&self) -> ValueFormat { - let range = self.shape.value_format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.value_format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Number of ValueRecords — must equal glyphCount in the /// Coverage table. pub fn value_count(&self) -> u16 { - let range = self.shape.value_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.value_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Array of ValueRecords — positioning values applied to glyphs. pub fn value_records(&self) -> ComputedArray<'a, ValueRecord> { - let range = self.shape.value_records_byte_range(); - self.data - .read_with_args(range, &self.value_format()) - .unwrap() + let range = self.value_records_byte_range(); + unchecked::read_with_args(self.data, range, &self.value_format()) } } @@ -1621,17 +1590,42 @@ impl Format for PairPosFormat1Marker { /// [Pair Adjustment Positioning Format 1](https://docs.microsoft.com/en-us/typography/opentype/spec/gpos#pair-adjustment-positioning-format-1-adjustments-for-glyph-pairs): Adjustments for Glyph Pairs #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct PairPosFormat1Marker { - pair_set_offsets_byte_len: usize, +pub struct PairPosFormat1Marker; + +impl<'a> MinByteRange for PairPosFormat1<'a> { + fn min_byte_range(&self) -> Range { + 0..self.pair_set_offsets_byte_range().end + } } -impl PairPosFormat1Marker { - pub fn pos_format_byte_range(&self) -> Range { - let start = 0; - start..start + u16::RAW_BYTE_LEN +impl<'a> FontRead<'a> for PairPosFormat1<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) } +} - pub fn coverage_offset_byte_range(&self) -> Range { +/// [Pair Adjustment Positioning Format 1](https://docs.microsoft.com/en-us/typography/opentype/spec/gpos#pair-adjustment-positioning-format-1-adjustments-for-glyph-pairs): Adjustments for Glyph Pairs +pub type PairPosFormat1<'a> = TableRef<'a, PairPosFormat1Marker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> PairPosFormat1<'a> { + fn pair_set_offsets_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.pair_set_count()) as usize) + .checked_mul(Offset16::RAW_BYTE_LEN) + .unwrap() + } + + pub fn pos_format_byte_range(&self) -> Range { + let start = 0; + start..start + u16::RAW_BYTE_LEN + } + + pub fn coverage_offset_byte_range(&self) -> Range { let start = self.pos_format_byte_range().end; start..start + Offset16::RAW_BYTE_LEN } @@ -1653,49 +1647,19 @@ impl PairPosFormat1Marker { pub fn pair_set_offsets_byte_range(&self) -> Range { let start = self.pair_set_count_byte_range().end; - start..start + self.pair_set_offsets_byte_len - } -} - -impl MinByteRange for PairPosFormat1Marker { - fn min_byte_range(&self) -> Range { - 0..self.pair_set_offsets_byte_range().end - } -} - -impl<'a> FontRead<'a> for PairPosFormat1<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - let pair_set_count: u16 = cursor.read()?; - let pair_set_offsets_byte_len = (pair_set_count as usize) - .checked_mul(Offset16::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(pair_set_offsets_byte_len); - cursor.finish(PairPosFormat1Marker { - pair_set_offsets_byte_len, - }) + start..start + self.pair_set_offsets_byte_len(start) } -} -/// [Pair Adjustment Positioning Format 1](https://docs.microsoft.com/en-us/typography/opentype/spec/gpos#pair-adjustment-positioning-format-1-adjustments-for-glyph-pairs): Adjustments for Glyph Pairs -pub type PairPosFormat1<'a> = TableRef<'a, PairPosFormat1Marker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> PairPosFormat1<'a> { /// Format identifier: format = 1 pub fn pos_format(&self) -> u16 { - let range = self.shape.pos_format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.pos_format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Offset to Coverage table, from beginning of PairPos subtable. pub fn coverage_offset(&self) -> Offset16 { - let range = self.shape.coverage_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.coverage_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`coverage_offset`][Self::coverage_offset]. @@ -1707,28 +1671,28 @@ impl<'a> PairPosFormat1<'a> { /// Defines the types of data in valueRecord1 — for the first /// glyph in the pair (may be zero). pub fn value_format1(&self) -> ValueFormat { - let range = self.shape.value_format1_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.value_format1_byte_range(); + unchecked::read_at(self.data, range.start) } /// Defines the types of data in valueRecord2 — for the second /// glyph in the pair (may be zero). pub fn value_format2(&self) -> ValueFormat { - let range = self.shape.value_format2_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.value_format2_byte_range(); + unchecked::read_at(self.data, range.start) } /// Number of PairSet tables pub fn pair_set_count(&self) -> u16 { - let range = self.shape.pair_set_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.pair_set_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Array of offsets to PairSet tables. Offsets are from beginning /// of PairPos subtable, ordered by Coverage Index. pub fn pair_set_offsets(&self) -> &'a [BigEndian] { - let range = self.shape.pair_set_offsets_byte_range(); - self.data.read_array(range).unwrap() + let range = self.pair_set_offsets_byte_range(); + unchecked::read_array(self.data, range) } /// A dynamically resolving wrapper for [`pair_set_offsets`][Self::pair_set_offsets]. @@ -1786,25 +1750,9 @@ impl<'a> std::fmt::Debug for PairPosFormat1<'a> { /// Part of [PairPosFormat1] #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct PairSetMarker { - value_format1: ValueFormat, - value_format2: ValueFormat, - pair_value_records_byte_len: usize, -} +pub struct PairSetMarker; -impl PairSetMarker { - pub fn pair_value_count_byte_range(&self) -> Range { - let start = 0; - start..start + u16::RAW_BYTE_LEN - } - - pub fn pair_value_records_byte_range(&self) -> Range { - let start = self.pair_value_count_byte_range().end; - start..start + self.pair_value_records_byte_len - } -} - -impl MinByteRange for PairSetMarker { +impl<'a> MinByteRange for PairSet<'a> { fn min_byte_range(&self) -> Range { 0..self.pair_value_records_byte_range().end } @@ -1819,20 +1767,11 @@ impl<'a> FontReadWithArgs<'a> for PairSet<'a> { data: FontData<'a>, args: &(ValueFormat, ValueFormat), ) -> Result { - let (value_format1, value_format2) = *args; - let mut cursor = data.cursor(); - let pair_value_count: u16 = cursor.read()?; - let pair_value_records_byte_len = (pair_value_count as usize) - .checked_mul(::compute_size(&( - value_format1, - value_format2, - ))?) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(pair_value_records_byte_len); - cursor.finish(PairSetMarker { - value_format1, - value_format2, - pair_value_records_byte_len, + let args = *args; + Ok(TableRef { + args, + data, + _marker: std::marker::PhantomData, }) } } @@ -1853,31 +1792,53 @@ impl<'a> PairSet<'a> { } /// Part of [PairPosFormat1] -pub type PairSet<'a> = TableRef<'a, PairSetMarker>; +pub type PairSet<'a> = TableRef<'a, PairSetMarker, (ValueFormat, ValueFormat)>; #[allow(clippy::needless_lifetimes)] impl<'a> PairSet<'a> { + fn pair_value_records_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.pair_value_count()) as usize) + .checked_mul( + ::compute_size(&(self.args.0, self.args.1)) + .unwrap(), + ) + .unwrap() + } + + pub fn pair_value_count_byte_range(&self) -> Range { + let start = 0; + start..start + u16::RAW_BYTE_LEN + } + + pub fn pair_value_records_byte_range(&self) -> Range { + let start = self.pair_value_count_byte_range().end; + start..start + self.pair_value_records_byte_len(start) + } + /// Number of PairValueRecords pub fn pair_value_count(&self) -> u16 { - let range = self.shape.pair_value_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.pair_value_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Array of PairValueRecords, ordered by glyph ID of the second /// glyph. pub fn pair_value_records(&self) -> ComputedArray<'a, PairValueRecord> { - let range = self.shape.pair_value_records_byte_range(); - self.data - .read_with_args(range, &(self.value_format1(), self.value_format2())) - .unwrap() + let range = self.pair_value_records_byte_range(); + unchecked::read_with_args( + self.data, + range, + &(self.value_format1(), self.value_format2()), + ) } pub(crate) fn value_format1(&self) -> ValueFormat { - self.shape.value_format1 + self.args.0 } pub(crate) fn value_format2(&self) -> ValueFormat { - self.shape.value_format2 + self.args.1 } } @@ -2022,11 +1983,43 @@ impl Format for PairPosFormat2Marker { /// [Pair Adjustment Positioning Format 2](https://docs.microsoft.com/en-us/typography/opentype/spec/gpos#pair-adjustment-positioning-format-2-class-pair-adjustment): Class Pair Adjustment #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct PairPosFormat2Marker { - class1_records_byte_len: usize, +pub struct PairPosFormat2Marker; + +impl<'a> MinByteRange for PairPosFormat2<'a> { + fn min_byte_range(&self) -> Range { + 0..self.class1_records_byte_range().end + } +} + +impl<'a> FontRead<'a> for PairPosFormat2<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } } -impl PairPosFormat2Marker { +/// [Pair Adjustment Positioning Format 2](https://docs.microsoft.com/en-us/typography/opentype/spec/gpos#pair-adjustment-positioning-format-2-class-pair-adjustment): Class Pair Adjustment +pub type PairPosFormat2<'a> = TableRef<'a, PairPosFormat2Marker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> PairPosFormat2<'a> { + fn class1_records_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.class1_count()) as usize) + .checked_mul( + ::compute_size(&( + self.class2_count(), + self.value_format1(), + self.value_format2(), + )) + .unwrap(), + ) + .unwrap() + } + pub fn pos_format_byte_range(&self) -> Range { let start = 0; start..start + u16::RAW_BYTE_LEN @@ -2069,56 +2062,19 @@ impl PairPosFormat2Marker { pub fn class1_records_byte_range(&self) -> Range { let start = self.class2_count_byte_range().end; - start..start + self.class1_records_byte_len - } -} - -impl MinByteRange for PairPosFormat2Marker { - fn min_byte_range(&self) -> Range { - 0..self.class1_records_byte_range().end - } -} - -impl<'a> FontRead<'a> for PairPosFormat2<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - let value_format1: ValueFormat = cursor.read()?; - let value_format2: ValueFormat = cursor.read()?; - cursor.advance::(); - cursor.advance::(); - let class1_count: u16 = cursor.read()?; - let class2_count: u16 = cursor.read()?; - let class1_records_byte_len = (class1_count as usize) - .checked_mul(::compute_size(&( - class2_count, - value_format1, - value_format2, - ))?) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(class1_records_byte_len); - cursor.finish(PairPosFormat2Marker { - class1_records_byte_len, - }) + start..start + self.class1_records_byte_len(start) } -} -/// [Pair Adjustment Positioning Format 2](https://docs.microsoft.com/en-us/typography/opentype/spec/gpos#pair-adjustment-positioning-format-2-class-pair-adjustment): Class Pair Adjustment -pub type PairPosFormat2<'a> = TableRef<'a, PairPosFormat2Marker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> PairPosFormat2<'a> { /// Format identifier: format = 2 pub fn pos_format(&self) -> u16 { - let range = self.shape.pos_format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.pos_format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Offset to Coverage table, from beginning of PairPos subtable. pub fn coverage_offset(&self) -> Offset16 { - let range = self.shape.coverage_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.coverage_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`coverage_offset`][Self::coverage_offset]. @@ -2130,22 +2086,22 @@ impl<'a> PairPosFormat2<'a> { /// ValueRecord definition — for the first glyph of the pair (may /// be zero). pub fn value_format1(&self) -> ValueFormat { - let range = self.shape.value_format1_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.value_format1_byte_range(); + unchecked::read_at(self.data, range.start) } /// ValueRecord definition — for the second glyph of the pair /// (may be zero). pub fn value_format2(&self) -> ValueFormat { - let range = self.shape.value_format2_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.value_format2_byte_range(); + unchecked::read_at(self.data, range.start) } /// Offset to ClassDef table, from beginning of PairPos subtable /// — for the first glyph of the pair. pub fn class_def1_offset(&self) -> Offset16 { - let range = self.shape.class_def1_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.class_def1_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`class_def1_offset`][Self::class_def1_offset]. @@ -2157,8 +2113,8 @@ impl<'a> PairPosFormat2<'a> { /// Offset to ClassDef table, from beginning of PairPos subtable /// — for the second glyph of the pair. pub fn class_def2_offset(&self) -> Offset16 { - let range = self.shape.class_def2_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.class_def2_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`class_def2_offset`][Self::class_def2_offset]. @@ -2169,29 +2125,28 @@ impl<'a> PairPosFormat2<'a> { /// Number of classes in classDef1 table — includes Class 0. pub fn class1_count(&self) -> u16 { - let range = self.shape.class1_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.class1_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Number of classes in classDef2 table — includes Class 0. pub fn class2_count(&self) -> u16 { - let range = self.shape.class2_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.class2_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Array of Class1 records, ordered by classes in classDef1. pub fn class1_records(&self) -> ComputedArray<'a, Class1Record<'a>> { - let range = self.shape.class1_records_byte_range(); - self.data - .read_with_args( - range, - &( - self.class2_count(), - self.value_format1(), - self.value_format2(), - ), - ) - .unwrap() + let range = self.class1_records_byte_range(); + unchecked::read_with_args( + self.data, + range, + &( + self.class2_count(), + self.value_format1(), + self.value_format2(), + ), + ) } } @@ -2421,11 +2376,36 @@ impl Format for CursivePosFormat1Marker { /// [Cursive Attachment Positioning Format 1](https://docs.microsoft.com/en-us/typography/opentype/spec/gpos#cursive-attachment-positioning-format1-cursive-attachment): Cursvie attachment #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct CursivePosFormat1Marker { - entry_exit_record_byte_len: usize, +pub struct CursivePosFormat1Marker; + +impl<'a> MinByteRange for CursivePosFormat1<'a> { + fn min_byte_range(&self) -> Range { + 0..self.entry_exit_record_byte_range().end + } +} + +impl<'a> FontRead<'a> for CursivePosFormat1<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } } -impl CursivePosFormat1Marker { +/// [Cursive Attachment Positioning Format 1](https://docs.microsoft.com/en-us/typography/opentype/spec/gpos#cursive-attachment-positioning-format1-cursive-attachment): Cursvie attachment +pub type CursivePosFormat1<'a> = TableRef<'a, CursivePosFormat1Marker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> CursivePosFormat1<'a> { + fn entry_exit_record_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.entry_exit_count()) as usize) + .checked_mul(EntryExitRecord::RAW_BYTE_LEN) + .unwrap() + } + pub fn pos_format_byte_range(&self) -> Range { let start = 0; start..start + u16::RAW_BYTE_LEN @@ -2443,47 +2423,19 @@ impl CursivePosFormat1Marker { pub fn entry_exit_record_byte_range(&self) -> Range { let start = self.entry_exit_count_byte_range().end; - start..start + self.entry_exit_record_byte_len - } -} - -impl MinByteRange for CursivePosFormat1Marker { - fn min_byte_range(&self) -> Range { - 0..self.entry_exit_record_byte_range().end + start..start + self.entry_exit_record_byte_len(start) } -} - -impl<'a> FontRead<'a> for CursivePosFormat1<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - let entry_exit_count: u16 = cursor.read()?; - let entry_exit_record_byte_len = (entry_exit_count as usize) - .checked_mul(EntryExitRecord::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(entry_exit_record_byte_len); - cursor.finish(CursivePosFormat1Marker { - entry_exit_record_byte_len, - }) - } -} - -/// [Cursive Attachment Positioning Format 1](https://docs.microsoft.com/en-us/typography/opentype/spec/gpos#cursive-attachment-positioning-format1-cursive-attachment): Cursvie attachment -pub type CursivePosFormat1<'a> = TableRef<'a, CursivePosFormat1Marker>; -#[allow(clippy::needless_lifetimes)] -impl<'a> CursivePosFormat1<'a> { /// Format identifier: format = 1 pub fn pos_format(&self) -> u16 { - let range = self.shape.pos_format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.pos_format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Offset to Coverage table, from beginning of CursivePos subtable. pub fn coverage_offset(&self) -> Offset16 { - let range = self.shape.coverage_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.coverage_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`coverage_offset`][Self::coverage_offset]. @@ -2494,14 +2446,14 @@ impl<'a> CursivePosFormat1<'a> { /// Number of EntryExit records pub fn entry_exit_count(&self) -> u16 { - let range = self.shape.entry_exit_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.entry_exit_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Array of EntryExit records, in Coverage index order. pub fn entry_exit_record(&self) -> &'a [EntryExitRecord] { - let range = self.shape.entry_exit_record_byte_range(); - self.data.read_array(range).unwrap() + let range = self.entry_exit_record_byte_range(); + unchecked::read_array(self.data, range) } } @@ -2622,9 +2574,29 @@ impl Format for MarkBasePosFormat1Marker { /// [Mark-to-Base Attachment Positioning Format 1](https://docs.microsoft.com/en-us/typography/opentype/spec/gpos#mark-to-base-attachment-positioning-format-1-mark-to-base-attachment-point): Mark-to-base Attachment Point #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct MarkBasePosFormat1Marker {} +pub struct MarkBasePosFormat1Marker; + +impl<'a> MinByteRange for MarkBasePosFormat1<'a> { + fn min_byte_range(&self) -> Range { + 0..self.base_array_offset_byte_range().end + } +} -impl MarkBasePosFormat1Marker { +impl<'a> FontRead<'a> for MarkBasePosFormat1<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// [Mark-to-Base Attachment Positioning Format 1](https://docs.microsoft.com/en-us/typography/opentype/spec/gpos#mark-to-base-attachment-positioning-format-1-mark-to-base-attachment-point): Mark-to-base Attachment Point +pub type MarkBasePosFormat1<'a> = TableRef<'a, MarkBasePosFormat1Marker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> MarkBasePosFormat1<'a> { pub fn pos_format_byte_range(&self) -> Range { let start = 0; start..start + u16::RAW_BYTE_LEN @@ -2654,43 +2626,18 @@ impl MarkBasePosFormat1Marker { let start = self.mark_array_offset_byte_range().end; start..start + Offset16::RAW_BYTE_LEN } -} - -impl MinByteRange for MarkBasePosFormat1Marker { - fn min_byte_range(&self) -> Range { - 0..self.base_array_offset_byte_range().end - } -} - -impl<'a> FontRead<'a> for MarkBasePosFormat1<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.finish(MarkBasePosFormat1Marker {}) - } -} - -/// [Mark-to-Base Attachment Positioning Format 1](https://docs.microsoft.com/en-us/typography/opentype/spec/gpos#mark-to-base-attachment-positioning-format-1-mark-to-base-attachment-point): Mark-to-base Attachment Point -pub type MarkBasePosFormat1<'a> = TableRef<'a, MarkBasePosFormat1Marker>; -#[allow(clippy::needless_lifetimes)] -impl<'a> MarkBasePosFormat1<'a> { /// Format identifier: format = 1 pub fn pos_format(&self) -> u16 { - let range = self.shape.pos_format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.pos_format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Offset to markCoverage table, from beginning of MarkBasePos /// subtable. pub fn mark_coverage_offset(&self) -> Offset16 { - let range = self.shape.mark_coverage_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.mark_coverage_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`mark_coverage_offset`][Self::mark_coverage_offset]. @@ -2702,8 +2649,8 @@ impl<'a> MarkBasePosFormat1<'a> { /// Offset to baseCoverage table, from beginning of MarkBasePos /// subtable. pub fn base_coverage_offset(&self) -> Offset16 { - let range = self.shape.base_coverage_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.base_coverage_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`base_coverage_offset`][Self::base_coverage_offset]. @@ -2714,15 +2661,15 @@ impl<'a> MarkBasePosFormat1<'a> { /// Number of classes defined for marks pub fn mark_class_count(&self) -> u16 { - let range = self.shape.mark_class_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.mark_class_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Offset to MarkArray table, from beginning of MarkBasePos /// subtable. pub fn mark_array_offset(&self) -> Offset16 { - let range = self.shape.mark_array_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.mark_array_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`mark_array_offset`][Self::mark_array_offset]. @@ -2734,8 +2681,8 @@ impl<'a> MarkBasePosFormat1<'a> { /// Offset to BaseArray table, from beginning of MarkBasePos /// subtable. pub fn base_array_offset(&self) -> Offset16 { - let range = self.shape.base_array_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.base_array_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`base_array_offset`][Self::base_array_offset]. @@ -2787,24 +2734,9 @@ impl<'a> std::fmt::Debug for MarkBasePosFormat1<'a> { /// Part of [MarkBasePosFormat1] #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct BaseArrayMarker { - mark_class_count: u16, - base_records_byte_len: usize, -} +pub struct BaseArrayMarker; -impl BaseArrayMarker { - pub fn base_count_byte_range(&self) -> Range { - let start = 0; - start..start + u16::RAW_BYTE_LEN - } - - pub fn base_records_byte_range(&self) -> Range { - let start = self.base_count_byte_range().end; - start..start + self.base_records_byte_len - } -} - -impl MinByteRange for BaseArrayMarker { +impl<'a> MinByteRange for BaseArray<'a> { fn min_byte_range(&self) -> Range { 0..self.base_records_byte_range().end } @@ -2816,18 +2748,11 @@ impl ReadArgs for BaseArray<'_> { impl<'a> FontReadWithArgs<'a> for BaseArray<'a> { fn read_with_args(data: FontData<'a>, args: &u16) -> Result { - let mark_class_count = *args; - let mut cursor = data.cursor(); - let base_count: u16 = cursor.read()?; - let base_records_byte_len = (base_count as usize) - .checked_mul(::compute_size( - &mark_class_count, - )?) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(base_records_byte_len); - cursor.finish(BaseArrayMarker { - mark_class_count, - base_records_byte_len, + let args = *args; + Ok(TableRef { + args, + data, + _marker: std::marker::PhantomData, }) } } @@ -2844,26 +2769,41 @@ impl<'a> BaseArray<'a> { } /// Part of [MarkBasePosFormat1] -pub type BaseArray<'a> = TableRef<'a, BaseArrayMarker>; +pub type BaseArray<'a> = TableRef<'a, BaseArrayMarker, u16>; #[allow(clippy::needless_lifetimes)] impl<'a> BaseArray<'a> { + fn base_records_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.base_count()) as usize) + .checked_mul(::compute_size(&self.args).unwrap()) + .unwrap() + } + + pub fn base_count_byte_range(&self) -> Range { + let start = 0; + start..start + u16::RAW_BYTE_LEN + } + + pub fn base_records_byte_range(&self) -> Range { + let start = self.base_count_byte_range().end; + start..start + self.base_records_byte_len(start) + } + /// Number of BaseRecords pub fn base_count(&self) -> u16 { - let range = self.shape.base_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.base_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Array of BaseRecords, in order of baseCoverage Index. pub fn base_records(&self) -> ComputedArray<'a, BaseRecord<'a>> { - let range = self.shape.base_records_byte_range(); - self.data - .read_with_args(range, &self.mark_class_count()) - .unwrap() + let range = self.base_records_byte_range(); + unchecked::read_with_args(self.data, range, &self.mark_class_count()) } pub(crate) fn mark_class_count(&self) -> u16 { - self.shape.mark_class_count + self.args } } @@ -2997,9 +2937,29 @@ impl Format for MarkLigPosFormat1Marker { /// [Mark-to-Ligature Positioning Format 1](https://docs.microsoft.com/en-us/typography/opentype/spec/gpos#mark-to-ligature-attachment-positioning-format-1-mark-to-ligature-attachment): Mark-to-Ligature Attachment #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct MarkLigPosFormat1Marker {} +pub struct MarkLigPosFormat1Marker; + +impl<'a> MinByteRange for MarkLigPosFormat1<'a> { + fn min_byte_range(&self) -> Range { + 0..self.ligature_array_offset_byte_range().end + } +} + +impl<'a> FontRead<'a> for MarkLigPosFormat1<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// [Mark-to-Ligature Positioning Format 1](https://docs.microsoft.com/en-us/typography/opentype/spec/gpos#mark-to-ligature-attachment-positioning-format-1-mark-to-ligature-attachment): Mark-to-Ligature Attachment +pub type MarkLigPosFormat1<'a> = TableRef<'a, MarkLigPosFormat1Marker, ()>; -impl MarkLigPosFormat1Marker { +#[allow(clippy::needless_lifetimes)] +impl<'a> MarkLigPosFormat1<'a> { pub fn pos_format_byte_range(&self) -> Range { let start = 0; start..start + u16::RAW_BYTE_LEN @@ -3029,43 +2989,18 @@ impl MarkLigPosFormat1Marker { let start = self.mark_array_offset_byte_range().end; start..start + Offset16::RAW_BYTE_LEN } -} -impl MinByteRange for MarkLigPosFormat1Marker { - fn min_byte_range(&self) -> Range { - 0..self.ligature_array_offset_byte_range().end - } -} - -impl<'a> FontRead<'a> for MarkLigPosFormat1<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.finish(MarkLigPosFormat1Marker {}) - } -} - -/// [Mark-to-Ligature Positioning Format 1](https://docs.microsoft.com/en-us/typography/opentype/spec/gpos#mark-to-ligature-attachment-positioning-format-1-mark-to-ligature-attachment): Mark-to-Ligature Attachment -pub type MarkLigPosFormat1<'a> = TableRef<'a, MarkLigPosFormat1Marker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> MarkLigPosFormat1<'a> { /// Format identifier: format = 1 pub fn pos_format(&self) -> u16 { - let range = self.shape.pos_format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.pos_format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Offset to markCoverage table, from beginning of MarkLigPos /// subtable. pub fn mark_coverage_offset(&self) -> Offset16 { - let range = self.shape.mark_coverage_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.mark_coverage_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`mark_coverage_offset`][Self::mark_coverage_offset]. @@ -3077,8 +3012,8 @@ impl<'a> MarkLigPosFormat1<'a> { /// Offset to ligatureCoverage table, from beginning of MarkLigPos /// subtable. pub fn ligature_coverage_offset(&self) -> Offset16 { - let range = self.shape.ligature_coverage_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.ligature_coverage_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`ligature_coverage_offset`][Self::ligature_coverage_offset]. @@ -3089,15 +3024,15 @@ impl<'a> MarkLigPosFormat1<'a> { /// Number of defined mark classes pub fn mark_class_count(&self) -> u16 { - let range = self.shape.mark_class_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.mark_class_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Offset to MarkArray table, from beginning of MarkLigPos /// subtable. pub fn mark_array_offset(&self) -> Offset16 { - let range = self.shape.mark_array_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.mark_array_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`mark_array_offset`][Self::mark_array_offset]. @@ -3109,8 +3044,8 @@ impl<'a> MarkLigPosFormat1<'a> { /// Offset to LigatureArray table, from beginning of MarkLigPos /// subtable. pub fn ligature_array_offset(&self) -> Offset16 { - let range = self.shape.ligature_array_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.ligature_array_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`ligature_array_offset`][Self::ligature_array_offset]. @@ -3162,24 +3097,9 @@ impl<'a> std::fmt::Debug for MarkLigPosFormat1<'a> { /// Part of [MarkLigPosFormat1] #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct LigatureArrayMarker { - mark_class_count: u16, - ligature_attach_offsets_byte_len: usize, -} - -impl LigatureArrayMarker { - pub fn ligature_count_byte_range(&self) -> Range { - let start = 0; - start..start + u16::RAW_BYTE_LEN - } +pub struct LigatureArrayMarker; - pub fn ligature_attach_offsets_byte_range(&self) -> Range { - let start = self.ligature_count_byte_range().end; - start..start + self.ligature_attach_offsets_byte_len - } -} - -impl MinByteRange for LigatureArrayMarker { +impl<'a> MinByteRange for LigatureArray<'a> { fn min_byte_range(&self) -> Range { 0..self.ligature_attach_offsets_byte_range().end } @@ -3191,16 +3111,11 @@ impl ReadArgs for LigatureArray<'_> { impl<'a> FontReadWithArgs<'a> for LigatureArray<'a> { fn read_with_args(data: FontData<'a>, args: &u16) -> Result { - let mark_class_count = *args; - let mut cursor = data.cursor(); - let ligature_count: u16 = cursor.read()?; - let ligature_attach_offsets_byte_len = (ligature_count as usize) - .checked_mul(Offset16::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(ligature_attach_offsets_byte_len); - cursor.finish(LigatureArrayMarker { - mark_class_count, - ligature_attach_offsets_byte_len, + let args = *args; + Ok(TableRef { + args, + data, + _marker: std::marker::PhantomData, }) } } @@ -3217,22 +3132,39 @@ impl<'a> LigatureArray<'a> { } /// Part of [MarkLigPosFormat1] -pub type LigatureArray<'a> = TableRef<'a, LigatureArrayMarker>; +pub type LigatureArray<'a> = TableRef<'a, LigatureArrayMarker, u16>; #[allow(clippy::needless_lifetimes)] impl<'a> LigatureArray<'a> { + fn ligature_attach_offsets_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.ligature_count()) as usize) + .checked_mul(Offset16::RAW_BYTE_LEN) + .unwrap() + } + + pub fn ligature_count_byte_range(&self) -> Range { + let start = 0; + start..start + u16::RAW_BYTE_LEN + } + + pub fn ligature_attach_offsets_byte_range(&self) -> Range { + let start = self.ligature_count_byte_range().end; + start..start + self.ligature_attach_offsets_byte_len(start) + } + /// Number of LigatureAttach table offsets pub fn ligature_count(&self) -> u16 { - let range = self.shape.ligature_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.ligature_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Array of offsets to LigatureAttach tables. Offsets are from /// beginning of LigatureArray table, ordered by ligatureCoverage /// index. pub fn ligature_attach_offsets(&self) -> &'a [BigEndian] { - let range = self.shape.ligature_attach_offsets_byte_range(); - self.data.read_array(range).unwrap() + let range = self.ligature_attach_offsets_byte_range(); + unchecked::read_array(self.data, range) } /// A dynamically resolving wrapper for [`ligature_attach_offsets`][Self::ligature_attach_offsets]. @@ -3244,7 +3176,7 @@ impl<'a> LigatureArray<'a> { } pub(crate) fn mark_class_count(&self) -> u16 { - self.shape.mark_class_count + self.args } } @@ -3287,24 +3219,9 @@ impl<'a> std::fmt::Debug for LigatureArray<'a> { /// Part of [MarkLigPosFormat1] #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct LigatureAttachMarker { - mark_class_count: u16, - component_records_byte_len: usize, -} - -impl LigatureAttachMarker { - pub fn component_count_byte_range(&self) -> Range { - let start = 0; - start..start + u16::RAW_BYTE_LEN - } +pub struct LigatureAttachMarker; - pub fn component_records_byte_range(&self) -> Range { - let start = self.component_count_byte_range().end; - start..start + self.component_records_byte_len - } -} - -impl MinByteRange for LigatureAttachMarker { +impl<'a> MinByteRange for LigatureAttach<'a> { fn min_byte_range(&self) -> Range { 0..self.component_records_byte_range().end } @@ -3316,18 +3233,11 @@ impl ReadArgs for LigatureAttach<'_> { impl<'a> FontReadWithArgs<'a> for LigatureAttach<'a> { fn read_with_args(data: FontData<'a>, args: &u16) -> Result { - let mark_class_count = *args; - let mut cursor = data.cursor(); - let component_count: u16 = cursor.read()?; - let component_records_byte_len = (component_count as usize) - .checked_mul(::compute_size( - &mark_class_count, - )?) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(component_records_byte_len); - cursor.finish(LigatureAttachMarker { - mark_class_count, - component_records_byte_len, + let args = *args; + Ok(TableRef { + args, + data, + _marker: std::marker::PhantomData, }) } } @@ -3344,26 +3254,41 @@ impl<'a> LigatureAttach<'a> { } /// Part of [MarkLigPosFormat1] -pub type LigatureAttach<'a> = TableRef<'a, LigatureAttachMarker>; +pub type LigatureAttach<'a> = TableRef<'a, LigatureAttachMarker, u16>; #[allow(clippy::needless_lifetimes)] impl<'a> LigatureAttach<'a> { + fn component_records_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.component_count()) as usize) + .checked_mul(::compute_size(&self.args).unwrap()) + .unwrap() + } + + pub fn component_count_byte_range(&self) -> Range { + let start = 0; + start..start + u16::RAW_BYTE_LEN + } + + pub fn component_records_byte_range(&self) -> Range { + let start = self.component_count_byte_range().end; + start..start + self.component_records_byte_len(start) + } + /// Number of ComponentRecords in this ligature pub fn component_count(&self) -> u16 { - let range = self.shape.component_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.component_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Array of Component records, ordered in writing direction. pub fn component_records(&self) -> ComputedArray<'a, ComponentRecord<'a>> { - let range = self.shape.component_records_byte_range(); - self.data - .read_with_args(range, &self.mark_class_count()) - .unwrap() + let range = self.component_records_byte_range(); + unchecked::read_with_args(self.data, range, &self.mark_class_count()) } pub(crate) fn mark_class_count(&self) -> u16 { - self.shape.mark_class_count + self.args } } @@ -3497,9 +3422,29 @@ impl Format for MarkMarkPosFormat1Marker { /// [Mark-to-Mark Attachment Positioning Format 1](https://docs.microsoft.com/en-us/typography/opentype/spec/gpos#mark-to-mark-attachment-positioning-format-1-mark-to-mark-attachment): Mark-to-Mark Attachment #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct MarkMarkPosFormat1Marker {} +pub struct MarkMarkPosFormat1Marker; + +impl<'a> MinByteRange for MarkMarkPosFormat1<'a> { + fn min_byte_range(&self) -> Range { + 0..self.mark2_array_offset_byte_range().end + } +} + +impl<'a> FontRead<'a> for MarkMarkPosFormat1<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} -impl MarkMarkPosFormat1Marker { +/// [Mark-to-Mark Attachment Positioning Format 1](https://docs.microsoft.com/en-us/typography/opentype/spec/gpos#mark-to-mark-attachment-positioning-format-1-mark-to-mark-attachment): Mark-to-Mark Attachment +pub type MarkMarkPosFormat1<'a> = TableRef<'a, MarkMarkPosFormat1Marker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> MarkMarkPosFormat1<'a> { pub fn pos_format_byte_range(&self) -> Range { let start = 0; start..start + u16::RAW_BYTE_LEN @@ -3529,43 +3474,18 @@ impl MarkMarkPosFormat1Marker { let start = self.mark1_array_offset_byte_range().end; start..start + Offset16::RAW_BYTE_LEN } -} - -impl MinByteRange for MarkMarkPosFormat1Marker { - fn min_byte_range(&self) -> Range { - 0..self.mark2_array_offset_byte_range().end - } -} - -impl<'a> FontRead<'a> for MarkMarkPosFormat1<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.finish(MarkMarkPosFormat1Marker {}) - } -} -/// [Mark-to-Mark Attachment Positioning Format 1](https://docs.microsoft.com/en-us/typography/opentype/spec/gpos#mark-to-mark-attachment-positioning-format-1-mark-to-mark-attachment): Mark-to-Mark Attachment -pub type MarkMarkPosFormat1<'a> = TableRef<'a, MarkMarkPosFormat1Marker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> MarkMarkPosFormat1<'a> { /// Format identifier: format = 1 pub fn pos_format(&self) -> u16 { - let range = self.shape.pos_format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.pos_format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Offset to Combining Mark Coverage table, from beginning of /// MarkMarkPos subtable. pub fn mark1_coverage_offset(&self) -> Offset16 { - let range = self.shape.mark1_coverage_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.mark1_coverage_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`mark1_coverage_offset`][Self::mark1_coverage_offset]. @@ -3577,8 +3497,8 @@ impl<'a> MarkMarkPosFormat1<'a> { /// Offset to Base Mark Coverage table, from beginning of /// MarkMarkPos subtable. pub fn mark2_coverage_offset(&self) -> Offset16 { - let range = self.shape.mark2_coverage_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.mark2_coverage_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`mark2_coverage_offset`][Self::mark2_coverage_offset]. @@ -3589,15 +3509,15 @@ impl<'a> MarkMarkPosFormat1<'a> { /// Number of Combining Mark classes defined pub fn mark_class_count(&self) -> u16 { - let range = self.shape.mark_class_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.mark_class_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Offset to MarkArray table for mark1, from beginning of /// MarkMarkPos subtable. pub fn mark1_array_offset(&self) -> Offset16 { - let range = self.shape.mark1_array_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.mark1_array_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`mark1_array_offset`][Self::mark1_array_offset]. @@ -3609,8 +3529,8 @@ impl<'a> MarkMarkPosFormat1<'a> { /// Offset to Mark2Array table for mark2, from beginning of /// MarkMarkPos subtable. pub fn mark2_array_offset(&self) -> Offset16 { - let range = self.shape.mark2_array_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.mark2_array_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`mark2_array_offset`][Self::mark2_array_offset]. @@ -3662,24 +3582,9 @@ impl<'a> std::fmt::Debug for MarkMarkPosFormat1<'a> { /// Part of [MarkMarkPosFormat1]Class2Record #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct Mark2ArrayMarker { - mark_class_count: u16, - mark2_records_byte_len: usize, -} +pub struct Mark2ArrayMarker; -impl Mark2ArrayMarker { - pub fn mark2_count_byte_range(&self) -> Range { - let start = 0; - start..start + u16::RAW_BYTE_LEN - } - - pub fn mark2_records_byte_range(&self) -> Range { - let start = self.mark2_count_byte_range().end; - start..start + self.mark2_records_byte_len - } -} - -impl MinByteRange for Mark2ArrayMarker { +impl<'a> MinByteRange for Mark2Array<'a> { fn min_byte_range(&self) -> Range { 0..self.mark2_records_byte_range().end } @@ -3691,18 +3596,11 @@ impl ReadArgs for Mark2Array<'_> { impl<'a> FontReadWithArgs<'a> for Mark2Array<'a> { fn read_with_args(data: FontData<'a>, args: &u16) -> Result { - let mark_class_count = *args; - let mut cursor = data.cursor(); - let mark2_count: u16 = cursor.read()?; - let mark2_records_byte_len = (mark2_count as usize) - .checked_mul(::compute_size( - &mark_class_count, - )?) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(mark2_records_byte_len); - cursor.finish(Mark2ArrayMarker { - mark_class_count, - mark2_records_byte_len, + let args = *args; + Ok(TableRef { + args, + data, + _marker: std::marker::PhantomData, }) } } @@ -3719,26 +3617,41 @@ impl<'a> Mark2Array<'a> { } /// Part of [MarkMarkPosFormat1]Class2Record -pub type Mark2Array<'a> = TableRef<'a, Mark2ArrayMarker>; +pub type Mark2Array<'a> = TableRef<'a, Mark2ArrayMarker, u16>; #[allow(clippy::needless_lifetimes)] impl<'a> Mark2Array<'a> { + fn mark2_records_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.mark2_count()) as usize) + .checked_mul(::compute_size(&self.args).unwrap()) + .unwrap() + } + + pub fn mark2_count_byte_range(&self) -> Range { + let start = 0; + start..start + u16::RAW_BYTE_LEN + } + + pub fn mark2_records_byte_range(&self) -> Range { + let start = self.mark2_count_byte_range().end; + start..start + self.mark2_records_byte_len(start) + } + /// Number of Mark2 records pub fn mark2_count(&self) -> u16 { - let range = self.shape.mark2_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.mark2_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Array of Mark2Records, in Coverage order. pub fn mark2_records(&self) -> ComputedArray<'a, Mark2Record<'a>> { - let range = self.shape.mark2_records_byte_range(); - self.data - .read_with_args(range, &self.mark_class_count()) - .unwrap() + let range = self.mark2_records_byte_range(); + unchecked::read_with_args(self.data, range, &self.mark_class_count()) } pub(crate) fn mark_class_count(&self) -> u16 { - self.shape.mark_class_count + self.args } } @@ -3870,51 +3783,22 @@ impl Format for ExtensionPosFormat1Marker { } /// [Extension Positioning Subtable Format 1](https://docs.microsoft.com/en-us/typography/opentype/spec/gpos#extension-positioning-subtable-format-1) -#[derive(Debug)] +#[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct ExtensionPosFormat1Marker { - offset_type: std::marker::PhantomData<*const T>, -} - -impl ExtensionPosFormat1Marker { - pub fn pos_format_byte_range(&self) -> Range { - let start = 0; - start..start + u16::RAW_BYTE_LEN - } - - pub fn extension_lookup_type_byte_range(&self) -> Range { - let start = self.pos_format_byte_range().end; - start..start + u16::RAW_BYTE_LEN - } - - pub fn extension_offset_byte_range(&self) -> Range { - let start = self.extension_lookup_type_byte_range().end; - start..start + Offset32::RAW_BYTE_LEN - } -} +pub struct ExtensionPosFormat1Marker; -impl MinByteRange for ExtensionPosFormat1Marker { +impl<'a, T> MinByteRange for ExtensionPosFormat1<'a, T> { fn min_byte_range(&self) -> Range { 0..self.extension_offset_byte_range().end } } -impl Clone for ExtensionPosFormat1Marker { - fn clone(&self) -> Self { - *self - } -} - -impl Copy for ExtensionPosFormat1Marker {} - impl<'a, T> FontRead<'a> for ExtensionPosFormat1<'a, T> { fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.finish(ExtensionPosFormat1Marker { - offset_type: std::marker::PhantomData, + Ok(TableRef { + args: std::marker::PhantomData, + data, + _marker: std::marker::PhantomData, }) } } @@ -3924,10 +3808,9 @@ impl<'a> ExtensionPosFormat1<'a, ()> { pub(crate) fn into_concrete(self) -> ExtensionPosFormat1<'a, T> { let TableRef { data, .. } = self; TableRef { - shape: ExtensionPosFormat1Marker { - offset_type: std::marker::PhantomData, - }, + args: std::marker::PhantomData, data, + _marker: std::marker::PhantomData, } } } @@ -3938,38 +3821,53 @@ impl<'a, T> ExtensionPosFormat1<'a, T> { pub(crate) fn of_unit_type(&self) -> ExtensionPosFormat1<'a, ()> { let TableRef { data, .. } = self; TableRef { - shape: ExtensionPosFormat1Marker { - offset_type: std::marker::PhantomData, - }, + args: std::marker::PhantomData, data: *data, + _marker: std::marker::PhantomData, } } } /// [Extension Positioning Subtable Format 1](https://docs.microsoft.com/en-us/typography/opentype/spec/gpos#extension-positioning-subtable-format-1) -pub type ExtensionPosFormat1<'a, T> = TableRef<'a, ExtensionPosFormat1Marker>; +pub type ExtensionPosFormat1<'a, T = ()> = + TableRef<'a, ExtensionPosFormat1Marker, std::marker::PhantomData<*const T>>; #[allow(clippy::needless_lifetimes)] impl<'a, T> ExtensionPosFormat1<'a, T> { + pub fn pos_format_byte_range(&self) -> Range { + let start = 0; + start..start + u16::RAW_BYTE_LEN + } + + pub fn extension_lookup_type_byte_range(&self) -> Range { + let start = self.pos_format_byte_range().end; + start..start + u16::RAW_BYTE_LEN + } + + pub fn extension_offset_byte_range(&self) -> Range { + let start = self.extension_lookup_type_byte_range().end; + start..start + Offset32::RAW_BYTE_LEN + } + /// Format identifier: format = 1 pub fn pos_format(&self) -> u16 { - let range = self.shape.pos_format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.pos_format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Lookup type of subtable referenced by extensionOffset (i.e. the /// extension subtable). pub fn extension_lookup_type(&self) -> u16 { - let range = self.shape.extension_lookup_type_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.extension_lookup_type_byte_range(); + unchecked::read_at(self.data, range.start) } /// Offset to the extension subtable, of lookup type /// extensionLookupType, relative to the start of the /// ExtensionPosFormat1 subtable. pub fn extension_offset(&self) -> Offset32 { - let range = self.shape.extension_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.extension_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`extension_offset`][Self::extension_offset]. diff --git a/read-fonts/generated/generated_gsub.rs b/read-fonts/generated/generated_gsub.rs index a6d0eafa0..27aa2599d 100644 --- a/read-fonts/generated/generated_gsub.rs +++ b/read-fonts/generated/generated_gsub.rs @@ -8,11 +8,34 @@ use crate::codegen_prelude::*; /// [GSUB](https://learn.microsoft.com/en-us/typography/opentype/spec/gsub#gsub-header) #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct GsubMarker { - feature_variations_offset_byte_start: Option, +pub struct GsubMarker; + +impl<'a> MinByteRange for Gsub<'a> { + fn min_byte_range(&self) -> Range { + 0..self.lookup_list_offset_byte_range().end + } +} + +impl TopLevelTable for Gsub<'_> { + /// `GSUB` + const TAG: Tag = Tag::new(b"GSUB"); +} + +impl<'a> FontRead<'a> for Gsub<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } } -impl GsubMarker { +/// [GSUB](https://learn.microsoft.com/en-us/typography/opentype/spec/gsub#gsub-header) +pub type Gsub<'a> = TableRef<'a, GsubMarker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> Gsub<'a> { pub fn version_byte_range(&self) -> Range { let start = 0; start..start + MajorMinor::RAW_BYTE_LEN @@ -34,57 +57,24 @@ impl GsubMarker { } pub fn feature_variations_offset_byte_range(&self) -> Option> { - let start = self.feature_variations_offset_byte_start?; - Some(start..start + Offset32::RAW_BYTE_LEN) - } -} - -impl MinByteRange for GsubMarker { - fn min_byte_range(&self) -> Range { - 0..self.lookup_list_offset_byte_range().end - } -} - -impl TopLevelTable for Gsub<'_> { - /// `GSUB` - const TAG: Tag = Tag::new(b"GSUB"); -} - -impl<'a> FontRead<'a> for Gsub<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - let version: MajorMinor = cursor.read()?; - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - let feature_variations_offset_byte_start = version - .compatible((1u16, 1u16)) - .then(|| cursor.position()) - .transpose()?; - version - .compatible((1u16, 1u16)) - .then(|| cursor.advance::()); - cursor.finish(GsubMarker { - feature_variations_offset_byte_start, - }) + if self.version().compatible((1u16, 1u16)) { + let start = self.lookup_list_offset_byte_range().end; + Some(start..start + Offset32::RAW_BYTE_LEN) + } else { + None + } } -} -/// [GSUB](https://learn.microsoft.com/en-us/typography/opentype/spec/gsub#gsub-header) -pub type Gsub<'a> = TableRef<'a, GsubMarker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> Gsub<'a> { /// The major and minor version of the GSUB table, as a tuple (u16, u16) pub fn version(&self) -> MajorMinor { - let range = self.shape.version_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.version_byte_range(); + unchecked::read_at(self.data, range.start) } /// Offset to ScriptList table, from beginning of GSUB table pub fn script_list_offset(&self) -> Offset16 { - let range = self.shape.script_list_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.script_list_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`script_list_offset`][Self::script_list_offset]. @@ -95,8 +85,8 @@ impl<'a> Gsub<'a> { /// Offset to FeatureList table, from beginning of GSUB table pub fn feature_list_offset(&self) -> Offset16 { - let range = self.shape.feature_list_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.feature_list_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`feature_list_offset`][Self::feature_list_offset]. @@ -107,8 +97,8 @@ impl<'a> Gsub<'a> { /// Offset to LookupList table, from beginning of GSUB table pub fn lookup_list_offset(&self) -> Offset16 { - let range = self.shape.lookup_list_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.lookup_list_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`lookup_list_offset`][Self::lookup_list_offset]. @@ -120,8 +110,8 @@ impl<'a> Gsub<'a> { /// Offset to FeatureVariations table, from beginning of the GSUB /// table (may be NULL) pub fn feature_variations_offset(&self) -> Option> { - let range = self.shape.feature_variations_offset_byte_range()?; - Some(self.data.read_at(range.start).unwrap()) + let range = self.feature_variations_offset_byte_range()?; + Some(unchecked::read_at(self.data, range.start)) } /// Attempt to resolve [`feature_variations_offset`][Self::feature_variations_offset]. @@ -341,9 +331,29 @@ impl Format for SingleSubstFormat1Marker { /// [Single Substitution Format 1](https://learn.microsoft.com/en-us/typography/opentype/spec/gsub#11-single-substitution-format-1) #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct SingleSubstFormat1Marker {} +pub struct SingleSubstFormat1Marker; + +impl<'a> MinByteRange for SingleSubstFormat1<'a> { + fn min_byte_range(&self) -> Range { + 0..self.delta_glyph_id_byte_range().end + } +} -impl SingleSubstFormat1Marker { +impl<'a> FontRead<'a> for SingleSubstFormat1<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// [Single Substitution Format 1](https://learn.microsoft.com/en-us/typography/opentype/spec/gsub#11-single-substitution-format-1) +pub type SingleSubstFormat1<'a> = TableRef<'a, SingleSubstFormat1Marker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> SingleSubstFormat1<'a> { pub fn subst_format_byte_range(&self) -> Range { let start = 0; start..start + u16::RAW_BYTE_LEN @@ -358,40 +368,18 @@ impl SingleSubstFormat1Marker { let start = self.coverage_offset_byte_range().end; start..start + i16::RAW_BYTE_LEN } -} - -impl MinByteRange for SingleSubstFormat1Marker { - fn min_byte_range(&self) -> Range { - 0..self.delta_glyph_id_byte_range().end - } -} -impl<'a> FontRead<'a> for SingleSubstFormat1<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.finish(SingleSubstFormat1Marker {}) - } -} - -/// [Single Substitution Format 1](https://learn.microsoft.com/en-us/typography/opentype/spec/gsub#11-single-substitution-format-1) -pub type SingleSubstFormat1<'a> = TableRef<'a, SingleSubstFormat1Marker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> SingleSubstFormat1<'a> { /// Format identifier: format = 1 pub fn subst_format(&self) -> u16 { - let range = self.shape.subst_format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.subst_format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Offset to Coverage table, from beginning of substitution /// subtable pub fn coverage_offset(&self) -> Offset16 { - let range = self.shape.coverage_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.coverage_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`coverage_offset`][Self::coverage_offset]. @@ -402,8 +390,8 @@ impl<'a> SingleSubstFormat1<'a> { /// Add to original glyph ID to get substitute glyph ID pub fn delta_glyph_id(&self) -> i16 { - let range = self.shape.delta_glyph_id_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.delta_glyph_id_byte_range(); + unchecked::read_at(self.data, range.start) } } @@ -440,11 +428,36 @@ impl Format for SingleSubstFormat2Marker { /// [Single Substitution Format 2](https://learn.microsoft.com/en-us/typography/opentype/spec/gsub#12-single-substitution-format-2) #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct SingleSubstFormat2Marker { - substitute_glyph_ids_byte_len: usize, +pub struct SingleSubstFormat2Marker; + +impl<'a> MinByteRange for SingleSubstFormat2<'a> { + fn min_byte_range(&self) -> Range { + 0..self.substitute_glyph_ids_byte_range().end + } } -impl SingleSubstFormat2Marker { +impl<'a> FontRead<'a> for SingleSubstFormat2<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// [Single Substitution Format 2](https://learn.microsoft.com/en-us/typography/opentype/spec/gsub#12-single-substitution-format-2) +pub type SingleSubstFormat2<'a> = TableRef<'a, SingleSubstFormat2Marker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> SingleSubstFormat2<'a> { + fn substitute_glyph_ids_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.glyph_count()) as usize) + .checked_mul(GlyphId16::RAW_BYTE_LEN) + .unwrap() + } + pub fn subst_format_byte_range(&self) -> Range { let start = 0; start..start + u16::RAW_BYTE_LEN @@ -462,48 +475,20 @@ impl SingleSubstFormat2Marker { pub fn substitute_glyph_ids_byte_range(&self) -> Range { let start = self.glyph_count_byte_range().end; - start..start + self.substitute_glyph_ids_byte_len - } -} - -impl MinByteRange for SingleSubstFormat2Marker { - fn min_byte_range(&self) -> Range { - 0..self.substitute_glyph_ids_byte_range().end + start..start + self.substitute_glyph_ids_byte_len(start) } -} -impl<'a> FontRead<'a> for SingleSubstFormat2<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - let glyph_count: u16 = cursor.read()?; - let substitute_glyph_ids_byte_len = (glyph_count as usize) - .checked_mul(GlyphId16::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(substitute_glyph_ids_byte_len); - cursor.finish(SingleSubstFormat2Marker { - substitute_glyph_ids_byte_len, - }) - } -} - -/// [Single Substitution Format 2](https://learn.microsoft.com/en-us/typography/opentype/spec/gsub#12-single-substitution-format-2) -pub type SingleSubstFormat2<'a> = TableRef<'a, SingleSubstFormat2Marker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> SingleSubstFormat2<'a> { /// Format identifier: format = 2 pub fn subst_format(&self) -> u16 { - let range = self.shape.subst_format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.subst_format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Offset to Coverage table, from beginning of substitution /// subtable pub fn coverage_offset(&self) -> Offset16 { - let range = self.shape.coverage_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.coverage_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`coverage_offset`][Self::coverage_offset]. @@ -514,14 +499,14 @@ impl<'a> SingleSubstFormat2<'a> { /// Number of glyph IDs in the substituteGlyphIDs array pub fn glyph_count(&self) -> u16 { - let range = self.shape.glyph_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.glyph_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Array of substitute glyph IDs — ordered by Coverage index pub fn substitute_glyph_ids(&self) -> &'a [BigEndian] { - let range = self.shape.substitute_glyph_ids_byte_range(); - self.data.read_array(range).unwrap() + let range = self.substitute_glyph_ids_byte_range(); + unchecked::read_array(self.data, range) } } @@ -562,11 +547,36 @@ impl Format for MultipleSubstFormat1Marker { /// [Multiple Substitution Format 1](https://learn.microsoft.com/en-us/typography/opentype/spec/gsub#21-multiple-substitution-format-1) #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct MultipleSubstFormat1Marker { - sequence_offsets_byte_len: usize, +pub struct MultipleSubstFormat1Marker; + +impl<'a> MinByteRange for MultipleSubstFormat1<'a> { + fn min_byte_range(&self) -> Range { + 0..self.sequence_offsets_byte_range().end + } } -impl MultipleSubstFormat1Marker { +impl<'a> FontRead<'a> for MultipleSubstFormat1<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// [Multiple Substitution Format 1](https://learn.microsoft.com/en-us/typography/opentype/spec/gsub#21-multiple-substitution-format-1) +pub type MultipleSubstFormat1<'a> = TableRef<'a, MultipleSubstFormat1Marker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> MultipleSubstFormat1<'a> { + fn sequence_offsets_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.sequence_count()) as usize) + .checked_mul(Offset16::RAW_BYTE_LEN) + .unwrap() + } + pub fn subst_format_byte_range(&self) -> Range { let start = 0; start..start + u16::RAW_BYTE_LEN @@ -584,48 +594,20 @@ impl MultipleSubstFormat1Marker { pub fn sequence_offsets_byte_range(&self) -> Range { let start = self.sequence_count_byte_range().end; - start..start + self.sequence_offsets_byte_len + start..start + self.sequence_offsets_byte_len(start) } -} - -impl MinByteRange for MultipleSubstFormat1Marker { - fn min_byte_range(&self) -> Range { - 0..self.sequence_offsets_byte_range().end - } -} - -impl<'a> FontRead<'a> for MultipleSubstFormat1<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - let sequence_count: u16 = cursor.read()?; - let sequence_offsets_byte_len = (sequence_count as usize) - .checked_mul(Offset16::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(sequence_offsets_byte_len); - cursor.finish(MultipleSubstFormat1Marker { - sequence_offsets_byte_len, - }) - } -} -/// [Multiple Substitution Format 1](https://learn.microsoft.com/en-us/typography/opentype/spec/gsub#21-multiple-substitution-format-1) -pub type MultipleSubstFormat1<'a> = TableRef<'a, MultipleSubstFormat1Marker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> MultipleSubstFormat1<'a> { /// Format identifier: format = 1 pub fn subst_format(&self) -> u16 { - let range = self.shape.subst_format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.subst_format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Offset to Coverage table, from beginning of substitution /// subtable pub fn coverage_offset(&self) -> Offset16 { - let range = self.shape.coverage_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.coverage_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`coverage_offset`][Self::coverage_offset]. @@ -636,15 +618,15 @@ impl<'a> MultipleSubstFormat1<'a> { /// Number of Sequence table offsets in the sequenceOffsets array pub fn sequence_count(&self) -> u16 { - let range = self.shape.sequence_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.sequence_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Array of offsets to Sequence tables. Offsets are from beginning /// of substitution subtable, ordered by Coverage index pub fn sequence_offsets(&self) -> &'a [BigEndian] { - let range = self.shape.sequence_offsets_byte_range(); - self.data.read_array(range).unwrap() + let range = self.sequence_offsets_byte_range(); + unchecked::read_array(self.data, range) } /// A dynamically resolving wrapper for [`sequence_offsets`][Self::sequence_offsets]. @@ -698,23 +680,9 @@ impl<'a> std::fmt::Debug for MultipleSubstFormat1<'a> { /// Part of [MultipleSubstFormat1] #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct SequenceMarker { - substitute_glyph_ids_byte_len: usize, -} - -impl SequenceMarker { - pub fn glyph_count_byte_range(&self) -> Range { - let start = 0; - start..start + u16::RAW_BYTE_LEN - } - - pub fn substitute_glyph_ids_byte_range(&self) -> Range { - let start = self.glyph_count_byte_range().end; - start..start + self.substitute_glyph_ids_byte_len - } -} +pub struct SequenceMarker; -impl MinByteRange for SequenceMarker { +impl<'a> MinByteRange for Sequence<'a> { fn min_byte_range(&self) -> Range { 0..self.substitute_glyph_ids_byte_range().end } @@ -722,34 +690,47 @@ impl MinByteRange for SequenceMarker { impl<'a> FontRead<'a> for Sequence<'a> { fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - let glyph_count: u16 = cursor.read()?; - let substitute_glyph_ids_byte_len = (glyph_count as usize) - .checked_mul(GlyphId16::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(substitute_glyph_ids_byte_len); - cursor.finish(SequenceMarker { - substitute_glyph_ids_byte_len, + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, }) } } /// Part of [MultipleSubstFormat1] -pub type Sequence<'a> = TableRef<'a, SequenceMarker>; +pub type Sequence<'a> = TableRef<'a, SequenceMarker, ()>; #[allow(clippy::needless_lifetimes)] impl<'a> Sequence<'a> { + fn substitute_glyph_ids_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.glyph_count()) as usize) + .checked_mul(GlyphId16::RAW_BYTE_LEN) + .unwrap() + } + + pub fn glyph_count_byte_range(&self) -> Range { + let start = 0; + start..start + u16::RAW_BYTE_LEN + } + + pub fn substitute_glyph_ids_byte_range(&self) -> Range { + let start = self.glyph_count_byte_range().end; + start..start + self.substitute_glyph_ids_byte_len(start) + } + /// Number of glyph IDs in the substituteGlyphIDs array. This must /// always be greater than 0. pub fn glyph_count(&self) -> u16 { - let range = self.shape.glyph_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.glyph_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// String of glyph IDs to substitute pub fn substitute_glyph_ids(&self) -> &'a [BigEndian] { - let range = self.shape.substitute_glyph_ids_byte_range(); - self.data.read_array(range).unwrap() + let range = self.substitute_glyph_ids_byte_range(); + unchecked::read_array(self.data, range) } } @@ -785,11 +766,36 @@ impl Format for AlternateSubstFormat1Marker { /// [Alternate Substitution Format 1](https://learn.microsoft.com/en-us/typography/opentype/spec/gsub#31-alternate-substitution-format-1) #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct AlternateSubstFormat1Marker { - alternate_set_offsets_byte_len: usize, +pub struct AlternateSubstFormat1Marker; + +impl<'a> MinByteRange for AlternateSubstFormat1<'a> { + fn min_byte_range(&self) -> Range { + 0..self.alternate_set_offsets_byte_range().end + } +} + +impl<'a> FontRead<'a> for AlternateSubstFormat1<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } } -impl AlternateSubstFormat1Marker { +/// [Alternate Substitution Format 1](https://learn.microsoft.com/en-us/typography/opentype/spec/gsub#31-alternate-substitution-format-1) +pub type AlternateSubstFormat1<'a> = TableRef<'a, AlternateSubstFormat1Marker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> AlternateSubstFormat1<'a> { + fn alternate_set_offsets_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.alternate_set_count()) as usize) + .checked_mul(Offset16::RAW_BYTE_LEN) + .unwrap() + } + pub fn subst_format_byte_range(&self) -> Range { let start = 0; start..start + u16::RAW_BYTE_LEN @@ -807,48 +813,20 @@ impl AlternateSubstFormat1Marker { pub fn alternate_set_offsets_byte_range(&self) -> Range { let start = self.alternate_set_count_byte_range().end; - start..start + self.alternate_set_offsets_byte_len + start..start + self.alternate_set_offsets_byte_len(start) } -} - -impl MinByteRange for AlternateSubstFormat1Marker { - fn min_byte_range(&self) -> Range { - 0..self.alternate_set_offsets_byte_range().end - } -} - -impl<'a> FontRead<'a> for AlternateSubstFormat1<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - let alternate_set_count: u16 = cursor.read()?; - let alternate_set_offsets_byte_len = (alternate_set_count as usize) - .checked_mul(Offset16::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(alternate_set_offsets_byte_len); - cursor.finish(AlternateSubstFormat1Marker { - alternate_set_offsets_byte_len, - }) - } -} - -/// [Alternate Substitution Format 1](https://learn.microsoft.com/en-us/typography/opentype/spec/gsub#31-alternate-substitution-format-1) -pub type AlternateSubstFormat1<'a> = TableRef<'a, AlternateSubstFormat1Marker>; -#[allow(clippy::needless_lifetimes)] -impl<'a> AlternateSubstFormat1<'a> { /// Format identifier: format = 1 pub fn subst_format(&self) -> u16 { - let range = self.shape.subst_format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.subst_format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Offset to Coverage table, from beginning of substitution /// subtable pub fn coverage_offset(&self) -> Offset16 { - let range = self.shape.coverage_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.coverage_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`coverage_offset`][Self::coverage_offset]. @@ -859,15 +837,15 @@ impl<'a> AlternateSubstFormat1<'a> { /// Number of AlternateSet tables pub fn alternate_set_count(&self) -> u16 { - let range = self.shape.alternate_set_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.alternate_set_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Array of offsets to AlternateSet tables. Offsets are from /// beginning of substitution subtable, ordered by Coverage index pub fn alternate_set_offsets(&self) -> &'a [BigEndian] { - let range = self.shape.alternate_set_offsets_byte_range(); - self.data.read_array(range).unwrap() + let range = self.alternate_set_offsets_byte_range(); + unchecked::read_array(self.data, range) } /// A dynamically resolving wrapper for [`alternate_set_offsets`][Self::alternate_set_offsets]. @@ -924,23 +902,9 @@ impl<'a> std::fmt::Debug for AlternateSubstFormat1<'a> { /// Part of [AlternateSubstFormat1] #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct AlternateSetMarker { - alternate_glyph_ids_byte_len: usize, -} - -impl AlternateSetMarker { - pub fn glyph_count_byte_range(&self) -> Range { - let start = 0; - start..start + u16::RAW_BYTE_LEN - } - - pub fn alternate_glyph_ids_byte_range(&self) -> Range { - let start = self.glyph_count_byte_range().end; - start..start + self.alternate_glyph_ids_byte_len - } -} +pub struct AlternateSetMarker; -impl MinByteRange for AlternateSetMarker { +impl<'a> MinByteRange for AlternateSet<'a> { fn min_byte_range(&self) -> Range { 0..self.alternate_glyph_ids_byte_range().end } @@ -948,33 +912,46 @@ impl MinByteRange for AlternateSetMarker { impl<'a> FontRead<'a> for AlternateSet<'a> { fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - let glyph_count: u16 = cursor.read()?; - let alternate_glyph_ids_byte_len = (glyph_count as usize) - .checked_mul(GlyphId16::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(alternate_glyph_ids_byte_len); - cursor.finish(AlternateSetMarker { - alternate_glyph_ids_byte_len, + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, }) } } /// Part of [AlternateSubstFormat1] -pub type AlternateSet<'a> = TableRef<'a, AlternateSetMarker>; +pub type AlternateSet<'a> = TableRef<'a, AlternateSetMarker, ()>; #[allow(clippy::needless_lifetimes)] impl<'a> AlternateSet<'a> { + fn alternate_glyph_ids_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.glyph_count()) as usize) + .checked_mul(GlyphId16::RAW_BYTE_LEN) + .unwrap() + } + + pub fn glyph_count_byte_range(&self) -> Range { + let start = 0; + start..start + u16::RAW_BYTE_LEN + } + + pub fn alternate_glyph_ids_byte_range(&self) -> Range { + let start = self.glyph_count_byte_range().end; + start..start + self.alternate_glyph_ids_byte_len(start) + } + /// Number of glyph IDs in the alternateGlyphIDs array pub fn glyph_count(&self) -> u16 { - let range = self.shape.glyph_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.glyph_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Array of alternate glyph IDs, in arbitrary order pub fn alternate_glyph_ids(&self) -> &'a [BigEndian] { - let range = self.shape.alternate_glyph_ids_byte_range(); - self.data.read_array(range).unwrap() + let range = self.alternate_glyph_ids_byte_range(); + unchecked::read_array(self.data, range) } } @@ -1010,11 +987,36 @@ impl Format for LigatureSubstFormat1Marker { /// [Ligature Substitution Format 1](https://learn.microsoft.com/en-us/typography/opentype/spec/gsub#41-ligature-substitution-format-1) #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct LigatureSubstFormat1Marker { - ligature_set_offsets_byte_len: usize, +pub struct LigatureSubstFormat1Marker; + +impl<'a> MinByteRange for LigatureSubstFormat1<'a> { + fn min_byte_range(&self) -> Range { + 0..self.ligature_set_offsets_byte_range().end + } } -impl LigatureSubstFormat1Marker { +impl<'a> FontRead<'a> for LigatureSubstFormat1<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// [Ligature Substitution Format 1](https://learn.microsoft.com/en-us/typography/opentype/spec/gsub#41-ligature-substitution-format-1) +pub type LigatureSubstFormat1<'a> = TableRef<'a, LigatureSubstFormat1Marker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> LigatureSubstFormat1<'a> { + fn ligature_set_offsets_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.ligature_set_count()) as usize) + .checked_mul(Offset16::RAW_BYTE_LEN) + .unwrap() + } + pub fn subst_format_byte_range(&self) -> Range { let start = 0; start..start + u16::RAW_BYTE_LEN @@ -1032,48 +1034,20 @@ impl LigatureSubstFormat1Marker { pub fn ligature_set_offsets_byte_range(&self) -> Range { let start = self.ligature_set_count_byte_range().end; - start..start + self.ligature_set_offsets_byte_len + start..start + self.ligature_set_offsets_byte_len(start) } -} - -impl MinByteRange for LigatureSubstFormat1Marker { - fn min_byte_range(&self) -> Range { - 0..self.ligature_set_offsets_byte_range().end - } -} -impl<'a> FontRead<'a> for LigatureSubstFormat1<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - let ligature_set_count: u16 = cursor.read()?; - let ligature_set_offsets_byte_len = (ligature_set_count as usize) - .checked_mul(Offset16::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(ligature_set_offsets_byte_len); - cursor.finish(LigatureSubstFormat1Marker { - ligature_set_offsets_byte_len, - }) - } -} - -/// [Ligature Substitution Format 1](https://learn.microsoft.com/en-us/typography/opentype/spec/gsub#41-ligature-substitution-format-1) -pub type LigatureSubstFormat1<'a> = TableRef<'a, LigatureSubstFormat1Marker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> LigatureSubstFormat1<'a> { /// Format identifier: format = 1 pub fn subst_format(&self) -> u16 { - let range = self.shape.subst_format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.subst_format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Offset to Coverage table, from beginning of substitution /// subtable pub fn coverage_offset(&self) -> Offset16 { - let range = self.shape.coverage_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.coverage_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`coverage_offset`][Self::coverage_offset]. @@ -1084,15 +1058,15 @@ impl<'a> LigatureSubstFormat1<'a> { /// Number of LigatureSet tables pub fn ligature_set_count(&self) -> u16 { - let range = self.shape.ligature_set_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.ligature_set_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Array of offsets to LigatureSet tables. Offsets are from /// beginning of substitution subtable, ordered by Coverage index pub fn ligature_set_offsets(&self) -> &'a [BigEndian] { - let range = self.shape.ligature_set_offsets_byte_range(); - self.data.read_array(range).unwrap() + let range = self.ligature_set_offsets_byte_range(); + unchecked::read_array(self.data, range) } /// A dynamically resolving wrapper for [`ligature_set_offsets`][Self::ligature_set_offsets]. @@ -1146,23 +1120,9 @@ impl<'a> std::fmt::Debug for LigatureSubstFormat1<'a> { /// Part of [LigatureSubstFormat1] #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct LigatureSetMarker { - ligature_offsets_byte_len: usize, -} +pub struct LigatureSetMarker; -impl LigatureSetMarker { - pub fn ligature_count_byte_range(&self) -> Range { - let start = 0; - start..start + u16::RAW_BYTE_LEN - } - - pub fn ligature_offsets_byte_range(&self) -> Range { - let start = self.ligature_count_byte_range().end; - start..start + self.ligature_offsets_byte_len - } -} - -impl MinByteRange for LigatureSetMarker { +impl<'a> MinByteRange for LigatureSet<'a> { fn min_byte_range(&self) -> Range { 0..self.ligature_offsets_byte_range().end } @@ -1170,34 +1130,47 @@ impl MinByteRange for LigatureSetMarker { impl<'a> FontRead<'a> for LigatureSet<'a> { fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - let ligature_count: u16 = cursor.read()?; - let ligature_offsets_byte_len = (ligature_count as usize) - .checked_mul(Offset16::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(ligature_offsets_byte_len); - cursor.finish(LigatureSetMarker { - ligature_offsets_byte_len, + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, }) } } /// Part of [LigatureSubstFormat1] -pub type LigatureSet<'a> = TableRef<'a, LigatureSetMarker>; +pub type LigatureSet<'a> = TableRef<'a, LigatureSetMarker, ()>; #[allow(clippy::needless_lifetimes)] impl<'a> LigatureSet<'a> { + fn ligature_offsets_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.ligature_count()) as usize) + .checked_mul(Offset16::RAW_BYTE_LEN) + .unwrap() + } + + pub fn ligature_count_byte_range(&self) -> Range { + let start = 0; + start..start + u16::RAW_BYTE_LEN + } + + pub fn ligature_offsets_byte_range(&self) -> Range { + let start = self.ligature_count_byte_range().end; + start..start + self.ligature_offsets_byte_len(start) + } + /// Number of Ligature tables pub fn ligature_count(&self) -> u16 { - let range = self.shape.ligature_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.ligature_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Array of offsets to Ligature tables. Offsets are from beginning /// of LigatureSet table, ordered by preference. pub fn ligature_offsets(&self) -> &'a [BigEndian] { - let range = self.shape.ligature_offsets_byte_range(); - self.data.read_array(range).unwrap() + let range = self.ligature_offsets_byte_range(); + unchecked::read_array(self.data, range) } /// A dynamically resolving wrapper for [`ligature_offsets`][Self::ligature_offsets]. @@ -1246,28 +1219,9 @@ impl<'a> std::fmt::Debug for LigatureSet<'a> { /// Part of [LigatureSubstFormat1] #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct LigatureMarker { - component_glyph_ids_byte_len: usize, -} +pub struct LigatureMarker; -impl LigatureMarker { - pub fn ligature_glyph_byte_range(&self) -> Range { - let start = 0; - start..start + GlyphId16::RAW_BYTE_LEN - } - - pub fn component_count_byte_range(&self) -> Range { - let start = self.ligature_glyph_byte_range().end; - start..start + u16::RAW_BYTE_LEN - } - - pub fn component_glyph_ids_byte_range(&self) -> Range { - let start = self.component_count_byte_range().end; - start..start + self.component_glyph_ids_byte_len - } -} - -impl MinByteRange for LigatureMarker { +impl<'a> MinByteRange for Ligature<'a> { fn min_byte_range(&self) -> Range { 0..self.component_glyph_ids_byte_range().end } @@ -1275,41 +1229,58 @@ impl MinByteRange for LigatureMarker { impl<'a> FontRead<'a> for Ligature<'a> { fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - let component_count: u16 = cursor.read()?; - let component_glyph_ids_byte_len = (transforms::subtract(component_count, 1_usize)) - .checked_mul(GlyphId16::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(component_glyph_ids_byte_len); - cursor.finish(LigatureMarker { - component_glyph_ids_byte_len, + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, }) } } /// Part of [LigatureSubstFormat1] -pub type Ligature<'a> = TableRef<'a, LigatureMarker>; +pub type Ligature<'a> = TableRef<'a, LigatureMarker, ()>; #[allow(clippy::needless_lifetimes)] impl<'a> Ligature<'a> { + fn component_glyph_ids_byte_len(&self, start: usize) -> usize { + let _ = start; + (transforms::subtract(self.component_count(), 1_usize)) + .checked_mul(GlyphId16::RAW_BYTE_LEN) + .unwrap() + } + + pub fn ligature_glyph_byte_range(&self) -> Range { + let start = 0; + start..start + GlyphId16::RAW_BYTE_LEN + } + + pub fn component_count_byte_range(&self) -> Range { + let start = self.ligature_glyph_byte_range().end; + start..start + u16::RAW_BYTE_LEN + } + + pub fn component_glyph_ids_byte_range(&self) -> Range { + let start = self.component_count_byte_range().end; + start..start + self.component_glyph_ids_byte_len(start) + } + /// glyph ID of ligature to substitute pub fn ligature_glyph(&self) -> GlyphId16 { - let range = self.shape.ligature_glyph_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.ligature_glyph_byte_range(); + unchecked::read_at(self.data, range.start) } /// Number of components in the ligature pub fn component_count(&self) -> u16 { - let range = self.shape.component_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.component_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Array of component glyph IDs — start with the second /// component, ordered in writing direction pub fn component_glyph_ids(&self) -> &'a [BigEndian] { - let range = self.shape.component_glyph_ids_byte_range(); - self.data.read_array(range).unwrap() + let range = self.component_glyph_ids_byte_range(); + unchecked::read_array(self.data, range) } } @@ -1344,51 +1315,22 @@ impl Format for ExtensionSubstFormat1Marker { } /// [Extension Substitution Subtable Format 1](https://learn.microsoft.com/en-us/typography/opentype/spec/gsub#71-extension-substitution-subtable-format-1) -#[derive(Debug)] +#[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct ExtensionSubstFormat1Marker { - offset_type: std::marker::PhantomData<*const T>, -} - -impl ExtensionSubstFormat1Marker { - pub fn subst_format_byte_range(&self) -> Range { - let start = 0; - start..start + u16::RAW_BYTE_LEN - } +pub struct ExtensionSubstFormat1Marker; - pub fn extension_lookup_type_byte_range(&self) -> Range { - let start = self.subst_format_byte_range().end; - start..start + u16::RAW_BYTE_LEN - } - - pub fn extension_offset_byte_range(&self) -> Range { - let start = self.extension_lookup_type_byte_range().end; - start..start + Offset32::RAW_BYTE_LEN - } -} - -impl MinByteRange for ExtensionSubstFormat1Marker { +impl<'a, T> MinByteRange for ExtensionSubstFormat1<'a, T> { fn min_byte_range(&self) -> Range { 0..self.extension_offset_byte_range().end } } -impl Clone for ExtensionSubstFormat1Marker { - fn clone(&self) -> Self { - *self - } -} - -impl Copy for ExtensionSubstFormat1Marker {} - impl<'a, T> FontRead<'a> for ExtensionSubstFormat1<'a, T> { fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.finish(ExtensionSubstFormat1Marker { - offset_type: std::marker::PhantomData, + Ok(TableRef { + args: std::marker::PhantomData, + data, + _marker: std::marker::PhantomData, }) } } @@ -1398,10 +1340,9 @@ impl<'a> ExtensionSubstFormat1<'a, ()> { pub(crate) fn into_concrete(self) -> ExtensionSubstFormat1<'a, T> { let TableRef { data, .. } = self; TableRef { - shape: ExtensionSubstFormat1Marker { - offset_type: std::marker::PhantomData, - }, + args: std::marker::PhantomData, data, + _marker: std::marker::PhantomData, } } } @@ -1412,38 +1353,53 @@ impl<'a, T> ExtensionSubstFormat1<'a, T> { pub(crate) fn of_unit_type(&self) -> ExtensionSubstFormat1<'a, ()> { let TableRef { data, .. } = self; TableRef { - shape: ExtensionSubstFormat1Marker { - offset_type: std::marker::PhantomData, - }, + args: std::marker::PhantomData, data: *data, + _marker: std::marker::PhantomData, } } } /// [Extension Substitution Subtable Format 1](https://learn.microsoft.com/en-us/typography/opentype/spec/gsub#71-extension-substitution-subtable-format-1) -pub type ExtensionSubstFormat1<'a, T> = TableRef<'a, ExtensionSubstFormat1Marker>; +pub type ExtensionSubstFormat1<'a, T = ()> = + TableRef<'a, ExtensionSubstFormat1Marker, std::marker::PhantomData<*const T>>; #[allow(clippy::needless_lifetimes)] impl<'a, T> ExtensionSubstFormat1<'a, T> { + pub fn subst_format_byte_range(&self) -> Range { + let start = 0; + start..start + u16::RAW_BYTE_LEN + } + + pub fn extension_lookup_type_byte_range(&self) -> Range { + let start = self.subst_format_byte_range().end; + start..start + u16::RAW_BYTE_LEN + } + + pub fn extension_offset_byte_range(&self) -> Range { + let start = self.extension_lookup_type_byte_range().end; + start..start + Offset32::RAW_BYTE_LEN + } + /// Format identifier. Set to 1. pub fn subst_format(&self) -> u16 { - let range = self.shape.subst_format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.subst_format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Lookup type of subtable referenced by extensionOffset (that is, /// the extension subtable). pub fn extension_lookup_type(&self) -> u16 { - let range = self.shape.extension_lookup_type_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.extension_lookup_type_byte_range(); + unchecked::read_at(self.data, range.start) } /// Offset to the extension subtable, of lookup type /// extensionLookupType, relative to the start of the /// ExtensionSubstFormat1 subtable. pub fn extension_offset(&self) -> Offset32 { - let range = self.shape.extension_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.extension_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`extension_offset`][Self::extension_offset]. @@ -1569,13 +1525,49 @@ impl Format for ReverseChainSingleSubstFormat1Marker { /// [Reverse Chaining Contextual Single Substitution Format 1](https://learn.microsoft.com/en-us/typography/opentype/spec/gsub#81-reverse-chaining-contextual-single-substitution-format-1-coverage-based-glyph-contexts) #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct ReverseChainSingleSubstFormat1Marker { - backtrack_coverage_offsets_byte_len: usize, - lookahead_coverage_offsets_byte_len: usize, - substitute_glyph_ids_byte_len: usize, +pub struct ReverseChainSingleSubstFormat1Marker; + +impl<'a> MinByteRange for ReverseChainSingleSubstFormat1<'a> { + fn min_byte_range(&self) -> Range { + 0..self.substitute_glyph_ids_byte_range().end + } } -impl ReverseChainSingleSubstFormat1Marker { +impl<'a> FontRead<'a> for ReverseChainSingleSubstFormat1<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// [Reverse Chaining Contextual Single Substitution Format 1](https://learn.microsoft.com/en-us/typography/opentype/spec/gsub#81-reverse-chaining-contextual-single-substitution-format-1-coverage-based-glyph-contexts) +pub type ReverseChainSingleSubstFormat1<'a> = + TableRef<'a, ReverseChainSingleSubstFormat1Marker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> ReverseChainSingleSubstFormat1<'a> { + fn backtrack_coverage_offsets_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.backtrack_glyph_count()) as usize) + .checked_mul(Offset16::RAW_BYTE_LEN) + .unwrap() + } + fn lookahead_coverage_offsets_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.lookahead_glyph_count()) as usize) + .checked_mul(Offset16::RAW_BYTE_LEN) + .unwrap() + } + fn substitute_glyph_ids_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.glyph_count()) as usize) + .checked_mul(GlyphId16::RAW_BYTE_LEN) + .unwrap() + } + pub fn subst_format_byte_range(&self) -> Range { let start = 0; start..start + u16::RAW_BYTE_LEN @@ -1593,7 +1585,7 @@ impl ReverseChainSingleSubstFormat1Marker { pub fn backtrack_coverage_offsets_byte_range(&self) -> Range { let start = self.backtrack_glyph_count_byte_range().end; - start..start + self.backtrack_coverage_offsets_byte_len + start..start + self.backtrack_coverage_offsets_byte_len(start) } pub fn lookahead_glyph_count_byte_range(&self) -> Range { @@ -1603,7 +1595,7 @@ impl ReverseChainSingleSubstFormat1Marker { pub fn lookahead_coverage_offsets_byte_range(&self) -> Range { let start = self.lookahead_glyph_count_byte_range().end; - start..start + self.lookahead_coverage_offsets_byte_len + start..start + self.lookahead_coverage_offsets_byte_len(start) } pub fn glyph_count_byte_range(&self) -> Range { @@ -1613,60 +1605,20 @@ impl ReverseChainSingleSubstFormat1Marker { pub fn substitute_glyph_ids_byte_range(&self) -> Range { let start = self.glyph_count_byte_range().end; - start..start + self.substitute_glyph_ids_byte_len + start..start + self.substitute_glyph_ids_byte_len(start) } -} -impl MinByteRange for ReverseChainSingleSubstFormat1Marker { - fn min_byte_range(&self) -> Range { - 0..self.substitute_glyph_ids_byte_range().end - } -} - -impl<'a> FontRead<'a> for ReverseChainSingleSubstFormat1<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - let backtrack_glyph_count: u16 = cursor.read()?; - let backtrack_coverage_offsets_byte_len = (backtrack_glyph_count as usize) - .checked_mul(Offset16::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(backtrack_coverage_offsets_byte_len); - let lookahead_glyph_count: u16 = cursor.read()?; - let lookahead_coverage_offsets_byte_len = (lookahead_glyph_count as usize) - .checked_mul(Offset16::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(lookahead_coverage_offsets_byte_len); - let glyph_count: u16 = cursor.read()?; - let substitute_glyph_ids_byte_len = (glyph_count as usize) - .checked_mul(GlyphId16::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(substitute_glyph_ids_byte_len); - cursor.finish(ReverseChainSingleSubstFormat1Marker { - backtrack_coverage_offsets_byte_len, - lookahead_coverage_offsets_byte_len, - substitute_glyph_ids_byte_len, - }) - } -} - -/// [Reverse Chaining Contextual Single Substitution Format 1](https://learn.microsoft.com/en-us/typography/opentype/spec/gsub#81-reverse-chaining-contextual-single-substitution-format-1-coverage-based-glyph-contexts) -pub type ReverseChainSingleSubstFormat1<'a> = TableRef<'a, ReverseChainSingleSubstFormat1Marker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> ReverseChainSingleSubstFormat1<'a> { /// Format identifier: format = 1 pub fn subst_format(&self) -> u16 { - let range = self.shape.subst_format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.subst_format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Offset to Coverage table, from beginning of substitution /// subtable. pub fn coverage_offset(&self) -> Offset16 { - let range = self.shape.coverage_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.coverage_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`coverage_offset`][Self::coverage_offset]. @@ -1677,15 +1629,15 @@ impl<'a> ReverseChainSingleSubstFormat1<'a> { /// Number of glyphs in the backtrack sequence. pub fn backtrack_glyph_count(&self) -> u16 { - let range = self.shape.backtrack_glyph_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.backtrack_glyph_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Array of offsets to coverage tables in backtrack sequence, in /// glyph sequence order. pub fn backtrack_coverage_offsets(&self) -> &'a [BigEndian] { - let range = self.shape.backtrack_coverage_offsets_byte_range(); - self.data.read_array(range).unwrap() + let range = self.backtrack_coverage_offsets_byte_range(); + unchecked::read_array(self.data, range) } /// A dynamically resolving wrapper for [`backtrack_coverage_offsets`][Self::backtrack_coverage_offsets]. @@ -1697,15 +1649,15 @@ impl<'a> ReverseChainSingleSubstFormat1<'a> { /// Number of glyphs in lookahead sequence. pub fn lookahead_glyph_count(&self) -> u16 { - let range = self.shape.lookahead_glyph_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.lookahead_glyph_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Array of offsets to coverage tables in lookahead sequence, in /// glyph sequence order. pub fn lookahead_coverage_offsets(&self) -> &'a [BigEndian] { - let range = self.shape.lookahead_coverage_offsets_byte_range(); - self.data.read_array(range).unwrap() + let range = self.lookahead_coverage_offsets_byte_range(); + unchecked::read_array(self.data, range) } /// A dynamically resolving wrapper for [`lookahead_coverage_offsets`][Self::lookahead_coverage_offsets]. @@ -1717,14 +1669,14 @@ impl<'a> ReverseChainSingleSubstFormat1<'a> { /// Number of glyph IDs in the substituteGlyphIDs array. pub fn glyph_count(&self) -> u16 { - let range = self.shape.glyph_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.glyph_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Array of substitute glyph IDs — ordered by Coverage index. pub fn substitute_glyph_ids(&self) -> &'a [BigEndian] { - let range = self.shape.substitute_glyph_ids_byte_range(); - self.data.read_array(range).unwrap() + let range = self.substitute_glyph_ids_byte_range(); + unchecked::read_array(self.data, range) } } diff --git a/read-fonts/generated/generated_gvar.rs b/read-fonts/generated/generated_gvar.rs index f658fe39e..ded61da67 100644 --- a/read-fonts/generated/generated_gvar.rs +++ b/read-fonts/generated/generated_gvar.rs @@ -8,11 +8,41 @@ use crate::codegen_prelude::*; /// The ['gvar' header](https://learn.microsoft.com/en-us/typography/opentype/spec/gvar#gvar-header) #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct GvarMarker { - glyph_variation_data_offsets_byte_len: usize, +pub struct GvarMarker; + +impl<'a> MinByteRange for Gvar<'a> { + fn min_byte_range(&self) -> Range { + 0..self.glyph_variation_data_offsets_byte_range().end + } +} + +impl TopLevelTable for Gvar<'_> { + /// `gvar` + const TAG: Tag = Tag::new(b"gvar"); +} + +impl<'a> FontRead<'a> for Gvar<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } } -impl GvarMarker { +/// The ['gvar' header](https://learn.microsoft.com/en-us/typography/opentype/spec/gvar#gvar-header) +pub type Gvar<'a> = TableRef<'a, GvarMarker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> Gvar<'a> { + fn glyph_variation_data_offsets_byte_len(&self, start: usize) -> usize { + let _ = start; + (transforms::add(self.glyph_count(), 1_usize)) + .checked_mul(::compute_size(&self.flags()).unwrap()) + .unwrap() + } + pub fn version_byte_range(&self) -> Range { let start = 0; start..start + MajorMinor::RAW_BYTE_LEN @@ -50,57 +80,20 @@ impl GvarMarker { pub fn glyph_variation_data_offsets_byte_range(&self) -> Range { let start = self.glyph_variation_data_array_offset_byte_range().end; - start..start + self.glyph_variation_data_offsets_byte_len - } -} - -impl MinByteRange for GvarMarker { - fn min_byte_range(&self) -> Range { - 0..self.glyph_variation_data_offsets_byte_range().end - } -} - -impl TopLevelTable for Gvar<'_> { - /// `gvar` - const TAG: Tag = Tag::new(b"gvar"); -} - -impl<'a> FontRead<'a> for Gvar<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - let glyph_count: u16 = cursor.read()?; - let flags: GvarFlags = cursor.read()?; - cursor.advance::(); - let glyph_variation_data_offsets_byte_len = (transforms::add(glyph_count, 1_usize)) - .checked_mul(::compute_size(&flags)?) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(glyph_variation_data_offsets_byte_len); - cursor.finish(GvarMarker { - glyph_variation_data_offsets_byte_len, - }) + start..start + self.glyph_variation_data_offsets_byte_len(start) } -} -/// The ['gvar' header](https://learn.microsoft.com/en-us/typography/opentype/spec/gvar#gvar-header) -pub type Gvar<'a> = TableRef<'a, GvarMarker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> Gvar<'a> { /// Major/minor version number of the glyph variations table — set to (1,0). pub fn version(&self) -> MajorMinor { - let range = self.shape.version_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.version_byte_range(); + unchecked::read_at(self.data, range.start) } /// The number of variation axes for this font. This must be the /// same number as axisCount in the 'fvar' table. pub fn axis_count(&self) -> u16 { - let range = self.shape.axis_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.axis_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// The number of shared tuple records. Shared tuple records can be @@ -108,14 +101,14 @@ impl<'a> Gvar<'a> { /// glyphs, as opposed to other tuple records stored directly /// within a glyph variation data table. pub fn shared_tuple_count(&self) -> u16 { - let range = self.shape.shared_tuple_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.shared_tuple_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Offset from the start of this table to the shared tuple records. pub fn shared_tuples_offset(&self) -> Offset32 { - let range = self.shape.shared_tuples_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.shared_tuples_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`shared_tuples_offset`][Self::shared_tuples_offset]. @@ -128,30 +121,30 @@ impl<'a> Gvar<'a> { /// The number of glyphs in this font. This must match the number /// of glyphs stored elsewhere in the font. pub fn glyph_count(&self) -> u16 { - let range = self.shape.glyph_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.glyph_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Bit-field that gives the format of the offset array that /// follows. If bit 0 is clear, the offsets are uint16; if bit 0 is /// set, the offsets are uint32. pub fn flags(&self) -> GvarFlags { - let range = self.shape.flags_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.flags_byte_range(); + unchecked::read_at(self.data, range.start) } /// Offset from the start of this table to the array of /// GlyphVariationData tables. pub fn glyph_variation_data_array_offset(&self) -> u32 { - let range = self.shape.glyph_variation_data_array_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.glyph_variation_data_array_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Offsets from the start of the GlyphVariationData array to each /// GlyphVariationData table. pub fn glyph_variation_data_offsets(&self) -> ComputedArray<'a, U16Or32> { - let range = self.shape.glyph_variation_data_offsets_byte_range(); - self.data.read_with_args(range, &self.flags()).unwrap() + let range = self.glyph_variation_data_offsets_byte_range(); + unchecked::read_with_args(self.data, range, &self.flags()) } } @@ -496,19 +489,9 @@ impl<'a> From for FieldType<'a> { /// Array of tuple records shared across all glyph variation data tables. #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct SharedTuplesMarker { - axis_count: u16, - tuples_byte_len: usize, -} - -impl SharedTuplesMarker { - pub fn tuples_byte_range(&self) -> Range { - let start = 0; - start..start + self.tuples_byte_len - } -} +pub struct SharedTuplesMarker; -impl MinByteRange for SharedTuplesMarker { +impl<'a> MinByteRange for SharedTuples<'a> { fn min_byte_range(&self) -> Range { 0..self.tuples_byte_range().end } @@ -520,15 +503,11 @@ impl ReadArgs for SharedTuples<'_> { impl<'a> FontReadWithArgs<'a> for SharedTuples<'a> { fn read_with_args(data: FontData<'a>, args: &(u16, u16)) -> Result { - let (shared_tuple_count, axis_count) = *args; - let mut cursor = data.cursor(); - let tuples_byte_len = (shared_tuple_count as usize) - .checked_mul(::compute_size(&axis_count)?) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(tuples_byte_len); - cursor.finish(SharedTuplesMarker { - axis_count, - tuples_byte_len, + let args = *args; + Ok(TableRef { + args, + data, + _marker: std::marker::PhantomData, }) } } @@ -549,17 +528,33 @@ impl<'a> SharedTuples<'a> { } /// Array of tuple records shared across all glyph variation data tables. -pub type SharedTuples<'a> = TableRef<'a, SharedTuplesMarker>; +pub type SharedTuples<'a> = TableRef<'a, SharedTuplesMarker, (u16, u16)>; #[allow(clippy::needless_lifetimes)] impl<'a> SharedTuples<'a> { + fn tuples_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.args.0) as usize) + .checked_mul(::compute_size(&self.args.1).unwrap()) + .unwrap() + } + + pub fn tuples_byte_range(&self) -> Range { + let start = 0; + start..start + self.tuples_byte_len(start) + } + pub fn tuples(&self) -> ComputedArray<'a, Tuple<'a>> { - let range = self.shape.tuples_byte_range(); - self.data.read_with_args(range, &self.axis_count()).unwrap() + let range = self.tuples_byte_range(); + unchecked::read_with_args(self.data, range, &self.axis_count()) + } + + pub(crate) fn shared_tuple_count(&self) -> u16 { + self.args.0 } pub(crate) fn axis_count(&self) -> u16 { - self.shape.axis_count + self.args.1 } } @@ -590,28 +585,9 @@ impl<'a> std::fmt::Debug for SharedTuples<'a> { /// The [GlyphVariationData](https://learn.microsoft.com/en-us/typography/opentype/spec/gvar#the-glyphvariationdata-table-array) table #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct GlyphVariationDataHeaderMarker { - tuple_variation_headers_byte_len: usize, -} - -impl GlyphVariationDataHeaderMarker { - pub fn tuple_variation_count_byte_range(&self) -> Range { - let start = 0; - start..start + TupleVariationCount::RAW_BYTE_LEN - } - - pub fn serialized_data_offset_byte_range(&self) -> Range { - let start = self.tuple_variation_count_byte_range().end; - start..start + Offset16::RAW_BYTE_LEN - } - - pub fn tuple_variation_headers_byte_range(&self) -> Range { - let start = self.serialized_data_offset_byte_range().end; - start..start + self.tuple_variation_headers_byte_len - } -} +pub struct GlyphVariationDataHeaderMarker; -impl MinByteRange for GlyphVariationDataHeaderMarker { +impl<'a> MinByteRange for GlyphVariationDataHeader<'a> { fn min_byte_range(&self) -> Range { 0..self.tuple_variation_headers_byte_range().end } @@ -619,36 +595,53 @@ impl MinByteRange for GlyphVariationDataHeaderMarker { impl<'a> FontRead<'a> for GlyphVariationDataHeader<'a> { fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - let tuple_variation_headers_byte_len = cursor.remaining_bytes(); - cursor.advance_by(tuple_variation_headers_byte_len); - cursor.finish(GlyphVariationDataHeaderMarker { - tuple_variation_headers_byte_len, + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, }) } } /// The [GlyphVariationData](https://learn.microsoft.com/en-us/typography/opentype/spec/gvar#the-glyphvariationdata-table-array) table -pub type GlyphVariationDataHeader<'a> = TableRef<'a, GlyphVariationDataHeaderMarker>; +pub type GlyphVariationDataHeader<'a> = TableRef<'a, GlyphVariationDataHeaderMarker, ()>; #[allow(clippy::needless_lifetimes)] impl<'a> GlyphVariationDataHeader<'a> { + fn tuple_variation_headers_byte_len(&self, start: usize) -> usize { + let _ = start; + self.data.len().saturating_sub(start) + } + + pub fn tuple_variation_count_byte_range(&self) -> Range { + let start = 0; + start..start + TupleVariationCount::RAW_BYTE_LEN + } + + pub fn serialized_data_offset_byte_range(&self) -> Range { + let start = self.tuple_variation_count_byte_range().end; + start..start + Offset16::RAW_BYTE_LEN + } + + pub fn tuple_variation_headers_byte_range(&self) -> Range { + let start = self.serialized_data_offset_byte_range().end; + start..start + self.tuple_variation_headers_byte_len(start) + } + /// A packed field. The high 4 bits are flags, and the low 12 bits /// are the number of tuple variation tables for this glyph. The /// number of tuple variation tables can be any number between 1 /// and 4095. pub fn tuple_variation_count(&self) -> TupleVariationCount { - let range = self.shape.tuple_variation_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.tuple_variation_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Offset from the start of the GlyphVariationData table to the /// serialized data pub fn serialized_data_offset(&self) -> Offset16 { - let range = self.shape.serialized_data_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.serialized_data_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`serialized_data_offset`][Self::serialized_data_offset]. @@ -659,8 +652,8 @@ impl<'a> GlyphVariationDataHeader<'a> { /// Array of tuple variation headers. pub fn tuple_variation_headers(&self) -> VarLenArray<'a, TupleVariationHeader<'a>> { - let range = self.shape.tuple_variation_headers_byte_range(); - VarLenArray::read(self.data.split_off(range.start).unwrap()).unwrap() + let range = self.tuple_variation_headers_byte_range(); + VarLenArray::read(unchecked::split_off(self.data, range.start)).unwrap() } } diff --git a/read-fonts/generated/generated_hdmx.rs b/read-fonts/generated/generated_hdmx.rs index a883d3d4c..ee8b9bcb3 100644 --- a/read-fonts/generated/generated_hdmx.rs +++ b/read-fonts/generated/generated_hdmx.rs @@ -8,34 +8,9 @@ use crate::codegen_prelude::*; /// The [Horizontal Device Metrics](https://learn.microsoft.com/en-us/typography/opentype/spec/hdmx) table. #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct HdmxMarker { - num_glyphs: u16, - records_byte_len: usize, -} - -impl HdmxMarker { - pub fn version_byte_range(&self) -> Range { - let start = 0; - start..start + u16::RAW_BYTE_LEN - } - - pub fn num_records_byte_range(&self) -> Range { - let start = self.version_byte_range().end; - start..start + u16::RAW_BYTE_LEN - } +pub struct HdmxMarker; - pub fn size_device_record_byte_range(&self) -> Range { - let start = self.num_records_byte_range().end; - start..start + u32::RAW_BYTE_LEN - } - - pub fn records_byte_range(&self) -> Range { - let start = self.size_device_record_byte_range().end; - start..start + self.records_byte_len - } -} - -impl MinByteRange for HdmxMarker { +impl<'a> MinByteRange for Hdmx<'a> { fn min_byte_range(&self) -> Range { 0..self.records_byte_range().end } @@ -52,21 +27,11 @@ impl ReadArgs for Hdmx<'_> { impl<'a> FontReadWithArgs<'a> for Hdmx<'a> { fn read_with_args(data: FontData<'a>, args: &u16) -> Result { - let num_glyphs = *args; - let mut cursor = data.cursor(); - cursor.advance::(); - let num_records: u16 = cursor.read()?; - let size_device_record: u32 = cursor.read()?; - let records_byte_len = (num_records as usize) - .checked_mul(::compute_size(&( - num_glyphs, - size_device_record, - ))?) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(records_byte_len); - cursor.finish(HdmxMarker { - num_glyphs, - records_byte_len, + let args = *args; + Ok(TableRef { + args, + data, + _marker: std::marker::PhantomData, }) } } @@ -83,38 +48,73 @@ impl<'a> Hdmx<'a> { } /// The [Horizontal Device Metrics](https://learn.microsoft.com/en-us/typography/opentype/spec/hdmx) table. -pub type Hdmx<'a> = TableRef<'a, HdmxMarker>; +pub type Hdmx<'a> = TableRef<'a, HdmxMarker, u16>; #[allow(clippy::needless_lifetimes)] impl<'a> Hdmx<'a> { + fn records_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.num_records()) as usize) + .checked_mul( + ::compute_size(&( + self.args, + self.size_device_record(), + )) + .unwrap(), + ) + .unwrap() + } + + pub fn version_byte_range(&self) -> Range { + let start = 0; + start..start + u16::RAW_BYTE_LEN + } + + pub fn num_records_byte_range(&self) -> Range { + let start = self.version_byte_range().end; + start..start + u16::RAW_BYTE_LEN + } + + pub fn size_device_record_byte_range(&self) -> Range { + let start = self.num_records_byte_range().end; + start..start + u32::RAW_BYTE_LEN + } + + pub fn records_byte_range(&self) -> Range { + let start = self.size_device_record_byte_range().end; + start..start + self.records_byte_len(start) + } + /// Table version number (set to 0). pub fn version(&self) -> u16 { - let range = self.shape.version_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.version_byte_range(); + unchecked::read_at(self.data, range.start) } /// Number of device records. pub fn num_records(&self) -> u16 { - let range = self.shape.num_records_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.num_records_byte_range(); + unchecked::read_at(self.data, range.start) } /// Size of device record, 32-bit aligned. pub fn size_device_record(&self) -> u32 { - let range = self.shape.size_device_record_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.size_device_record_byte_range(); + unchecked::read_at(self.data, range.start) } /// Array of device records. pub fn records(&self) -> ComputedArray<'a, DeviceRecord<'a>> { - let range = self.shape.records_byte_range(); - self.data - .read_with_args(range, &(self.num_glyphs(), self.size_device_record())) - .unwrap() + let range = self.records_byte_range(); + unchecked::read_with_args( + self.data, + range, + &(self.num_glyphs(), self.size_device_record()), + ) } pub(crate) fn num_glyphs(&self) -> u16 { - self.shape.num_glyphs + self.args } } diff --git a/read-fonts/generated/generated_head.rs b/read-fonts/generated/generated_head.rs index 88057c57d..954789f4a 100644 --- a/read-fonts/generated/generated_head.rs +++ b/read-fonts/generated/generated_head.rs @@ -696,9 +696,35 @@ impl<'a> From for FieldType<'a> { /// (font header) table. #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct HeadMarker {} +pub struct HeadMarker; -impl HeadMarker { +impl<'a> MinByteRange for Head<'a> { + fn min_byte_range(&self) -> Range { + 0..self.glyph_data_format_byte_range().end + } +} + +impl TopLevelTable for Head<'_> { + /// `head` + const TAG: Tag = Tag::new(b"head"); +} + +impl<'a> FontRead<'a> for Head<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// The [head](https://docs.microsoft.com/en-us/typography/opentype/spec/head) +/// (font header) table. +pub type Head<'a> = TableRef<'a, HeadMarker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> Head<'a> { pub fn version_byte_range(&self) -> Range { let start = 0; start..start + MajorMinor::RAW_BYTE_LEN @@ -783,59 +809,17 @@ impl HeadMarker { let start = self.index_to_loc_format_byte_range().end; start..start + i16::RAW_BYTE_LEN } -} - -impl MinByteRange for HeadMarker { - fn min_byte_range(&self) -> Range { - 0..self.glyph_data_format_byte_range().end - } -} - -impl TopLevelTable for Head<'_> { - /// `head` - const TAG: Tag = Tag::new(b"head"); -} -impl<'a> FontRead<'a> for Head<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.finish(HeadMarker {}) - } -} - -/// The [head](https://docs.microsoft.com/en-us/typography/opentype/spec/head) -/// (font header) table. -pub type Head<'a> = TableRef<'a, HeadMarker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> Head<'a> { /// Version number of the font header table, set to (1, 0) pub fn version(&self) -> MajorMinor { - let range = self.shape.version_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.version_byte_range(); + unchecked::read_at(self.data, range.start) } /// Set by font manufacturer. pub fn font_revision(&self) -> Fixed { - let range = self.shape.font_revision_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.font_revision_byte_range(); + unchecked::read_at(self.data, range.start) } /// To compute: set it to 0, sum the entire font as uint32, then @@ -844,20 +828,20 @@ impl<'a> Head<'a> { /// invalidated by changes to the file structure and font table /// directory, and must be ignored. pub fn checksum_adjustment(&self) -> u32 { - let range = self.shape.checksum_adjustment_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.checksum_adjustment_byte_range(); + unchecked::read_at(self.data, range.start) } /// Set to 0x5F0F3CF5. pub fn magic_number(&self) -> u32 { - let range = self.shape.magic_number_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.magic_number_byte_range(); + unchecked::read_at(self.data, range.start) } /// See the flags enum. pub fn flags(&self) -> Flags { - let range = self.shape.flags_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.flags_byte_range(); + unchecked::read_at(self.data, range.start) } /// Set to a value from 16 to 16384. Any value in this range is @@ -865,76 +849,76 @@ impl<'a> Head<'a> { /// recommended as this allows performance optimizations in some /// rasterizers. pub fn units_per_em(&self) -> u16 { - let range = self.shape.units_per_em_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.units_per_em_byte_range(); + unchecked::read_at(self.data, range.start) } /// Number of seconds since 12:00 midnight that started January 1st /// 1904 in GMT/UTC time zone. pub fn created(&self) -> LongDateTime { - let range = self.shape.created_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.created_byte_range(); + unchecked::read_at(self.data, range.start) } /// Number of seconds since 12:00 midnight that started January 1st /// 1904 in GMT/UTC time zone. pub fn modified(&self) -> LongDateTime { - let range = self.shape.modified_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.modified_byte_range(); + unchecked::read_at(self.data, range.start) } /// Minimum x coordinate across all glyph bounding boxes. pub fn x_min(&self) -> i16 { - let range = self.shape.x_min_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.x_min_byte_range(); + unchecked::read_at(self.data, range.start) } /// Minimum y coordinate across all glyph bounding boxes. pub fn y_min(&self) -> i16 { - let range = self.shape.y_min_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.y_min_byte_range(); + unchecked::read_at(self.data, range.start) } /// Maximum x coordinate across all glyph bounding boxes. pub fn x_max(&self) -> i16 { - let range = self.shape.x_max_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.x_max_byte_range(); + unchecked::read_at(self.data, range.start) } /// Maximum y coordinate across all glyph bounding boxes. pub fn y_max(&self) -> i16 { - let range = self.shape.y_max_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.y_max_byte_range(); + unchecked::read_at(self.data, range.start) } /// Bits identifying the font's style; see [MacStyle] pub fn mac_style(&self) -> MacStyle { - let range = self.shape.mac_style_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.mac_style_byte_range(); + unchecked::read_at(self.data, range.start) } /// Smallest readable size in pixels. pub fn lowest_rec_ppem(&self) -> u16 { - let range = self.shape.lowest_rec_ppem_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.lowest_rec_ppem_byte_range(); + unchecked::read_at(self.data, range.start) } /// Deprecated (Set to 2). pub fn font_direction_hint(&self) -> i16 { - let range = self.shape.font_direction_hint_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.font_direction_hint_byte_range(); + unchecked::read_at(self.data, range.start) } /// 0 for short offsets (Offset16), 1 for long (Offset32). pub fn index_to_loc_format(&self) -> i16 { - let range = self.shape.index_to_loc_format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.index_to_loc_format_byte_range(); + unchecked::read_at(self.data, range.start) } /// 0 for current format. pub fn glyph_data_format(&self) -> i16 { - let range = self.shape.glyph_data_format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.glyph_data_format_byte_range(); + unchecked::read_at(self.data, range.start) } } diff --git a/read-fonts/generated/generated_hhea.rs b/read-fonts/generated/generated_hhea.rs index 73912bacd..9a786b58d 100644 --- a/read-fonts/generated/generated_hhea.rs +++ b/read-fonts/generated/generated_hhea.rs @@ -8,9 +8,34 @@ use crate::codegen_prelude::*; /// [hhea](https://docs.microsoft.com/en-us/typography/opentype/spec/hhea) Horizontal Header Table #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct HheaMarker {} +pub struct HheaMarker; -impl HheaMarker { +impl<'a> MinByteRange for Hhea<'a> { + fn min_byte_range(&self) -> Range { + 0..self.number_of_h_metrics_byte_range().end + } +} + +impl TopLevelTable for Hhea<'_> { + /// `hhea` + const TAG: Tag = Tag::new(b"hhea"); +} + +impl<'a> FontRead<'a> for Hhea<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// [hhea](https://docs.microsoft.com/en-us/typography/opentype/spec/hhea) Horizontal Header Table +pub type Hhea<'a> = TableRef<'a, HheaMarker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> Hhea<'a> { pub fn version_byte_range(&self) -> Range { let start = 0; start..start + MajorMinor::RAW_BYTE_LEN @@ -95,130 +120,89 @@ impl HheaMarker { let start = self.metric_data_format_byte_range().end; start..start + u16::RAW_BYTE_LEN } -} -impl MinByteRange for HheaMarker { - fn min_byte_range(&self) -> Range { - 0..self.number_of_h_metrics_byte_range().end - } -} - -impl TopLevelTable for Hhea<'_> { - /// `hhea` - const TAG: Tag = Tag::new(b"hhea"); -} - -impl<'a> FontRead<'a> for Hhea<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.finish(HheaMarker {}) - } -} - -/// [hhea](https://docs.microsoft.com/en-us/typography/opentype/spec/hhea) Horizontal Header Table -pub type Hhea<'a> = TableRef<'a, HheaMarker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> Hhea<'a> { /// The major/minor version (1, 0) pub fn version(&self) -> MajorMinor { - let range = self.shape.version_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.version_byte_range(); + unchecked::read_at(self.data, range.start) } /// Typographic ascent. pub fn ascender(&self) -> FWord { - let range = self.shape.ascender_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.ascender_byte_range(); + unchecked::read_at(self.data, range.start) } /// Typographic descent. pub fn descender(&self) -> FWord { - let range = self.shape.descender_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.descender_byte_range(); + unchecked::read_at(self.data, range.start) } /// Typographic line gap. Negative LineGap values are treated as /// zero in some legacy platform implementations. pub fn line_gap(&self) -> FWord { - let range = self.shape.line_gap_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.line_gap_byte_range(); + unchecked::read_at(self.data, range.start) } /// Maximum advance width value in 'hmtx' table. pub fn advance_width_max(&self) -> UfWord { - let range = self.shape.advance_width_max_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.advance_width_max_byte_range(); + unchecked::read_at(self.data, range.start) } /// Minimum left sidebearing value in 'hmtx' table for glyphs with /// contours (empty glyphs should be ignored). pub fn min_left_side_bearing(&self) -> FWord { - let range = self.shape.min_left_side_bearing_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.min_left_side_bearing_byte_range(); + unchecked::read_at(self.data, range.start) } /// Minimum right sidebearing value; calculated as min(aw - (lsb + /// xMax - xMin)) for glyphs with contours (empty glyphs should be ignored). pub fn min_right_side_bearing(&self) -> FWord { - let range = self.shape.min_right_side_bearing_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.min_right_side_bearing_byte_range(); + unchecked::read_at(self.data, range.start) } /// Max(lsb + (xMax-xMin)) pub fn x_max_extent(&self) -> FWord { - let range = self.shape.x_max_extent_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.x_max_extent_byte_range(); + unchecked::read_at(self.data, range.start) } /// Used to calculate the slope of the cursor (rise/run); 1 for /// vertical caret, 0 for horizontal. pub fn caret_slope_rise(&self) -> i16 { - let range = self.shape.caret_slope_rise_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.caret_slope_rise_byte_range(); + unchecked::read_at(self.data, range.start) } /// 0 for vertical caret, 1 for horizontal. pub fn caret_slope_run(&self) -> i16 { - let range = self.shape.caret_slope_run_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.caret_slope_run_byte_range(); + unchecked::read_at(self.data, range.start) } /// The amount by which a slanted highlight on a glyph needs to be /// shifted to produce the best appearance. Set to 0 for /// non-slanted fonts pub fn caret_offset(&self) -> i16 { - let range = self.shape.caret_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.caret_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// 0 for current format. pub fn metric_data_format(&self) -> i16 { - let range = self.shape.metric_data_format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.metric_data_format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Number of hMetric entries in 'hmtx' table pub fn number_of_h_metrics(&self) -> u16 { - let range = self.shape.number_of_h_metrics_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.number_of_h_metrics_byte_range(); + unchecked::read_at(self.data, range.start) } } diff --git a/read-fonts/generated/generated_hmtx.rs b/read-fonts/generated/generated_hmtx.rs index 85a8d565a..3d565b6a3 100644 --- a/read-fonts/generated/generated_hmtx.rs +++ b/read-fonts/generated/generated_hmtx.rs @@ -8,24 +8,9 @@ use crate::codegen_prelude::*; /// The [hmtx (Horizontal Metrics)](https://docs.microsoft.com/en-us/typography/opentype/spec/hmtx) table #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct HmtxMarker { - h_metrics_byte_len: usize, - left_side_bearings_byte_len: usize, -} - -impl HmtxMarker { - pub fn h_metrics_byte_range(&self) -> Range { - let start = 0; - start..start + self.h_metrics_byte_len - } - - pub fn left_side_bearings_byte_range(&self) -> Range { - let start = self.h_metrics_byte_range().end; - start..start + self.left_side_bearings_byte_len - } -} +pub struct HmtxMarker; -impl MinByteRange for HmtxMarker { +impl<'a> MinByteRange for Hmtx<'a> { fn min_byte_range(&self) -> Range { 0..self.left_side_bearings_byte_range().end } @@ -42,18 +27,11 @@ impl ReadArgs for Hmtx<'_> { impl<'a> FontReadWithArgs<'a> for Hmtx<'a> { fn read_with_args(data: FontData<'a>, args: &u16) -> Result { - let number_of_h_metrics = *args; - let mut cursor = data.cursor(); - let h_metrics_byte_len = (number_of_h_metrics as usize) - .checked_mul(LongMetric::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(h_metrics_byte_len); - let left_side_bearings_byte_len = - cursor.remaining_bytes() / i16::RAW_BYTE_LEN * i16::RAW_BYTE_LEN; - cursor.advance_by(left_side_bearings_byte_len); - cursor.finish(HmtxMarker { - h_metrics_byte_len, - left_side_bearings_byte_len, + let args = *args; + Ok(TableRef { + args, + data, + _marker: std::marker::PhantomData, }) } } @@ -70,22 +48,50 @@ impl<'a> Hmtx<'a> { } /// The [hmtx (Horizontal Metrics)](https://docs.microsoft.com/en-us/typography/opentype/spec/hmtx) table -pub type Hmtx<'a> = TableRef<'a, HmtxMarker>; +pub type Hmtx<'a> = TableRef<'a, HmtxMarker, u16>; #[allow(clippy::needless_lifetimes)] impl<'a> Hmtx<'a> { + fn h_metrics_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.args) as usize) + .checked_mul(LongMetric::RAW_BYTE_LEN) + .unwrap() + } + fn left_side_bearings_byte_len(&self, start: usize) -> usize { + let _ = start; + { + let remaining = self.data.len().saturating_sub(start); + remaining / i16::RAW_BYTE_LEN * i16::RAW_BYTE_LEN + } + } + + pub fn h_metrics_byte_range(&self) -> Range { + let start = 0; + start..start + self.h_metrics_byte_len(start) + } + + pub fn left_side_bearings_byte_range(&self) -> Range { + let start = self.h_metrics_byte_range().end; + start..start + self.left_side_bearings_byte_len(start) + } + /// Paired advance width/height and left/top side bearing values for each /// glyph. Records are indexed by glyph ID. pub fn h_metrics(&self) -> &'a [LongMetric] { - let range = self.shape.h_metrics_byte_range(); - self.data.read_array(range).unwrap() + let range = self.h_metrics_byte_range(); + unchecked::read_array(self.data, range) } /// Leading (left/top) side bearings for glyph IDs greater than or equal to /// numberOfLongMetrics. pub fn left_side_bearings(&self) -> &'a [BigEndian] { - let range = self.shape.left_side_bearings_byte_range(); - self.data.read_array(range).unwrap() + let range = self.left_side_bearings_byte_range(); + unchecked::read_array(self.data, range) + } + + pub(crate) fn number_of_h_metrics(&self) -> u16 { + self.args } } diff --git a/read-fonts/generated/generated_hvar.rs b/read-fonts/generated/generated_hvar.rs index 8afca3166..e8cfde2ee 100644 --- a/read-fonts/generated/generated_hvar.rs +++ b/read-fonts/generated/generated_hvar.rs @@ -8,9 +8,34 @@ use crate::codegen_prelude::*; /// The [HVAR (Horizontal Metrics Variations)](https://docs.microsoft.com/en-us/typography/opentype/spec/hvar) table #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct HvarMarker {} +pub struct HvarMarker; -impl HvarMarker { +impl<'a> MinByteRange for Hvar<'a> { + fn min_byte_range(&self) -> Range { + 0..self.rsb_mapping_offset_byte_range().end + } +} + +impl TopLevelTable for Hvar<'_> { + /// `HVAR` + const TAG: Tag = Tag::new(b"HVAR"); +} + +impl<'a> FontRead<'a> for Hvar<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// The [HVAR (Horizontal Metrics Variations)](https://docs.microsoft.com/en-us/typography/opentype/spec/hvar) table +pub type Hvar<'a> = TableRef<'a, HvarMarker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> Hvar<'a> { pub fn version_byte_range(&self) -> Range { let start = 0; start..start + MajorMinor::RAW_BYTE_LEN @@ -35,47 +60,18 @@ impl HvarMarker { let start = self.lsb_mapping_offset_byte_range().end; start..start + Offset32::RAW_BYTE_LEN } -} -impl MinByteRange for HvarMarker { - fn min_byte_range(&self) -> Range { - 0..self.rsb_mapping_offset_byte_range().end - } -} - -impl TopLevelTable for Hvar<'_> { - /// `HVAR` - const TAG: Tag = Tag::new(b"HVAR"); -} - -impl<'a> FontRead<'a> for Hvar<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.finish(HvarMarker {}) - } -} - -/// The [HVAR (Horizontal Metrics Variations)](https://docs.microsoft.com/en-us/typography/opentype/spec/hvar) table -pub type Hvar<'a> = TableRef<'a, HvarMarker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> Hvar<'a> { /// Major version number of the horizontal metrics variations table — set to 1. /// Minor version number of the horizontal metrics variations table — set to 0. pub fn version(&self) -> MajorMinor { - let range = self.shape.version_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.version_byte_range(); + unchecked::read_at(self.data, range.start) } /// Offset in bytes from the start of this table to the item variation store table. pub fn item_variation_store_offset(&self) -> Offset32 { - let range = self.shape.item_variation_store_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.item_variation_store_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`item_variation_store_offset`][Self::item_variation_store_offset]. @@ -86,8 +82,8 @@ impl<'a> Hvar<'a> { /// Offset in bytes from the start of this table to the delta-set index mapping for advance widths (may be NULL). pub fn advance_width_mapping_offset(&self) -> Nullable { - let range = self.shape.advance_width_mapping_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.advance_width_mapping_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`advance_width_mapping_offset`][Self::advance_width_mapping_offset]. @@ -98,8 +94,8 @@ impl<'a> Hvar<'a> { /// Offset in bytes from the start of this table to the delta-set index mapping for left side bearings (may be NULL). pub fn lsb_mapping_offset(&self) -> Nullable { - let range = self.shape.lsb_mapping_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.lsb_mapping_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`lsb_mapping_offset`][Self::lsb_mapping_offset]. @@ -110,8 +106,8 @@ impl<'a> Hvar<'a> { /// Offset in bytes from the start of this table to the delta-set index mapping for right side bearings (may be NULL). pub fn rsb_mapping_offset(&self) -> Nullable { - let range = self.shape.rsb_mapping_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.rsb_mapping_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`rsb_mapping_offset`][Self::rsb_mapping_offset]. diff --git a/read-fonts/generated/generated_ift.rs b/read-fonts/generated/generated_ift.rs index 19699fb4e..3308a03b3 100644 --- a/read-fonts/generated/generated_ift.rs +++ b/read-fonts/generated/generated_ift.rs @@ -431,14 +431,42 @@ impl Format for PatchMapFormat1Marker { /// [Patch Map Format Format 1](https://w3c.github.io/IFT/Overview.html#patch-map-format-1) #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct PatchMapFormat1Marker { - applied_entries_bitmap_byte_len: usize, - url_template_byte_len: usize, - cff_charstrings_offset_byte_start: Option, - cff2_charstrings_offset_byte_start: Option, +pub struct PatchMapFormat1Marker; + +impl<'a> MinByteRange for PatchMapFormat1<'a> { + fn min_byte_range(&self) -> Range { + 0..self.patch_format_byte_range().end + } } -impl PatchMapFormat1Marker { +impl<'a> FontRead<'a> for PatchMapFormat1<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// [Patch Map Format Format 1](https://w3c.github.io/IFT/Overview.html#patch-map-format-1) +pub type PatchMapFormat1<'a> = TableRef<'a, PatchMapFormat1Marker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> PatchMapFormat1<'a> { + fn applied_entries_bitmap_byte_len(&self, start: usize) -> usize { + let _ = start; + (transforms::max_value_bitmap_len(self.max_entry_index())) + .checked_mul(u8::RAW_BYTE_LEN) + .unwrap() + } + fn url_template_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.url_template_length()) as usize) + .checked_mul(u8::RAW_BYTE_LEN) + .unwrap() + } + pub fn format_byte_range(&self) -> Range { let start = 0; start..start + u8::RAW_BYTE_LEN @@ -496,7 +524,7 @@ impl PatchMapFormat1Marker { pub fn applied_entries_bitmap_byte_range(&self) -> Range { let start = self.feature_map_offset_byte_range().end; - start..start + self.applied_entries_bitmap_byte_len + start..start + self.applied_entries_bitmap_byte_len(start) } pub fn url_template_length_byte_range(&self) -> Range { @@ -506,7 +534,7 @@ impl PatchMapFormat1Marker { pub fn url_template_byte_range(&self) -> Range { let start = self.url_template_length_byte_range().end; - start..start + self.url_template_byte_len + start..start + self.url_template_byte_len(start) } pub fn patch_format_byte_range(&self) -> Range { @@ -515,112 +543,70 @@ impl PatchMapFormat1Marker { } pub fn cff_charstrings_offset_byte_range(&self) -> Option> { - let start = self.cff_charstrings_offset_byte_start?; - Some(start..start + u32::RAW_BYTE_LEN) + if self + .field_flags() + .contains(PatchMapFieldPresenceFlags::CFF_CHARSTRINGS_OFFSET) + { + let start = self.patch_format_byte_range().end; + Some(start..start + u32::RAW_BYTE_LEN) + } else { + None + } } pub fn cff2_charstrings_offset_byte_range(&self) -> Option> { - let start = self.cff2_charstrings_offset_byte_start?; - Some(start..start + u32::RAW_BYTE_LEN) - } -} - -impl MinByteRange for PatchMapFormat1Marker { - fn min_byte_range(&self) -> Range { - 0..self.patch_format_byte_range().end - } -} - -impl<'a> FontRead<'a> for PatchMapFormat1<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - let field_flags: PatchMapFieldPresenceFlags = cursor.read()?; - cursor.advance::(); - let max_entry_index: u16 = cursor.read()?; - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - let applied_entries_bitmap_byte_len = (transforms::max_value_bitmap_len(max_entry_index)) - .checked_mul(u8::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(applied_entries_bitmap_byte_len); - let url_template_length: u16 = cursor.read()?; - let url_template_byte_len = (url_template_length as usize) - .checked_mul(u8::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(url_template_byte_len); - cursor.advance::(); - let cff_charstrings_offset_byte_start = field_flags - .contains(PatchMapFieldPresenceFlags::CFF_CHARSTRINGS_OFFSET) - .then(|| cursor.position()) - .transpose()?; - field_flags - .contains(PatchMapFieldPresenceFlags::CFF_CHARSTRINGS_OFFSET) - .then(|| cursor.advance::()); - let cff2_charstrings_offset_byte_start = field_flags - .contains(PatchMapFieldPresenceFlags::CFF2_CHARSTRINGS_OFFSET) - .then(|| cursor.position()) - .transpose()?; - field_flags + if self + .field_flags() .contains(PatchMapFieldPresenceFlags::CFF2_CHARSTRINGS_OFFSET) - .then(|| cursor.advance::()); - cursor.finish(PatchMapFormat1Marker { - applied_entries_bitmap_byte_len, - url_template_byte_len, - cff_charstrings_offset_byte_start, - cff2_charstrings_offset_byte_start, - }) + { + let start = self + .cff_charstrings_offset_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| self.patch_format_byte_range().end); + Some(start..start + u32::RAW_BYTE_LEN) + } else { + None + } } -} - -/// [Patch Map Format Format 1](https://w3c.github.io/IFT/Overview.html#patch-map-format-1) -pub type PatchMapFormat1<'a> = TableRef<'a, PatchMapFormat1Marker>; -#[allow(clippy::needless_lifetimes)] -impl<'a> PatchMapFormat1<'a> { /// Format identifier: format = 1 pub fn format(&self) -> u8 { - let range = self.shape.format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.format_byte_range(); + unchecked::read_at(self.data, range.start) } pub fn field_flags(&self) -> PatchMapFieldPresenceFlags { - let range = self.shape.field_flags_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.field_flags_byte_range(); + unchecked::read_at(self.data, range.start) } /// Unique ID that identifies compatible patches. pub fn compatibility_id(&self) -> CompatibilityId { - let range = self.shape.compatibility_id_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.compatibility_id_byte_range(); + unchecked::read_at(self.data, range.start) } /// Largest entry index which appears in either the glyph map or feature map. pub fn max_entry_index(&self) -> u16 { - let range = self.shape.max_entry_index_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.max_entry_index_byte_range(); + unchecked::read_at(self.data, range.start) } /// Largest entry index which appears in the glyph map. pub fn max_glyph_map_entry_index(&self) -> u16 { - let range = self.shape.max_glyph_map_entry_index_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.max_glyph_map_entry_index_byte_range(); + unchecked::read_at(self.data, range.start) } pub fn glyph_count(&self) -> Uint24 { - let range = self.shape.glyph_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.glyph_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Sub table that maps glyph ids to entry indices. pub fn glyph_map_offset(&self) -> Offset32 { - let range = self.shape.glyph_map_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.glyph_map_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`glyph_map_offset`][Self::glyph_map_offset]. @@ -632,8 +618,8 @@ impl<'a> PatchMapFormat1<'a> { /// Sub table that maps feature and glyph ids to entry indices. pub fn feature_map_offset(&self) -> Nullable { - let range = self.shape.feature_map_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.feature_map_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`feature_map_offset`][Self::feature_map_offset]. @@ -644,34 +630,34 @@ impl<'a> PatchMapFormat1<'a> { } pub fn applied_entries_bitmap(&self) -> &'a [u8] { - let range = self.shape.applied_entries_bitmap_byte_range(); - self.data.read_array(range).unwrap() + let range = self.applied_entries_bitmap_byte_range(); + unchecked::read_array(self.data, range) } pub fn url_template_length(&self) -> u16 { - let range = self.shape.url_template_length_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.url_template_length_byte_range(); + unchecked::read_at(self.data, range.start) } pub fn url_template(&self) -> &'a [u8] { - let range = self.shape.url_template_byte_range(); - self.data.read_array(range).unwrap() + let range = self.url_template_byte_range(); + unchecked::read_array(self.data, range) } /// Patch format number for patches referenced by this mapping. pub fn patch_format(&self) -> u8 { - let range = self.shape.patch_format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.patch_format_byte_range(); + unchecked::read_at(self.data, range.start) } pub fn cff_charstrings_offset(&self) -> Option { - let range = self.shape.cff_charstrings_offset_byte_range()?; - Some(self.data.read_at(range.start).unwrap()) + let range = self.cff_charstrings_offset_byte_range()?; + Some(unchecked::read_at(self.data, range.start)) } pub fn cff2_charstrings_offset(&self) -> Option { - let range = self.shape.cff2_charstrings_offset_byte_range()?; - Some(self.data.read_at(range.start).unwrap()) + let range = self.cff2_charstrings_offset_byte_range()?; + Some(unchecked::read_at(self.data, range.start)) } } @@ -742,24 +728,9 @@ impl<'a> std::fmt::Debug for PatchMapFormat1<'a> { #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct GlyphMapMarker { - max_entry_index: u16, - entry_index_byte_len: usize, -} - -impl GlyphMapMarker { - pub fn first_mapped_glyph_byte_range(&self) -> Range { - let start = 0; - start..start + u16::RAW_BYTE_LEN - } - - pub fn entry_index_byte_range(&self) -> Range { - let start = self.first_mapped_glyph_byte_range().end; - start..start + self.entry_index_byte_len - } -} +pub struct GlyphMapMarker; -impl MinByteRange for GlyphMapMarker { +impl<'a> MinByteRange for GlyphMap<'a> { fn min_byte_range(&self) -> Range { 0..self.entry_index_byte_range().end } @@ -771,16 +742,11 @@ impl ReadArgs for GlyphMap<'_> { impl<'a> FontReadWithArgs<'a> for GlyphMap<'a> { fn read_with_args(data: FontData<'a>, args: &(Uint24, u16)) -> Result { - let (glyph_count, max_entry_index) = *args; - let mut cursor = data.cursor(); - let first_mapped_glyph: u16 = cursor.read()?; - let entry_index_byte_len = (transforms::subtract(glyph_count, first_mapped_glyph)) - .checked_mul(::compute_size(&max_entry_index)?) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(entry_index_byte_len); - cursor.finish(GlyphMapMarker { - max_entry_index, - entry_index_byte_len, + let args = *args; + Ok(TableRef { + args, + data, + _marker: std::marker::PhantomData, }) } } @@ -800,24 +766,43 @@ impl<'a> GlyphMap<'a> { } } -pub type GlyphMap<'a> = TableRef<'a, GlyphMapMarker>; +pub type GlyphMap<'a> = TableRef<'a, GlyphMapMarker, (Uint24, u16)>; #[allow(clippy::needless_lifetimes)] impl<'a> GlyphMap<'a> { + fn entry_index_byte_len(&self, start: usize) -> usize { + let _ = start; + (transforms::subtract(self.args.0, self.first_mapped_glyph())) + .checked_mul(::compute_size(&self.args.1).unwrap()) + .unwrap() + } + + pub fn first_mapped_glyph_byte_range(&self) -> Range { + let start = 0; + start..start + u16::RAW_BYTE_LEN + } + + pub fn entry_index_byte_range(&self) -> Range { + let start = self.first_mapped_glyph_byte_range().end; + start..start + self.entry_index_byte_len(start) + } + pub fn first_mapped_glyph(&self) -> u16 { - let range = self.shape.first_mapped_glyph_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.first_mapped_glyph_byte_range(); + unchecked::read_at(self.data, range.start) } pub fn entry_index(&self) -> ComputedArray<'a, U8Or16> { - let range = self.shape.entry_index_byte_range(); - self.data - .read_with_args(range, &self.max_entry_index()) - .unwrap() + let range = self.entry_index_byte_range(); + unchecked::read_with_args(self.data, range, &self.max_entry_index()) + } + + pub(crate) fn glyph_count(&self) -> Uint24 { + self.args.0 } pub(crate) fn max_entry_index(&self) -> u16 { - self.shape.max_entry_index + self.args.1 } } @@ -845,30 +830,9 @@ impl<'a> std::fmt::Debug for GlyphMap<'a> { #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct FeatureMapMarker { - max_entry_index: u16, - feature_records_byte_len: usize, - entry_map_data_byte_len: usize, -} - -impl FeatureMapMarker { - pub fn feature_count_byte_range(&self) -> Range { - let start = 0; - start..start + u16::RAW_BYTE_LEN - } - - pub fn feature_records_byte_range(&self) -> Range { - let start = self.feature_count_byte_range().end; - start..start + self.feature_records_byte_len - } +pub struct FeatureMapMarker; - pub fn entry_map_data_byte_range(&self) -> Range { - let start = self.feature_records_byte_range().end; - start..start + self.entry_map_data_byte_len - } -} - -impl MinByteRange for FeatureMapMarker { +impl<'a> MinByteRange for FeatureMap<'a> { fn min_byte_range(&self) -> Range { 0..self.entry_map_data_byte_range().end } @@ -880,22 +844,11 @@ impl ReadArgs for FeatureMap<'_> { impl<'a> FontReadWithArgs<'a> for FeatureMap<'a> { fn read_with_args(data: FontData<'a>, args: &u16) -> Result { - let max_entry_index = *args; - let mut cursor = data.cursor(); - let feature_count: u16 = cursor.read()?; - let feature_records_byte_len = (feature_count as usize) - .checked_mul(::compute_size( - &max_entry_index, - )?) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(feature_records_byte_len); - let entry_map_data_byte_len = - cursor.remaining_bytes() / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN; - cursor.advance_by(entry_map_data_byte_len); - cursor.finish(FeatureMapMarker { - max_entry_index, - feature_records_byte_len, - entry_map_data_byte_len, + let args = *args; + Ok(TableRef { + args, + data, + _marker: std::marker::PhantomData, }) } } @@ -911,29 +864,56 @@ impl<'a> FeatureMap<'a> { } } -pub type FeatureMap<'a> = TableRef<'a, FeatureMapMarker>; +pub type FeatureMap<'a> = TableRef<'a, FeatureMapMarker, u16>; #[allow(clippy::needless_lifetimes)] impl<'a> FeatureMap<'a> { + fn feature_records_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.feature_count()) as usize) + .checked_mul(::compute_size(&self.args).unwrap()) + .unwrap() + } + fn entry_map_data_byte_len(&self, start: usize) -> usize { + let _ = start; + { + let remaining = self.data.len().saturating_sub(start); + remaining / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN + } + } + + pub fn feature_count_byte_range(&self) -> Range { + let start = 0; + start..start + u16::RAW_BYTE_LEN + } + + pub fn feature_records_byte_range(&self) -> Range { + let start = self.feature_count_byte_range().end; + start..start + self.feature_records_byte_len(start) + } + + pub fn entry_map_data_byte_range(&self) -> Range { + let start = self.feature_records_byte_range().end; + start..start + self.entry_map_data_byte_len(start) + } + pub fn feature_count(&self) -> u16 { - let range = self.shape.feature_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.feature_count_byte_range(); + unchecked::read_at(self.data, range.start) } pub fn feature_records(&self) -> ComputedArray<'a, FeatureRecord> { - let range = self.shape.feature_records_byte_range(); - self.data - .read_with_args(range, &self.max_entry_index()) - .unwrap() + let range = self.feature_records_byte_range(); + unchecked::read_with_args(self.data, range, &self.max_entry_index()) } pub fn entry_map_data(&self) -> &'a [u8] { - let range = self.shape.entry_map_data_byte_range(); - self.data.read_array(range).unwrap() + let range = self.entry_map_data_byte_range(); + unchecked::read_array(self.data, range) } pub(crate) fn max_entry_index(&self) -> u16 { - self.shape.max_entry_index + self.args } } @@ -1132,13 +1112,36 @@ impl Format for PatchMapFormat2Marker { /// [Patch Map Format Format 2](https://w3c.github.io/IFT/Overview.html#patch-map-format-2) #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct PatchMapFormat2Marker { - url_template_byte_len: usize, - cff_charstrings_offset_byte_start: Option, - cff2_charstrings_offset_byte_start: Option, +pub struct PatchMapFormat2Marker; + +impl<'a> MinByteRange for PatchMapFormat2<'a> { + fn min_byte_range(&self) -> Range { + 0..self.url_template_byte_range().end + } +} + +impl<'a> FontRead<'a> for PatchMapFormat2<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } } -impl PatchMapFormat2Marker { +/// [Patch Map Format Format 2](https://w3c.github.io/IFT/Overview.html#patch-map-format-2) +pub type PatchMapFormat2<'a> = TableRef<'a, PatchMapFormat2Marker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> PatchMapFormat2<'a> { + fn url_template_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.url_template_length()) as usize) + .checked_mul(u8::RAW_BYTE_LEN) + .unwrap() + } + pub fn format_byte_range(&self) -> Range { let start = 0; start..start + u8::RAW_BYTE_LEN @@ -1196,102 +1199,67 @@ impl PatchMapFormat2Marker { pub fn url_template_byte_range(&self) -> Range { let start = self.url_template_length_byte_range().end; - start..start + self.url_template_byte_len + start..start + self.url_template_byte_len(start) } pub fn cff_charstrings_offset_byte_range(&self) -> Option> { - let start = self.cff_charstrings_offset_byte_start?; - Some(start..start + u32::RAW_BYTE_LEN) + if self + .field_flags() + .contains(PatchMapFieldPresenceFlags::CFF_CHARSTRINGS_OFFSET) + { + let start = self.url_template_byte_range().end; + Some(start..start + u32::RAW_BYTE_LEN) + } else { + None + } } pub fn cff2_charstrings_offset_byte_range(&self) -> Option> { - let start = self.cff2_charstrings_offset_byte_start?; - Some(start..start + u32::RAW_BYTE_LEN) - } -} - -impl MinByteRange for PatchMapFormat2Marker { - fn min_byte_range(&self) -> Range { - 0..self.url_template_byte_range().end - } -} - -impl<'a> FontRead<'a> for PatchMapFormat2<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - let field_flags: PatchMapFieldPresenceFlags = cursor.read()?; - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - let url_template_length: u16 = cursor.read()?; - let url_template_byte_len = (url_template_length as usize) - .checked_mul(u8::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(url_template_byte_len); - let cff_charstrings_offset_byte_start = field_flags - .contains(PatchMapFieldPresenceFlags::CFF_CHARSTRINGS_OFFSET) - .then(|| cursor.position()) - .transpose()?; - field_flags - .contains(PatchMapFieldPresenceFlags::CFF_CHARSTRINGS_OFFSET) - .then(|| cursor.advance::()); - let cff2_charstrings_offset_byte_start = field_flags - .contains(PatchMapFieldPresenceFlags::CFF2_CHARSTRINGS_OFFSET) - .then(|| cursor.position()) - .transpose()?; - field_flags + if self + .field_flags() .contains(PatchMapFieldPresenceFlags::CFF2_CHARSTRINGS_OFFSET) - .then(|| cursor.advance::()); - cursor.finish(PatchMapFormat2Marker { - url_template_byte_len, - cff_charstrings_offset_byte_start, - cff2_charstrings_offset_byte_start, - }) + { + let start = self + .cff_charstrings_offset_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| self.url_template_byte_range().end); + Some(start..start + u32::RAW_BYTE_LEN) + } else { + None + } } -} -/// [Patch Map Format Format 2](https://w3c.github.io/IFT/Overview.html#patch-map-format-2) -pub type PatchMapFormat2<'a> = TableRef<'a, PatchMapFormat2Marker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> PatchMapFormat2<'a> { /// Format identifier: format = 2 pub fn format(&self) -> u8 { - let range = self.shape.format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.format_byte_range(); + unchecked::read_at(self.data, range.start) } pub fn field_flags(&self) -> PatchMapFieldPresenceFlags { - let range = self.shape.field_flags_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.field_flags_byte_range(); + unchecked::read_at(self.data, range.start) } /// Unique ID that identifies compatible patches. pub fn compatibility_id(&self) -> CompatibilityId { - let range = self.shape.compatibility_id_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.compatibility_id_byte_range(); + unchecked::read_at(self.data, range.start) } /// Patch format number for patches referenced by this mapping. pub fn default_patch_format(&self) -> u8 { - let range = self.shape.default_patch_format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.default_patch_format_byte_range(); + unchecked::read_at(self.data, range.start) } pub fn entry_count(&self) -> Uint24 { - let range = self.shape.entry_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.entry_count_byte_range(); + unchecked::read_at(self.data, range.start) } pub fn entries_offset(&self) -> Offset32 { - let range = self.shape.entries_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.entries_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`entries_offset`][Self::entries_offset]. @@ -1301,8 +1269,8 @@ impl<'a> PatchMapFormat2<'a> { } pub fn entry_id_string_data_offset(&self) -> Nullable { - let range = self.shape.entry_id_string_data_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.entry_id_string_data_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`entry_id_string_data_offset`][Self::entry_id_string_data_offset]. @@ -1312,23 +1280,23 @@ impl<'a> PatchMapFormat2<'a> { } pub fn url_template_length(&self) -> u16 { - let range = self.shape.url_template_length_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.url_template_length_byte_range(); + unchecked::read_at(self.data, range.start) } pub fn url_template(&self) -> &'a [u8] { - let range = self.shape.url_template_byte_range(); - self.data.read_array(range).unwrap() + let range = self.url_template_byte_range(); + unchecked::read_array(self.data, range) } pub fn cff_charstrings_offset(&self) -> Option { - let range = self.shape.cff_charstrings_offset_byte_range()?; - Some(self.data.read_at(range.start).unwrap()) + let range = self.cff_charstrings_offset_byte_range()?; + Some(unchecked::read_at(self.data, range.start)) } pub fn cff2_charstrings_offset(&self) -> Option { - let range = self.shape.cff2_charstrings_offset_byte_range()?; - Some(self.data.read_at(range.start).unwrap()) + let range = self.cff2_charstrings_offset_byte_range()?; + Some(unchecked::read_at(self.data, range.start)) } } @@ -1396,18 +1364,9 @@ impl<'a> std::fmt::Debug for PatchMapFormat2<'a> { #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct MappingEntriesMarker { - entry_data_byte_len: usize, -} - -impl MappingEntriesMarker { - pub fn entry_data_byte_range(&self) -> Range { - let start = 0; - start..start + self.entry_data_byte_len - } -} +pub struct MappingEntriesMarker; -impl MinByteRange for MappingEntriesMarker { +impl<'a> MinByteRange for MappingEntries<'a> { fn min_byte_range(&self) -> Range { 0..self.entry_data_byte_range().end } @@ -1415,22 +1374,34 @@ impl MinByteRange for MappingEntriesMarker { impl<'a> FontRead<'a> for MappingEntries<'a> { fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - let entry_data_byte_len = cursor.remaining_bytes() / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN; - cursor.advance_by(entry_data_byte_len); - cursor.finish(MappingEntriesMarker { - entry_data_byte_len, + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, }) } } -pub type MappingEntries<'a> = TableRef<'a, MappingEntriesMarker>; +pub type MappingEntries<'a> = TableRef<'a, MappingEntriesMarker, ()>; #[allow(clippy::needless_lifetimes)] impl<'a> MappingEntries<'a> { + fn entry_data_byte_len(&self, start: usize) -> usize { + let _ = start; + { + let remaining = self.data.len().saturating_sub(start); + remaining / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN + } + } + + pub fn entry_data_byte_range(&self) -> Range { + let start = 0; + start..start + self.entry_data_byte_len(start) + } + pub fn entry_data(&self) -> &'a [u8] { - let range = self.shape.entry_data_byte_range(); - self.data.read_array(range).unwrap() + let range = self.entry_data_byte_range(); + unchecked::read_array(self.data, range) } } @@ -1457,53 +1428,186 @@ impl<'a> std::fmt::Debug for MappingEntries<'a> { #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct EntryDataMarker { - feature_count_byte_start: Option, - feature_tags_byte_start: Option, - feature_tags_byte_len: Option, - design_space_count_byte_start: Option, - design_space_segments_byte_start: Option, - design_space_segments_byte_len: Option, - match_mode_and_count_byte_start: Option, - child_indices_byte_start: Option, - child_indices_byte_len: Option, - trailing_data_byte_len: usize, -} - -impl EntryDataMarker { +pub struct EntryDataMarker; + +impl<'a> MinByteRange for EntryData<'a> { + fn min_byte_range(&self) -> Range { + 0..self.trailing_data_byte_range().end + } +} + +impl<'a> FontRead<'a> for EntryData<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +pub type EntryData<'a> = TableRef<'a, EntryDataMarker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> EntryData<'a> { + fn feature_tags_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.feature_count().unwrap_or_default()) as usize) + .checked_mul(Tag::RAW_BYTE_LEN) + .unwrap() + } + fn design_space_segments_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.design_space_count().unwrap_or_default()) as usize) + .checked_mul(DesignSpaceSegment::RAW_BYTE_LEN) + .unwrap() + } + fn child_indices_byte_len(&self, start: usize) -> usize { + let _ = start; + (usize::try_from(self.match_mode_and_count().unwrap_or_default()).unwrap_or_default()) + .checked_mul(Uint24::RAW_BYTE_LEN) + .unwrap() + } + fn trailing_data_byte_len(&self, start: usize) -> usize { + let _ = start; + { + let remaining = self.data.len().saturating_sub(start); + remaining / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN + } + } + pub fn format_flags_byte_range(&self) -> Range { let start = 0; start..start + EntryFormatFlags::RAW_BYTE_LEN } pub fn feature_count_byte_range(&self) -> Option> { - let start = self.feature_count_byte_start?; - Some(start..start + u8::RAW_BYTE_LEN) + if self + .format_flags() + .contains(EntryFormatFlags::FEATURES_AND_DESIGN_SPACE) + { + let start = self.format_flags_byte_range().end; + Some(start..start + u8::RAW_BYTE_LEN) + } else { + None + } } pub fn feature_tags_byte_range(&self) -> Option> { - let start = self.feature_tags_byte_start?; - Some(start..start + self.feature_tags_byte_len?) + if self + .format_flags() + .contains(EntryFormatFlags::FEATURES_AND_DESIGN_SPACE) + { + let start = self + .feature_count_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| self.format_flags_byte_range().end); + Some(start..start + self.feature_tags_byte_len(start)) + } else { + None + } } pub fn design_space_count_byte_range(&self) -> Option> { - let start = self.design_space_count_byte_start?; - Some(start..start + u16::RAW_BYTE_LEN) + if self + .format_flags() + .contains(EntryFormatFlags::FEATURES_AND_DESIGN_SPACE) + { + let start = self + .feature_tags_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| { + self.feature_count_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| self.format_flags_byte_range().end) + }); + Some(start..start + u16::RAW_BYTE_LEN) + } else { + None + } } pub fn design_space_segments_byte_range(&self) -> Option> { - let start = self.design_space_segments_byte_start?; - Some(start..start + self.design_space_segments_byte_len?) + if self + .format_flags() + .contains(EntryFormatFlags::FEATURES_AND_DESIGN_SPACE) + { + let start = self + .design_space_count_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| { + self.feature_tags_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| { + self.feature_count_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| self.format_flags_byte_range().end) + }) + }); + Some(start..start + self.design_space_segments_byte_len(start)) + } else { + None + } } pub fn match_mode_and_count_byte_range(&self) -> Option> { - let start = self.match_mode_and_count_byte_start?; - Some(start..start + MatchModeAndCount::RAW_BYTE_LEN) + if self + .format_flags() + .contains(EntryFormatFlags::CHILD_INDICES) + { + let start = self + .design_space_segments_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| { + self.design_space_count_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| { + self.feature_tags_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| { + self.feature_count_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| self.format_flags_byte_range().end) + }) + }) + }); + Some(start..start + MatchModeAndCount::RAW_BYTE_LEN) + } else { + None + } } pub fn child_indices_byte_range(&self) -> Option> { - let start = self.child_indices_byte_start?; - Some(start..start + self.child_indices_byte_len?) + if self + .format_flags() + .contains(EntryFormatFlags::CHILD_INDICES) + { + let start = self + .match_mode_and_count_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| { + self.design_space_segments_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| { + self.design_space_count_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| { + self.feature_tags_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| { + self.feature_count_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| { + self.format_flags_byte_range().end + }) + }) + }) + }) + }); + Some(start..start + self.child_indices_byte_len(start)) + } else { + None + } } pub fn trailing_data_byte_range(&self) -> Range { @@ -1533,148 +1637,47 @@ impl EntryDataMarker { }) }) }); - start..start + self.trailing_data_byte_len - } -} - -impl MinByteRange for EntryDataMarker { - fn min_byte_range(&self) -> Range { - 0..self.trailing_data_byte_range().end + start..start + self.trailing_data_byte_len(start) } -} -impl<'a> FontRead<'a> for EntryData<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - let format_flags: EntryFormatFlags = cursor.read()?; - let feature_count_byte_start = format_flags - .contains(EntryFormatFlags::FEATURES_AND_DESIGN_SPACE) - .then(|| cursor.position()) - .transpose()?; - let feature_count = format_flags - .contains(EntryFormatFlags::FEATURES_AND_DESIGN_SPACE) - .then(|| cursor.read::()) - .transpose()? - .unwrap_or_default(); - let feature_tags_byte_start = format_flags - .contains(EntryFormatFlags::FEATURES_AND_DESIGN_SPACE) - .then(|| cursor.position()) - .transpose()?; - let feature_tags_byte_len = format_flags - .contains(EntryFormatFlags::FEATURES_AND_DESIGN_SPACE) - .then_some( - (feature_count as usize) - .checked_mul(Tag::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?, - ); - if let Some(value) = feature_tags_byte_len { - cursor.advance_by(value); - } - let design_space_count_byte_start = format_flags - .contains(EntryFormatFlags::FEATURES_AND_DESIGN_SPACE) - .then(|| cursor.position()) - .transpose()?; - let design_space_count = format_flags - .contains(EntryFormatFlags::FEATURES_AND_DESIGN_SPACE) - .then(|| cursor.read::()) - .transpose()? - .unwrap_or_default(); - let design_space_segments_byte_start = format_flags - .contains(EntryFormatFlags::FEATURES_AND_DESIGN_SPACE) - .then(|| cursor.position()) - .transpose()?; - let design_space_segments_byte_len = format_flags - .contains(EntryFormatFlags::FEATURES_AND_DESIGN_SPACE) - .then_some( - (design_space_count as usize) - .checked_mul(DesignSpaceSegment::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?, - ); - if let Some(value) = design_space_segments_byte_len { - cursor.advance_by(value); - } - let match_mode_and_count_byte_start = format_flags - .contains(EntryFormatFlags::CHILD_INDICES) - .then(|| cursor.position()) - .transpose()?; - let match_mode_and_count = format_flags - .contains(EntryFormatFlags::CHILD_INDICES) - .then(|| cursor.read::()) - .transpose()? - .unwrap_or_default(); - let child_indices_byte_start = format_flags - .contains(EntryFormatFlags::CHILD_INDICES) - .then(|| cursor.position()) - .transpose()?; - let child_indices_byte_len = format_flags - .contains(EntryFormatFlags::CHILD_INDICES) - .then_some( - (usize::try_from(match_mode_and_count).unwrap_or_default()) - .checked_mul(Uint24::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?, - ); - if let Some(value) = child_indices_byte_len { - cursor.advance_by(value); - } - let trailing_data_byte_len = cursor.remaining_bytes() / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN; - cursor.advance_by(trailing_data_byte_len); - cursor.finish(EntryDataMarker { - feature_count_byte_start, - feature_tags_byte_start, - feature_tags_byte_len, - design_space_count_byte_start, - design_space_segments_byte_start, - design_space_segments_byte_len, - match_mode_and_count_byte_start, - child_indices_byte_start, - child_indices_byte_len, - trailing_data_byte_len, - }) - } -} - -pub type EntryData<'a> = TableRef<'a, EntryDataMarker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> EntryData<'a> { pub fn format_flags(&self) -> EntryFormatFlags { - let range = self.shape.format_flags_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.format_flags_byte_range(); + unchecked::read_at(self.data, range.start) } pub fn feature_count(&self) -> Option { - let range = self.shape.feature_count_byte_range()?; - Some(self.data.read_at(range.start).unwrap()) + let range = self.feature_count_byte_range()?; + Some(unchecked::read_at(self.data, range.start)) } pub fn feature_tags(&self) -> Option<&'a [BigEndian]> { - let range = self.shape.feature_tags_byte_range()?; - Some(self.data.read_array(range).unwrap()) + let range = self.feature_tags_byte_range()?; + Some(unchecked::read_array(self.data, range)) } pub fn design_space_count(&self) -> Option { - let range = self.shape.design_space_count_byte_range()?; - Some(self.data.read_at(range.start).unwrap()) + let range = self.design_space_count_byte_range()?; + Some(unchecked::read_at(self.data, range.start)) } pub fn design_space_segments(&self) -> Option<&'a [DesignSpaceSegment]> { - let range = self.shape.design_space_segments_byte_range()?; - Some(self.data.read_array(range).unwrap()) + let range = self.design_space_segments_byte_range()?; + Some(unchecked::read_array(self.data, range)) } pub fn match_mode_and_count(&self) -> Option { - let range = self.shape.match_mode_and_count_byte_range()?; - Some(self.data.read_at(range.start).unwrap()) + let range = self.match_mode_and_count_byte_range()?; + Some(unchecked::read_at(self.data, range.start)) } pub fn child_indices(&self) -> Option<&'a [BigEndian]> { - let range = self.shape.child_indices_byte_range()?; - Some(self.data.read_array(range).unwrap()) + let range = self.child_indices_byte_range()?; + Some(unchecked::read_array(self.data, range)) } pub fn trailing_data(&self) -> &'a [u8] { - let range = self.shape.trailing_data_byte_range(); - self.data.read_array(range).unwrap() + let range = self.trailing_data_byte_range(); + unchecked::read_array(self.data, range) } } @@ -2102,18 +2105,9 @@ impl<'a> SomeRecord<'a> for DesignSpaceSegment { #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct IdStringDataMarker { - id_data_byte_len: usize, -} - -impl IdStringDataMarker { - pub fn id_data_byte_range(&self) -> Range { - let start = 0; - start..start + self.id_data_byte_len - } -} +pub struct IdStringDataMarker; -impl MinByteRange for IdStringDataMarker { +impl<'a> MinByteRange for IdStringData<'a> { fn min_byte_range(&self) -> Range { 0..self.id_data_byte_range().end } @@ -2121,20 +2115,34 @@ impl MinByteRange for IdStringDataMarker { impl<'a> FontRead<'a> for IdStringData<'a> { fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - let id_data_byte_len = cursor.remaining_bytes() / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN; - cursor.advance_by(id_data_byte_len); - cursor.finish(IdStringDataMarker { id_data_byte_len }) + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) } } -pub type IdStringData<'a> = TableRef<'a, IdStringDataMarker>; +pub type IdStringData<'a> = TableRef<'a, IdStringDataMarker, ()>; #[allow(clippy::needless_lifetimes)] impl<'a> IdStringData<'a> { + fn id_data_byte_len(&self, start: usize) -> usize { + let _ = start; + { + let remaining = self.data.len().saturating_sub(start); + remaining / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN + } + } + + pub fn id_data_byte_range(&self) -> Range { + let start = 0; + start..start + self.id_data_byte_len(start) + } + pub fn id_data(&self) -> &'a [u8] { - let range = self.shape.id_data_byte_range(); - self.data.read_array(range).unwrap() + let range = self.id_data_byte_range(); + unchecked::read_array(self.data, range) } } @@ -2162,11 +2170,36 @@ impl<'a> std::fmt::Debug for IdStringData<'a> { /// [Table Keyed Patch](https://w3c.github.io/IFT/Overview.html#table-keyed) #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct TableKeyedPatchMarker { - patch_offsets_byte_len: usize, +pub struct TableKeyedPatchMarker; + +impl<'a> MinByteRange for TableKeyedPatch<'a> { + fn min_byte_range(&self) -> Range { + 0..self.patch_offsets_byte_range().end + } +} + +impl<'a> FontRead<'a> for TableKeyedPatch<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } } -impl TableKeyedPatchMarker { +/// [Table Keyed Patch](https://w3c.github.io/IFT/Overview.html#table-keyed) +pub type TableKeyedPatch<'a> = TableRef<'a, TableKeyedPatchMarker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> TableKeyedPatch<'a> { + fn patch_offsets_byte_len(&self, start: usize) -> usize { + let _ = start; + (transforms::add(self.patches_count(), 1_usize)) + .checked_mul(Offset32::RAW_BYTE_LEN) + .unwrap() + } + pub fn format_byte_range(&self) -> Range { let start = 0; start..start + Tag::RAW_BYTE_LEN @@ -2189,57 +2222,28 @@ impl TableKeyedPatchMarker { pub fn patch_offsets_byte_range(&self) -> Range { let start = self.patches_count_byte_range().end; - start..start + self.patch_offsets_byte_len + start..start + self.patch_offsets_byte_len(start) } -} -impl MinByteRange for TableKeyedPatchMarker { - fn min_byte_range(&self) -> Range { - 0..self.patch_offsets_byte_range().end - } -} - -impl<'a> FontRead<'a> for TableKeyedPatch<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - let patches_count: u16 = cursor.read()?; - let patch_offsets_byte_len = (transforms::add(patches_count, 1_usize)) - .checked_mul(Offset32::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(patch_offsets_byte_len); - cursor.finish(TableKeyedPatchMarker { - patch_offsets_byte_len, - }) - } -} - -/// [Table Keyed Patch](https://w3c.github.io/IFT/Overview.html#table-keyed) -pub type TableKeyedPatch<'a> = TableRef<'a, TableKeyedPatchMarker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> TableKeyedPatch<'a> { pub fn format(&self) -> Tag { - let range = self.shape.format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Unique ID that identifies compatible patches. pub fn compatibility_id(&self) -> CompatibilityId { - let range = self.shape.compatibility_id_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.compatibility_id_byte_range(); + unchecked::read_at(self.data, range.start) } pub fn patches_count(&self) -> u16 { - let range = self.shape.patches_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.patches_count_byte_range(); + unchecked::read_at(self.data, range.start) } pub fn patch_offsets(&self) -> &'a [BigEndian] { - let range = self.shape.patch_offsets_byte_range(); - self.data.read_array(range).unwrap() + let range = self.patch_offsets_byte_range(); + unchecked::read_array(self.data, range) } /// A dynamically resolving wrapper for [`patch_offsets`][Self::patch_offsets]. @@ -2293,11 +2297,37 @@ impl<'a> std::fmt::Debug for TableKeyedPatch<'a> { /// [TablePatch](https://w3c.github.io/IFT/Overview.html#tablepatch) #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct TablePatchMarker { - brotli_stream_byte_len: usize, +pub struct TablePatchMarker; + +impl<'a> MinByteRange for TablePatch<'a> { + fn min_byte_range(&self) -> Range { + 0..self.brotli_stream_byte_range().end + } +} + +impl<'a> FontRead<'a> for TablePatch<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } } -impl TablePatchMarker { +/// [TablePatch](https://w3c.github.io/IFT/Overview.html#tablepatch) +pub type TablePatch<'a> = TableRef<'a, TablePatchMarker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> TablePatch<'a> { + fn brotli_stream_byte_len(&self, start: usize) -> usize { + let _ = start; + { + let remaining = self.data.len().saturating_sub(start); + remaining / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN + } + } + pub fn tag_byte_range(&self) -> Range { let start = 0; start..start + Tag::RAW_BYTE_LEN @@ -2315,53 +2345,27 @@ impl TablePatchMarker { pub fn brotli_stream_byte_range(&self) -> Range { let start = self.max_uncompressed_length_byte_range().end; - start..start + self.brotli_stream_byte_len - } -} - -impl MinByteRange for TablePatchMarker { - fn min_byte_range(&self) -> Range { - 0..self.brotli_stream_byte_range().end - } -} - -impl<'a> FontRead<'a> for TablePatch<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - let brotli_stream_byte_len = cursor.remaining_bytes() / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN; - cursor.advance_by(brotli_stream_byte_len); - cursor.finish(TablePatchMarker { - brotli_stream_byte_len, - }) + start..start + self.brotli_stream_byte_len(start) } -} -/// [TablePatch](https://w3c.github.io/IFT/Overview.html#tablepatch) -pub type TablePatch<'a> = TableRef<'a, TablePatchMarker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> TablePatch<'a> { pub fn tag(&self) -> Tag { - let range = self.shape.tag_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.tag_byte_range(); + unchecked::read_at(self.data, range.start) } pub fn flags(&self) -> TablePatchFlags { - let range = self.shape.flags_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.flags_byte_range(); + unchecked::read_at(self.data, range.start) } pub fn max_uncompressed_length(&self) -> u32 { - let range = self.shape.max_uncompressed_length_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.max_uncompressed_length_byte_range(); + unchecked::read_at(self.data, range.start) } pub fn brotli_stream(&self) -> &'a [u8] { - let range = self.shape.brotli_stream_byte_range(); - self.data.read_array(range).unwrap() + let range = self.brotli_stream_byte_range(); + unchecked::read_array(self.data, range) } } @@ -2700,11 +2704,37 @@ impl<'a> From for FieldType<'a> { /// [Glyph Keyed Patch](https://w3c.github.io/IFT/Overview.html#glyph-keyed) #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct GlyphKeyedPatchMarker { - brotli_stream_byte_len: usize, +pub struct GlyphKeyedPatchMarker; + +impl<'a> MinByteRange for GlyphKeyedPatch<'a> { + fn min_byte_range(&self) -> Range { + 0..self.brotli_stream_byte_range().end + } +} + +impl<'a> FontRead<'a> for GlyphKeyedPatch<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } } -impl GlyphKeyedPatchMarker { +/// [Glyph Keyed Patch](https://w3c.github.io/IFT/Overview.html#glyph-keyed) +pub type GlyphKeyedPatch<'a> = TableRef<'a, GlyphKeyedPatchMarker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> GlyphKeyedPatch<'a> { + fn brotli_stream_byte_len(&self, start: usize) -> usize { + let _ = start; + { + let remaining = self.data.len().saturating_sub(start); + remaining / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN + } + } + pub fn format_byte_range(&self) -> Range { let start = 0; start..start + Tag::RAW_BYTE_LEN @@ -2732,60 +2762,32 @@ impl GlyphKeyedPatchMarker { pub fn brotli_stream_byte_range(&self) -> Range { let start = self.max_uncompressed_length_byte_range().end; - start..start + self.brotli_stream_byte_len - } -} - -impl MinByteRange for GlyphKeyedPatchMarker { - fn min_byte_range(&self) -> Range { - 0..self.brotli_stream_byte_range().end - } -} - -impl<'a> FontRead<'a> for GlyphKeyedPatch<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - let brotli_stream_byte_len = cursor.remaining_bytes() / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN; - cursor.advance_by(brotli_stream_byte_len); - cursor.finish(GlyphKeyedPatchMarker { - brotli_stream_byte_len, - }) + start..start + self.brotli_stream_byte_len(start) } -} - -/// [Glyph Keyed Patch](https://w3c.github.io/IFT/Overview.html#glyph-keyed) -pub type GlyphKeyedPatch<'a> = TableRef<'a, GlyphKeyedPatchMarker>; -#[allow(clippy::needless_lifetimes)] -impl<'a> GlyphKeyedPatch<'a> { pub fn format(&self) -> Tag { - let range = self.shape.format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.format_byte_range(); + unchecked::read_at(self.data, range.start) } pub fn flags(&self) -> GlyphKeyedFlags { - let range = self.shape.flags_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.flags_byte_range(); + unchecked::read_at(self.data, range.start) } pub fn compatibility_id(&self) -> CompatibilityId { - let range = self.shape.compatibility_id_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.compatibility_id_byte_range(); + unchecked::read_at(self.data, range.start) } pub fn max_uncompressed_length(&self) -> u32 { - let range = self.shape.max_uncompressed_length_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.max_uncompressed_length_byte_range(); + unchecked::read_at(self.data, range.start) } pub fn brotli_stream(&self) -> &'a [u8] { - let range = self.shape.brotli_stream_byte_range(); - self.data.read_array(range).unwrap() + let range = self.brotli_stream_byte_range(); + unchecked::read_array(self.data, range) } } @@ -3128,41 +3130,9 @@ impl<'a> From for FieldType<'a> { /// [GlyphPatches](https://w3c.github.io/IFT/Overview.html#glyphpatches) #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct GlyphPatchesMarker { - flags: GlyphKeyedFlags, - glyph_ids_byte_len: usize, - tables_byte_len: usize, - glyph_data_offsets_byte_len: usize, -} - -impl GlyphPatchesMarker { - pub fn glyph_count_byte_range(&self) -> Range { - let start = 0; - start..start + u32::RAW_BYTE_LEN - } - - pub fn table_count_byte_range(&self) -> Range { - let start = self.glyph_count_byte_range().end; - start..start + u8::RAW_BYTE_LEN - } - - pub fn glyph_ids_byte_range(&self) -> Range { - let start = self.table_count_byte_range().end; - start..start + self.glyph_ids_byte_len - } - - pub fn tables_byte_range(&self) -> Range { - let start = self.glyph_ids_byte_range().end; - start..start + self.tables_byte_len - } +pub struct GlyphPatchesMarker; - pub fn glyph_data_offsets_byte_range(&self) -> Range { - let start = self.tables_byte_range().end; - start..start + self.glyph_data_offsets_byte_len - } -} - -impl MinByteRange for GlyphPatchesMarker { +impl<'a> MinByteRange for GlyphPatches<'a> { fn min_byte_range(&self) -> Range { 0..self.glyph_data_offsets_byte_range().end } @@ -3174,28 +3144,11 @@ impl ReadArgs for GlyphPatches<'_> { impl<'a> FontReadWithArgs<'a> for GlyphPatches<'a> { fn read_with_args(data: FontData<'a>, args: &GlyphKeyedFlags) -> Result { - let flags = *args; - let mut cursor = data.cursor(); - let glyph_count: u32 = cursor.read()?; - let table_count: u8 = cursor.read()?; - let glyph_ids_byte_len = (glyph_count as usize) - .checked_mul(::compute_size(&flags)?) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(glyph_ids_byte_len); - let tables_byte_len = (table_count as usize) - .checked_mul(Tag::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(tables_byte_len); - let glyph_data_offsets_byte_len = - (transforms::multiply_add(glyph_count, table_count, 1_usize)) - .checked_mul(Offset32::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(glyph_data_offsets_byte_len); - cursor.finish(GlyphPatchesMarker { - flags, - glyph_ids_byte_len, - tables_byte_len, - glyph_data_offsets_byte_len, + let args = *args; + Ok(TableRef { + args, + data, + _marker: std::marker::PhantomData, }) } } @@ -3212,33 +3165,77 @@ impl<'a> GlyphPatches<'a> { } /// [GlyphPatches](https://w3c.github.io/IFT/Overview.html#glyphpatches) -pub type GlyphPatches<'a> = TableRef<'a, GlyphPatchesMarker>; +pub type GlyphPatches<'a> = TableRef<'a, GlyphPatchesMarker, GlyphKeyedFlags>; #[allow(clippy::needless_lifetimes)] impl<'a> GlyphPatches<'a> { + fn glyph_ids_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.glyph_count()) as usize) + .checked_mul(::compute_size(&self.args).unwrap()) + .unwrap() + } + fn tables_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.table_count()) as usize) + .checked_mul(Tag::RAW_BYTE_LEN) + .unwrap() + } + fn glyph_data_offsets_byte_len(&self, start: usize) -> usize { + let _ = start; + (transforms::multiply_add(self.glyph_count(), self.table_count(), 1_usize)) + .checked_mul(Offset32::RAW_BYTE_LEN) + .unwrap() + } + + pub fn glyph_count_byte_range(&self) -> Range { + let start = 0; + start..start + u32::RAW_BYTE_LEN + } + + pub fn table_count_byte_range(&self) -> Range { + let start = self.glyph_count_byte_range().end; + start..start + u8::RAW_BYTE_LEN + } + + pub fn glyph_ids_byte_range(&self) -> Range { + let start = self.table_count_byte_range().end; + start..start + self.glyph_ids_byte_len(start) + } + + pub fn tables_byte_range(&self) -> Range { + let start = self.glyph_ids_byte_range().end; + start..start + self.tables_byte_len(start) + } + + pub fn glyph_data_offsets_byte_range(&self) -> Range { + let start = self.tables_byte_range().end; + start..start + self.glyph_data_offsets_byte_len(start) + } + pub fn glyph_count(&self) -> u32 { - let range = self.shape.glyph_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.glyph_count_byte_range(); + unchecked::read_at(self.data, range.start) } pub fn table_count(&self) -> u8 { - let range = self.shape.table_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.table_count_byte_range(); + unchecked::read_at(self.data, range.start) } pub fn glyph_ids(&self) -> ComputedArray<'a, U16Or24> { - let range = self.shape.glyph_ids_byte_range(); - self.data.read_with_args(range, &self.flags()).unwrap() + let range = self.glyph_ids_byte_range(); + unchecked::read_with_args(self.data, range, &self.flags()) } pub fn tables(&self) -> &'a [BigEndian] { - let range = self.shape.tables_byte_range(); - self.data.read_array(range).unwrap() + let range = self.tables_byte_range(); + unchecked::read_array(self.data, range) } pub fn glyph_data_offsets(&self) -> &'a [BigEndian] { - let range = self.shape.glyph_data_offsets_byte_range(); - self.data.read_array(range).unwrap() + let range = self.glyph_data_offsets_byte_range(); + unchecked::read_array(self.data, range) } /// A dynamically resolving wrapper for [`glyph_data_offsets`][Self::glyph_data_offsets]. @@ -3249,7 +3246,7 @@ impl<'a> GlyphPatches<'a> { } pub(crate) fn flags(&self) -> GlyphKeyedFlags { - self.shape.flags + self.args } } @@ -3293,18 +3290,9 @@ impl<'a> std::fmt::Debug for GlyphPatches<'a> { #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct GlyphDataMarker { - data_byte_len: usize, -} - -impl GlyphDataMarker { - pub fn data_byte_range(&self) -> Range { - let start = 0; - start..start + self.data_byte_len - } -} +pub struct GlyphDataMarker; -impl MinByteRange for GlyphDataMarker { +impl<'a> MinByteRange for GlyphData<'a> { fn min_byte_range(&self) -> Range { 0..self.data_byte_range().end } @@ -3312,20 +3300,34 @@ impl MinByteRange for GlyphDataMarker { impl<'a> FontRead<'a> for GlyphData<'a> { fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - let data_byte_len = cursor.remaining_bytes() / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN; - cursor.advance_by(data_byte_len); - cursor.finish(GlyphDataMarker { data_byte_len }) + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) } } -pub type GlyphData<'a> = TableRef<'a, GlyphDataMarker>; +pub type GlyphData<'a> = TableRef<'a, GlyphDataMarker, ()>; #[allow(clippy::needless_lifetimes)] impl<'a> GlyphData<'a> { + fn data_byte_len(&self, start: usize) -> usize { + let _ = start; + { + let remaining = self.data.len().saturating_sub(start); + remaining / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN + } + } + + pub fn data_byte_range(&self) -> Range { + let start = 0; + start..start + self.data_byte_len(start) + } + pub fn data(&self) -> &'a [u8] { - let range = self.shape.data_byte_range(); - self.data.read_array(range).unwrap() + let range = self.data_byte_range(); + unchecked::read_array(self.data, range) } } diff --git a/read-fonts/generated/generated_kern.rs b/read-fonts/generated/generated_kern.rs index b67f5c4a6..1b6891d86 100644 --- a/read-fonts/generated/generated_kern.rs +++ b/read-fonts/generated/generated_kern.rs @@ -8,28 +8,9 @@ use crate::codegen_prelude::*; /// The OpenType [kerning](https://learn.microsoft.com/en-us/typography/opentype/spec/kern) table. #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct OtKernMarker { - subtable_data_byte_len: usize, -} - -impl OtKernMarker { - pub fn version_byte_range(&self) -> Range { - let start = 0; - start..start + u16::RAW_BYTE_LEN - } - - pub fn n_tables_byte_range(&self) -> Range { - let start = self.version_byte_range().end; - start..start + u16::RAW_BYTE_LEN - } - - pub fn subtable_data_byte_range(&self) -> Range { - let start = self.n_tables_byte_range().end; - start..start + self.subtable_data_byte_len - } -} +pub struct OtKernMarker; -impl MinByteRange for OtKernMarker { +impl<'a> MinByteRange for OtKern<'a> { fn min_byte_range(&self) -> Range { 0..self.subtable_data_byte_range().end } @@ -37,38 +18,58 @@ impl MinByteRange for OtKernMarker { impl<'a> FontRead<'a> for OtKern<'a> { fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - let subtable_data_byte_len = cursor.remaining_bytes() / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN; - cursor.advance_by(subtable_data_byte_len); - cursor.finish(OtKernMarker { - subtable_data_byte_len, + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, }) } } /// The OpenType [kerning](https://learn.microsoft.com/en-us/typography/opentype/spec/kern) table. -pub type OtKern<'a> = TableRef<'a, OtKernMarker>; +pub type OtKern<'a> = TableRef<'a, OtKernMarker, ()>; #[allow(clippy::needless_lifetimes)] impl<'a> OtKern<'a> { + fn subtable_data_byte_len(&self, start: usize) -> usize { + let _ = start; + { + let remaining = self.data.len().saturating_sub(start); + remaining / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN + } + } + + pub fn version_byte_range(&self) -> Range { + let start = 0; + start..start + u16::RAW_BYTE_LEN + } + + pub fn n_tables_byte_range(&self) -> Range { + let start = self.version_byte_range().end; + start..start + u16::RAW_BYTE_LEN + } + + pub fn subtable_data_byte_range(&self) -> Range { + let start = self.n_tables_byte_range().end; + start..start + self.subtable_data_byte_len(start) + } + /// Table version number—set to 0. pub fn version(&self) -> u16 { - let range = self.shape.version_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.version_byte_range(); + unchecked::read_at(self.data, range.start) } /// Number of subtables in the kerning table. pub fn n_tables(&self) -> u16 { - let range = self.shape.n_tables_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.n_tables_byte_range(); + unchecked::read_at(self.data, range.start) } /// Data for subtables, immediately following the header. pub fn subtable_data(&self) -> &'a [u8] { - let range = self.shape.subtable_data_byte_range(); - self.data.read_array(range).unwrap() + let range = self.subtable_data_byte_range(); + unchecked::read_array(self.data, range) } } @@ -98,28 +99,9 @@ impl<'a> std::fmt::Debug for OtKern<'a> { /// The Apple Advanced Typography [kerning](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6kern.html) table. #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct AatKernMarker { - subtable_data_byte_len: usize, -} - -impl AatKernMarker { - pub fn version_byte_range(&self) -> Range { - let start = 0; - start..start + MajorMinor::RAW_BYTE_LEN - } - - pub fn n_tables_byte_range(&self) -> Range { - let start = self.version_byte_range().end; - start..start + u32::RAW_BYTE_LEN - } - - pub fn subtable_data_byte_range(&self) -> Range { - let start = self.n_tables_byte_range().end; - start..start + self.subtable_data_byte_len - } -} +pub struct AatKernMarker; -impl MinByteRange for AatKernMarker { +impl<'a> MinByteRange for AatKern<'a> { fn min_byte_range(&self) -> Range { 0..self.subtable_data_byte_range().end } @@ -127,38 +109,58 @@ impl MinByteRange for AatKernMarker { impl<'a> FontRead<'a> for AatKern<'a> { fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - let subtable_data_byte_len = cursor.remaining_bytes() / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN; - cursor.advance_by(subtable_data_byte_len); - cursor.finish(AatKernMarker { - subtable_data_byte_len, + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, }) } } /// The Apple Advanced Typography [kerning](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6kern.html) table. -pub type AatKern<'a> = TableRef<'a, AatKernMarker>; +pub type AatKern<'a> = TableRef<'a, AatKernMarker, ()>; #[allow(clippy::needless_lifetimes)] impl<'a> AatKern<'a> { + fn subtable_data_byte_len(&self, start: usize) -> usize { + let _ = start; + { + let remaining = self.data.len().saturating_sub(start); + remaining / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN + } + } + + pub fn version_byte_range(&self) -> Range { + let start = 0; + start..start + MajorMinor::RAW_BYTE_LEN + } + + pub fn n_tables_byte_range(&self) -> Range { + let start = self.version_byte_range().end; + start..start + u32::RAW_BYTE_LEN + } + + pub fn subtable_data_byte_range(&self) -> Range { + let start = self.n_tables_byte_range().end; + start..start + self.subtable_data_byte_len(start) + } + /// The version number of the kerning table (0x00010000 for the current version). pub fn version(&self) -> MajorMinor { - let range = self.shape.version_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.version_byte_range(); + unchecked::read_at(self.data, range.start) } /// The number of subtables included in the kerning table. pub fn n_tables(&self) -> u32 { - let range = self.shape.n_tables_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.n_tables_byte_range(); + unchecked::read_at(self.data, range.start) } /// Data for subtables, immediately following the header. pub fn subtable_data(&self) -> &'a [u8] { - let range = self.shape.subtable_data_byte_range(); - self.data.read_array(range).unwrap() + let range = self.subtable_data_byte_range(); + unchecked::read_array(self.data, range) } } @@ -188,11 +190,37 @@ impl<'a> std::fmt::Debug for AatKern<'a> { /// A subtable in an OT `kern` table. #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct OtSubtableMarker { - data_byte_len: usize, +pub struct OtSubtableMarker; + +impl<'a> MinByteRange for OtSubtable<'a> { + fn min_byte_range(&self) -> Range { + 0..self.data_byte_range().end + } +} + +impl<'a> FontRead<'a> for OtSubtable<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } } -impl OtSubtableMarker { +/// A subtable in an OT `kern` table. +pub type OtSubtable<'a> = TableRef<'a, OtSubtableMarker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> OtSubtable<'a> { + fn data_byte_len(&self, start: usize) -> usize { + let _ = start; + { + let remaining = self.data.len().saturating_sub(start); + remaining / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN + } + } + pub fn version_byte_range(&self) -> Range { let start = 0; start..start + u16::RAW_BYTE_LEN @@ -210,55 +238,31 @@ impl OtSubtableMarker { pub fn data_byte_range(&self) -> Range { let start = self.coverage_byte_range().end; - start..start + self.data_byte_len + start..start + self.data_byte_len(start) } -} -impl MinByteRange for OtSubtableMarker { - fn min_byte_range(&self) -> Range { - 0..self.data_byte_range().end - } -} - -impl<'a> FontRead<'a> for OtSubtable<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - let data_byte_len = cursor.remaining_bytes() / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN; - cursor.advance_by(data_byte_len); - cursor.finish(OtSubtableMarker { data_byte_len }) - } -} - -/// A subtable in an OT `kern` table. -pub type OtSubtable<'a> = TableRef<'a, OtSubtableMarker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> OtSubtable<'a> { /// Kern subtable version number-- set to 0. pub fn version(&self) -> u16 { - let range = self.shape.version_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.version_byte_range(); + unchecked::read_at(self.data, range.start) } /// The length of this subtable in bytes, including this header. pub fn length(&self) -> u16 { - let range = self.shape.length_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.length_byte_range(); + unchecked::read_at(self.data, range.start) } /// Circumstances under which this table is used. pub fn coverage(&self) -> u16 { - let range = self.shape.coverage_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.coverage_byte_range(); + unchecked::read_at(self.data, range.start) } /// Subtable specific data. pub fn data(&self) -> &'a [u8] { - let range = self.shape.data_byte_range(); - self.data.read_array(range).unwrap() + let range = self.data_byte_range(); + unchecked::read_array(self.data, range) } } @@ -289,11 +293,37 @@ impl<'a> std::fmt::Debug for OtSubtable<'a> { /// A subtable in an AAT `kern` table. #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct AatSubtableMarker { - data_byte_len: usize, +pub struct AatSubtableMarker; + +impl<'a> MinByteRange for AatSubtable<'a> { + fn min_byte_range(&self) -> Range { + 0..self.data_byte_range().end + } } -impl AatSubtableMarker { +impl<'a> FontRead<'a> for AatSubtable<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// A subtable in an AAT `kern` table. +pub type AatSubtable<'a> = TableRef<'a, AatSubtableMarker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> AatSubtable<'a> { + fn data_byte_len(&self, start: usize) -> usize { + let _ = start; + { + let remaining = self.data.len().saturating_sub(start); + remaining / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN + } + } + pub fn length_byte_range(&self) -> Range { let start = 0; start..start + u32::RAW_BYTE_LEN @@ -311,55 +341,31 @@ impl AatSubtableMarker { pub fn data_byte_range(&self) -> Range { let start = self.tuple_index_byte_range().end; - start..start + self.data_byte_len - } -} - -impl MinByteRange for AatSubtableMarker { - fn min_byte_range(&self) -> Range { - 0..self.data_byte_range().end - } -} - -impl<'a> FontRead<'a> for AatSubtable<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - let data_byte_len = cursor.remaining_bytes() / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN; - cursor.advance_by(data_byte_len); - cursor.finish(AatSubtableMarker { data_byte_len }) + start..start + self.data_byte_len(start) } -} -/// A subtable in an AAT `kern` table. -pub type AatSubtable<'a> = TableRef<'a, AatSubtableMarker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> AatSubtable<'a> { /// The length of this subtable in bytes, including this header. pub fn length(&self) -> u32 { - let range = self.shape.length_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.length_byte_range(); + unchecked::read_at(self.data, range.start) } /// Circumstances under which this table is used. pub fn coverage(&self) -> u16 { - let range = self.shape.coverage_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.coverage_byte_range(); + unchecked::read_at(self.data, range.start) } /// The tuple index (used for variations fonts). This value specifies which tuple this subtable covers. pub fn tuple_index(&self) -> u16 { - let range = self.shape.tuple_index_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.tuple_index_byte_range(); + unchecked::read_at(self.data, range.start) } /// Subtable specific data. pub fn data(&self) -> &'a [u8] { - let range = self.shape.data_byte_range(); - self.data.read_array(range).unwrap() + let range = self.data_byte_range(); + unchecked::read_array(self.data, range) } } @@ -390,11 +396,36 @@ impl<'a> std::fmt::Debug for AatSubtable<'a> { /// The type 0 `kern` subtable. #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct Subtable0Marker { - pairs_byte_len: usize, +pub struct Subtable0Marker; + +impl<'a> MinByteRange for Subtable0<'a> { + fn min_byte_range(&self) -> Range { + 0..self.pairs_byte_range().end + } } -impl Subtable0Marker { +impl<'a> FontRead<'a> for Subtable0<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// The type 0 `kern` subtable. +pub type Subtable0<'a> = TableRef<'a, Subtable0Marker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> Subtable0<'a> { + fn pairs_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.n_pairs()) as usize) + .checked_mul(Subtable0Pair::RAW_BYTE_LEN) + .unwrap() + } + pub fn n_pairs_byte_range(&self) -> Range { let start = 0; start..start + u16::RAW_BYTE_LEN @@ -417,64 +448,37 @@ impl Subtable0Marker { pub fn pairs_byte_range(&self) -> Range { let start = self.range_shift_byte_range().end; - start..start + self.pairs_byte_len - } -} - -impl MinByteRange for Subtable0Marker { - fn min_byte_range(&self) -> Range { - 0..self.pairs_byte_range().end + start..start + self.pairs_byte_len(start) } -} -impl<'a> FontRead<'a> for Subtable0<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - let n_pairs: u16 = cursor.read()?; - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - let pairs_byte_len = (n_pairs as usize) - .checked_mul(Subtable0Pair::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(pairs_byte_len); - cursor.finish(Subtable0Marker { pairs_byte_len }) - } -} - -/// The type 0 `kern` subtable. -pub type Subtable0<'a> = TableRef<'a, Subtable0Marker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> Subtable0<'a> { /// The number of kerning pairs in this subtable. pub fn n_pairs(&self) -> u16 { - let range = self.shape.n_pairs_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.n_pairs_byte_range(); + unchecked::read_at(self.data, range.start) } /// The largest power of two less than or equal to the value of nPairs, multiplied by the size in bytes of an entry in the subtable. pub fn search_range(&self) -> u16 { - let range = self.shape.search_range_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.search_range_byte_range(); + unchecked::read_at(self.data, range.start) } /// This is calculated as log2 of the largest power of two less than or equal to the value of nPairs. This value indicates how many iterations of the search loop have to be made. For example, in a list of eight items, there would be three iterations of the loop. pub fn entry_selector(&self) -> u16 { - let range = self.shape.entry_selector_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.entry_selector_byte_range(); + unchecked::read_at(self.data, range.start) } /// The value of nPairs minus the largest power of two less than or equal to nPairs. This is multiplied by the size in bytes of an entry in the table. pub fn range_shift(&self) -> u16 { - let range = self.shape.range_shift_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.range_shift_byte_range(); + unchecked::read_at(self.data, range.start) } /// Kerning records. pub fn pairs(&self) -> &'a [Subtable0Pair] { - let range = self.shape.pairs_byte_range(); - self.data.read_array(range).unwrap() + let range = self.pairs_byte_range(); + unchecked::read_array(self.data, range) } } @@ -513,11 +517,36 @@ impl<'a> std::fmt::Debug for Subtable0<'a> { /// Class table for the type 2 `kern` subtable. #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct Subtable2ClassTableMarker { - offsets_byte_len: usize, +pub struct Subtable2ClassTableMarker; + +impl<'a> MinByteRange for Subtable2ClassTable<'a> { + fn min_byte_range(&self) -> Range { + 0..self.offsets_byte_range().end + } } -impl Subtable2ClassTableMarker { +impl<'a> FontRead<'a> for Subtable2ClassTable<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// Class table for the type 2 `kern` subtable. +pub type Subtable2ClassTable<'a> = TableRef<'a, Subtable2ClassTableMarker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> Subtable2ClassTable<'a> { + fn offsets_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.n_glyphs()) as usize) + .checked_mul(u16::RAW_BYTE_LEN) + .unwrap() + } + pub fn first_glyph_byte_range(&self) -> Range { let start = 0; start..start + GlyphId16::RAW_BYTE_LEN @@ -530,50 +559,25 @@ impl Subtable2ClassTableMarker { pub fn offsets_byte_range(&self) -> Range { let start = self.n_glyphs_byte_range().end; - start..start + self.offsets_byte_len - } -} - -impl MinByteRange for Subtable2ClassTableMarker { - fn min_byte_range(&self) -> Range { - 0..self.offsets_byte_range().end + start..start + self.offsets_byte_len(start) } -} - -impl<'a> FontRead<'a> for Subtable2ClassTable<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - let n_glyphs: u16 = cursor.read()?; - let offsets_byte_len = (n_glyphs as usize) - .checked_mul(u16::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(offsets_byte_len); - cursor.finish(Subtable2ClassTableMarker { offsets_byte_len }) - } -} - -/// Class table for the type 2 `kern` subtable. -pub type Subtable2ClassTable<'a> = TableRef<'a, Subtable2ClassTableMarker>; -#[allow(clippy::needless_lifetimes)] -impl<'a> Subtable2ClassTable<'a> { /// First glyph in class range. pub fn first_glyph(&self) -> GlyphId16 { - let range = self.shape.first_glyph_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.first_glyph_byte_range(); + unchecked::read_at(self.data, range.start) } /// Number of glyph in class range. pub fn n_glyphs(&self) -> u16 { - let range = self.shape.n_glyphs_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.n_glyphs_byte_range(); + unchecked::read_at(self.data, range.start) } /// The offsets array for all of the glyphs in the range. pub fn offsets(&self) -> &'a [BigEndian] { - let range = self.shape.offsets_byte_range(); - self.data.read_array(range).unwrap() + let range = self.offsets_byte_range(); + unchecked::read_array(self.data, range) } } @@ -603,14 +607,54 @@ impl<'a> std::fmt::Debug for Subtable2ClassTable<'a> { /// The type 3 'kern' subtable. #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct Subtable3Marker { - kern_value_byte_len: usize, - left_class_byte_len: usize, - right_class_byte_len: usize, - kern_index_byte_len: usize, +pub struct Subtable3Marker; + +impl<'a> MinByteRange for Subtable3<'a> { + fn min_byte_range(&self) -> Range { + 0..self.kern_index_byte_range().end + } } -impl Subtable3Marker { +impl<'a> FontRead<'a> for Subtable3<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// The type 3 'kern' subtable. +pub type Subtable3<'a> = TableRef<'a, Subtable3Marker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> Subtable3<'a> { + fn kern_value_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.kern_value_count()) as usize) + .checked_mul(i16::RAW_BYTE_LEN) + .unwrap() + } + fn left_class_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.glyph_count()) as usize) + .checked_mul(u8::RAW_BYTE_LEN) + .unwrap() + } + fn right_class_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.glyph_count()) as usize) + .checked_mul(u8::RAW_BYTE_LEN) + .unwrap() + } + fn kern_index_byte_len(&self, start: usize) -> usize { + let _ = start; + (transforms::add_multiply(self.left_class_count(), 0_usize, self.right_class_count())) + .checked_mul(u8::RAW_BYTE_LEN) + .unwrap() + } + pub fn glyph_count_byte_range(&self) -> Range { let start = 0; start..start + u16::RAW_BYTE_LEN @@ -638,122 +682,76 @@ impl Subtable3Marker { pub fn kern_value_byte_range(&self) -> Range { let start = self.flags_byte_range().end; - start..start + self.kern_value_byte_len + start..start + self.kern_value_byte_len(start) } pub fn left_class_byte_range(&self) -> Range { let start = self.kern_value_byte_range().end; - start..start + self.left_class_byte_len + start..start + self.left_class_byte_len(start) } pub fn right_class_byte_range(&self) -> Range { let start = self.left_class_byte_range().end; - start..start + self.right_class_byte_len + start..start + self.right_class_byte_len(start) } pub fn kern_index_byte_range(&self) -> Range { let start = self.right_class_byte_range().end; - start..start + self.kern_index_byte_len + start..start + self.kern_index_byte_len(start) } -} -impl MinByteRange for Subtable3Marker { - fn min_byte_range(&self) -> Range { - 0..self.kern_index_byte_range().end - } -} - -impl<'a> FontRead<'a> for Subtable3<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - let glyph_count: u16 = cursor.read()?; - let kern_value_count: u8 = cursor.read()?; - let left_class_count: u8 = cursor.read()?; - let right_class_count: u8 = cursor.read()?; - cursor.advance::(); - let kern_value_byte_len = (kern_value_count as usize) - .checked_mul(i16::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(kern_value_byte_len); - let left_class_byte_len = (glyph_count as usize) - .checked_mul(u8::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(left_class_byte_len); - let right_class_byte_len = (glyph_count as usize) - .checked_mul(u8::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(right_class_byte_len); - let kern_index_byte_len = - (transforms::add_multiply(left_class_count, 0_usize, right_class_count)) - .checked_mul(u8::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(kern_index_byte_len); - cursor.finish(Subtable3Marker { - kern_value_byte_len, - left_class_byte_len, - right_class_byte_len, - kern_index_byte_len, - }) - } -} - -/// The type 3 'kern' subtable. -pub type Subtable3<'a> = TableRef<'a, Subtable3Marker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> Subtable3<'a> { /// The number of glyphs in this font. pub fn glyph_count(&self) -> u16 { - let range = self.shape.glyph_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.glyph_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// The number of kerning values. pub fn kern_value_count(&self) -> u8 { - let range = self.shape.kern_value_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.kern_value_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// The number of left-hand classes. pub fn left_class_count(&self) -> u8 { - let range = self.shape.left_class_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.left_class_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// The number of right-hand classes. pub fn right_class_count(&self) -> u8 { - let range = self.shape.right_class_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.right_class_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Set to zero (reserved for future use). pub fn flags(&self) -> u8 { - let range = self.shape.flags_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.flags_byte_range(); + unchecked::read_at(self.data, range.start) } /// The kerning values. pub fn kern_value(&self) -> &'a [BigEndian] { - let range = self.shape.kern_value_byte_range(); - self.data.read_array(range).unwrap() + let range = self.kern_value_byte_range(); + unchecked::read_array(self.data, range) } /// The left-hand classes. pub fn left_class(&self) -> &'a [u8] { - let range = self.shape.left_class_byte_range(); - self.data.read_array(range).unwrap() + let range = self.left_class_byte_range(); + unchecked::read_array(self.data, range) } /// The right-hand classes. pub fn right_class(&self) -> &'a [u8] { - let range = self.shape.right_class_byte_range(); - self.data.read_array(range).unwrap() + let range = self.right_class_byte_range(); + unchecked::read_array(self.data, range) } /// The indices into the kernValue array. pub fn kern_index(&self) -> &'a [u8] { - let range = self.shape.kern_index_byte_range(); - self.data.read_array(range).unwrap() + let range = self.kern_index_byte_range(); + unchecked::read_array(self.data, range) } } diff --git a/read-fonts/generated/generated_kerx.rs b/read-fonts/generated/generated_kerx.rs index 21880e467..07ac92132 100644 --- a/read-fonts/generated/generated_kerx.rs +++ b/read-fonts/generated/generated_kerx.rs @@ -8,11 +8,42 @@ use crate::codegen_prelude::*; /// The [kerx (Extended Kerning)](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6morx.html) table. #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct KerxMarker { - subtables_byte_len: usize, +pub struct KerxMarker; + +impl<'a> MinByteRange for Kerx<'a> { + fn min_byte_range(&self) -> Range { + 0..self.subtables_byte_range().end + } +} + +impl TopLevelTable for Kerx<'_> { + /// `kerx` + const TAG: Tag = Tag::new(b"kerx"); } -impl KerxMarker { +impl<'a> FontRead<'a> for Kerx<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// The [kerx (Extended Kerning)](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6morx.html) table. +pub type Kerx<'a> = TableRef<'a, KerxMarker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> Kerx<'a> { + fn subtables_byte_len(&self, start: usize) -> usize { + let _ = start; + { + let data = self.data.split_off(start).unwrap(); + ::total_len_for_count(data, (self.n_tables()) as usize).unwrap() + } + } + pub fn version_byte_range(&self) -> Range { let start = 0; start..start + u16::RAW_BYTE_LEN @@ -30,56 +61,24 @@ impl KerxMarker { pub fn subtables_byte_range(&self) -> Range { let start = self.n_tables_byte_range().end; - start..start + self.subtables_byte_len - } -} - -impl MinByteRange for KerxMarker { - fn min_byte_range(&self) -> Range { - 0..self.subtables_byte_range().end + start..start + self.subtables_byte_len(start) } -} - -impl TopLevelTable for Kerx<'_> { - /// `kerx` - const TAG: Tag = Tag::new(b"kerx"); -} - -impl<'a> FontRead<'a> for Kerx<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - let n_tables: u32 = cursor.read()?; - let subtables_byte_len = { - let data = cursor.remaining().ok_or(ReadError::OutOfBounds)?; - ::total_len_for_count(data, n_tables as usize)? - }; - cursor.advance_by(subtables_byte_len); - cursor.finish(KerxMarker { subtables_byte_len }) - } -} -/// The [kerx (Extended Kerning)](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6morx.html) table. -pub type Kerx<'a> = TableRef<'a, KerxMarker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> Kerx<'a> { /// The version number of the extended kerning table (currently 2, 3, or 4) pub fn version(&self) -> u16 { - let range = self.shape.version_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.version_byte_range(); + unchecked::read_at(self.data, range.start) } /// The number of subtables included in the extended kerning table. pub fn n_tables(&self) -> u32 { - let range = self.shape.n_tables_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.n_tables_byte_range(); + unchecked::read_at(self.data, range.start) } pub fn subtables(&self) -> VarLenArray<'a, Subtable<'a>> { - let range = self.shape.subtables_byte_range(); - VarLenArray::read(self.data.split_off(range.start).unwrap()).unwrap() + let range = self.subtables_byte_range(); + VarLenArray::read(unchecked::split_off(self.data, range.start)).unwrap() } } @@ -112,11 +111,37 @@ impl<'a> std::fmt::Debug for Kerx<'a> { /// A subtable in a `kerx` table. #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct SubtableMarker { - data_byte_len: usize, +pub struct SubtableMarker; + +impl<'a> MinByteRange for Subtable<'a> { + fn min_byte_range(&self) -> Range { + 0..self.data_byte_range().end + } } -impl SubtableMarker { +impl<'a> FontRead<'a> for Subtable<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// A subtable in a `kerx` table. +pub type Subtable<'a> = TableRef<'a, SubtableMarker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> Subtable<'a> { + fn data_byte_len(&self, start: usize) -> usize { + let _ = start; + { + let remaining = self.data.len().saturating_sub(start); + remaining / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN + } + } + pub fn length_byte_range(&self) -> Range { let start = 0; start..start + u32::RAW_BYTE_LEN @@ -134,55 +159,31 @@ impl SubtableMarker { pub fn data_byte_range(&self) -> Range { let start = self.tuple_count_byte_range().end; - start..start + self.data_byte_len - } -} - -impl MinByteRange for SubtableMarker { - fn min_byte_range(&self) -> Range { - 0..self.data_byte_range().end + start..start + self.data_byte_len(start) } -} -impl<'a> FontRead<'a> for Subtable<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - let data_byte_len = cursor.remaining_bytes() / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN; - cursor.advance_by(data_byte_len); - cursor.finish(SubtableMarker { data_byte_len }) - } -} - -/// A subtable in a `kerx` table. -pub type Subtable<'a> = TableRef<'a, SubtableMarker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> Subtable<'a> { /// The length of this subtable in bytes, including this header. pub fn length(&self) -> u32 { - let range = self.shape.length_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.length_byte_range(); + unchecked::read_at(self.data, range.start) } /// Circumstances under which this table is used. pub fn coverage(&self) -> u32 { - let range = self.shape.coverage_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.coverage_byte_range(); + unchecked::read_at(self.data, range.start) } /// The tuple count. This value is only used with variation fonts and should be 0 for all other fonts. The subtable's tupleCount will be ignored if the 'kerx' table version is less than 4. pub fn tuple_count(&self) -> u32 { - let range = self.shape.tuple_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.tuple_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Subtable specific data. pub fn data(&self) -> &'a [u8] { - let range = self.shape.data_byte_range(); - self.data.read_array(range).unwrap() + let range = self.data_byte_range(); + unchecked::read_array(self.data, range) } } @@ -213,11 +214,36 @@ impl<'a> std::fmt::Debug for Subtable<'a> { /// The type 0 `kerx` subtable. #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct Subtable0Marker { - pairs_byte_len: usize, +pub struct Subtable0Marker; + +impl<'a> MinByteRange for Subtable0<'a> { + fn min_byte_range(&self) -> Range { + 0..self.pairs_byte_range().end + } } -impl Subtable0Marker { +impl<'a> FontRead<'a> for Subtable0<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// The type 0 `kerx` subtable. +pub type Subtable0<'a> = TableRef<'a, Subtable0Marker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> Subtable0<'a> { + fn pairs_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.n_pairs()) as usize) + .checked_mul(Subtable0Pair::RAW_BYTE_LEN) + .unwrap() + } + pub fn n_pairs_byte_range(&self) -> Range { let start = 0; start..start + u32::RAW_BYTE_LEN @@ -240,64 +266,37 @@ impl Subtable0Marker { pub fn pairs_byte_range(&self) -> Range { let start = self.range_shift_byte_range().end; - start..start + self.pairs_byte_len - } -} - -impl MinByteRange for Subtable0Marker { - fn min_byte_range(&self) -> Range { - 0..self.pairs_byte_range().end + start..start + self.pairs_byte_len(start) } -} -impl<'a> FontRead<'a> for Subtable0<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - let n_pairs: u32 = cursor.read()?; - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - let pairs_byte_len = (n_pairs as usize) - .checked_mul(Subtable0Pair::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(pairs_byte_len); - cursor.finish(Subtable0Marker { pairs_byte_len }) - } -} - -/// The type 0 `kerx` subtable. -pub type Subtable0<'a> = TableRef<'a, Subtable0Marker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> Subtable0<'a> { /// The number of kerning pairs in this subtable. pub fn n_pairs(&self) -> u32 { - let range = self.shape.n_pairs_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.n_pairs_byte_range(); + unchecked::read_at(self.data, range.start) } /// The largest power of two less than or equal to the value of nPairs, multiplied by the size in bytes of an entry in the subtable. pub fn search_range(&self) -> u32 { - let range = self.shape.search_range_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.search_range_byte_range(); + unchecked::read_at(self.data, range.start) } /// This is calculated as log2 of the largest power of two less than or equal to the value of nPairs. This value indicates how many iterations of the search loop have to be made. For example, in a list of eight items, there would be three iterations of the loop. pub fn entry_selector(&self) -> u32 { - let range = self.shape.entry_selector_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.entry_selector_byte_range(); + unchecked::read_at(self.data, range.start) } /// The value of nPairs minus the largest power of two less than or equal to nPairs. This is multiplied by the size in bytes of an entry in the table. pub fn range_shift(&self) -> u32 { - let range = self.shape.range_shift_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.range_shift_byte_range(); + unchecked::read_at(self.data, range.start) } /// Kerning records. pub fn pairs(&self) -> &'a [Subtable0Pair] { - let range = self.shape.pairs_byte_range(); - self.data.read_array(range).unwrap() + let range = self.pairs_byte_range(); + unchecked::read_array(self.data, range) } } diff --git a/read-fonts/generated/generated_layout.rs b/read-fonts/generated/generated_layout.rs index 3b4bb04e8..3ac9c97e6 100644 --- a/read-fonts/generated/generated_layout.rs +++ b/read-fonts/generated/generated_layout.rs @@ -8,23 +8,9 @@ use crate::codegen_prelude::*; /// [Script List Table](https://docs.microsoft.com/en-us/typography/opentype/spec/chapter2#script-list-table-and-script-record) #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct ScriptListMarker { - script_records_byte_len: usize, -} - -impl ScriptListMarker { - pub fn script_count_byte_range(&self) -> Range { - let start = 0; - start..start + u16::RAW_BYTE_LEN - } - - pub fn script_records_byte_range(&self) -> Range { - let start = self.script_count_byte_range().end; - start..start + self.script_records_byte_len - } -} +pub struct ScriptListMarker; -impl MinByteRange for ScriptListMarker { +impl<'a> MinByteRange for ScriptList<'a> { fn min_byte_range(&self) -> Range { 0..self.script_records_byte_range().end } @@ -32,33 +18,46 @@ impl MinByteRange for ScriptListMarker { impl<'a> FontRead<'a> for ScriptList<'a> { fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - let script_count: u16 = cursor.read()?; - let script_records_byte_len = (script_count as usize) - .checked_mul(ScriptRecord::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(script_records_byte_len); - cursor.finish(ScriptListMarker { - script_records_byte_len, + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, }) } } /// [Script List Table](https://docs.microsoft.com/en-us/typography/opentype/spec/chapter2#script-list-table-and-script-record) -pub type ScriptList<'a> = TableRef<'a, ScriptListMarker>; +pub type ScriptList<'a> = TableRef<'a, ScriptListMarker, ()>; #[allow(clippy::needless_lifetimes)] impl<'a> ScriptList<'a> { + fn script_records_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.script_count()) as usize) + .checked_mul(ScriptRecord::RAW_BYTE_LEN) + .unwrap() + } + + pub fn script_count_byte_range(&self) -> Range { + let start = 0; + start..start + u16::RAW_BYTE_LEN + } + + pub fn script_records_byte_range(&self) -> Range { + let start = self.script_count_byte_range().end; + start..start + self.script_records_byte_len(start) + } + /// Number of ScriptRecords pub fn script_count(&self) -> u16 { - let range = self.shape.script_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.script_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Array of ScriptRecords, listed alphabetically by script tag pub fn script_records(&self) -> &'a [ScriptRecord] { - let range = self.shape.script_records_byte_range(); - self.data.read_array(range).unwrap() + let range = self.script_records_byte_range(); + unchecked::read_array(self.data, range) } } @@ -147,28 +146,9 @@ impl<'a> SomeRecord<'a> for ScriptRecord { /// [Script Table](https://docs.microsoft.com/en-us/typography/opentype/spec/chapter2#script-table-and-language-system-record) #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct ScriptMarker { - lang_sys_records_byte_len: usize, -} - -impl ScriptMarker { - pub fn default_lang_sys_offset_byte_range(&self) -> Range { - let start = 0; - start..start + Offset16::RAW_BYTE_LEN - } - - pub fn lang_sys_count_byte_range(&self) -> Range { - let start = self.default_lang_sys_offset_byte_range().end; - start..start + u16::RAW_BYTE_LEN - } - - pub fn lang_sys_records_byte_range(&self) -> Range { - let start = self.lang_sys_count_byte_range().end; - start..start + self.lang_sys_records_byte_len - } -} +pub struct ScriptMarker; -impl MinByteRange for ScriptMarker { +impl<'a> MinByteRange for Script<'a> { fn min_byte_range(&self) -> Range { 0..self.lang_sys_records_byte_range().end } @@ -176,29 +156,46 @@ impl MinByteRange for ScriptMarker { impl<'a> FontRead<'a> for Script<'a> { fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - let lang_sys_count: u16 = cursor.read()?; - let lang_sys_records_byte_len = (lang_sys_count as usize) - .checked_mul(LangSysRecord::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(lang_sys_records_byte_len); - cursor.finish(ScriptMarker { - lang_sys_records_byte_len, + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, }) } } /// [Script Table](https://docs.microsoft.com/en-us/typography/opentype/spec/chapter2#script-table-and-language-system-record) -pub type Script<'a> = TableRef<'a, ScriptMarker>; +pub type Script<'a> = TableRef<'a, ScriptMarker, ()>; #[allow(clippy::needless_lifetimes)] impl<'a> Script<'a> { + fn lang_sys_records_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.lang_sys_count()) as usize) + .checked_mul(LangSysRecord::RAW_BYTE_LEN) + .unwrap() + } + + pub fn default_lang_sys_offset_byte_range(&self) -> Range { + let start = 0; + start..start + Offset16::RAW_BYTE_LEN + } + + pub fn lang_sys_count_byte_range(&self) -> Range { + let start = self.default_lang_sys_offset_byte_range().end; + start..start + u16::RAW_BYTE_LEN + } + + pub fn lang_sys_records_byte_range(&self) -> Range { + let start = self.lang_sys_count_byte_range().end; + start..start + self.lang_sys_records_byte_len(start) + } + /// Offset to default LangSys table, from beginning of Script table /// — may be NULL pub fn default_lang_sys_offset(&self) -> Nullable { - let range = self.shape.default_lang_sys_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.default_lang_sys_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`default_lang_sys_offset`][Self::default_lang_sys_offset]. @@ -210,14 +207,14 @@ impl<'a> Script<'a> { /// Number of LangSysRecords for this script — excluding the /// default LangSys pub fn lang_sys_count(&self) -> u16 { - let range = self.shape.lang_sys_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.lang_sys_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Array of LangSysRecords, listed alphabetically by LangSys tag pub fn lang_sys_records(&self) -> &'a [LangSysRecord] { - let range = self.shape.lang_sys_records_byte_range(); - self.data.read_array(range).unwrap() + let range = self.lang_sys_records_byte_range(); + unchecked::read_array(self.data, range) } } @@ -309,11 +306,36 @@ impl<'a> SomeRecord<'a> for LangSysRecord { /// [Language System Table](https://docs.microsoft.com/en-us/typography/opentype/spec/chapter2#language-system-table) #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct LangSysMarker { - feature_indices_byte_len: usize, +pub struct LangSysMarker; + +impl<'a> MinByteRange for LangSys<'a> { + fn min_byte_range(&self) -> Range { + 0..self.feature_indices_byte_range().end + } } -impl LangSysMarker { +impl<'a> FontRead<'a> for LangSys<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// [Language System Table](https://docs.microsoft.com/en-us/typography/opentype/spec/chapter2#language-system-table) +pub type LangSys<'a> = TableRef<'a, LangSysMarker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> LangSys<'a> { + fn feature_indices_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.feature_index_count()) as usize) + .checked_mul(u16::RAW_BYTE_LEN) + .unwrap() + } + pub fn lookup_order_offset_byte_range(&self) -> Range { let start = 0; start..start + u16::RAW_BYTE_LEN @@ -331,55 +353,27 @@ impl LangSysMarker { pub fn feature_indices_byte_range(&self) -> Range { let start = self.feature_index_count_byte_range().end; - start..start + self.feature_indices_byte_len - } -} - -impl MinByteRange for LangSysMarker { - fn min_byte_range(&self) -> Range { - 0..self.feature_indices_byte_range().end - } -} - -impl<'a> FontRead<'a> for LangSys<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - let feature_index_count: u16 = cursor.read()?; - let feature_indices_byte_len = (feature_index_count as usize) - .checked_mul(u16::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(feature_indices_byte_len); - cursor.finish(LangSysMarker { - feature_indices_byte_len, - }) + start..start + self.feature_indices_byte_len(start) } -} - -/// [Language System Table](https://docs.microsoft.com/en-us/typography/opentype/spec/chapter2#language-system-table) -pub type LangSys<'a> = TableRef<'a, LangSysMarker>; -#[allow(clippy::needless_lifetimes)] -impl<'a> LangSys<'a> { /// Index of a feature required for this language system; if no /// required features = 0xFFFF pub fn required_feature_index(&self) -> u16 { - let range = self.shape.required_feature_index_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.required_feature_index_byte_range(); + unchecked::read_at(self.data, range.start) } /// Number of feature index values for this language system — /// excludes the required feature pub fn feature_index_count(&self) -> u16 { - let range = self.shape.feature_index_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.feature_index_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Array of indices into the FeatureList, in arbitrary order pub fn feature_indices(&self) -> &'a [BigEndian] { - let range = self.shape.feature_indices_byte_range(); - self.data.read_array(range).unwrap() + let range = self.feature_indices_byte_range(); + unchecked::read_array(self.data, range) } } @@ -415,23 +409,9 @@ impl<'a> std::fmt::Debug for LangSys<'a> { /// [Feature List Table](https://docs.microsoft.com/en-us/typography/opentype/spec/chapter2#feature-list-table) #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct FeatureListMarker { - feature_records_byte_len: usize, -} +pub struct FeatureListMarker; -impl FeatureListMarker { - pub fn feature_count_byte_range(&self) -> Range { - let start = 0; - start..start + u16::RAW_BYTE_LEN - } - - pub fn feature_records_byte_range(&self) -> Range { - let start = self.feature_count_byte_range().end; - start..start + self.feature_records_byte_len - } -} - -impl MinByteRange for FeatureListMarker { +impl<'a> MinByteRange for FeatureList<'a> { fn min_byte_range(&self) -> Range { 0..self.feature_records_byte_range().end } @@ -439,34 +419,47 @@ impl MinByteRange for FeatureListMarker { impl<'a> FontRead<'a> for FeatureList<'a> { fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - let feature_count: u16 = cursor.read()?; - let feature_records_byte_len = (feature_count as usize) - .checked_mul(FeatureRecord::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(feature_records_byte_len); - cursor.finish(FeatureListMarker { - feature_records_byte_len, + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, }) } } /// [Feature List Table](https://docs.microsoft.com/en-us/typography/opentype/spec/chapter2#feature-list-table) -pub type FeatureList<'a> = TableRef<'a, FeatureListMarker>; +pub type FeatureList<'a> = TableRef<'a, FeatureListMarker, ()>; #[allow(clippy::needless_lifetimes)] impl<'a> FeatureList<'a> { + fn feature_records_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.feature_count()) as usize) + .checked_mul(FeatureRecord::RAW_BYTE_LEN) + .unwrap() + } + + pub fn feature_count_byte_range(&self) -> Range { + let start = 0; + start..start + u16::RAW_BYTE_LEN + } + + pub fn feature_records_byte_range(&self) -> Range { + let start = self.feature_count_byte_range().end; + start..start + self.feature_records_byte_len(start) + } + /// Number of FeatureRecords in this table pub fn feature_count(&self) -> u16 { - let range = self.shape.feature_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.feature_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Array of FeatureRecords — zero-based (first feature has /// FeatureIndex = 0), listed alphabetically by feature tag pub fn feature_records(&self) -> &'a [FeatureRecord] { - let range = self.shape.feature_records_byte_range(); - self.data.read_array(range).unwrap() + let range = self.feature_records_byte_range(); + unchecked::read_array(self.data, range) } } @@ -556,29 +549,9 @@ impl<'a> SomeRecord<'a> for FeatureRecord { /// [Feature Table](https://docs.microsoft.com/en-us/typography/opentype/spec/chapter2#feature-table) #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct FeatureMarker { - feature_tag: Tag, - lookup_list_indices_byte_len: usize, -} - -impl FeatureMarker { - pub fn feature_params_offset_byte_range(&self) -> Range { - let start = 0; - start..start + Offset16::RAW_BYTE_LEN - } - - pub fn lookup_index_count_byte_range(&self) -> Range { - let start = self.feature_params_offset_byte_range().end; - start..start + u16::RAW_BYTE_LEN - } - - pub fn lookup_list_indices_byte_range(&self) -> Range { - let start = self.lookup_index_count_byte_range().end; - start..start + self.lookup_list_indices_byte_len - } -} +pub struct FeatureMarker; -impl MinByteRange for FeatureMarker { +impl<'a> MinByteRange for Feature<'a> { fn min_byte_range(&self) -> Range { 0..self.lookup_list_indices_byte_range().end } @@ -590,17 +563,11 @@ impl ReadArgs for Feature<'_> { impl<'a> FontReadWithArgs<'a> for Feature<'a> { fn read_with_args(data: FontData<'a>, args: &Tag) -> Result { - let feature_tag = *args; - let mut cursor = data.cursor(); - cursor.advance::(); - let lookup_index_count: u16 = cursor.read()?; - let lookup_list_indices_byte_len = (lookup_index_count as usize) - .checked_mul(u16::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(lookup_list_indices_byte_len); - cursor.finish(FeatureMarker { - feature_tag, - lookup_list_indices_byte_len, + let args = *args; + Ok(TableRef { + args, + data, + _marker: std::marker::PhantomData, }) } } @@ -617,14 +584,36 @@ impl<'a> Feature<'a> { } /// [Feature Table](https://docs.microsoft.com/en-us/typography/opentype/spec/chapter2#feature-table) -pub type Feature<'a> = TableRef<'a, FeatureMarker>; +pub type Feature<'a> = TableRef<'a, FeatureMarker, Tag>; #[allow(clippy::needless_lifetimes)] impl<'a> Feature<'a> { + fn lookup_list_indices_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.lookup_index_count()) as usize) + .checked_mul(u16::RAW_BYTE_LEN) + .unwrap() + } + + pub fn feature_params_offset_byte_range(&self) -> Range { + let start = 0; + start..start + Offset16::RAW_BYTE_LEN + } + + pub fn lookup_index_count_byte_range(&self) -> Range { + let start = self.feature_params_offset_byte_range().end; + start..start + u16::RAW_BYTE_LEN + } + + pub fn lookup_list_indices_byte_range(&self) -> Range { + let start = self.lookup_index_count_byte_range().end; + start..start + self.lookup_list_indices_byte_len(start) + } + /// Offset from start of Feature table to FeatureParams table, if defined for the feature and present, else NULL pub fn feature_params_offset(&self) -> Nullable { - let range = self.shape.feature_params_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.feature_params_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`feature_params_offset`][Self::feature_params_offset]. @@ -636,19 +625,19 @@ impl<'a> Feature<'a> { /// Number of LookupList indices for this feature pub fn lookup_index_count(&self) -> u16 { - let range = self.shape.lookup_index_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.lookup_index_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Array of indices into the LookupList — zero-based (first /// lookup is LookupListIndex = 0) pub fn lookup_list_indices(&self) -> &'a [BigEndian] { - let range = self.shape.lookup_list_indices_byte_range(); - self.data.read_array(range).unwrap() + let range = self.lookup_list_indices_byte_range(); + unchecked::read_array(self.data, range) } pub(crate) fn feature_tag(&self) -> Tag { - self.shape.feature_tag + self.args } } @@ -682,50 +671,22 @@ impl<'a> std::fmt::Debug for Feature<'a> { } /// [Lookup List Table](https://docs.microsoft.com/en-us/typography/opentype/spec/chapter2#lookup-list-table) -#[derive(Debug)] +#[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct LookupListMarker { - lookup_offsets_byte_len: usize, - offset_type: std::marker::PhantomData<*const T>, -} - -impl LookupListMarker { - pub fn lookup_count_byte_range(&self) -> Range { - let start = 0; - start..start + u16::RAW_BYTE_LEN - } - - pub fn lookup_offsets_byte_range(&self) -> Range { - let start = self.lookup_count_byte_range().end; - start..start + self.lookup_offsets_byte_len - } -} +pub struct LookupListMarker; -impl MinByteRange for LookupListMarker { +impl<'a, T> MinByteRange for LookupList<'a, T> { fn min_byte_range(&self) -> Range { 0..self.lookup_offsets_byte_range().end } } -impl Clone for LookupListMarker { - fn clone(&self) -> Self { - *self - } -} - -impl Copy for LookupListMarker {} - impl<'a, T> FontRead<'a> for LookupList<'a, T> { fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - let lookup_count: u16 = cursor.read()?; - let lookup_offsets_byte_len = (lookup_count as usize) - .checked_mul(Offset16::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(lookup_offsets_byte_len); - cursor.finish(LookupListMarker { - lookup_offsets_byte_len, - offset_type: std::marker::PhantomData, + Ok(TableRef { + args: std::marker::PhantomData, + data, + _marker: std::marker::PhantomData, }) } } @@ -733,13 +694,11 @@ impl<'a, T> FontRead<'a> for LookupList<'a, T> { impl<'a> LookupList<'a, ()> { #[allow(dead_code)] pub(crate) fn into_concrete(self) -> LookupList<'a, T> { - let TableRef { data, shape } = self; + let TableRef { data, .. } = self; TableRef { - shape: LookupListMarker { - lookup_offsets_byte_len: shape.lookup_offsets_byte_len, - offset_type: std::marker::PhantomData, - }, + args: std::marker::PhantomData, data, + _marker: std::marker::PhantomData, } } } @@ -748,33 +707,49 @@ impl<'a, T> LookupList<'a, T> { #[allow(dead_code)] /// Replace the specific generic type on this implementation with `()` pub(crate) fn of_unit_type(&self) -> LookupList<'a, ()> { - let TableRef { data, shape } = self; + let TableRef { data, .. } = self; TableRef { - shape: LookupListMarker { - lookup_offsets_byte_len: shape.lookup_offsets_byte_len, - offset_type: std::marker::PhantomData, - }, + args: std::marker::PhantomData, data: *data, + _marker: std::marker::PhantomData, } } } /// [Lookup List Table](https://docs.microsoft.com/en-us/typography/opentype/spec/chapter2#lookup-list-table) -pub type LookupList<'a, T> = TableRef<'a, LookupListMarker>; +pub type LookupList<'a, T = ()> = + TableRef<'a, LookupListMarker, std::marker::PhantomData<*const T>>; #[allow(clippy::needless_lifetimes)] impl<'a, T> LookupList<'a, T> { + fn lookup_offsets_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.lookup_count()) as usize) + .checked_mul(Offset16::RAW_BYTE_LEN) + .unwrap() + } + + pub fn lookup_count_byte_range(&self) -> Range { + let start = 0; + start..start + u16::RAW_BYTE_LEN + } + + pub fn lookup_offsets_byte_range(&self) -> Range { + let start = self.lookup_count_byte_range().end; + start..start + self.lookup_offsets_byte_len(start) + } + /// Number of lookups in this table pub fn lookup_count(&self) -> u16 { - let range = self.shape.lookup_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.lookup_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Array of offsets to Lookup tables, from beginning of LookupList /// — zero based (first lookup is Lookup index = 0) pub fn lookup_offsets(&self) -> &'a [BigEndian] { - let range = self.shape.lookup_offsets_byte_range(); - self.data.read_array(range).unwrap() + let range = self.lookup_offsets_byte_range(); + unchecked::read_array(self.data, range) } /// A dynamically resolving wrapper for [`lookup_offsets`][Self::lookup_offsets]. @@ -824,76 +799,22 @@ impl<'a, T: FontRead<'a> + SomeTable<'a> + 'a> std::fmt::Debug for LookupList<'a } /// [Lookup Table](https://docs.microsoft.com/en-us/typography/opentype/spec/chapter2#lookup-table) -#[derive(Debug)] +#[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct LookupMarker { - subtable_offsets_byte_len: usize, - mark_filtering_set_byte_start: Option, - offset_type: std::marker::PhantomData<*const T>, -} - -impl LookupMarker { - pub fn lookup_type_byte_range(&self) -> Range { - let start = 0; - start..start + u16::RAW_BYTE_LEN - } +pub struct LookupMarker; - pub fn lookup_flag_byte_range(&self) -> Range { - let start = self.lookup_type_byte_range().end; - start..start + LookupFlag::RAW_BYTE_LEN - } - - pub fn sub_table_count_byte_range(&self) -> Range { - let start = self.lookup_flag_byte_range().end; - start..start + u16::RAW_BYTE_LEN - } - - pub fn subtable_offsets_byte_range(&self) -> Range { - let start = self.sub_table_count_byte_range().end; - start..start + self.subtable_offsets_byte_len - } - - pub fn mark_filtering_set_byte_range(&self) -> Option> { - let start = self.mark_filtering_set_byte_start?; - Some(start..start + u16::RAW_BYTE_LEN) - } -} - -impl MinByteRange for LookupMarker { +impl<'a, T> MinByteRange for Lookup<'a, T> { fn min_byte_range(&self) -> Range { 0..self.subtable_offsets_byte_range().end } } -impl Clone for LookupMarker { - fn clone(&self) -> Self { - *self - } -} - -impl Copy for LookupMarker {} - impl<'a, T> FontRead<'a> for Lookup<'a, T> { fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - let lookup_flag: LookupFlag = cursor.read()?; - let sub_table_count: u16 = cursor.read()?; - let subtable_offsets_byte_len = (sub_table_count as usize) - .checked_mul(Offset16::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(subtable_offsets_byte_len); - let mark_filtering_set_byte_start = lookup_flag - .contains(LookupFlag::USE_MARK_FILTERING_SET) - .then(|| cursor.position()) - .transpose()?; - lookup_flag - .contains(LookupFlag::USE_MARK_FILTERING_SET) - .then(|| cursor.advance::()); - cursor.finish(LookupMarker { - subtable_offsets_byte_len, - mark_filtering_set_byte_start, - offset_type: std::marker::PhantomData, + Ok(TableRef { + args: std::marker::PhantomData, + data, + _marker: std::marker::PhantomData, }) } } @@ -901,14 +822,11 @@ impl<'a, T> FontRead<'a> for Lookup<'a, T> { impl<'a> Lookup<'a, ()> { #[allow(dead_code)] pub(crate) fn into_concrete(self) -> Lookup<'a, T> { - let TableRef { data, shape } = self; + let TableRef { data, .. } = self; TableRef { - shape: LookupMarker { - subtable_offsets_byte_len: shape.subtable_offsets_byte_len, - mark_filtering_set_byte_start: shape.mark_filtering_set_byte_start, - offset_type: std::marker::PhantomData, - }, + args: std::marker::PhantomData, data, + _marker: std::marker::PhantomData, } } } @@ -917,46 +835,82 @@ impl<'a, T> Lookup<'a, T> { #[allow(dead_code)] /// Replace the specific generic type on this implementation with `()` pub(crate) fn of_unit_type(&self) -> Lookup<'a, ()> { - let TableRef { data, shape } = self; + let TableRef { data, .. } = self; TableRef { - shape: LookupMarker { - subtable_offsets_byte_len: shape.subtable_offsets_byte_len, - mark_filtering_set_byte_start: shape.mark_filtering_set_byte_start, - offset_type: std::marker::PhantomData, - }, + args: std::marker::PhantomData, data: *data, + _marker: std::marker::PhantomData, } } } /// [Lookup Table](https://docs.microsoft.com/en-us/typography/opentype/spec/chapter2#lookup-table) -pub type Lookup<'a, T> = TableRef<'a, LookupMarker>; +pub type Lookup<'a, T = ()> = TableRef<'a, LookupMarker, std::marker::PhantomData<*const T>>; #[allow(clippy::needless_lifetimes)] impl<'a, T> Lookup<'a, T> { + fn subtable_offsets_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.sub_table_count()) as usize) + .checked_mul(Offset16::RAW_BYTE_LEN) + .unwrap() + } + + pub fn lookup_type_byte_range(&self) -> Range { + let start = 0; + start..start + u16::RAW_BYTE_LEN + } + + pub fn lookup_flag_byte_range(&self) -> Range { + let start = self.lookup_type_byte_range().end; + start..start + LookupFlag::RAW_BYTE_LEN + } + + pub fn sub_table_count_byte_range(&self) -> Range { + let start = self.lookup_flag_byte_range().end; + start..start + u16::RAW_BYTE_LEN + } + + pub fn subtable_offsets_byte_range(&self) -> Range { + let start = self.sub_table_count_byte_range().end; + start..start + self.subtable_offsets_byte_len(start) + } + + pub fn mark_filtering_set_byte_range(&self) -> Option> { + if self + .lookup_flag() + .contains(LookupFlag::USE_MARK_FILTERING_SET) + { + let start = self.subtable_offsets_byte_range().end; + Some(start..start + u16::RAW_BYTE_LEN) + } else { + None + } + } + /// Different enumerations for GSUB and GPOS pub fn lookup_type(&self) -> u16 { - let range = self.shape.lookup_type_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.lookup_type_byte_range(); + unchecked::read_at(self.data, range.start) } /// Lookup qualifiers pub fn lookup_flag(&self) -> LookupFlag { - let range = self.shape.lookup_flag_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.lookup_flag_byte_range(); + unchecked::read_at(self.data, range.start) } /// Number of subtables for this lookup pub fn sub_table_count(&self) -> u16 { - let range = self.shape.sub_table_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.sub_table_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Array of offsets to lookup subtables, from beginning of Lookup /// table pub fn subtable_offsets(&self) -> &'a [BigEndian] { - let range = self.shape.subtable_offsets_byte_range(); - self.data.read_array(range).unwrap() + let range = self.subtable_offsets_byte_range(); + unchecked::read_array(self.data, range) } /// A dynamically resolving wrapper for [`subtable_offsets`][Self::subtable_offsets]. @@ -973,8 +927,8 @@ impl<'a, T> Lookup<'a, T> { /// is only present if the USE_MARK_FILTERING_SET lookup flag is /// set. pub fn mark_filtering_set(&self) -> Option { - let range = self.shape.mark_filtering_set_byte_range()?; - Some(self.data.read_at(range.start).unwrap()) + let range = self.mark_filtering_set_byte_range()?; + Some(unchecked::read_at(self.data, range.start)) } } @@ -1027,69 +981,67 @@ impl Format for CoverageFormat1Marker { /// [Coverage Format 1](https://docs.microsoft.com/en-us/typography/opentype/spec/chapter2#coverage-format-1) #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct CoverageFormat1Marker { - glyph_array_byte_len: usize, -} +pub struct CoverageFormat1Marker; -impl CoverageFormat1Marker { - pub fn coverage_format_byte_range(&self) -> Range { - let start = 0; - start..start + u16::RAW_BYTE_LEN +impl<'a> MinByteRange for CoverageFormat1<'a> { + fn min_byte_range(&self) -> Range { + 0..self.glyph_array_byte_range().end } - - pub fn glyph_count_byte_range(&self) -> Range { - let start = self.coverage_format_byte_range().end; - start..start + u16::RAW_BYTE_LEN - } - - pub fn glyph_array_byte_range(&self) -> Range { - let start = self.glyph_count_byte_range().end; - start..start + self.glyph_array_byte_len - } -} - -impl MinByteRange for CoverageFormat1Marker { - fn min_byte_range(&self) -> Range { - 0..self.glyph_array_byte_range().end - } -} +} impl<'a> FontRead<'a> for CoverageFormat1<'a> { fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - let glyph_count: u16 = cursor.read()?; - let glyph_array_byte_len = (glyph_count as usize) - .checked_mul(GlyphId16::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(glyph_array_byte_len); - cursor.finish(CoverageFormat1Marker { - glyph_array_byte_len, + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, }) } } /// [Coverage Format 1](https://docs.microsoft.com/en-us/typography/opentype/spec/chapter2#coverage-format-1) -pub type CoverageFormat1<'a> = TableRef<'a, CoverageFormat1Marker>; +pub type CoverageFormat1<'a> = TableRef<'a, CoverageFormat1Marker, ()>; #[allow(clippy::needless_lifetimes)] impl<'a> CoverageFormat1<'a> { + fn glyph_array_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.glyph_count()) as usize) + .checked_mul(GlyphId16::RAW_BYTE_LEN) + .unwrap() + } + + pub fn coverage_format_byte_range(&self) -> Range { + let start = 0; + start..start + u16::RAW_BYTE_LEN + } + + pub fn glyph_count_byte_range(&self) -> Range { + let start = self.coverage_format_byte_range().end; + start..start + u16::RAW_BYTE_LEN + } + + pub fn glyph_array_byte_range(&self) -> Range { + let start = self.glyph_count_byte_range().end; + start..start + self.glyph_array_byte_len(start) + } + /// Format identifier — format = 1 pub fn coverage_format(&self) -> u16 { - let range = self.shape.coverage_format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.coverage_format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Number of glyphs in the glyph array pub fn glyph_count(&self) -> u16 { - let range = self.shape.glyph_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.glyph_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Array of glyph IDs — in numerical order pub fn glyph_array(&self) -> &'a [BigEndian] { - let range = self.shape.glyph_array_byte_range(); - self.data.read_array(range).unwrap() + let range = self.glyph_array_byte_range(); + unchecked::read_array(self.data, range) } } @@ -1123,28 +1075,9 @@ impl Format for CoverageFormat2Marker { /// [Coverage Format 2](https://docs.microsoft.com/en-us/typography/opentype/spec/chapter2#coverage-format-2) #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct CoverageFormat2Marker { - range_records_byte_len: usize, -} - -impl CoverageFormat2Marker { - pub fn coverage_format_byte_range(&self) -> Range { - let start = 0; - start..start + u16::RAW_BYTE_LEN - } - - pub fn range_count_byte_range(&self) -> Range { - let start = self.coverage_format_byte_range().end; - start..start + u16::RAW_BYTE_LEN - } - - pub fn range_records_byte_range(&self) -> Range { - let start = self.range_count_byte_range().end; - start..start + self.range_records_byte_len - } -} +pub struct CoverageFormat2Marker; -impl MinByteRange for CoverageFormat2Marker { +impl<'a> MinByteRange for CoverageFormat2<'a> { fn min_byte_range(&self) -> Range { 0..self.range_records_byte_range().end } @@ -1152,40 +1085,57 @@ impl MinByteRange for CoverageFormat2Marker { impl<'a> FontRead<'a> for CoverageFormat2<'a> { fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - let range_count: u16 = cursor.read()?; - let range_records_byte_len = (range_count as usize) - .checked_mul(RangeRecord::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(range_records_byte_len); - cursor.finish(CoverageFormat2Marker { - range_records_byte_len, + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, }) } } /// [Coverage Format 2](https://docs.microsoft.com/en-us/typography/opentype/spec/chapter2#coverage-format-2) -pub type CoverageFormat2<'a> = TableRef<'a, CoverageFormat2Marker>; +pub type CoverageFormat2<'a> = TableRef<'a, CoverageFormat2Marker, ()>; #[allow(clippy::needless_lifetimes)] impl<'a> CoverageFormat2<'a> { + fn range_records_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.range_count()) as usize) + .checked_mul(RangeRecord::RAW_BYTE_LEN) + .unwrap() + } + + pub fn coverage_format_byte_range(&self) -> Range { + let start = 0; + start..start + u16::RAW_BYTE_LEN + } + + pub fn range_count_byte_range(&self) -> Range { + let start = self.coverage_format_byte_range().end; + start..start + u16::RAW_BYTE_LEN + } + + pub fn range_records_byte_range(&self) -> Range { + let start = self.range_count_byte_range().end; + start..start + self.range_records_byte_len(start) + } + /// Format identifier — format = 2 pub fn coverage_format(&self) -> u16 { - let range = self.shape.coverage_format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.coverage_format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Number of RangeRecords pub fn range_count(&self) -> u16 { - let range = self.shape.range_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.range_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Array of glyph ranges — ordered by startGlyphID. pub fn range_records(&self) -> &'a [RangeRecord] { - let range = self.shape.range_records_byte_range(); - self.data.read_array(range).unwrap() + let range = self.range_records_byte_range(); + unchecked::read_array(self.data, range) } } @@ -1352,11 +1302,36 @@ impl Format for ClassDefFormat1Marker { /// [Class Definition Table Format 1](https://docs.microsoft.com/en-us/typography/opentype/spec/chapter2#class-definition-table-format-1) #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct ClassDefFormat1Marker { - class_value_array_byte_len: usize, +pub struct ClassDefFormat1Marker; + +impl<'a> MinByteRange for ClassDefFormat1<'a> { + fn min_byte_range(&self) -> Range { + 0..self.class_value_array_byte_range().end + } +} + +impl<'a> FontRead<'a> for ClassDefFormat1<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } } -impl ClassDefFormat1Marker { +/// [Class Definition Table Format 1](https://docs.microsoft.com/en-us/typography/opentype/spec/chapter2#class-definition-table-format-1) +pub type ClassDefFormat1<'a> = TableRef<'a, ClassDefFormat1Marker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> ClassDefFormat1<'a> { + fn class_value_array_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.glyph_count()) as usize) + .checked_mul(u16::RAW_BYTE_LEN) + .unwrap() + } + pub fn class_format_byte_range(&self) -> Range { let start = 0; start..start + u16::RAW_BYTE_LEN @@ -1374,59 +1349,31 @@ impl ClassDefFormat1Marker { pub fn class_value_array_byte_range(&self) -> Range { let start = self.glyph_count_byte_range().end; - start..start + self.class_value_array_byte_len - } -} - -impl MinByteRange for ClassDefFormat1Marker { - fn min_byte_range(&self) -> Range { - 0..self.class_value_array_byte_range().end + start..start + self.class_value_array_byte_len(start) } -} - -impl<'a> FontRead<'a> for ClassDefFormat1<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - let glyph_count: u16 = cursor.read()?; - let class_value_array_byte_len = (glyph_count as usize) - .checked_mul(u16::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(class_value_array_byte_len); - cursor.finish(ClassDefFormat1Marker { - class_value_array_byte_len, - }) - } -} -/// [Class Definition Table Format 1](https://docs.microsoft.com/en-us/typography/opentype/spec/chapter2#class-definition-table-format-1) -pub type ClassDefFormat1<'a> = TableRef<'a, ClassDefFormat1Marker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> ClassDefFormat1<'a> { /// Format identifier — format = 1 pub fn class_format(&self) -> u16 { - let range = self.shape.class_format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.class_format_byte_range(); + unchecked::read_at(self.data, range.start) } /// First glyph ID of the classValueArray pub fn start_glyph_id(&self) -> GlyphId16 { - let range = self.shape.start_glyph_id_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.start_glyph_id_byte_range(); + unchecked::read_at(self.data, range.start) } /// Size of the classValueArray pub fn glyph_count(&self) -> u16 { - let range = self.shape.glyph_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.glyph_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Array of Class Values — one per glyph ID pub fn class_value_array(&self) -> &'a [BigEndian] { - let range = self.shape.class_value_array_byte_range(); - self.data.read_array(range).unwrap() + let range = self.class_value_array_byte_range(); + unchecked::read_array(self.data, range) } } @@ -1461,28 +1408,9 @@ impl Format for ClassDefFormat2Marker { /// [Class Definition Table Format 2](https://docs.microsoft.com/en-us/typography/opentype/spec/chapter2#class-definition-table-format-2) #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct ClassDefFormat2Marker { - class_range_records_byte_len: usize, -} - -impl ClassDefFormat2Marker { - pub fn class_format_byte_range(&self) -> Range { - let start = 0; - start..start + u16::RAW_BYTE_LEN - } - - pub fn class_range_count_byte_range(&self) -> Range { - let start = self.class_format_byte_range().end; - start..start + u16::RAW_BYTE_LEN - } - - pub fn class_range_records_byte_range(&self) -> Range { - let start = self.class_range_count_byte_range().end; - start..start + self.class_range_records_byte_len - } -} +pub struct ClassDefFormat2Marker; -impl MinByteRange for ClassDefFormat2Marker { +impl<'a> MinByteRange for ClassDefFormat2<'a> { fn min_byte_range(&self) -> Range { 0..self.class_range_records_byte_range().end } @@ -1490,40 +1418,57 @@ impl MinByteRange for ClassDefFormat2Marker { impl<'a> FontRead<'a> for ClassDefFormat2<'a> { fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - let class_range_count: u16 = cursor.read()?; - let class_range_records_byte_len = (class_range_count as usize) - .checked_mul(ClassRangeRecord::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(class_range_records_byte_len); - cursor.finish(ClassDefFormat2Marker { - class_range_records_byte_len, + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, }) } } /// [Class Definition Table Format 2](https://docs.microsoft.com/en-us/typography/opentype/spec/chapter2#class-definition-table-format-2) -pub type ClassDefFormat2<'a> = TableRef<'a, ClassDefFormat2Marker>; +pub type ClassDefFormat2<'a> = TableRef<'a, ClassDefFormat2Marker, ()>; #[allow(clippy::needless_lifetimes)] impl<'a> ClassDefFormat2<'a> { + fn class_range_records_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.class_range_count()) as usize) + .checked_mul(ClassRangeRecord::RAW_BYTE_LEN) + .unwrap() + } + + pub fn class_format_byte_range(&self) -> Range { + let start = 0; + start..start + u16::RAW_BYTE_LEN + } + + pub fn class_range_count_byte_range(&self) -> Range { + let start = self.class_format_byte_range().end; + start..start + u16::RAW_BYTE_LEN + } + + pub fn class_range_records_byte_range(&self) -> Range { + let start = self.class_range_count_byte_range().end; + start..start + self.class_range_records_byte_len(start) + } + /// Format identifier — format = 2 pub fn class_format(&self) -> u16 { - let range = self.shape.class_format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.class_format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Number of ClassRangeRecords pub fn class_range_count(&self) -> u16 { - let range = self.shape.class_range_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.class_range_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Array of ClassRangeRecords — ordered by startGlyphID pub fn class_range_records(&self) -> &'a [ClassRangeRecord] { - let range = self.shape.class_range_records_byte_range(); - self.data.read_array(range).unwrap() + let range = self.class_range_records_byte_range(); + unchecked::read_array(self.data, range) } } @@ -1729,11 +1674,36 @@ impl Format for SequenceContextFormat1Marker { /// [Sequence Context Format 1](https://docs.microsoft.com/en-us/typography/opentype/spec/chapter2#sequence-context-format-1-simple-glyph-contexts) #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct SequenceContextFormat1Marker { - seq_rule_set_offsets_byte_len: usize, +pub struct SequenceContextFormat1Marker; + +impl<'a> MinByteRange for SequenceContextFormat1<'a> { + fn min_byte_range(&self) -> Range { + 0..self.seq_rule_set_offsets_byte_range().end + } +} + +impl<'a> FontRead<'a> for SequenceContextFormat1<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } } -impl SequenceContextFormat1Marker { +/// [Sequence Context Format 1](https://docs.microsoft.com/en-us/typography/opentype/spec/chapter2#sequence-context-format-1-simple-glyph-contexts) +pub type SequenceContextFormat1<'a> = TableRef<'a, SequenceContextFormat1Marker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> SequenceContextFormat1<'a> { + fn seq_rule_set_offsets_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.seq_rule_set_count()) as usize) + .checked_mul(Offset16::RAW_BYTE_LEN) + .unwrap() + } + pub fn format_byte_range(&self) -> Range { let start = 0; start..start + u16::RAW_BYTE_LEN @@ -1751,48 +1721,20 @@ impl SequenceContextFormat1Marker { pub fn seq_rule_set_offsets_byte_range(&self) -> Range { let start = self.seq_rule_set_count_byte_range().end; - start..start + self.seq_rule_set_offsets_byte_len - } -} - -impl MinByteRange for SequenceContextFormat1Marker { - fn min_byte_range(&self) -> Range { - 0..self.seq_rule_set_offsets_byte_range().end - } -} - -impl<'a> FontRead<'a> for SequenceContextFormat1<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - let seq_rule_set_count: u16 = cursor.read()?; - let seq_rule_set_offsets_byte_len = (seq_rule_set_count as usize) - .checked_mul(Offset16::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(seq_rule_set_offsets_byte_len); - cursor.finish(SequenceContextFormat1Marker { - seq_rule_set_offsets_byte_len, - }) + start..start + self.seq_rule_set_offsets_byte_len(start) } -} - -/// [Sequence Context Format 1](https://docs.microsoft.com/en-us/typography/opentype/spec/chapter2#sequence-context-format-1-simple-glyph-contexts) -pub type SequenceContextFormat1<'a> = TableRef<'a, SequenceContextFormat1Marker>; -#[allow(clippy::needless_lifetimes)] -impl<'a> SequenceContextFormat1<'a> { /// Format identifier: format = 1 pub fn format(&self) -> u16 { - let range = self.shape.format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Offset to Coverage table, from beginning of /// SequenceContextFormat1 table pub fn coverage_offset(&self) -> Offset16 { - let range = self.shape.coverage_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.coverage_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`coverage_offset`][Self::coverage_offset]. @@ -1803,15 +1745,15 @@ impl<'a> SequenceContextFormat1<'a> { /// Number of SequenceRuleSet tables pub fn seq_rule_set_count(&self) -> u16 { - let range = self.shape.seq_rule_set_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.seq_rule_set_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Array of offsets to SequenceRuleSet tables, from beginning of /// SequenceContextFormat1 table (offsets may be NULL) pub fn seq_rule_set_offsets(&self) -> &'a [BigEndian>] { - let range = self.shape.seq_rule_set_offsets_byte_range(); - self.data.read_array(range).unwrap() + let range = self.seq_rule_set_offsets_byte_range(); + unchecked::read_array(self.data, range) } /// A dynamically resolving wrapper for [`seq_rule_set_offsets`][Self::seq_rule_set_offsets]. @@ -1865,23 +1807,9 @@ impl<'a> std::fmt::Debug for SequenceContextFormat1<'a> { /// Part of [SequenceContextFormat1] #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct SequenceRuleSetMarker { - seq_rule_offsets_byte_len: usize, -} - -impl SequenceRuleSetMarker { - pub fn seq_rule_count_byte_range(&self) -> Range { - let start = 0; - start..start + u16::RAW_BYTE_LEN - } +pub struct SequenceRuleSetMarker; - pub fn seq_rule_offsets_byte_range(&self) -> Range { - let start = self.seq_rule_count_byte_range().end; - start..start + self.seq_rule_offsets_byte_len - } -} - -impl MinByteRange for SequenceRuleSetMarker { +impl<'a> MinByteRange for SequenceRuleSet<'a> { fn min_byte_range(&self) -> Range { 0..self.seq_rule_offsets_byte_range().end } @@ -1889,34 +1817,47 @@ impl MinByteRange for SequenceRuleSetMarker { impl<'a> FontRead<'a> for SequenceRuleSet<'a> { fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - let seq_rule_count: u16 = cursor.read()?; - let seq_rule_offsets_byte_len = (seq_rule_count as usize) - .checked_mul(Offset16::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(seq_rule_offsets_byte_len); - cursor.finish(SequenceRuleSetMarker { - seq_rule_offsets_byte_len, + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, }) } } /// Part of [SequenceContextFormat1] -pub type SequenceRuleSet<'a> = TableRef<'a, SequenceRuleSetMarker>; +pub type SequenceRuleSet<'a> = TableRef<'a, SequenceRuleSetMarker, ()>; #[allow(clippy::needless_lifetimes)] impl<'a> SequenceRuleSet<'a> { + fn seq_rule_offsets_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.seq_rule_count()) as usize) + .checked_mul(Offset16::RAW_BYTE_LEN) + .unwrap() + } + + pub fn seq_rule_count_byte_range(&self) -> Range { + let start = 0; + start..start + u16::RAW_BYTE_LEN + } + + pub fn seq_rule_offsets_byte_range(&self) -> Range { + let start = self.seq_rule_count_byte_range().end; + start..start + self.seq_rule_offsets_byte_len(start) + } + /// Number of SequenceRule tables pub fn seq_rule_count(&self) -> u16 { - let range = self.shape.seq_rule_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.seq_rule_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Array of offsets to SequenceRule tables, from beginning of the /// SequenceRuleSet table pub fn seq_rule_offsets(&self) -> &'a [BigEndian] { - let range = self.shape.seq_rule_offsets_byte_range(); - self.data.read_array(range).unwrap() + let range = self.seq_rule_offsets_byte_range(); + unchecked::read_array(self.data, range) } /// A dynamically resolving wrapper for [`seq_rule_offsets`][Self::seq_rule_offsets]. @@ -1965,12 +1906,42 @@ impl<'a> std::fmt::Debug for SequenceRuleSet<'a> { /// Part of [SequenceContextFormat1] #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct SequenceRuleMarker { - input_sequence_byte_len: usize, - seq_lookup_records_byte_len: usize, +pub struct SequenceRuleMarker; + +impl<'a> MinByteRange for SequenceRule<'a> { + fn min_byte_range(&self) -> Range { + 0..self.seq_lookup_records_byte_range().end + } +} + +impl<'a> FontRead<'a> for SequenceRule<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } } -impl SequenceRuleMarker { +/// Part of [SequenceContextFormat1] +pub type SequenceRule<'a> = TableRef<'a, SequenceRuleMarker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> SequenceRule<'a> { + fn input_sequence_byte_len(&self, start: usize) -> usize { + let _ = start; + (transforms::subtract(self.glyph_count(), 1_usize)) + .checked_mul(GlyphId16::RAW_BYTE_LEN) + .unwrap() + } + fn seq_lookup_records_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.seq_lookup_count()) as usize) + .checked_mul(SequenceLookupRecord::RAW_BYTE_LEN) + .unwrap() + } + pub fn glyph_count_byte_range(&self) -> Range { let start = 0; start..start + u16::RAW_BYTE_LEN @@ -1983,68 +1954,36 @@ impl SequenceRuleMarker { pub fn input_sequence_byte_range(&self) -> Range { let start = self.seq_lookup_count_byte_range().end; - start..start + self.input_sequence_byte_len + start..start + self.input_sequence_byte_len(start) } pub fn seq_lookup_records_byte_range(&self) -> Range { let start = self.input_sequence_byte_range().end; - start..start + self.seq_lookup_records_byte_len - } -} - -impl MinByteRange for SequenceRuleMarker { - fn min_byte_range(&self) -> Range { - 0..self.seq_lookup_records_byte_range().end - } -} - -impl<'a> FontRead<'a> for SequenceRule<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - let glyph_count: u16 = cursor.read()?; - let seq_lookup_count: u16 = cursor.read()?; - let input_sequence_byte_len = (transforms::subtract(glyph_count, 1_usize)) - .checked_mul(GlyphId16::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(input_sequence_byte_len); - let seq_lookup_records_byte_len = (seq_lookup_count as usize) - .checked_mul(SequenceLookupRecord::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(seq_lookup_records_byte_len); - cursor.finish(SequenceRuleMarker { - input_sequence_byte_len, - seq_lookup_records_byte_len, - }) + start..start + self.seq_lookup_records_byte_len(start) } -} - -/// Part of [SequenceContextFormat1] -pub type SequenceRule<'a> = TableRef<'a, SequenceRuleMarker>; -#[allow(clippy::needless_lifetimes)] -impl<'a> SequenceRule<'a> { /// Number of glyphs in the input glyph sequence pub fn glyph_count(&self) -> u16 { - let range = self.shape.glyph_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.glyph_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Number of SequenceLookupRecords pub fn seq_lookup_count(&self) -> u16 { - let range = self.shape.seq_lookup_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.seq_lookup_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Array of input glyph IDs—starting with the second glyph pub fn input_sequence(&self) -> &'a [BigEndian] { - let range = self.shape.input_sequence_byte_range(); - self.data.read_array(range).unwrap() + let range = self.input_sequence_byte_range(); + unchecked::read_array(self.data, range) } /// Array of Sequence lookup records pub fn seq_lookup_records(&self) -> &'a [SequenceLookupRecord] { - let range = self.shape.seq_lookup_records_byte_range(); - self.data.read_array(range).unwrap() + let range = self.seq_lookup_records_byte_range(); + unchecked::read_array(self.data, range) } } @@ -2086,11 +2025,36 @@ impl Format for SequenceContextFormat2Marker { /// [Sequence Context Format 2](https://docs.microsoft.com/en-us/typography/opentype/spec/chapter2#sequence-context-format-2-class-based-glyph-contexts) #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct SequenceContextFormat2Marker { - class_seq_rule_set_offsets_byte_len: usize, +pub struct SequenceContextFormat2Marker; + +impl<'a> MinByteRange for SequenceContextFormat2<'a> { + fn min_byte_range(&self) -> Range { + 0..self.class_seq_rule_set_offsets_byte_range().end + } +} + +impl<'a> FontRead<'a> for SequenceContextFormat2<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } } -impl SequenceContextFormat2Marker { +/// [Sequence Context Format 2](https://docs.microsoft.com/en-us/typography/opentype/spec/chapter2#sequence-context-format-2-class-based-glyph-contexts) +pub type SequenceContextFormat2<'a> = TableRef<'a, SequenceContextFormat2Marker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> SequenceContextFormat2<'a> { + fn class_seq_rule_set_offsets_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.class_seq_rule_set_count()) as usize) + .checked_mul(Offset16::RAW_BYTE_LEN) + .unwrap() + } + pub fn format_byte_range(&self) -> Range { let start = 0; start..start + u16::RAW_BYTE_LEN @@ -2113,49 +2077,20 @@ impl SequenceContextFormat2Marker { pub fn class_seq_rule_set_offsets_byte_range(&self) -> Range { let start = self.class_seq_rule_set_count_byte_range().end; - start..start + self.class_seq_rule_set_offsets_byte_len + start..start + self.class_seq_rule_set_offsets_byte_len(start) } -} -impl MinByteRange for SequenceContextFormat2Marker { - fn min_byte_range(&self) -> Range { - 0..self.class_seq_rule_set_offsets_byte_range().end - } -} - -impl<'a> FontRead<'a> for SequenceContextFormat2<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - let class_seq_rule_set_count: u16 = cursor.read()?; - let class_seq_rule_set_offsets_byte_len = (class_seq_rule_set_count as usize) - .checked_mul(Offset16::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(class_seq_rule_set_offsets_byte_len); - cursor.finish(SequenceContextFormat2Marker { - class_seq_rule_set_offsets_byte_len, - }) - } -} - -/// [Sequence Context Format 2](https://docs.microsoft.com/en-us/typography/opentype/spec/chapter2#sequence-context-format-2-class-based-glyph-contexts) -pub type SequenceContextFormat2<'a> = TableRef<'a, SequenceContextFormat2Marker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> SequenceContextFormat2<'a> { - /// Format identifier: format = 2 - pub fn format(&self) -> u16 { - let range = self.shape.format_byte_range(); - self.data.read_at(range.start).unwrap() + /// Format identifier: format = 2 + pub fn format(&self) -> u16 { + let range = self.format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Offset to Coverage table, from beginning of /// SequenceContextFormat2 table pub fn coverage_offset(&self) -> Offset16 { - let range = self.shape.coverage_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.coverage_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`coverage_offset`][Self::coverage_offset]. @@ -2167,8 +2102,8 @@ impl<'a> SequenceContextFormat2<'a> { /// Offset to ClassDef table, from beginning of /// SequenceContextFormat2 table pub fn class_def_offset(&self) -> Offset16 { - let range = self.shape.class_def_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.class_def_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`class_def_offset`][Self::class_def_offset]. @@ -2179,15 +2114,15 @@ impl<'a> SequenceContextFormat2<'a> { /// Number of ClassSequenceRuleSet tables pub fn class_seq_rule_set_count(&self) -> u16 { - let range = self.shape.class_seq_rule_set_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.class_seq_rule_set_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Array of offsets to ClassSequenceRuleSet tables, from beginning /// of SequenceContextFormat2 table (may be NULL) pub fn class_seq_rule_set_offsets(&self) -> &'a [BigEndian>] { - let range = self.shape.class_seq_rule_set_offsets_byte_range(); - self.data.read_array(range).unwrap() + let range = self.class_seq_rule_set_offsets_byte_range(); + unchecked::read_array(self.data, range) } /// A dynamically resolving wrapper for [`class_seq_rule_set_offsets`][Self::class_seq_rule_set_offsets]. @@ -2250,23 +2185,9 @@ impl<'a> std::fmt::Debug for SequenceContextFormat2<'a> { /// Part of [SequenceContextFormat2] #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct ClassSequenceRuleSetMarker { - class_seq_rule_offsets_byte_len: usize, -} - -impl ClassSequenceRuleSetMarker { - pub fn class_seq_rule_count_byte_range(&self) -> Range { - let start = 0; - start..start + u16::RAW_BYTE_LEN - } - - pub fn class_seq_rule_offsets_byte_range(&self) -> Range { - let start = self.class_seq_rule_count_byte_range().end; - start..start + self.class_seq_rule_offsets_byte_len - } -} +pub struct ClassSequenceRuleSetMarker; -impl MinByteRange for ClassSequenceRuleSetMarker { +impl<'a> MinByteRange for ClassSequenceRuleSet<'a> { fn min_byte_range(&self) -> Range { 0..self.class_seq_rule_offsets_byte_range().end } @@ -2274,34 +2195,47 @@ impl MinByteRange for ClassSequenceRuleSetMarker { impl<'a> FontRead<'a> for ClassSequenceRuleSet<'a> { fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - let class_seq_rule_count: u16 = cursor.read()?; - let class_seq_rule_offsets_byte_len = (class_seq_rule_count as usize) - .checked_mul(Offset16::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(class_seq_rule_offsets_byte_len); - cursor.finish(ClassSequenceRuleSetMarker { - class_seq_rule_offsets_byte_len, + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, }) } } /// Part of [SequenceContextFormat2] -pub type ClassSequenceRuleSet<'a> = TableRef<'a, ClassSequenceRuleSetMarker>; +pub type ClassSequenceRuleSet<'a> = TableRef<'a, ClassSequenceRuleSetMarker, ()>; #[allow(clippy::needless_lifetimes)] impl<'a> ClassSequenceRuleSet<'a> { + fn class_seq_rule_offsets_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.class_seq_rule_count()) as usize) + .checked_mul(Offset16::RAW_BYTE_LEN) + .unwrap() + } + + pub fn class_seq_rule_count_byte_range(&self) -> Range { + let start = 0; + start..start + u16::RAW_BYTE_LEN + } + + pub fn class_seq_rule_offsets_byte_range(&self) -> Range { + let start = self.class_seq_rule_count_byte_range().end; + start..start + self.class_seq_rule_offsets_byte_len(start) + } + /// Number of ClassSequenceRule tables pub fn class_seq_rule_count(&self) -> u16 { - let range = self.shape.class_seq_rule_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.class_seq_rule_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Array of offsets to ClassSequenceRule tables, from beginning of /// ClassSequenceRuleSet table pub fn class_seq_rule_offsets(&self) -> &'a [BigEndian] { - let range = self.shape.class_seq_rule_offsets_byte_range(); - self.data.read_array(range).unwrap() + let range = self.class_seq_rule_offsets_byte_range(); + unchecked::read_array(self.data, range) } /// A dynamically resolving wrapper for [`class_seq_rule_offsets`][Self::class_seq_rule_offsets]. @@ -2353,12 +2287,42 @@ impl<'a> std::fmt::Debug for ClassSequenceRuleSet<'a> { /// Part of [SequenceContextFormat2] #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct ClassSequenceRuleMarker { - input_sequence_byte_len: usize, - seq_lookup_records_byte_len: usize, +pub struct ClassSequenceRuleMarker; + +impl<'a> MinByteRange for ClassSequenceRule<'a> { + fn min_byte_range(&self) -> Range { + 0..self.seq_lookup_records_byte_range().end + } +} + +impl<'a> FontRead<'a> for ClassSequenceRule<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } } -impl ClassSequenceRuleMarker { +/// Part of [SequenceContextFormat2] +pub type ClassSequenceRule<'a> = TableRef<'a, ClassSequenceRuleMarker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> ClassSequenceRule<'a> { + fn input_sequence_byte_len(&self, start: usize) -> usize { + let _ = start; + (transforms::subtract(self.glyph_count(), 1_usize)) + .checked_mul(u16::RAW_BYTE_LEN) + .unwrap() + } + fn seq_lookup_records_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.seq_lookup_count()) as usize) + .checked_mul(SequenceLookupRecord::RAW_BYTE_LEN) + .unwrap() + } + pub fn glyph_count_byte_range(&self) -> Range { let start = 0; start..start + u16::RAW_BYTE_LEN @@ -2371,69 +2335,37 @@ impl ClassSequenceRuleMarker { pub fn input_sequence_byte_range(&self) -> Range { let start = self.seq_lookup_count_byte_range().end; - start..start + self.input_sequence_byte_len + start..start + self.input_sequence_byte_len(start) } pub fn seq_lookup_records_byte_range(&self) -> Range { let start = self.input_sequence_byte_range().end; - start..start + self.seq_lookup_records_byte_len - } -} - -impl MinByteRange for ClassSequenceRuleMarker { - fn min_byte_range(&self) -> Range { - 0..self.seq_lookup_records_byte_range().end - } -} - -impl<'a> FontRead<'a> for ClassSequenceRule<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - let glyph_count: u16 = cursor.read()?; - let seq_lookup_count: u16 = cursor.read()?; - let input_sequence_byte_len = (transforms::subtract(glyph_count, 1_usize)) - .checked_mul(u16::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(input_sequence_byte_len); - let seq_lookup_records_byte_len = (seq_lookup_count as usize) - .checked_mul(SequenceLookupRecord::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(seq_lookup_records_byte_len); - cursor.finish(ClassSequenceRuleMarker { - input_sequence_byte_len, - seq_lookup_records_byte_len, - }) + start..start + self.seq_lookup_records_byte_len(start) } -} - -/// Part of [SequenceContextFormat2] -pub type ClassSequenceRule<'a> = TableRef<'a, ClassSequenceRuleMarker>; -#[allow(clippy::needless_lifetimes)] -impl<'a> ClassSequenceRule<'a> { /// Number of glyphs to be matched pub fn glyph_count(&self) -> u16 { - let range = self.shape.glyph_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.glyph_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Number of SequenceLookupRecords pub fn seq_lookup_count(&self) -> u16 { - let range = self.shape.seq_lookup_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.seq_lookup_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Sequence of classes to be matched to the input glyph sequence, /// beginning with the second glyph position pub fn input_sequence(&self) -> &'a [BigEndian] { - let range = self.shape.input_sequence_byte_range(); - self.data.read_array(range).unwrap() + let range = self.input_sequence_byte_range(); + unchecked::read_array(self.data, range) } /// Array of SequenceLookupRecords pub fn seq_lookup_records(&self) -> &'a [SequenceLookupRecord] { - let range = self.shape.seq_lookup_records_byte_range(); - self.data.read_array(range).unwrap() + let range = self.seq_lookup_records_byte_range(); + unchecked::read_array(self.data, range) } } @@ -2475,12 +2407,42 @@ impl Format for SequenceContextFormat3Marker { /// [Sequence Context Format 3](https://docs.microsoft.com/en-us/typography/opentype/spec/chapter2#sequence-context-format-3-coverage-based-glyph-contexts) #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct SequenceContextFormat3Marker { - coverage_offsets_byte_len: usize, - seq_lookup_records_byte_len: usize, +pub struct SequenceContextFormat3Marker; + +impl<'a> MinByteRange for SequenceContextFormat3<'a> { + fn min_byte_range(&self) -> Range { + 0..self.seq_lookup_records_byte_range().end + } +} + +impl<'a> FontRead<'a> for SequenceContextFormat3<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } } -impl SequenceContextFormat3Marker { +/// [Sequence Context Format 3](https://docs.microsoft.com/en-us/typography/opentype/spec/chapter2#sequence-context-format-3-coverage-based-glyph-contexts) +pub type SequenceContextFormat3<'a> = TableRef<'a, SequenceContextFormat3Marker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> SequenceContextFormat3<'a> { + fn coverage_offsets_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.glyph_count()) as usize) + .checked_mul(Offset16::RAW_BYTE_LEN) + .unwrap() + } + fn seq_lookup_records_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.seq_lookup_count()) as usize) + .checked_mul(SequenceLookupRecord::RAW_BYTE_LEN) + .unwrap() + } + pub fn format_byte_range(&self) -> Range { let start = 0; start..start + u16::RAW_BYTE_LEN @@ -2498,70 +2460,37 @@ impl SequenceContextFormat3Marker { pub fn coverage_offsets_byte_range(&self) -> Range { let start = self.seq_lookup_count_byte_range().end; - start..start + self.coverage_offsets_byte_len + start..start + self.coverage_offsets_byte_len(start) } pub fn seq_lookup_records_byte_range(&self) -> Range { let start = self.coverage_offsets_byte_range().end; - start..start + self.seq_lookup_records_byte_len - } -} - -impl MinByteRange for SequenceContextFormat3Marker { - fn min_byte_range(&self) -> Range { - 0..self.seq_lookup_records_byte_range().end - } -} - -impl<'a> FontRead<'a> for SequenceContextFormat3<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - let glyph_count: u16 = cursor.read()?; - let seq_lookup_count: u16 = cursor.read()?; - let coverage_offsets_byte_len = (glyph_count as usize) - .checked_mul(Offset16::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(coverage_offsets_byte_len); - let seq_lookup_records_byte_len = (seq_lookup_count as usize) - .checked_mul(SequenceLookupRecord::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(seq_lookup_records_byte_len); - cursor.finish(SequenceContextFormat3Marker { - coverage_offsets_byte_len, - seq_lookup_records_byte_len, - }) + start..start + self.seq_lookup_records_byte_len(start) } -} - -/// [Sequence Context Format 3](https://docs.microsoft.com/en-us/typography/opentype/spec/chapter2#sequence-context-format-3-coverage-based-glyph-contexts) -pub type SequenceContextFormat3<'a> = TableRef<'a, SequenceContextFormat3Marker>; -#[allow(clippy::needless_lifetimes)] -impl<'a> SequenceContextFormat3<'a> { /// Format identifier: format = 3 pub fn format(&self) -> u16 { - let range = self.shape.format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Number of glyphs in the input sequence pub fn glyph_count(&self) -> u16 { - let range = self.shape.glyph_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.glyph_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Number of SequenceLookupRecords pub fn seq_lookup_count(&self) -> u16 { - let range = self.shape.seq_lookup_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.seq_lookup_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Array of offsets to Coverage tables, from beginning of /// SequenceContextFormat3 subtable pub fn coverage_offsets(&self) -> &'a [BigEndian] { - let range = self.shape.coverage_offsets_byte_range(); - self.data.read_array(range).unwrap() + let range = self.coverage_offsets_byte_range(); + unchecked::read_array(self.data, range) } /// A dynamically resolving wrapper for [`coverage_offsets`][Self::coverage_offsets]. @@ -2573,8 +2502,8 @@ impl<'a> SequenceContextFormat3<'a> { /// Array of SequenceLookupRecords pub fn seq_lookup_records(&self) -> &'a [SequenceLookupRecord] { - let range = self.shape.seq_lookup_records_byte_range(); - self.data.read_array(range).unwrap() + let range = self.seq_lookup_records_byte_range(); + unchecked::read_array(self.data, range) } } @@ -2707,11 +2636,36 @@ impl Format for ChainedSequenceContextFormat1Marker { /// [Chained Sequence Context Format 1](https://docs.microsoft.com/en-us/typography/opentype/spec/chapter2#chained-sequence-context-format-1-simple-glyph-contexts) #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct ChainedSequenceContextFormat1Marker { - chained_seq_rule_set_offsets_byte_len: usize, +pub struct ChainedSequenceContextFormat1Marker; + +impl<'a> MinByteRange for ChainedSequenceContextFormat1<'a> { + fn min_byte_range(&self) -> Range { + 0..self.chained_seq_rule_set_offsets_byte_range().end + } +} + +impl<'a> FontRead<'a> for ChainedSequenceContextFormat1<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } } -impl ChainedSequenceContextFormat1Marker { +/// [Chained Sequence Context Format 1](https://docs.microsoft.com/en-us/typography/opentype/spec/chapter2#chained-sequence-context-format-1-simple-glyph-contexts) +pub type ChainedSequenceContextFormat1<'a> = TableRef<'a, ChainedSequenceContextFormat1Marker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> ChainedSequenceContextFormat1<'a> { + fn chained_seq_rule_set_offsets_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.chained_seq_rule_set_count()) as usize) + .checked_mul(Offset16::RAW_BYTE_LEN) + .unwrap() + } + pub fn format_byte_range(&self) -> Range { let start = 0; start..start + u16::RAW_BYTE_LEN @@ -2729,48 +2683,20 @@ impl ChainedSequenceContextFormat1Marker { pub fn chained_seq_rule_set_offsets_byte_range(&self) -> Range { let start = self.chained_seq_rule_set_count_byte_range().end; - start..start + self.chained_seq_rule_set_offsets_byte_len - } -} - -impl MinByteRange for ChainedSequenceContextFormat1Marker { - fn min_byte_range(&self) -> Range { - 0..self.chained_seq_rule_set_offsets_byte_range().end - } -} - -impl<'a> FontRead<'a> for ChainedSequenceContextFormat1<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - let chained_seq_rule_set_count: u16 = cursor.read()?; - let chained_seq_rule_set_offsets_byte_len = (chained_seq_rule_set_count as usize) - .checked_mul(Offset16::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(chained_seq_rule_set_offsets_byte_len); - cursor.finish(ChainedSequenceContextFormat1Marker { - chained_seq_rule_set_offsets_byte_len, - }) + start..start + self.chained_seq_rule_set_offsets_byte_len(start) } -} -/// [Chained Sequence Context Format 1](https://docs.microsoft.com/en-us/typography/opentype/spec/chapter2#chained-sequence-context-format-1-simple-glyph-contexts) -pub type ChainedSequenceContextFormat1<'a> = TableRef<'a, ChainedSequenceContextFormat1Marker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> ChainedSequenceContextFormat1<'a> { /// Format identifier: format = 1 pub fn format(&self) -> u16 { - let range = self.shape.format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Offset to Coverage table, from beginning of /// ChainSequenceContextFormat1 table pub fn coverage_offset(&self) -> Offset16 { - let range = self.shape.coverage_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.coverage_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`coverage_offset`][Self::coverage_offset]. @@ -2781,15 +2707,15 @@ impl<'a> ChainedSequenceContextFormat1<'a> { /// Number of ChainedSequenceRuleSet tables pub fn chained_seq_rule_set_count(&self) -> u16 { - let range = self.shape.chained_seq_rule_set_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.chained_seq_rule_set_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Array of offsets to ChainedSeqRuleSet tables, from beginning of /// ChainedSequenceContextFormat1 table (may be NULL) pub fn chained_seq_rule_set_offsets(&self) -> &'a [BigEndian>] { - let range = self.shape.chained_seq_rule_set_offsets_byte_range(); - self.data.read_array(range).unwrap() + let range = self.chained_seq_rule_set_offsets_byte_range(); + unchecked::read_array(self.data, range) } /// A dynamically resolving wrapper for [`chained_seq_rule_set_offsets`][Self::chained_seq_rule_set_offsets]. @@ -2848,23 +2774,9 @@ impl<'a> std::fmt::Debug for ChainedSequenceContextFormat1<'a> { /// Part of [ChainedSequenceContextFormat1] #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct ChainedSequenceRuleSetMarker { - chained_seq_rule_offsets_byte_len: usize, -} - -impl ChainedSequenceRuleSetMarker { - pub fn chained_seq_rule_count_byte_range(&self) -> Range { - let start = 0; - start..start + u16::RAW_BYTE_LEN - } - - pub fn chained_seq_rule_offsets_byte_range(&self) -> Range { - let start = self.chained_seq_rule_count_byte_range().end; - start..start + self.chained_seq_rule_offsets_byte_len - } -} +pub struct ChainedSequenceRuleSetMarker; -impl MinByteRange for ChainedSequenceRuleSetMarker { +impl<'a> MinByteRange for ChainedSequenceRuleSet<'a> { fn min_byte_range(&self) -> Range { 0..self.chained_seq_rule_offsets_byte_range().end } @@ -2872,34 +2784,47 @@ impl MinByteRange for ChainedSequenceRuleSetMarker { impl<'a> FontRead<'a> for ChainedSequenceRuleSet<'a> { fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - let chained_seq_rule_count: u16 = cursor.read()?; - let chained_seq_rule_offsets_byte_len = (chained_seq_rule_count as usize) - .checked_mul(Offset16::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(chained_seq_rule_offsets_byte_len); - cursor.finish(ChainedSequenceRuleSetMarker { - chained_seq_rule_offsets_byte_len, + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, }) } } /// Part of [ChainedSequenceContextFormat1] -pub type ChainedSequenceRuleSet<'a> = TableRef<'a, ChainedSequenceRuleSetMarker>; +pub type ChainedSequenceRuleSet<'a> = TableRef<'a, ChainedSequenceRuleSetMarker, ()>; #[allow(clippy::needless_lifetimes)] impl<'a> ChainedSequenceRuleSet<'a> { + fn chained_seq_rule_offsets_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.chained_seq_rule_count()) as usize) + .checked_mul(Offset16::RAW_BYTE_LEN) + .unwrap() + } + + pub fn chained_seq_rule_count_byte_range(&self) -> Range { + let start = 0; + start..start + u16::RAW_BYTE_LEN + } + + pub fn chained_seq_rule_offsets_byte_range(&self) -> Range { + let start = self.chained_seq_rule_count_byte_range().end; + start..start + self.chained_seq_rule_offsets_byte_len(start) + } + /// Number of ChainedSequenceRule tables pub fn chained_seq_rule_count(&self) -> u16 { - let range = self.shape.chained_seq_rule_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.chained_seq_rule_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Array of offsets to ChainedSequenceRule tables, from beginning /// of ChainedSequenceRuleSet table pub fn chained_seq_rule_offsets(&self) -> &'a [BigEndian] { - let range = self.shape.chained_seq_rule_offsets_byte_range(); - self.data.read_array(range).unwrap() + let range = self.chained_seq_rule_offsets_byte_range(); + unchecked::read_array(self.data, range) } /// A dynamically resolving wrapper for [`chained_seq_rule_offsets`][Self::chained_seq_rule_offsets]. @@ -2951,14 +2876,54 @@ impl<'a> std::fmt::Debug for ChainedSequenceRuleSet<'a> { /// Part of [ChainedSequenceContextFormat1] #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct ChainedSequenceRuleMarker { - backtrack_sequence_byte_len: usize, - input_sequence_byte_len: usize, - lookahead_sequence_byte_len: usize, - seq_lookup_records_byte_len: usize, +pub struct ChainedSequenceRuleMarker; + +impl<'a> MinByteRange for ChainedSequenceRule<'a> { + fn min_byte_range(&self) -> Range { + 0..self.seq_lookup_records_byte_range().end + } +} + +impl<'a> FontRead<'a> for ChainedSequenceRule<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } } -impl ChainedSequenceRuleMarker { +/// Part of [ChainedSequenceContextFormat1] +pub type ChainedSequenceRule<'a> = TableRef<'a, ChainedSequenceRuleMarker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> ChainedSequenceRule<'a> { + fn backtrack_sequence_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.backtrack_glyph_count()) as usize) + .checked_mul(GlyphId16::RAW_BYTE_LEN) + .unwrap() + } + fn input_sequence_byte_len(&self, start: usize) -> usize { + let _ = start; + (transforms::subtract(self.input_glyph_count(), 1_usize)) + .checked_mul(GlyphId16::RAW_BYTE_LEN) + .unwrap() + } + fn lookahead_sequence_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.lookahead_glyph_count()) as usize) + .checked_mul(GlyphId16::RAW_BYTE_LEN) + .unwrap() + } + fn seq_lookup_records_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.seq_lookup_count()) as usize) + .checked_mul(SequenceLookupRecord::RAW_BYTE_LEN) + .unwrap() + } + pub fn backtrack_glyph_count_byte_range(&self) -> Range { let start = 0; start..start + u16::RAW_BYTE_LEN @@ -2966,7 +2931,7 @@ impl ChainedSequenceRuleMarker { pub fn backtrack_sequence_byte_range(&self) -> Range { let start = self.backtrack_glyph_count_byte_range().end; - start..start + self.backtrack_sequence_byte_len + start..start + self.backtrack_sequence_byte_len(start) } pub fn input_glyph_count_byte_range(&self) -> Range { @@ -2976,7 +2941,7 @@ impl ChainedSequenceRuleMarker { pub fn input_sequence_byte_range(&self) -> Range { let start = self.input_glyph_count_byte_range().end; - start..start + self.input_sequence_byte_len + start..start + self.input_sequence_byte_len(start) } pub fn lookahead_glyph_count_byte_range(&self) -> Range { @@ -2986,7 +2951,7 @@ impl ChainedSequenceRuleMarker { pub fn lookahead_sequence_byte_range(&self) -> Range { let start = self.lookahead_glyph_count_byte_range().end; - start..start + self.lookahead_sequence_byte_len + start..start + self.lookahead_sequence_byte_len(start) } pub fn seq_lookup_count_byte_range(&self) -> Range { @@ -2996,99 +2961,55 @@ impl ChainedSequenceRuleMarker { pub fn seq_lookup_records_byte_range(&self) -> Range { let start = self.seq_lookup_count_byte_range().end; - start..start + self.seq_lookup_records_byte_len - } -} - -impl MinByteRange for ChainedSequenceRuleMarker { - fn min_byte_range(&self) -> Range { - 0..self.seq_lookup_records_byte_range().end - } -} - -impl<'a> FontRead<'a> for ChainedSequenceRule<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - let backtrack_glyph_count: u16 = cursor.read()?; - let backtrack_sequence_byte_len = (backtrack_glyph_count as usize) - .checked_mul(GlyphId16::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(backtrack_sequence_byte_len); - let input_glyph_count: u16 = cursor.read()?; - let input_sequence_byte_len = (transforms::subtract(input_glyph_count, 1_usize)) - .checked_mul(GlyphId16::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(input_sequence_byte_len); - let lookahead_glyph_count: u16 = cursor.read()?; - let lookahead_sequence_byte_len = (lookahead_glyph_count as usize) - .checked_mul(GlyphId16::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(lookahead_sequence_byte_len); - let seq_lookup_count: u16 = cursor.read()?; - let seq_lookup_records_byte_len = (seq_lookup_count as usize) - .checked_mul(SequenceLookupRecord::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(seq_lookup_records_byte_len); - cursor.finish(ChainedSequenceRuleMarker { - backtrack_sequence_byte_len, - input_sequence_byte_len, - lookahead_sequence_byte_len, - seq_lookup_records_byte_len, - }) + start..start + self.seq_lookup_records_byte_len(start) } -} - -/// Part of [ChainedSequenceContextFormat1] -pub type ChainedSequenceRule<'a> = TableRef<'a, ChainedSequenceRuleMarker>; -#[allow(clippy::needless_lifetimes)] -impl<'a> ChainedSequenceRule<'a> { /// Number of glyphs in the backtrack sequence pub fn backtrack_glyph_count(&self) -> u16 { - let range = self.shape.backtrack_glyph_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.backtrack_glyph_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Array of backtrack glyph IDs pub fn backtrack_sequence(&self) -> &'a [BigEndian] { - let range = self.shape.backtrack_sequence_byte_range(); - self.data.read_array(range).unwrap() + let range = self.backtrack_sequence_byte_range(); + unchecked::read_array(self.data, range) } /// Number of glyphs in the input sequence pub fn input_glyph_count(&self) -> u16 { - let range = self.shape.input_glyph_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.input_glyph_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Array of input glyph IDs—start with second glyph pub fn input_sequence(&self) -> &'a [BigEndian] { - let range = self.shape.input_sequence_byte_range(); - self.data.read_array(range).unwrap() + let range = self.input_sequence_byte_range(); + unchecked::read_array(self.data, range) } /// Number of glyphs in the lookahead sequence pub fn lookahead_glyph_count(&self) -> u16 { - let range = self.shape.lookahead_glyph_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.lookahead_glyph_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Array of lookahead glyph IDs pub fn lookahead_sequence(&self) -> &'a [BigEndian] { - let range = self.shape.lookahead_sequence_byte_range(); - self.data.read_array(range).unwrap() + let range = self.lookahead_sequence_byte_range(); + unchecked::read_array(self.data, range) } /// Number of SequenceLookupRecords pub fn seq_lookup_count(&self) -> u16 { - let range = self.shape.seq_lookup_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.seq_lookup_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Array of SequenceLookupRecords pub fn seq_lookup_records(&self) -> &'a [SequenceLookupRecord] { - let range = self.shape.seq_lookup_records_byte_range(); - self.data.read_array(range).unwrap() + let range = self.seq_lookup_records_byte_range(); + unchecked::read_array(self.data, range) } } @@ -3140,11 +3061,36 @@ impl Format for ChainedSequenceContextFormat2Marker { /// [Chained Sequence Context Format 2](https://docs.microsoft.com/en-us/typography/opentype/spec/chapter2#chained-sequence-context-format-2-class-based-glyph-contexts) #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct ChainedSequenceContextFormat2Marker { - chained_class_seq_rule_set_offsets_byte_len: usize, +pub struct ChainedSequenceContextFormat2Marker; + +impl<'a> MinByteRange for ChainedSequenceContextFormat2<'a> { + fn min_byte_range(&self) -> Range { + 0..self.chained_class_seq_rule_set_offsets_byte_range().end + } +} + +impl<'a> FontRead<'a> for ChainedSequenceContextFormat2<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } } -impl ChainedSequenceContextFormat2Marker { +/// [Chained Sequence Context Format 2](https://docs.microsoft.com/en-us/typography/opentype/spec/chapter2#chained-sequence-context-format-2-class-based-glyph-contexts) +pub type ChainedSequenceContextFormat2<'a> = TableRef<'a, ChainedSequenceContextFormat2Marker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> ChainedSequenceContextFormat2<'a> { + fn chained_class_seq_rule_set_offsets_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.chained_class_seq_rule_set_count()) as usize) + .checked_mul(Offset16::RAW_BYTE_LEN) + .unwrap() + } + pub fn format_byte_range(&self) -> Range { let start = 0; start..start + u16::RAW_BYTE_LEN @@ -3177,52 +3123,20 @@ impl ChainedSequenceContextFormat2Marker { pub fn chained_class_seq_rule_set_offsets_byte_range(&self) -> Range { let start = self.chained_class_seq_rule_set_count_byte_range().end; - start..start + self.chained_class_seq_rule_set_offsets_byte_len - } -} - -impl MinByteRange for ChainedSequenceContextFormat2Marker { - fn min_byte_range(&self) -> Range { - 0..self.chained_class_seq_rule_set_offsets_byte_range().end - } -} - -impl<'a> FontRead<'a> for ChainedSequenceContextFormat2<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - let chained_class_seq_rule_set_count: u16 = cursor.read()?; - let chained_class_seq_rule_set_offsets_byte_len = (chained_class_seq_rule_set_count - as usize) - .checked_mul(Offset16::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(chained_class_seq_rule_set_offsets_byte_len); - cursor.finish(ChainedSequenceContextFormat2Marker { - chained_class_seq_rule_set_offsets_byte_len, - }) + start..start + self.chained_class_seq_rule_set_offsets_byte_len(start) } -} -/// [Chained Sequence Context Format 2](https://docs.microsoft.com/en-us/typography/opentype/spec/chapter2#chained-sequence-context-format-2-class-based-glyph-contexts) -pub type ChainedSequenceContextFormat2<'a> = TableRef<'a, ChainedSequenceContextFormat2Marker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> ChainedSequenceContextFormat2<'a> { /// Format identifier: format = 2 pub fn format(&self) -> u16 { - let range = self.shape.format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Offset to Coverage table, from beginning of /// ChainedSequenceContextFormat2 table pub fn coverage_offset(&self) -> Offset16 { - let range = self.shape.coverage_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.coverage_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`coverage_offset`][Self::coverage_offset]. @@ -3234,8 +3148,8 @@ impl<'a> ChainedSequenceContextFormat2<'a> { /// Offset to ClassDef table containing backtrack sequence context, /// from beginning of ChainedSequenceContextFormat2 table pub fn backtrack_class_def_offset(&self) -> Offset16 { - let range = self.shape.backtrack_class_def_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.backtrack_class_def_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`backtrack_class_def_offset`][Self::backtrack_class_def_offset]. @@ -3247,8 +3161,8 @@ impl<'a> ChainedSequenceContextFormat2<'a> { /// Offset to ClassDef table containing input sequence context, /// from beginning of ChainedSequenceContextFormat2 table pub fn input_class_def_offset(&self) -> Offset16 { - let range = self.shape.input_class_def_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.input_class_def_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`input_class_def_offset`][Self::input_class_def_offset]. @@ -3260,8 +3174,8 @@ impl<'a> ChainedSequenceContextFormat2<'a> { /// Offset to ClassDef table containing lookahead sequence context, /// from beginning of ChainedSequenceContextFormat2 table pub fn lookahead_class_def_offset(&self) -> Offset16 { - let range = self.shape.lookahead_class_def_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.lookahead_class_def_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`lookahead_class_def_offset`][Self::lookahead_class_def_offset]. @@ -3272,15 +3186,15 @@ impl<'a> ChainedSequenceContextFormat2<'a> { /// Number of ChainedClassSequenceRuleSet tables pub fn chained_class_seq_rule_set_count(&self) -> u16 { - let range = self.shape.chained_class_seq_rule_set_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.chained_class_seq_rule_set_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Array of offsets to ChainedClassSequenceRuleSet tables, from /// beginning of ChainedSequenceContextFormat2 table (may be NULL) pub fn chained_class_seq_rule_set_offsets(&self) -> &'a [BigEndian>] { - let range = self.shape.chained_class_seq_rule_set_offsets_byte_range(); - self.data.read_array(range).unwrap() + let range = self.chained_class_seq_rule_set_offsets_byte_range(); + unchecked::read_array(self.data, range) } /// A dynamically resolving wrapper for [`chained_class_seq_rule_set_offsets`][Self::chained_class_seq_rule_set_offsets]. @@ -3357,23 +3271,9 @@ impl<'a> std::fmt::Debug for ChainedSequenceContextFormat2<'a> { /// Part of [ChainedSequenceContextFormat2] #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct ChainedClassSequenceRuleSetMarker { - chained_class_seq_rule_offsets_byte_len: usize, -} - -impl ChainedClassSequenceRuleSetMarker { - pub fn chained_class_seq_rule_count_byte_range(&self) -> Range { - let start = 0; - start..start + u16::RAW_BYTE_LEN - } - - pub fn chained_class_seq_rule_offsets_byte_range(&self) -> Range { - let start = self.chained_class_seq_rule_count_byte_range().end; - start..start + self.chained_class_seq_rule_offsets_byte_len - } -} +pub struct ChainedClassSequenceRuleSetMarker; -impl MinByteRange for ChainedClassSequenceRuleSetMarker { +impl<'a> MinByteRange for ChainedClassSequenceRuleSet<'a> { fn min_byte_range(&self) -> Range { 0..self.chained_class_seq_rule_offsets_byte_range().end } @@ -3381,34 +3281,47 @@ impl MinByteRange for ChainedClassSequenceRuleSetMarker { impl<'a> FontRead<'a> for ChainedClassSequenceRuleSet<'a> { fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - let chained_class_seq_rule_count: u16 = cursor.read()?; - let chained_class_seq_rule_offsets_byte_len = (chained_class_seq_rule_count as usize) - .checked_mul(Offset16::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(chained_class_seq_rule_offsets_byte_len); - cursor.finish(ChainedClassSequenceRuleSetMarker { - chained_class_seq_rule_offsets_byte_len, + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, }) } } /// Part of [ChainedSequenceContextFormat2] -pub type ChainedClassSequenceRuleSet<'a> = TableRef<'a, ChainedClassSequenceRuleSetMarker>; +pub type ChainedClassSequenceRuleSet<'a> = TableRef<'a, ChainedClassSequenceRuleSetMarker, ()>; #[allow(clippy::needless_lifetimes)] impl<'a> ChainedClassSequenceRuleSet<'a> { + fn chained_class_seq_rule_offsets_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.chained_class_seq_rule_count()) as usize) + .checked_mul(Offset16::RAW_BYTE_LEN) + .unwrap() + } + + pub fn chained_class_seq_rule_count_byte_range(&self) -> Range { + let start = 0; + start..start + u16::RAW_BYTE_LEN + } + + pub fn chained_class_seq_rule_offsets_byte_range(&self) -> Range { + let start = self.chained_class_seq_rule_count_byte_range().end; + start..start + self.chained_class_seq_rule_offsets_byte_len(start) + } + /// Number of ChainedClassSequenceRule tables pub fn chained_class_seq_rule_count(&self) -> u16 { - let range = self.shape.chained_class_seq_rule_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.chained_class_seq_rule_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Array of offsets to ChainedClassSequenceRule tables, from /// beginning of ChainedClassSequenceRuleSet pub fn chained_class_seq_rule_offsets(&self) -> &'a [BigEndian] { - let range = self.shape.chained_class_seq_rule_offsets_byte_range(); - self.data.read_array(range).unwrap() + let range = self.chained_class_seq_rule_offsets_byte_range(); + unchecked::read_array(self.data, range) } /// A dynamically resolving wrapper for [`chained_class_seq_rule_offsets`][Self::chained_class_seq_rule_offsets]. @@ -3462,14 +3375,54 @@ impl<'a> std::fmt::Debug for ChainedClassSequenceRuleSet<'a> { /// Part of [ChainedSequenceContextFormat2] #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct ChainedClassSequenceRuleMarker { - backtrack_sequence_byte_len: usize, - input_sequence_byte_len: usize, - lookahead_sequence_byte_len: usize, - seq_lookup_records_byte_len: usize, +pub struct ChainedClassSequenceRuleMarker; + +impl<'a> MinByteRange for ChainedClassSequenceRule<'a> { + fn min_byte_range(&self) -> Range { + 0..self.seq_lookup_records_byte_range().end + } +} + +impl<'a> FontRead<'a> for ChainedClassSequenceRule<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } } -impl ChainedClassSequenceRuleMarker { +/// Part of [ChainedSequenceContextFormat2] +pub type ChainedClassSequenceRule<'a> = TableRef<'a, ChainedClassSequenceRuleMarker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> ChainedClassSequenceRule<'a> { + fn backtrack_sequence_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.backtrack_glyph_count()) as usize) + .checked_mul(u16::RAW_BYTE_LEN) + .unwrap() + } + fn input_sequence_byte_len(&self, start: usize) -> usize { + let _ = start; + (transforms::subtract(self.input_glyph_count(), 1_usize)) + .checked_mul(u16::RAW_BYTE_LEN) + .unwrap() + } + fn lookahead_sequence_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.lookahead_glyph_count()) as usize) + .checked_mul(u16::RAW_BYTE_LEN) + .unwrap() + } + fn seq_lookup_records_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.seq_lookup_count()) as usize) + .checked_mul(SequenceLookupRecord::RAW_BYTE_LEN) + .unwrap() + } + pub fn backtrack_glyph_count_byte_range(&self) -> Range { let start = 0; start..start + u16::RAW_BYTE_LEN @@ -3477,7 +3430,7 @@ impl ChainedClassSequenceRuleMarker { pub fn backtrack_sequence_byte_range(&self) -> Range { let start = self.backtrack_glyph_count_byte_range().end; - start..start + self.backtrack_sequence_byte_len + start..start + self.backtrack_sequence_byte_len(start) } pub fn input_glyph_count_byte_range(&self) -> Range { @@ -3487,7 +3440,7 @@ impl ChainedClassSequenceRuleMarker { pub fn input_sequence_byte_range(&self) -> Range { let start = self.input_glyph_count_byte_range().end; - start..start + self.input_sequence_byte_len + start..start + self.input_sequence_byte_len(start) } pub fn lookahead_glyph_count_byte_range(&self) -> Range { @@ -3497,7 +3450,7 @@ impl ChainedClassSequenceRuleMarker { pub fn lookahead_sequence_byte_range(&self) -> Range { let start = self.lookahead_glyph_count_byte_range().end; - start..start + self.lookahead_sequence_byte_len + start..start + self.lookahead_sequence_byte_len(start) } pub fn seq_lookup_count_byte_range(&self) -> Range { @@ -3507,100 +3460,56 @@ impl ChainedClassSequenceRuleMarker { pub fn seq_lookup_records_byte_range(&self) -> Range { let start = self.seq_lookup_count_byte_range().end; - start..start + self.seq_lookup_records_byte_len - } -} - -impl MinByteRange for ChainedClassSequenceRuleMarker { - fn min_byte_range(&self) -> Range { - 0..self.seq_lookup_records_byte_range().end - } -} - -impl<'a> FontRead<'a> for ChainedClassSequenceRule<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - let backtrack_glyph_count: u16 = cursor.read()?; - let backtrack_sequence_byte_len = (backtrack_glyph_count as usize) - .checked_mul(u16::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(backtrack_sequence_byte_len); - let input_glyph_count: u16 = cursor.read()?; - let input_sequence_byte_len = (transforms::subtract(input_glyph_count, 1_usize)) - .checked_mul(u16::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(input_sequence_byte_len); - let lookahead_glyph_count: u16 = cursor.read()?; - let lookahead_sequence_byte_len = (lookahead_glyph_count as usize) - .checked_mul(u16::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(lookahead_sequence_byte_len); - let seq_lookup_count: u16 = cursor.read()?; - let seq_lookup_records_byte_len = (seq_lookup_count as usize) - .checked_mul(SequenceLookupRecord::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(seq_lookup_records_byte_len); - cursor.finish(ChainedClassSequenceRuleMarker { - backtrack_sequence_byte_len, - input_sequence_byte_len, - lookahead_sequence_byte_len, - seq_lookup_records_byte_len, - }) + start..start + self.seq_lookup_records_byte_len(start) } -} - -/// Part of [ChainedSequenceContextFormat2] -pub type ChainedClassSequenceRule<'a> = TableRef<'a, ChainedClassSequenceRuleMarker>; -#[allow(clippy::needless_lifetimes)] -impl<'a> ChainedClassSequenceRule<'a> { /// Number of glyphs in the backtrack sequence pub fn backtrack_glyph_count(&self) -> u16 { - let range = self.shape.backtrack_glyph_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.backtrack_glyph_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Array of backtrack-sequence classes pub fn backtrack_sequence(&self) -> &'a [BigEndian] { - let range = self.shape.backtrack_sequence_byte_range(); - self.data.read_array(range).unwrap() + let range = self.backtrack_sequence_byte_range(); + unchecked::read_array(self.data, range) } /// Total number of glyphs in the input sequence pub fn input_glyph_count(&self) -> u16 { - let range = self.shape.input_glyph_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.input_glyph_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Array of input sequence classes, beginning with the second /// glyph position pub fn input_sequence(&self) -> &'a [BigEndian] { - let range = self.shape.input_sequence_byte_range(); - self.data.read_array(range).unwrap() + let range = self.input_sequence_byte_range(); + unchecked::read_array(self.data, range) } /// Number of glyphs in the lookahead sequence pub fn lookahead_glyph_count(&self) -> u16 { - let range = self.shape.lookahead_glyph_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.lookahead_glyph_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Array of lookahead-sequence classes pub fn lookahead_sequence(&self) -> &'a [BigEndian] { - let range = self.shape.lookahead_sequence_byte_range(); - self.data.read_array(range).unwrap() + let range = self.lookahead_sequence_byte_range(); + unchecked::read_array(self.data, range) } /// Number of SequenceLookupRecords pub fn seq_lookup_count(&self) -> u16 { - let range = self.shape.seq_lookup_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.seq_lookup_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Array of SequenceLookupRecords pub fn seq_lookup_records(&self) -> &'a [SequenceLookupRecord] { - let range = self.shape.seq_lookup_records_byte_range(); - self.data.read_array(range).unwrap() + let range = self.seq_lookup_records_byte_range(); + unchecked::read_array(self.data, range) } } @@ -3652,14 +3561,54 @@ impl Format for ChainedSequenceContextFormat3Marker { /// [Chained Sequence Context Format 3](https://docs.microsoft.com/en-us/typography/opentype/spec/chapter2#chained-sequence-context-format-3-coverage-based-glyph-contexts) #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct ChainedSequenceContextFormat3Marker { - backtrack_coverage_offsets_byte_len: usize, - input_coverage_offsets_byte_len: usize, - lookahead_coverage_offsets_byte_len: usize, - seq_lookup_records_byte_len: usize, +pub struct ChainedSequenceContextFormat3Marker; + +impl<'a> MinByteRange for ChainedSequenceContextFormat3<'a> { + fn min_byte_range(&self) -> Range { + 0..self.seq_lookup_records_byte_range().end + } +} + +impl<'a> FontRead<'a> for ChainedSequenceContextFormat3<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } } -impl ChainedSequenceContextFormat3Marker { +/// [Chained Sequence Context Format 3](https://docs.microsoft.com/en-us/typography/opentype/spec/chapter2#chained-sequence-context-format-3-coverage-based-glyph-contexts) +pub type ChainedSequenceContextFormat3<'a> = TableRef<'a, ChainedSequenceContextFormat3Marker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> ChainedSequenceContextFormat3<'a> { + fn backtrack_coverage_offsets_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.backtrack_glyph_count()) as usize) + .checked_mul(Offset16::RAW_BYTE_LEN) + .unwrap() + } + fn input_coverage_offsets_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.input_glyph_count()) as usize) + .checked_mul(Offset16::RAW_BYTE_LEN) + .unwrap() + } + fn lookahead_coverage_offsets_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.lookahead_glyph_count()) as usize) + .checked_mul(Offset16::RAW_BYTE_LEN) + .unwrap() + } + fn seq_lookup_records_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.seq_lookup_count()) as usize) + .checked_mul(SequenceLookupRecord::RAW_BYTE_LEN) + .unwrap() + } + pub fn format_byte_range(&self) -> Range { let start = 0; start..start + u16::RAW_BYTE_LEN @@ -3672,7 +3621,7 @@ impl ChainedSequenceContextFormat3Marker { pub fn backtrack_coverage_offsets_byte_range(&self) -> Range { let start = self.backtrack_glyph_count_byte_range().end; - start..start + self.backtrack_coverage_offsets_byte_len + start..start + self.backtrack_coverage_offsets_byte_len(start) } pub fn input_glyph_count_byte_range(&self) -> Range { @@ -3682,7 +3631,7 @@ impl ChainedSequenceContextFormat3Marker { pub fn input_coverage_offsets_byte_range(&self) -> Range { let start = self.input_glyph_count_byte_range().end; - start..start + self.input_coverage_offsets_byte_len + start..start + self.input_coverage_offsets_byte_len(start) } pub fn lookahead_glyph_count_byte_range(&self) -> Range { @@ -3692,7 +3641,7 @@ impl ChainedSequenceContextFormat3Marker { pub fn lookahead_coverage_offsets_byte_range(&self) -> Range { let start = self.lookahead_glyph_count_byte_range().end; - start..start + self.lookahead_coverage_offsets_byte_len + start..start + self.lookahead_coverage_offsets_byte_len(start) } pub fn seq_lookup_count_byte_range(&self) -> Range { @@ -3702,70 +3651,25 @@ impl ChainedSequenceContextFormat3Marker { pub fn seq_lookup_records_byte_range(&self) -> Range { let start = self.seq_lookup_count_byte_range().end; - start..start + self.seq_lookup_records_byte_len - } -} - -impl MinByteRange for ChainedSequenceContextFormat3Marker { - fn min_byte_range(&self) -> Range { - 0..self.seq_lookup_records_byte_range().end - } -} - -impl<'a> FontRead<'a> for ChainedSequenceContextFormat3<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - let backtrack_glyph_count: u16 = cursor.read()?; - let backtrack_coverage_offsets_byte_len = (backtrack_glyph_count as usize) - .checked_mul(Offset16::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(backtrack_coverage_offsets_byte_len); - let input_glyph_count: u16 = cursor.read()?; - let input_coverage_offsets_byte_len = (input_glyph_count as usize) - .checked_mul(Offset16::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(input_coverage_offsets_byte_len); - let lookahead_glyph_count: u16 = cursor.read()?; - let lookahead_coverage_offsets_byte_len = (lookahead_glyph_count as usize) - .checked_mul(Offset16::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(lookahead_coverage_offsets_byte_len); - let seq_lookup_count: u16 = cursor.read()?; - let seq_lookup_records_byte_len = (seq_lookup_count as usize) - .checked_mul(SequenceLookupRecord::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(seq_lookup_records_byte_len); - cursor.finish(ChainedSequenceContextFormat3Marker { - backtrack_coverage_offsets_byte_len, - input_coverage_offsets_byte_len, - lookahead_coverage_offsets_byte_len, - seq_lookup_records_byte_len, - }) + start..start + self.seq_lookup_records_byte_len(start) } -} - -/// [Chained Sequence Context Format 3](https://docs.microsoft.com/en-us/typography/opentype/spec/chapter2#chained-sequence-context-format-3-coverage-based-glyph-contexts) -pub type ChainedSequenceContextFormat3<'a> = TableRef<'a, ChainedSequenceContextFormat3Marker>; -#[allow(clippy::needless_lifetimes)] -impl<'a> ChainedSequenceContextFormat3<'a> { /// Format identifier: format = 3 pub fn format(&self) -> u16 { - let range = self.shape.format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Number of glyphs in the backtrack sequence pub fn backtrack_glyph_count(&self) -> u16 { - let range = self.shape.backtrack_glyph_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.backtrack_glyph_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Array of offsets to coverage tables for the backtrack sequence pub fn backtrack_coverage_offsets(&self) -> &'a [BigEndian] { - let range = self.shape.backtrack_coverage_offsets_byte_range(); - self.data.read_array(range).unwrap() + let range = self.backtrack_coverage_offsets_byte_range(); + unchecked::read_array(self.data, range) } /// A dynamically resolving wrapper for [`backtrack_coverage_offsets`][Self::backtrack_coverage_offsets]. @@ -3777,14 +3681,14 @@ impl<'a> ChainedSequenceContextFormat3<'a> { /// Number of glyphs in the input sequence pub fn input_glyph_count(&self) -> u16 { - let range = self.shape.input_glyph_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.input_glyph_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Array of offsets to coverage tables for the input sequence pub fn input_coverage_offsets(&self) -> &'a [BigEndian] { - let range = self.shape.input_coverage_offsets_byte_range(); - self.data.read_array(range).unwrap() + let range = self.input_coverage_offsets_byte_range(); + unchecked::read_array(self.data, range) } /// A dynamically resolving wrapper for [`input_coverage_offsets`][Self::input_coverage_offsets]. @@ -3796,14 +3700,14 @@ impl<'a> ChainedSequenceContextFormat3<'a> { /// Number of glyphs in the lookahead sequence pub fn lookahead_glyph_count(&self) -> u16 { - let range = self.shape.lookahead_glyph_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.lookahead_glyph_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Array of offsets to coverage tables for the lookahead sequence pub fn lookahead_coverage_offsets(&self) -> &'a [BigEndian] { - let range = self.shape.lookahead_coverage_offsets_byte_range(); - self.data.read_array(range).unwrap() + let range = self.lookahead_coverage_offsets_byte_range(); + unchecked::read_array(self.data, range) } /// A dynamically resolving wrapper for [`lookahead_coverage_offsets`][Self::lookahead_coverage_offsets]. @@ -3815,14 +3719,14 @@ impl<'a> ChainedSequenceContextFormat3<'a> { /// Number of SequenceLookupRecords pub fn seq_lookup_count(&self) -> u16 { - let range = self.shape.seq_lookup_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.seq_lookup_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Array of SequenceLookupRecords pub fn seq_lookup_records(&self) -> &'a [SequenceLookupRecord] { - let range = self.shape.seq_lookup_records_byte_range(); - self.data.read_array(range).unwrap() + let range = self.seq_lookup_records_byte_range(); + unchecked::read_array(self.data, range) } } @@ -4041,11 +3945,36 @@ impl<'a> From for FieldType<'a> { /// [Device Table](https://docs.microsoft.com/en-us/typography/opentype/spec/chapter2#device-and-variationindex-tables) #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct DeviceMarker { - delta_value_byte_len: usize, +pub struct DeviceMarker; + +impl<'a> MinByteRange for Device<'a> { + fn min_byte_range(&self) -> Range { + 0..self.delta_value_byte_range().end + } +} + +impl<'a> FontRead<'a> for Device<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } } -impl DeviceMarker { +/// [Device Table](https://docs.microsoft.com/en-us/typography/opentype/spec/chapter2#device-and-variationindex-tables) +pub type Device<'a> = TableRef<'a, DeviceMarker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> Device<'a> { + fn delta_value_byte_len(&self, start: usize) -> usize { + let _ = start; + (DeltaFormat::value_count(self.delta_format(), self.start_size(), self.end_size())) + .checked_mul(u16::RAW_BYTE_LEN) + .unwrap() + } + pub fn start_size_byte_range(&self) -> Range { let start = 0; start..start + u16::RAW_BYTE_LEN @@ -4063,59 +3992,31 @@ impl DeviceMarker { pub fn delta_value_byte_range(&self) -> Range { let start = self.delta_format_byte_range().end; - start..start + self.delta_value_byte_len - } -} - -impl MinByteRange for DeviceMarker { - fn min_byte_range(&self) -> Range { - 0..self.delta_value_byte_range().end + start..start + self.delta_value_byte_len(start) } -} - -impl<'a> FontRead<'a> for Device<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - let start_size: u16 = cursor.read()?; - let end_size: u16 = cursor.read()?; - let delta_format: DeltaFormat = cursor.read()?; - let delta_value_byte_len = (DeltaFormat::value_count(delta_format, start_size, end_size)) - .checked_mul(u16::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(delta_value_byte_len); - cursor.finish(DeviceMarker { - delta_value_byte_len, - }) - } -} -/// [Device Table](https://docs.microsoft.com/en-us/typography/opentype/spec/chapter2#device-and-variationindex-tables) -pub type Device<'a> = TableRef<'a, DeviceMarker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> Device<'a> { /// Smallest size to correct, in ppem pub fn start_size(&self) -> u16 { - let range = self.shape.start_size_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.start_size_byte_range(); + unchecked::read_at(self.data, range.start) } /// Largest size to correct, in ppem pub fn end_size(&self) -> u16 { - let range = self.shape.end_size_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.end_size_byte_range(); + unchecked::read_at(self.data, range.start) } /// Format of deltaValue array data: 0x0001, 0x0002, or 0x0003 pub fn delta_format(&self) -> DeltaFormat { - let range = self.shape.delta_format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.delta_format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Array of compressed data pub fn delta_value(&self) -> &'a [BigEndian] { - let range = self.shape.delta_value_byte_range(); - self.data.read_array(range).unwrap() + let range = self.delta_value_byte_range(); + unchecked::read_array(self.data, range) } } @@ -4146,9 +4047,29 @@ impl<'a> std::fmt::Debug for Device<'a> { /// Variation index table #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct VariationIndexMarker {} +pub struct VariationIndexMarker; + +impl<'a> MinByteRange for VariationIndex<'a> { + fn min_byte_range(&self) -> Range { + 0..self.delta_format_byte_range().end + } +} + +impl<'a> FontRead<'a> for VariationIndex<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} -impl VariationIndexMarker { +/// Variation index table +pub type VariationIndex<'a> = TableRef<'a, VariationIndexMarker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> VariationIndex<'a> { pub fn delta_set_outer_index_byte_range(&self) -> Range { let start = 0; start..start + u16::RAW_BYTE_LEN @@ -4163,47 +4084,25 @@ impl VariationIndexMarker { let start = self.delta_set_inner_index_byte_range().end; start..start + DeltaFormat::RAW_BYTE_LEN } -} - -impl MinByteRange for VariationIndexMarker { - fn min_byte_range(&self) -> Range { - 0..self.delta_format_byte_range().end - } -} - -impl<'a> FontRead<'a> for VariationIndex<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.finish(VariationIndexMarker {}) - } -} - -/// Variation index table -pub type VariationIndex<'a> = TableRef<'a, VariationIndexMarker>; -#[allow(clippy::needless_lifetimes)] -impl<'a> VariationIndex<'a> { /// A delta-set outer index — used to select an item variation /// data subtable within the item variation store. pub fn delta_set_outer_index(&self) -> u16 { - let range = self.shape.delta_set_outer_index_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.delta_set_outer_index_byte_range(); + unchecked::read_at(self.data, range.start) } /// A delta-set inner index — used to select a delta-set row /// within an item variation data subtable. pub fn delta_set_inner_index(&self) -> u16 { - let range = self.shape.delta_set_inner_index_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.delta_set_inner_index_byte_range(); + unchecked::read_at(self.data, range.start) } /// Format, = 0x8000 pub fn delta_format(&self) -> DeltaFormat { - let range = self.shape.delta_format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.delta_format_byte_range(); + unchecked::read_at(self.data, range.start) } } @@ -4309,28 +4208,9 @@ impl<'a> SomeTable<'a> for DeviceOrVariationIndex<'a> { /// [FeatureVariations Table](https://docs.microsoft.com/en-us/typography/opentype/spec/chapter2#featurevariations-table) #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct FeatureVariationsMarker { - feature_variation_records_byte_len: usize, -} - -impl FeatureVariationsMarker { - pub fn version_byte_range(&self) -> Range { - let start = 0; - start..start + MajorMinor::RAW_BYTE_LEN - } - - pub fn feature_variation_record_count_byte_range(&self) -> Range { - let start = self.version_byte_range().end; - start..start + u32::RAW_BYTE_LEN - } - - pub fn feature_variation_records_byte_range(&self) -> Range { - let start = self.feature_variation_record_count_byte_range().end; - start..start + self.feature_variation_records_byte_len - } -} +pub struct FeatureVariationsMarker; -impl MinByteRange for FeatureVariationsMarker { +impl<'a> MinByteRange for FeatureVariations<'a> { fn min_byte_range(&self) -> Range { 0..self.feature_variation_records_byte_range().end } @@ -4338,39 +4218,56 @@ impl MinByteRange for FeatureVariationsMarker { impl<'a> FontRead<'a> for FeatureVariations<'a> { fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - let feature_variation_record_count: u32 = cursor.read()?; - let feature_variation_records_byte_len = (feature_variation_record_count as usize) - .checked_mul(FeatureVariationRecord::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(feature_variation_records_byte_len); - cursor.finish(FeatureVariationsMarker { - feature_variation_records_byte_len, + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, }) } } /// [FeatureVariations Table](https://docs.microsoft.com/en-us/typography/opentype/spec/chapter2#featurevariations-table) -pub type FeatureVariations<'a> = TableRef<'a, FeatureVariationsMarker>; +pub type FeatureVariations<'a> = TableRef<'a, FeatureVariationsMarker, ()>; #[allow(clippy::needless_lifetimes)] impl<'a> FeatureVariations<'a> { + fn feature_variation_records_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.feature_variation_record_count()) as usize) + .checked_mul(FeatureVariationRecord::RAW_BYTE_LEN) + .unwrap() + } + + pub fn version_byte_range(&self) -> Range { + let start = 0; + start..start + MajorMinor::RAW_BYTE_LEN + } + + pub fn feature_variation_record_count_byte_range(&self) -> Range { + let start = self.version_byte_range().end; + start..start + u32::RAW_BYTE_LEN + } + + pub fn feature_variation_records_byte_range(&self) -> Range { + let start = self.feature_variation_record_count_byte_range().end; + start..start + self.feature_variation_records_byte_len(start) + } + pub fn version(&self) -> MajorMinor { - let range = self.shape.version_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.version_byte_range(); + unchecked::read_at(self.data, range.start) } /// Number of feature variation records. pub fn feature_variation_record_count(&self) -> u32 { - let range = self.shape.feature_variation_record_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.feature_variation_record_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Array of feature variation records. pub fn feature_variation_records(&self) -> &'a [FeatureVariationRecord] { - let range = self.shape.feature_variation_records_byte_range(); - self.data.read_array(range).unwrap() + let range = self.feature_variation_records_byte_range(); + unchecked::read_array(self.data, range) } } @@ -4489,23 +4386,9 @@ impl<'a> SomeRecord<'a> for FeatureVariationRecord { /// [ConditionSet Table](https://docs.microsoft.com/en-us/typography/opentype/spec/chapter2#conditionset-table) #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct ConditionSetMarker { - condition_offsets_byte_len: usize, -} - -impl ConditionSetMarker { - pub fn condition_count_byte_range(&self) -> Range { - let start = 0; - start..start + u16::RAW_BYTE_LEN - } - - pub fn condition_offsets_byte_range(&self) -> Range { - let start = self.condition_count_byte_range().end; - start..start + self.condition_offsets_byte_len - } -} +pub struct ConditionSetMarker; -impl MinByteRange for ConditionSetMarker { +impl<'a> MinByteRange for ConditionSet<'a> { fn min_byte_range(&self) -> Range { 0..self.condition_offsets_byte_range().end } @@ -4513,34 +4396,47 @@ impl MinByteRange for ConditionSetMarker { impl<'a> FontRead<'a> for ConditionSet<'a> { fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - let condition_count: u16 = cursor.read()?; - let condition_offsets_byte_len = (condition_count as usize) - .checked_mul(Offset32::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(condition_offsets_byte_len); - cursor.finish(ConditionSetMarker { - condition_offsets_byte_len, + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, }) } } /// [ConditionSet Table](https://docs.microsoft.com/en-us/typography/opentype/spec/chapter2#conditionset-table) -pub type ConditionSet<'a> = TableRef<'a, ConditionSetMarker>; +pub type ConditionSet<'a> = TableRef<'a, ConditionSetMarker, ()>; #[allow(clippy::needless_lifetimes)] impl<'a> ConditionSet<'a> { + fn condition_offsets_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.condition_count()) as usize) + .checked_mul(Offset32::RAW_BYTE_LEN) + .unwrap() + } + + pub fn condition_count_byte_range(&self) -> Range { + let start = 0; + start..start + u16::RAW_BYTE_LEN + } + + pub fn condition_offsets_byte_range(&self) -> Range { + let start = self.condition_count_byte_range().end; + start..start + self.condition_offsets_byte_len(start) + } + /// Number of conditions for this condition set. pub fn condition_count(&self) -> u16 { - let range = self.shape.condition_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.condition_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Array of offsets to condition tables, from beginning of the /// ConditionSet table. pub fn condition_offsets(&self) -> &'a [BigEndian] { - let range = self.shape.condition_offsets_byte_range(); - self.data.read_array(range).unwrap() + let range = self.condition_offsets_byte_range(); + unchecked::read_array(self.data, range) } /// A dynamically resolving wrapper for [`condition_offsets`][Self::condition_offsets]. @@ -4686,9 +4582,29 @@ impl Format for ConditionFormat1Marker { /// [Condition Table Format 1](https://docs.microsoft.com/en-us/typography/opentype/spec/chapter2#condition-table-format-1-font-variation-axis-range): Font Variation Axis Range #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct ConditionFormat1Marker {} +pub struct ConditionFormat1Marker; + +impl<'a> MinByteRange for ConditionFormat1<'a> { + fn min_byte_range(&self) -> Range { + 0..self.filter_range_max_value_byte_range().end + } +} + +impl<'a> FontRead<'a> for ConditionFormat1<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// [Condition Table Format 1](https://docs.microsoft.com/en-us/typography/opentype/spec/chapter2#condition-table-format-1-font-variation-axis-range): Font Variation Axis Range +pub type ConditionFormat1<'a> = TableRef<'a, ConditionFormat1Marker, ()>; -impl ConditionFormat1Marker { +#[allow(clippy::needless_lifetimes)] +impl<'a> ConditionFormat1<'a> { pub fn format_byte_range(&self) -> Range { let start = 0; start..start + u16::RAW_BYTE_LEN @@ -4708,55 +4624,32 @@ impl ConditionFormat1Marker { let start = self.filter_range_min_value_byte_range().end; start..start + F2Dot14::RAW_BYTE_LEN } -} -impl MinByteRange for ConditionFormat1Marker { - fn min_byte_range(&self) -> Range { - 0..self.filter_range_max_value_byte_range().end - } -} - -impl<'a> FontRead<'a> for ConditionFormat1<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.finish(ConditionFormat1Marker {}) - } -} - -/// [Condition Table Format 1](https://docs.microsoft.com/en-us/typography/opentype/spec/chapter2#condition-table-format-1-font-variation-axis-range): Font Variation Axis Range -pub type ConditionFormat1<'a> = TableRef<'a, ConditionFormat1Marker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> ConditionFormat1<'a> { /// Format, = 1 pub fn format(&self) -> u16 { - let range = self.shape.format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Index (zero-based) for the variation axis within the 'fvar' /// table. pub fn axis_index(&self) -> u16 { - let range = self.shape.axis_index_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.axis_index_byte_range(); + unchecked::read_at(self.data, range.start) } /// Minimum value of the font variation instances that satisfy this /// condition. pub fn filter_range_min_value(&self) -> F2Dot14 { - let range = self.shape.filter_range_min_value_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.filter_range_min_value_byte_range(); + unchecked::read_at(self.data, range.start) } /// Maximum value of the font variation instances that satisfy this /// condition. pub fn filter_range_max_value(&self) -> F2Dot14 { - let range = self.shape.filter_range_max_value_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.filter_range_max_value_byte_range(); + unchecked::read_at(self.data, range.start) } } @@ -4797,9 +4690,29 @@ impl Format for ConditionFormat2Marker { /// [Condition Table Format 2](https://github.com/fonttools/fonttools/blob/5e6b12d12fa08abafbeb7570f47707fbedf69a45/Lib/fontTools/ttLib/tables/otData.py#L3237-L3255): Variation index #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct ConditionFormat2Marker {} +pub struct ConditionFormat2Marker; -impl ConditionFormat2Marker { +impl<'a> MinByteRange for ConditionFormat2<'a> { + fn min_byte_range(&self) -> Range { + 0..self.var_index_byte_range().end + } +} + +impl<'a> FontRead<'a> for ConditionFormat2<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// [Condition Table Format 2](https://github.com/fonttools/fonttools/blob/5e6b12d12fa08abafbeb7570f47707fbedf69a45/Lib/fontTools/ttLib/tables/otData.py#L3237-L3255): Variation index +pub type ConditionFormat2<'a> = TableRef<'a, ConditionFormat2Marker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> ConditionFormat2<'a> { pub fn format_byte_range(&self) -> Range { let start = 0; start..start + u16::RAW_BYTE_LEN @@ -4814,45 +4727,23 @@ impl ConditionFormat2Marker { let start = self.default_value_byte_range().end; start..start + u32::RAW_BYTE_LEN } -} -impl MinByteRange for ConditionFormat2Marker { - fn min_byte_range(&self) -> Range { - 0..self.var_index_byte_range().end - } -} - -impl<'a> FontRead<'a> for ConditionFormat2<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.finish(ConditionFormat2Marker {}) - } -} - -/// [Condition Table Format 2](https://github.com/fonttools/fonttools/blob/5e6b12d12fa08abafbeb7570f47707fbedf69a45/Lib/fontTools/ttLib/tables/otData.py#L3237-L3255): Variation index -pub type ConditionFormat2<'a> = TableRef<'a, ConditionFormat2Marker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> ConditionFormat2<'a> { /// Format, = 2 pub fn format(&self) -> u16 { - let range = self.shape.format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Value at default instance. pub fn default_value(&self) -> i16 { - let range = self.shape.default_value_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.default_value_byte_range(); + unchecked::read_at(self.data, range.start) } /// Variation index to vary the value based on current designspace location. pub fn var_index(&self) -> u32 { - let range = self.shape.var_index_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.var_index_byte_range(); + unchecked::read_at(self.data, range.start) } } @@ -4886,28 +4777,9 @@ impl Format for ConditionFormat3Marker { /// [Condition Table Format 3](https://github.com/fonttools/fonttools/blob/5e6b12d12fa08abafbeb7570f47707fbedf69a45/Lib/fontTools/ttLib/tables/otData.py#L3257-L3275): AND #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct ConditionFormat3Marker { - condition_offsets_byte_len: usize, -} - -impl ConditionFormat3Marker { - pub fn format_byte_range(&self) -> Range { - let start = 0; - start..start + u16::RAW_BYTE_LEN - } - - pub fn condition_count_byte_range(&self) -> Range { - let start = self.format_byte_range().end; - start..start + u8::RAW_BYTE_LEN - } - - pub fn condition_offsets_byte_range(&self) -> Range { - let start = self.condition_count_byte_range().end; - start..start + self.condition_offsets_byte_len - } -} +pub struct ConditionFormat3Marker; -impl MinByteRange for ConditionFormat3Marker { +impl<'a> MinByteRange for ConditionFormat3<'a> { fn min_byte_range(&self) -> Range { 0..self.condition_offsets_byte_range().end } @@ -4915,40 +4787,57 @@ impl MinByteRange for ConditionFormat3Marker { impl<'a> FontRead<'a> for ConditionFormat3<'a> { fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - let condition_count: u8 = cursor.read()?; - let condition_offsets_byte_len = (condition_count as usize) - .checked_mul(Offset24::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(condition_offsets_byte_len); - cursor.finish(ConditionFormat3Marker { - condition_offsets_byte_len, + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, }) } } /// [Condition Table Format 3](https://github.com/fonttools/fonttools/blob/5e6b12d12fa08abafbeb7570f47707fbedf69a45/Lib/fontTools/ttLib/tables/otData.py#L3257-L3275): AND -pub type ConditionFormat3<'a> = TableRef<'a, ConditionFormat3Marker>; +pub type ConditionFormat3<'a> = TableRef<'a, ConditionFormat3Marker, ()>; #[allow(clippy::needless_lifetimes)] impl<'a> ConditionFormat3<'a> { + fn condition_offsets_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.condition_count()) as usize) + .checked_mul(Offset24::RAW_BYTE_LEN) + .unwrap() + } + + pub fn format_byte_range(&self) -> Range { + let start = 0; + start..start + u16::RAW_BYTE_LEN + } + + pub fn condition_count_byte_range(&self) -> Range { + let start = self.format_byte_range().end; + start..start + u8::RAW_BYTE_LEN + } + + pub fn condition_offsets_byte_range(&self) -> Range { + let start = self.condition_count_byte_range().end; + start..start + self.condition_offsets_byte_len(start) + } + /// Format, = 3 pub fn format(&self) -> u16 { - let range = self.shape.format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Number of conditions. pub fn condition_count(&self) -> u8 { - let range = self.shape.condition_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.condition_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Array of condition tables for this conjunction (AND) expression. pub fn condition_offsets(&self) -> &'a [BigEndian] { - let range = self.shape.condition_offsets_byte_range(); - self.data.read_array(range).unwrap() + let range = self.condition_offsets_byte_range(); + unchecked::read_array(self.data, range) } /// A dynamically resolving wrapper for [`condition_offsets`][Self::condition_offsets]. @@ -5002,28 +4891,9 @@ impl Format for ConditionFormat4Marker { /// [Condition Table Format 4](https://github.com/fonttools/fonttools/blob/5e6b12d12fa08abafbeb7570f47707fbedf69a45/Lib/fontTools/ttLib/tables/otData.py#L3276-L3295): OR #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct ConditionFormat4Marker { - condition_offsets_byte_len: usize, -} +pub struct ConditionFormat4Marker; -impl ConditionFormat4Marker { - pub fn format_byte_range(&self) -> Range { - let start = 0; - start..start + u16::RAW_BYTE_LEN - } - - pub fn condition_count_byte_range(&self) -> Range { - let start = self.format_byte_range().end; - start..start + u8::RAW_BYTE_LEN - } - - pub fn condition_offsets_byte_range(&self) -> Range { - let start = self.condition_count_byte_range().end; - start..start + self.condition_offsets_byte_len - } -} - -impl MinByteRange for ConditionFormat4Marker { +impl<'a> MinByteRange for ConditionFormat4<'a> { fn min_byte_range(&self) -> Range { 0..self.condition_offsets_byte_range().end } @@ -5031,40 +4901,57 @@ impl MinByteRange for ConditionFormat4Marker { impl<'a> FontRead<'a> for ConditionFormat4<'a> { fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - let condition_count: u8 = cursor.read()?; - let condition_offsets_byte_len = (condition_count as usize) - .checked_mul(Offset24::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(condition_offsets_byte_len); - cursor.finish(ConditionFormat4Marker { - condition_offsets_byte_len, + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, }) } } /// [Condition Table Format 4](https://github.com/fonttools/fonttools/blob/5e6b12d12fa08abafbeb7570f47707fbedf69a45/Lib/fontTools/ttLib/tables/otData.py#L3276-L3295): OR -pub type ConditionFormat4<'a> = TableRef<'a, ConditionFormat4Marker>; +pub type ConditionFormat4<'a> = TableRef<'a, ConditionFormat4Marker, ()>; #[allow(clippy::needless_lifetimes)] impl<'a> ConditionFormat4<'a> { + fn condition_offsets_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.condition_count()) as usize) + .checked_mul(Offset24::RAW_BYTE_LEN) + .unwrap() + } + + pub fn format_byte_range(&self) -> Range { + let start = 0; + start..start + u16::RAW_BYTE_LEN + } + + pub fn condition_count_byte_range(&self) -> Range { + let start = self.format_byte_range().end; + start..start + u8::RAW_BYTE_LEN + } + + pub fn condition_offsets_byte_range(&self) -> Range { + let start = self.condition_count_byte_range().end; + start..start + self.condition_offsets_byte_len(start) + } + /// Format, = 4 pub fn format(&self) -> u16 { - let range = self.shape.format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Number of conditions. pub fn condition_count(&self) -> u8 { - let range = self.shape.condition_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.condition_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Array of condition tables for this disjunction (OR) expression. pub fn condition_offsets(&self) -> &'a [BigEndian] { - let range = self.shape.condition_offsets_byte_range(); - self.data.read_array(range).unwrap() + let range = self.condition_offsets_byte_range(); + unchecked::read_array(self.data, range) } /// A dynamically resolving wrapper for [`condition_offsets`][Self::condition_offsets]. @@ -5118,21 +5005,9 @@ impl Format for ConditionFormat5Marker { /// [Condition Table Format 5](https://github.com/fonttools/fonttools/blob/5e6b12d12fa08abafbeb7570f47707fbedf69a45/Lib/fontTools/ttLib/tables/otData.py#L3296-L3308): NOT #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct ConditionFormat5Marker {} - -impl ConditionFormat5Marker { - pub fn format_byte_range(&self) -> Range { - let start = 0; - start..start + u16::RAW_BYTE_LEN - } - - pub fn condition_offset_byte_range(&self) -> Range { - let start = self.format_byte_range().end; - start..start + Offset24::RAW_BYTE_LEN - } -} +pub struct ConditionFormat5Marker; -impl MinByteRange for ConditionFormat5Marker { +impl<'a> MinByteRange for ConditionFormat5<'a> { fn min_byte_range(&self) -> Range { 0..self.condition_offset_byte_range().end } @@ -5140,28 +5015,39 @@ impl MinByteRange for ConditionFormat5Marker { impl<'a> FontRead<'a> for ConditionFormat5<'a> { fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.finish(ConditionFormat5Marker {}) + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) } } /// [Condition Table Format 5](https://github.com/fonttools/fonttools/blob/5e6b12d12fa08abafbeb7570f47707fbedf69a45/Lib/fontTools/ttLib/tables/otData.py#L3296-L3308): NOT -pub type ConditionFormat5<'a> = TableRef<'a, ConditionFormat5Marker>; +pub type ConditionFormat5<'a> = TableRef<'a, ConditionFormat5Marker, ()>; #[allow(clippy::needless_lifetimes)] impl<'a> ConditionFormat5<'a> { + pub fn format_byte_range(&self) -> Range { + let start = 0; + start..start + u16::RAW_BYTE_LEN + } + + pub fn condition_offset_byte_range(&self) -> Range { + let start = self.format_byte_range().end; + start..start + Offset24::RAW_BYTE_LEN + } + /// Format, = 5 pub fn format(&self) -> u16 { - let range = self.shape.format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Condition to negate. pub fn condition_offset(&self) -> Offset24 { - let range = self.shape.condition_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.condition_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`condition_offset`][Self::condition_offset]. @@ -5199,28 +5085,9 @@ impl<'a> std::fmt::Debug for ConditionFormat5<'a> { /// [FeatureTableSubstitution Table](https://docs.microsoft.com/en-us/typography/opentype/spec/chapter2#featuretablesubstitution-table) #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct FeatureTableSubstitutionMarker { - substitutions_byte_len: usize, -} +pub struct FeatureTableSubstitutionMarker; -impl FeatureTableSubstitutionMarker { - pub fn version_byte_range(&self) -> Range { - let start = 0; - start..start + MajorMinor::RAW_BYTE_LEN - } - - pub fn substitution_count_byte_range(&self) -> Range { - let start = self.version_byte_range().end; - start..start + u16::RAW_BYTE_LEN - } - - pub fn substitutions_byte_range(&self) -> Range { - let start = self.substitution_count_byte_range().end; - start..start + self.substitutions_byte_len - } -} - -impl MinByteRange for FeatureTableSubstitutionMarker { +impl<'a> MinByteRange for FeatureTableSubstitution<'a> { fn min_byte_range(&self) -> Range { 0..self.substitutions_byte_range().end } @@ -5228,40 +5095,57 @@ impl MinByteRange for FeatureTableSubstitutionMarker { impl<'a> FontRead<'a> for FeatureTableSubstitution<'a> { fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - let substitution_count: u16 = cursor.read()?; - let substitutions_byte_len = (substitution_count as usize) - .checked_mul(FeatureTableSubstitutionRecord::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(substitutions_byte_len); - cursor.finish(FeatureTableSubstitutionMarker { - substitutions_byte_len, + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, }) } } /// [FeatureTableSubstitution Table](https://docs.microsoft.com/en-us/typography/opentype/spec/chapter2#featuretablesubstitution-table) -pub type FeatureTableSubstitution<'a> = TableRef<'a, FeatureTableSubstitutionMarker>; +pub type FeatureTableSubstitution<'a> = TableRef<'a, FeatureTableSubstitutionMarker, ()>; #[allow(clippy::needless_lifetimes)] impl<'a> FeatureTableSubstitution<'a> { + fn substitutions_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.substitution_count()) as usize) + .checked_mul(FeatureTableSubstitutionRecord::RAW_BYTE_LEN) + .unwrap() + } + + pub fn version_byte_range(&self) -> Range { + let start = 0; + start..start + MajorMinor::RAW_BYTE_LEN + } + + pub fn substitution_count_byte_range(&self) -> Range { + let start = self.version_byte_range().end; + start..start + u16::RAW_BYTE_LEN + } + + pub fn substitutions_byte_range(&self) -> Range { + let start = self.substitution_count_byte_range().end; + start..start + self.substitutions_byte_len(start) + } + /// Major & minor version of the table: (1, 0) pub fn version(&self) -> MajorMinor { - let range = self.shape.version_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.version_byte_range(); + unchecked::read_at(self.data, range.start) } /// Number of feature table substitution records. pub fn substitution_count(&self) -> u16 { - let range = self.shape.substitution_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.substitution_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Array of feature table substitution records. pub fn substitutions(&self) -> &'a [FeatureTableSubstitutionRecord] { - let range = self.shape.substitutions_byte_range(); - self.data.read_array(range).unwrap() + let range = self.substitutions_byte_range(); + unchecked::read_array(self.data, range) } } @@ -5347,9 +5231,28 @@ impl<'a> SomeRecord<'a> for FeatureTableSubstitutionRecord { #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct SizeParamsMarker {} +pub struct SizeParamsMarker; + +impl<'a> MinByteRange for SizeParams<'a> { + fn min_byte_range(&self) -> Range { + 0..self.range_end_byte_range().end + } +} + +impl<'a> FontRead<'a> for SizeParams<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} -impl SizeParamsMarker { +pub type SizeParams<'a> = TableRef<'a, SizeParamsMarker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> SizeParams<'a> { pub fn design_size_byte_range(&self) -> Range { let start = 0; start..start + u16::RAW_BYTE_LEN @@ -5374,37 +5277,14 @@ impl SizeParamsMarker { let start = self.range_start_byte_range().end; start..start + u16::RAW_BYTE_LEN } -} - -impl MinByteRange for SizeParamsMarker { - fn min_byte_range(&self) -> Range { - 0..self.range_end_byte_range().end - } -} -impl<'a> FontRead<'a> for SizeParams<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.finish(SizeParamsMarker {}) - } -} - -pub type SizeParams<'a> = TableRef<'a, SizeParamsMarker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> SizeParams<'a> { /// The first value represents the design size in 720/inch units (decipoints). /// /// The design size entry must be non-zero. When there is a design size but /// no recommended size range, the rest of the array will consist of zeros. pub fn design_size(&self) -> u16 { - let range = self.shape.design_size_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.design_size_byte_range(); + unchecked::read_at(self.data, range.start) } /// The second value has no independent meaning, but serves as an identifier that associates fonts in a subfamily. @@ -5414,8 +5294,8 @@ impl<'a> SizeParams<'a> { /// which differ in weight or style shall have the same subfamily value. /// If this value is zero, the remaining fields in the array will be ignored. pub fn identifier(&self) -> u16 { - let range = self.shape.identifier_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.identifier_byte_range(); + unchecked::read_at(self.data, range.start) } /// The third value enables applications to use a single name for the subfamily identified by the second value. @@ -5429,8 +5309,8 @@ impl<'a> SizeParams<'a> { /// represent the subfamily in a menu. Applications will choose the /// appropriate version based on their selection criteria. pub fn name_entry(&self) -> u16 { - let range = self.shape.name_entry_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.name_entry_byte_range(); + unchecked::read_at(self.data, range.start) } /// The fourth and fifth values represent the small end of the recommended @@ -5439,13 +5319,13 @@ impl<'a> SizeParams<'a> { /// /// Ranges must not overlap, and should generally be contiguous. pub fn range_start(&self) -> u16 { - let range = self.shape.range_start_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.range_start_byte_range(); + unchecked::read_at(self.data, range.start) } pub fn range_end(&self) -> u16 { - let range = self.shape.range_end_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.range_end_byte_range(); + unchecked::read_at(self.data, range.start) } } @@ -5476,21 +5356,9 @@ impl<'a> std::fmt::Debug for SizeParams<'a> { #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct StylisticSetParamsMarker {} - -impl StylisticSetParamsMarker { - pub fn version_byte_range(&self) -> Range { - let start = 0; - start..start + u16::RAW_BYTE_LEN - } - - pub fn ui_name_id_byte_range(&self) -> Range { - let start = self.version_byte_range().end; - start..start + NameId::RAW_BYTE_LEN - } -} +pub struct StylisticSetParamsMarker; -impl MinByteRange for StylisticSetParamsMarker { +impl<'a> MinByteRange for StylisticSetParams<'a> { fn min_byte_range(&self) -> Range { 0..self.ui_name_id_byte_range().end } @@ -5498,20 +5366,31 @@ impl MinByteRange for StylisticSetParamsMarker { impl<'a> FontRead<'a> for StylisticSetParams<'a> { fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.finish(StylisticSetParamsMarker {}) + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) } } -pub type StylisticSetParams<'a> = TableRef<'a, StylisticSetParamsMarker>; +pub type StylisticSetParams<'a> = TableRef<'a, StylisticSetParamsMarker, ()>; #[allow(clippy::needless_lifetimes)] impl<'a> StylisticSetParams<'a> { + pub fn version_byte_range(&self) -> Range { + let start = 0; + start..start + u16::RAW_BYTE_LEN + } + + pub fn ui_name_id_byte_range(&self) -> Range { + let start = self.version_byte_range().end; + start..start + NameId::RAW_BYTE_LEN + } + pub fn version(&self) -> u16 { - let range = self.shape.version_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.version_byte_range(); + unchecked::read_at(self.data, range.start) } /// The 'name' table name ID that specifies a string (or strings, for @@ -5524,8 +5403,8 @@ impl<'a> StylisticSetParams<'a> { /// as a fallback. The string should be kept to a minimal length to fit /// comfortably with different application interfaces. pub fn ui_name_id(&self) -> NameId { - let range = self.shape.ui_name_id_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.ui_name_id_byte_range(); + unchecked::read_at(self.data, range.start) } } @@ -5558,11 +5437,36 @@ impl Format for CharacterVariantParamsMarker { /// featureParams for ['cv01'-'cv99'](https://docs.microsoft.com/en-us/typography/opentype/spec/features_ae#cv01-cv99) #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct CharacterVariantParamsMarker { - character_byte_len: usize, +pub struct CharacterVariantParamsMarker; + +impl<'a> MinByteRange for CharacterVariantParams<'a> { + fn min_byte_range(&self) -> Range { + 0..self.character_byte_range().end + } +} + +impl<'a> FontRead<'a> for CharacterVariantParams<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } } -impl CharacterVariantParamsMarker { +/// featureParams for ['cv01'-'cv99'](https://docs.microsoft.com/en-us/typography/opentype/spec/features_ae#cv01-cv99) +pub type CharacterVariantParams<'a> = TableRef<'a, CharacterVariantParamsMarker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> CharacterVariantParams<'a> { + fn character_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.char_count()) as usize) + .checked_mul(Uint24::RAW_BYTE_LEN) + .unwrap() + } + pub fn format_byte_range(&self) -> Range { let start = 0; start..start + u16::RAW_BYTE_LEN @@ -5600,94 +5504,64 @@ impl CharacterVariantParamsMarker { pub fn character_byte_range(&self) -> Range { let start = self.char_count_byte_range().end; - start..start + self.character_byte_len + start..start + self.character_byte_len(start) } -} - -impl MinByteRange for CharacterVariantParamsMarker { - fn min_byte_range(&self) -> Range { - 0..self.character_byte_range().end - } -} - -impl<'a> FontRead<'a> for CharacterVariantParams<'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 char_count: u16 = cursor.read()?; - let character_byte_len = (char_count as usize) - .checked_mul(Uint24::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(character_byte_len); - cursor.finish(CharacterVariantParamsMarker { character_byte_len }) - } -} -/// featureParams for ['cv01'-'cv99'](https://docs.microsoft.com/en-us/typography/opentype/spec/features_ae#cv01-cv99) -pub type CharacterVariantParams<'a> = TableRef<'a, CharacterVariantParamsMarker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> CharacterVariantParams<'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() + let range = self.format_byte_range(); + unchecked::read_at(self.data, range.start) } /// The 'name' table name ID that specifies a string (or strings, /// for multiple languages) for a user-interface label for this /// feature. (May be NULL.) pub fn feat_ui_label_name_id(&self) -> NameId { - let range = self.shape.feat_ui_label_name_id_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.feat_ui_label_name_id_byte_range(); + unchecked::read_at(self.data, range.start) } /// The 'name' table name ID that specifies a string (or strings, /// for multiple languages) that an application can use for tooltip /// text for this feature. (May be NULL.) pub fn feat_ui_tooltip_text_name_id(&self) -> NameId { - let range = self.shape.feat_ui_tooltip_text_name_id_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.feat_ui_tooltip_text_name_id_byte_range(); + unchecked::read_at(self.data, range.start) } /// The 'name' table name ID that specifies sample text that /// illustrates the effect of this feature. (May be NULL.) pub fn sample_text_name_id(&self) -> NameId { - let range = self.shape.sample_text_name_id_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.sample_text_name_id_byte_range(); + unchecked::read_at(self.data, range.start) } /// Number of named parameters. (May be zero.) pub fn num_named_parameters(&self) -> u16 { - let range = self.shape.num_named_parameters_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.num_named_parameters_byte_range(); + unchecked::read_at(self.data, range.start) } /// The first 'name' table name ID used to specify strings for /// user-interface labels for the feature parameters. (Must be zero /// if numParameters is zero.) pub fn first_param_ui_label_name_id(&self) -> NameId { - let range = self.shape.first_param_ui_label_name_id_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.first_param_ui_label_name_id_byte_range(); + unchecked::read_at(self.data, range.start) } /// The count of characters for which this feature provides glyph /// variants. (May be zero.) pub fn char_count(&self) -> u16 { - let range = self.shape.char_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.char_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// The Unicode Scalar Value of the characters for which this /// feature provides glyph variants. pub fn character(&self) -> &'a [BigEndian] { - let range = self.shape.character_byte_range(); - self.data.read_array(range).unwrap() + let range = self.character_byte_range(); + unchecked::read_array(self.data, range) } } diff --git a/read-fonts/generated/generated_ltag.rs b/read-fonts/generated/generated_ltag.rs index 45e991043..b77939b89 100644 --- a/read-fonts/generated/generated_ltag.rs +++ b/read-fonts/generated/generated_ltag.rs @@ -8,33 +8,9 @@ use crate::codegen_prelude::*; /// The [language tag](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6ltag.html) table. #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct LtagMarker { - tag_ranges_byte_len: usize, -} - -impl LtagMarker { - pub fn version_byte_range(&self) -> Range { - let start = 0; - start..start + u32::RAW_BYTE_LEN - } +pub struct LtagMarker; - pub fn flags_byte_range(&self) -> Range { - let start = self.version_byte_range().end; - start..start + u32::RAW_BYTE_LEN - } - - pub fn num_tags_byte_range(&self) -> Range { - let start = self.flags_byte_range().end; - start..start + u32::RAW_BYTE_LEN - } - - pub fn tag_ranges_byte_range(&self) -> Range { - let start = self.num_tags_byte_range().end; - start..start + self.tag_ranges_byte_len - } -} - -impl MinByteRange for LtagMarker { +impl<'a> MinByteRange for Ltag<'a> { fn min_byte_range(&self) -> Range { 0..self.tag_ranges_byte_range().end } @@ -47,47 +23,68 @@ impl TopLevelTable for Ltag<'_> { impl<'a> FontRead<'a> for Ltag<'a> { fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - let num_tags: u32 = cursor.read()?; - let tag_ranges_byte_len = (num_tags as usize) - .checked_mul(FTStringRange::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(tag_ranges_byte_len); - cursor.finish(LtagMarker { - tag_ranges_byte_len, + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, }) } } /// The [language tag](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6ltag.html) table. -pub type Ltag<'a> = TableRef<'a, LtagMarker>; +pub type Ltag<'a> = TableRef<'a, LtagMarker, ()>; #[allow(clippy::needless_lifetimes)] impl<'a> Ltag<'a> { + fn tag_ranges_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.num_tags()) as usize) + .checked_mul(FTStringRange::RAW_BYTE_LEN) + .unwrap() + } + + pub fn version_byte_range(&self) -> Range { + let start = 0; + start..start + u32::RAW_BYTE_LEN + } + + pub fn flags_byte_range(&self) -> Range { + let start = self.version_byte_range().end; + start..start + u32::RAW_BYTE_LEN + } + + pub fn num_tags_byte_range(&self) -> Range { + let start = self.flags_byte_range().end; + start..start + u32::RAW_BYTE_LEN + } + + pub fn tag_ranges_byte_range(&self) -> Range { + let start = self.num_tags_byte_range().end; + start..start + self.tag_ranges_byte_len(start) + } + /// Table version; currently 1. pub fn version(&self) -> u32 { - let range = self.shape.version_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.version_byte_range(); + unchecked::read_at(self.data, range.start) } /// Table flags; currently none defined. pub fn flags(&self) -> u32 { - let range = self.shape.flags_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.flags_byte_range(); + unchecked::read_at(self.data, range.start) } /// Number of language tags which follow. pub fn num_tags(&self) -> u32 { - let range = self.shape.num_tags_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.num_tags_byte_range(); + unchecked::read_at(self.data, range.start) } /// Range of each tag's string. pub fn tag_ranges(&self) -> &'a [FTStringRange] { - let range = self.shape.tag_ranges_byte_range(); - self.data.read_array(range).unwrap() + let range = self.tag_ranges_byte_range(); + unchecked::read_array(self.data, range) } } diff --git a/read-fonts/generated/generated_maxp.rs b/read-fonts/generated/generated_maxp.rs index 40e560994..ccb5c1415 100644 --- a/read-fonts/generated/generated_maxp.rs +++ b/read-fonts/generated/generated_maxp.rs @@ -8,23 +8,34 @@ use crate::codegen_prelude::*; /// [`maxp`](https://docs.microsoft.com/en-us/typography/opentype/spec/maxp) #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct MaxpMarker { - max_points_byte_start: Option, - max_contours_byte_start: Option, - max_composite_points_byte_start: Option, - max_composite_contours_byte_start: Option, - max_zones_byte_start: Option, - max_twilight_points_byte_start: Option, - max_storage_byte_start: Option, - max_function_defs_byte_start: Option, - max_instruction_defs_byte_start: Option, - max_stack_elements_byte_start: Option, - max_size_of_instructions_byte_start: Option, - max_component_elements_byte_start: Option, - max_component_depth_byte_start: Option, +pub struct MaxpMarker; + +impl<'a> MinByteRange for Maxp<'a> { + fn min_byte_range(&self) -> Range { + 0..self.num_glyphs_byte_range().end + } +} + +impl TopLevelTable for Maxp<'_> { + /// `maxp` + const TAG: Tag = Tag::new(b"maxp"); } -impl MaxpMarker { +impl<'a> FontRead<'a> for Maxp<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// [`maxp`](https://docs.microsoft.com/en-us/typography/opentype/spec/maxp) +pub type Maxp<'a> = TableRef<'a, MaxpMarker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> Maxp<'a> { pub fn version_byte_range(&self) -> Range { let start = 0; start..start + Version16Dot16::RAW_BYTE_LEN @@ -36,293 +47,323 @@ impl MaxpMarker { } pub fn max_points_byte_range(&self) -> Option> { - let start = self.max_points_byte_start?; - Some(start..start + u16::RAW_BYTE_LEN) + if self.version().compatible((1u16, 0u16)) { + let start = self.num_glyphs_byte_range().end; + Some(start..start + u16::RAW_BYTE_LEN) + } else { + None + } } pub fn max_contours_byte_range(&self) -> Option> { - let start = self.max_contours_byte_start?; - Some(start..start + u16::RAW_BYTE_LEN) + if self.version().compatible((1u16, 0u16)) { + let start = self + .max_points_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| self.num_glyphs_byte_range().end); + Some(start..start + u16::RAW_BYTE_LEN) + } else { + None + } } pub fn max_composite_points_byte_range(&self) -> Option> { - let start = self.max_composite_points_byte_start?; - Some(start..start + u16::RAW_BYTE_LEN) + if self.version().compatible((1u16, 0u16)) { + let start = self + .max_contours_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| { + self.max_points_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| self.num_glyphs_byte_range().end) + }); + Some(start..start + u16::RAW_BYTE_LEN) + } else { + None + } } pub fn max_composite_contours_byte_range(&self) -> Option> { - let start = self.max_composite_contours_byte_start?; - Some(start..start + u16::RAW_BYTE_LEN) + if self.version().compatible((1u16, 0u16)) { + let start = self + .max_composite_points_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| { + self.max_contours_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| { + self.max_points_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| self.num_glyphs_byte_range().end) + }) + }); + Some(start..start + u16::RAW_BYTE_LEN) + } else { + None + } } pub fn max_zones_byte_range(&self) -> Option> { - let start = self.max_zones_byte_start?; - Some(start..start + u16::RAW_BYTE_LEN) + if self.version().compatible((1u16, 0u16)) { + let start = self + .max_composite_contours_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| { + self.max_composite_points_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| { + self.max_contours_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| { + self.max_points_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| self.num_glyphs_byte_range().end) + }) + }) + }); + Some(start..start + u16::RAW_BYTE_LEN) + } else { + None + } } pub fn max_twilight_points_byte_range(&self) -> Option> { - let start = self.max_twilight_points_byte_start?; - Some(start..start + u16::RAW_BYTE_LEN) + if self.version().compatible((1u16, 0u16)) { + let start = self + .max_zones_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| { + self.max_composite_contours_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| { + self.max_composite_points_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| { + self.max_contours_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| { + self.max_points_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| self.num_glyphs_byte_range().end) + }) + }) + }) + }); + Some(start..start + u16::RAW_BYTE_LEN) + } else { + None + } } pub fn max_storage_byte_range(&self) -> Option> { - let start = self.max_storage_byte_start?; - Some(start..start + u16::RAW_BYTE_LEN) + if self.version().compatible((1u16, 0u16)) { + let start = self + .max_twilight_points_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| { + self.max_zones_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| { + self.max_composite_contours_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| { + self.max_composite_points_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| { + self.max_contours_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| { + self.max_points_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| { + self.num_glyphs_byte_range().end + }) + }) + }) + }) + }) + }); + Some(start..start + u16::RAW_BYTE_LEN) + } else { + None + } } pub fn max_function_defs_byte_range(&self) -> Option> { - let start = self.max_function_defs_byte_start?; - Some(start..start + u16::RAW_BYTE_LEN) + if self.version().compatible((1u16, 0u16)) { + let start = self + .max_storage_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| { + self.max_twilight_points_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| { + self.max_zones_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| { + self.max_composite_contours_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| { + self.max_composite_points_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| { + self.max_contours_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| { + self.max_points_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| { + self.num_glyphs_byte_range().end + }) + }) + }) + }) + }) + }) + }); + Some(start..start + u16::RAW_BYTE_LEN) + } else { + None + } } pub fn max_instruction_defs_byte_range(&self) -> Option> { - let start = self.max_instruction_defs_byte_start?; - Some(start..start + u16::RAW_BYTE_LEN) + if self.version().compatible((1u16, 0u16)) { + let start = self . max_function_defs_byte_range () . map (| range | range . end) . unwrap_or_else (|| self . max_storage_byte_range () . map (| range | range . end) . unwrap_or_else (|| self . max_twilight_points_byte_range () . map (| range | range . end) . unwrap_or_else (|| self . max_zones_byte_range () . map (| range | range . end) . unwrap_or_else (|| self . max_composite_contours_byte_range () . map (| range | range . end) . unwrap_or_else (|| self . max_composite_points_byte_range () . map (| range | range . end) . unwrap_or_else (|| self . max_contours_byte_range () . map (| range | range . end) . unwrap_or_else (|| self . max_points_byte_range () . map (| range | range . end) . unwrap_or_else (|| self . num_glyphs_byte_range () . end)))))))) ; + Some(start..start + u16::RAW_BYTE_LEN) + } else { + None + } } pub fn max_stack_elements_byte_range(&self) -> Option> { - let start = self.max_stack_elements_byte_start?; - Some(start..start + u16::RAW_BYTE_LEN) + if self.version().compatible((1u16, 0u16)) { + let start = self . max_instruction_defs_byte_range () . map (| range | range . end) . unwrap_or_else (|| self . max_function_defs_byte_range () . map (| range | range . end) . unwrap_or_else (|| self . max_storage_byte_range () . map (| range | range . end) . unwrap_or_else (|| self . max_twilight_points_byte_range () . map (| range | range . end) . unwrap_or_else (|| self . max_zones_byte_range () . map (| range | range . end) . unwrap_or_else (|| self . max_composite_contours_byte_range () . map (| range | range . end) . unwrap_or_else (|| self . max_composite_points_byte_range () . map (| range | range . end) . unwrap_or_else (|| self . max_contours_byte_range () . map (| range | range . end) . unwrap_or_else (|| self . max_points_byte_range () . map (| range | range . end) . unwrap_or_else (|| self . num_glyphs_byte_range () . end))))))))) ; + Some(start..start + u16::RAW_BYTE_LEN) + } else { + None + } } pub fn max_size_of_instructions_byte_range(&self) -> Option> { - let start = self.max_size_of_instructions_byte_start?; - Some(start..start + u16::RAW_BYTE_LEN) + if self.version().compatible((1u16, 0u16)) { + let start = self . max_stack_elements_byte_range () . map (| range | range . end) . unwrap_or_else (|| self . max_instruction_defs_byte_range () . map (| range | range . end) . unwrap_or_else (|| self . max_function_defs_byte_range () . map (| range | range . end) . unwrap_or_else (|| self . max_storage_byte_range () . map (| range | range . end) . unwrap_or_else (|| self . max_twilight_points_byte_range () . map (| range | range . end) . unwrap_or_else (|| self . max_zones_byte_range () . map (| range | range . end) . unwrap_or_else (|| self . max_composite_contours_byte_range () . map (| range | range . end) . unwrap_or_else (|| self . max_composite_points_byte_range () . map (| range | range . end) . unwrap_or_else (|| self . max_contours_byte_range () . map (| range | range . end) . unwrap_or_else (|| self . max_points_byte_range () . map (| range | range . end) . unwrap_or_else (|| self . num_glyphs_byte_range () . end)))))))))) ; + Some(start..start + u16::RAW_BYTE_LEN) + } else { + None + } } pub fn max_component_elements_byte_range(&self) -> Option> { - let start = self.max_component_elements_byte_start?; - Some(start..start + u16::RAW_BYTE_LEN) + if self.version().compatible((1u16, 0u16)) { + let start = self . max_size_of_instructions_byte_range () . map (| range | range . end) . unwrap_or_else (|| self . max_stack_elements_byte_range () . map (| range | range . end) . unwrap_or_else (|| self . max_instruction_defs_byte_range () . map (| range | range . end) . unwrap_or_else (|| self . max_function_defs_byte_range () . map (| range | range . end) . unwrap_or_else (|| self . max_storage_byte_range () . map (| range | range . end) . unwrap_or_else (|| self . max_twilight_points_byte_range () . map (| range | range . end) . unwrap_or_else (|| self . max_zones_byte_range () . map (| range | range . end) . unwrap_or_else (|| self . max_composite_contours_byte_range () . map (| range | range . end) . unwrap_or_else (|| self . max_composite_points_byte_range () . map (| range | range . end) . unwrap_or_else (|| self . max_contours_byte_range () . map (| range | range . end) . unwrap_or_else (|| self . max_points_byte_range () . map (| range | range . end) . unwrap_or_else (|| self . num_glyphs_byte_range () . end))))))))))) ; + Some(start..start + u16::RAW_BYTE_LEN) + } else { + None + } } pub fn max_component_depth_byte_range(&self) -> Option> { - let start = self.max_component_depth_byte_start?; - Some(start..start + u16::RAW_BYTE_LEN) - } -} - -impl MinByteRange for MaxpMarker { - fn min_byte_range(&self) -> Range { - 0..self.num_glyphs_byte_range().end - } -} - -impl TopLevelTable for Maxp<'_> { - /// `maxp` - const TAG: Tag = Tag::new(b"maxp"); -} - -impl<'a> FontRead<'a> for Maxp<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - let version: Version16Dot16 = cursor.read()?; - cursor.advance::(); - let max_points_byte_start = version - .compatible((1u16, 0u16)) - .then(|| cursor.position()) - .transpose()?; - version - .compatible((1u16, 0u16)) - .then(|| cursor.advance::()); - let max_contours_byte_start = version - .compatible((1u16, 0u16)) - .then(|| cursor.position()) - .transpose()?; - version - .compatible((1u16, 0u16)) - .then(|| cursor.advance::()); - let max_composite_points_byte_start = version - .compatible((1u16, 0u16)) - .then(|| cursor.position()) - .transpose()?; - version - .compatible((1u16, 0u16)) - .then(|| cursor.advance::()); - let max_composite_contours_byte_start = version - .compatible((1u16, 0u16)) - .then(|| cursor.position()) - .transpose()?; - version - .compatible((1u16, 0u16)) - .then(|| cursor.advance::()); - let max_zones_byte_start = version - .compatible((1u16, 0u16)) - .then(|| cursor.position()) - .transpose()?; - version - .compatible((1u16, 0u16)) - .then(|| cursor.advance::()); - let max_twilight_points_byte_start = version - .compatible((1u16, 0u16)) - .then(|| cursor.position()) - .transpose()?; - version - .compatible((1u16, 0u16)) - .then(|| cursor.advance::()); - let max_storage_byte_start = version - .compatible((1u16, 0u16)) - .then(|| cursor.position()) - .transpose()?; - version - .compatible((1u16, 0u16)) - .then(|| cursor.advance::()); - let max_function_defs_byte_start = version - .compatible((1u16, 0u16)) - .then(|| cursor.position()) - .transpose()?; - version - .compatible((1u16, 0u16)) - .then(|| cursor.advance::()); - let max_instruction_defs_byte_start = version - .compatible((1u16, 0u16)) - .then(|| cursor.position()) - .transpose()?; - version - .compatible((1u16, 0u16)) - .then(|| cursor.advance::()); - let max_stack_elements_byte_start = version - .compatible((1u16, 0u16)) - .then(|| cursor.position()) - .transpose()?; - version - .compatible((1u16, 0u16)) - .then(|| cursor.advance::()); - let max_size_of_instructions_byte_start = version - .compatible((1u16, 0u16)) - .then(|| cursor.position()) - .transpose()?; - version - .compatible((1u16, 0u16)) - .then(|| cursor.advance::()); - let max_component_elements_byte_start = version - .compatible((1u16, 0u16)) - .then(|| cursor.position()) - .transpose()?; - version - .compatible((1u16, 0u16)) - .then(|| cursor.advance::()); - let max_component_depth_byte_start = version - .compatible((1u16, 0u16)) - .then(|| cursor.position()) - .transpose()?; - version - .compatible((1u16, 0u16)) - .then(|| cursor.advance::()); - cursor.finish(MaxpMarker { - max_points_byte_start, - max_contours_byte_start, - max_composite_points_byte_start, - max_composite_contours_byte_start, - max_zones_byte_start, - max_twilight_points_byte_start, - max_storage_byte_start, - max_function_defs_byte_start, - max_instruction_defs_byte_start, - max_stack_elements_byte_start, - max_size_of_instructions_byte_start, - max_component_elements_byte_start, - max_component_depth_byte_start, - }) + if self.version().compatible((1u16, 0u16)) { + let start = self . max_component_elements_byte_range () . map (| range | range . end) . unwrap_or_else (|| self . max_size_of_instructions_byte_range () . map (| range | range . end) . unwrap_or_else (|| self . max_stack_elements_byte_range () . map (| range | range . end) . unwrap_or_else (|| self . max_instruction_defs_byte_range () . map (| range | range . end) . unwrap_or_else (|| self . max_function_defs_byte_range () . map (| range | range . end) . unwrap_or_else (|| self . max_storage_byte_range () . map (| range | range . end) . unwrap_or_else (|| self . max_twilight_points_byte_range () . map (| range | range . end) . unwrap_or_else (|| self . max_zones_byte_range () . map (| range | range . end) . unwrap_or_else (|| self . max_composite_contours_byte_range () . map (| range | range . end) . unwrap_or_else (|| self . max_composite_points_byte_range () . map (| range | range . end) . unwrap_or_else (|| self . max_contours_byte_range () . map (| range | range . end) . unwrap_or_else (|| self . max_points_byte_range () . map (| range | range . end) . unwrap_or_else (|| self . num_glyphs_byte_range () . end)))))))))))) ; + Some(start..start + u16::RAW_BYTE_LEN) + } else { + None + } } -} - -/// [`maxp`](https://docs.microsoft.com/en-us/typography/opentype/spec/maxp) -pub type Maxp<'a> = TableRef<'a, MaxpMarker>; -#[allow(clippy::needless_lifetimes)] -impl<'a> Maxp<'a> { /// The version: 0x00005000 for version 0.5, 0x00010000 for version 1.0. pub fn version(&self) -> Version16Dot16 { - let range = self.shape.version_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.version_byte_range(); + unchecked::read_at(self.data, range.start) } /// The number of glyphs in the font. pub fn num_glyphs(&self) -> u16 { - let range = self.shape.num_glyphs_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.num_glyphs_byte_range(); + unchecked::read_at(self.data, range.start) } /// Maximum points in a non-composite glyph. pub fn max_points(&self) -> Option { - let range = self.shape.max_points_byte_range()?; - Some(self.data.read_at(range.start).unwrap()) + let range = self.max_points_byte_range()?; + Some(unchecked::read_at(self.data, range.start)) } /// Maximum contours in a non-composite glyph. pub fn max_contours(&self) -> Option { - let range = self.shape.max_contours_byte_range()?; - Some(self.data.read_at(range.start).unwrap()) + let range = self.max_contours_byte_range()?; + Some(unchecked::read_at(self.data, range.start)) } /// Maximum points in a composite glyph. pub fn max_composite_points(&self) -> Option { - let range = self.shape.max_composite_points_byte_range()?; - Some(self.data.read_at(range.start).unwrap()) + let range = self.max_composite_points_byte_range()?; + Some(unchecked::read_at(self.data, range.start)) } /// Maximum contours in a composite glyph. pub fn max_composite_contours(&self) -> Option { - let range = self.shape.max_composite_contours_byte_range()?; - Some(self.data.read_at(range.start).unwrap()) + let range = self.max_composite_contours_byte_range()?; + Some(unchecked::read_at(self.data, range.start)) } /// 1 if instructions do not use the twilight zone (Z0), or 2 if /// instructions do use Z0; should be set to 2 in most cases. pub fn max_zones(&self) -> Option { - let range = self.shape.max_zones_byte_range()?; - Some(self.data.read_at(range.start).unwrap()) + let range = self.max_zones_byte_range()?; + Some(unchecked::read_at(self.data, range.start)) } /// Maximum points used in Z0. pub fn max_twilight_points(&self) -> Option { - let range = self.shape.max_twilight_points_byte_range()?; - Some(self.data.read_at(range.start).unwrap()) + let range = self.max_twilight_points_byte_range()?; + Some(unchecked::read_at(self.data, range.start)) } /// Number of Storage Area locations. pub fn max_storage(&self) -> Option { - let range = self.shape.max_storage_byte_range()?; - Some(self.data.read_at(range.start).unwrap()) + let range = self.max_storage_byte_range()?; + Some(unchecked::read_at(self.data, range.start)) } /// Number of FDEFs, equal to the highest function number + 1. pub fn max_function_defs(&self) -> Option { - let range = self.shape.max_function_defs_byte_range()?; - Some(self.data.read_at(range.start).unwrap()) + let range = self.max_function_defs_byte_range()?; + Some(unchecked::read_at(self.data, range.start)) } /// Number of IDEFs. pub fn max_instruction_defs(&self) -> Option { - let range = self.shape.max_instruction_defs_byte_range()?; - Some(self.data.read_at(range.start).unwrap()) + let range = self.max_instruction_defs_byte_range()?; + Some(unchecked::read_at(self.data, range.start)) } /// Maximum stack depth across Font Program ('fpgm' table), CVT /// Program ('prep' table) and all glyph instructions (in the /// 'glyf' table). pub fn max_stack_elements(&self) -> Option { - let range = self.shape.max_stack_elements_byte_range()?; - Some(self.data.read_at(range.start).unwrap()) + let range = self.max_stack_elements_byte_range()?; + Some(unchecked::read_at(self.data, range.start)) } /// Maximum byte count for glyph instructions. pub fn max_size_of_instructions(&self) -> Option { - let range = self.shape.max_size_of_instructions_byte_range()?; - Some(self.data.read_at(range.start).unwrap()) + let range = self.max_size_of_instructions_byte_range()?; + Some(unchecked::read_at(self.data, range.start)) } /// Maximum number of components referenced at “top level” for /// any composite glyph. pub fn max_component_elements(&self) -> Option { - let range = self.shape.max_component_elements_byte_range()?; - Some(self.data.read_at(range.start).unwrap()) + let range = self.max_component_elements_byte_range()?; + Some(unchecked::read_at(self.data, range.start)) } /// Maximum levels of recursion; 1 for simple components. pub fn max_component_depth(&self) -> Option { - let range = self.shape.max_component_depth_byte_range()?; - Some(self.data.read_at(range.start).unwrap()) + let range = self.max_component_depth_byte_range()?; + Some(unchecked::read_at(self.data, range.start)) } } diff --git a/read-fonts/generated/generated_meta.rs b/read-fonts/generated/generated_meta.rs index 556d5d9ad..258d9724e 100644 --- a/read-fonts/generated/generated_meta.rs +++ b/read-fonts/generated/generated_meta.rs @@ -8,11 +8,41 @@ use crate::codegen_prelude::*; /// [`meta`](https://docs.microsoft.com/en-us/typography/opentype/spec/meta) #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct MetaMarker { - data_maps_byte_len: usize, +pub struct MetaMarker; + +impl<'a> MinByteRange for Meta<'a> { + fn min_byte_range(&self) -> Range { + 0..self.data_maps_byte_range().end + } +} + +impl TopLevelTable for Meta<'_> { + /// `meta` + const TAG: Tag = Tag::new(b"meta"); +} + +impl<'a> FontRead<'a> for Meta<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } } -impl MetaMarker { +/// [`meta`](https://docs.microsoft.com/en-us/typography/opentype/spec/meta) +pub type Meta<'a> = TableRef<'a, MetaMarker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> Meta<'a> { + fn data_maps_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.data_maps_count()) as usize) + .checked_mul(DataMapRecord::RAW_BYTE_LEN) + .unwrap() + } + pub fn version_byte_range(&self) -> Range { let start = 0; start..start + u32::RAW_BYTE_LEN @@ -35,63 +65,31 @@ impl MetaMarker { pub fn data_maps_byte_range(&self) -> Range { let start = self.data_maps_count_byte_range().end; - start..start + self.data_maps_byte_len + start..start + self.data_maps_byte_len(start) } -} - -impl MinByteRange for MetaMarker { - fn min_byte_range(&self) -> Range { - 0..self.data_maps_byte_range().end - } -} - -impl TopLevelTable for Meta<'_> { - /// `meta` - const TAG: Tag = Tag::new(b"meta"); -} -impl<'a> FontRead<'a> for Meta<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - let data_maps_count: u32 = cursor.read()?; - let data_maps_byte_len = (data_maps_count as usize) - .checked_mul(DataMapRecord::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(data_maps_byte_len); - cursor.finish(MetaMarker { data_maps_byte_len }) - } -} - -/// [`meta`](https://docs.microsoft.com/en-us/typography/opentype/spec/meta) -pub type Meta<'a> = TableRef<'a, MetaMarker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> Meta<'a> { /// Version number of the metadata table — set to 1. pub fn version(&self) -> u32 { - let range = self.shape.version_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.version_byte_range(); + unchecked::read_at(self.data, range.start) } /// Flags — currently unused; set to 0. pub fn flags(&self) -> u32 { - let range = self.shape.flags_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.flags_byte_range(); + unchecked::read_at(self.data, range.start) } /// The number of data maps in the table. pub fn data_maps_count(&self) -> u32 { - let range = self.shape.data_maps_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.data_maps_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Array of data map records. pub fn data_maps(&self) -> &'a [DataMapRecord] { - let range = self.shape.data_maps_byte_range(); - self.data.read_array(range).unwrap() + let range = self.data_maps_byte_range(); + unchecked::read_array(self.data, range) } } diff --git a/read-fonts/generated/generated_morx.rs b/read-fonts/generated/generated_morx.rs index 045febe5d..e53beb028 100644 --- a/read-fonts/generated/generated_morx.rs +++ b/read-fonts/generated/generated_morx.rs @@ -8,11 +8,42 @@ use crate::codegen_prelude::*; /// The [morx (Extended Glyph Metamorphosis)](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6morx.html) table. #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct MorxMarker { - chains_byte_len: usize, +pub struct MorxMarker; + +impl<'a> MinByteRange for Morx<'a> { + fn min_byte_range(&self) -> Range { + 0..self.chains_byte_range().end + } } -impl MorxMarker { +impl TopLevelTable for Morx<'_> { + /// `morx` + const TAG: Tag = Tag::new(b"morx"); +} + +impl<'a> FontRead<'a> for Morx<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// The [morx (Extended Glyph Metamorphosis)](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6morx.html) table. +pub type Morx<'a> = TableRef<'a, MorxMarker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> Morx<'a> { + fn chains_byte_len(&self, start: usize) -> usize { + let _ = start; + { + let data = self.data.split_off(start).unwrap(); + ::total_len_for_count(data, (self.n_chains()) as usize).unwrap() + } + } + pub fn version_byte_range(&self) -> Range { let start = 0; start..start + u16::RAW_BYTE_LEN @@ -30,56 +61,24 @@ impl MorxMarker { pub fn chains_byte_range(&self) -> Range { let start = self.n_chains_byte_range().end; - start..start + self.chains_byte_len + start..start + self.chains_byte_len(start) } -} - -impl MinByteRange for MorxMarker { - fn min_byte_range(&self) -> Range { - 0..self.chains_byte_range().end - } -} -impl TopLevelTable for Morx<'_> { - /// `morx` - const TAG: Tag = Tag::new(b"morx"); -} - -impl<'a> FontRead<'a> for Morx<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - let n_chains: u32 = cursor.read()?; - let chains_byte_len = { - let data = cursor.remaining().ok_or(ReadError::OutOfBounds)?; - ::total_len_for_count(data, n_chains as usize)? - }; - cursor.advance_by(chains_byte_len); - cursor.finish(MorxMarker { chains_byte_len }) - } -} - -/// The [morx (Extended Glyph Metamorphosis)](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6morx.html) table. -pub type Morx<'a> = TableRef<'a, MorxMarker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> Morx<'a> { /// Version number of the extended glyph metamorphosis table (either 2 or 3). pub fn version(&self) -> u16 { - let range = self.shape.version_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.version_byte_range(); + unchecked::read_at(self.data, range.start) } /// Number of metamorphosis chains contained in this table. pub fn n_chains(&self) -> u32 { - let range = self.shape.n_chains_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.n_chains_byte_range(); + unchecked::read_at(self.data, range.start) } pub fn chains(&self) -> VarLenArray<'a, Chain<'a>> { - let range = self.shape.chains_byte_range(); - VarLenArray::read(self.data.split_off(range.start).unwrap()).unwrap() + let range = self.chains_byte_range(); + VarLenArray::read(unchecked::split_off(self.data, range.start)).unwrap() } } @@ -112,12 +111,43 @@ impl<'a> std::fmt::Debug for Morx<'a> { /// A chain in a `morx` table. #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct ChainMarker { - features_byte_len: usize, - subtables_byte_len: usize, +pub struct ChainMarker; + +impl<'a> MinByteRange for Chain<'a> { + fn min_byte_range(&self) -> Range { + 0..self.subtables_byte_range().end + } +} + +impl<'a> FontRead<'a> for Chain<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } } -impl ChainMarker { +/// A chain in a `morx` table. +pub type Chain<'a> = TableRef<'a, ChainMarker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> Chain<'a> { + fn features_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.n_feature_entries()) as usize) + .checked_mul(Feature::RAW_BYTE_LEN) + .unwrap() + } + fn subtables_byte_len(&self, start: usize) -> usize { + let _ = start; + { + let data = self.data.split_off(start).unwrap(); + ::total_len_for_count(data, (self.n_subtables()) as usize).unwrap() + } + } + pub fn default_flags_byte_range(&self) -> Range { let start = 0; start..start + u32::RAW_BYTE_LEN @@ -140,83 +170,48 @@ impl ChainMarker { pub fn features_byte_range(&self) -> Range { let start = self.n_subtables_byte_range().end; - start..start + self.features_byte_len + start..start + self.features_byte_len(start) } pub fn subtables_byte_range(&self) -> Range { let start = self.features_byte_range().end; - start..start + self.subtables_byte_len - } -} - -impl MinByteRange for ChainMarker { - fn min_byte_range(&self) -> Range { - 0..self.subtables_byte_range().end - } -} - -impl<'a> FontRead<'a> for Chain<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - let n_feature_entries: u32 = cursor.read()?; - let n_subtables: u32 = cursor.read()?; - let features_byte_len = (n_feature_entries as usize) - .checked_mul(Feature::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(features_byte_len); - let subtables_byte_len = { - let data = cursor.remaining().ok_or(ReadError::OutOfBounds)?; - ::total_len_for_count(data, n_subtables as usize)? - }; - cursor.advance_by(subtables_byte_len); - cursor.finish(ChainMarker { - features_byte_len, - subtables_byte_len, - }) + start..start + self.subtables_byte_len(start) } -} - -/// A chain in a `morx` table. -pub type Chain<'a> = TableRef<'a, ChainMarker>; -#[allow(clippy::needless_lifetimes)] -impl<'a> Chain<'a> { /// The default specification for subtables. pub fn default_flags(&self) -> u32 { - let range = self.shape.default_flags_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.default_flags_byte_range(); + unchecked::read_at(self.data, range.start) } /// Total byte count, including this header; must be a multiple of 4. pub fn chain_length(&self) -> u32 { - let range = self.shape.chain_length_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.chain_length_byte_range(); + unchecked::read_at(self.data, range.start) } /// Number of feature subtable entries. pub fn n_feature_entries(&self) -> u32 { - let range = self.shape.n_feature_entries_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.n_feature_entries_byte_range(); + unchecked::read_at(self.data, range.start) } /// The number of subtables in the chain. pub fn n_subtables(&self) -> u32 { - let range = self.shape.n_subtables_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.n_subtables_byte_range(); + unchecked::read_at(self.data, range.start) } /// Feature entries for this chain. pub fn features(&self) -> &'a [Feature] { - let range = self.shape.features_byte_range(); - self.data.read_array(range).unwrap() + let range = self.features_byte_range(); + unchecked::read_array(self.data, range) } /// Array of chain subtables. pub fn subtables(&self) -> VarLenArray<'a, Subtable<'a>> { - let range = self.shape.subtables_byte_range(); - VarLenArray::read(self.data.split_off(range.start).unwrap()).unwrap() + let range = self.subtables_byte_range(); + VarLenArray::read(unchecked::split_off(self.data, range.start)).unwrap() } } @@ -318,11 +313,37 @@ impl<'a> SomeRecord<'a> for Feature { /// A subtable in a `morx` chain. #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct SubtableMarker { - data_byte_len: usize, +pub struct SubtableMarker; + +impl<'a> MinByteRange for Subtable<'a> { + fn min_byte_range(&self) -> Range { + 0..self.data_byte_range().end + } +} + +impl<'a> FontRead<'a> for Subtable<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } } -impl SubtableMarker { +/// A subtable in a `morx` chain. +pub type Subtable<'a> = TableRef<'a, SubtableMarker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> Subtable<'a> { + fn data_byte_len(&self, start: usize) -> usize { + let _ = start; + { + let remaining = self.data.len().saturating_sub(start); + remaining / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN + } + } + pub fn length_byte_range(&self) -> Range { let start = 0; start..start + u32::RAW_BYTE_LEN @@ -340,55 +361,31 @@ impl SubtableMarker { pub fn data_byte_range(&self) -> Range { let start = self.sub_feature_flags_byte_range().end; - start..start + self.data_byte_len - } -} - -impl MinByteRange for SubtableMarker { - fn min_byte_range(&self) -> Range { - 0..self.data_byte_range().end - } -} - -impl<'a> FontRead<'a> for Subtable<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - let data_byte_len = cursor.remaining_bytes() / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN; - cursor.advance_by(data_byte_len); - cursor.finish(SubtableMarker { data_byte_len }) + start..start + self.data_byte_len(start) } -} -/// A subtable in a `morx` chain. -pub type Subtable<'a> = TableRef<'a, SubtableMarker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> Subtable<'a> { /// Total subtable length, including this header. pub fn length(&self) -> u32 { - let range = self.shape.length_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.length_byte_range(); + unchecked::read_at(self.data, range.start) } /// Coverage flags and subtable type. pub fn coverage(&self) -> u32 { - let range = self.shape.coverage_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.coverage_byte_range(); + unchecked::read_at(self.data, range.start) } /// The 32-bit mask identifying which subtable this is (the subtable being executed if the AND of this value and the processed defaultFlags is nonzero). pub fn sub_feature_flags(&self) -> u32 { - let range = self.shape.sub_feature_flags_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.sub_feature_flags_byte_range(); + unchecked::read_at(self.data, range.start) } /// Data for specific subtable. pub fn data(&self) -> &'a [u8] { - let range = self.shape.data_byte_range(); - self.data.read_array(range).unwrap() + let range = self.data_byte_range(); + unchecked::read_array(self.data, range) } } diff --git a/read-fonts/generated/generated_mvar.rs b/read-fonts/generated/generated_mvar.rs index 7cb806489..ca37c24d0 100644 --- a/read-fonts/generated/generated_mvar.rs +++ b/read-fonts/generated/generated_mvar.rs @@ -8,11 +8,41 @@ use crate::codegen_prelude::*; /// The [MVAR (Metrics Variations)](https://docs.microsoft.com/en-us/typography/opentype/spec/mvar) table #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct MvarMarker { - value_records_byte_len: usize, +pub struct MvarMarker; + +impl<'a> MinByteRange for Mvar<'a> { + fn min_byte_range(&self) -> Range { + 0..self.value_records_byte_range().end + } +} + +impl TopLevelTable for Mvar<'_> { + /// `MVAR` + const TAG: Tag = Tag::new(b"MVAR"); } -impl MvarMarker { +impl<'a> FontRead<'a> for Mvar<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// The [MVAR (Metrics Variations)](https://docs.microsoft.com/en-us/typography/opentype/spec/mvar) table +pub type Mvar<'a> = TableRef<'a, MvarMarker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> Mvar<'a> { + fn value_records_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.value_record_count()) as usize) + .checked_mul(ValueRecord::RAW_BYTE_LEN) + .unwrap() + } + pub fn version_byte_range(&self) -> Range { let start = 0; start..start + MajorMinor::RAW_BYTE_LEN @@ -40,67 +70,32 @@ impl MvarMarker { pub fn value_records_byte_range(&self) -> Range { let start = self.item_variation_store_offset_byte_range().end; - start..start + self.value_records_byte_len + start..start + self.value_records_byte_len(start) } -} - -impl MinByteRange for MvarMarker { - fn min_byte_range(&self) -> Range { - 0..self.value_records_byte_range().end - } -} - -impl TopLevelTable for Mvar<'_> { - /// `MVAR` - const TAG: Tag = Tag::new(b"MVAR"); -} -impl<'a> FontRead<'a> for Mvar<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - let value_record_count: u16 = cursor.read()?; - cursor.advance::(); - let value_records_byte_len = (value_record_count as usize) - .checked_mul(ValueRecord::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(value_records_byte_len); - cursor.finish(MvarMarker { - value_records_byte_len, - }) - } -} - -/// The [MVAR (Metrics Variations)](https://docs.microsoft.com/en-us/typography/opentype/spec/mvar) table -pub type Mvar<'a> = TableRef<'a, MvarMarker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> Mvar<'a> { /// Major version number of the horizontal metrics variations table — set to 1. /// Minor version number of the horizontal metrics variations table — set to 0. pub fn version(&self) -> MajorMinor { - let range = self.shape.version_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.version_byte_range(); + unchecked::read_at(self.data, range.start) } /// The size in bytes of each value record — must be greater than zero. pub fn value_record_size(&self) -> u16 { - let range = self.shape.value_record_size_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.value_record_size_byte_range(); + unchecked::read_at(self.data, range.start) } /// The number of value records — may be zero. pub fn value_record_count(&self) -> u16 { - let range = self.shape.value_record_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.value_record_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Offset in bytes from the start of this table to the item variation store table. If valueRecordCount is zero, set to zero; if valueRecordCount is greater than zero, must be greater than zero. pub fn item_variation_store_offset(&self) -> Nullable { - let range = self.shape.item_variation_store_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.item_variation_store_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`item_variation_store_offset`][Self::item_variation_store_offset]. @@ -111,8 +106,8 @@ impl<'a> Mvar<'a> { /// Array of value records that identify target items and the associated delta-set index for each. The valueTag records must be in binary order of their valueTag field. pub fn value_records(&self) -> &'a [ValueRecord] { - let range = self.shape.value_records_byte_range(); - self.data.read_array(range).unwrap() + let range = self.value_records_byte_range(); + unchecked::read_array(self.data, range) } } diff --git a/read-fonts/generated/generated_name.rs b/read-fonts/generated/generated_name.rs index 3b9cb83ba..a39d29385 100644 --- a/read-fonts/generated/generated_name.rs +++ b/read-fonts/generated/generated_name.rs @@ -8,14 +8,47 @@ use crate::codegen_prelude::*; /// [Naming table version 1](https://docs.microsoft.com/en-us/typography/opentype/spec/name#naming-table-version-1) #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct NameMarker { - name_record_byte_len: usize, - lang_tag_count_byte_start: Option, - lang_tag_record_byte_start: Option, - lang_tag_record_byte_len: Option, +pub struct NameMarker; + +impl<'a> MinByteRange for Name<'a> { + fn min_byte_range(&self) -> Range { + 0..self.name_record_byte_range().end + } +} + +impl TopLevelTable for Name<'_> { + /// `name` + const TAG: Tag = Tag::new(b"name"); +} + +impl<'a> FontRead<'a> for Name<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } } -impl NameMarker { +/// [Naming table version 1](https://docs.microsoft.com/en-us/typography/opentype/spec/name#naming-table-version-1) +pub type Name<'a> = TableRef<'a, NameMarker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> Name<'a> { + fn name_record_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.count()) as usize) + .checked_mul(NameRecord::RAW_BYTE_LEN) + .unwrap() + } + fn lang_tag_record_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.lang_tag_count().unwrap_or_default()) as usize) + .checked_mul(LangTagRecord::RAW_BYTE_LEN) + .unwrap() + } + pub fn version_byte_range(&self) -> Range { let start = 0; start..start + u16::RAW_BYTE_LEN @@ -33,110 +66,64 @@ impl NameMarker { pub fn name_record_byte_range(&self) -> Range { let start = self.storage_offset_byte_range().end; - start..start + self.name_record_byte_len + start..start + self.name_record_byte_len(start) } pub fn lang_tag_count_byte_range(&self) -> Option> { - let start = self.lang_tag_count_byte_start?; - Some(start..start + u16::RAW_BYTE_LEN) + if self.version().compatible(1u16) { + let start = self.name_record_byte_range().end; + Some(start..start + u16::RAW_BYTE_LEN) + } else { + None + } } pub fn lang_tag_record_byte_range(&self) -> Option> { - let start = self.lang_tag_record_byte_start?; - Some(start..start + self.lang_tag_record_byte_len?) - } -} - -impl MinByteRange for NameMarker { - fn min_byte_range(&self) -> Range { - 0..self.name_record_byte_range().end - } -} - -impl TopLevelTable for Name<'_> { - /// `name` - const TAG: Tag = Tag::new(b"name"); -} - -impl<'a> FontRead<'a> for Name<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - let version: u16 = cursor.read()?; - let count: u16 = cursor.read()?; - cursor.advance::(); - let name_record_byte_len = (count as usize) - .checked_mul(NameRecord::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(name_record_byte_len); - let lang_tag_count_byte_start = version - .compatible(1u16) - .then(|| cursor.position()) - .transpose()?; - let lang_tag_count = version - .compatible(1u16) - .then(|| cursor.read::()) - .transpose()? - .unwrap_or_default(); - let lang_tag_record_byte_start = version - .compatible(1u16) - .then(|| cursor.position()) - .transpose()?; - let lang_tag_record_byte_len = version.compatible(1u16).then_some( - (lang_tag_count as usize) - .checked_mul(LangTagRecord::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?, - ); - if let Some(value) = lang_tag_record_byte_len { - cursor.advance_by(value); + if self.version().compatible(1u16) { + let start = self + .lang_tag_count_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| self.name_record_byte_range().end); + Some(start..start + self.lang_tag_record_byte_len(start)) + } else { + None } - cursor.finish(NameMarker { - name_record_byte_len, - lang_tag_count_byte_start, - lang_tag_record_byte_start, - lang_tag_record_byte_len, - }) } -} - -/// [Naming table version 1](https://docs.microsoft.com/en-us/typography/opentype/spec/name#naming-table-version-1) -pub type Name<'a> = TableRef<'a, NameMarker>; -#[allow(clippy::needless_lifetimes)] -impl<'a> Name<'a> { /// Table version number (0 or 1) pub fn version(&self) -> u16 { - let range = self.shape.version_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.version_byte_range(); + unchecked::read_at(self.data, range.start) } /// Number of name records. pub fn count(&self) -> u16 { - let range = self.shape.count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Offset to start of string storage (from start of table). pub fn storage_offset(&self) -> u16 { - let range = self.shape.storage_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.storage_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// The name records where count is the number of records. pub fn name_record(&self) -> &'a [NameRecord] { - let range = self.shape.name_record_byte_range(); - self.data.read_array(range).unwrap() + let range = self.name_record_byte_range(); + unchecked::read_array(self.data, range) } /// Number of language-tag records. pub fn lang_tag_count(&self) -> Option { - let range = self.shape.lang_tag_count_byte_range()?; - Some(self.data.read_at(range.start).unwrap()) + let range = self.lang_tag_count_byte_range()?; + Some(unchecked::read_at(self.data, range.start)) } /// The language-tag records where langTagCount is the number of records. pub fn lang_tag_record(&self) -> Option<&'a [LangTagRecord]> { - let range = self.shape.lang_tag_record_byte_range()?; - Some(self.data.read_array(range).unwrap()) + let range = self.lang_tag_record_byte_range()?; + Some(unchecked::read_array(self.data, range)) } } diff --git a/read-fonts/generated/generated_os2.rs b/read-fonts/generated/generated_os2.rs index 13d89c197..68d60caf9 100644 --- a/read-fonts/generated/generated_os2.rs +++ b/read-fonts/generated/generated_os2.rs @@ -361,20 +361,39 @@ impl<'a> From for FieldType<'a> { /// [`OS/2`](https://docs.microsoft.com/en-us/typography/opentype/spec/os2) #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct Os2Marker { - panose_10_byte_len: usize, - ul_code_page_range_1_byte_start: Option, - ul_code_page_range_2_byte_start: Option, - sx_height_byte_start: Option, - s_cap_height_byte_start: Option, - us_default_char_byte_start: Option, - us_break_char_byte_start: Option, - us_max_context_byte_start: Option, - us_lower_optical_point_size_byte_start: Option, - us_upper_optical_point_size_byte_start: Option, +pub struct Os2Marker; + +impl<'a> MinByteRange for Os2<'a> { + fn min_byte_range(&self) -> Range { + 0..self.us_win_descent_byte_range().end + } +} + +impl TopLevelTable for Os2<'_> { + /// `OS/2` + const TAG: Tag = Tag::new(b"OS/2"); } -impl Os2Marker { +impl<'a> FontRead<'a> for Os2<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// [`OS/2`](https://docs.microsoft.com/en-us/typography/opentype/spec/os2) +pub type Os2<'a> = TableRef<'a, Os2Marker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> Os2<'a> { + fn panose_10_byte_len(&self, start: usize) -> usize { + let _ = start; + (10_usize).checked_mul(u8::RAW_BYTE_LEN).unwrap() + } + pub fn version_byte_range(&self) -> Range { let start = 0; start..start + u16::RAW_BYTE_LEN @@ -457,7 +476,7 @@ impl Os2Marker { pub fn panose_10_byte_range(&self) -> Range { let start = self.s_family_class_byte_range().end; - start..start + self.panose_10_byte_len + start..start + self.panose_10_byte_len(start) } pub fn ul_unicode_range_1_byte_range(&self) -> Range { @@ -526,166 +545,201 @@ impl Os2Marker { } pub fn ul_code_page_range_1_byte_range(&self) -> Option> { - let start = self.ul_code_page_range_1_byte_start?; - Some(start..start + u32::RAW_BYTE_LEN) + if self.version().compatible(1u16) { + let start = self.us_win_descent_byte_range().end; + Some(start..start + u32::RAW_BYTE_LEN) + } else { + None + } } pub fn ul_code_page_range_2_byte_range(&self) -> Option> { - let start = self.ul_code_page_range_2_byte_start?; - Some(start..start + u32::RAW_BYTE_LEN) + if self.version().compatible(1u16) { + let start = self + .ul_code_page_range_1_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| self.us_win_descent_byte_range().end); + Some(start..start + u32::RAW_BYTE_LEN) + } else { + None + } } pub fn sx_height_byte_range(&self) -> Option> { - let start = self.sx_height_byte_start?; - Some(start..start + i16::RAW_BYTE_LEN) + if self.version().compatible(2u16) { + let start = self + .ul_code_page_range_2_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| { + self.ul_code_page_range_1_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| self.us_win_descent_byte_range().end) + }); + Some(start..start + i16::RAW_BYTE_LEN) + } else { + None + } } pub fn s_cap_height_byte_range(&self) -> Option> { - let start = self.s_cap_height_byte_start?; - Some(start..start + i16::RAW_BYTE_LEN) + if self.version().compatible(2u16) { + let start = self + .sx_height_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| { + self.ul_code_page_range_2_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| { + self.ul_code_page_range_1_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| self.us_win_descent_byte_range().end) + }) + }); + Some(start..start + i16::RAW_BYTE_LEN) + } else { + None + } } pub fn us_default_char_byte_range(&self) -> Option> { - let start = self.us_default_char_byte_start?; - Some(start..start + u16::RAW_BYTE_LEN) + if self.version().compatible(2u16) { + let start = self + .s_cap_height_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| { + self.sx_height_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| { + self.ul_code_page_range_2_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| { + self.ul_code_page_range_1_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| self.us_win_descent_byte_range().end) + }) + }) + }); + Some(start..start + u16::RAW_BYTE_LEN) + } else { + None + } } pub fn us_break_char_byte_range(&self) -> Option> { - let start = self.us_break_char_byte_start?; - Some(start..start + u16::RAW_BYTE_LEN) + if self.version().compatible(2u16) { + let start = self + .us_default_char_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| { + self.s_cap_height_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| { + self.sx_height_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| { + self.ul_code_page_range_2_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| { + self.ul_code_page_range_1_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| { + self.us_win_descent_byte_range().end + }) + }) + }) + }) + }); + Some(start..start + u16::RAW_BYTE_LEN) + } else { + None + } } pub fn us_max_context_byte_range(&self) -> Option> { - let start = self.us_max_context_byte_start?; - Some(start..start + u16::RAW_BYTE_LEN) + if self.version().compatible(2u16) { + let start = self + .us_break_char_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| { + self.us_default_char_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| { + self.s_cap_height_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| { + self.sx_height_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| { + self.ul_code_page_range_2_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| { + self.ul_code_page_range_1_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| { + self.us_win_descent_byte_range().end + }) + }) + }) + }) + }) + }); + Some(start..start + u16::RAW_BYTE_LEN) + } else { + None + } } pub fn us_lower_optical_point_size_byte_range(&self) -> Option> { - let start = self.us_lower_optical_point_size_byte_start?; - Some(start..start + u16::RAW_BYTE_LEN) + if self.version().compatible(5u16) { + let start = self + .us_max_context_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| { + self.us_break_char_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| { + self.us_default_char_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| { + self.s_cap_height_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| { + self.sx_height_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| { + self.ul_code_page_range_2_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| { + self.ul_code_page_range_1_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| { + self.us_win_descent_byte_range() + .end + }) + }) + }) + }) + }) + }) + }); + Some(start..start + u16::RAW_BYTE_LEN) + } else { + None + } } pub fn us_upper_optical_point_size_byte_range(&self) -> Option> { - let start = self.us_upper_optical_point_size_byte_start?; - Some(start..start + u16::RAW_BYTE_LEN) - } -} - -impl MinByteRange for Os2Marker { - fn min_byte_range(&self) -> Range { - 0..self.us_win_descent_byte_range().end - } -} - -impl TopLevelTable for Os2<'_> { - /// `OS/2` - const TAG: Tag = Tag::new(b"OS/2"); -} - -impl<'a> FontRead<'a> for Os2<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - let version: u16 = cursor.read()?; - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - let panose_10_byte_len = (10_usize) - .checked_mul(u8::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(panose_10_byte_len); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - let ul_code_page_range_1_byte_start = version - .compatible(1u16) - .then(|| cursor.position()) - .transpose()?; - version.compatible(1u16).then(|| cursor.advance::()); - let ul_code_page_range_2_byte_start = version - .compatible(1u16) - .then(|| cursor.position()) - .transpose()?; - version.compatible(1u16).then(|| cursor.advance::()); - let sx_height_byte_start = version - .compatible(2u16) - .then(|| cursor.position()) - .transpose()?; - version.compatible(2u16).then(|| cursor.advance::()); - let s_cap_height_byte_start = version - .compatible(2u16) - .then(|| cursor.position()) - .transpose()?; - version.compatible(2u16).then(|| cursor.advance::()); - let us_default_char_byte_start = version - .compatible(2u16) - .then(|| cursor.position()) - .transpose()?; - version.compatible(2u16).then(|| cursor.advance::()); - let us_break_char_byte_start = version - .compatible(2u16) - .then(|| cursor.position()) - .transpose()?; - version.compatible(2u16).then(|| cursor.advance::()); - let us_max_context_byte_start = version - .compatible(2u16) - .then(|| cursor.position()) - .transpose()?; - version.compatible(2u16).then(|| cursor.advance::()); - let us_lower_optical_point_size_byte_start = version - .compatible(5u16) - .then(|| cursor.position()) - .transpose()?; - version.compatible(5u16).then(|| cursor.advance::()); - let us_upper_optical_point_size_byte_start = version - .compatible(5u16) - .then(|| cursor.position()) - .transpose()?; - version.compatible(5u16).then(|| cursor.advance::()); - cursor.finish(Os2Marker { - panose_10_byte_len, - ul_code_page_range_1_byte_start, - ul_code_page_range_2_byte_start, - sx_height_byte_start, - s_cap_height_byte_start, - us_default_char_byte_start, - us_break_char_byte_start, - us_max_context_byte_start, - us_lower_optical_point_size_byte_start, - us_upper_optical_point_size_byte_start, - }) + if self.version().compatible(5u16) { + let start = self . us_lower_optical_point_size_byte_range () . map (| range | range . end) . unwrap_or_else (|| self . us_max_context_byte_range () . map (| range | range . end) . unwrap_or_else (|| self . us_break_char_byte_range () . map (| range | range . end) . unwrap_or_else (|| self . us_default_char_byte_range () . map (| range | range . end) . unwrap_or_else (|| self . s_cap_height_byte_range () . map (| range | range . end) . unwrap_or_else (|| self . sx_height_byte_range () . map (| range | range . end) . unwrap_or_else (|| self . ul_code_page_range_2_byte_range () . map (| range | range . end) . unwrap_or_else (|| self . ul_code_page_range_1_byte_range () . map (| range | range . end) . unwrap_or_else (|| self . us_win_descent_byte_range () . end)))))))) ; + Some(start..start + u16::RAW_BYTE_LEN) + } else { + None + } } -} -/// [`OS/2`](https://docs.microsoft.com/en-us/typography/opentype/spec/os2) -pub type Os2<'a> = TableRef<'a, Os2Marker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> Os2<'a> { pub fn version(&self) -> u16 { - let range = self.shape.version_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.version_byte_range(); + unchecked::read_at(self.data, range.start) } /// [Average weighted escapement](https://learn.microsoft.com/en-us/typography/opentype/spec/os2#xavgcharwidth). @@ -693,8 +747,8 @@ impl<'a> Os2<'a> { /// The Average Character Width parameter specifies the arithmetic average /// of the escapement (width) of all non-zero width glyphs in the font. pub fn x_avg_char_width(&self) -> i16 { - let range = self.shape.x_avg_char_width_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.x_avg_char_width_byte_range(); + unchecked::read_at(self.data, range.start) } /// [Weight class](https://learn.microsoft.com/en-us/typography/opentype/spec/os2#usweightclass). @@ -702,8 +756,8 @@ impl<'a> Os2<'a> { /// Indicates the visual weight (degree of blackness or thickness of /// strokes) of the characters in the font. Values from 1 to 1000 are valid. pub fn us_weight_class(&self) -> u16 { - let range = self.shape.us_weight_class_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.us_weight_class_byte_range(); + unchecked::read_at(self.data, range.start) } /// [Width class](https://learn.microsoft.com/en-us/typography/opentype/spec/os2#uswidthclass). @@ -711,92 +765,92 @@ impl<'a> Os2<'a> { /// Indicates a relative change from the normal aspect ratio (width to height /// ratio) as specified by a font designer for the glyphs in a font. pub fn us_width_class(&self) -> u16 { - let range = self.shape.us_width_class_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.us_width_class_byte_range(); + unchecked::read_at(self.data, range.start) } /// [Type flags](https://learn.microsoft.com/en-us/typography/opentype/spec/os2#fstype). /// /// Indicates font embedding licensing rights for the font. pub fn fs_type(&self) -> u16 { - let range = self.shape.fs_type_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.fs_type_byte_range(); + unchecked::read_at(self.data, range.start) } /// The recommended horizontal size in font design units for subscripts for /// this font. pub fn y_subscript_x_size(&self) -> i16 { - let range = self.shape.y_subscript_x_size_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.y_subscript_x_size_byte_range(); + unchecked::read_at(self.data, range.start) } /// The recommended vertical size in font design units for subscripts for /// this font. pub fn y_subscript_y_size(&self) -> i16 { - let range = self.shape.y_subscript_y_size_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.y_subscript_y_size_byte_range(); + unchecked::read_at(self.data, range.start) } /// The recommended horizontal offset in font design units for subscripts /// for this font. pub fn y_subscript_x_offset(&self) -> i16 { - let range = self.shape.y_subscript_x_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.y_subscript_x_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// The recommended vertical offset in font design units for subscripts /// for this font. pub fn y_subscript_y_offset(&self) -> i16 { - let range = self.shape.y_subscript_y_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.y_subscript_y_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// The recommended horizontal size in font design units for superscripts /// for this font. pub fn y_superscript_x_size(&self) -> i16 { - let range = self.shape.y_superscript_x_size_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.y_superscript_x_size_byte_range(); + unchecked::read_at(self.data, range.start) } /// The recommended vertical size in font design units for superscripts /// for this font. pub fn y_superscript_y_size(&self) -> i16 { - let range = self.shape.y_superscript_y_size_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.y_superscript_y_size_byte_range(); + unchecked::read_at(self.data, range.start) } /// The recommended horizontal offset in font design units for superscripts /// for this font. pub fn y_superscript_x_offset(&self) -> i16 { - let range = self.shape.y_superscript_x_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.y_superscript_x_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// The recommended vertical offset in font design units for superscripts /// for this font. pub fn y_superscript_y_offset(&self) -> i16 { - let range = self.shape.y_superscript_y_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.y_superscript_y_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Thickness of the strikeout stroke in font design units. pub fn y_strikeout_size(&self) -> i16 { - let range = self.shape.y_strikeout_size_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.y_strikeout_size_byte_range(); + unchecked::read_at(self.data, range.start) } /// The position of the top of the strikeout stroke relative to the /// baseline in font design units. pub fn y_strikeout_position(&self) -> i16 { - let range = self.shape.y_strikeout_position_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.y_strikeout_position_byte_range(); + unchecked::read_at(self.data, range.start) } /// [Font-family class and subclass](https://learn.microsoft.com/en-us/typography/opentype/spec/os2#sfamilyclass). /// This parameter is a classification of font-family design. pub fn s_family_class(&self) -> i16 { - let range = self.shape.s_family_class_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.s_family_class_byte_range(); + unchecked::read_at(self.data, range.start) } /// [PANOSE classification number](https://learn.microsoft.com/en-us/typography/opentype/spec/os2#panose). @@ -804,80 +858,80 @@ impl<'a> Os2<'a> { /// Additional specifications are required for PANOSE to classify non-Latin /// character sets. pub fn panose_10(&self) -> &'a [u8] { - let range = self.shape.panose_10_byte_range(); - self.data.read_array(range).unwrap() + let range = self.panose_10_byte_range(); + unchecked::read_array(self.data, range) } /// [Unicode Character Range](https://learn.microsoft.com/en-us/typography/opentype/spec/os2#ulunicoderange1-bits-031ulunicoderange2-bits-3263ulunicoderange3-bits-6495ulunicoderange4-bits-96127). /// /// Unicode Character Range (bits 0-31). pub fn ul_unicode_range_1(&self) -> u32 { - let range = self.shape.ul_unicode_range_1_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.ul_unicode_range_1_byte_range(); + unchecked::read_at(self.data, range.start) } /// Unicode Character Range (bits 32-63). pub fn ul_unicode_range_2(&self) -> u32 { - let range = self.shape.ul_unicode_range_2_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.ul_unicode_range_2_byte_range(); + unchecked::read_at(self.data, range.start) } /// Unicode Character Range (bits 64-95). pub fn ul_unicode_range_3(&self) -> u32 { - let range = self.shape.ul_unicode_range_3_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.ul_unicode_range_3_byte_range(); + unchecked::read_at(self.data, range.start) } /// Unicode Character Range (bits 96-127). pub fn ul_unicode_range_4(&self) -> u32 { - let range = self.shape.ul_unicode_range_4_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.ul_unicode_range_4_byte_range(); + unchecked::read_at(self.data, range.start) } /// [Font Vendor Identification](https://learn.microsoft.com/en-us/typography/opentype/spec/os2#achvendid). /// /// The four-character identifier for the vendor of the given type face. pub fn ach_vend_id(&self) -> Tag { - let range = self.shape.ach_vend_id_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.ach_vend_id_byte_range(); + unchecked::read_at(self.data, range.start) } /// [Font selection flags](https://learn.microsoft.com/en-us/typography/opentype/spec/os2#fsselection). /// /// Contains information concerning the nature of the font patterns. pub fn fs_selection(&self) -> SelectionFlags { - let range = self.shape.fs_selection_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.fs_selection_byte_range(); + unchecked::read_at(self.data, range.start) } /// The minimum Unicode index (character code) in this font. pub fn us_first_char_index(&self) -> u16 { - let range = self.shape.us_first_char_index_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.us_first_char_index_byte_range(); + unchecked::read_at(self.data, range.start) } /// The maximum Unicode index (character code) in this font. pub fn us_last_char_index(&self) -> u16 { - let range = self.shape.us_last_char_index_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.us_last_char_index_byte_range(); + unchecked::read_at(self.data, range.start) } /// The typographic ascender for this font. pub fn s_typo_ascender(&self) -> i16 { - let range = self.shape.s_typo_ascender_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.s_typo_ascender_byte_range(); + unchecked::read_at(self.data, range.start) } /// The typographic descender for this font. pub fn s_typo_descender(&self) -> i16 { - let range = self.shape.s_typo_descender_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.s_typo_descender_byte_range(); + unchecked::read_at(self.data, range.start) } /// The typographic line gap for this font. pub fn s_typo_line_gap(&self) -> i16 { - let range = self.shape.s_typo_line_gap_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.s_typo_line_gap_byte_range(); + unchecked::read_at(self.data, range.start) } /// The “Windows ascender” metric. @@ -885,8 +939,8 @@ impl<'a> Os2<'a> { /// This should be used to specify the height above the baseline for a /// clipping region. pub fn us_win_ascent(&self) -> u16 { - let range = self.shape.us_win_ascent_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.us_win_ascent_byte_range(); + unchecked::read_at(self.data, range.start) } /// The “Windows descender” metric. @@ -894,67 +948,67 @@ impl<'a> Os2<'a> { /// This should be used to specify the vertical extent below the baseline /// for a clipping region. pub fn us_win_descent(&self) -> u16 { - let range = self.shape.us_win_descent_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.us_win_descent_byte_range(); + unchecked::read_at(self.data, range.start) } /// Code page character range bits 0-31. pub fn ul_code_page_range_1(&self) -> Option { - let range = self.shape.ul_code_page_range_1_byte_range()?; - Some(self.data.read_at(range.start).unwrap()) + let range = self.ul_code_page_range_1_byte_range()?; + Some(unchecked::read_at(self.data, range.start)) } /// Code page character range bits 32-63. pub fn ul_code_page_range_2(&self) -> Option { - let range = self.shape.ul_code_page_range_2_byte_range()?; - Some(self.data.read_at(range.start).unwrap()) + let range = self.ul_code_page_range_2_byte_range()?; + Some(unchecked::read_at(self.data, range.start)) } /// This metric specifies the distance between the baseline and the /// approximate height of non-ascending lowercase letters measured in /// FUnits. pub fn sx_height(&self) -> Option { - let range = self.shape.sx_height_byte_range()?; - Some(self.data.read_at(range.start).unwrap()) + let range = self.sx_height_byte_range()?; + Some(unchecked::read_at(self.data, range.start)) } /// This metric specifies the distance between the baseline and the /// approximate height of uppercase letters measured in FUnits. pub fn s_cap_height(&self) -> Option { - let range = self.shape.s_cap_height_byte_range()?; - Some(self.data.read_at(range.start).unwrap()) + let range = self.s_cap_height_byte_range()?; + Some(unchecked::read_at(self.data, range.start)) } /// This is the Unicode codepoint, in UTF-16 encoding, of a character that /// can be used for a default glyph. pub fn us_default_char(&self) -> Option { - let range = self.shape.us_default_char_byte_range()?; - Some(self.data.read_at(range.start).unwrap()) + let range = self.us_default_char_byte_range()?; + Some(unchecked::read_at(self.data, range.start)) } /// This is the Unicode codepoint, in UTF-16 encoding, of a character that /// can be used as a default break character. pub fn us_break_char(&self) -> Option { - let range = self.shape.us_break_char_byte_range()?; - Some(self.data.read_at(range.start).unwrap()) + let range = self.us_break_char_byte_range()?; + Some(unchecked::read_at(self.data, range.start)) } /// This field is used for fonts with multiple optical styles. pub fn us_max_context(&self) -> Option { - let range = self.shape.us_max_context_byte_range()?; - Some(self.data.read_at(range.start).unwrap()) + let range = self.us_max_context_byte_range()?; + Some(unchecked::read_at(self.data, range.start)) } /// This field is used for fonts with multiple optical styles. pub fn us_lower_optical_point_size(&self) -> Option { - let range = self.shape.us_lower_optical_point_size_byte_range()?; - Some(self.data.read_at(range.start).unwrap()) + let range = self.us_lower_optical_point_size_byte_range()?; + Some(unchecked::read_at(self.data, range.start)) } /// This field is used for fonts with multiple optical styles. pub fn us_upper_optical_point_size(&self) -> Option { - let range = self.shape.us_upper_optical_point_size_byte_range()?; - Some(self.data.read_at(range.start).unwrap()) + let range = self.us_upper_optical_point_size_byte_range()?; + Some(unchecked::read_at(self.data, range.start)) } } diff --git a/read-fonts/generated/generated_post.rs b/read-fonts/generated/generated_post.rs index af65dba1a..84b876af0 100644 --- a/read-fonts/generated/generated_post.rs +++ b/read-fonts/generated/generated_post.rs @@ -8,15 +8,45 @@ use crate::codegen_prelude::*; /// [post (PostScript)](https://docs.microsoft.com/en-us/typography/opentype/spec/post#header) table #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct PostMarker { - num_glyphs_byte_start: Option, - glyph_name_index_byte_start: Option, - glyph_name_index_byte_len: Option, - string_data_byte_start: Option, - string_data_byte_len: Option, +pub struct PostMarker; + +impl<'a> MinByteRange for Post<'a> { + fn min_byte_range(&self) -> Range { + 0..self.max_mem_type1_byte_range().end + } +} + +impl TopLevelTable for Post<'_> { + /// `post` + const TAG: Tag = Tag::new(b"post"); } -impl PostMarker { +impl<'a> FontRead<'a> for Post<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// [post (PostScript)](https://docs.microsoft.com/en-us/typography/opentype/spec/post#header) table +pub type Post<'a> = TableRef<'a, PostMarker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> Post<'a> { + fn glyph_name_index_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.num_glyphs().unwrap_or_default()) as usize) + .checked_mul(u16::RAW_BYTE_LEN) + .unwrap() + } + fn string_data_byte_len(&self, start: usize) -> usize { + let _ = start; + self.data.len().saturating_sub(start) + } + pub fn version_byte_range(&self) -> Range { let start = 0; start..start + Version16Dot16::RAW_BYTE_LEN @@ -63,104 +93,56 @@ impl PostMarker { } pub fn num_glyphs_byte_range(&self) -> Option> { - let start = self.num_glyphs_byte_start?; - Some(start..start + u16::RAW_BYTE_LEN) + if self.version().compatible((2u16, 0u16)) { + let start = self.max_mem_type1_byte_range().end; + Some(start..start + u16::RAW_BYTE_LEN) + } else { + None + } } pub fn glyph_name_index_byte_range(&self) -> Option> { - let start = self.glyph_name_index_byte_start?; - Some(start..start + self.glyph_name_index_byte_len?) + if self.version().compatible((2u16, 0u16)) { + let start = self + .num_glyphs_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| self.max_mem_type1_byte_range().end); + Some(start..start + self.glyph_name_index_byte_len(start)) + } else { + None + } } pub fn string_data_byte_range(&self) -> Option> { - let start = self.string_data_byte_start?; - Some(start..start + self.string_data_byte_len?) - } -} - -impl MinByteRange for PostMarker { - fn min_byte_range(&self) -> Range { - 0..self.max_mem_type1_byte_range().end - } -} - -impl TopLevelTable for Post<'_> { - /// `post` - const TAG: Tag = Tag::new(b"post"); -} - -impl<'a> FontRead<'a> for Post<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - let version: Version16Dot16 = cursor.read()?; - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - let num_glyphs_byte_start = version - .compatible((2u16, 0u16)) - .then(|| cursor.position()) - .transpose()?; - let num_glyphs = version - .compatible((2u16, 0u16)) - .then(|| cursor.read::()) - .transpose()? - .unwrap_or_default(); - let glyph_name_index_byte_start = version - .compatible((2u16, 0u16)) - .then(|| cursor.position()) - .transpose()?; - let glyph_name_index_byte_len = version.compatible((2u16, 0u16)).then_some( - (num_glyphs as usize) - .checked_mul(u16::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?, - ); - if let Some(value) = glyph_name_index_byte_len { - cursor.advance_by(value); - } - let string_data_byte_start = version - .compatible((2u16, 0u16)) - .then(|| cursor.position()) - .transpose()?; - let string_data_byte_len = version - .compatible((2u16, 0u16)) - .then_some(cursor.remaining_bytes()); - if let Some(value) = string_data_byte_len { - cursor.advance_by(value); + if self.version().compatible((2u16, 0u16)) { + let start = self + .glyph_name_index_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| { + self.num_glyphs_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| self.max_mem_type1_byte_range().end) + }); + Some(start..start + self.string_data_byte_len(start)) + } else { + None } - cursor.finish(PostMarker { - num_glyphs_byte_start, - glyph_name_index_byte_start, - glyph_name_index_byte_len, - string_data_byte_start, - string_data_byte_len, - }) } -} - -/// [post (PostScript)](https://docs.microsoft.com/en-us/typography/opentype/spec/post#header) table -pub type Post<'a> = TableRef<'a, PostMarker>; -#[allow(clippy::needless_lifetimes)] -impl<'a> Post<'a> { /// 0x00010000 for version 1.0 0x00020000 for version 2.0 /// 0x00025000 for version 2.5 (deprecated) 0x00030000 for version /// 3.0 pub fn version(&self) -> Version16Dot16 { - let range = self.shape.version_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.version_byte_range(); + unchecked::read_at(self.data, range.start) } /// Italic angle in counter-clockwise degrees from the vertical. /// Zero for upright text, negative for text that leans to the /// right (forward). pub fn italic_angle(&self) -> Fixed { - let range = self.shape.italic_angle_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.italic_angle_byte_range(); + unchecked::read_at(self.data, range.start) } /// This is the suggested distance of the top of the underline from @@ -171,8 +153,8 @@ impl<'a> Post<'a> { /// calculated by subtracting half the underlineThickness from the /// value of this field. pub fn underline_position(&self) -> FWord { - let range = self.shape.underline_position_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.underline_position_byte_range(); + unchecked::read_at(self.data, range.start) } /// Suggested values for the underline thickness. In general, the @@ -180,60 +162,60 @@ impl<'a> Post<'a> { /// underscore character (U+005F LOW LINE), and should also match /// the strikeout thickness, which is specified in the OS/2 table. pub fn underline_thickness(&self) -> FWord { - let range = self.shape.underline_thickness_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.underline_thickness_byte_range(); + unchecked::read_at(self.data, range.start) } /// Set to 0 if the font is proportionally spaced, non-zero if the /// font is not proportionally spaced (i.e. monospaced). pub fn is_fixed_pitch(&self) -> u32 { - let range = self.shape.is_fixed_pitch_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.is_fixed_pitch_byte_range(); + unchecked::read_at(self.data, range.start) } /// Minimum memory usage when an OpenType font is downloaded. pub fn min_mem_type42(&self) -> u32 { - let range = self.shape.min_mem_type42_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.min_mem_type42_byte_range(); + unchecked::read_at(self.data, range.start) } /// Maximum memory usage when an OpenType font is downloaded. pub fn max_mem_type42(&self) -> u32 { - let range = self.shape.max_mem_type42_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.max_mem_type42_byte_range(); + unchecked::read_at(self.data, range.start) } /// Minimum memory usage when an OpenType font is downloaded as a /// Type 1 font. pub fn min_mem_type1(&self) -> u32 { - let range = self.shape.min_mem_type1_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.min_mem_type1_byte_range(); + unchecked::read_at(self.data, range.start) } /// Maximum memory usage when an OpenType font is downloaded as a /// Type 1 font. pub fn max_mem_type1(&self) -> u32 { - let range = self.shape.max_mem_type1_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.max_mem_type1_byte_range(); + unchecked::read_at(self.data, range.start) } /// Number of glyphs (this should be the same as numGlyphs in /// 'maxp' table). pub fn num_glyphs(&self) -> Option { - let range = self.shape.num_glyphs_byte_range()?; - Some(self.data.read_at(range.start).unwrap()) + let range = self.num_glyphs_byte_range()?; + Some(unchecked::read_at(self.data, range.start)) } /// Array of indices into the string data. See below for details. pub fn glyph_name_index(&self) -> Option<&'a [BigEndian]> { - let range = self.shape.glyph_name_index_byte_range()?; - Some(self.data.read_array(range).unwrap()) + let range = self.glyph_name_index_byte_range()?; + Some(unchecked::read_array(self.data, range)) } /// Storage for the string data. pub fn string_data(&self) -> Option>> { - let range = self.shape.string_data_byte_range()?; - Some(VarLenArray::read(self.data.split_off(range.start).unwrap()).unwrap()) + let range = self.string_data_byte_range()?; + Some(VarLenArray::read(unchecked::split_off(self.data, range.start)).unwrap()) } } diff --git a/read-fonts/generated/generated_postscript.rs b/read-fonts/generated/generated_postscript.rs index f037a29fa..b92bac7cf 100644 --- a/read-fonts/generated/generated_postscript.rs +++ b/read-fonts/generated/generated_postscript.rs @@ -8,12 +8,43 @@ use crate::codegen_prelude::*; /// An array of variable-sized objects in a `CFF` table. #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct Index1Marker { - offsets_byte_len: usize, - data_byte_len: usize, +pub struct Index1Marker; + +impl<'a> MinByteRange for Index1<'a> { + fn min_byte_range(&self) -> Range { + 0..self.data_byte_range().end + } +} + +impl<'a> FontRead<'a> for Index1<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } } -impl Index1Marker { +/// An array of variable-sized objects in a `CFF` table. +pub type Index1<'a> = TableRef<'a, Index1Marker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> Index1<'a> { + fn offsets_byte_len(&self, start: usize) -> usize { + let _ = start; + (transforms::add_multiply(self.count(), 1_usize, self.off_size())) + .checked_mul(u8::RAW_BYTE_LEN) + .unwrap() + } + fn data_byte_len(&self, start: usize) -> usize { + let _ = start; + { + let remaining = self.data.len().saturating_sub(start); + remaining / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN + } + } + pub fn count_byte_range(&self) -> Range { let start = 0; start..start + u16::RAW_BYTE_LEN @@ -26,66 +57,36 @@ impl Index1Marker { pub fn offsets_byte_range(&self) -> Range { let start = self.off_size_byte_range().end; - start..start + self.offsets_byte_len + start..start + self.offsets_byte_len(start) } pub fn data_byte_range(&self) -> Range { let start = self.offsets_byte_range().end; - start..start + self.data_byte_len + start..start + self.data_byte_len(start) } -} -impl MinByteRange for Index1Marker { - fn min_byte_range(&self) -> Range { - 0..self.data_byte_range().end - } -} - -impl<'a> FontRead<'a> for Index1<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - let count: u16 = cursor.read()?; - let off_size: u8 = cursor.read()?; - let offsets_byte_len = (transforms::add_multiply(count, 1_usize, off_size)) - .checked_mul(u8::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(offsets_byte_len); - let data_byte_len = cursor.remaining_bytes() / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN; - cursor.advance_by(data_byte_len); - cursor.finish(Index1Marker { - offsets_byte_len, - data_byte_len, - }) - } -} - -/// An array of variable-sized objects in a `CFF` table. -pub type Index1<'a> = TableRef<'a, Index1Marker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> Index1<'a> { /// Number of objects stored in INDEX. pub fn count(&self) -> u16 { - let range = self.shape.count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Object array element size. pub fn off_size(&self) -> u8 { - let range = self.shape.off_size_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.off_size_byte_range(); + unchecked::read_at(self.data, range.start) } /// Bytes containing `count + 1` offsets each of `off_size`. pub fn offsets(&self) -> &'a [u8] { - let range = self.shape.offsets_byte_range(); - self.data.read_array(range).unwrap() + let range = self.offsets_byte_range(); + unchecked::read_array(self.data, range) } /// Array containing the object data. pub fn data(&self) -> &'a [u8] { - let range = self.shape.data_byte_range(); - self.data.read_array(range).unwrap() + let range = self.data_byte_range(); + unchecked::read_array(self.data, range) } } @@ -116,12 +117,43 @@ impl<'a> std::fmt::Debug for Index1<'a> { /// An array of variable-sized objects in a `CFF2` table. #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct Index2Marker { - offsets_byte_len: usize, - data_byte_len: usize, +pub struct Index2Marker; + +impl<'a> MinByteRange for Index2<'a> { + fn min_byte_range(&self) -> Range { + 0..self.data_byte_range().end + } +} + +impl<'a> FontRead<'a> for Index2<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } } -impl Index2Marker { +/// An array of variable-sized objects in a `CFF2` table. +pub type Index2<'a> = TableRef<'a, Index2Marker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> Index2<'a> { + fn offsets_byte_len(&self, start: usize) -> usize { + let _ = start; + (transforms::add_multiply(self.count(), 1_usize, self.off_size())) + .checked_mul(u8::RAW_BYTE_LEN) + .unwrap() + } + fn data_byte_len(&self, start: usize) -> usize { + let _ = start; + { + let remaining = self.data.len().saturating_sub(start); + remaining / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN + } + } + pub fn count_byte_range(&self) -> Range { let start = 0; start..start + u32::RAW_BYTE_LEN @@ -134,66 +166,36 @@ impl Index2Marker { pub fn offsets_byte_range(&self) -> Range { let start = self.off_size_byte_range().end; - start..start + self.offsets_byte_len + start..start + self.offsets_byte_len(start) } pub fn data_byte_range(&self) -> Range { let start = self.offsets_byte_range().end; - start..start + self.data_byte_len + start..start + self.data_byte_len(start) } -} -impl MinByteRange for Index2Marker { - fn min_byte_range(&self) -> Range { - 0..self.data_byte_range().end - } -} - -impl<'a> FontRead<'a> for Index2<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - let count: u32 = cursor.read()?; - let off_size: u8 = cursor.read()?; - let offsets_byte_len = (transforms::add_multiply(count, 1_usize, off_size)) - .checked_mul(u8::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(offsets_byte_len); - let data_byte_len = cursor.remaining_bytes() / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN; - cursor.advance_by(data_byte_len); - cursor.finish(Index2Marker { - offsets_byte_len, - data_byte_len, - }) - } -} - -/// An array of variable-sized objects in a `CFF2` table. -pub type Index2<'a> = TableRef<'a, Index2Marker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> Index2<'a> { /// Number of objects stored in INDEX. pub fn count(&self) -> u32 { - let range = self.shape.count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Object array element size. pub fn off_size(&self) -> u8 { - let range = self.shape.off_size_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.off_size_byte_range(); + unchecked::read_at(self.data, range.start) } /// Bytes containing `count + 1` offsets each of `off_size`. pub fn offsets(&self) -> &'a [u8] { - let range = self.shape.offsets_byte_range(); - self.data.read_array(range).unwrap() + let range = self.offsets_byte_range(); + unchecked::read_array(self.data, range) } /// Array containing the object data. pub fn data(&self) -> &'a [u8] { - let range = self.shape.data_byte_range(); - self.data.read_array(range).unwrap() + let range = self.data_byte_range(); + unchecked::read_array(self.data, range) } } @@ -306,23 +308,9 @@ impl Format for FdSelectFormat0Marker { /// FdSelect format 0. #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct FdSelectFormat0Marker { - fds_byte_len: usize, -} - -impl FdSelectFormat0Marker { - pub fn format_byte_range(&self) -> Range { - let start = 0; - start..start + u8::RAW_BYTE_LEN - } +pub struct FdSelectFormat0Marker; - pub fn fds_byte_range(&self) -> Range { - let start = self.format_byte_range().end; - start..start + self.fds_byte_len - } -} - -impl MinByteRange for FdSelectFormat0Marker { +impl<'a> MinByteRange for FdSelectFormat0<'a> { fn min_byte_range(&self) -> Range { 0..self.fds_byte_range().end } @@ -330,29 +318,47 @@ impl MinByteRange for FdSelectFormat0Marker { impl<'a> FontRead<'a> for FdSelectFormat0<'a> { fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - let fds_byte_len = cursor.remaining_bytes() / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN; - cursor.advance_by(fds_byte_len); - cursor.finish(FdSelectFormat0Marker { fds_byte_len }) + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) } } /// FdSelect format 0. -pub type FdSelectFormat0<'a> = TableRef<'a, FdSelectFormat0Marker>; +pub type FdSelectFormat0<'a> = TableRef<'a, FdSelectFormat0Marker, ()>; #[allow(clippy::needless_lifetimes)] impl<'a> FdSelectFormat0<'a> { + fn fds_byte_len(&self, start: usize) -> usize { + let _ = start; + { + let remaining = self.data.len().saturating_sub(start); + remaining / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN + } + } + + pub fn format_byte_range(&self) -> Range { + let start = 0; + start..start + u8::RAW_BYTE_LEN + } + + pub fn fds_byte_range(&self) -> Range { + let start = self.format_byte_range().end; + start..start + self.fds_byte_len(start) + } + /// Format = 0. pub fn format(&self) -> u8 { - let range = self.shape.format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.format_byte_range(); + unchecked::read_at(self.data, range.start) } /// FD selector array (one entry for each glyph). pub fn fds(&self) -> &'a [u8] { - let range = self.shape.fds_byte_range(); - self.data.read_array(range).unwrap() + let range = self.fds_byte_range(); + unchecked::read_array(self.data, range) } } @@ -385,11 +391,36 @@ impl Format for FdSelectFormat3Marker { /// FdSelect format 3. #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct FdSelectFormat3Marker { - ranges_byte_len: usize, +pub struct FdSelectFormat3Marker; + +impl<'a> MinByteRange for FdSelectFormat3<'a> { + fn min_byte_range(&self) -> Range { + 0..self.sentinel_byte_range().end + } +} + +impl<'a> FontRead<'a> for FdSelectFormat3<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } } -impl FdSelectFormat3Marker { +/// FdSelect format 3. +pub type FdSelectFormat3<'a> = TableRef<'a, FdSelectFormat3Marker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> FdSelectFormat3<'a> { + fn ranges_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.n_ranges()) as usize) + .checked_mul(FdSelectRange3::RAW_BYTE_LEN) + .unwrap() + } + pub fn format_byte_range(&self) -> Range { let start = 0; start..start + u8::RAW_BYTE_LEN @@ -402,62 +433,36 @@ impl FdSelectFormat3Marker { pub fn ranges_byte_range(&self) -> Range { let start = self.n_ranges_byte_range().end; - start..start + self.ranges_byte_len + start..start + self.ranges_byte_len(start) } pub fn sentinel_byte_range(&self) -> Range { let start = self.ranges_byte_range().end; start..start + u16::RAW_BYTE_LEN } -} - -impl MinByteRange for FdSelectFormat3Marker { - fn min_byte_range(&self) -> Range { - 0..self.sentinel_byte_range().end - } -} - -impl<'a> FontRead<'a> for FdSelectFormat3<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - let n_ranges: u16 = cursor.read()?; - let ranges_byte_len = (n_ranges as usize) - .checked_mul(FdSelectRange3::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(ranges_byte_len); - cursor.advance::(); - cursor.finish(FdSelectFormat3Marker { ranges_byte_len }) - } -} -/// FdSelect format 3. -pub type FdSelectFormat3<'a> = TableRef<'a, FdSelectFormat3Marker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> FdSelectFormat3<'a> { /// Format = 3. pub fn format(&self) -> u8 { - let range = self.shape.format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Number of ranges. pub fn n_ranges(&self) -> u16 { - let range = self.shape.n_ranges_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.n_ranges_byte_range(); + unchecked::read_at(self.data, range.start) } /// Range3 array. pub fn ranges(&self) -> &'a [FdSelectRange3] { - let range = self.shape.ranges_byte_range(); - self.data.read_array(range).unwrap() + let range = self.ranges_byte_range(); + unchecked::read_array(self.data, range) } /// Sentinel GID. Set equal to the number of glyphs in the font. pub fn sentinel(&self) -> u16 { - let range = self.shape.sentinel_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.sentinel_byte_range(); + unchecked::read_at(self.data, range.start) } } @@ -541,11 +546,36 @@ impl Format for FdSelectFormat4Marker { /// FdSelect format 4. #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct FdSelectFormat4Marker { - ranges_byte_len: usize, +pub struct FdSelectFormat4Marker; + +impl<'a> MinByteRange for FdSelectFormat4<'a> { + fn min_byte_range(&self) -> Range { + 0..self.sentinel_byte_range().end + } } -impl FdSelectFormat4Marker { +impl<'a> FontRead<'a> for FdSelectFormat4<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// FdSelect format 4. +pub type FdSelectFormat4<'a> = TableRef<'a, FdSelectFormat4Marker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> FdSelectFormat4<'a> { + fn ranges_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.n_ranges()) as usize) + .checked_mul(FdSelectRange4::RAW_BYTE_LEN) + .unwrap() + } + pub fn format_byte_range(&self) -> Range { let start = 0; start..start + u8::RAW_BYTE_LEN @@ -558,62 +588,36 @@ impl FdSelectFormat4Marker { pub fn ranges_byte_range(&self) -> Range { let start = self.n_ranges_byte_range().end; - start..start + self.ranges_byte_len + start..start + self.ranges_byte_len(start) } pub fn sentinel_byte_range(&self) -> Range { let start = self.ranges_byte_range().end; start..start + u32::RAW_BYTE_LEN } -} -impl MinByteRange for FdSelectFormat4Marker { - fn min_byte_range(&self) -> Range { - 0..self.sentinel_byte_range().end - } -} - -impl<'a> FontRead<'a> for FdSelectFormat4<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - let n_ranges: u32 = cursor.read()?; - let ranges_byte_len = (n_ranges as usize) - .checked_mul(FdSelectRange4::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(ranges_byte_len); - cursor.advance::(); - cursor.finish(FdSelectFormat4Marker { ranges_byte_len }) - } -} - -/// FdSelect format 4. -pub type FdSelectFormat4<'a> = TableRef<'a, FdSelectFormat4Marker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> FdSelectFormat4<'a> { /// Format = 4. pub fn format(&self) -> u8 { - let range = self.shape.format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Number of ranges. pub fn n_ranges(&self) -> u32 { - let range = self.shape.n_ranges_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.n_ranges_byte_range(); + unchecked::read_at(self.data, range.start) } /// Range4 array. pub fn ranges(&self) -> &'a [FdSelectRange4] { - let range = self.shape.ranges_byte_range(); - self.data.read_array(range).unwrap() + let range = self.ranges_byte_range(); + unchecked::read_array(self.data, range) } /// Sentinel GID. Set equal to the number of glyphs in the font. pub fn sentinel(&self) -> u32 { - let range = self.shape.sentinel_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.sentinel_byte_range(); + unchecked::read_at(self.data, range.start) } } @@ -775,23 +779,9 @@ impl Format for CharsetFormat0Marker { /// Charset format 0. #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct CharsetFormat0Marker { - glyph_byte_len: usize, -} - -impl CharsetFormat0Marker { - pub fn format_byte_range(&self) -> Range { - let start = 0; - start..start + u8::RAW_BYTE_LEN - } +pub struct CharsetFormat0Marker; - pub fn glyph_byte_range(&self) -> Range { - let start = self.format_byte_range().end; - start..start + self.glyph_byte_len - } -} - -impl MinByteRange for CharsetFormat0Marker { +impl<'a> MinByteRange for CharsetFormat0<'a> { fn min_byte_range(&self) -> Range { 0..self.glyph_byte_range().end } @@ -799,29 +789,47 @@ impl MinByteRange for CharsetFormat0Marker { impl<'a> FontRead<'a> for CharsetFormat0<'a> { fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - let glyph_byte_len = cursor.remaining_bytes() / u16::RAW_BYTE_LEN * u16::RAW_BYTE_LEN; - cursor.advance_by(glyph_byte_len); - cursor.finish(CharsetFormat0Marker { glyph_byte_len }) + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) } } /// Charset format 0. -pub type CharsetFormat0<'a> = TableRef<'a, CharsetFormat0Marker>; +pub type CharsetFormat0<'a> = TableRef<'a, CharsetFormat0Marker, ()>; #[allow(clippy::needless_lifetimes)] impl<'a> CharsetFormat0<'a> { + fn glyph_byte_len(&self, start: usize) -> usize { + let _ = start; + { + let remaining = self.data.len().saturating_sub(start); + remaining / u16::RAW_BYTE_LEN * u16::RAW_BYTE_LEN + } + } + + pub fn format_byte_range(&self) -> Range { + let start = 0; + start..start + u8::RAW_BYTE_LEN + } + + pub fn glyph_byte_range(&self) -> Range { + let start = self.format_byte_range().end; + start..start + self.glyph_byte_len(start) + } + /// Format; =0 pub fn format(&self) -> u8 { - let range = self.shape.format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Glyph name array. pub fn glyph(&self) -> &'a [BigEndian] { - let range = self.shape.glyph_byte_range(); - self.data.read_array(range).unwrap() + let range = self.glyph_byte_range(); + unchecked::read_array(self.data, range) } } @@ -854,23 +862,9 @@ impl Format for CharsetFormat1Marker { /// Charset format 1. #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct CharsetFormat1Marker { - ranges_byte_len: usize, -} - -impl CharsetFormat1Marker { - pub fn format_byte_range(&self) -> Range { - let start = 0; - start..start + u8::RAW_BYTE_LEN - } - - pub fn ranges_byte_range(&self) -> Range { - let start = self.format_byte_range().end; - start..start + self.ranges_byte_len - } -} +pub struct CharsetFormat1Marker; -impl MinByteRange for CharsetFormat1Marker { +impl<'a> MinByteRange for CharsetFormat1<'a> { fn min_byte_range(&self) -> Range { 0..self.ranges_byte_range().end } @@ -878,30 +872,47 @@ impl MinByteRange for CharsetFormat1Marker { impl<'a> FontRead<'a> for CharsetFormat1<'a> { fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - let ranges_byte_len = - cursor.remaining_bytes() / CharsetRange1::RAW_BYTE_LEN * CharsetRange1::RAW_BYTE_LEN; - cursor.advance_by(ranges_byte_len); - cursor.finish(CharsetFormat1Marker { ranges_byte_len }) + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) } } /// Charset format 1. -pub type CharsetFormat1<'a> = TableRef<'a, CharsetFormat1Marker>; +pub type CharsetFormat1<'a> = TableRef<'a, CharsetFormat1Marker, ()>; #[allow(clippy::needless_lifetimes)] impl<'a> CharsetFormat1<'a> { + fn ranges_byte_len(&self, start: usize) -> usize { + let _ = start; + { + let remaining = self.data.len().saturating_sub(start); + remaining / CharsetRange1::RAW_BYTE_LEN * CharsetRange1::RAW_BYTE_LEN + } + } + + pub fn format_byte_range(&self) -> Range { + let start = 0; + start..start + u8::RAW_BYTE_LEN + } + + pub fn ranges_byte_range(&self) -> Range { + let start = self.format_byte_range().end; + start..start + self.ranges_byte_len(start) + } + /// Format; =1 pub fn format(&self) -> u8 { - let range = self.shape.format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Range1 array. pub fn ranges(&self) -> &'a [CharsetRange1] { - let range = self.shape.ranges_byte_range(); - self.data.read_array(range).unwrap() + let range = self.ranges_byte_range(); + unchecked::read_array(self.data, range) } } @@ -983,23 +994,9 @@ impl Format for CharsetFormat2Marker { /// Charset format 2. #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct CharsetFormat2Marker { - ranges_byte_len: usize, -} - -impl CharsetFormat2Marker { - pub fn format_byte_range(&self) -> Range { - let start = 0; - start..start + u8::RAW_BYTE_LEN - } - - pub fn ranges_byte_range(&self) -> Range { - let start = self.format_byte_range().end; - start..start + self.ranges_byte_len - } -} +pub struct CharsetFormat2Marker; -impl MinByteRange for CharsetFormat2Marker { +impl<'a> MinByteRange for CharsetFormat2<'a> { fn min_byte_range(&self) -> Range { 0..self.ranges_byte_range().end } @@ -1007,30 +1004,47 @@ impl MinByteRange for CharsetFormat2Marker { impl<'a> FontRead<'a> for CharsetFormat2<'a> { fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - let ranges_byte_len = - cursor.remaining_bytes() / CharsetRange2::RAW_BYTE_LEN * CharsetRange2::RAW_BYTE_LEN; - cursor.advance_by(ranges_byte_len); - cursor.finish(CharsetFormat2Marker { ranges_byte_len }) + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) } } /// Charset format 2. -pub type CharsetFormat2<'a> = TableRef<'a, CharsetFormat2Marker>; +pub type CharsetFormat2<'a> = TableRef<'a, CharsetFormat2Marker, ()>; #[allow(clippy::needless_lifetimes)] impl<'a> CharsetFormat2<'a> { + fn ranges_byte_len(&self, start: usize) -> usize { + let _ = start; + { + let remaining = self.data.len().saturating_sub(start); + remaining / CharsetRange2::RAW_BYTE_LEN * CharsetRange2::RAW_BYTE_LEN + } + } + + pub fn format_byte_range(&self) -> Range { + let start = 0; + start..start + u8::RAW_BYTE_LEN + } + + pub fn ranges_byte_range(&self) -> Range { + let start = self.format_byte_range().end; + start..start + self.ranges_byte_len(start) + } + /// Format; =2 pub fn format(&self) -> u8 { - let range = self.shape.format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Range2 array. pub fn ranges(&self) -> &'a [CharsetRange2] { - let range = self.shape.ranges_byte_range(); - self.data.read_array(range).unwrap() + let range = self.ranges_byte_range(); + unchecked::read_array(self.data, range) } } diff --git a/read-fonts/generated/generated_sbix.rs b/read-fonts/generated/generated_sbix.rs index f4a4f1d72..48a73613d 100644 --- a/read-fonts/generated/generated_sbix.rs +++ b/read-fonts/generated/generated_sbix.rs @@ -316,34 +316,9 @@ impl<'a> From for FieldType<'a> { /// The [sbix (Standard Bitmap Graphics)](https://docs.microsoft.com/en-us/typography/opentype/spec/sbix) table #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct SbixMarker { - num_glyphs: u16, - strike_offsets_byte_len: usize, -} - -impl SbixMarker { - pub fn version_byte_range(&self) -> Range { - let start = 0; - start..start + u16::RAW_BYTE_LEN - } +pub struct SbixMarker; - pub fn flags_byte_range(&self) -> Range { - let start = self.version_byte_range().end; - start..start + HeaderFlags::RAW_BYTE_LEN - } - - pub fn num_strikes_byte_range(&self) -> Range { - let start = self.flags_byte_range().end; - start..start + u32::RAW_BYTE_LEN - } - - pub fn strike_offsets_byte_range(&self) -> Range { - let start = self.num_strikes_byte_range().end; - start..start + self.strike_offsets_byte_len - } -} - -impl MinByteRange for SbixMarker { +impl<'a> MinByteRange for Sbix<'a> { fn min_byte_range(&self) -> Range { 0..self.strike_offsets_byte_range().end } @@ -360,18 +335,11 @@ impl ReadArgs for Sbix<'_> { impl<'a> FontReadWithArgs<'a> for Sbix<'a> { fn read_with_args(data: FontData<'a>, args: &u16) -> Result { - let num_glyphs = *args; - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - let num_strikes: u32 = cursor.read()?; - let strike_offsets_byte_len = (num_strikes as usize) - .checked_mul(Offset32::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(strike_offsets_byte_len); - cursor.finish(SbixMarker { - num_glyphs, - strike_offsets_byte_len, + let args = *args; + Ok(TableRef { + args, + data, + _marker: std::marker::PhantomData, }) } } @@ -388,34 +356,61 @@ impl<'a> Sbix<'a> { } /// The [sbix (Standard Bitmap Graphics)](https://docs.microsoft.com/en-us/typography/opentype/spec/sbix) table -pub type Sbix<'a> = TableRef<'a, SbixMarker>; +pub type Sbix<'a> = TableRef<'a, SbixMarker, u16>; #[allow(clippy::needless_lifetimes)] impl<'a> Sbix<'a> { + fn strike_offsets_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.num_strikes()) as usize) + .checked_mul(Offset32::RAW_BYTE_LEN) + .unwrap() + } + + pub fn version_byte_range(&self) -> Range { + let start = 0; + start..start + u16::RAW_BYTE_LEN + } + + pub fn flags_byte_range(&self) -> Range { + let start = self.version_byte_range().end; + start..start + HeaderFlags::RAW_BYTE_LEN + } + + pub fn num_strikes_byte_range(&self) -> Range { + let start = self.flags_byte_range().end; + start..start + u32::RAW_BYTE_LEN + } + + pub fn strike_offsets_byte_range(&self) -> Range { + let start = self.num_strikes_byte_range().end; + start..start + self.strike_offsets_byte_len(start) + } + /// Table version number — set to 1. pub fn version(&self) -> u16 { - let range = self.shape.version_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.version_byte_range(); + unchecked::read_at(self.data, range.start) } /// Bit 0: Set to 1. /// Bit 1: Draw outlines. /// Bits 2 to 15: reserved (set to 0). pub fn flags(&self) -> HeaderFlags { - let range = self.shape.flags_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.flags_byte_range(); + unchecked::read_at(self.data, range.start) } /// Number of bitmap strikes. pub fn num_strikes(&self) -> u32 { - let range = self.shape.num_strikes_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.num_strikes_byte_range(); + unchecked::read_at(self.data, range.start) } /// Offsets from the beginning of the 'sbix' table to data for each individual bitmap strike. pub fn strike_offsets(&self) -> &'a [BigEndian] { - let range = self.shape.strike_offsets_byte_range(); - self.data.read_array(range).unwrap() + let range = self.strike_offsets_byte_range(); + unchecked::read_array(self.data, range) } /// A dynamically resolving wrapper for [`strike_offsets`][Self::strike_offsets]. @@ -427,7 +422,7 @@ impl<'a> Sbix<'a> { } pub(crate) fn num_glyphs(&self) -> u16 { - self.shape.num_glyphs + self.args } } @@ -472,28 +467,9 @@ impl<'a> std::fmt::Debug for Sbix<'a> { /// [Strike](https://learn.microsoft.com/en-us/typography/opentype/spec/sbix#strikes) header table #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct StrikeMarker { - glyph_data_offsets_byte_len: usize, -} - -impl StrikeMarker { - pub fn ppem_byte_range(&self) -> Range { - let start = 0; - start..start + u16::RAW_BYTE_LEN - } +pub struct StrikeMarker; - pub fn ppi_byte_range(&self) -> Range { - let start = self.ppem_byte_range().end; - start..start + u16::RAW_BYTE_LEN - } - - pub fn glyph_data_offsets_byte_range(&self) -> Range { - let start = self.ppi_byte_range().end; - start..start + self.glyph_data_offsets_byte_len - } -} - -impl MinByteRange for StrikeMarker { +impl<'a> MinByteRange for Strike<'a> { fn min_byte_range(&self) -> Range { 0..self.glyph_data_offsets_byte_range().end } @@ -505,16 +481,11 @@ impl ReadArgs for Strike<'_> { impl<'a> FontReadWithArgs<'a> for Strike<'a> { fn read_with_args(data: FontData<'a>, args: &u16) -> Result { - let num_glyphs = *args; - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - let glyph_data_offsets_byte_len = (transforms::add(num_glyphs, 1_usize)) - .checked_mul(u32::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(glyph_data_offsets_byte_len); - cursor.finish(StrikeMarker { - glyph_data_offsets_byte_len, + let args = *args; + Ok(TableRef { + args, + data, + _marker: std::marker::PhantomData, }) } } @@ -531,26 +502,52 @@ impl<'a> Strike<'a> { } /// [Strike](https://learn.microsoft.com/en-us/typography/opentype/spec/sbix#strikes) header table -pub type Strike<'a> = TableRef<'a, StrikeMarker>; +pub type Strike<'a> = TableRef<'a, StrikeMarker, u16>; #[allow(clippy::needless_lifetimes)] impl<'a> Strike<'a> { + fn glyph_data_offsets_byte_len(&self, start: usize) -> usize { + let _ = start; + (transforms::add(self.args, 1_usize)) + .checked_mul(u32::RAW_BYTE_LEN) + .unwrap() + } + + pub fn ppem_byte_range(&self) -> Range { + let start = 0; + start..start + u16::RAW_BYTE_LEN + } + + pub fn ppi_byte_range(&self) -> Range { + let start = self.ppem_byte_range().end; + start..start + u16::RAW_BYTE_LEN + } + + pub fn glyph_data_offsets_byte_range(&self) -> Range { + let start = self.ppi_byte_range().end; + start..start + self.glyph_data_offsets_byte_len(start) + } + /// The PPEM size for which this strike was designed. pub fn ppem(&self) -> u16 { - let range = self.shape.ppem_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.ppem_byte_range(); + unchecked::read_at(self.data, range.start) } /// The device pixel density (in PPI) for which this strike was designed. (E.g., 96 PPI, 192 PPI.) pub fn ppi(&self) -> u16 { - let range = self.shape.ppi_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.ppi_byte_range(); + unchecked::read_at(self.data, range.start) } /// Offset from the beginning of the strike data header to bitmap data for an individual glyph ID. pub fn glyph_data_offsets(&self) -> &'a [BigEndian] { - let range = self.shape.glyph_data_offsets_byte_range(); - self.data.read_array(range).unwrap() + let range = self.glyph_data_offsets_byte_range(); + unchecked::read_array(self.data, range) + } + + pub(crate) fn num_glyphs(&self) -> u16 { + self.args } } @@ -580,11 +577,37 @@ impl<'a> std::fmt::Debug for Strike<'a> { /// [Glyph data](https://learn.microsoft.com/en-us/typography/opentype/spec/sbix#glyph-data) table #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct GlyphDataMarker { - data_byte_len: usize, +pub struct GlyphDataMarker; + +impl<'a> MinByteRange for GlyphData<'a> { + fn min_byte_range(&self) -> Range { + 0..self.data_byte_range().end + } } -impl GlyphDataMarker { +impl<'a> FontRead<'a> for GlyphData<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// [Glyph data](https://learn.microsoft.com/en-us/typography/opentype/spec/sbix#glyph-data) table +pub type GlyphData<'a> = TableRef<'a, GlyphDataMarker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> GlyphData<'a> { + fn data_byte_len(&self, start: usize) -> usize { + let _ = start; + { + let remaining = self.data.len().saturating_sub(start); + remaining / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN + } + } + pub fn origin_offset_x_byte_range(&self) -> Range { let start = 0; start..start + i16::RAW_BYTE_LEN @@ -602,55 +625,31 @@ impl GlyphDataMarker { pub fn data_byte_range(&self) -> Range { let start = self.graphic_type_byte_range().end; - start..start + self.data_byte_len - } -} - -impl MinByteRange for GlyphDataMarker { - fn min_byte_range(&self) -> Range { - 0..self.data_byte_range().end - } -} - -impl<'a> FontRead<'a> for GlyphData<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - let data_byte_len = cursor.remaining_bytes() / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN; - cursor.advance_by(data_byte_len); - cursor.finish(GlyphDataMarker { data_byte_len }) + start..start + self.data_byte_len(start) } -} -/// [Glyph data](https://learn.microsoft.com/en-us/typography/opentype/spec/sbix#glyph-data) table -pub type GlyphData<'a> = TableRef<'a, GlyphDataMarker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> GlyphData<'a> { /// The horizontal (x-axis) position of the left edge of the bitmap graphic in relation to the glyph design space origin. pub fn origin_offset_x(&self) -> i16 { - let range = self.shape.origin_offset_x_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.origin_offset_x_byte_range(); + unchecked::read_at(self.data, range.start) } /// The vertical (y-axis) position of the bottom edge of the bitmap graphic in relation to the glyph design space origin. pub fn origin_offset_y(&self) -> i16 { - let range = self.shape.origin_offset_y_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.origin_offset_y_byte_range(); + unchecked::read_at(self.data, range.start) } /// Indicates the format of the embedded graphic data: one of 'jpg ', 'png ' or 'tiff', or the special format 'dupe'. pub fn graphic_type(&self) -> Tag { - let range = self.shape.graphic_type_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.graphic_type_byte_range(); + unchecked::read_at(self.data, range.start) } /// The actual embedded graphic data. The total length is inferred from sequential entries in the glyphDataOffsets array and the fixed size (8 bytes) of the preceding fields. pub fn data(&self) -> &'a [u8] { - let range = self.shape.data_byte_range(); - self.data.read_array(range).unwrap() + let range = self.data_byte_range(); + unchecked::read_array(self.data, range) } } diff --git a/read-fonts/generated/generated_stat.rs b/read-fonts/generated/generated_stat.rs index 5b54a2663..d0af27780 100644 --- a/read-fonts/generated/generated_stat.rs +++ b/read-fonts/generated/generated_stat.rs @@ -8,11 +8,34 @@ use crate::codegen_prelude::*; /// [STAT](https://docs.microsoft.com/en-us/typography/opentype/spec/stat) (Style Attributes Table) #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct StatMarker { - elided_fallback_name_id_byte_start: Option, +pub struct StatMarker; + +impl<'a> MinByteRange for Stat<'a> { + fn min_byte_range(&self) -> Range { + 0..self.offset_to_axis_value_offsets_byte_range().end + } +} + +impl TopLevelTable for Stat<'_> { + /// `STAT` + const TAG: Tag = Tag::new(b"STAT"); +} + +impl<'a> FontRead<'a> for Stat<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } } -impl StatMarker { +/// [STAT](https://docs.microsoft.com/en-us/typography/opentype/spec/stat) (Style Attributes Table) +pub type Stat<'a> = TableRef<'a, StatMarker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> Stat<'a> { pub fn version_byte_range(&self) -> Range { let start = 0; start..start + MajorMinor::RAW_BYTE_LEN @@ -44,59 +67,24 @@ impl StatMarker { } pub fn elided_fallback_name_id_byte_range(&self) -> Option> { - let start = self.elided_fallback_name_id_byte_start?; - Some(start..start + NameId::RAW_BYTE_LEN) - } -} - -impl MinByteRange for StatMarker { - fn min_byte_range(&self) -> Range { - 0..self.offset_to_axis_value_offsets_byte_range().end - } -} - -impl TopLevelTable for Stat<'_> { - /// `STAT` - const TAG: Tag = Tag::new(b"STAT"); -} - -impl<'a> FontRead<'a> for Stat<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - let version: MajorMinor = cursor.read()?; - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - let elided_fallback_name_id_byte_start = version - .compatible((1u16, 1u16)) - .then(|| cursor.position()) - .transpose()?; - version - .compatible((1u16, 1u16)) - .then(|| cursor.advance::()); - cursor.finish(StatMarker { - elided_fallback_name_id_byte_start, - }) + if self.version().compatible((1u16, 1u16)) { + let start = self.offset_to_axis_value_offsets_byte_range().end; + Some(start..start + NameId::RAW_BYTE_LEN) + } else { + None + } } -} - -/// [STAT](https://docs.microsoft.com/en-us/typography/opentype/spec/stat) (Style Attributes Table) -pub type Stat<'a> = TableRef<'a, StatMarker>; -#[allow(clippy::needless_lifetimes)] -impl<'a> Stat<'a> { /// Major/minor version number. Set to 1.2 for new fonts. pub fn version(&self) -> MajorMinor { - let range = self.shape.version_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.version_byte_range(); + unchecked::read_at(self.data, range.start) } /// The size in bytes of each axis record. pub fn design_axis_size(&self) -> u16 { - let range = self.shape.design_axis_size_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.design_axis_size_byte_range(); + unchecked::read_at(self.data, range.start) } /// The number of axis records. In a font with an 'fvar' table, @@ -104,8 +92,8 @@ impl<'a> Stat<'a> { /// in the 'fvar' table. In all fonts, must be greater than zero if /// axisValueCount is greater than zero. pub fn design_axis_count(&self) -> u16 { - let range = self.shape.design_axis_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.design_axis_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Offset in bytes from the beginning of the STAT table to the @@ -113,8 +101,8 @@ impl<'a> Stat<'a> { /// to zero; if designAxisCount is greater than zero, must be /// greater than zero. pub fn design_axes_offset(&self) -> Offset32 { - let range = self.shape.design_axes_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.design_axes_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`design_axes_offset`][Self::design_axes_offset]. @@ -126,8 +114,8 @@ impl<'a> Stat<'a> { /// The number of axis value tables. pub fn axis_value_count(&self) -> u16 { - let range = self.shape.axis_value_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.axis_value_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Offset in bytes from the beginning of the STAT table to the @@ -135,8 +123,8 @@ impl<'a> Stat<'a> { /// is zero, set to zero; if axisValueCount is greater than zero, /// must be greater than zero. pub fn offset_to_axis_value_offsets(&self) -> Nullable { - let range = self.shape.offset_to_axis_value_offsets_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.offset_to_axis_value_offsets_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`offset_to_axis_value_offsets`][Self::offset_to_axis_value_offsets]. @@ -151,8 +139,8 @@ impl<'a> Stat<'a> { /// particular font model produces a subfamily name containing only /// elidable elements. pub fn elided_fallback_name_id(&self) -> Option { - let range = self.shape.elided_fallback_name_id_byte_range()?; - Some(self.data.read_at(range.start).unwrap()) + let range = self.elided_fallback_name_id_byte_range()?; + Some(unchecked::read_at(self.data, range.start)) } } @@ -260,18 +248,9 @@ impl<'a> SomeRecord<'a> for AxisRecord { /// An array of [AxisValue] tables. #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct AxisValueArrayMarker { - axis_value_offsets_byte_len: usize, -} +pub struct AxisValueArrayMarker; -impl AxisValueArrayMarker { - pub fn axis_value_offsets_byte_range(&self) -> Range { - let start = 0; - start..start + self.axis_value_offsets_byte_len - } -} - -impl MinByteRange for AxisValueArrayMarker { +impl<'a> MinByteRange for AxisValueArray<'a> { fn min_byte_range(&self) -> Range { 0..self.axis_value_offsets_byte_range().end } @@ -283,14 +262,11 @@ impl ReadArgs for AxisValueArray<'_> { impl<'a> FontReadWithArgs<'a> for AxisValueArray<'a> { fn read_with_args(data: FontData<'a>, args: &u16) -> Result { - let axis_value_count = *args; - let mut cursor = data.cursor(); - let axis_value_offsets_byte_len = (axis_value_count as usize) - .checked_mul(Offset16::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(axis_value_offsets_byte_len); - cursor.finish(AxisValueArrayMarker { - axis_value_offsets_byte_len, + let args = *args; + Ok(TableRef { + args, + data, + _marker: std::marker::PhantomData, }) } } @@ -307,15 +283,27 @@ impl<'a> AxisValueArray<'a> { } /// An array of [AxisValue] tables. -pub type AxisValueArray<'a> = TableRef<'a, AxisValueArrayMarker>; +pub type AxisValueArray<'a> = TableRef<'a, AxisValueArrayMarker, u16>; #[allow(clippy::needless_lifetimes)] impl<'a> AxisValueArray<'a> { + fn axis_value_offsets_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.args) as usize) + .checked_mul(Offset16::RAW_BYTE_LEN) + .unwrap() + } + + pub fn axis_value_offsets_byte_range(&self) -> Range { + let start = 0; + start..start + self.axis_value_offsets_byte_len(start) + } + /// Array of offsets to axis value tables, in bytes from the start /// of the axis value offsets array. pub fn axis_value_offsets(&self) -> &'a [BigEndian] { - let range = self.shape.axis_value_offsets_byte_range(); - self.data.read_array(range).unwrap() + let range = self.axis_value_offsets_byte_range(); + unchecked::read_array(self.data, range) } /// A dynamically resolving wrapper for [`axis_value_offsets`][Self::axis_value_offsets]. @@ -324,6 +312,10 @@ impl<'a> AxisValueArray<'a> { let offsets = self.axis_value_offsets(); ArrayOfOffsets::new(offsets, data, ()) } + + pub(crate) fn axis_value_count(&self) -> u16 { + self.args + } } #[cfg(feature = "experimental_traverse")] @@ -472,9 +464,29 @@ impl Format for AxisValueFormat1Marker { /// [Axis value table format 1](https://docs.microsoft.com/en-us/typography/opentype/spec/stat#axis-value-table-format-1) #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct AxisValueFormat1Marker {} +pub struct AxisValueFormat1Marker; + +impl<'a> MinByteRange for AxisValueFormat1<'a> { + fn min_byte_range(&self) -> Range { + 0..self.value_byte_range().end + } +} -impl AxisValueFormat1Marker { +impl<'a> FontRead<'a> for AxisValueFormat1<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// [Axis value table format 1](https://docs.microsoft.com/en-us/typography/opentype/spec/stat#axis-value-table-format-1) +pub type AxisValueFormat1<'a> = TableRef<'a, AxisValueFormat1Marker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> AxisValueFormat1<'a> { pub fn format_byte_range(&self) -> Range { let start = 0; start..start + u16::RAW_BYTE_LEN @@ -499,62 +511,38 @@ impl AxisValueFormat1Marker { let start = self.value_name_id_byte_range().end; start..start + Fixed::RAW_BYTE_LEN } -} - -impl MinByteRange for AxisValueFormat1Marker { - fn min_byte_range(&self) -> Range { - 0..self.value_byte_range().end - } -} -impl<'a> FontRead<'a> for AxisValueFormat1<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.finish(AxisValueFormat1Marker {}) - } -} - -/// [Axis value table format 1](https://docs.microsoft.com/en-us/typography/opentype/spec/stat#axis-value-table-format-1) -pub type AxisValueFormat1<'a> = TableRef<'a, AxisValueFormat1Marker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> AxisValueFormat1<'a> { /// Format identifier — set to 1. pub fn format(&self) -> u16 { - let range = self.shape.format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Zero-base index into the axis record array identifying the axis /// of design variation to which the axis value table applies. Must /// be less than designAxisCount. pub fn axis_index(&self) -> u16 { - let range = self.shape.axis_index_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.axis_index_byte_range(); + unchecked::read_at(self.data, range.start) } /// Flags — see below for details. pub fn flags(&self) -> AxisValueTableFlags { - let range = self.shape.flags_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.flags_byte_range(); + unchecked::read_at(self.data, range.start) } /// The name ID for entries in the 'name' table that provide a /// display string for this attribute value. pub fn value_name_id(&self) -> NameId { - let range = self.shape.value_name_id_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.value_name_id_byte_range(); + unchecked::read_at(self.data, range.start) } /// A numeric value for this attribute value. pub fn value(&self) -> Fixed { - let range = self.shape.value_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.value_byte_range(); + unchecked::read_at(self.data, range.start) } } @@ -590,9 +578,29 @@ impl Format for AxisValueFormat2Marker { /// [Axis value table format 2](https://docs.microsoft.com/en-us/typography/opentype/spec/stat#axis-value-table-format-2) #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct AxisValueFormat2Marker {} +pub struct AxisValueFormat2Marker; -impl AxisValueFormat2Marker { +impl<'a> MinByteRange for AxisValueFormat2<'a> { + fn min_byte_range(&self) -> Range { + 0..self.range_max_value_byte_range().end + } +} + +impl<'a> FontRead<'a> for AxisValueFormat2<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// [Axis value table format 2](https://docs.microsoft.com/en-us/typography/opentype/spec/stat#axis-value-table-format-2) +pub type AxisValueFormat2<'a> = TableRef<'a, AxisValueFormat2Marker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> AxisValueFormat2<'a> { pub fn format_byte_range(&self) -> Range { let start = 0; start..start + u16::RAW_BYTE_LEN @@ -627,78 +635,52 @@ impl AxisValueFormat2Marker { let start = self.range_min_value_byte_range().end; start..start + Fixed::RAW_BYTE_LEN } -} - -impl MinByteRange for AxisValueFormat2Marker { - fn min_byte_range(&self) -> Range { - 0..self.range_max_value_byte_range().end - } -} - -impl<'a> FontRead<'a> for AxisValueFormat2<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.finish(AxisValueFormat2Marker {}) - } -} -/// [Axis value table format 2](https://docs.microsoft.com/en-us/typography/opentype/spec/stat#axis-value-table-format-2) -pub type AxisValueFormat2<'a> = TableRef<'a, AxisValueFormat2Marker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> AxisValueFormat2<'a> { /// Format identifier — set to 2. pub fn format(&self) -> u16 { - let range = self.shape.format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Zero-base index into the axis record array identifying the axis /// of design variation to which the axis value table applies. Must /// be less than designAxisCount. pub fn axis_index(&self) -> u16 { - let range = self.shape.axis_index_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.axis_index_byte_range(); + unchecked::read_at(self.data, range.start) } /// Flags — see below for details. pub fn flags(&self) -> AxisValueTableFlags { - let range = self.shape.flags_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.flags_byte_range(); + unchecked::read_at(self.data, range.start) } /// The name ID for entries in the 'name' table that provide a /// display string for this attribute value. pub fn value_name_id(&self) -> NameId { - let range = self.shape.value_name_id_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.value_name_id_byte_range(); + unchecked::read_at(self.data, range.start) } /// A nominal numeric value for this attribute value. pub fn nominal_value(&self) -> Fixed { - let range = self.shape.nominal_value_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.nominal_value_byte_range(); + unchecked::read_at(self.data, range.start) } /// The minimum value for a range associated with the specified /// name ID. pub fn range_min_value(&self) -> Fixed { - let range = self.shape.range_min_value_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.range_min_value_byte_range(); + unchecked::read_at(self.data, range.start) } /// The maximum value for a range associated with the specified /// name ID. pub fn range_max_value(&self) -> Fixed { - let range = self.shape.range_max_value_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.range_max_value_byte_range(); + unchecked::read_at(self.data, range.start) } } @@ -736,9 +718,29 @@ impl Format for AxisValueFormat3Marker { /// [Axis value table format 3](https://docs.microsoft.com/en-us/typography/opentype/spec/stat#axis-value-table-format-3) #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct AxisValueFormat3Marker {} +pub struct AxisValueFormat3Marker; + +impl<'a> MinByteRange for AxisValueFormat3<'a> { + fn min_byte_range(&self) -> Range { + 0..self.linked_value_byte_range().end + } +} -impl AxisValueFormat3Marker { +impl<'a> FontRead<'a> for AxisValueFormat3<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// [Axis value table format 3](https://docs.microsoft.com/en-us/typography/opentype/spec/stat#axis-value-table-format-3) +pub type AxisValueFormat3<'a> = TableRef<'a, AxisValueFormat3Marker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> AxisValueFormat3<'a> { pub fn format_byte_range(&self) -> Range { let start = 0; start..start + u16::RAW_BYTE_LEN @@ -768,69 +770,44 @@ impl AxisValueFormat3Marker { let start = self.value_byte_range().end; start..start + Fixed::RAW_BYTE_LEN } -} - -impl MinByteRange for AxisValueFormat3Marker { - fn min_byte_range(&self) -> Range { - 0..self.linked_value_byte_range().end - } -} - -impl<'a> FontRead<'a> for AxisValueFormat3<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.finish(AxisValueFormat3Marker {}) - } -} - -/// [Axis value table format 3](https://docs.microsoft.com/en-us/typography/opentype/spec/stat#axis-value-table-format-3) -pub type AxisValueFormat3<'a> = TableRef<'a, AxisValueFormat3Marker>; -#[allow(clippy::needless_lifetimes)] -impl<'a> AxisValueFormat3<'a> { /// Format identifier — set to 3. pub fn format(&self) -> u16 { - let range = self.shape.format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Zero-base index into the axis record array identifying the axis /// of design variation to which the axis value table applies. Must /// be less than designAxisCount. pub fn axis_index(&self) -> u16 { - let range = self.shape.axis_index_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.axis_index_byte_range(); + unchecked::read_at(self.data, range.start) } /// Flags — see below for details. pub fn flags(&self) -> AxisValueTableFlags { - let range = self.shape.flags_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.flags_byte_range(); + unchecked::read_at(self.data, range.start) } /// The name ID for entries in the 'name' table that provide a /// display string for this attribute value. pub fn value_name_id(&self) -> NameId { - let range = self.shape.value_name_id_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.value_name_id_byte_range(); + unchecked::read_at(self.data, range.start) } /// A numeric value for this attribute value. pub fn value(&self) -> Fixed { - let range = self.shape.value_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.value_byte_range(); + unchecked::read_at(self.data, range.start) } /// The numeric value for a style-linked mapping from this value. pub fn linked_value(&self) -> Fixed { - let range = self.shape.linked_value_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.linked_value_byte_range(); + unchecked::read_at(self.data, range.start) } } @@ -867,11 +844,36 @@ impl Format for AxisValueFormat4Marker { /// [Axis value table format 4](https://docs.microsoft.com/en-us/typography/opentype/spec/stat#axis-value-table-format-4) #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct AxisValueFormat4Marker { - axis_values_byte_len: usize, +pub struct AxisValueFormat4Marker; + +impl<'a> MinByteRange for AxisValueFormat4<'a> { + fn min_byte_range(&self) -> Range { + 0..self.axis_values_byte_range().end + } +} + +impl<'a> FontRead<'a> for AxisValueFormat4<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } } -impl AxisValueFormat4Marker { +/// [Axis value table format 4](https://docs.microsoft.com/en-us/typography/opentype/spec/stat#axis-value-table-format-4) +pub type AxisValueFormat4<'a> = TableRef<'a, AxisValueFormat4Marker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> AxisValueFormat4<'a> { + fn axis_values_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.axis_count()) as usize) + .checked_mul(AxisValueRecord::RAW_BYTE_LEN) + .unwrap() + } + pub fn format_byte_range(&self) -> Range { let start = 0; start..start + u16::RAW_BYTE_LEN @@ -894,69 +896,40 @@ impl AxisValueFormat4Marker { pub fn axis_values_byte_range(&self) -> Range { let start = self.value_name_id_byte_range().end; - start..start + self.axis_values_byte_len + start..start + self.axis_values_byte_len(start) } -} - -impl MinByteRange for AxisValueFormat4Marker { - fn min_byte_range(&self) -> Range { - 0..self.axis_values_byte_range().end - } -} -impl<'a> FontRead<'a> for AxisValueFormat4<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - let axis_count: u16 = cursor.read()?; - cursor.advance::(); - cursor.advance::(); - let axis_values_byte_len = (axis_count as usize) - .checked_mul(AxisValueRecord::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(axis_values_byte_len); - cursor.finish(AxisValueFormat4Marker { - axis_values_byte_len, - }) - } -} - -/// [Axis value table format 4](https://docs.microsoft.com/en-us/typography/opentype/spec/stat#axis-value-table-format-4) -pub type AxisValueFormat4<'a> = TableRef<'a, AxisValueFormat4Marker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> AxisValueFormat4<'a> { /// Format identifier — set to 4. pub fn format(&self) -> u16 { - let range = self.shape.format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.format_byte_range(); + unchecked::read_at(self.data, range.start) } /// The total number of axes contributing to this axis-values /// combination. pub fn axis_count(&self) -> u16 { - let range = self.shape.axis_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.axis_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Flags — see below for details. pub fn flags(&self) -> AxisValueTableFlags { - let range = self.shape.flags_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.flags_byte_range(); + unchecked::read_at(self.data, range.start) } /// The name ID for entries in the 'name' table that provide a /// display string for this combination of axis values. pub fn value_name_id(&self) -> NameId { - let range = self.shape.value_name_id_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.value_name_id_byte_range(); + unchecked::read_at(self.data, range.start) } /// Array of AxisValue records that provide the combination of axis /// values, one for each contributing axis. pub fn axis_values(&self) -> &'a [AxisValueRecord] { - let range = self.shape.axis_values_byte_range(); - self.data.read_array(range).unwrap() + let range = self.axis_values_byte_range(); + unchecked::read_array(self.data, range) } } diff --git a/read-fonts/generated/generated_svg.rs b/read-fonts/generated/generated_svg.rs index 0d4e75cff..8ed74e783 100644 --- a/read-fonts/generated/generated_svg.rs +++ b/read-fonts/generated/generated_svg.rs @@ -8,26 +8,9 @@ use crate::codegen_prelude::*; /// The [SVG](https://learn.microsoft.com/en-us/typography/opentype/spec/svg) table #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct SvgMarker {} +pub struct SvgMarker; -impl SvgMarker { - pub fn version_byte_range(&self) -> Range { - let start = 0; - start..start + u16::RAW_BYTE_LEN - } - - pub fn svg_document_list_offset_byte_range(&self) -> Range { - let start = self.version_byte_range().end; - start..start + Offset32::RAW_BYTE_LEN - } - - pub fn _reserved_byte_range(&self) -> Range { - let start = self.svg_document_list_offset_byte_range().end; - start..start + u16::RAW_BYTE_LEN - } -} - -impl MinByteRange for SvgMarker { +impl<'a> MinByteRange for Svg<'a> { fn min_byte_range(&self) -> Range { 0..self._reserved_byte_range().end } @@ -40,30 +23,45 @@ impl TopLevelTable for Svg<'_> { impl<'a> FontRead<'a> for Svg<'a> { fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.finish(SvgMarker {}) + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) } } /// The [SVG](https://learn.microsoft.com/en-us/typography/opentype/spec/svg) table -pub type Svg<'a> = TableRef<'a, SvgMarker>; +pub type Svg<'a> = TableRef<'a, SvgMarker, ()>; #[allow(clippy::needless_lifetimes)] impl<'a> Svg<'a> { + pub fn version_byte_range(&self) -> Range { + let start = 0; + start..start + u16::RAW_BYTE_LEN + } + + pub fn svg_document_list_offset_byte_range(&self) -> Range { + let start = self.version_byte_range().end; + start..start + Offset32::RAW_BYTE_LEN + } + + pub fn _reserved_byte_range(&self) -> Range { + let start = self.svg_document_list_offset_byte_range().end; + start..start + u16::RAW_BYTE_LEN + } + /// Table version (starting at 0). Set to 0. pub fn version(&self) -> u16 { - let range = self.shape.version_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.version_byte_range(); + unchecked::read_at(self.data, range.start) } /// Offset to the SVGDocumentList, from the start of the SVG table. /// Must be non-zero. pub fn svg_document_list_offset(&self) -> Offset32 { - let range = self.shape.svg_document_list_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.svg_document_list_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`svg_document_list_offset`][Self::svg_document_list_offset]. @@ -101,23 +99,9 @@ impl<'a> std::fmt::Debug for Svg<'a> { /// [SVGDocumentList](https://learn.microsoft.com/en-us/typography/opentype/spec/svg) #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct SVGDocumentListMarker { - document_records_byte_len: usize, -} - -impl SVGDocumentListMarker { - pub fn num_entries_byte_range(&self) -> Range { - let start = 0; - start..start + u16::RAW_BYTE_LEN - } - - pub fn document_records_byte_range(&self) -> Range { - let start = self.num_entries_byte_range().end; - start..start + self.document_records_byte_len - } -} +pub struct SVGDocumentListMarker; -impl MinByteRange for SVGDocumentListMarker { +impl<'a> MinByteRange for SVGDocumentList<'a> { fn min_byte_range(&self) -> Range { 0..self.document_records_byte_range().end } @@ -125,33 +109,46 @@ impl MinByteRange for SVGDocumentListMarker { impl<'a> FontRead<'a> for SVGDocumentList<'a> { fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - let num_entries: u16 = cursor.read()?; - let document_records_byte_len = (num_entries as usize) - .checked_mul(SVGDocumentRecord::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(document_records_byte_len); - cursor.finish(SVGDocumentListMarker { - document_records_byte_len, + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, }) } } /// [SVGDocumentList](https://learn.microsoft.com/en-us/typography/opentype/spec/svg) -pub type SVGDocumentList<'a> = TableRef<'a, SVGDocumentListMarker>; +pub type SVGDocumentList<'a> = TableRef<'a, SVGDocumentListMarker, ()>; #[allow(clippy::needless_lifetimes)] impl<'a> SVGDocumentList<'a> { + fn document_records_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.num_entries()) as usize) + .checked_mul(SVGDocumentRecord::RAW_BYTE_LEN) + .unwrap() + } + + pub fn num_entries_byte_range(&self) -> Range { + let start = 0; + start..start + u16::RAW_BYTE_LEN + } + + pub fn document_records_byte_range(&self) -> Range { + let start = self.num_entries_byte_range().end; + start..start + self.document_records_byte_len(start) + } + /// Number of SVGDocumentRecords. Must be non-zero. pub fn num_entries(&self) -> u16 { - let range = self.shape.num_entries_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.num_entries_byte_range(); + unchecked::read_at(self.data, range.start) } /// Array of SVGDocumentRecords. pub fn document_records(&self) -> &'a [SVGDocumentRecord] { - let range = self.shape.document_records_byte_range(); - self.data.read_array(range).unwrap() + let range = self.document_records_byte_range(); + unchecked::read_array(self.data, range) } } diff --git a/read-fonts/generated/generated_test_conditions.rs b/read-fonts/generated/generated_test_conditions.rs index c720ffd88..05c210267 100644 --- a/read-fonts/generated/generated_test_conditions.rs +++ b/read-fonts/generated/generated_test_conditions.rs @@ -7,12 +7,28 @@ use crate::codegen_prelude::*; #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct MajorMinorVersionMarker { - if_11_byte_start: Option, - if_20_byte_start: Option, +pub struct MajorMinorVersionMarker; + +impl<'a> MinByteRange for MajorMinorVersion<'a> { + fn min_byte_range(&self) -> Range { + 0..self.always_present_byte_range().end + } +} + +impl<'a> FontRead<'a> for MajorMinorVersion<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } } -impl MajorMinorVersionMarker { +pub type MajorMinorVersion<'a> = TableRef<'a, MajorMinorVersionMarker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> MajorMinorVersion<'a> { pub fn version_byte_range(&self) -> Range { let start = 0; start..start + MajorMinor::RAW_BYTE_LEN @@ -24,70 +40,44 @@ impl MajorMinorVersionMarker { } pub fn if_11_byte_range(&self) -> Option> { - let start = self.if_11_byte_start?; - Some(start..start + u16::RAW_BYTE_LEN) + if self.version().compatible((1u16, 1u16)) { + let start = self.always_present_byte_range().end; + Some(start..start + u16::RAW_BYTE_LEN) + } else { + None + } } pub fn if_20_byte_range(&self) -> Option> { - let start = self.if_20_byte_start?; - Some(start..start + u32::RAW_BYTE_LEN) - } -} - -impl MinByteRange for MajorMinorVersionMarker { - fn min_byte_range(&self) -> Range { - 0..self.always_present_byte_range().end - } -} - -impl<'a> FontRead<'a> for MajorMinorVersion<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - let version: MajorMinor = cursor.read()?; - cursor.advance::(); - let if_11_byte_start = version - .compatible((1u16, 1u16)) - .then(|| cursor.position()) - .transpose()?; - version - .compatible((1u16, 1u16)) - .then(|| cursor.advance::()); - let if_20_byte_start = version - .compatible((2u16, 0u16)) - .then(|| cursor.position()) - .transpose()?; - version - .compatible((2u16, 0u16)) - .then(|| cursor.advance::()); - cursor.finish(MajorMinorVersionMarker { - if_11_byte_start, - if_20_byte_start, - }) + if self.version().compatible((2u16, 0u16)) { + let start = self + .if_11_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| self.always_present_byte_range().end); + Some(start..start + u32::RAW_BYTE_LEN) + } else { + None + } } -} -pub type MajorMinorVersion<'a> = TableRef<'a, MajorMinorVersionMarker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> MajorMinorVersion<'a> { pub fn version(&self) -> MajorMinor { - let range = self.shape.version_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.version_byte_range(); + unchecked::read_at(self.data, range.start) } pub fn always_present(&self) -> u16 { - let range = self.shape.always_present_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.always_present_byte_range(); + unchecked::read_at(self.data, range.start) } pub fn if_11(&self) -> Option { - let range = self.shape.if_11_byte_range()?; - Some(self.data.read_at(range.start).unwrap()) + let range = self.if_11_byte_range()?; + Some(unchecked::read_at(self.data, range.start)) } pub fn if_20(&self) -> Option { - let range = self.shape.if_20_byte_range()?; - Some(self.data.read_at(range.start).unwrap()) + let range = self.if_20_byte_range()?; + Some(unchecked::read_at(self.data, range.start)) } } @@ -427,13 +417,28 @@ impl<'a> From for FieldType<'a> { #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct FlagDayMarker { - foo_byte_start: Option, - bar_byte_start: Option, - baz_byte_start: Option, +pub struct FlagDayMarker; + +impl<'a> MinByteRange for FlagDay<'a> { + fn min_byte_range(&self) -> Range { + 0..self.flags_byte_range().end + } } -impl FlagDayMarker { +impl<'a> FontRead<'a> for FlagDay<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +pub type FlagDay<'a> = TableRef<'a, FlagDayMarker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> FlagDay<'a> { pub fn volume_byte_range(&self) -> Range { let start = 0; start..start + u16::RAW_BYTE_LEN @@ -445,88 +450,65 @@ impl FlagDayMarker { } pub fn foo_byte_range(&self) -> Option> { - let start = self.foo_byte_start?; - Some(start..start + u16::RAW_BYTE_LEN) + if self.flags().contains(GotFlags::FOO) { + let start = self.flags_byte_range().end; + Some(start..start + u16::RAW_BYTE_LEN) + } else { + None + } } pub fn bar_byte_range(&self) -> Option> { - let start = self.bar_byte_start?; - Some(start..start + u16::RAW_BYTE_LEN) + if self.flags().contains(GotFlags::BAR) { + let start = self + .foo_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| self.flags_byte_range().end); + Some(start..start + u16::RAW_BYTE_LEN) + } else { + None + } } pub fn baz_byte_range(&self) -> Option> { - let start = self.baz_byte_start?; - Some(start..start + u16::RAW_BYTE_LEN) - } -} - -impl MinByteRange for FlagDayMarker { - fn min_byte_range(&self) -> Range { - 0..self.flags_byte_range().end - } -} - -impl<'a> FontRead<'a> for FlagDay<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - let flags: GotFlags = cursor.read()?; - let foo_byte_start = flags - .contains(GotFlags::FOO) - .then(|| cursor.position()) - .transpose()?; - flags - .contains(GotFlags::FOO) - .then(|| cursor.advance::()); - let bar_byte_start = flags - .contains(GotFlags::BAR) - .then(|| cursor.position()) - .transpose()?; - flags - .contains(GotFlags::BAR) - .then(|| cursor.advance::()); - let baz_byte_start = flags - .intersects(GotFlags::BAZ | GotFlags::FOO) - .then(|| cursor.position()) - .transpose()?; - flags - .intersects(GotFlags::BAZ | GotFlags::FOO) - .then(|| cursor.advance::()); - cursor.finish(FlagDayMarker { - foo_byte_start, - bar_byte_start, - baz_byte_start, - }) + if self.flags().intersects(GotFlags::BAZ | GotFlags::FOO) { + let start = self + .bar_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| { + self.foo_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| self.flags_byte_range().end) + }); + Some(start..start + u16::RAW_BYTE_LEN) + } else { + None + } } -} -pub type FlagDay<'a> = TableRef<'a, FlagDayMarker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> FlagDay<'a> { pub fn volume(&self) -> u16 { - let range = self.shape.volume_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.volume_byte_range(); + unchecked::read_at(self.data, range.start) } pub fn flags(&self) -> GotFlags { - let range = self.shape.flags_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.flags_byte_range(); + unchecked::read_at(self.data, range.start) } pub fn foo(&self) -> Option { - let range = self.shape.foo_byte_range()?; - Some(self.data.read_at(range.start).unwrap()) + let range = self.foo_byte_range()?; + Some(unchecked::read_at(self.data, range.start)) } pub fn bar(&self) -> Option { - let range = self.shape.bar_byte_range()?; - Some(self.data.read_at(range.start).unwrap()) + let range = self.bar_byte_range()?; + Some(unchecked::read_at(self.data, range.start)) } pub fn baz(&self) -> Option { - let range = self.shape.baz_byte_range()?; - Some(self.data.read_at(range.start).unwrap()) + let range = self.baz_byte_range()?; + Some(unchecked::read_at(self.data, range.start)) } } @@ -560,21 +542,40 @@ impl<'a> std::fmt::Debug for FlagDay<'a> { #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct FieldsAfterConditionalsMarker { - foo_byte_start: Option, - bar_byte_start: Option, - baz_byte_start: Option, +pub struct FieldsAfterConditionalsMarker; + +impl<'a> MinByteRange for FieldsAfterConditionals<'a> { + fn min_byte_range(&self) -> Range { + 0..self.and_me_too_byte_range().end + } +} + +impl<'a> FontRead<'a> for FieldsAfterConditionals<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } } -impl FieldsAfterConditionalsMarker { +pub type FieldsAfterConditionals<'a> = TableRef<'a, FieldsAfterConditionalsMarker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> FieldsAfterConditionals<'a> { pub fn flags_byte_range(&self) -> Range { let start = 0; start..start + GotFlags::RAW_BYTE_LEN } pub fn foo_byte_range(&self) -> Option> { - let start = self.foo_byte_start?; - Some(start..start + u16::RAW_BYTE_LEN) + if self.flags().contains(GotFlags::FOO) { + let start = self.flags_byte_range().end; + Some(start..start + u16::RAW_BYTE_LEN) + } else { + None + } } pub fn always_here_byte_range(&self) -> Range { @@ -586,13 +587,24 @@ impl FieldsAfterConditionalsMarker { } pub fn bar_byte_range(&self) -> Option> { - let start = self.bar_byte_start?; - Some(start..start + u16::RAW_BYTE_LEN) + if self.flags().contains(GotFlags::BAR) { + let start = self.always_here_byte_range().end; + Some(start..start + u16::RAW_BYTE_LEN) + } else { + None + } } pub fn baz_byte_range(&self) -> Option> { - let start = self.baz_byte_start?; - Some(start..start + u16::RAW_BYTE_LEN) + if self.flags().contains(GotFlags::BAZ) { + let start = self + .bar_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| self.always_here_byte_range().end); + Some(start..start + u16::RAW_BYTE_LEN) + } else { + None + } } pub fn also_always_here_byte_range(&self) -> Range { @@ -611,87 +623,40 @@ impl FieldsAfterConditionalsMarker { let start = self.also_always_here_byte_range().end; start..start + u16::RAW_BYTE_LEN } -} -impl MinByteRange for FieldsAfterConditionalsMarker { - fn min_byte_range(&self) -> Range { - 0..self.and_me_too_byte_range().end - } -} - -impl<'a> FontRead<'a> for FieldsAfterConditionals<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - let flags: GotFlags = cursor.read()?; - let foo_byte_start = flags - .contains(GotFlags::FOO) - .then(|| cursor.position()) - .transpose()?; - flags - .contains(GotFlags::FOO) - .then(|| cursor.advance::()); - cursor.advance::(); - let bar_byte_start = flags - .contains(GotFlags::BAR) - .then(|| cursor.position()) - .transpose()?; - flags - .contains(GotFlags::BAR) - .then(|| cursor.advance::()); - let baz_byte_start = flags - .contains(GotFlags::BAZ) - .then(|| cursor.position()) - .transpose()?; - flags - .contains(GotFlags::BAZ) - .then(|| cursor.advance::()); - cursor.advance::(); - cursor.advance::(); - cursor.finish(FieldsAfterConditionalsMarker { - foo_byte_start, - bar_byte_start, - baz_byte_start, - }) - } -} - -pub type FieldsAfterConditionals<'a> = TableRef<'a, FieldsAfterConditionalsMarker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> FieldsAfterConditionals<'a> { pub fn flags(&self) -> GotFlags { - let range = self.shape.flags_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.flags_byte_range(); + unchecked::read_at(self.data, range.start) } pub fn foo(&self) -> Option { - let range = self.shape.foo_byte_range()?; - Some(self.data.read_at(range.start).unwrap()) + let range = self.foo_byte_range()?; + Some(unchecked::read_at(self.data, range.start)) } pub fn always_here(&self) -> u16 { - let range = self.shape.always_here_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.always_here_byte_range(); + unchecked::read_at(self.data, range.start) } pub fn bar(&self) -> Option { - let range = self.shape.bar_byte_range()?; - Some(self.data.read_at(range.start).unwrap()) + let range = self.bar_byte_range()?; + Some(unchecked::read_at(self.data, range.start)) } pub fn baz(&self) -> Option { - let range = self.shape.baz_byte_range()?; - Some(self.data.read_at(range.start).unwrap()) + let range = self.baz_byte_range()?; + Some(unchecked::read_at(self.data, range.start)) } pub fn also_always_here(&self) -> u16 { - let range = self.shape.also_always_here_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.also_always_here_byte_range(); + unchecked::read_at(self.data, range.start) } pub fn and_me_too(&self) -> u16 { - let range = self.shape.and_me_too_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.and_me_too_byte_range(); + unchecked::read_at(self.data, range.start) } } diff --git a/read-fonts/generated/generated_test_count_all.rs b/read-fonts/generated/generated_test_count_all.rs index 052e07fdc..53d0e5e34 100644 --- a/read-fonts/generated/generated_test_count_all.rs +++ b/read-fonts/generated/generated_test_count_all.rs @@ -7,23 +7,9 @@ use crate::codegen_prelude::*; #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct CountAll16Marker { - remainder_byte_len: usize, -} - -impl CountAll16Marker { - pub fn some_field_byte_range(&self) -> Range { - let start = 0; - start..start + u16::RAW_BYTE_LEN - } +pub struct CountAll16Marker; - pub fn remainder_byte_range(&self) -> Range { - let start = self.some_field_byte_range().end; - start..start + self.remainder_byte_len - } -} - -impl MinByteRange for CountAll16Marker { +impl<'a> MinByteRange for CountAll16<'a> { fn min_byte_range(&self) -> Range { 0..self.remainder_byte_range().end } @@ -31,26 +17,44 @@ impl MinByteRange for CountAll16Marker { impl<'a> FontRead<'a> for CountAll16<'a> { fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - let remainder_byte_len = cursor.remaining_bytes() / u16::RAW_BYTE_LEN * u16::RAW_BYTE_LEN; - cursor.advance_by(remainder_byte_len); - cursor.finish(CountAll16Marker { remainder_byte_len }) + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) } } -pub type CountAll16<'a> = TableRef<'a, CountAll16Marker>; +pub type CountAll16<'a> = TableRef<'a, CountAll16Marker, ()>; #[allow(clippy::needless_lifetimes)] impl<'a> CountAll16<'a> { + fn remainder_byte_len(&self, start: usize) -> usize { + let _ = start; + { + let remaining = self.data.len().saturating_sub(start); + remaining / u16::RAW_BYTE_LEN * u16::RAW_BYTE_LEN + } + } + + pub fn some_field_byte_range(&self) -> Range { + let start = 0; + start..start + u16::RAW_BYTE_LEN + } + + pub fn remainder_byte_range(&self) -> Range { + let start = self.some_field_byte_range().end; + start..start + self.remainder_byte_len(start) + } + pub fn some_field(&self) -> u16 { - let range = self.shape.some_field_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.some_field_byte_range(); + unchecked::read_at(self.data, range.start) } pub fn remainder(&self) -> &'a [BigEndian] { - let range = self.shape.remainder_byte_range(); - self.data.read_array(range).unwrap() + let range = self.remainder_byte_range(); + unchecked::read_array(self.data, range) } } @@ -78,23 +82,9 @@ impl<'a> std::fmt::Debug for CountAll16<'a> { #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct CountAll32Marker { - remainder_byte_len: usize, -} - -impl CountAll32Marker { - pub fn some_field_byte_range(&self) -> Range { - let start = 0; - start..start + u16::RAW_BYTE_LEN - } +pub struct CountAll32Marker; - pub fn remainder_byte_range(&self) -> Range { - let start = self.some_field_byte_range().end; - start..start + self.remainder_byte_len - } -} - -impl MinByteRange for CountAll32Marker { +impl<'a> MinByteRange for CountAll32<'a> { fn min_byte_range(&self) -> Range { 0..self.remainder_byte_range().end } @@ -102,26 +92,44 @@ impl MinByteRange for CountAll32Marker { impl<'a> FontRead<'a> for CountAll32<'a> { fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - let remainder_byte_len = cursor.remaining_bytes() / u32::RAW_BYTE_LEN * u32::RAW_BYTE_LEN; - cursor.advance_by(remainder_byte_len); - cursor.finish(CountAll32Marker { remainder_byte_len }) + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) } } -pub type CountAll32<'a> = TableRef<'a, CountAll32Marker>; +pub type CountAll32<'a> = TableRef<'a, CountAll32Marker, ()>; #[allow(clippy::needless_lifetimes)] impl<'a> CountAll32<'a> { + fn remainder_byte_len(&self, start: usize) -> usize { + let _ = start; + { + let remaining = self.data.len().saturating_sub(start); + remaining / u32::RAW_BYTE_LEN * u32::RAW_BYTE_LEN + } + } + + pub fn some_field_byte_range(&self) -> Range { + let start = 0; + start..start + u16::RAW_BYTE_LEN + } + + pub fn remainder_byte_range(&self) -> Range { + let start = self.some_field_byte_range().end; + start..start + self.remainder_byte_len(start) + } + pub fn some_field(&self) -> u16 { - let range = self.shape.some_field_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.some_field_byte_range(); + unchecked::read_at(self.data, range.start) } pub fn remainder(&self) -> &'a [BigEndian] { - let range = self.shape.remainder_byte_range(); - self.data.read_array(range).unwrap() + let range = self.remainder_byte_range(); + unchecked::read_array(self.data, range) } } diff --git a/read-fonts/generated/generated_test_formats.rs b/read-fonts/generated/generated_test_formats.rs index 225e10006..788b03c2a 100644 --- a/read-fonts/generated/generated_test_formats.rs +++ b/read-fonts/generated/generated_test_formats.rs @@ -11,9 +11,28 @@ impl Format for Table1Marker { #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct Table1Marker {} +pub struct Table1Marker; -impl Table1Marker { +impl<'a> MinByteRange for Table1<'a> { + fn min_byte_range(&self) -> Range { + 0..self.flex_byte_range().end + } +} + +impl<'a> FontRead<'a> for Table1<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +pub type Table1<'a> = TableRef<'a, Table1Marker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> Table1<'a> { pub fn format_byte_range(&self) -> Range { let start = 0; start..start + u16::RAW_BYTE_LEN @@ -28,41 +47,20 @@ impl Table1Marker { let start = self.heft_byte_range().end; start..start + u16::RAW_BYTE_LEN } -} - -impl MinByteRange for Table1Marker { - fn min_byte_range(&self) -> Range { - 0..self.flex_byte_range().end - } -} -impl<'a> FontRead<'a> for Table1<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.finish(Table1Marker {}) - } -} - -pub type Table1<'a> = TableRef<'a, Table1Marker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> Table1<'a> { pub fn format(&self) -> u16 { - let range = self.shape.format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.format_byte_range(); + unchecked::read_at(self.data, range.start) } pub fn heft(&self) -> u32 { - let range = self.shape.heft_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.heft_byte_range(); + unchecked::read_at(self.data, range.start) } pub fn flex(&self) -> u16 { - let range = self.shape.flex_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.flex_byte_range(); + unchecked::read_at(self.data, range.start) } } @@ -95,11 +93,35 @@ impl Format for Table2Marker { #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct Table2Marker { - values_byte_len: usize, +pub struct Table2Marker; + +impl<'a> MinByteRange for Table2<'a> { + fn min_byte_range(&self) -> Range { + 0..self.values_byte_range().end + } } -impl Table2Marker { +impl<'a> FontRead<'a> for Table2<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +pub type Table2<'a> = TableRef<'a, Table2Marker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> Table2<'a> { + fn values_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.value_count()) as usize) + .checked_mul(u16::RAW_BYTE_LEN) + .unwrap() + } + pub fn format_byte_range(&self) -> Range { let start = 0; start..start + u16::RAW_BYTE_LEN @@ -112,46 +134,22 @@ impl Table2Marker { pub fn values_byte_range(&self) -> Range { let start = self.value_count_byte_range().end; - start..start + self.values_byte_len - } -} - -impl MinByteRange for Table2Marker { - fn min_byte_range(&self) -> Range { - 0..self.values_byte_range().end - } -} - -impl<'a> FontRead<'a> for Table2<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - let value_count: u16 = cursor.read()?; - let values_byte_len = (value_count as usize) - .checked_mul(u16::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(values_byte_len); - cursor.finish(Table2Marker { values_byte_len }) + start..start + self.values_byte_len(start) } -} -pub type Table2<'a> = TableRef<'a, Table2Marker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> Table2<'a> { pub fn format(&self) -> u16 { - let range = self.shape.format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.format_byte_range(); + unchecked::read_at(self.data, range.start) } pub fn value_count(&self) -> u16 { - let range = self.shape.value_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.value_count_byte_range(); + unchecked::read_at(self.data, range.start) } pub fn values(&self) -> &'a [BigEndian] { - let range = self.shape.values_byte_range(); - self.data.read_array(range).unwrap() + let range = self.values_byte_range(); + unchecked::read_array(self.data, range) } } @@ -184,21 +182,9 @@ impl Format for Table3Marker { #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct Table3Marker {} +pub struct Table3Marker; -impl Table3Marker { - pub fn format_byte_range(&self) -> Range { - let start = 0; - start..start + u16::RAW_BYTE_LEN - } - - pub fn something_byte_range(&self) -> Range { - let start = self.format_byte_range().end; - start..start + u16::RAW_BYTE_LEN - } -} - -impl MinByteRange for Table3Marker { +impl<'a> MinByteRange for Table3<'a> { fn min_byte_range(&self) -> Range { 0..self.something_byte_range().end } @@ -206,25 +192,36 @@ impl MinByteRange for Table3Marker { impl<'a> FontRead<'a> for Table3<'a> { fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.finish(Table3Marker {}) + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) } } -pub type Table3<'a> = TableRef<'a, Table3Marker>; +pub type Table3<'a> = TableRef<'a, Table3Marker, ()>; #[allow(clippy::needless_lifetimes)] impl<'a> Table3<'a> { + pub fn format_byte_range(&self) -> Range { + let start = 0; + start..start + u16::RAW_BYTE_LEN + } + + pub fn something_byte_range(&self) -> Range { + let start = self.format_byte_range().end; + start..start + u16::RAW_BYTE_LEN + } + pub fn format(&self) -> u16 { - let range = self.shape.format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.format_byte_range(); + unchecked::read_at(self.data, range.start) } pub fn something(&self) -> u16 { - let range = self.shape.something_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.something_byte_range(); + unchecked::read_at(self.data, range.start) } } diff --git a/read-fonts/generated/generated_test_offsets_arrays.rs b/read-fonts/generated/generated_test_offsets_arrays.rs index 365c9e8a8..9470d33f5 100644 --- a/read-fonts/generated/generated_test_offsets_arrays.rs +++ b/read-fonts/generated/generated_test_offsets_arrays.rs @@ -7,13 +7,28 @@ use crate::codegen_prelude::*; #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct KindsOfOffsetsMarker { - versioned_nullable_record_array_offset_byte_start: Option, - versioned_nonnullable_offset_byte_start: Option, - versioned_nullable_offset_byte_start: Option, +pub struct KindsOfOffsetsMarker; + +impl<'a> MinByteRange for KindsOfOffsets<'a> { + fn min_byte_range(&self) -> Range { + 0..self.record_array_offset_byte_range().end + } +} + +impl<'a> FontRead<'a> for KindsOfOffsets<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } } -impl KindsOfOffsetsMarker { +pub type KindsOfOffsets<'a> = TableRef<'a, KindsOfOffsetsMarker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> KindsOfOffsets<'a> { pub fn version_byte_range(&self) -> Range { let start = 0; start..start + MajorMinor::RAW_BYTE_LEN @@ -45,79 +60,52 @@ impl KindsOfOffsetsMarker { } pub fn versioned_nullable_record_array_offset_byte_range(&self) -> Option> { - let start = self.versioned_nullable_record_array_offset_byte_start?; - Some(start..start + Offset16::RAW_BYTE_LEN) + if self.version().compatible((1u16, 1u16)) { + let start = self.record_array_offset_byte_range().end; + Some(start..start + Offset16::RAW_BYTE_LEN) + } else { + None + } } pub fn versioned_nonnullable_offset_byte_range(&self) -> Option> { - let start = self.versioned_nonnullable_offset_byte_start?; - Some(start..start + Offset16::RAW_BYTE_LEN) + if self.version().compatible((1u16, 1u16)) { + let start = self + .versioned_nullable_record_array_offset_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| self.record_array_offset_byte_range().end); + Some(start..start + Offset16::RAW_BYTE_LEN) + } else { + None + } } pub fn versioned_nullable_offset_byte_range(&self) -> Option> { - let start = self.versioned_nullable_offset_byte_start?; - Some(start..start + Offset32::RAW_BYTE_LEN) - } -} - -impl MinByteRange for KindsOfOffsetsMarker { - fn min_byte_range(&self) -> Range { - 0..self.record_array_offset_byte_range().end - } -} - -impl<'a> FontRead<'a> for KindsOfOffsets<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - let version: MajorMinor = cursor.read()?; - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - let versioned_nullable_record_array_offset_byte_start = version - .compatible((1u16, 1u16)) - .then(|| cursor.position()) - .transpose()?; - version - .compatible((1u16, 1u16)) - .then(|| cursor.advance::()); - let versioned_nonnullable_offset_byte_start = version - .compatible((1u16, 1u16)) - .then(|| cursor.position()) - .transpose()?; - version - .compatible((1u16, 1u16)) - .then(|| cursor.advance::()); - let versioned_nullable_offset_byte_start = version - .compatible((1u16, 1u16)) - .then(|| cursor.position()) - .transpose()?; - version - .compatible((1u16, 1u16)) - .then(|| cursor.advance::()); - cursor.finish(KindsOfOffsetsMarker { - versioned_nullable_record_array_offset_byte_start, - versioned_nonnullable_offset_byte_start, - versioned_nullable_offset_byte_start, - }) + if self.version().compatible((1u16, 1u16)) { + let start = self + .versioned_nonnullable_offset_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| { + self.versioned_nullable_record_array_offset_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| self.record_array_offset_byte_range().end) + }); + Some(start..start + Offset32::RAW_BYTE_LEN) + } else { + None + } } -} - -pub type KindsOfOffsets<'a> = TableRef<'a, KindsOfOffsetsMarker>; -#[allow(clippy::needless_lifetimes)] -impl<'a> KindsOfOffsets<'a> { /// The major/minor version of the GDEF table pub fn version(&self) -> MajorMinor { - let range = self.shape.version_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.version_byte_range(); + unchecked::read_at(self.data, range.start) } /// A normal offset pub fn nonnullable_offset(&self) -> Offset16 { - let range = self.shape.nonnullable_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.nonnullable_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`nonnullable_offset`][Self::nonnullable_offset]. @@ -128,8 +116,8 @@ impl<'a> KindsOfOffsets<'a> { /// An offset that is nullable, but always present pub fn nullable_offset(&self) -> Nullable { - let range = self.shape.nullable_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.nullable_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`nullable_offset`][Self::nullable_offset]. @@ -140,14 +128,14 @@ impl<'a> KindsOfOffsets<'a> { /// count of the array at array_offset pub fn array_offset_count(&self) -> u16 { - let range = self.shape.array_offset_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.array_offset_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// An offset to an array: pub fn array_offset(&self) -> Offset16 { - let range = self.shape.array_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.array_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`array_offset`][Self::array_offset]. @@ -159,8 +147,8 @@ impl<'a> KindsOfOffsets<'a> { /// An offset to an array of records pub fn record_array_offset(&self) -> Offset16 { - let range = self.shape.record_array_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.record_array_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`record_array_offset`][Self::record_array_offset]. @@ -172,10 +160,8 @@ impl<'a> KindsOfOffsets<'a> { /// A nullable, versioned offset to an array of records pub fn versioned_nullable_record_array_offset(&self) -> Option> { - let range = self - .shape - .versioned_nullable_record_array_offset_byte_range()?; - Some(self.data.read_at(range.start).unwrap()) + let range = self.versioned_nullable_record_array_offset_byte_range()?; + Some(unchecked::read_at(self.data, range.start)) } /// Attempt to resolve [`versioned_nullable_record_array_offset`][Self::versioned_nullable_record_array_offset]. @@ -188,8 +174,8 @@ impl<'a> KindsOfOffsets<'a> { /// A normal offset that is versioned pub fn versioned_nonnullable_offset(&self) -> Option { - let range = self.shape.versioned_nonnullable_offset_byte_range()?; - Some(self.data.read_at(range.start).unwrap()) + let range = self.versioned_nonnullable_offset_byte_range()?; + Some(unchecked::read_at(self.data, range.start)) } /// Attempt to resolve [`versioned_nonnullable_offset`][Self::versioned_nonnullable_offset]. @@ -200,8 +186,8 @@ impl<'a> KindsOfOffsets<'a> { /// An offset that is nullable and versioned pub fn versioned_nullable_offset(&self) -> Option> { - let range = self.shape.versioned_nullable_offset_byte_range()?; - Some(self.data.read_at(range.start).unwrap()) + let range = self.versioned_nullable_offset_byte_range()?; + Some(unchecked::read_at(self.data, range.start)) } /// Attempt to resolve [`versioned_nullable_offset`][Self::versioned_nullable_offset]. @@ -280,16 +266,53 @@ impl<'a> std::fmt::Debug for KindsOfOffsets<'a> { #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct KindsOfArraysOfOffsetsMarker { - nonnullable_offsets_byte_len: usize, - nullable_offsets_byte_len: usize, - versioned_nonnullable_offsets_byte_start: Option, - versioned_nonnullable_offsets_byte_len: Option, - versioned_nullable_offsets_byte_start: Option, - versioned_nullable_offsets_byte_len: Option, +pub struct KindsOfArraysOfOffsetsMarker; + +impl<'a> MinByteRange for KindsOfArraysOfOffsets<'a> { + fn min_byte_range(&self) -> Range { + 0..self.nullable_offsets_byte_range().end + } +} + +impl<'a> FontRead<'a> for KindsOfArraysOfOffsets<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } } -impl KindsOfArraysOfOffsetsMarker { +pub type KindsOfArraysOfOffsets<'a> = TableRef<'a, KindsOfArraysOfOffsetsMarker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> KindsOfArraysOfOffsets<'a> { + fn nonnullable_offsets_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.count()) as usize) + .checked_mul(Offset16::RAW_BYTE_LEN) + .unwrap() + } + fn nullable_offsets_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.count()) as usize) + .checked_mul(Offset16::RAW_BYTE_LEN) + .unwrap() + } + fn versioned_nonnullable_offsets_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.count()) as usize) + .checked_mul(Offset16::RAW_BYTE_LEN) + .unwrap() + } + fn versioned_nullable_offsets_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.count()) as usize) + .checked_mul(Offset16::RAW_BYTE_LEN) + .unwrap() + } + pub fn version_byte_range(&self) -> Range { let start = 0; start..start + MajorMinor::RAW_BYTE_LEN @@ -302,99 +325,51 @@ impl KindsOfArraysOfOffsetsMarker { pub fn nonnullable_offsets_byte_range(&self) -> Range { let start = self.count_byte_range().end; - start..start + self.nonnullable_offsets_byte_len + start..start + self.nonnullable_offsets_byte_len(start) } pub fn nullable_offsets_byte_range(&self) -> Range { let start = self.nonnullable_offsets_byte_range().end; - start..start + self.nullable_offsets_byte_len + start..start + self.nullable_offsets_byte_len(start) } pub fn versioned_nonnullable_offsets_byte_range(&self) -> Option> { - let start = self.versioned_nonnullable_offsets_byte_start?; - Some(start..start + self.versioned_nonnullable_offsets_byte_len?) + if self.version().compatible((1u16, 1u16)) { + let start = self.nullable_offsets_byte_range().end; + Some(start..start + self.versioned_nonnullable_offsets_byte_len(start)) + } else { + None + } } pub fn versioned_nullable_offsets_byte_range(&self) -> Option> { - let start = self.versioned_nullable_offsets_byte_start?; - Some(start..start + self.versioned_nullable_offsets_byte_len?) - } -} - -impl MinByteRange for KindsOfArraysOfOffsetsMarker { - fn min_byte_range(&self) -> Range { - 0..self.nullable_offsets_byte_range().end - } -} - -impl<'a> FontRead<'a> for KindsOfArraysOfOffsets<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - let version: MajorMinor = cursor.read()?; - let count: u16 = cursor.read()?; - let nonnullable_offsets_byte_len = (count as usize) - .checked_mul(Offset16::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(nonnullable_offsets_byte_len); - let nullable_offsets_byte_len = (count as usize) - .checked_mul(Offset16::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(nullable_offsets_byte_len); - let versioned_nonnullable_offsets_byte_start = version - .compatible((1u16, 1u16)) - .then(|| cursor.position()) - .transpose()?; - let versioned_nonnullable_offsets_byte_len = version.compatible((1u16, 1u16)).then_some( - (count as usize) - .checked_mul(Offset16::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?, - ); - if let Some(value) = versioned_nonnullable_offsets_byte_len { - cursor.advance_by(value); - } - let versioned_nullable_offsets_byte_start = version - .compatible((1u16, 1u16)) - .then(|| cursor.position()) - .transpose()?; - let versioned_nullable_offsets_byte_len = version.compatible((1u16, 1u16)).then_some( - (count as usize) - .checked_mul(Offset16::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?, - ); - if let Some(value) = versioned_nullable_offsets_byte_len { - cursor.advance_by(value); + if self.version().compatible((1u16, 1u16)) { + let start = self + .versioned_nonnullable_offsets_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| self.nullable_offsets_byte_range().end); + Some(start..start + self.versioned_nullable_offsets_byte_len(start)) + } else { + None } - cursor.finish(KindsOfArraysOfOffsetsMarker { - nonnullable_offsets_byte_len, - nullable_offsets_byte_len, - versioned_nonnullable_offsets_byte_start, - versioned_nonnullable_offsets_byte_len, - versioned_nullable_offsets_byte_start, - versioned_nullable_offsets_byte_len, - }) } -} - -pub type KindsOfArraysOfOffsets<'a> = TableRef<'a, KindsOfArraysOfOffsetsMarker>; -#[allow(clippy::needless_lifetimes)] -impl<'a> KindsOfArraysOfOffsets<'a> { /// The version pub fn version(&self) -> MajorMinor { - let range = self.shape.version_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.version_byte_range(); + unchecked::read_at(self.data, range.start) } /// The number of items in each array pub fn count(&self) -> u16 { - let range = self.shape.count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.count_byte_range(); + unchecked::read_at(self.data, range.start) } /// A normal array offset pub fn nonnullable_offsets(&self) -> &'a [BigEndian] { - let range = self.shape.nonnullable_offsets_byte_range(); - self.data.read_array(range).unwrap() + let range = self.nonnullable_offsets_byte_range(); + unchecked::read_array(self.data, range) } /// A dynamically resolving wrapper for [`nonnullable_offsets`][Self::nonnullable_offsets]. @@ -406,8 +381,8 @@ impl<'a> KindsOfArraysOfOffsets<'a> { /// An offset that is nullable, but always present pub fn nullable_offsets(&self) -> &'a [BigEndian>] { - let range = self.shape.nullable_offsets_byte_range(); - self.data.read_array(range).unwrap() + let range = self.nullable_offsets_byte_range(); + unchecked::read_array(self.data, range) } /// A dynamically resolving wrapper for [`nullable_offsets`][Self::nullable_offsets]. @@ -419,8 +394,8 @@ impl<'a> KindsOfArraysOfOffsets<'a> { /// A normal offset that is versioned pub fn versioned_nonnullable_offsets(&self) -> Option<&'a [BigEndian]> { - let range = self.shape.versioned_nonnullable_offsets_byte_range()?; - Some(self.data.read_array(range).unwrap()) + let range = self.versioned_nonnullable_offsets_byte_range()?; + Some(unchecked::read_array(self.data, range)) } /// A dynamically resolving wrapper for [`versioned_nonnullable_offsets`][Self::versioned_nonnullable_offsets]. @@ -432,8 +407,8 @@ impl<'a> KindsOfArraysOfOffsets<'a> { /// An offset that is nullable and versioned pub fn versioned_nullable_offsets(&self) -> Option<&'a [BigEndian>]> { - let range = self.shape.versioned_nullable_offsets_byte_range()?; - Some(self.data.read_array(range).unwrap()) + let range = self.versioned_nullable_offsets_byte_range()?; + Some(unchecked::read_array(self.data, range)) } /// A dynamically resolving wrapper for [`versioned_nullable_offsets`][Self::versioned_nullable_offsets]. @@ -525,16 +500,53 @@ impl<'a> std::fmt::Debug for KindsOfArraysOfOffsets<'a> { #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct KindsOfArraysMarker { - scalars_byte_len: usize, - records_byte_len: usize, - versioned_scalars_byte_start: Option, - versioned_scalars_byte_len: Option, - versioned_records_byte_start: Option, - versioned_records_byte_len: Option, +pub struct KindsOfArraysMarker; + +impl<'a> MinByteRange for KindsOfArrays<'a> { + fn min_byte_range(&self) -> Range { + 0..self.records_byte_range().end + } +} + +impl<'a> FontRead<'a> for KindsOfArrays<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } } -impl KindsOfArraysMarker { +pub type KindsOfArrays<'a> = TableRef<'a, KindsOfArraysMarker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> KindsOfArrays<'a> { + fn scalars_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.count()) as usize) + .checked_mul(u16::RAW_BYTE_LEN) + .unwrap() + } + fn records_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.count()) as usize) + .checked_mul(Shmecord::RAW_BYTE_LEN) + .unwrap() + } + fn versioned_scalars_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.count()) as usize) + .checked_mul(u16::RAW_BYTE_LEN) + .unwrap() + } + fn versioned_records_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.count()) as usize) + .checked_mul(Shmecord::RAW_BYTE_LEN) + .unwrap() + } + pub fn version_byte_range(&self) -> Range { let start = 0; start..start + u16::RAW_BYTE_LEN @@ -547,116 +559,68 @@ impl KindsOfArraysMarker { pub fn scalars_byte_range(&self) -> Range { let start = self.count_byte_range().end; - start..start + self.scalars_byte_len + start..start + self.scalars_byte_len(start) } pub fn records_byte_range(&self) -> Range { let start = self.scalars_byte_range().end; - start..start + self.records_byte_len + start..start + self.records_byte_len(start) } pub fn versioned_scalars_byte_range(&self) -> Option> { - let start = self.versioned_scalars_byte_start?; - Some(start..start + self.versioned_scalars_byte_len?) + if self.version().compatible(1u16) { + let start = self.records_byte_range().end; + Some(start..start + self.versioned_scalars_byte_len(start)) + } else { + None + } } pub fn versioned_records_byte_range(&self) -> Option> { - let start = self.versioned_records_byte_start?; - Some(start..start + self.versioned_records_byte_len?) - } -} - -impl MinByteRange for KindsOfArraysMarker { - fn min_byte_range(&self) -> Range { - 0..self.records_byte_range().end - } -} - -impl<'a> FontRead<'a> for KindsOfArrays<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - let version: u16 = cursor.read()?; - let count: u16 = cursor.read()?; - let scalars_byte_len = (count as usize) - .checked_mul(u16::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(scalars_byte_len); - let records_byte_len = (count as usize) - .checked_mul(Shmecord::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(records_byte_len); - let versioned_scalars_byte_start = version - .compatible(1u16) - .then(|| cursor.position()) - .transpose()?; - let versioned_scalars_byte_len = version.compatible(1u16).then_some( - (count as usize) - .checked_mul(u16::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?, - ); - if let Some(value) = versioned_scalars_byte_len { - cursor.advance_by(value); + if self.version().compatible(1u16) { + let start = self + .versioned_scalars_byte_range() + .map(|range| range.end) + .unwrap_or_else(|| self.records_byte_range().end); + Some(start..start + self.versioned_records_byte_len(start)) + } else { + None } - let versioned_records_byte_start = version - .compatible(1u16) - .then(|| cursor.position()) - .transpose()?; - let versioned_records_byte_len = version.compatible(1u16).then_some( - (count as usize) - .checked_mul(Shmecord::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?, - ); - if let Some(value) = versioned_records_byte_len { - cursor.advance_by(value); - } - cursor.finish(KindsOfArraysMarker { - scalars_byte_len, - records_byte_len, - versioned_scalars_byte_start, - versioned_scalars_byte_len, - versioned_records_byte_start, - versioned_records_byte_len, - }) } -} -pub type KindsOfArrays<'a> = TableRef<'a, KindsOfArraysMarker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> KindsOfArrays<'a> { pub fn version(&self) -> u16 { - let range = self.shape.version_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.version_byte_range(); + unchecked::read_at(self.data, range.start) } /// the number of items in each array pub fn count(&self) -> u16 { - let range = self.shape.count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.count_byte_range(); + unchecked::read_at(self.data, range.start) } /// an array of scalars pub fn scalars(&self) -> &'a [BigEndian] { - let range = self.shape.scalars_byte_range(); - self.data.read_array(range).unwrap() + let range = self.scalars_byte_range(); + unchecked::read_array(self.data, range) } /// an array of records pub fn records(&self) -> &'a [Shmecord] { - let range = self.shape.records_byte_range(); - self.data.read_array(range).unwrap() + let range = self.records_byte_range(); + unchecked::read_array(self.data, range) } /// a versioned array of scalars pub fn versioned_scalars(&self) -> Option<&'a [BigEndian]> { - let range = self.shape.versioned_scalars_byte_range()?; - Some(self.data.read_array(range).unwrap()) + let range = self.versioned_scalars_byte_range()?; + Some(unchecked::read_array(self.data, range)) } /// a versioned array of scalars pub fn versioned_records(&self) -> Option<&'a [Shmecord]> { - let range = self.shape.versioned_records_byte_range()?; - Some(self.data.read_array(range).unwrap()) + let range = self.versioned_records_byte_range()?; + Some(unchecked::read_array(self.data, range)) } } @@ -706,11 +670,36 @@ impl<'a> std::fmt::Debug for KindsOfArrays<'a> { #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct VarLenHaverMarker { - var_len_byte_len: usize, +pub struct VarLenHaverMarker; + +impl<'a> MinByteRange for VarLenHaver<'a> { + fn min_byte_range(&self) -> Range { + 0..self.other_field_byte_range().end + } +} + +impl<'a> FontRead<'a> for VarLenHaver<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } } -impl VarLenHaverMarker { +pub type VarLenHaver<'a> = TableRef<'a, VarLenHaverMarker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> VarLenHaver<'a> { + fn var_len_byte_len(&self, start: usize) -> usize { + let _ = start; + { + let data = self.data.split_off(start).unwrap(); + ::total_len_for_count(data, (self.count()) as usize).unwrap() + } + } + pub fn count_byte_range(&self) -> Range { let start = 0; start..start + u16::RAW_BYTE_LEN @@ -718,52 +707,27 @@ impl VarLenHaverMarker { pub fn var_len_byte_range(&self) -> Range { let start = self.count_byte_range().end; - start..start + self.var_len_byte_len + start..start + self.var_len_byte_len(start) } pub fn other_field_byte_range(&self) -> Range { let start = self.var_len_byte_range().end; start..start + u32::RAW_BYTE_LEN } -} - -impl MinByteRange for VarLenHaverMarker { - fn min_byte_range(&self) -> Range { - 0..self.other_field_byte_range().end - } -} -impl<'a> FontRead<'a> for VarLenHaver<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - let count: u16 = cursor.read()?; - let var_len_byte_len = { - let data = cursor.remaining().ok_or(ReadError::OutOfBounds)?; - ::total_len_for_count(data, count as usize)? - }; - cursor.advance_by(var_len_byte_len); - cursor.advance::(); - cursor.finish(VarLenHaverMarker { var_len_byte_len }) - } -} - -pub type VarLenHaver<'a> = TableRef<'a, VarLenHaverMarker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> VarLenHaver<'a> { pub fn count(&self) -> u16 { - let range = self.shape.count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.count_byte_range(); + unchecked::read_at(self.data, range.start) } pub fn var_len(&self) -> VarLenArray<'a, VarSizeDummy> { - let range = self.shape.var_len_byte_range(); - VarLenArray::read(self.data.split_off(range.start).unwrap()).unwrap() + let range = self.var_len_byte_range(); + VarLenArray::read(unchecked::split_off(self.data, range.start)).unwrap() } pub fn other_field(&self) -> u32 { - let range = self.shape.other_field_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.other_field_byte_range(); + unchecked::read_at(self.data, range.start) } } @@ -792,21 +756,9 @@ impl<'a> std::fmt::Debug for VarLenHaver<'a> { #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct DummyMarker {} - -impl DummyMarker { - pub fn value_byte_range(&self) -> Range { - let start = 0; - start..start + u16::RAW_BYTE_LEN - } +pub struct DummyMarker; - pub fn _reserved_byte_range(&self) -> Range { - let start = self.value_byte_range().end; - start..start + u16::RAW_BYTE_LEN - } -} - -impl MinByteRange for DummyMarker { +impl<'a> MinByteRange for Dummy<'a> { fn min_byte_range(&self) -> Range { 0..self._reserved_byte_range().end } @@ -814,20 +766,31 @@ impl MinByteRange for DummyMarker { impl<'a> FontRead<'a> for Dummy<'a> { fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.finish(DummyMarker {}) + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) } } -pub type Dummy<'a> = TableRef<'a, DummyMarker>; +pub type Dummy<'a> = TableRef<'a, DummyMarker, ()>; #[allow(clippy::needless_lifetimes)] impl<'a> Dummy<'a> { + pub fn value_byte_range(&self) -> Range { + let start = 0; + start..start + u16::RAW_BYTE_LEN + } + + pub fn _reserved_byte_range(&self) -> Range { + let start = self.value_byte_range().end; + start..start + u16::RAW_BYTE_LEN + } + pub fn value(&self) -> u16 { - let range = self.shape.value_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.value_byte_range(); + unchecked::read_at(self.data, range.start) } } diff --git a/read-fonts/generated/generated_test_records.rs b/read-fonts/generated/generated_test_records.rs index 4181801ef..a74b93a72 100644 --- a/read-fonts/generated/generated_test_records.rs +++ b/read-fonts/generated/generated_test_records.rs @@ -7,12 +7,43 @@ use crate::codegen_prelude::*; #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct BasicTableMarker { - simple_records_byte_len: usize, - array_records_byte_len: usize, +pub struct BasicTableMarker; + +impl<'a> MinByteRange for BasicTable<'a> { + fn min_byte_range(&self) -> Range { + 0..self.array_records_byte_range().end + } } -impl BasicTableMarker { +impl<'a> FontRead<'a> for BasicTable<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +pub type BasicTable<'a> = TableRef<'a, BasicTableMarker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> BasicTable<'a> { + fn simple_records_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.simple_count()) as usize) + .checked_mul(SimpleRecord::RAW_BYTE_LEN) + .unwrap() + } + fn array_records_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.array_records_count()) as usize) + .checked_mul( + ::compute_size(&self.arrays_inner_count()).unwrap(), + ) + .unwrap() + } + pub fn simple_count_byte_range(&self) -> Range { let start = 0; start..start + u16::RAW_BYTE_LEN @@ -20,7 +51,7 @@ impl BasicTableMarker { pub fn simple_records_byte_range(&self) -> Range { let start = self.simple_count_byte_range().end; - start..start + self.simple_records_byte_len + start..start + self.simple_records_byte_len(start) } pub fn arrays_inner_count_byte_range(&self) -> Range { @@ -35,68 +66,32 @@ impl BasicTableMarker { pub fn array_records_byte_range(&self) -> Range { let start = self.array_records_count_byte_range().end; - start..start + self.array_records_byte_len + start..start + self.array_records_byte_len(start) } -} -impl MinByteRange for BasicTableMarker { - fn min_byte_range(&self) -> Range { - 0..self.array_records_byte_range().end - } -} - -impl<'a> FontRead<'a> for BasicTable<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - let simple_count: u16 = cursor.read()?; - let simple_records_byte_len = (simple_count as usize) - .checked_mul(SimpleRecord::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(simple_records_byte_len); - let arrays_inner_count: u16 = cursor.read()?; - let array_records_count: u32 = cursor.read()?; - let array_records_byte_len = (array_records_count as usize) - .checked_mul(::compute_size( - &arrays_inner_count, - )?) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(array_records_byte_len); - cursor.finish(BasicTableMarker { - simple_records_byte_len, - array_records_byte_len, - }) - } -} - -pub type BasicTable<'a> = TableRef<'a, BasicTableMarker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> BasicTable<'a> { pub fn simple_count(&self) -> u16 { - let range = self.shape.simple_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.simple_count_byte_range(); + unchecked::read_at(self.data, range.start) } pub fn simple_records(&self) -> &'a [SimpleRecord] { - let range = self.shape.simple_records_byte_range(); - self.data.read_array(range).unwrap() + let range = self.simple_records_byte_range(); + unchecked::read_array(self.data, range) } pub fn arrays_inner_count(&self) -> u16 { - let range = self.shape.arrays_inner_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.arrays_inner_count_byte_range(); + unchecked::read_at(self.data, range.start) } pub fn array_records_count(&self) -> u32 { - let range = self.shape.array_records_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.array_records_count_byte_range(); + unchecked::read_at(self.data, range.start) } pub fn array_records(&self) -> ComputedArray<'a, ContainsArrays<'a>> { - let range = self.shape.array_records_byte_range(); - self.data - .read_with_args(range, &self.arrays_inner_count()) - .unwrap() + let range = self.array_records_byte_range(); + unchecked::read_with_args(self.data, range, &self.arrays_inner_count()) } } @@ -338,23 +333,9 @@ impl<'a> SomeRecord<'a> for ContainsOffsets { #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct VarLenItemMarker { - data_byte_len: usize, -} +pub struct VarLenItemMarker; -impl VarLenItemMarker { - pub fn length_byte_range(&self) -> Range { - let start = 0; - start..start + u32::RAW_BYTE_LEN - } - - pub fn data_byte_range(&self) -> Range { - let start = self.length_byte_range().end; - start..start + self.data_byte_len - } -} - -impl MinByteRange for VarLenItemMarker { +impl<'a> MinByteRange for VarLenItem<'a> { fn min_byte_range(&self) -> Range { 0..self.data_byte_range().end } @@ -362,26 +343,44 @@ impl MinByteRange for VarLenItemMarker { impl<'a> FontRead<'a> for VarLenItem<'a> { fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - let data_byte_len = cursor.remaining_bytes() / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN; - cursor.advance_by(data_byte_len); - cursor.finish(VarLenItemMarker { data_byte_len }) + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) } } -pub type VarLenItem<'a> = TableRef<'a, VarLenItemMarker>; +pub type VarLenItem<'a> = TableRef<'a, VarLenItemMarker, ()>; #[allow(clippy::needless_lifetimes)] impl<'a> VarLenItem<'a> { + fn data_byte_len(&self, start: usize) -> usize { + let _ = start; + { + let remaining = self.data.len().saturating_sub(start); + remaining / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN + } + } + + pub fn length_byte_range(&self) -> Range { + let start = 0; + start..start + u32::RAW_BYTE_LEN + } + + pub fn data_byte_range(&self) -> Range { + let start = self.length_byte_range().end; + start..start + self.data_byte_len(start) + } + pub fn length(&self) -> u32 { - let range = self.shape.length_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.length_byte_range(); + unchecked::read_at(self.data, range.start) } pub fn data(&self) -> &'a [u8] { - let range = self.shape.data_byte_range(); - self.data.read_array(range).unwrap() + let range = self.data_byte_range(); + unchecked::read_array(self.data, range) } } diff --git a/read-fonts/generated/generated_trak.rs b/read-fonts/generated/generated_trak.rs index 6c2d58a60..fc6d668fb 100644 --- a/read-fonts/generated/generated_trak.rs +++ b/read-fonts/generated/generated_trak.rs @@ -8,9 +8,34 @@ use crate::codegen_prelude::*; /// The [tracking (trak)](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6trak.html) table. #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct TrakMarker {} +pub struct TrakMarker; -impl TrakMarker { +impl<'a> MinByteRange for Trak<'a> { + fn min_byte_range(&self) -> Range { + 0..self.reserved_byte_range().end + } +} + +impl TopLevelTable for Trak<'_> { + /// `trak` + const TAG: Tag = Tag::new(b"trak"); +} + +impl<'a> FontRead<'a> for Trak<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// The [tracking (trak)](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6trak.html) table. +pub type Trak<'a> = TableRef<'a, TrakMarker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> Trak<'a> { pub fn version_byte_range(&self) -> Range { let start = 0; start..start + MajorMinor::RAW_BYTE_LEN @@ -35,52 +60,23 @@ impl TrakMarker { let start = self.vert_offset_byte_range().end; start..start + u16::RAW_BYTE_LEN } -} - -impl MinByteRange for TrakMarker { - fn min_byte_range(&self) -> Range { - 0..self.reserved_byte_range().end - } -} - -impl TopLevelTable for Trak<'_> { - /// `trak` - const TAG: Tag = Tag::new(b"trak"); -} - -impl<'a> FontRead<'a> for Trak<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.finish(TrakMarker {}) - } -} - -/// The [tracking (trak)](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6trak.html) table. -pub type Trak<'a> = TableRef<'a, TrakMarker>; -#[allow(clippy::needless_lifetimes)] -impl<'a> Trak<'a> { /// Version number of the tracking table (0x00010000 for the current version). pub fn version(&self) -> MajorMinor { - let range = self.shape.version_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.version_byte_range(); + unchecked::read_at(self.data, range.start) } /// Format of the tracking table (set to 0). pub fn format(&self) -> u16 { - let range = self.shape.format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Offset from start of tracking table to TrackData for horizontal text (or 0 if none). pub fn horiz_offset(&self) -> Nullable { - let range = self.shape.horiz_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.horiz_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`horiz_offset`][Self::horiz_offset]. @@ -91,8 +87,8 @@ impl<'a> Trak<'a> { /// Offset from start of tracking table to TrackData for vertical text (or 0 if none). pub fn vert_offset(&self) -> Nullable { - let range = self.shape.vert_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.vert_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`vert_offset`][Self::vert_offset]. @@ -135,11 +131,36 @@ impl<'a> std::fmt::Debug for Trak<'a> { /// The tracking data table. #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct TrackDataMarker { - track_table_byte_len: usize, +pub struct TrackDataMarker; + +impl<'a> MinByteRange for TrackData<'a> { + fn min_byte_range(&self) -> Range { + 0..self.track_table_byte_range().end + } } -impl TrackDataMarker { +impl<'a> FontRead<'a> for TrackData<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// The tracking data table. +pub type TrackData<'a> = TableRef<'a, TrackDataMarker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> TrackData<'a> { + fn track_table_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.n_tracks()) as usize) + .checked_mul(TrackTableEntry::RAW_BYTE_LEN) + .unwrap() + } + pub fn n_tracks_byte_range(&self) -> Range { let start = 0; start..start + u16::RAW_BYTE_LEN @@ -157,59 +178,31 @@ impl TrackDataMarker { pub fn track_table_byte_range(&self) -> Range { let start = self.size_table_offset_byte_range().end; - start..start + self.track_table_byte_len - } -} - -impl MinByteRange for TrackDataMarker { - fn min_byte_range(&self) -> Range { - 0..self.track_table_byte_range().end + start..start + self.track_table_byte_len(start) } -} -impl<'a> FontRead<'a> for TrackData<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - let n_tracks: u16 = cursor.read()?; - cursor.advance::(); - cursor.advance::(); - let track_table_byte_len = (n_tracks as usize) - .checked_mul(TrackTableEntry::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(track_table_byte_len); - cursor.finish(TrackDataMarker { - track_table_byte_len, - }) - } -} - -/// The tracking data table. -pub type TrackData<'a> = TableRef<'a, TrackDataMarker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> TrackData<'a> { /// Number of separate tracks included in this table. pub fn n_tracks(&self) -> u16 { - let range = self.shape.n_tracks_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.n_tracks_byte_range(); + unchecked::read_at(self.data, range.start) } /// Number of point sizes included in this table. pub fn n_sizes(&self) -> u16 { - let range = self.shape.n_sizes_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.n_sizes_byte_range(); + unchecked::read_at(self.data, range.start) } /// Offset from the start of the tracking table to the start of the size subtable. pub fn size_table_offset(&self) -> u32 { - let range = self.shape.size_table_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.size_table_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Array of TrackTableEntry records. pub fn track_table(&self) -> &'a [TrackTableEntry] { - let range = self.shape.track_table_byte_range(); - self.data.read_array(range).unwrap() + let range = self.track_table_byte_range(); + unchecked::read_array(self.data, range) } } diff --git a/read-fonts/generated/generated_varc.rs b/read-fonts/generated/generated_varc.rs index e137ba6d0..78b7ce354 100644 --- a/read-fonts/generated/generated_varc.rs +++ b/read-fonts/generated/generated_varc.rs @@ -10,9 +10,36 @@ use crate::codegen_prelude::*; /// [FontTools VARC](https://github.com/fonttools/fonttools/blob/5e6b12d12fa08abafbeb7570f47707fbedf69a45/Lib/fontTools/ttLib/tables/otData.py#L3459-L3476) #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct VarcMarker {} +pub struct VarcMarker; -impl VarcMarker { +impl<'a> MinByteRange for Varc<'a> { + fn min_byte_range(&self) -> Range { + 0..self.var_composite_glyphs_offset_byte_range().end + } +} + +impl TopLevelTable for Varc<'_> { + /// `VARC` + const TAG: Tag = Tag::new(b"VARC"); +} + +impl<'a> FontRead<'a> for Varc<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// [VARC](https://github.com/harfbuzz/boring-expansion-spec/blob/main/VARC.md) (Variable Composites / Components Table) +/// +/// [FontTools VARC](https://github.com/fonttools/fonttools/blob/5e6b12d12fa08abafbeb7570f47707fbedf69a45/Lib/fontTools/ttLib/tables/otData.py#L3459-L3476) +pub type Varc<'a> = TableRef<'a, VarcMarker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> Varc<'a> { pub fn version_byte_range(&self) -> Range { let start = 0; start..start + MajorMinor::RAW_BYTE_LEN @@ -42,48 +69,16 @@ impl VarcMarker { let start = self.axis_indices_list_offset_byte_range().end; start..start + Offset32::RAW_BYTE_LEN } -} - -impl MinByteRange for VarcMarker { - fn min_byte_range(&self) -> Range { - 0..self.var_composite_glyphs_offset_byte_range().end - } -} - -impl TopLevelTable for Varc<'_> { - /// `VARC` - const TAG: Tag = Tag::new(b"VARC"); -} - -impl<'a> FontRead<'a> for Varc<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.finish(VarcMarker {}) - } -} - -/// [VARC](https://github.com/harfbuzz/boring-expansion-spec/blob/main/VARC.md) (Variable Composites / Components Table) -/// -/// [FontTools VARC](https://github.com/fonttools/fonttools/blob/5e6b12d12fa08abafbeb7570f47707fbedf69a45/Lib/fontTools/ttLib/tables/otData.py#L3459-L3476) -pub type Varc<'a> = TableRef<'a, VarcMarker>; -#[allow(clippy::needless_lifetimes)] -impl<'a> Varc<'a> { /// Major/minor version number. Set to 1.0. pub fn version(&self) -> MajorMinor { - let range = self.shape.version_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.version_byte_range(); + unchecked::read_at(self.data, range.start) } pub fn coverage_offset(&self) -> Offset32 { - let range = self.shape.coverage_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.coverage_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`coverage_offset`][Self::coverage_offset]. @@ -93,8 +88,8 @@ impl<'a> Varc<'a> { } pub fn multi_var_store_offset(&self) -> Nullable { - let range = self.shape.multi_var_store_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.multi_var_store_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`multi_var_store_offset`][Self::multi_var_store_offset]. @@ -104,8 +99,8 @@ impl<'a> Varc<'a> { } pub fn condition_list_offset(&self) -> Nullable { - let range = self.shape.condition_list_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.condition_list_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`condition_list_offset`][Self::condition_list_offset]. @@ -115,8 +110,8 @@ impl<'a> Varc<'a> { } pub fn axis_indices_list_offset(&self) -> Nullable { - let range = self.shape.axis_indices_list_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.axis_indices_list_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`axis_indices_list_offset`][Self::axis_indices_list_offset]. @@ -126,8 +121,8 @@ impl<'a> Varc<'a> { } pub fn var_composite_glyphs_offset(&self) -> Offset32 { - let range = self.shape.var_composite_glyphs_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.var_composite_glyphs_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`var_composite_glyphs_offset`][Self::var_composite_glyphs_offset]. @@ -189,11 +184,37 @@ impl Format for MultiItemVariationStoreMarker { /// * #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct MultiItemVariationStoreMarker { - variation_data_offsets_byte_len: usize, +pub struct MultiItemVariationStoreMarker; + +impl<'a> MinByteRange for MultiItemVariationStore<'a> { + fn min_byte_range(&self) -> Range { + 0..self.variation_data_offsets_byte_range().end + } +} + +impl<'a> FontRead<'a> for MultiItemVariationStore<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } } -impl MultiItemVariationStoreMarker { +/// * +/// * +pub type MultiItemVariationStore<'a> = TableRef<'a, MultiItemVariationStoreMarker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> MultiItemVariationStore<'a> { + fn variation_data_offsets_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.variation_data_count()) as usize) + .checked_mul(Offset32::RAW_BYTE_LEN) + .unwrap() + } + pub fn format_byte_range(&self) -> Range { let start = 0; start..start + u16::RAW_BYTE_LEN @@ -211,46 +232,17 @@ impl MultiItemVariationStoreMarker { pub fn variation_data_offsets_byte_range(&self) -> Range { let start = self.variation_data_count_byte_range().end; - start..start + self.variation_data_offsets_byte_len - } -} - -impl MinByteRange for MultiItemVariationStoreMarker { - fn min_byte_range(&self) -> Range { - 0..self.variation_data_offsets_byte_range().end - } -} - -impl<'a> FontRead<'a> for MultiItemVariationStore<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - let variation_data_count: u16 = cursor.read()?; - let variation_data_offsets_byte_len = (variation_data_count as usize) - .checked_mul(Offset32::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(variation_data_offsets_byte_len); - cursor.finish(MultiItemVariationStoreMarker { - variation_data_offsets_byte_len, - }) + start..start + self.variation_data_offsets_byte_len(start) } -} - -/// * -/// * -pub type MultiItemVariationStore<'a> = TableRef<'a, MultiItemVariationStoreMarker>; -#[allow(clippy::needless_lifetimes)] -impl<'a> MultiItemVariationStore<'a> { pub fn format(&self) -> u16 { - let range = self.shape.format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.format_byte_range(); + unchecked::read_at(self.data, range.start) } pub fn region_list_offset(&self) -> Offset32 { - let range = self.shape.region_list_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.region_list_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`region_list_offset`][Self::region_list_offset]. @@ -260,13 +252,13 @@ impl<'a> MultiItemVariationStore<'a> { } pub fn variation_data_count(&self) -> u16 { - let range = self.shape.variation_data_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.variation_data_count_byte_range(); + unchecked::read_at(self.data, range.start) } pub fn variation_data_offsets(&self) -> &'a [BigEndian] { - let range = self.shape.variation_data_offsets_byte_range(); - self.data.read_array(range).unwrap() + let range = self.variation_data_offsets_byte_range(); + unchecked::read_array(self.data, range) } /// A dynamically resolving wrapper for [`variation_data_offsets`][Self::variation_data_offsets]. @@ -322,23 +314,9 @@ impl<'a> std::fmt::Debug for MultiItemVariationStore<'a> { #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct SparseVariationRegionListMarker { - region_offsets_byte_len: usize, -} - -impl SparseVariationRegionListMarker { - pub fn region_count_byte_range(&self) -> Range { - let start = 0; - start..start + u16::RAW_BYTE_LEN - } - - pub fn region_offsets_byte_range(&self) -> Range { - let start = self.region_count_byte_range().end; - start..start + self.region_offsets_byte_len - } -} +pub struct SparseVariationRegionListMarker; -impl MinByteRange for SparseVariationRegionListMarker { +impl<'a> MinByteRange for SparseVariationRegionList<'a> { fn min_byte_range(&self) -> Range { 0..self.region_offsets_byte_range().end } @@ -346,30 +324,43 @@ impl MinByteRange for SparseVariationRegionListMarker { impl<'a> FontRead<'a> for SparseVariationRegionList<'a> { fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - let region_count: u16 = cursor.read()?; - let region_offsets_byte_len = (region_count as usize) - .checked_mul(Offset32::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(region_offsets_byte_len); - cursor.finish(SparseVariationRegionListMarker { - region_offsets_byte_len, + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, }) } } -pub type SparseVariationRegionList<'a> = TableRef<'a, SparseVariationRegionListMarker>; +pub type SparseVariationRegionList<'a> = TableRef<'a, SparseVariationRegionListMarker, ()>; #[allow(clippy::needless_lifetimes)] impl<'a> SparseVariationRegionList<'a> { + fn region_offsets_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.region_count()) as usize) + .checked_mul(Offset32::RAW_BYTE_LEN) + .unwrap() + } + + pub fn region_count_byte_range(&self) -> Range { + let start = 0; + start..start + u16::RAW_BYTE_LEN + } + + pub fn region_offsets_byte_range(&self) -> Range { + let start = self.region_count_byte_range().end; + start..start + self.region_offsets_byte_len(start) + } + pub fn region_count(&self) -> u16 { - let range = self.shape.region_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.region_count_byte_range(); + unchecked::read_at(self.data, range.start) } pub fn region_offsets(&self) -> &'a [BigEndian] { - let range = self.shape.region_offsets_byte_range(); - self.data.read_array(range).unwrap() + let range = self.region_offsets_byte_range(); + unchecked::read_array(self.data, range) } /// A dynamically resolving wrapper for [`region_offsets`][Self::region_offsets]. @@ -417,23 +408,9 @@ impl<'a> std::fmt::Debug for SparseVariationRegionList<'a> { #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct SparseVariationRegionMarker { - region_axis_offsets_byte_len: usize, -} +pub struct SparseVariationRegionMarker; -impl SparseVariationRegionMarker { - pub fn region_axis_count_byte_range(&self) -> Range { - let start = 0; - start..start + u16::RAW_BYTE_LEN - } - - pub fn region_axis_offsets_byte_range(&self) -> Range { - let start = self.region_axis_count_byte_range().end; - start..start + self.region_axis_offsets_byte_len - } -} - -impl MinByteRange for SparseVariationRegionMarker { +impl<'a> MinByteRange for SparseVariationRegion<'a> { fn min_byte_range(&self) -> Range { 0..self.region_axis_offsets_byte_range().end } @@ -441,30 +418,43 @@ impl MinByteRange for SparseVariationRegionMarker { impl<'a> FontRead<'a> for SparseVariationRegion<'a> { fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - let region_axis_count: u16 = cursor.read()?; - let region_axis_offsets_byte_len = (region_axis_count as usize) - .checked_mul(SparseRegionAxisCoordinates::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(region_axis_offsets_byte_len); - cursor.finish(SparseVariationRegionMarker { - region_axis_offsets_byte_len, + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, }) } } -pub type SparseVariationRegion<'a> = TableRef<'a, SparseVariationRegionMarker>; +pub type SparseVariationRegion<'a> = TableRef<'a, SparseVariationRegionMarker, ()>; #[allow(clippy::needless_lifetimes)] impl<'a> SparseVariationRegion<'a> { + fn region_axis_offsets_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.region_axis_count()) as usize) + .checked_mul(SparseRegionAxisCoordinates::RAW_BYTE_LEN) + .unwrap() + } + + pub fn region_axis_count_byte_range(&self) -> Range { + let start = 0; + start..start + u16::RAW_BYTE_LEN + } + + pub fn region_axis_offsets_byte_range(&self) -> Range { + let start = self.region_axis_count_byte_range().end; + start..start + self.region_axis_offsets_byte_len(start) + } + pub fn region_axis_count(&self) -> u16 { - let range = self.shape.region_axis_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.region_axis_count_byte_range(); + unchecked::read_at(self.data, range.start) } pub fn region_axis_offsets(&self) -> &'a [SparseRegionAxisCoordinates] { - let range = self.shape.region_axis_offsets_byte_range(); - self.data.read_array(range).unwrap() + let range = self.region_axis_offsets_byte_range(); + unchecked::read_array(self.data, range) } } @@ -553,12 +543,42 @@ impl Format for MultiItemVariationDataMarker { #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct MultiItemVariationDataMarker { - region_indices_byte_len: usize, - raw_delta_sets_byte_len: usize, +pub struct MultiItemVariationDataMarker; + +impl<'a> MinByteRange for MultiItemVariationData<'a> { + fn min_byte_range(&self) -> Range { + 0..self.raw_delta_sets_byte_range().end + } +} + +impl<'a> FontRead<'a> for MultiItemVariationData<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } } -impl MultiItemVariationDataMarker { +pub type MultiItemVariationData<'a> = TableRef<'a, MultiItemVariationDataMarker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> MultiItemVariationData<'a> { + fn region_indices_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.region_index_count()) as usize) + .checked_mul(u16::RAW_BYTE_LEN) + .unwrap() + } + fn raw_delta_sets_byte_len(&self, start: usize) -> usize { + let _ = start; + { + let remaining = self.data.len().saturating_sub(start); + remaining / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN + } + } + pub fn format_byte_range(&self) -> Range { let start = 0; start..start + u8::RAW_BYTE_LEN @@ -571,62 +591,32 @@ impl MultiItemVariationDataMarker { pub fn region_indices_byte_range(&self) -> Range { let start = self.region_index_count_byte_range().end; - start..start + self.region_indices_byte_len + start..start + self.region_indices_byte_len(start) } pub fn raw_delta_sets_byte_range(&self) -> Range { let start = self.region_indices_byte_range().end; - start..start + self.raw_delta_sets_byte_len - } -} - -impl MinByteRange for MultiItemVariationDataMarker { - fn min_byte_range(&self) -> Range { - 0..self.raw_delta_sets_byte_range().end + start..start + self.raw_delta_sets_byte_len(start) } -} - -impl<'a> FontRead<'a> for MultiItemVariationData<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - let region_index_count: u16 = cursor.read()?; - let region_indices_byte_len = (region_index_count as usize) - .checked_mul(u16::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(region_indices_byte_len); - let raw_delta_sets_byte_len = - cursor.remaining_bytes() / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN; - cursor.advance_by(raw_delta_sets_byte_len); - cursor.finish(MultiItemVariationDataMarker { - region_indices_byte_len, - raw_delta_sets_byte_len, - }) - } -} - -pub type MultiItemVariationData<'a> = TableRef<'a, MultiItemVariationDataMarker>; -#[allow(clippy::needless_lifetimes)] -impl<'a> MultiItemVariationData<'a> { pub fn format(&self) -> u8 { - let range = self.shape.format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.format_byte_range(); + unchecked::read_at(self.data, range.start) } pub fn region_index_count(&self) -> u16 { - let range = self.shape.region_index_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.region_index_count_byte_range(); + unchecked::read_at(self.data, range.start) } pub fn region_indices(&self) -> &'a [BigEndian] { - let range = self.shape.region_indices_byte_range(); - self.data.read_array(range).unwrap() + let range = self.region_indices_byte_range(); + unchecked::read_array(self.data, range) } pub fn raw_delta_sets(&self) -> &'a [u8] { - let range = self.shape.raw_delta_sets_byte_range(); - self.data.read_array(range).unwrap() + let range = self.raw_delta_sets_byte_range(); + unchecked::read_array(self.data, range) } } @@ -656,23 +646,9 @@ impl<'a> std::fmt::Debug for MultiItemVariationData<'a> { #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct ConditionListMarker { - condition_offsets_byte_len: usize, -} +pub struct ConditionListMarker; -impl ConditionListMarker { - pub fn condition_count_byte_range(&self) -> Range { - let start = 0; - start..start + u32::RAW_BYTE_LEN - } - - pub fn condition_offsets_byte_range(&self) -> Range { - let start = self.condition_count_byte_range().end; - start..start + self.condition_offsets_byte_len - } -} - -impl MinByteRange for ConditionListMarker { +impl<'a> MinByteRange for ConditionList<'a> { fn min_byte_range(&self) -> Range { 0..self.condition_offsets_byte_range().end } @@ -680,30 +656,43 @@ impl MinByteRange for ConditionListMarker { impl<'a> FontRead<'a> for ConditionList<'a> { fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - let condition_count: u32 = cursor.read()?; - let condition_offsets_byte_len = (condition_count as usize) - .checked_mul(Offset32::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(condition_offsets_byte_len); - cursor.finish(ConditionListMarker { - condition_offsets_byte_len, + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, }) } } -pub type ConditionList<'a> = TableRef<'a, ConditionListMarker>; +pub type ConditionList<'a> = TableRef<'a, ConditionListMarker, ()>; #[allow(clippy::needless_lifetimes)] impl<'a> ConditionList<'a> { + fn condition_offsets_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.condition_count()) as usize) + .checked_mul(Offset32::RAW_BYTE_LEN) + .unwrap() + } + + pub fn condition_count_byte_range(&self) -> Range { + let start = 0; + start..start + u32::RAW_BYTE_LEN + } + + pub fn condition_offsets_byte_range(&self) -> Range { + let start = self.condition_count_byte_range().end; + start..start + self.condition_offsets_byte_len(start) + } + pub fn condition_count(&self) -> u32 { - let range = self.shape.condition_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.condition_count_byte_range(); + unchecked::read_at(self.data, range.start) } pub fn condition_offsets(&self) -> &'a [BigEndian] { - let range = self.shape.condition_offsets_byte_range(); - self.data.read_array(range).unwrap() + let range = self.condition_offsets_byte_range(); + unchecked::read_array(self.data, range) } /// A dynamically resolving wrapper for [`condition_offsets`][Self::condition_offsets]. diff --git a/read-fonts/generated/generated_variations.rs b/read-fonts/generated/generated_variations.rs index cd0733183..a4532b44f 100644 --- a/read-fonts/generated/generated_variations.rs +++ b/read-fonts/generated/generated_variations.rs @@ -8,40 +8,9 @@ use crate::codegen_prelude::*; /// [TupleVariationHeader](https://learn.microsoft.com/en-us/typography/opentype/spec/otvarcommonformats#tuplevariationheader) #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct TupleVariationHeaderMarker { - peak_tuple_byte_len: usize, - intermediate_start_tuple_byte_len: usize, - intermediate_end_tuple_byte_len: usize, -} - -impl TupleVariationHeaderMarker { - pub fn variation_data_size_byte_range(&self) -> Range { - let start = 0; - start..start + u16::RAW_BYTE_LEN - } - - pub fn tuple_index_byte_range(&self) -> Range { - let start = self.variation_data_size_byte_range().end; - start..start + TupleIndex::RAW_BYTE_LEN - } - - pub fn peak_tuple_byte_range(&self) -> Range { - let start = self.tuple_index_byte_range().end; - start..start + self.peak_tuple_byte_len - } +pub struct TupleVariationHeaderMarker; - pub fn intermediate_start_tuple_byte_range(&self) -> Range { - let start = self.peak_tuple_byte_range().end; - start..start + self.intermediate_start_tuple_byte_len - } - - pub fn intermediate_end_tuple_byte_range(&self) -> Range { - let start = self.intermediate_start_tuple_byte_range().end; - start..start + self.intermediate_end_tuple_byte_len - } -} - -impl MinByteRange for TupleVariationHeaderMarker { +impl<'a> MinByteRange for TupleVariationHeader<'a> { fn min_byte_range(&self) -> Range { 0..self.intermediate_end_tuple_byte_range().end } @@ -53,28 +22,11 @@ impl ReadArgs for TupleVariationHeader<'_> { impl<'a> FontReadWithArgs<'a> for TupleVariationHeader<'a> { fn read_with_args(data: FontData<'a>, args: &u16) -> Result { - let axis_count = *args; - let mut cursor = data.cursor(); - cursor.advance::(); - let tuple_index: TupleIndex = cursor.read()?; - let peak_tuple_byte_len = (TupleIndex::tuple_len(tuple_index, axis_count, 0_usize)) - .checked_mul(F2Dot14::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(peak_tuple_byte_len); - let intermediate_start_tuple_byte_len = - (TupleIndex::tuple_len(tuple_index, axis_count, 1_usize)) - .checked_mul(F2Dot14::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(intermediate_start_tuple_byte_len); - let intermediate_end_tuple_byte_len = - (TupleIndex::tuple_len(tuple_index, axis_count, 1_usize)) - .checked_mul(F2Dot14::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(intermediate_end_tuple_byte_len); - cursor.finish(TupleVariationHeaderMarker { - peak_tuple_byte_len, - intermediate_start_tuple_byte_len, - intermediate_end_tuple_byte_len, + let args = *args; + Ok(TableRef { + args, + data, + _marker: std::marker::PhantomData, }) } } @@ -91,22 +43,70 @@ impl<'a> TupleVariationHeader<'a> { } /// [TupleVariationHeader](https://learn.microsoft.com/en-us/typography/opentype/spec/otvarcommonformats#tuplevariationheader) -pub type TupleVariationHeader<'a> = TableRef<'a, TupleVariationHeaderMarker>; +pub type TupleVariationHeader<'a> = TableRef<'a, TupleVariationHeaderMarker, u16>; #[allow(clippy::needless_lifetimes)] impl<'a> TupleVariationHeader<'a> { + fn peak_tuple_byte_len(&self, start: usize) -> usize { + let _ = start; + (TupleIndex::tuple_len(self.tuple_index(), self.args, 0_usize)) + .checked_mul(F2Dot14::RAW_BYTE_LEN) + .unwrap() + } + fn intermediate_start_tuple_byte_len(&self, start: usize) -> usize { + let _ = start; + (TupleIndex::tuple_len(self.tuple_index(), self.args, 1_usize)) + .checked_mul(F2Dot14::RAW_BYTE_LEN) + .unwrap() + } + fn intermediate_end_tuple_byte_len(&self, start: usize) -> usize { + let _ = start; + (TupleIndex::tuple_len(self.tuple_index(), self.args, 1_usize)) + .checked_mul(F2Dot14::RAW_BYTE_LEN) + .unwrap() + } + + pub fn variation_data_size_byte_range(&self) -> Range { + let start = 0; + start..start + u16::RAW_BYTE_LEN + } + + pub fn tuple_index_byte_range(&self) -> Range { + let start = self.variation_data_size_byte_range().end; + start..start + TupleIndex::RAW_BYTE_LEN + } + + pub fn peak_tuple_byte_range(&self) -> Range { + let start = self.tuple_index_byte_range().end; + start..start + self.peak_tuple_byte_len(start) + } + + pub fn intermediate_start_tuple_byte_range(&self) -> Range { + let start = self.peak_tuple_byte_range().end; + start..start + self.intermediate_start_tuple_byte_len(start) + } + + pub fn intermediate_end_tuple_byte_range(&self) -> Range { + let start = self.intermediate_start_tuple_byte_range().end; + start..start + self.intermediate_end_tuple_byte_len(start) + } + /// The size in bytes of the serialized data for this tuple /// variation table. pub fn variation_data_size(&self) -> u16 { - let range = self.shape.variation_data_size_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.variation_data_size_byte_range(); + unchecked::read_at(self.data, range.start) } /// A packed field. The high 4 bits are flags (see below). The low /// 12 bits are an index into a shared tuple records array. pub fn tuple_index(&self) -> TupleIndex { - let range = self.shape.tuple_index_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.tuple_index_byte_range(); + unchecked::read_at(self.data, range.start) + } + + pub(crate) fn axis_count(&self) -> u16 { + self.args } } @@ -216,11 +216,36 @@ impl Format for DeltaSetIndexMapFormat0Marker { /// The [DeltaSetIndexMap](https://learn.microsoft.com/en-us/typography/opentype/spec/otvarcommonformats#associating-target-items-to-variation-data) table format 0 #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct DeltaSetIndexMapFormat0Marker { - map_data_byte_len: usize, +pub struct DeltaSetIndexMapFormat0Marker; + +impl<'a> MinByteRange for DeltaSetIndexMapFormat0<'a> { + fn min_byte_range(&self) -> Range { + 0..self.map_data_byte_range().end + } } -impl DeltaSetIndexMapFormat0Marker { +impl<'a> FontRead<'a> for DeltaSetIndexMapFormat0<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// The [DeltaSetIndexMap](https://learn.microsoft.com/en-us/typography/opentype/spec/otvarcommonformats#associating-target-items-to-variation-data) table format 0 +pub type DeltaSetIndexMapFormat0<'a> = TableRef<'a, DeltaSetIndexMapFormat0Marker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> DeltaSetIndexMapFormat0<'a> { + fn map_data_byte_len(&self, start: usize) -> usize { + let _ = start; + (EntryFormat::map_size(self.entry_format(), self.map_count())) + .checked_mul(u8::RAW_BYTE_LEN) + .unwrap() + } + pub fn format_byte_range(&self) -> Range { let start = 0; start..start + u8::RAW_BYTE_LEN @@ -238,58 +263,32 @@ impl DeltaSetIndexMapFormat0Marker { pub fn map_data_byte_range(&self) -> Range { let start = self.map_count_byte_range().end; - start..start + self.map_data_byte_len + start..start + self.map_data_byte_len(start) } -} -impl MinByteRange for DeltaSetIndexMapFormat0Marker { - fn min_byte_range(&self) -> Range { - 0..self.map_data_byte_range().end - } -} - -impl<'a> FontRead<'a> for DeltaSetIndexMapFormat0<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - let entry_format: EntryFormat = cursor.read()?; - let map_count: u16 = cursor.read()?; - let map_data_byte_len = (EntryFormat::map_size(entry_format, map_count)) - .checked_mul(u8::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(map_data_byte_len); - cursor.finish(DeltaSetIndexMapFormat0Marker { map_data_byte_len }) - } -} - -/// The [DeltaSetIndexMap](https://learn.microsoft.com/en-us/typography/opentype/spec/otvarcommonformats#associating-target-items-to-variation-data) table format 0 -pub type DeltaSetIndexMapFormat0<'a> = TableRef<'a, DeltaSetIndexMapFormat0Marker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> DeltaSetIndexMapFormat0<'a> { /// DeltaSetIndexMap format: set to 0. pub fn format(&self) -> u8 { - let range = self.shape.format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.format_byte_range(); + unchecked::read_at(self.data, range.start) } /// A packed field that describes the compressed representation of /// delta-set indices. See details below. pub fn entry_format(&self) -> EntryFormat { - let range = self.shape.entry_format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.entry_format_byte_range(); + unchecked::read_at(self.data, range.start) } /// The number of mapping entries. pub fn map_count(&self) -> u16 { - let range = self.shape.map_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.map_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// The delta-set index mapping data. See details below. pub fn map_data(&self) -> &'a [u8] { - let range = self.shape.map_data_byte_range(); - self.data.read_array(range).unwrap() + let range = self.map_data_byte_range(); + unchecked::read_array(self.data, range) } } @@ -324,11 +323,36 @@ impl Format for DeltaSetIndexMapFormat1Marker { /// The [DeltaSetIndexMap](https://learn.microsoft.com/en-us/typography/opentype/spec/otvarcommonformats#associating-target-items-to-variation-data) table format 1 #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct DeltaSetIndexMapFormat1Marker { - map_data_byte_len: usize, +pub struct DeltaSetIndexMapFormat1Marker; + +impl<'a> MinByteRange for DeltaSetIndexMapFormat1<'a> { + fn min_byte_range(&self) -> Range { + 0..self.map_data_byte_range().end + } } -impl DeltaSetIndexMapFormat1Marker { +impl<'a> FontRead<'a> for DeltaSetIndexMapFormat1<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// The [DeltaSetIndexMap](https://learn.microsoft.com/en-us/typography/opentype/spec/otvarcommonformats#associating-target-items-to-variation-data) table format 1 +pub type DeltaSetIndexMapFormat1<'a> = TableRef<'a, DeltaSetIndexMapFormat1Marker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> DeltaSetIndexMapFormat1<'a> { + fn map_data_byte_len(&self, start: usize) -> usize { + let _ = start; + (EntryFormat::map_size(self.entry_format(), self.map_count())) + .checked_mul(u8::RAW_BYTE_LEN) + .unwrap() + } + pub fn format_byte_range(&self) -> Range { let start = 0; start..start + u8::RAW_BYTE_LEN @@ -346,58 +370,32 @@ impl DeltaSetIndexMapFormat1Marker { pub fn map_data_byte_range(&self) -> Range { let start = self.map_count_byte_range().end; - start..start + self.map_data_byte_len - } -} - -impl MinByteRange for DeltaSetIndexMapFormat1Marker { - fn min_byte_range(&self) -> Range { - 0..self.map_data_byte_range().end - } -} - -impl<'a> FontRead<'a> for DeltaSetIndexMapFormat1<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - let entry_format: EntryFormat = cursor.read()?; - let map_count: u32 = cursor.read()?; - let map_data_byte_len = (EntryFormat::map_size(entry_format, map_count)) - .checked_mul(u8::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(map_data_byte_len); - cursor.finish(DeltaSetIndexMapFormat1Marker { map_data_byte_len }) + start..start + self.map_data_byte_len(start) } -} -/// The [DeltaSetIndexMap](https://learn.microsoft.com/en-us/typography/opentype/spec/otvarcommonformats#associating-target-items-to-variation-data) table format 1 -pub type DeltaSetIndexMapFormat1<'a> = TableRef<'a, DeltaSetIndexMapFormat1Marker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> DeltaSetIndexMapFormat1<'a> { /// DeltaSetIndexMap format: set to 1. pub fn format(&self) -> u8 { - let range = self.shape.format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.format_byte_range(); + unchecked::read_at(self.data, range.start) } /// A packed field that describes the compressed representation of /// delta-set indices. See details below. pub fn entry_format(&self) -> EntryFormat { - let range = self.shape.entry_format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.entry_format_byte_range(); + unchecked::read_at(self.data, range.start) } /// The number of mapping entries. pub fn map_count(&self) -> u32 { - let range = self.shape.map_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.map_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// The delta-set index mapping data. See details below. pub fn map_data(&self) -> &'a [u8] { - let range = self.shape.map_data_byte_range(); - self.data.read_array(range).unwrap() + let range = self.map_data_byte_range(); + unchecked::read_array(self.data, range) } } @@ -828,28 +826,9 @@ impl<'a> From for FieldType<'a> { /// The [VariationRegionList](https://learn.microsoft.com/en-us/typography/opentype/spec/otvarcommonformats#variation-regions) table #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct VariationRegionListMarker { - variation_regions_byte_len: usize, -} - -impl VariationRegionListMarker { - pub fn axis_count_byte_range(&self) -> Range { - let start = 0; - start..start + u16::RAW_BYTE_LEN - } - - pub fn region_count_byte_range(&self) -> Range { - let start = self.axis_count_byte_range().end; - start..start + u16::RAW_BYTE_LEN - } +pub struct VariationRegionListMarker; - pub fn variation_regions_byte_range(&self) -> Range { - let start = self.region_count_byte_range().end; - start..start + self.variation_regions_byte_len - } -} - -impl MinByteRange for VariationRegionListMarker { +impl<'a> MinByteRange for VariationRegionList<'a> { fn min_byte_range(&self) -> Range { 0..self.variation_regions_byte_range().end } @@ -857,42 +836,61 @@ impl MinByteRange for VariationRegionListMarker { impl<'a> FontRead<'a> for VariationRegionList<'a> { fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - let axis_count: u16 = cursor.read()?; - let region_count: u16 = cursor.read()?; - let variation_regions_byte_len = (region_count as usize) - .checked_mul(::compute_size(&axis_count)?) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(variation_regions_byte_len); - cursor.finish(VariationRegionListMarker { - variation_regions_byte_len, + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, }) } } /// The [VariationRegionList](https://learn.microsoft.com/en-us/typography/opentype/spec/otvarcommonformats#variation-regions) table -pub type VariationRegionList<'a> = TableRef<'a, VariationRegionListMarker>; +pub type VariationRegionList<'a> = TableRef<'a, VariationRegionListMarker, ()>; #[allow(clippy::needless_lifetimes)] impl<'a> VariationRegionList<'a> { + fn variation_regions_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.region_count()) as usize) + .checked_mul( + ::compute_size(&self.axis_count()).unwrap(), + ) + .unwrap() + } + + pub fn axis_count_byte_range(&self) -> Range { + let start = 0; + start..start + u16::RAW_BYTE_LEN + } + + pub fn region_count_byte_range(&self) -> Range { + let start = self.axis_count_byte_range().end; + start..start + u16::RAW_BYTE_LEN + } + + pub fn variation_regions_byte_range(&self) -> Range { + let start = self.region_count_byte_range().end; + start..start + self.variation_regions_byte_len(start) + } + /// The number of variation axes for this font. This must be the /// same number as axisCount in the 'fvar' table. pub fn axis_count(&self) -> u16 { - let range = self.shape.axis_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.axis_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// The number of variation region tables in the variation region /// list. Must be less than 32,768. pub fn region_count(&self) -> u16 { - let range = self.shape.region_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.region_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Array of variation regions. pub fn variation_regions(&self) -> ComputedArray<'a, VariationRegion<'a>> { - let range = self.shape.variation_regions_byte_range(); - self.data.read_with_args(range, &self.axis_count()).unwrap() + let range = self.variation_regions_byte_range(); + unchecked::read_with_args(self.data, range, &self.axis_count()) } } @@ -1053,11 +1051,36 @@ impl<'a> SomeRecord<'a> for RegionAxisCoordinates { /// The [ItemVariationStore](https://learn.microsoft.com/en-us/typography/opentype/spec/otvarcommonformats#item-variation-store-header-and-item-variation-data-subtables) table #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct ItemVariationStoreMarker { - item_variation_data_offsets_byte_len: usize, +pub struct ItemVariationStoreMarker; + +impl<'a> MinByteRange for ItemVariationStore<'a> { + fn min_byte_range(&self) -> Range { + 0..self.item_variation_data_offsets_byte_range().end + } +} + +impl<'a> FontRead<'a> for ItemVariationStore<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } } -impl ItemVariationStoreMarker { +/// The [ItemVariationStore](https://learn.microsoft.com/en-us/typography/opentype/spec/otvarcommonformats#item-variation-store-header-and-item-variation-data-subtables) table +pub type ItemVariationStore<'a> = TableRef<'a, ItemVariationStoreMarker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> ItemVariationStore<'a> { + fn item_variation_data_offsets_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.item_variation_data_count()) as usize) + .checked_mul(Offset32::RAW_BYTE_LEN) + .unwrap() + } + pub fn format_byte_range(&self) -> Range { let start = 0; start..start + u16::RAW_BYTE_LEN @@ -1075,48 +1098,20 @@ impl ItemVariationStoreMarker { pub fn item_variation_data_offsets_byte_range(&self) -> Range { let start = self.item_variation_data_count_byte_range().end; - start..start + self.item_variation_data_offsets_byte_len - } -} - -impl MinByteRange for ItemVariationStoreMarker { - fn min_byte_range(&self) -> Range { - 0..self.item_variation_data_offsets_byte_range().end - } -} - -impl<'a> FontRead<'a> for ItemVariationStore<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - let item_variation_data_count: u16 = cursor.read()?; - let item_variation_data_offsets_byte_len = (item_variation_data_count as usize) - .checked_mul(Offset32::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(item_variation_data_offsets_byte_len); - cursor.finish(ItemVariationStoreMarker { - item_variation_data_offsets_byte_len, - }) + start..start + self.item_variation_data_offsets_byte_len(start) } -} - -/// The [ItemVariationStore](https://learn.microsoft.com/en-us/typography/opentype/spec/otvarcommonformats#item-variation-store-header-and-item-variation-data-subtables) table -pub type ItemVariationStore<'a> = TableRef<'a, ItemVariationStoreMarker>; -#[allow(clippy::needless_lifetimes)] -impl<'a> ItemVariationStore<'a> { /// Format— set to 1 pub fn format(&self) -> u16 { - let range = self.shape.format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Offset in bytes from the start of the item variation store to /// the variation region list. pub fn variation_region_list_offset(&self) -> Offset32 { - let range = self.shape.variation_region_list_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.variation_region_list_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`variation_region_list_offset`][Self::variation_region_list_offset]. @@ -1127,15 +1122,15 @@ impl<'a> ItemVariationStore<'a> { /// The number of item variation data subtables. pub fn item_variation_data_count(&self) -> u16 { - let range = self.shape.item_variation_data_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.item_variation_data_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Offsets in bytes from the start of the item variation store to /// each item variation data subtable. pub fn item_variation_data_offsets(&self) -> &'a [BigEndian>] { - let range = self.shape.item_variation_data_offsets_byte_range(); - self.data.read_array(range).unwrap() + let range = self.item_variation_data_offsets_byte_range(); + unchecked::read_array(self.data, range) } /// A dynamically resolving wrapper for [`item_variation_data_offsets`][Self::item_variation_data_offsets]. @@ -1197,12 +1192,46 @@ impl<'a> std::fmt::Debug for ItemVariationStore<'a> { /// The [ItemVariationData](https://learn.microsoft.com/en-us/typography/opentype/spec/otvarcommonformats#item-variation-store-header-and-item-variation-data-subtables) subtable #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct ItemVariationDataMarker { - region_indexes_byte_len: usize, - delta_sets_byte_len: usize, +pub struct ItemVariationDataMarker; + +impl<'a> MinByteRange for ItemVariationData<'a> { + fn min_byte_range(&self) -> Range { + 0..self.delta_sets_byte_range().end + } } -impl ItemVariationDataMarker { +impl<'a> FontRead<'a> for ItemVariationData<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// The [ItemVariationData](https://learn.microsoft.com/en-us/typography/opentype/spec/otvarcommonformats#item-variation-store-header-and-item-variation-data-subtables) subtable +pub type ItemVariationData<'a> = TableRef<'a, ItemVariationDataMarker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> ItemVariationData<'a> { + fn region_indexes_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.region_index_count()) as usize) + .checked_mul(u16::RAW_BYTE_LEN) + .unwrap() + } + fn delta_sets_byte_len(&self, start: usize) -> usize { + let _ = start; + (ItemVariationData::delta_sets_len( + self.item_count(), + self.word_delta_count(), + self.region_index_count(), + )) + .checked_mul(u8::RAW_BYTE_LEN) + .unwrap() + } + pub fn item_count_byte_range(&self) -> Range { let start = 0; start..start + u16::RAW_BYTE_LEN @@ -1220,77 +1249,43 @@ impl ItemVariationDataMarker { pub fn region_indexes_byte_range(&self) -> Range { let start = self.region_index_count_byte_range().end; - start..start + self.region_indexes_byte_len + start..start + self.region_indexes_byte_len(start) } pub fn delta_sets_byte_range(&self) -> Range { let start = self.region_indexes_byte_range().end; - start..start + self.delta_sets_byte_len + start..start + self.delta_sets_byte_len(start) } -} -impl MinByteRange for ItemVariationDataMarker { - fn min_byte_range(&self) -> Range { - 0..self.delta_sets_byte_range().end - } -} - -impl<'a> FontRead<'a> for ItemVariationData<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - let item_count: u16 = cursor.read()?; - let word_delta_count: u16 = cursor.read()?; - let region_index_count: u16 = cursor.read()?; - let region_indexes_byte_len = (region_index_count as usize) - .checked_mul(u16::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(region_indexes_byte_len); - let delta_sets_byte_len = - (ItemVariationData::delta_sets_len(item_count, word_delta_count, region_index_count)) - .checked_mul(u8::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(delta_sets_byte_len); - cursor.finish(ItemVariationDataMarker { - region_indexes_byte_len, - delta_sets_byte_len, - }) - } -} - -/// The [ItemVariationData](https://learn.microsoft.com/en-us/typography/opentype/spec/otvarcommonformats#item-variation-store-header-and-item-variation-data-subtables) subtable -pub type ItemVariationData<'a> = TableRef<'a, ItemVariationDataMarker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> ItemVariationData<'a> { /// The number of delta sets for distinct items. pub fn item_count(&self) -> u16 { - let range = self.shape.item_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.item_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// A packed field: the high bit is a flag—see details below. pub fn word_delta_count(&self) -> u16 { - let range = self.shape.word_delta_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.word_delta_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// The number of variation regions referenced. pub fn region_index_count(&self) -> u16 { - let range = self.shape.region_index_count_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.region_index_count_byte_range(); + unchecked::read_at(self.data, range.start) } /// Array of indices into the variation region list for the regions /// referenced by this item variation data table. pub fn region_indexes(&self) -> &'a [BigEndian] { - let range = self.shape.region_indexes_byte_range(); - self.data.read_array(range).unwrap() + let range = self.region_indexes_byte_range(); + unchecked::read_array(self.data, range) } /// Delta-set rows. pub fn delta_sets(&self) -> &'a [u8] { - let range = self.shape.delta_sets_byte_range(); - self.data.read_array(range).unwrap() + let range = self.delta_sets_byte_range(); + unchecked::read_array(self.data, range) } } diff --git a/read-fonts/generated/generated_vhea.rs b/read-fonts/generated/generated_vhea.rs index 9034afe35..658b768fe 100644 --- a/read-fonts/generated/generated_vhea.rs +++ b/read-fonts/generated/generated_vhea.rs @@ -8,9 +8,34 @@ use crate::codegen_prelude::*; /// The [vhea](https://docs.microsoft.com/en-us/typography/opentype/spec/vhea) Vertical Header Table #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct VheaMarker {} +pub struct VheaMarker; -impl VheaMarker { +impl<'a> MinByteRange for Vhea<'a> { + fn min_byte_range(&self) -> Range { + 0..self.number_of_long_ver_metrics_byte_range().end + } +} + +impl TopLevelTable for Vhea<'_> { + /// `vhea` + const TAG: Tag = Tag::new(b"vhea"); +} + +impl<'a> FontRead<'a> for Vhea<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// The [vhea](https://docs.microsoft.com/en-us/typography/opentype/spec/vhea) Vertical Header Table +pub type Vhea<'a> = TableRef<'a, VheaMarker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> Vhea<'a> { pub fn version_byte_range(&self) -> Range { let start = 0; start..start + Version16Dot16::RAW_BYTE_LEN @@ -95,129 +120,88 @@ impl VheaMarker { let start = self.metric_data_format_byte_range().end; start..start + u16::RAW_BYTE_LEN } -} -impl MinByteRange for VheaMarker { - fn min_byte_range(&self) -> Range { - 0..self.number_of_long_ver_metrics_byte_range().end - } -} - -impl TopLevelTable for Vhea<'_> { - /// `vhea` - const TAG: Tag = Tag::new(b"vhea"); -} - -impl<'a> FontRead<'a> for Vhea<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.finish(VheaMarker {}) - } -} - -/// The [vhea](https://docs.microsoft.com/en-us/typography/opentype/spec/vhea) Vertical Header Table -pub type Vhea<'a> = TableRef<'a, VheaMarker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> Vhea<'a> { /// The major/minor version (1, 1) pub fn version(&self) -> Version16Dot16 { - let range = self.shape.version_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.version_byte_range(); + unchecked::read_at(self.data, range.start) } /// Typographic ascent. pub fn ascender(&self) -> FWord { - let range = self.shape.ascender_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.ascender_byte_range(); + unchecked::read_at(self.data, range.start) } /// Typographic descent. pub fn descender(&self) -> FWord { - let range = self.shape.descender_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.descender_byte_range(); + unchecked::read_at(self.data, range.start) } /// Typographic line gap. Negative LineGap values are treated as /// zero in some legacy platform implementations. pub fn line_gap(&self) -> FWord { - let range = self.shape.line_gap_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.line_gap_byte_range(); + unchecked::read_at(self.data, range.start) } /// Maximum advance height value in 'vmtx' table. pub fn advance_height_max(&self) -> UfWord { - let range = self.shape.advance_height_max_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.advance_height_max_byte_range(); + unchecked::read_at(self.data, range.start) } /// Minimum top sidebearing value in 'vmtx' table for glyphs with /// contours (empty glyphs should be ignored). pub fn min_top_side_bearing(&self) -> FWord { - let range = self.shape.min_top_side_bearing_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.min_top_side_bearing_byte_range(); + unchecked::read_at(self.data, range.start) } /// Minimum bottom sidebearing value pub fn min_bottom_side_bearing(&self) -> FWord { - let range = self.shape.min_bottom_side_bearing_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.min_bottom_side_bearing_byte_range(); + unchecked::read_at(self.data, range.start) } /// Defined as max( tsb + (yMax-yMin)). pub fn y_max_extent(&self) -> FWord { - let range = self.shape.y_max_extent_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.y_max_extent_byte_range(); + unchecked::read_at(self.data, range.start) } /// Used to calculate the slope of the cursor (rise/run); 1 for /// vertical caret, 0 for horizontal. pub fn caret_slope_rise(&self) -> i16 { - let range = self.shape.caret_slope_rise_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.caret_slope_rise_byte_range(); + unchecked::read_at(self.data, range.start) } /// 0 for vertical caret, 1 for horizontal. pub fn caret_slope_run(&self) -> i16 { - let range = self.shape.caret_slope_run_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.caret_slope_run_byte_range(); + unchecked::read_at(self.data, range.start) } /// The amount by which a slanted highlight on a glyph needs to be /// shifted to produce the best appearance. Set to 0 for /// non-slanted fonts pub fn caret_offset(&self) -> i16 { - let range = self.shape.caret_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.caret_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// 0 for current format. pub fn metric_data_format(&self) -> i16 { - let range = self.shape.metric_data_format_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.metric_data_format_byte_range(); + unchecked::read_at(self.data, range.start) } /// Number of advance heights in the vertical metrics (`vmtx`) table. pub fn number_of_long_ver_metrics(&self) -> u16 { - let range = self.shape.number_of_long_ver_metrics_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.number_of_long_ver_metrics_byte_range(); + unchecked::read_at(self.data, range.start) } } diff --git a/read-fonts/generated/generated_vmtx.rs b/read-fonts/generated/generated_vmtx.rs index a57110389..8bdd461d4 100644 --- a/read-fonts/generated/generated_vmtx.rs +++ b/read-fonts/generated/generated_vmtx.rs @@ -8,24 +8,9 @@ use crate::codegen_prelude::*; /// The [vmtx (Vertical Metrics)](https://docs.microsoft.com/en-us/typography/opentype/spec/vmtx) table #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct VmtxMarker { - v_metrics_byte_len: usize, - top_side_bearings_byte_len: usize, -} +pub struct VmtxMarker; -impl VmtxMarker { - pub fn v_metrics_byte_range(&self) -> Range { - let start = 0; - start..start + self.v_metrics_byte_len - } - - pub fn top_side_bearings_byte_range(&self) -> Range { - let start = self.v_metrics_byte_range().end; - start..start + self.top_side_bearings_byte_len - } -} - -impl MinByteRange for VmtxMarker { +impl<'a> MinByteRange for Vmtx<'a> { fn min_byte_range(&self) -> Range { 0..self.top_side_bearings_byte_range().end } @@ -42,18 +27,11 @@ impl ReadArgs for Vmtx<'_> { impl<'a> FontReadWithArgs<'a> for Vmtx<'a> { fn read_with_args(data: FontData<'a>, args: &u16) -> Result { - let number_of_long_ver_metrics = *args; - let mut cursor = data.cursor(); - let v_metrics_byte_len = (number_of_long_ver_metrics as usize) - .checked_mul(LongMetric::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(v_metrics_byte_len); - let top_side_bearings_byte_len = - cursor.remaining_bytes() / i16::RAW_BYTE_LEN * i16::RAW_BYTE_LEN; - cursor.advance_by(top_side_bearings_byte_len); - cursor.finish(VmtxMarker { - v_metrics_byte_len, - top_side_bearings_byte_len, + let args = *args; + Ok(TableRef { + args, + data, + _marker: std::marker::PhantomData, }) } } @@ -70,21 +48,49 @@ impl<'a> Vmtx<'a> { } /// The [vmtx (Vertical Metrics)](https://docs.microsoft.com/en-us/typography/opentype/spec/vmtx) table -pub type Vmtx<'a> = TableRef<'a, VmtxMarker>; +pub type Vmtx<'a> = TableRef<'a, VmtxMarker, u16>; #[allow(clippy::needless_lifetimes)] impl<'a> Vmtx<'a> { + fn v_metrics_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.args) as usize) + .checked_mul(LongMetric::RAW_BYTE_LEN) + .unwrap() + } + fn top_side_bearings_byte_len(&self, start: usize) -> usize { + let _ = start; + { + let remaining = self.data.len().saturating_sub(start); + remaining / i16::RAW_BYTE_LEN * i16::RAW_BYTE_LEN + } + } + + pub fn v_metrics_byte_range(&self) -> Range { + let start = 0; + start..start + self.v_metrics_byte_len(start) + } + + pub fn top_side_bearings_byte_range(&self) -> Range { + let start = self.v_metrics_byte_range().end; + start..start + self.top_side_bearings_byte_len(start) + } + /// Paired advance height and top side bearing values for each /// glyph. Records are indexed by glyph ID. pub fn v_metrics(&self) -> &'a [LongMetric] { - let range = self.shape.v_metrics_byte_range(); - self.data.read_array(range).unwrap() + let range = self.v_metrics_byte_range(); + unchecked::read_array(self.data, range) } /// Top side bearings for glyph IDs greater than or equal to numberOfLongMetrics. pub fn top_side_bearings(&self) -> &'a [BigEndian] { - let range = self.shape.top_side_bearings_byte_range(); - self.data.read_array(range).unwrap() + let range = self.top_side_bearings_byte_range(); + unchecked::read_array(self.data, range) + } + + pub(crate) fn number_of_long_ver_metrics(&self) -> u16 { + self.args } } diff --git a/read-fonts/generated/generated_vorg.rs b/read-fonts/generated/generated_vorg.rs index d7ae485b1..9dcdd36dc 100644 --- a/read-fonts/generated/generated_vorg.rs +++ b/read-fonts/generated/generated_vorg.rs @@ -8,33 +8,9 @@ use crate::codegen_prelude::*; /// The [VORG (Vertical Origin)](https://docs.microsoft.com/en-us/typography/opentype/spec/vorg) table. #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct VorgMarker { - vert_origin_y_metrics_byte_len: usize, -} - -impl VorgMarker { - pub fn version_byte_range(&self) -> Range { - let start = 0; - start..start + MajorMinor::RAW_BYTE_LEN - } +pub struct VorgMarker; - pub fn default_vert_origin_y_byte_range(&self) -> Range { - let start = self.version_byte_range().end; - start..start + i16::RAW_BYTE_LEN - } - - pub fn num_vert_origin_y_metrics_byte_range(&self) -> Range { - let start = self.default_vert_origin_y_byte_range().end; - start..start + u16::RAW_BYTE_LEN - } - - pub fn vert_origin_y_metrics_byte_range(&self) -> Range { - let start = self.num_vert_origin_y_metrics_byte_range().end; - start..start + self.vert_origin_y_metrics_byte_len - } -} - -impl MinByteRange for VorgMarker { +impl<'a> MinByteRange for Vorg<'a> { fn min_byte_range(&self) -> Range { 0..self.vert_origin_y_metrics_byte_range().end } @@ -47,49 +23,70 @@ impl TopLevelTable for Vorg<'_> { impl<'a> FontRead<'a> for Vorg<'a> { fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - let num_vert_origin_y_metrics: u16 = cursor.read()?; - let vert_origin_y_metrics_byte_len = (num_vert_origin_y_metrics as usize) - .checked_mul(VertOriginYMetrics::RAW_BYTE_LEN) - .ok_or(ReadError::OutOfBounds)?; - cursor.advance_by(vert_origin_y_metrics_byte_len); - cursor.finish(VorgMarker { - vert_origin_y_metrics_byte_len, + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, }) } } /// The [VORG (Vertical Origin)](https://docs.microsoft.com/en-us/typography/opentype/spec/vorg) table. -pub type Vorg<'a> = TableRef<'a, VorgMarker>; +pub type Vorg<'a> = TableRef<'a, VorgMarker, ()>; #[allow(clippy::needless_lifetimes)] impl<'a> Vorg<'a> { + fn vert_origin_y_metrics_byte_len(&self, start: usize) -> usize { + let _ = start; + ((self.num_vert_origin_y_metrics()) as usize) + .checked_mul(VertOriginYMetrics::RAW_BYTE_LEN) + .unwrap() + } + + pub fn version_byte_range(&self) -> Range { + let start = 0; + start..start + MajorMinor::RAW_BYTE_LEN + } + + pub fn default_vert_origin_y_byte_range(&self) -> Range { + let start = self.version_byte_range().end; + start..start + i16::RAW_BYTE_LEN + } + + pub fn num_vert_origin_y_metrics_byte_range(&self) -> Range { + let start = self.default_vert_origin_y_byte_range().end; + start..start + u16::RAW_BYTE_LEN + } + + pub fn vert_origin_y_metrics_byte_range(&self) -> Range { + let start = self.num_vert_origin_y_metrics_byte_range().end; + start..start + self.vert_origin_y_metrics_byte_len(start) + } + /// Major/minor version number. Set to 1.0. pub fn version(&self) -> MajorMinor { - let range = self.shape.version_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.version_byte_range(); + unchecked::read_at(self.data, range.start) } /// The y coordinate of a glyph’s vertical origin, in the font’s design /// coordinate system, to be used if no entry is present for the glyph /// in the vertOriginYMetrics array. pub fn default_vert_origin_y(&self) -> i16 { - let range = self.shape.default_vert_origin_y_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.default_vert_origin_y_byte_range(); + unchecked::read_at(self.data, range.start) } /// Number of elements in the vertOriginYMetrics array. pub fn num_vert_origin_y_metrics(&self) -> u16 { - let range = self.shape.num_vert_origin_y_metrics_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.num_vert_origin_y_metrics_byte_range(); + unchecked::read_at(self.data, range.start) } /// Array of VertOriginYMetrics records, sorted by glyph ID. pub fn vert_origin_y_metrics(&self) -> &'a [VertOriginYMetrics] { - let range = self.shape.vert_origin_y_metrics_byte_range(); - self.data.read_array(range).unwrap() + let range = self.vert_origin_y_metrics_byte_range(); + unchecked::read_array(self.data, range) } } diff --git a/read-fonts/generated/generated_vvar.rs b/read-fonts/generated/generated_vvar.rs index be82f8056..12daf5059 100644 --- a/read-fonts/generated/generated_vvar.rs +++ b/read-fonts/generated/generated_vvar.rs @@ -8,9 +8,34 @@ use crate::codegen_prelude::*; /// The [VVAR (Vertical Metrics Variations)](https://docs.microsoft.com/en-us/typography/opentype/spec/vvar) table #[derive(Debug, Clone, Copy)] #[doc(hidden)] -pub struct VvarMarker {} +pub struct VvarMarker; -impl VvarMarker { +impl<'a> MinByteRange for Vvar<'a> { + fn min_byte_range(&self) -> Range { + 0..self.v_org_mapping_offset_byte_range().end + } +} + +impl TopLevelTable for Vvar<'_> { + /// `VVAR` + const TAG: Tag = Tag::new(b"VVAR"); +} + +impl<'a> FontRead<'a> for Vvar<'a> { + fn read(data: FontData<'a>) -> Result { + Ok(TableRef { + args: (), + data, + _marker: std::marker::PhantomData, + }) + } +} + +/// The [VVAR (Vertical Metrics Variations)](https://docs.microsoft.com/en-us/typography/opentype/spec/vvar) table +pub type Vvar<'a> = TableRef<'a, VvarMarker, ()>; + +#[allow(clippy::needless_lifetimes)] +impl<'a> Vvar<'a> { pub fn version_byte_range(&self) -> Range { let start = 0; start..start + MajorMinor::RAW_BYTE_LEN @@ -40,48 +65,18 @@ impl VvarMarker { let start = self.bsb_mapping_offset_byte_range().end; start..start + Offset32::RAW_BYTE_LEN } -} -impl MinByteRange for VvarMarker { - fn min_byte_range(&self) -> Range { - 0..self.v_org_mapping_offset_byte_range().end - } -} - -impl TopLevelTable for Vvar<'_> { - /// `VVAR` - const TAG: Tag = Tag::new(b"VVAR"); -} - -impl<'a> FontRead<'a> for Vvar<'a> { - fn read(data: FontData<'a>) -> Result { - let mut cursor = data.cursor(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.advance::(); - cursor.finish(VvarMarker {}) - } -} - -/// The [VVAR (Vertical Metrics Variations)](https://docs.microsoft.com/en-us/typography/opentype/spec/vvar) table -pub type Vvar<'a> = TableRef<'a, VvarMarker>; - -#[allow(clippy::needless_lifetimes)] -impl<'a> Vvar<'a> { /// Major version number of the horizontal metrics variations table — set to 1. /// Minor version number of the horizontal metrics variations table — set to 0. pub fn version(&self) -> MajorMinor { - let range = self.shape.version_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.version_byte_range(); + unchecked::read_at(self.data, range.start) } /// Offset in bytes from the start of this table to the item variation store table. pub fn item_variation_store_offset(&self) -> Offset32 { - let range = self.shape.item_variation_store_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.item_variation_store_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`item_variation_store_offset`][Self::item_variation_store_offset]. @@ -92,8 +87,8 @@ impl<'a> Vvar<'a> { /// Offset in bytes from the start of this table to the delta-set index mapping for advance heights (may be NULL). pub fn advance_height_mapping_offset(&self) -> Nullable { - let range = self.shape.advance_height_mapping_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.advance_height_mapping_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`advance_height_mapping_offset`][Self::advance_height_mapping_offset]. @@ -104,8 +99,8 @@ impl<'a> Vvar<'a> { /// Offset in bytes from the start of this table to the delta-set index mapping for top side bearings (may be NULL). pub fn tsb_mapping_offset(&self) -> Nullable { - let range = self.shape.tsb_mapping_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.tsb_mapping_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`tsb_mapping_offset`][Self::tsb_mapping_offset]. @@ -116,8 +111,8 @@ impl<'a> Vvar<'a> { /// Offset in bytes from the start of this table to the delta-set index mapping for bottom side bearings (may be NULL). pub fn bsb_mapping_offset(&self) -> Nullable { - let range = self.shape.bsb_mapping_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.bsb_mapping_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`bsb_mapping_offset`][Self::bsb_mapping_offset]. @@ -128,8 +123,8 @@ impl<'a> Vvar<'a> { /// Offset in bytes from the start of this table to the delta-set index mapping for Y coordinates of vertical origins (may be NULL). pub fn v_org_mapping_offset(&self) -> Nullable { - let range = self.shape.v_org_mapping_offset_byte_range(); - self.data.read_at(range.start).unwrap() + let range = self.v_org_mapping_offset_byte_range(); + unchecked::read_at(self.data, range.start) } /// Attempt to resolve [`v_org_mapping_offset`][Self::v_org_mapping_offset]. diff --git a/read-fonts/src/font_data.rs b/read-fonts/src/font_data.rs index fd83483ab..9395b9e35 100644 --- a/read-fonts/src/font_data.rs +++ b/read-fonts/src/font_data.rs @@ -60,6 +60,19 @@ impl<'a> FontData<'a> { self.bytes.get(pos..).map(|bytes| FontData { bytes }) } + /// Returns `self[pos..]` without bounds checks. + /// + /// # Safety + /// + /// `pos` must be within `self.bytes`. + #[allow(clippy::arithmetic_side_effects)] + pub(crate) unsafe fn split_off_unchecked(&self, pos: usize) -> FontData<'a> { + let len = self.bytes.len() - pos; + let ptr = self.bytes.as_ptr().add(pos); + let bytes = std::slice::from_raw_parts(ptr, len); + FontData { bytes } + } + /// returns self[..pos], and updates self to = self[pos..]; pub fn take_up_to(&mut self, pos: usize) -> Option> { if pos > self.len() { @@ -75,6 +88,19 @@ impl<'a> FontData<'a> { self.bytes.get(bounds).map(|bytes| FontData { bytes }) } + /// Return a subslice without bounds checks. + /// + /// # Safety + /// + /// `range` must be within `self.bytes`. + #[allow(clippy::arithmetic_side_effects)] + pub(crate) unsafe fn slice_unchecked(&self, range: Range) -> FontData<'a> { + let len = range.end - range.start; + let ptr = self.bytes.as_ptr().add(range.start); + let bytes = std::slice::from_raw_parts(ptr, len); + FontData { bytes } + } + /// Read a scalar at the provided location in the data. pub fn read_at(&self, offset: usize) -> Result { let end = offset @@ -86,6 +112,17 @@ impl<'a> FontData<'a> { .ok_or(ReadError::OutOfBounds) } + /// Read a scalar at the provided location in the data, without bounds checks. + /// + /// # Safety + /// + /// `offset..offset + T::RAW_BYTE_LEN` must be within `self.bytes`. + pub(crate) unsafe fn read_at_unchecked(&self, offset: usize) -> T { + let ptr = self.bytes.as_ptr().add(offset) as *const T::Raw; + let raw = ptr.read_unaligned(); + T::from_raw(raw) + } + /// Read a big-endian value at the provided location in the data. pub fn read_be_at(&self, offset: usize) -> Result, ReadError> { let end = offset @@ -97,6 +134,17 @@ impl<'a> FontData<'a> { .ok_or(ReadError::OutOfBounds) } + /// Read a big-endian value at the provided location in the data, without bounds checks. + /// + /// # Safety + /// + /// `offset..offset + T::RAW_BYTE_LEN` must be within `self.bytes`. + pub(crate) unsafe fn read_be_at_unchecked(&self, offset: usize) -> BigEndian { + let ptr = self.bytes.as_ptr().add(offset) as *const T::Raw; + let raw = ptr.read_unaligned(); + BigEndian::new(raw) + } + pub fn read_with_args(&self, range: Range, args: &T::Args) -> Result where T: FontReadWithArgs<'a>, @@ -106,6 +154,23 @@ impl<'a> FontData<'a> { .and_then(|data| T::read_with_args(data, args)) } + /// Read a value with args at the provided range, without bounds checks. + /// + /// # Safety + /// + /// `range` must be within `self.bytes`. + pub(crate) unsafe fn read_with_args_unchecked( + &self, + range: Range, + args: &T::Args, + ) -> Result + where + T: FontReadWithArgs<'a>, + { + let data = self.slice_unchecked(range); + T::read_with_args(data, args) + } + fn check_in_bounds(&self, offset: usize) -> Result<(), ReadError> { self.bytes .get(..offset) @@ -139,6 +204,20 @@ impl<'a> FontData<'a> { .map(bytemuck::from_bytes) } + /// Interpret the bytes at the provided offset as a reference to `T`, without bounds checks. + /// + /// # Safety + /// + /// `offset..offset + T::RAW_BYTE_LEN` must be within `self.bytes`, and the + /// type must have alignment 1 and no padding. + pub(crate) unsafe fn read_ref_unchecked( + &self, + offset: usize, + ) -> &'a T { + let ptr = self.bytes.as_ptr().add(offset) as *const T; + &*ptr + } + /// Interpret the bytes at the provided offset as a slice of `T`. /// /// Returns an error if `range` is out of bounds for the underlying data, @@ -172,6 +251,24 @@ impl<'a> FontData<'a> { Ok(bytemuck::cast_slice(bytes)) } + /// Interpret the bytes at the provided range as a slice of `T`, without bounds checks. + /// + /// # Safety + /// + /// `range` must be within `self.bytes`, must be a multiple of `T::RAW_BYTE_LEN`, + /// and the type must have alignment 1 and no padding. + #[allow(clippy::arithmetic_side_effects)] + pub(crate) unsafe fn read_array_unchecked( + &self, + range: Range, + ) -> &'a [T] { + let len = range.end - range.start; + debug_assert!(len % T::RAW_BYTE_LEN == 0); + let count = len / T::RAW_BYTE_LEN; + let ptr = self.bytes.as_ptr().add(range.start) as *const T; + std::slice::from_raw_parts(ptr, count) + } + pub(crate) fn cursor(&self) -> Cursor<'a> { Cursor { pos: 0, @@ -292,7 +389,12 @@ impl<'a> Cursor<'a> { pub(crate) fn finish(self, shape: T) -> Result, ReadError> { let data = self.data; data.check_in_bounds(self.pos)?; - Ok(TableRef { data, shape }) + let _ = shape; + Ok(TableRef { + data, + args: (), + _marker: std::marker::PhantomData, + }) } } @@ -315,6 +417,70 @@ impl<'a> From<&'a [u8]> for FontData<'a> { } } +pub(crate) mod unchecked { + use super::FontData; + use bytemuck::AnyBitPattern; + use std::ops::Range; + use types::{BigEndian, FixedSize, Scalar}; + + use crate::read::FontReadWithArgs; + + #[inline] + pub(crate) fn split_off<'a>(data: FontData<'a>, pos: usize) -> FontData<'a> { + // SAFETY: callers ensure the range is within bounds. + unsafe { data.split_off_unchecked(pos) } + } + + #[inline] + pub(crate) fn slice<'a>(data: FontData<'a>, range: Range) -> FontData<'a> { + // SAFETY: callers ensure the range is within bounds. + unsafe { data.slice_unchecked(range) } + } + + #[inline] + pub(crate) fn read_at<'a, T: Scalar>(data: FontData<'a>, offset: usize) -> T { + // SAFETY: callers ensure the range is within bounds. + unsafe { data.read_at_unchecked(offset) } + } + + #[inline] + pub(crate) fn read_be_at<'a, T: Scalar>(data: FontData<'a>, offset: usize) -> BigEndian { + // SAFETY: callers ensure the range is within bounds. + unsafe { data.read_be_at_unchecked(offset) } + } + + #[inline] + pub(crate) fn read_with_args<'a, T>( + data: FontData<'a>, + range: Range, + args: &T::Args, + ) -> T + where + T: FontReadWithArgs<'a>, + { + // SAFETY: callers ensure the range is within bounds. + unsafe { data.read_with_args_unchecked(range, args).unwrap() } + } + + #[inline] + pub(crate) fn read_ref<'a, T: AnyBitPattern + FixedSize>( + data: FontData<'a>, + offset: usize, + ) -> &'a T { + // SAFETY: callers ensure the range is within bounds and type invariants hold. + unsafe { data.read_ref_unchecked(offset) } + } + + #[inline] + pub(crate) fn read_array<'a, T: AnyBitPattern + FixedSize>( + data: FontData<'a>, + range: Range, + ) -> &'a [T] { + // SAFETY: callers ensure the range is within bounds and aligned to item size. + unsafe { data.read_array_unchecked(range) } + } +} + //kind of ugly, but makes FontData work with FontBuilder. If FontBuilder stops using //Cow in its API, we can probably get rid of this? #[cfg(feature = "std")] diff --git a/read-fonts/src/lib.rs b/read-fonts/src/lib.rs index f711cba64..caa4fd1e6 100644 --- a/read-fonts/src/lib.rs +++ b/read-fonts/src/lib.rs @@ -57,7 +57,7 @@ //! [table-directory]: https://learn.microsoft.com/en-us/typography/opentype/spec/otff#table-directory #![cfg_attr(docsrs, feature(doc_cfg))] -#![forbid(unsafe_code)] +//#![forbid(unsafe_code)] #![deny(rustdoc::broken_intra_doc_links)] #![cfg_attr(not(feature = "std"), no_std)] @@ -99,6 +99,7 @@ pub extern crate font_types as types; #[doc(hidden)] pub(crate) mod codegen_prelude { pub use crate::array::{ComputedArray, VarLenArray}; + pub(crate) use crate::font_data::unchecked; pub use crate::font_data::{Cursor, FontData}; pub use crate::offset::{Offset, ResolveNullableOffset, ResolveOffset}; pub use crate::offset_array::{ArrayOfNullableOffsets, ArrayOfOffsets}; diff --git a/read-fonts/src/table_ref.rs b/read-fonts/src/table_ref.rs index 817b9b494..bfb796afa 100644 --- a/read-fonts/src/table_ref.rs +++ b/read-fonts/src/table_ref.rs @@ -5,6 +5,7 @@ use crate::{ font_data::FontData, offset::{Offset, ResolveOffset}, }; +use std::marker::PhantomData; use std::ops::Range; /// Return the minimum range of the table bytes /// @@ -15,12 +16,13 @@ pub trait MinByteRange { #[derive(Clone)] /// Typed access to raw table data. -pub struct TableRef<'a, T> { - pub(crate) shape: T, +pub struct TableRef<'a, T, A = ()> { + pub(crate) args: A, pub(crate) data: FontData<'a>, + pub(crate) _marker: PhantomData, } -impl<'a, T> TableRef<'a, T> { +impl<'a, T, A> TableRef<'a, T, A> { /// Resolve the provided offset from the start of this table. pub fn resolve_offset>(&self, offset: O) -> Result { offset.resolve(self.data) @@ -32,33 +34,27 @@ impl<'a, T> TableRef<'a, T> { pub fn offset_data(&self) -> FontData<'a> { self.data } - - /// Return a reference to the table's 'Shape' struct. - /// - /// This is a low level implementation detail, but it can be useful in - /// some cases where you want to know things about a table's layout, such - /// as the byte offsets of specific fields. - pub fn shape(&self) -> &T { - &self.shape - } } // a blanket impl so that the format is available through a TableRef -impl> Format for TableRef<'_, T> { +impl, A> Format for TableRef<'_, T, A> { const FORMAT: U = T::FORMAT; } -impl<'a, T: MinByteRange> TableRef<'a, T> { +impl<'a, T, A> TableRef<'a, T, A> +where + TableRef<'a, T, A>: MinByteRange, +{ /// Return the minimum byte range of this table pub fn min_byte_range(&self) -> Range { - self.shape.min_byte_range() + MinByteRange::min_byte_range(self) } /// Return the minimum bytes of this table pub fn min_table_bytes(&self) -> &'a [u8] { self.offset_data() .as_bytes() - .get(self.shape.min_byte_range()) + .get(self.min_byte_range()) .unwrap_or_default() } } diff --git a/read-fonts/src/tables/cvar.rs b/read-fonts/src/tables/cvar.rs index 220153158..850012083 100644 --- a/read-fonts/src/tables/cvar.rs +++ b/read-fonts/src/tables/cvar.rs @@ -66,7 +66,7 @@ impl<'a> Cvar<'a> { } fn raw_tuple_header_data(&self) -> FontData<'a> { - let range = self.shape.tuple_variation_headers_byte_range(); + let range = self.tuple_variation_headers_byte_range(); self.data.split_off(range.start).unwrap() } } diff --git a/read-fonts/src/tables/gpos.rs b/read-fonts/src/tables/gpos.rs index 22b828643..71db30304 100644 --- a/read-fonts/src/tables/gpos.rs +++ b/read-fonts/src/tables/gpos.rs @@ -164,7 +164,7 @@ impl PairPosFormat2<'_> { // Compute an offset into the 2D array of positioning records let record_offset = (class1 as usize * record_size * self.class2_count() as usize) + (class2 as usize * record_size) - + self.shape().class1_records_byte_range().start; + + self.class1_records_byte_range().start; Ok([ Value::read(data, record_offset, format1, context)?, Value::read(data, record_offset + format1_len, format2, context)?, diff --git a/read-fonts/src/tables/gvar.rs b/read-fonts/src/tables/gvar.rs index 727a6cc29..f64239d37 100644 --- a/read-fonts/src/tables/gvar.rs +++ b/read-fonts/src/tables/gvar.rs @@ -51,7 +51,7 @@ impl U16Or32 { impl<'a> GlyphVariationDataHeader<'a> { fn raw_tuple_header_data(&self) -> FontData<'a> { - let range = self.shape.tuple_variation_headers_byte_range(); + let range = self.tuple_variation_headers_byte_range(); self.data.split_off(range.start).unwrap() } } diff --git a/read-fonts/src/tables/variations.rs b/read-fonts/src/tables/variations.rs index 70e038a16..906ab29d7 100644 --- a/read-fonts/src/tables/variations.rs +++ b/read-fonts/src/tables/variations.rs @@ -165,7 +165,7 @@ impl<'a> TupleVariationHeader<'a> { #[inline(always)] pub fn peak_tuple(&self) -> Option> { self.tuple_index().embedded_peak_tuple().then(|| { - let range = self.shape.peak_tuple_byte_range(); + let range = self.peak_tuple_byte_range(); Tuple { values: self.data.read_array(range).unwrap(), } @@ -177,7 +177,7 @@ impl<'a> TupleVariationHeader<'a> { #[inline(always)] pub fn intermediate_start_tuple(&self) -> Option> { self.tuple_index().intermediate_region().then(|| { - let range = self.shape.intermediate_start_tuple_byte_range(); + let range = self.intermediate_start_tuple_byte_range(); Tuple { values: self.data.read_array(range).unwrap(), } @@ -189,7 +189,7 @@ impl<'a> TupleVariationHeader<'a> { #[inline(always)] pub fn intermediate_end_tuple(&self) -> Option> { self.tuple_index().intermediate_region().then(|| { - let range = self.shape.intermediate_end_tuple_byte_range(); + let range = self.intermediate_end_tuple_byte_range(); Tuple { values: self.data.read_array(range).unwrap(), } @@ -201,8 +201,8 @@ impl<'a> TupleVariationHeader<'a> { #[inline(always)] pub fn intermediate_tuples(&self) -> Option<(Tuple<'a>, Tuple<'a>)> { self.tuple_index().intermediate_region().then(|| { - let start_range = self.shape.intermediate_start_tuple_byte_range(); - let end_range = self.shape.intermediate_end_tuple_byte_range(); + let start_range = self.intermediate_start_tuple_byte_range(); + let end_range = self.intermediate_end_tuple_byte_range(); ( Tuple { values: self.data.read_array(start_range).unwrap(),