2 ==============================================================================
\r
4 This file is part of the JUCE library - "Jules' Utility Class Extensions"
\r
5 Copyright 2004-11 by Raw Material Software Ltd.
\r
7 ------------------------------------------------------------------------------
\r
9 JUCE can be redistributed and/or modified under the terms of the GNU General
\r
10 Public License (Version 2), as published by the Free Software Foundation.
\r
11 A copy of the license is included in the JUCE distribution, or can be found
\r
12 online at www.gnu.org/licenses.
\r
14 JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
\r
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
\r
16 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
\r
18 ------------------------------------------------------------------------------
\r
20 To release a closed-source product which uses JUCE, commercial licenses are
\r
21 available: visit www.rawmaterialsoftware.com/juce for more information.
\r
23 ==============================================================================
\r
26 // (This file gets included by juce_mac_NativeCode.mm, rather than being
\r
27 // compiled on its own).
\r
28 #if JUCE_INCLUDED_FILE
\r
30 #if (JUCE_MAC && defined (MAC_OS_X_VERSION_10_5) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 \
\r
31 && MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_5) \
\r
32 || (JUCE_IOS && defined (__IPHONE_3_0) && __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_3_2)
\r
33 #define JUCE_CORETEXT_AVAILABLE 1
\r
36 #if JUCE_CORETEXT_AVAILABLE
\r
38 //==============================================================================
\r
39 class MacTypeface : public Typeface
\r
42 //==============================================================================
\r
43 MacTypeface (const Font& font)
\r
44 : Typeface (font.getTypefaceName()),
\r
46 fontHeightToCGSizeFactor (1.0f),
\r
47 renderingTransform (CGAffineTransformIdentity),
\r
48 ctFontRef (nullptr),
\r
49 attributedStringAtts (nullptr),
\r
51 unitsToHeightScaleFactor (0.0f)
\r
53 JUCE_AUTORELEASEPOOL
\r
54 CFStringRef cfName = PlatformUtilities::juceStringToCFString (font.getTypefaceName());
\r
55 ctFontRef = CTFontCreateWithName (cfName, 1024, nullptr);
\r
58 if (ctFontRef != nullptr)
\r
60 bool needsItalicTransform = false;
\r
62 if (font.isItalic())
\r
64 CTFontRef newFont = CTFontCreateCopyWithSymbolicTraits (ctFontRef, 0.0f, nullptr,
\r
65 kCTFontItalicTrait, kCTFontItalicTrait);
\r
67 if (newFont != nullptr)
\r
69 CFRelease (ctFontRef);
\r
70 ctFontRef = newFont;
\r
74 needsItalicTransform = true; // couldn't find a proper italic version, so fake it with a transform..
\r
80 CTFontRef newFont = CTFontCreateCopyWithSymbolicTraits (ctFontRef, 0.0f, nullptr,
\r
81 kCTFontBoldTrait, kCTFontBoldTrait);
\r
82 if (newFont != nullptr)
\r
84 CFRelease (ctFontRef);
\r
85 ctFontRef = newFont;
\r
89 ascent = std::abs ((float) CTFontGetAscent (ctFontRef));
\r
90 const float totalSize = ascent + std::abs ((float) CTFontGetDescent (ctFontRef));
\r
91 ascent /= totalSize;
\r
93 pathTransform = AffineTransform::identity.scale (1.0f / totalSize, 1.0f / totalSize);
\r
95 if (needsItalicTransform)
\r
97 pathTransform = pathTransform.sheared (-0.15f, 0.0f);
\r
98 renderingTransform.c = 0.15f;
\r
101 fontRef = CTFontCopyGraphicsFont (ctFontRef, nullptr);
\r
103 const int totalHeight = abs (CGFontGetAscent (fontRef)) + abs (CGFontGetDescent (fontRef));
\r
104 const float ctTotalHeight = abs (CTFontGetAscent (ctFontRef)) + abs (CTFontGetDescent (ctFontRef));
\r
105 unitsToHeightScaleFactor = 1.0f / ctTotalHeight;
\r
106 fontHeightToCGSizeFactor = CGFontGetUnitsPerEm (fontRef) / (float) totalHeight;
\r
108 const short zero = 0;
\r
109 CFNumberRef numberRef = CFNumberCreate (0, kCFNumberShortType, &zero);
\r
111 CFStringRef keys[] = { kCTFontAttributeName, kCTLigatureAttributeName };
\r
112 CFTypeRef values[] = { ctFontRef, numberRef };
\r
113 attributedStringAtts = CFDictionaryCreate (nullptr, (const void**) &keys, (const void**) &values, numElementsInArray (keys),
\r
114 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
\r
115 CFRelease (numberRef);
\r
121 if (attributedStringAtts != nullptr)
\r
122 CFRelease (attributedStringAtts);
\r
124 if (fontRef != nullptr)
\r
125 CGFontRelease (fontRef);
\r
127 if (ctFontRef != nullptr)
\r
128 CFRelease (ctFontRef);
\r
131 float getAscent() const { return ascent; }
\r
132 float getDescent() const { return 1.0f - ascent; }
\r
134 float getStringWidth (const String& text)
\r
138 if (ctFontRef != nullptr && text.isNotEmpty())
\r
140 CFStringRef cfText = PlatformUtilities::juceStringToCFString (text);
\r
141 CFAttributedStringRef attribString = CFAttributedStringCreate (kCFAllocatorDefault, cfText, attributedStringAtts);
\r
142 CFRelease (cfText);
\r
144 CTLineRef line = CTLineCreateWithAttributedString (attribString);
\r
145 CFArrayRef runArray = CTLineGetGlyphRuns (line);
\r
147 for (CFIndex i = 0; i < CFArrayGetCount (runArray); ++i)
\r
149 CTRunRef run = (CTRunRef) CFArrayGetValueAtIndex (runArray, i);
\r
150 CFIndex length = CTRunGetGlyphCount (run);
\r
151 HeapBlock <CGSize> advances (length);
\r
152 CTRunGetAdvances (run, CFRangeMake (0, 0), advances);
\r
154 for (int j = 0; j < length; ++j)
\r
155 x += (float) advances[j].width;
\r
159 CFRelease (attribString);
\r
161 x *= unitsToHeightScaleFactor;
\r
167 void getGlyphPositions (const String& text, Array <int>& resultGlyphs, Array <float>& xOffsets)
\r
171 if (ctFontRef != nullptr && text.isNotEmpty())
\r
175 CFStringRef cfText = PlatformUtilities::juceStringToCFString (text);
\r
176 CFAttributedStringRef attribString = CFAttributedStringCreate (kCFAllocatorDefault, cfText, attributedStringAtts);
\r
177 CFRelease (cfText);
\r
179 CTLineRef line = CTLineCreateWithAttributedString (attribString);
\r
180 CFArrayRef runArray = CTLineGetGlyphRuns (line);
\r
182 for (CFIndex i = 0; i < CFArrayGetCount (runArray); ++i)
\r
184 CTRunRef run = (CTRunRef) CFArrayGetValueAtIndex (runArray, i);
\r
185 CFIndex length = CTRunGetGlyphCount (run);
\r
186 HeapBlock <CGSize> advances (length);
\r
187 CTRunGetAdvances (run, CFRangeMake (0, 0), advances);
\r
188 HeapBlock <CGGlyph> glyphs (length);
\r
189 CTRunGetGlyphs (run, CFRangeMake (0, 0), glyphs);
\r
191 for (int j = 0; j < length; ++j)
\r
193 x += (float) advances[j].width;
\r
194 xOffsets.add (x * unitsToHeightScaleFactor);
\r
195 resultGlyphs.add (glyphs[j]);
\r
200 CFRelease (attribString);
\r
204 EdgeTable* getEdgeTableForGlyph (int glyphNumber, const AffineTransform& transform)
\r
208 if (getOutlineForGlyph (glyphNumber, path) && ! path.isEmpty())
\r
209 return new EdgeTable (path.getBoundsTransformed (transform).getSmallestIntegerContainer().expanded (1, 0),
\r
215 bool getOutlineForGlyph (int glyphNumber, Path& path)
\r
217 jassert (path.isEmpty()); // we might need to apply a transform to the path, so this must be empty
\r
219 CGPathRef pathRef = CTFontCreatePathForGlyph (ctFontRef, (CGGlyph) glyphNumber, &renderingTransform);
\r
223 CGPathApply (pathRef, &path, pathApplier);
\r
224 CFRelease (pathRef);
\r
226 if (! pathTransform.isIdentity())
\r
227 path.applyTransform (pathTransform);
\r
232 //==============================================================================
\r
235 float fontHeightToCGSizeFactor;
\r
236 CGAffineTransform renderingTransform;
\r
239 CTFontRef ctFontRef;
\r
240 CFDictionaryRef attributedStringAtts;
\r
241 float ascent, unitsToHeightScaleFactor;
\r
242 AffineTransform pathTransform;
\r
244 static void pathApplier (void* info, const CGPathElement* const element)
\r
246 Path& path = *static_cast<Path*> (info);
\r
247 const CGPoint* const p = element->points;
\r
249 switch (element->type)
\r
251 case kCGPathElementMoveToPoint: path.startNewSubPath ((float) p[0].x, (float) -p[0].y); break;
\r
252 case kCGPathElementAddLineToPoint: path.lineTo ((float) p[0].x, (float) -p[0].y); break;
\r
253 case kCGPathElementAddQuadCurveToPoint: path.quadraticTo ((float) p[0].x, (float) -p[0].y,
\r
254 (float) p[1].x, (float) -p[1].y); break;
\r
255 case kCGPathElementAddCurveToPoint: path.cubicTo ((float) p[0].x, (float) -p[0].y,
\r
256 (float) p[1].x, (float) -p[1].y,
\r
257 (float) p[2].x, (float) -p[2].y); break;
\r
258 case kCGPathElementCloseSubpath: path.closeSubPath(); break;
\r
259 default: jassertfalse; break;
\r
263 JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MacTypeface);
\r
268 //==============================================================================
\r
269 // The stuff that follows is a mash-up that supports pre-OSX 10.5 and pre-iOS 3.2 APIs.
\r
270 // (Hopefully all of this can be ditched at some point in the future).
\r
272 //==============================================================================
\r
273 #if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
\r
274 #define SUPPORT_10_4_FONTS 1
\r
275 #define NEW_CGFONT_FUNCTIONS_UNAVAILABLE (CGFontCreateWithFontName == 0)
\r
277 #if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5
\r
278 #define SUPPORT_ONLY_10_4_FONTS 1
\r
282 @interface NSFont (PrivateHack)
\r
283 - (NSGlyph) _defaultGlyphForChar: (unichar) theChar;
\r
285 BEGIN_JUCE_NAMESPACE
\r
288 //==============================================================================
\r
289 class MacTypeface : public Typeface
\r
292 //==============================================================================
\r
293 MacTypeface (const Font& font)
\r
294 : Typeface (font.getTypefaceName())
\r
296 JUCE_AUTORELEASEPOOL
\r
297 renderingTransform = CGAffineTransformIdentity;
\r
299 bool needsItalicTransform = false;
\r
302 NSString* fontName = juceStringToNS (font.getTypefaceName());
\r
304 if (font.isItalic() || font.isBold())
\r
306 NSArray* familyFonts = [UIFont fontNamesForFamilyName: juceStringToNS (font.getTypefaceName())];
\r
308 for (NSString* i in familyFonts)
\r
310 const String fn (nsStringToJuce (i));
\r
311 const String afterDash (fn.fromFirstOccurrenceOf ("-", false, false));
\r
313 const bool probablyBold = afterDash.containsIgnoreCase ("bold") || fn.endsWithIgnoreCase ("bold");
\r
314 const bool probablyItalic = afterDash.containsIgnoreCase ("oblique")
\r
315 || afterDash.containsIgnoreCase ("italic")
\r
316 || fn.endsWithIgnoreCase ("oblique")
\r
317 || fn.endsWithIgnoreCase ("italic");
\r
319 if (probablyBold == font.isBold()
\r
320 && probablyItalic == font.isItalic())
\r
323 needsItalicTransform = false;
\r
326 else if (probablyBold && (! probablyItalic) && probablyBold == font.isBold())
\r
329 needsItalicTransform = true; // not ideal, so carry on in case we find a better one
\r
333 if (needsItalicTransform)
\r
334 renderingTransform.c = 0.15f;
\r
337 fontRef = CGFontCreateWithFontName ((CFStringRef) fontName);
\r
339 const int ascender = abs (CGFontGetAscent (fontRef));
\r
340 const float totalHeight = ascender + abs (CGFontGetDescent (fontRef));
\r
341 ascent = ascender / totalHeight;
\r
342 unitsToHeightScaleFactor = 1.0f / totalHeight;
\r
343 fontHeightToCGSizeFactor = CGFontGetUnitsPerEm (fontRef) / totalHeight;
\r
345 nsFont = [NSFont fontWithName: juceStringToNS (font.getTypefaceName()) size: 1024];
\r
347 if (font.isItalic())
\r
349 NSFont* newFont = [[NSFontManager sharedFontManager] convertFont: nsFont
\r
350 toHaveTrait: NSItalicFontMask];
\r
352 if (newFont == nsFont)
\r
353 needsItalicTransform = true; // couldn't find a proper italic version, so fake it with a transform..
\r
359 nsFont = [[NSFontManager sharedFontManager] convertFont: nsFont toHaveTrait: NSBoldFontMask];
\r
363 ascent = std::abs ((float) [nsFont ascender]);
\r
364 float totalSize = ascent + std::abs ((float) [nsFont descender]);
\r
365 ascent /= totalSize;
\r
367 pathTransform = AffineTransform::identity.scale (1.0f / totalSize, 1.0f / totalSize);
\r
369 if (needsItalicTransform)
\r
371 pathTransform = pathTransform.sheared (-0.15f, 0.0f);
\r
372 renderingTransform.c = 0.15f;
\r
375 #if SUPPORT_ONLY_10_4_FONTS
\r
376 ATSFontRef atsFont = ATSFontFindFromName ((CFStringRef) [nsFont fontName], kATSOptionFlagsDefault);
\r
379 atsFont = ATSFontFindFromPostScriptName ((CFStringRef) [nsFont fontName], kATSOptionFlagsDefault);
\r
381 fontRef = CGFontCreateWithPlatformFont (&atsFont);
\r
383 const float totalHeight = std::abs ([nsFont ascender]) + std::abs ([nsFont descender]);
\r
384 unitsToHeightScaleFactor = 1.0f / totalHeight;
\r
385 fontHeightToCGSizeFactor = 1024.0f / totalHeight;
\r
387 #if SUPPORT_10_4_FONTS
\r
388 if (NEW_CGFONT_FUNCTIONS_UNAVAILABLE)
\r
390 ATSFontRef atsFont = ATSFontFindFromName ((CFStringRef) [nsFont fontName], kATSOptionFlagsDefault);
\r
393 atsFont = ATSFontFindFromPostScriptName ((CFStringRef) [nsFont fontName], kATSOptionFlagsDefault);
\r
395 fontRef = CGFontCreateWithPlatformFont (&atsFont);
\r
397 const float totalHeight = std::abs ([nsFont ascender]) + std::abs ([nsFont descender]);
\r
398 unitsToHeightScaleFactor = 1.0f / totalHeight;
\r
399 fontHeightToCGSizeFactor = 1024.0f / totalHeight;
\r
404 fontRef = CGFontCreateWithFontName ((CFStringRef) [nsFont fontName]);
\r
406 const int totalHeight = abs (CGFontGetAscent (fontRef)) + abs (CGFontGetDescent (fontRef));
\r
407 unitsToHeightScaleFactor = 1.0f / totalHeight;
\r
408 fontHeightToCGSizeFactor = CGFontGetUnitsPerEm (fontRef) / (float) totalHeight;
\r
422 CGFontRelease (fontRef);
\r
425 float getAscent() const
\r
430 float getDescent() const
\r
432 return 1.0f - ascent;
\r
435 float getStringWidth (const String& text)
\r
437 if (fontRef == 0 || text.isEmpty())
\r
440 const int length = text.length();
\r
441 HeapBlock <CGGlyph> glyphs;
\r
442 createGlyphsForString (text.getCharPointer(), length, glyphs);
\r
446 #if SUPPORT_ONLY_10_4_FONTS
\r
447 HeapBlock <NSSize> advances (length);
\r
448 [nsFont getAdvancements: advances forGlyphs: reinterpret_cast <NSGlyph*> (glyphs.getData()) count: length];
\r
450 for (int i = 0; i < length; ++i)
\r
451 x += advances[i].width;
\r
453 #if SUPPORT_10_4_FONTS
\r
454 if (NEW_CGFONT_FUNCTIONS_UNAVAILABLE)
\r
456 HeapBlock <NSSize> advances (length);
\r
457 [nsFont getAdvancements: advances forGlyphs: reinterpret_cast<NSGlyph*> (glyphs.getData()) count: length];
\r
459 for (int i = 0; i < length; ++i)
\r
460 x += advances[i].width;
\r
465 HeapBlock <int> advances (length);
\r
467 if (CGFontGetGlyphAdvances (fontRef, glyphs, length, advances))
\r
468 for (int i = 0; i < length; ++i)
\r
473 return x * unitsToHeightScaleFactor;
\r
476 void getGlyphPositions (const String& text, Array <int>& resultGlyphs, Array <float>& xOffsets)
\r
480 if (fontRef == 0 || text.isEmpty())
\r
483 const int length = text.length();
\r
484 HeapBlock <CGGlyph> glyphs;
\r
485 createGlyphsForString (text.getCharPointer(), length, glyphs);
\r
487 #if SUPPORT_ONLY_10_4_FONTS
\r
488 HeapBlock <NSSize> advances (length);
\r
489 [nsFont getAdvancements: advances forGlyphs: reinterpret_cast <NSGlyph*> (glyphs.getData()) count: length];
\r
492 for (int i = 0; i < length; ++i)
\r
494 x += advances[i].width;
\r
495 xOffsets.add (x * unitsToHeightScaleFactor);
\r
496 resultGlyphs.add (reinterpret_cast <NSGlyph*> (glyphs.getData())[i]);
\r
500 #if SUPPORT_10_4_FONTS
\r
501 if (NEW_CGFONT_FUNCTIONS_UNAVAILABLE)
\r
503 HeapBlock <NSSize> advances (length);
\r
504 NSGlyph* const nsGlyphs = reinterpret_cast<NSGlyph*> (glyphs.getData());
\r
505 [nsFont getAdvancements: advances forGlyphs: nsGlyphs count: length];
\r
508 for (int i = 0; i < length; ++i)
\r
510 x += advances[i].width;
\r
511 xOffsets.add (x * unitsToHeightScaleFactor);
\r
512 resultGlyphs.add (nsGlyphs[i]);
\r
518 HeapBlock <int> advances (length);
\r
520 if (CGFontGetGlyphAdvances (fontRef, glyphs, length, advances))
\r
523 for (int i = 0; i < length; ++i)
\r
526 xOffsets.add (x * unitsToHeightScaleFactor);
\r
527 resultGlyphs.add (glyphs[i]);
\r
534 EdgeTable* getEdgeTableForGlyph (int glyphNumber, const AffineTransform& transform)
\r
538 if (getOutlineForGlyph (glyphNumber, path) && ! path.isEmpty())
\r
539 return new EdgeTable (path.getBoundsTransformed (transform).getSmallestIntegerContainer().expanded (1, 0),
\r
545 bool getOutlineForGlyph (int glyphNumber, Path& path)
\r
553 // we might need to apply a transform to the path, so it mustn't have anything else in it
\r
554 jassert (path.isEmpty());
\r
556 JUCE_AUTORELEASEPOOL
\r
558 NSBezierPath* bez = [NSBezierPath bezierPath];
\r
559 [bez moveToPoint: NSMakePoint (0, 0)];
\r
560 [bez appendBezierPathWithGlyph: (NSGlyph) glyphNumber
\r
563 for (int i = 0; i < [bez elementCount]; ++i)
\r
566 switch ([bez elementAtIndex: i associatedPoints: p])
\r
568 case NSMoveToBezierPathElement: path.startNewSubPath ((float) p[0].x, (float) -p[0].y); break;
\r
569 case NSLineToBezierPathElement: path.lineTo ((float) p[0].x, (float) -p[0].y); break;
\r
570 case NSCurveToBezierPathElement: path.cubicTo ((float) p[0].x, (float) -p[0].y,
\r
571 (float) p[1].x, (float) -p[1].y,
\r
572 (float) p[2].x, (float) -p[2].y); break;
\r
573 case NSClosePathBezierPathElement: path.closeSubPath(); break;
\r
574 default: jassertfalse; break;
\r
578 path.applyTransform (pathTransform);
\r
583 //==============================================================================
\r
585 float fontHeightToCGSizeFactor;
\r
586 CGAffineTransform renderingTransform;
\r
589 float ascent, unitsToHeightScaleFactor;
\r
593 AffineTransform pathTransform;
\r
596 void createGlyphsForString (String::CharPointerType text, const int length, HeapBlock <CGGlyph>& glyphs)
\r
598 #if SUPPORT_10_4_FONTS
\r
599 #if ! SUPPORT_ONLY_10_4_FONTS
\r
600 if (NEW_CGFONT_FUNCTIONS_UNAVAILABLE)
\r
603 glyphs.malloc (sizeof (NSGlyph) * length, 1);
\r
604 NSGlyph* const nsGlyphs = reinterpret_cast<NSGlyph*> (glyphs.getData());
\r
606 for (int i = 0; i < length; ++i)
\r
607 nsGlyphs[i] = (NSGlyph) [nsFont _defaultGlyphForChar: text.getAndAdvance()];
\r
613 #if ! SUPPORT_ONLY_10_4_FONTS
\r
614 if (charToGlyphMapper == nullptr)
\r
615 charToGlyphMapper = new CharToGlyphMapper (fontRef);
\r
617 glyphs.malloc (length);
\r
619 for (int i = 0; i < length; ++i)
\r
620 glyphs[i] = (CGGlyph) charToGlyphMapper->getGlyphForCharacter (text.getAndAdvance());
\r
624 #if ! SUPPORT_ONLY_10_4_FONTS
\r
625 // Reads a CGFontRef's character map table to convert unicode into glyph numbers
\r
626 class CharToGlyphMapper
\r
629 CharToGlyphMapper (CGFontRef fontRef)
\r
630 : segCount (0), endCode (0), startCode (0), idDelta (0),
\r
631 idRangeOffset (0), glyphIndexes (0)
\r
633 CFDataRef cmapTable = CGFontCopyTableForTag (fontRef, 'cmap');
\r
635 if (cmapTable != 0)
\r
637 const int numSubtables = getValue16 (cmapTable, 2);
\r
639 for (int i = 0; i < numSubtables; ++i)
\r
641 if (getValue16 (cmapTable, i * 8 + 4) == 0) // check for platform ID of 0
\r
643 const int offset = getValue32 (cmapTable, i * 8 + 8);
\r
645 if (getValue16 (cmapTable, offset) == 4) // check that it's format 4..
\r
647 const int length = getValue16 (cmapTable, offset + 2);
\r
648 const int segCountX2 = getValue16 (cmapTable, offset + 6);
\r
649 segCount = segCountX2 / 2;
\r
650 const int endCodeOffset = offset + 14;
\r
651 const int startCodeOffset = endCodeOffset + 2 + segCountX2;
\r
652 const int idDeltaOffset = startCodeOffset + segCountX2;
\r
653 const int idRangeOffsetOffset = idDeltaOffset + segCountX2;
\r
654 const int glyphIndexesOffset = idRangeOffsetOffset + segCountX2;
\r
656 endCode = CFDataCreate (kCFAllocatorDefault, CFDataGetBytePtr (cmapTable) + endCodeOffset, segCountX2);
\r
657 startCode = CFDataCreate (kCFAllocatorDefault, CFDataGetBytePtr (cmapTable) + startCodeOffset, segCountX2);
\r
658 idDelta = CFDataCreate (kCFAllocatorDefault, CFDataGetBytePtr (cmapTable) + idDeltaOffset, segCountX2);
\r
659 idRangeOffset = CFDataCreate (kCFAllocatorDefault, CFDataGetBytePtr (cmapTable) + idRangeOffsetOffset, segCountX2);
\r
660 glyphIndexes = CFDataCreate (kCFAllocatorDefault, CFDataGetBytePtr (cmapTable) + glyphIndexesOffset, offset + length - glyphIndexesOffset);
\r
667 CFRelease (cmapTable);
\r
671 ~CharToGlyphMapper()
\r
675 CFRelease (endCode);
\r
676 CFRelease (startCode);
\r
677 CFRelease (idDelta);
\r
678 CFRelease (idRangeOffset);
\r
679 CFRelease (glyphIndexes);
\r
683 int getGlyphForCharacter (const juce_wchar c) const
\r
685 for (int i = 0; i < segCount; ++i)
\r
687 if (getValue16 (endCode, i * 2) >= c)
\r
689 const int start = getValue16 (startCode, i * 2);
\r
693 const int delta = getValue16 (idDelta, i * 2);
\r
694 const int rangeOffset = getValue16 (idRangeOffset, i * 2);
\r
696 if (rangeOffset == 0)
\r
699 return getValue16 (glyphIndexes, 2 * ((rangeOffset / 2) + (c - start) - (segCount - i)));
\r
703 // If we failed to find it "properly", this dodgy fall-back seems to do the trick for most fonts!
\r
704 return jmax (-1, (int) c - 29);
\r
709 CFDataRef endCode, startCode, idDelta, idRangeOffset, glyphIndexes;
\r
711 static uint16 getValue16 (CFDataRef data, const int index)
\r
713 return CFSwapInt16BigToHost (*(UInt16*) (CFDataGetBytePtr (data) + index));
\r
716 static uint32 getValue32 (CFDataRef data, const int index)
\r
718 return CFSwapInt32BigToHost (*(UInt32*) (CFDataGetBytePtr (data) + index));
\r
722 ScopedPointer <CharToGlyphMapper> charToGlyphMapper;
\r
725 JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MacTypeface);
\r
730 //==============================================================================
\r
731 Typeface::Ptr Typeface::createSystemTypefaceFor (const Font& font)
\r
733 return new MacTypeface (font);
\r
736 StringArray Font::findAllTypefaceNames()
\r
740 JUCE_AUTORELEASEPOOL
\r
743 NSArray* fonts = [UIFont familyNames];
\r
745 NSArray* fonts = [[NSFontManager sharedFontManager] availableFontFamilies];
\r
748 for (unsigned int i = 0; i < [fonts count]; ++i)
\r
749 names.add (nsStringToJuce ((NSString*) [fonts objectAtIndex: i]));
\r
755 void Font::getPlatformDefaultFontNames (String& defaultSans, String& defaultSerif, String& defaultFixed, String& defaultFallback)
\r
758 defaultSans = "Helvetica";
\r
759 defaultSerif = "Times New Roman";
\r
760 defaultFixed = "Courier New";
\r
762 defaultSans = "Lucida Grande";
\r
763 defaultSerif = "Times New Roman";
\r
764 defaultFixed = "Monaco";
\r
767 defaultFallback = "Arial Unicode MS";
\r