Vendor things
This commit is contained in:
parent
5deceec006
commit
977e3c17e5
19434 changed files with 10682014 additions and 0 deletions
47
third-party/vendor/ttf-parser-0.15.2/src/tables/cmap/format0.rs
vendored
Normal file
47
third-party/vendor/ttf-parser-0.15.2/src/tables/cmap/format0.rs
vendored
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
use crate::parser::{Stream, NumFrom};
|
||||
use crate::GlyphId;
|
||||
|
||||
/// A [format 0](https://docs.microsoft.com/en-us/typography/opentype/spec/cmap#format-0-byte-encoding-table)
|
||||
/// subtable.
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct Subtable0<'a> {
|
||||
/// Just a list of 256 8bit glyph IDs.
|
||||
pub glyph_ids: &'a [u8],
|
||||
}
|
||||
|
||||
impl<'a> Subtable0<'a> {
|
||||
/// Parses a subtable from raw data.
|
||||
pub fn parse(data: &'a [u8]) -> Option<Self> {
|
||||
let mut s = Stream::new(data);
|
||||
s.skip::<u16>(); // format
|
||||
s.skip::<u16>(); // length
|
||||
s.skip::<u16>(); // language
|
||||
let glyph_ids = s.read_bytes(256)?;
|
||||
Some(Self { glyph_ids })
|
||||
}
|
||||
|
||||
/// Returns a glyph index for a code point.
|
||||
pub fn glyph_index(&self, code_point: u32) -> Option<GlyphId> {
|
||||
let glyph_id = *self.glyph_ids.get(usize::num_from(code_point))?;
|
||||
// Make sure that the glyph is not zero, the array always has 256 ids,
|
||||
// but some codepoints may be mapped to zero.
|
||||
if glyph_id != 0 {
|
||||
Some(GlyphId(u16::from(glyph_id)))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Calls `f` for each codepoint defined in this table.
|
||||
pub fn codepoints(&self, mut f: impl FnMut(u32)) {
|
||||
for (i, glyph_id) in self.glyph_ids.iter().enumerate() {
|
||||
// In contrast to every other format, here we take a look at the glyph
|
||||
// id and check whether it is zero because otherwise this method would
|
||||
// always simply call `f` for `0..256` which would be kind of pointless
|
||||
// (this array always has length 256 even when the face has fewer glyphs).
|
||||
if *glyph_id != 0 {
|
||||
f(i as u32);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
42
third-party/vendor/ttf-parser-0.15.2/src/tables/cmap/format10.rs
vendored
Normal file
42
third-party/vendor/ttf-parser-0.15.2/src/tables/cmap/format10.rs
vendored
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
use crate::parser::{LazyArray32, Stream};
|
||||
use crate::GlyphId;
|
||||
|
||||
/// A [format 10](https://docs.microsoft.com/en-us/typography/opentype/spec/cmap#format-10-trimmed-array)
|
||||
/// subtable.
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct Subtable10<'a> {
|
||||
/// First character code covered.
|
||||
pub first_code_point: u32,
|
||||
/// Array of glyph indices for the character codes covered.
|
||||
pub glyphs: LazyArray32<'a, GlyphId>,
|
||||
}
|
||||
|
||||
impl<'a> Subtable10<'a> {
|
||||
/// Parses a subtable from raw data.
|
||||
pub fn parse(data: &'a [u8]) -> Option<Self> {
|
||||
let mut s = Stream::new(data);
|
||||
s.skip::<u16>(); // format
|
||||
s.skip::<u16>(); // reserved
|
||||
s.skip::<u32>(); // length
|
||||
s.skip::<u32>(); // language
|
||||
let first_code_point = s.read::<u32>()?;
|
||||
let count = s.read::<u32>()?;
|
||||
let glyphs = s.read_array32::<GlyphId>(count)?;
|
||||
Some(Self { first_code_point, glyphs })
|
||||
}
|
||||
|
||||
/// Returns a glyph index for a code point.
|
||||
pub fn glyph_index(&self, code_point: u32) -> Option<GlyphId> {
|
||||
let idx = code_point.checked_sub(self.first_code_point)?;
|
||||
self.glyphs.get(idx)
|
||||
}
|
||||
|
||||
/// Calls `f` for each codepoint defined in this table.
|
||||
pub fn codepoints(&self, mut f: impl FnMut(u32)) {
|
||||
for i in 0..self.glyphs.len() {
|
||||
if let Some(code_point) = self.first_code_point.checked_add(i) {
|
||||
f(code_point);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
80
third-party/vendor/ttf-parser-0.15.2/src/tables/cmap/format12.rs
vendored
Normal file
80
third-party/vendor/ttf-parser-0.15.2/src/tables/cmap/format12.rs
vendored
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
use core::convert::TryFrom;
|
||||
|
||||
use crate::parser::{FromData, LazyArray32, Stream};
|
||||
use crate::GlyphId;
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct SequentialMapGroup {
|
||||
pub start_char_code: u32,
|
||||
pub end_char_code: u32,
|
||||
pub start_glyph_id: u32,
|
||||
}
|
||||
|
||||
impl FromData for SequentialMapGroup {
|
||||
const SIZE: usize = 12;
|
||||
|
||||
#[inline]
|
||||
fn parse(data: &[u8]) -> Option<Self> {
|
||||
let mut s = Stream::new(data);
|
||||
Some(SequentialMapGroup {
|
||||
start_char_code: s.read::<u32>()?,
|
||||
end_char_code: s.read::<u32>()?,
|
||||
start_glyph_id: s.read::<u32>()?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// A [format 12](https://docs.microsoft.com/en-us/typography/opentype/spec/cmap#format-12-segmented-coverage)
|
||||
/// subtable.
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct Subtable12<'a> {
|
||||
groups: LazyArray32<'a, SequentialMapGroup>,
|
||||
}
|
||||
|
||||
impl<'a> Subtable12<'a> {
|
||||
/// Parses a subtable from raw data.
|
||||
pub fn parse(data: &'a [u8]) -> Option<Self> {
|
||||
let mut s = Stream::new(data);
|
||||
s.skip::<u16>(); // format
|
||||
s.skip::<u16>(); // reserved
|
||||
s.skip::<u32>(); // length
|
||||
s.skip::<u32>(); // language
|
||||
let count = s.read::<u32>()?;
|
||||
let groups = s.read_array32::<SequentialMapGroup>(count)?;
|
||||
Some(Self { groups })
|
||||
}
|
||||
|
||||
/// Returns a glyph index for a code point.
|
||||
pub fn glyph_index(&self, code_point: u32) -> Option<GlyphId> {
|
||||
let (_, group) = self.groups.binary_search_by(|range| {
|
||||
use core::cmp::Ordering;
|
||||
|
||||
if range.start_char_code > code_point {
|
||||
Ordering::Greater
|
||||
} else if range.end_char_code < code_point {
|
||||
Ordering::Less
|
||||
} else {
|
||||
Ordering::Equal
|
||||
}
|
||||
})?;
|
||||
|
||||
let id = group.start_glyph_id.checked_add(code_point)?.checked_sub(group.start_char_code)?;
|
||||
return u16::try_from(id).ok().map(GlyphId);
|
||||
}
|
||||
|
||||
/// Calls `f` for each codepoint defined in this table.
|
||||
pub fn codepoints(&self, mut f: impl FnMut(u32)) {
|
||||
for group in self.groups {
|
||||
for code_point in group.start_char_code..=group.end_char_code {
|
||||
f(code_point);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl core::fmt::Debug for Subtable12<'_> {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
|
||||
write!(f, "Subtable12 {{ ... }}")
|
||||
}
|
||||
}
|
||||
55
third-party/vendor/ttf-parser-0.15.2/src/tables/cmap/format13.rs
vendored
Normal file
55
third-party/vendor/ttf-parser-0.15.2/src/tables/cmap/format13.rs
vendored
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
// https://docs.microsoft.com/en-us/typography/opentype/spec/cmap#format-13-many-to-one-range-mappings
|
||||
|
||||
use core::convert::TryFrom;
|
||||
|
||||
use crate::parser::{LazyArray32, Stream};
|
||||
use super::format12::SequentialMapGroup;
|
||||
use crate::GlyphId;
|
||||
|
||||
/// A [format 13](https://docs.microsoft.com/en-us/typography/opentype/spec/cmap#format-13-segmented-coverage)
|
||||
/// subtable.
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct Subtable13<'a> {
|
||||
groups: LazyArray32<'a, SequentialMapGroup>,
|
||||
}
|
||||
|
||||
impl<'a> Subtable13<'a> {
|
||||
/// Parses a subtable from raw data.
|
||||
pub fn parse(data: &'a [u8]) -> Option<Self> {
|
||||
let mut s = Stream::new(data);
|
||||
s.skip::<u16>(); // format
|
||||
s.skip::<u16>(); // reserved
|
||||
s.skip::<u32>(); // length
|
||||
s.skip::<u32>(); // language
|
||||
let count = s.read::<u32>()?;
|
||||
let groups = s.read_array32::<super::format12::SequentialMapGroup>(count)?;
|
||||
Some(Self { groups })
|
||||
}
|
||||
|
||||
/// Returns a glyph index for a code point.
|
||||
pub fn glyph_index(&self, code_point: u32) -> Option<GlyphId> {
|
||||
for group in self.groups {
|
||||
let start_char_code = group.start_char_code;
|
||||
if code_point >= start_char_code && code_point <= group.end_char_code {
|
||||
return u16::try_from(group.start_glyph_id).ok().map(GlyphId);
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
/// Calls `f` for each codepoint defined in this table.
|
||||
pub fn codepoints(&self, mut f: impl FnMut(u32)) {
|
||||
for group in self.groups {
|
||||
for code_point in group.start_char_code..=group.end_char_code {
|
||||
f(code_point);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl core::fmt::Debug for Subtable13<'_> {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
|
||||
write!(f, "Subtable13 {{ ... }}")
|
||||
}
|
||||
}
|
||||
140
third-party/vendor/ttf-parser-0.15.2/src/tables/cmap/format14.rs
vendored
Normal file
140
third-party/vendor/ttf-parser-0.15.2/src/tables/cmap/format14.rs
vendored
Normal file
|
|
@ -0,0 +1,140 @@
|
|||
use crate::GlyphId;
|
||||
use crate::parser::{FromData, LazyArray32, Offset, Offset32, Stream, U24};
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
struct VariationSelectorRecord {
|
||||
var_selector: u32,
|
||||
default_uvs_offset: Option<Offset32>,
|
||||
non_default_uvs_offset: Option<Offset32>,
|
||||
}
|
||||
|
||||
impl FromData for VariationSelectorRecord {
|
||||
const SIZE: usize = 11;
|
||||
|
||||
#[inline]
|
||||
fn parse(data: &[u8]) -> Option<Self> {
|
||||
let mut s = Stream::new(data);
|
||||
Some(VariationSelectorRecord {
|
||||
var_selector: s.read::<U24>()?.0,
|
||||
default_uvs_offset: s.read::<Option<Offset32>>()?,
|
||||
non_default_uvs_offset: s.read::<Option<Offset32>>()?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
struct UVSMappingRecord {
|
||||
unicode_value: u32,
|
||||
glyph_id: GlyphId,
|
||||
}
|
||||
|
||||
impl FromData for UVSMappingRecord {
|
||||
const SIZE: usize = 5;
|
||||
|
||||
#[inline]
|
||||
fn parse(data: &[u8]) -> Option<Self> {
|
||||
let mut s = Stream::new(data);
|
||||
Some(UVSMappingRecord {
|
||||
unicode_value: s.read::<U24>()?.0,
|
||||
glyph_id: s.read::<GlyphId>()?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
struct UnicodeRangeRecord {
|
||||
start_unicode_value: u32,
|
||||
additional_count: u8,
|
||||
}
|
||||
|
||||
impl UnicodeRangeRecord {
|
||||
fn contains(&self, c: u32) -> bool {
|
||||
// Never overflows, since `start_unicode_value` is actually u24.
|
||||
let end = self.start_unicode_value + u32::from(self.additional_count);
|
||||
(self.start_unicode_value..=end).contains(&c)
|
||||
}
|
||||
}
|
||||
|
||||
impl FromData for UnicodeRangeRecord {
|
||||
const SIZE: usize = 4;
|
||||
|
||||
#[inline]
|
||||
fn parse(data: &[u8]) -> Option<Self> {
|
||||
let mut s = Stream::new(data);
|
||||
Some(UnicodeRangeRecord {
|
||||
start_unicode_value: s.read::<U24>()?.0,
|
||||
additional_count: s.read::<u8>()?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// A result of a variation glyph mapping.
|
||||
#[derive(Clone, Copy, PartialEq, Debug)]
|
||||
pub enum GlyphVariationResult {
|
||||
/// Glyph was found in the variation encoding table.
|
||||
Found(GlyphId),
|
||||
/// Glyph should be looked in other, non-variation tables.
|
||||
///
|
||||
/// Basically, you should use `Encoding::glyph_index` or `Face::glyph_index`
|
||||
/// in this case.
|
||||
UseDefault,
|
||||
}
|
||||
|
||||
|
||||
/// A [format 14](https://docs.microsoft.com/en-us/typography/opentype/spec/cmap#format-14-unicode-variation-sequences)
|
||||
/// subtable.
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct Subtable14<'a> {
|
||||
records: LazyArray32<'a, VariationSelectorRecord>,
|
||||
// The whole subtable data.
|
||||
data: &'a [u8],
|
||||
}
|
||||
|
||||
impl<'a> Subtable14<'a> {
|
||||
/// Parses a subtable from raw data.
|
||||
pub fn parse(data: &'a [u8]) -> Option<Self> {
|
||||
let mut s = Stream::new(data);
|
||||
s.skip::<u16>(); // format
|
||||
s.skip::<u32>(); // length
|
||||
let count = s.read::<u32>()?;
|
||||
let records = s.read_array32::<VariationSelectorRecord>(count)?;
|
||||
Some(Self { records, data })
|
||||
}
|
||||
|
||||
/// Returns a glyph index for a code point.
|
||||
pub fn glyph_index(&self, code_point: u32, variation: u32) -> Option<GlyphVariationResult> {
|
||||
let (_, record) = self.records.binary_search_by(|v| v.var_selector.cmp(&variation))?;
|
||||
|
||||
if let Some(offset) = record.default_uvs_offset {
|
||||
let data = self.data.get(offset.to_usize()..)?;
|
||||
let mut s = Stream::new(data);
|
||||
let count = s.read::<u32>()?;
|
||||
let ranges = s.read_array32::<UnicodeRangeRecord>(count)?;
|
||||
for range in ranges {
|
||||
if range.contains(code_point) {
|
||||
return Some(GlyphVariationResult::UseDefault);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(offset) = record.non_default_uvs_offset {
|
||||
let data = self.data.get(offset.to_usize()..)?;
|
||||
let mut s = Stream::new(data);
|
||||
let count = s.read::<u32>()?;
|
||||
let uvs_mappings = s.read_array32::<UVSMappingRecord>(count)?;
|
||||
let (_, mapping) = uvs_mappings.binary_search_by(|v| v.unicode_value.cmp(&code_point))?;
|
||||
return Some(GlyphVariationResult::Found(mapping.glyph_id));
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl core::fmt::Debug for Subtable14<'_> {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
|
||||
write!(f, "Subtable14 {{ ... }}")
|
||||
}
|
||||
}
|
||||
157
third-party/vendor/ttf-parser-0.15.2/src/tables/cmap/format2.rs
vendored
Normal file
157
third-party/vendor/ttf-parser-0.15.2/src/tables/cmap/format2.rs
vendored
Normal file
|
|
@ -0,0 +1,157 @@
|
|||
// This table has a pretty complex parsing algorithm.
|
||||
// A detailed explanation can be found here:
|
||||
// https://docs.microsoft.com/en-us/typography/opentype/spec/cmap#format-2-high-byte-mapping-through-table
|
||||
// https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6cmap.html
|
||||
// https://github.com/fonttools/fonttools/blob/a360252709a3d65f899915db0a5bd753007fdbb7/Lib/fontTools/ttLib/tables/_c_m_a_p.py#L360
|
||||
|
||||
use core::convert::TryFrom;
|
||||
|
||||
use crate::parser::{FromData, LazyArray16, Stream};
|
||||
use crate::GlyphId;
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
struct SubHeaderRecord {
|
||||
first_code: u16,
|
||||
entry_count: u16,
|
||||
id_delta: i16,
|
||||
id_range_offset: u16,
|
||||
}
|
||||
|
||||
impl FromData for SubHeaderRecord {
|
||||
const SIZE: usize = 8;
|
||||
|
||||
#[inline]
|
||||
fn parse(data: &[u8]) -> Option<Self> {
|
||||
let mut s = Stream::new(data);
|
||||
Some(SubHeaderRecord {
|
||||
first_code: s.read::<u16>()?,
|
||||
entry_count: s.read::<u16>()?,
|
||||
id_delta: s.read::<i16>()?,
|
||||
id_range_offset: s.read::<u16>()?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// A [format 2](https://docs.microsoft.com/en-us/typography/opentype/spec/cmap#format-2-high-byte-mapping-through-table)
|
||||
/// subtable.
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct Subtable2<'a> {
|
||||
sub_header_keys: LazyArray16<'a, u16>,
|
||||
sub_headers_offset: usize,
|
||||
sub_headers: LazyArray16<'a, SubHeaderRecord>,
|
||||
// The whole subtable data.
|
||||
data: &'a [u8],
|
||||
}
|
||||
|
||||
impl<'a> Subtable2<'a> {
|
||||
/// Parses a subtable from raw data.
|
||||
pub fn parse(data: &'a [u8]) -> Option<Self> {
|
||||
let mut s = Stream::new(data);
|
||||
s.skip::<u16>(); // format
|
||||
s.skip::<u16>(); // length
|
||||
s.skip::<u16>(); // language
|
||||
let sub_header_keys = s.read_array16::<u16>(256)?;
|
||||
// The maximum index in a sub_header_keys is a sub_headers count.
|
||||
let sub_headers_count = sub_header_keys.into_iter().map(|n| n / 8).max()? + 1;
|
||||
|
||||
// Remember sub_headers offset before reading. Will be used later.
|
||||
let sub_headers_offset = s.offset();
|
||||
let sub_headers = s.read_array16::<SubHeaderRecord>(sub_headers_count)?;
|
||||
|
||||
Some(Self {
|
||||
sub_header_keys,
|
||||
sub_headers_offset,
|
||||
sub_headers,
|
||||
data,
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns a glyph index for a code point.
|
||||
///
|
||||
/// Returns `None` when `code_point` is larger than `u16`.
|
||||
pub fn glyph_index(&self, code_point: u32) -> Option<GlyphId> {
|
||||
// This subtable supports code points only in a u16 range.
|
||||
let code_point = u16::try_from(code_point).ok()?;
|
||||
|
||||
let code_point = code_point;
|
||||
let high_byte = code_point >> 8;
|
||||
let low_byte = code_point & 0x00FF;
|
||||
|
||||
let i = if code_point < 0xff {
|
||||
// 'SubHeader 0 is special: it is used for single-byte character codes.'
|
||||
0
|
||||
} else {
|
||||
// 'Array that maps high bytes to subHeaders: value is subHeader index × 8.'
|
||||
self.sub_header_keys.get(high_byte)? / 8
|
||||
};
|
||||
|
||||
let sub_header = self.sub_headers.get(i)?;
|
||||
|
||||
let first_code = sub_header.first_code;
|
||||
let range_end = first_code.checked_add(sub_header.entry_count)?;
|
||||
if low_byte < first_code || low_byte >= range_end {
|
||||
return None;
|
||||
}
|
||||
|
||||
// SubHeaderRecord::id_range_offset points to SubHeaderRecord::first_code
|
||||
// in the glyphIndexArray. So we have to advance to our code point.
|
||||
let index_offset = usize::from(low_byte.checked_sub(first_code)?) * u16::SIZE;
|
||||
|
||||
// 'The value of the idRangeOffset is the number of bytes
|
||||
// past the actual location of the idRangeOffset'.
|
||||
let offset =
|
||||
self.sub_headers_offset
|
||||
// Advance to required subheader.
|
||||
+ SubHeaderRecord::SIZE * usize::from(i + 1)
|
||||
// Move back to idRangeOffset start.
|
||||
- u16::SIZE
|
||||
// Use defined offset.
|
||||
+ usize::from(sub_header.id_range_offset)
|
||||
// Advance to required index in the glyphIndexArray.
|
||||
+ index_offset;
|
||||
|
||||
let glyph: u16 = Stream::read_at(self.data, offset)?;
|
||||
if glyph == 0 {
|
||||
return None;
|
||||
}
|
||||
|
||||
u16::try_from((i32::from(glyph) + i32::from(sub_header.id_delta)) % 65536).ok().map(GlyphId)
|
||||
}
|
||||
|
||||
/// Calls `f` for each codepoint defined in this table.
|
||||
pub fn codepoints(&self, f: impl FnMut(u32)) {
|
||||
let _ = self.codepoints_inner(f);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn codepoints_inner(&self, mut f: impl FnMut(u32)) -> Option<()> {
|
||||
for first_byte in 0u16..256 {
|
||||
let i = self.sub_header_keys.get(first_byte)? / 8;
|
||||
let sub_header = self.sub_headers.get(i)?;
|
||||
let first_code = sub_header.first_code;
|
||||
|
||||
if i == 0 {
|
||||
// This is a single byte code.
|
||||
let range_end = first_code.checked_add(sub_header.entry_count)?;
|
||||
if first_byte >= first_code && first_byte < range_end {
|
||||
f(u32::from(first_byte));
|
||||
}
|
||||
} else {
|
||||
// This is a two byte code.
|
||||
let base = first_code.checked_add(first_byte << 8)?;
|
||||
for k in 0..sub_header.entry_count {
|
||||
let code_point = base.checked_add(k)?;
|
||||
f(u32::from(code_point));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Some(())
|
||||
}
|
||||
}
|
||||
|
||||
impl core::fmt::Debug for Subtable2<'_> {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
|
||||
write!(f, "Subtable2 {{ ... }}")
|
||||
}
|
||||
}
|
||||
121
third-party/vendor/ttf-parser-0.15.2/src/tables/cmap/format4.rs
vendored
Normal file
121
third-party/vendor/ttf-parser-0.15.2/src/tables/cmap/format4.rs
vendored
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
use core::convert::TryFrom;
|
||||
|
||||
use crate::parser::{LazyArray16, Stream};
|
||||
use crate::GlyphId;
|
||||
|
||||
/// A [format 4](https://docs.microsoft.com/en-us/typography/opentype/spec/cmap#format-4-segment-mapping-to-delta-values)
|
||||
/// subtable.
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct Subtable4<'a> {
|
||||
start_codes: LazyArray16<'a, u16>,
|
||||
end_codes: LazyArray16<'a, u16>,
|
||||
id_deltas: LazyArray16<'a, i16>,
|
||||
id_range_offsets: LazyArray16<'a, u16>,
|
||||
id_range_offset_pos: usize,
|
||||
// The whole subtable data.
|
||||
data: &'a [u8],
|
||||
}
|
||||
|
||||
impl<'a> Subtable4<'a> {
|
||||
/// Parses a subtable from raw data.
|
||||
pub fn parse(data: &'a [u8]) -> Option<Self> {
|
||||
let mut s = Stream::new(data);
|
||||
s.advance(6); // format + length + language
|
||||
let seg_count_x2 = s.read::<u16>()?;
|
||||
if seg_count_x2 < 2 {
|
||||
return None;
|
||||
}
|
||||
|
||||
let seg_count = seg_count_x2 / 2;
|
||||
s.advance(6); // searchRange + entrySelector + rangeShift
|
||||
|
||||
let end_codes = s.read_array16::<u16>(seg_count)?;
|
||||
s.skip::<u16>(); // reservedPad
|
||||
let start_codes = s.read_array16::<u16>(seg_count)?;
|
||||
let id_deltas = s.read_array16::<i16>(seg_count)?;
|
||||
let id_range_offset_pos = s.offset();
|
||||
let id_range_offsets = s.read_array16::<u16>(seg_count)?;
|
||||
|
||||
Some(Self {
|
||||
start_codes,
|
||||
end_codes,
|
||||
id_deltas,
|
||||
id_range_offsets,
|
||||
id_range_offset_pos,
|
||||
data,
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns a glyph index for a code point.
|
||||
///
|
||||
/// Returns `None` when `code_point` is larger than `u16`.
|
||||
pub fn glyph_index(&self, code_point: u32) -> Option<GlyphId> {
|
||||
// This subtable supports code points only in a u16 range.
|
||||
let code_point = u16::try_from(code_point).ok()?;
|
||||
|
||||
// A custom binary search.
|
||||
let mut start = 0;
|
||||
let mut end = self.start_codes.len();
|
||||
while end > start {
|
||||
let index = (start + end) / 2;
|
||||
let end_value = self.end_codes.get(index)?;
|
||||
if end_value >= code_point {
|
||||
let start_value = self.start_codes.get(index)?;
|
||||
if start_value > code_point {
|
||||
end = index;
|
||||
} else {
|
||||
let id_range_offset = self.id_range_offsets.get(index)?;
|
||||
let id_delta = self.id_deltas.get(index)?;
|
||||
if id_range_offset == 0 {
|
||||
return Some(GlyphId(code_point.wrapping_add(id_delta as u16)));
|
||||
} else if id_range_offset == 0xFFFF {
|
||||
// Some malformed fonts have 0xFFFF as the last offset,
|
||||
// which is invalid and should be ignored.
|
||||
return None;
|
||||
}
|
||||
|
||||
let delta = (u32::from(code_point) - u32::from(start_value)) * 2;
|
||||
let delta = u16::try_from(delta).ok()?;
|
||||
|
||||
let id_range_offset_pos = (self.id_range_offset_pos + usize::from(index) * 2) as u16;
|
||||
let pos = id_range_offset_pos.wrapping_add(delta);
|
||||
let pos = pos.wrapping_add(id_range_offset);
|
||||
|
||||
let glyph_array_value: u16 = Stream::read_at(self.data, usize::from(pos))?;
|
||||
|
||||
// 0 indicates missing glyph.
|
||||
if glyph_array_value == 0 {
|
||||
return None;
|
||||
}
|
||||
|
||||
let glyph_id = (glyph_array_value as i16).wrapping_add(id_delta);
|
||||
return u16::try_from(glyph_id).ok().map(GlyphId);
|
||||
}
|
||||
} else {
|
||||
start = index + 1;
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
/// Calls `f` for each codepoint defined in this table.
|
||||
pub fn codepoints(&self, mut f: impl FnMut(u32)) {
|
||||
for (start, end) in self.start_codes.into_iter().zip(self.end_codes) {
|
||||
// OxFFFF value is special and indicates codes end.
|
||||
if start == end && start == 0xFFFF {
|
||||
break;
|
||||
}
|
||||
|
||||
for code_point in start..=end {
|
||||
f(u32::from(code_point));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl core::fmt::Debug for Subtable4<'_> {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
|
||||
write!(f, "Subtable4 {{ ... }}")
|
||||
}
|
||||
}
|
||||
47
third-party/vendor/ttf-parser-0.15.2/src/tables/cmap/format6.rs
vendored
Normal file
47
third-party/vendor/ttf-parser-0.15.2/src/tables/cmap/format6.rs
vendored
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
use core::convert::TryFrom;
|
||||
|
||||
use crate::parser::{LazyArray16, Stream};
|
||||
use crate::GlyphId;
|
||||
|
||||
/// A [format 6](https://docs.microsoft.com/en-us/typography/opentype/spec/cmap#format-6-trimmed-table-mapping)
|
||||
/// subtable.
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct Subtable6<'a> {
|
||||
/// First character code of subrange.
|
||||
pub first_code_point: u16,
|
||||
/// Array of glyph indexes for character codes in the range.
|
||||
pub glyphs: LazyArray16<'a, GlyphId>,
|
||||
}
|
||||
|
||||
impl<'a> Subtable6<'a> {
|
||||
/// Parses a subtable from raw data.
|
||||
pub fn parse(data: &'a [u8]) -> Option<Self> {
|
||||
let mut s = Stream::new(data);
|
||||
s.skip::<u16>(); // format
|
||||
s.skip::<u16>(); // length
|
||||
s.skip::<u16>(); // language
|
||||
let first_code_point = s.read::<u16>()?;
|
||||
let count = s.read::<u16>()?;
|
||||
let glyphs = s.read_array16::<GlyphId>(count)?;
|
||||
Some(Self { first_code_point, glyphs })
|
||||
}
|
||||
|
||||
/// Returns a glyph index for a code point.
|
||||
///
|
||||
/// Returns `None` when `code_point` is larger than `u16`.
|
||||
pub fn glyph_index(&self, code_point: u32) -> Option<GlyphId> {
|
||||
// This subtable supports code points only in a u16 range.
|
||||
let code_point = u16::try_from(code_point).ok()?;
|
||||
let idx = code_point.checked_sub(self.first_code_point)?;
|
||||
self.glyphs.get(idx)
|
||||
}
|
||||
|
||||
/// Calls `f` for each codepoint defined in this table.
|
||||
pub fn codepoints(&self, mut f: impl FnMut(u32)) {
|
||||
for i in 0..self.glyphs.len() {
|
||||
if let Some(code_point) = self.first_code_point.checked_add(i) {
|
||||
f(u32::from(code_point));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
275
third-party/vendor/ttf-parser-0.15.2/src/tables/cmap/mod.rs
vendored
Normal file
275
third-party/vendor/ttf-parser-0.15.2/src/tables/cmap/mod.rs
vendored
Normal file
|
|
@ -0,0 +1,275 @@
|
|||
/*!
|
||||
A [Character to Glyph Index Mapping Table](
|
||||
https://docs.microsoft.com/en-us/typography/opentype/spec/cmap) implementation.
|
||||
|
||||
This module provides a low-level alternative to
|
||||
[`Face::glyph_index`](../struct.Face.html#method.glyph_index) and
|
||||
[`Face::glyph_variation_index`](../struct.Face.html#method.glyph_variation_index)
|
||||
methods.
|
||||
*/
|
||||
|
||||
use crate::{GlyphId, name::PlatformId};
|
||||
use crate::parser::{FromData, LazyArray16, Offset, Offset32, Stream};
|
||||
|
||||
mod format0;
|
||||
mod format2;
|
||||
mod format4;
|
||||
mod format6;
|
||||
mod format10;
|
||||
mod format12;
|
||||
mod format13;
|
||||
mod format14;
|
||||
|
||||
pub use format0::Subtable0;
|
||||
pub use format2::Subtable2;
|
||||
pub use format4::Subtable4;
|
||||
pub use format6::Subtable6;
|
||||
pub use format10::Subtable10;
|
||||
pub use format12::Subtable12;
|
||||
pub use format13::Subtable13;
|
||||
pub use format14::{Subtable14, GlyphVariationResult};
|
||||
|
||||
/// A character encoding subtable variant.
|
||||
#[allow(missing_docs)]
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum Format<'a> {
|
||||
ByteEncodingTable(Subtable0<'a>),
|
||||
HighByteMappingThroughTable(Subtable2<'a>),
|
||||
SegmentMappingToDeltaValues(Subtable4<'a>),
|
||||
TrimmedTableMapping(Subtable6<'a>),
|
||||
MixedCoverage, // unsupported
|
||||
TrimmedArray(Subtable10<'a>),
|
||||
SegmentedCoverage(Subtable12<'a>),
|
||||
ManyToOneRangeMappings(Subtable13<'a>),
|
||||
UnicodeVariationSequences(Subtable14<'a>),
|
||||
}
|
||||
|
||||
|
||||
/// A character encoding subtable.
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct Subtable<'a> {
|
||||
/// Subtable platform.
|
||||
pub platform_id: PlatformId,
|
||||
/// Subtable encoding.
|
||||
pub encoding_id: u16,
|
||||
/// A subtable format.
|
||||
pub format: Format<'a>,
|
||||
}
|
||||
|
||||
impl<'a> Subtable<'a> {
|
||||
/// Checks that the current encoding is Unicode compatible.
|
||||
#[inline]
|
||||
pub fn is_unicode(&self) -> bool {
|
||||
// https://docs.microsoft.com/en-us/typography/opentype/spec/name#windows-encoding-ids
|
||||
const WINDOWS_UNICODE_BMP_ENCODING_ID: u16 = 1;
|
||||
const WINDOWS_UNICODE_FULL_REPERTOIRE_ENCODING_ID: u16 = 10;
|
||||
|
||||
match self.platform_id {
|
||||
PlatformId::Unicode => true,
|
||||
PlatformId::Windows if self.encoding_id == WINDOWS_UNICODE_BMP_ENCODING_ID => true,
|
||||
PlatformId::Windows => {
|
||||
// "Note: Subtable format 13 has the same structure as format 12; it differs only
|
||||
// in the interpretation of the startGlyphID/glyphID fields".
|
||||
let is_format_12_compatible =
|
||||
matches!(self.format, Format::SegmentedCoverage(..) | Format::ManyToOneRangeMappings(..));
|
||||
|
||||
// "Fonts that support Unicode supplementary-plane characters (U+10000 to U+10FFFF)
|
||||
// on the Windows platform must have a format 12 subtable for platform ID 3,
|
||||
// encoding ID 10."
|
||||
self.encoding_id == WINDOWS_UNICODE_FULL_REPERTOIRE_ENCODING_ID
|
||||
&& is_format_12_compatible
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Maps a character to a glyph ID.
|
||||
///
|
||||
/// This is a low-level method and unlike `Face::glyph_index` it doesn't
|
||||
/// check that the current encoding is Unicode.
|
||||
/// It simply maps a `u32` codepoint number to a glyph ID.
|
||||
///
|
||||
/// Returns `None`:
|
||||
/// - when glyph ID is `0`.
|
||||
/// - when format is `MixedCoverage`, since it's not supported.
|
||||
/// - when format is `UnicodeVariationSequences`. Use `glyph_variation_index` instead.
|
||||
#[inline]
|
||||
pub fn glyph_index(&self, code_point: u32) -> Option<GlyphId> {
|
||||
match self.format {
|
||||
Format::ByteEncodingTable(ref subtable) => subtable.glyph_index(code_point),
|
||||
Format::HighByteMappingThroughTable(ref subtable) => subtable.glyph_index(code_point),
|
||||
Format::SegmentMappingToDeltaValues(ref subtable) => subtable.glyph_index(code_point),
|
||||
Format::TrimmedTableMapping(ref subtable) => subtable.glyph_index(code_point),
|
||||
Format::MixedCoverage => None,
|
||||
Format::TrimmedArray(ref subtable) => subtable.glyph_index(code_point),
|
||||
Format::SegmentedCoverage(ref subtable) => subtable.glyph_index(code_point),
|
||||
Format::ManyToOneRangeMappings(ref subtable) => subtable.glyph_index(code_point),
|
||||
// This subtable should be accessed via glyph_variation_index().
|
||||
Format::UnicodeVariationSequences(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Resolves a variation of a glyph ID from two code points.
|
||||
///
|
||||
/// Returns `None`:
|
||||
/// - when glyph ID is `0`.
|
||||
/// - when format is not `UnicodeVariationSequences`.
|
||||
#[inline]
|
||||
pub fn glyph_variation_index(&self, code_point: u32, variation: u32) -> Option<GlyphVariationResult> {
|
||||
match self.format {
|
||||
Format::UnicodeVariationSequences(ref subtable) => {
|
||||
subtable.glyph_index(code_point, variation)
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Calls `f` for all codepoints contained in this subtable.
|
||||
///
|
||||
/// This is a low-level method and it doesn't check that the current
|
||||
/// encoding is Unicode. It simply calls the function `f` for all `u32`
|
||||
/// codepoints that are present in this subtable.
|
||||
///
|
||||
/// Note that this may list codepoints for which `glyph_index` still returns
|
||||
/// `None` because this method finds all codepoints which were _defined_ in
|
||||
/// this subtable. The subtable may still map them to glyph ID `0`.
|
||||
///
|
||||
/// Returns without doing anything:
|
||||
/// - when format is `MixedCoverage`, since it's not supported.
|
||||
/// - when format is `UnicodeVariationSequences`, since it's not supported.
|
||||
pub fn codepoints<F: FnMut(u32)>(&self, f: F) {
|
||||
match self.format {
|
||||
Format::ByteEncodingTable(ref subtable) => subtable.codepoints(f),
|
||||
Format::HighByteMappingThroughTable(ref subtable) => subtable.codepoints(f),
|
||||
Format::SegmentMappingToDeltaValues(ref subtable) => subtable.codepoints(f),
|
||||
Format::TrimmedTableMapping(ref subtable) => subtable.codepoints(f),
|
||||
Format::MixedCoverage => {} // unsupported
|
||||
Format::TrimmedArray(ref subtable) => subtable.codepoints(f),
|
||||
Format::SegmentedCoverage(ref subtable) => subtable.codepoints(f),
|
||||
Format::ManyToOneRangeMappings(ref subtable) => subtable.codepoints(f),
|
||||
Format::UnicodeVariationSequences(_) => {} // unsupported
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
struct EncodingRecord {
|
||||
platform_id: PlatformId,
|
||||
encoding_id: u16,
|
||||
offset: Offset32,
|
||||
}
|
||||
|
||||
impl FromData for EncodingRecord {
|
||||
const SIZE: usize = 8;
|
||||
|
||||
#[inline]
|
||||
fn parse(data: &[u8]) -> Option<Self> {
|
||||
let mut s = Stream::new(data);
|
||||
Some(EncodingRecord {
|
||||
platform_id: s.read::<PlatformId>()?,
|
||||
encoding_id: s.read::<u16>()?,
|
||||
offset: s.read::<Offset32>()?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// A list of subtables.
|
||||
#[derive(Clone, Copy, Default)]
|
||||
pub struct Subtables<'a> {
|
||||
data: &'a [u8],
|
||||
records: LazyArray16<'a, EncodingRecord>,
|
||||
}
|
||||
|
||||
impl core::fmt::Debug for Subtables<'_> {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
|
||||
write!(f, "Subtables {{ ... }}")
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Subtables<'a> {
|
||||
/// Returns a subtable at an index.
|
||||
pub fn get(&self, index: u16) -> Option<Subtable<'a>> {
|
||||
let record = self.records.get(index)?;
|
||||
let data = self.data.get(record.offset.to_usize()..)?;
|
||||
let format = match Stream::read_at::<u16>(data, 0)? {
|
||||
0 => Format::ByteEncodingTable(Subtable0::parse(data)?),
|
||||
2 => Format::HighByteMappingThroughTable(Subtable2::parse(data)?),
|
||||
4 => Format::SegmentMappingToDeltaValues(Subtable4::parse(data)?),
|
||||
6 => Format::TrimmedTableMapping(Subtable6::parse(data)?),
|
||||
8 => Format::MixedCoverage, // unsupported
|
||||
10 => Format::TrimmedArray(Subtable10::parse(data)?),
|
||||
12 => Format::SegmentedCoverage(Subtable12::parse(data)?),
|
||||
13 => Format::ManyToOneRangeMappings(Subtable13::parse(data)?),
|
||||
14 => Format::UnicodeVariationSequences(Subtable14::parse(data)?),
|
||||
_ => return None,
|
||||
};
|
||||
|
||||
Some(Subtable {
|
||||
platform_id: record.platform_id,
|
||||
encoding_id: record.encoding_id,
|
||||
format,
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns the number
|
||||
#[inline]
|
||||
pub fn len(&self) -> u16 {
|
||||
self.records.len()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> IntoIterator for Subtables<'a> {
|
||||
type Item = Subtable<'a>;
|
||||
type IntoIter = SubtablesIter<'a>;
|
||||
|
||||
#[inline]
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
SubtablesIter {
|
||||
subtables: self,
|
||||
index: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// An iterator over [`Subtables`].
|
||||
#[allow(missing_debug_implementations)]
|
||||
pub struct SubtablesIter<'a> {
|
||||
subtables: Subtables<'a>,
|
||||
index: u16,
|
||||
}
|
||||
|
||||
impl<'a> Iterator for SubtablesIter<'a> {
|
||||
type Item = Subtable<'a>;
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if self.index < self.subtables.len() {
|
||||
self.index += 1;
|
||||
self.subtables.get(self.index - 1)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// A [Character to Glyph Index Mapping Table](
|
||||
/// https://docs.microsoft.com/en-us/typography/opentype/spec/cmap).
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct Table<'a> {
|
||||
/// A list of subtables.
|
||||
pub subtables: Subtables<'a>,
|
||||
}
|
||||
|
||||
impl<'a> Table<'a> {
|
||||
/// Parses a table from raw data.
|
||||
pub fn parse(data: &'a [u8]) -> Option<Self> {
|
||||
let mut s = Stream::new(data);
|
||||
s.skip::<u16>(); // version
|
||||
let count = s.read::<u16>()?;
|
||||
let records = s.read_array16::<EncodingRecord>(count)?;
|
||||
Some(Table { subtables: Subtables { data, records }})
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue