~ubuntu-branches/ubuntu/quantal/texmacs/quantal

« back to all changes in this revision

Viewing changes to src/Plugins/MacOS/cg_renderer.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Atsuhito KOHDA, Kamaraju Kusumanchi, kohda
  • Date: 2009-04-26 19:35:14 UTC
  • mfrom: (1.1.10 upstream) (4.1.4 squeeze)
  • Revision ID: james.westby@ubuntu.com-20090426193514-9yo3oggdslgdls4b
Tags: 1:1.0.7.2-1
[Kamaraju Kusumanchi <kamaraju@gmail.com>]
* New upstream release
* texmacs crashes if /usr/share/texmacs/TeXmacs/misc/pixmaps/unknown.ps
  is not present. Do not remove it. (Closes: #484073, #497021)
* update patches 03_mupad.dpatch, 04_axiom.dpatch, 11-desktop-file.dpatch
* fix the mime problem in gnome. Thanks to Andrea Gamba for the fix.
[kohda]
* Refined a fix for the mime problem in gnome a bit.
* Try to fix /bin/sh problem (debian/fixsh) but it is not complete fix yet.
* Try to fix hard coded settings for ipa fonts(patches/09_ipa.dpatch), 
  especially for Debian where no ipa fonts exist yet.
* Fixed obsolete Build-Depends: changed libltdl3-dev to 
  libltdl-dev | libltdl7-dev (the latter for Ubuntu?)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
2
/******************************************************************************
 
3
* MODULE     : cg_renderer.cpp
 
4
* DESCRIPTION: CoreGraphics drawing interface class
 
5
* COPYRIGHT  : (C) 2008 Massimiliano Gubinelli
 
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 "cg_renderer.hpp"
 
14
#include "analyze.hpp"
 
15
#include "image_files.hpp"
 
16
#include "file.hpp"
 
17
#include "iterator.hpp"
 
18
#include "gui.hpp" // for INTERRUPT_EVENT, INTERRUPTED_EVENT
 
19
#include "font.hpp" // for the definition of font
 
20
 
 
21
#include "Freetype/tt_file.hpp" // tt_font_find
 
22
 
 
23
/******************************************************************************
 
24
* CG images
 
25
******************************************************************************/
 
26
 
 
27
struct cg_image_rep: concrete_struct {
 
28
        CGImageRef img;
 
29
        SI xo,yo;
 
30
        int w,h;
 
31
        cg_image_rep (CGImageRef img2, SI xo2, SI yo2, int w2, int h2) :
 
32
    img (img2), xo (xo2), yo (yo2), w (w2), h (h2) { CGImageRetain(img); };
 
33
        ~cg_image_rep()  {  CGImageRelease(img); };
 
34
        friend class cg_image;
 
35
};
 
36
 
 
37
class cg_image {
 
38
        CONCRETE_NULL(cg_image);
 
39
  cg_image (CGImageRef img2, SI xo2, SI yo2, int w2, int h2):
 
40
    rep (tm_new <cg_image_rep> (img2, xo2, yo2, w2, h2)) {}     
 
41
};
 
42
 
 
43
CONCRETE_NULL_CODE(cg_image);
 
44
 
 
45
/******************************************************************************
 
46
 * Global support variables for all cg_renderers
 
47
 ******************************************************************************/
 
48
 
 
49
 
 
50
static hashmap<basic_character,cg_image> character_image;  // bitmaps of all characters
 
51
static hashmap<string,cg_image> images; 
 
52
 
 
53
 
 
54
 
 
55
/******************************************************************************
 
56
 * cg_renderer
 
57
 ******************************************************************************/
 
58
 
 
59
void 
 
60
cg_set_color (CGContextRef cxt, color col) {
 
61
  int r, g, b;
 
62
  get_rgb_color(col,r,g,b);
 
63
  CGContextSetRGBFillColor(cxt, r/255.0, g/255.0, b/255.0, 1.0);
 
64
  CGContextSetRGBStrokeColor(cxt, r/255.0, g/255.0, b/255.0, 1.0);
 
65
}
 
66
 
 
67
cg_renderer_rep::cg_renderer_rep (int w2, int h2):
 
68
 basic_renderer_rep(w2,h2), context(NULL)
 
69
{
 
70
}
 
71
 
 
72
cg_renderer_rep::~cg_renderer_rep () {
 
73
  if (context) end();
 
74
}
 
75
 
 
76
 
 
77
void 
 
78
cg_renderer_rep::begin (void * c) { 
 
79
  context = (CGContextRef)c; 
 
80
  CGContextRetain(context);
 
81
  CGContextBeginPage(context, NULL);
 
82
}
 
83
 
 
84
void 
 
85
cg_renderer_rep::end () { 
 
86
  CGContextEndPage(context);
 
87
  CGContextRelease(context); 
 
88
  context = NULL;  
 
89
}
 
90
 
 
91
void 
 
92
cg_renderer_rep::next_page () { 
 
93
  CGContextEndPage(context);
 
94
  CGContextBeginPage(context, NULL);
 
95
}
 
96
 
 
97
void
 
98
cg_renderer_rep::set_color (color c) {
 
99
  basic_renderer_rep::set_color(c);
 
100
  cg_set_color(context,cur_fg);
 
101
}
 
102
 
 
103
void
 
104
cg_renderer_rep::set_line_style (SI lw, int type, bool round) {
 
105
  (void) type;
 
106
        
 
107
  CGContextSetLineCap(context, round? kCGLineCapRound : kCGLineCapSquare);
 
108
  CGContextSetLineJoin(context, kCGLineJoinRound);
 
109
  CGContextSetLineWidth(context, lw <= pixel ? 1 : ((lw+thicken) / (1.0*pixel)));
 
110
}
 
111
 
 
112
void
 
113
cg_renderer_rep::line (SI x1, SI y1, SI x2, SI y2) {
 
114
  decode (x1, y1);
 
115
  decode (x2, y2);
 
116
  // y1--; y2--; // top-left origin to bottom-left origin conversion
 
117
  CGContextSetShouldAntialias(context, true);
 
118
  CGPoint points[2]= { CGPointMake(x1,y1), CGPointMake(x2,y2) };
 
119
  CGContextStrokeLineSegments(context, points, 2);
 
120
}
 
121
 
 
122
void
 
123
cg_renderer_rep::lines (array<SI> x, array<SI> y) {
 
124
  int i, n= N(x);
 
125
  if ((N(y) != n) || (n<1)) return;
 
126
  STACK_NEW_ARRAY (pnt, CGPoint, n);
 
127
  CGContextSetShouldAntialias(context, true);
 
128
  for (i=0; i<n; i++) {
 
129
    SI xx= x[i], yy= y[i];
 
130
    decode (xx, yy);
 
131
    pnt[i] = CGPointMake(xx,yy);
 
132
    if (i>0) {
 
133
                CGContextStrokeLineSegments(context, pnt + (i - 1), 2); // FIX: hack
 
134
    }
 
135
  }
 
136
  STACK_DELETE_ARRAY (pnt);
 
137
}
 
138
 
 
139
void
 
140
cg_renderer_rep::clear (SI x1, SI y1, SI x2, SI y2) {
 
141
  x1= max (x1, cx1-ox); y1= max (y1, cy1-oy);
 
142
  x2= min (x2, cx2-ox); y2= min (y2, cy2-oy);
 
143
  // outer_round (x1, y1, x2, y2); might still be needed somewhere
 
144
  decode (x1, y1);
 
145
  decode (x2, y2);
 
146
  if ((x1>=x2) || (y1<=y2)) return;
 
147
  cg_set_color (context, cur_bg);
 
148
  CGContextSetShouldAntialias(context, false);
 
149
  CGContextFillRect(context, CGRectMake(x1, y2, x2-x1, y1-y2) );
 
150
  cg_set_color (context, cur_fg);
 
151
}
 
152
 
 
153
void
 
154
cg_renderer_rep::fill (SI x1, SI y1, SI x2, SI y2) {
 
155
  if ((x2>x1) && ((x2-x1)<pixel)) {
 
156
    SI d= pixel-(x2-x1);
 
157
    x1 -= (d>>1);
 
158
    x2 += ((d+1)>>1);
 
159
  }
 
160
  if ((y2>y1) && ((y2-y1)<pixel)) {
 
161
    SI d= pixel-(y2-y1);
 
162
    y1 -= (d>>1);
 
163
    y2 += ((d+1)>>1);
 
164
  }
 
165
  
 
166
  x1= max (x1, cx1-ox); y1= max (y1, cy1-oy);
 
167
  x2= min (x2, cx2-ox); y2= min (y2, cy2-oy);
 
168
  // outer_round (x1, y1, x2, y2); might still be needed somewhere
 
169
  if ((x1>=x2) || (y1>=y2)) return;
 
170
  
 
171
  decode (x1, y1);
 
172
  decode (x2, y2);
 
173
 
 
174
 // cg_set_color (context, cur_fg);
 
175
  CGContextSetShouldAntialias (context, false);
 
176
  CGContextFillRect (context, CGRectMake(x1, y2, x2-x1, y1-y2) );
 
177
}
 
178
 
 
179
void
 
180
cg_renderer_rep::arc (SI x1, SI y1, SI x2, SI y2, int alpha, int delta) {
 
181
  (void) alpha; (void) delta;
 
182
  if ((x1>=x2) || (y1>=y2)) return;
 
183
  decode (x1, y1);
 
184
  decode (x2, y2);
 
185
  //FIXME: XDrawArc (dpy, win, gc, x1, y2, x2-x1, y1-y2, alpha, delta);
 
186
}
 
187
 
 
188
void
 
189
cg_renderer_rep::fill_arc (SI x1, SI y1, SI x2, SI y2, int alpha, int delta) {
 
190
  (void) alpha; (void) delta;
 
191
  if ((x1>=x2) || (y1>=y2)) return;
 
192
  decode (x1, y1);
 
193
  decode (x2, y2);
 
194
  //FIXME: XFillArc (dpy, win, gc, x1, y2, x2-x1, y1-y2, alpha, delta);
 
195
}
 
196
 
 
197
void
 
198
cg_renderer_rep::polygon (array<SI> x, array<SI> y, bool convex) {  
 
199
  int i, n= N(x);
 
200
  if ((N(y) != n) || (n<1)) return;
 
201
        
 
202
  CGContextBeginPath(context);
 
203
  for (i=0; i<n; i++) {
 
204
    SI xx= x[i], yy= y[i];
 
205
    decode (xx, yy);
 
206
        if (i==0) CGContextMoveToPoint (context, xx, yy);
 
207
        else  CGContextAddLineToPoint(context, xx ,yy);
 
208
  }
 
209
  CGContextClosePath (context);
 
210
//  cg_set_color (context, cur_fg);
 
211
  CGContextSetShouldAntialias (context, true);
 
212
  if (convex)    CGContextEOFillPath (context); 
 
213
  else CGContextFillPath (context);     
 
214
}
 
215
 
 
216
 
 
217
/******************************************************************************
 
218
* Image rendering
 
219
******************************************************************************/
 
220
struct cg_cache_image_rep: cache_image_element_rep {
 
221
        cg_cache_image_rep (int w2, int h2, int time2, CGImageRef ptr2) :
 
222
    cache_image_element_rep(w2,h2,time2,ptr2) {  CGImageRetain((CGImageRef)ptr); };
 
223
        virtual ~cg_cache_image_rep() { CGImageRelease((CGImageRef)ptr); };
 
224
};
 
225
 
 
226
void
 
227
cg_renderer_rep::image (url u, SI w, SI h, SI x, SI y,
 
228
                        double cx1, double cy1, double cx2, double cy2) 
 
229
{
 
230
  // Given an image of original size (W, H),
 
231
  // we display the part (cx1 * W, xy1 * H, cx2 * W, cy2 * H)
 
232
  // at position (x, y) in a rectangle of size (w, h)
 
233
 
 
234
  // if (DEBUG_EVENTS) cout << "cg_renderer_rep::image " << as_string(u) << LF;
 
235
 
 
236
  w= w/pixel; h= h/pixel;
 
237
  decode (x, y);
 
238
  
 
239
  //painter.setRenderHints (0);
 
240
  //painter.drawRect (QRect (x, y-h, w, h));
 
241
  
 
242
  CGImageRef pm = NULL;
 
243
  tree lookup= tuple (u->t);
 
244
  lookup << as_string (w ) << as_string (h )
 
245
  << as_string (cx1) << as_string (cy1)
 
246
  << as_string (cx2) << as_string (cy2) << "cg-image" ;
 
247
  cache_image_element ci = get_image_cache(lookup);
 
248
  if (!is_nil(ci)) {
 
249
    pm = static_cast<CGImageRef> (ci->ptr);
 
250
  } else {
 
251
          if (suffix (u) == "png") {
 
252
      // rendering
 
253
      string suu = as_string (u);
 
254
      char * buf = as_charp(suu); 
 
255
      // cout << suu << LF;
 
256
      CFURLRef uu =  CFURLCreateFromFileSystemRepresentation(NULL, (UInt8*)buf, N(suu),  false);
 
257
      tm_delete (buf);
 
258
      CGImageSourceRef source =  CGImageSourceCreateWithURL ( uu, NULL );
 
259
      pm =  CGImageSourceCreateImageAtIndex(source, 0, NULL);
 
260
      CFRelease(source);
 
261
      CFRelease(uu);
 
262
          } else if (suffix (u) == "ps" ||
 
263
               suffix (u) == "eps" ||
 
264
               suffix (u) == "pdf") {
 
265
      url temp= url_temp (".png");
 
266
      system ("convert", u, temp);
 
267
      string suu = as_string (temp);
 
268
      char * buf = as_charp(suu); 
 
269
      //cout << suu << LF;
 
270
      CFURLRef uu =  CFURLCreateFromFileSystemRepresentation(NULL, (UInt8*)buf, N(suu),  false);
 
271
      tm_delete (buf);
 
272
      CGImageSourceRef source =  CGImageSourceCreateWithURL ( uu, NULL );
 
273
      pm =  CGImageSourceCreateImageAtIndex(source, 0, NULL);
 
274
      CFRelease(source);
 
275
      CFRelease(uu);
 
276
      remove (temp);
 
277
    }
 
278
 
 
279
    if (pm == NULL ) {
 
280
      cout << "TeXmacs] warning: cannot render " << as_string (u) << "\n";
 
281
      return;
 
282
    }
 
283
    // caching
 
284
    ci = tm_new <cg_cache_image_rep> (w,h, texmacs_time(), pm);
 
285
    set_image_cache(lookup, ci);
 
286
    (ci->nr)++;
 
287
  }
 
288
  
 
289
        CGContextSetShouldAntialias(context, false);
 
290
        CGContextSaveGState(context);
 
291
        CGContextTranslateCTM(context, x,y);
 
292
        CGContextScaleCTM(context,1.0,-1.0);
 
293
        CGContextDrawImage(context, CGRectMake(0, 0, w, h), pm); 
 
294
        CGContextRestoreGState(context);
 
295
}
 
296
 
 
297
 
 
298
 
 
299
void
 
300
cg_renderer_rep::draw_clipped (CGImageRef im, int w, int h, SI x, SI y) {
 
301
  decode (x , y );
 
302
  y--; // top-left origin to bottom-left origin conversion
 
303
       // clear(x1,y1,x2,y2);
 
304
  CGContextSetShouldAntialias(context, true);
 
305
//  CGContextSetBlendMode(context,kCGBlendModeSourceAtop);
 
306
  CGContextDrawImage(context, CGRectMake(x,y,w,h), im); 
 
307
}  
 
308
 
 
309
 
 
310
 
 
311
 
 
312
static hashmap<string,pointer> native_fonts;
 
313
static hashset<string> native_loaded;
 
314
 
 
315
int 
 
316
posixStringToFSSpec(FSSpec *fss, CFStringRef posixPath, bool isDirectory)  {
 
317
        FSRef fsRef;
 
318
        FSSpec fileSpec;
 
319
        // create a URL from the posix path:
 
320
        CFURLRef url = CFURLCreateWithFileSystemPath(kCFAllocatorDefault,posixPath,kCFURLPOSIXPathStyle,isDirectory);
 
321
        // check to be sure the URL was created properly:
 
322
        if (url == 0) {
 
323
                //fprintf(stderr,"Can't get URL");
 
324
                return(1);
 
325
        }
 
326
        // use the CF function to extract an FSRef from the URL:
 
327
        if (CFURLGetFSRef(url, &fsRef) == 0){
 
328
                //fprintf(stderr,"Can't get FSRef.\n");
 
329
                CFRelease(url);
 
330
                return(1);
 
331
        }
 
332
        // use Carbon call to get the FSSpec from the FSRef
 
333
        if (FSGetCatalogInfo (&fsRef, kFSCatInfoNone, 0, 0, &fileSpec, 0) != noErr) {           
 
334
                //fprintf(stderr,"Can't get FSSpec.\n");
 
335
                CFRelease(url);
 
336
                return(1);
 
337
        }
 
338
        // We have a valid FSSpec! Clean up and return it:
 
339
        CFRelease(url);
 
340
        *fss = fileSpec;
 
341
        return 0;
 
342
}
 
343
 
 
344
 
 
345
 
 
346
bool 
 
347
cg_renderer_rep::native_draw (int ch, font_glyphs fn, SI x, SI y) {
 
348
        string name= fn->res_name;
 
349
        unsigned char c= ch;
 
350
        if (ch >= 256) {
 
351
                name= name * "-" * as_string (ch / 256);
 
352
                c= (unsigned char) (ch & 255);
 
353
        }
 
354
        
 
355
        //      cout << name << LF;
 
356
        int size;
 
357
        {
 
358
                // find size (weird)
 
359
                int    pos1  = search_forwards (".", name);
 
360
                int pos2= search_backwards (":", name);
 
361
                string sz = name(pos2+1,pos1);
 
362
                size = as_int(sz);
 
363
        }
 
364
        CGFontRef f = (CGFontRef)native_fonts(name);
 
365
        
 
366
        if ((f == NULL)&&(! native_loaded->contains(name))) {
 
367
                native_loaded->insert(name);
 
368
                string ttf;
 
369
                int    pos  = search_forwards (".", name);
 
370
                string root = (pos==-1? name: name (0, pos));
 
371
                if ((pos!=-1) && ends (name, "tt")) {
 
372
                        int pos2= search_backwards (":", name);
 
373
                        root= name (0, pos2);
 
374
                        url u= tt_font_find (root);
 
375
                        if (suffix (u) == "pfb") {
 
376
//                cout << u << LF;
 
377
        url v= url_temp (".otf");
 
378
                                string vs = concretize(v);
 
379
                                system ("/Users/mgubi/t/t1wrap/T1Wrap " * concretize(u) * " > " * vs);
 
380
                                FSSpec fss;
 
381
                                ATSFontRef atsFont;
 
382
                                ATSFontContainerRef container;
 
383
                                char *p = as_charp(vs);
 
384
                                CFStringRef font_filename = CFStringCreateWithCString(NULL,p,kCFStringEncodingASCII);
 
385
                                        
 
386
                                if (posixStringToFSSpec(&fss,font_filename,false)) {
 
387
                                        cout << "Cannot load font" << vs << LF;
 
388
                                } else {
 
389
                                        int status =  ATSFontActivateFromFileSpecification(&fss,kATSFontContextLocal,kATSFontFormatUnspecified,NULL,NULL,&container);
 
390
                                        cout << "Font " << vs << " loaded" << LF;
 
391
                                        ItemCount count;
 
392
                                        status = ATSFontFindFromContainer(container, 0, 1, &atsFont, &count);
 
393
                                                
 
394
                                        f = CGFontCreateWithPlatformFont((void*)&atsFont);
 
395
                                        native_fonts(name) = f;
 
396
                                }
 
397
                                tm_delete (p);
 
398
                                CFRelease(font_filename);
 
399
                                remove (v);
 
400
      }
 
401
                }
 
402
        } // end caching
 
403
        
 
404
        if (f) {
 
405
                decode (x , y );
 
406
                y--; // top-left origin to bottom-left origin conversion
 
407
    CGContextRef cgc = context;
 
408
                CGContextSetFont(cgc,f);
 
409
                CGContextSetFontSize(cgc,size);
 
410
                CGAffineTransform       kHorizontalMatrix = { PIXEL*600.0/(pixel*72.0),  0.0,  0.0,  -PIXEL*600.0/(pixel*72.0),  0.0,  0.0 };
 
411
                CGContextSetTextMatrix(cgc, kHorizontalMatrix);
 
412
                CGContextSetTextDrawingMode(cgc,  kCGTextFill);
 
413
                CGContextSetShouldAntialias(cgc,true);
 
414
                CGContextSetShouldSmoothFonts(cgc,true);
 
415
                //       CGContextSetBlendMode(context,kCGBlendModeSourceAtop);
 
416
  //  cg_set_color (context, cur_fg);
 
417
                CGGlyph buf[1] = {c};
 
418
                CGContextShowGlyphsAtPoint(cgc,x,y,(CGGlyph*)buf,1);
 
419
        } 
 
420
        return true;
 
421
}
 
422
 
 
423
 
 
424
CGContextRef 
 
425
MyCreateBitmapContext (int pixelsWide, int pixelsHigh) {
 
426
    int bitmapBytesPerRow   = (pixelsWide * 4);
 
427
    int bitmapByteCount     = (bitmapBytesPerRow * pixelsHigh); 
 
428
    CGColorSpaceRef colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
 
429
    void *bitmapData = malloc( bitmapByteCount );
 
430
    if (bitmapData == NULL) {
 
431
        //fprintf (stderr, "Memory not allocated!");
 
432
        return NULL;
 
433
    }
 
434
    CGContextRef context = CGBitmapContextCreate (bitmapData, pixelsWide,       pixelsHigh,     8,
 
435
                                                  bitmapBytesPerRow, colorSpace, kCGImageAlphaPremultipliedLast);
 
436
    if (context == NULL) {
 
437
        free (bitmapData);
 
438
       // fprintf (stderr, "Context not created!");
 
439
        return NULL;
 
440
    }
 
441
    CGColorSpaceRelease (colorSpace);
 
442
    return context;
 
443
}
 
444
 
 
445
 
 
446
void
 
447
cg_renderer_rep::draw (int c, font_glyphs fng, SI x, SI y) {
 
448
  // get the pixmap
 
449
  basic_character xc (c, fng, sfactor, 0, 0);
 
450
  cg_image mi = character_image [xc];
 
451
  if (is_nil(mi)) {
 
452
    SI xo, yo;
 
453
    glyph pre_gl= fng->get (c); if (is_nil (pre_gl)) return;
 
454
    glyph gl= shrink (pre_gl, sfactor, sfactor, xo, yo);
 
455
    int i, j, w= gl->width, h= gl->height;
 
456
          CGImageRef im = NULL;
 
457
          {
 
458
                  CGContextRef ic = MyCreateBitmapContext(w,h);
 
459
                  int nr_cols= sfactor*sfactor;
 
460
                  if (nr_cols >= 64) nr_cols= 64;
 
461
                  //CGContextSetShouldAntialias(ic,true);
 
462
                  CGContextSetBlendMode(ic,kCGBlendModeCopy);
 
463
                  //CGContextSetRGBFillColor(ic,1.0,1.0,1.0,0.0);
 
464
                  //CGContextFillRect(ic,CGRectMake(0,0,w,h));
 
465
                  
 
466
                  for (j=0; j<h; j++)
 
467
                          for (i=0; i<w; i++) {
 
468
                                  int col = gl->get_x (i, j);
 
469
                                  CGContextSetRGBFillColor(ic, 0.0,0.0,0.0,  ((255*col)/(nr_cols+1))/255.0);
 
470
                                  CGContextFillRect(ic,CGRectMake(i,j,1,1));
 
471
                          }
 
472
                  im = CGBitmapContextCreateImage (ic);
 
473
                  CGContextRelease (ic);
 
474
          }
 
475
    cg_image mi2 (im, xo, yo, w, h);
 
476
    mi = mi2;
 
477
          CGImageRelease(im); // cg_image retains im
 
478
    character_image (xc)= mi;
 
479
  }
 
480
  
 
481
  // draw the character
 
482
  {
 
483
    (void) w; (void) h;
 
484
    int x1= x- mi->xo*sfactor;
 
485
    int y1=  y+ mi->yo*sfactor;
 
486
    decode (x1, y1);
 
487
    y1--; // top-left origin to bottom-left origin conversion
 
488
    CGRect r = CGRectMake(x1,y1,mi->w,mi->h);
 
489
    CGContextSetShouldAntialias (context, true);
 
490
    CGContextSaveGState (context);
 
491
  //  cg_set_color (context, cur_fg);
 
492
    CGContextClipToMask (context, r, mi->img); 
 
493
    CGContextFillRect (context, r);
 
494
    CGContextRestoreGState (context);
 
495
  }  
 
496
}
 
497
 
 
498
/******************************************************************************
 
499
* Setting up and displaying xpm pixmaps
 
500
******************************************************************************/
 
501
 
 
502
 
 
503
 
 
504
static CGImageRef xpm_init(url file_name)
 
505
{
 
506
        tree t= xpm_load (file_name);
 
507
        
 
508
        // get main info
 
509
        int ok, i=0, j, k, w, h, c, b, x, y;
 
510
        string s= as_string (t[0]);
 
511
        skip_spaces (s, i);
 
512
        ok= read_int (s, i, w);
 
513
        skip_spaces (s, i);
 
514
        ok= read_int (s, i, h) && ok;
 
515
        skip_spaces (s, i);
 
516
        ok= read_int (s, i, c) && ok;
 
517
        skip_spaces (s, i);
 
518
        ok= read_int (s, i, b) && ok;
 
519
        if ((!ok) || (N(t)<(c+1)) || (c<=0)) {
 
520
          cerr << "File name= " << file_name << "\n";
 
521
          FAILED ("invalid xpm");
 
522
        }
 
523
        
 
524
        // setup colors
 
525
        string first_name;
 
526
        hashmap<string,color> pmcs;
 
527
        for (k=0; k<c; k++) {
 
528
                string s   = as_string (t[k+1]);
 
529
                string name= "";
 
530
                string def = "none";
 
531
                if (N(s)<b) i=N(s);
 
532
                else { name= s(0,b); i=b; }
 
533
                if (k==0) first_name= name;
 
534
                
 
535
                skip_spaces (s, i);
 
536
                if ((i<N(s)) && (s[i]=='s')) {
 
537
                        i++;
 
538
                        skip_spaces (s, i);
 
539
                        while ((i<N(s)) && (s[i]!=' ') && (s[i]!='\t')) i++;
 
540
                        skip_spaces (s, i);
 
541
                }
 
542
                if ((i<N(s)) && (s[i]=='c')) {
 
543
                        i++;
 
544
                        skip_spaces (s, i);
 
545
                        j=i;
 
546
                        while ((i<N(s)) && (s[i]!=' ') && (s[i]!='\t')) i++;
 
547
                        def= locase_all (s (j, i));
 
548
                }
 
549
                
 
550
                pmcs(name)= xpm_to_color(def);
 
551
        }
 
552
        CGContextRef ic = MyCreateBitmapContext(w,h);
 
553
        CGContextSetBlendMode(ic,kCGBlendModeCopy);
 
554
        // setup pixmap
 
555
        for (y=0; y<h; y++) {
 
556
                if (N(t)< (y+c+1)) s= "";
 
557
                else s= as_string (t[y+c+1]);
 
558
                for (x=0; x<w; x++) {
 
559
                        string name;
 
560
                        if (N(s)<(b*(x+1))) name= first_name;
 
561
                        else name= s (b*x, b*(x+1));
 
562
                        color col = pmcs[(pmcs->contains (name) ? name : first_name)];
 
563
      cg_set_color (ic, col);
 
564
                        CGContextFillRect (ic,CGRectMake(x,y,1,1));
 
565
                }
 
566
        }
 
567
        CGImageRef im = CGBitmapContextCreateImage (ic);
 
568
        CGContextRelease (ic);
 
569
        return im;
 
570
}
 
571
 
 
572
 
 
573
 
 
574
extern int char_clip;
 
575
 
 
576
CGImageRef 
 
577
cg_renderer_rep::xpm_image (url file_name) { 
 
578
  CGImageRef pxm= NULL;
 
579
  cg_image mi= images [as_string (file_name)];
 
580
  if (is_nil (mi)) {    
 
581
          pxm = xpm_init(file_name);
 
582
    cg_image mi2 (pxm, 0, 0, CGImageGetWidth (pxm), CGImageGetHeight (pxm));
 
583
    mi= mi2;
 
584
    images (as_string (file_name))= mi2;
 
585
    CGImageRelease(pxm);
 
586
  } else pxm= mi->img;
 
587
  return pxm;
 
588
}
 
589
 
 
590
void
 
591
cg_renderer_rep::xpm (url file_name, SI x, SI y) {
 
592
  y -= pixel; // counter balance shift in draw_clipped
 
593
  CGImageRef image = xpm_image (file_name);
 
594
  ASSERT (sfactor == 1, "shrinking factor should be 1");
 
595
  int w = CGImageGetWidth(image);
 
596
  int h = CGImageGetHeight(image);
 
597
  int old_clip= char_clip;
 
598
  char_clip = true;
 
599
  draw_clipped (image, w, h, x, y);
 
600
  char_clip = old_clip;
 
601
}
 
602
 
 
603
/******************************************************************************
 
604
 * main coregraphics renderer
 
605
 ******************************************************************************/
 
606
 
 
607
static cg_renderer_rep* the_renderer= NULL;
 
608
 
 
609
cg_renderer_rep*
 
610
the_cg_renderer () {
 
611
        if (!the_renderer) the_renderer= tm_new <cg_renderer_rep> ();
 
612
        return the_renderer;
 
613
}