#include "surface.h"
Surface::Surface():
m_width(), m_height(), m_pitch(), m_origin() { }
Surface::Surface(const Surface &):
m_width(), m_height(), m_pitch(), m_origin() { }
void
Surface::reset() {
m_width = m_height = m_pitch = 0;
m_origin = NULL;
}
void Surface::copy(int width, int height, const Color *src_origin, Color *dest_origin, int src_pitch, int dest_pitch) {
#ifndef NDEBUG
{ // check source and destination ranges
assert(dest_origin);
assert(src_origin);
Color *dest_begin = dest_origin + begin_offset(width, height, dest_pitch),
*dest_end = dest_origin + end_offset(width, height, dest_pitch);
const Color *src_begin = src_origin + begin_offset(width, height, src_pitch),
*src_end = src_origin + end_offset(width, height, src_pitch);
assert(src_end <= dest_begin || dest_end <= src_begin);
}
#endif
if (!src_pitch) src_pitch = width;
if (!dest_pitch) dest_pitch = width;
const Color *src_row = src_origin;
for( Color *dest_row = dest_origin, *dest_row_end = dest_row + height*dest_pitch;
dest_row != dest_row_end;
dest_row += dest_pitch, src_row += src_pitch )
{
const Color *src_col = src_row;
for( Color *dest_col = dest_row, *dest_col_end = dest_col + width;
dest_col != dest_col_end;
++dest_col, ++src_col )
{ *dest_col = *src_col; }
}
}
Glib::RefPtr<Gdk::Pixbuf>
Surface::to_pixbuf() const {
if (empty())
return Glib::RefPtr<Gdk::Pixbuf>();
Glib::RefPtr<Gdk::Pixbuf> pixbuf = Gdk::Pixbuf::create(
Gdk::COLORSPACE_RGB, true, 8, width(), height() );
guint8 *pixels = pixbuf->get_pixels();
int stride = pixbuf->get_rowstride();
for(int r = 0; r < height(); ++r) {
const Color *src_row = row(r);
guint8 *pixel = pixels;
pixels += stride;
for(int c = 0; c < width(); ++c) {
const Color &color = src_row[c];
*(pixel++) = (guint8)(color.r*255.9);
*(pixel++) = (guint8)(color.g*255.9);
*(pixel++) = (guint8)(color.b*255.9);
*(pixel++) = (guint8)(color.a*255.9);
}
}
return pixbuf;
}
Cairo::RefPtr<Cairo::ImageSurface>
Surface::to_cairo_surface() const {
if (empty())
return Cairo::RefPtr<Cairo::ImageSurface>();
Cairo::RefPtr<Cairo::ImageSurface> cairo_surface =
Cairo::ImageSurface::create(Cairo::FORMAT_ARGB32, width(), height());
cairo_surface->flush();
unsigned char *pixels = cairo_surface->get_data();
int stride = cairo_surface->get_stride();
for(int r = 0; r < height(); ++r) {
const Color *src_row = row(r);
unsigned char *pixel = pixels;
pixels += stride;
for(int c = 0; c < width(); ++c) {
const Color &color = src_row[c];
*(pixel++) = (guint8)(color.r*255.9);
*(pixel++) = (guint8)(color.g*255.9);
*(pixel++) = (guint8)(color.b*255.9);
*(pixel++) = (guint8)(color.a*255.9);
}
}
cairo_surface->mark_dirty();
return cairo_surface;
}
void DataSurface::clear() {
if (Color *data = data_begin()) delete[] data;
reset();
}
void DataSurface::init(int width, int height, int pitch, const Color *src_origin, int src_pitch) {
Color *origin = NULL;
if (width > 0 && height > 0) {
if (!pitch) pitch = width;
int count = data_count(width, height, pitch);
int offset = begin_offset(width, height, pitch);
Color *data = new Color[count];
origin = data - offset;
if (src_origin)
copy(width, height, src_origin, origin, src_pitch, pitch);
} else {
width = 0;
height = 0;
pitch = 0;
}
clear();
m_width = width;
m_height = height;
m_pitch = pitch;
m_origin = origin;
}
void AliasSurface::init(Color *origin, int width, int height, int pitch) {
clear();
if (origin && width > 0 && height > 0) {
m_width = width;
m_height = height;
m_pitch = pitch ? pitch : width;
m_origin = origin;
}
}