~ubuntu-branches/ubuntu/trusty/gnustep-back/trusty

« back to all changes in this revision

Viewing changes to Source/cairo/CairoGState.m

  • Committer: Bazaar Package Importer
  • Author(s): Hubert Chathi
  • Date: 2008-07-02 17:19:03 UTC
  • mfrom: (1.2.5 upstream) (4.1.1 lenny)
  • Revision ID: james.westby@ubuntu.com-20080702171903-n1potlcotage8xy0
Upload to unstable.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
 * CairoGState.m
3
 
 
4
 
 * Copyright (C) 2003 Free Software Foundation, Inc.
5
 
 * August 31, 2003
6
 
 * Written by Banlu Kemiyatorn <object at gmail dot com>
7
 
 * Rewrite: Fred Kiefer <fredkiefer@gmx.de>
8
 
 * Date: Jan 2006
9
 
 *
10
 
 * This library is free software; you can redistribute it and/or
11
 
 * modify it under the terms of the GNU Library General Public
12
 
 * License as published by the Free Software Foundation; either
13
 
 * version 2 of the License, or (at your option) any later version.
14
 
 
15
 
 * This library is distributed in the hope that it will be useful,
16
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18
 
 * Library General Public License for more details.
19
 
 
20
 
 * You should have received a copy of the GNU Library General Public
21
 
 * License along with this library; if not, write to the Free
22
 
 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111 USA.
23
 
 */
 
2
   CairoGState.m
 
3
 
 
4
   Copyright (C) 2003 Free Software Foundation, Inc.
 
5
 
 
6
   August 31, 2003
 
7
   Written by Banlu Kemiyatorn <object at gmail dot com>
 
8
   Rewrite: Fred Kiefer <fredkiefer@gmx.de>
 
9
   Date: Jan 2006
 
10
 
 
11
   This file is part of GNUstep.
 
12
 
 
13
   This library is free software; you can redistribute it and/or
 
14
   modify it under the terms of the GNU Lesser General Public
 
15
   License as published by the Free Software Foundation; either
 
16
   version 2 of the License, or (at your option) any later version.
 
17
 
 
18
   This library is distributed in the hope that it will be useful,
 
19
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
20
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
21
   Lesser General Public License for more details.
 
22
 
 
23
   You should have received a copy of the GNU Lesser General Public
 
24
   License along with this library; see the file COPYING.LIB.
 
25
   If not, see <http://www.gnu.org/licenses/> or write to the 
 
26
   Free Software Foundation, 51 Franklin Street, Fifth Floor, 
 
27
   Boston, MA 02110-1301, USA.
 
28
*/
24
29
 
25
30
#include <AppKit/NSAffineTransform.h>
26
31
#include <AppKit/NSBezierPath.h>
67
72
    NSZoneFree(NSDefaultMallocZone(), _base); \
68
73
  }
69
74
 
 
75
static float floatFromUserSpace(NSAffineTransform *ctm, float f)
 
76
{
 
77
  NSSize s = {f, f};
 
78
 
 
79
  if (ctm)
 
80
    {
 
81
      s = [ctm transformSize: s];
 
82
      f = (((s.width > 0.0) ? s.width : -s.width) + 
 
83
           ((s.height > 0.0) ? s.height : -s.height)) / 2;
 
84
    }
 
85
  return f;
 
86
}
 
87
 
 
88
static float floatToUserSpace(NSAffineTransform *ctm, float f)
 
89
{
 
90
  NSAffineTransform *ictm;
 
91
  
 
92
  ictm = [ctm copyWithZone: GSObjCZone(ctm)];
 
93
  [ictm invert];
 
94
  f = floatFromUserSpace(ictm, f);
 
95
  RELEASE(ictm);
 
96
  return f;
 
97
}
 
98
 
 
99
 
 
100
 
70
101
@implementation CairoGState 
71
102
 
72
103
+ (void) initialize
91
122
{
92
123
  CairoGState *copy = (CairoGState *)[super copyWithZone: zone];
93
124
 
 
125
  RETAIN(_surface);
 
126
 
94
127
  if (_ct)
95
128
    {
96
 
      cairo_path_t *cpath;
97
129
      cairo_status_t status;
98
 
      cairo_matrix_t local_matrix;
99
130
 
100
131
      // FIXME: Need some way to do a copy
101
 
      //cairo_copy(copy->_ct, _ct);
 
132
      // but there isnt anything like copy->_ct = cairo_copy(_ct);
102
133
      copy->_ct = cairo_create(cairo_get_target(_ct));
103
 
      cairo_get_matrix(_ct, &local_matrix);
104
 
      cairo_set_matrix(copy->_ct, &local_matrix);
105
 
      cpath = cairo_copy_path(_ct);
106
 
      cairo_append_path(copy->_ct, cpath);
107
 
      cairo_path_destroy(cpath);
108
 
      
109
 
      cairo_set_operator(copy->_ct, cairo_get_operator(_ct));
110
 
      cairo_set_source(copy->_ct, cairo_get_source(_ct));
111
 
      cairo_set_tolerance(copy->_ct, cairo_get_tolerance(_ct));
112
 
      cairo_set_antialias(copy->_ct, cairo_get_antialias(_ct));
113
 
      cairo_set_line_width(copy->_ct, cairo_get_line_width(_ct));
114
 
      cairo_set_line_cap(copy->_ct, cairo_get_line_cap(_ct));
115
 
      cairo_set_line_join(copy->_ct, cairo_get_line_join(_ct));
116
 
      cairo_set_miter_limit(copy->_ct, cairo_get_miter_limit(_ct));
117
 
      // FIXME: In cairo 1.2.4 there is no way get the dash or copy it.
118
 
      // There also is no way to get the current clipping path
119
 
 
120
134
      status = cairo_status(copy->_ct);
121
135
      if (status != CAIRO_STATUS_SUCCESS)
122
136
        {
123
 
          NSLog(@"Cairo status %s in copy", cairo_status_to_string(status));
124
 
        }
 
137
          NSLog(@"Cairo status '%s' in copy", cairo_status_to_string(status));
 
138
          copy->_ct = NULL;
 
139
        }
 
140
      else
 
141
        {
 
142
          cairo_path_t *cpath;
 
143
          cairo_matrix_t local_matrix;
 
144
#if CAIRO_VERSION > CAIRO_VERSION_ENCODE(1, 4, 0)
 
145
          cairo_rectangle_list_t *clip_rects;
 
146
          int   num_dashes;
 
147
#endif
 
148
 
 
149
          cairo_get_matrix(_ct, &local_matrix);
 
150
          cairo_set_matrix(copy->_ct, &local_matrix);
 
151
          status = cairo_status(copy->_ct);
 
152
          if (status != CAIRO_STATUS_SUCCESS)
 
153
            {
 
154
              NSLog(@"Cairo status '%s' in set matrix", cairo_status_to_string(status));
 
155
            }
 
156
 
 
157
          cpath = cairo_copy_path(_ct);
 
158
          status = cpath->status;
 
159
          if (status != CAIRO_STATUS_SUCCESS)
 
160
            {
 
161
              /*
 
162
                Due to an interesting programming concept in cairo this does not
 
163
                mean that an error has occured. It may as well just be that the 
 
164
                old path had no elements. 
 
165
                At least in cairo 1.4.10 (See file cairo-path.c, line 379).
 
166
              */
 
167
              // NSLog(@"Cairo status '%s' in copy path", cairo_status_to_string(status));
 
168
            }
 
169
          else
 
170
            {
 
171
              cairo_append_path(copy->_ct, cpath);
 
172
            }
 
173
          cairo_path_destroy(cpath);
 
174
          
 
175
          cairo_set_operator(copy->_ct, cairo_get_operator(_ct));
 
176
          cairo_set_source(copy->_ct, cairo_get_source(_ct));
 
177
          cairo_set_tolerance(copy->_ct, cairo_get_tolerance(_ct));
 
178
          cairo_set_antialias(copy->_ct, cairo_get_antialias(_ct));
 
179
          cairo_set_line_width(copy->_ct, cairo_get_line_width(_ct));
 
180
          cairo_set_line_cap(copy->_ct, cairo_get_line_cap(_ct));
 
181
          cairo_set_line_join(copy->_ct, cairo_get_line_join(_ct));
 
182
          cairo_set_miter_limit(copy->_ct, cairo_get_miter_limit(_ct));
 
183
 
 
184
#if CAIRO_VERSION > CAIRO_VERSION_ENCODE(1, 4, 0)
 
185
          // In cairo 1.4 there is a way get the dash.
 
186
          num_dashes = cairo_get_dash_count(_ct);
 
187
          if (num_dashes != 0)
 
188
            {
 
189
              double dash_offset;
 
190
              GS_BEGINITEMBUF(dashes, num_dashes, double);
 
191
 
 
192
              cairo_get_dash(_ct, dashes, &dash_offset);
 
193
              cairo_set_dash (copy->_ct, dashes, num_dashes, dash_offset);
 
194
              GS_ENDITEMBUF();
 
195
            }
 
196
 
 
197
          // In cairo 1.4 there also is a way to get the current clipping path
 
198
          clip_rects = cairo_copy_clip_rectangle_list(_ct);
 
199
          status = clip_rects->status;
 
200
          if (status != CAIRO_STATUS_SUCCESS)
 
201
            {
 
202
              NSLog(@"Cairo status '%s' in copy clip", cairo_status_to_string(status));
 
203
            }
 
204
          else
 
205
            {
 
206
              int i;
 
207
 
 
208
              for (i = 0; i < clip_rects->num_rectangles; i++)
 
209
                {
 
210
                  cairo_rectangle_t rect = clip_rects->rectangles[i];
 
211
                  NSSize size = [_surface size];
 
212
 
 
213
                  cairo_rectangle(copy->_ct, rect.x, 
 
214
#if CAIRO_VERSION > CAIRO_VERSION_ENCODE(1, 6, 0)
 
215
                                  rect.y, 
 
216
#else
 
217
                                  // This strange computation is due to the device offset. 
 
218
                                  rect.y + 2*(offset.y - size.height), 
 
219
#endif
 
220
                                  rect.width, rect.height);
 
221
                  cairo_clip(copy->_ct);
 
222
                }
 
223
            }
 
224
          cairo_rectangle_list_destroy(clip_rects);
 
225
#endif
 
226
        }
125
227
    }
126
228
 
127
 
  RETAIN(_surface);
128
 
 
129
229
  return copy;
130
230
}
131
231
 
132
 
- (void) GSCurrentDevice: (void **)device: (int *)x : (int *)y
 
232
- (void) GSCurrentSurface: (CairoSurface **)surface: (int *)x : (int *)y
133
233
{
134
234
  if (x)
135
235
    *x = offset.x;
136
236
  if (y)
137
237
    *y = offset.y;
138
 
  if (device)
 
238
  if (surface)
139
239
    {
140
 
      if (_surface)
141
 
        {
142
 
          *device = _surface->gsDevice;
143
 
        }
144
 
      else
145
 
        {
146
 
          *device = NULL;
147
 
        }
 
240
      *surface = _surface;
148
241
    }
149
242
}
150
243
 
151
 
- (void) GSSetDevice: (void *)device : (int)x : (int)y
 
244
- (void) GSSetSurface: (CairoSurface *)surface : (int)x : (int)y
152
245
{
153
 
  DESTROY(_surface);
154
 
  _surface = [[CairoSurface alloc] initWithDevice: device];
 
246
  ASSIGN(_surface, surface);
155
247
  [self setOffset: NSMakePoint(x, y)];
156
248
  [self DPSinitgraphics];
157
249
}
158
250
 
159
251
- (void) setOffset: (NSPoint)theOffset
160
252
{
161
 
  NSSize size = {0, 0};
162
 
 
163
253
  if (_surface != nil)
164
254
    {
165
 
      size = [_surface size];
 
255
      NSSize size = [_surface size];
 
256
 
 
257
      cairo_surface_set_device_offset([_surface surface], -theOffset.x, 
 
258
                                      theOffset.y - size.height);
166
259
    }
167
260
  [super setOffset: theOffset];
168
 
  cairo_surface_set_device_offset([_surface surface], -theOffset.x, 
169
 
                                  theOffset.y - size.height);
 
261
}
 
262
 
 
263
- (void) showPage
 
264
{
 
265
  if (_ct)
 
266
    {
 
267
      cairo_show_page(_ct);
 
268
    }
170
269
}
171
270
 
172
271
/*
203
302
  NSPoint p;
204
303
 
205
304
  p = [path currentPoint];
206
 
  cairo_move_to(_ct, p.x, p.y);
 
305
  cairo_move_to(_ct, floorf(p.x), floorf(p.y));
207
306
}
208
307
 
209
308
- (void) DPScharpath: (const char *)s : (int)b
217
316
      c[b] = 0;
218
317
      cairo_text_path(_ct, c);
219
318
      GS_ENDITEMBUF();
 
319
      if (cairo_status(_ct) == CAIRO_STATUS_SUCCESS)
 
320
        {
 
321
          cairo_path_t *cpath;
 
322
          cairo_path_data_t *data;
 
323
          int i;
 
324
         
 
325
          cpath = cairo_copy_path(_ct);
 
326
          
 
327
          for (i = 0; i < cpath->num_data; i += cpath->data[i].header.length) 
 
328
            {
 
329
              data = &cpath->data[i];
 
330
              switch (data->header.type) 
 
331
                {
 
332
                  case CAIRO_PATH_MOVE_TO:
 
333
                    [path moveToPoint: NSMakePoint(data[1].point.x, data[1].point.y)];
 
334
                    break;
 
335
                  case CAIRO_PATH_LINE_TO:
 
336
                    [path lineToPoint: NSMakePoint(data[1].point.x, data[1].point.y)];
 
337
                    break;
 
338
                  case CAIRO_PATH_CURVE_TO:
 
339
                    [path curveToPoint: NSMakePoint(data[3].point.x, data[3].point.y) 
 
340
                          controlPoint1: NSMakePoint(data[1].point.x, data[1].point.y)
 
341
                          controlPoint2: NSMakePoint(data[2].point.x, data[2].point.y)];
 
342
                    break;
 
343
                  case CAIRO_PATH_CLOSE_PATH:
 
344
                    [path closePath];
 
345
                    break;
 
346
                }
 
347
            }
 
348
          cairo_path_destroy(cpath);
 
349
        }
220
350
    }
221
351
}
222
352
 
224
354
{
225
355
  if (_ct)
226
356
    {
227
 
      [self _setPoint];
 
357
      cairo_matrix_t saved_matrix;
 
358
      cairo_matrix_t local_matrix;
 
359
      NSPoint        p = [path currentPoint];
 
360
 
 
361
      cairo_get_matrix(_ct, &saved_matrix);
 
362
 
 
363
      cairo_matrix_init_scale(&local_matrix, 1, 1);
 
364
      cairo_matrix_translate(&local_matrix, 0, [_surface size].height-(p.y*2));
 
365
      cairo_set_matrix(_ct, &local_matrix);
 
366
 
 
367
      cairo_move_to(_ct, p.x, p.y);
228
368
      cairo_show_text(_ct, s);
 
369
 
 
370
      cairo_set_matrix(_ct, &saved_matrix);
229
371
    }
230
372
}
231
373
 
250
392
{
251
393
  if (_ct)
252
394
    {
 
395
      size = floatFromUserSpace(ctm, size);
253
396
      cairo_set_font_size(_ct, size);
254
397
    }
255
398
}
272
415
{
273
416
  if (_ct)
274
417
    {
 
418
      cairo_matrix_t local_matrix;
 
419
      NSAffineTransformStruct   matrix = [ctm transformStruct];
 
420
 
275
421
      [self _setPoint];
 
422
      // FIXME: Hack to get font in rotated view working
 
423
      cairo_save(_ct);
 
424
      cairo_matrix_init(&local_matrix, matrix.m11, matrix.m12, matrix.m21,
 
425
                        matrix.m22, 0, 0);
 
426
      cairo_transform(_ct, &local_matrix);
 
427
      // Undo the 
 
428
      cairo_matrix_init_scale(&local_matrix, 1, -1);
 
429
      cairo_matrix_translate(&local_matrix, 0,  -[_surface size].height);
 
430
      cairo_transform(_ct, &local_matrix);
 
431
 
276
432
      [(CairoFontInfo *)font drawGlyphs: glyphs
277
 
                        length: length
278
 
                        on: _ct];
 
433
                        length: length
 
434
                        on: _ct];
 
435
      cairo_restore(_ct);
279
436
    }
280
437
}
281
438
 
302
459
  status = cairo_status(_ct);
303
460
  if (status != CAIRO_STATUS_SUCCESS)
304
461
    {
305
 
      NSLog(@"Cairo status %s in DPSinitgraphics", cairo_status_to_string(status));
 
462
      NSLog(@"Cairo status '%s' in DPSinitgraphics", cairo_status_to_string(status));
306
463
      _ct = NULL;
307
464
      return;
308
465
    }
322
479
  cairo_set_line_width(_ct, 1.0);
323
480
  cairo_set_operator(_ct, CAIRO_OPERATOR_OVER);
324
481
  cairo_new_path(_ct);
 
482
 
 
483
  _strokeadjust = 1;
325
484
}
326
485
 
327
486
- (void) DPScurrentflat: (float *)flatness
328
487
{
329
488
  if (_ct)
330
489
    {
331
 
      *flatness = cairo_get_tolerance(_ct);
 
490
      *flatness = (float)cairo_get_tolerance(_ct);
 
491
      *flatness = floatToUserSpace(ctm, *flatness);
332
492
    }
333
493
}
334
494
 
392
552
{
393
553
  if (_ct)
394
554
    {
395
 
      *width = cairo_get_line_width(_ct);
 
555
      *width = (float)cairo_get_line_width(_ct);
 
556
      *width = floatToUserSpace(ctm, *width);
396
557
    }
397
558
}
398
559
 
400
561
{
401
562
  if (_ct)
402
563
    {
403
 
      *limit = cairo_get_miter_limit(_ct);
 
564
      *limit = (float)cairo_get_miter_limit(_ct);
 
565
      *limit = floatToUserSpace(ctm, *limit);
404
566
    }
405
567
}
406
568
 
414
576
  if (_ct)
415
577
    {
416
578
      GS_BEGINITEMBUF(dpat, size, double);
417
 
      double doffset = foffset;
 
579
      double doffset = (double)floatFromUserSpace(ctm, foffset);
418
580
      int i;
419
581
 
420
582
      i = size;
421
583
      while (i)
422
584
        {
423
 
          i--;
424
 
          dpat[i] = pat[i];
425
 
        }
426
 
      // FIXME: There may be a difference in concept as some dashes look wrong
 
585
          i--;
 
586
          // FIXME: When using the correct values, some dashes look wrong
 
587
          dpat[i] = (double)floatFromUserSpace(ctm, pat[i]) * 1.4;
 
588
        }
427
589
      cairo_set_dash(_ct, dpat, size, doffset);
428
590
      GS_ENDITEMBUF();
429
591
    }
434
596
  [super DPSsetflat: flatness];
435
597
  if (_ct)
436
598
    {
437
 
      cairo_set_tolerance(_ct, flatness);
 
599
      cairo_set_tolerance(_ct, floatFromUserSpace(ctm, flatness));
438
600
    }
439
601
}
440
602
 
458
620
{
459
621
  if (_ct)
460
622
    {
461
 
      cairo_set_line_width(_ct, width);
 
623
      cairo_set_line_width(_ct, floatFromUserSpace(ctm, width));
462
624
    }
463
625
}
464
626
 
466
628
{
467
629
  if (_ct)
468
630
    {
469
 
      cairo_set_miter_limit(_ct, limit);
 
631
      cairo_set_miter_limit(_ct, floatFromUserSpace(ctm, limit));
470
632
    }
471
633
}
472
634
 
473
635
- (void) DPSsetstrokeadjust: (int)b
474
636
{
475
 
    // FIXME
 
637
  _strokeadjust = b;
476
638
}
477
639
 
478
640
/*
479
641
 * Path operations
480
642
 */
481
643
 
482
 
- (void) _setPath
 
644
- (void) _adjustPath: (float)offs
 
645
{
 
646
  unsigned            count = [path elementCount];
 
647
  NSBezierPathElement type;
 
648
  NSPoint             points[3] = {{0.0, 0.0}, {0.0, 0.0}, {0.0, 0.0}};
 
649
  NSPoint             last_points[3] = {{0.0, 0.0}, {0.0, 0.0}, {0.0, 0.0}};
 
650
  unsigned            i;
 
651
  int                 index, last_index;
 
652
 
 
653
  for (i = 0; i < count; i++)
 
654
    {
 
655
      type = [path elementAtIndex:i associatedPoints:points];
 
656
 
 
657
      if (type == NSCurveToBezierPathElement) break;
 
658
 
 
659
      points[0].x = floorf(points[0].x) + offs;
 
660
      points[0].y = floorf(points[0].y) + offs;
 
661
 
 
662
      index = i;
 
663
      last_index = i - 1;
 
664
 
 
665
      if (type == NSClosePathBezierPathElement)
 
666
        {
 
667
          index = 0;
 
668
          [path elementAtIndex:0 associatedPoints:points];
 
669
          if (fabs(last_points[0].x - points[0].x) < 1.0)
 
670
            {
 
671
              last_points[0].x = floorf(last_points[0].x) + offs;
 
672
              points[0].x = last_points[0].x;
 
673
            }
 
674
          else if (fabs(last_points[0].y - points[0].y) < 1.0)
 
675
            {
 
676
              last_points[0].y = floorf(last_points[0].y) + offs;
 
677
              points[0].y = last_points[0].y;
 
678
            }
 
679
          else
 
680
            {
 
681
              index = -1;
 
682
            }
 
683
        }
 
684
      else if (fabs(last_points[0].x - points[0].x) < 1.0)
 
685
        { // Vertical path
 
686
          points[0].x = floorf(points[0].x) + offs;
 
687
          points[0].y = floorf(points[0].y);
 
688
          if (type == NSLineToBezierPathElement)
 
689
            {
 
690
              last_points[0].x = points[0].x;
 
691
            }
 
692
        }
 
693
      else if (fabs(last_points[0].y - points[0].y) < 1.0)
 
694
        { // Horizontal path
 
695
          points[0].x = floorf(points[0].x);
 
696
          points[0].y = floorf(points[0].y) + offs;
 
697
          if (type == NSLineToBezierPathElement)
 
698
            {
 
699
              last_points[0].y = points[0].y;
 
700
            }
 
701
        }
 
702
 
 
703
      // Save adjusted values into NSBezierPath
 
704
      if (index >= 0)
 
705
        [path setAssociatedPoints:points atIndex:index];
 
706
      if (last_index >= 0)
 
707
        [path setAssociatedPoints:last_points atIndex:last_index];
 
708
 
 
709
      last_points[0].x = points[0].x;
 
710
      last_points[0].y = points[0].y;
 
711
    }
 
712
}
 
713
 
 
714
- (void) _setPath: (BOOL)fillOrClip
483
715
{
484
716
  unsigned count = [path elementCount];
485
717
  unsigned i;
486
718
  SEL elmsel = @selector(elementAtIndex:associatedPoints:);
487
719
  IMP elmidx = [path methodForSelector: elmsel];
488
720
 
 
721
  if (_strokeadjust)
 
722
    {
 
723
      float offs;
 
724
 
 
725
      if ((remainderf(cairo_get_line_width(_ct), 2.0) == 0.0)
 
726
          || fillOrClip == YES)
 
727
        offs = 0.0;
 
728
      else
 
729
        offs = 0.5;
 
730
 
 
731
      [self _adjustPath:offs];
 
732
    }
 
733
 
 
734
  // reset current cairo path
 
735
  cairo_new_path(_ct);
489
736
  for (i = 0; i < count; i++) 
490
737
    {
491
738
      NSBezierPathElement type;
494
741
      type = (NSBezierPathElement)(*elmidx)(path, elmsel, i, points);
495
742
      switch(type) 
496
743
        {
497
 
          case NSMoveToBezierPathElement:
498
 
            cairo_move_to(_ct, points[0].x, points[0].y);
499
 
            break;
500
 
          case NSLineToBezierPathElement:
501
 
            cairo_line_to(_ct, points[0].x, points[0].y);
502
 
            break;
503
 
          case NSCurveToBezierPathElement:
504
 
            cairo_curve_to(_ct, points[0].x, points[0].y, 
505
 
                           points[1].x, points[1].y, 
506
 
                           points[2].x, points[2].y);
507
 
            break;
508
 
          case NSClosePathBezierPathElement:
509
 
            cairo_close_path(_ct);
510
 
            break;
511
 
          default:
512
 
            break;
513
 
        }
 
744
          case NSMoveToBezierPathElement:
 
745
            cairo_move_to(_ct, points[0].x, points[0].y);
 
746
            break;
 
747
          case NSLineToBezierPathElement:
 
748
            cairo_line_to(_ct, points[0].x, points[0].y);
 
749
            break;
 
750
          case NSCurveToBezierPathElement:
 
751
            cairo_curve_to(_ct, points[0].x, points[0].y, 
 
752
                           points[1].x, points[1].y, 
 
753
                           points[2].x, points[2].y);
 
754
            break;
 
755
          case NSClosePathBezierPathElement:
 
756
            cairo_close_path(_ct);
 
757
            break;
 
758
          default:
 
759
            break;
 
760
        }
514
761
    }
515
762
}
516
763
 
518
765
{
519
766
  if (_ct)
520
767
    {
521
 
      [self _setPath];
 
768
      [self _setPath:YES];
522
769
      cairo_clip(_ct);
523
 
    }
 
770
     }
524
771
}
525
772
 
526
773
- (void) DPSeoclip
527
774
{
528
775
  if (_ct)
529
776
    {
530
 
      [self _setPath];
 
777
      [self _setPath:YES];
531
778
      cairo_set_fill_rule(_ct, CAIRO_FILL_RULE_EVEN_ODD);
532
779
      cairo_clip(_ct);
533
780
      cairo_set_fill_rule(_ct, CAIRO_FILL_RULE_WINDING);
538
785
{
539
786
  if (_ct)
540
787
    {
541
 
      [self _setPath];
 
788
      [self _setPath:YES];
542
789
      cairo_set_fill_rule(_ct, CAIRO_FILL_RULE_EVEN_ODD);
543
790
      cairo_fill(_ct);
544
791
      cairo_set_fill_rule(_ct, CAIRO_FILL_RULE_WINDING);
545
792
    }
 
793
  [self DPSnewpath];
546
794
}
547
795
 
548
796
- (void) DPSfill
549
797
{
550
798
  if (_ct)
551
799
    {
552
 
      [self _setPath];
 
800
      [self _setPath:YES];
553
801
      cairo_fill(_ct);
554
802
    }
 
803
  [self DPSnewpath];
555
804
}
556
805
 
557
806
- (void) DPSinitclip
566
815
{
567
816
  if (_ct)
568
817
    {
569
 
      [self _setPath];
 
818
      [self _setPath:NO];
570
819
      cairo_stroke(_ct);
571
820
    }
 
821
  [self DPSnewpath];
572
822
}
573
823
 
574
824
- (NSDictionary *) GSReadRect: (NSRect)r
582
832
  cairo_surface_t *surface;
583
833
  cairo_surface_t *isurface;
584
834
  cairo_t *ct;
 
835
  cairo_status_t status;
585
836
  int size;
586
837
  int i;
587
838
  NSMutableData *data;
624
875
 
625
876
  surface = cairo_get_target(_ct);
626
877
  isurface = cairo_image_surface_create_for_data(cdata, format, ix, iy, 4*ix);
 
878
  status = cairo_surface_status(isurface);
 
879
  if (status != CAIRO_STATUS_SUCCESS)
 
880
    {
 
881
      NSLog(@"Cairo status '%s' in GSReadRect", cairo_status_to_string(status));
 
882
      return nil;
 
883
    }
 
884
 
627
885
  ct = cairo_create(isurface);
 
886
  status = cairo_status(ct);
 
887
  if (status != CAIRO_STATUS_SUCCESS)
 
888
    {
 
889
      NSLog(@"Cairo status '%s' in GSReadRect", cairo_status_to_string(status));
 
890
      cairo_surface_destroy(isurface);
 
891
      return nil;
 
892
    }
628
893
 
629
894
  if (_surface != nil)
630
895
    {
634
899
    {
635
900
      ssize = NSMakeSize(0, 0);
636
901
    }
637
 
  cairo_set_source_surface(ct, surface, -r.origin.x, -ssize.height + r.size.height + r.origin.y);
 
902
  cairo_set_source_surface(ct, surface, -r.origin.x, 
 
903
                           -ssize.height + r.size.height + r.origin.y);
638
904
  cairo_rectangle(ct, 0, 0, ix, iy);
639
905
  cairo_paint(ct);
640
906
  cairo_destroy(ct);
733
999
  unsigned int pixels = pixelsHigh * pixelsWide;
734
1000
  unsigned char *rowData;
735
1001
  cairo_matrix_t local_matrix;
 
1002
  cairo_status_t status;
736
1003
 
737
1004
  if (!_ct)
738
1005
    {
739
 
        return;
 
1006
      return;
740
1007
    }
741
1008
 
742
1009
  if (isPlanar || !([colorSpaceName isEqualToString: NSDeviceRGBColorSpace] ||
766
1033
  switch (bitsPerPixel)
767
1034
    {
768
1035
    case 32:
 
1036
      tmp = objc_malloc(pixels * 4);
 
1037
      if (!tmp)
 
1038
        {
 
1039
          NSLog(@"Could not allocate drawing space for image");
 
1040
          return;
 
1041
        }
 
1042
 
769
1043
      rowData = (unsigned char *)data[0];
770
 
      tmp = objc_malloc(pixels * 4);
771
1044
      index = 0;
772
1045
 
773
1046
      for (i = 0; i < pixelsHigh; i++)
774
1047
        {
775
 
          unsigned char *d = rowData;
 
1048
          unsigned char *d = rowData;
776
1049
 
777
 
          for (j = 0; j < pixelsWide; j++)
778
 
          {
 
1050
          for (j = 0; j < pixelsWide; j++)
 
1051
            {
779
1052
#if GS_WORDS_BIGENDIAN
780
 
              tmp[index++] = d[3];
781
 
              tmp[index++] = d[0];
782
 
              tmp[index++] = d[1];
783
 
              tmp[index++] = d[2];
 
1053
              tmp[index++] = d[3];
 
1054
              tmp[index++] = d[0];
 
1055
              tmp[index++] = d[1];
 
1056
              tmp[index++] = d[2];
784
1057
#else
785
 
              tmp[index++] = d[2];
786
 
              tmp[index++] = d[1];
787
 
              tmp[index++] = d[0];
788
 
              tmp[index++] = d[3];
 
1058
              tmp[index++] = d[2];
 
1059
              tmp[index++] = d[1];
 
1060
              tmp[index++] = d[0];
 
1061
              tmp[index++] = d[3];
789
1062
#endif 
790
 
              d += 4;
791
 
            }
792
 
          rowData += bytesPerRow;
793
 
        }
 
1063
              d += 4;
 
1064
            }
 
1065
          rowData += bytesPerRow;
 
1066
        }
794
1067
      format = CAIRO_FORMAT_ARGB32;
795
1068
      break;
796
1069
    case 24:
 
1070
      tmp = objc_malloc(pixels * 4);
 
1071
      if (!tmp)
 
1072
        {
 
1073
          NSLog(@"Could not allocate drawing space for image");
 
1074
          return;
 
1075
        }
 
1076
 
797
1077
      rowData = (unsigned char *)data[0];
798
 
      tmp = objc_malloc(pixels * 4);
799
1078
      index = 0;
800
1079
 
801
1080
      for (i = 0; i < pixelsHigh; i++)
802
1081
        {
803
 
          unsigned char *d = rowData;
 
1082
          unsigned char *d = rowData;
804
1083
 
805
 
          for (j = 0; j < pixelsWide; j++)
806
 
            {
 
1084
          for (j = 0; j < pixelsWide; j++)
 
1085
            {
807
1086
#if GS_WORDS_BIGENDIAN
808
 
              tmp[index++] = 0;
809
 
              tmp[index++] = d[0];
810
 
              tmp[index++] = d[1];
811
 
              tmp[index++] = d[2];
 
1087
              tmp[index++] = 0;
 
1088
              tmp[index++] = d[0];
 
1089
              tmp[index++] = d[1];
 
1090
              tmp[index++] = d[2];
812
1091
#else
813
 
              tmp[index++] = d[2];
814
 
              tmp[index++] = d[1];
815
 
              tmp[index++] = d[0];
816
 
              tmp[index++] = 0;
 
1092
              tmp[index++] = d[2];
 
1093
              tmp[index++] = d[1];
 
1094
              tmp[index++] = d[0];
 
1095
              tmp[index++] = 0;
817
1096
#endif
818
 
              d += 3;
819
 
            }
820
 
          rowData += bytesPerRow;
821
 
        }
 
1097
              d += 3;
 
1098
            }
 
1099
          rowData += bytesPerRow;
 
1100
        }
822
1101
      format = CAIRO_FORMAT_RGB24;
823
1102
      break;
824
1103
    default:
831
1110
                                                pixelsWide,
832
1111
                                                pixelsHigh,
833
1112
                                                pixelsWide * 4);
834
 
 
835
 
  if (cairo_surface_status(surface))
 
1113
  status = cairo_surface_status(surface);
 
1114
  if (status != CAIRO_STATUS_SUCCESS)
836
1115
    {
837
 
      NSLog(@"Image surface could not be created");
 
1116
      NSLog(@"Cairo status '%s' in DPSimage", cairo_status_to_string(status));
838
1117
      if (tmp)
839
1118
        {
840
 
          objc_free(tmp);
841
 
        }
 
1119
          objc_free(tmp);
 
1120
        }
842
1121
 
843
1122
      return;
844
1123
    }
914
1193
      // This is almost a rectclip::::, but the path stays unchanged.
915
1194
      path = [NSBezierPath bezierPathWithRect: aRect];
916
1195
      [path transformUsingAffineTransform: ctm];
917
 
      [self _setPath];
 
1196
      [self _setPath:YES];
 
1197
      cairo_clip(_ct);
 
1198
      cairo_paint(_ct);
 
1199
      cairo_restore(_ct);
918
1200
      path = oldPath;
919
 
      cairo_clip(_ct);
920
 
 
921
 
      cairo_paint(_ct);
922
 
      cairo_restore(_ct);
923
1201
    }
924
1202
}
925
1203
 
926
1204
- (void) compositeGState: (CairoGState *)source 
927
 
                fromRect: (NSRect)aRect 
928
 
                 toPoint: (NSPoint)aPoint 
929
 
                      op: (NSCompositingOperation)op
930
 
                fraction: (float)delta
 
1205
                fromRect: (NSRect)aRect 
 
1206
                 toPoint: (NSPoint)aPoint 
 
1207
                      op: (NSCompositingOperation)op
 
1208
                fraction: (float)delta
931
1209
{
932
1210
  cairo_surface_t *src;
933
1211
  double minx, miny;
936
1214
  NSSize ssize;
937
1215
  cairo_pattern_t *cpattern;
938
1216
  cairo_matrix_t local_matrix;
 
1217
  BOOL copyOnSelf = NO;
939
1218
 
940
1219
  if (!_ct || !source->_ct)
941
1220
    {
942
1221
      return;
943
1222
    }
944
1223
 
945
 
  cairo_save(_ct);
946
 
  cairo_new_path(_ct);
947
 
  _set_op(_ct, op);
948
1224
 
 
1225
  /* 
 
1226
   * we check if we copy on ourself, if that's the case
 
1227
   * we'll use the groups trick...
 
1228
   */
 
1229
 
949
1230
  src = cairo_get_target(source->_ct);
950
1231
  if (src == cairo_get_target(_ct))
951
1232
    {
952
 
/*
953
1233
      NSRect targetRect;
954
1234
 
955
1235
      targetRect.origin = aPoint;
956
1236
      targetRect.size = aRect.size;
957
1237
 
958
1238
      if (!NSIsEmptyRect(NSIntersectionRect(aRect, targetRect)))
959
 
        {
960
 
          NSLog(@"Copy onto self");
961
 
          NSLog(NSStringFromRect(aRect));
962
 
          NSLog(NSStringFromPoint(aPoint));
963
 
          NSLog(@"src %p(%p,%@) des %p(%p,%@)", 
964
 
                source,cairo_get_target(source->_ct),NSStringFromSize([source->_surface size]),
965
 
                self,cairo_get_target(_ct),NSStringFromSize([_surface size]));
966
 
        }
967
 
*/
 
1239
        {
 
1240
          copyOnSelf = YES;
 
1241
        }
968
1242
    }
969
1243
 
970
 
/*
971
 
  With this bit of code enable scrolling works correctly, but images in cells get displayed wrongly.
972
 
  if (viewIsFlipped)
 
1244
  cairo_save(_ct);
 
1245
 
 
1246
  if (copyOnSelf) cairo_push_group(_ct);
 
1247
 
 
1248
  cairo_new_path(_ct);
 
1249
  _set_op(_ct, op);
 
1250
  
 
1251
  if (viewIsFlipped && !copyOnSelf)
973
1252
    {
974
 
      aPoint.y += NSHeight(aRect);
 
1253
      aPoint.y -= aRect.size.height;
975
1254
    }
976
 
*/
 
1255
 
 
1256
  {
 
1257
      NSRect newRect;
 
1258
      
 
1259
      newRect.origin = aPoint;
 
1260
      newRect.size = aRect.size;
 
1261
      [ctm boundingRectFor: newRect result: &newRect];
 
1262
      aPoint = newRect.origin;
 
1263
  }
 
1264
 
977
1265
  [source->ctm boundingRectFor: aRect result: &aRect];
978
 
  aPoint = [ctm transformPoint: aPoint];
979
1266
 
980
 
  x = aPoint.x;
981
 
  y = aPoint.y;
 
1267
  x = floorf(aPoint.x);
 
1268
  y = floorf(aPoint.y);
982
1269
  minx = NSMinX(aRect);
983
1270
  miny = NSMinY(aRect);
984
1271
  width = NSWidth(aRect);
1010
1297
    {
1011
1298
      cairo_paint(_ct);
1012
1299
    }
 
1300
 
 
1301
  if (copyOnSelf)
 
1302
    {
 
1303
      cairo_pop_group_to_source(_ct);
 
1304
      cairo_paint(_ct);
 
1305
    }
 
1306
 
1013
1307
  cairo_restore(_ct);
1014
1308
}
1015
1309