@@ -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