36 DBG (
"Failed to initialize FreeType");
42 if (library !=
nullptr)
46 FT_Library library = {};
64 : library (
ftLib), savedFaceData (data, dataSize)
92 scanFontPaths (getDefaultFontDirectories());
105 family (face.face->family_name),
106 style (face.face->style_name),
109 isSansSerif (isFaceSansSerif (family))
114 const String family, style;
116 const bool isMonospaced, isSansSerif;
133 return selectUnicodeCharmap (
new FTFaceWrapper (library, data, dataSize, index));
136 FTFaceWrapper::Ptr createFace (
const File& file,
int index)
138 return selectUnicodeCharmap (
new FTFaceWrapper (library, file, index));
155 StringArray findAllFamilyNames()
const
159 for (
auto* face : faces)
160 set.insert (face->family);
164 for (
const auto& family : set)
170 StringArray findAllTypefaceStyles (
const String& family)
const
174 for (
auto* face : faces)
175 if (face->family == family)
176 s.addIfNotAlreadyThere (face->style);
182 void scanFontPaths (
const StringArray&
paths)
184 for (
auto& path :
paths)
186 for (
const auto& iter : RangedDirectoryIterator (File::getCurrentWorkingDirectory().getChildFile (path),
true))
188 if (iter.getFile().hasFileExtension (
"ttf;pfb;pcf;otf"))
189 scanFont (iter.getFile());
193 std::sort (faces.begin(), faces.end(), [] (
const auto* a,
const auto* b)
195 const auto tie = [] (const KnownTypeface& t)
198 const auto computeStyleNormalcy = [] (const String& style)
200 if (style ==
"Regular")
203 if (style ==
"Roman")
209 if (style.containsIgnoreCase (
"Bold"))
212 if (style.containsIgnoreCase (
"Italic"))
218 return std::make_tuple (t.family,
219 computeStyleNormalcy (t.style),
227 return tie (*a) <
tie (*b);
231 void getMonospacedNames (StringArray&
monoSpaced)
const
233 for (
auto* face : faces)
234 if (face->isMonospaced)
235 monoSpaced.addIfNotAlreadyThere (face->family);
238 void getSerifNames (StringArray& serif)
const
240 for (
auto* face : faces)
241 if (! (face->isSansSerif || face->isMonospaced))
242 serif.addIfNotAlreadyThere (face->family);
245 void getSansSerifNames (StringArray&
sansSerif)
const
247 for (
auto* face : faces)
248 if (face->isSansSerif)
249 sansSerif.addIfNotAlreadyThere (face->family);
255 FTLibWrapper::Ptr library;
258 static StringArray getDefaultFontDirectories();
260 void scanFont (
const File& file)
267 FTFaceWrapper face (library, file, faceIndex);
269 if (face.face !=
nullptr)
275 faces.add (
new KnownTypeface (file, faceIndex, face));
283 const KnownTypeface* matchTypeface (
const String&
familyName,
const String& style)
const noexcept
285 for (
auto* face : faces)
287 && (face->style.equalsIgnoreCase (style) || style.isEmpty()))
293 static bool isFaceSansSerif (
const String& family)
295 static const char*
sansNames[] = {
"Sans",
"Verdana",
"Arial",
"Ubuntu" };
298 if (family.containsIgnoreCase (name))
315 : faceWrapper (FTTypefaceList::getInstance()->createFace (font.
getTypefaceName(),
318 if (faceWrapper !=
nullptr)
324 : faceWrapper (FTTypefaceList::getInstance()->createFace (data, dataSize, 0))
326 if (faceWrapper !=
nullptr)
327 initialiseCharacteristics (faceWrapper->face->family_name,
328 faceWrapper->face->style_name);
331 void initialiseCharacteristics (
const String& fontName,
const String& fontStyle)
333 setCharacteristics (fontName, fontStyle,
334 faceWrapper->face->ascender / (
float) (faceWrapper->face->ascender - faceWrapper->face->descender),
340 if (faceWrapper !=
nullptr)
342 auto face = faceWrapper->face;
343 auto glyphIndex = FT_Get_Char_Index (face, (FT_ULong) character);
345 if (FT_Load_Glyph (face, glyphIndex, FT_LOAD_NO_SCALE | FT_LOAD_NO_BITMAP | FT_LOAD_IGNORE_TRANSFORM | FT_LOAD_NO_HINTING) == 0
346 && face->glyph->format == ft_glyph_format_outline)
348 auto scale = 1.0f / (
float) (face->ascender - face->descender);
351 if (getGlyphShape (destShape, face->glyph->outline, scale))
353 addGlyph (character, destShape, (
float) face->glyph->metrics.horiAdvance * scale);
355 if ((face->face_flags & FT_FACE_FLAG_KERNING) != 0)
356 addKerning (face, (
uint32) character, glyphIndex);
369 bool getGlyphShape (
Path& destShape,
const FT_Outline& outline,
float scaleX)
371 auto scaleY = -scaleX;
372 auto* contours = outline.contours;
373 auto* tags = outline.tags;
374 auto* points = outline.points;
376 for (
int c = 0; c < outline.n_contours; ++c)
378 const int startPoint = (c == 0) ? 0 : contours [c - 1] + 1;
379 const int endPoint = contours[c];
381 for (
int p = startPoint; p <= endPoint; ++p)
383 auto x = scaleX * (
float) points[p].x;
384 auto y = scaleY * (
float) points[p].y;
388 if (FT_CURVE_TAG (tags[p]) == FT_Curve_Tag_Conic)
390 auto x2 = scaleX * (
float) points[endPoint].x;
391 auto y2 = scaleY * (
float) points[endPoint].y;
393 if (FT_CURVE_TAG (tags[endPoint]) != FT_Curve_Tag_On)
395 x2 = (x + x2) * 0.5f;
396 y2 = (y + y2) * 0.5f;
407 if (FT_CURVE_TAG (tags[p]) == FT_Curve_Tag_On)
412 else if (FT_CURVE_TAG (tags[p]) == FT_Curve_Tag_Conic)
414 const int nextIndex = (p == endPoint) ? startPoint : p + 1;
415 auto x2 = scaleX * (
float) points[nextIndex].x;
416 auto y2 = scaleY * (
float) points[nextIndex].y;
418 if (FT_CURVE_TAG (tags [nextIndex]) == FT_Curve_Tag_Conic)
420 x2 = (x + x2) * 0.5f;
421 y2 = (y + y2) * 0.5f;
430 else if (FT_CURVE_TAG (tags[p]) == FT_Curve_Tag_Cubic)
432 const int next1 = p + 1;
433 const int next2 = (p == (endPoint - 1)) ? startPoint : (p + 2);
436 || FT_CURVE_TAG (tags[next1]) != FT_Curve_Tag_Cubic
437 || FT_CURVE_TAG (tags[next2]) != FT_Curve_Tag_On)
440 auto x2 = scaleX * (
float) points[next1].x;
441 auto y2 = scaleY * (
float) points[next1].y;
442 auto x3 = scaleX * (
float) points[next2].x;
443 auto y3 = scaleY * (
float) points[next2].y;
445 destShape.
cubicTo (x, y, x2, y2, x3, y3);
456 void addKerning (FT_Face face,
const uint32 character,
const uint32 glyphIndex)
458 auto height = (
float) (face->ascender - face->descender);
460 uint32 rightGlyphIndex;
461 auto rightCharCode = FT_Get_First_Char (face, &rightGlyphIndex);
463 while (rightGlyphIndex != 0)
467 if (FT_Get_Kerning (face, glyphIndex, rightGlyphIndex, ft_kerning_unscaled, &kerning) == 0
469 addKerningPair ((juce_wchar) character, (juce_wchar) rightCharCode, (
float) kerning.x / height);
471 rightCharCode = FT_Get_Next_Char (face, rightCharCode, &rightGlyphIndex);
A typeface that can be populated with custom glyphs.
Classes derived from this will be automatically deleted when the application exits.
Represents a local file or directory.
const String & getFullPathName() const noexcept
Returns the complete, absolute path of this file.
Represents a particular font, including its size, style, etc.
String getTypefaceName() const noexcept
Returns the font family of the typeface that this font uses.
String getTypefaceStyle() const noexcept
Returns the font style of the typeface that this font uses.
bool loadGlyphIfPossible(const juce_wchar character) override
If a subclass overrides this, it can load glyphs into the font on-demand.
A class to hold a resizable block of raw data.
void * getData() noexcept
Returns a void pointer to the data.
size_t getSize() const noexcept
Returns the block's current allocated size, in bytes.
A path is a sequence of lines and curves that may either form a closed shape or be open-ended.
void startNewSubPath(float startX, float startY)
Begins a new subpath with a given starting position.
void quadraticTo(float controlPointX, float controlPointY, float endPointX, float endPointY)
Adds a quadratic bezier curve from the shape's last position to a new position.
void cubicTo(float controlPoint1X, float controlPoint1Y, float controlPoint2X, float controlPoint2Y, float endPointX, float endPointY)
Adds a cubic bezier curve from the shape's last position to a new position.
void closeSubPath()
Closes a the current sub-path with a line back to its start-point.
void lineTo(float endX, float endY)
Adds a line from the shape's last position to a new end-point.
A base class which provides methods for reference-counting.
CharPointer_UTF8 toUTF8() const
Returns a pointer to a UTF-8 version of this string.
#define JUCE_IMPLEMENT_SINGLETON(Classname)
This is a counterpart to the JUCE_DECLARE_SINGLETON macros.
#define JUCE_DECLARE_SINGLETON_SINGLETHREADED_MINIMAL(Classname)
Macro to declare member variables and methods for a singleton class.
wchar_t juce_wchar
A platform-independent 32-bit unicode character type.
Type unalignedPointerCast(void *ptr) noexcept
Casts a pointer to another type via void*, which suppresses the cast-align warning which sometimes ar...
unsigned int uint32
A platform-independent 32-bit unsigned integer type.