mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-10 23:44:24 +00:00
Font: Make Font and TypefaceCache threadsafe
Previously, it wasn't safe to access Font instances from multiple
threads because there was a chance that they might reference the same
shared internal state. In this case, calling getTypeface() or getAscent from
two threads simultaneously would cause a race on the typeface and ascent
data members, even though the Font instances appeared to be disjoint.
With this change in place, it is now safe to use Font instances from
multiple threads simultaneously.
It is still an error to modify the same Font instance from multiple
threads without synchronization!
// Fine:
Font a;
Font b = a;
auto futureA = std::async (std::launch::async, [&a] { /* do something with a */ });
auto futureB = std::async (std::launch::async, [&b] { /* do something with b */ });
// Bad idea:
Font f;
auto futureA = std::async (std::launch::async, [&f] { /* do something with f */ });
auto futureB = std::async (std::launch::async, [&f] { /* do something with f */ });
This commit is contained in:
parent
300f573163
commit
3768349a05
14 changed files with 226 additions and 108 deletions
|
|
@ -399,7 +399,7 @@ public:
|
|||
{
|
||||
Path p;
|
||||
Font& font = getState().font;
|
||||
font.getTypeface()->getOutlineForGlyph (glyphNumber, p);
|
||||
font.getTypefacePtr()->getOutlineForGlyph (glyphNumber, p);
|
||||
fillPath (p, AffineTransform::scale (font.getHeight() * font.getHorizontalScale(), font.getHeight()).followedBy (transform));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -532,7 +532,7 @@ void LowLevelGraphicsPostScriptRenderer::drawGlyph (int glyphNumber, const Affin
|
|||
{
|
||||
Path p;
|
||||
Font& font = stateStack.getLast()->font;
|
||||
font.getTypeface()->getOutlineForGlyph (glyphNumber, p);
|
||||
font.getTypefacePtr()->getOutlineForGlyph (glyphNumber, p);
|
||||
fillPath (p, AffineTransform::scale (font.getHeight() * font.getHorizontalScale(), font.getHeight()).followedBy (transform));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -135,7 +135,11 @@ public:
|
|||
return face.typeface;
|
||||
}
|
||||
|
||||
Typeface::Ptr defaultFace;
|
||||
Typeface::Ptr getDefaultFace() const noexcept
|
||||
{
|
||||
const ScopedReadLock slr (lock);
|
||||
return defaultFace;
|
||||
}
|
||||
|
||||
private:
|
||||
struct CachedFace
|
||||
|
|
@ -151,6 +155,7 @@ private:
|
|||
Typeface::Ptr typeface;
|
||||
};
|
||||
|
||||
Typeface::Ptr defaultFace;
|
||||
ReadWriteLock lock;
|
||||
Array<CachedFace> faces;
|
||||
size_t counter = 0;
|
||||
|
|
@ -182,7 +187,7 @@ class Font::SharedFontInternal : public ReferenceCountedObject
|
|||
{
|
||||
public:
|
||||
SharedFontInternal() noexcept
|
||||
: typeface (TypefaceCache::getInstance()->defaultFace),
|
||||
: typeface (TypefaceCache::getInstance()->getDefaultFace()),
|
||||
typefaceName (Font::getDefaultSansSerifFontName()),
|
||||
typefaceStyle (Font::getDefaultStyle()),
|
||||
height (FontValues::defaultFontHeight)
|
||||
|
|
@ -196,7 +201,7 @@ public:
|
|||
underline ((styleFlags & underlined) != 0)
|
||||
{
|
||||
if (styleFlags == plain)
|
||||
typeface = TypefaceCache::getInstance()->defaultFace;
|
||||
typeface = TypefaceCache::getInstance()->getDefaultFace();
|
||||
}
|
||||
|
||||
SharedFontInternal (const String& name, int styleFlags, float fontHeight) noexcept
|
||||
|
|
@ -206,7 +211,7 @@ public:
|
|||
underline ((styleFlags & underlined) != 0)
|
||||
{
|
||||
if (styleFlags == plain && typefaceName.isEmpty())
|
||||
typeface = TypefaceCache::getInstance()->defaultFace;
|
||||
typeface = TypefaceCache::getInstance()->getDefaultFace();
|
||||
}
|
||||
|
||||
SharedFontInternal (const String& name, const String& style, float fontHeight) noexcept
|
||||
|
|
@ -248,10 +253,119 @@ public:
|
|||
&& typefaceStyle == other.typefaceStyle;
|
||||
}
|
||||
|
||||
/* The typeface and ascent data members may be read/set from multiple threads
|
||||
simultaneously, e.g. in the case that two Font instances reference the same
|
||||
SharedFontInternal and call getTypefacePtr() simultaneously.
|
||||
|
||||
We lock in functions that modify the typeface or ascent in order to
|
||||
ensure thread safety.
|
||||
*/
|
||||
|
||||
Typeface::Ptr getTypefacePtr (const Font& f)
|
||||
{
|
||||
const ScopedLock lock (mutex);
|
||||
|
||||
if (typeface == nullptr)
|
||||
{
|
||||
typeface = TypefaceCache::getInstance()->findTypefaceFor (f);
|
||||
jassert (typeface != nullptr);
|
||||
}
|
||||
|
||||
return typeface;
|
||||
}
|
||||
|
||||
void checkTypefaceSuitability (const Font& f)
|
||||
{
|
||||
const ScopedLock lock (mutex);
|
||||
|
||||
if (typeface != nullptr && ! typeface->isSuitableForFont (f))
|
||||
typeface = nullptr;
|
||||
}
|
||||
|
||||
float getAscent (const Font& f)
|
||||
{
|
||||
const ScopedLock lock (mutex);
|
||||
|
||||
if (ascent == 0.0f)
|
||||
ascent = getTypefacePtr (f)->getAscent();
|
||||
|
||||
return height * ascent;
|
||||
}
|
||||
|
||||
/* We do not need to lock in these functions, as it's guaranteed
|
||||
that these data members can only change if there is a single Font
|
||||
instance referencing the shared state.
|
||||
*/
|
||||
|
||||
String getTypefaceName() const { return typefaceName; }
|
||||
String getTypefaceStyle() const { return typefaceStyle; }
|
||||
float getHeight() const { return height; }
|
||||
float getHorizontalScale() const { return horizontalScale; }
|
||||
float getKerning() const { return kerning; }
|
||||
bool getUnderline() const { return underline; }
|
||||
|
||||
/* This shared state may be shared between two or more Font instances that are being
|
||||
read/modified from multiple threads.
|
||||
Before modifying a shared instance you *must* call dupeInternalIfShared to
|
||||
ensure that only one Font instance is pointing to the SharedFontInternal instance
|
||||
during the modification.
|
||||
*/
|
||||
|
||||
void setTypeface (Typeface::Ptr x)
|
||||
{
|
||||
jassert (getReferenceCount() == 1);
|
||||
typeface = std::move (x);
|
||||
}
|
||||
|
||||
void setTypefaceName (String x)
|
||||
{
|
||||
jassert (getReferenceCount() == 1);
|
||||
typefaceName = std::move (x);
|
||||
}
|
||||
|
||||
void setTypefaceStyle (String x)
|
||||
{
|
||||
jassert (getReferenceCount() == 1);
|
||||
typefaceStyle = std::move (x);
|
||||
}
|
||||
|
||||
void setHeight (float x)
|
||||
{
|
||||
jassert (getReferenceCount() == 1);
|
||||
height = x;
|
||||
}
|
||||
|
||||
void setHorizontalScale (float x)
|
||||
{
|
||||
jassert (getReferenceCount() == 1);
|
||||
horizontalScale = x;
|
||||
}
|
||||
|
||||
void setKerning (float x)
|
||||
{
|
||||
jassert (getReferenceCount() == 1);
|
||||
kerning = x;
|
||||
}
|
||||
|
||||
void setAscent (float x)
|
||||
{
|
||||
jassert (getReferenceCount() == 1);
|
||||
ascent = x;
|
||||
}
|
||||
|
||||
void setUnderline (bool x)
|
||||
{
|
||||
jassert (getReferenceCount() == 1);
|
||||
underline = x;
|
||||
}
|
||||
|
||||
private:
|
||||
Typeface::Ptr typeface;
|
||||
String typefaceName, typefaceStyle;
|
||||
float height, horizontalScale = 1.0f, kerning = 0, ascent = 0;
|
||||
float height = 0.0f, horizontalScale = 1.0f, kerning = 0.0f, ascent = 0.0f;
|
||||
bool underline = false;
|
||||
|
||||
CriticalSection mutex;
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
|
|
@ -291,9 +405,7 @@ Font& Font::operator= (Font&& other) noexcept
|
|||
return *this;
|
||||
}
|
||||
|
||||
Font::~Font() noexcept
|
||||
{
|
||||
}
|
||||
Font::~Font() noexcept = default;
|
||||
|
||||
bool Font::operator== (const Font& other) const noexcept
|
||||
{
|
||||
|
|
@ -314,8 +426,7 @@ void Font::dupeInternalIfShared()
|
|||
|
||||
void Font::checkTypefaceSuitability()
|
||||
{
|
||||
if (font->typeface != nullptr && ! font->typeface->isSuitableForFont (*this))
|
||||
font->typeface = nullptr;
|
||||
font->checkTypefaceSuitability (*this);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
|
@ -346,30 +457,30 @@ const String& Font::getDefaultSerifFontName() { return getFontPlacehol
|
|||
const String& Font::getDefaultMonospacedFontName() { return getFontPlaceholderNames().mono; }
|
||||
const String& Font::getDefaultStyle() { return getFontPlaceholderNames().regular; }
|
||||
|
||||
const String& Font::getTypefaceName() const noexcept { return font->typefaceName; }
|
||||
const String& Font::getTypefaceStyle() const noexcept { return font->typefaceStyle; }
|
||||
String Font::getTypefaceName() const noexcept { return font->getTypefaceName(); }
|
||||
String Font::getTypefaceStyle() const noexcept { return font->getTypefaceStyle(); }
|
||||
|
||||
void Font::setTypefaceName (const String& faceName)
|
||||
{
|
||||
if (faceName != font->typefaceName)
|
||||
if (faceName != font->getTypefaceName())
|
||||
{
|
||||
jassert (faceName.isNotEmpty());
|
||||
|
||||
dupeInternalIfShared();
|
||||
font->typefaceName = faceName;
|
||||
font->typeface = nullptr;
|
||||
font->ascent = 0;
|
||||
font->setTypefaceName (faceName);
|
||||
font->setTypeface (nullptr);
|
||||
font->setAscent (0);
|
||||
}
|
||||
}
|
||||
|
||||
void Font::setTypefaceStyle (const String& typefaceStyle)
|
||||
{
|
||||
if (typefaceStyle != font->typefaceStyle)
|
||||
if (typefaceStyle != font->getTypefaceStyle())
|
||||
{
|
||||
dupeInternalIfShared();
|
||||
font->typefaceStyle = typefaceStyle;
|
||||
font->typeface = nullptr;
|
||||
font->ascent = 0;
|
||||
font->setTypefaceStyle (typefaceStyle);
|
||||
font->setTypeface (nullptr);
|
||||
font->setAscent (0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -382,18 +493,17 @@ Font Font::withTypefaceStyle (const String& newStyle) const
|
|||
|
||||
StringArray Font::getAvailableStyles() const
|
||||
{
|
||||
return findAllTypefaceStyles (getTypeface()->getName());
|
||||
return findAllTypefaceStyles (getTypefacePtr()->getName());
|
||||
}
|
||||
|
||||
Typeface::Ptr Font::getTypefacePtr() const
|
||||
{
|
||||
return font->getTypefacePtr (*this);
|
||||
}
|
||||
|
||||
Typeface* Font::getTypeface() const
|
||||
{
|
||||
if (font->typeface == nullptr)
|
||||
{
|
||||
font->typeface = TypefaceCache::getInstance()->findTypefaceFor (*this);
|
||||
jassert (font->typeface != nullptr);
|
||||
}
|
||||
|
||||
return font->typeface.get();
|
||||
return getTypefacePtr().get();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
|
@ -435,7 +545,7 @@ Font Font::withHeight (const float newHeight) const
|
|||
|
||||
float Font::getHeightToPointsFactor() const
|
||||
{
|
||||
return getTypeface()->getHeightToPointsFactor();
|
||||
return getTypefacePtr()->getHeightToPointsFactor();
|
||||
}
|
||||
|
||||
Font Font::withPointHeight (float heightInPoints) const
|
||||
|
|
@ -449,10 +559,10 @@ void Font::setHeight (float newHeight)
|
|||
{
|
||||
newHeight = FontValues::limitFontHeight (newHeight);
|
||||
|
||||
if (font->height != newHeight)
|
||||
if (font->getHeight() != newHeight)
|
||||
{
|
||||
dupeInternalIfShared();
|
||||
font->height = newHeight;
|
||||
font->setHeight (newHeight);
|
||||
checkTypefaceSuitability();
|
||||
}
|
||||
}
|
||||
|
|
@ -461,18 +571,18 @@ void Font::setHeightWithoutChangingWidth (float newHeight)
|
|||
{
|
||||
newHeight = FontValues::limitFontHeight (newHeight);
|
||||
|
||||
if (font->height != newHeight)
|
||||
if (font->getHeight() != newHeight)
|
||||
{
|
||||
dupeInternalIfShared();
|
||||
font->horizontalScale *= (font->height / newHeight);
|
||||
font->height = newHeight;
|
||||
font->setHorizontalScale (font->getHorizontalScale() * (font->getHeight() / newHeight));
|
||||
font->setHeight (newHeight);
|
||||
checkTypefaceSuitability();
|
||||
}
|
||||
}
|
||||
|
||||
int Font::getStyleFlags() const noexcept
|
||||
{
|
||||
int styleFlags = font->underline ? underlined : plain;
|
||||
int styleFlags = font->getUnderline() ? underlined : plain;
|
||||
|
||||
if (isBold()) styleFlags |= bold;
|
||||
if (isItalic()) styleFlags |= italic;
|
||||
|
|
@ -492,10 +602,10 @@ void Font::setStyleFlags (const int newFlags)
|
|||
if (getStyleFlags() != newFlags)
|
||||
{
|
||||
dupeInternalIfShared();
|
||||
font->typeface = nullptr;
|
||||
font->typefaceStyle = FontStyleHelpers::getStyleName (newFlags);
|
||||
font->underline = (newFlags & underlined) != 0;
|
||||
font->ascent = 0;
|
||||
font->setTypeface (nullptr);
|
||||
font->setTypefaceStyle (FontStyleHelpers::getStyleName (newFlags));
|
||||
font->setUnderline ((newFlags & underlined) != 0);
|
||||
font->setAscent (0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -506,14 +616,14 @@ void Font::setSizeAndStyle (float newHeight,
|
|||
{
|
||||
newHeight = FontValues::limitFontHeight (newHeight);
|
||||
|
||||
if (font->height != newHeight
|
||||
|| font->horizontalScale != newHorizontalScale
|
||||
|| font->kerning != newKerningAmount)
|
||||
if (font->getHeight() != newHeight
|
||||
|| font->getHorizontalScale() != newHorizontalScale
|
||||
|| font->getKerning() != newKerningAmount)
|
||||
{
|
||||
dupeInternalIfShared();
|
||||
font->height = newHeight;
|
||||
font->horizontalScale = newHorizontalScale;
|
||||
font->kerning = newKerningAmount;
|
||||
font->setHeight (newHeight);
|
||||
font->setHorizontalScale (newHorizontalScale);
|
||||
font->setKerning (newKerningAmount);
|
||||
checkTypefaceSuitability();
|
||||
}
|
||||
|
||||
|
|
@ -527,14 +637,14 @@ void Font::setSizeAndStyle (float newHeight,
|
|||
{
|
||||
newHeight = FontValues::limitFontHeight (newHeight);
|
||||
|
||||
if (font->height != newHeight
|
||||
|| font->horizontalScale != newHorizontalScale
|
||||
|| font->kerning != newKerningAmount)
|
||||
if (font->getHeight() != newHeight
|
||||
|| font->getHorizontalScale() != newHorizontalScale
|
||||
|| font->getKerning() != newKerningAmount)
|
||||
{
|
||||
dupeInternalIfShared();
|
||||
font->height = newHeight;
|
||||
font->horizontalScale = newHorizontalScale;
|
||||
font->kerning = newKerningAmount;
|
||||
font->setHeight (newHeight);
|
||||
font->setHorizontalScale (newHorizontalScale);
|
||||
font->setKerning (newKerningAmount);
|
||||
checkTypefaceSuitability();
|
||||
}
|
||||
|
||||
|
|
@ -551,18 +661,18 @@ Font Font::withHorizontalScale (const float newHorizontalScale) const
|
|||
void Font::setHorizontalScale (const float scaleFactor)
|
||||
{
|
||||
dupeInternalIfShared();
|
||||
font->horizontalScale = scaleFactor;
|
||||
font->setHorizontalScale (scaleFactor);
|
||||
checkTypefaceSuitability();
|
||||
}
|
||||
|
||||
float Font::getHorizontalScale() const noexcept
|
||||
{
|
||||
return font->horizontalScale;
|
||||
return font->getHorizontalScale();
|
||||
}
|
||||
|
||||
float Font::getExtraKerningFactor() const noexcept
|
||||
{
|
||||
return font->kerning;
|
||||
return font->getKerning();
|
||||
}
|
||||
|
||||
Font Font::withExtraKerningFactor (const float extraKerning) const
|
||||
|
|
@ -575,16 +685,16 @@ Font Font::withExtraKerningFactor (const float extraKerning) const
|
|||
void Font::setExtraKerningFactor (const float extraKerning)
|
||||
{
|
||||
dupeInternalIfShared();
|
||||
font->kerning = extraKerning;
|
||||
font->setKerning (extraKerning);
|
||||
checkTypefaceSuitability();
|
||||
}
|
||||
|
||||
Font Font::boldened() const { return withStyle (getStyleFlags() | bold); }
|
||||
Font Font::italicised() const { return withStyle (getStyleFlags() | italic); }
|
||||
|
||||
bool Font::isBold() const noexcept { return FontStyleHelpers::isBold (font->typefaceStyle); }
|
||||
bool Font::isItalic() const noexcept { return FontStyleHelpers::isItalic (font->typefaceStyle); }
|
||||
bool Font::isUnderlined() const noexcept { return font->underline; }
|
||||
bool Font::isBold() const noexcept { return FontStyleHelpers::isBold (font->getTypefaceStyle()); }
|
||||
bool Font::isItalic() const noexcept { return FontStyleHelpers::isItalic (font->getTypefaceStyle()); }
|
||||
bool Font::isUnderlined() const noexcept { return font->getUnderline(); }
|
||||
|
||||
void Font::setBold (const bool shouldBeBold)
|
||||
{
|
||||
|
|
@ -603,20 +713,17 @@ void Font::setItalic (const bool shouldBeItalic)
|
|||
void Font::setUnderline (const bool shouldBeUnderlined)
|
||||
{
|
||||
dupeInternalIfShared();
|
||||
font->underline = shouldBeUnderlined;
|
||||
font->setUnderline (shouldBeUnderlined);
|
||||
checkTypefaceSuitability();
|
||||
}
|
||||
|
||||
float Font::getAscent() const
|
||||
{
|
||||
if (font->ascent == 0.0f)
|
||||
font->ascent = getTypeface()->getAscent();
|
||||
|
||||
return font->height * font->ascent;
|
||||
return font->getAscent (*this);
|
||||
}
|
||||
|
||||
float Font::getHeight() const noexcept { return font->height; }
|
||||
float Font::getDescent() const { return font->height - getAscent(); }
|
||||
float Font::getHeight() const noexcept { return font->getHeight(); }
|
||||
float Font::getDescent() const { return font->getHeight() - getAscent(); }
|
||||
|
||||
float Font::getHeightInPoints() const { return getHeight() * getHeightToPointsFactor(); }
|
||||
float Font::getAscentInPoints() const { return getAscent() * getHeightToPointsFactor(); }
|
||||
|
|
@ -629,35 +736,27 @@ int Font::getStringWidth (const String& text) const
|
|||
|
||||
float Font::getStringWidthFloat (const String& text) const
|
||||
{
|
||||
// This call isn't thread-safe when there's a message thread running
|
||||
jassert (MessageManager::getInstanceWithoutCreating() == nullptr
|
||||
|| MessageManager::getInstanceWithoutCreating()->currentThreadHasLockedMessageManager());
|
||||
auto w = getTypefacePtr()->getStringWidth (text);
|
||||
|
||||
auto w = getTypeface()->getStringWidth (text);
|
||||
if (font->getKerning() != 0.0f)
|
||||
w += font->getKerning() * (float) text.length();
|
||||
|
||||
if (font->kerning != 0.0f)
|
||||
w += font->kerning * (float) text.length();
|
||||
|
||||
return w * font->height * font->horizontalScale;
|
||||
return w * font->getHeight() * font->getHorizontalScale();
|
||||
}
|
||||
|
||||
void Font::getGlyphPositions (const String& text, Array<int>& glyphs, Array<float>& xOffsets) const
|
||||
{
|
||||
// This call isn't thread-safe when there's a message thread running
|
||||
jassert (MessageManager::getInstanceWithoutCreating() == nullptr
|
||||
|| MessageManager::getInstanceWithoutCreating()->currentThreadHasLockedMessageManager());
|
||||
|
||||
getTypeface()->getGlyphPositions (text, glyphs, xOffsets);
|
||||
getTypefacePtr()->getGlyphPositions (text, glyphs, xOffsets);
|
||||
|
||||
if (auto num = xOffsets.size())
|
||||
{
|
||||
auto scale = font->height * font->horizontalScale;
|
||||
auto scale = font->getHeight() * font->getHorizontalScale();
|
||||
auto* x = xOffsets.getRawDataPointer();
|
||||
|
||||
if (font->kerning != 0.0f)
|
||||
if (font->getKerning() != 0.0f)
|
||||
{
|
||||
for (int i = 0; i < num; ++i)
|
||||
x[i] = (x[i] + (float) i * font->kerning) * scale;
|
||||
x[i] = (x[i] + (float) i * font->getKerning()) * scale;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
|
|
@ -121,7 +121,7 @@ public:
|
|||
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()->getName(), which will give you the platform-specific font family.
|
||||
Font::getTypefacePtr()->getName(), 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.
|
||||
*/
|
||||
|
|
@ -136,15 +136,15 @@ public:
|
|||
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()->getName(), which will give you the platform-specific font family.
|
||||
Font::getTypefacePtr()->getName(), which will give you the platform-specific font family.
|
||||
*/
|
||||
const String& getTypefaceName() const noexcept;
|
||||
String getTypefaceName() const noexcept;
|
||||
|
||||
//==============================================================================
|
||||
/** Returns the font style of the typeface that this font uses.
|
||||
@see withTypefaceStyle, getAvailableStyles()
|
||||
*/
|
||||
const String& getTypefaceStyle() const noexcept;
|
||||
String getTypefaceStyle() const noexcept;
|
||||
|
||||
/** Changes the font style of the typeface.
|
||||
@see getAvailableStyles()
|
||||
|
|
@ -395,12 +395,17 @@ public:
|
|||
void getGlyphPositions (const String& text, Array<int>& glyphs, Array<float>& xOffsets) const;
|
||||
|
||||
//==============================================================================
|
||||
/** Returns the typeface used by this font.
|
||||
/** This is unsafe, use getTypefacePtr() instead.
|
||||
|
||||
Returns the typeface used by this font.
|
||||
|
||||
Note that the object returned may go out of scope if this font is deleted
|
||||
or has its style changed.
|
||||
*/
|
||||
Typeface* getTypeface() const;
|
||||
JUCE_DEPRECATED (Typeface* getTypeface() const);
|
||||
|
||||
/** Returns the typeface used by this font. */
|
||||
Typeface::Ptr getTypefacePtr() const;
|
||||
|
||||
/** Creates an array of Font objects to represent all the fonts on the system.
|
||||
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ void PositionedGlyph::createPath (Path& path) const
|
|||
{
|
||||
if (! isWhitespace())
|
||||
{
|
||||
if (auto* t = font.getTypeface())
|
||||
if (auto t = font.getTypefacePtr())
|
||||
{
|
||||
Path p;
|
||||
t->getOutlineForGlyph (glyph, p);
|
||||
|
|
@ -78,7 +78,7 @@ bool PositionedGlyph::hitTest (float px, float py) const
|
|||
{
|
||||
if (getBounds().contains (px, py) && ! isWhitespace())
|
||||
{
|
||||
if (auto* t = font.getTypeface())
|
||||
if (auto t = font.getTypefacePtr())
|
||||
{
|
||||
Path p;
|
||||
t->getOutlineForGlyph (glyph, p);
|
||||
|
|
|
|||
|
|
@ -110,14 +110,12 @@ Typeface::Typeface (const String& faceName, const String& styleName) noexcept
|
|||
{
|
||||
}
|
||||
|
||||
Typeface::~Typeface()
|
||||
{
|
||||
}
|
||||
Typeface::~Typeface() = default;
|
||||
|
||||
Typeface::Ptr Typeface::getFallbackTypeface()
|
||||
{
|
||||
const Font fallbackFont (Font::getFallbackFontName(), Font::getFallbackFontStyle(), 10.0f);
|
||||
return Typeface::Ptr (fallbackFont.getTypeface());
|
||||
return fallbackFont.getTypefacePtr();
|
||||
}
|
||||
|
||||
EdgeTable* Typeface::getEdgeTableForGlyph (int glyphNumber, const AffineTransform& transform, float fontHeight)
|
||||
|
|
|
|||
|
|
@ -289,7 +289,7 @@ public:
|
|||
void generate (const Font& newFont, int glyphNumber)
|
||||
{
|
||||
font = newFont;
|
||||
auto* typeface = newFont.getTypeface();
|
||||
auto typeface = newFont.getTypefacePtr();
|
||||
snapToIntegerCoordinate = typeface->isHinted();
|
||||
glyph = glyphNumber;
|
||||
|
||||
|
|
@ -2567,7 +2567,7 @@ public:
|
|||
auto t = transform.getTransformWith (AffineTransform::scale (fontHeight * font.getHorizontalScale(), fontHeight)
|
||||
.followedBy (trans));
|
||||
|
||||
std::unique_ptr<EdgeTable> et (font.getTypeface()->getEdgeTableForGlyph (glyphNumber, t, fontHeight));
|
||||
std::unique_ptr<EdgeTable> et (font.getTypefacePtr()->getEdgeTableForGlyph (glyphNumber, t, fontHeight));
|
||||
|
||||
if (et != nullptr)
|
||||
fillShape (*new EdgeTableRegionType (*et), false);
|
||||
|
|
|
|||
|
|
@ -610,7 +610,9 @@ void CoreGraphicsContext::setFont (const Font& newFont)
|
|||
state->fontRef = nullptr;
|
||||
state->font = newFont;
|
||||
|
||||
if (auto osxTypeface = dynamic_cast<OSXTypeface*> (state->font.getTypeface()))
|
||||
auto typeface = state->font.getTypefacePtr();
|
||||
|
||||
if (auto osxTypeface = dynamic_cast<OSXTypeface*> (typeface.get()))
|
||||
{
|
||||
state->fontRef = osxTypeface->fontRef;
|
||||
CGContextSetFont (context.get(), state->fontRef);
|
||||
|
|
@ -667,7 +669,7 @@ void CoreGraphicsContext::drawGlyph (int glyphNumber, const AffineTransform& tra
|
|||
{
|
||||
Path p;
|
||||
auto& f = state->font;
|
||||
f.getTypeface()->getOutlineForGlyph (glyphNumber, p);
|
||||
f.getTypefacePtr()->getOutlineForGlyph (glyphNumber, p);
|
||||
|
||||
fillPath (p, AffineTransform::scale (f.getHeight() * f.getHorizontalScale(), f.getHeight())
|
||||
.followedBy (transform));
|
||||
|
|
|
|||
|
|
@ -748,7 +748,9 @@ private:
|
|||
|
||||
CTFontRef getCTFontFromTypeface (const Font& f)
|
||||
{
|
||||
if (auto* tf = dynamic_cast<OSXTypeface*> (f.getTypeface()))
|
||||
const auto typeface = f.getTypefacePtr();
|
||||
|
||||
if (auto* tf = dynamic_cast<OSXTypeface*> (typeface.get()))
|
||||
return tf->ctFontRef.get();
|
||||
|
||||
return {};
|
||||
|
|
@ -848,7 +850,7 @@ Typeface::Ptr Font::getDefaultTypefaceForFont (const Font& font)
|
|||
static DefaultFontNames defaultNames;
|
||||
|
||||
auto newFont = font;
|
||||
auto& faceName = font.getTypefaceName();
|
||||
auto faceName = font.getTypefaceName();
|
||||
|
||||
if (faceName == getDefaultSansSerifFontName()) newFont.setTypefaceName (defaultNames.defaultSans);
|
||||
else if (faceName == getDefaultSerifFontName()) newFont.setTypefaceName (defaultNames.defaultSerif);
|
||||
|
|
@ -866,7 +868,9 @@ static bool canAllTypefacesBeUsedInLayout (const AttributedString& text)
|
|||
|
||||
for (int i = 0; i < numCharacterAttributes; ++i)
|
||||
{
|
||||
if (auto tf = dynamic_cast<OSXTypeface*> (text.getAttribute (i).font.getTypeface()))
|
||||
auto typeface = text.getAttribute (i).font.getTypefacePtr();
|
||||
|
||||
if (auto tf = dynamic_cast<OSXTypeface*> (typeface.get()))
|
||||
if (tf->canBeUsedForLayout)
|
||||
continue;
|
||||
|
||||
|
|
|
|||
|
|
@ -370,7 +370,8 @@ public:
|
|||
{
|
||||
if (currentFontFace == nullptr)
|
||||
{
|
||||
auto* typeface = dynamic_cast<WindowsDirectWriteTypeface*> (font.getTypeface());
|
||||
auto typefacePtr = font.getTypefacePtr();
|
||||
auto* typeface = dynamic_cast<WindowsDirectWriteTypeface*> (typefacePtr.get());
|
||||
currentFontFace = typeface->getIDWriteFontFace();
|
||||
fontHeightToEmSizeFactor = typeface->getUnitsToHeightScaleFactor();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -192,8 +192,9 @@ namespace DirectWriteTypeLayout
|
|||
for (int i = 0; i < attributedString.getNumAttributes(); ++i)
|
||||
{
|
||||
auto& font = attributedString.getAttribute(i).font;
|
||||
auto typeface = font.getTypefacePtr();
|
||||
|
||||
if (auto* wt = dynamic_cast<WindowsDirectWriteTypeface*> (font.getTypeface()))
|
||||
if (auto* wt = dynamic_cast<WindowsDirectWriteTypeface*> (typeface.get()))
|
||||
if (wt->getIDWriteFontFace() == glyphRun.fontFace)
|
||||
return font.withHeight (fontHeight);
|
||||
}
|
||||
|
|
@ -334,7 +335,7 @@ namespace DirectWriteTypeLayout
|
|||
Font defaultFont;
|
||||
BOOL fontFound = false;
|
||||
uint32 fontIndex;
|
||||
fontCollection.FindFamilyName (defaultFont.getTypeface()->getName().toWideCharPointer(), &fontIndex, &fontFound);
|
||||
fontCollection.FindFamilyName (defaultFont.getTypefacePtr()->getName().toWideCharPointer(), &fontIndex, &fontFound);
|
||||
|
||||
if (! fontFound)
|
||||
fontIndex = 0;
|
||||
|
|
@ -443,8 +444,9 @@ static bool canAllTypefacesAndFontsBeUsedInLayout (const AttributedString& text)
|
|||
for (int i = 0; i < numCharacterAttributes; ++i)
|
||||
{
|
||||
const auto& font = text.getAttribute (i).font;
|
||||
auto typeface = font.getTypefacePtr();
|
||||
|
||||
if (font.getHorizontalScale() != 1.0f || dynamic_cast<WindowsDirectWriteTypeface*> (font.getTypeface()) == nullptr)
|
||||
if (font.getHorizontalScale() != 1.0f || dynamic_cast<WindowsDirectWriteTypeface*> (typeface.get()) == nullptr)
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -300,7 +300,7 @@ Typeface::Ptr Font::getDefaultTypefaceForFont (const Font& font)
|
|||
static DefaultFontNames defaultNames;
|
||||
|
||||
Font newFont (font);
|
||||
auto& faceName = font.getTypefaceName();
|
||||
auto faceName = font.getTypefaceName();
|
||||
|
||||
if (faceName == getDefaultSansSerifFontName()) newFont.setTypefaceName (defaultNames.defaultSans);
|
||||
else if (faceName == getDefaultSerifFontName()) newFont.setTypefaceName (defaultNames.defaultSerif);
|
||||
|
|
|
|||
|
|
@ -1664,7 +1664,7 @@ struct SavedState : public RenderingHelpers::SavedStateBase<SavedState>
|
|||
auto t = transform.getTransformWith (AffineTransform::scale (fontHeight * font.getHorizontalScale(), fontHeight)
|
||||
.followedBy (trans));
|
||||
|
||||
const std::unique_ptr<EdgeTable> et (font.getTypeface()->getEdgeTableForGlyph (glyphNumber, t, fontHeight));
|
||||
const std::unique_ptr<EdgeTable> et (font.getTypefacePtr()->getEdgeTableForGlyph (glyphNumber, t, fontHeight));
|
||||
|
||||
if (et != nullptr)
|
||||
fillShape (*new EdgeTableRegionType (*et), false);
|
||||
|
|
|
|||
|
|
@ -62,6 +62,13 @@ public:
|
|||
|
||||
For information about how to trigger a render callback, see
|
||||
OpenGLContext::triggerRepaint() and OpenGLContext::setContinuousRepainting().
|
||||
|
||||
IMPORTANT: Never take a MessageManagerLock inside this function! On
|
||||
macOS, the OpenGL context will be locked for the duration of this call.
|
||||
The main thread may also attempt to interact with the OpenGL context at
|
||||
any time, which will also require locking the OpenGL context. As a
|
||||
result, taking a MessageManagerLock inside renderOpenGL() may cause a
|
||||
hierarchical deadlock.
|
||||
*/
|
||||
virtual void renderOpenGL() = 0;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue