image::paste throws exception if graphics or image is empty
This commit is contained in:
parent
17556cae99
commit
1eb76307e4
@ -170,7 +170,7 @@ namespace nana{
|
||||
pixbuf.pixel(0, r.height - 1, px2);
|
||||
pixbuf.pixel(r.width - 1, r.height - 1, px3);
|
||||
|
||||
pixbuf.paste(wd->root, r.x, r.y);
|
||||
pixbuf.paste(wd->root, { r.x, r.y });
|
||||
|
||||
std::vector<typename window_layer::wd_rectangle> overlaps;
|
||||
if(window_layer::read_overlaps(wd, visual, overlaps))
|
||||
|
||||
@ -576,7 +576,7 @@ namespace nana{ namespace widgets{ namespace skeletons
|
||||
if(size_ != image_.size())
|
||||
image_.stretch(::nana::rectangle{ image_.size() }, graph, nana::rectangle(x, y, size_.width, size_.height));
|
||||
else
|
||||
image_.paste(graph, x, y);
|
||||
image_.paste(graph, point{ x, y });
|
||||
}
|
||||
|
||||
virtual const nana::size & size() const override
|
||||
|
||||
@ -1,371 +0,0 @@
|
||||
/*
|
||||
* Bitmap Format Graphics 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/detail/image_bmp.hpp
|
||||
* @contributors: Ryan Gonzalez
|
||||
*/
|
||||
#ifndef NANA_PAINT_DETAIL_IMAGE_BMP_HPP
|
||||
#define NANA_PAINT_DETAIL_IMAGE_BMP_HPP
|
||||
|
||||
#include "image_impl_interface.hpp"
|
||||
#include <memory>
|
||||
|
||||
namespace nana{ namespace paint
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
|
||||
#ifndef NANA_WINDOWS
|
||||
struct bitmap_file_header
|
||||
{
|
||||
unsigned short bfType;
|
||||
unsigned long bfSize;
|
||||
unsigned short bfReserved1;
|
||||
unsigned short bfReserved2;
|
||||
unsigned long bfOffBits;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct bitmap_info_header {
|
||||
unsigned long biSize;
|
||||
long biWidth;
|
||||
long biHeight;
|
||||
unsigned short biPlanes;
|
||||
unsigned short biBitCount;
|
||||
unsigned long biCompression;
|
||||
unsigned long biSizeImage;
|
||||
long biXPelsPerMeter;
|
||||
long biYPelsPerMeter;
|
||||
unsigned long biClrUsed;
|
||||
unsigned long biClrImportant;
|
||||
}__attribute__((packed));
|
||||
|
||||
struct rgb_quad
|
||||
{
|
||||
unsigned char rgbBlue;
|
||||
unsigned char rgbGreen;
|
||||
unsigned char rgbRed;
|
||||
unsigned char rgbReserved;
|
||||
};
|
||||
|
||||
struct bitmap_info
|
||||
{
|
||||
bitmap_info_header bmiHeader;
|
||||
rgb_quad bmiColors[1];
|
||||
}__attribute__((packed));
|
||||
#else
|
||||
typedef BITMAPFILEHEADER bitmap_file_header;
|
||||
typedef BITMAPINFO bitmap_info;
|
||||
typedef RGBQUAD rgb_quad;
|
||||
#endif
|
||||
|
||||
class image_bmp
|
||||
:public image::image_impl_interface
|
||||
{
|
||||
public:
|
||||
image_bmp(){}
|
||||
|
||||
~image_bmp()
|
||||
{
|
||||
this->close();
|
||||
}
|
||||
|
||||
bool open(const nana::char_t* filename)
|
||||
{
|
||||
if(nullptr == filename) return false;
|
||||
std::ifstream ifs;
|
||||
#if defined(NANA_UNICODE)
|
||||
ifs.open(static_cast<std::string>(nana::charset(filename)).c_str(), std::ios::binary);
|
||||
#else
|
||||
ifs.open(filename, std::ios::binary);
|
||||
#endif
|
||||
if(ifs)
|
||||
{
|
||||
ifs.seekg(0, std::ios::end);
|
||||
auto size = ifs.tellg();
|
||||
ifs.seekg(0, std::ios::beg);
|
||||
|
||||
if(size <= static_cast<int>(sizeof(bitmap_file_header)))
|
||||
return false;
|
||||
|
||||
std::unique_ptr<char[]> buffer(new char[static_cast<int>(size)]);
|
||||
|
||||
ifs.read(buffer.get(), size);
|
||||
if(size == ifs.gcount())
|
||||
{
|
||||
bitmap_file_header * header = reinterpret_cast<bitmap_file_header*>(buffer.get());
|
||||
if((header->bfType == 0x4D42) && (static_cast<std::streamsize>(header->bfSize) == size))
|
||||
{
|
||||
unsigned char* bits = reinterpret_cast<unsigned char*>(buffer.get() + header->bfOffBits);
|
||||
bitmap_info * info = reinterpret_cast<bitmap_info *>(header + 1);
|
||||
|
||||
//Bitmap file is 4byte-aligned for each line.
|
||||
std::size_t bytes_per_line;
|
||||
const std::size_t height_pixels = std::abs(info->bmiHeader.biHeight);
|
||||
if(0 == info->bmiHeader.biSizeImage)
|
||||
bytes_per_line = (((info->bmiHeader.biWidth * info->bmiHeader.biBitCount + 31) & ~31) >> 3);
|
||||
else
|
||||
bytes_per_line = info->bmiHeader.biSizeImage / height_pixels;
|
||||
|
||||
pixbuf_.open(info->bmiHeader.biWidth, height_pixels);
|
||||
|
||||
auto d = pixbuf_.raw_ptr(0);
|
||||
|
||||
if(16 <= info->bmiHeader.biBitCount)
|
||||
{
|
||||
pixbuf_.put(bits, info->bmiHeader.biWidth, height_pixels, info->bmiHeader.biBitCount, bytes_per_line, (info->bmiHeader.biHeight < 0));
|
||||
}
|
||||
else if(8 == info->bmiHeader.biBitCount)
|
||||
{
|
||||
const auto lend = d + info->bmiHeader.biWidth * height_pixels;
|
||||
|
||||
if(info->bmiHeader.biHeight < 0)
|
||||
{
|
||||
auto s = bits;
|
||||
while(d < lend)
|
||||
{
|
||||
auto d_p = d;
|
||||
auto dpend = d_p + info->bmiHeader.biWidth;
|
||||
auto s_p = s;
|
||||
while(d_p != dpend)
|
||||
{
|
||||
rgb_quad & rgb = info->bmiColors[*s_p++];
|
||||
d_p->element.red = rgb.rgbRed;
|
||||
d_p->element.green = rgb.rgbGreen;
|
||||
d_p->element.blue = rgb.rgbBlue;
|
||||
d_p->element.alpha_channel = rgb.rgbReserved;
|
||||
++d_p;
|
||||
}
|
||||
d = dpend;
|
||||
s += bytes_per_line;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto* s = bits + bytes_per_line * (height_pixels - 1);
|
||||
while(d < lend)
|
||||
{
|
||||
auto d_p = d;
|
||||
auto* const dpend = d_p + info->bmiHeader.biWidth;
|
||||
const auto * s_p = s;
|
||||
while(d_p != dpend)
|
||||
{
|
||||
rgb_quad & rgb = info->bmiColors[*s_p++];
|
||||
d_p->element.red = rgb.rgbRed;
|
||||
d_p->element.green = rgb.rgbGreen;
|
||||
d_p->element.blue = rgb.rgbBlue;
|
||||
d_p->element.alpha_channel = rgb.rgbReserved;
|
||||
++d_p;
|
||||
}
|
||||
d = dpend;
|
||||
s -= bytes_per_line;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(4 == info->bmiHeader.biBitCount)
|
||||
{
|
||||
const auto * const lend = d + info->bmiHeader.biWidth * height_pixels;
|
||||
if(info->bmiHeader.biHeight < 0)
|
||||
{
|
||||
const unsigned char* s = bits;
|
||||
while(d < lend)
|
||||
{
|
||||
auto d_p = d;
|
||||
auto * const dpend = d_p + info->bmiHeader.biWidth;
|
||||
unsigned index = 0;
|
||||
while(d_p != dpend)
|
||||
{
|
||||
rgb_quad & rgb = info->bmiColors[(index & 1) ? (s[index >> 1] & 0xF) : (s[index >> 1] & 0xF0) >> 4];
|
||||
|
||||
d_p->element.red = rgb.rgbRed;
|
||||
d_p->element.green = rgb.rgbGreen;
|
||||
d_p->element.blue = rgb.rgbBlue;
|
||||
d_p->element.alpha_channel = rgb.rgbReserved;
|
||||
++d_p;
|
||||
++index;
|
||||
}
|
||||
d = dpend;
|
||||
s += bytes_per_line;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto* s = bits + bytes_per_line * (height_pixels - 1);
|
||||
while(d < lend)
|
||||
{
|
||||
auto d_p = d;
|
||||
auto * const dpend = d_p + info->bmiHeader.biWidth;
|
||||
|
||||
unsigned index = 0;
|
||||
while(d_p != dpend)
|
||||
{
|
||||
rgb_quad & rgb = info->bmiColors[(index & 1) ? (s[index >> 1] & 0xF) : (s[index >> 1] & 0xF0) >> 4];
|
||||
|
||||
d_p->element.red = rgb.rgbRed;
|
||||
d_p->element.green = rgb.rgbGreen;
|
||||
d_p->element.blue = rgb.rgbBlue;
|
||||
d_p->element.alpha_channel = rgb.rgbReserved;
|
||||
++d_p;
|
||||
++index;
|
||||
}
|
||||
d = dpend;
|
||||
s -= bytes_per_line;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(2 == info->bmiHeader.biBitCount)
|
||||
{
|
||||
const auto * const lend = d + info->bmiHeader.biWidth * height_pixels;
|
||||
if(info->bmiHeader.biHeight < 0)
|
||||
{
|
||||
const unsigned char* s = bits;
|
||||
while(d < lend)
|
||||
{
|
||||
auto d_p = d;
|
||||
auto * const dpend = d_p + info->bmiHeader.biWidth;
|
||||
unsigned index = 0;
|
||||
while(d_p != dpend)
|
||||
{
|
||||
unsigned shift = (3 - (index & 0x3)) << 1; // (index % 4) * 2
|
||||
rgb_quad& rgb = info->bmiColors[(s[index >> 2] & (0x3 << shift))>>shift];
|
||||
|
||||
d_p->element.red = rgb.rgbRed;
|
||||
d_p->element.green = rgb.rgbGreen;
|
||||
d_p->element.blue = rgb.rgbBlue;
|
||||
d_p->element.alpha_channel = rgb.rgbReserved;
|
||||
++d_p;
|
||||
++index;
|
||||
}
|
||||
d = dpend;
|
||||
s += bytes_per_line;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto* s = bits + bytes_per_line * (height_pixels - 1);
|
||||
while(d < lend)
|
||||
{
|
||||
auto d_p = d;
|
||||
auto * const dpend = d_p + info->bmiHeader.biWidth;
|
||||
|
||||
unsigned index = 0;
|
||||
while(d_p != dpend)
|
||||
{
|
||||
unsigned shift = (3 - (index & 0x3)) << 1; // (index % 4) * 2
|
||||
rgb_quad& rgb = info->bmiColors[(s[index >> 2] & (0x3 << shift))>>shift];
|
||||
|
||||
d_p->element.red = rgb.rgbRed;
|
||||
d_p->element.green = rgb.rgbGreen;
|
||||
d_p->element.blue = rgb.rgbBlue;
|
||||
d_p->element.alpha_channel = rgb.rgbReserved;
|
||||
++d_p;
|
||||
++index;
|
||||
}
|
||||
d = dpend;
|
||||
s -= bytes_per_line;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(1 == info->bmiHeader.biBitCount)
|
||||
{
|
||||
const auto * const lend = d + info->bmiHeader.biWidth * height_pixels;
|
||||
if(info->bmiHeader.biHeight < 0)
|
||||
{
|
||||
const auto* s = bits;
|
||||
while(d < lend)
|
||||
{
|
||||
auto d_p = d;
|
||||
auto * const dpend = d_p + info->bmiHeader.biWidth;
|
||||
unsigned index = 0;
|
||||
while(d_p != dpend)
|
||||
{
|
||||
unsigned bi = (7 - (index & 7)); //(index % 8)
|
||||
rgb_quad & rgb = info->bmiColors[(s[index >> 3] & (1 << bi)) >> bi];
|
||||
|
||||
d_p->element.red = rgb.rgbRed;
|
||||
d_p->element.green = rgb.rgbGreen;
|
||||
d_p->element.blue = rgb.rgbBlue;
|
||||
d_p->element.alpha_channel = rgb.rgbReserved;
|
||||
++d_p;
|
||||
++index;
|
||||
}
|
||||
d = dpend;
|
||||
s += bytes_per_line;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto* s = bits + bytes_per_line * (height_pixels - 1);
|
||||
while(d < lend)
|
||||
{
|
||||
auto d_p = d;
|
||||
auto * const dpend = d_p + info->bmiHeader.biWidth;
|
||||
|
||||
unsigned index = 0;
|
||||
while(d_p != dpend)
|
||||
{
|
||||
unsigned bi = (7 - (index & 7));
|
||||
rgb_quad & rgb = info->bmiColors[(s[index >> 3] & (1 << bi)) >> bi];
|
||||
|
||||
d_p->element.red = rgb.rgbRed;
|
||||
d_p->element.green = rgb.rgbGreen;
|
||||
d_p->element.blue = rgb.rgbBlue;
|
||||
d_p->element.alpha_channel = rgb.rgbReserved;
|
||||
++d_p;
|
||||
++index;
|
||||
}
|
||||
d = dpend;
|
||||
s -= bytes_per_line;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return (false == pixbuf_.empty());
|
||||
}
|
||||
|
||||
bool alpha_channel() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool empty() const
|
||||
{
|
||||
return pixbuf_.empty();
|
||||
}
|
||||
|
||||
void close()
|
||||
{
|
||||
pixbuf_.close();
|
||||
}
|
||||
|
||||
nana::size size() const
|
||||
{
|
||||
return pixbuf_.size();
|
||||
}
|
||||
|
||||
void paste(const nana::rectangle& src_r, graph_reference graph, int x, int y) const
|
||||
{
|
||||
if(graph && pixbuf_)
|
||||
pixbuf_.paste(src_r, graph.handle(), x, y);
|
||||
}
|
||||
|
||||
void stretch(const nana::rectangle& src_r, graph_reference graph, const nana::rectangle& r) const
|
||||
{
|
||||
if(graph && pixbuf_)
|
||||
pixbuf_.stretch(src_r, graph.handle(), r);
|
||||
}
|
||||
private:
|
||||
nana::paint::pixel_buffer pixbuf_;
|
||||
};//end class bmpfile
|
||||
}//end namespace detail
|
||||
}//end namespace paint
|
||||
}//end namespace nana
|
||||
|
||||
#endif
|
||||
@ -1,43 +0,0 @@
|
||||
#ifndef NANA_PAINT_DETAIL_IMAGE_ICO_HPP
|
||||
#define NANA_PAINT_DETAIL_IMAGE_ICO_HPP
|
||||
|
||||
#include "image_impl_interface.hpp"
|
||||
|
||||
namespace nana{ namespace paint
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
class image_ico
|
||||
:public image::image_impl_interface
|
||||
{
|
||||
#if defined(NANA_WINDOWS)
|
||||
struct handle_deleter
|
||||
{
|
||||
void operator()(HICON* handle) const;
|
||||
};//end struct handle_deleter
|
||||
typedef std::shared_ptr<HICON> ptr_t;
|
||||
#else
|
||||
typedef std::shared_ptr<int*> ptr_t;
|
||||
#endif
|
||||
public:
|
||||
image_ico(bool is_ico);
|
||||
|
||||
bool open(const nana::char_t* filename);
|
||||
bool alpha_channel() const;
|
||||
bool empty() const;
|
||||
void close();
|
||||
nana::size size() const;
|
||||
virtual void paste(const nana::rectangle& src_r, graph_reference graph, int x, int y) const;
|
||||
virtual void stretch(const nana::rectangle&, graph_reference graph, const nana::rectangle& r) const;
|
||||
|
||||
const ptr_t & ptr() const;
|
||||
private:
|
||||
const bool is_ico_;
|
||||
nana::size size_;
|
||||
ptr_t ptr_;
|
||||
};//end class image_ico
|
||||
}
|
||||
}//end namespace paint
|
||||
}//end namespace nana
|
||||
|
||||
#endif
|
||||
@ -20,7 +20,7 @@ namespace nana{ namespace paint{
|
||||
virtual bool empty() const = 0;
|
||||
virtual void close() = 0;
|
||||
virtual nana::size size() const = 0;
|
||||
virtual void paste(const nana::rectangle& src_r, graph_reference dst, int x, int y) const = 0;
|
||||
virtual void paste(const nana::rectangle& src_r, graph_reference dst, const point& p_dst) const = 0;
|
||||
virtual void stretch(const nana::rectangle& src_r, graph_reference dst, const nana::rectangle& r) const = 0;
|
||||
};//end class image::image_impl_interface
|
||||
}//end namespace paint
|
||||
|
||||
@ -1,188 +0,0 @@
|
||||
#ifndef NANA_PAINT_DETAIL_IMAGE_PNG_HPP
|
||||
#define NANA_PAINT_DETAIL_IMAGE_PNG_HPP
|
||||
|
||||
#include "image_impl_interface.hpp"
|
||||
|
||||
//Separate the libpng from the package that system provides.
|
||||
#if defined(NANA_LIBPNG)
|
||||
#include <nana/extrlib/png.h>
|
||||
#else
|
||||
#include <png.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include "../pixel_buffer.hpp"
|
||||
|
||||
namespace nana
|
||||
{
|
||||
namespace paint{ namespace detail{
|
||||
|
||||
class image_png
|
||||
: public image::image_impl_interface
|
||||
{
|
||||
public:
|
||||
image_png()
|
||||
{
|
||||
}
|
||||
|
||||
bool open(const nana::char_t* png_file)
|
||||
{
|
||||
#ifdef NANA_UNICODE
|
||||
FILE * fp = ::fopen(static_cast<std::string>(nana::charset(png_file)).c_str(), "rb");
|
||||
#else
|
||||
FILE* fp = ::fopen(png_file, "rb");
|
||||
#endif
|
||||
if(nullptr == fp) return false;
|
||||
|
||||
bool is_opened = false;
|
||||
|
||||
png_byte png_sig[8];
|
||||
::fread(png_sig, 1, 8, fp);
|
||||
|
||||
//Test whether the file is a png.
|
||||
if(0 == png_sig_cmp(png_sig, 0, 8))
|
||||
{
|
||||
png_structp png_ptr = ::png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
|
||||
if(png_ptr)
|
||||
{
|
||||
png_infop info_ptr = ::png_create_info_struct(png_ptr);
|
||||
|
||||
if(info_ptr)
|
||||
{
|
||||
if(!setjmp(png_jmpbuf(png_ptr)))
|
||||
{
|
||||
//The following codes may longjmp while init_io error.
|
||||
::png_init_io(png_ptr, fp);
|
||||
::png_set_sig_bytes(png_ptr, 8);
|
||||
::png_read_info(png_ptr, info_ptr);
|
||||
|
||||
const int png_width = ::png_get_image_width(png_ptr, info_ptr);
|
||||
const int png_height = ::png_get_image_height(png_ptr, info_ptr);
|
||||
png_byte color_type = ::png_get_color_type(png_ptr, info_ptr);
|
||||
|
||||
::png_set_interlace_handling(png_ptr);
|
||||
::png_read_update_info(png_ptr, info_ptr);
|
||||
|
||||
//The following codes may longjmp while image_read error.
|
||||
png_bytep * row_ptrs = new png_bytep[png_height];
|
||||
const std::size_t png_rowbytes = ::png_get_rowbytes(png_ptr, info_ptr);
|
||||
|
||||
pixbuf_.open(png_width, png_height);
|
||||
|
||||
const bool is_alpha_enabled = ((PNG_COLOR_MASK_ALPHA & color_type) != 0);
|
||||
pixbuf_.alpha_channel(is_alpha_enabled);
|
||||
|
||||
if(is_alpha_enabled && (png_rowbytes == png_width * sizeof(pixel_argb_t)))
|
||||
{
|
||||
for(int i = 0; i < png_height; ++i)
|
||||
row_ptrs[i] = reinterpret_cast<png_bytep>(pixbuf_.raw_ptr(i));
|
||||
|
||||
::png_read_image(png_ptr, row_ptrs);
|
||||
::png_destroy_read_struct(&png_ptr, &info_ptr, nullptr);
|
||||
|
||||
for (int i = 0; i < png_height; ++i)
|
||||
{
|
||||
auto p = pixbuf_.raw_ptr(i);
|
||||
for (int u = 0; u < png_width; ++u)
|
||||
{
|
||||
auto t = p[u].element.red;
|
||||
p[u].element.red = p[u].element.blue;
|
||||
p[u].element.blue = t;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
png_byte * png_pixbuf = new png_byte[png_height * png_rowbytes];
|
||||
|
||||
for(int i = 0; i < png_height; ++i)
|
||||
row_ptrs[i] = reinterpret_cast<png_bytep>(png_pixbuf + png_rowbytes * i);
|
||||
|
||||
::png_read_image(png_ptr, row_ptrs);
|
||||
::png_destroy_read_struct(&png_ptr, &info_ptr, 0);
|
||||
|
||||
std::size_t png_pixel_bytes = png_rowbytes / png_width;
|
||||
|
||||
pixel_argb_t * rgb_row_ptr = pixbuf_.raw_ptr(0);
|
||||
for(int y = 0; y < png_height; ++y)
|
||||
{
|
||||
png_bytep png_ptr = row_ptrs[y];
|
||||
|
||||
pixel_argb_t * rgb_end = rgb_row_ptr + png_width;
|
||||
|
||||
if(is_alpha_enabled)
|
||||
{
|
||||
for(pixel_argb_t * i = rgb_row_ptr; i < rgb_end; ++i)
|
||||
{
|
||||
i->element.red = png_ptr[0];
|
||||
i->element.green = png_ptr[1];
|
||||
i->element.blue = png_ptr[2];
|
||||
i->element.alpha_channel = png_ptr[3];
|
||||
png_ptr += png_pixel_bytes;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for(pixel_argb_t * i = rgb_row_ptr; i < rgb_end; ++i)
|
||||
{
|
||||
i->element.red = png_ptr[0];
|
||||
i->element.green = png_ptr[1];
|
||||
i->element.blue = png_ptr[2];
|
||||
i->element.alpha_channel = 255;
|
||||
png_ptr += png_pixel_bytes;
|
||||
}
|
||||
}
|
||||
rgb_row_ptr = rgb_end;
|
||||
}
|
||||
|
||||
delete [] png_pixbuf;
|
||||
}
|
||||
delete [] row_ptrs;
|
||||
is_opened = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
::fclose(fp);
|
||||
return is_opened;
|
||||
}
|
||||
|
||||
bool alpha_channel() const
|
||||
{
|
||||
return pixbuf_.alpha_channel();
|
||||
}
|
||||
|
||||
virtual bool empty() const
|
||||
{
|
||||
return pixbuf_.empty();
|
||||
}
|
||||
|
||||
virtual void close()
|
||||
{
|
||||
pixbuf_.close();
|
||||
}
|
||||
|
||||
virtual nana::size size() const
|
||||
{
|
||||
return pixbuf_.size();
|
||||
}
|
||||
|
||||
void paste(const nana::rectangle& src_r, graph_reference graph, int x, int y) const
|
||||
{
|
||||
pixbuf_.paste(src_r, graph.handle(), x, y);
|
||||
}
|
||||
|
||||
void stretch(const nana::rectangle& src_r, graph_reference dst, const nana::rectangle& r) const
|
||||
{
|
||||
pixbuf_.stretch(src_r, dst.handle(), r);
|
||||
}
|
||||
private:
|
||||
nana::paint::pixel_buffer pixbuf_;
|
||||
|
||||
};
|
||||
}//end namespace detail
|
||||
}//end namespace paint
|
||||
}//end namespace nana
|
||||
|
||||
#endif
|
||||
@ -43,7 +43,7 @@ namespace paint
|
||||
|
||||
bool alpha() const;
|
||||
nana::size size() const;
|
||||
void paste(graphics& dst, int x, int y) const;
|
||||
void paste(graphics& dst, const point& p_dst) const;
|
||||
void paste(const nana::rectangle& r_src, graphics& dst, const point& p_dst) const;///< Paste the area of picture specified by r_src into the destination graphics specified by dst at position p_dst.
|
||||
void stretch(const nana::rectangle& r_src, graphics& dst, const nana::rectangle& r_dst) const;///<Paste the picture into the dst, stretching or compressing the picture to fit the given area.
|
||||
private:
|
||||
|
||||
@ -76,9 +76,9 @@ namespace nana{ namespace paint
|
||||
pixel_color_t pixel(int x, int y) const;
|
||||
void pixel(int x, int y, pixel_color_t);
|
||||
|
||||
void paste(drawable_type, int x, int y) const;
|
||||
void paste(const nana::rectangle& s_r, drawable_type, int x, int y) const;
|
||||
void paste(native_window_type, int x, int y) const;
|
||||
void paste(drawable_type, const point& p_dst) const;
|
||||
void paste(const nana::rectangle& s_r, drawable_type, const point& p_dst) const;
|
||||
void paste(native_window_type, const point& p_dst) const;
|
||||
void stretch(const std::string& name);
|
||||
void stretch(const nana::rectangle& s_r, drawable_type, const nana::rectangle& r) const;
|
||||
void blend(const std::string& name);
|
||||
|
||||
@ -201,7 +201,7 @@ namespace nana
|
||||
case frame::kind::oneshot:
|
||||
_m_render(outs, [&frmobj](paint::graphics& tar, const nana::point& pos)
|
||||
{
|
||||
frmobj.u.oneshot->paste(tar, pos.x, pos.y);
|
||||
frmobj.u.oneshot->paste(tar, pos);
|
||||
});
|
||||
break;
|
||||
case frame::kind::framebuilder:
|
||||
@ -230,7 +230,7 @@ namespace nana
|
||||
switch(frmobj.type)
|
||||
{
|
||||
case frame::kind::oneshot:
|
||||
frmobj.u.oneshot->paste(graph, pos.x, pos.y);
|
||||
frmobj.u.oneshot->paste(graph, pos);
|
||||
break;
|
||||
case frame::kind::framebuilder:
|
||||
if(rebuild_frame)
|
||||
|
||||
@ -258,7 +258,7 @@ namespace nana{ namespace drawerbase
|
||||
}
|
||||
|
||||
if(attr_.icon)
|
||||
attr_.icon->paste(graph, 3, (gsize.height - icon_sz.height) / 2);
|
||||
attr_.icon->paste(graph, point{ 3, static_cast<int>(gsize.height - icon_sz.height) / 2 });
|
||||
}
|
||||
|
||||
void trigger::_m_draw(graph_reference graph)
|
||||
|
||||
@ -1263,7 +1263,7 @@ namespace nana
|
||||
img->stretch(::nana::rectangle{ size }, graph, attr.area);
|
||||
}
|
||||
else
|
||||
img->paste(graph, attr.area.x + static_cast<int>(attr.area.width - size.width) / 2, attr.area.y + static_cast<int>(attr.area.height - size.height) / 2);
|
||||
img->paste(graph, point{ attr.area.x + static_cast<int>(attr.area.width - size.width) / 2, attr.area.y + static_cast<int>(attr.area.height - size.height) / 2 });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -126,7 +126,7 @@ namespace detail
|
||||
i->value = (px_r | px_g | px_b);
|
||||
}
|
||||
}
|
||||
pixbuf.paste(nana::rectangle(r.x, 0, r.width, r.height), dw, r.x, r.y);
|
||||
pixbuf.paste(nana::rectangle(r.x, 0, r.width, r.height), dw, point{r.x, r.y});
|
||||
}
|
||||
|
||||
nana::size raw_text_extent_size(drawable_type dw, const nana::char_t* text, std::size_t len)
|
||||
|
||||
@ -618,7 +618,7 @@ namespace paint
|
||||
{
|
||||
pixel_buffer pixbuf(handle_, 0, 0);
|
||||
pixbuf.blur(r, radius);
|
||||
pixbuf.paste(handle_, 0, 0);
|
||||
pixbuf.paste(handle_, point{});
|
||||
}
|
||||
}
|
||||
|
||||
@ -677,7 +677,7 @@ namespace paint
|
||||
}
|
||||
delete [] tablebuf;
|
||||
|
||||
pixbuf.paste(handle_, 0, 0);
|
||||
pixbuf.paste(handle_, point{});
|
||||
if(changed_ == false) changed_ = true;
|
||||
}
|
||||
}
|
||||
@ -1074,7 +1074,7 @@ namespace paint
|
||||
if (pxbuf_.open(handle_))
|
||||
{
|
||||
pxbuf_.gradual_rectangle(rct, from, to, 0.0, vertical);
|
||||
pxbuf_.paste(handle_, 0, 0);
|
||||
pxbuf_.paste(handle_, point{});
|
||||
}
|
||||
#elif defined(NANA_X11)
|
||||
if (nullptr == handle_) return;
|
||||
|
||||
@ -16,14 +16,15 @@
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
#include <iterator>
|
||||
#include <stdexcept>
|
||||
|
||||
#include <nana/paint/detail/image_impl_interface.hpp>
|
||||
#include <nana/paint/pixel_buffer.hpp>
|
||||
#if defined(NANA_ENABLE_PNG)
|
||||
#include <nana/paint/detail/image_png.hpp>
|
||||
#include "detail/image_png.hpp"
|
||||
#endif
|
||||
#include <nana/paint/detail/image_bmp.hpp>
|
||||
#include <nana/paint/detail/image_ico.hpp>
|
||||
#include "detail/image_bmp.hpp"
|
||||
#include "detail/image_ico.hpp"
|
||||
|
||||
namespace nana
|
||||
{
|
||||
@ -89,12 +90,12 @@ namespace paint
|
||||
return size_;
|
||||
}
|
||||
|
||||
void image_ico::paste(const nana::rectangle& src_r, graph_reference graph, int x, int y) const
|
||||
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, x, y, *ptr_, src_r.width, src_r.height, 0, 0, DI_NORMAL);
|
||||
::DrawIconEx(graph.handle()->context, p_dst.x, p_dst.y, *ptr_, src_r.width, src_r.height, 0, 0, DI_NORMAL);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@ -260,22 +261,40 @@ namespace paint
|
||||
return (image_ptr_ ? image_ptr_->size() : nana::size());
|
||||
}
|
||||
|
||||
void image::paste(graphics& dst, int x, int y) const
|
||||
void image::paste(graphics& dst, const point& p_dst) const
|
||||
{
|
||||
if(image_ptr_)
|
||||
image_ptr_->paste(::nana::rectangle{ image_ptr_->size() }, dst, x, y);
|
||||
if(image_ptr_ && !dst.empty())
|
||||
image_ptr_->paste(::nana::rectangle{ image_ptr_->size() }, dst, p_dst);
|
||||
|
||||
if (!image_ptr_)
|
||||
throw std::runtime_error("image is empty");
|
||||
|
||||
if (dst.empty())
|
||||
throw std::invalid_argument("graphics is empty");
|
||||
}
|
||||
|
||||
void image::paste(const nana::rectangle& r_src, graphics & dst, const nana::point& p_dst) const
|
||||
{
|
||||
if(image_ptr_)
|
||||
image_ptr_->paste(r_src, dst, p_dst.x, p_dst.y);
|
||||
if(image_ptr_ && !dst.empty())
|
||||
image_ptr_->paste(r_src, dst, p_dst);
|
||||
|
||||
if (!image_ptr_)
|
||||
throw std::runtime_error("image is empty");
|
||||
|
||||
if (dst.empty())
|
||||
throw std::invalid_argument("graphics is empty");
|
||||
}
|
||||
|
||||
void image::stretch(const nana::rectangle& r_src, graphics& dst, const nana::rectangle & r_dst) const
|
||||
{
|
||||
if(image_ptr_)
|
||||
if(image_ptr_ && !dst.empty())
|
||||
image_ptr_->stretch(r_src, dst, r_dst);
|
||||
|
||||
if (!image_ptr_)
|
||||
throw std::runtime_error("image is empty");
|
||||
|
||||
if (dst.empty())
|
||||
throw std::invalid_argument("graphics is empty");
|
||||
}
|
||||
//end class image
|
||||
|
||||
|
||||
@ -633,13 +633,13 @@ namespace nana{ namespace paint
|
||||
*reinterpret_cast<pixel_color_t*>(reinterpret_cast<char*>(sp->raw_pixel_buffer + x) + y * sp->bytes_per_line) = px;
|
||||
}
|
||||
|
||||
void pixel_buffer::paste(drawable_type drawable, int x, int y) const
|
||||
void pixel_buffer::paste(drawable_type drawable, const point& p_dst) const
|
||||
{
|
||||
if(storage_)
|
||||
paste(nana::rectangle(storage_->pixel_size), drawable, x, y);
|
||||
paste(nana::rectangle(storage_->pixel_size), drawable, p_dst);
|
||||
}
|
||||
|
||||
void pixel_buffer::paste(const nana::rectangle& src_r, drawable_type drawable, int x, int y) const
|
||||
void pixel_buffer::paste(const nana::rectangle& src_r, drawable_type drawable, const point& p_dst) const
|
||||
{
|
||||
auto sp = storage_.get();
|
||||
if(drawable && sp)
|
||||
@ -647,7 +647,7 @@ namespace nana{ namespace paint
|
||||
if(sp->alpha_channel)
|
||||
{
|
||||
nana::rectangle s_good_r, d_good_r;
|
||||
if(overlap(src_r, sp->pixel_size, nana::rectangle(x, y, src_r.width, src_r.height), paint::detail::drawable_size(drawable), s_good_r, d_good_r))
|
||||
if(overlap(src_r, sp->pixel_size, nana::rectangle(p_dst.x, p_dst.y, src_r.width, src_r.height), paint::detail::drawable_size(drawable), s_good_r, d_good_r))
|
||||
{
|
||||
pixel_buffer d_pixbuf;
|
||||
d_pixbuf.attach(drawable, d_good_r);
|
||||
@ -660,16 +660,16 @@ namespace nana{ namespace paint
|
||||
assign_windows_bitmapinfo(sp->pixel_size, bi);
|
||||
|
||||
::SetDIBitsToDevice(drawable->context,
|
||||
x, y, src_r.width, src_r.height,
|
||||
p_dst.x, p_dst.y, src_r.width, src_r.height,
|
||||
src_r.x, static_cast<int>(sp->pixel_size.height) - src_r.y - src_r.height, 0, sp->pixel_size.height,
|
||||
sp->raw_pixel_buffer, &bi, DIB_RGB_COLORS);
|
||||
#elif defined(NANA_X11)
|
||||
sp->put(drawable->pixmap, drawable->context, src_r.x, src_r.y, x, y, src_r.width, src_r.height);
|
||||
sp->put(drawable->pixmap, drawable->context, src_r.x, src_r.y, p_dst.x, p_dst.y, src_r.width, src_r.height);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void pixel_buffer::paste(native_window_type wd, int x, int y) const
|
||||
void pixel_buffer::paste(native_window_type wd, const point& p_dst) const
|
||||
{
|
||||
auto sp = storage_.get();
|
||||
if(nullptr == wd || nullptr == sp) return;
|
||||
@ -681,7 +681,7 @@ namespace nana{ namespace paint
|
||||
assign_windows_bitmapinfo(sp->pixel_size, bi);
|
||||
|
||||
::SetDIBitsToDevice(handle,
|
||||
x, y, sp->pixel_size.width, sp->pixel_size.height,
|
||||
p_dst.x, p_dst.y, sp->pixel_size.width, sp->pixel_size.height,
|
||||
0, 0, 0, sp->pixel_size.height,
|
||||
sp->raw_pixel_buffer, &bi, DIB_RGB_COLORS);
|
||||
|
||||
@ -690,7 +690,7 @@ namespace nana{ namespace paint
|
||||
#elif defined(NANA_X11)
|
||||
auto & spec = nana::detail::platform_spec::instance();
|
||||
Display * disp = spec.open_display();
|
||||
sp->put(reinterpret_cast<Window>(wd), XDefaultGC(disp, XDefaultScreen(disp)), 0, 0, x, y, sp->pixel_size.width, sp->pixel_size.height);
|
||||
sp->put(reinterpret_cast<Window>(wd), XDefaultGC(disp, XDefaultScreen(disp)), 0, 0, p_dst.x, p_dst.y, sp->pixel_size.width, sp->pixel_size.height);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user