Honor the calt font feature

This commit is contained in:
Antonio Scandurra 2023-03-17 12:01:27 +01:00
parent 76167ca65c
commit 9181ac9872
2 changed files with 136 additions and 4 deletions

View file

@ -1,3 +1,5 @@
mod open_type;
use crate::{
fonts::{Features, FontId, GlyphId, Metrics, Properties},
geometry::{
@ -14,19 +16,29 @@ use core_foundation::{
array::CFIndex,
attributed_string::{CFAttributedStringRef, CFMutableAttributedString},
base::{CFRange, TCFType},
number::CFNumber,
string::CFString,
};
use core_graphics::{
base::{kCGImageAlphaPremultipliedLast, CGGlyph},
color_space::CGColorSpace,
context::CGContext,
geometry::CGAffineTransform,
};
use core_text::{
font::{CTFont, CTFontRef},
font_descriptor::{
CTFontDescriptor, CTFontDescriptorCreateCopyWithFeature, CTFontDescriptorRef,
},
line::CTLine,
string_attributes::kCTFontAttributeName,
};
use core_text::{font::CTFont, line::CTLine, string_attributes::kCTFontAttributeName};
use font_kit::{
handle::Handle, hinting::HintingOptions, source::SystemSource, sources::mem::MemSource,
font::Font, handle::Handle, hinting::HintingOptions, source::SystemSource,
sources::mem::MemSource,
};
use parking_lot::RwLock;
use std::{cell::RefCell, char, cmp, convert::TryFrom, ffi::c_void, sync::Arc};
use std::{cell::RefCell, char, cmp, convert::TryFrom, ffi::c_void, ptr, sync::Arc};
#[allow(non_upper_case_globals)]
const kCGImageAlphaOnly: u32 = 7;
@ -134,7 +146,17 @@ impl FontSystemState {
.select_family_by_name(name)
.or_else(|_| self.system_source.select_family_by_name(name))?;
for font in family.fonts() {
let font = font.load()?;
let mut font = font.load()?;
if let Some(calt) = features.calt {
let value = if calt {
open_type::kContextualAlternatesOnSelector
} else {
open_type::kContextualAlternatesOffSelector
};
font = toggle_open_type_feature(&font, open_type::kContextualAlternatesType, value);
}
let font_id = FontId(self.fonts.len());
font_ids.push(font_id);
let postscript_name = font.postscript_name().unwrap();
@ -490,6 +512,33 @@ extern "C" {
start_index: CFIndex,
width: f64,
) -> CFIndex;
fn CTFontCreateCopyWithAttributes(
font: CTFontRef,
size: CGFloat,
matrix: *const CGAffineTransform,
attributes: CTFontDescriptorRef,
) -> CTFontRef;
}
fn toggle_open_type_feature(font: &Font, type_identifier: i32, selector_identifier: i32) -> Font {
let native_font = font.native_font();
unsafe {
let new_descriptor = CTFontDescriptorCreateCopyWithFeature(
native_font.copy_descriptor().as_concrete_TypeRef(),
CFNumber::from(type_identifier).as_concrete_TypeRef(),
CFNumber::from(selector_identifier).as_concrete_TypeRef(),
);
let new_descriptor = CTFontDescriptor::wrap_under_create_rule(new_descriptor);
let new_font = CTFontCreateCopyWithAttributes(
font.native_font().as_concrete_TypeRef(),
0.0,
ptr::null(),
new_descriptor.as_concrete_TypeRef(),
);
let new_font = CTFont::wrap_under_create_rule(new_font);
Font::from_native_font(new_font)
}
}
#[cfg(test)]

View file

@ -0,0 +1,83 @@
#![allow(unused, non_upper_case_globals)]
pub const kAltHalfWidthTextSelector: i32 = 6;
pub const kAltProportionalTextSelector: i32 = 5;
pub const kAlternateHorizKanaOffSelector: i32 = 1;
pub const kAlternateHorizKanaOnSelector: i32 = 0;
pub const kAlternateKanaType: i32 = 34;
pub const kAlternateVertKanaOffSelector: i32 = 3;
pub const kAlternateVertKanaOnSelector: i32 = 2;
pub const kCaseSensitiveLayoutOffSelector: i32 = 1;
pub const kCaseSensitiveLayoutOnSelector: i32 = 0;
pub const kCaseSensitiveLayoutType: i32 = 33;
pub const kCaseSensitiveSpacingOffSelector: i32 = 3;
pub const kCaseSensitiveSpacingOnSelector: i32 = 2;
pub const kContextualAlternatesOffSelector: i32 = 1;
pub const kContextualAlternatesOnSelector: i32 = 0;
pub const kContextualAlternatesType: i32 = 36;
pub const kContextualLigaturesOffSelector: i32 = 19;
pub const kContextualLigaturesOnSelector: i32 = 18;
pub const kContextualSwashAlternatesOffSelector: i32 = 5;
pub const kContextualSwashAlternatesOnSelector: i32 = 4;
pub const kDefaultLowerCaseSelector: i32 = 0;
pub const kDefaultUpperCaseSelector: i32 = 0;
pub const kHistoricalLigaturesOffSelector: i32 = 21;
pub const kHistoricalLigaturesOnSelector: i32 = 20;
pub const kHojoCharactersSelector: i32 = 12;
pub const kJIS2004CharactersSelector: i32 = 11;
pub const kLowerCasePetiteCapsSelector: i32 = 2;
pub const kLowerCaseSmallCapsSelector: i32 = 1;
pub const kLowerCaseType: i32 = 37;
pub const kMathematicalGreekOffSelector: i32 = 11;
pub const kMathematicalGreekOnSelector: i32 = 10;
pub const kNLCCharactersSelector: i32 = 13;
pub const kQuarterWidthTextSelector: i32 = 4;
pub const kScientificInferiorsSelector: i32 = 4;
pub const kStylisticAltEightOffSelector: i32 = 17;
pub const kStylisticAltEightOnSelector: i32 = 16;
pub const kStylisticAltEighteenOffSelector: i32 = 37;
pub const kStylisticAltEighteenOnSelector: i32 = 36;
pub const kStylisticAltElevenOffSelector: i32 = 23;
pub const kStylisticAltElevenOnSelector: i32 = 22;
pub const kStylisticAltFifteenOffSelector: i32 = 31;
pub const kStylisticAltFifteenOnSelector: i32 = 30;
pub const kStylisticAltFiveOffSelector: i32 = 11;
pub const kStylisticAltFiveOnSelector: i32 = 10;
pub const kStylisticAltFourOffSelector: i32 = 9;
pub const kStylisticAltFourOnSelector: i32 = 8;
pub const kStylisticAltFourteenOffSelector: i32 = 29;
pub const kStylisticAltFourteenOnSelector: i32 = 28;
pub const kStylisticAltNineOffSelector: i32 = 19;
pub const kStylisticAltNineOnSelector: i32 = 18;
pub const kStylisticAltNineteenOffSelector: i32 = 39;
pub const kStylisticAltNineteenOnSelector: i32 = 38;
pub const kStylisticAltOneOffSelector: i32 = 3;
pub const kStylisticAltOneOnSelector: i32 = 2;
pub const kStylisticAltSevenOffSelector: i32 = 15;
pub const kStylisticAltSevenOnSelector: i32 = 14;
pub const kStylisticAltSeventeenOffSelector: i32 = 35;
pub const kStylisticAltSeventeenOnSelector: i32 = 34;
pub const kStylisticAltSixOffSelector: i32 = 13;
pub const kStylisticAltSixOnSelector: i32 = 12;
pub const kStylisticAltSixteenOffSelector: i32 = 33;
pub const kStylisticAltSixteenOnSelector: i32 = 32;
pub const kStylisticAltTenOffSelector: i32 = 21;
pub const kStylisticAltTenOnSelector: i32 = 20;
pub const kStylisticAltThirteenOffSelector: i32 = 27;
pub const kStylisticAltThirteenOnSelector: i32 = 26;
pub const kStylisticAltThreeOffSelector: i32 = 7;
pub const kStylisticAltThreeOnSelector: i32 = 6;
pub const kStylisticAltTwelveOffSelector: i32 = 25;
pub const kStylisticAltTwelveOnSelector: i32 = 24;
pub const kStylisticAltTwentyOffSelector: i32 = 41;
pub const kStylisticAltTwentyOnSelector: i32 = 40;
pub const kStylisticAltTwoOffSelector: i32 = 5;
pub const kStylisticAltTwoOnSelector: i32 = 4;
pub const kStylisticAlternativesType: i32 = 35;
pub const kSwashAlternatesOffSelector: i32 = 3;
pub const kSwashAlternatesOnSelector: i32 = 2;
pub const kThirdWidthTextSelector: i32 = 3;
pub const kTraditionalNamesCharactersSelector: i32 = 14;
pub const kUpperCasePetiteCapsSelector: i32 = 2;
pub const kUpperCaseSmallCapsSelector: i32 = 1;
pub const kUpperCaseType: i32 = 38;