mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-02-01 03:10:06 +00:00
Mac Fonts: Fix rendering of AttributedStrings with empty ranges
Previously, lifetime management of CTFontRefs was not implemented correctly. For zero-length ranges, the font may not be retained when applying it to a CFAttributedString, meaning that the reference stored in the fontMap sometimes became invalid before createCFAttributedString() returned. We now retain font refs when adding them to the font map, and release them when the map is destroyed, ensuring that the font references remain valid throughout the lifetime of the map.
This commit is contained in:
parent
3f315ddd00
commit
50dacbc8fc
1 changed files with 42 additions and 8 deletions
|
|
@ -208,15 +208,51 @@ namespace CoreTextTypeLayout
|
|||
}
|
||||
|
||||
//==============================================================================
|
||||
// A flatmap that properly retains/releases font refs
|
||||
class FontMap
|
||||
{
|
||||
public:
|
||||
void emplace (CTFontRef ctFontRef, Font value)
|
||||
{
|
||||
pairs.emplace (std::lower_bound (pairs.begin(), pairs.end(), ctFontRef), ctFontRef, std::move (value));
|
||||
}
|
||||
|
||||
const Font* find (CTFontRef ctFontRef) const
|
||||
{
|
||||
const auto iter = std::lower_bound (pairs.begin(), pairs.end(), ctFontRef);
|
||||
|
||||
if (iter == pairs.end())
|
||||
return nullptr;
|
||||
|
||||
if (iter->key.get() != ctFontRef)
|
||||
return nullptr;
|
||||
|
||||
return &iter->value;
|
||||
}
|
||||
|
||||
private:
|
||||
struct Pair
|
||||
{
|
||||
Pair (CTFontRef ref, Font font) : key (ref), value (std::move (font)) { CFRetain (ref); }
|
||||
|
||||
auto operator< (CTFontRef other) const { return key.get() < other; }
|
||||
|
||||
CFUniquePtr<CTFontRef> key;
|
||||
Font value;
|
||||
};
|
||||
|
||||
std::vector<Pair> pairs;
|
||||
};
|
||||
|
||||
struct AttributedStringAndFontMap
|
||||
{
|
||||
CFUniquePtr<CFAttributedStringRef> string;
|
||||
std::map<CTFontRef, Font> fontMap;
|
||||
FontMap fontMap;
|
||||
};
|
||||
|
||||
static AttributedStringAndFontMap createCFAttributedString (const AttributedString& text)
|
||||
{
|
||||
std::map<CTFontRef, Font> fontMap;
|
||||
FontMap fontMap;
|
||||
|
||||
const detail::ColorSpacePtr rgbColourSpace { CGColorSpaceCreateWithName (kCGColorSpaceSRGB) };
|
||||
|
||||
|
|
@ -300,7 +336,7 @@ namespace CoreTextTypeLayout
|
|||
struct FramesetterAndFontMap
|
||||
{
|
||||
CFUniquePtr<CTFramesetterRef> framesetter;
|
||||
std::map<CTFontRef, Font> fontMap;
|
||||
FontMap fontMap;
|
||||
};
|
||||
|
||||
static FramesetterAndFontMap createCTFramesetter (const AttributedString& text)
|
||||
|
|
@ -324,7 +360,7 @@ namespace CoreTextTypeLayout
|
|||
struct FrameAndFontMap
|
||||
{
|
||||
CFUniquePtr<CTFrameRef> frame;
|
||||
std::map<CTFontRef, Font> fontMap;
|
||||
FontMap fontMap;
|
||||
};
|
||||
|
||||
static FrameAndFontMap createCTFrame (const AttributedString& text, CGRect bounds)
|
||||
|
|
@ -476,10 +512,8 @@ namespace CoreTextTypeLayout
|
|||
{
|
||||
glyphRun->font = [&]
|
||||
{
|
||||
auto it = frameAndMap.fontMap.find (ctRunFont);
|
||||
|
||||
if (it != frameAndMap.fontMap.end())
|
||||
return it->second;
|
||||
if (auto* it = frameAndMap.fontMap.find (ctRunFont))
|
||||
return *it;
|
||||
|
||||
CFUniquePtr<CFStringRef> cfsFontName (CTFontCopyPostScriptName (ctRunFont));
|
||||
CFUniquePtr<CTFontRef> ctFontRef (CTFontCreateWithName (cfsFontName.get(), referenceFontSize, nullptr));
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue