Custom Font creation using DTDefaultFontFamily on ios < 5 #365

Closed
farfromrefug opened this Issue Mar 29, 2013 · 15 comments

2 participants

@farfromrefug

I use custom font for html string. For that i use initWithHTMLData with an option dictionary where i set DTDefaultFontFamily.
It works great on ios 6, my problem is with ios 5.
I narrowed the problem to that line
On ios 5 it will return a font "Helvetica"
I think the problem is that we use fontFamily and not fontName.
I solved using a different method. I replace the line with

if (_needsChineseFontCascadeFix) //ios <6
            {
                CTFontRef correctFont;

                NSMutableDictionary *fontAttrs = [attributes mutableCopy];
                [fontAttrs removeObjectsForKeys:[NSArray arrayWithObjects:(id)kCTFontNameAttribute, (id)kCTFontFamilyNameAttribute, nil]];

                NSString *usedName = overrideName?overrideName:(_fontName?_fontName:_fontFamily);
                correctFont = CTFontCreateWithName((__bridge CFStringRef)usedName, _pointSize, NULL);

                matchingFont = CTFontCreateCopyWithAttributes(correctFont, _pointSize, NULL, fontDesc);
                CFRelease(correctFont);
            }
            else
            {
                // fast font creation
                matchingFont = CTFontCreateWithFontDescriptor(fontDesc, _pointSize, NULL);
            }

I don't know if it is the right fix but it works for me and doesnt break fast creation in ios 6.
I hope it can make it into your master branch

@odrobnik

I have to see a test case for that and an explanation why this should be fixing it.

@farfromrefug

thanks for answering so quickly. You made have some doubt about that "bug". So i tried to reproduce it with the Demo App. And i did!
What i can tell you is that i think it comes from font instead! As to reproduce it i HAVE to use that font
So Here's how to reproduce it
Include this font into the demo App
Now we will test it in the about controller.
in DemoAboutViewController, replace viewDidLoad with this

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view from its nib.

    NSString *path = @"This is my test string";

    NSMutableDictionary *options = [NSMutableDictionary dictionaryWithObjectsAndKeys:
                                    [NSNumber numberWithInt:kCTLeftTextAlignment], DTDefaultTextAlignment,
                                    [NSNumber numberWithInt:0], DTDefaultFontStyle,
                                    @"Zero Threes", DTDefaultFontFamily,
                                    [NSNumber numberWithFloat:(40 / 12)], NSTextSizeMultiplierDocumentOption,
                                    kCTLineBreakByWordWrapping, DTDefaultLineBreakMode, nil];

    NSAttributedString *attributedString = [[NSAttributedString alloc] initWithHTMLData:[path dataUsingEncoding:NSUTF8StringEncoding] options:options documentAttributes:NULL];

    self.attributedTextView.attributedString = attributedString;
    self.attributedTextView.contentInset = UIEdgeInsetsMake(10, 10, 10, 10);
}

Run it on ios 6, the font is used. Then run it on ios 5.1, the font is helvetica.
The problem comes from that line.
If you add

NSString *postScriptName = (NSString *)CFBridgingRelease(CTFontCopyPostScriptName(matchingFont));
            NSLog(@"postScriptName == %@", postScriptName);

just after you can see that the font is Helvetica on ios 5

Now about my fix. I actually saw a similar code in another project, that s why i tried it. But you are right i am not so sure as WHY it works :s

@odrobnik

What happens if you use the font override table for your custom font, like I describe here: http://www.cocoanetics.com/2013/03/using-custom-fonts-with-dtcoretext/

@farfromrefug

I will test it. But my problem is that i use DTCoreText inside a framework, so the font family is given as a string property and so i cant override with plist or at runtime :s
I will test it in the demo though and let you know

@odrobnik

Not a plist. setOverrideFont methods, see the article.

@farfromrefug

Yes I saw that. But it s said that it should be called upon app loading. Could I call it at any point while my app is running?

Thanks

@odrobnik
@farfromrefug

That i cant :D
I guess i ll have to stick with my "dirty" fix

@odrobnik
@odrobnik odrobnik added a commit that closed this issue Mar 30, 2013
@odrobnik odrobnik Load available fonts into override table
Now the +initialize of DTCoreTextFontDescriptor gets a list of all available fonts and registers them in the override table. This way fonts can be found even if they are not registered in the override plist, in fact the override plist can be reduced or omitted.

This fixes a problem on iOS 5 where some fonts could not be matched if their family name contained a space.

Fixes #365
bba9959
@odrobnik odrobnik closed this in bba9959 Mar 30, 2013
@odrobnik

@farfromrefug The root cause was a bug in iOS 5 where the font creation would fail for your custom font. I am not exactly certain why, maybe it had to do with there being a different space character in the name than the normal one.

Anyway my fix is to load all available fonts into the override table so that it can always create system fonts via font name.

@odrobnik odrobnik was assigned Mar 30, 2013
@farfromrefug

To me the bug on ios 5 is related to the method CTFontCreateWithFontDescriptor, may be because my font doesnt have a FontFamily.
So your fix seems good but how do i use it?
I mean will CTFontCollectionCreateFromAvailableFonts see my custom font ? (maybe it does because it is in my app plist)

@odrobnik

You don't need to do anything. If the font is registered in the app's info.plist then it is used automatically. I tested it with the font TTF you mentioned.

@farfromrefug

Superb :D
Thank you so much
Will test/merge right away

@farfromrefug

And i am really happy to report that it works great!!!

Thanks

@odrobnik

Awesome! Thanks for reporting this iOS 5 bug and helping with fixing it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment