use super::cache::CacheKey;
use super::internal::{raw_data, RawFont};
use super::Tag;
#[derive(Copy, Clone)]
pub struct FontDataRef<'a> {
data: &'a [u8],
len: usize,
}
impl<'a> FontDataRef<'a> {
pub fn new(data: &'a [u8]) -> Option<Self> {
if !raw_data::is_font(data, 0) && !raw_data::is_collection(data) {
None
} else {
Some(Self {
data,
len: raw_data::count(data) as usize,
})
}
}
pub fn is_collection(&self) -> bool {
raw_data::is_collection(self.data)
}
pub fn data(&self) -> &'a [u8] {
self.data
}
pub fn len(&self) -> usize {
self.len
}
pub fn is_empty(&self) -> bool {
self.len == 0
}
pub fn get(&self, index: usize) -> Option<FontRef<'a>> {
FontRef::from_offset(self.data, raw_data::offset(self.data, index as u32)?)
}
pub fn fonts(&self) -> Fonts<'a> {
Fonts {
data: *self,
pos: 0,
}
}
}
#[derive(Copy, Clone)]
pub struct FontRef<'a> {
pub data: &'a [u8],
pub offset: u32,
pub key: CacheKey,
}
impl<'a> FontRef<'a> {
pub fn from_index(data: &'a [u8], index: usize) -> Option<Self> {
FontDataRef::new(data)?.get(index)
}
pub fn from_offset(data: &'a [u8], offset: u32) -> Option<Self> {
if !raw_data::is_font(data, offset) {
None
} else {
Some(Self {
data,
offset,
key: CacheKey::new(),
})
}
}
}
impl<'a> RawFont<'a> for FontRef<'a> {
fn data(&self) -> &'a [u8] {
self.data
}
fn offset(&self) -> u32 {
self.offset
}
}
pub struct Fonts<'a> {
data: FontDataRef<'a>,
pos: usize,
}
impl<'a> Iterator for Fonts<'a> {
type Item = FontRef<'a>;
fn size_hint(&self) -> (usize, Option<usize>) {
let remaining = (self.data.len - self.pos) as usize;
(remaining, Some(remaining))
}
fn nth(&mut self, n: usize) -> Option<Self::Item> {
let pos = self.pos.checked_add(n)?;
self.pos = pos.checked_add(1)?;
self.data.get(pos)
}
fn next(&mut self) -> Option<Self::Item> {
if self.pos >= self.data.len {
None
} else {
let pos = self.pos;
self.pos += 1;
self.data.get(pos)
}
}
}
impl<'a> ExactSizeIterator for Fonts<'a> {
fn len(&self) -> usize {
(self.data.len - self.pos) as usize
}
}
impl<'a> IntoIterator for FontDataRef<'a> {
type IntoIter = Fonts<'a>;
type Item = FontRef<'a>;
fn into_iter(self) -> Self::IntoIter {
self.fonts()
}
}
pub trait TableProvider {
fn table_by_tag(&self, tag: Tag) -> Option<&[u8]>;
}
impl<'a> TableProvider for FontRef<'a> {
fn table_by_tag(&self, tag: Tag) -> Option<&[u8]> {
self.table_data(tag)
}
}
impl<'a> TableProvider for &'a FontRef<'a> {
fn table_by_tag(&self, tag: Tag) -> Option<&[u8]> {
self.table_data(tag)
}
}