|
- /*
- ==============================================================================
-
- This file is part of the JUCE library - "Jules' Utility Class Extensions"
- Copyright 2004-7 by Raw Material Software ltd.
-
- ------------------------------------------------------------------------------
-
- JUCE can be redistributed and/or modified under the terms of the
- GNU General Public License, as published by the Free Software Foundation;
- either version 2 of the License, or (at your option) any later version.
-
- 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.
-
- You should have received a copy of the GNU General Public License
- along with JUCE; if not, visit www.gnu.org/licenses or write to the
- Free Software Foundation, Inc., 59 Temple Place, Suite 330,
- Boston, MA 02111-1307 USA
-
- ------------------------------------------------------------------------------
-
- If you'd like to release a closed-source product which uses JUCE, commercial
- licenses are also available: visit www.rawmaterialsoftware.com/juce for
- more information.
-
- ==============================================================================
- */
-
- // (This file gets included by juce_mac_NativeCode.mm, rather than being
- // compiled on its own).
- #ifdef JUCE_INCLUDED_FILE
-
-
- //==============================================================================
- class FontHelper
- {
- NSFont* font;
-
- public:
- String name;
- bool isBold, isItalic, needsItalicTransform;
- float fontSize, totalSize, ascent;
- int refCount;
- NSMutableDictionary* attributes;
-
- FontHelper (const String& name_,
- const bool bold_,
- const bool italic_,
- const float size_)
- : font (0),
- name (name_),
- isBold (bold_),
- isItalic (italic_),
- needsItalicTransform (false),
- fontSize (size_),
- refCount (1)
- {
- attributes = [[NSMutableDictionary dictionaryWithObject: [NSNumber numberWithInt: 0]
- forKey: NSLigatureAttributeName] retain];
-
- font = [NSFont fontWithName: juceStringToNS (name_) size: size_];
-
- if (italic_)
- {
- NSFont* newFont = [[NSFontManager sharedFontManager] convertFont: font toHaveTrait: NSItalicFontMask];
-
- if (newFont == font)
- needsItalicTransform = true; // couldn't find a proper italic version, so fake it with a transform..
-
- font = newFont;
- }
-
- if (bold_)
- font = [[NSFontManager sharedFontManager] convertFont: font toHaveTrait: NSBoldFontMask];
-
- [font retain];
-
- ascent = fabsf ([font ascender]);
- totalSize = ascent + fabsf ([font descender]);
- }
-
- ~FontHelper()
- {
- [font release];
- [attributes release];
- }
-
- bool getPathAndKerning (const juce_wchar char1,
- const juce_wchar char2,
- Path* path,
- float& kerning,
- float* ascent,
- float* descent)
- {
- const ScopedAutoReleasePool pool;
-
- if (font == 0
- || ! [[font coveredCharacterSet] longCharacterIsMember: (UTF32Char) char1])
- return false;
-
- String chars;
- chars << ' ' << char1 << char2;
-
- NSTextStorage* textStorage = [[[NSTextStorage alloc] initWithString: juceStringToNS (chars)
- attributes: attributes] autorelease];
- NSLayoutManager* layoutManager = [[[NSLayoutManager alloc] init] autorelease];
- NSTextContainer* textContainer = [[[NSTextContainer alloc] init] autorelease];
- [layoutManager addTextContainer: textContainer];
- [textStorage addLayoutManager: layoutManager];
- [textStorage setFont: font];
-
- unsigned int glyphIndex = [layoutManager glyphRangeForCharacterRange: NSMakeRange (1, 1)
- actualCharacterRange: 0].location;
- NSPoint p1 = [layoutManager locationForGlyphAtIndex: glyphIndex];
- NSPoint p2 = [layoutManager locationForGlyphAtIndex: glyphIndex + 1];
- kerning = p2.x - p1.x;
-
- if (ascent != 0)
- *ascent = this->ascent;
-
- if (descent != 0)
- *descent = fabsf ([font descender]);
-
- if (path != 0)
- {
- NSBezierPath* bez = [NSBezierPath bezierPath];
- [bez moveToPoint: NSMakePoint (0, 0)];
- [bez appendBezierPathWithGlyph: [layoutManager glyphAtIndex: glyphIndex]
- inFont: font];
-
- for (int i = 0; i < [bez elementCount]; ++i)
- {
- NSPoint p[3];
- switch ([bez elementAtIndex: i associatedPoints: p])
- {
- case NSMoveToBezierPathElement:
- path->startNewSubPath (p[0].x, -p[0].y);
- break;
- case NSLineToBezierPathElement:
- path->lineTo (p[0].x, -p[0].y);
- break;
- case NSCurveToBezierPathElement:
- path->cubicTo (p[0].x, -p[0].y, p[1].x, -p[1].y, p[2].x, -p[2].y);
- break;
- case NSClosePathBezierPathElement:
- path->closeSubPath();
- break;
- default:
- jassertfalse
- break;
- }
- }
-
- if (needsItalicTransform)
- path->applyTransform (AffineTransform::identity.sheared (-0.15, 0));
- }
-
- return kerning != 0;
- }
-
- juce_wchar getDefaultChar()
- {
- return 0;
- }
- };
-
- //==============================================================================
- class FontHelperCache : public Timer,
- public DeletedAtShutdown
- {
- VoidArray cache;
-
- public:
- FontHelperCache()
- {
- }
-
- ~FontHelperCache()
- {
- for (int i = cache.size(); --i >= 0;)
- {
- FontHelper* const f = (FontHelper*) cache.getUnchecked(i);
- delete f;
- }
-
- clearSingletonInstance();
- }
-
- FontHelper* getFont (const String& name,
- const bool bold,
- const bool italic,
- const float size = 1024)
- {
- for (int i = cache.size(); --i >= 0;)
- {
- FontHelper* const f = (FontHelper*) cache.getUnchecked(i);
-
- if (f->name == name
- && f->isBold == bold
- && f->isItalic == italic
- && f->fontSize == size)
- {
- f->refCount++;
- return f;
- }
- }
-
- FontHelper* const f = new FontHelper (name, bold, italic, size);
- cache.add (f);
- return f;
- }
-
- void releaseFont (FontHelper* f)
- {
- for (int i = cache.size(); --i >= 0;)
- {
- FontHelper* const f2 = (FontHelper*) cache.getUnchecked(i);
-
- if (f == f2)
- {
- f->refCount--;
-
- if (f->refCount == 0)
- startTimer (5000);
-
- break;
- }
- }
- }
-
- void timerCallback()
- {
- stopTimer();
-
- for (int i = cache.size(); --i >= 0;)
- {
- FontHelper* const f = (FontHelper*) cache.getUnchecked(i);
-
- if (f->refCount == 0)
- {
- cache.remove (i);
- delete f;
- }
- }
-
- if (cache.size() == 0)
- delete this;
- }
-
- juce_DeclareSingleton_SingleThreaded_Minimal (FontHelperCache)
- };
-
- juce_ImplementSingleton_SingleThreaded (FontHelperCache)
-
- //==============================================================================
- void Typeface::initialiseTypefaceCharacteristics (const String& fontName,
- bool bold,
- bool italic,
- bool addAllGlyphsToFont) throw()
- {
- // This method is only safe to be called from the normal UI thread..
- jassert (MessageManager::getInstance()->isThisTheMessageThread());
-
- FontHelper* const helper = FontHelperCache::getInstance()
- ->getFont (fontName, bold, italic);
-
- clear();
- setAscent (helper->ascent / helper->totalSize);
- setName (fontName);
- setDefaultCharacter (helper->getDefaultChar());
- setBold (bold);
- setItalic (italic);
-
- if (addAllGlyphsToFont)
- {
- //xxx
- jassertfalse
- }
-
- FontHelperCache::getInstance()->releaseFont (helper);
- }
-
- bool Typeface::findAndAddSystemGlyph (juce_wchar character) throw()
- {
- // This method is only safe to be called from the normal UI thread..
- jassert (MessageManager::getInstance()->isThisTheMessageThread());
-
- FontHelper* const helper = FontHelperCache::getInstance()
- ->getFont (getName(), isBold(), isItalic());
-
- Path path;
- float width;
- bool foundOne = false;
-
- if (helper->getPathAndKerning (character, T('I'), &path, width, 0, 0))
- {
- path.applyTransform (AffineTransform::scale (1.0f / helper->totalSize,
- 1.0f / helper->totalSize));
-
- addGlyph (character, path, width / helper->totalSize);
-
- for (int i = 0; i < glyphs.size(); ++i)
- {
- const TypefaceGlyphInfo* const g = (const TypefaceGlyphInfo*) glyphs.getUnchecked(i);
-
- float kerning;
- if (helper->getPathAndKerning (character, g->getCharacter(), 0, kerning, 0, 0))
- {
- kerning = (kerning - width) / helper->totalSize;
-
- if (kerning != 0)
- addKerningPair (character, g->getCharacter(), kerning);
- }
-
- if (helper->getPathAndKerning (g->getCharacter(), character, 0, kerning, 0, 0))
- {
- kerning = kerning / helper->totalSize - g->width;
-
- if (kerning != 0)
- addKerningPair (g->getCharacter(), character, kerning);
- }
- }
-
- foundOne = true;
- }
-
- FontHelperCache::getInstance()->releaseFont (helper);
- return foundOne;
- }
-
- //==============================================================================
- const StringArray Font::findAllTypefaceNames() throw()
- {
- StringArray names;
-
- const ScopedAutoReleasePool pool;
- NSArray* fonts = [[NSFontManager sharedFontManager] availableFontFamilies];
-
- for (int i = 0; i < [fonts count]; ++i)
- names.add (nsStringToJuce ((NSString*) [fonts objectAtIndex: i]));
-
- names.sort (true);
- return names;
- }
-
- void Typeface::getDefaultFontNames (String& defaultSans, String& defaultSerif, String& defaultFixed) throw()
- {
- defaultSans = "Lucida Grande";
- defaultSerif = "Times New Roman";
- defaultFixed = "Monaco";
- }
-
- #endif
|