@@ -741,4 +741,160 @@ fn copy_system_font() {
741
741
assert ! ( matching. attributes( ) . find( CFString :: from_static_string( "NSFontSizeAttribute" ) ) . is_none( ) ) ;
742
742
743
743
assert_eq ! ( small. postscript_name( ) , cgfont. postscript_name( ) ) ;
744
+ //assert!(false);
745
+ }
746
+
747
+
748
+ fn calc_table_checksum ( table : & [ u8 ] , skipChecksumAdjust : bool ) -> u32 {
749
+ let mut sum = std:: num:: Wrapping ( 0 ) ;
750
+ let mut i = 0 ;
751
+ let mut chunks = table. chunks_exact ( 4 ) ;
752
+ for chunk in & mut chunks {
753
+ if skipChecksumAdjust && i == 2 {
754
+
755
+ } else {
756
+ let val = ( chunk[ 0 ] as u32 ) << 24 |
757
+ ( chunk[ 1 ] as u32 ) << 16 |
758
+ ( chunk[ 2 ] as u32 ) << 8 |
759
+ ( chunk[ 3 ] as u32 ) << 0 ;
760
+ sum += std:: num:: Wrapping ( val)
761
+ }
762
+ i += 1 ;
763
+ }
764
+ let mut val: u32 = 0 ;
765
+ let mut shift = 24 ;
766
+ for byte in chunks. remainder ( ) {
767
+ val |= ( * byte as u32 ) << shift;
768
+ shift -= 8 ;
769
+ }
770
+ sum += std:: num:: Wrapping ( val) ;
771
+ sum. 0
772
+ }
773
+
774
+ fn maxPow2LessThanEqual ( a : i32 ) -> i32 {
775
+ let x = 1 ;
776
+ let mut shift = 0 ;
777
+ while ( ( x << ( shift + 1 ) ) <= a) {
778
+ shift+=1 ;
779
+ }
780
+ return shift;
781
+ }
782
+
783
+
784
+ fn construct_font_data ( font : CGFont ) -> Vec < u8 > {
785
+ struct TableRecord {
786
+ tag : u32 ,
787
+ checkSum : u32 ,
788
+ offset : u32 ,
789
+ length : u32 ,
790
+ data : CFData ,
791
+ }
792
+
793
+ let tags = font. copy_table_tags ( ) ;
794
+ let count = tags. len ( ) ;
795
+ let mut records = Vec :: with_capacity ( tags. len ( ) as usize ) ;
796
+ let mut offset: u32 = 0 ;
797
+ offset += std:: mem:: size_of :: < u32 > ( ) as u32 * 3 ;
798
+ offset += std:: mem:: size_of :: < u32 > ( ) as u32 * 4 * count as u32 ;
799
+ let mut CFF = false ;
800
+ for tag in tags. iter ( ) {
801
+ let data = font. copy_table_for_tag ( * tag) . unwrap ( ) ;
802
+ let skipChecksumAdjust = * tag == 0x68656164 ; // 'head'
803
+
804
+ if * tag == 0x43464620 { // 'CFF '
805
+ CFF = true ;
806
+ }
807
+ let checkSum = calc_table_checksum ( data. bytes ( ) , skipChecksumAdjust) ;
808
+ records. push ( TableRecord { tag : * tag, offset, length : data. len ( ) as u32 , data : data. clone ( ) , checkSum} ) ;
809
+ offset += data. len ( ) as u32 ;
810
+ // 32 bit align the tables
811
+ offset = ( offset + 3 ) & !3 ;
812
+ }
813
+
814
+ let mut buf: Vec < u8 > = Vec :: new ( ) ;
815
+ if CFF {
816
+ buf. extend_from_slice ( & 0x4f54544fu32 . to_be_bytes ( ) ) ;
817
+ } else {
818
+ buf. extend_from_slice ( & 0x00010000u32 . to_be_bytes ( ) ) ;
819
+ }
820
+
821
+ buf. extend_from_slice ( & ( count as u16 ) . to_be_bytes ( ) ) ;
822
+ let maxPow2Count = maxPow2LessThanEqual ( count as i32 ) ;
823
+ buf. extend_from_slice ( & ( ( 1u16 << maxPow2Count) * 16 ) . to_be_bytes ( ) ) ;
824
+ buf. extend_from_slice ( & ( maxPow2Count as u16 ) . to_be_bytes ( ) ) ;
825
+ buf. extend_from_slice ( & ( ( count as u16 - ( 1 << maxPow2Count) ) * 16 ) . to_be_bytes ( ) ) ;
826
+
827
+ // write table record entries
828
+ for rec in & records {
829
+ buf. extend_from_slice ( & rec. tag . to_be_bytes ( ) ) ;
830
+ buf. extend_from_slice ( & rec. checkSum . to_be_bytes ( ) ) ;
831
+ buf. extend_from_slice ( & rec. offset . to_be_bytes ( ) ) ;
832
+ buf. extend_from_slice ( & rec. length . to_be_bytes ( ) ) ;
833
+ }
834
+
835
+ // write tables
836
+ let mut checksum_adjustment_offset = 0 ;
837
+ for rec in & records {
838
+ if rec. tag == 0x68656164 { // 'head'
839
+ checksum_adjustment_offset = buf. len ( ) + 2 * 4 ;
840
+ }
841
+ assert ! ( buf. len( ) == rec. offset as usize ) ;
842
+ buf. extend_from_slice ( rec. data . bytes ( ) ) ;
843
+ // align
844
+ let extra = ( ( buf. len ( ) + 3 ) & !3 ) - buf. len ( ) ;
845
+ buf. extend_from_slice ( & [ 0 ; 4 ] [ 0 ..extra] ) ;
846
+ }
847
+
848
+ // clear the checksumAdjust field before checksumming the whole font
849
+ for b in & mut buf[ checksum_adjustment_offset..checksum_adjustment_offset+4 ] {
850
+ * b = 0 ;
851
+ }
852
+ let font_check_sum = ( 0xb1b0afbau32 . wrapping_sub (
853
+ calc_table_checksum ( & buf, false ) ) ) . to_be_bytes ( ) ;
854
+ ( & mut buf[ checksum_adjustment_offset..checksum_adjustment_offset+4 ] ) . copy_from_slice ( & font_check_sum) ;
855
+
856
+ buf
857
+ }
858
+
859
+ #[ test]
860
+ fn font_data ( ) {
861
+ let small = new_from_name ( "Zapf Dingbats" , 19. ) . unwrap ( ) ;
862
+ let small = unsafe {
863
+ CTFont :: wrap_under_create_rule (
864
+ CTFontCreateUIFontForLanguage ( kCTFontSystemDetailFontType, 19. , std:: ptr:: null ( ) )
865
+ )
866
+ } ;
867
+ println ! ( "{:?}" , ( small. postscript_name( ) , small. url( ) ) ) ;
868
+ let data = construct_font_data ( small. copy_to_CGFont ( ) ) ;
869
+ let mut file = std:: fs:: File :: create ( "test.ttf" ) . unwrap ( ) ;
870
+ // Write a slice of bytes to the file
871
+ use std:: io:: Write ;
872
+ file. write_all ( & data) ;
873
+ drop ( file) ;
874
+ let font = new_from_buffer ( & data) . unwrap ( ) ;
875
+ println ! ( "{:?}" , ( font. postscript_name( ) , font. url( ) ) ) ;
876
+ //assert!(false);
877
+ }
878
+
879
+ #[ test]
880
+ fn variations ( ) {
881
+ let mut vals_str: Vec < ( CFString , CFNumber ) > = Vec :: new ( ) ;
882
+ let small = unsafe {
883
+ CTFont :: wrap_under_create_rule (
884
+ CTFontCreateUIFontForLanguage ( kCTFontEmphasizedSystemDetailFontType, 19. , std:: ptr:: null ( ) )
885
+ )
886
+ } ;
887
+ dbg ! ( & small) ;
888
+ //let font = CGFont::from_name(&CFString::new(".SFNSText-Bold")).unwrap();
889
+ let font= small. copy_to_CGFont ( ) ;
890
+ vals_str. push ( ( CFString :: new ( "Weight" ) , ( 700. ) . into ( ) ) ) ;
891
+ let vars = CFDictionary :: from_CFType_pairs ( & vals_str) ;
892
+ let var_font = CGFont :: create_copy_from_variations ( & font, & vars) . unwrap ( ) ;
893
+ extern {
894
+ pub fn CFCopyDescription ( obj : usize ) -> usize ;
895
+ }
896
+ let s: CFString = unsafe { std:: mem:: transmute ( CFCopyDescription ( std:: mem:: transmute ( var_font. clone ( ) ) ) ) } ;
897
+ println ! ( "{:}" , s) ;
898
+ dbg ! ( new_from_CGFont( & var_font. clone( ) , 19. ) ) ;
899
+ assert ! ( false ) ;
744
900
}
0 commit comments