Back to index

texmacs  1.0.7.15
cg_renderer.cpp
Go to the documentation of this file.
00001 
00002 /******************************************************************************
00003 * MODULE     : cg_renderer.cpp
00004 * DESCRIPTION: CoreGraphics drawing interface class
00005 * COPYRIGHT  : (C) 2008 Massimiliano Gubinelli
00006 *******************************************************************************
00007 * This software falls under the GNU general public license and comes WITHOUT
00008 * ANY WARRANTY WHATSOEVER. See the file $TEXMACS_PATH/LICENSE for more details.
00009 * If you don't have this file, write to the Free Software Foundation, Inc.,
00010 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00011 ******************************************************************************/
00012 
00013 #include "cg_renderer.hpp"
00014 #include "analyze.hpp"
00015 #include "image_files.hpp"
00016 #include "file.hpp"
00017 #include "iterator.hpp"
00018 #include "gui.hpp" // for INTERRUPT_EVENT, INTERRUPTED_EVENT
00019 #include "font.hpp" // for the definition of font
00020 
00021 #include "Freetype/tt_file.hpp" // tt_font_find
00022 
00023 #include "mac_images.h"
00024 
00025 /******************************************************************************
00026 * CG images
00027 ******************************************************************************/
00028 
00029 struct cg_image_rep: concrete_struct {
00030        CGImageRef img;
00031        SI xo,yo;
00032        int w,h;
00033        cg_image_rep (CGImageRef img2, SI xo2, SI yo2, int w2, int h2) :
00034     img (img2), xo (xo2), yo (yo2), w (w2), h (h2) { CGImageRetain(img); };
00035        ~cg_image_rep()  {  CGImageRelease(img); };
00036        friend class cg_image;
00037 };
00038 
00039 class cg_image {
00040        CONCRETE_NULL(cg_image);
00041   cg_image (CGImageRef img2, SI xo2, SI yo2, int w2, int h2):
00042     rep (tm_new <cg_image_rep> (img2, xo2, yo2, w2, h2)) {}    
00043 };
00044 
00045 CONCRETE_NULL_CODE(cg_image);
00046 
00047 /******************************************************************************
00048  * Global support variables for all cg_renderers
00049  ******************************************************************************/
00050 
00051 
00052 static hashmap<basic_character,cg_image> character_image;  // bitmaps of all characters
00053 static hashmap<string,cg_image> images; 
00054 
00055 
00056 
00057 /******************************************************************************
00058  * cg_renderer
00059  ******************************************************************************/
00060 
00061 void 
00062 cg_set_color (CGContextRef cxt, color col) {
00063   int r, g, b, a;
00064   get_rgb_color (col, r, g, b, a);
00065   CGContextSetRGBFillColor(cxt, r/255.0, g/255.0, b/255.0, a/255.0);
00066   CGContextSetRGBStrokeColor(cxt, r/255.0, g/255.0, b/255.0, a/255.0);
00067 }
00068 
00069 cg_renderer_rep::cg_renderer_rep (int w2, int h2):
00070  basic_renderer_rep(w2,h2), context(NULL)
00071 {
00072 }
00073 
00074 cg_renderer_rep::~cg_renderer_rep () {
00075   if (context) end();
00076 }
00077 
00078 
00079 void 
00080 cg_renderer_rep::begin (void * c) { 
00081   context = (CGContextRef)c; 
00082   CGContextRetain(context);
00083   CGContextBeginPage(context, NULL);
00084 }
00085 
00086 void 
00087 cg_renderer_rep::end () { 
00088   CGContextEndPage(context);
00089   CGContextRelease(context); 
00090   context = NULL;  
00091 }
00092 
00093 void 
00094 cg_renderer_rep::next_page () { 
00095   CGContextEndPage(context);
00096   CGContextBeginPage(context, NULL);
00097 }
00098 
00099 void
00100 cg_renderer_rep::set_color (color c) {
00101   basic_renderer_rep::set_color(c);
00102   cg_set_color(context,cur_fg);
00103 }
00104 
00105 void
00106 cg_renderer_rep::set_line_style (SI lw, int type, bool round) {
00107   (void) type;
00108        
00109   CGContextSetLineCap(context, round? kCGLineCapRound : kCGLineCapSquare);
00110   CGContextSetLineJoin(context, kCGLineJoinRound);
00111   CGContextSetLineWidth(context, lw <= pixel ? 1 : ((lw+thicken) / (1.0*pixel)));
00112 }
00113 
00114 void
00115 cg_renderer_rep::line (SI x1, SI y1, SI x2, SI y2) {
00116   decode (x1, y1);
00117   decode (x2, y2);
00118   // y1--; y2--; // top-left origin to bottom-left origin conversion
00119   CGContextSetShouldAntialias(context, true);
00120   CGPoint points[2]= { CGPointMake(x1,y1), CGPointMake(x2,y2) };
00121   CGContextStrokeLineSegments(context, points, 2);
00122 }
00123 
00124 void
00125 cg_renderer_rep::lines (array<SI> x, array<SI> y) {
00126   int i, n= N(x);
00127   if ((N(y) != n) || (n<1)) return;
00128   STACK_NEW_ARRAY (pnt, CGPoint, n);
00129   CGContextSetShouldAntialias(context, true);
00130   for (i=0; i<n; i++) {
00131     SI xx= x[i], yy= y[i];
00132     decode (xx, yy);
00133     pnt[i] = CGPointMake(xx,yy);
00134     if (i>0) {
00135               CGContextStrokeLineSegments(context, pnt + (i - 1), 2); // FIX: hack
00136     }
00137   }
00138   STACK_DELETE_ARRAY (pnt);
00139 }
00140 
00141 void
00142 cg_renderer_rep::clear (SI x1, SI y1, SI x2, SI y2) {
00143   x1= max (x1, cx1-ox); y1= max (y1, cy1-oy);
00144   x2= min (x2, cx2-ox); y2= min (y2, cy2-oy);
00145   // outer_round (x1, y1, x2, y2); might still be needed somewhere
00146   decode (x1, y1);
00147   decode (x2, y2);
00148   if ((x1>=x2) || (y1<=y2)) return;
00149   cg_set_color (context, cur_bg);
00150   CGContextSetShouldAntialias(context, false);
00151   CGContextFillRect(context, CGRectMake(x1, y2, x2-x1, y1-y2) );
00152   cg_set_color (context, cur_fg);
00153 }
00154 
00155 void
00156 cg_renderer_rep::fill (SI x1, SI y1, SI x2, SI y2) {
00157   if ((x2>x1) && ((x2-x1)<pixel)) {
00158     SI d= pixel-(x2-x1);
00159     x1 -= (d>>1);
00160     x2 += ((d+1)>>1);
00161   }
00162   if ((y2>y1) && ((y2-y1)<pixel)) {
00163     SI d= pixel-(y2-y1);
00164     y1 -= (d>>1);
00165     y2 += ((d+1)>>1);
00166   }
00167   
00168   x1= max (x1, cx1-ox); y1= max (y1, cy1-oy);
00169   x2= min (x2, cx2-ox); y2= min (y2, cy2-oy);
00170   // outer_round (x1, y1, x2, y2); might still be needed somewhere
00171   if ((x1>=x2) || (y1>=y2)) return;
00172   
00173   decode (x1, y1);
00174   decode (x2, y2);
00175 
00176  // cg_set_color (context, cur_fg);
00177   CGContextSetShouldAntialias (context, false);
00178   CGContextFillRect (context, CGRectMake(x1, y2, x2-x1, y1-y2) );
00179 }
00180 
00181 void
00182 cg_renderer_rep::arc (SI x1, SI y1, SI x2, SI y2, int alpha, int delta) {
00183   (void) alpha; (void) delta;
00184   if ((x1>=x2) || (y1>=y2)) return;
00185   decode (x1, y1);
00186   decode (x2, y2);
00187   //FIXME: XDrawArc (dpy, win, gc, x1, y2, x2-x1, y1-y2, alpha, delta);
00188 }
00189 
00190 void
00191 cg_renderer_rep::fill_arc (SI x1, SI y1, SI x2, SI y2, int alpha, int delta) {
00192   (void) alpha; (void) delta;
00193   if ((x1>=x2) || (y1>=y2)) return;
00194   decode (x1, y1);
00195   decode (x2, y2);
00196   //FIXME: XFillArc (dpy, win, gc, x1, y2, x2-x1, y1-y2, alpha, delta);
00197 }
00198 
00199 void
00200 cg_renderer_rep::polygon (array<SI> x, array<SI> y, bool convex) {  
00201   int i, n= N(x);
00202   if ((N(y) != n) || (n<1)) return;
00203        
00204   CGContextBeginPath(context);
00205   for (i=0; i<n; i++) {
00206     SI xx= x[i], yy= y[i];
00207     decode (xx, yy);
00208        if (i==0) CGContextMoveToPoint (context, xx, yy);
00209        else  CGContextAddLineToPoint(context, xx ,yy);
00210   }
00211   CGContextClosePath (context);
00212 //  cg_set_color (context, cur_fg);
00213   CGContextSetShouldAntialias (context, true);
00214   if (convex)    CGContextEOFillPath (context);  
00215   else CGContextFillPath (context);       
00216 }
00217 
00218 
00219 /******************************************************************************
00220 * Image rendering
00221 ******************************************************************************/
00222 struct cg_cache_image_rep: cache_image_element_rep {
00223        cg_cache_image_rep (int w2, int h2, time_t time2, CGImageRef ptr2) :
00224     cache_image_element_rep(w2,h2,time2,ptr2) {  CGImageRetain((CGImageRef)ptr); };
00225        virtual ~cg_cache_image_rep() { CGImageRelease((CGImageRef)ptr); };
00226 };
00227 
00228 void
00229 cg_renderer_rep::image (url u, SI w, SI h, SI x, SI y,
00230                      double cx1, double cy1, double cx2, double cy2,
00231                         int alpha)
00232 {
00233   // Given an image of original size (W, H),
00234   // we display the part (cx1 * W, xy1 * H, cx2 * W, cy2 * H)
00235   // at position (x, y) in a rectangle of size (w, h)
00236 
00237   // if (DEBUG_EVENTS) cout << "cg_renderer_rep::image " << as_string(u) << LF;
00238   (void) alpha;
00239 
00240   w= w/pixel; h= h/pixel;
00241   decode (x, y);
00242   
00243   //painter.setRenderHints (0);
00244   //painter.drawRect (QRect (x, y-h, w, h));
00245   
00246   CGImageRef pm = NULL;
00247   tree lookup= tuple (u->t);
00248   lookup << as_string (w ) << as_string (h )
00249   << as_string (cx1) << as_string (cy1)
00250   << as_string (cx2) << as_string (cy2) << "cg-image" ;
00251   cache_image_element ci = get_image_cache(lookup);
00252   if (!is_nil(ci)) {
00253     pm = static_cast<CGImageRef> (ci->ptr);
00254   } else {
00255          if (suffix (u) == "png") {
00256       // rendering
00257       string suu = as_string (u);
00258       char * buf = as_charp(suu); 
00259       // cout << suu << LF;
00260       CFURLRef uu =  CFURLCreateFromFileSystemRepresentation(NULL, (UInt8*)buf, N(suu),  false);
00261       tm_delete (buf);
00262       CGImageSourceRef source =  CGImageSourceCreateWithURL ( uu, NULL );
00263       pm =  CGImageSourceCreateImageAtIndex(source, 0, NULL);
00264       CFRelease(source);
00265       CFRelease(uu);
00266          } else if (suffix (u) == "ps" ||
00267                suffix (u) == "eps" ||
00268                suffix (u) == "pdf") {
00269       url temp= url_temp (".png");
00270 //      system ("convert", u, temp);
00271       mac_image_to_png (u, temp); 
00272       string suu = as_string (temp);
00273       char * buf = as_charp(suu); 
00274       //cout << suu << LF;
00275       CFURLRef uu =  CFURLCreateFromFileSystemRepresentation(NULL, (UInt8*)buf, N(suu),  false);
00276       tm_delete (buf);
00277       CGImageSourceRef source =  CGImageSourceCreateWithURL ( uu, NULL );
00278       pm =  CGImageSourceCreateImageAtIndex(source, 0, NULL);
00279       CFRelease(source);
00280       CFRelease(uu);
00281       remove (temp);
00282     }
00283 
00284     if (pm == NULL ) {
00285       cout << "TeXmacs] warning: cannot render " << as_string (u) << "\n";
00286       return;
00287     }
00288     // caching
00289     ci = tm_new <cg_cache_image_rep> (w,h, texmacs_time(), pm);
00290     set_image_cache(lookup, ci);
00291     (ci->nr)++;
00292   }
00293   
00294        CGContextSetShouldAntialias(context, false);
00295        CGContextSaveGState(context);
00296        CGContextTranslateCTM(context, x,y);
00297        CGContextScaleCTM(context,1.0,-1.0);
00298        CGContextDrawImage(context, CGRectMake(0, 0, w, h), pm); 
00299        CGContextRestoreGState(context);
00300 }
00301 
00302 
00303 
00304 void
00305 cg_renderer_rep::draw_clipped (CGImageRef im, int w, int h, SI x, SI y) {
00306   decode (x , y );
00307   y--; // top-left origin to bottom-left origin conversion
00308        // clear(x1,y1,x2,y2);
00309   CGContextSetShouldAntialias(context, true);
00310 //  CGContextSetBlendMode(context,kCGBlendModeSourceAtop);
00311   CGContextDrawImage(context, CGRectMake(x,y,w,h), im); 
00312 }  
00313 
00314 
00315 
00316 
00317 static hashmap<string,pointer> native_fonts;
00318 static hashset<string> native_loaded;
00319 
00320 int 
00321 posixStringToFSSpec(FSSpec *fss, CFStringRef posixPath, bool isDirectory)  {
00322        FSRef fsRef;
00323        FSSpec fileSpec;
00324        // create a URL from the posix path:
00325        CFURLRef url = CFURLCreateWithFileSystemPath(kCFAllocatorDefault,posixPath,kCFURLPOSIXPathStyle,isDirectory);
00326        // check to be sure the URL was created properly:
00327        if (url == 0) {
00328               //fprintf(stderr,"Can't get URL");
00329               return(1);
00330        }
00331        // use the CF function to extract an FSRef from the URL:
00332        if (CFURLGetFSRef(url, &fsRef) == 0){
00333               //fprintf(stderr,"Can't get FSRef.\n");
00334               CFRelease(url);
00335               return(1);
00336        }
00337        // use Carbon call to get the FSSpec from the FSRef
00338        if (FSGetCatalogInfo (&fsRef, kFSCatInfoNone, 0, 0, &fileSpec, 0) != noErr) {              
00339               //fprintf(stderr,"Can't get FSSpec.\n");
00340               CFRelease(url);
00341               return(1);
00342        }
00343        // We have a valid FSSpec! Clean up and return it:
00344        CFRelease(url);
00345        *fss = fileSpec;
00346        return 0;
00347 }
00348 
00349 
00350 
00351 bool 
00352 cg_renderer_rep::native_draw (int ch, font_glyphs fn, SI x, SI y) {
00353        string name= fn->res_name;
00354        unsigned char c= ch;
00355        if (ch >= 256) {
00356               name= name * "-" * as_string (ch / 256);
00357               c= (unsigned char) (ch & 255);
00358        }
00359        
00360        //     cout << name << LF;
00361        int size;
00362        {
00363               // find size (weird)
00364               int    pos1  = search_forwards (".", name);
00365               int pos2= search_backwards (":", name);
00366               string sz = name(pos2+1,pos1);
00367               size = as_int(sz);
00368        }
00369        CGFontRef f = (CGFontRef)native_fonts(name);
00370        
00371        if ((f == NULL)&&(! native_loaded->contains(name))) {
00372               native_loaded->insert(name);
00373               string ttf;
00374               int    pos  = search_forwards (".", name);
00375               string root = (pos==-1? name: name (0, pos));
00376               if ((pos!=-1) && ends (name, "tt")) {
00377                      int pos2= search_backwards (":", name);
00378                      root= name (0, pos2);
00379                      url u= tt_font_find (root);
00380                      if (suffix (u) == "pfb") {
00381 //              cout << u << LF;
00382         url v= url_temp (".otf");
00383                             string vs = concretize(v);
00384                             system ("/Users/mgubi/t/t1wrap/T1Wrap " * concretize(u) * " > " * vs);
00385                             FSSpec fss;
00386                             ATSFontRef atsFont;
00387                             ATSFontContainerRef container;
00388                             char *p = as_charp(vs);
00389                             CFStringRef font_filename = CFStringCreateWithCString(NULL,p,kCFStringEncodingASCII);
00390                                    
00391                             if (posixStringToFSSpec(&fss,font_filename,false)) {
00392                                    cout << "Cannot load font" << vs << LF;
00393                             } else {
00394                                    int status =  ATSFontActivateFromFileSpecification(&fss,kATSFontContextLocal,kATSFontFormatUnspecified,NULL,NULL,&container);
00395                                    cout << "Font " << vs << " loaded" << LF;
00396                                    ItemCount count;
00397                                    status = ATSFontFindFromContainer(container, 0, 1, &atsFont, &count);
00398                                           
00399                                    f = CGFontCreateWithPlatformFont((void*)&atsFont);
00400                                    native_fonts(name) = f;
00401                             }
00402                             tm_delete (p);
00403                             CFRelease(font_filename);
00404                             remove (v);
00405       }
00406               }
00407        } // end caching
00408        
00409        if (f) {
00410               decode (x , y );
00411               y--; // top-left origin to bottom-left origin conversion
00412     CGContextRef cgc = context;
00413               CGContextSetFont(cgc,f);
00414               CGContextSetFontSize(cgc,size);
00415               CGAffineTransform    kHorizontalMatrix = { PIXEL*600.0/(pixel*72.0),  0.0,  0.0,  -PIXEL*600.0/(pixel*72.0),  0.0,  0.0 };
00416               CGContextSetTextMatrix(cgc, kHorizontalMatrix);
00417               CGContextSetTextDrawingMode(cgc,  kCGTextFill);
00418               CGContextSetShouldAntialias(cgc,true);
00419               CGContextSetShouldSmoothFonts(cgc,true);
00420               //      CGContextSetBlendMode(context,kCGBlendModeSourceAtop);
00421   //  cg_set_color (context, cur_fg);
00422               CGGlyph buf[1] = {c};
00423               CGContextShowGlyphsAtPoint(cgc,x,y,(CGGlyph*)buf,1);
00424        } 
00425        return true;
00426 }
00427 
00428 
00429 CGContextRef 
00430 MyCreateBitmapContext (int pixelsWide, int pixelsHigh) {
00431     int bitmapBytesPerRow   = (pixelsWide * 4);
00432     int bitmapByteCount     = (bitmapBytesPerRow * pixelsHigh);       
00433     CGColorSpaceRef colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
00434     void *bitmapData = malloc( bitmapByteCount );
00435     if (bitmapData == NULL) {
00436         //fprintf (stderr, "Memory not allocated!");
00437         return NULL;
00438     }
00439     CGContextRef context = CGBitmapContextCreate (bitmapData, pixelsWide,    pixelsHigh,   8,
00440                                                   bitmapBytesPerRow, colorSpace, kCGImageAlphaPremultipliedLast);
00441     if (context == NULL) {
00442         free (bitmapData);
00443        // fprintf (stderr, "Context not created!");
00444         return NULL;
00445     }
00446     CGColorSpaceRelease (colorSpace);
00447     return context;
00448 }
00449 
00450 
00451 void
00452 cg_renderer_rep::draw (int c, font_glyphs fng, SI x, SI y) {
00453   // get the pixmap
00454   basic_character xc (c, fng, sfactor, 0, 0);
00455   cg_image mi = character_image [xc];
00456   if (is_nil(mi)) {
00457     SI xo, yo;
00458     glyph pre_gl= fng->get (c); if (is_nil (pre_gl)) return;
00459     glyph gl= shrink (pre_gl, sfactor, sfactor, xo, yo);
00460     int i, j, w= gl->width, h= gl->height;
00461          CGImageRef im = NULL;
00462          {
00463                 CGContextRef ic = MyCreateBitmapContext(w,h);
00464                 int nr_cols= sfactor*sfactor;
00465                 if (nr_cols >= 64) nr_cols= 64;
00466                 //CGContextSetShouldAntialias(ic,true);
00467                 CGContextSetBlendMode(ic,kCGBlendModeCopy);
00468                 //CGContextSetRGBFillColor(ic,1.0,1.0,1.0,0.0);
00469                 //CGContextFillRect(ic,CGRectMake(0,0,w,h));
00470                 
00471                 for (j=0; j<h; j++)
00472                        for (i=0; i<w; i++) {
00473                               int col = gl->get_x (i, j);
00474                               CGContextSetRGBFillColor(ic, 0.0,0.0,0.0,  ((255*col)/(nr_cols+1))/255.0);
00475                               CGContextFillRect(ic,CGRectMake(i,j,1,1));
00476                        }
00477                 im = CGBitmapContextCreateImage (ic);
00478                 CGContextRelease (ic);
00479          }
00480     cg_image mi2 (im, xo, yo, w, h);
00481     mi = mi2;
00482          CGImageRelease(im); // cg_image retains im
00483     character_image (xc)= mi;
00484   }
00485   
00486   // draw the character
00487   {
00488     (void) w; (void) h;
00489     int x1= x- mi->xo*sfactor;
00490     int y1=  y+ mi->yo*sfactor;
00491     decode (x1, y1);
00492     y1--; // top-left origin to bottom-left origin conversion
00493     CGRect r = CGRectMake(x1,y1,mi->w,mi->h);
00494     CGContextSetShouldAntialias (context, true);
00495     CGContextSaveGState (context);
00496   //  cg_set_color (context, cur_fg);
00497     CGContextClipToMask (context, r, mi->img); 
00498     CGContextFillRect (context, r);
00499     CGContextRestoreGState (context);
00500   }  
00501 }
00502 
00503 /******************************************************************************
00504 * Setting up and displaying xpm pixmaps
00505 ******************************************************************************/
00506 
00507 
00508 
00509 static CGImageRef xpm_init(url file_name)
00510 {
00511        tree t= xpm_load (file_name);
00512        
00513        // get main info
00514        int ok, i=0, j, k, w, h, c, b, x, y;
00515        string s= as_string (t[0]);
00516        skip_spaces (s, i);
00517        ok= read_int (s, i, w);
00518        skip_spaces (s, i);
00519        ok= read_int (s, i, h) && ok;
00520        skip_spaces (s, i);
00521        ok= read_int (s, i, c) && ok;
00522        skip_spaces (s, i);
00523        ok= read_int (s, i, b) && ok;
00524        if ((!ok) || (N(t)<(c+1)) || (c<=0)) {
00525          cerr << "File name= " << file_name << "\n";
00526          FAILED ("invalid xpm");
00527        }
00528        
00529        // setup colors
00530        string first_name;
00531        hashmap<string,color> pmcs;
00532        for (k=0; k<c; k++) {
00533               string s   = as_string (t[k+1]);
00534               string name= "";
00535               string def = "none";
00536               if (N(s)<b) i=N(s);
00537               else { name= s(0,b); i=b; }
00538               if (k==0) first_name= name;
00539               
00540               skip_spaces (s, i);
00541               if ((i<N(s)) && (s[i]=='s')) {
00542                      i++;
00543                      skip_spaces (s, i);
00544                      while ((i<N(s)) && (s[i]!=' ') && (s[i]!='\t')) i++;
00545                      skip_spaces (s, i);
00546               }
00547               if ((i<N(s)) && (s[i]=='c')) {
00548                      i++;
00549                      skip_spaces (s, i);
00550                      j=i;
00551                      while ((i<N(s)) && (s[i]!=' ') && (s[i]!='\t')) i++;
00552                      def= locase_all (s (j, i));
00553               }
00554               
00555               pmcs(name)= xpm_to_color(def);
00556        }
00557        CGContextRef ic = MyCreateBitmapContext(w,h);
00558        CGContextSetBlendMode(ic,kCGBlendModeCopy);
00559        // setup pixmap
00560        for (y=0; y<h; y++) {
00561               if (N(t)< (y+c+1)) s= "";
00562               else s= as_string (t[y+c+1]);
00563               for (x=0; x<w; x++) {
00564                      string name;
00565                      if (N(s)<(b*(x+1))) name= first_name;
00566                      else name= s (b*x, b*(x+1));
00567                      color col = pmcs[(pmcs->contains (name) ? name : first_name)];
00568       cg_set_color (ic, col);
00569                      CGContextFillRect (ic,CGRectMake(x,y,1,1));
00570               }
00571        }
00572        CGImageRef im = CGBitmapContextCreateImage (ic);
00573        CGContextRelease (ic);
00574        return im;
00575 }
00576 
00577 
00578 
00579 extern int char_clip;
00580 
00581 CGImageRef 
00582 cg_renderer_rep::xpm_image (url file_name) { 
00583   CGImageRef pxm= NULL;
00584   cg_image mi= images [as_string (file_name)];
00585   if (is_nil (mi)) {    
00586          pxm = xpm_init(file_name);
00587     cg_image mi2 (pxm, 0, 0, CGImageGetWidth (pxm), CGImageGetHeight (pxm));
00588     mi= mi2;
00589     images (as_string (file_name))= mi2;
00590     CGImageRelease(pxm);
00591   } else pxm= mi->img;
00592   return pxm;
00593 }
00594 
00595 void
00596 cg_renderer_rep::xpm (url file_name, SI x, SI y) {
00597   y -= pixel; // counter balance shift in draw_clipped
00598   CGImageRef image = xpm_image (file_name);
00599   ASSERT (sfactor == 1, "shrinking factor should be 1");
00600   int w = CGImageGetWidth(image);
00601   int h = CGImageGetHeight(image);
00602   int old_clip= char_clip;
00603   char_clip = true;
00604   draw_clipped (image, w, h, x, y);
00605   char_clip = old_clip;
00606 }
00607 
00608 /******************************************************************************
00609  * main coregraphics renderer
00610  ******************************************************************************/
00611 
00612 static cg_renderer_rep* the_renderer= NULL;
00613 
00614 cg_renderer_rep*
00615 the_cg_renderer () {
00616        if (!the_renderer) the_renderer= tm_new <cg_renderer_rep> ();
00617        return the_renderer;
00618 }