1
2 /******************************************************************************
3 * MODULE : x_picture.cpp
4 * DESCRIPTION: X pictures
5 * COPYRIGHT : (C) 2013 Joris van der Hoeven
6 *******************************************************************************
7 * This software falls under the GNU general public license version 3 or later.
8 * It comes WITHOUT ANY WARRANTY WHATSOEVER. For details, see the file LICENSE
9 * in the root directory or <http://www.gnu.org/licenses/gpl-3.0.html>.
10 ******************************************************************************/
11
12 #include "X11/x_window.hpp"
13 #include "x_picture.hpp"
14 #include "analyze.hpp"
15 #include "file.hpp"
16 #include "image_files.hpp"
17 #include "iterator.hpp"
18 #include "Ghostscript/ghostscript.hpp"
19
20 #define IMLIB2_X11TEXMACS // for imlib2_display
21 #include "Imlib2/imlib2.hpp"
22
23 extern hashmap<tree,string> ps_bbox;
24 extern int nr_windows;
25
26 #define VCONVERT(c) (true_colors? (c & 0xffffff): the_gui->cmap [c & 0xffffff])
27
28 /******************************************************************************
29 * Abstract X pictures
30 ******************************************************************************/
31
x_picture_rep(Pixmap pm2,int w2,int h2,int ox2,int oy2)32 x_picture_rep::x_picture_rep (Pixmap pm2, int w2, int h2, int ox2, int oy2):
33 pm (pm2), im (NULL), bm (0), data (NULL),
34 w (w2), h (h2), ox (ox2), oy (oy2), ok (true) {}
~x_picture_rep()35 x_picture_rep::~x_picture_rep () {
36 XFreePixmap (the_gui->dpy, pm);
37 if (im != NULL) XDestroyImage (im);
38 if (bm != 0) XFreePixmap (the_gui->dpy, bm);
39 if (data != NULL) tm_delete_array (data); }
40
41 void
force_mask()42 x_picture_rep::force_mask () {
43 int byte_width= ((w-1)>>3)+1;
44 if (data == NULL) {
45 data= tm_new_array<char> (byte_width * h);
46 for (int i=0; i<byte_width * h; i++) data[i]= 0x00;
47 }
48 if (bm == 0)
49 bm= XCreateBitmapFromData (the_gui->dpy, the_gui->root, data, w, h);
50 ok= true;
51 }
52
get_type()53 picture_kind x_picture_rep::get_type () { return picture_native; }
get_handle()54 void* x_picture_rep::get_handle () { return (void*) this; }
55
get_width()56 int x_picture_rep::get_width () { return w; }
get_height()57 int x_picture_rep::get_height () { return h; }
get_origin_x()58 int x_picture_rep::get_origin_x () { return ox; }
get_origin_y()59 int x_picture_rep::get_origin_y () { return oy; }
set_origin(int ox2,int oy2)60 void x_picture_rep::set_origin (int ox2, int oy2) { ox= ox2; oy= oy2; }
61
62 color
internal_get_pixel(int x,int y)63 x_picture_rep::internal_get_pixel (int x, int y) {
64 if (im == NULL)
65 im= XGetImage (the_gui->dpy, pm, 0, 0, w, h, AllPlanes, XYPixmap);
66 if (im != NULL) {
67 unsigned long c= XGetPixel (im, x, h-1-y);
68 int r= (c >> 16) & 0xff;
69 int g= (c >> 8 ) & 0xff;
70 int b= (c ) & 0xff;
71 if (r == 0x64 && g == 0x65 && b == 0x66) return 0x00ffffff;
72 return rgb_color (r, g, b, 255);
73 }
74 return 0;
75 }
76
77 void
internal_set_pixel(int x,int y,color col)78 x_picture_rep::internal_set_pixel (int x, int y, color col) {
79 if (0 > x || 0 > y || x >= w || y >= h) return;
80 ok= false;
81 int r, g, b, a;
82 get_rgb_color (col, r, g, b, a);
83 r= (r * a + 255 * (255 - a)) / 255;
84 g= (g * a + 255 * (255 - a)) / 255;
85 b= (b * a + 255 * (255 - a)) / 255;
86 col= rgb_color (r, g, b, 255);
87 XSetForeground (the_gui->dpy, the_gui->pixmap_gc, VCONVERT (col));
88 XDrawPoint (the_gui->dpy, (Drawable) pm, the_gui->pixmap_gc, x, h - 1 - y);
89 if (im != NULL)
90 XPutPixel (im, x, h-1-y, (r << 16) + (g << 8) + b);
91 if (data == NULL && a < 64) {
92 int byte_width= ((w-1)>>3)+1;
93 data= tm_new_array<char> (byte_width * h);
94 for (int i=0; i<byte_width * h; i++) data[i]= 0xff;
95 }
96 if (data != NULL) {
97 int byte_width= ((w-1)>>3)+1;
98 int idx= (h-1-y) * byte_width + (x>>3);
99 if (a < 64)
100 data[idx]= data[idx] & (~(1<<(x&7)));
101 else
102 data[idx]= data[idx] | (1<<(x&7));
103 }
104 }
105
106 picture
x_picture(Pixmap pm,int w,int h,int ox,int oy)107 x_picture (Pixmap pm, int w, int h, int ox, int oy) {
108 return (picture) tm_new<x_picture_rep> (pm, w, h, ox, oy);
109 }
110
111 picture
as_x_picture(picture pic)112 as_x_picture (picture pic) {
113 if (pic->get_type () == picture_native) return pic;
114 int w= pic->get_width (), h= pic->get_height ();
115 int ox= pic->get_origin_x (), oy= pic->get_origin_y ();
116 Pixmap pm= XCreatePixmap (the_gui->dpy, the_gui->root, w, h, the_gui->depth);
117 picture ret= x_picture (pm, w, h, ox, oy);
118 ret->copy_from (pic);
119 return ret;
120 }
121
122 picture
as_native_picture(picture pict)123 as_native_picture (picture pict) {
124 return as_x_picture (pict);
125 }
126
127 Pixmap
retrieve_bitmap(picture pic)128 retrieve_bitmap (picture pic) {
129 x_picture_rep* rep= (x_picture_rep*) pic->get_handle ();
130 rep->force_mask ();
131 return rep->bm;
132 }
133
134 Pixmap
retrieve_pixmap(picture pic)135 retrieve_pixmap (picture pic) {
136 x_picture_rep* rep= (x_picture_rep*) pic->get_handle ();
137 return rep->pm;
138 }
139
140 picture
native_picture(int w,int h,int ox,int oy)141 native_picture (int w, int h, int ox, int oy) {
142 Pixmap pm= XCreatePixmap (the_gui->dpy, the_gui->root, w, h, the_gui->depth);
143 return x_picture (pm, w, h, ox, oy);
144 }
145
146 void
draw_picture(picture p,SI x,SI y,int alpha)147 x_drawable_rep::draw_picture (picture p, SI x, SI y, int alpha) {
148 (void) alpha; // FIMXE: might be improved
149 p= as_x_picture (p);
150 x_picture_rep* pict= (x_picture_rep*) p->get_handle ();
151 int w= pict->w, h= pict->h;
152 int x0= pict->ox, y0= pict->h - 1 - pict->oy;
153 decode (x, y);
154 x -= x0; y -= y0;
155 int x1=cx1-ox, y1=cy2-oy, x2= cx2-ox, y2= cy1-oy;
156 outer_round (x1, y1, x2, y2);
157 decode (x1, y1);
158 decode (x2, y2);
159 int X1= max (x1- x, 0); if (X1>=w) return;
160 int Y1= max (y1- y, 0); if (Y1>=h) return;
161 int X2= min (x2- x, w); if (X2<0) return;
162 int Y2= min (y2- y, h); if (Y2<0) return;
163 if (pict->data != NULL) {
164 if (!pict->ok) {
165 if (pict->bm != 0) XFreePixmap (gui->dpy, pict->bm);
166 pict->bm= XCreateBitmapFromData (gui->dpy, gui->root, pict->data, w, h);
167 pict->ok= true;
168 }
169 XSetClipMask (dpy, gc, pict->bm);
170 XSetClipOrigin (dpy, gc, x, y);
171 XCopyArea (dpy, pict->pm, win, gc, X1, Y1, X2-X1, Y2-Y1, x+X1, y+Y1);
172 set_clipping (cx1- ox, cy1- oy, cx2- ox, cy2- oy);
173 }
174 else
175 XCopyArea (dpy, pict->pm, win, gc, X1, Y1, X2-X1, Y2-Y1, x+X1, y+Y1);
176 }
177
178 /******************************************************************************
179 * Rendering on images
180 ******************************************************************************/
181
182 Pixmap
get_Pixmap(picture p)183 get_Pixmap (picture p) {
184 x_picture_rep* rep= (x_picture_rep*) p->get_handle ();
185 return rep->pm;
186 }
187
x_image_renderer_rep(picture p,double zoom)188 x_image_renderer_rep::x_image_renderer_rep (picture p, double zoom):
189 x_drawable_rep (the_gui, get_Pixmap (p), p->get_width (), p->get_height ()),
190 pict (p)
191 {
192 zoomf = zoom;
193 shrinkf= (int) tm_round (std_shrinkf / zoomf);
194 pixel = (SI) tm_round ((std_shrinkf * PIXEL) / zoomf);
195 thicken= (shrinkf >> 1) * PIXEL;
196
197 int pw = p->get_width ();
198 int ph = p->get_height ();
199 int pox= p->get_origin_x ();
200 int poy= p->get_origin_y ();
201
202 ox = pox * pixel;
203 oy = poy * pixel;
204 cx1= 0;
205 cy1= 0;
206 cx2= pw * pixel;
207 cy2= ph * pixel;
208
209 Region region= XCreateRegion ();
210 XRectangle r;
211 r.x = 0;
212 r.y = 0;
213 r.width = w;
214 r.height= h;
215 XUnionRectWithRegion (&r, region, region);
216 XSetRegion (dpy, gc, region);
217 XDestroyRegion (region);
218 XSetForeground (dpy, gc, VCONVERT (white));
219 XFillRectangle (dpy, win, gc, 0, 0, w, h);
220 }
221
~x_image_renderer_rep()222 x_image_renderer_rep::~x_image_renderer_rep () {}
223
224 void*
get_data_handle()225 x_image_renderer_rep::get_data_handle () {
226 return (void*) this;
227 }
228
229 renderer
picture_renderer(picture p,double zoomf)230 picture_renderer (picture p, double zoomf) {
231 return (renderer) tm_new<x_image_renderer_rep> (p, zoomf);
232 }
233
234 /******************************************************************************
235 * Loading pictures
236 ******************************************************************************/
237
238 Pixmap
load_Pixmap(url u,int w,int h)239 load_Pixmap (url u, int w, int h) {
240 if (the_gui->gswindow == NULL) {
241 SI max_w= the_gui->screen_width * PIXEL;
242 SI max_h= the_gui->screen_height * PIXEL;
243 //widget dummy= text_widget (0, "ghostscript window");
244 if (ghostscript_bugged ()) {
245 max_w *= 2;
246 max_h *= 2;
247 //dummy= glue_widget (false, false, max_w, max_h);
248 }
249 widget dummy = glue_widget (false, false, max_w, max_h);
250 widget win = plain_window_widget (dummy, "Ghostscript");
251 the_gui->gswindow= get_x_window (win);
252 //the_gui->gswindow= tm_new<x_window_rep> (dummy, the_gui, "ghostscript",
253 //0, 0);
254 //the_gui->gswindow= tm_new<x_window_rep> (dummy, the_gui, "ghostscript",
255 //max_w, max_h, max_w, max_h, max_w, max_h);
256 nr_windows--; // the dummy window should not be counted
257 }
258
259 Pixmap pm;
260 Window gs_win= the_gui->gswindow->win;
261
262 // XCreatePixmap does not allow for zero sized images.
263 // This fixes bug #10425.
264 w = (w==0 ? 1 : w);
265 h = (h==0 ? 1 : h);
266
267 pm= XCreatePixmap (the_gui->dpy, gs_win, w, h, the_gui->depth);
268 if (imlib2_supports (u))
269 imlib2_display (the_gui->dpy, pm, u, w, h);
270 else {
271 //XSetForeground (the_gui->dpy, gc, white);
272 //XFillRectangle (the_gui->dpy, pm, gc, 0, 0, w, h);
273 ghostscript_run (the_gui->dpy, gs_win, pm, u, w, h);
274 }
275
276 return pm;
277 }
278
279 picture
load_picture(url u,int w,int h)280 load_picture (url u, int w, int h) {
281 Pixmap pm= load_Pixmap (u, w, h);
282 if (pm == 0) return error_picture (w, h);
283 return x_picture (pm, w, h, 0, 0);
284 }
285