Replace manual memory allocation / deletion with a unique_ptr.
Add ScopedDIBitmap, which is std::unique_ptr with a custom deleter, to
remove a case with manual memory management.
Also fix some nits along the way:
- Rename (anonymous_namespace)::LoadDIBitmap(), so it does not clash
with CGdiplusExt::LoadDIBitmap().
- Remove / more narrowly scope a couple of variables.
Change-Id: I1b5d331c1222c0a8bd23e3ec61eef575a464864c
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/75570
Reviewed-by: Hui Yingst <nigi@chromium.org>
Commit-Queue: Lei Zhang <thestig@chromium.org>
diff --git a/core/fxge/win32/cgdi_plus_ext.cpp b/core/fxge/win32/cgdi_plus_ext.cpp
index c5d48d2..8dcb453 100644
--- a/core/fxge/win32/cgdi_plus_ext.cpp
+++ b/core/fxge/win32/cgdi_plus_ext.cpp
@@ -659,28 +659,45 @@
GpStream* pStream;
};
-PREVIEW3_DIBITMAP* LoadDIBitmap(WINDIB_Open_Args_ args) {
+struct DIBitmapDeleter {
+ void operator()(PREVIEW3_DIBITMAP* bitmap) const {
+ const CGdiplusExt& GdiplusExt = GetGdiplusExt();
+ CallFunc(GdipBitmapUnlockBits)(bitmap->pBitmap, bitmap->pBitmapData);
+ CallFunc(GdipDisposeImage)(bitmap->pBitmap);
+ FX_Free(bitmap->pBitmapData);
+ FX_Free((LPBYTE)bitmap->pbmi);
+ if (bitmap->pStream)
+ bitmap->pStream->Release();
+ FX_Free(bitmap);
+ }
+};
+
+using ScopedDIBitmap = std::unique_ptr<PREVIEW3_DIBITMAP, DIBitmapDeleter>;
+
+ScopedDIBitmap LoadDIBitmapImpl(WINDIB_Open_Args_ args) {
Gdiplus::GpBitmap* pBitmap;
GpStream* pStream = nullptr;
const CGdiplusExt& GdiplusExt = GetGdiplusExt();
- Gdiplus::Status status = Gdiplus::Ok;
if (args.flags == WINDIB_OPEN_PATHNAME) {
- status = CallFunc(GdipCreateBitmapFromFileICM)(args.path_name, &pBitmap);
+ if (CallFunc(GdipCreateBitmapFromFileICM)(args.path_name, &pBitmap) !=
+ Gdiplus::Ok) {
+ return nullptr;
+ }
} else {
if (args.memory_size == 0 || !args.memory_base)
return nullptr;
pStream = new GpStream;
pStream->Write(args.memory_base, (ULONG)args.memory_size, nullptr);
- status = CallFunc(GdipCreateBitmapFromStreamICM)(pStream, &pBitmap);
- }
- if (status != Gdiplus::Ok) {
- if (pStream)
+ if (CallFunc(GdipCreateBitmapFromStreamICM)(pStream, &pBitmap) !=
+ Gdiplus::Ok) {
pStream->Release();
-
- return nullptr;
+ return nullptr;
+ }
}
- UINT height, width;
+
+ UINT height;
+ UINT width;
CallFunc(GdipGetImageHeight)(pBitmap, &height);
CallFunc(GdipGetImageWidth)(pBitmap, &width);
Gdiplus::PixelFormat pixel_format;
@@ -727,7 +744,7 @@
ppal[i] = pal.Entries[i] & 0x00ffffff;
}
}
- PREVIEW3_DIBITMAP* pInfo = FX_Alloc(PREVIEW3_DIBITMAP, 1);
+ ScopedDIBitmap pInfo(FX_Alloc(PREVIEW3_DIBITMAP, 1));
pInfo->pbmi = (BITMAPINFO*)buf;
pInfo->pScan0 = (LPBYTE)pBitmapData->Scan0;
pInfo->Stride = pBitmapData->Stride;
@@ -737,17 +754,6 @@
return pInfo;
}
-void FreeDIBitmap(PREVIEW3_DIBITMAP* pInfo) {
- const CGdiplusExt& GdiplusExt = GetGdiplusExt();
- CallFunc(GdipBitmapUnlockBits)(pInfo->pBitmap, pInfo->pBitmapData);
- CallFunc(GdipDisposeImage)(pInfo->pBitmap);
- FX_Free(pInfo->pBitmapData);
- FX_Free((LPBYTE)pInfo->pbmi);
- if (pInfo->pStream)
- pInfo->pStream->Release();
- FX_Free(pInfo);
-}
-
} // namespace
CGdiplusExt::CGdiplusExt() = default;
@@ -975,7 +981,7 @@
}
RetainPtr<CFX_DIBitmap> CGdiplusExt::LoadDIBitmap(WINDIB_Open_Args_ args) {
- PREVIEW3_DIBITMAP* pInfo = ::LoadDIBitmap(args);
+ ScopedDIBitmap pInfo = LoadDIBitmapImpl(args);
if (!pInfo)
return nullptr;
@@ -994,6 +1000,5 @@
RetainPtr<CFX_DIBitmap> pDIBitmap =
CFX_WindowsDIB::LoadFromBuf(pInfo->pbmi, pData);
FX_Free(pData);
- FreeDIBitmap(pInfo);
return pDIBitmap;
}