|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198 |
- /* Copyright 2016 Pierre Ossman for Cendio AB
- *
- * This is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this software; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
- * USA.
- */
-
- #include <assert.h>
-
- #include <FL/Fl_RGB_Image.H>
- #include <FL/x.H>
-
- #include <rdr/Exception.h>
-
- #include "Surface.h"
-
- void Surface::clear(unsigned char r, unsigned char g, unsigned char b, unsigned char a)
- {
- XRenderColor color;
-
- color.red = (unsigned)r * 65535 / 255 * a / 255;
- color.green = (unsigned)g * 65535 / 255 * a / 255;
- color.blue = (unsigned)b * 65535 / 255 * a / 255;
- color.alpha = (unsigned)a * 65535 / 255;
-
- XRenderFillRectangle(fl_display, PictOpSrc, picture, &color,
- 0, 0, width(), height());
- }
-
- void Surface::draw(int src_x, int src_y, int x, int y, int w, int h)
- {
- Picture winPict;
-
- winPict = XRenderCreatePicture(fl_display, fl_window, visFormat, 0, NULL);
- XRenderComposite(fl_display, PictOpSrc, picture, None, winPict,
- src_x, src_y, 0, 0, x, y, w, h);
- XRenderFreePicture(fl_display, winPict);
- }
-
- void Surface::draw(Surface* dst, int src_x, int src_y, int x, int y, int w, int h)
- {
- XRenderComposite(fl_display, PictOpSrc, picture, None, dst->picture,
- src_x, src_y, 0, 0, x, y, w, h);
- }
-
- static Picture alpha_mask(int a)
- {
- Pixmap pixmap;
- XRenderPictFormat* format;
- XRenderPictureAttributes rep;
- Picture pict;
- XRenderColor color;
-
- if (a == 255)
- return None;
-
- pixmap = XCreatePixmap(fl_display, XDefaultRootWindow(fl_display),
- 1, 1, 8);
-
- format = XRenderFindStandardFormat(fl_display, PictStandardA8);
- rep.repeat = RepeatNormal;
- pict = XRenderCreatePicture(fl_display, pixmap, format, CPRepeat, &rep);
- XFreePixmap(fl_display, pixmap);
-
- color.alpha = (unsigned)a * 65535 / 255;
-
- XRenderFillRectangle(fl_display, PictOpSrc, pict, &color,
- 0, 0, 1, 1);
-
- return pict;
- }
-
- void Surface::blend(int src_x, int src_y, int x, int y, int w, int h, int a)
- {
- Picture winPict, alpha;
-
- winPict = XRenderCreatePicture(fl_display, fl_window, visFormat, 0, NULL);
- alpha = alpha_mask(a);
- XRenderComposite(fl_display, PictOpOver, picture, alpha, winPict,
- src_x, src_y, 0, 0, x, y, w, h);
- XRenderFreePicture(fl_display, winPict);
-
- if (alpha != None)
- XRenderFreePicture(fl_display, alpha);
- }
-
- void Surface::blend(Surface* dst, int src_x, int src_y, int x, int y, int w, int h, int a)
- {
- Picture alpha;
-
- alpha = alpha_mask(a);
- XRenderComposite(fl_display, PictOpOver, picture, alpha, dst->picture,
- src_x, src_y, 0, 0, x, y, w, h);
- if (alpha != None)
- XRenderFreePicture(fl_display, alpha);
- }
-
-
- void Surface::alloc()
- {
- XRenderPictFormat* format;
-
- // Might not be open at this point
- fl_open_display();
-
- pixmap = XCreatePixmap(fl_display, XDefaultRootWindow(fl_display),
- width(), height(), 32);
-
- format = XRenderFindStandardFormat(fl_display, PictStandardARGB32);
- picture = XRenderCreatePicture(fl_display, pixmap, format, 0, NULL);
-
- visFormat = XRenderFindVisualFormat(fl_display, fl_visual->visual);
- }
-
- void Surface::dealloc()
- {
- XRenderFreePicture(fl_display, picture);
- XFreePixmap(fl_display, pixmap);
- }
-
- void Surface::update(const Fl_RGB_Image* image)
- {
- XImage* img;
- GC gc;
-
- int x, y;
- const unsigned char* in;
- unsigned char* out;
-
- assert(image->w() == width());
- assert(image->h() == height());
-
- img = XCreateImage(fl_display, CopyFromParent, 32,
- ZPixmap, 0, NULL, width(), height(),
- 32, 0);
- if (!img)
- throw rdr::Exception("XCreateImage");
-
- img->data = (char*)malloc(img->bytes_per_line * img->height);
- if (!img->data)
- throw rdr::Exception("malloc");
-
- // Convert data and pre-multiply alpha
- in = (const unsigned char*)image->data()[0];
- out = (unsigned char*)img->data;
- for (y = 0;y < img->height;y++) {
- for (x = 0;x < img->width;x++) {
- switch (image->d()) {
- case 1:
- *out++ = in[0];
- *out++ = in[0];
- *out++ = in[0];
- *out++ = 0xff;
- break;
- case 2:
- *out++ = (unsigned)in[0] * in[1] / 255;
- *out++ = (unsigned)in[0] * in[1] / 255;
- *out++ = (unsigned)in[0] * in[1] / 255;
- *out++ = in[1];
- break;
- case 3:
- *out++ = in[2];
- *out++ = in[1];
- *out++ = in[0];
- *out++ = 0xff;
- break;
- case 4:
- *out++ = (unsigned)in[2] * in[3] / 255;
- *out++ = (unsigned)in[1] * in[3] / 255;
- *out++ = (unsigned)in[0] * in[3] / 255;
- *out++ = in[3];
- break;
- }
- in += image->d();
- }
- if (image->ld() != 0)
- in += image->ld() - image->w() * image->d();
- }
-
- gc = XCreateGC(fl_display, pixmap, 0, NULL);
- XPutImage(fl_display, pixmap, gc, img,
- 0, 0, 0, 0, img->width, img->height);
- XFreeGC(fl_display, gc);
-
- XDestroyImage(img);
- }
-
|