diff options
author | Michael Lutz <michi@icosahedron.de> | 2019-09-01 15:27:39 +0200 |
---|---|---|
committer | Michael Lutz <michi@icosahedron.de> | 2019-11-01 22:32:53 +0100 |
commit | d5a9bd404a3ca90a18abeeaaaabdbf5185437ba7 (patch) | |
tree | 5dc82f54f00bc5633e4131d7c77f988367beb425 /src/os/macosx | |
parent | 58122983fb1284270a4fd9f420b1c3a3a3605bcb (diff) | |
download | openttd-d5a9bd404a3ca90a18abeeaaaabdbf5185437ba7.tar.xz |
Codechange: [OSX] Use std::unique_ptr with a custom deleter to simply memory management of Core Foundation types.
Diffstat (limited to 'src/os/macosx')
-rw-r--r-- | src/os/macosx/macos.h | 13 | ||||
-rw-r--r-- | src/os/macosx/string_osx.cpp | 102 |
2 files changed, 50 insertions, 65 deletions
diff --git a/src/os/macosx/macos.h b/src/os/macosx/macos.h index 4204d93bb..12e41cd25 100644 --- a/src/os/macosx/macos.h +++ b/src/os/macosx/macos.h @@ -40,4 +40,17 @@ bool IsMonospaceFont(CFStringRef name); void MacOSSetThreadName(const char *name); + +/** Deleter that calls CFRelease rather than deleting the pointer. */ +template <typename T> struct CFDeleter { + void operator()(T *p) + { + if (p) ::CFRelease(p); + } +}; + +/** Specialisation of std::unique_ptr for CoreFoundation objects. */ +template <typename T> +using CFAutoRelease = std::unique_ptr<typename std::remove_pointer<T>::type, CFDeleter<typename std::remove_pointer<T>::type>>; + #endif /* MACOS_H */ diff --git a/src/os/macosx/string_osx.cpp b/src/os/macosx/string_osx.cpp index 6e5916e7c..a3d674658 100644 --- a/src/os/macosx/string_osx.cpp +++ b/src/os/macosx/string_osx.cpp @@ -22,9 +22,9 @@ #if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5) /** Cached current locale. */ -static CFLocaleRef _osx_locale = nullptr; +static CFAutoRelease<CFLocaleRef> _osx_locale; /** CoreText cache for font information, cleared when OTTD changes fonts. */ -static CTFontRef _font_cache[FS_END]; +static CFAutoRelease<CTFontRef> _font_cache[FS_END]; /** @@ -36,7 +36,7 @@ private: ptrdiff_t length; const FontMap& font_map; - CTTypesetterRef typesetter; + CFAutoRelease<CTTypesetterRef> typesetter; CFIndex cur_offset = 0; ///< Offset from the start of the current run from where to output. @@ -68,9 +68,9 @@ public: /** A single line worth of VisualRuns. */ class CoreTextLine : public std::vector<CoreTextVisualRun>, public ParagraphLayouter::Line { public: - CoreTextLine(CTLineRef line, const FontMap &fontMapping, const CoreTextParagraphLayoutFactory::CharType *buff) + CoreTextLine(CFAutoRelease<CTLineRef> line, const FontMap &fontMapping, const CoreTextParagraphLayoutFactory::CharType *buff) { - CFArrayRef runs = CTLineGetGlyphRuns(line); + CFArrayRef runs = CTLineGetGlyphRuns(line.get()); for (CFIndex i = 0; i < CFArrayGetCount(runs); i++) { CTRunRef run = (CTRunRef)CFArrayGetValueAtIndex(runs, i); @@ -81,7 +81,6 @@ public: this->emplace_back(run, map->second, buff); } - CFRelease(line); } int GetLeading() const override; @@ -96,16 +95,11 @@ public: } }; - CoreTextParagraphLayout(CTTypesetterRef typesetter, const CoreTextParagraphLayoutFactory::CharType *buffer, ptrdiff_t len, const FontMap &fontMapping) : text_buffer(buffer), length(len), font_map(fontMapping), typesetter(typesetter) + CoreTextParagraphLayout(CFAutoRelease<CTTypesetterRef> typesetter, const CoreTextParagraphLayoutFactory::CharType *buffer, ptrdiff_t len, const FontMap &fontMapping) : text_buffer(buffer), length(len), font_map(fontMapping), typesetter(std::move(typesetter)) { this->Reflow(); } - ~CoreTextParagraphLayout() override - { - CFRelease(this->typesetter); - } - void Reflow() override { this->cur_offset = 0; @@ -143,12 +137,11 @@ static CTRunDelegateCallbacks _sprite_font_callback = { } /* Make attributed string with embedded font information. */ - CFMutableAttributedStringRef str = CFAttributedStringCreateMutable(kCFAllocatorDefault, 0); - CFAttributedStringBeginEditing(str); + CFAutoRelease<CFMutableAttributedStringRef> str(CFAttributedStringCreateMutable(kCFAllocatorDefault, 0)); + CFAttributedStringBeginEditing(str.get()); - CFStringRef base = CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault, buff, length, kCFAllocatorNull); - CFAttributedStringReplaceString(str, CFRangeMake(0, 0), base); - CFRelease(base); + CFAutoRelease<CFStringRef> base(CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault, buff, length, kCFAllocatorNull)); + CFAttributedStringReplaceString(str.get(), CFRangeMake(0, 0), base.get()); /* Apply font and colour ranges to our string. This is important to make sure * that we get proper glyph boundaries on style changes. */ @@ -156,36 +149,33 @@ static CTRunDelegateCallbacks _sprite_font_callback = { for (const auto &i : fontMapping) { if (i.first - last == 0) continue; - if (_font_cache[i.second->fc->GetSize()] == nullptr) { + if (!_font_cache[i.second->fc->GetSize()]) { /* Cache font information. */ - CFStringRef font_name = CFStringCreateWithCString(kCFAllocatorDefault, i.second->fc->GetFontName(), kCFStringEncodingUTF8); - _font_cache[i.second->fc->GetSize()] = CTFontCreateWithName(font_name, i.second->fc->GetFontSize(), nullptr); - CFRelease(font_name); + CFAutoRelease<CFStringRef> font_name(CFStringCreateWithCString(kCFAllocatorDefault, i.second->fc->GetFontName(), kCFStringEncodingUTF8)); + _font_cache[i.second->fc->GetSize()].reset(CTFontCreateWithName(font_name.get(), i.second->fc->GetFontSize(), nullptr)); } - CFAttributedStringSetAttribute(str, CFRangeMake(last, i.first - last), kCTFontAttributeName, _font_cache[i.second->fc->GetSize()]); + CFAttributedStringSetAttribute(str.get(), CFRangeMake(last, i.first - last), kCTFontAttributeName, _font_cache[i.second->fc->GetSize()].get()); CGColorRef color = CGColorCreateGenericGray((uint8)i.second->colour / 255.0f, 1.0f); // We don't care about the real colours, just that they are different. - CFAttributedStringSetAttribute(str, CFRangeMake(last, i.first - last), kCTForegroundColorAttributeName, color); + CFAttributedStringSetAttribute(str.get(), CFRangeMake(last, i.first - last), kCTForegroundColorAttributeName, color); CGColorRelease(color); /* Install a size callback for our special sprite glyphs. */ for (ssize_t c = last; c < i.first; c++) { if (buff[c] >= SCC_SPRITE_START && buff[c] <= SCC_SPRITE_END) { - CTRunDelegateRef del = CTRunDelegateCreate(&_sprite_font_callback, (void *)(size_t)(buff[c] | (i.second->fc->GetSize() << 24))); - CFAttributedStringSetAttribute(str, CFRangeMake(c, 1), kCTRunDelegateAttributeName, del); - CFRelease(del); + CFAutoRelease<CTRunDelegateRef> del(CTRunDelegateCreate(&_sprite_font_callback, (void *)(size_t)(buff[c] | (i.second->fc->GetSize() << 24)))); + CFAttributedStringSetAttribute(str.get(), CFRangeMake(c, 1), kCTRunDelegateAttributeName, del.get()); } } last = i.first; } - CFAttributedStringEndEditing(str); + CFAttributedStringEndEditing(str.get()); /* Create and return typesetter for the string. */ - CTTypesetterRef typesetter = CTTypesetterCreateWithAttributedString(str); - CFRelease(str); + CFAutoRelease<CTTypesetterRef> typesetter(CTTypesetterCreateWithAttributedString(str.get())); - return typesetter != nullptr ? new CoreTextParagraphLayout(typesetter, buff, length, fontMapping) : nullptr; + return typesetter ? new CoreTextParagraphLayout(std::move(typesetter), buff, length, fontMapping) : nullptr; } /* virtual */ std::unique_ptr<const ParagraphLayouter::Line> CoreTextParagraphLayout::NextLine(int max_width) @@ -193,14 +183,14 @@ static CTRunDelegateCallbacks _sprite_font_callback = { if (this->cur_offset >= this->length) return nullptr; /* Get line break position, trying word breaking first and breaking somewhere if that doesn't work. */ - CFIndex len = CTTypesetterSuggestLineBreak(this->typesetter, this->cur_offset, max_width); - if (len <= 0) len = CTTypesetterSuggestClusterBreak(this->typesetter, this->cur_offset, max_width); + CFIndex len = CTTypesetterSuggestLineBreak(this->typesetter.get(), this->cur_offset, max_width); + if (len <= 0) len = CTTypesetterSuggestClusterBreak(this->typesetter.get(), this->cur_offset, max_width); /* Create line. */ - CTLineRef line = CTTypesetterCreateLine(this->typesetter, CFRangeMake(this->cur_offset, len)); + CFAutoRelease<CTLineRef> line(CTTypesetterCreateLine(this->typesetter.get(), CFRangeMake(this->cur_offset, len))); this->cur_offset += len; - return std::unique_ptr<const Line>(line != nullptr ? new CoreTextLine(line, this->font_map, this->text_buffer) : nullptr); + return std::unique_ptr<const Line>(line ? new CoreTextLine(std::move(line), this->font_map, this->text_buffer) : nullptr); } CoreTextParagraphLayout::CoreTextVisualRun::CoreTextVisualRun(CTRunRef run, Font *font, const CoreTextParagraphLayoutFactory::CharType *buff) : font(font) @@ -271,10 +261,7 @@ int CoreTextParagraphLayout::CoreTextLine::GetWidth() const /** Delete CoreText font reference for a specific font size. */ void MacOSResetScriptCache(FontSize size) { - if (_font_cache[size] != nullptr) { - CFRelease(_font_cache[size]); - _font_cache[size] = nullptr; - } + _font_cache[size].reset(); } /** Store current language locale as a CoreFounation locale. */ @@ -282,11 +269,8 @@ void MacOSSetCurrentLocaleName(const char *iso_code) { if (!MacOSVersionIsAtLeast(10, 5, 0)) return; - if (_osx_locale != nullptr) CFRelease(_osx_locale); - - CFStringRef iso = CFStringCreateWithCString(kCFAllocatorDefault, iso_code, kCFStringEncodingUTF8); - _osx_locale = CFLocaleCreate(kCFAllocatorDefault, iso); - CFRelease(iso); + CFAutoRelease<CFStringRef> iso(CFStringCreateWithCString(kCFAllocatorDefault, iso_code, kCFStringEncodingUTF8)); + _osx_locale.reset(CFLocaleCreate(kCFAllocatorDefault, iso.get())); } /** @@ -303,22 +287,13 @@ int MacOSStringCompare(const char *s1, const char *s2) CFStringCompareFlags flags = kCFCompareCaseInsensitive | kCFCompareNumerically | kCFCompareLocalized | kCFCompareWidthInsensitive | kCFCompareForcedOrdering; - CFStringRef cf1 = CFStringCreateWithCString(kCFAllocatorDefault, s1, kCFStringEncodingUTF8); - CFStringRef cf2 = CFStringCreateWithCString(kCFAllocatorDefault, s2, kCFStringEncodingUTF8); + CFAutoRelease<CFStringRef> cf1(CFStringCreateWithCString(kCFAllocatorDefault, s1, kCFStringEncodingUTF8)); + CFAutoRelease<CFStringRef> cf2(CFStringCreateWithCString(kCFAllocatorDefault, s2, kCFStringEncodingUTF8)); /* If any CFString could not be created (e.g., due to UTF8 invalid chars), return OS unsupported functionality */ - if (cf1 == nullptr || cf2 == nullptr) { - if (cf1 != nullptr) CFRelease(cf1); - if (cf2 != nullptr) CFRelease(cf2); - return 0; - } - - CFComparisonResult res = CFStringCompareWithOptionsAndLocale(cf1, cf2, CFRangeMake(0, CFStringGetLength(cf1)), flags, _osx_locale); + if (cf1 == nullptr || cf2 == nullptr) return 0; - CFRelease(cf1); - CFRelease(cf2); - - return (int)res + 2; + return (int)CFStringCompareWithOptionsAndLocale(cf1.get(), cf2.get(), CFRangeMake(0, CFStringGetLength(cf1.get())), flags, _osx_locale.get()) + 2; } @@ -353,30 +328,27 @@ int MacOSStringCompare(const char *s1, const char *s2) this->str_info.resize(utf16_to_utf8.size()); if (utf16_str.size() > 0) { - CFStringRef str = CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault, &utf16_str[0], utf16_str.size(), kCFAllocatorNull); + CFAutoRelease<CFStringRef> str(CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault, &utf16_str[0], utf16_str.size(), kCFAllocatorNull)); /* Get cluster breaks. */ - for (CFIndex i = 0; i < CFStringGetLength(str); ) { - CFRange r = CFStringGetRangeOfComposedCharactersAtIndex(str, i); + for (CFIndex i = 0; i < CFStringGetLength(str.get()); ) { + CFRange r = CFStringGetRangeOfComposedCharactersAtIndex(str.get(), i); this->str_info[r.location].char_stop = true; i += r.length; } /* Get word breaks. */ - CFStringTokenizerRef tokenizer = CFStringTokenizerCreate(kCFAllocatorDefault, str, CFRangeMake(0, CFStringGetLength(str)), kCFStringTokenizerUnitWordBoundary, _osx_locale); + CFAutoRelease<CFStringTokenizerRef> tokenizer(CFStringTokenizerCreate(kCFAllocatorDefault, str.get(), CFRangeMake(0, CFStringGetLength(str.get())), kCFStringTokenizerUnitWordBoundary, _osx_locale.get())); CFStringTokenizerTokenType tokenType = kCFStringTokenizerTokenNone; - while ((tokenType = CFStringTokenizerAdvanceToNextToken(tokenizer)) != kCFStringTokenizerTokenNone) { + while ((tokenType = CFStringTokenizerAdvanceToNextToken(tokenizer.get())) != kCFStringTokenizerTokenNone) { /* Skip tokens that are white-space or punctuation tokens. */ if ((tokenType & kCFStringTokenizerTokenHasNonLettersMask) != kCFStringTokenizerTokenHasNonLettersMask) { - CFRange r = CFStringTokenizerGetCurrentTokenRange(tokenizer); + CFRange r = CFStringTokenizerGetCurrentTokenRange(tokenizer.get()); this->str_info[r.location].word_stop = true; } } - - CFRelease(tokenizer); - CFRelease(str); } /* End-of-string is always a valid stopping point. */ |