mirror of
https://github.com/zed-industries/zed.git
synced 2024-12-27 11:26:42 +03:00
Honor more OpenType features
This commit is contained in:
parent
9181ac9872
commit
f9d793cb4a
@ -24,6 +24,39 @@ pub type GlyphId = u32;
|
||||
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize, JsonSchema)]
|
||||
pub struct Features {
|
||||
pub calt: Option<bool>,
|
||||
pub case: Option<bool>,
|
||||
pub cpsp: Option<bool>,
|
||||
pub frac: Option<bool>,
|
||||
pub liga: Option<bool>,
|
||||
pub onum: Option<bool>,
|
||||
pub ordn: Option<bool>,
|
||||
pub pnum: Option<bool>,
|
||||
pub ss01: Option<bool>,
|
||||
pub ss02: Option<bool>,
|
||||
pub ss03: Option<bool>,
|
||||
pub ss04: Option<bool>,
|
||||
pub ss05: Option<bool>,
|
||||
pub ss06: Option<bool>,
|
||||
pub ss07: Option<bool>,
|
||||
pub ss08: Option<bool>,
|
||||
pub ss09: Option<bool>,
|
||||
pub ss10: Option<bool>,
|
||||
pub ss11: Option<bool>,
|
||||
pub ss12: Option<bool>,
|
||||
pub ss13: Option<bool>,
|
||||
pub ss14: Option<bool>,
|
||||
pub ss15: Option<bool>,
|
||||
pub ss16: Option<bool>,
|
||||
pub ss17: Option<bool>,
|
||||
pub ss18: Option<bool>,
|
||||
pub ss19: Option<bool>,
|
||||
pub ss20: Option<bool>,
|
||||
pub subs: Option<bool>,
|
||||
pub sups: Option<bool>,
|
||||
pub swsh: Option<bool>,
|
||||
pub titl: Option<bool>,
|
||||
pub tnum: Option<bool>,
|
||||
pub zero: Option<bool>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
|
@ -16,29 +16,19 @@ 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::{
|
||||
font::Font, handle::Handle, hinting::HintingOptions, source::SystemSource,
|
||||
sources::mem::MemSource,
|
||||
handle::Handle, hinting::HintingOptions, source::SystemSource, sources::mem::MemSource,
|
||||
};
|
||||
use parking_lot::RwLock;
|
||||
use std::{cell::RefCell, char, cmp, convert::TryFrom, ffi::c_void, ptr, sync::Arc};
|
||||
use std::{cell::RefCell, char, cmp, convert::TryFrom, ffi::c_void, sync::Arc};
|
||||
|
||||
#[allow(non_upper_case_globals)]
|
||||
const kCGImageAlphaOnly: u32 = 7;
|
||||
@ -147,16 +137,7 @@ impl FontSystemState {
|
||||
.or_else(|_| self.system_source.select_family_by_name(name))?;
|
||||
for font in family.fonts() {
|
||||
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);
|
||||
}
|
||||
|
||||
open_type::apply_features(&mut font, features);
|
||||
let font_id = FontId(self.fonts.len());
|
||||
font_ids.push(font_id);
|
||||
let postscript_name = font.postscript_name().unwrap();
|
||||
@ -512,33 +493,6 @@ 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)]
|
||||
|
@ -1,83 +1,395 @@
|
||||
#![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;
|
||||
use std::ptr;
|
||||
|
||||
use crate::fonts::Features;
|
||||
use cocoa::appkit::CGFloat;
|
||||
use core_foundation::{base::TCFType, number::CFNumber};
|
||||
use core_graphics::geometry::CGAffineTransform;
|
||||
use core_text::{
|
||||
font::{CTFont, CTFontRef},
|
||||
font_descriptor::{
|
||||
CTFontDescriptor, CTFontDescriptorCreateCopyWithFeature, CTFontDescriptorRef,
|
||||
},
|
||||
};
|
||||
use font_kit::font::Font;
|
||||
|
||||
const kCaseSensitiveLayoutOffSelector: i32 = 1;
|
||||
const kCaseSensitiveLayoutOnSelector: i32 = 0;
|
||||
const kCaseSensitiveLayoutType: i32 = 33;
|
||||
const kCaseSensitiveSpacingOffSelector: i32 = 3;
|
||||
const kCaseSensitiveSpacingOnSelector: i32 = 2;
|
||||
const kCharacterAlternativesType: i32 = 17;
|
||||
const kCommonLigaturesOffSelector: i32 = 3;
|
||||
const kCommonLigaturesOnSelector: i32 = 2;
|
||||
const kContextualAlternatesOffSelector: i32 = 1;
|
||||
const kContextualAlternatesOnSelector: i32 = 0;
|
||||
const kContextualAlternatesType: i32 = 36;
|
||||
const kContextualLigaturesOffSelector: i32 = 19;
|
||||
const kContextualLigaturesOnSelector: i32 = 18;
|
||||
const kContextualSwashAlternatesOffSelector: i32 = 5;
|
||||
const kContextualSwashAlternatesOnSelector: i32 = 4;
|
||||
const kDefaultLowerCaseSelector: i32 = 0;
|
||||
const kDefaultUpperCaseSelector: i32 = 0;
|
||||
const kDiagonalFractionsSelector: i32 = 2;
|
||||
const kFractionsType: i32 = 11;
|
||||
const kHistoricalLigaturesOffSelector: i32 = 21;
|
||||
const kHistoricalLigaturesOnSelector: i32 = 20;
|
||||
const kHojoCharactersSelector: i32 = 12;
|
||||
const kInferiorsSelector: i32 = 2;
|
||||
const kJIS2004CharactersSelector: i32 = 11;
|
||||
const kLigaturesType: i32 = 1;
|
||||
const kLowerCasePetiteCapsSelector: i32 = 2;
|
||||
const kLowerCaseSmallCapsSelector: i32 = 1;
|
||||
const kLowerCaseType: i32 = 37;
|
||||
const kLowerCaseNumbersSelector: i32 = 0;
|
||||
const kMathematicalGreekOffSelector: i32 = 11;
|
||||
const kMathematicalGreekOnSelector: i32 = 10;
|
||||
const kMonospacedNumbersSelector: i32 = 0;
|
||||
const kNLCCharactersSelector: i32 = 13;
|
||||
const kNoFractionsSelector: i32 = 0;
|
||||
const kNormalPositionSelector: i32 = 0;
|
||||
const kNoStyleOptionsSelector: i32 = 0;
|
||||
const kNumberCaseType: i32 = 21;
|
||||
const kNumberSpacingType: i32 = 6;
|
||||
const kOrdinalsSelector: i32 = 3;
|
||||
const kProportionalNumbersSelector: i32 = 1;
|
||||
const kQuarterWidthTextSelector: i32 = 4;
|
||||
const kScientificInferiorsSelector: i32 = 4;
|
||||
const kSlashedZeroOffSelector: i32 = 5;
|
||||
const kSlashedZeroOnSelector: i32 = 4;
|
||||
const kStyleOptionsType: i32 = 19;
|
||||
const kStylisticAltEighteenOffSelector: i32 = 37;
|
||||
const kStylisticAltEighteenOnSelector: i32 = 36;
|
||||
const kStylisticAltEightOffSelector: i32 = 17;
|
||||
const kStylisticAltEightOnSelector: i32 = 16;
|
||||
const kStylisticAltElevenOffSelector: i32 = 23;
|
||||
const kStylisticAltElevenOnSelector: i32 = 22;
|
||||
const kStylisticAlternativesType: i32 = 35;
|
||||
const kStylisticAltFifteenOffSelector: i32 = 31;
|
||||
const kStylisticAltFifteenOnSelector: i32 = 30;
|
||||
const kStylisticAltFiveOffSelector: i32 = 11;
|
||||
const kStylisticAltFiveOnSelector: i32 = 10;
|
||||
const kStylisticAltFourOffSelector: i32 = 9;
|
||||
const kStylisticAltFourOnSelector: i32 = 8;
|
||||
const kStylisticAltFourteenOffSelector: i32 = 29;
|
||||
const kStylisticAltFourteenOnSelector: i32 = 28;
|
||||
const kStylisticAltNineOffSelector: i32 = 19;
|
||||
const kStylisticAltNineOnSelector: i32 = 18;
|
||||
const kStylisticAltNineteenOffSelector: i32 = 39;
|
||||
const kStylisticAltNineteenOnSelector: i32 = 38;
|
||||
const kStylisticAltOneOffSelector: i32 = 3;
|
||||
const kStylisticAltOneOnSelector: i32 = 2;
|
||||
const kStylisticAltSevenOffSelector: i32 = 15;
|
||||
const kStylisticAltSevenOnSelector: i32 = 14;
|
||||
const kStylisticAltSeventeenOffSelector: i32 = 35;
|
||||
const kStylisticAltSeventeenOnSelector: i32 = 34;
|
||||
const kStylisticAltSixOffSelector: i32 = 13;
|
||||
const kStylisticAltSixOnSelector: i32 = 12;
|
||||
const kStylisticAltSixteenOffSelector: i32 = 33;
|
||||
const kStylisticAltSixteenOnSelector: i32 = 32;
|
||||
const kStylisticAltTenOffSelector: i32 = 21;
|
||||
const kStylisticAltTenOnSelector: i32 = 20;
|
||||
const kStylisticAltThirteenOffSelector: i32 = 27;
|
||||
const kStylisticAltThirteenOnSelector: i32 = 26;
|
||||
const kStylisticAltThreeOffSelector: i32 = 7;
|
||||
const kStylisticAltThreeOnSelector: i32 = 6;
|
||||
const kStylisticAltTwelveOffSelector: i32 = 25;
|
||||
const kStylisticAltTwelveOnSelector: i32 = 24;
|
||||
const kStylisticAltTwentyOffSelector: i32 = 41;
|
||||
const kStylisticAltTwentyOnSelector: i32 = 40;
|
||||
const kStylisticAltTwoOffSelector: i32 = 5;
|
||||
const kStylisticAltTwoOnSelector: i32 = 4;
|
||||
const kSuperiorsSelector: i32 = 1;
|
||||
const kSwashAlternatesOffSelector: i32 = 3;
|
||||
const kSwashAlternatesOnSelector: i32 = 2;
|
||||
const kTitlingCapsSelector: i32 = 4;
|
||||
const kTypographicExtrasType: i32 = 14;
|
||||
const kVerticalFractionsSelector: i32 = 1;
|
||||
const kVerticalPositionType: i32 = 10;
|
||||
|
||||
pub fn apply_features(font: &mut Font, features: &Features) {
|
||||
// See https://chromium.googlesource.com/chromium/src/+/66.0.3359.158/third_party/harfbuzz-ng/src/hb-coretext.cc
|
||||
// for a reference implementation.
|
||||
toggle_open_type_feature(
|
||||
font,
|
||||
features.calt,
|
||||
kContextualAlternatesType,
|
||||
kContextualAlternatesOnSelector,
|
||||
kContextualAlternatesOffSelector,
|
||||
);
|
||||
toggle_open_type_feature(
|
||||
font,
|
||||
features.case,
|
||||
kCaseSensitiveLayoutType,
|
||||
kCaseSensitiveLayoutOnSelector,
|
||||
kCaseSensitiveLayoutOffSelector,
|
||||
);
|
||||
toggle_open_type_feature(
|
||||
font,
|
||||
features.cpsp,
|
||||
kCaseSensitiveLayoutType,
|
||||
kCaseSensitiveSpacingOnSelector,
|
||||
kCaseSensitiveSpacingOffSelector,
|
||||
);
|
||||
toggle_open_type_feature(
|
||||
font,
|
||||
features.frac,
|
||||
kFractionsType,
|
||||
kDiagonalFractionsSelector,
|
||||
kNoFractionsSelector,
|
||||
);
|
||||
toggle_open_type_feature(
|
||||
font,
|
||||
features.liga,
|
||||
kLigaturesType,
|
||||
kCommonLigaturesOnSelector,
|
||||
kCommonLigaturesOffSelector,
|
||||
);
|
||||
toggle_open_type_feature(
|
||||
font,
|
||||
features.onum,
|
||||
kNumberCaseType,
|
||||
kLowerCaseNumbersSelector,
|
||||
2,
|
||||
);
|
||||
toggle_open_type_feature(
|
||||
font,
|
||||
features.ordn,
|
||||
kVerticalPositionType,
|
||||
kOrdinalsSelector,
|
||||
kNormalPositionSelector,
|
||||
);
|
||||
toggle_open_type_feature(
|
||||
font,
|
||||
features.pnum,
|
||||
kNumberSpacingType,
|
||||
kProportionalNumbersSelector,
|
||||
4,
|
||||
);
|
||||
toggle_open_type_feature(
|
||||
font,
|
||||
features.ss01,
|
||||
kStylisticAlternativesType,
|
||||
kStylisticAltOneOnSelector,
|
||||
kStylisticAltOneOffSelector,
|
||||
);
|
||||
toggle_open_type_feature(
|
||||
font,
|
||||
features.ss02,
|
||||
kStylisticAlternativesType,
|
||||
kStylisticAltTwoOnSelector,
|
||||
kStylisticAltTwoOffSelector,
|
||||
);
|
||||
toggle_open_type_feature(
|
||||
font,
|
||||
features.ss03,
|
||||
kStylisticAlternativesType,
|
||||
kStylisticAltThreeOnSelector,
|
||||
kStylisticAltThreeOffSelector,
|
||||
);
|
||||
toggle_open_type_feature(
|
||||
font,
|
||||
features.ss04,
|
||||
kStylisticAlternativesType,
|
||||
kStylisticAltFourOnSelector,
|
||||
kStylisticAltFourOffSelector,
|
||||
);
|
||||
toggle_open_type_feature(
|
||||
font,
|
||||
features.ss05,
|
||||
kStylisticAlternativesType,
|
||||
kStylisticAltFiveOnSelector,
|
||||
kStylisticAltFiveOffSelector,
|
||||
);
|
||||
toggle_open_type_feature(
|
||||
font,
|
||||
features.ss06,
|
||||
kStylisticAlternativesType,
|
||||
kStylisticAltSixOnSelector,
|
||||
kStylisticAltSixOffSelector,
|
||||
);
|
||||
toggle_open_type_feature(
|
||||
font,
|
||||
features.ss07,
|
||||
kStylisticAlternativesType,
|
||||
kStylisticAltSevenOnSelector,
|
||||
kStylisticAltSevenOffSelector,
|
||||
);
|
||||
toggle_open_type_feature(
|
||||
font,
|
||||
features.ss08,
|
||||
kStylisticAlternativesType,
|
||||
kStylisticAltEightOnSelector,
|
||||
kStylisticAltEightOffSelector,
|
||||
);
|
||||
toggle_open_type_feature(
|
||||
font,
|
||||
features.ss09,
|
||||
kStylisticAlternativesType,
|
||||
kStylisticAltNineOnSelector,
|
||||
kStylisticAltNineOffSelector,
|
||||
);
|
||||
toggle_open_type_feature(
|
||||
font,
|
||||
features.ss10,
|
||||
kStylisticAlternativesType,
|
||||
kStylisticAltTenOnSelector,
|
||||
kStylisticAltTenOffSelector,
|
||||
);
|
||||
toggle_open_type_feature(
|
||||
font,
|
||||
features.ss11,
|
||||
kStylisticAlternativesType,
|
||||
kStylisticAltElevenOnSelector,
|
||||
kStylisticAltElevenOffSelector,
|
||||
);
|
||||
toggle_open_type_feature(
|
||||
font,
|
||||
features.ss12,
|
||||
kStylisticAlternativesType,
|
||||
kStylisticAltTwelveOnSelector,
|
||||
kStylisticAltTwelveOffSelector,
|
||||
);
|
||||
toggle_open_type_feature(
|
||||
font,
|
||||
features.ss13,
|
||||
kStylisticAlternativesType,
|
||||
kStylisticAltThirteenOnSelector,
|
||||
kStylisticAltThirteenOffSelector,
|
||||
);
|
||||
toggle_open_type_feature(
|
||||
font,
|
||||
features.ss14,
|
||||
kStylisticAlternativesType,
|
||||
kStylisticAltFourteenOnSelector,
|
||||
kStylisticAltFourteenOffSelector,
|
||||
);
|
||||
toggle_open_type_feature(
|
||||
font,
|
||||
features.ss15,
|
||||
kStylisticAlternativesType,
|
||||
kStylisticAltFifteenOnSelector,
|
||||
kStylisticAltFifteenOffSelector,
|
||||
);
|
||||
toggle_open_type_feature(
|
||||
font,
|
||||
features.ss16,
|
||||
kStylisticAlternativesType,
|
||||
kStylisticAltSixteenOnSelector,
|
||||
kStylisticAltSixteenOffSelector,
|
||||
);
|
||||
toggle_open_type_feature(
|
||||
font,
|
||||
features.ss17,
|
||||
kStylisticAlternativesType,
|
||||
kStylisticAltSeventeenOnSelector,
|
||||
kStylisticAltSeventeenOffSelector,
|
||||
);
|
||||
toggle_open_type_feature(
|
||||
font,
|
||||
features.ss18,
|
||||
kStylisticAlternativesType,
|
||||
kStylisticAltEighteenOnSelector,
|
||||
kStylisticAltEighteenOffSelector,
|
||||
);
|
||||
toggle_open_type_feature(
|
||||
font,
|
||||
features.ss19,
|
||||
kStylisticAlternativesType,
|
||||
kStylisticAltNineteenOnSelector,
|
||||
kStylisticAltNineteenOffSelector,
|
||||
);
|
||||
toggle_open_type_feature(
|
||||
font,
|
||||
features.ss20,
|
||||
kStylisticAlternativesType,
|
||||
kStylisticAltTwentyOnSelector,
|
||||
kStylisticAltTwentyOffSelector,
|
||||
);
|
||||
toggle_open_type_feature(
|
||||
font,
|
||||
features.subs,
|
||||
kVerticalPositionType,
|
||||
kInferiorsSelector,
|
||||
kNormalPositionSelector,
|
||||
);
|
||||
toggle_open_type_feature(
|
||||
font,
|
||||
features.sups,
|
||||
kVerticalPositionType,
|
||||
kSuperiorsSelector,
|
||||
kNormalPositionSelector,
|
||||
);
|
||||
toggle_open_type_feature(
|
||||
font,
|
||||
features.swsh,
|
||||
kContextualAlternatesType,
|
||||
kSwashAlternatesOnSelector,
|
||||
kSwashAlternatesOffSelector,
|
||||
);
|
||||
toggle_open_type_feature(
|
||||
font,
|
||||
features.titl,
|
||||
kStyleOptionsType,
|
||||
kTitlingCapsSelector,
|
||||
kNoStyleOptionsSelector,
|
||||
);
|
||||
toggle_open_type_feature(
|
||||
font,
|
||||
features.tnum,
|
||||
kNumberSpacingType,
|
||||
kMonospacedNumbersSelector,
|
||||
4,
|
||||
);
|
||||
toggle_open_type_feature(
|
||||
font,
|
||||
features.zero,
|
||||
kTypographicExtrasType,
|
||||
kSlashedZeroOnSelector,
|
||||
kSlashedZeroOffSelector,
|
||||
);
|
||||
}
|
||||
|
||||
fn toggle_open_type_feature(
|
||||
font: &mut Font,
|
||||
enabled: Option<bool>,
|
||||
type_identifier: i32,
|
||||
on_selector_identifier: i32,
|
||||
off_selector_identifier: i32,
|
||||
) {
|
||||
if let Some(enabled) = enabled {
|
||||
let native_font = font.native_font();
|
||||
unsafe {
|
||||
let selector_identifier = if enabled {
|
||||
on_selector_identifier
|
||||
} else {
|
||||
off_selector_identifier
|
||||
};
|
||||
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 = Font::from_native_font(new_font);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[link(name = "CoreText", kind = "framework")]
|
||||
extern "C" {
|
||||
fn CTFontCreateCopyWithAttributes(
|
||||
font: CTFontRef,
|
||||
size: CGFloat,
|
||||
matrix: *const CGAffineTransform,
|
||||
attributes: CTFontDescriptorRef,
|
||||
) -> CTFontRef;
|
||||
}
|
||||
|
@ -98,11 +98,78 @@ export interface TextProperties {
|
||||
weight?: FontWeight
|
||||
underline?: boolean
|
||||
color?: string,
|
||||
features?: TextFeatures,
|
||||
features?: FontFeatures,
|
||||
}
|
||||
|
||||
interface TextFeatures {
|
||||
calt?: boolean
|
||||
interface FontFeatures {
|
||||
/** Contextual Alternates: Applies a second substitution feature based on a match of a character pattern within a context of surrounding patterns */
|
||||
calt?: boolean;
|
||||
/** Case-Sensitive Forms: Shifts various punctuation marks up to a position that works better with all-capital sequences */
|
||||
case?: boolean;
|
||||
/** Capital Spacing: Adjusts inter-glyph spacing for all-capital text */
|
||||
cpsp?: boolean;
|
||||
/** Fractions: Replaces figures separated by a slash with diagonal fractions */
|
||||
frac?: boolean;
|
||||
/** Standard Ligatures: Replaces a sequence of glyphs with a single glyph which is preferred for typographic purposes */
|
||||
liga?: boolean;
|
||||
/** Oldstyle Figures: Changes selected figures from the default or lining style to oldstyle form. */
|
||||
onum?: boolean;
|
||||
/** Ordinals: Replaces default alphabetic glyphs with the corresponding ordinal forms for use after figures */
|
||||
ordn?: boolean;
|
||||
/** Proportional Figures: Replaces figure glyphs set on uniform (tabular) widths with corresponding glyphs set on proportional widths */
|
||||
pnum?: boolean;
|
||||
/** Stylistic set 01 */
|
||||
ss01?: boolean;
|
||||
/** Stylistic set 02 */
|
||||
ss02?: boolean;
|
||||
/** Stylistic set 03 */
|
||||
ss03?: boolean;
|
||||
/** Stylistic set 04 */
|
||||
ss04?: boolean;
|
||||
/** Stylistic set 05 */
|
||||
ss05?: boolean;
|
||||
/** Stylistic set 06 */
|
||||
ss06?: boolean;
|
||||
/** Stylistic set 07 */
|
||||
ss07?: boolean;
|
||||
/** Stylistic set 08 */
|
||||
ss08?: boolean;
|
||||
/** Stylistic set 09 */
|
||||
ss09?: boolean;
|
||||
/** Stylistic set 10 */
|
||||
ss10?: boolean;
|
||||
/** Stylistic set 11 */
|
||||
ss11?: boolean;
|
||||
/** Stylistic set 12 */
|
||||
ss12?: boolean;
|
||||
/** Stylistic set 13 */
|
||||
ss13?: boolean;
|
||||
/** Stylistic set 14 */
|
||||
ss14?: boolean;
|
||||
/** Stylistic set 15 */
|
||||
ss15?: boolean;
|
||||
/** Stylistic set 16 */
|
||||
ss16?: boolean;
|
||||
/** Stylistic set 17 */
|
||||
ss17?: boolean;
|
||||
/** Stylistic set 18 */
|
||||
ss18?: boolean;
|
||||
/** Stylistic set 19 */
|
||||
ss19?: boolean;
|
||||
/** Stylistic set 20 */
|
||||
ss20?: boolean;
|
||||
/** Subscript: Replaces default glyphs with subscript glyphs */
|
||||
subs?: boolean;
|
||||
/** Superscript: Replaces default glyphs with superscript glyphs */
|
||||
sups?: boolean;
|
||||
/** Swash: Replaces default glyphs with swash glyphs for stylistic purposes */
|
||||
swsh?: boolean;
|
||||
/** Titling: Replaces default glyphs with titling glyphs for use in large-size settings */
|
||||
titl?: boolean;
|
||||
/** Tabular Figures: Replaces figure glyphs set on proportional widths with corresponding glyphs set on uniform (tabular) widths */
|
||||
tnum?: boolean;
|
||||
/** Slashed Zero: Replaces default zero with a slashed zero for better distinction between "0" and "O" */
|
||||
zero?: boolean;
|
||||
}
|
||||
|
||||
export function text(
|
||||
|
Loading…
Reference in New Issue
Block a user