@@ -539,7 +539,8 @@ extern {
539
539
fn CTFontCreateWithFontDescriptor ( descriptor : CTFontDescriptorRef , size : CGFloat ,
540
540
matrix : * const CGAffineTransform ) -> CTFontRef ;
541
541
//fn CTFontCreateWithFontDescriptorAndOptions
542
- //fn CTFontCreateUIFontForLanguage
542
+ #[ cfg( test) ]
543
+ fn CTFontCreateUIFontForLanguage ( uiType : CTFontUIFontType , size : CGFloat , language : CFStringRef ) -> CTFontRef ;
543
544
fn CTFontCreateCopyWithAttributes ( font : CTFontRef , size : CGFloat , matrix : * const CGAffineTransform ,
544
545
attributes : CTFontDescriptorRef ) -> CTFontRef ;
545
546
fn CTFontCreateCopyWithSymbolicTraits ( font : CTFontRef ,
@@ -660,3 +661,84 @@ fn copy_font() {
660
661
assert_eq ! ( font. family_name( ) , "Zapf Dingbats" ) ;
661
662
}
662
663
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