use super::hb_mask_t;
use super::unicode::CharExt;
use crate::hb::face::BasicFontMetrics;
use crate::hb::glyph_metrics::GlyphMetrics;
use crate::hb::glyph_names::GlyphNames;
use crate::hb::set_digest::hb_set_digest_t;
use crate::hb::tables::TableRanges;
use crate::hb::unicode::Codepoint;
use crate::U32Set;
use crate::{script, BufferClusterLevel, BufferFlags, Direction, Language, Script, SerializeFlags};
use alloc::{string::String, vec::Vec};
use core::cmp::min;
use core::convert::TryFrom;
use read_fonts::types::{F2Dot14, GlyphId, GlyphId16};
const CONTEXT_LENGTH: usize = 5;
#[repr(C)]
#[derive(Clone, Copy, Default, Debug, bytemuck::Pod, bytemuck::Zeroable)]
pub struct GlyphPosition {
pub x_advance: i32,
pub y_advance: i32,
pub x_offset: i32,
pub y_offset: i32,
pub(crate) var: u32,
}
impl GlyphPosition {
#[inline]
pub(crate) fn attach_chain(&self) -> i16 {
let v: &[i16; 2] = bytemuck::cast_ref(&self.var);
v[0]
}
#[inline]
pub(crate) fn set_attach_chain(&mut self, n: i16) {
let v: &mut [i16; 2] = bytemuck::cast_mut(&mut self.var);
v[0] = n;
}
#[inline]
pub(crate) fn attach_type(&self) -> u8 {
let v: &[u8; 4] = bytemuck::cast_ref(&self.var);
v[2]
}
#[inline]
pub(crate) fn set_attach_type(&mut self, n: u8) {
let v: &mut [u8; 4] = bytemuck::cast_mut(&mut self.var);
v[2] = n;
}
}
#[repr(C)]
#[derive(Clone, Copy, Default, Debug, bytemuck::Pod, bytemuck::Zeroable)]
pub struct GlyphInfo {
pub glyph_id: u32,
pub(crate) mask: hb_mask_t,
pub cluster: u32,
pub(crate) vars: [u32; 2],
}
#[allow(dead_code)]
pub(crate) struct buffer_var_shape {
pub(crate) width: u8,
pub(crate) var_index: u8,
pub(crate) index: u8,
}
impl buffer_var_shape {
#[inline]
pub fn start(&self) -> u8 {
(self.var_index - 1) * 4 + self.index * self.width
}
#[inline]
pub fn count(&self) -> u8 {
self.width
}
#[inline]
pub fn bits(&self) -> u8 {
let start = self.start();
let end = start + self.count();
debug_assert!(end <= 8);
((1u16 << end) - (1u16 << start)) as u8
}
}
macro_rules! declare_buffer_var {
($ty:ty, $var_index:expr, $index:expr, $var_name:ident, $getter:ident, $setter:ident) => {
#[allow(dead_code)]
pub(crate) const $var_name: buffer_var_shape = buffer_var_shape {
width: core::mem::size_of::<$ty>() as u8,
var_index: $var_index,
index: $index,
};
#[inline]
#[allow(dead_code)]
pub(crate) fn $getter(&self) -> $ty {
const LEN: usize = core::mem::size_of::<u32>() / core::mem::size_of::<$ty>();
let v: &[$ty; LEN] = bytemuck::cast_ref(&self.vars[$var_index - 1usize]);
v[$index]
}
#[inline]
#[allow(dead_code)]
pub(crate) fn $setter(&mut self, value: $ty) {
const LEN: usize = core::mem::size_of::<u32>() / core::mem::size_of::<$ty>();
let v: &mut [$ty; LEN] = bytemuck::cast_mut(&mut self.vars[$var_index - 1usize]);
v[$index] = value;
}
};
}
macro_rules! declare_buffer_var_alias {
($alias_var:ident, $ty:ty, $var_name:ident, $getter:ident, $setter:ident) => {
#[allow(dead_code)]
pub(crate) const $var_name: buffer_var_shape = GlyphInfo::$alias_var;
#[inline]
pub(crate) fn $getter(&self) -> $ty {
const { assert!(GlyphInfo::$alias_var.width == core::mem::size_of::<$ty>() as u8) };
const LEN: usize = core::mem::size_of::<u32>() / core::mem::size_of::<$ty>();
let v: &[$ty; LEN] =
bytemuck::cast_ref(&self.vars[GlyphInfo::$alias_var.var_index as usize - 1usize]);
v[GlyphInfo::$alias_var.index as usize]
}
#[inline]
pub(crate) fn $setter(&mut self, value: $ty) {
const { assert!(GlyphInfo::$alias_var.width == core::mem::size_of::<$ty>() as u8) };
const LEN: usize = core::mem::size_of::<u32>() / core::mem::size_of::<$ty>();
let v: &mut [$ty; LEN] = bytemuck::cast_mut(
&mut self.vars[GlyphInfo::$alias_var.var_index as usize - 1usize],
);
v[GlyphInfo::$alias_var.index as usize] = value;
}
};
}
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
pub struct GlyphFlags(pub(crate) u32);
impl GlyphFlags {
pub const UNSAFE_TO_BREAK: Self = Self(0x0000_0001);
pub const UNSAFE_TO_CONCAT: Self = Self(0x0000_0002);
pub const SAFE_TO_INSERT_TATWEEL: Self = Self(0x0000_0004);
pub const ALL: Self = Self(Self::DEFINED_BITS);
pub(crate) const DEFINED_BITS: u32 = 0x0000_0007;
pub const fn from_bits_truncate(bits: u32) -> Self {
Self(bits & Self::DEFINED_BITS)
}
#[inline(always)]
pub const fn to_bits(self) -> u32 {
self.0
}
#[inline(always)]
pub const fn is_unsafe_to_break(self) -> bool {
self.intersects(Self::UNSAFE_TO_BREAK)
}
#[inline(always)]
pub const fn is_unsafe_to_concat(self) -> bool {
self.intersects(Self::UNSAFE_TO_CONCAT)
}
#[inline(always)]
pub const fn is_safe_to_insert_tatweel(self) -> bool {
self.intersects(Self::SAFE_TO_INSERT_TATWEEL)
}
#[inline(always)]
pub const fn contains(self, other: Self) -> bool {
(self.0 & other.0) == other.0
}
#[inline(always)]
pub const fn intersects(self, other: Self) -> bool {
(self.0 & other.0) != 0
}
}
impl core::ops::BitOr for GlyphFlags {
type Output = Self;
#[inline(always)]
fn bitor(self, rhs: Self) -> Self::Output {
Self(self.0 | rhs.0)
}
}
impl core::ops::BitOrAssign for GlyphFlags {
#[inline(always)]
fn bitor_assign(&mut self, rhs: Self) {
self.0 |= rhs.0;
}
}
impl core::ops::BitAnd for GlyphFlags {
type Output = Self;
#[inline(always)]
fn bitand(self, rhs: Self) -> Self::Output {
Self(self.0 & rhs.0)
}
}
impl core::ops::BitAndAssign for GlyphFlags {
#[inline(always)]
fn bitand_assign(&mut self, rhs: Self) {
self.0 &= rhs.0;
}
}
impl core::ops::Not for GlyphFlags {
type Output = Self;
#[inline(always)]
fn not(self) -> Self::Output {
Self(!self.0 & Self::DEFINED_BITS)
}
}
impl GlyphInfo {
#[inline(always)]
pub const fn flags(&self) -> GlyphFlags {
GlyphFlags(self.mask)
}
#[inline(always)]
pub fn unsafe_to_break(&self) -> bool {
self.flags().is_unsafe_to_break()
}
#[inline(always)]
pub fn unsafe_to_concat(&self) -> bool {
self.flags().is_unsafe_to_concat()
}
#[inline(always)]
pub fn safe_to_insert_tatweel(&self) -> bool {
self.flags().is_safe_to_insert_tatweel()
}
pub(crate) fn as_codepoint(&self) -> Codepoint {
self.glyph_id
}
#[inline]
pub(crate) fn as_glyph(&self) -> GlyphId {
GlyphId::new(self.glyph_id)
}
#[inline]
pub(crate) fn as_gid16(&self) -> Option<GlyphId16> {
let gid: u16 = self.glyph_id.try_into().ok()?;
Some(gid.into())
}
pub(crate) fn init_unicode_props(&mut self, scratch_flags: &mut hb_buffer_scratch_flags_t) {
let u = self.as_codepoint();
let gc = u.general_category();
let mut props = gc.0 as u16;
if u >= 0x80 {
if u.is_default_ignorable() {
props |= UnicodeProps::IGNORABLE.bits();
*scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_DEFAULT_IGNORABLES;
match u {
0x200C => props |= UnicodeProps::CF_ZWNJ.bits(),
0x200D => props |= UnicodeProps::CF_ZWJ.bits(),
0x180B..=0x180D | 0x180F => props |= UnicodeProps::HIDDEN.bits(),
0xE0020..=0xE007F => props |= UnicodeProps::HIDDEN.bits(),
0x034F => {
props |= UnicodeProps::HIDDEN.bits();
*scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_CGJ;
}
_ => {}
}
}
if gc.is_mark() {
*scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_CONTINUATIONS;
props |= UnicodeProps::CONTINUATION.bits();
props |= (u.modified_combining_class() as u16) << 8;
}
}
self.set_unicode_props(props);
}
#[inline]
pub(crate) fn unhide(&mut self) {
let mut n = self.unicode_props();
n &= !UnicodeProps::HIDDEN.bits();
self.set_unicode_props(n);
}
}
pub type hb_buffer_cluster_level_t = u32;
pub const HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES: u32 = 0;
pub const HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS: u32 = 1;
pub const HB_BUFFER_CLUSTER_LEVEL_CHARACTERS: u32 = 2;
pub const HB_BUFFER_CLUSTER_LEVEL_GRAPHEMES: u32 = 3;
pub const HB_BUFFER_CLUSTER_LEVEL_DEFAULT: u32 = HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES;
pub struct hb_buffer_t {
pub flags: BufferFlags,
pub cluster_level: hb_buffer_cluster_level_t,
pub invisible: Option<GlyphId>,
pub not_found_variation_selector: Option<u32>,
pub direction: Direction,
pub script: Option<Script>,
pub language: Option<Language>,
pub successful: bool,
pub(crate) have_output: bool,
pub have_separate_output: bool,
pub have_positions: bool,
pub idx: usize,
pub len: usize,
pub out_len: usize,
pub info: Vec<GlyphInfo>,
pub pos: Vec<GlyphPosition>,
pub context: [[Codepoint; CONTEXT_LENGTH]; 2],
pub context_len: [usize; 2],
pub(crate) digest: hb_set_digest_t,
pub(crate) glyph_set: U32Set,
pub allocated_var_bits: u8,
pub serial: u8,
pub scratch_flags: hb_buffer_scratch_flags_t,
pub max_len: usize,
pub max_ops: i32,
}
impl hb_buffer_t {
pub const MAX_LEN_FACTOR: usize = 256;
pub const MAX_LEN_MIN: usize = 65536;
pub const MAX_LEN_DEFAULT: usize = 0x3FFF_FFFF;
pub const MAX_OPS_FACTOR: i32 = 4096;
pub const MAX_OPS_MIN: i32 = 65536;
pub const MAX_OPS_DEFAULT: i32 = 0x1FFF_FFFF;
pub fn new() -> Self {
hb_buffer_t {
flags: BufferFlags::empty(),
cluster_level: HB_BUFFER_CLUSTER_LEVEL_DEFAULT,
invisible: None,
scratch_flags: HB_BUFFER_SCRATCH_FLAG_DEFAULT,
not_found_variation_selector: None,
max_len: Self::MAX_LEN_DEFAULT,
max_ops: Self::MAX_OPS_DEFAULT,
direction: Direction::Invalid,
script: None,
language: None,
successful: true,
have_output: false,
have_positions: false,
idx: 0,
len: 0,
out_len: 0,
info: Vec::new(),
pos: Vec::new(),
have_separate_output: false,
allocated_var_bits: 0,
serial: 0,
context: Default::default(),
context_len: [0, 0],
digest: hb_set_digest_t::new(),
glyph_set: U32Set::default(),
}
}
#[inline]
pub fn allocate_var(&mut self, shape: buffer_var_shape) {
let bits = shape.bits();
debug_assert_eq!(
self.allocated_var_bits & bits,
0,
"Variable already allocated"
);
self.allocated_var_bits |= bits;
}
#[inline]
pub fn try_allocate_var(&mut self, shape: buffer_var_shape) -> bool {
let bits = shape.bits();
if self.allocated_var_bits & bits != 0 {
return false;
}
self.allocated_var_bits |= bits;
true
}
#[inline]
pub fn deallocate_var(&mut self, shape: buffer_var_shape) {
let bits = shape.bits();
debug_assert_eq!(
self.allocated_var_bits & bits,
bits,
"Deallocating unallocated var"
);
self.allocated_var_bits &= !bits;
}
#[inline]
pub fn assert_var(&self, shape: buffer_var_shape) {
let bits = shape.bits();
debug_assert_eq!(
self.allocated_var_bits & bits,
bits,
"Variable not allocated"
);
}
#[inline]
pub fn info_slice_mut(&mut self) -> &mut [GlyphInfo] {
&mut self.info[..self.len]
}
#[inline]
pub fn out_info(&self) -> &[GlyphInfo] {
if self.have_separate_output {
bytemuck::cast_slice(self.pos.as_slice())
} else {
&self.info
}
}
#[inline]
pub fn out_info_mut(&mut self) -> &mut [GlyphInfo] {
if self.have_separate_output {
bytemuck::cast_slice_mut(self.pos.as_mut_slice())
} else {
&mut self.info
}
}
#[inline]
fn set_out_info(&mut self, i: usize, info: GlyphInfo) {
self.out_info_mut()[i] = info;
}
#[inline]
pub fn cur(&self, i: usize) -> &GlyphInfo {
&self.info[self.idx + i]
}
#[inline]
pub fn cur_mut(&mut self, i: usize) -> &mut GlyphInfo {
let idx = self.idx + i;
&mut self.info[idx]
}
#[inline]
pub fn cur_pos_mut(&mut self) -> &mut GlyphPosition {
let i = self.idx;
&mut self.pos[i]
}
#[inline]
pub fn prev(&self) -> &GlyphInfo {
let idx = self.out_len.saturating_sub(1);
&self.out_info()[idx]
}
#[inline]
pub fn prev_mut(&mut self) -> &mut GlyphInfo {
let idx = self.out_len.saturating_sub(1);
&mut self.out_info_mut()[idx]
}
pub fn update_digest(&mut self) {
self.digest = hb_set_digest_t::new();
self.digest.add_array(self.info.iter().map(|i| i.glyph_id));
}
pub fn update_glyph_set(&mut self) {
self.glyph_set.clear();
self.glyph_set
.extend_unsorted(self.info.iter().map(|i| i.glyph_id));
}
fn clear(&mut self) {
self.direction = Direction::Invalid;
self.script = None;
self.language = None;
self.successful = true;
self.have_output = false;
self.have_positions = false;
self.idx = 0;
self.info.clear();
self.pos.clear();
self.len = 0;
self.out_len = 0;
self.have_separate_output = false;
self.context = Default::default();
self.context_len = [0, 0];
self.serial = 0;
self.scratch_flags = HB_BUFFER_SCRATCH_FLAG_DEFAULT;
self.cluster_level = HB_BUFFER_CLUSTER_LEVEL_DEFAULT;
self.not_found_variation_selector = None;
}
#[inline]
pub fn backtrack_len(&self) -> usize {
if self.have_output {
self.out_len
} else {
self.idx
}
}
#[inline]
pub fn lookahead_len(&self) -> usize {
self.len - self.idx
}
#[inline]
fn next_serial(&mut self) -> u8 {
self.serial = self.serial.wrapping_add(1);
if self.serial == 0 {
self.serial += 1;
}
self.serial
}
fn add(&mut self, codepoint: u32, cluster: u32) {
if !self.ensure(self.len + 1) {
return;
}
self.info[self.len] = GlyphInfo {
glyph_id: codepoint,
cluster,
..GlyphInfo::default()
};
self.len += 1;
}
#[inline]
pub fn reverse(&mut self) {
if self.is_empty() {
return;
}
self.reverse_range(0, self.len);
}
pub fn reverse_range(&mut self, start: usize, end: usize) {
if end - start < 2 {
return;
}
self.info[start..end].reverse();
if self.have_positions {
self.pos[start..end].reverse();
}
}
pub fn reverse_groups<F>(&mut self, group: F, merge_clusters: bool)
where
F: Fn(&GlyphInfo, &GlyphInfo) -> bool,
{
if self.is_empty() {
return;
}
let mut start = 0;
let mut i = 1;
while i < self.len {
if !group(&self.info[i - 1], &self.info[i]) {
if merge_clusters {
self.merge_clusters(start, i);
}
self.reverse_range(start, i);
start = i;
}
i += 1;
}
if merge_clusters {
self.merge_clusters(start, i);
}
self.reverse_range(start, i);
self.reverse();
}
pub fn group_end<F>(&self, mut start: usize, group: F) -> usize
where
F: Fn(&GlyphInfo, &GlyphInfo) -> bool,
{
start += 1;
while start < self.len && group(&self.info[start - 1], &self.info[start]) {
start += 1;
}
start
}
#[inline]
fn reset_clusters(&mut self) {
for (i, info) in self.info.iter_mut().enumerate() {
info.cluster = i as u32;
}
}
pub fn guess_segment_properties(&mut self) {
if self.script.is_none() {
for info in &self.info {
match info.as_codepoint().script() {
script::COMMON | script::INHERITED | script::UNKNOWN => {}
s => {
self.script = Some(s);
break;
}
}
}
}
if self.direction == Direction::Invalid {
if let Some(script) = self.script {
self.direction = Direction::from_script(script).unwrap_or_default();
}
if self.direction == Direction::Invalid {
self.direction = Direction::LeftToRight;
}
}
}
pub fn sync(&mut self) -> bool {
debug_assert!(self.have_output);
debug_assert!(self.idx <= self.len);
if !self.successful {
self.have_output = false;
self.out_len = 0;
self.idx = 0;
return false;
}
self.next_glyphs(self.len - self.idx);
if self.have_separate_output {
let info: Vec<GlyphPosition> = bytemuck::cast_vec(core::mem::take(&mut self.info));
let pos: Vec<GlyphInfo> = bytemuck::cast_vec(core::mem::take(&mut self.pos));
self.pos = info;
self.info = pos;
self.have_separate_output = false;
}
self.len = self.out_len;
self.have_output = false;
self.out_len = 0;
self.idx = 0;
true
}
pub fn clear_output(&mut self) {
self.have_output = true;
self.have_positions = false;
self.idx = 0;
self.out_len = 0;
self.have_separate_output = false;
}
pub fn clear_positions(&mut self) {
self.have_output = false;
self.have_positions = true;
self.out_len = 0;
self.have_separate_output = false;
for pos in &mut self.pos {
*pos = GlyphPosition::default();
}
}
pub fn replace_glyphs(&mut self, num_in: usize, num_out: usize, glyph_data: &[u32]) {
if !self.make_room_for(num_in, num_out) {
return;
}
debug_assert!(self.idx + num_in <= self.len);
self.merge_clusters(self.idx, self.idx + num_in);
let orig_info = self.info[self.idx];
for i in 0..num_out {
let ii = self.out_len + i;
self.set_out_info(ii, orig_info);
self.out_info_mut()[ii].glyph_id = glyph_data[i];
}
self.idx += num_in;
self.out_len += num_out;
}
pub fn replace_glyph(&mut self, glyph_index: u32) {
if self.have_separate_output || self.out_len != self.idx {
if !self.make_room_for(1, 1) {
return;
}
self.set_out_info(self.out_len, self.info[self.idx]);
}
let out_len = self.out_len;
self.out_info_mut()[out_len].glyph_id = glyph_index;
self.idx += 1;
self.out_len += 1;
}
pub fn output_glyph(&mut self, glyph_index: u32) {
if !self.make_room_for(0, 1) {
return;
}
if self.idx == self.len && self.out_len == 0 {
return;
}
let out_len = self.out_len;
if self.idx < self.len {
self.set_out_info(out_len, self.info[self.idx]);
} else {
let info = self.out_info()[out_len - 1];
self.set_out_info(out_len, info);
}
self.out_info_mut()[out_len].glyph_id = glyph_index;
self.out_len += 1;
}
pub fn output_info(&mut self, glyph_info: GlyphInfo) {
if !self.make_room_for(0, 1) {
return;
}
self.set_out_info(self.out_len, glyph_info);
self.out_len += 1;
}
pub fn copy_glyph(&mut self) {
if !self.make_room_for(0, 1) {
return;
}
self.set_out_info(self.out_len, self.info[self.idx]);
self.out_len += 1;
}
#[inline(always)]
pub fn next_glyph(&mut self) {
if self.have_output {
if self.have_separate_output || self.out_len != self.idx {
if !self.ensure(self.out_len + 1) {
return;
}
let i = self.out_len;
self.out_info_mut()[i] = self.info[self.idx];
}
self.out_len += 1;
}
self.idx += 1;
}
pub fn next_glyphs(&mut self, n: usize) {
if self.have_output {
if self.have_separate_output || self.out_len != self.idx {
if !self.ensure(self.out_len + n) {
return;
}
for i in 0..n {
self.set_out_info(self.out_len + i, self.info[self.idx + i]);
}
}
self.out_len += n;
}
self.idx += n;
}
pub fn skip_glyph(&mut self) {
self.idx += 1;
}
pub fn reset_masks(&mut self, mask: hb_mask_t) {
for info in &mut self.info[..self.len] {
info.mask = mask;
}
}
pub fn set_masks(
&mut self,
mut value: hb_mask_t,
mask: hb_mask_t,
cluster_start: u32,
cluster_end: u32,
) {
if mask == 0 {
return;
}
let not_mask = !mask;
value &= mask;
self.max_ops -= self.len as i32;
if self.max_ops < 0 {
self.successful = false;
}
if cluster_start == 0 && cluster_end == u32::MAX {
for info in &mut self.info[..self.len] {
info.mask = (info.mask & not_mask) | value;
}
return;
}
for info in &mut self.info[..self.len] {
if cluster_start <= info.cluster && info.cluster < cluster_end {
info.mask = (info.mask & not_mask) | value;
}
}
}
#[inline(always)]
pub fn merge_clusters(&mut self, start: usize, end: usize) {
if end - start < 2 {
return;
}
if !BufferClusterLevel::new(self.cluster_level).is_monotone() {
self.unsafe_to_break(Some(start), Some(end));
return;
}
self.merge_clusters_impl(start, end);
}
fn merge_clusters_impl(&mut self, mut start: usize, mut end: usize) {
self.max_ops -= (end - start) as i32;
if self.max_ops < 0 {
self.successful = false;
}
let cluster = self.info[start..end]
.iter()
.map(|info| info.cluster)
.min()
.unwrap();
if cluster != self.info[end - 1].cluster {
while end < self.len && self.info[end - 1].cluster == self.info[end].cluster {
end += 1;
}
}
if cluster != self.info[start].cluster {
while self.idx < start && self.info[start - 1].cluster == self.info[start].cluster {
start -= 1;
}
}
if self.idx == start && self.info[start].cluster != cluster {
let mut i = self.out_len;
while i != 0 && self.out_info()[i - 1].cluster == self.info[start].cluster {
Self::set_cluster(&mut self.out_info_mut()[i - 1], cluster, 0);
i -= 1;
}
}
for info in &mut self.info[start..end] {
Self::set_cluster(info, cluster, 0);
}
}
pub fn merge_grapheme_clusters(&mut self, start: usize, end: usize) {
if end - start < 2 {
return;
}
if !BufferClusterLevel::new(self.cluster_level).is_graphemes() {
self.unsafe_to_break(Some(start), Some(end));
return;
}
self.merge_clusters_impl(start, end);
}
pub fn merge_out_clusters(&mut self, start: usize, end: usize) {
if end - start < 2 {
return;
}
if !BufferClusterLevel::new(self.cluster_level).is_monotone() {
return;
}
self.merge_out_clusters_impl(start, end);
}
pub fn merge_out_grapheme_clusters(&mut self, start: usize, end: usize) {
if end - start < 2 {
return;
}
if !BufferClusterLevel::new(self.cluster_level).is_graphemes() {
return;
}
self.merge_out_clusters_impl(start, end);
}
fn merge_out_clusters_impl(&mut self, mut start: usize, mut end: usize) {
self.max_ops -= (end - start) as i32;
if self.max_ops < 0 {
self.successful = false;
}
let cluster = self.out_info()[start..end]
.iter()
.map(|info| info.cluster)
.min()
.unwrap();
while start != 0 && self.out_info()[start - 1].cluster == self.out_info()[start].cluster {
start -= 1;
}
while end < self.out_len && self.out_info()[end - 1].cluster == self.out_info()[end].cluster
{
end += 1;
}
if end == self.out_len {
let mut i = self.idx;
while i < self.len && self.info[i].cluster == self.out_info()[end - 1].cluster {
Self::set_cluster(&mut self.info[i], cluster, 0);
i += 1;
}
}
for info in &mut self.out_info_mut()[start..end] {
Self::set_cluster(info, cluster, 0);
}
}
pub fn delete_glyph(&mut self) {
let cluster = self.info[self.idx].cluster;
if (self.idx + 1 < self.len && cluster == self.info[self.idx + 1].cluster)
|| (self.out_len != 0 && cluster == self.out_info()[self.out_len - 1].cluster)
{
self.skip_glyph();
return;
}
if self.out_len != 0 {
if cluster < self.out_info()[self.out_len - 1].cluster {
let mask = self.info[self.idx].mask;
let old_cluster = self.out_info()[self.out_len - 1].cluster;
let mut i = self.out_len;
while i != 0 && self.out_info()[i - 1].cluster == old_cluster {
Self::set_cluster(&mut self.out_info_mut()[i - 1], cluster, mask);
i -= 1;
}
}
self.skip_glyph();
return;
}
if self.idx + 1 < self.len {
self.merge_clusters(self.idx, self.idx + 2);
}
self.skip_glyph();
}
pub fn delete_glyphs_inplace(&mut self, filter: impl Fn(&GlyphInfo) -> bool) {
let mut j = 0;
for i in 0..self.len {
if filter(&self.info[i]) {
let cluster = self.info[i].cluster;
if i + 1 < self.len && cluster == self.info[i + 1].cluster {
continue;
}
if j != 0 {
if cluster < self.info[j - 1].cluster {
let mask = self.info[i].mask;
let old_cluster = self.info[j - 1].cluster;
let mut k = j;
while k > 0 && self.info[k - 1].cluster == old_cluster {
Self::set_cluster(&mut self.info[k - 1], cluster, mask);
k -= 1;
}
}
continue;
}
if i + 1 < self.len {
self.merge_clusters(i, i + 2);
}
continue;
}
if j != i {
self.info[j] = self.info[i];
self.pos[j] = self.pos[i];
}
j += 1;
}
self.len = j;
}
pub fn unsafe_to_break(&mut self, start: Option<usize>, end: Option<usize>) {
self.set_glyph_flags(
GlyphFlags::UNSAFE_TO_BREAK | GlyphFlags::UNSAFE_TO_CONCAT,
start,
end,
Some(true),
None,
);
}
pub fn safe_to_insert_tatweel(&mut self, start: Option<usize>, end: Option<usize>) {
if !self
.flags
.contains(BufferFlags::PRODUCE_SAFE_TO_INSERT_TATWEEL)
{
self.unsafe_to_break(start, end);
return;
}
self.set_glyph_flags(
GlyphFlags::SAFE_TO_INSERT_TATWEEL,
start,
end,
Some(true),
None,
);
}
fn _set_glyph_flags_impl(
&mut self,
mask: hb_mask_t,
start: usize,
end: usize,
interior: bool,
from_out_buffer: bool,
) {
if !from_out_buffer || !self.have_output {
if !interior {
for info in &mut self.info[start..end] {
info.mask |= mask;
}
} else {
let cluster = self._infos_find_min_cluster(&self.info, start, end, None);
self._infos_set_glyph_flags(false, start, end, cluster, mask);
}
} else {
debug_assert!(start <= self.out_len);
debug_assert!(self.idx <= end);
if !interior {
let range_end = self.out_len;
for info in &mut self.out_info_mut()[start..range_end] {
info.mask |= mask;
}
for info in &mut self.info[self.idx..end] {
info.mask |= mask;
}
} else {
let mut cluster = self._infos_find_min_cluster(&self.info, self.idx, end, None);
cluster = self._infos_find_min_cluster(
self.out_info(),
start,
self.out_len,
Some(cluster),
);
let out_len = self.out_len;
self._infos_set_glyph_flags(true, start, out_len, cluster, mask);
self._infos_set_glyph_flags(false, self.idx, end, cluster, mask);
}
}
}
fn set_glyph_flags(
&mut self,
flags: GlyphFlags,
start: Option<usize>,
end: Option<usize>,
interior: Option<bool>,
from_out_buffer: Option<bool>,
) {
if let (Some(start), Some(end)) = (start, end) {
if end.wrapping_sub(start) > 255 {
return;
}
}
let start = start.unwrap_or(0);
let end = min(end.unwrap_or(self.len), self.len);
let interior = interior.unwrap_or(false);
let from_out_buffer = from_out_buffer.unwrap_or(false);
if interior && !from_out_buffer && end - start < 2 {
return;
}
self._set_glyph_flags_impl(flags.0, start, end, interior, from_out_buffer);
}
pub fn unsafe_to_concat(&mut self, start: Option<usize>, end: Option<usize>) {
if !self.flags.contains(BufferFlags::PRODUCE_UNSAFE_TO_CONCAT) {
return;
}
self.set_glyph_flags(GlyphFlags::UNSAFE_TO_CONCAT, start, end, Some(false), None);
}
pub fn unsafe_to_break_from_outbuffer(&mut self, start: Option<usize>, end: Option<usize>) {
self.set_glyph_flags(
GlyphFlags::UNSAFE_TO_BREAK | GlyphFlags::UNSAFE_TO_CONCAT,
start,
end,
Some(true),
Some(true),
);
}
pub fn unsafe_to_concat_from_outbuffer(&mut self, start: Option<usize>, end: Option<usize>) {
if !self.flags.contains(BufferFlags::PRODUCE_UNSAFE_TO_CONCAT) {
return;
}
self.set_glyph_flags(
GlyphFlags::UNSAFE_TO_CONCAT,
start,
end,
Some(false),
Some(true),
);
}
pub fn move_to(&mut self, i: usize) -> bool {
if !self.have_output {
debug_assert!(i <= self.len);
self.idx = i;
return true;
}
if !self.successful {
return false;
}
debug_assert!(i <= self.out_len + (self.len - self.idx));
if self.out_len < i {
let count = i - self.out_len;
if !self.make_room_for(count, count) {
return false;
}
for j in 0..count {
self.set_out_info(self.out_len + j, self.info[self.idx + j]);
}
self.idx += count;
self.out_len += count;
} else if self.out_len > i {
let count = self.out_len - i;
if self.idx < count && !self.shift_forward(count - self.idx) {
return false;
}
debug_assert!(self.idx >= count);
self.idx -= count;
self.out_len -= count;
for j in 0..count {
self.info[self.idx + j] = self.out_info()[self.out_len + j];
}
}
true
}
#[must_use]
#[inline(always)]
pub fn ensure(&mut self, size: usize) -> bool {
if size <= self.info.len() {
true
} else {
self.enlarge(size)
}
}
#[must_use]
fn enlarge(&mut self, size: usize) -> bool {
if size > self.max_len {
self.successful = false;
return false;
}
self.info.resize(size, GlyphInfo::default());
self.pos.resize(size, GlyphPosition::default());
true
}
#[must_use]
fn make_room_for(&mut self, num_in: usize, num_out: usize) -> bool {
if !self.ensure(self.out_len + num_out) {
return false;
}
if !self.have_separate_output && self.out_len + num_out > self.idx + num_in {
debug_assert!(self.have_output);
self.have_separate_output = true;
for i in 0..self.out_len {
self.set_out_info(i, self.info[i]);
}
}
true
}
fn shift_forward(&mut self, count: usize) -> bool {
debug_assert!(self.have_output);
if !self.ensure(self.len + count) {
return false;
}
self.max_ops -= (self.len - self.idx) as i32;
if self.max_ops < 0 {
self.successful = false;
return false;
}
for i in (0..(self.len - self.idx)).rev() {
self.info[self.idx + count + i] = self.info[self.idx + i];
}
if self.idx + count > self.len {
for info in &mut self.info[self.len..self.idx + count] {
*info = GlyphInfo::default();
}
}
self.len += count;
self.idx += count;
true
}
fn clear_context(&mut self, side: usize) {
self.context_len[side] = 0;
}
pub fn sort(&mut self, start: usize, end: usize, cmp: impl Fn(&GlyphInfo, &GlyphInfo) -> bool) {
debug_assert!(!self.have_positions);
for i in start + 1..end {
let mut j = i;
while j > start && cmp(&self.info[j - 1], &self.info[i]) {
j -= 1;
}
if i == j {
continue;
}
self.merge_clusters(j, i + 1);
{
let t = self.info[i];
for idx in (0..i - j).rev() {
self.info[idx + j + 1] = self.info[idx + j];
}
self.info[j] = t;
}
}
}
pub fn set_cluster(info: &mut GlyphInfo, cluster: u32, mask: hb_mask_t) {
if info.cluster != cluster {
info.mask = (info.mask & !GlyphFlags::DEFINED_BITS) | (mask & GlyphFlags::DEFINED_BITS);
}
info.cluster = cluster;
}
pub(crate) fn enter(&mut self) {
self.serial = 0;
self.scratch_flags = HB_BUFFER_SCRATCH_FLAG_DEFAULT;
if let Some(len) = self.len.checked_mul(hb_buffer_t::MAX_LEN_FACTOR) {
self.max_len = len.max(hb_buffer_t::MAX_LEN_MIN);
}
if let Ok(len) = i32::try_from(self.len) {
if let Some(ops) = len.checked_mul(hb_buffer_t::MAX_OPS_FACTOR) {
self.max_ops = ops.max(hb_buffer_t::MAX_OPS_MIN);
}
}
}
pub(crate) fn leave(&mut self) {
self.max_len = hb_buffer_t::MAX_LEN_DEFAULT;
self.max_ops = hb_buffer_t::MAX_OPS_DEFAULT;
self.serial = 0;
}
fn _infos_find_min_cluster(
&self,
info: &[GlyphInfo],
start: usize,
end: usize,
cluster: Option<u32>,
) -> u32 {
let mut cluster = cluster.unwrap_or(u32::MAX);
if start == end {
return cluster;
}
if self.cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS {
for glyph_info in &info[start..end] {
cluster = min(cluster, glyph_info.cluster);
}
}
cluster.min(info[start].cluster.min(info[end - 1].cluster))
}
#[inline(always)]
fn _infos_set_glyph_flags(
&mut self,
out_info: bool,
start: usize,
end: usize,
cluster: u32,
mask: hb_mask_t,
) {
if start == end {
return;
}
let cluster_level = self.cluster_level;
let infos = if out_info {
self.out_info_mut()
} else {
self.info.as_mut_slice()
};
let cluster_first = infos[start].cluster;
let cluster_last = infos[end - 1].cluster;
if cluster_level == HB_BUFFER_CLUSTER_LEVEL_CHARACTERS
|| (cluster != cluster_first && cluster != cluster_last)
{
for info in &mut infos[start..end] {
if info.cluster != cluster {
info.mask |= mask;
}
}
return;
}
if cluster == cluster_first {
let mut i = end;
while start < i && infos[i - 1].cluster != cluster_first {
if cluster != infos[i - 1].cluster {
infos[i - 1].mask |= mask;
}
i -= 1;
}
} else {
let mut i = start;
while i < end && infos[i].cluster != cluster_last {
if cluster != infos[i].cluster {
infos[i].mask |= mask;
}
i += 1;
}
}
}
pub fn is_empty(&self) -> bool {
self.len == 0
}
fn push_str(&mut self, text: &str) {
if !self.ensure(self.len + text.chars().count()) {
return;
}
for (i, c) in text.char_indices() {
self.info[self.len] = GlyphInfo {
glyph_id: c as u32,
cluster: i as u32,
..GlyphInfo::default()
};
self.len += 1;
}
}
fn set_pre_context(&mut self, text: &str) {
self.clear_context(0);
for (i, c) in text.chars().rev().enumerate().take(CONTEXT_LENGTH) {
self.context[0][i] = c as Codepoint;
self.context_len[0] += 1;
}
}
fn set_pre_context_codepoints(&mut self, codepoints: &[u32]) {
self.clear_context(0);
for (i, &c) in codepoints.iter().take(CONTEXT_LENGTH).enumerate() {
self.context[0][i] = c;
self.context_len[0] += 1;
}
}
fn set_post_context(&mut self, text: &str) {
self.clear_context(1);
for (i, c) in text.chars().enumerate().take(CONTEXT_LENGTH) {
self.context[1][i] = c as Codepoint;
self.context_len[1] += 1;
}
}
fn set_post_context_codepoints(&mut self, codepoints: &[u32]) {
self.clear_context(1);
for (i, &c) in codepoints.iter().take(CONTEXT_LENGTH).enumerate() {
self.context[1][i] = c;
self.context_len[1] += 1;
}
}
pub fn next_syllable(&self, mut start: usize) -> usize {
if start >= self.len {
return start;
}
let syllable = self.info[start].syllable();
start += 1;
while start < self.len && syllable == self.info[start].syllable() {
start += 1;
}
start
}
#[inline]
pub fn allocate_lig_id(&mut self) -> u8 {
let mut lig_id = self.next_serial() & 0x07;
if lig_id == 0 {
lig_id = self.allocate_lig_id();
}
lig_id
}
}
pub(crate) fn _cluster_group_func(a: &GlyphInfo, b: &GlyphInfo) -> bool {
a.cluster == b.cluster
}
macro_rules! foreach_cluster {
($buffer:expr, $start:ident, $end:ident, $($body:tt)*) => {
foreach_group!($buffer, $start, $end, $crate::hb::buffer::_cluster_group_func, $($body)*)
};
}
macro_rules! foreach_group {
($buffer:expr, $start:ident, $end:ident, $group_func:expr, $($body:tt)*) => {{
let count = $buffer.len;
let mut $start = 0;
let mut $end = if count > 0 { $buffer.group_end(0, $group_func) } else { 0 };
while $start < count {
$($body)*;
$start = $end;
$end = $buffer.group_end($start, $group_func);
}
}};
}
macro_rules! foreach_syllable {
($buffer:expr, $start:ident, $end:ident, $($body:tt)*) => {{
let mut $start = 0;
let mut $end = $buffer.next_syllable(0);
while $start < $buffer.len {
$($body)*;
$start = $end;
$end = $buffer.next_syllable($start);
}
}};
}
macro_rules! foreach_grapheme {
($buffer:expr, $start:ident, $end:ident, $($body:tt)*) => {
foreach_group!($buffer, $start, $end, $crate::hb::ot_layout::_hb_grapheme_group_func, $($body)*)
};
}
bitflags::bitflags! {
#[derive(Default, Debug, Clone, Copy)]
pub struct UnicodeProps: u16 {
const GENERAL_CATEGORY = 0x001F;
const IGNORABLE = 0x0020;
const HIDDEN = 0x0040;
const CONTINUATION = 0x0080;
const CF_ZWJ = 0x0100;
const CF_ZWNJ = 0x0200;
const CF_VS = 0x0400;
const CF_AAT_DELETED = 0x0800;
}
}
bitflags::bitflags! {
#[derive(Default, Debug, Clone, Copy)]
pub struct GlyphPropsFlags: u16 {
const BASE_GLYPH = 0x02;
const LIGATURE = 0x04;
const MARK = 0x08;
const CLASS_MASK = Self::BASE_GLYPH.bits() | Self::LIGATURE.bits() | Self::MARK.bits();
const SUBSTITUTED = 0x10;
const LIGATED = 0x20;
const MULTIPLIED = 0x40;
const PRESERVE = Self::SUBSTITUTED.bits() | Self::LIGATED.bits() | Self::MULTIPLIED.bits();
}
}
pub type hb_buffer_scratch_flags_t = u32;
pub const HB_BUFFER_SCRATCH_FLAG_DEFAULT: u32 = 0x0000_0000;
pub const HB_BUFFER_SCRATCH_FLAG_HAS_FRACTION_SLASH: u32 = 0x0000_0001;
pub const HB_BUFFER_SCRATCH_FLAG_HAS_DEFAULT_IGNORABLES: u32 = 0x0000_0002;
pub const HB_BUFFER_SCRATCH_FLAG_HAS_SPACE_FALLBACK: u32 = 0x0000_0004;
pub const HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT: u32 = 0x0000_0008;
pub const HB_BUFFER_SCRATCH_FLAG_HAS_CGJ: u32 = 0x0000_0010;
pub const HB_BUFFER_SCRATCH_FLAG_HAS_BROKEN_SYLLABLE: u32 = 0x0000_0020;
pub const HB_BUFFER_SCRATCH_FLAG_HAS_VARIATION_SELECTOR_FALLBACK: u32 = 0x0000_0040;
pub const HB_BUFFER_SCRATCH_FLAG_HAS_CONTINUATIONS: u32 = 0x0000_0080;
pub const HB_BUFFER_SCRATCH_FLAG_SHAPER0: u32 = 0x0100_0000;
pub struct UnicodeBuffer(pub(crate) hb_buffer_t);
impl UnicodeBuffer {
#[inline]
pub fn new() -> UnicodeBuffer {
UnicodeBuffer(hb_buffer_t::new())
}
#[inline]
pub fn len(&self) -> usize {
self.0.len
}
pub fn reserve(&mut self, size: usize) -> bool {
self.0.ensure(size)
}
#[inline]
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
#[inline]
pub fn push_str(&mut self, str: &str) {
self.0.push_str(str);
}
#[inline]
pub fn set_pre_context(&mut self, str: &str) {
self.0.set_pre_context(str);
}
#[inline]
pub fn set_pre_context_codepoints(&mut self, codepoints: &[u32]) {
self.0.set_pre_context_codepoints(codepoints);
}
#[inline]
pub fn set_post_context(&mut self, str: &str) {
self.0.set_post_context(str);
}
#[inline]
pub fn set_post_context_codepoints(&mut self, codepoints: &[u32]) {
self.0.set_post_context_codepoints(codepoints);
}
#[inline]
pub fn push_glyph_infos(&mut self, infos: &[GlyphInfo]) -> bool {
let len = infos.len();
if !self.0.ensure(self.0.len + len) {
return false;
}
self.0.info[self.0.len..self.0.len + len].copy_from_slice(infos);
self.0.len += len;
true
}
#[inline]
pub fn add(&mut self, codepoint: char, cluster: u32) {
self.0.add(codepoint as u32, cluster);
self.0.context_len[1] = 0;
}
#[inline]
pub fn set_direction(&mut self, direction: Direction) {
self.0.direction = direction;
}
#[inline]
pub fn direction(&self) -> Direction {
self.0.direction
}
#[inline]
pub fn set_script(&mut self, script: Script) {
self.0.script = Some(script);
}
pub fn script(&self) -> Script {
self.0.script.unwrap_or(script::UNKNOWN)
}
#[inline]
pub fn set_language(&mut self, lang: Language) {
self.0.language = Some(lang);
}
#[inline]
pub fn set_not_found_variation_selector_glyph(&mut self, glyph: u32) {
self.0.not_found_variation_selector = Some(glyph);
}
#[inline]
pub fn language(&self) -> Option<Language> {
self.0.language.clone()
}
#[inline]
pub fn guess_segment_properties(&mut self) {
self.0.guess_segment_properties();
}
#[inline]
pub fn set_flags(&mut self, flags: BufferFlags) {
self.0.flags = flags;
}
#[inline]
pub fn flags(&self) -> BufferFlags {
self.0.flags
}
#[inline]
pub fn set_cluster_level(&mut self, cluster_level: BufferClusterLevel) {
self.0.cluster_level = match cluster_level {
BufferClusterLevel::MonotoneGraphemes => HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES,
BufferClusterLevel::MonotoneCharacters => HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS,
BufferClusterLevel::Characters => HB_BUFFER_CLUSTER_LEVEL_CHARACTERS,
BufferClusterLevel::Graphemes => HB_BUFFER_CLUSTER_LEVEL_GRAPHEMES,
}
}
#[inline]
pub fn cluster_level(&self) -> BufferClusterLevel {
match self.0.cluster_level {
HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES => BufferClusterLevel::MonotoneGraphemes,
HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS => BufferClusterLevel::MonotoneCharacters,
HB_BUFFER_CLUSTER_LEVEL_CHARACTERS => BufferClusterLevel::Characters,
HB_BUFFER_CLUSTER_LEVEL_GRAPHEMES => BufferClusterLevel::Graphemes,
_ => BufferClusterLevel::MonotoneGraphemes,
}
}
#[inline]
pub fn reset_clusters(&mut self) {
self.0.reset_clusters();
}
#[inline]
pub fn clear(&mut self) {
self.0.clear();
}
}
impl core::fmt::Debug for UnicodeBuffer {
fn fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
fmt.debug_struct("UnicodeBuffer")
.field("direction", &self.direction())
.field("language", &self.language())
.field("script", &self.script())
.field("cluster_level", &self.cluster_level())
.finish()
}
}
impl Default for UnicodeBuffer {
fn default() -> UnicodeBuffer {
UnicodeBuffer::new()
}
}
pub struct GlyphBuffer(pub(crate) hb_buffer_t);
impl GlyphBuffer {
#[inline]
pub fn len(&self) -> usize {
self.0.len
}
#[inline]
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
#[inline]
pub fn glyph_infos(&self) -> &[GlyphInfo] {
&self.0.info[0..self.0.len]
}
#[inline]
pub fn glyph_positions(&self) -> &[GlyphPosition] {
&self.0.pos[0..self.0.len]
}
#[inline]
pub fn clear(mut self) -> UnicodeBuffer {
self.0.clear();
UnicodeBuffer(self.0)
}
pub fn serialize(&self, font: &impl SerializerFont, flags: SerializeFlags) -> String {
self.serialize_impl(font, flags).unwrap_or_default()
}
pub(crate) fn serialize_impl(
&self,
font: &impl SerializerFont,
flags: SerializeFlags,
) -> Result<String, core::fmt::Error> {
use core::fmt::Write;
let mut s = String::with_capacity(64);
let info = self.glyph_infos();
let pos = self.glyph_positions();
let mut x = 0;
let mut y = 0;
let names = font.glyph_names();
let glyph_metrics = if flags.contains(SerializeFlags::GLYPH_EXTENTS) {
Some(font.glyph_metrics())
} else {
None
};
for (info, pos) in info.iter().zip(pos) {
s.push(if s.is_empty() { '[' } else { '|' });
if !flags.contains(SerializeFlags::NO_GLYPH_NAMES) {
match names.get(info.as_glyph().to_u32()) {
Some(name) => s.push_str(name),
None => write!(&mut s, "gid{}", info.glyph_id)?,
}
} else {
write!(&mut s, "{}", info.glyph_id)?;
}
if !flags.contains(SerializeFlags::NO_CLUSTERS) {
write!(&mut s, "={}", info.cluster)?;
}
if !flags.contains(SerializeFlags::NO_POSITIONS) {
if x + pos.x_offset != 0 || y + pos.y_offset != 0 {
write!(&mut s, "@{},{}", x + pos.x_offset, y + pos.y_offset)?;
}
if !flags.contains(SerializeFlags::NO_ADVANCES) {
write!(&mut s, "+{}", pos.x_advance)?;
if pos.y_advance != 0 {
write!(&mut s, ",{}", pos.y_advance)?;
}
}
}
if flags.contains(SerializeFlags::GLYPH_FLAGS) {
if info.mask & GlyphFlags::DEFINED_BITS != 0 {
write!(&mut s, "#{:X}", info.mask & GlyphFlags::DEFINED_BITS)?;
}
}
if flags.contains(SerializeFlags::GLYPH_EXTENTS) {
let extents = glyph_metrics
.as_ref()
.unwrap()
.extents(info.as_glyph(), font.coords())
.unwrap_or_default();
write!(
&mut s,
"<{},{},{},{}>",
extents.x_bearing, extents.y_bearing, extents.width, extents.height
)?;
}
if flags.contains(SerializeFlags::NO_ADVANCES) {
x += pos.x_advance;
y += pos.y_advance;
}
}
if !s.is_empty() {
s.push(']');
}
Ok(s)
}
}
pub trait SerializerFont {
fn coords(&self) -> &[F2Dot14];
fn glyph_names(&self) -> GlyphNames<'_>;
fn glyph_metrics(&self) -> GlyphMetrics<'_>;
}
impl SerializerFont for crate::Shaper<'_> {
fn coords(&self) -> &[F2Dot14] {
self.coords()
}
fn glyph_names(&self) -> GlyphNames<'_> {
crate::Shaper::glyph_names(self)
}
fn glyph_metrics(&self) -> GlyphMetrics<'_> {
crate::Shaper::glyph_metrics(self)
}
}
impl SerializerFont for crate::font::FontInstance {
fn coords(&self) -> &[F2Dot14] {
self.normalized_coords()
}
fn glyph_names(&self) -> GlyphNames<'_> {
GlyphNames::from_tables(&self.tables())
}
fn glyph_metrics(&self) -> GlyphMetrics<'_> {
let table_ranges = TableRanges::from_tables(&self.tables());
let metrics = BasicFontMetrics {
num_glyphs: table_ranges.num_glyphs,
units_per_em: table_ranges.units_per_em,
ascent: table_ranges.ascent,
descent: table_ranges.descent,
};
GlyphMetrics::from_tables(&self.tables(), &metrics)
}
}
impl core::fmt::Debug for GlyphBuffer {
fn fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
fmt.debug_struct("GlyphBuffer")
.field("glyph_positions", &self.glyph_positions())
.field("glyph_infos", &self.glyph_infos())
.finish()
}
}