Objective-C – CTFont change font style?

I have a CTFont that contains a font style, and sumbolic traits.

I want to create a new font with a new style that inherits the symbolic traits of the first font.
How can I achieve this?

  • Giving Framesetter the correct line spacing adjustment
  • iPhone - Convert CTFont to UIFont?
  • Determine if unicode character has a glyph in UIFont
  • CTFontRef newFontWithoutTraits = CTFontCreateWithName((CFString)newFontName, CTFontGetSize(font), NULL);
    CTFontRef newFont = CTFontCreateCopyWithSymbolicTraits(newFontWithoutTraits, CTFontGetSize(font), NULL, 0, CTFontGetSymbolicTraits(font));
    

    the new font is null here
    I don’t know what should I pass to the 4th parameter in CTFontCreateCopyWithSymbolicTraits.

    Solutions Collect From Internet About “Objective-C – CTFont change font style?”

    I do this line of code to generate a bold font from non-bold font:

    CTFontRef newFont = CTFontCreateCopyWithSymbolicTraits(currentFont, 0.0, NULL, (wantBold?kCTFontBoldTrait:0), kCTFontBoldTrait);
    
    • currentFont is the CTFontRef I want to add symbolic traits to
    • wantBold is a boolean to tell if I want to add or remove the bold trait to the font
    • kCTFontBoldTrait is the symbolic trait I want to modify on the font.

    The 4th parameter is the value you want to apply. The 5th is the mask to select the symbolic trait.


    You may thing of it as bitmask to apply to the symbolic trait, where the 4th parameter of CTFontCreateCopyWithSymbolicTraits is the value and the 5th parameter is the mask:

    • If you want to set the symtrait and add it to the font, iOS will probably apply sthg like newTrait = oldTrait | (value&mask), setting the bit corresponding to mask to the value of value.
    • If you want to unset the symtrait and remove it from the font, you use the value of 0 as the 4th parameter and iOS will probably apply sthg like newTrait = oldTrait & ~mask to unset the bit.

    • But if you need to, you can also set and unset multiple bits (thus multiple symbolic traits) at once, using the right value that have 1 on bits to set and 0 on bits to unset (or to ignore), and and using the right mask that have 1 on bits that needs to be modified and 0 on bits that don’t need to be changed.


    [EDIT2]

    I finally managed to find the solution for your specific case: you need to get the symtraits mask of your font as you already do… and bitwise-or it with the symtraits of your newFontWithoutTraits font.

    This is because newFontWithoutTraits actually do have default symtraits (contrary to what I thought, it has a non-zero CTFontSymbolicTraits value) as the symtraits value also contains info for the font class and such things (so even a non-bold, non-italic font can have a non-zero symtraits value, log the hex value of the symtraits of your font to understand better).

    So this is the code you need:

    CTFontRef font = CTFontCreateWithName((CFStringRef)@"Courier Bold", 12, NULL);
    CGFloat fontSize = CTFontGetSize(font);
    CTFontSymbolicTraits fontTraits = CTFontGetSymbolicTraits(font);
    CTFontRef newFontWithoutTraits = CTFontCreateWithName((CFStringRef)@"Arial", fontSize, NULL);
    fontTraits |= CTFontGetSymbolicTraits(newFontWithoutTraits);
    CTFontRef newFont = CTFontCreateCopyWithSymbolicTraits(newFontWithoutTraits, fontSize, NULL, fontTraits, fontTraits);
    
    // Check the results (yes, this NSLog create leaks as I don't release the CFStrings, but this is just for debugging)
    NSLog(@"font:%@, newFontWithoutTraits:%@, newFont:%@", CTFontCopyFullName(font), CTFontCopyFullName(newFontWithoutTraits), CTFontCopyFullName(newFont));
    
    // Clear memory (CoreFoundation "Create Rule", objects needs to be CFRelease'd)
    CFRelease(newFont);
    CFRelease(newFontWithoutTraits);
    CFRelease(font);