1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-10 23:44:24 +00:00
JUCE/modules/juce_graphics/native/juce_mac_Fonts.mm

780 lines
29 KiB
Text

/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/
#if (JUCE_MAC && defined (MAC_OS_X_VERSION_10_5) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 \
&& MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_5) \
|| (JUCE_IOS && defined (__IPHONE_3_0) && __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_3_2)
#define JUCE_CORETEXT_AVAILABLE 1
#endif
#if JUCE_CORETEXT_AVAILABLE
//==============================================================================
class OSXTypeface : public Typeface
{
public:
OSXTypeface (const Font& font)
: Typeface (font.getTypefaceName()),
fontRef (nullptr),
fontHeightToCGSizeFactor (1.0f),
renderingTransform (CGAffineTransformIdentity),
ctFontRef (nullptr),
attributedStringAtts (nullptr),
ascent (0.0f),
unitsToHeightScaleFactor (0.0f)
{
CFStringRef cfName = font.getTypefaceName().toCFString();
ctFontRef = CTFontCreateWithName (cfName, 1024, nullptr);
CFRelease (cfName);
if (ctFontRef != nullptr)
{
bool needsItalicTransform = false;
if (font.isItalic())
{
CTFontRef newFont = CTFontCreateCopyWithSymbolicTraits (ctFontRef, 0.0f, nullptr,
kCTFontItalicTrait, kCTFontItalicTrait);
if (newFont != nullptr)
{
CFRelease (ctFontRef);
ctFontRef = newFont;
}
else
{
needsItalicTransform = true; // couldn't find a proper italic version, so fake it with a transform..
}
}
if (font.isBold())
{
CTFontRef newFont = CTFontCreateCopyWithSymbolicTraits (ctFontRef, 0.0f, nullptr,
kCTFontBoldTrait, kCTFontBoldTrait);
if (newFont != nullptr)
{
CFRelease (ctFontRef);
ctFontRef = newFont;
}
}
ascent = std::abs ((float) CTFontGetAscent (ctFontRef));
const float totalSize = ascent + std::abs ((float) CTFontGetDescent (ctFontRef));
ascent /= totalSize;
pathTransform = AffineTransform::identity.scale (1.0f / totalSize, 1.0f / totalSize);
if (needsItalicTransform)
{
pathTransform = pathTransform.sheared (-0.15f, 0.0f);
renderingTransform.c = 0.15f;
}
fontRef = CTFontCopyGraphicsFont (ctFontRef, nullptr);
const int totalHeight = abs (CGFontGetAscent (fontRef)) + abs (CGFontGetDescent (fontRef));
const float ctTotalHeight = abs (CTFontGetAscent (ctFontRef)) + abs (CTFontGetDescent (ctFontRef));
unitsToHeightScaleFactor = 1.0f / ctTotalHeight;
fontHeightToCGSizeFactor = CGFontGetUnitsPerEm (fontRef) / (float) totalHeight;
const short zero = 0;
CFNumberRef numberRef = CFNumberCreate (0, kCFNumberShortType, &zero);
CFStringRef keys[] = { kCTFontAttributeName, kCTLigatureAttributeName };
CFTypeRef values[] = { ctFontRef, numberRef };
attributedStringAtts = CFDictionaryCreate (nullptr, (const void**) &keys, (const void**) &values, numElementsInArray (keys),
&kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
CFRelease (numberRef);
}
}
~OSXTypeface()
{
if (attributedStringAtts != nullptr)
CFRelease (attributedStringAtts);
if (fontRef != nullptr)
CGFontRelease (fontRef);
if (ctFontRef != nullptr)
CFRelease (ctFontRef);
}
float getAscent() const { return ascent; }
float getDescent() const { return 1.0f - ascent; }
float getStringWidth (const String& text)
{
float x = 0;
if (ctFontRef != nullptr && text.isNotEmpty())
{
CFStringRef cfText = text.toCFString();
CFAttributedStringRef attribString = CFAttributedStringCreate (kCFAllocatorDefault, cfText, attributedStringAtts);
CFRelease (cfText);
CTLineRef line = CTLineCreateWithAttributedString (attribString);
CFArrayRef runArray = CTLineGetGlyphRuns (line);
for (CFIndex i = 0; i < CFArrayGetCount (runArray); ++i)
{
CTRunRef run = (CTRunRef) CFArrayGetValueAtIndex (runArray, i);
CFIndex length = CTRunGetGlyphCount (run);
HeapBlock <CGSize> advances (length);
CTRunGetAdvances (run, CFRangeMake (0, 0), advances);
for (int j = 0; j < length; ++j)
x += (float) advances[j].width;
}
CFRelease (line);
CFRelease (attribString);
x *= unitsToHeightScaleFactor;
}
return x;
}
void getGlyphPositions (const String& text, Array <int>& resultGlyphs, Array <float>& xOffsets)
{
xOffsets.add (0);
if (ctFontRef != nullptr && text.isNotEmpty())
{
float x = 0;
CFStringRef cfText = text.toCFString();
CFAttributedStringRef attribString = CFAttributedStringCreate (kCFAllocatorDefault, cfText, attributedStringAtts);
CFRelease (cfText);
CTLineRef line = CTLineCreateWithAttributedString (attribString);
CFArrayRef runArray = CTLineGetGlyphRuns (line);
for (CFIndex i = 0; i < CFArrayGetCount (runArray); ++i)
{
CTRunRef run = (CTRunRef) CFArrayGetValueAtIndex (runArray, i);
CFIndex length = CTRunGetGlyphCount (run);
HeapBlock <CGSize> advances (length);
CTRunGetAdvances (run, CFRangeMake (0, 0), advances);
HeapBlock <CGGlyph> glyphs (length);
CTRunGetGlyphs (run, CFRangeMake (0, 0), glyphs);
for (int j = 0; j < length; ++j)
{
x += (float) advances[j].width;
xOffsets.add (x * unitsToHeightScaleFactor);
resultGlyphs.add (glyphs[j]);
}
}
CFRelease (line);
CFRelease (attribString);
}
}
EdgeTable* getEdgeTableForGlyph (int glyphNumber, const AffineTransform& transform)
{
Path path;
if (getOutlineForGlyph (glyphNumber, path) && ! path.isEmpty())
return new EdgeTable (path.getBoundsTransformed (transform).getSmallestIntegerContainer().expanded (1, 0),
path, transform);
return nullptr;
}
bool getOutlineForGlyph (int glyphNumber, Path& path)
{
jassert (path.isEmpty()); // we might need to apply a transform to the path, so this must be empty
CGPathRef pathRef = CTFontCreatePathForGlyph (ctFontRef, (CGGlyph) glyphNumber, &renderingTransform);
if (pathRef == 0)
return false;
CGPathApply (pathRef, &path, pathApplier);
CFRelease (pathRef);
if (! pathTransform.isIdentity())
path.applyTransform (pathTransform);
return true;
}
//==============================================================================
CGFontRef fontRef;
float fontHeightToCGSizeFactor;
CGAffineTransform renderingTransform;
private:
CTFontRef ctFontRef;
CFDictionaryRef attributedStringAtts;
float ascent, unitsToHeightScaleFactor;
AffineTransform pathTransform;
static void pathApplier (void* info, const CGPathElement* const element)
{
Path& path = *static_cast<Path*> (info);
const CGPoint* const p = element->points;
switch (element->type)
{
case kCGPathElementMoveToPoint: path.startNewSubPath ((float) p[0].x, (float) -p[0].y); break;
case kCGPathElementAddLineToPoint: path.lineTo ((float) p[0].x, (float) -p[0].y); break;
case kCGPathElementAddQuadCurveToPoint: path.quadraticTo ((float) p[0].x, (float) -p[0].y,
(float) p[1].x, (float) -p[1].y); break;
case kCGPathElementAddCurveToPoint: path.cubicTo ((float) p[0].x, (float) -p[0].y,
(float) p[1].x, (float) -p[1].y,
(float) p[2].x, (float) -p[2].y); break;
case kCGPathElementCloseSubpath: path.closeSubPath(); break;
default: jassertfalse; break;
}
}
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OSXTypeface);
};
#else
//==============================================================================
// The stuff that follows is a mash-up that supports pre-OSX 10.5 and pre-iOS 3.2 APIs.
// (Hopefully all of this can be ditched at some point in the future).
//==============================================================================
#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
#define SUPPORT_10_4_FONTS 1
#define NEW_CGFONT_FUNCTIONS_UNAVAILABLE (CGFontCreateWithFontName == 0)
#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5
#define SUPPORT_ONLY_10_4_FONTS 1
#endif
END_JUCE_NAMESPACE
@interface NSFont (PrivateHack)
- (NSGlyph) _defaultGlyphForChar: (unichar) theChar;
@end
BEGIN_JUCE_NAMESPACE
#endif
//==============================================================================
class OSXTypeface : public Typeface
{
public:
OSXTypeface (const Font& font)
: Typeface (font.getTypefaceName())
{
JUCE_AUTORELEASEPOOL
renderingTransform = CGAffineTransformIdentity;
bool needsItalicTransform = false;
#if JUCE_IOS
NSString* fontName = juceStringToNS (font.getTypefaceName());
if (font.isItalic() || font.isBold())
{
NSArray* familyFonts = [UIFont fontNamesForFamilyName: juceStringToNS (font.getTypefaceName())];
for (NSString* i in familyFonts)
{
const String fn (nsStringToJuce (i));
const String afterDash (fn.fromFirstOccurrenceOf ("-", false, false));
const bool probablyBold = afterDash.containsIgnoreCase ("bold") || fn.endsWithIgnoreCase ("bold");
const bool probablyItalic = afterDash.containsIgnoreCase ("oblique")
|| afterDash.containsIgnoreCase ("italic")
|| fn.endsWithIgnoreCase ("oblique")
|| fn.endsWithIgnoreCase ("italic");
if (probablyBold == font.isBold()
&& probablyItalic == font.isItalic())
{
fontName = i;
needsItalicTransform = false;
break;
}
else if (probablyBold && (! probablyItalic) && probablyBold == font.isBold())
{
fontName = i;
needsItalicTransform = true; // not ideal, so carry on in case we find a better one
}
}
if (needsItalicTransform)
renderingTransform.c = 0.15f;
}
fontRef = CGFontCreateWithFontName ((CFStringRef) fontName);
if (fontRef == 0)
{
// Sometimes, UIFont manages to handle names that CGFontCreateWithFontName fails on...
UIFont* uiFont = [UIFont fontWithName: fontName size: 12];
fontRef = CGFontCreateWithFontName ((CFStringRef) uiFont.fontName);
}
const int ascender = abs (CGFontGetAscent (fontRef));
const float totalHeight = ascender + abs (CGFontGetDescent (fontRef));
ascent = ascender / totalHeight;
unitsToHeightScaleFactor = 1.0f / totalHeight;
fontHeightToCGSizeFactor = CGFontGetUnitsPerEm (fontRef) / totalHeight;
#else
nsFont = [NSFont fontWithName: juceStringToNS (font.getTypefaceName()) size: 1024];
if (font.isItalic())
{
NSFont* newFont = [[NSFontManager sharedFontManager] convertFont: nsFont
toHaveTrait: NSItalicFontMask];
if (newFont == nsFont)
needsItalicTransform = true; // couldn't find a proper italic version, so fake it with a transform..
nsFont = newFont;
}
if (font.isBold())
nsFont = [[NSFontManager sharedFontManager] convertFont: nsFont toHaveTrait: NSBoldFontMask];
[nsFont retain];
ascent = std::abs ((float) [nsFont ascender]);
float totalSize = ascent + std::abs ((float) [nsFont descender]);
ascent /= totalSize;
pathTransform = AffineTransform::identity.scale (1.0f / totalSize, 1.0f / totalSize);
if (needsItalicTransform)
{
pathTransform = pathTransform.sheared (-0.15f, 0.0f);
renderingTransform.c = 0.15f;
}
#if SUPPORT_ONLY_10_4_FONTS
ATSFontRef atsFont = ATSFontFindFromName ((CFStringRef) [nsFont fontName], kATSOptionFlagsDefault);
if (atsFont == 0)
atsFont = ATSFontFindFromPostScriptName ((CFStringRef) [nsFont fontName], kATSOptionFlagsDefault);
fontRef = CGFontCreateWithPlatformFont (&atsFont);
const float totalHeight = std::abs ([nsFont ascender]) + std::abs ([nsFont descender]);
unitsToHeightScaleFactor = 1.0f / totalHeight;
fontHeightToCGSizeFactor = 1024.0f / totalHeight;
#else
#if SUPPORT_10_4_FONTS
if (NEW_CGFONT_FUNCTIONS_UNAVAILABLE)
{
ATSFontRef atsFont = ATSFontFindFromName ((CFStringRef) [nsFont fontName], kATSOptionFlagsDefault);
if (atsFont == 0)
atsFont = ATSFontFindFromPostScriptName ((CFStringRef) [nsFont fontName], kATSOptionFlagsDefault);
fontRef = CGFontCreateWithPlatformFont (&atsFont);
const float totalHeight = std::abs ([nsFont ascender]) + std::abs ([nsFont descender]);
unitsToHeightScaleFactor = 1.0f / totalHeight;
fontHeightToCGSizeFactor = 1024.0f / totalHeight;
}
else
#endif
{
fontRef = CGFontCreateWithFontName ((CFStringRef) [nsFont fontName]);
const int totalHeight = abs (CGFontGetAscent (fontRef)) + abs (CGFontGetDescent (fontRef));
unitsToHeightScaleFactor = 1.0f / totalHeight;
fontHeightToCGSizeFactor = CGFontGetUnitsPerEm (fontRef) / (float) totalHeight;
}
#endif
#endif
}
~OSXTypeface()
{
#if ! JUCE_IOS
[nsFont release];
#endif
if (fontRef != 0)
CGFontRelease (fontRef);
}
float getAscent() const { return ascent; }
float getDescent() const { return 1.0f - ascent; }
float getStringWidth (const String& text)
{
if (fontRef == 0 || text.isEmpty())
return 0;
const int length = text.length();
HeapBlock <CGGlyph> glyphs;
createGlyphsForString (text.getCharPointer(), length, glyphs);
float x = 0;
#if SUPPORT_ONLY_10_4_FONTS
HeapBlock <NSSize> advances (length);
[nsFont getAdvancements: advances forGlyphs: reinterpret_cast <NSGlyph*> (glyphs.getData()) count: length];
for (int i = 0; i < length; ++i)
x += advances[i].width;
#else
#if SUPPORT_10_4_FONTS
if (NEW_CGFONT_FUNCTIONS_UNAVAILABLE)
{
HeapBlock <NSSize> advances (length);
[nsFont getAdvancements: advances forGlyphs: reinterpret_cast<NSGlyph*> (glyphs.getData()) count: length];
for (int i = 0; i < length; ++i)
x += advances[i].width;
}
else
#endif
{
HeapBlock <int> advances (length);
if (CGFontGetGlyphAdvances (fontRef, glyphs, length, advances))
for (int i = 0; i < length; ++i)
x += advances[i];
}
#endif
return x * unitsToHeightScaleFactor;
}
void getGlyphPositions (const String& text, Array <int>& resultGlyphs, Array <float>& xOffsets)
{
xOffsets.add (0);
if (fontRef == 0 || text.isEmpty())
return;
const int length = text.length();
HeapBlock <CGGlyph> glyphs;
createGlyphsForString (text.getCharPointer(), length, glyphs);
#if SUPPORT_ONLY_10_4_FONTS
HeapBlock <NSSize> advances (length);
[nsFont getAdvancements: advances forGlyphs: reinterpret_cast <NSGlyph*> (glyphs.getData()) count: length];
int x = 0;
for (int i = 0; i < length; ++i)
{
x += advances[i].width;
xOffsets.add (x * unitsToHeightScaleFactor);
resultGlyphs.add (reinterpret_cast <NSGlyph*> (glyphs.getData())[i]);
}
#else
#if SUPPORT_10_4_FONTS
if (NEW_CGFONT_FUNCTIONS_UNAVAILABLE)
{
HeapBlock <NSSize> advances (length);
NSGlyph* const nsGlyphs = reinterpret_cast<NSGlyph*> (glyphs.getData());
[nsFont getAdvancements: advances forGlyphs: nsGlyphs count: length];
float x = 0;
for (int i = 0; i < length; ++i)
{
x += advances[i].width;
xOffsets.add (x * unitsToHeightScaleFactor);
resultGlyphs.add (nsGlyphs[i]);
}
}
else
#endif
{
HeapBlock <int> advances (length);
if (CGFontGetGlyphAdvances (fontRef, glyphs, length, advances))
{
int x = 0;
for (int i = 0; i < length; ++i)
{
x += advances [i];
xOffsets.add (x * unitsToHeightScaleFactor);
resultGlyphs.add (glyphs[i]);
}
}
}
#endif
}
EdgeTable* getEdgeTableForGlyph (int glyphNumber, const AffineTransform& transform)
{
Path path;
if (getOutlineForGlyph (glyphNumber, path) && ! path.isEmpty())
return new EdgeTable (path.getBoundsTransformed (transform).getSmallestIntegerContainer().expanded (1, 0),
path, transform);
return nullptr;
}
bool getOutlineForGlyph (int glyphNumber, Path& path)
{
#if JUCE_IOS
return false;
#else
if (nsFont == nil)
return false;
// we might need to apply a transform to the path, so it mustn't have anything else in it
jassert (path.isEmpty());
JUCE_AUTORELEASEPOOL
NSBezierPath* bez = [NSBezierPath bezierPath];
[bez moveToPoint: NSMakePoint (0, 0)];
[bez appendBezierPathWithGlyph: (NSGlyph) glyphNumber
inFont: nsFont];
for (int i = 0; i < [bez elementCount]; ++i)
{
NSPoint p[3];
switch ([bez elementAtIndex: i associatedPoints: p])
{
case NSMoveToBezierPathElement: path.startNewSubPath ((float) p[0].x, (float) -p[0].y); break;
case NSLineToBezierPathElement: path.lineTo ((float) p[0].x, (float) -p[0].y); break;
case NSCurveToBezierPathElement: path.cubicTo ((float) p[0].x, (float) -p[0].y,
(float) p[1].x, (float) -p[1].y,
(float) p[2].x, (float) -p[2].y); break;
case NSClosePathBezierPathElement: path.closeSubPath(); break;
default: jassertfalse; break;
}
}
path.applyTransform (pathTransform);
return true;
#endif
}
//==============================================================================
CGFontRef fontRef;
float fontHeightToCGSizeFactor;
CGAffineTransform renderingTransform;
private:
float ascent, unitsToHeightScaleFactor;
#if ! JUCE_IOS
NSFont* nsFont;
AffineTransform pathTransform;
#endif
void createGlyphsForString (String::CharPointerType text, const int length, HeapBlock <CGGlyph>& glyphs)
{
#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 < length; ++i)
nsGlyphs[i] = (NSGlyph) [nsFont _defaultGlyphForChar: text.getAndAdvance()];
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
}
#if ! SUPPORT_ONLY_10_4_FONTS
// Reads a CGFontRef's character map table to convert unicode into glyph numbers
class CharToGlyphMapper
{
public:
CharToGlyphMapper (CGFontRef fontRef)
: segCount (0), endCode (0), startCode (0), idDelta (0),
idRangeOffset (0), glyphIndexes (0)
{
CFDataRef cmapTable = CGFontCopyTableForTag (fontRef, 'cmap');
if (cmapTable != 0)
{
const int numSubtables = getValue16 (cmapTable, 2);
for (int i = 0; i < numSubtables; ++i)
{
if (getValue16 (cmapTable, i * 8 + 4) == 0) // check for platform ID of 0
{
const int offset = getValue32 (cmapTable, i * 8 + 8);
if (getValue16 (cmapTable, offset) == 4) // check that it's format 4..
{
const int length = getValue16 (cmapTable, offset + 2);
const int segCountX2 = getValue16 (cmapTable, offset + 6);
segCount = segCountX2 / 2;
const int endCodeOffset = offset + 14;
const int startCodeOffset = endCodeOffset + 2 + segCountX2;
const int idDeltaOffset = startCodeOffset + segCountX2;
const int idRangeOffsetOffset = idDeltaOffset + segCountX2;
const int glyphIndexesOffset = idRangeOffsetOffset + segCountX2;
endCode = CFDataCreate (kCFAllocatorDefault, CFDataGetBytePtr (cmapTable) + endCodeOffset, segCountX2);
startCode = CFDataCreate (kCFAllocatorDefault, CFDataGetBytePtr (cmapTable) + startCodeOffset, segCountX2);
idDelta = CFDataCreate (kCFAllocatorDefault, CFDataGetBytePtr (cmapTable) + idDeltaOffset, segCountX2);
idRangeOffset = CFDataCreate (kCFAllocatorDefault, CFDataGetBytePtr (cmapTable) + idRangeOffsetOffset, segCountX2);
glyphIndexes = CFDataCreate (kCFAllocatorDefault, CFDataGetBytePtr (cmapTable) + glyphIndexesOffset, offset + length - glyphIndexesOffset);
}
break;
}
}
CFRelease (cmapTable);
}
}
~CharToGlyphMapper()
{
if (endCode != 0)
{
CFRelease (endCode);
CFRelease (startCode);
CFRelease (idDelta);
CFRelease (idRangeOffset);
CFRelease (glyphIndexes);
}
}
int getGlyphForCharacter (const juce_wchar c) const
{
for (int i = 0; i < segCount; ++i)
{
if (getValue16 (endCode, i * 2) >= c)
{
const int start = getValue16 (startCode, i * 2);
if (start > c)
break;
const int delta = getValue16 (idDelta, i * 2);
const int rangeOffset = getValue16 (idRangeOffset, i * 2);
if (rangeOffset == 0)
return delta + c;
else
return getValue16 (glyphIndexes, 2 * ((rangeOffset / 2) + (c - start) - (segCount - i)));
}
}
// If we failed to find it "properly", this dodgy fall-back seems to do the trick for most fonts!
return jmax (-1, (int) c - 29);
}
private:
int segCount;
CFDataRef endCode, startCode, idDelta, idRangeOffset, glyphIndexes;
static uint16 getValue16 (CFDataRef data, const int index)
{
return CFSwapInt16BigToHost (*(UInt16*) (CFDataGetBytePtr (data) + index));
}
static uint32 getValue32 (CFDataRef data, const int index)
{
return CFSwapInt32BigToHost (*(UInt32*) (CFDataGetBytePtr (data) + index));
}
};
ScopedPointer <CharToGlyphMapper> charToGlyphMapper;
#endif
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OSXTypeface);
};
#endif
//==============================================================================
Typeface::Ptr Typeface::createSystemTypefaceFor (const Font& font)
{
return new OSXTypeface (font);
}
StringArray Font::findAllTypefaceNames()
{
StringArray names;
JUCE_AUTORELEASEPOOL
#if JUCE_IOS
NSArray* fonts = [UIFont familyNames];
#else
NSArray* fonts = [[NSFontManager sharedFontManager] availableFontFamilies];
#endif
for (unsigned int i = 0; i < [fonts count]; ++i)
names.add (nsStringToJuce ((NSString*) [fonts objectAtIndex: i]));
names.sort (true);
return names;
}
struct DefaultFontNames
{
DefaultFontNames()
#if JUCE_IOS
: defaultSans ("Helvetica"),
defaultSerif ("Times New Roman"),
defaultFixed ("Courier New"),
#else
: defaultSans ("Lucida Grande"),
defaultSerif ("Times New Roman"),
defaultFixed ("Monaco"),
#endif
defaultFallback ("Arial Unicode MS")
{
}
String defaultSans, defaultSerif, defaultFixed, defaultFallback;
};
Typeface::Ptr Font::getDefaultTypefaceForFont (const Font& font)
{
static DefaultFontNames defaultNames;
String faceName (font.getTypefaceName());
if (faceName == Font::getDefaultSansSerifFontName()) faceName = defaultNames.defaultSans;
else if (faceName == Font::getDefaultSerifFontName()) faceName = defaultNames.defaultSerif;
else if (faceName == Font::getDefaultMonospacedFontName()) faceName = defaultNames.defaultFixed;
Font f (font);
f.setTypefaceName (faceName);
return Typeface::createSystemTypefaceFor (f);
}