setFallbackFontName broken?

Discussion and support for general JUCE issues

Re: setFallbackFontName broken?

Postby justin » Mon Oct 10, 2011 5:13 pm

Good point. Well, it may be too slow, but if a glyph isn't found(via CTFontGetGlyphsForCharacters) how about calling CTFontCreateForString with just that UniChar?

Pain in the butt though...
User avatar
justin
JUCE UberWeenie
 
Posts: 297
Joined: Mon May 19, 2008 1:37 pm
Location: Canada

Re: setFallbackFontName broken?

Postby jules » Mon Oct 10, 2011 5:20 pm

The real problem on OSX is that there's no way I've found to actually find out whether a glyph exists in the font or not. Any missing ones are just replaced with default glyphs, but it doesn't tell you that it's done so.
User avatar
jules
Fearless Leader
 
Posts: 17209
Joined: Mon Sep 06, 2004 9:03 am
Location: London, UK

Re: setFallbackFontName broken?

Postby justin » Mon Oct 10, 2011 5:58 pm

CTFontGetGlyphsForCharacters returns true if the font could encode all the characters.
If a glyph could not be encoded, a value of 0 is passed back at the corresponding index in the glyphs array and the function returns False.


Let me see if I can hack something together to send you, lord knows you have enough on your plate!
User avatar
justin
JUCE UberWeenie
 
Posts: 297
Joined: Mon May 19, 2008 1:37 pm
Location: Canada

Re: setFallbackFontName broken?

Postby jules » Mon Oct 10, 2011 6:34 pm

Ah, I didn't see that one. I think CoreText is only available on 10.5 and above, but better than nothing!
User avatar
jules
Fearless Leader
 
Posts: 17209
Joined: Mon Sep 06, 2004 9:03 am
Location: London, UK

Re: setFallbackFontName broken?

Postby justin » Tue Oct 11, 2011 6:24 pm

I hacked on this, first for a 10.4 version, and while I got the glyph substitution working. (Instead of [nsFont _defaultGlyphForChar: text.getAndAdvance()] I made a slew of cocoa classes NSTextStorage, NSTextContainer, and a NSLayoutManager, stuffed the attributed string in there and used NSLayoutManager's glyphAtIndex:i].

This worked, and if I iterated over the attributes of the layoutmanager, I could see font substitution worked (in my case I used the Katakana string プールの and the layout went from using Helvetica to HiraKakuProN-W3 for those characters.)

The problem though is that the Mac drawGlyph in CoregraphicsContext sets the context's font and draws the glyph(even though that glyph doesn't exist in the font.) In my case I've gone from the missing square boxes for the characters to some incoherent glyphs!

There seems to be ways for the glyph array to be manipulated outside the typeface class(ellipses for instance), so keeping the NSLayoutManager in sync with the string to draw would need to happen somewhere, then drawGlyph could call into the typeface and get the font for the character at index n.

Anyway, i think i'll just continue setting to a unicode font for now!
User avatar
justin
JUCE UberWeenie
 
Posts: 297
Joined: Mon May 19, 2008 1:37 pm
Location: Canada

Re: setFallbackFontName broken?

Postby justin » Tue Oct 11, 2011 6:30 pm

HACK CODE BELOW!

(juce_mac_fonts.mm)


Code: Select all
A little wrapper around obj-c
template <typename T>
class  JuceOBJCType
{
public:
    inline JuceOBJCType(const T* t = nil) : objCtype(t) {}
    inline JuceOBJCType(const JuceOBJCType &helper) : objCtype(helper.objCtype) { if (objCtype) [objCtype retain]; }
    inline ~JuceOBJCType() { if (objCtype) [objCtype release]; }
   
    inline  operator T*() { return objCtype; }
   inline T * get(){
      return objCtype;
   }
    inline JuceOBJCType operator =(const JuceOBJCType &helper)
    {
      if (objCtype !=helper.objCtype)
      {   
         [helper.objCtype retain];
         [objCtype release];
         objCtype=helper.objCtype;
         
      }
      return *this;
    }
    inline T *operator&() { return &objCtype; }
protected:
    T * objCtype;
};

Code: Select all

    void createGlyphsForString (String::CharPointerType text, const int length, HeapBlock <CGGlyph>& glyphs)
    {
      //http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/TextLayout/Tasks/DrawingStrings.html
      
      textStorage=[[NSTextStorage alloc] init];
      layoutManager=[[NSLayoutManager alloc] init];

      
      [textStorage.get() addLayoutManager:layoutManager];
      textContainer=[[NSTextContainer alloc] init];
      [layoutManager.get() addTextContainer:textContainer];
      [[textStorage.get() mutableString] setString:juceStringToNS(String(text,length))];
      
      #if SUPPORT_10_4_FONTS
       #if ! SUPPORT_ONLY_10_4_FONTS
        if (NEW_CGFONT_FUNCTIONS_UNAVAILABLE)
       #endif
        {
            glyphs.malloc (sizeof (NSGlyph) * length, 1);
            NSGlyph* const nsGlyphs = reinterpret_cast<NSGlyph*> (glyphs.getData());

            for (int i = 0; i < [layoutManager.get() numberOfGlyphs]; ++i)
         {   nsGlyphs[i] = [layoutManager.get() glyphAtIndex:i];//(NSGlyph) [nsFont _defaultGlyphForChar: text.getAndAdvance()];
            
            
            jassert(textStorage !=nil);
            NSRange aRange=NSMakeRange(1,1); // Let's see what font is at the index now...
            NSLog([[textStorage.get() attribute:NSFontAttributeName
                                            atIndex:1 effectiveRange:&aRange]fontName]);
         }

            return;
        }
      #endif

       #if ! SUPPORT_ONLY_10_4_FONTS
        if (charToGlyphMapper == nullptr)
            charToGlyphMapper = new CharToGlyphMapper (fontRef);

        glyphs.malloc (length);

        for (int i = 0; i < length; ++i)
            glyphs[i] = (CGGlyph) charToGlyphMapper->getGlyphForCharacter (text.getAndAdvance());
       #endif
    }



Stuffed in the MacTypeFace class
Code: Select all
//==============================================================================
    CGFontRef fontRef;
    float fontHeightToCGSizeFactor;
    CGAffineTransform renderingTransform;
   JuceOBJCType<NSTextStorage> textStorage;
   JuceOBJCType<NSLayoutManager> layoutManager;
   JuceOBJCType<NSTextContainer> textContainer;
User avatar
justin
JUCE UberWeenie
 
Posts: 297
Joined: Mon May 19, 2008 1:37 pm
Location: Canada

Re: setFallbackFontName broken?

Postby gekkie100 » Wed Oct 12, 2011 8:22 am

That only returns one font. What we'd need to handle is a string where some of the characters end up using a fallback font, and other don'

Is that really what needs to be done? In our case we would like 'Lucida Grande' to render the text, but if one of the glyphs isn't present it can use 'Arial Unicode MS' as fallback. Can't we just render in the fallback if one of the glyphs is not present?
gekkie100
JUCE UberWeenie
 
Posts: 249
Joined: Tue Apr 12, 2005 2:35 pm

Re: setFallbackFontName broken?

Postby jules » Wed Oct 12, 2011 9:55 am

Thanks Justin! The main worry about your approach is that it'll be vastly slower than the old code.
(Interesting that you wrote an obj-c wrapper - I've considered writing one of those many times, but never quite got around to it.)

Gekkie: well, I suppose it could just give up on the entire string and use the fallback font, but even then it'd need to be able to pass that information along to the graphics context, so it wouldn't be a free ride.
User avatar
jules
Fearless Leader
 
Posts: 17209
Joined: Mon Sep 06, 2004 9:03 am
Location: London, UK

Re: setFallbackFontName broken?

Postby gekkie100 » Wed Oct 12, 2011 10:08 am

Justin, could you explain me how you create a font (code snippet) with a cascade list using CTFontCreateForString. I dug around the apple developer site and they say you can create a cascade list but i couldn't find exactly how to do this.
gekkie100
JUCE UberWeenie
 
Posts: 249
Joined: Tue Apr 12, 2005 2:35 pm

Re: setFallbackFontName broken?

Postby justin » Wed Oct 12, 2011 7:26 pm

It should all be in
http://developer.apple.com/library/mac/#documentation/Carbon/Reference/CTFontDescriptorRef/Reference/reference.html

Specifically kCTFontCascadeListAttribute

This is all untested, but you should be able to get the global cascade list by calling

CTFontDescriptorCreateWithNameAndSize to get a CTFontDescriptorRef and then CTFontDescriptorCopyAttributes. The kCTFontCascadeListAttribute key will then give you an array.
User avatar
justin
JUCE UberWeenie
 
Posts: 297
Joined: Mon May 19, 2008 1:37 pm
Location: Canada

Re: setFallbackFontName broken?

Postby justin » Wed Oct 12, 2011 7:32 pm

I should stress though that this won't help you because of the coregraphics stuff I mentioned earlier.

If you only had a few items to display and you didn't know the string contents ahead of time, I suppose you could check if it is displayable with the current font by calling CTFontGetGlyphsForCharacters and manually setting the font for the component to a unicode font if it fails?
User avatar
justin
JUCE UberWeenie
 
Posts: 297
Joined: Mon May 19, 2008 1:37 pm
Location: Canada

Re: setFallbackFontName broken?

Postby justin » Wed Oct 12, 2011 7:37 pm

Jules wrote
Thanks Justin! The main worry about your approach is that it'll be vastly slower than the old code.
(Interesting that you wrote an obj-c wrapper - I've considered writing one of those many times, but never quite got around to it.)


All your posts stressing RAII finally sunk in I guess...
Its too bad the operator () overload doesn't work though!

[textStorage.get() addLayoutManager:layoutManager];
vs the treacherous waters of...
[(NSTextStorage*) textStorage addLayoutManager:layoutManager];
User avatar
justin
JUCE UberWeenie
 
Posts: 297
Joined: Mon May 19, 2008 1:37 pm
Location: Canada

Re: setFallbackFontName broken?

Postby jules » Thu Oct 13, 2011 2:41 pm

Ah yes.. Maybe that was the reason I didn't write one, I think I might actually have started doing one, but then realised it was going to be troublesome and decided not to complicate things.
User avatar
jules
Fearless Leader
 
Posts: 17209
Joined: Mon Sep 06, 2004 9:03 am
Location: London, UK

Re: setFallbackFontName broken?

Postby sonic59 » Mon Oct 17, 2011 4:09 am

While working on the Mac software renderer for the next gen JUCE text system I noticed some messed up fonts. Sure enough this thread explained it.

This confirms what I suspected in my other post, it would seem my CoreText-CoreGraphics renderer is doing auto font fallback on its own. You can see it in action in the following links:

Arabic - http://i.minus.com/iMzFcLlsN6qvQ.png
Thai - http://i.minus.com/ikqqzV7dDYFex.png
Hindi - http://i.minus.com/iYW8NX8YqVqMq.png

The non English glyphs are definitely not in Lucia Grande, so font fall back is automatically kicking in.

With the hints that justin gave, I hope that I can get font fallback working on my CoreText-Software renderer. I should be able to save some time by checking only one glyph per run since the font family in each run should be the same.

DirectWrite (what I'll be using on Windows) is supposed to have some sort of font fallback as well but I won't know for sure until I get my feet wet.

So once I finish the system and then Jules integrates/rewrites it, you should have your font fallback.
sonic59
JUCE UberWeenie
 
Posts: 224
Joined: Tue Mar 09, 2010 5:51 pm

Re: setFallbackFontName broken?

Postby gekkie100 » Tue Nov 22, 2011 3:24 pm

Jules did you find some more time to work on this. We are nearing a release and would really love to have the fallback back.
gekkie100
JUCE UberWeenie
 
Posts: 249
Joined: Tue Apr 12, 2005 2:35 pm

PreviousNext

Return to General JUCE discussion

Who is online

Users browsing this forum: Daven, Google [Bot] and 4 guests