Make SkFunctionWrapper a better wrapper.
SkFunctionWrapper was made to be a simple abstraction over existing resource release functions which generally follow a specific pattern of returning void and taking a pointer to the underlying type. However, this has been observed to be an unnecessary limit. This makes it more generic while also making the call sites a little less brittle. This change also uncovered an issue in msvc v19.20 to v19.22, see https://developercommunity.visualstudio.com/content/problem/698192/in-templateusing-decltype-is-void.html To work around this, several otherwise redundant '&' are used. There was an attempt to take references to functions instead of pointers to functions which greatly simplifies the intermediate wrappers. However, that uncovered another issue in msvc, see https://developercommunity.visualstudio.com/content/problem/699878/function-to-pointer.html Change-Id: I54ab945ed9d9cfd0204d4d6650c2fde47cc9e175 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/235105 Commit-Queue: Ben Wagner <bungeman@google.com> Reviewed-by: Herb Derby <herb@google.com>
This commit is contained in:
parent
6f1ff9fca1
commit
723a877d0c
@ -47,8 +47,12 @@ template <typename D, typename S> static D* SkTAddOffset(S* ptr, size_t byteOffs
|
||||
return reinterpret_cast<D*>(reinterpret_cast<sknonstd::same_cv_t<char, D>*>(ptr) + byteOffset);
|
||||
}
|
||||
|
||||
template <typename R, typename T, R (*P)(T*)> struct SkFunctionWrapper {
|
||||
R operator()(T* t) { return P(t); }
|
||||
// TODO: when C++17 the language is available, use template <auto P>
|
||||
template <typename T, T* P> struct SkFunctionWrapper {
|
||||
template <typename... Args>
|
||||
auto operator()(Args&&... args) const -> decltype(P(std::forward<Args>(args)...)) {
|
||||
return P(std::forward<Args>(args)...);
|
||||
}
|
||||
};
|
||||
|
||||
/** \class SkAutoTCallVProc
|
||||
@ -60,9 +64,10 @@ template <typename R, typename T, R (*P)(T*)> struct SkFunctionWrapper {
|
||||
function.
|
||||
*/
|
||||
template <typename T, void (*P)(T*)> class SkAutoTCallVProc
|
||||
: public std::unique_ptr<T, SkFunctionWrapper<void, T, P>> {
|
||||
: public std::unique_ptr<T, SkFunctionWrapper<skstd::remove_pointer_t<decltype(P)>, P>> {
|
||||
public:
|
||||
SkAutoTCallVProc(T* obj): std::unique_ptr<T, SkFunctionWrapper<void, T, P>>(obj) {}
|
||||
SkAutoTCallVProc(T* obj)
|
||||
: std::unique_ptr<T, SkFunctionWrapper<skstd::remove_pointer_t<decltype(P)>, P>>(obj) {}
|
||||
|
||||
operator T*() const { return this->get(); }
|
||||
};
|
||||
@ -259,7 +264,7 @@ public:
|
||||
T* release() { return fPtr.release(); }
|
||||
|
||||
private:
|
||||
std::unique_ptr<T, SkFunctionWrapper<void, void, sk_free>> fPtr;
|
||||
std::unique_ptr<T, SkFunctionWrapper<decltype(sk_free), sk_free>> fPtr;
|
||||
};
|
||||
|
||||
template <size_t kCountRequested, typename T> class SkAutoSTMalloc {
|
||||
@ -434,7 +439,7 @@ private:
|
||||
SkAlignedSStorage<sizeof(T)*N> fStorage;
|
||||
};
|
||||
|
||||
using SkAutoFree = std::unique_ptr<void, SkFunctionWrapper<void, void, sk_free>>;
|
||||
using SkAutoFree = std::unique_ptr<void, SkFunctionWrapper<decltype(sk_free), sk_free>>;
|
||||
|
||||
template<typename C, std::size_t... Is>
|
||||
constexpr auto SkMakeArrayFromIndexSequence(C c, skstd::index_sequence<Is...>)
|
||||
|
@ -25,10 +25,9 @@ bool TextBreaker::initialize(SkSpan<const char> text, UBreakIteratorType type) {
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
fIterator = nullptr;
|
||||
fSize = text.size();
|
||||
UText utf8UText = UTEXT_INITIALIZER;
|
||||
utext_openUTF8(&utf8UText, text.begin(), text.size(), &status);
|
||||
fAutoClose =
|
||||
std::unique_ptr<UText, SkFunctionWrapper<UText*, UText, utext_close>>(&utf8UText);
|
||||
UText sUtf8UText = UTEXT_INITIALIZER;
|
||||
std::unique_ptr<UText, SkFunctionWrapper<decltype(utext_close), utext_close>> utf8UText(
|
||||
utext_openUTF8(&sUtf8UText, text.begin(), text.size(), &status));
|
||||
if (U_FAILURE(status)) {
|
||||
SkDebugf("Could not create utf8UText: %s", u_errorName(status));
|
||||
return false;
|
||||
@ -39,7 +38,7 @@ bool TextBreaker::initialize(SkSpan<const char> text, UBreakIteratorType type) {
|
||||
SK_ABORT("");
|
||||
}
|
||||
|
||||
ubrk_setUText(fIterator.get(), &utf8UText, &status);
|
||||
ubrk_setUText(fIterator.get(), utf8UText.get(), &status);
|
||||
if (U_FAILURE(status)) {
|
||||
SkDebugf("Could not setText on break iterator: %s", u_errorName(status));
|
||||
return false;
|
||||
|
@ -75,8 +75,7 @@ public:
|
||||
bool eof() { return fPos == icu::BreakIterator::DONE; }
|
||||
|
||||
private:
|
||||
std::unique_ptr<UText, SkFunctionWrapper<UText*, UText, utext_close>> fAutoClose;
|
||||
std::unique_ptr<UBreakIterator, SkFunctionWrapper<void, UBreakIterator, ubrk_close>> fIterator;
|
||||
std::unique_ptr<UBreakIterator, SkFunctionWrapper<decltype(ubrk_close), ubrk_close>> fIterator;
|
||||
bool fInitialized;
|
||||
int32_t fPos;
|
||||
size_t fSize;
|
||||
|
@ -55,13 +55,15 @@ template <> struct is_bitmask_enum<hb_buffer_flags_t> : std::true_type {};
|
||||
}
|
||||
|
||||
namespace {
|
||||
template <class T, void(*P)(T*)> using resource = std::unique_ptr<T, SkFunctionWrapper<void, T, P>>;
|
||||
using HBBlob = resource<hb_blob_t , hb_blob_destroy >;
|
||||
using HBFace = resource<hb_face_t , hb_face_destroy >;
|
||||
using HBFont = resource<hb_font_t , hb_font_destroy >;
|
||||
using HBBuffer = resource<hb_buffer_t , hb_buffer_destroy>;
|
||||
using ICUBiDi = resource<UBiDi , ubidi_close >;
|
||||
using ICUBrk = resource<UBreakIterator, ubrk_close >;
|
||||
template <typename T, void(*P)(T*)> using resource =
|
||||
std::unique_ptr<T, SkFunctionWrapper<skstd::remove_pointer_t<decltype(P)>, P>>;
|
||||
using HBBlob = resource<hb_blob_t , &hb_blob_destroy >;
|
||||
using HBFace = resource<hb_face_t , &hb_face_destroy >;
|
||||
using HBFont = resource<hb_font_t , &hb_font_destroy >;
|
||||
using HBBuffer = resource<hb_buffer_t , &hb_buffer_destroy>;
|
||||
using ICUBiDi = resource<UBiDi , &ubidi_close >;
|
||||
using ICUBrk = resource<UBreakIterator, &ubrk_close >;
|
||||
using ICUUText = std::unique_ptr<UText, SkFunctionWrapper<decltype(utext_close), utext_close>>;
|
||||
|
||||
HBBlob stream_to_blob(std::unique_ptr<SkStreamAsset> asset) {
|
||||
size_t size = asset->getLength();
|
||||
@ -863,14 +865,13 @@ void ShaperDrivenWrapper::wrap(char const * const utf8, size_t utf8Bytes,
|
||||
UBreakIterator& breakIterator = *fLineBreakIterator;
|
||||
{
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
UText utf8UText = UTEXT_INITIALIZER;
|
||||
utext_openUTF8(&utf8UText, utf8Start, utf8runLength, &status);
|
||||
std::unique_ptr<UText, SkFunctionWrapper<UText*, UText, utext_close>> autoClose(&utf8UText);
|
||||
UText sUtf8UText = UTEXT_INITIALIZER;
|
||||
ICUUText utf8UText(utext_openUTF8(&sUtf8UText, utf8Start, utf8runLength, &status));
|
||||
if (U_FAILURE(status)) {
|
||||
SkDebugf("Could not create utf8UText: %s", u_errorName(status));
|
||||
return;
|
||||
}
|
||||
ubrk_setUText(&breakIterator, &utf8UText, &status);
|
||||
ubrk_setUText(&breakIterator, utf8UText.get(), &status);
|
||||
if (U_FAILURE(status)) {
|
||||
SkDebugf("Could not setText on break iterator: %s", u_errorName(status));
|
||||
return;
|
||||
@ -966,20 +967,19 @@ void ShapeThenWrap::wrap(char const * const utf8, size_t utf8Bytes,
|
||||
UBreakIterator& graphemeBreakIterator = *fGraphemeBreakIterator;
|
||||
{
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
UText utf8UText = UTEXT_INITIALIZER;
|
||||
utext_openUTF8(&utf8UText, utf8, utf8Bytes, &status);
|
||||
std::unique_ptr<UText, SkFunctionWrapper<UText*, UText, utext_close>> autoClose(&utf8UText);
|
||||
UText sUtf8UText = UTEXT_INITIALIZER;
|
||||
ICUUText utf8UText(utext_openUTF8(&sUtf8UText, utf8, utf8Bytes, &status));
|
||||
if (U_FAILURE(status)) {
|
||||
SkDebugf("Could not create utf8UText: %s", u_errorName(status));
|
||||
return;
|
||||
}
|
||||
|
||||
ubrk_setUText(&lineBreakIterator, &utf8UText, &status);
|
||||
ubrk_setUText(&lineBreakIterator, utf8UText.get(), &status);
|
||||
if (U_FAILURE(status)) {
|
||||
SkDebugf("Could not setText on line break iterator: %s", u_errorName(status));
|
||||
return;
|
||||
}
|
||||
ubrk_setUText(&graphemeBreakIterator, &utf8UText, &status);
|
||||
ubrk_setUText(&graphemeBreakIterator, utf8UText.get(), &status);
|
||||
if (U_FAILURE(status)) {
|
||||
SkDebugf("Could not setText on grapheme break iterator: %s", u_errorName(status));
|
||||
return;
|
||||
|
@ -237,7 +237,7 @@ template <> struct SkMask::AlphaIter<SkMask::kLCD16_Format> {
|
||||
* Stack class used to manage the fImage buffer in a SkMask.
|
||||
* When this object loses scope, the buffer is freed with SkMask::FreeImage().
|
||||
*/
|
||||
using SkAutoMaskFreeImage = std::unique_ptr<uint8_t,SkFunctionWrapper<void,void,SkMask::FreeImage>>;
|
||||
using SkAutoMaskFreeImage = std::unique_ptr<uint8_t, SkFunctionWrapper<decltype(SkMask::FreeImage), SkMask::FreeImage>>;
|
||||
#define SkAutoMaskFreeImage(...) SK_REQUIRE_LOCAL_VAR(SkAutoMaskFreeImage)
|
||||
|
||||
#endif
|
||||
|
@ -16,11 +16,12 @@
|
||||
#include "hb.h"
|
||||
#include "hb-subset.h"
|
||||
|
||||
template <class T, void(*P)(T*)> using resource = std::unique_ptr<T, SkFunctionWrapper<void, T, P>>;
|
||||
using HBBlob = resource<hb_blob_t, hb_blob_destroy>;
|
||||
using HBFace = resource<hb_face_t, hb_face_destroy>;
|
||||
using HBSubsetInput = resource<hb_subset_input_t, hb_subset_input_destroy>;
|
||||
using HBSet = resource<hb_set_t, hb_set_destroy>;
|
||||
template <class T, void(*P)(T*)> using resource =
|
||||
std::unique_ptr<T, SkFunctionWrapper<skstd::remove_pointer_t<decltype(P)>, P>>;
|
||||
using HBBlob = resource<hb_blob_t, &hb_blob_destroy>;
|
||||
using HBFace = resource<hb_face_t, &hb_face_destroy>;
|
||||
using HBSubsetInput = resource<hb_subset_input_t, &hb_subset_input_destroy>;
|
||||
using HBSet = resource<hb_set_t, &hb_set_destroy>;
|
||||
|
||||
static HBBlob to_blob(sk_sp<SkData> data) {
|
||||
using blob_size_t = SkCallableTraits<decltype(hb_blob_create)>::argument<1>::type;
|
||||
|
@ -297,7 +297,7 @@ static void unref_ft_library() {
|
||||
|
||||
struct SkFaceRec {
|
||||
SkFaceRec* fNext;
|
||||
std::unique_ptr<FT_FaceRec, SkFunctionWrapper<FT_Error, FT_FaceRec, FT_Done_Face>> fFace;
|
||||
std::unique_ptr<FT_FaceRec, SkFunctionWrapper<decltype(FT_Done_Face), FT_Done_Face>> fFace;
|
||||
FT_StreamRec fFTStream;
|
||||
std::unique_ptr<SkStreamAsset> fSkStream;
|
||||
uint32_t fRefCnt;
|
||||
@ -529,7 +529,7 @@ protected:
|
||||
void generateFontMetrics(SkFontMetrics*) override;
|
||||
|
||||
private:
|
||||
using UnrefFTFace = SkFunctionWrapper<void, SkFaceRec, unref_ft_face>;
|
||||
using UnrefFTFace = SkFunctionWrapper<decltype(unref_ft_face), unref_ft_face>;
|
||||
std::unique_ptr<SkFaceRec, UnrefFTFace> fFaceRec;
|
||||
|
||||
FT_Face fFace; // Borrowed face from gFaceRecHead.
|
||||
@ -932,7 +932,7 @@ SkScalerContext_FreeType::SkScalerContext_FreeType(sk_sp<SkTypeface> typeface,
|
||||
fLoadGlyphFlags = loadFlags;
|
||||
}
|
||||
|
||||
using DoneFTSize = SkFunctionWrapper<FT_Error, skstd::remove_pointer_t<FT_Size>, FT_Done_Size>;
|
||||
using DoneFTSize = SkFunctionWrapper<decltype(FT_Done_Size), FT_Done_Size>;
|
||||
std::unique_ptr<skstd::remove_pointer_t<FT_Size>, DoneFTSize> ftSize([this]() -> FT_Size {
|
||||
FT_Size size;
|
||||
FT_Error err = FT_New_Size(fFaceRec->fFace.get(), &size);
|
||||
|
@ -51,7 +51,7 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
std::unique_ptr<uint32_t, SkFunctionWrapper<void, void, sk_free>> fBitData;
|
||||
std::unique_ptr<uint32_t, SkFunctionWrapper<decltype(sk_free), sk_free>> fBitData;
|
||||
size_t fDwordCount; // Dword (32-bit) count of the bitset.
|
||||
|
||||
uint32_t* internalGet(int index) const {
|
||||
|
@ -19,7 +19,7 @@
|
||||
|
||||
template <typename CFRef> using SkUniqueCFRef =
|
||||
std::unique_ptr<skstd::remove_pointer_t<CFRef>,
|
||||
SkFunctionWrapper<void, skstd::remove_pointer_t<CFTypeRef>, CFRelease>>;
|
||||
SkFunctionWrapper<decltype(CFRelease), CFRelease>>;
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user