views:

78

answers:

2

How can i make a new CFAttributedStringRef with increased font-size based on a CFAttributedStringRef i got?

In my specific project i would like to dynamically increase the size. If i call CFAttributedStringSetAttribute(...) on the whole string using CTFontRef the string will lose it's formatting and the new will replace all the others fonts in the string.. I would not like to parse and recreate the whole attributedstring just to increase the size of it, but it seems that is the only way...

A: 

I believe parsing is the only way. Attributed string can have quite complex format, it's your job to increase the font size.

However, if you need this trick for rendering, you can avoid string parsing - use a scale transform to increase the text size.

Gobra
allright, i see. i'll try that scale thingy!
Fossli
I'm not really sure where is best to implement CGAffineTransformMakeScale(). I tried doing it in drawrect, but then it was just applied to the all the glyphs which where weird since they had the same position.
Fossli
Also, i would really much like to know dimensions, text left etc before actually drawing takes place.
Fossli
hi again. please have a look at my try. Am I missing something or is there something i should take into consideration when doing it like that?
Fossli
I think you can use default system font (and font size) as a basement for those formatted segments without the font attribute. Just a trick.
Gobra
+1  A: 

I've got it working with the following code. One miss though is if some text in the attributedstring has not been set a font-attribute it will not be updated. So i had to encapsulate everything with font-attributes.

- (void)recalculateSizeChangeInAttributedString {

    if(self.attributedStringOriginal == nil) {
        self.attributedStringOriginal = [self.attributedString copy];
    }

    CFMutableAttributedStringRef tempString = CFAttributedStringCreateMutableCopy(CFAllocatorGetDefault(), self.attributedStringOriginal.length, (CFMutableAttributedStringRef)self.attributedStringOriginal);

    int lastIndex = 0;
    int limit = CFAttributedStringGetLength(tempString);
    for (int index = 0; index < limit;) {

        CFRange inRange = CFRangeMake(0, limit - index);
        CFRange longestEffective;
        CTFontRef font = (CTFontRef)CFAttributedStringGetAttribute(tempString, index, kCTFontAttributeName, &longestEffective);

        if(font != nil) {

            // log for testing
            NSLog(@"index: %i, range: %i - %i, longest: %i - %i, attribute: %@", 
                  index, inRange.location, 
                  inRange.location + inRange.length, 
                  longestEffective.location, longestEffective.location + longestEffective.length, 
                  @"..." 
                  );


            // alter the font and set the altered font/attribute
            int rangeEnd = longestEffective.length != 0 ? longestEffective.length : 1;
            CTFontRef modifiedFont = CTFontCreateCopyWithAttributes(font, CTFontGetSize((CTFontRef)font) * sizeFactor, NULL, NULL); 
            CFAttributedStringSetAttribute(tempString, CFRangeMake(index, rangeEnd), kCTFontAttributeName, modifiedFont); 
            CFRelease(modifiedFont);

        }

        // make next loop continue where current attribute ended
        index += longestEffective.length; 

        if(index == lastIndex)
            index ++;
        lastIndex = index;

    }

    self.attributedString = (NSMutableAttributedString *)tempString;

    CFRelease(tempString); 

 }
Fossli