pre-removing copy
This commit is contained in:
parent
f5879b3425
commit
1d7850099f
2 changed files with 75 additions and 51 deletions
88
src/attrs.rs
88
src/attrs.rs
|
|
@ -5,6 +5,8 @@ use alloc::vec::Vec;
|
||||||
use core::ops::Range;
|
use core::ops::Range;
|
||||||
use rangemap::RangeMap;
|
use rangemap::RangeMap;
|
||||||
use smol_str::SmolStr;
|
use smol_str::SmolStr;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
use crate::{CacheKeyFlags, Metrics};
|
use crate::{CacheKeyFlags, Metrics};
|
||||||
|
|
||||||
|
|
@ -125,31 +127,69 @@ impl From<CacheMetrics> for Metrics {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Font features for controlling typographic behavior
|
/// OpenType feature tag
|
||||||
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
|
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
|
||||||
|
pub struct FeatureTag([u8; 4]);
|
||||||
|
|
||||||
|
impl FeatureTag {
|
||||||
|
/// Create a new feature tag from a 4-character string
|
||||||
|
pub const fn new(tag: &[u8; 4]) -> Self {
|
||||||
|
Self(*tag)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Common OpenType features as constants
|
||||||
|
pub const KERNING: Self = Self::new(b"kern");
|
||||||
|
pub const STANDARD_LIGATURES: Self = Self::new(b"liga");
|
||||||
|
pub const CONTEXTUAL_LIGATURES: Self = Self::new(b"clig");
|
||||||
|
pub const CONTEXTUAL_ALTERNATES: Self = Self::new(b"calt");
|
||||||
|
pub const DISCRETIONARY_LIGATURES: Self = Self::new(b"dlig");
|
||||||
|
pub const SMALL_CAPS: Self = Self::new(b"smcp");
|
||||||
|
pub const ALL_SMALL_CAPS: Self = Self::new(b"c2sc");
|
||||||
|
pub const STYLISTIC_SET_1: Self = Self::new(b"ss01");
|
||||||
|
pub const STYLISTIC_SET_2: Self = Self::new(b"ss02");
|
||||||
|
// Add more common features as needed
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Font feature with tag and value
|
||||||
|
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
|
||||||
|
pub struct Feature {
|
||||||
|
pub tag: FeatureTag,
|
||||||
|
pub value: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Font features for text shaping
|
||||||
|
#[derive(Clone, Debug, Default, Eq, Hash, PartialEq)]
|
||||||
pub struct FontFeatures {
|
pub struct FontFeatures {
|
||||||
/// Kerning adjusts spacing between specific character pairs
|
/// List of OpenType features with their values (0 = disabled, 1 = enabled)
|
||||||
pub kerning: bool,
|
pub features: Vec<Feature>,
|
||||||
/// Standard ligatures (fi, fl, etc.)
|
|
||||||
pub standard_ligatures: bool,
|
|
||||||
/// Contextual ligatures (context-dependent ligatures)
|
|
||||||
pub contextual_ligatures: bool,
|
|
||||||
/// Contextual alternates (glyph substitutions based on context)
|
|
||||||
pub contextual_alternates: bool,
|
|
||||||
/// Discretionary ligatures (optional stylistic ligatures)
|
|
||||||
pub discretionary_ligatures: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FontFeatures {
|
impl FontFeatures {
|
||||||
/// Create new font features with default settings
|
/// Create new font features with default settings
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
let mut features = Vec::new();
|
||||||
kerning: true,
|
// Enable kerning by default
|
||||||
standard_ligatures: true,
|
features.push(Feature { tag: FeatureTag::KERNING, value: 1 });
|
||||||
contextual_ligatures: true,
|
// Enable standard ligatures by default
|
||||||
contextual_alternates: true,
|
features.push(Feature { tag: FeatureTag::STANDARD_LIGATURES, value: 1 });
|
||||||
discretionary_ligatures: true,
|
|
||||||
}
|
Self { features }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set a feature value
|
||||||
|
pub fn set(&mut self, tag: FeatureTag, value: u32) -> &mut Self {
|
||||||
|
self.features.push(Feature { tag, value });
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Enable a feature (set to 1)
|
||||||
|
pub fn enable(&mut self, tag: FeatureTag) -> &mut Self {
|
||||||
|
self.set(tag, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Disable a feature (set to 0)
|
||||||
|
pub fn disable(&mut self, tag: FeatureTag) -> &mut Self {
|
||||||
|
self.set(tag, 0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -165,7 +205,7 @@ pub struct Attrs<'a> {
|
||||||
pub metadata: usize,
|
pub metadata: usize,
|
||||||
pub cache_key_flags: CacheKeyFlags,
|
pub cache_key_flags: CacheKeyFlags,
|
||||||
pub metrics_opt: Option<CacheMetrics>,
|
pub metrics_opt: Option<CacheMetrics>,
|
||||||
pub font_features: FontFeatures,
|
pub font_features: Option<Rc<FontFeatures>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Attrs<'a> {
|
impl<'a> Attrs<'a> {
|
||||||
|
|
@ -182,7 +222,7 @@ impl<'a> Attrs<'a> {
|
||||||
metadata: 0,
|
metadata: 0,
|
||||||
cache_key_flags: CacheKeyFlags::empty(),
|
cache_key_flags: CacheKeyFlags::empty(),
|
||||||
metrics_opt: None,
|
metrics_opt: None,
|
||||||
font_features: FontFeatures::new(),
|
font_features: None, // Use default features
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -236,7 +276,7 @@ impl<'a> Attrs<'a> {
|
||||||
|
|
||||||
/// Set [FontFeatures]
|
/// Set [FontFeatures]
|
||||||
pub fn font_features(mut self, font_features: FontFeatures) -> Self {
|
pub fn font_features(mut self, font_features: FontFeatures) -> Self {
|
||||||
self.font_features = font_features;
|
self.font_features = Some(Rc::new(font_features));
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -288,7 +328,7 @@ pub struct AttrsOwned {
|
||||||
pub metadata: usize,
|
pub metadata: usize,
|
||||||
pub cache_key_flags: CacheKeyFlags,
|
pub cache_key_flags: CacheKeyFlags,
|
||||||
pub metrics_opt: Option<CacheMetrics>,
|
pub metrics_opt: Option<CacheMetrics>,
|
||||||
pub font_features: FontFeatures,
|
pub font_features: Option<Rc<FontFeatures>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AttrsOwned {
|
impl AttrsOwned {
|
||||||
|
|
@ -302,7 +342,7 @@ impl AttrsOwned {
|
||||||
metadata: attrs.metadata,
|
metadata: attrs.metadata,
|
||||||
cache_key_flags: attrs.cache_key_flags,
|
cache_key_flags: attrs.cache_key_flags,
|
||||||
metrics_opt: attrs.metrics_opt,
|
metrics_opt: attrs.metrics_opt,
|
||||||
font_features: attrs.font_features,
|
font_features: attrs.font_features.clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -316,7 +356,7 @@ impl AttrsOwned {
|
||||||
metadata: self.metadata,
|
metadata: self.metadata,
|
||||||
cache_key_flags: self.cache_key_flags,
|
cache_key_flags: self.cache_key_flags,
|
||||||
metrics_opt: self.metrics_opt,
|
metrics_opt: self.metrics_opt,
|
||||||
font_features: self.font_features,
|
font_features: self.font_features.clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
38
src/shape.rs
38
src/shape.rs
|
|
@ -142,39 +142,23 @@ fn shape_fallback(
|
||||||
|
|
||||||
let attrs = attrs_list.get_span(start_run);
|
let attrs = attrs_list.get_span(start_run);
|
||||||
|
|
||||||
let mut features = Vec::new();
|
// Convert attrs::Feature to rustybuzz::Feature
|
||||||
features.push(rustybuzz::Feature::new(
|
let font_features = attrs.get_font_features();
|
||||||
rustybuzz::ttf_parser::Tag::from_bytes(b"kern"),
|
let mut rb_features = Vec::with_capacity(font_features.features.len());
|
||||||
attrs.font_features.kerning as u32,
|
for feature in &font_features.features {
|
||||||
0..usize::MAX,
|
rb_features.push(rustybuzz::Feature::new(
|
||||||
));
|
rustybuzz::ttf_parser::Tag::from_bytes(&feature.tag.as_bytes()),
|
||||||
features.push(rustybuzz::Feature::new(
|
feature.value,
|
||||||
rustybuzz::ttf_parser::Tag::from_bytes(b"liga"),
|
0..usize::MAX,
|
||||||
attrs.font_features.standard_ligatures as u32,
|
));
|
||||||
0..usize::MAX,
|
}
|
||||||
));
|
|
||||||
features.push(rustybuzz::Feature::new(
|
|
||||||
rustybuzz::ttf_parser::Tag::from_bytes(b"clig"),
|
|
||||||
attrs.font_features.contextual_ligatures as u32,
|
|
||||||
0..usize::MAX,
|
|
||||||
));
|
|
||||||
features.push(rustybuzz::Feature::new(
|
|
||||||
rustybuzz::ttf_parser::Tag::from_bytes(b"calt"),
|
|
||||||
attrs.font_features.contextual_alternates as u32,
|
|
||||||
0..usize::MAX,
|
|
||||||
));
|
|
||||||
features.push(rustybuzz::Feature::new(
|
|
||||||
rustybuzz::ttf_parser::Tag::from_bytes(b"dlig"),
|
|
||||||
attrs.font_features.discretionary_ligatures as u32,
|
|
||||||
0..usize::MAX,
|
|
||||||
));
|
|
||||||
|
|
||||||
let shape_plan = rustybuzz::ShapePlan::new(
|
let shape_plan = rustybuzz::ShapePlan::new(
|
||||||
font.rustybuzz(),
|
font.rustybuzz(),
|
||||||
buffer.direction(),
|
buffer.direction(),
|
||||||
Some(buffer.script()),
|
Some(buffer.script()),
|
||||||
buffer.language().as_ref(),
|
buffer.language().as_ref(),
|
||||||
&features,
|
&rb_features,
|
||||||
);
|
);
|
||||||
let glyph_buffer = rustybuzz::shape_with_plan(font.rustybuzz(), &shape_plan, buffer);
|
let glyph_buffer = rustybuzz::shape_with_plan(font.rustybuzz(), &shape_plan, buffer);
|
||||||
let glyph_infos = glyph_buffer.glyph_infos();
|
let glyph_infos = glyph_buffer.glyph_infos();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue