macOS: Support all OpenType
font features (#11611)
This PR brings support for all `OpenType` font features to `macOS(v10.10+)`. Now, both `Windows`(with #10756 ) and `macOS` support all font features. Due to my limited familiarity with the APIs on macOS, I believe I have made sure to call `CFRelease` on all variables where it should be called. Close #11486 , and I think the official website's [documentation](https://zed.dev/docs/configuring-zed) can be updated after merging this PR. > Zed supports a subset of OpenType features that can be enabled or disabled for a given buffer or terminal font. The following OpenType features can be enabled or disabled too: calt, case, cpsp, frac, liga, onum, ordn, pnum, ss01, ss02, ss03, ss04, ss05, ss06, ss07, ss08, ss09, ss10, ss11, ss12, ss13, ss14, ss15, ss16, ss17, ss18, ss19, ss20, subs, sups, swsh, titl, tnum, zero. https://github.com/zed-industries/zed/assets/14981363/44e503f9-1496-4746-bc7d-20878c6f8a93 Release Notes: - Added support for **all** `OpenType` font features to macOS.
This commit is contained in:
parent
f47bd32f15
commit
f7c5d70740
2 changed files with 60 additions and 394 deletions
|
@ -2,374 +2,66 @@
|
||||||
|
|
||||||
use crate::FontFeatures;
|
use crate::FontFeatures;
|
||||||
use cocoa::appkit::CGFloat;
|
use cocoa::appkit::CGFloat;
|
||||||
use core_foundation::{base::TCFType, number::CFNumber};
|
use core_foundation::{
|
||||||
use core_graphics::geometry::CGAffineTransform;
|
array::{
|
||||||
|
kCFTypeArrayCallBacks, CFArray, CFArrayAppendValue, CFArrayCreateMutable, CFMutableArrayRef,
|
||||||
|
},
|
||||||
|
base::{kCFAllocatorDefault, CFRelease, TCFType},
|
||||||
|
dictionary::{
|
||||||
|
kCFTypeDictionaryKeyCallBacks, kCFTypeDictionaryValueCallBacks, CFDictionaryCreate,
|
||||||
|
},
|
||||||
|
number::CFNumber,
|
||||||
|
string::{CFString, CFStringRef},
|
||||||
|
};
|
||||||
|
use core_graphics::{display::CFDictionary, geometry::CGAffineTransform};
|
||||||
use core_text::{
|
use core_text::{
|
||||||
font::{CTFont, CTFontRef},
|
font::{CTFont, CTFontRef},
|
||||||
font_descriptor::{
|
font_descriptor::{
|
||||||
CTFontDescriptor, CTFontDescriptorCreateCopyWithFeature, CTFontDescriptorRef,
|
kCTFontFeatureSettingsAttribute, CTFontDescriptor, CTFontDescriptorCopyAttributes,
|
||||||
|
CTFontDescriptorCreateCopyWithFeature, CTFontDescriptorCreateWithAttributes,
|
||||||
|
CTFontDescriptorRef,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use font_kit::font::Font;
|
use font_kit::font::Font;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
|
|
||||||
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: &FontFeatures) {
|
pub fn apply_features(font: &mut Font, features: &FontFeatures) {
|
||||||
// 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 {
|
unsafe {
|
||||||
let selector_identifier = if enabled {
|
let native_font = font.native_font();
|
||||||
on_selector_identifier
|
let mut feature_array =
|
||||||
} else {
|
CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
|
||||||
off_selector_identifier
|
for (tag, enable) in features.tag_value_list() {
|
||||||
};
|
if !enable {
|
||||||
let new_descriptor = CTFontDescriptorCreateCopyWithFeature(
|
continue;
|
||||||
native_font.copy_descriptor().as_concrete_TypeRef(),
|
}
|
||||||
CFNumber::from(type_identifier).as_concrete_TypeRef(),
|
let keys = [kCTFontOpenTypeFeatureTag, kCTFontOpenTypeFeatureValue];
|
||||||
CFNumber::from(selector_identifier).as_concrete_TypeRef(),
|
let values = [
|
||||||
|
CFString::new(&tag).as_CFTypeRef(),
|
||||||
|
CFNumber::from(1).as_CFTypeRef(),
|
||||||
|
];
|
||||||
|
let dict = CFDictionaryCreate(
|
||||||
|
kCFAllocatorDefault,
|
||||||
|
&keys as *const _ as _,
|
||||||
|
&values as *const _ as _,
|
||||||
|
2,
|
||||||
|
&kCFTypeDictionaryKeyCallBacks,
|
||||||
|
&kCFTypeDictionaryValueCallBacks,
|
||||||
);
|
);
|
||||||
|
values.into_iter().for_each(|value| CFRelease(value));
|
||||||
|
CFArrayAppendValue(feature_array, dict as _);
|
||||||
|
CFRelease(dict as _);
|
||||||
|
}
|
||||||
|
let attrs = CFDictionaryCreate(
|
||||||
|
kCFAllocatorDefault,
|
||||||
|
&kCTFontFeatureSettingsAttribute as *const _ as _,
|
||||||
|
&feature_array as *const _ as _,
|
||||||
|
1,
|
||||||
|
&kCFTypeDictionaryKeyCallBacks,
|
||||||
|
&kCFTypeDictionaryValueCallBacks,
|
||||||
|
);
|
||||||
|
CFRelease(feature_array as *const _ as _);
|
||||||
|
let new_descriptor = CTFontDescriptorCreateWithAttributes(attrs);
|
||||||
|
CFRelease(attrs as _);
|
||||||
let new_descriptor = CTFontDescriptor::wrap_under_create_rule(new_descriptor);
|
let new_descriptor = CTFontDescriptor::wrap_under_create_rule(new_descriptor);
|
||||||
let new_font = CTFontCreateCopyWithAttributes(
|
let new_font = CTFontCreateCopyWithAttributes(
|
||||||
font.native_font().as_concrete_TypeRef(),
|
font.native_font().as_concrete_TypeRef(),
|
||||||
|
@ -381,10 +73,12 @@ fn toggle_open_type_feature(
|
||||||
*font = Font::from_native_font(&new_font);
|
*font = Font::from_native_font(&new_font);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
#[link(name = "CoreText", kind = "framework")]
|
#[link(name = "CoreText", kind = "framework")]
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
static kCTFontOpenTypeFeatureTag: CFStringRef;
|
||||||
|
static kCTFontOpenTypeFeatureValue: CFStringRef;
|
||||||
|
|
||||||
fn CTFontCreateCopyWithAttributes(
|
fn CTFontCreateCopyWithAttributes(
|
||||||
font: CTFontRef,
|
font: CTFontRef,
|
||||||
size: CGFloat,
|
size: CGFloat,
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
#[cfg(target_os = "windows")]
|
|
||||||
use crate::SharedString;
|
use crate::SharedString;
|
||||||
#[cfg(target_os = "windows")]
|
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use schemars::{
|
use schemars::{
|
||||||
schema::{InstanceType, Schema, SchemaObject, SingleOrVec},
|
schema::{InstanceType, Schema, SchemaObject, SingleOrVec},
|
||||||
|
@ -15,9 +13,7 @@ macro_rules! create_definitions {
|
||||||
pub struct FontFeatures {
|
pub struct FontFeatures {
|
||||||
enabled: u64,
|
enabled: u64,
|
||||||
disabled: u64,
|
disabled: u64,
|
||||||
#[cfg(target_os = "windows")]
|
|
||||||
other_enabled: SharedString,
|
other_enabled: SharedString,
|
||||||
#[cfg(target_os = "windows")]
|
|
||||||
other_disabled: SharedString,
|
other_disabled: SharedString,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,7 +33,6 @@ macro_rules! create_definitions {
|
||||||
|
|
||||||
/// Get the tag name list of the font OpenType features
|
/// Get the tag name list of the font OpenType features
|
||||||
/// only enabled or disabled features are returned
|
/// only enabled or disabled features are returned
|
||||||
#[cfg(target_os = "windows")]
|
|
||||||
pub fn tag_value_list(&self) -> Vec<(String, bool)> {
|
pub fn tag_value_list(&self) -> Vec<(String, bool)> {
|
||||||
let mut result = Vec::new();
|
let mut result = Vec::new();
|
||||||
$(
|
$(
|
||||||
|
@ -105,29 +100,6 @@ macro_rules! create_definitions {
|
||||||
formatter.write_str("a map of font features")
|
formatter.write_str("a map of font features")
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(target_os = "windows"))]
|
|
||||||
fn visit_map<M>(self, mut access: M) -> Result<Self::Value, M::Error>
|
|
||||||
where
|
|
||||||
M: MapAccess<'de>,
|
|
||||||
{
|
|
||||||
let mut enabled: u64 = 0;
|
|
||||||
let mut disabled: u64 = 0;
|
|
||||||
|
|
||||||
while let Some((key, value)) = access.next_entry::<String, Option<bool>>()? {
|
|
||||||
let idx = match key.as_str() {
|
|
||||||
$(stringify!($name) => $idx,)*
|
|
||||||
_ => continue,
|
|
||||||
};
|
|
||||||
match value {
|
|
||||||
Some(true) => enabled |= 1 << idx,
|
|
||||||
Some(false) => disabled |= 1 << idx,
|
|
||||||
None => {}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
Ok(FontFeatures { enabled, disabled })
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(target_os = "windows")]
|
|
||||||
fn visit_map<M>(self, mut access: M) -> Result<Self::Value, M::Error>
|
fn visit_map<M>(self, mut access: M) -> Result<Self::Value, M::Error>
|
||||||
where
|
where
|
||||||
M: MapAccess<'de>,
|
M: MapAccess<'de>,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue