~ubuntu-branches/ubuntu/hardy/texmacs/hardy

« back to all changes in this revision

Viewing changes to src/Window/X/x_drawable.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Ralf Treinen
  • Date: 2004-04-19 20:34:00 UTC
  • Revision ID: james.westby@ubuntu.com-20040419203400-g4e34ih0315wcn8v
Tags: upstream-1.0.3-R2
ImportĀ upstreamĀ versionĀ 1.0.3-R2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
2
/******************************************************************************
 
3
* MODULE     : x_drawables.cpp
 
4
* DESCRIPTION: Drawables under X
 
5
* COPYRIGHT  : (C) 1999  Joris van der Hoeven
 
6
*******************************************************************************
 
7
* This software falls under the GNU general public license and comes WITHOUT
 
8
* ANY WARRANTY WHATSOEVER. See the file $TEXMACS_PATH/LICENSE for more details.
 
9
* If you don't have this file, write to the Free Software Foundation, Inc.,
 
10
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
11
******************************************************************************/
 
12
 
 
13
#include "X/x_window.hpp"
 
14
#include "file.hpp"
 
15
#include "image_files.hpp"
 
16
#include "sys_utils.hpp"
 
17
#include "analyze.hpp"
 
18
#include "iterator.hpp"
 
19
#include "Ghostscript/ghostscript.hpp"
 
20
 
 
21
extern hashmap<tree,string> ps_bbox;
 
22
 
 
23
/******************************************************************************
 
24
* Constructors and destructors
 
25
******************************************************************************/
 
26
 
 
27
x_drawable_rep::x_drawable_rep (x_display dis2, int w2, int h2):
 
28
  dis (dis2), w (w2), h (h2)
 
29
{
 
30
  dpy         = dis->dpy;
 
31
  gc          = dis->gc;
 
32
  cur_fg      = dis->black;
 
33
  cur_bg      = dis->white;
 
34
  event_status= false;
 
35
 
 
36
  black       = dis->black;
 
37
  white       = dis->white;
 
38
  red         = dis->red;
 
39
  green       = dis->green;
 
40
  blue        = dis->blue;
 
41
  yellow      = dis->yellow;
 
42
  magenta     = dis->magenta;
 
43
  orange      = dis->orange;
 
44
  brown       = dis->brown;
 
45
  pink        = dis->pink;
 
46
  light_grey  = dis->light_grey;
 
47
  grey        = dis->grey;
 
48
  dark_grey   = dis->dark_grey;
 
49
 
 
50
  if ((w>0) && (h>0))
 
51
    win= (Drawable) XCreatePixmap (dis->dpy, dis->root, w, h, dis->depth);
 
52
}
 
53
 
 
54
x_drawable_rep::~x_drawable_rep () {
 
55
  if ((w>0) && (h>0)) XFreePixmap (dis->dpy, (Pixmap) win);
 
56
}
 
57
 
 
58
int
 
59
x_drawable_rep::get_type () {
 
60
  return PS_DEVICE_SCREEN;
 
61
}
 
62
 
 
63
/******************************************************************************
 
64
* Conversion between window and postscript coordinates
 
65
******************************************************************************/
 
66
 
 
67
void
 
68
x_drawable_rep::encode (SI& x, SI& y) {
 
69
  x= (x*pixel) - ox;
 
70
  y= ((-y)*pixel) - oy;
 
71
}
 
72
 
 
73
void
 
74
x_drawable_rep::decode (SI& x, SI& y) {
 
75
  x += ox; y += oy;
 
76
  if (x>=0) x= x/pixel; else x= (x-pixel+1)/pixel;
 
77
  if (y>=0) y= -(y/pixel); else y= -((y-pixel+1)/pixel);
 
78
}
 
79
 
 
80
/******************************************************************************
 
81
* Clipping
 
82
******************************************************************************/
 
83
 
 
84
void
 
85
x_drawable_rep::set_clipping (SI x1, SI y1, SI x2, SI y2) {
 
86
  outer_round (x1, y1, x2, y2);
 
87
  ps_device_rep::set_clipping (x1, y1, x2, y2);
 
88
  Region region= XCreateRegion ();
 
89
  decode (x1, y1);
 
90
  decode (x2, y2);
 
91
  XRectangle r;
 
92
  r.x     = x1;
 
93
  r.y     = y2;
 
94
  r.width = x2-x1;
 
95
  r.height= y1-y2;
 
96
  XUnionRectWithRegion (&r, region, region);
 
97
  XSetRegion (dpy, gc, region);
 
98
  XDestroyRegion (region);
 
99
}
 
100
 
 
101
/******************************************************************************
 
102
* Drawing into drawables
 
103
******************************************************************************/
 
104
 
 
105
color
 
106
x_drawable_rep::rgb (int r, int g, int b) {
 
107
  return dis->rgb (r, g, b);
 
108
}
 
109
 
 
110
void
 
111
x_drawable_rep::get_rgb (color col, int& r, int& g, int& b) {
 
112
  dis->get_rgb (col, r, g, b);
 
113
}
 
114
 
 
115
color
 
116
x_drawable_rep::get_color () {
 
117
  return cur_fg;
 
118
}
 
119
 
 
120
color
 
121
x_drawable_rep::get_background () {
 
122
  return cur_bg;
 
123
}
 
124
 
 
125
void
 
126
x_drawable_rep::set_color (color c) {
 
127
  XSetForeground (dpy, gc, dis->cmap[c]);
 
128
  cur_fg= c;
 
129
}
 
130
 
 
131
void
 
132
x_drawable_rep::set_background (color c) {
 
133
  XSetBackground (dpy, gc, dis->cmap[c]);
 
134
  cur_bg= c;
 
135
}
 
136
 
 
137
void
 
138
x_drawable_rep::set_line_style (SI lw, int type) { (void) type;
 
139
  if (lw <= pixel)
 
140
    XSetLineAttributes (dpy, (GC) gc, 1,
 
141
                        LineSolid, CapRound, JoinRound);
 
142
  else
 
143
    XSetLineAttributes (dpy, (GC) gc, (lw+thicken) / pixel,
 
144
                        LineSolid, CapRound, JoinRound);
 
145
}
 
146
 
 
147
void
 
148
x_drawable_rep::line (SI x1, SI y1, SI x2, SI y2) {
 
149
  decode (x1, y1);
 
150
  decode (x2, y2);
 
151
  y1--; y2--; // top-left origin to bottom-left origin conversion
 
152
  XDrawLine (dpy, win, gc, x1, y1, x2, y2);
 
153
}
 
154
 
 
155
void
 
156
x_drawable_rep::clear (SI x1, SI y1, SI x2, SI y2) {
 
157
  x1= max (x1, cx1-ox); y1= max (y1, cy1-oy);
 
158
  x2= min (x2, cx2-ox); y2= min (y2, cy2-oy);
 
159
  // outer_round (x1, y1, x2, y2); might still be needed somewhere
 
160
  decode (x1, y1);
 
161
  decode (x2, y2);
 
162
  if ((x1>=x2) || (y1<=y2)) return;
 
163
  XSetForeground (dpy, gc, dis->cmap[cur_bg]);
 
164
  XFillRectangle (dpy, win, gc, x1, y2, x2-x1, y1-y2);
 
165
  XSetForeground (dpy, gc, dis->cmap[cur_fg]);
 
166
}
 
167
 
 
168
void
 
169
x_drawable_rep::fill (SI x1, SI y1, SI x2, SI y2) {
 
170
  if ((x2>x1) && ((x2-x1)<pixel)) {
 
171
    SI d= pixel-(x2-x1);
 
172
    x1 -= (d>>1);
 
173
    x2 += ((d+1)>>1);
 
174
  }
 
175
  if ((y2>y1) && ((y2-y1)<pixel)) {
 
176
    SI d= pixel-(y2-y1);
 
177
    y1 -= (d>>1);
 
178
    y2 += ((d+1)>>1);
 
179
  }
 
180
 
 
181
  x1= max (x1, cx1-ox); y1= max (y1, cy1-oy);
 
182
  x2= min (x2, cx2-ox); y2= min (y2, cy2-oy);
 
183
  // outer_round (x1, y1, x2, y2); might still be needed somewhere
 
184
  if ((x1>=x2) || (y1>=y2)) return;
 
185
 
 
186
  decode (x1, y1);
 
187
  decode (x2, y2);
 
188
  XFillRectangle (dpy, win, gc, x1, y2, x2-x1, y1-y2);
 
189
}
 
190
 
 
191
void
 
192
x_drawable_rep::arc (SI x1, SI y1, SI x2, SI y2, int alpha, int delta) {
 
193
  if ((x1>=x2) || (y1>=y2)) return;
 
194
  decode (x1, y1);
 
195
  decode (x2, y2);
 
196
  XDrawArc (dpy, win, gc, x1, y2, x2-x1, y1-y2, alpha, delta);
 
197
}
 
198
 
 
199
void
 
200
x_drawable_rep::polygon (array<SI> x, array<SI> y) {
 
201
  int i, n= N(x);
 
202
  if ((N(y) != n) || (n<1)) return;
 
203
  STACK_NEW_ARRAY (pnt, XPoint, n);
 
204
  for (i=0; i<n; i++) {
 
205
    SI xx= x[i], yy= y[i];
 
206
    decode (xx, yy);
 
207
    pnt[i].x= xx;
 
208
    pnt[i].y= yy;
 
209
  }
 
210
  XFillPolygon (dpy, win, gc, pnt, n, Convex, CoordModeOrigin);
 
211
  STACK_DELETE_ARRAY (pnt);
 
212
}
 
213
 
 
214
/******************************************************************************
 
215
* Setting up and displaying xpm pixmaps
 
216
******************************************************************************/
 
217
 
 
218
void
 
219
x_drawable_rep::xpm_initialize (url file_name) {
 
220
  tree t= xpm_load (file_name);
 
221
 
 
222
  // get main info
 
223
  int ok, i=0, j, k, w, h, c, b, x, y;
 
224
  string s= as_string (t[0]);
 
225
  skip_spaces (s, i);
 
226
  ok= read_int (s, i, w);
 
227
  skip_spaces (s, i);
 
228
  ok= read_int (s, i, h) && ok;
 
229
  skip_spaces (s, i);
 
230
  ok= read_int (s, i, c) && ok;
 
231
  skip_spaces (s, i);
 
232
  ok= read_int (s, i, b) && ok;
 
233
  if ((!ok) || (N(t)<(c+1)) || (c<=0))
 
234
    fatal_error ("Invalid xpm (" * as_string (file_name) * ")",
 
235
                 "x_drawable_rep::xpm_initialize");
 
236
 
 
237
  // setup colors
 
238
  string first_name;
 
239
  hashmap<string,int> pmcs(0);
 
240
  hashmap<string,int> bmcs(1);
 
241
  for (k=0; k<c; k++) {
 
242
    string s   = as_string (t[k+1]);
 
243
    string name= "";
 
244
    string def = "none";
 
245
    if (N(s)<b) i=N(s);
 
246
    else { name= s(0,b); i=b; }
 
247
    if (k==0) first_name= name;
 
248
 
 
249
    skip_spaces (s, i);
 
250
    if ((i<N(s)) && (s[i]=='s')) {
 
251
      i++;
 
252
      skip_spaces (s, i);
 
253
      while ((i<N(s)) && (s[i]!=' ') && (s[i]!='\t')) i++;
 
254
      skip_spaces (s, i);
 
255
    }
 
256
    if ((i<N(s)) && (s[i]=='c')) {
 
257
      i++;
 
258
      skip_spaces (s, i);
 
259
      j=i;
 
260
      while ((i<N(s)) && (s[i]!=' ') && (s[i]!='\t')) i++;
 
261
      def= locase_all (s (j, i));
 
262
    }
 
263
    if (def == "none") {
 
264
      bmcs(name)= 0;
 
265
      def= "lightgrey";
 
266
    }
 
267
    else bmcs(name)= 1;
 
268
 
 
269
    char* _def= as_charp (def);
 
270
    XColor exact, closest;
 
271
    XLookupColor (dis->dpy, dis->cols, _def, &exact, &closest);
 
272
    if (XAllocColor (dis->dpy, dis->cols, &exact))
 
273
      pmcs(name)= exact.pixel;
 
274
    else if (XAllocColor (dis->dpy, dis->cols, &closest))
 
275
      pmcs(name)= closest.pixel;
 
276
    else {
 
277
      int myc= dis->rgb ((exact.red+128)/256,
 
278
                         (exact.green+128)/256,
 
279
                         (exact.blue+128)/256);
 
280
      pmcs(name)= dis->cmap[myc];
 
281
    }
 
282
    delete[] _def;
 
283
  }
 
284
 
 
285
  // setup bitmap and pixmap
 
286
  Pixmap pm= XCreatePixmap (dis->dpy, dis->root, w, h, dis->depth);
 
287
  int byte_width= ((w-1)>>3)+1;
 
288
  char* data= new char [byte_width * h];
 
289
  for (i=0; i<(byte_width * h); i++) data[i]=0;
 
290
  for (y=0; y<h; y++) {
 
291
    if (N(t)< (y+c+1)) s= "";
 
292
    else s= as_string (t[y+c+1]);
 
293
    for (x=0; x<w; x++) {
 
294
      string name;
 
295
      int bit;
 
296
      if (N(s)<(b*(x+1))) name= first_name;
 
297
      else name= s (b*x, b*(x+1));
 
298
      int bmc= bmcs[name];
 
299
      int pmc= pmcs[name];
 
300
      if (!bmcs->contains (name)) bmc= bmcs[first_name];
 
301
      if (!pmcs->contains (name)) pmc= pmcs[first_name];
 
302
      XSetForeground (dis->dpy, dis->pixmap_gc, pmc);
 
303
      XDrawPoint (dis->dpy, (Drawable) pm, dis->pixmap_gc, x, y);
 
304
      bit= y*byte_width + (x>>3);
 
305
      if (bmc!=0) data[bit]= data[bit] | (1<<(x&7));      
 
306
    }
 
307
  }
 
308
  Pixmap bm= XCreateBitmapFromData (dis->dpy, dis->root, data, w, h);
 
309
  dis->xpm_pixmap (as_string (file_name))= (int) pm;
 
310
  dis->xpm_bitmap (as_string (file_name))= (int) bm;
 
311
  delete[] data;
 
312
}
 
313
 
 
314
extern bool char_clip;
 
315
 
 
316
void
 
317
x_drawable_rep::xpm (url file_name, SI x, SI y) {
 
318
  y -= pixel; // counter balance shift in draw_clipped
 
319
  if (!dis->xpm_pixmap->contains (as_string (file_name)))
 
320
    xpm_initialize (file_name);
 
321
  if (sfactor != 1)
 
322
    fatal_error ("Shrinking factor should be 1", "x_drawable_rep::xpm");
 
323
  int w, h;
 
324
  xpm_size (file_name, w, h);
 
325
  Pixmap bm= (Pixmap) dis->xpm_bitmap [as_string (file_name)];
 
326
  Pixmap pm= (Pixmap) dis->xpm_pixmap [as_string (file_name)];
 
327
  int old_clip= char_clip;
 
328
  char_clip= true;
 
329
  draw_clipped (pm, bm, w, h, x, y);
 
330
  char_clip=old_clip;
 
331
}
 
332
 
 
333
/******************************************************************************
 
334
* Invocation of ghostscript
 
335
******************************************************************************/
 
336
 
 
337
static int ps_figs_last_gc = 0;
 
338
static int ps_figs_tot_size= 0;
 
339
static int ps_figs_max_size= 10000;
 
340
static hashmap<tree,Pixmap> ps_figs (0);
 
341
static hashmap<tree,int> ps_figs_w (0);
 
342
static hashmap<tree,int> ps_figs_h (0);
 
343
static hashmap<tree,int> ps_figs_time (0);
 
344
static hashmap<tree,int> ps_figs_nr (0);
 
345
 
 
346
void
 
347
x_drawable_rep::postscript (
 
348
  url image,
 
349
  SI w, SI h, SI x, SI y,
 
350
  int x1, int y1, int x2, int y2)
 
351
{
 
352
  w= w/pixel; h= h/pixel;
 
353
  decode (x, y);
 
354
 
 
355
  if (dis->gswindow == NULL) {
 
356
    widget dummy= text_widget ("ghostscript window");
 
357
    if (ghostscript_bugged ()) {
 
358
      SI max_w= 2 * dis->display_width  * PIXEL;
 
359
      SI max_h= 2 * dis->display_height * PIXEL;
 
360
      dummy= glue_widget (false, false, max_w, max_h);
 
361
    }
 
362
    dis->gswindow= new x_window_rep (dummy, dis, "ghostscript", 0, 0);
 
363
  }
 
364
  if (ghostscript_bugged ()) {
 
365
    SI max_w= 2 * dis->display_width;
 
366
    SI max_h= 2 * dis->display_height;
 
367
    w= min (w, max_w);
 
368
    h= min (h, max_h);
 
369
  }
 
370
 
 
371
  Pixmap pm;
 
372
  tree lookup= tuple (image->t);
 
373
  lookup << as_string (w ) << as_string (h )
 
374
         << as_string (x1) << as_string (y1)
 
375
         << as_string (x2) << as_string (y2);
 
376
  if (ps_figs->contains (lookup)) pm= (Pixmap) ps_figs [lookup];
 
377
  else {
 
378
    if (DEBUG_AUTO) cout << "TeXmacs] Running ghostscript " << image << "\n";
 
379
    Window gs_win= dis->gswindow->win;
 
380
    pm= XCreatePixmap (dis->dpy, gs_win, w, h, dis->depth);
 
381
    ghostscript_run (dpy, gs_win, pm, image, w, h, x1, y1, x2, y2);
 
382
    if (N(ps_figs_nr) == 0) ps_figs_last_gc= texmacs_time ();
 
383
    ps_figs      (lookup)= (int) pm;
 
384
    ps_figs_w    (lookup)= w;
 
385
    ps_figs_h    (lookup)= h;
 
386
    ps_figs_time (lookup)= texmacs_time ();
 
387
    ps_figs_nr   (lookup)= ps_figs_nr [lookup] + 1;
 
388
    ps_figs_tot_size += w*h;
 
389
    if (ps_figs_tot_size > ps_figs_max_size) {
 
390
      dis->postscript_auto_gc ();
 
391
      if (ps_figs_tot_size > ps_figs_max_size)
 
392
        ps_figs_max_size= ps_figs_tot_size << 1;
 
393
    }
 
394
  }
 
395
 
 
396
  XCopyArea (dpy, (Drawable) pm, win, gc, 0, 0, w, h, x, y-h);
 
397
}
 
398
 
 
399
void
 
400
x_display_rep::postscript_auto_gc () {
 
401
  int time= texmacs_time ();
 
402
  if (time-ps_figs_last_gc <= 300000) return;
 
403
  ps_figs_last_gc= time;
 
404
  if (DEBUG_AUTO)
 
405
    cout << "TeXmacs] Launching garbage collection for unused pictures\n";
 
406
 
 
407
  iterator<tree> it= iterate (ps_figs);
 
408
  while (it->busy()) {
 
409
    tree lookup= it->next();
 
410
    int diff= time- ps_figs_time [lookup];
 
411
    int fact= ps_figs_nr [lookup];
 
412
    fact= fact * fact * fact;
 
413
    if (ps_figs_w [lookup] * ps_figs_h [lookup] < 400) fact= fact * 5;
 
414
    if (ps_figs_w [lookup] * ps_figs_h [lookup] < 6400) fact= fact * 5;
 
415
    if (diff/fact > 60000) {
 
416
      Pixmap pm= (Pixmap) ps_figs [lookup];
 
417
      XFreePixmap (dpy, pm);
 
418
      ps_figs->reset (lookup);
 
419
      ps_figs_w->reset (lookup);
 
420
      ps_figs_h->reset (lookup);
 
421
      ps_figs_time->reset (lookup);
 
422
      ps_bbox->reset (lookup[0]);
 
423
    }
 
424
  }
 
425
}
 
426
 
 
427
void
 
428
x_display_rep::postscript_gc (string name) {
 
429
  (void) name;
 
430
  ps_figs_last_gc= texmacs_time ();
 
431
  iterator<tree> it= iterate (ps_figs);
 
432
  while (it->busy()) {
 
433
    tree lookup= it->next();
 
434
    if (!is_ramdisc (as_url (lookup[0]))) {
 
435
      Pixmap pm= (Pixmap) ps_figs [lookup];
 
436
      XFreePixmap (dpy, pm);
 
437
      ps_figs->reset (lookup);
 
438
      ps_figs_w->reset (lookup);
 
439
      ps_figs_h->reset (lookup);
 
440
      ps_figs_time->reset (lookup);
 
441
      ps_figs_nr->reset (lookup);
 
442
      ps_bbox->reset (lookup[0]);
 
443
    }
 
444
  }
 
445
}
 
446
 
 
447
/******************************************************************************
 
448
* Miscellaneous routines
 
449
******************************************************************************/
 
450
 
 
451
void
 
452
x_drawable_rep::next_page () {
 
453
}
 
454
 
 
455
bool
 
456
x_drawable_rep::check_event (int type) {
 
457
  bool status;
 
458
  XEvent ev;
 
459
  switch (type) {
 
460
  case ANY_EVENT:
 
461
    if (event_status) return true;
 
462
    event_status= (XPending (dpy)>0);
 
463
    break;
 
464
  case INPUT_EVENT:
 
465
    if (event_status) return true;
 
466
    event_status= XCheckMaskEvent (dpy, KeyPressMask|ButtonPressMask, &ev);
 
467
    if (event_status) XPutBackEvent (dpy, &ev);
 
468
    break;
 
469
  case MOTION_EVENT:
 
470
    event_status= XCheckMaskEvent (dpy, PointerMotionMask, &ev);
 
471
    if (event_status) XPutBackEvent (dpy, &ev);
 
472
    break;
 
473
  case DRAG_EVENT:
 
474
    event_status= XCheckMaskEvent (dpy, ButtonMotionMask, &ev);
 
475
    if (event_status) XPutBackEvent (dpy, &ev);
 
476
    break;
 
477
  case MENU_EVENT:
 
478
    status= XCheckMaskEvent (dpy, ButtonMotionMask|ButtonReleaseMask, &ev);
 
479
    if (status) XPutBackEvent (dpy, &ev);
 
480
    return status;
 
481
  case EVENT_STATUS:
 
482
    break;
 
483
  }
 
484
  return event_status;
 
485
}
 
486
 
 
487
void
 
488
x_drawable_rep::apply_shadow (SI x1, SI y1, SI x2, SI y2) {
 
489
  if (this != dis->shadow) return;
 
490
  outer_round (x1, y1, x2, y2);
 
491
  decode (x1, y1);
 
492
  decode (x2, y2);
 
493
  dis->shadow_src->encode (x1, y1);
 
494
  dis->shadow_src->encode (x2, y2);
 
495
  dis->shadow_src->shadow_to_window (x1, y1, x2, y2);
 
496
}