graphics::make throws std::bad_alloc when it fails

This commit is contained in:
Jinhao
2017-09-27 08:13:55 +08:00
parent 13761be5e9
commit 8d9351e051

View File

@@ -293,7 +293,7 @@ namespace paint
void graphics::make(const ::nana::size& sz) void graphics::make(const ::nana::size& sz)
{ {
if(impl_->handle == nullptr || impl_->size != sz) if (impl_->handle == nullptr || impl_->size != sz)
{ {
if (sz.empty()) if (sz.empty())
{ {
@@ -302,9 +302,10 @@ namespace paint
} }
//The object will be delete while dwptr_ is performing a release. //The object will be delete while dwptr_ is performing a release.
drawable_type dw = new nana::detail::drawable_impl_type; std::shared_ptr<nana::detail::drawable_impl_type> dw{ new nana::detail::drawable_impl_type, detail::drawable_deleter{} };
//Reuse the old font //Reuse the old font
if(impl_->platform_drawable) if (impl_->platform_drawable)
{ {
drawable_type reuse = impl_->platform_drawable.get(); drawable_type reuse = impl_->platform_drawable.get();
dw->font = reuse->font; dw->font = reuse->font;
@@ -314,8 +315,13 @@ namespace paint
dw->font = impl_->font_shadow.impl_->real_font; dw->font = impl_->font_shadow.impl_->real_font;
#if defined(NANA_WINDOWS) #if defined(NANA_WINDOWS)
HDC hdc = ::GetDC(0); HDC hdc = ::GetDC(nullptr);
HDC cdc = ::CreateCompatibleDC(hdc); HDC cdc = ::CreateCompatibleDC(hdc);
if (nullptr == cdc)
{
::ReleaseDC(nullptr, hdc);
throw std::bad_alloc{};
}
BITMAPINFO bmi; BITMAPINFO bmi;
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
@@ -328,34 +334,60 @@ namespace paint
HBITMAP bmp = ::CreateDIBSection(cdc, &bmi, DIB_RGB_COLORS, reinterpret_cast<void**>(&(dw->pixbuf_ptr)), 0, 0); HBITMAP bmp = ::CreateDIBSection(cdc, &bmi, DIB_RGB_COLORS, reinterpret_cast<void**>(&(dw->pixbuf_ptr)), 0, 0);
if(bmp) if (nullptr == bmp)
{
::DeleteObject((HBITMAP)::SelectObject(cdc, bmp));
::DeleteObject(::SelectObject(cdc, dw->font->native_handle()));
dw->context = cdc;
dw->pixmap = bmp;
::SetBkMode(cdc, TRANSPARENT);
}
else
{ {
::DeleteDC(cdc); ::DeleteDC(cdc);
delete dw; ::ReleaseDC(nullptr, hdc);
dw = nullptr; throw std::bad_alloc{};
release();
} }
::DeleteObject((HBITMAP)::SelectObject(cdc, bmp));
::DeleteObject(::SelectObject(cdc, dw->font->native_handle()));
dw->context = cdc;
dw->pixmap = bmp;
::SetBkMode(cdc, TRANSPARENT);
::ReleaseDC(0, hdc); ::ReleaseDC(0, hdc);
#elif defined(NANA_X11) #elif defined(NANA_X11)
auto & spec = nana::detail::platform_spec::instance(); auto & spec = nana::detail::platform_spec::instance();
Display* disp = spec.open_display(); {
int screen = DefaultScreen(disp); nana::detail::platform_scope_guard psg;
Window root = ::XRootWindow(disp, screen);
dw->pixmap = ::XCreatePixmap(disp, root, sz.width, sz.height, DefaultDepth(disp, screen)); spec.set_error_handler();
dw->context = ::XCreateGC(disp, dw->pixmap, 0, 0);
#if defined(NANA_USE_XFT) Display* disp = spec.open_display();
dw->xftdraw = ::XftDrawCreate(disp, dw->pixmap, spec.screen_visual(), spec.colormap()); int screen = DefaultScreen(disp);
#endif Window root = ::XRootWindow(disp, screen);
auto pixmap = ::XCreatePixmap(disp, root, sz.width, sz.height, DefaultDepth(disp, screen));
if(spec.error_code)
{
spec.rev_error_handler();
throw std::bad_alloc();
}
auto context = ::XCreateGC(disp, pixmap, 0, 0);
if (spec.error_code)
{
::XFreePixmap(disp, pixmap);
spec.rev_error_handler();
throw std::bad_alloc();
}
# if defined(NANA_USE_XFT)
auto xftdraw = ::XftDrawCreate(disp, pixmap, spec.screen_visual(), spec.colormap());
if (spec.error_code)
{
::XFreeGC(disp, context);
::XFreePixmap(disp, pixmap);
spec.rev_error_handler();
throw std::bad_alloc();
}
dw->xftdraw = xftdraw;
# endif
dw->pixmap = pixmap;
dw->context = context;
}
#endif #endif
if(dw) if(dw)
{ {
@@ -366,8 +398,8 @@ namespace paint
#else #else
dw->update_text_color(); dw->update_text_color();
#endif #endif
impl_->platform_drawable.reset(dw, detail::drawable_deleter{}); impl_->platform_drawable = dw;
impl_->handle = dw; impl_->handle = dw.get();
impl_->size = sz; impl_->size = sz;
impl_->handle->string.tab_pixels = detail::raw_text_extent_size(impl_->handle, L"\t", 1).width; impl_->handle->string.tab_pixels = detail::raw_text_extent_size(impl_->handle, L"\t", 1).width;