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