| @@ -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()); | ||||
| @@ -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()); | ||||
| @@ -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. | ||||
| @@ -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); | |||||
| } | } | ||||
| @@ -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 | ||||
| @@ -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(); | ||||
| } | } | ||||
| @@ -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(); | ||||
| @@ -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 | ||||
| @@ -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); | ||||
| }; | }; | ||||
| @@ -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]; | ||||
| @@ -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) | ||||
| @@ -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); | ||||
| @@ -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; | ||||
| @@ -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)); | ||||