4
4
* DESCRIPTION: QT drawing interface class
5
5
* COPYRIGHT : (C) 2008 Massimiliano Gubinelli
6
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.
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>.
11
10
******************************************************************************/
13
12
#include "qt_renderer.hpp"
14
13
#include "analyze.hpp"
15
14
#include "image_files.hpp"
17
15
#include "qt_utilities.hpp"
18
16
#include "file.hpp"
19
#include "iterator.hpp"
20
#include "MacOS/mac_images.h"
21
23
/******************************************************************************
23
25
******************************************************************************/
25
qt_image::qt_image (QTMImage* img2, SI xo2, SI yo2, int w2, int h2):
26
rep (new qt_image_rep (img2, xo2, yo2, w2, h2)) {}
27
//qt_image::qt_image () : rep(NULL) {}
29
qt_image_rep::qt_image_rep (QTMImage* img2, SI xo2, SI yo2, int w2, int h2):
30
img (img2), xo (xo2), yo (yo2), w (w2), h (h2) {}
32
qt_image_rep::~qt_image_rep () { delete img; }
34
/*****************************************************************************/
36
qt_renderer_rep::qt_renderer_rep (qt_gui dis2, int w2, int h2):
37
dis (dis2), w (w2), h (h2)
49
magenta = dis->magenta;
53
light_grey = dis->light_grey;
55
dark_grey = dis->dark_grey;
27
struct qt_image_rep: concrete_struct {
31
qt_image_rep (QTMImage* img2, SI xo2, SI yo2, int w2, int h2):
32
img (img2), xo (xo2), yo (yo2), w (w2), h (h2) {};
33
~qt_image_rep() { delete img; };
34
friend class qt_image;
38
CONCRETE_NULL(qt_image);
39
qt_image (QTMImage* img2, SI xo2, SI yo2, int w2, int h2):
40
rep (tm_new<qt_image_rep> (img2, xo2, yo2, w2, h2)) {};
44
CONCRETE_NULL_CODE(qt_image);
46
/******************************************************************************
48
******************************************************************************/
50
struct qt_pixmap_rep: concrete_struct {
54
qt_pixmap_rep (QPixmap* img2, SI xo2, SI yo2, int w2, int h2):
55
img (img2), xo (xo2), yo (yo2), w (w2), h (h2) {};
56
~qt_pixmap_rep() { delete img; };
57
friend class qt_pixmap;
61
CONCRETE_NULL(qt_pixmap);
62
qt_pixmap (QPixmap* img2, SI xo2, SI yo2, int w2, int h2):
63
rep (tm_new<qt_pixmap_rep> (img2, xo2, yo2, w2, h2)) {};
67
CONCRETE_NULL_CODE(qt_pixmap);
69
/******************************************************************************
70
* Global support variables for all qt_renderers
71
******************************************************************************/
73
static hashmap<basic_character,qt_image> character_image; // bitmaps of all characters
74
static hashmap<string,qt_pixmap> images;
76
/******************************************************************************
78
******************************************************************************/
80
qt_renderer_rep::qt_renderer_rep (int w2, int h2):
81
basic_renderer_rep(w2, h2) {}
59
83
qt_renderer_rep::~qt_renderer_rep () {}
61
/******************************************************************************
62
* Conversion between window and postscript coordinates
63
******************************************************************************/
66
qt_renderer_rep::encode (SI& x, SI& y) {
72
qt_renderer_rep::decode (SI& x, SI& y) {
74
if (x>=0) x= x/pixel; else x= (x-pixel+1)/pixel;
75
if (y>=0) y= -(y/pixel); else y= -((y-pixel+1)/pixel);
78
/*****************************************************************************/
81
qt_renderer_rep::get_extents (int& w2, int& h2) {
86
qt_renderer_rep::interrupted (bool check) {
87
return dis->check_event (check? INTERRUPT_EVENT: INTERRUPTED_EVENT);
90
/* routines from renderer.hpp **********************************************/
86
qt_renderer_rep::begin (void* handle) {
87
QPaintDevice *device = (QPaintDevice*)handle;
88
painter.begin (device);
91
void qt_renderer_rep::end () { painter.end (); }
97
get_rgb_color (c,r,g,b);
98
return QColor(r, g, b);
92
101
/******************************************************************************
93
102
* Drawing into drawables
94
103
******************************************************************************/
97
qt_renderer_rep::rgb (int r, int g, int b) {
98
return rgb_color (r, g, b);
102
qt_renderer_rep::get_rgb (color col, int& r, int& g, int& b) {
103
get_rgb_color (col, r, g, b);
107
qt_renderer_rep::get_color () {
113
qt_renderer_rep::get_color (string s) {
114
return named_color (s);
119
qt_renderer_rep::get_background () {
124
106
qt_renderer_rep::set_color (color c) {
107
basic_renderer_rep::set_color(c);
125
108
QPen p (painter.pen ());
126
109
QBrush b (painter.brush ());
127
p.setColor (dis->cmap[c]);
128
b.setColor (dis->cmap[c]);
110
p.setColor (qt_color(cur_fg));
111
b.setColor (qt_color(cur_fg));
129
112
painter.setPen (p);
130
113
painter.setBrush (b);
135
qt_renderer_rep::set_background (color c) {
136
// XSetBackground (dpy, gc, dis->cmap[c]);
257
233
* Image rendering
258
234
******************************************************************************/
260
static int cache_image_last_gc = 0;
261
static int cache_image_tot_size= 0;
262
static int cache_image_max_size= 10000;
263
static hashmap<tree,QImage*> cache_image (0);
264
static hashmap<tree,int> cache_image_w (0);
265
static hashmap<tree,int> cache_image_h (0);
266
static hashmap<tree,int> cache_image_time (0);
267
static hashmap<tree,int> cache_image_nr (0);
269
// to inform texmacs about image sizes we need to fill this structure
270
// see System/Files/image_files.cpp
272
extern hashmap<tree,string> ps_bbox;
274
void image_auto_gc () {
275
int time= texmacs_time ();
276
if (time-cache_image_last_gc <= 300000) return;
277
cache_image_last_gc= time;
279
cout << "TeXmacs] Launching garbage collection for unused pictures\n";
281
iterator<tree> it= iterate (cache_image);
283
tree lookup= it->next();
284
int diff= time- cache_image_time [lookup];
285
int fact= cache_image_nr [lookup];
286
fact= fact * fact * fact;
287
if (cache_image_w [lookup] * cache_image_h [lookup] < 400) fact= fact * 5;
288
if (cache_image_w [lookup] * cache_image_h [lookup] < 6400) fact= fact * 5;
289
if (diff/fact > 60000) {
290
QImage *pm= (QImage*) cache_image [lookup];
292
cache_image->reset (lookup);
293
cache_image_w->reset (lookup);
294
cache_image_h->reset (lookup);
295
cache_image_time->reset (lookup);
296
ps_bbox->reset (lookup[0]);
301
void image_gc (string name) {
303
cache_image_last_gc= texmacs_time ();
304
iterator<tree> it= iterate (cache_image);
306
tree lookup= it->next();
307
if (!is_ramdisc (as_url (lookup[0]))) {
308
QImage *pm= (QImage*) cache_image [lookup];
310
cache_image->reset (lookup);
311
cache_image_w->reset (lookup);
312
cache_image_h->reset (lookup);
313
cache_image_time->reset (lookup);
314
cache_image_nr->reset (lookup);
315
ps_bbox->reset (lookup[0]);
236
struct qt_cache_image_rep: cache_image_element_rep {
237
qt_cache_image_rep (int w2, int h2, int time2, QImage *ptr2):
238
cache_image_element_rep (w2, h2, time2, ptr2) {}
239
virtual ~qt_cache_image_rep () {
240
delete static_cast<QImage*> (ptr); }
321
244
qt_renderer_rep::image (url u, SI w, SI h, SI x, SI y,
322
double cx1, double cy1, double cx2, double cy2)
245
double cx1, double cy1, double cx2, double cy2)
324
247
// Given an image of original size (W, H),
325
248
// we display the part (cx1 * W, xy1 * H, cx2 * W, cy2 * H)
326
249
// at position (x, y) in a rectangle of size (w, h)
328
251
// if (DEBUG_EVENTS) cout << "qt_renderer_rep::image " << as_string(u) << LF;
330
253
w= w/pixel; h= h/pixel;
336
259
QImage *pm = NULL;
337
260
tree lookup= tuple (u->t);
338
261
lookup << as_string (w ) << as_string (h )
339
<< as_string (cx1) << as_string (cy1)
340
<< as_string (cx2) << as_string (cy2);
341
if (cache_image->contains (lookup)) pm= (QImage*) cache_image [lookup];
262
<< as_string (cx1) << as_string (cy1)
263
<< as_string (cx2) << as_string (cy2) << "qt-image" ;
264
cache_image_element ci = get_image_cache(lookup);
266
pm= static_cast<QImage*> (ci->ptr);
344
269
if (qt_supports_image (u))
345
270
pm= new QImage (to_qstring (as_string (u)));
346
271
else if (suffix (u) == "ps" ||
347
suffix (u) == "eps" ||
348
suffix (u) == "pdf") {
272
suffix (u) == "eps" ||
273
suffix (u) == "pdf") {
349
274
url temp= url_temp (".png");
276
mac_image_to_png (u, temp);
350
278
system ("convert", u, temp);
351
280
pm= new QImage (to_qstring (as_string (temp)));
354
if (pm == NULL || pm->isNull()) {
283
if (pm == NULL || pm->isNull ()) {
355
284
cout << "TeXmacs] warning: cannot render " << as_string (u) << "\n";
356
285
if (pm != NULL) delete pm;
360
if (N(cache_image_nr) == 0) cache_image_last_gc= texmacs_time ();
361
cache_image (lookup)= pm;
362
cache_image_w (lookup)= w;
363
cache_image_h (lookup)= h;
364
cache_image_time (lookup)= texmacs_time ();
365
cache_image_nr (lookup)= cache_image_nr [lookup] + 1;
366
cache_image_tot_size += w*h;
367
if (cache_image_tot_size > cache_image_max_size) {
369
if (cache_image_tot_size > cache_image_max_size)
370
cache_image_max_size= cache_image_tot_size << 1;
288
ci = tm_new<qt_cache_image_rep> (w,h, texmacs_time(), pm);
289
set_image_cache(lookup, ci);
374
293
int iw= pm->width ();
399
315
y--; // top-left origin to bottom-left origin conversion
400
316
// clear(x1,y1,x2,y2);
317
painter.setRenderHints (0);
318
painter.drawImage (x, y, *im);
319
// [im drawAtPoint:NSMakePoint(x,y) fromRect:NSMakeRect(0,0,w,h) operation:NSCompositeSourceAtop fraction:1.0];
323
qt_renderer_rep::draw_clipped (QPixmap *im, int w, int h, SI x, SI y) {
325
y--; // top-left origin to bottom-left origin conversion
326
// clear(x1,y1,x2,y2);
402
327
painter.setRenderHints (0);
403
328
painter.drawPixmap (x, y, w, h, *im);
405
painter.setRenderHints (0);
406
painter.drawImage (x, y, *im);
408
329
// [im drawAtPoint:NSMakePoint(x,y) fromRect:NSMakeRect(0,0,w,h) operation:NSCompositeSourceAtop fraction:1.0];
412
335
qt_renderer_rep::draw (int c, font_glyphs fng, SI x, SI y) {
413
336
// get the pixmap
414
x_character xc (c, fng, sfactor, cur_fg, 0);
415
qt_image mi = dis->character_image [xc];
337
basic_character xc (c, fng, sfactor, cur_fg, 0);
338
qt_image mi = character_image [xc];
416
339
if (is_nil(mi)) {
418
341
get_rgb (cur_fg, r, g, b);
468
391
draw_clipped (mi->img, mi->w, mi->h, x- mi->xo*sfactor, y+ mi->yo*sfactor);
473
394
/******************************************************************************
474
395
* Setting up and displaying xpm pixmaps
475
396
******************************************************************************/
478
xpm_to_ns_color (string s) {
479
if (s == "none") return QColor(100,100,100);
480
if ((N(s) == 4) && (s[0]=='#')) {
481
int r= 17 * from_hexadecimal (s (1, 2));
482
int g= 17 * from_hexadecimal (s (2, 3));
483
int b= 17 * from_hexadecimal (s (3, 4));
484
return QColor(r,g,b);
486
if ((N(s) == 7) && (s[0]=='#')) {
487
int r= from_hexadecimal (s (1, 3));
488
int g= from_hexadecimal (s (3, 5));
489
int b= from_hexadecimal (s (5, 7));
490
return QColor(r,g,b);
492
if ((N(s) == 13) && (s[0]=='#')) {
493
int r= from_hexadecimal (s (1, 5));
494
int g= from_hexadecimal (s (5, 9));
495
int b= from_hexadecimal (s (9, 13));
496
return QColor(r,g,b);
498
char *name = as_charp(s);
499
for(int i = 0; i<RGBColorsSize; i++) {
500
if (strcmp(name,RGBColors[i].name)==0) {
502
return QColor(RGBColors[i].r,RGBColors[i].g,RGBColors[i].b);
506
return QColor (0, 0, 0);
509
398
extern int char_clip;
512
401
qt_renderer_rep::xpm_image (url file_name) {
514
qt_image mi= dis->images [as_string (file_name)];
403
qt_pixmap mi= images [as_string (file_name)];
515
404
if (is_nil (mi)) {
517
406
load_string ("$TEXMACS_PIXMAP_PATH" * file_name, sss, false);
519
408
load_string ("$TEXMACS_PATH/misc/pixmaps/TeXmacs.xpm", sss, true);
520
409
uchar *buf= (uchar*) as_charp (sss);
522
411
pxm->loadFromData (buf, N(sss));
412
tm_delete_array ((char*) buf);
525
414
//cout << "pxm: " << file_name << "(" << pxm->size().width() << "," << pxm->size().height() << ")\n";
526
qt_image mi2 (pxm, 0, 0, pxm->width(), pxm->height());
415
qt_pixmap mi2 (pxm, 0, 0, pxm->width(), pxm->height());
528
dis->images (as_string (file_name))= mi2;
417
images (as_string (file_name))= mi2;
535
424
qt_renderer_rep::xpm (url file_name, SI x, SI y) {
536
425
y -= pixel; // counter balance shift in draw_clipped
537
QTMImage* image = xpm_image (file_name);
539
fatal_error ("Shrinking factor should be 1", "qt_renderer_rep::xpm");
426
QPixmap* image = xpm_image (file_name);
427
ASSERT (sfactor == 1, "shrinking factor should be 1");
541
429
w = image->width ();
542
430
h = image->height ();
546
434
char_clip=old_clip;
550
//void qt_renderer_rep::get_clipping (SI &x1, SI &y1, SI &x2, SI &y2) {} ;
551
//void qt_renderer_rep::set_clipping (SI x1, SI y1, SI x2, SI y2, bool restore) {} ;
554
qt_renderer_rep::set_clipping (SI x1, SI y1, SI x2, SI y2, bool restore) {
556
outer_round (x1, y1, x2, y2);
557
renderer_rep::set_clipping (x1, y1, x2, y2);
560
// NSBezierPath clipRect:NSMakeRect(x1,y2,x2-x1,y1-y2)];
561
// [NSBezierPath clipRect:NSMakeRect(x1,y2,x2-x1,y1-y2)];
564
/* shadowing and copying rectangular regions across devices */
566
void qt_renderer_rep::fetch (SI x1, SI y1, SI x2, SI y2, renderer dev, SI x, SI y) {
567
(void) x1; (void) y1; (void) x2; (void) y2; (void) dev; (void) x; (void) y; }
568
void qt_renderer_rep::new_shadow (renderer& dev) { dev = this; }
569
void qt_renderer_rep::delete_shadow (renderer& dev) { dev= NULL; }
570
void qt_renderer_rep::get_shadow (renderer dev, SI x1, SI y1, SI x2, SI y2) {
571
(void) x1; (void) y1; (void) x2; (void) y2; (void) dev; }
572
void qt_renderer_rep::put_shadow (renderer dev, SI x1, SI y1, SI x2, SI y2) {
573
(void) x1; (void) y1; (void) x2; (void) y2; (void) dev; }
574
void qt_renderer_rep::apply_shadow (SI x1, SI y1, SI x2, SI y2) {
575
(void) x1; (void) y1; (void) x2; (void) y2; }
578
font x_font (string family, int size, int dpi)
580
(void) family; (void) size; (void) dpi;
581
if (DEBUG_EVENTS) cout << "x_font(): SHOULD NOT BE CALLED\n";
437
/******************************************************************************
439
******************************************************************************/
444
static qt_renderer_rep* the_renderer= NULL;
445
if (!the_renderer) the_renderer= tm_new<qt_renderer_rep> ();