/* * Paint Image Implementation * Nana C++ Library(http://www.nanapro.org) * Copyright(C) 2003-2015 Jinhao(cnjinhao@hotmail.com) * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) * * @file: nana/paint/image.cpp */ #include #include PLATFORM_SPEC_HPP #include #include #include #include #include #include #include #if defined(NANA_ENABLE_PNG) #include "detail/image_png.hpp" #endif #include "detail/image_bmp.hpp" #include "detail/image_ico.hpp" namespace nana { namespace paint { namespace detail { //class image_ico image_ico::image_ico(bool is_ico): is_ico_(is_ico){} bool image_ico::open(const nana::char_t* filename) { close(); #if defined(NANA_WINDOWS) HICON handle = 0; if(is_ico_) { handle = (HICON)::LoadImage(0, filename, IMAGE_ICON, 0, 0, LR_LOADFROMFILE); } else { SHFILEINFO sfi; ::SHGetFileInfo(filename, 0, &sfi, sizeof(sfi), SHGFI_ICON); handle = sfi.hIcon; } if(handle) { HICON * p = new HICON(handle); ptr_ = std::shared_ptr(p, handle_deleter()); ICONINFO info; ::GetIconInfo(handle, &info); size_.width = (info.xHotspot << 1); size_.height = (info.yHotspot << 1); ::DeleteObject(info.hbmColor); ::DeleteObject(info.hbmMask); return true; } #else if(is_ico_){} //kill the unused compiler warning in Linux. #endif return false; } bool image_ico::open(const void* data, std::size_t bytes) { close(); #if defined(NANA_WINDOWS) HICON handle = ::CreateIconFromResource((PBYTE)data, static_cast(bytes), TRUE, 0x00030000); if(handle) { ICONINFO info; if (::GetIconInfo(handle, &info) != 0) { HICON * p = new HICON(handle); ptr_ = std::shared_ptr(p, handle_deleter()); size_.width = (info.xHotspot << 1); size_.height = (info.yHotspot << 1); ::DeleteObject(info.hbmColor); ::DeleteObject(info.hbmMask); return true; } } #else if(is_ico_){} //kill the unused compiler warning in Linux. #endif return false; } bool image_ico::alpha_channel() const { return false; } bool image_ico::empty() const { return (nullptr == ptr_); } void image_ico::close() { ptr_.reset(); } nana::size image_ico::size() const { return size_; } void image_ico::paste(const nana::rectangle& src_r, graph_reference graph, const point& p_dst) const { if(ptr_ && (graph.empty() == false)) { #if defined(NANA_WINDOWS) ::DrawIconEx(graph.handle()->context, p_dst.x, p_dst.y, *ptr_, src_r.width, src_r.height, 0, 0, DI_NORMAL); #endif } } void image_ico::stretch(const nana::rectangle&, graph_reference graph, const nana::rectangle& r) const { if(ptr_ && (graph.empty() == false)) { #if defined(NANA_WINDOWS) ::DrawIconEx(graph.handle()->context, r.x, r.y, *ptr_, r.width, r.height, 0, 0, DI_NORMAL); #endif } } const image_ico::ptr_t& image_ico::ptr() const { return ptr_; } #if defined(NANA_WINDOWS) //struct handle_deleter void image_ico::handle_deleter::operator()(HICON* p) const { if(p && *p) ::DestroyIcon(*p); delete p; } //end struct handle_deleter #endif //end class image_ico } image::image_impl_interface::~image_impl_interface() {} namespace detail { int toupper(int c) { return (('a' <= c && c <= 'z') ? c - ('a' - 'A') : c); } }//end namespace detail //class image image::image() {} image::image(const image& rhs) : image_ptr_(rhs.image_ptr_) {} image::image(image&& r) : image_ptr_(std::move(r.image_ptr_)) {} image::image(const nana::char_t* file) { if(file) open(file); } image::image(const nana::string& file) { this->open(file); } image::~image() { close(); } image& image::operator=(const image& r) { if(this != &r) image_ptr_ = r.image_ptr_; return * this; } image& image::operator=(image&& r) { if(this != &r) image_ptr_ = std::move(r.image_ptr_); return *this; } bool image::open(const nana::string& filename) { image_ptr_.reset(); image::image_impl_interface * helper = nullptr; if(filename.size()) { nana::string fn; std::transform(filename.cbegin(), filename.cend(), std::back_inserter(fn), detail::toupper); if(filename.size() >= 4) { nana::string suffix = fn.substr(fn.size() - 4); if(STR(".ICO") == suffix) { #if defined(NANA_WINDOWS) helper = new detail::image_ico(true); #endif } #if defined(NANA_ENABLE_PNG) else if(STR(".PNG") == suffix) helper = new detail::image_png; #endif } if(0 == helper) { #if defined(NANA_UNICODE) std::ifstream ifs(std::string(nana::charset(filename)).c_str(), std::ios::binary); #else std::ifstream ifs(filename.c_str(), std::ios::binary); #endif if(ifs) { unsigned short meta = 0; ifs.read(reinterpret_cast(&meta), 2); if(*reinterpret_cast("BM") == meta) helper = new detail::image_bmp; else if(*reinterpret_cast("MZ") == meta) helper = new detail::image_ico(false); } } if(helper) { image_ptr_ = std::shared_ptr(helper); return helper->open(filename.data()); } } return false; } bool image::open_icon(const void* data, std::size_t bytes) { image::image_impl_interface * helper = new detail::image_ico(true); image_ptr_ = std::shared_ptr(helper); return helper->open(data, bytes); } bool image::empty() const { return ((nullptr == image_ptr_) || image_ptr_->empty()); } image::operator unspecified_bool_t() const { return (image_ptr_ ? &image::empty : nullptr); } void image::close() { image_ptr_.reset(); } bool image::alpha() const { return (image_ptr_ ? image_ptr_->alpha_channel() : false); } nana::size image::size() const { return (image_ptr_ ? image_ptr_->size() : nana::size()); } void image::paste(graphics& dst, const point& p_dst) const { this->paste(rectangle{ this->size() }, dst, p_dst); } void image::paste(const rectangle& r_src, graphics & dst, const point& p_dst) const { if (image_ptr_) { if (dst.empty()) dst.make({ r_src.width, r_src.height }); //throws if failed to create image_ptr_->paste(r_src, dst, p_dst); } else throw std::runtime_error("image is empty"); } void image::stretch(const nana::rectangle& r_src, graphics& dst, const nana::rectangle & r_dst) const { if (image_ptr_) { if (dst.empty()) dst.make({ r_src.width, r_src.height }); //throws if failed to create image_ptr_->stretch(r_src, dst, r_dst); } else throw std::runtime_error("image is empty"); } //end class image }//end namespace paint }//end namespace nana