Browse Source

Initial commit of font style access, providing access to the styles available for each font family.

tags/2021-05-28
jules 13 years ago
parent
commit
941907a3d1
14 changed files with 824 additions and 348 deletions
  1. +1
    -1
      extras/Introjucer/Source/Code Editor/jucer_SourceCodeEditor.cpp
  2. +23
    -12
      modules/juce_graphics/fonts/juce_CustomTypeface.cpp
  3. +21
    -10
      modules/juce_graphics/fonts/juce_CustomTypeface.h
  4. +151
    -50
      modules/juce_graphics/fonts/juce_Font.cpp
  5. +89
    -25
      modules/juce_graphics/fonts/juce_Font.h
  6. +40
    -3
      modules/juce_graphics/fonts/juce_Typeface.cpp
  7. +9
    -3
      modules/juce_graphics/fonts/juce_Typeface.h
  8. +1
    -4
      modules/juce_graphics/juce_graphics.cpp
  9. +61
    -8
      modules/juce_graphics/native/juce_android_Fonts.cpp
  10. +32
    -13
      modules/juce_graphics/native/juce_linux_Fonts.cpp
  11. +187
    -135
      modules/juce_graphics/native/juce_mac_Fonts.mm
  12. +54
    -51
      modules/juce_graphics/native/juce_win32_DirectWriteTypeLayout.cpp
  13. +56
    -5
      modules/juce_graphics/native/juce_win32_DirectWriteTypeface.cpp
  14. +99
    -28
      modules/juce_graphics/native/juce_win32_Fonts.cpp

+ 1
- 1
extras/Introjucer/Source/Code Editor/jucer_SourceCodeEditor.cpp View File

@@ -38,7 +38,7 @@ SourceCodeEditor::SourceCodeEditor (OpenDocumentManager::Document* document_,
#if JUCE_MAC #if JUCE_MAC
Font font (10.6f); Font font (10.6f);
font.setTypefaceName ("Menlo Regular");
font.setTypefaceName ("Menlo");
#else #else
Font font (10.0f); Font font (10.0f);
font.setTypefaceName (Font::getDefaultMonospacedFontName()); font.setTypefaceName (Font::getDefaultMonospacedFontName());


+ 23
- 12
modules/juce_graphics/fonts/juce_CustomTypeface.cpp View File

@@ -102,13 +102,13 @@ namespace CustomTypefaceHelpers
//============================================================================== //==============================================================================
CustomTypeface::CustomTypeface() CustomTypeface::CustomTypeface()
: Typeface (String::empty)
: Typeface (String::empty, String::empty)
{ {
clear(); clear();
} }
CustomTypeface::CustomTypeface (InputStream& serialisedTypefaceStream) CustomTypeface::CustomTypeface (InputStream& serialisedTypefaceStream)
: Typeface (String::empty)
: Typeface (String::empty, String::empty)
{ {
clear(); clear();
@@ -116,8 +116,11 @@ CustomTypeface::CustomTypeface (InputStream& serialisedTypefaceStream)
BufferedInputStream in (gzin, 32768); BufferedInputStream in (gzin, 32768);
name = in.readString(); name = in.readString();
isBold = in.readBool();
isItalic = in.readBool();
const bool isBold = in.readBool();
const bool isItalic = in.readBool();
style = FontStyleHelpers::getStyleName (isBold, isItalic);
ascent = in.readFloat(); ascent = in.readFloat();
defaultCharacter = CustomTypefaceHelpers::readChar (in); defaultCharacter = CustomTypefaceHelpers::readChar (in);
@@ -153,19 +156,27 @@ void CustomTypeface::clear()
{ {
defaultCharacter = 0; defaultCharacter = 0;
ascent = 1.0f; ascent = 1.0f;
isBold = isItalic = false;
style = "Regular";
zeromem (lookupTable, sizeof (lookupTable)); zeromem (lookupTable, sizeof (lookupTable));
glyphs.clear(); glyphs.clear();
} }
void CustomTypeface::setCharacteristics (const String& name_, const float ascent_, const bool isBold_,
const bool isItalic_, const juce_wchar defaultCharacter_) noexcept
void CustomTypeface::setCharacteristics (const String& name_, const float ascent_, const bool isBold,
const bool isItalic, const juce_wchar defaultCharacter_) noexcept
{
name = name_;
defaultCharacter = defaultCharacter_;
ascent = ascent_;
style = FontStyleHelpers::getStyleName (isBold, isItalic);
}
void CustomTypeface::setCharacteristics (const String& name_, const String& style_, const float ascent_,
const juce_wchar defaultCharacter_) noexcept
{ {
name = name_; name = name_;
style = style_;
defaultCharacter = defaultCharacter_; defaultCharacter = defaultCharacter_;
ascent = ascent_; ascent = ascent_;
isBold = isBold_;
isItalic = isItalic_;
} }
void CustomTypeface::addGlyph (const juce_wchar character, const Path& path, const float width) noexcept void CustomTypeface::addGlyph (const juce_wchar character, const Path& path, const float width) noexcept
@@ -216,7 +227,7 @@ bool CustomTypeface::loadGlyphIfPossible (const juce_wchar /*characterNeeded*/)
void CustomTypeface::addGlyphsFromOtherTypeface (Typeface& typefaceToCopy, juce_wchar characterStartIndex, int numCharacters) noexcept void CustomTypeface::addGlyphsFromOtherTypeface (Typeface& typefaceToCopy, juce_wchar characterStartIndex, int numCharacters) noexcept
{ {
setCharacteristics (name, typefaceToCopy.getAscent(), isBold, isItalic, defaultCharacter);
setCharacteristics (name, style, typefaceToCopy.getAscent(), defaultCharacter);
for (int i = 0; i < numCharacters; ++i) for (int i = 0; i < numCharacters; ++i)
{ {
@@ -256,8 +267,8 @@ bool CustomTypeface::writeToStream (OutputStream& outputStream)
GZIPCompressorOutputStream out (&outputStream); GZIPCompressorOutputStream out (&outputStream);
out.writeString (name); out.writeString (name);
out.writeBool (isBold);
out.writeBool (isItalic);
out.writeBool (FontStyleHelpers::isBold (style));
out.writeBool (FontStyleHelpers::isItalic (style));
out.writeFloat (ascent); out.writeFloat (ascent);
CustomTypefaceHelpers::writeChar (out, defaultCharacter); CustomTypefaceHelpers::writeChar (out, defaultCharacter);
out.writeInt (glyphs.size()); out.writeInt (glyphs.size());


+ 21
- 10
modules/juce_graphics/fonts/juce_CustomTypeface.h View File

@@ -64,19 +64,31 @@ public:
void clear(); void clear();
/** Sets the vital statistics for the typeface. /** Sets the vital statistics for the typeface.
@param name the typeface's name
@param ascent the ascent - this is normalised to a height of 1.0 and this is
the value that will be returned by Typeface::getAscent(). The
descent is assumed to be (1.0 - ascent)
@param isBold should be true if the typeface is bold
@param isItalic should be true if the typeface is italic
@param defaultCharacter the character to be used as a replacement if there's
no glyph available for the character that's being drawn
@param fontFamily the typeface's font family
@param ascent the ascent - this is normalised to a height of 1.0 and this is
the value that will be returned by Typeface::getAscent(). The
descent is assumed to be (1.0 - ascent)
@param isBold should be true if the typeface is bold
@param isItalic should be true if the typeface is italic
@param defaultCharacter the character to be used as a replacement if there's
no glyph available for the character that's being drawn
*/ */
void setCharacteristics (const String& name, float ascent,
void setCharacteristics (const String& fontFamily, float ascent,
bool isBold, bool isItalic, bool isBold, bool isItalic,
juce_wchar defaultCharacter) noexcept; juce_wchar defaultCharacter) noexcept;
/** Sets the vital statistics for the typeface.
@param fontFamily the typeface's font family
@param fontStyle the typeface's font style
@param ascent the ascent - this is normalised to a height of 1.0 and this is
the value that will be returned by Typeface::getAscent(). The
descent is assumed to be (1.0 - ascent)
@param defaultCharacter the character to be used as a replacement if there's
no glyph available for the character that's being drawn
*/
void setCharacteristics (const String& fontFamily, const String& fontStyle,
float ascent, juce_wchar defaultCharacter) noexcept;
/** Adds a glyph to the typeface. /** Adds a glyph to the typeface.
The path that is passed in is normalised so that the font height is 1.0, and its The path that is passed in is normalised so that the font height is 1.0, and its
@@ -117,7 +129,6 @@ protected:
//============================================================================== //==============================================================================
juce_wchar defaultCharacter; juce_wchar defaultCharacter;
float ascent; float ascent;
bool isBold, isItalic;
//============================================================================== //==============================================================================
/** If a subclass overrides this, it can load glyphs into the font on-demand. /** If a subclass overrides this, it can load glyphs into the font on-demand.


+ 151
- 50
modules/juce_graphics/fonts/juce_Font.cpp View File

@@ -32,6 +32,7 @@ namespace FontValues
const float defaultFontHeight = 14.0f; const float defaultFontHeight = 14.0f;
String fallbackFont; String fallbackFont;
String fallbackFontStyle;
} }
typedef Typeface::Ptr (*GetTypefaceForFont) (const Font&); typedef Typeface::Ptr (*GetTypefaceForFont) (const Font&);
@@ -62,16 +63,18 @@ public:
Typeface::Ptr findTypefaceFor (const Font& font) Typeface::Ptr findTypefaceFor (const Font& font)
{ {
const int flags = font.getStyleFlags() & (Font::bold | Font::italic);
const String faceName (font.getTypefaceName()); const String faceName (font.getTypefaceName());
const String faceStyle (font.getTypefaceStyle());
int i;
for (i = faces.size(); --i >= 0;)
jassert (faceName.isNotEmpty());
for (int i = faces.size(); --i >= 0;)
{ {
CachedFace& face = faces.getReference(i); CachedFace& face = faces.getReference(i);
if (face.flags == flags
&& face.typefaceName == faceName
if (face.typefaceName == faceName
&& face.typefaceStyle == faceStyle
&& face.typeface != nullptr
&& face.typeface->isSuitableForFont (font)) && face.typeface->isSuitableForFont (font))
{ {
face.lastUsageCount = ++counter; face.lastUsageCount = ++counter;
@@ -82,7 +85,7 @@ public:
int replaceIndex = 0; int replaceIndex = 0;
size_t bestLastUsageCount = std::numeric_limits<int>::max(); size_t bestLastUsageCount = std::numeric_limits<int>::max();
for (i = faces.size(); --i >= 0;)
for (int i = faces.size(); --i >= 0;)
{ {
const size_t lu = faces.getReference(i).lastUsageCount; const size_t lu = faces.getReference(i).lastUsageCount;
@@ -95,7 +98,7 @@ public:
CachedFace& face = faces.getReference (replaceIndex); CachedFace& face = faces.getReference (replaceIndex);
face.typefaceName = faceName; face.typefaceName = faceName;
face.flags = flags;
face.typefaceStyle = faceStyle;
face.lastUsageCount = ++counter; face.lastUsageCount = ++counter;
if (juce_getTypefaceForFont == nullptr) if (juce_getTypefaceForFont == nullptr)
@@ -120,7 +123,7 @@ private:
struct CachedFace struct CachedFace
{ {
CachedFace() noexcept CachedFace() noexcept
: lastUsageCount (0), flags (-1)
: lastUsageCount (0)
{ {
} }
@@ -129,8 +132,8 @@ private:
// Since the typeface itself doesn't know that it may have this alias, the name under // Since the typeface itself doesn't know that it may have this alias, the name under
// which it was fetched needs to be stored separately. // which it was fetched needs to be stored separately.
String typefaceName; String typefaceName;
String typefaceStyle;
size_t lastUsageCount; size_t lastUsageCount;
int flags;
Typeface::Ptr typeface; Typeface::Ptr typeface;
}; };
@@ -152,47 +155,54 @@ void Typeface::setTypefaceCacheSize (int numFontsToCache)
class Font::SharedFontInternal : public SingleThreadedReferenceCountedObject class Font::SharedFontInternal : public SingleThreadedReferenceCountedObject
{ {
public: public:
SharedFontInternal (const float height_, const int styleFlags_) noexcept
SharedFontInternal (const String& typefaceStyle_, const float height_) noexcept
: typefaceName (Font::getDefaultSansSerifFontName()), : typefaceName (Font::getDefaultSansSerifFontName()),
typefaceStyle (typefaceStyle_),
height (height_), height (height_),
horizontalScale (1.0f), horizontalScale (1.0f),
kerning (0), kerning (0),
ascent (0), ascent (0),
styleFlags (styleFlags_),
typeface ((styleFlags_ & (Font::bold | Font::italic)) == 0
underline (false),
typeface (typefaceStyle_ == Font::getDefaultStyle()
? TypefaceCache::getInstance()->getDefaultTypeface() : nullptr) ? TypefaceCache::getInstance()->getDefaultTypeface() : nullptr)
{ {
} }
SharedFontInternal (const String& typefaceName_, const float height_, const int styleFlags_) noexcept
SharedFontInternal (const String& typefaceName_, const String& typefaceStyle_, const float height_) noexcept
: typefaceName (typefaceName_), : typefaceName (typefaceName_),
typefaceStyle (typefaceStyle_),
height (height_), height (height_),
horizontalScale (1.0f), horizontalScale (1.0f),
kerning (0), kerning (0),
ascent (0), ascent (0),
styleFlags (styleFlags_),
underline (false),
typeface (nullptr) typeface (nullptr)
{ {
if (typefaceName.isEmpty())
typefaceName = Font::getDefaultSansSerifFontName();
} }
SharedFontInternal (const Typeface::Ptr& typeface_) noexcept SharedFontInternal (const Typeface::Ptr& typeface_) noexcept
: typefaceName (typeface_->getName()), : typefaceName (typeface_->getName()),
typefaceStyle (typeface_->getStyle()),
height (FontValues::defaultFontHeight), height (FontValues::defaultFontHeight),
horizontalScale (1.0f), horizontalScale (1.0f),
kerning (0), kerning (0),
ascent (0), ascent (0),
styleFlags (Font::plain),
underline (false),
typeface (typeface_) typeface (typeface_)
{ {
jassert (typefaceName.isNotEmpty());
} }
SharedFontInternal (const SharedFontInternal& other) noexcept SharedFontInternal (const SharedFontInternal& other) noexcept
: typefaceName (other.typefaceName), : typefaceName (other.typefaceName),
typefaceStyle (other.typefaceStyle),
height (other.height), height (other.height),
horizontalScale (other.horizontalScale), horizontalScale (other.horizontalScale),
kerning (other.kerning), kerning (other.kerning),
ascent (other.ascent), ascent (other.ascent),
styleFlags (other.styleFlags),
underline (other.underline),
typeface (other.typeface) typeface (other.typeface)
{ {
} }
@@ -200,31 +210,44 @@ public:
bool operator== (const SharedFontInternal& other) const noexcept bool operator== (const SharedFontInternal& other) const noexcept
{ {
return height == other.height return height == other.height
&& styleFlags == other.styleFlags
&& underline == other.underline
&& horizontalScale == other.horizontalScale && horizontalScale == other.horizontalScale
&& kerning == other.kerning && kerning == other.kerning
&& typefaceName == other.typefaceName;
&& typefaceName == other.typefaceName
&& typefaceStyle == other.typefaceStyle;
} }
String typefaceName;
String typefaceName, typefaceStyle;
float height, horizontalScale, kerning, ascent; float height, horizontalScale, kerning, ascent;
int styleFlags;
bool underline;
Typeface::Ptr typeface; Typeface::Ptr typeface;
}; };
//============================================================================== //==============================================================================
Font::Font() Font::Font()
: font (new SharedFontInternal (FontValues::defaultFontHeight, Font::plain))
: font (new SharedFontInternal (Font::getDefaultStyle(), FontValues::defaultFontHeight))
{ {
} }
Font::Font (const float fontHeight, const int styleFlags) Font::Font (const float fontHeight, const int styleFlags)
: font (new SharedFontInternal (FontValues::limitFontHeight (fontHeight), styleFlags))
: font (new SharedFontInternal (Font::getDefaultStyle(), FontValues::limitFontHeight (fontHeight)))
{ {
setStyleFlags(styleFlags);
} }
Font::Font (const String& typefaceName, const float fontHeight, const int styleFlags) Font::Font (const String& typefaceName, const float fontHeight, const int styleFlags)
: font (new SharedFontInternal (typefaceName, FontValues::limitFontHeight (fontHeight), styleFlags))
: font (new SharedFontInternal (typefaceName, Font::getDefaultStyle(), FontValues::limitFontHeight (fontHeight)))
{
setStyleFlags (styleFlags);
}
Font::Font (const String& typefaceStyle, float fontHeight)
: font (new SharedFontInternal (typefaceStyle, FontValues::limitFontHeight (fontHeight)))
{
}
Font::Font (const String& typefaceName, const String& typefaceStyle, float fontHeight)
: font (new SharedFontInternal (typefaceName, typefaceStyle, FontValues::limitFontHeight (fontHeight)))
{ {
} }
@@ -297,6 +320,12 @@ const String& Font::getDefaultMonospacedFontName()
return name; return name;
} }
const String& Font::getDefaultStyle()
{
static const String style ("<Regular>");
return style;
}
const String& Font::getTypefaceName() const noexcept const String& Font::getTypefaceName() const noexcept
{ {
return font->typefaceName; return font->typefaceName;
@@ -306,6 +335,8 @@ void Font::setTypefaceName (const String& faceName)
{ {
if (faceName != font->typefaceName) if (faceName != font->typefaceName)
{ {
jassert (faceName.isNotEmpty());
dupeInternalIfShared(); dupeInternalIfShared();
font->typefaceName = faceName; font->typefaceName = faceName;
font->typeface = nullptr; font->typeface = nullptr;
@@ -313,6 +344,22 @@ void Font::setTypefaceName (const String& faceName)
} }
} }
const String& Font::getTypefaceStyle() const noexcept
{
return font->typefaceStyle;
}
void Font::setTypefaceStyle (const String& typefaceStyle)
{
if (typefaceStyle != font->typefaceStyle)
{
dupeInternalIfShared();
font->typefaceStyle = typefaceStyle;
font->typeface = nullptr;
font->ascent = 0;
}
}
Typeface* Font::getTypeface() const Typeface* Font::getTypeface() const
{ {
if (font->typeface == nullptr) if (font->typeface == nullptr)
@@ -336,6 +383,20 @@ void Font::setFallbackFontName (const String& name)
#endif #endif
} }
const String& Font::getFallbackFontStyle()
{
return FontValues::fallbackFontStyle;
}
void Font::setFallbackFontStyle (const String& style)
{
FontValues::fallbackFontStyle = style;
#if JUCE_MAC || JUCE_IOS
jassertfalse; // Note that use of a fallback font isn't currently implemented in OSX..
#endif
}
//============================================================================== //==============================================================================
float Font::getHeight() const noexcept float Font::getHeight() const noexcept
{ {
@@ -374,7 +435,12 @@ void Font::setHeightWithoutChangingWidth (float newHeight)
int Font::getStyleFlags() const noexcept int Font::getStyleFlags() const noexcept
{ {
return font->styleFlags;
int styleFlags = font->underline ? underlined : plain;
if (isBold()) styleFlags |= bold;
if (isItalic()) styleFlags |= italic;
return styleFlags;
} }
Font Font::withStyle (const int newFlags) const Font Font::withStyle (const int newFlags) const
@@ -386,10 +452,12 @@ Font Font::withStyle (const int newFlags) const
void Font::setStyleFlags (const int newFlags) void Font::setStyleFlags (const int newFlags)
{ {
if (font->styleFlags != newFlags)
if (getStyleFlags() != newFlags)
{ {
dupeInternalIfShared(); dupeInternalIfShared();
font->styleFlags = newFlags;
font->typefaceStyle = FontStyleHelpers::getStyleName ((newFlags & bold) != 0,
(newFlags & italic) != 0);
font->underline = (newFlags & underlined) != 0;
font->typeface = nullptr; font->typeface = nullptr;
font->ascent = 0; font->ascent = 0;
} }
@@ -415,6 +483,26 @@ void Font::setSizeAndStyle (float newHeight,
setStyleFlags (newStyleFlags); setStyleFlags (newStyleFlags);
} }
void Font::setSizeAndStyle (float newHeight,
const String& newStyle,
const float newHorizontalScale,
const float newKerningAmount)
{
newHeight = FontValues::limitFontHeight (newHeight);
if (font->height != newHeight
|| font->horizontalScale != newHorizontalScale
|| font->kerning != newKerningAmount)
{
dupeInternalIfShared();
font->height = newHeight;
font->horizontalScale = newHorizontalScale;
font->kerning = newKerningAmount;
}
setTypefaceStyle (newStyle);
}
float Font::getHorizontalScale() const noexcept float Font::getHorizontalScale() const noexcept
{ {
return font->horizontalScale; return font->horizontalScale;
@@ -451,33 +539,41 @@ void Font::setExtraKerningFactor (const float extraKerning)
font->kerning = extraKerning; font->kerning = extraKerning;
} }
Font Font::boldened() const { return withStyle (font->styleFlags | bold); }
Font Font::italicised() const { return withStyle (font->styleFlags | italic); }
Font Font::boldened() const { return withStyle (getStyleFlags() | bold); }
Font Font::italicised() const { return withStyle (getStyleFlags() | italic); }
bool Font::isBold() const noexcept { return (font->styleFlags & bold) != 0; }
bool Font::isItalic() const noexcept { return (font->styleFlags & italic) != 0; }
bool Font::isBold() const noexcept
{
return FontStyleHelpers::isBold (font->typefaceStyle);
}
bool Font::isItalic() const noexcept
{
return FontStyleHelpers::isItalic (font->typefaceStyle);
}
void Font::setBold (const bool shouldBeBold) void Font::setBold (const bool shouldBeBold)
{ {
setStyleFlags (shouldBeBold ? (font->styleFlags | bold)
: (font->styleFlags & ~bold));
const int flags = getStyleFlags();
setStyleFlags (shouldBeBold ? (flags | bold)
: (flags & ~bold));
} }
void Font::setItalic (const bool shouldBeItalic) void Font::setItalic (const bool shouldBeItalic)
{ {
setStyleFlags (shouldBeItalic ? (font->styleFlags | italic)
: (font->styleFlags & ~italic));
const int flags = getStyleFlags();
setStyleFlags (shouldBeItalic ? (flags | italic)
: (flags & ~italic));
} }
void Font::setUnderline (const bool shouldBeUnderlined) void Font::setUnderline (const bool shouldBeUnderlined)
{ {
setStyleFlags (shouldBeUnderlined ? (font->styleFlags | underlined)
: (font->styleFlags & ~underlined));
font->underline = shouldBeUnderlined;
} }
bool Font::isUnderlined() const noexcept bool Font::isUnderlined() const noexcept
{ {
return (font->styleFlags & underlined) != 0;
return font->underline;
} }
float Font::getAscent() const float Font::getAscent() const
@@ -537,23 +633,30 @@ void Font::findFonts (Array<Font>& destArray)
const StringArray names (findAllTypefaceNames()); const StringArray names (findAllTypefaceNames());
for (int i = 0; i < names.size(); ++i) for (int i = 0; i < names.size(); ++i)
destArray.add (Font (names[i], FontValues::defaultFontHeight, Font::plain));
{
const StringArray styles (findAllTypefaceStyles (names[i]));
String style ("Regular");
if (! styles.contains (style, true))
style = styles[0];
destArray.add (Font (names[i], style, FontValues::defaultFontHeight));
}
} }
//============================================================================== //==============================================================================
String Font::toString() const String Font::toString() const
{ {
String s (getTypefaceName());
String s;
if (s == getDefaultSansSerifFontName())
s = String::empty;
else
s += "; ";
if (getTypefaceName() != getDefaultSansSerifFontName())
s << getTypefaceName() << "; ";
s += String (getHeight(), 1);
s << String (getHeight(), 1);
if (isBold()) s += " bold";
if (isItalic()) s += " italic";
if (getTypefaceStyle() != getDefaultStyle())
s << ' ' << getTypefaceStyle();
return s; return s;
} }
@@ -575,9 +678,7 @@ Font Font::fromString (const String& fontDescription)
if (height <= 0) if (height <= 0)
height = 10.0f; height = 10.0f;
int flags = Font::plain;
if (sizeAndStyle.containsIgnoreCase ("bold")) flags |= Font::bold;
if (sizeAndStyle.containsIgnoreCase ("italic")) flags |= Font::italic;
const String style (sizeAndStyle.fromFirstOccurrenceOf (" ", false, false));
return Font (name, height, flags);
return Font (name, style, height);
} }

+ 89
- 25
modules/juce_graphics/fonts/juce_Font.h View File

@@ -68,7 +68,7 @@ public:
/** Creates a font with a given typeface and parameters. /** Creates a font with a given typeface and parameters.
@param typefaceName the name of the typeface to use
@param typefaceName the font family of the typeface to use
@param fontHeight the height in pixels (can be fractional) @param fontHeight the height in pixels (can be fractional)
@param styleFlags the style to use - this can be a combination of the @param styleFlags the style to use - this can be a combination of the
Font::bold, Font::italic and Font::underlined, or Font::bold, Font::italic and Font::underlined, or
@@ -77,6 +77,21 @@ public:
*/ */
Font (const String& typefaceName, float fontHeight, int styleFlags); Font (const String& typefaceName, float fontHeight, int styleFlags);
/** Creates a sans-serif font in a given style and size.
@param typefaceStyle the font style of the typeface to use
@param fontHeight the height in pixels (can be fractional)
*/
Font (const String& typefaceStyle, float fontHeight);
/** Creates a font with a given typeface and parameters.
@param typefaceName the font family of the typeface to use
@param typefaceStyle the font style of the typeface to use
@param fontHeight the height in pixels (can be fractional)
*/
Font (const String& typefaceName, const String& typefaceStyle, float fontHeight);
/** Creates a copy of another Font object. */ /** Creates a copy of another Font object. */
Font (const Font& other) noexcept; Font (const Font& other) noexcept;
@@ -106,64 +121,88 @@ public:
~Font() noexcept; ~Font() noexcept;
//============================================================================== //==============================================================================
/** Changes the name of the typeface family.
/** Changes the font family of the typeface.
e.g. "Arial", "Courier", etc. e.g. "Arial", "Courier", etc.
This may also be set to Font::getDefaultSansSerifFontName(), Font::getDefaultSerifFontName(), This may also be set to Font::getDefaultSansSerifFontName(), Font::getDefaultSerifFontName(),
or Font::getDefaultMonospacedFontName(), which are not actual platform-specific font names,
but are generic names that are used to represent the various default fonts.
If you need to know the exact typeface name being used, you can call
Font::getTypeface()->getTypefaceName(), which will give you the platform-specific name.
or Font::getDefaultMonospacedFontName(), which are not actual platform-specific font family names,
but are generic font family names that are used to represent the various default fonts.
If you need to know the exact typeface font family being used, you can call
Font::getTypeface()->getFamily(), which will give you the platform-specific font family.
If a suitable font isn't found on the machine, it'll just use a default instead. If a suitable font isn't found on the machine, it'll just use a default instead.
*/ */
void setTypefaceName (const String& faceName); void setTypefaceName (const String& faceName);
/** Returns the name of the typeface family that this font uses.
/** Returns the font family of the typeface that this font uses.
e.g. "Arial", "Courier", etc. e.g. "Arial", "Courier", etc.
This may also be set to Font::getDefaultSansSerifFontName(), Font::getDefaultSerifFontName(), This may also be set to Font::getDefaultSansSerifFontName(), Font::getDefaultSerifFontName(),
or Font::getDefaultMonospacedFontName(), which are not actual platform-specific font names,
but are generic names that are used to represent the various default fonts.
or Font::getDefaultMonospacedFontName(), which are not actual platform-specific font family names,
but are generic font familiy names that are used to represent the various default fonts.
If you need to know the exact typeface name being used, you can call
Font::getTypeface()->getTypefaceName(), which will give you the platform-specific name.
If you need to know the exact typeface font family being used, you can call
Font::getTypeface()->getFamily(), which will give you the platform-specific font family.
*/ */
const String& getTypefaceName() const noexcept; const String& getTypefaceName() const noexcept;
//============================================================================== //==============================================================================
/** Returns a typeface name that represents the default sans-serif font.
/** Changes the font style of the typeface
e.g. "Regular", "Italic", etc.
*/
void setTypefaceStyle (const String& typefaceStyle);
/** Returns the font style of the typeface that this font uses.
e.g. "Regular", "Italic", etc.
*/
const String& getTypefaceStyle() const noexcept;
//==============================================================================
/** Returns a typeface font family that represents the default sans-serif font.
This is also the typeface that will be used when a font is created without This is also the typeface that will be used when a font is created without
specifying any typeface details. specifying any typeface details.
Note that this method just returns a generic placeholder string that means "the default Note that this method just returns a generic placeholder string that means "the default
sans-serif font" - it's not the actual name of this font.
sans-serif font" - it's not the actual font family of this font.
@see setTypefaceName, getDefaultSerifFontName, getDefaultMonospacedFontName @see setTypefaceName, getDefaultSerifFontName, getDefaultMonospacedFontName
*/ */
static const String& getDefaultSansSerifFontName(); static const String& getDefaultSansSerifFontName();
/** Returns a typeface name that represents the default sans-serif font.
/** Returns a typeface font family that represents the default sans-serif font.
Note that this method just returns a generic placeholder string that means "the default Note that this method just returns a generic placeholder string that means "the default
serif font" - it's not the actual name of this font.
serif font" - it's not the actual font family of this font.
@see setTypefaceName, getDefaultSansSerifFontName, getDefaultMonospacedFontName @see setTypefaceName, getDefaultSansSerifFontName, getDefaultMonospacedFontName
*/ */
static const String& getDefaultSerifFontName(); static const String& getDefaultSerifFontName();
/** Returns a typeface name that represents the default sans-serif font.
/** Returns a typeface font family that represents the default sans-serif font.
Note that this method just returns a generic placeholder string that means "the default Note that this method just returns a generic placeholder string that means "the default
monospaced font" - it's not the actual name of this font.
monospaced font" - it's not the actual font family of this font.
@see setTypefaceName, getDefaultSansSerifFontName, getDefaultSerifFontName @see setTypefaceName, getDefaultSansSerifFontName, getDefaultSerifFontName
*/ */
static const String& getDefaultMonospacedFontName(); static const String& getDefaultMonospacedFontName();
/** Returns a typeface font style that represents the default sans-serif font.
Note that this method just returns a generic placeholder string that means "the default
font style" - it's not the actual font style of this font.
@see setTypefaceStyle
*/
static const String& getDefaultStyle();
/** Returns the default system typeface for the given font. */ /** Returns the default system typeface for the given font. */
static Typeface::Ptr getDefaultTypefaceForFont (const Font& font); static Typeface::Ptr getDefaultTypefaceForFont (const Font& font);
@@ -299,6 +338,12 @@ public:
float newHorizontalScale, float newHorizontalScale,
float newKerningAmount); float newKerningAmount);
/** Changes all the font's characteristics with one call. */
void setSizeAndStyle (float newHeight,
const String& newStyle,
float newHorizontalScale,
float newKerningAmount);
//============================================================================== //==============================================================================
/** Returns the total width of a string as it would be drawn using this font. /** Returns the total width of a string as it would be drawn using this font.
@@ -329,33 +374,52 @@ public:
/** Creates an array of Font objects to represent all the fonts on the system. /** Creates an array of Font objects to represent all the fonts on the system.
If you just need the names of the typefaces, you can also use
If you just need the font family names of the typefaces, you can also use
findAllTypefaceNames() instead. findAllTypefaceNames() instead.
@param results the array to which new Font objects will be added. @param results the array to which new Font objects will be added.
*/ */
static void findFonts (Array<Font>& results); static void findFonts (Array<Font>& results);
/** Returns a list of all the available typeface names.
/** Returns a list of all the available typeface font families.
The names returned can be passed into setTypefaceName(). The names returned can be passed into setTypefaceName().
You can use this instead of findFonts() if you only need their names, and not
font objects.
You can use this instead of findFonts() if you only need their font family names,
and not font objects.
*/ */
static StringArray findAllTypefaceNames(); static StringArray findAllTypefaceNames();
/** Returns a list of all the available typeface font styles.
The names returned can be passed into setTypefaceStyle().
You can use this instead of findFonts() if you only need their styles, and not
font objects.
*/
static StringArray findAllTypefaceStyles (const String& family);
//============================================================================== //==============================================================================
/** Returns the name of the typeface to be used for rendering glyphs that aren't found
in the requested typeface.
/** Returns the font family of the typeface to be used for rendering glyphs that aren't
found in the requested typeface.
*/ */
static const String& getFallbackFontName(); static const String& getFallbackFontName();
/** Sets the (platform-specific) name of the typeface to use to find glyphs that aren't
available in whatever font you're trying to use.
/** Sets the (platform-specific) font family of the typeface to use to find glyphs that
aren't available in whatever font you're trying to use.
*/ */
static void setFallbackFontName (const String& name); static void setFallbackFontName (const String& name);
/** Returns the font style of the typeface to be used for rendering glyphs that aren't
found in the requested typeface.
*/
static const String& getFallbackFontStyle();
/** Sets the (platform-specific) font style of the typeface to use to find glyphs that
aren't available in whatever font you're trying to use.
*/
static void setFallbackFontStyle (const String& style);
//============================================================================== //==============================================================================
/** Creates a string to describe this font. /** Creates a string to describe this font.
The string will contain information to describe the font's typeface, size, and The string will contain information to describe the font's typeface, size, and


+ 40
- 3
modules/juce_graphics/fonts/juce_Typeface.cpp View File

@@ -23,8 +23,45 @@
============================================================================== ==============================================================================
*/ */
Typeface::Typeface (const String& name_) noexcept
: name (name_)
namespace FontStyleHelpers
{
static const char* getStyleName (const bool bold,
const bool italic) noexcept
{
if (bold && ! italic) return "Bold";
if (italic && ! bold) return "Italic";
if (bold && italic) return "Bold Italic";
return "Regular";
}
static bool isBold (const String& style) noexcept
{
return style.containsWholeWordIgnoreCase ("Bold");
}
static bool isItalic (const String& style) noexcept
{
return style.containsWholeWordIgnoreCase ("Italic")
|| style.containsWholeWordIgnoreCase ("Oblique");
}
static bool isPlaceholderFamilyName (const String& family)
{
return family == Font::getDefaultSansSerifFontName()
|| family == Font::getDefaultSerifFontName()
|| family == Font::getDefaultMonospacedFontName();
}
static String getConcreteFamilyNameFromPlaceholder (const String& family)
{
const Font f (family, Font::getDefaultStyle(), 15.0f);
return Font::getDefaultTypefaceForFont (f)->getName();
}
}
//==============================================================================
Typeface::Typeface (const String& name_, const String& style_) noexcept
: name (name_), style (style_)
{ {
} }
@@ -34,7 +71,7 @@ Typeface::~Typeface()
Typeface::Ptr Typeface::getFallbackTypeface() Typeface::Ptr Typeface::getFallbackTypeface()
{ {
const Font fallbackFont (Font::getFallbackFontName(), 10, 0);
const Font fallbackFont (Font::getFallbackFontName(), Font::getFallbackFontStyle(), 10.0f);
return fallbackFont.getTypeface(); return fallbackFont.getTypeface();
} }


+ 9
- 3
modules/juce_graphics/fonts/juce_Typeface.h View File

@@ -55,11 +55,17 @@ public:
typedef ReferenceCountedObjectPtr <Typeface> Ptr; typedef ReferenceCountedObjectPtr <Typeface> Ptr;
//============================================================================== //==============================================================================
/** Returns the name of the typeface.
/** Returns the font family of the typeface.
@see Font::getTypefaceName @see Font::getTypefaceName
*/ */
const String& getName() const noexcept { return name; } const String& getName() const noexcept { return name; }
//==============================================================================
/** Returns the font style of the typeface.
@see Font::getTypefaceStyle
*/
const String& getStyle() const noexcept { return style; }
//============================================================================== //==============================================================================
/** Creates a new system typeface. */ /** Creates a new system typeface. */
static Ptr createSystemTypefaceFor (const Font& font); static Ptr createSystemTypefaceFor (const Font& font);
@@ -122,9 +128,9 @@ public:
protected: protected:
//============================================================================== //==============================================================================
String name;
String name, style;
explicit Typeface (const String& name) noexcept;
Typeface (const String& name, const String& style) noexcept;
static Ptr getFallbackTypeface(); static Ptr getFallbackTypeface();


+ 1
- 4
modules/juce_graphics/juce_graphics.cpp View File

@@ -67,8 +67,6 @@
namespace juce namespace juce
{ {
// START_AUTOINCLUDE colour/*.cpp, geometry/*.cpp, placement/*.cpp, contexts/*.cpp, images/*.cpp,
// image_formats/*.cpp, fonts/*.cpp, effects/*.cpp
#include "colour/juce_Colour.cpp" #include "colour/juce_Colour.cpp"
#include "colour/juce_ColourGradient.cpp" #include "colour/juce_ColourGradient.cpp"
#include "colour/juce_Colours.cpp" #include "colour/juce_Colours.cpp"
@@ -92,14 +90,13 @@ namespace juce
#include "image_formats/juce_JPEGLoader.cpp" #include "image_formats/juce_JPEGLoader.cpp"
#include "image_formats/juce_PNGLoader.cpp" #include "image_formats/juce_PNGLoader.cpp"
#include "fonts/juce_AttributedString.cpp" #include "fonts/juce_AttributedString.cpp"
#include "fonts/juce_Typeface.cpp"
#include "fonts/juce_CustomTypeface.cpp" #include "fonts/juce_CustomTypeface.cpp"
#include "fonts/juce_Font.cpp" #include "fonts/juce_Font.cpp"
#include "fonts/juce_GlyphArrangement.cpp" #include "fonts/juce_GlyphArrangement.cpp"
#include "fonts/juce_TextLayout.cpp" #include "fonts/juce_TextLayout.cpp"
#include "fonts/juce_Typeface.cpp"
#include "effects/juce_DropShadowEffect.cpp" #include "effects/juce_DropShadowEffect.cpp"
#include "effects/juce_GlowEffect.cpp" #include "effects/juce_GlowEffect.cpp"
// END_AUTOINCLUDE
//============================================================================== //==============================================================================
#if JUCE_MAC || JUCE_IOS #if JUCE_MAC || JUCE_IOS


+ 61
- 8
modules/juce_graphics/native/juce_android_Fonts.cpp View File

@@ -41,7 +41,22 @@ StringArray Font::findAllTypefaceNames()
File ("/system/fonts").findChildFiles (fonts, File::findFiles, false, "*.ttf"); File ("/system/fonts").findChildFiles (fonts, File::findFiles, false, "*.ttf");
for (int i = 0; i < fonts.size(); ++i) for (int i = 0; i < fonts.size(); ++i)
results.add (fonts.getReference(i).getFileNameWithoutExtension());
results.addIfNotAlreadyThere (fonts.getReference(i).getFileNameWithoutExtension()
.upToLastOccurrenceOf ("-", false, false));
return results;
}
StringArray Font::findAllTypefaceStyles (const String& family)
{
StringArray results ("Regular");
Array<File> fonts;
File ("/system/fonts").findChildFiles (fonts, File::findFiles, false, family + "-*.ttf");
for (int i = 0; i < fonts.size(); ++i)
results.addIfNotAlreadyThere (fonts.getReference(i).getFileNameWithoutExtension()
.fromLastOccurrenceOf ("-", false, false));
return results; return results;
} }
@@ -79,24 +94,27 @@ class AndroidTypeface : public Typeface
{ {
public: public:
AndroidTypeface (const Font& font) AndroidTypeface (const Font& font)
: Typeface (font.getTypefaceName()),
: Typeface (font.getTypefaceName(), font.getTypefaceStyle()),
ascent (0), ascent (0),
descent (0) descent (0)
{ {
jint flags = 0;
if (font.isBold()) flags = 1;
if (font.isItalic()) flags += 2;
JNIEnv* const env = getEnv();
JNIEnv* env = getEnv();
const bool isBold = style.contains ("Bold");
const bool isItalic = style.contains ("Italic");
File fontFile (getFontFile (name, style));
File fontFile (File ("/system/fonts").getChildFile (name).withFileExtension (".ttf"));
if (! fontFile.exists())
fontFile = findFontFile (name, isBold, isItalic);
if (fontFile.exists()) if (fontFile.exists())
typeface = GlobalRef (env->CallStaticObjectMethod (TypefaceClass, TypefaceClass.createFromFile, typeface = GlobalRef (env->CallStaticObjectMethod (TypefaceClass, TypefaceClass.createFromFile,
javaString (fontFile.getFullPathName()).get())); javaString (fontFile.getFullPathName()).get()));
else else
typeface = GlobalRef (env->CallStaticObjectMethod (TypefaceClass, TypefaceClass.create, typeface = GlobalRef (env->CallStaticObjectMethod (TypefaceClass, TypefaceClass.create,
javaString (getName()).get(), flags));
javaString (getName()).get(),
(isBold ? 1 : 0) + (isItalic ? 2 : 0)));
rect = GlobalRef (env->NewObject (RectClass, RectClass.constructor, 0, 0, 0, 0)); rect = GlobalRef (env->NewObject (RectClass, RectClass.constructor, 0, 0, 0, 0));
@@ -212,6 +230,41 @@ public:
float ascent, descent, unitsToHeightScaleFactor; float ascent, descent, unitsToHeightScaleFactor;
private: private:
static File findFontFile (const String& family,
const bool bold, const bool italic)
{
File file;
if (bold || italic)
{
String suffix;
if (bold) suffix = "Bold";
if (italic) suffix << "Italic";
file = getFontFile (family, suffix);
if (file.exists())
return file;
}
file = getFontFile (family, "Regular");
if (! file.exists())
file = getFontFile (family, String::empty);
return file;
}
static File getFontFile (const String& family, const String& style)
{
String path ("/system/fonts/" + family);
if (style.isNotEmpty())
path << '-' << style;
return File (path + ".ttf");
}
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AndroidTypeface); JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AndroidTypeface);
}; };


+ 32
- 13
modules/juce_graphics/native/juce_linux_Fonts.cpp View File

@@ -222,10 +222,29 @@ public:
} }
//============================================================================== //==============================================================================
void getFamilyNames (StringArray& familyNames) const
StringArray findAllFamilyNames() const
{ {
StringArray s;
for (int i = 0; i < faces.size(); i++) for (int i = 0; i < faces.size(); i++)
familyNames.addIfNotAlreadyThere (faces.getUnchecked(i)->family);
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 (FontStyleHelpers::getStyleName (face->isBold, face->isItalic));
}
return s;
} }
void getMonospacedNames (StringArray& monoSpaced) const void getMonospacedNames (StringArray& monoSpaced) const
@@ -298,14 +317,13 @@ public:
if (faceWrapper != nullptr) if (faceWrapper != nullptr)
{ {
setCharacteristics (font.getTypefaceName(), setCharacteristics (font.getTypefaceName(),
font.getTypefaceStyle(),
faceWrapper->face->ascender / (float) (faceWrapper->face->ascender - faceWrapper->face->descender), faceWrapper->face->ascender / (float) (faceWrapper->face->ascender - faceWrapper->face->descender),
font.isBold(), font.isItalic(),
L' '); L' ');
} }
else else
{ {
DBG ("Failed to create typeface: " << font.getTypefaceName() << " "
<< (font.isBold() ? 'B' : ' ') << (font.isItalic() ? 'I' : ' '));
DBG ("Failed to create typeface: " << font.toString());
} }
} }
@@ -457,10 +475,12 @@ Typeface::Ptr Typeface::createSystemTypefaceFor (const Font& font)
StringArray Font::findAllTypefaceNames() StringArray Font::findAllTypefaceNames()
{ {
StringArray s;
FTTypefaceList::getInstance()->getFamilyNames (s);
s.sort (true);
return s;
return FTTypefaceList::getInstance()->findAllFamilyNames();
}
StringArray Font::findAllTypefaceStyles (const String& family)
{
return FTTypefaceList::getInstance()->findAllTypefaceStyles (family);
} }
//============================================================================== //==============================================================================
@@ -480,17 +500,16 @@ private:
{ {
const StringArray choices (choicesArray); const StringArray choices (choicesArray);
int j;
for (j = 0; j < choices.size(); ++j)
for (int j = 0; j < choices.size(); ++j)
if (names.contains (choices[j], true)) if (names.contains (choices[j], true))
return choices[j]; return choices[j];
for (j = 0; j < choices.size(); ++j)
for (int j = 0; j < choices.size(); ++j)
for (int i = 0; i < names.size(); ++i) for (int i = 0; i < names.size(); ++i)
if (names[i].startsWithIgnoreCase (choices[j])) if (names[i].startsWithIgnoreCase (choices[j]))
return names[i]; return names[i];
for (j = 0; j < choices.size(); ++j)
for (int j = 0; j < choices.size(); ++j)
for (int i = 0; i < names.size(); ++i) for (int i = 0; i < names.size(); ++i)
if (names[i].containsIgnoreCase (choices[j])) if (names[i].containsIgnoreCase (choices[j]))
return names[i]; return names[i];


+ 187
- 135
modules/juce_graphics/native/juce_mac_Fonts.mm View File

@@ -34,52 +34,37 @@
namespace CoreTextTypeLayout namespace CoreTextTypeLayout
{ {
static CTFontRef createCTFont (const Font& font, const float fontSize, static CTFontRef createCTFont (const Font& font, const float fontSize,
const bool applyScaleFactor, bool& needsItalicTransform)
const bool applyScaleFactor)
{ {
CFStringRef cfName = font.getTypefaceName().toCFString();
CTFontRef ctFontRef = CTFontCreateWithName (cfName, fontSize, nullptr);
CFRelease (cfName);
if (ctFontRef != nullptr)
CFStringRef cfFontFamily = font.getTypefaceName().toCFString();
CFStringRef cfFontStyle = font.getTypefaceStyle().toCFString();
CFStringRef keys[] = { kCTFontFamilyNameAttribute, kCTFontStyleNameAttribute };
CFTypeRef values[] = { cfFontFamily, cfFontStyle };
CFDictionaryRef fontDescAttributes = CFDictionaryCreate (nullptr, (const void**) &keys,
(const void**) &values,
numElementsInArray (keys),
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
CFRelease (cfFontStyle);
CFRelease (cfFontFamily);
CTFontDescriptorRef ctFontDescRef = CTFontDescriptorCreateWithAttributes (fontDescAttributes);
CFRelease (fontDescAttributes);
CTFontRef ctFontRef = CTFontCreateWithFontDescriptor (ctFontDescRef, fontSize, nullptr);
CFRelease (ctFontDescRef);
if (applyScaleFactor)
{ {
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;
}
}
CGFontRef cgFontRef = CTFontCopyGraphicsFont (ctFontRef, nullptr);
const int totalHeight = std::abs (CGFontGetAscent (cgFontRef)) + std::abs (CGFontGetDescent (cgFontRef));
const float factor = CGFontGetUnitsPerEm (cgFontRef) / (float) totalHeight;
CGFontRelease (cgFontRef);
if (applyScaleFactor)
{
CGFontRef cgFontRef = CTFontCopyGraphicsFont (ctFontRef, nullptr);
const int totalHeight = std::abs (CGFontGetAscent (cgFontRef)) + std::abs (CGFontGetDescent (cgFontRef));
const float factor = CGFontGetUnitsPerEm (cgFontRef) / (float) totalHeight;
CGFontRelease (cgFontRef);
CTFontRef newFont = CTFontCreateCopyWithAttributes (ctFontRef, fontSize * factor, nullptr, nullptr);
CFRelease (ctFontRef);
ctFontRef = newFont;
}
CTFontRef newFont = CTFontCreateCopyWithAttributes (ctFontRef, fontSize * factor, nullptr, nullptr);
CFRelease (ctFontRef);
ctFontRef = newFont;
} }
return ctFontRef; return ctFontRef;
@@ -164,8 +149,7 @@ namespace CoreTextTypeLayout
if (attr->getFont() != nullptr) if (attr->getFont() != nullptr)
{ {
const Font& f = *attr->getFont(); const Font& f = *attr->getFont();
bool needsItalicTransform = false;
CTFontRef ctFontRef = createCTFont (f, f.getHeight(), true, needsItalicTransform);
CTFontRef ctFontRef = createCTFont (f, f.getHeight(), true);
CFAttributedStringSetAttribute (attribString, CFRangeMake (range.getStart(), range.getLength()), CFAttributedStringSetAttribute (attribString, CFRangeMake (range.getStart(), range.getLength()),
kCTFontAttributeName, ctFontRef); kCTFontAttributeName, ctFontRef);
@@ -317,17 +301,24 @@ namespace CoreTextTypeLayout
CTFontRef ctRunFont; CTFontRef ctRunFont;
if (CFDictionaryGetValueIfPresent (runAttributes, kCTFontAttributeName, (const void **) &ctRunFont)) if (CFDictionaryGetValueIfPresent (runAttributes, kCTFontAttributeName, (const void **) &ctRunFont))
{ {
CFStringRef cfsFontName = CTFontCopyPostScriptName (ctRunFont);
CTFontRef ctFontRef = CTFontCreateWithName (cfsFontName, 1024, nullptr);
CTFontDescriptorRef ctFontDescRef = CTFontCopyFontDescriptor (ctRunFont);
CFDictionaryRef fontDescAttributes = CTFontDescriptorCopyAttributes (ctFontDescRef);
CTFontRef ctFontRef = CTFontCreateWithFontDescriptor (ctFontDescRef, 1024, nullptr);
CFRelease (ctFontDescRef);
CGFontRef cgFontRef = CTFontCopyGraphicsFont (ctFontRef, nullptr); CGFontRef cgFontRef = CTFontCopyGraphicsFont (ctFontRef, nullptr);
CFRelease (ctFontRef); CFRelease (ctFontRef);
const int totalHeight = std::abs (CGFontGetAscent (cgFontRef)) + std::abs (CGFontGetDescent (cgFontRef)); const int totalHeight = std::abs (CGFontGetAscent (cgFontRef)) + std::abs (CGFontGetDescent (cgFontRef));
const float fontHeightToCGSizeFactor = CGFontGetUnitsPerEm (cgFontRef) / (float) totalHeight; const float fontHeightToCGSizeFactor = CGFontGetUnitsPerEm (cgFontRef) / (float) totalHeight;
CGFontRelease (cgFontRef); CGFontRelease (cgFontRef);
glyphRun->font = Font (String::fromCFString (cfsFontName),
CTFontGetSize (ctRunFont) / fontHeightToCGSizeFactor, 0); // XXX bold/italic flags?
CFRelease (cfsFontName);
CFStringRef cfsFontFamily = (CFStringRef) CFDictionaryGetValue (fontDescAttributes, kCTFontFamilyNameAttribute);
CFStringRef cfsFontStyle = (CFStringRef) CFDictionaryGetValue (fontDescAttributes, kCTFontStyleNameAttribute);
glyphRun->font = Font (String::fromCFString (cfsFontFamily),
String::fromCFString (cfsFontStyle),
CTFontGetSize (ctRunFont) / fontHeightToCGSizeFactor);
CFRelease (fontDescAttributes);
} }
CGColorRef cgRunColor; CGColorRef cgRunColor;
@@ -360,7 +351,8 @@ class OSXTypeface : public Typeface
{ {
public: public:
OSXTypeface (const Font& font) OSXTypeface (const Font& font)
: Typeface (font.getTypefaceName()),
: Typeface (font.getTypefaceName(),
font.getTypefaceStyle()),
fontRef (nullptr), fontRef (nullptr),
fontHeightToCGSizeFactor (1.0f), fontHeightToCGSizeFactor (1.0f),
renderingTransform (CGAffineTransformIdentity), renderingTransform (CGAffineTransformIdentity),
@@ -369,8 +361,7 @@ public:
ascent (0.0f), ascent (0.0f),
unitsToHeightScaleFactor (0.0f) unitsToHeightScaleFactor (0.0f)
{ {
bool needsItalicTransform = false;
ctFontRef = CoreTextTypeLayout::createCTFont (font, 1024.0f, false, needsItalicTransform);
ctFontRef = CoreTextTypeLayout::createCTFont (font, 1024.0f, false);
if (ctFontRef != nullptr) if (ctFontRef != nullptr)
{ {
@@ -380,12 +371,6 @@ public:
pathTransform = AffineTransform::identity.scale (1.0f / totalSize, 1.0f / 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); fontRef = CTFontCopyGraphicsFont (ctFontRef, nullptr);
const int totalHeight = abs (CGFontGetAscent (fontRef)) + abs (CGFontGetDescent (fontRef)); const int totalHeight = abs (CGFontGetAscent (fontRef)) + abs (CGFontGetDescent (fontRef));
@@ -550,6 +535,87 @@ private:
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OSXTypeface); JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OSXTypeface);
}; };
StringArray Font::findAllTypefaceNames()
{
StringArray names;
#if MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_5 && ! JUCE_IOS
// CTFontManager only exists on OS X 10.6 and later, it does not exist on iOS
CFArrayRef fontFamilyArray = CTFontManagerCopyAvailableFontFamilyNames();
for (CFIndex i = 0; i < CFArrayGetCount (fontFamilyArray); ++i)
{
const String family (String::fromCFString ((CFStringRef) CFArrayGetValueAtIndex (fontFamilyArray, i)));
if (! family.startsWithChar ('.')) // ignore fonts that start with a '.'
names.addIfNotAlreadyThere (family);
}
CFRelease (fontFamilyArray);
#else
CTFontCollectionRef fontCollectionRef = CTFontCollectionCreateFromAvailableFonts (nullptr);
CFArrayRef fontDescriptorArray = CTFontCollectionCreateMatchingFontDescriptors (fontCollectionRef);
CFRelease (fontCollectionRef);
for (CFIndex i = 0; i < CFArrayGetCount (fontDescriptorArray); ++i)
{
CTFontDescriptorRef ctFontDescriptorRef = (CTFontDescriptorRef) CFArrayGetValueAtIndex (fontDescriptorArray, i);
CFStringRef cfsFontFamily = (CFStringRef) CTFontDescriptorCopyAttribute (ctFontDescriptorRef, kCTFontFamilyNameAttribute);
names.addIfNotAlreadyThere (String::fromCFString (cfsFontFamily));
CFRelease (cfsFontFamily);
}
CFRelease (fontDescriptorArray);
#endif
names.sort (true);
return names;
}
StringArray Font::findAllTypefaceStyles (const String& family)
{
if (FontStyleHelpers::isPlaceholderFamilyName (family))
return findAllTypefaceStyles (FontStyleHelpers::getConcreteFamilyNameFromPlaceholder (family));
StringArray results;
CFStringRef cfsFontFamily = family.toCFString();
CFStringRef keys[] = { kCTFontFamilyNameAttribute };
CFTypeRef values[] = { cfsFontFamily };
CFDictionaryRef fontDescAttributes = CFDictionaryCreate (nullptr, (const void**) &keys, (const void**) &values, numElementsInArray (keys), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
CFRelease (cfsFontFamily);
CTFontDescriptorRef ctFontDescRef = CTFontDescriptorCreateWithAttributes (fontDescAttributes);
CFRelease (fontDescAttributes);
CFArrayRef fontFamilyArray = CFArrayCreate(kCFAllocatorDefault, (const void**) &ctFontDescRef, 1, &kCFTypeArrayCallBacks);
CFRelease (ctFontDescRef);
CTFontCollectionRef fontCollectionRef = CTFontCollectionCreateWithFontDescriptors (fontFamilyArray, nullptr);
CFRelease (fontFamilyArray);
CFArrayRef fontDescriptorArray = CTFontCollectionCreateMatchingFontDescriptors (fontCollectionRef);
CFRelease (fontCollectionRef);
if (fontDescriptorArray != nullptr)
{
for (CFIndex i = 0; i < CFArrayGetCount (fontDescriptorArray); ++i)
{
CTFontDescriptorRef ctFontDescriptorRef = (CTFontDescriptorRef) CFArrayGetValueAtIndex (fontDescriptorArray, i);
CFStringRef cfsFontStyle = (CFStringRef) CTFontDescriptorCopyAttribute (ctFontDescriptorRef, kCTFontStyleNameAttribute);
results.add (String::fromCFString (cfsFontStyle));
CFRelease (cfsFontStyle);
}
CFRelease (fontDescriptorArray);
}
return results;
}
#else #else
//============================================================================== //==============================================================================
@@ -580,49 +646,13 @@ class OSXTypeface : public Typeface
{ {
public: public:
OSXTypeface (const Font& font) OSXTypeface (const Font& font)
: Typeface (font.getTypefaceName())
: Typeface (font.getTypefaceName(), font.getTypefaceStyle())
{ {
JUCE_AUTORELEASEPOOL JUCE_AUTORELEASEPOOL
renderingTransform = CGAffineTransformIdentity; renderingTransform = CGAffineTransformIdentity;
bool needsItalicTransform = false;
#if JUCE_IOS #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;
}
NSString* fontName = juceStringToNS (style);
fontRef = CGFontCreateWithFontName ((CFStringRef) fontName); fontRef = CGFontCreateWithFontName ((CFStringRef) fontName);
if (fontRef == 0) if (fontRef == 0)
@@ -638,21 +668,12 @@ public:
unitsToHeightScaleFactor = 1.0f / totalHeight; unitsToHeightScaleFactor = 1.0f / totalHeight;
fontHeightToCGSizeFactor = CGFontGetUnitsPerEm (fontRef) / totalHeight; fontHeightToCGSizeFactor = CGFontGetUnitsPerEm (fontRef) / totalHeight;
#else #else
nsFont = [NSFont fontWithName: juceStringToNS (font.getTypefaceName()) size: 1024];
NSDictionary* nsDict = [NSDictionary dictionaryWithObjectsAndKeys:
juceStringToNS (name), NSFontFamilyAttribute,
juceStringToNS (style), NSFontFaceAttribute, nil];
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];
NSFontDescriptor* nsFontDesc = [NSFontDescriptor fontDescriptorWithFontAttributes: nsDict];
nsFont = [NSFont fontWithDescriptor: nsFontDesc size: 1024];
[nsFont retain]; [nsFont retain];
@@ -662,12 +683,6 @@ public:
pathTransform = AffineTransform::identity.scale (1.0f / totalSize, 1.0f / 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 #if SUPPORT_ONLY_10_4_FONTS
ATSFontRef atsFont = ATSFontFindFromName ((CFStringRef) [nsFont fontName], kATSOptionFlagsDefault); ATSFontRef atsFont = ATSFontFindFromName ((CFStringRef) [nsFont fontName], kATSOptionFlagsDefault);
@@ -910,7 +925,7 @@ private:
#endif #endif
} }
#if ! SUPPORT_ONLY_10_4_FONTS
#if ! SUPPORT_ONLY_10_4_FONTS
// Reads a CGFontRef's character map table to convert unicode into glyph numbers // Reads a CGFontRef's character map table to convert unicode into glyph numbers
class CharToGlyphMapper class CharToGlyphMapper
{ {
@@ -1009,23 +1024,14 @@ private:
}; };
ScopedPointer <CharToGlyphMapper> charToGlyphMapper; ScopedPointer <CharToGlyphMapper> charToGlyphMapper;
#endif
#endif
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OSXTypeface); JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OSXTypeface);
}; };
#endif
//==============================================================================
Typeface::Ptr Typeface::createSystemTypefaceFor (const Font& font)
{
return new OSXTypeface (font);
}
StringArray Font::findAllTypefaceNames() StringArray Font::findAllTypefaceNames()
{ {
StringArray names; StringArray names;
JUCE_AUTORELEASEPOOL JUCE_AUTORELEASEPOOL
#if JUCE_IOS #if JUCE_IOS
@@ -1041,6 +1047,43 @@ StringArray Font::findAllTypefaceNames()
return names; return names;
} }
StringArray Font::findAllTypefaceStyles (const String& family)
{
if (FontStyleHelpers::isPlaceholderFamilyName (family))
return findAllTypefaceStyles (FontStyleHelpers::getConcreteFamilyNameFromPlaceholder (family));
StringArray results;
JUCE_AUTORELEASEPOOL
#if JUCE_IOS
NSArray* styles = [UIFont fontNamesForFamilyName: juceStringToNS (family)];
#else
NSArray* styles = [[NSFontManager sharedFontManager] availableMembersOfFontFamily: juceStringToNS (family)];
#endif
for (unsigned int i = 0; i < [styles count]; ++i)
{
#if JUCE_IOS
// Fonts are returned in the form of "Arial-BoldMT"
results.add (nsStringToJuce ((NSString*) [styles objectAtIndex: i]));
#else
NSArray* style = [styles objectAtIndex: i];
results.add (nsStringToJuce ((NSString*) [style objectAtIndex: 1]));
#endif
}
return results;
}
#endif
//==============================================================================
Typeface::Ptr Typeface::createSystemTypefaceFor (const Font& font)
{
return new OSXTypeface (font);
}
struct DefaultFontNames struct DefaultFontNames
{ {
DefaultFontNames() DefaultFontNames()
@@ -1064,15 +1107,24 @@ Typeface::Ptr Font::getDefaultTypefaceForFont (const Font& font)
{ {
static DefaultFontNames defaultNames; static DefaultFontNames defaultNames;
String faceName (font.getTypefaceName());
Font newFont (font);
const 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;
if (faceName == getDefaultSansSerifFontName()) newFont.setTypefaceName (defaultNames.defaultSans);
else if (faceName == getDefaultSerifFontName()) newFont.setTypefaceName (defaultNames.defaultSerif);
else if (faceName == getDefaultMonospacedFontName()) newFont.setTypefaceName (defaultNames.defaultFixed);
if (font.getTypefaceStyle() == getDefaultStyle())
newFont.setTypefaceStyle ("Regular");
#if JUCE_IOS && ! JUCE_CORETEXT_AVAILABLE
// Fonts style names on Cocoa Touch are unusual like "Arial-BoldMT"
// No font will be found for the style of "Regular" so we must modify the style
if (newFont.getTypefaceStyle() == "Regular")
newFont.setTypefaceStyle (faceName);
#endif
Font f (font);
f.setTypefaceName (faceName);
return Typeface::createSystemTypefaceFor (f);
return Typeface::createSystemTypefaceFor (newFont);
} }
bool TextLayout::createNativeLayout (const AttributedString& text) bool TextLayout::createNativeLayout (const AttributedString& text)


+ 54
- 51
modules/juce_graphics/native/juce_win32_DirectWriteTypeLayout.cpp View File

@@ -89,8 +89,8 @@ namespace DirectWriteTypeLayout
glyphLine.ascent = jmax (glyphLine.ascent, scaledFontSize (dwFontMetrics.ascent, dwFontMetrics, glyphRun)); glyphLine.ascent = jmax (glyphLine.ascent, scaledFontSize (dwFontMetrics.ascent, dwFontMetrics, glyphRun));
glyphLine.descent = jmax (glyphLine.descent, scaledFontSize (dwFontMetrics.descent, dwFontMetrics, glyphRun)); glyphLine.descent = jmax (glyphLine.descent, scaledFontSize (dwFontMetrics.descent, dwFontMetrics, glyphRun));
int styleFlags = 0;
const String fontName (getFontName (glyphRun, styleFlags));
String fontFamily, fontStyle;
getFontFamilyAndStyle (glyphRun, fontFamily, fontStyle);
TextLayout::Run* const glyphRunLayout = new TextLayout::Run (Range<int> (runDescription->textPosition, TextLayout::Run* const glyphRunLayout = new TextLayout::Run (Range<int> (runDescription->textPosition,
runDescription->textPosition + runDescription->stringLength), runDescription->textPosition + runDescription->stringLength),
@@ -102,7 +102,7 @@ namespace DirectWriteTypeLayout
const float totalHeight = std::abs ((float) dwFontMetrics.ascent) + std::abs ((float) dwFontMetrics.descent); const float totalHeight = std::abs ((float) dwFontMetrics.ascent) + std::abs ((float) dwFontMetrics.descent);
const float fontHeightToEmSizeFactor = (float) dwFontMetrics.designUnitsPerEm / totalHeight; const float fontHeightToEmSizeFactor = (float) dwFontMetrics.designUnitsPerEm / totalHeight;
glyphRunLayout->font = Font (fontName, glyphRun->fontEmSize / fontHeightToEmSizeFactor, styleFlags);
glyphRunLayout->font = Font (fontFamily, fontStyle, glyphRun->fontEmSize / fontHeightToEmSizeFactor);
glyphRunLayout->colour = getColourOf (static_cast<ID2D1SolidColorBrush*> (clientDrawingEffect)); glyphRunLayout->colour = getColourOf (static_cast<ID2D1SolidColorBrush*> (clientDrawingEffect));
const Point<float> lineOrigin (layout->getLine (currentLine).lineOrigin); const Point<float> lineOrigin (layout->getLine (currentLine).lineOrigin);
@@ -145,62 +145,29 @@ namespace DirectWriteTypeLayout
return Colour::fromFloatRGBA (colour.r, colour.g, colour.b, colour.a); return Colour::fromFloatRGBA (colour.r, colour.g, colour.b, colour.a);
} }
String getFontName (DWRITE_GLYPH_RUN const* glyphRun, int& styleFlags) const
void getFontFamilyAndStyle (DWRITE_GLYPH_RUN const* glyphRun, String& family, String& style) const
{ {
ComSmartPtr<IDWriteFont> dwFont; ComSmartPtr<IDWriteFont> dwFont;
HRESULT hr = fontCollection->GetFontFromFontFace (glyphRun->fontFace, dwFont.resetAndGetPointerAddress()); HRESULT hr = fontCollection->GetFontFromFontFace (glyphRun->fontFace, dwFont.resetAndGetPointerAddress());
jassert (dwFont != nullptr); jassert (dwFont != nullptr);
if (dwFont->GetWeight() == DWRITE_FONT_WEIGHT_BOLD) styleFlags |= Font::bold;
if (dwFont->GetStyle() == DWRITE_FONT_STYLE_ITALIC) styleFlags |= Font::italic;
ComSmartPtr<IDWriteFontFamily> dwFontFamily;
hr = dwFont->GetFontFamily (dwFontFamily.resetAndGetPointerAddress());
jassert (dwFontFamily != nullptr);
// Get the Font Family Names
ComSmartPtr<IDWriteLocalizedStrings> dwFamilyNames;
hr = dwFontFamily->GetFamilyNames (dwFamilyNames.resetAndGetPointerAddress());
jassert (dwFamilyNames != nullptr);
UINT32 index = 0;
BOOL exists = false;
hr = dwFamilyNames->FindLocaleName (L"en-us", &index, &exists);
if (! exists)
index = 0;
UINT32 length = 0;
hr = dwFamilyNames->GetStringLength (index, &length);
HeapBlock <wchar_t> name (length + 1);
hr = dwFamilyNames->GetString (index, name, length + 1);
{
ComSmartPtr<IDWriteFontFamily> dwFontFamily;
hr = dwFont->GetFontFamily (dwFontFamily.resetAndGetPointerAddress());
family = getFontFamilyName (dwFontFamily);
}
return String (name);
style = getFontFaceName (dwFont);
} }
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (CustomDirectWriteTextRenderer); JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (CustomDirectWriteTextRenderer);
}; };
//================================================================================================== //==================================================================================================
float getFontHeightToEmSizeFactor (const Font& font, IDWriteFontCollection& dwFontCollection)
float getFontHeightToEmSizeFactor (IDWriteFont* const dwFont)
{ {
BOOL fontFound = false;
uint32 fontIndex;
dwFontCollection.FindFamilyName (font.getTypefaceName().toWideCharPointer(), &fontIndex, &fontFound);
if (! fontFound)
fontIndex = 0;
ComSmartPtr<IDWriteFontFamily> dwFontFamily;
HRESULT hr = dwFontCollection.GetFontFamily (fontIndex, dwFontFamily.resetAndGetPointerAddress());
ComSmartPtr<IDWriteFont> dwFont;
hr = dwFontFamily->GetFirstMatchingFont (DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STRETCH_NORMAL, DWRITE_FONT_STYLE_NORMAL,
dwFont.resetAndGetPointerAddress());
ComSmartPtr<IDWriteFontFace> dwFontFace; ComSmartPtr<IDWriteFontFace> dwFontFace;
hr = dwFont->CreateFontFace (dwFontFace.resetAndGetPointerAddress());
dwFont->CreateFontFace (dwFontFace.resetAndGetPointerAddress());
DWRITE_FONT_METRICS dwFontMetrics; DWRITE_FONT_METRICS dwFontMetrics;
dwFontFace->GetMetrics (&dwFontMetrics); dwFontFace->GetMetrics (&dwFontMetrics);
@@ -251,13 +218,35 @@ namespace DirectWriteTypeLayout
if (font != nullptr) if (font != nullptr)
{ {
textLayout->SetFontFamilyName (font->getTypefaceName().toWideCharPointer(), range);
BOOL fontFound = false;
uint32 fontIndex;
fontCollection->FindFamilyName (font->getTypefaceName().toWideCharPointer(), &fontIndex, &fontFound);
const float fontHeightToEmSizeFactor = getFontHeightToEmSizeFactor (*font, *fontCollection);
textLayout->SetFontSize (font->getHeight() * fontHeightToEmSizeFactor, range);
if (! fontFound)
fontIndex = 0;
if (font->isBold()) textLayout->SetFontWeight (DWRITE_FONT_WEIGHT_BOLD, range);
if (font->isItalic()) textLayout->SetFontStyle (DWRITE_FONT_STYLE_ITALIC, range);
ComSmartPtr<IDWriteFontFamily> fontFamily;
HRESULT hr = fontCollection->GetFontFamily (fontIndex, fontFamily.resetAndGetPointerAddress());
ComSmartPtr<IDWriteFont> dwFont;
uint32 fontFacesCount = 0;
fontFacesCount = fontFamily->GetFontCount();
for (uint32 i = 0; i < fontFacesCount; ++i)
{
hr = fontFamily->GetFont (i, dwFont.resetAndGetPointerAddress());
if (attr.getFont()->getTypefaceStyle() == getFontFaceName (dwFont))
break;
}
textLayout->SetFontFamilyName (attr.getFont()->getTypefaceName().toWideCharPointer(), range);
textLayout->SetFontWeight (dwFont->GetWeight(), range);
textLayout->SetFontStretch (dwFont->GetStretch(), range);
textLayout->SetFontStyle (dwFont->GetStyle(), range);
const float fontHeightToEmSizeFactor = getFontHeightToEmSizeFactor (dwFont);
textLayout->SetFontSize (font->getHeight() * fontHeightToEmSizeFactor, range);
} }
if (attr.getColour() != nullptr) if (attr.getColour() != nullptr)
@@ -290,7 +279,21 @@ namespace DirectWriteTypeLayout
HRESULT hr = direct2dFactory->CreateDCRenderTarget (&d2dRTProp, renderTarget.resetAndGetPointerAddress()); HRESULT hr = direct2dFactory->CreateDCRenderTarget (&d2dRTProp, renderTarget.resetAndGetPointerAddress());
Font defaultFont; Font defaultFont;
const float defaultFontHeightToEmSizeFactor = getFontHeightToEmSizeFactor (defaultFont, *fontCollection);
BOOL fontFound = false;
uint32 fontIndex;
fontCollection->FindFamilyName (defaultFont.getTypefaceName().toWideCharPointer(), &fontIndex, &fontFound);
if (! fontFound)
fontIndex = 0;
ComSmartPtr<IDWriteFontFamily> dwFontFamily;
hr = fontCollection->GetFontFamily (fontIndex, dwFontFamily.resetAndGetPointerAddress());
ComSmartPtr<IDWriteFont> dwFont;
hr = dwFontFamily->GetFirstMatchingFont (DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STRETCH_NORMAL, DWRITE_FONT_STYLE_NORMAL,
dwFont.resetAndGetPointerAddress());
const float defaultFontHeightToEmSizeFactor = getFontHeightToEmSizeFactor (dwFont);
jassert (directWriteFactory != nullptr); jassert (directWriteFactory != nullptr);


+ 56
- 5
modules/juce_graphics/native/juce_win32_DirectWriteTypeface.cpp View File

@@ -24,6 +24,47 @@
*/ */
#if JUCE_USE_DIRECTWRITE #if JUCE_USE_DIRECTWRITE
namespace
{
static String getLocalisedName (IDWriteLocalizedStrings* names)
{
jassert (names != nullptr);
uint32 index = 0;
BOOL exists = false;
HRESULT hr = names->FindLocaleName (L"en-us", &index, &exists);
if (! exists)
index = 0;
uint32 length = 0;
hr = names->GetStringLength (index, &length);
HeapBlock<wchar_t> name (length + 1);
hr = names->GetString (index, name, length + 1);
return static_cast <const wchar_t*> (name);
}
static String getFontFamilyName (IDWriteFontFamily* family)
{
jassert (family != nullptr);
ComSmartPtr<IDWriteLocalizedStrings> familyNames;
HRESULT hr = family->GetFamilyNames (familyNames.resetAndGetPointerAddress());
jassert (SUCCEEDED (hr)); (void) hr;
return getLocalisedName (familyNames);
}
static String getFontFaceName (IDWriteFont* font)
{
jassert (font != nullptr);
ComSmartPtr<IDWriteLocalizedStrings> faceNames;
HRESULT hr = font->GetFaceNames (faceNames.resetAndGetPointerAddress());
jassert (SUCCEEDED (hr)); (void) hr;
return getLocalisedName (faceNames);
}
}
class Direct2DFactories class Direct2DFactories
{ {
public: public:
@@ -86,7 +127,7 @@ class WindowsDirectWriteTypeface : public Typeface
{ {
public: public:
WindowsDirectWriteTypeface (const Font& font, IDWriteFontCollection* fontCollection) WindowsDirectWriteTypeface (const Font& font, IDWriteFontCollection* fontCollection)
: Typeface (font.getTypefaceName()),
: Typeface (font.getTypefaceName(), font.getTypefaceStyle()),
ascent (0.0f) ascent (0.0f)
{ {
jassert (fontCollection != nullptr); jassert (fontCollection != nullptr);
@@ -102,12 +143,22 @@ public:
ComSmartPtr<IDWriteFontFamily> dwFontFamily; ComSmartPtr<IDWriteFontFamily> dwFontFamily;
hr = fontCollection->GetFontFamily (fontIndex, dwFontFamily.resetAndGetPointerAddress()); hr = fontCollection->GetFontFamily (fontIndex, dwFontFamily.resetAndGetPointerAddress());
// Get a specific font in the font family using certain weight and style flags
// Get a specific font in the font family using typeface style
ComSmartPtr<IDWriteFont> dwFont; ComSmartPtr<IDWriteFont> dwFont;
DWRITE_FONT_WEIGHT dwWeight = font.isBold() ? DWRITE_FONT_WEIGHT_BOLD : DWRITE_FONT_WEIGHT_NORMAL;
DWRITE_FONT_STYLE dwStyle = font.isItalic() ? DWRITE_FONT_STYLE_ITALIC : DWRITE_FONT_STYLE_NORMAL;
uint32 fontFacesCount = 0;
fontFacesCount = dwFontFamily->GetFontCount();
for (uint32 i = 0; i < fontFacesCount; ++i)
{
hr = dwFontFamily->GetFont (i, dwFont.resetAndGetPointerAddress());
ComSmartPtr<IDWriteLocalizedStrings> faceNames;
hr = dwFont->GetFaceNames (faceNames.resetAndGetPointerAddress());
if (font.getTypefaceStyle() == getLocalisedName (faceNames))
break;
}
hr = dwFontFamily->GetFirstMatchingFont (dwWeight, DWRITE_FONT_STRETCH_NORMAL, dwStyle, dwFont.resetAndGetPointerAddress());
hr = dwFont->CreateFontFace (dwFontFace.resetAndGetPointerAddress()); hr = dwFont->CreateFontFace (dwFontFace.resetAndGetPointerAddress());
DWRITE_FONT_METRICS dwFontMetrics; DWRITE_FONT_METRICS dwFontMetrics;


+ 99
- 28
modules/juce_graphics/native/juce_win32_Fonts.cpp View File

@@ -25,7 +25,7 @@
namespace FontEnumerators namespace FontEnumerators
{ {
int CALLBACK fontEnum2 (ENUMLOGFONTEXW* lpelfe, NEWTEXTMETRICEXW*, int type, LPARAM lParam)
static int CALLBACK fontEnum2 (ENUMLOGFONTEXW* lpelfe, NEWTEXTMETRICEXW*, int type, LPARAM lParam)
{ {
if (lpelfe != nullptr && (type & RASTER_FONTTYPE) == 0) if (lpelfe != nullptr && (type & RASTER_FONTTYPE) == 0)
{ {
@@ -36,7 +36,7 @@ namespace FontEnumerators
return 1; return 1;
} }
int CALLBACK fontEnum1 (ENUMLOGFONTEXW* lpelfe, NEWTEXTMETRICEXW*, int type, LPARAM lParam)
static int CALLBACK fontEnum1 (ENUMLOGFONTEXW* lpelfe, NEWTEXTMETRICEXW*, int type, LPARAM lParam)
{ {
if (lpelfe != nullptr && (type & RASTER_FONTTYPE) == 0) if (lpelfe != nullptr && (type & RASTER_FONTTYPE) == 0)
{ {
@@ -65,28 +65,99 @@ namespace FontEnumerators
StringArray Font::findAllTypefaceNames() StringArray Font::findAllTypefaceNames()
{ {
StringArray results; StringArray results;
HDC dc = CreateCompatibleDC (0);
#if JUCE_USE_DIRECTWRITE
const Direct2DFactories& factories = Direct2DFactories::getInstance();
if (factories.systemFonts != nullptr)
{ {
LOGFONTW lf = { 0 };
lf.lfWeight = FW_DONTCARE;
lf.lfOutPrecision = OUT_OUTLINE_PRECIS;
lf.lfQuality = DEFAULT_QUALITY;
lf.lfCharSet = DEFAULT_CHARSET;
lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
lf.lfPitchAndFamily = FF_DONTCARE;
ComSmartPtr<IDWriteFontFamily> fontFamily;
uint32 fontFamilyCount = 0;
fontFamilyCount = factories.systemFonts->GetFontFamilyCount();
for (uint32 i = 0; i < fontFamilyCount; ++i)
{
HRESULT hr = factories.systemFonts->GetFontFamily (i, fontFamily.resetAndGetPointerAddress());
EnumFontFamiliesEx (dc, &lf,
(FONTENUMPROCW) &FontEnumerators::fontEnum1,
(LPARAM) &results, 0);
if (SUCCEEDED (hr))
results.addIfNotAlreadyThere (getFontFamilyName (fontFamily));
}
} }
else
#endif
{
HDC dc = CreateCompatibleDC (0);
{
LOGFONTW lf = { 0 };
lf.lfWeight = FW_DONTCARE;
lf.lfOutPrecision = OUT_OUTLINE_PRECIS;
lf.lfQuality = DEFAULT_QUALITY;
lf.lfCharSet = DEFAULT_CHARSET;
lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
lf.lfPitchAndFamily = FF_DONTCARE;
EnumFontFamiliesEx (dc, &lf,
(FONTENUMPROCW) &FontEnumerators::fontEnum1,
(LPARAM) &results, 0);
}
DeleteDC (dc);
DeleteDC (dc);
}
results.sort (true); results.sort (true);
return results; return results;
} }
StringArray Font::findAllTypefaceStyles (const String& family)
{
if (FontStyleHelpers::isPlaceholderFamilyName (family))
return findAllTypefaceStyles (FontStyleHelpers::getConcreteFamilyNameFromPlaceholder (family));
StringArray results;
#if JUCE_USE_DIRECTWRITE
const Direct2DFactories& factories = Direct2DFactories::getInstance();
if (factories.systemFonts != nullptr)
{
BOOL fontFound = false;
uint32 fontIndex = 0;
HRESULT hr = factories.systemFonts->FindFamilyName (family.toWideCharPointer(), &fontIndex, &fontFound);
if (! fontFound)
fontIndex = 0;
// Get the font family using the search results
// Fonts like: Times New Roman, Times New Roman Bold, Times New Roman Italic are all in the same font family
ComSmartPtr<IDWriteFontFamily> fontFamily;
hr = factories.systemFonts->GetFontFamily (fontIndex, fontFamily.resetAndGetPointerAddress());
// Get the font faces
ComSmartPtr<IDWriteFont> dwFont;
uint32 fontFacesCount = 0;
fontFacesCount = fontFamily->GetFontCount();
for (uint32 i = 0; i < fontFacesCount; ++i)
{
hr = fontFamily->GetFont (i, dwFont.resetAndGetPointerAddress());
// Ignore any algorithmically generated bold and oblique styles..
if (dwFont->GetSimulations() == DWRITE_FONT_SIMULATIONS_NONE)
results.addIfNotAlreadyThere (getFontFaceName (dwFont));
}
}
else
#endif
{
results.add ("Regular");
results.add ("Italic");
results.add ("Bold");
results.add ("Bold Italic");
}
return results;
}
extern bool juce_IsRunningInWine(); extern bool juce_IsRunningInWine();
struct DefaultFontNames struct DefaultFontNames
@@ -116,15 +187,17 @@ Typeface::Ptr Font::getDefaultTypefaceForFont (const Font& font)
{ {
static DefaultFontNames defaultNames; static DefaultFontNames defaultNames;
String faceName (font.getTypefaceName());
Font newFont (font);
const String& faceName = font.getTypefaceName();
if (faceName == getDefaultSansSerifFontName()) newFont.setTypefaceName (defaultNames.defaultSans);
else if (faceName == getDefaultSerifFontName()) newFont.setTypefaceName (defaultNames.defaultSerif);
else if (faceName == getDefaultMonospacedFontName()) newFont.setTypefaceName (defaultNames.defaultFixed);
if (faceName == Font::getDefaultSansSerifFontName()) faceName = defaultNames.defaultSans;
else if (faceName == Font::getDefaultSerifFontName()) faceName = defaultNames.defaultSerif;
else if (faceName == Font::getDefaultMonospacedFontName()) faceName = defaultNames.defaultFixed;
if (font.getTypefaceStyle() == getDefaultStyle())
newFont.setTypefaceStyle ("Regular");
Font f (font);
f.setTypefaceName (faceName);
return Typeface::createSystemTypefaceFor (f);
return Typeface::createSystemTypefaceFor (newFont);
} }
//============================================================================== //==============================================================================
@@ -132,14 +205,13 @@ class WindowsTypeface : public Typeface
{ {
public: public:
WindowsTypeface (const Font& font) WindowsTypeface (const Font& font)
: Typeface (font.getTypefaceName()),
: Typeface (font.getTypefaceName(),
font.getTypefaceStyle()),
fontH (0), fontH (0),
previousFontH (0), previousFontH (0),
dc (CreateCompatibleDC (0)), dc (CreateCompatibleDC (0)),
ascent (1.0f), ascent (1.0f),
defaultGlyph (-1),
bold (font.isBold()),
italic (font.isItalic())
defaultGlyph (-1)
{ {
loadFont(); loadFont();
@@ -282,7 +354,6 @@ private:
TEXTMETRIC tm; TEXTMETRIC tm;
float ascent; float ascent;
int defaultGlyph; int defaultGlyph;
bool bold, italic;
struct KerningPair struct KerningPair
{ {
@@ -314,8 +385,8 @@ private:
lf.lfOutPrecision = OUT_OUTLINE_PRECIS; lf.lfOutPrecision = OUT_OUTLINE_PRECIS;
lf.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE; lf.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
lf.lfQuality = PROOF_QUALITY; lf.lfQuality = PROOF_QUALITY;
lf.lfItalic = (BYTE) (italic ? TRUE : FALSE);
lf.lfWeight = bold ? FW_BOLD : FW_NORMAL;
lf.lfItalic = (BYTE) (style == "Italic" ? TRUE : FALSE);
lf.lfWeight = style == "Bold" ? FW_BOLD : FW_NORMAL;
lf.lfHeight = -256; lf.lfHeight = -256;
name.copyToUTF16 (lf.lfFaceName, sizeof (lf.lfFaceName)); name.copyToUTF16 (lf.lfFaceName, sizeof (lf.lfFaceName));


Loading…
Cancel
Save