| 
							- /*
 -   ==============================================================================
 - 
 -    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.
 - 
 -   ==============================================================================
 - */
 - 
 - struct FTLibWrapper     : public ReferenceCountedObject
 - {
 -     FTLibWrapper() : library (0)
 -     {
 -         if (FT_Init_FreeType (&library) != 0)
 -         {
 -             library = 0;
 -             DBG ("Failed to initialize FreeType");
 -         }
 -     }
 - 
 -     ~FTLibWrapper()
 -     {
 -         if (library != 0)
 -             FT_Done_FreeType (library);
 -     }
 - 
 -     FT_Library library;
 - 
 -     typedef ReferenceCountedObjectPtr <FTLibWrapper> Ptr;
 - 
 -     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (FTLibWrapper);
 - };
 - 
 - //==============================================================================
 - struct FTFaceWrapper     : public ReferenceCountedObject
 - {
 -     FTFaceWrapper (const FTLibWrapper::Ptr& ftLib, const File& file, int faceIndex)
 -         : face (0), library (ftLib)
 -     {
 -         if (FT_New_Face (ftLib->library, file.getFullPathName().toUTF8(), faceIndex, &face) != 0)
 -             face = 0;
 -     }
 - 
 -     ~FTFaceWrapper()
 -     {
 -         if (face != 0)
 -             FT_Done_Face (face);
 -     }
 - 
 -     FT_Face face;
 -     FTLibWrapper::Ptr library;
 - 
 -     typedef ReferenceCountedObjectPtr <FTFaceWrapper> Ptr;
 - 
 -     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (FTFaceWrapper);
 - };
 - 
 - //==============================================================================
 - class LinuxFontFileIterator
 - {
 - public:
 -     LinuxFontFileIterator()
 -         : index (0)
 -     {
 -         fontDirs.addTokens (CharPointer_UTF8 (getenv ("JUCE_FONT_PATH")), ";,", String::empty);
 -         fontDirs.removeEmptyStrings (true);
 - 
 -         if (fontDirs.size() == 0)
 -         {
 -             const ScopedPointer<XmlElement> fontsInfo (XmlDocument::parse (File ("/etc/fonts/fonts.conf")));
 - 
 -             if (fontsInfo != nullptr)
 -             {
 -                 forEachXmlChildElementWithTagName (*fontsInfo, e, "dir")
 -                 {
 -                     fontDirs.add (e->getAllSubText().trim());
 -                 }
 -             }
 -         }
 - 
 -         if (fontDirs.size() == 0)
 -             fontDirs.add ("/usr/X11R6/lib/X11/fonts");
 - 
 -         fontDirs.removeEmptyStrings (true);
 -     }
 - 
 -     bool next()
 -     {
 -         if (iter != nullptr)
 -         {
 -             while (iter->next())
 -                 if (getFile().hasFileExtension ("ttf;pfb;pcf"))
 -                     return true;
 -         }
 - 
 -         if (index >= fontDirs.size())
 -             return false;
 - 
 -         iter = new DirectoryIterator (fontDirs [index++], true);
 -         return next();
 -     }
 - 
 -     File getFile() const    { jassert (iter != nullptr); return iter->getFile(); }
 - 
 - private:
 -     StringArray fontDirs;
 -     int index;
 -     ScopedPointer<DirectoryIterator> iter;
 - 
 -     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (LinuxFontFileIterator);
 - };
 - 
 - //==============================================================================
 - class FTTypefaceList  : public DeletedAtShutdown
 - {
 - public:
 -     FTTypefaceList()
 -         : library (new FTLibWrapper())
 -     {
 -         LinuxFontFileIterator fontFileIterator;
 - 
 -         while (fontFileIterator.next())
 -         {
 -             int faceIndex = 0;
 -             int numFaces = 0;
 - 
 -             do
 -             {
 -                 FTFaceWrapper face (library, fontFileIterator.getFile(), faceIndex);
 - 
 -                 if (face.face != 0)
 -                 {
 -                     if (faceIndex == 0)
 -                         numFaces = face.face->num_faces;
 - 
 -                     if ((face.face->face_flags & FT_FACE_FLAG_SCALABLE) != 0)
 -                         faces.add (new KnownTypeface (fontFileIterator.getFile(), faceIndex, face));
 -                 }
 - 
 -                 ++faceIndex;
 -             }
 -             while (faceIndex < numFaces);
 -         }
 -     }
 - 
 -     ~FTTypefaceList()
 -     {
 -         clearSingletonInstance();
 -     }
 - 
 -     //==============================================================================
 -     struct KnownTypeface
 -     {
 -         KnownTypeface (const File& file_, const int faceIndex_, const FTFaceWrapper& face)
 -            : file (file_),
 -              family (face.face->family_name),
 -              style (face.face->style_name),
 -              faceIndex (faceIndex_),
 -              isMonospaced ((face.face->face_flags & FT_FACE_FLAG_FIXED_WIDTH) != 0),
 -              isSansSerif (isFaceSansSerif (family))
 -         {
 -         }
 - 
 -         const File file;
 -         const String family, style;
 -         const int faceIndex;
 -         const bool isMonospaced, isSansSerif;
 - 
 -         JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (KnownTypeface);
 -     };
 - 
 -     //==============================================================================
 -     FTFaceWrapper::Ptr createFace (const String& fontName, const String& fontStyle)
 -     {
 -         const KnownTypeface* ftFace = matchTypeface (fontName, fontStyle);
 - 
 -         if (ftFace == nullptr)
 -             ftFace = matchTypeface (fontName, "Regular");
 - 
 -         if (ftFace == nullptr)
 -             ftFace = matchTypeface (fontName, String::empty);
 - 
 -         if (ftFace != nullptr)
 -         {
 -             FTFaceWrapper::Ptr face (new FTFaceWrapper (library, ftFace->file, ftFace->faceIndex));
 - 
 -             if (face->face != 0)
 -             {
 -                 // If there isn't a unicode charmap then select the first one.
 -                 if (FT_Select_Charmap (face->face, ft_encoding_unicode) != 0)
 -                     FT_Set_Charmap (face->face, face->face->charmaps[0]);
 - 
 -                 return face;
 -             }
 -         }
 - 
 -         return nullptr;
 -     }
 - 
 -     //==============================================================================
 -     StringArray findAllFamilyNames() const
 -     {
 -         StringArray s;
 - 
 -         for (int i = 0; i < faces.size(); i++)
 -             s.addIfNotAlreadyThere (faces.getUnchecked(i)->family);
 - 
 -         return s;
 -     }
 - 
 -     StringArray findAllTypefaceStyles (const String& family) const
 -     {
 -         StringArray s;
 - 
 -         for (int i = 0; i < faces.size(); i++)
 -         {
 -             const KnownTypeface* const face = faces.getUnchecked(i);
 - 
 -             if (face->family == family)
 -                 s.addIfNotAlreadyThere (face->style);
 -         }
 - 
 -         return s;
 -     }
 - 
 -     void getMonospacedNames (StringArray& monoSpaced) const
 -     {
 -         for (int i = 0; i < faces.size(); i++)
 -             if (faces.getUnchecked(i)->isMonospaced)
 -                 monoSpaced.addIfNotAlreadyThere (faces.getUnchecked(i)->family);
 -     }
 - 
 -     void getSerifNames (StringArray& serif) const
 -     {
 -         for (int i = 0; i < faces.size(); i++)
 -             if (! faces.getUnchecked(i)->isSansSerif)
 -                 serif.addIfNotAlreadyThere (faces.getUnchecked(i)->family);
 -     }
 - 
 -     void getSansSerifNames (StringArray& sansSerif) const
 -     {
 -         for (int i = 0; i < faces.size(); i++)
 -             if (faces.getUnchecked(i)->isSansSerif)
 -                 sansSerif.addIfNotAlreadyThere (faces.getUnchecked(i)->family);
 -     }
 - 
 -     juce_DeclareSingleton_SingleThreaded_Minimal (FTTypefaceList);
 - 
 - private:
 -     FTLibWrapper::Ptr library;
 -     OwnedArray<KnownTypeface> faces;
 - 
 -     const KnownTypeface* matchTypeface (const String& familyName, const String& style) const noexcept
 -     {
 -         for (int i = 0; i < faces.size(); ++i)
 -         {
 -             const KnownTypeface* const face = faces.getUnchecked(i);
 - 
 -             if (face->family == familyName
 -                   && (face->style.equalsIgnoreCase (style) || style.isEmpty()))
 -                 return face;
 -         }
 - 
 -         return nullptr;
 -     }
 - 
 -     static bool isFaceSansSerif (const String& family)
 -     {
 -         const char* sansNames[] = { "Sans", "Verdana", "Arial", "Ubuntu" };
 - 
 -         for (int i = 0; i < numElementsInArray (sansNames); ++i)
 -             if (family.containsIgnoreCase (sansNames[i]))
 -                 return true;
 - 
 -         return false;
 -     }
 - 
 -     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (FTTypefaceList);
 - };
 - 
 - juce_ImplementSingleton_SingleThreaded (FTTypefaceList)
 - 
 - 
 - //==============================================================================
 - class FreeTypeTypeface   : public CustomTypeface
 - {
 - public:
 -     FreeTypeTypeface (const Font& font)
 -         : faceWrapper (FTTypefaceList::getInstance()
 -                            ->createFace (font.getTypefaceName(), font.getTypefaceStyle()))
 -     {
 -         if (faceWrapper != nullptr)
 -         {
 -             setCharacteristics (font.getTypefaceName(),
 -                                 font.getTypefaceStyle(),
 -                                 faceWrapper->face->ascender / (float) (faceWrapper->face->ascender - faceWrapper->face->descender),
 -                                 L' ');
 -         }
 -         else
 -         {
 -             DBG ("Failed to create typeface: " << font.toString());
 -         }
 -     }
 - 
 -     bool loadGlyphIfPossible (const juce_wchar character)
 -     {
 -         if (faceWrapper != nullptr)
 -         {
 -             FT_Face face = faceWrapper->face;
 -             const unsigned int glyphIndex = FT_Get_Char_Index (face, character);
 - 
 -             if (FT_Load_Glyph (face, glyphIndex, FT_LOAD_NO_SCALE | FT_LOAD_NO_BITMAP | FT_LOAD_IGNORE_TRANSFORM) == 0
 -                   && face->glyph->format == ft_glyph_format_outline)
 -             {
 -                 const float scale = 1.0f / (float) (face->ascender - face->descender);
 -                 Path destShape;
 - 
 -                 if (getGlyphShape (destShape, face->glyph->outline, scale))
 -                 {
 -                     addGlyph (character, destShape, face->glyph->metrics.horiAdvance * scale);
 - 
 -                     if ((face->face_flags & FT_FACE_FLAG_KERNING) != 0)
 -                         addKerning (face, character, glyphIndex);
 - 
 -                     return true;
 -                 }
 -             }
 -         }
 - 
 -         return false;
 -     }
 - 
 - private:
 -     FTFaceWrapper::Ptr faceWrapper;
 - 
 -     bool getGlyphShape (Path& destShape, const FT_Outline& outline, const float scaleX)
 -     {
 -         const float scaleY = -scaleX;
 -         const short* const contours = outline.contours;
 -         const char* const tags = outline.tags;
 -         const FT_Vector* const points = outline.points;
 - 
 -         for (int c = 0; c < outline.n_contours; ++c)
 -         {
 -             const int startPoint = (c == 0) ? 0 : contours [c - 1] + 1;
 -             const int endPoint = contours[c];
 - 
 -             for (int p = startPoint; p <= endPoint; ++p)
 -             {
 -                 const float x = scaleX * points[p].x;
 -                 const float y = scaleY * points[p].y;
 - 
 -                 if (p == startPoint)
 -                 {
 -                     if (FT_CURVE_TAG (tags[p]) == FT_Curve_Tag_Conic)
 -                     {
 -                         float x2 = scaleX * points [endPoint].x;
 -                         float y2 = scaleY * points [endPoint].y;
 - 
 -                         if (FT_CURVE_TAG (tags[endPoint]) != FT_Curve_Tag_On)
 -                         {
 -                             x2 = (x + x2) * 0.5f;
 -                             y2 = (y + y2) * 0.5f;
 -                         }
 - 
 -                         destShape.startNewSubPath (x2, y2);
 -                     }
 -                     else
 -                     {
 -                         destShape.startNewSubPath (x, y);
 -                     }
 -                 }
 - 
 -                 if (FT_CURVE_TAG (tags[p]) == FT_Curve_Tag_On)
 -                 {
 -                     if (p != startPoint)
 -                         destShape.lineTo (x, y);
 -                 }
 -                 else if (FT_CURVE_TAG (tags[p]) == FT_Curve_Tag_Conic)
 -                 {
 -                     const int nextIndex = (p == endPoint) ? startPoint : p + 1;
 -                     float x2 = scaleX * points [nextIndex].x;
 -                     float y2 = scaleY * points [nextIndex].y;
 - 
 -                     if (FT_CURVE_TAG (tags [nextIndex]) == FT_Curve_Tag_Conic)
 -                     {
 -                         x2 = (x + x2) * 0.5f;
 -                         y2 = (y + y2) * 0.5f;
 -                     }
 -                     else
 -                     {
 -                         ++p;
 -                     }
 - 
 -                     destShape.quadraticTo (x, y, x2, y2);
 -                 }
 -                 else if (FT_CURVE_TAG (tags[p]) == FT_Curve_Tag_Cubic)
 -                 {
 -                     const int next1 = p + 1;
 -                     const int next2 = (p == (endPoint - 1)) ? startPoint : (p + 2);
 - 
 -                     if (p >= endPoint
 -                          || FT_CURVE_TAG (tags[next1]) != FT_Curve_Tag_Cubic
 -                          || FT_CURVE_TAG (tags[next2]) != FT_Curve_Tag_On)
 -                         return false;
 - 
 -                     const float x2 = scaleX * points [next1].x;
 -                     const float y2 = scaleY * points [next1].y;
 -                     const float x3 = scaleX * points [next2].x;
 -                     const float y3 = scaleY * points [next2].y;
 - 
 -                     destShape.cubicTo (x, y, x2, y2, x3, y3);
 -                     p += 2;
 -                 }
 -             }
 - 
 -             destShape.closeSubPath();
 -         }
 - 
 -         return true;
 -     }
 - 
 -     void addKerning (FT_Face face, const uint32 character, const uint32 glyphIndex)
 -     {
 -         const float height = (float) (face->ascender - face->descender);
 - 
 -         uint32 rightGlyphIndex;
 -         uint32 rightCharCode = FT_Get_First_Char (face, &rightGlyphIndex);
 - 
 -         while (rightGlyphIndex != 0)
 -         {
 -             FT_Vector kerning;
 - 
 -             if (FT_Get_Kerning (face, glyphIndex, rightGlyphIndex, ft_kerning_unscaled, &kerning) == 0
 -                    && kerning.x != 0)
 -                 addKerningPair (character, rightCharCode, kerning.x / height);
 - 
 -             rightCharCode = FT_Get_Next_Char (face, rightCharCode, &rightGlyphIndex);
 -         }
 -     }
 - 
 -     JUCE_DECLARE_NON_COPYABLE (FreeTypeTypeface);
 - };
 - 
 - //==============================================================================
 - Typeface::Ptr Typeface::createSystemTypefaceFor (const Font& font)
 - {
 -     return new FreeTypeTypeface (font);
 - }
 - 
 - StringArray Font::findAllTypefaceNames()
 - {
 -     return FTTypefaceList::getInstance()->findAllFamilyNames();
 - }
 - 
 - StringArray Font::findAllTypefaceStyles (const String& family)
 - {
 -     return FTTypefaceList::getInstance()->findAllTypefaceStyles (family);
 - }
 - 
 - //==============================================================================
 - struct DefaultFontNames
 - {
 -     DefaultFontNames()
 -         : defaultSans  (getDefaultSansSerifFontName()),
 -           defaultSerif (getDefaultSerifFontName()),
 -           defaultFixed (getDefaultMonospacedFontName())
 -     {
 -     }
 - 
 -     String defaultSans, defaultSerif, defaultFixed;
 - 
 - private:
 -     static String pickBestFont (const StringArray& names, const char* const* choicesArray)
 -     {
 -         const StringArray choices (choicesArray);
 - 
 -         for (int j = 0; j < choices.size(); ++j)
 -             if (names.contains (choices[j], true))
 -                 return choices[j];
 - 
 -         for (int j = 0; j < choices.size(); ++j)
 -             for (int i = 0; i < names.size(); ++i)
 -                 if (names[i].startsWithIgnoreCase (choices[j]))
 -                     return names[i];
 - 
 -         for (int j = 0; j < choices.size(); ++j)
 -             for (int i = 0; i < names.size(); ++i)
 -                 if (names[i].containsIgnoreCase (choices[j]))
 -                     return names[i];
 - 
 -         return names[0];
 -     }
 - 
 -     static String getDefaultSansSerifFontName()
 -     {
 -         StringArray allFonts;
 -         FTTypefaceList::getInstance()->getSansSerifNames (allFonts);
 - 
 -         const char* targets[] = { "Verdana", "Bitstream Vera Sans", "Luxi Sans",
 -                                   "Liberation Sans", "DejaVu Sans", "Sans", 0 };
 -         return pickBestFont (allFonts, targets);
 -     }
 - 
 -     static String getDefaultSerifFontName()
 -     {
 -         StringArray allFonts;
 -         FTTypefaceList::getInstance()->getSerifNames (allFonts);
 - 
 -         const char* targets[] = { "Bitstream Vera Serif", "Times", "Nimbus Roman",
 -                                   "Liberation Serif", "DejaVu Serif", "Serif", 0 };
 -         return pickBestFont (allFonts, targets);
 -     }
 - 
 -     static String getDefaultMonospacedFontName()
 -     {
 -         StringArray allFonts;
 -         FTTypefaceList::getInstance()->getMonospacedNames (allFonts);
 - 
 -         const char* targets[] = { "Bitstream Vera Sans Mono", "Courier", "Sans Mono",
 -                                   "Liberation Mono", "DejaVu Mono", "Mono", 0 };
 -         return pickBestFont (allFonts, targets);
 -     }
 - 
 -     JUCE_DECLARE_NON_COPYABLE (DefaultFontNames);
 - };
 - 
 - Typeface::Ptr Font::getDefaultTypefaceForFont (const Font& font)
 - {
 -     static DefaultFontNames defaultNames;
 - 
 -     String faceName (font.getTypefaceName());
 - 
 -     if (faceName == getDefaultSansSerifFontName())       faceName = defaultNames.defaultSans;
 -     else if (faceName == getDefaultSerifFontName())      faceName = defaultNames.defaultSerif;
 -     else if (faceName == getDefaultMonospacedFontName()) faceName = defaultNames.defaultFixed;
 - 
 -     Font f (font);
 -     f.setTypefaceName (faceName);
 -     return Typeface::createSystemTypefaceFor (f);
 - }
 - 
 - bool TextLayout::createNativeLayout (const AttributedString&)
 - {
 -     return false;
 - }
 
 
  |