Font woes again (chinese)


#1

On Windows 10, and I want to be able to show mixed languages, english + chinese f.i. I’ve tried setting a font fallback (“Microsoft YaHei”) but I cannot get it to work, I only get those little “boxes”…

Anyone ?


#2

Can you post some code which reproduces the problem?


#3

This will reproduce it:

g.drawText (L"Hello \u4E16\u754C!", getLocalBounds(), Justification::centred, true);

From a Hello World appl generated by Introjucer.

If I set:

LookAndFeel::getDefaultLookAndFeel().setDefaultSansSerifTypefaceName("Microsoft YaHei UI");

at startup, the correct characters are shown, so obviously I’d need to set a fallback typeface for the chinese characters (because I want to use “Arial” as default sans-serif typeface), and this I don’t know/recall how to.


#4

The best way to deal with foreign text and regular one is to use https://www.juce.com/doc/classTextLayout instead of drawText


#5

This won’t work, as the user can f.i. save a project name with arbitrary characters (or a file name), and I won’t know which font which character belongs to. I only have unicode to go on.

I.e. the example above was just to show how it looks :slight_smile:


#6

TextLayout is actually the only way to deal with this as the fallback font selection is done automatically.

Please check how it works.


#7

I know how it works, and it won’t do. Example: User saves a file with name having chinese characters, and then you want to show the filename in a Label. How will TextLayout help me here? The only way to set specific fonts is with TL is to explicitly add text with a special font. I need to have a custom typeface that handles lookup of unicode chars with fallback typface(s).


#8

use a custom LnF where drawLabel use TextLayout as its implementation.

  void drawLabel(juce::Graphics &g, juce::Label &label)
  {
    g.fillAll (label.findColour (Label::backgroundColourId));
    
    if (! label.isBeingEdited())
    {
      const float alpha = label.isEnabled() ? 1.0f : 0.5f;
      const juce::Font font (getLabelFont (label));
      
      g.setColour (label.findColour (Label::textColourId).withMultipliedAlpha (alpha));
      g.setFont (font);
      
      juce::Rectangle<int> textArea (label.getBorderSize().subtractedFrom (label.getLocalBounds()));
      
      juce::TextLayout textLayout;
      juce::AttributedString str(label.getText());
      str.setJustification(label.getJustificationType());
      str.setColour(label.findColour(juce::Label::textColourId).withMultipliedAlpha(alpha));
      str.setFont(font);
      textLayout.createLayout(str, label.getWidth());
      
      textLayout.draw(g, textArea.toFloat());
      
      g.setColour (label.findColour (Label::outlineColourId).withMultipliedAlpha (alpha));
    }
    else if (label.isEnabled())
    {
      g.setColour (label.findColour (Label::outlineColourId));
    }
    
    g.drawRect (label.getLocalBounds());
  }

#9

Thanks, will try it!


#10

Ok, this seems to work. Thanks otristan!


#11

Still if it will fail if you use a custom Juce font by default which I’m trying to get Jules fixed since a while…
@jules Bump :slight_smile:


#12

Yeah I can’t really reproduce this when using a suitably large unicode font such as ‘Arial Unicode MS’.

I feel like I have seen this discussion on the forum a while back and you’ll probably give me a really good reason why using a better font with more unicode points is a bad idea. :slight_smile:


#13

Probably because on OSX there is no Arial Unicode MS or any suitably large unicode font.
Please correct me if I am wrong.


#14

I was under the impression that macOS also licenses this font. At least it’s on my machine:


#15

Didn’t know that. Thanks for letting me know.
Still, it would be great to have custom font that fallback right when there is not the right glyph in it :slight_smile:


#16

“Arial Unicode MS” is not installed by default on Windows 10 Pro either.


#17

That’s correct: it’s a font that comes packaged with Microsoft Word (or the Office suite).


#18

That’s ironic: There’s a font called “Arial Unicode MS” it’s not installed on Microsoft systems by default but is installed on Apple systems by default. Is there any other font like “Arial Unicode MS” which is for free?


#19

There are some free options:


#20

@otristan if you want to get custom memory font working with fallback on macOS I had something working today.

First add your drawLabel change above.
Then rather than using JUCE in-memory fonts register them to the system. Something like the following.

CFDataRef cfData = CFDataCreate (kCFAllocatorDefault, (const UInt8*) data, (CFIndex) dataSize);
CGDataProviderRef provider = CGDataProviderCreateWithCFData (cfData);
CTFontDescriptorRef descRef = CTFontManagerCreateFontDescriptorFromData(cfData);
CFRelease (cfData);

fontRef = CGFontCreateWithDataProvider (provider);
CGDataProviderRelease (provider);

if (fontRef != nullptr)
{
    bool success = CTFontManagerRegisterGraphicsFont(fontRef, nullptr);

    if (success)
    {
        ctFontRef = CTFontCreateWithFontDescriptor(descRef, referenceFontSize, nullptr);

        if (ctFontRef != nullptr)
        {
            if (CFStringRef fontName = CTFontCopyName (ctFontRef, kCTFontFamilyNameKey))
            {
                name = String::fromCFString (fontName);
                CFRelease (fontName);
            }

            if (CFStringRef fontStyle = CTFontCopyName (ctFontRef, kCTFontStyleNameKey))
            {
                style = String::fromCFString (fontStyle);
                CFRelease (fontStyle);
            }

            initialiseMetrics();
        }
    }
}

After RegisterGraphicsFont my custom font appears in the “Font::findAllTypefaceNames()” list. @fabian do you think this kind of ‘registerInMemoryFont’ API could be something that could deprecate the old API and work on all platforms?