Skip to content

Commit

Permalink
For 32-bit depth visuals render to a dedicated pixmap32 and cache it.
Browse files Browse the repository at this point in the history
This solves issue #183.
  • Loading branch information
gijsbers committed Dec 21, 2017
1 parent 1505c8f commit 6291dee
Show file tree
Hide file tree
Showing 7 changed files with 163 additions and 76 deletions.
1 change: 0 additions & 1 deletion src/yimage.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ class Graphics;

class YImage: public refcounted {
public:
static ref<YImage> create(unsigned width, unsigned height);
static ref<YImage> load(upath filename);
static ref<YImage> createFromPixmap(ref<YPixmap> image);
static ref<YImage> createFromPixmapAndMask(Pixmap pix, Pixmap mask,
Expand Down
88 changes: 68 additions & 20 deletions src/yimage_gdk.cc
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ extern "C" {

class YImageGDK: public YImage {
public:
YImageGDK(unsigned width, unsigned height, GdkPixbuf *pixbuf): YImage(width, height) {
YImageGDK(unsigned width, unsigned height, GdkPixbuf *pixbuf):
YImage(width, height)
{
fPixbuf = pixbuf;
}
virtual ~YImageGDK() {
Expand All @@ -20,23 +22,15 @@ class YImageGDK: public YImage {
virtual ref<YPixmap> renderToPixmap(unsigned depth);
virtual ref<YImage> scale(unsigned width, unsigned height);
virtual void draw(Graphics &g, int dx, int dy);
virtual void draw(Graphics &g, int x, int y, unsigned w, unsigned h, int dx, int dy);
virtual void composite(Graphics &g, int x, int y, unsigned w, unsigned h, int dx, int dy);
virtual void draw(Graphics &g, int x, int y,
unsigned w, unsigned h, int dx, int dy);
virtual void composite(Graphics &g, int x, int y,
unsigned w, unsigned h, int dx, int dy);
virtual bool valid() const { return fPixbuf != 0; }
private:
GdkPixbuf *fPixbuf;
};

ref<YImage> YImage::create(unsigned width, unsigned height) {
ref<YImage> image;
GdkPixbuf *pixbuf =
gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, width, height);
if (pixbuf != NULL) {
image.init(new YImageGDK(width, height, pixbuf));
}
return image;
}

ref<YImage> YImage::load(upath filename) {
ref<YImage> image;
GError *gerror = 0;
Expand Down Expand Up @@ -159,18 +153,72 @@ ref<YImage> YImage::createFromPixmapAndMaskScaled(Pixmap pix, Pixmap mask,

ref<YPixmap> YImageGDK::renderToPixmap(unsigned depth) {
Pixmap pixmap = None, mask = None;
gdk_pixbuf_xlib_render_pixmap_and_mask(fPixbuf, &pixmap, &mask, 128);

return createPixmap(pixmap, mask,
gdk_pixbuf_get_width(fPixbuf),
gdk_pixbuf_get_height(fPixbuf),
depth);
if (depth == (unsigned) xlib_rgb_get_depth()) {
gdk_pixbuf_xlib_render_pixmap_and_mask(fPixbuf, &pixmap, &mask, 128);
}
else if (depth == 32) {
int width = int(this->width());
int height = int(this->height());
XImage* image = XCreateImage(xapp->display(), xapp->visual(), depth,
ZPixmap, 0, NULL, width, height, 8, 0);
if (image)
image->data = (char *) calloc(image->bytes_per_line * height, 1);
XImage* imask = XCreateImage(xapp->display(), xapp->visual(), 1,
XYPixmap, 0, NULL, width, height, 8, 0);
if (imask)
imask->data = (char *) calloc(imask->bytes_per_line * height, 1);

if (image && image->data && imask && imask->data) {
if (4 != gdk_pixbuf_get_n_channels(fPixbuf) ||
1 != gdk_pixbuf_get_has_alpha(fPixbuf)) {
static int atmost(3);
if (atmost-- > 0)
tlog("gdk pixbuf channels %d != 4 || has_alpha %d != 1",
gdk_pixbuf_get_n_channels(fPixbuf),
gdk_pixbuf_get_has_alpha(fPixbuf));
}
guchar *pixels = gdk_pixbuf_get_pixels(fPixbuf);

for (int r = 0; r < height; r++) {
for (int c = 0; c < width; c++) {
XPutPixel(image, c, r,
(pixels[c * 4] << 16) +
(pixels[c * 4 + 1] << 8) +
(pixels[c * 4 + 2] << 0) +
(pixels[c * 4 + 3] << 24));
XPutPixel(imask, c, r, pixels[c * 4 + 3] >= 128);
}
pixels += gdk_pixbuf_get_rowstride(fPixbuf);
}

pixmap = XCreatePixmap(xapp->display(), xapp->root(),
width, height, depth);
GC gc = XCreateGC(xapp->display(), pixmap, None, None);
XPutImage(xapp->display(), pixmap, gc, image,
0, 0, 0, 0, width, height);
XFreeGC(xapp->display(), gc);

mask = XCreatePixmap(xapp->display(), xapp->root(),
width, height, 1);
gc = XCreateGC(xapp->display(), mask, None, None);
XPutImage(xapp->display(), mask, gc, imask,
0, 0, 0, 0, width, height);
XFreeGC(xapp->display(), gc);

XDestroyImage(image);
XDestroyImage(imask);
}
}

return createPixmap(pixmap, mask, width(), height(), depth);
}

ref<YPixmap> YImage::createPixmap(Pixmap pixmap, Pixmap mask, unsigned w, unsigned h, unsigned depth) {
ref<YPixmap> YImage::createPixmap(Pixmap pixmap, Pixmap mask,
unsigned w, unsigned h, unsigned depth) {
ref<YPixmap> n;

n.init(new YPixmap(pixmap, mask, w, h, depth));
n.init(new YPixmap(pixmap, mask, w, h, depth, ref<YImage>(this)));
return n;
}

Expand Down
69 changes: 57 additions & 12 deletions src/ypaint.cc
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ void YColor::alloc() {
double u_red, u_green, u_blue;

pix = 0xFFFFFFFF;
ncells = DisplayCells(display(), DefaultScreen(display()));
ncells = DisplayCells(display(), xapp->screen());
for (j = 0; j < ncells; j++) {
clr.pixel = j;
XQueryColor(display(), colormap(), &clr);
Expand Down Expand Up @@ -165,11 +165,9 @@ void YColor::alloc() {
}
if (XAllocColor(display(), colormap(), &color) == 0) {
if (color.red + color.green + color.blue >= 32768)
color.pixel = WhitePixel(display(),
DefaultScreen(display()));
color.pixel = xapp->white();
else
color.pixel = BlackPixel(display(),
DefaultScreen(display()));
color.pixel = xapp->black();
}
}
fRed = color.red;
Expand Down Expand Up @@ -237,7 +235,7 @@ Graphics::Graphics(YWindow & window):
#endif
}

Graphics::Graphics(const ref<YPixmap> &pixmap, int x_org, int y_org):
Graphics::Graphics(ref<YPixmap> pixmap, int x_org, int y_org):
fDrawable(pixmap->pixmap()),
fColor(NULL), fFont(null),
xOrigin(x_org), yOrigin(y_org)
Expand Down Expand Up @@ -312,7 +310,8 @@ void Graphics::copyArea(const int x, const int y,
}

void Graphics::copyDrawable(Drawable const d,
const int x, const int y, const unsigned w, const unsigned h,
const int x, const int y,
const unsigned w, const unsigned h,
const int dx, const int dy)
{
if (d == None)
Expand All @@ -323,8 +322,9 @@ void Graphics::copyDrawable(Drawable const d,
dx - xOrigin, dy - yOrigin);
}

void Graphics::copyPixmap(const ref<YPixmap> &p,
const int x, const int y, const unsigned w, const unsigned h,
void Graphics::copyPixmap(ref<YPixmap> p,
const int x, const int y,
const unsigned w, const unsigned h,
const int dx, const int dy)
{
if (p == null)
Expand All @@ -333,8 +333,17 @@ void Graphics::copyPixmap(const ref<YPixmap> &p,
copyDrawable(p->pixmap(), x, y, w, h, dx, dy);
return;
}
tlog("Graphics::%s: attempt to copy pixmap 0x%lx of depth %d using gc of depth %d\n",
__func__, p->pixmap(), p->depth(), rdepth());

if (32 == rdepth()) {
Pixmap pixmap32 = p->pixmap32();
if (pixmap32) {
copyDrawable(pixmap32, x, y, w, h, dx, dy);
return;
}
}

tlog("%s:%d:Graphics::%s: attempt to copy pixmap 0x%lx of depth %d using gc of depth %d",
__FILE__, __LINE__, __func__, p->pixmap(), p->depth(), rdepth());
}

/******************************************************************************/
Expand Down Expand Up @@ -996,7 +1005,43 @@ void Graphics::repVert(Drawable d, unsigned pw, unsigned ph, int x, int y, unsig
#endif
}

void Graphics::fillPixmap(const ref<YPixmap> &pixmap, int x, int y,
void Graphics::repHorz(ref<YPixmap> p, int x, int y, unsigned w) {
if (p == null)
return;

if (p->depth() == rdepth()) {
repHorz(p->pixmap(), p->width(), p->height(), x, y, w);
return;
}

if (32 == rdepth()) {
Pixmap pixmap = p->pixmap32();
if (pixmap) {
repHorz(pixmap, p->width(), p->height(), x, y, w);
return;
}
}
}

void Graphics::repVert(ref<YPixmap> p, int x, int y, unsigned h) {
if (p == null)
return;

if (p->depth() == rdepth()) {
repVert(p->pixmap(), p->width(), p->height(), x, y, h);
return;
}

if (32 == rdepth()) {
Pixmap pixmap32 = p->pixmap32();
if (pixmap32) {
repVert(pixmap32, p->width(), p->height(), x, y, h);
return;
}
}
}

void Graphics::fillPixmap(ref<YPixmap> pixmap, int x, int y,
unsigned w, unsigned h, int px, int py) {
int const pw(pixmap->width());
int const ph(pixmap->height());
Expand Down
16 changes: 5 additions & 11 deletions src/ypaint.h
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ class Graphics {
public:
Graphics(YWindow & window, unsigned long vmask, XGCValues * gcv);
Graphics(YWindow & window);
Graphics(const ref<YPixmap> &pixmap, int x_org, int y_org);
Graphics(ref<YPixmap> pixmap, int x_org, int y_org);
Graphics(Drawable drawable, unsigned w, unsigned h, unsigned depth, unsigned long vmask, XGCValues * gcv);
Graphics(Drawable drawable, unsigned w, unsigned h, unsigned depth);
~Graphics();
Expand All @@ -142,7 +142,7 @@ class Graphics {
copyImage(im, 0, 0, im->width, im->height, x, y);
}
#endif
void copyPixmap(const ref<YPixmap> &p, const int x, const int y,
void copyPixmap(ref<YPixmap> p, const int x, const int y,
const unsigned w, const unsigned h, const int dx, const int dy);

void drawPoint(int x, int y);
Expand Down Expand Up @@ -196,7 +196,7 @@ class Graphics {
void drawOutline(int l, int t, int r, int b, unsigned iw, unsigned ih);
void repHorz(Drawable drawable, unsigned pw, unsigned ph, int x, int y, unsigned w);
void repVert(Drawable drawable, unsigned pw, unsigned ph, int x, int y, unsigned h);
void fillPixmap(const ref<YPixmap> &pixmap, int x, int y, unsigned w, unsigned h,
void fillPixmap(ref<YPixmap> pixmap, int x, int y, unsigned w, unsigned h,
int sx = 0, int sy = 0);

void drawSurface(YSurface const & surface, int x, int y, unsigned w, unsigned h,
Expand All @@ -213,14 +213,8 @@ class Graphics {
drawGradient(gradient, x, y, w, h, 0, 0, w, h);
}

void repHorz(ref<YPixmap> p, int x, int y, unsigned w) {
if (p != null)
repHorz(p->pixmap(), p->width(), p->height(), x, y, w);
}
void repVert(ref<YPixmap> p, int x, int y, unsigned h) {
if (p != null)
repVert(p->pixmap(), p->width(), p->height(), x, y, h);
}
void repHorz(ref<YPixmap> p, int x, int y, unsigned w);
void repVert(ref<YPixmap> p, int x, int y, unsigned h);

Drawable drawable() const { return fDrawable; }
GC handleX() const { return gc; }
Expand Down
16 changes: 15 additions & 1 deletion src/ypixmap.cc
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,20 @@ YPixmap::~YPixmap() {
}
}

ref<YImage> YPixmap::image() {
if (fImage == null) {
fImage = YImage::createFromPixmap(ref<YPixmap>(this));
}
return fImage;
}

Pixmap YPixmap::pixmap32() {
if (fPixmap32 == null && image() != null) {
fPixmap32 = fImage->renderToPixmap(32);
}
return fPixmap32 != null ? fPixmap32->pixmap() : None;
}

ref<YPixmap> YPixmap::scale(unsigned const w, unsigned const h) {
ref<YPixmap> pixmap;
pixmap.init(this);
Expand All @@ -84,7 +98,7 @@ ref<YPixmap> YPixmap::create(unsigned w, unsigned h, unsigned depth, bool useMas
Pixmap pixmap = createPixmap(w, h, depth);
Pixmap mask = useMask ? createMask(w, h) : None;
if (pixmap != None && (!useMask || mask != None)) {
n.init(new YPixmap(pixmap, mask, w, h, depth));
n.init(new YPixmap(pixmap, mask, w, h, depth, null));
}
return n;
}
Expand Down
32 changes: 17 additions & 15 deletions src/ypixmap.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,32 +16,33 @@ class YPixmap: public virtual refcounted {
static ref<YPixmap> createFromPixmapAndMask(Pixmap pixmap,
Pixmap mask,
unsigned w, unsigned h);
#if 1
static ref<YPixmap> createFromPixmapAndMaskScaled(Pixmap pix, Pixmap mask,
unsigned width, unsigned height,
unsigned nw, unsigned nh);
#endif

#if 1
void replicate(bool horiz, bool copyMask);
#endif

#if 1
Pixmap pixmap() const { return fPixmap; }
Pixmap mask() const { return fMask; }
#endif
unsigned width() const { return fWidth; }
unsigned height() const { return fHeight; }
unsigned depth() const { return fDepth; }
ref<YImage> image();
Pixmap pixmap32();
ref<YPixmap> scale(unsigned w, unsigned h);

protected:
YPixmap(Pixmap pixmap, Pixmap mask, unsigned w, unsigned h, unsigned depth) {
fPixmap = pixmap;
fMask = mask;
fWidth = w;
fHeight = h;
fDepth = depth;
private:
YPixmap(Pixmap pixmap, Pixmap mask,
unsigned width, unsigned height,
unsigned depth, ref<YImage> image):
fWidth(width),
fHeight(height),
fDepth(depth),
fPixmap(pixmap),
fMask(mask),
fImage(image),
fPixmap32()
{
}
virtual ~YPixmap();

Expand All @@ -51,10 +52,11 @@ class YPixmap: public virtual refcounted {
unsigned fWidth;
unsigned fHeight;
unsigned fDepth;
#if 1

Pixmap fPixmap;
Pixmap fMask;
#endif
ref<YImage> fImage;
ref<YPixmap> fPixmap32;
};

#endif
Expand Down
Loading

0 comments on commit 6291dee

Please sign in to comment.