blob: f36976faaf6088bfc6a8624846266e688ed5d769 [file] [log] [blame]
Pierre Ossman403ac272017-01-02 17:00:41 +01001/* Copyright 2016 Pierre Ossman for Cendio AB
2 *
3 * This is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This software is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this software; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
16 * USA.
17 */
18
19#include <assert.h>
20
21#include <FL/Fl_RGB_Image.H>
22#include <FL/x.H>
23
24#include <rdr/Exception.h>
25
26#include "Surface.h"
27
28void Surface::clear(unsigned char r, unsigned char g, unsigned char b, unsigned char a)
29{
30 XRenderColor color;
31
32 color.red = (unsigned)r * 65535 / 255 * a / 255;
33 color.green = (unsigned)g * 65535 / 255 * a / 255;
34 color.blue = (unsigned)b * 65535 / 255 * a / 255;
35 color.alpha = (unsigned)a * 65535 / 255;
36
37 XRenderFillRectangle(fl_display, PictOpSrc, picture, &color,
38 0, 0, width(), height());
39}
40
41void Surface::draw(int src_x, int src_y, int x, int y, int w, int h)
42{
43 Picture winPict;
44
45 winPict = XRenderCreatePicture(fl_display, fl_window, visFormat, 0, NULL);
46 XRenderComposite(fl_display, PictOpSrc, picture, None, winPict,
47 src_x, src_y, 0, 0, x, y, w, h);
48 XRenderFreePicture(fl_display, winPict);
49}
50
Pierre Ossman3d74d882017-01-02 19:49:52 +010051void Surface::draw(Surface* dst, int src_x, int src_y, int x, int y, int w, int h)
52{
53 XRenderComposite(fl_display, PictOpSrc, picture, None, dst->picture,
54 src_x, src_y, 0, 0, x, y, w, h);
55}
56
Pierre Ossmande6a5802017-01-02 20:07:10 +010057void Surface::blend(int src_x, int src_y, int x, int y, int w, int h)
58{
59 Picture winPict;
60
61 winPict = XRenderCreatePicture(fl_display, fl_window, visFormat, 0, NULL);
62 XRenderComposite(fl_display, PictOpOver, picture, None, winPict,
63 src_x, src_y, 0, 0, x, y, w, h);
64 XRenderFreePicture(fl_display, winPict);
65}
66
67void Surface::blend(Surface* dst, int src_x, int src_y, int x, int y, int w, int h)
68{
69 XRenderComposite(fl_display, PictOpOver, picture, None, dst->picture,
70 src_x, src_y, 0, 0, x, y, w, h);
71}
72
73
Pierre Ossman403ac272017-01-02 17:00:41 +010074void Surface::alloc()
75{
76 XRenderPictFormat* format;
77
78 // Might not be open at this point
79 fl_open_display();
80
81 pixmap = XCreatePixmap(fl_display, XDefaultRootWindow(fl_display),
82 width(), height(), 32);
83
84 format = XRenderFindStandardFormat(fl_display, PictStandardARGB32);
85 picture = XRenderCreatePicture(fl_display, pixmap, format, 0, NULL);
86
87 visFormat = XRenderFindVisualFormat(fl_display, fl_visual->visual);
88}
89
90void Surface::dealloc()
91{
92 XRenderFreePicture(fl_display, picture);
93 XFreePixmap(fl_display, pixmap);
94}
95
96void Surface::update(const Fl_RGB_Image* image)
97{
98 XImage* img;
99 GC gc;
100
101 int x, y;
102 const unsigned char* in;
103 unsigned char* out;
104
105 assert(image->w() == width());
106 assert(image->h() == height());
107
108 img = XCreateImage(fl_display, CopyFromParent, 32,
109 ZPixmap, 0, NULL, width(), height(),
110 32, 0);
111 if (!img)
112 throw rdr::Exception("XCreateImage");
113
114 img->data = (char*)malloc(img->bytes_per_line * img->height);
115 if (!img->data)
116 throw rdr::Exception("malloc");
117
118 // Convert data and pre-multiply alpha
119 in = (const unsigned char*)image->data()[0];
120 out = (unsigned char*)img->data;
121 for (y = 0;y < img->height;y++) {
122 for (x = 0;x < img->width;x++) {
123 switch (image->d()) {
124 case 1:
125 *out++ = in[0];
126 *out++ = in[0];
127 *out++ = in[0];
128 *out++ = 0xff;
129 break;
130 case 2:
131 *out++ = (unsigned)in[0] * in[1] / 255;
132 *out++ = (unsigned)in[0] * in[1] / 255;
133 *out++ = (unsigned)in[0] * in[1] / 255;
134 *out++ = in[1];
135 break;
136 case 3:
137 *out++ = in[2];
138 *out++ = in[1];
139 *out++ = in[0];
140 *out++ = 0xff;
141 break;
142 case 4:
143 *out++ = (unsigned)in[2] * in[3] / 255;
144 *out++ = (unsigned)in[1] * in[3] / 255;
145 *out++ = (unsigned)in[0] * in[3] / 255;
146 *out++ = in[3];
147 break;
148 }
149 in += image->d();
150 }
151 if (image->ld() != 0)
152 in += image->ld() - image->w() * image->d();
153 }
154
155 gc = XCreateGC(fl_display, pixmap, 0, NULL);
156 XPutImage(fl_display, pixmap, gc, img,
157 0, 0, 0, 0, img->width, img->height);
158 XFreeGC(fl_display, gc);
159
160 XDestroyImage(img);
161}
162