Skip to content

Commit 7a2ec12

Browse files
authored
Auto merge of #421 - jrmuizel:copy-system, r=jdm
Test that copying system fonts doesn't change the url
2 parents d107afb + 11247e3 commit 7a2ec12

File tree

1 file changed

+83
-1
lines changed

1 file changed

+83
-1
lines changed

core-text/src/font.rs

Lines changed: 83 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -539,7 +539,8 @@ extern {
539539
fn CTFontCreateWithFontDescriptor(descriptor: CTFontDescriptorRef, size: CGFloat,
540540
matrix: *const CGAffineTransform) -> CTFontRef;
541541
//fn CTFontCreateWithFontDescriptorAndOptions
542-
//fn CTFontCreateUIFontForLanguage
542+
#[cfg(test)]
543+
fn CTFontCreateUIFontForLanguage(uiType: CTFontUIFontType, size: CGFloat, language: CFStringRef) -> CTFontRef;
543544
fn CTFontCreateCopyWithAttributes(font: CTFontRef, size: CGFloat, matrix: *const CGAffineTransform,
544545
attributes: CTFontDescriptorRef) -> CTFontRef;
545546
fn CTFontCreateCopyWithSymbolicTraits(font: CTFontRef,
@@ -660,3 +661,84 @@ fn copy_font() {
660661
assert_eq!(font.family_name(), "Zapf Dingbats");
661662
}
662663

664+
#[cfg(test)]
665+
fn macos_version() -> (i32, i32, i32) {
666+
use std::io::Read;
667+
668+
// This is the same approach that Firefox uses for detecting versions
669+
let file = "/System/Library/CoreServices/SystemVersion.plist";
670+
let mut f = std::fs::File::open(file).unwrap();
671+
let mut system_version_data = Vec::new();
672+
f.read_to_end(&mut system_version_data).unwrap();
673+
674+
use core_foundation::propertylist;
675+
let (list, _) = propertylist::create_with_data(core_foundation::data::CFData::from_buffer(&system_version_data), propertylist::kCFPropertyListImmutable).unwrap();
676+
let k = unsafe { propertylist::CFPropertyList::wrap_under_create_rule(list) };
677+
678+
let dict = unsafe { std::mem::transmute::<_, CFDictionary<CFType, CFType>>(k.downcast::<CFDictionary>().unwrap()) };
679+
680+
let version = dict.find(&CFString::new("ProductVersion").as_CFType())
681+
.as_ref().unwrap()
682+
.downcast::<CFString>().unwrap()
683+
.to_string();
684+
685+
match version.split(".").map(|x| x.parse().unwrap()).collect::<Vec<_>>()[..] {
686+
[a, b, c] => (a, b, c),
687+
[a, b] => (a, b, 0),
688+
_ => panic!()
689+
}
690+
}
691+
692+
#[test]
693+
fn copy_system_font() {
694+
let small = unsafe {
695+
CTFont::wrap_under_create_rule(
696+
CTFontCreateUIFontForLanguage(kCTFontSystemDetailFontType, 19., std::ptr::null())
697+
)
698+
};
699+
let big = small.clone_with_font_size(20.);
700+
701+
// ensure that we end up with different fonts for the different sizes before 10.15
702+
if macos_version() < (10, 15, 0) {
703+
assert_ne!(big.url(), small.url());
704+
} else {
705+
assert_eq!(big.url(), small.url());
706+
}
707+
708+
let ps = small.postscript_name();
709+
let desc = small.copy_descriptor();
710+
711+
// check that we can construct a new vesion by descriptor
712+
let ctfont = new_from_descriptor(&desc, 20.);
713+
assert_eq!(big.postscript_name(), ctfont.postscript_name());
714+
715+
// on newer versions of macos we can't construct by name anymore
716+
if macos_version() < (10, 13, 0) {
717+
let ui_font_by_name = new_from_name(&small.postscript_name(), 19.).unwrap();
718+
assert_eq!(ui_font_by_name.postscript_name(), small.postscript_name());
719+
720+
let ui_font_by_name = new_from_name(&small.postscript_name(), 20.).unwrap();
721+
assert_eq!(ui_font_by_name.postscript_name(), small.postscript_name());
722+
723+
let ui_font_by_name = new_from_name(&big.postscript_name(), 20.).unwrap();
724+
assert_eq!(ui_font_by_name.postscript_name(), big.postscript_name());
725+
}
726+
727+
// but we can still construct the CGFont by name
728+
let cgfont = CGFont::from_name(&CFString::new(&ps)).unwrap();
729+
let cgfont = new_from_CGFont(&cgfont, 0.);
730+
println!("{:?}", cgfont);
731+
let desc = cgfont.copy_descriptor();
732+
let matching = unsafe { crate::font_descriptor::CTFontDescriptorCreateMatchingFontDescriptor(desc.as_concrete_TypeRef(), std::ptr::null()) };
733+
let matching = unsafe { CTFontDescriptor::wrap_under_create_rule(matching) };
734+
735+
println!("{:?}", cgfont.copy_descriptor());
736+
assert!(desc.attributes().find(CFString::from_static_string("NSFontSizeAttribute")).is_some());
737+
738+
println!("{:?}", matching);
739+
println!("{:?}", matching.attributes().find(CFString::from_static_string("NSFontSizeAttribute")));
740+
741+
assert!(matching.attributes().find(CFString::from_static_string("NSFontSizeAttribute")).is_none());
742+
743+
assert_eq!(small.postscript_name(), cgfont.postscript_name());
744+
}

0 commit comments

Comments
 (0)