Back to index

texmacs  1.0.7.15
cairo_renderer.cpp
Go to the documentation of this file.
00001 
00002 /******************************************************************************
00003 * MODULE     : cairo_renderer.cpp
00004 * DESCRIPTION: Cairo drawing interface class
00005 * COPYRIGHT  : (C) 2008 Massimiliano Gubinelli
00006 *******************************************************************************
00007 * This software falls under the GNU general public license version 3 or later.
00008 * It comes WITHOUT ANY WARRANTY WHATSOEVER. For details, see the file LICENSE
00009 * in the root directory or <http://www.gnu.org/licenses/gpl-3.0.html>.
00010 ******************************************************************************/
00011 
00012 #include "config.h"
00013 #include "cairo_renderer.hpp"
00014 
00015 #ifdef USE_CAIRO
00016 
00017 #include "analyze.hpp"
00018 #include "image_files.hpp"
00019 #include "file.hpp"
00020 #include "iterator.hpp"
00021 #include "gui.hpp" // for INTERRUPT_EVENT, INTERRUPTED_EVENT
00022 #include "font.hpp" // for the definition of font
00023 
00024 #include "Freetype/tt_file.hpp" // tt_font_find
00025 #include "Freetype/free_type.hpp"
00026 #include "tm_cairo.hpp"
00027 
00028 /******************************************************************************
00029 * Cairo images
00030 ******************************************************************************/
00031 
00032 struct cairo_image_rep: concrete_struct {
00033   cairo_surface_t* img;
00034   SI xo,yo;
00035   int w,h;
00036   cairo_image_rep (cairo_surface_t* img2, SI xo2, SI yo2, int w2, int h2) :
00037     img (img2), xo (xo2), yo (yo2), w (w2), h (h2) {
00038       tm_cairo_surface_reference(img); }
00039   ~cairo_image_rep() { tm_cairo_surface_destroy(img); }
00040 };
00041 
00042 class cairo_image {
00043   CONCRETE_NULL(cairo_image);
00044   cairo_image (cairo_surface_t* img2, SI xo2, SI yo2, int w2, int h2) :
00045     rep (tm_new<cairo_image_rep> (img2, xo2, yo2, w2, h2)) {};
00046 };
00047 
00048 CONCRETE_NULL_CODE(cairo_image);
00049 
00050 /******************************************************************************
00051 * Global support variables for all cairo_renderers
00052 ******************************************************************************/
00053 
00054 static hashmap<basic_character,cairo_image> character_image;  // bitmaps of all characters
00055 static hashmap<string,cairo_image> images;
00056 
00057 /******************************************************************************
00058 * cairo_renderer
00059 ******************************************************************************/
00060 
00061 class cairo_renderer_rep:  public basic_renderer_rep {
00062 public:
00063   cairo_t* context;
00064   
00065 public:
00066   cairo_renderer_rep (int w = 0, int h = 0);
00067   virtual ~cairo_renderer_rep ();
00068   
00069   void  draw (int char_code, font_glyphs fn, SI x, SI y);
00070   void  set_color (color c);
00071   void  set_line_style (SI w, int type=0, bool round=true);
00072   void  line (SI x1, SI y1, SI x2, SI y2);
00073   void  lines (array<SI> x, array<SI> y);
00074   void  clear (SI x1, SI y1, SI x2, SI y2);
00075   void  fill (SI x1, SI y1, SI x2, SI y2);
00076   void  arc (SI x1, SI y1, SI x2, SI y2, int alpha, int delta);
00077   void  fill_arc (SI x1, SI y1, SI x2, SI y2, int alpha, int delta);
00078   void  polygon (array<SI> x, array<SI> y, bool convex=true);
00079   void  xpm (url file_name, SI x, SI y);
00080   void  image (url u, SI w, SI h, SI x, SI y,
00081                double cx1, double cy1, double cx2, double cy2, int alpha);
00082   
00083   void next_page ();
00084   bool is_printer();
00085   bool interrupted (bool check);
00086   
00087   /***** private section *****************************************************/
00088   
00089   void draw_clipped (cairo_surface_t* im, int w, int h, SI x, SI y);
00090        
00091   bool native_draw (int ch, font_glyphs fn, SI x, SI y);
00092   
00093   void begin (void* c); // c must be a cairo context of type (cairo_t*)
00094   void end ();
00095     
00096 };
00097 
00098 
00099 cairo_renderer_rep::cairo_renderer_rep (int w2, int h2):
00100   basic_renderer_rep(w2,h2), context(NULL)
00101 {
00102   //cout << "Init cairo renderer" << LF;
00103 }
00104 
00105 cairo_renderer_rep::~cairo_renderer_rep () {
00106   if (context) end ();
00107 }
00108 
00109 void
00110 cairo_renderer_rep::begin (void* c) { 
00111   context = (cairo_t*)c; tm_cairo_reference(context);
00112   set_clipping (0, -h, w, 0);
00113 }
00114 
00115 void
00116 cairo_renderer_rep::end () {
00117   next_page();
00118   tm_cairo_destroy(context);
00119   context = NULL;
00120 }
00121 
00122 void
00123 cairo_renderer_rep::next_page () { 
00124   //cout << "NEXT PAGE" << LF; tm_cairo_show_page (context); 
00125   set_clipping (0, -h, w, 0);
00126   // tm_cairo_translate (context, 0, (h*72.0)/pixel);
00127   // tm_cairo_scale(context, 1.0, -1.0);
00128 }
00129 
00130 void
00131 tm_cairo_set_source_color(cairo_t *context, color c) {
00132   int r, g, b, a;
00133   get_rgb_color(c, r, g, b, a);
00134   tm_cairo_set_source_rgba(context, r/255.0, g/255.0, b/255.0, a/255.0);
00135 }
00136 
00137 void
00138 cairo_renderer_rep::set_color (color c) {
00139   //cout << "set_color" << LF;
00140   basic_renderer_rep::set_color(c);
00141   tm_cairo_set_source_color(context, cur_fg);
00142 }
00143 
00144 void
00145 cairo_renderer_rep::set_line_style (SI lw, int type, bool round) {
00146   (void) type;
00147   tm_cairo_set_line_cap (context,
00148                     round? CAIRO_LINE_CAP_ROUND : CAIRO_LINE_CAP_SQUARE);
00149   tm_cairo_set_line_join (context, CAIRO_LINE_JOIN_ROUND);
00150   tm_cairo_set_line_width (context,
00151                      lw <= pixel ? 1 : ((lw+thicken) / (1.0*pixel)));
00152 }
00153 
00154 void
00155 cairo_renderer_rep::line (SI x1, SI y1, SI x2, SI y2) {
00156   decode (x1, y1);
00157   decode (x2, y2);
00158   // y1--; y2--; // top-left origin to bottom-left origin conversion
00159   tm_cairo_set_antialias(context, CAIRO_ANTIALIAS_DEFAULT);
00160   tm_cairo_move_to(context, x1, y1);
00161   tm_cairo_line_to(context, x2, y2);
00162   tm_cairo_stroke(context);
00163 }
00164 
00165 void
00166 cairo_renderer_rep::lines (array<SI> x, array<SI> y) {
00167   int i, n= N(x);
00168   if ((N(y) != n) || (n<1)) return;
00169   tm_cairo_set_antialias(context, CAIRO_ANTIALIAS_DEFAULT);
00170   for (i=0; i<n; i++) {
00171     SI xx= x[i], yy= y[i];
00172     decode (xx, yy);
00173     tm_cairo_line_to (context, xx, yy);
00174   }
00175   tm_cairo_stroke (context);
00176 }
00177 
00178 void
00179 cairo_renderer_rep::clear (SI x1, SI y1, SI x2, SI y2) {
00180   x1= max (x1, cx1-ox); y1= max (y1, cy1-oy);
00181   x2= min (x2, cx2-ox); y2= min (y2, cy2-oy);
00182   // outer_round (x1, y1, x2, y2); might still be needed somewhere
00183   decode (x1, y1);
00184   decode (x2, y2);
00185   if ((x1>=x2) || (y1<=y2)) return;
00186   tm_cairo_set_antialias(context, CAIRO_ANTIALIAS_NONE);
00187   tm_cairo_set_source_color(context, cur_bg);
00188   tm_cairo_rectangle(context, x1, y2, x2-x1, y1-y2);
00189   tm_cairo_fill(context);
00190   tm_cairo_set_source_color(context, cur_fg);
00191 }
00192 
00193 void
00194 cairo_renderer_rep::fill (SI x1, SI y1, SI x2, SI y2) {
00195   if ((x2>x1) && ((x2-x1)<pixel)) {
00196     SI d= pixel-(x2-x1);
00197     x1 -= (d>>1);
00198     x2 += ((d+1)>>1);
00199   }
00200   if ((y2>y1) && ((y2-y1)<pixel)) {
00201     SI d= pixel-(y2-y1);
00202     y1 -= (d>>1);
00203     y2 += ((d+1)>>1);
00204   }
00205   
00206   x1= max (x1, cx1-ox); y1= max (y1, cy1-oy);
00207   x2= min (x2, cx2-ox); y2= min (y2, cy2-oy);
00208   // outer_round (x1, y1, x2, y2); might still be needed somewhere
00209   if ((x1>=x2) || (y1>=y2)) return;
00210   
00211   decode (x1, y1);
00212   decode (x2, y2);
00213 
00214   tm_cairo_set_antialias(context, CAIRO_ANTIALIAS_NONE);
00215   // tm_cairo_set_source_color(context, cur_fg);
00216   tm_cairo_rectangle(context, x1, y2, x2-x1, y1-y2);
00217  // cout << "fill " << x1 << "," << y2 << "," << x2-x1 << "," << y1-y2 << LF;
00218   tm_cairo_fill(context);
00219 }
00220 
00221 void
00222 cairo_renderer_rep::arc (SI x1, SI y1, SI x2, SI y2, int alpha, int delta) {
00223   (void) alpha; (void) delta;
00224   if ((x1>=x2) || (y1>=y2)) return;
00225   decode (x1, y1);
00226   decode (x2, y2);
00227   //FIXME: XDrawArc (dpy, win, gc, x1, y2, x2-x1, y1-y2, alpha, delta);
00228 }
00229 
00230 void
00231 cairo_renderer_rep::fill_arc (SI x1, SI y1, SI x2, SI y2, int alpha, int delta) {
00232   (void) alpha; (void) delta;
00233   if ((x1>=x2) || (y1>=y2)) return;
00234   decode (x1, y1);
00235   decode (x2, y2);
00236   //FIXME: XFillArc (dpy, win, gc, x1, y2, x2-x1, y1-y2, alpha, delta);
00237 }
00238 
00239 void
00240 cairo_renderer_rep::polygon (array<SI> x, array<SI> y, bool convex) {  
00241   int i, n= N(x);
00242   if ((N(y) != n) || (n<1)) return;
00243 
00244   tm_cairo_new_path(context);
00245   for (i=0; i<n; i++) {
00246     SI xx= x[i], yy= y[i];
00247     decode (xx, yy);
00248     tm_cairo_line_to(context,xx,yy);
00249   }
00250   tm_cairo_close_path(context);
00251   tm_cairo_set_antialias(context, CAIRO_ANTIALIAS_DEFAULT);
00252   // tm_cairo_set_source_color(context, cur_fg);
00253   tm_cairo_set_fill_rule(context, convex ? CAIRO_FILL_RULE_EVEN_ODD : CAIRO_FILL_RULE_WINDING);
00254   tm_cairo_fill(context);
00255 }
00256 
00257 /******************************************************************************
00258 * Image rendering
00259 ******************************************************************************/
00260 
00261 struct cairo_cache_image_rep: cache_image_element_rep {
00262   cairo_cache_image_rep (int w2, int h2, time_t time2, cairo_surface_t *ptr2) :
00263     cache_image_element_rep(w2,h2,time2,ptr2) {
00264       tm_cairo_surface_reference ((cairo_surface_t *) ptr); }
00265   virtual ~cairo_cache_image_rep() {
00266     tm_cairo_surface_destroy ((cairo_surface_t *) ptr); }
00267 };
00268 
00269 void
00270 cairo_renderer_rep::image (url u, SI w, SI h, SI x, SI y,
00271                         double cx1, double cy1, double cx2, double cy2,
00272                            int alpha)
00273 {
00274   // Given an image of original size (W, H),
00275   // we display the part (cx1 * W, xy1 * H, cx2 * W, cy2 * H)
00276   // at position (x, y) in a rectangle of size (w, h)
00277 
00278   // if (DEBUG_EVENTS) cout << "cairo_renderer_rep::image " << as_string(u) << LF;
00279   (void) alpha; // FIXME
00280 
00281   w= w/pixel; h= h/pixel;
00282   decode (x, y);
00283   
00284   //painter.setRenderHints (0);
00285   //painter.drawRect (QRect (x, y-h, w, h));
00286   
00287   cairo_surface_t* pm = NULL;
00288   tree lookup= tuple (u->t);
00289   lookup << as_string (w ) << as_string (h )
00290         << as_string (cx1) << as_string (cy1)
00291         << as_string (cx2) << as_string (cy2) << "cairo-image" ;
00292   
00293   cache_image_element ci = get_image_cache(lookup);
00294   if (!is_nil(ci)) {
00295     pm = static_cast<cairo_surface_t*> (ci->ptr);
00296   }
00297   else {
00298     if (suffix (u) == "png") {
00299       // rendering
00300       string suu = as_string (u);
00301       char * buf = as_charp(suu);
00302       //cout << suu << LF;
00303       pm = tm_cairo_image_surface_create_from_png(buf);
00304       tm_delete (buf);
00305     }
00306     else if (suffix (u) == "ps" ||
00307             suffix (u) == "eps" ||
00308             suffix (u) == "pdf") {
00309       url temp= url_temp (".png");
00310       system ("convert", u, temp);
00311       string suu = as_string (temp);
00312       char * buf = as_charp(suu); 
00313       //cout << suu << LF;
00314       pm = tm_cairo_image_surface_create_from_png(buf);
00315       tm_delete (buf);
00316       remove (temp);
00317     }
00318 
00319     if (pm == NULL ) {
00320       cout << "TeXmacs] warning: cannot render " << as_string (u) << "\n";
00321       return;
00322     }
00323     // caching
00324     ci = tm_new<cairo_cache_image_rep> (w,h, texmacs_time(), pm);
00325     set_image_cache(lookup, ci);
00326     (ci->nr)++;
00327   }
00328   
00329   int iw= tm_cairo_image_surface_get_width(pm);
00330   int ih= tm_cairo_image_surface_get_height(pm);
00331 
00332   tm_cairo_set_antialias(context, CAIRO_ANTIALIAS_NONE);
00333   tm_cairo_save(context);
00334   tm_cairo_translate(context,x,y-h);
00335   tm_cairo_scale(context, (1.0*w)/iw, (1.0*h)/ih);
00336   tm_cairo_set_source_surface (context, pm, 0, 0);
00337   tm_cairo_paint (context);
00338   tm_cairo_restore(context);
00339 };
00340 
00341 void
00342 cairo_renderer_rep::draw_clipped (cairo_surface_t* im, int w, int h, SI x, SI y) {
00343   decode (x , y );
00344   y--; // top-left origin to bottom-left origin conversion
00345        // clear(x1,y1,x2,y2);
00346   tm_cairo_set_antialias(context, CAIRO_ANTIALIAS_DEFAULT);
00347   tm_cairo_set_operator(context, CAIRO_OPERATOR_SOURCE);
00348 
00349   // tm_cairo_mask_surface(context, im, x, y);
00350   tm_cairo_set_source_surface (context, im, x, y);
00351   
00352   tm_cairo_paint (context);
00353 }  
00354 
00355 static hashmap<string,pointer> native_fonts;
00356 static hashset<string> native_loaded;
00357 
00358 static const cairo_user_data_key_t font_face_key = { 0 };
00359 
00360 static cairo_font_face_t *
00361 create_font_face_from_file (FT_Library library, const char *file) {
00362   cairo_font_face_t *font_face;
00363   FT_Error error;
00364   FT_Face face;
00365   cairo_status_t status;
00366 
00367   error = FT_New_Face (library, file, 0, &face);
00368   if (error) return NULL;
00369   font_face = tm_cairo_ft_font_face_create_for_ft_face (face, 0);
00370   status = tm_cairo_font_face_set_user_data (font_face, &font_face_key,
00371                                           face, (cairo_destroy_func_t) FT_Done_Face);
00372   if (status) {
00373     tm_cairo_font_face_destroy (font_face);
00374     FT_Done_Face (face);
00375     return NULL;
00376   }
00377   return font_face;
00378 }
00379 
00380 // WARNING:
00381 // freetype fonts are not supported on quartz surface so for the moment native redering is 
00382 // disabled.
00383 
00384 bool 
00385 cairo_renderer_rep::native_draw (int ch, font_glyphs fn, SI x, SI y) {
00386   string name= fn->res_name;
00387   unsigned char c= ch;
00388   if (ch >= 256) {
00389     name= name * "-" * as_string (ch / 256);
00390     c= (unsigned char) (ch & 255);
00391   }
00392   
00393   // cout << name << LF;
00394   int size;
00395        
00396   {
00397     // find size (weird)
00398     int    pos1  = search_forwards (".", name);
00399     int pos2= search_backwards (":", name);
00400     string sz = name(pos2+1,pos1);
00401     size = as_int(sz);
00402   }
00403   cairo_font_face_t* f = (cairo_font_face_t*)native_fonts(name);
00404        
00405   if ((f == NULL)&&(! native_loaded->contains(name))) {
00406     native_loaded->insert(name);
00407     string ttf;
00408     int    pos  = search_forwards (".", name);
00409     string root = (pos==-1? name: name (0, pos));
00410     if ((pos!=-1) && ends (name, "tt")) {
00411       int pos2= search_backwards (":", name);
00412       root= name (0, pos2);
00413       url u= tt_font_find (root);
00414       if (suffix (u) == "pfb") {
00415        //     cout << u << LF;
00416        char* _name= as_charp (concretize (u));
00417        f = create_font_face_from_file(ft_library,  _name);
00418        tm_delete_array (_name);
00419        if (tm_cairo_font_face_status(f) == CAIRO_STATUS_SUCCESS) {
00420          // cout << "Font" << u << " loaded " << LF;
00421          native_fonts(name) = f;
00422        }        
00423        else {
00424          f = NULL;
00425          //          cout << "Problems with font" << u << LF;
00426        }
00427       }
00428     }
00429   } // end caching
00430        
00431   if (f) {
00432     decode (x , y );
00433     y--; // top-left origin to bottom-left origin conversion
00434     tm_cairo_set_font_face(context, f);
00435     //cout << "status " << tm_cairo_status_to_string(tm_cairo_status(context)) << LF;
00436     tm_cairo_set_font_size(context, size*(PIXEL*600.0/(pixel*72.0)));
00437     //               CGAffineTransform    kHorizontalMatrix = { PIXEL*600.0/(pixel*72.0),  0.0,  0.0,  -PIXEL*600.0/(pixel*72.0),  0.0,  0.0 };
00438     tm_cairo_set_antialias(context, CAIRO_ANTIALIAS_DEFAULT);
00439     // tm_cairo_set_source_color(context, cur_fg);
00440     cairo_glyph_t gl = { c, x, y };
00441     tm_cairo_show_glyphs(context, &gl, 1 );
00442   }
00443 
00444   return true;
00445 }
00446 
00447 void
00448 cairo_renderer_rep::draw (int c, font_glyphs fng, SI x, SI y) {
00449   //cout << "draw" << LF;
00450   // get the pixmap
00451   basic_character xc (c, fng, sfactor, 0, 0);
00452   cairo_image mi = character_image [xc];
00453   if (is_nil(mi)) {
00454     int r, g, b, a;
00455     get_rgb (cur_fg, r, g, b, a);
00456     SI xo, yo;
00457     glyph pre_gl= fng->get (c); if (is_nil (pre_gl)) return;
00458     glyph gl= shrink (pre_gl, sfactor, sfactor, xo, yo);
00459     int i, j, w= gl->width, h= gl->height;
00460     cairo_surface_t *im = tm_cairo_image_surface_create(CAIRO_FORMAT_A8,w,h);
00461     //FIXME: release the surface when done
00462     {
00463       cairo_t* ic = tm_cairo_create(im);
00464       int nr_cols= sfactor*sfactor;
00465       if (nr_cols >= 64) nr_cols= 64;
00466       tm_cairo_set_operator(ic, CAIRO_OPERATOR_SOURCE);
00467       for (j=0; j<h; j++)
00468        for (i=0; i<w; i++) {
00469          int col = gl->get_x (i, j);
00470          tm_cairo_set_source_rgba(ic, 0.0, 0.0, 0.0, ((255*col)/(nr_cols+1))/255.0);
00471          tm_cairo_rectangle(ic,i,j,1,1);
00472           tm_cairo_fill(ic);
00473        }
00474       tm_cairo_destroy (ic);
00475     }
00476     cairo_image mi2 (im, xo, yo, w, h);
00477     mi = mi2;
00478     tm_cairo_surface_destroy (im); // cairo_image retains im
00479     character_image (xc)= mi;
00480   }
00481   
00482   // draw the character
00483   {
00484     int x1 = x- mi->xo*sfactor;
00485     int y1 =  y+ mi->yo*sfactor;
00486     decode (x1, y1);
00487     y1--; // top-left origin to bottom-left origin conversion
00488     tm_cairo_set_antialias(context, CAIRO_ANTIALIAS_DEFAULT);
00489     tm_cairo_set_operator(context, CAIRO_OPERATOR_SOURCE);
00490     // tm_cairo_set_source_color (context, cur_fg);
00491     tm_cairo_mask_surface(context, mi->img, x1, y1);
00492   }  
00493 }
00494 
00495 /******************************************************************************
00496 * Setting up and displaying xpm pixmaps
00497 ******************************************************************************/
00498 
00499 static cairo_surface_t*
00500 xpm_init (url file_name) {
00501   tree t= xpm_load (file_name);
00502   
00503   // get main info
00504   int ok, i=0, j, k, w, h, c, b, x, y;
00505   string s= as_string (t[0]);
00506   skip_spaces (s, i);
00507   ok= read_int (s, i, w);
00508   skip_spaces (s, i);
00509   ok= read_int (s, i, h) && ok;
00510   skip_spaces (s, i);
00511   ok= read_int (s, i, c) && ok;
00512   skip_spaces (s, i);
00513   ok= read_int (s, i, b) && ok;
00514   if ((!ok) || (N(t)<(c+1)) || (c<=0)) {
00515     cerr << "File name= " << file_name << "\n";
00516     FAILED ("invalid xpm");
00517   }
00518   
00519   // setup colors
00520   string first_name;
00521   hashmap<string,color> pmcs;
00522   for (k=0; k<c; k++) {
00523     string s   = as_string (t[k+1]);
00524     string name= "";
00525     string def = "none";
00526     if (N(s)<b) i=N(s);
00527     else { name= s(0,b); i=b; }
00528     if (k==0) first_name= name;
00529     
00530     skip_spaces (s, i);
00531     if ((i<N(s)) && (s[i]=='s')) {
00532       i++;
00533       skip_spaces (s, i);
00534       while ((i<N(s)) && (s[i]!=' ') && (s[i]!='\t')) i++;
00535       skip_spaces (s, i);
00536     }
00537     if ((i<N(s)) && (s[i]=='c')) {
00538       i++;
00539       skip_spaces (s, i);
00540       j=i;
00541       while ((i<N(s)) && (s[i]!=' ') && (s[i]!='\t')) i++;
00542       def= locase_all (s (j, i));
00543     }  
00544     pmcs(name)= xpm_to_color(def);
00545   }
00546   cairo_surface_t *im = tm_cairo_image_surface_create (CAIRO_FORMAT_ARGB32,w,h);
00547   cairo_t* ic = tm_cairo_create (im);
00548   tm_cairo_set_operator (ic, CAIRO_OPERATOR_SOURCE);
00549   // setup pixmap
00550   for (y=0; y<h; y++) {
00551     if (N(t)< (y+c+1)) s= "";
00552     else s= as_string (t[y+c+1]);
00553     for (x=0; x<w; x++) {
00554       string name;
00555       if (N(s)<(b*(x+1))) name= first_name;
00556       else name= s (b*x, b*(x+1));
00557       color col = pmcs[(pmcs->contains (name) ? name : first_name)];
00558       tm_cairo_set_source_color (ic, col);
00559       tm_cairo_rectangle (ic,x,y,1,1);
00560       tm_cairo_fill (ic);
00561     }
00562   }
00563   tm_cairo_destroy (ic);
00564   return im;
00565 }
00566 
00567 extern int char_clip;
00568 
00569 static cairo_surface_t* 
00570 xpm_image (url file_name) { 
00571   cairo_surface_t *pxm= NULL;
00572   cairo_image mi= images [as_string (file_name)];
00573   if (is_nil (mi)) {    
00574     pxm = xpm_init(file_name);
00575     cairo_image mi2 (pxm, 0, 0, tm_cairo_image_surface_get_width(pxm),
00576                    tm_cairo_image_surface_get_height(pxm));
00577     mi= mi2;
00578     images (as_string (file_name))= mi2;
00579     tm_cairo_surface_destroy (pxm);
00580   }  
00581   else pxm= mi->img;
00582   return pxm;
00583 }
00584 
00585 void
00586 cairo_renderer_rep::xpm (url file_name, SI x, SI y) {
00587   y -= pixel; // counter balance shift in draw_clipped
00588   cairo_surface_t *image = xpm_image (file_name);
00589   ASSERT (sfactor == 1, "shrinking factor should be 1");
00590   int w, h;
00591   w = tm_cairo_image_surface_get_width(image);
00592   h = tm_cairo_image_surface_get_height(image);
00593   int old_clip= char_clip;
00594   char_clip= true;
00595   draw_clipped (image, w, h, x, y);
00596   char_clip=old_clip;
00597 }
00598 
00599 bool
00600 cairo_renderer_rep::is_printer () {
00601   return true;
00602 }
00603 
00604 bool
00605 cairo_renderer_rep::interrupted (bool check) {
00606   return false;
00607 }
00608 
00609 /******************************************************************************
00610 * main cairo renderer
00611 ******************************************************************************/
00612 
00613 static cairo_renderer_rep* the_renderer= NULL;
00614 
00615 basic_renderer_rep*
00616 the_cairo_renderer () {
00617   if (tm_cairo_present()) {
00618     if (!the_renderer) the_renderer= tm_new<cairo_renderer_rep> ();
00619     return the_renderer;
00620   } else {
00621     return NULL;
00622   }
00623 }
00624 
00625 #if 0
00626 renderer
00627 printer (url ps_file_name, int dpi, int nr_pages,
00628          string page_type, bool landscape, double paper_w, double paper_h)
00629 {
00630   cout << "PS output to file : " << as_string(ps_file_name) << LF;
00631   int h = (dpi*PIXEL*paper_h)/2.54;
00632   int w = (dpi*PIXEL*paper_w)/2.54;
00633   cairo_renderer_rep *ren = tm_new<cairo_renderer_rep> (w,h);
00634   char *buf = as_charp(as_string(ps_file_name));
00635   cairo_surface_t* surface =
00636     tm_cairo_ps_surface_create(buf, paper_w/2.54*72.0, paper_h/2.54*72.0);
00637   tm_delete_array (buf);
00638   cairo_t *context = tm_cairo_create (surface);
00639   // tm_cairo_translate (context, 0,  paper_h/2.54*72.0);
00640   // tm_cairo_scale(context, 1.0, -1.0);
00641 
00642   ren->begin (context);
00643   tm_cairo_destroy (context);
00644   tm_cairo_surface_destroy (surface);
00645   renderer r = ren;
00646   r->set_color(black);
00647   r->fill(0,-10000,10000,0);
00648   r->next_page();
00649   return r;
00650 }
00651 #endif
00652 
00653 #else // USE_CAIRO
00654 basic_renderer_rep*
00655 the_cairo_renderer () {
00656     return NULL;
00657 }
00658 #endif // USE_CAIRO