~ubuntu-branches/ubuntu/utopic/gnustep-back/utopic-proposed

« back to all changes in this revision

Viewing changes to Source/opal/OpalGState.m

  • Committer: Package Import Robot
  • Author(s): Yavor Doganov
  • Date: 2014-07-07 16:00:20 UTC
  • mfrom: (4.1.7 sid)
  • Revision ID: package-import@ubuntu.com-20140707160020-0ukvke5ml6ibbezv
Tags: 0.24.0-2
* Upload to unstable; should finally fix the piuparts issue once
  mknfonts.tool is binNMUed (Closes: #663388).
* debian/compat: Bump to 9 to get .build-id debugging symbols.
* debian/control.m4 (Build-Depends): Require debhlper >= 9.
  (Description): Mention that the art backend is deprecated.
  (Suggests): Remove fonts-freefont-ttf as -common depends on it.
* debian/control: Regenerate.
* debian/rules (confflags): Define conditionally and pass --host to
  configure only if cross-compiling.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
   OpalGState.m
 
3
 
 
4
   Copyright (C) 2013 Free Software Foundation, Inc.
 
5
 
 
6
   Author: Ivan Vucica <ivan@vucica.net>
 
7
   Date: June 2013
 
8
 
 
9
   This file is part of GNUstep.
 
10
 
 
11
   This library is free software; you can redistribute it and/or
 
12
   modify it under the terms of the GNU Lesser General Public
 
13
   License as published by the Free Software Foundation; either
 
14
   version 2 of the License, or (at your option) any later version.
 
15
 
 
16
   This library is distributed in the hope that it will be useful,
 
17
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
18
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
19
   Lesser General Public License for more details.
 
20
 
 
21
   You should have received a copy of the GNU Lesser General Public
 
22
   License along with this library; see the file COPYING.LIB.
 
23
   If not, see <http://www.gnu.org/licenses/> or write to the
 
24
   Free Software Foundation, 51 Franklin Street, Fifth Floor,
 
25
   Boston, MA 02110-1301, USA.
 
26
*/
 
27
 
 
28
#import <CoreGraphics/CoreGraphics.h>
 
29
#import <AppKit/NSGraphics.h> // NS*ColorSpace
 
30
#import <AppKit/NSAffineTransform.h>
 
31
#import <AppKit/NSBezierPath.h>
 
32
#import "opal/OpalGState.h"
 
33
#import "opal/OpalSurface.h"
 
34
#import "opal/OpalFontInfo.h"
 
35
 
 
36
#define CGCTX [self CGContext]
 
37
 
 
38
static inline NSString * _CGRectRepr(CGRect rect)
 
39
{
 
40
  return [NSString stringWithFormat: @"(%g,%g,%g,%g)",
 
41
          rect.origin.x, rect.origin.y,
 
42
          rect.size.width, rect.size.height];
 
43
}
 
44
 
 
45
static inline CGRect _CGRectFromNSRect(NSRect nsrect)
 
46
{
 
47
  return CGRectMake(nsrect.origin.x, nsrect.origin.y,
 
48
                    nsrect.size.width, nsrect.size.height);
 
49
}
 
50
 
 
51
static inline NSPoint _NSPointFromCGPoint(CGPoint cgpoint)
 
52
{
 
53
  return NSMakePoint(cgpoint.x, cgpoint.y);
 
54
}
 
55
 
 
56
@implementation OpalGState
 
57
 
 
58
- (id)copyWithZone: (NSZone *)zone
 
59
{
 
60
  NSDebugLLog(@"OpalGState", @"%p (%@): %s", self, [self class], __PRETTY_FUNCTION__);
 
61
  OpalGState * theCopy = (OpalGState *) [super copyWithZone: zone];
 
62
  CGContextRef cgctx = CGCTX;
 
63
 
 
64
  [_opalSurface retain];
 
65
  if (cgctx)
 
66
    {
 
67
      theCopy->_opGState = OPContextCopyGState(cgctx);
 
68
    }
 
69
  else
 
70
    {
 
71
      // FIXME: perhaps Opal could provide an API for getting the default
 
72
      // gstate?
 
73
      CGColorSpaceRef colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
 
74
      CGContextRef ctx = CGBitmapContextCreate(NULL, 1, 1, 8, 32, colorSpace, kCGImageAlphaPremultipliedFirst);
 
75
      CGColorSpaceRelease(colorSpace);
 
76
      theCopy->_opGState = OPContextCopyGState(ctx);
 
77
      CGContextRelease(ctx);
 
78
      NSDebugLLog(@"OpalGState", @"Included default gstate %p", theCopy->_opGState);
 
79
    }
 
80
 
 
81
  return theCopy;
 
82
}
 
83
 
 
84
- (void) setOffset: (NSPoint)theOffset
 
85
{
 
86
  NSDebugLLog(@"OpalGState", @"%p (%@): %s - %g %g", self, [self class], __PRETTY_FUNCTION__, theOffset.x, theOffset.y);
 
87
  CGContextRef cgctx = CGCTX;
 
88
 
 
89
  if (cgctx)
 
90
    {
 
91
      OPContextSetCairoDeviceOffset(cgctx, -theOffset.x,
 
92
          theOffset.y - [_opalSurface size].height);
 
93
    }
 
94
  [super setOffset: theOffset];
 
95
}
 
96
 
 
97
@end
 
98
 
 
99
@implementation OpalGState (Ops)
 
100
 
 
101
- (void) DPSsetalpha: (CGFloat)a
 
102
{
 
103
  NSDebugLLog(@"OpalGState", @"%p (%@): %s - alpha %g", self, [self class], __PRETTY_FUNCTION__, a);
 
104
  CGContextRef cgctx = CGCTX;
 
105
 
 
106
  if (cgctx)
 
107
    {
 
108
      CGContextSetAlpha(cgctx, a);
 
109
    }
 
110
  [super DPSsetalpha: a];
 
111
}
 
112
 
 
113
- (void) DPSsetgray: (CGFloat)gray
 
114
{
 
115
  NSDebugLLog(@"OpalGState", @"%p (%@): %s", self, [self class], __PRETTY_FUNCTION__);
 
116
  CGContextRef cgctx = CGCTX;
 
117
 
 
118
  const CGFloat alpha = 1.0; // TODO: is this correct?
 
119
  if (cgctx)
 
120
    {
 
121
      CGContextSetGrayFillColor(cgctx, gray, alpha);
 
122
    }
 
123
  [super DPSsetgray: gray];
 
124
}
 
125
 
 
126
- (void) DPSsetrgbcolor: (CGFloat)r : (CGFloat)g : (CGFloat)b
 
127
{
 
128
  NSDebugLLog(@"OpalGState", @"%p (%@): %s", self, [self class], __PRETTY_FUNCTION__);
 
129
  CGContextRef cgctx = CGCTX;
 
130
 
 
131
  const CGFloat alpha = 1.0; // TODO: is this correct?
 
132
  if (cgctx)
 
133
    {
 
134
      CGContextSetRGBStrokeColor(cgctx, r, g, b, alpha);
 
135
      CGContextSetRGBFillColor(CGCTX, r, g, b, alpha);
 
136
    }
 
137
  [super DPSsetrgbcolor: r : g : b];
 
138
}
 
139
 
 
140
 
 
141
- (void) DPSshow: (const char *)s
 
142
{
 
143
  NSDebugLLog(@"OpalGState", @"%p (%@): %s", self, [self class], __PRETTY_FUNCTION__);
 
144
  CGContextRef cgctx = CGCTX;
 
145
 
 
146
  if (cgctx)
 
147
    {
 
148
      CGContextSaveGState(cgctx);
 
149
      CGContextSetRGBFillColor(cgctx, 0, 1, 0, 1);
 
150
      CGContextFillRect(cgctx, CGRectMake(0, 0, strlen(s) * 12, 12));
 
151
      CGContextRestoreGState(cgctx);
 
152
    }
 
153
}
 
154
 
 
155
- (void) GSShowText: (const char *)s  : (size_t) length
 
156
{
 
157
  NSDebugLLog(@"OpalGState", @"%p (%@): %s", self, [self class], __PRETTY_FUNCTION__);
 
158
  CGContextRef cgctx = CGCTX;
 
159
 
 
160
  if (cgctx)
 
161
    {
 
162
      CGContextSaveGState(cgctx);
 
163
      CGContextSetRGBFillColor(cgctx, 0, 1, 0, 1);
 
164
      CGContextFillRect(cgctx, CGRectMake(0, 0, length * 12, 12));
 
165
      CGContextRestoreGState(cgctx);
 
166
      // TODO: implement!
 
167
    }
 
168
}
 
169
 
 
170
- (void) GSSetFont: (GSFontInfo *)fontref
 
171
{
 
172
  const CGFloat * matrix;
 
173
  NSDebugLLog(@"OpalGState", @"%p (%@): %s", self, [self class], __PRETTY_FUNCTION__);
 
174
  [super GSSetFont: fontref];
 
175
 
 
176
  CGContextRef cgctx = CGCTX;
 
177
 
 
178
  if (cgctx)
 
179
    {
 
180
      CGFontRef opalFont = (CGFontRef)[((OpalFontInfo *)fontref)->_faceInfo fontFace];
 
181
      CGContextSetFont(cgctx, opalFont);
 
182
      CGContextSetFontSize(cgctx, 1);
 
183
      matrix = [fontref matrix];
 
184
      CGAffineTransform cgAT = CGAffineTransformMake(matrix[0], matrix[1],
 
185
                                                 matrix[2], matrix[3],
 
186
                                                 matrix[4], matrix[5]);
 
187
      CGContextSetTextMatrix(cgctx, cgAT);
 
188
    }
 
189
}
 
190
 
 
191
- (void) GSShowGlyphsWithAdvances: (const NSGlyph *)glyphs : (const NSSize *)advances : (size_t) length
 
192
{
 
193
  size_t i;
 
194
  NSDebugLLog(@"OpalGState", @"%p (%@): %s", self, [self class], __PRETTY_FUNCTION__);
 
195
 
 
196
  CGContextRef cgctx = CGCTX;
 
197
 
 
198
  if (cgctx)
 
199
    {
 
200
      // NSGlyph = unsigned int, CGGlyph = unsigned short
 
201
      CGGlyph cgglyphs[length];
 
202
 
 
203
      for (i = 0; i < length; i++)
 
204
        {
 
205
          cgglyphs[i] = glyphs[i];
 
206
        }
 
207
 
 
208
      CGPoint pt = CGContextGetPathCurrentPoint(cgctx);
 
209
      // FIXME: why * 0.66?
 
210
      pt.y += [self->font defaultLineHeightForFont] * 0.66;
 
211
      CGContextSetTextPosition(cgctx, pt.x, pt.y);
 
212
      CGContextShowGlyphsWithAdvances(cgctx, cgglyphs, (const CGSize *)advances,
 
213
                                      length);
 
214
    }
 
215
}
 
216
 
 
217
- (NSPoint) currentPoint
 
218
{
 
219
  NSDebugLLog(@"OpalGState", @"%p (%@): %s", self, [self class], __PRETTY_FUNCTION__);
 
220
  CGContextRef cgctx = CGCTX;
 
221
 
 
222
  if (cgctx)
 
223
    {
 
224
      CGPoint pt = CGContextGetPathCurrentPoint(cgctx);
 
225
      return _NSPointFromCGPoint(pt);
 
226
    }
 
227
  else
 
228
    {
 
229
      return NSZeroPoint;
 
230
    }
 
231
}
 
232
 
 
233
- (void) DPSsetdash: (const CGFloat*)pat
 
234
                   : (NSInteger)size
 
235
                   : (CGFloat)dashOffset
 
236
{
 
237
  NSDebugLLog(@"OpalGState", @"%p (%@): %s", self, [self class], __PRETTY_FUNCTION__);
 
238
 
 
239
  if (!pat && size != 0)
 
240
    {
 
241
      NSLog(@"%s: null 'pat' passed with size %d. Fixing by setting size to 0.", pat, (int)size);
 
242
      size = 0;
 
243
      // TODO: looking at opal, it does not seem to have a tolerance for
 
244
      // pat=NULL although CGContextSetLineDash() explicitly specifies that
 
245
      // as a possible argument
 
246
    }
 
247
  CGContextRef cgctx = CGCTX;
 
248
 
 
249
  if (cgctx)
 
250
    {
 
251
      CGContextSetLineDash(cgctx, dashOffset, pat, size);
 
252
    }
 
253
}
 
254
 
 
255
- (void) DPSsetlinecap: (int)linecap
 
256
{
 
257
  NSDebugLLog(@"OpalGState", @"%p (%@): %s", self, [self class], __PRETTY_FUNCTION__);
 
258
 
 
259
  CGContextRef cgctx = CGCTX;
 
260
 
 
261
  if (cgctx)
 
262
    {
 
263
      // TODO: ensure match of linecap constants between Opal and DPS
 
264
      CGContextSetLineCap(cgctx, linecap);
 
265
    }
 
266
}
 
267
 
 
268
- (void) DPSsetlinejoin: (int)linejoin
 
269
{
 
270
  NSDebugLLog(@"OpalGState", @"%p (%@): %s", self, [self class], __PRETTY_FUNCTION__);
 
271
  CGContextRef cgctx = CGCTX;
 
272
 
 
273
  if (cgctx)
 
274
    {
 
275
      CGContextSetLineJoin(cgctx, linejoin);
 
276
    }
 
277
}
 
278
 
 
279
- (void) DPSsetlinewidth: (CGFloat) width
 
280
{
 
281
  NSDebugLLog(@"OpalGState", @"%p (%@): %s", self, [self class], __PRETTY_FUNCTION__);
 
282
  CGContextRef cgctx = CGCTX;
 
283
 
 
284
  if (cgctx)
 
285
    {
 
286
      CGContextSetLineWidth(cgctx, width);
 
287
    }
 
288
}
 
289
 
 
290
- (void) DPSsetmiterlimit: (CGFloat)miterlimit
 
291
{
 
292
  NSDebugLLog(@"OpalGState", @"%p (%@): %s", self, [self class], __PRETTY_FUNCTION__);
 
293
  CGContextRef cgctx = CGCTX;
 
294
 
 
295
  if (cgctx)
 
296
    {
 
297
      CGContextSetMiterLimit(cgctx, miterlimit);
 
298
    }
 
299
}
 
300
 
 
301
- (void) DPSsetstrokeadjust: (int) b
 
302
{
 
303
  NSDebugLLog(@"OpalGState", @"%p (%@): %s", self, [self class], __PRETTY_FUNCTION__);
 
304
 
 
305
  // TODO: Opal doesn't implement this private API of Core Graphics
 
306
}
 
307
 
 
308
/* Matrix operations */
 
309
- (void)DPSconcat: (const CGFloat *)m
 
310
{
 
311
  NSDebugLLog(@"OpalGState", @"%p (%@): %s - %g %g %g %g %g %g", self,
 
312
              [self class], __PRETTY_FUNCTION__,
 
313
              m[0], m[1], m[2], m[3], m[4], m[5]);
 
314
  CGContextRef cgctx = CGCTX;
 
315
 
 
316
  if (cgctx)
 
317
    {
 
318
      CGContextConcatCTM(cgctx,
 
319
                         CGAffineTransformMake(m[0], m[1], m[2],
 
320
                                               m[3], m[4], m[5]));
 
321
    }
 
322
  [super DPSconcat: m];
 
323
}
 
324
 
 
325
- (void)DPSinitmatrix
 
326
{
 
327
  NSDebugLLog(@"OpalGState", @"%p (%@): %s", self, [self class], __PRETTY_FUNCTION__);
 
328
  CGContextRef cgctx = CGCTX;
 
329
 
 
330
  if (cgctx)
 
331
    {
 
332
      OPContextSetIdentityCTM(cgctx);
 
333
    }
 
334
  [super DPSinitmatrix];
 
335
}
 
336
 
 
337
- (void)DPSrotate: (CGFloat)angle
 
338
{
 
339
  CGContextRef cgctx = CGCTX;
 
340
 
 
341
  if (cgctx)
 
342
    {
 
343
      CGContextRotateCTM(cgctx, angle);
 
344
    }
 
345
  [super DPSrotate: angle];
 
346
}
 
347
 
 
348
- (void)DPSscale: (CGFloat)x
 
349
                : (CGFloat)y
 
350
{
 
351
  NSDebugLLog(@"OpalGState", @"%p (%@): %s - %g %g", self, [self class], __PRETTY_FUNCTION__, x, y);
 
352
  CGContextRef cgctx = CGCTX;
 
353
 
 
354
  if (cgctx)
 
355
    {
 
356
      CGContextScaleCTM(cgctx, x, y);
 
357
    }
 
358
  [super DPSscale: x : y];
 
359
}
 
360
 
 
361
- (void)DPStranslate: (CGFloat)x
 
362
                    : (CGFloat)y
 
363
{
 
364
  NSDebugLLog(@"OpalGState", @"%p (%@): %s - x %g y %g", self, [self class], __PRETTY_FUNCTION__, x, y);
 
365
  CGContextRef cgctx = CGCTX;
 
366
 
 
367
  if (cgctx)
 
368
    {
 
369
      CGContextTranslateCTM(cgctx, x, y);
 
370
    }
 
371
  [super DPStranslate: x: y];
 
372
}
 
373
 
 
374
- (NSAffineTransform *) GSCurrentCTM
 
375
{
 
376
  NSDebugLLog(@"OpalGState", @"%p (%@): %s", self, [self class], __PRETTY_FUNCTION__);
 
377
 
 
378
  return [super GSCurrentCTM];
 
379
 
 
380
  /*
 
381
  CGAffineTransform cgCTM = CGContextGetCTM(CGCTX);
 
382
  NSAffineTransform * affineTransform = [NSAffineTransform transform];
 
383
 
 
384
  // This depends on CGAffineTransform and NSAffineTransformStruct having
 
385
  // the same in-memory layout.
 
386
  // Here's an elementary check if that is true.
 
387
  // We should probably check this in -back's "configure" script.
 
388
  assert(sizeof(CGAffineTransform) == sizeof(NSAffineTransformStruct));
 
389
 
 
390
  NSAffineTransformStruct nsCTM = *(NSAffineTransformStruct *)&cgCTM;
 
391
  [affineTransform setTransformStruct: nsCTM];
 
392
 
 
393
  return affineTransform;
 
394
  */
 
395
}
 
396
 
 
397
- (void) GSSetCTM: (NSAffineTransform *)newCTM
 
398
{
 
399
  CGContextRef cgctx = CGCTX;
 
400
 
 
401
  if (cgctx)
 
402
    {
 
403
      // This depends on CGAffineTransform and NSAffineTransformStruct having
 
404
      // the same in-memory layout.
 
405
      // Here's an elementary check if that is true.
 
406
      // We should probably check this in -back's "configure" script.
 
407
      assert(sizeof(CGAffineTransform) == sizeof(NSAffineTransformStruct));
 
408
      NSAffineTransformStruct nsAT = [newCTM transformStruct];
 
409
      CGAffineTransform cgAT = *(CGAffineTransform *)&nsAT;
 
410
 
 
411
      OPContextSetIdentityCTM(cgctx);
 
412
      CGContextConcatCTM(cgctx, cgAT);
 
413
    }
 
414
 
 
415
  [super GSSetCTM: newCTM];
 
416
}
 
417
 
 
418
- (void) GSConcatCTM: (NSAffineTransform *)newCTM
 
419
{
 
420
  CGContextRef cgctx = CGCTX;
 
421
 
 
422
  if (cgctx)
 
423
    {
 
424
      assert(sizeof(CGAffineTransform) == sizeof(NSAffineTransformStruct));
 
425
      NSAffineTransformStruct nsAT = [newCTM transformStruct];
 
426
      CGAffineTransform cgAT = *(CGAffineTransform *)&nsAT;
 
427
 
 
428
      CGContextConcatCTM(cgctx, cgAT);
 
429
    }
 
430
 
 
431
  [super GSConcatCTM: newCTM];
 
432
}
 
433
 
 
434
 
 
435
// MARK: Path operations
 
436
// MARK: -
 
437
 
 
438
- (void) DPSarc: (CGFloat)x : (CGFloat)y : (CGFloat)r : (CGFloat)angle1 : (CGFloat)angle2
 
439
{
 
440
  CGContextRef cgctx = CGCTX;
 
441
 
 
442
  if (cgctx)
 
443
    {
 
444
      CGContextAddArc(cgctx, x, y, r, angle1, angle2, YES);
 
445
    }
 
446
  [super DPSarc: x : y : r : angle1 : angle2];
 
447
}
 
448
 
 
449
- (void) DPSarcn: (CGFloat)x : (CGFloat)y : (CGFloat)r : (CGFloat)angle1 : (CGFloat)angle2
 
450
{
 
451
  CGContextRef cgctx = CGCTX;
 
452
 
 
453
  if (cgctx)
 
454
    {
 
455
      CGContextAddArc(cgctx, x, y, r, angle1, angle2, NO);
 
456
    }
 
457
  [super DPSarcn: x : y : r : angle1 : angle2];
 
458
}
 
459
 
 
460
- (void)DPSarct: (CGFloat)x1 : (CGFloat)y1 : (CGFloat)x2 : (CGFloat)y2 : (CGFloat)r
 
461
{
 
462
  CGContextRef cgctx = CGCTX;
 
463
 
 
464
  if (cgctx)
 
465
    {
 
466
      CGContextAddArcToPoint(cgctx, x1, y1, x1, y2, r);
 
467
    }
 
468
  [super DPSarct: x1 : y1 : x2 : y2 : r];
 
469
}
 
470
 
 
471
- (void) DPSclip
 
472
{
 
473
  NSDebugLLog(@"OpalGState", @"%p (%@): %s", self, [self class], __PRETTY_FUNCTION__);
 
474
  CGContextRef cgctx = CGCTX;
 
475
 
 
476
  if (cgctx)
 
477
    {
 
478
      CGContextClip(cgctx);
 
479
    }
 
480
  [super DPSnewpath];
 
481
}
 
482
 
 
483
- (void)DPSclosepath
 
484
{
 
485
  CGContextRef cgctx = CGCTX;
 
486
 
 
487
  if (cgctx)
 
488
    {
 
489
      CGContextClosePath(cgctx);
 
490
    }
 
491
  [super DPSclosepath];
 
492
}
 
493
 
 
494
- (void)DPScurveto: (CGFloat)x1 : (CGFloat)y1 : (CGFloat)x2 : (CGFloat)y2
 
495
                  : (CGFloat)x3 : (CGFloat)y3
 
496
{
 
497
  CGContextRef cgctx = CGCTX;
 
498
 
 
499
  if (cgctx)
 
500
    {
 
501
      CGContextAddCurveToPoint(cgctx, x1, y1, x2, y2, x3, y3);
 
502
    }
 
503
  [super DPScurveto: x1 : y1 : x2 : y2 : x3 : y3];
 
504
}
 
505
 
 
506
- (void) DPSeoclip
 
507
{
 
508
  NSDebugLLog(@"OpalGState", @"%p (%@): %s", self, [self class], __PRETTY_FUNCTION__);
 
509
  CGContextRef cgctx = CGCTX;
 
510
 
 
511
  if (cgctx)
 
512
    {
 
513
      CGContextEOClip(cgctx);
 
514
    }
 
515
  [super DPSnewpath];
 
516
}
 
517
 
 
518
- (void) DPSeofill
 
519
{
 
520
  NSDebugLLog(@"OpalGState", @"%p (%@): %s", self, [self class], __PRETTY_FUNCTION__);
 
521
  CGContextRef cgctx = CGCTX;
 
522
 
 
523
  if (cgctx)
 
524
    {
 
525
      CGContextEOFillPath(cgctx);
 
526
    }
 
527
  [super DPSnewpath];
 
528
}
 
529
 
 
530
- (void) DPSfill
 
531
{
 
532
  NSDebugLLog(@"OpalGState", @"%p (%@): %s", self, [self class], __PRETTY_FUNCTION__);
 
533
  CGContextRef cgctx = CGCTX;
 
534
 
 
535
  if (cgctx)
 
536
    {
 
537
      CGContextFillPath(cgctx);
 
538
    }
 
539
  [super DPSnewpath];
 
540
}
 
541
 
 
542
- (void) DPSinitclip
 
543
{
 
544
  NSDebugLLog(@"OpalGState", @"%p (%@): %s", self, [self class], __PRETTY_FUNCTION__);
 
545
  CGContextRef cgctx = CGCTX;
 
546
 
 
547
  if (cgctx)
 
548
    {
 
549
      OPContextResetClip(cgctx);
 
550
    }
 
551
}
 
552
 
 
553
- (void) DPSlineto: (CGFloat) x
 
554
                  : (CGFloat) y
 
555
{
 
556
  NSDebugLLog(@"OpalGState", @"%p (%@): %s - %g %g", self, [self class], __PRETTY_FUNCTION__, x, y);
 
557
  CGContextRef cgctx = CGCTX;
 
558
 
 
559
  if (cgctx)
 
560
    {
 
561
      CGContextAddLineToPoint(cgctx, x, y);
 
562
    }
 
563
  [super DPSlineto: x : y];
 
564
}
 
565
 
 
566
- (void) DPSmoveto: (CGFloat) x
 
567
                  : (CGFloat) y
 
568
{
 
569
  NSDebugLLog(@"OpalGState", @"%p (%@): %s - %g %g", self, [self class], __PRETTY_FUNCTION__, x, y);
 
570
  CGContextRef cgctx = CGCTX;
 
571
 
 
572
  if (cgctx)
 
573
    {
 
574
      CGContextMoveToPoint(cgctx, x, y);
 
575
    }
 
576
  [super DPSmoveto: x : y];
 
577
}
 
578
 
 
579
- (void)DPSnewpath
 
580
{
 
581
  CGContextRef cgctx = CGCTX;
 
582
 
 
583
  if (cgctx)
 
584
    {
 
585
      CGContextBeginPath(cgctx);
 
586
    }
 
587
  [super DPSnewpath];
 
588
}
 
589
 
 
590
- (void)DPSrcurveto: (CGFloat)x1 : (CGFloat)y1 : (CGFloat)x2 : (CGFloat)y2
 
591
                   : (CGFloat)x3 : (CGFloat)y3
 
592
{
 
593
  CGContextRef cgctx = CGCTX;
 
594
 
 
595
  if (cgctx)
 
596
    {
 
597
      CGFloat x, y;
 
598
 
 
599
      [self DPScurrentpoint: &x : &y];
 
600
      x1 += x;
 
601
      y1 += y;
 
602
      x2 += x;
 
603
      y2 += y;
 
604
      x3 += x;
 
605
      y3 += y;
 
606
      CGContextAddCurveToPoint(cgctx, x1, y1, x2, y2, x3, y3);
 
607
    }
 
608
  [super DPSrcurveto: x1 : y1 : x2 : y2 : x3 : y3];
 
609
}
 
610
 
 
611
- (void) DPSrectclip: (CGFloat)x : (CGFloat)y : (CGFloat)w : (CGFloat)h
 
612
{
 
613
  NSDebugLLog(@"OpalGState", @"%p (%@): %s - %g %g %g %g", self, [self class], __PRETTY_FUNCTION__, x, y, w, h);
 
614
  CGContextRef cgctx = CGCTX;
 
615
 
 
616
  if (cgctx)
 
617
    {
 
618
      CGContextClipToRect(cgctx, CGRectMake(x, y, w, h));
 
619
    }
 
620
}
 
621
 
 
622
- (void) DPSrectfill: (CGFloat)x : (CGFloat)y : (CGFloat)w : (CGFloat)h
 
623
{
 
624
  NSDebugLLog(@"OpalGState", @"%p (%@): %s - rect %g %g %g %g", self, [self class], __PRETTY_FUNCTION__, x, y, w, h);
 
625
  CGContextRef cgctx = CGCTX;
 
626
 
 
627
  if (cgctx)
 
628
    {
 
629
      CGContextFillRect(cgctx, CGRectMake(x, y, w, h));
 
630
    }
 
631
}
 
632
 
 
633
- (void) DPSrectstroke: (CGFloat)x : (CGFloat)y : (CGFloat)w : (CGFloat)h
 
634
{
 
635
  CGContextRef cgctx = CGCTX;
 
636
 
 
637
  if (cgctx)
 
638
    {
 
639
      CGContextStrokeRect(cgctx, CGRectMake(x, y, w, h));
 
640
    }
 
641
}
 
642
 
 
643
- (void) DPSrlineto: (CGFloat) x
 
644
                   : (CGFloat) y
 
645
{
 
646
  NSDebugLLog(@"OpalGState", @"%p (%@): %s - %g %g", self, [self class], __PRETTY_FUNCTION__, x, y);
 
647
  CGContextRef cgctx = CGCTX;
 
648
 
 
649
  if (cgctx)
 
650
    {
 
651
      CGFloat x2, y2;
 
652
 
 
653
      [self DPScurrentpoint: &x2 : &y2];
 
654
      x2 += x;
 
655
      y2 += y;
 
656
      CGContextAddLineToPoint(cgctx, x, y);
 
657
    }
 
658
  [super DPSrlineto: x : y];
 
659
}
 
660
 
 
661
- (void) DPSrmoveto: (CGFloat) x
 
662
                   : (CGFloat) y
 
663
{
 
664
  NSDebugLLog(@"OpalGState", @"%p (%@): %s - %g %g", self, [self class], __PRETTY_FUNCTION__, x, y);
 
665
  CGContextRef cgctx = CGCTX;
 
666
 
 
667
  if (cgctx)
 
668
    {
 
669
      CGFloat x2, y2;
 
670
 
 
671
      [self DPScurrentpoint: &x2 : &y2];
 
672
      x2 += x;
 
673
      y2 += y;
 
674
      CGContextMoveToPoint(cgctx, x2, y2);
 
675
    }
 
676
  [super DPSrmoveto: x : y];
 
677
}
 
678
 
 
679
- (void) DPSstroke
 
680
{
 
681
  NSDebugLLog(@"OpalGState", @"%p (%@): %s", self, [self class], __PRETTY_FUNCTION__);
 
682
  CGContextRef cgctx = CGCTX;
 
683
 
 
684
  if (cgctx)
 
685
    {
 
686
      CGContextStrokePath(cgctx);
 
687
    }
 
688
  [super DPSnewpath];
 
689
}
 
690
 
 
691
- (void) GSSendBezierPath: (NSBezierPath *)newpath
 
692
{
 
693
  NSInteger count = [newpath elementCount];
 
694
  NSInteger i;
 
695
  SEL elmsel = @selector(elementAtIndex:associatedPoints:);
 
696
  NSBezierPathElement (*elmidx)(id, SEL, NSInteger, NSPoint*) =
 
697
    (NSBezierPathElement (*)(id, SEL, NSInteger, NSPoint*))[newpath methodForSelector: elmsel];
 
698
 
 
699
  [super GSSendBezierPath: newpath];
 
700
  CGContextRef cgctx = CGCTX;
 
701
 
 
702
  if (cgctx)
 
703
    {
 
704
      CGContextBeginPath(cgctx);
 
705
      for (i = 0; i < count; i++)
 
706
        {
 
707
          NSBezierPathElement type;
 
708
          NSPoint points[3];
 
709
 
 
710
          type = (NSBezierPathElement)(*elmidx)(newpath, elmsel, i, points);
 
711
          switch(type)
 
712
            {
 
713
            case NSMoveToBezierPathElement:
 
714
              CGContextMoveToPoint(cgctx, points[0].x, points[0].y);
 
715
              break;
 
716
            case NSLineToBezierPathElement:
 
717
              CGContextAddLineToPoint(cgctx, points[0].x, points[0].y);
 
718
              break;
 
719
            case NSCurveToBezierPathElement:
 
720
              CGContextAddCurveToPoint(cgctx, points[0].x, points[0].y,
 
721
                                       points[1].x, points[1].y,
 
722
                                       points[2].x, points[2].y);
 
723
              break;
 
724
            case NSClosePathBezierPathElement:
 
725
              CGContextClosePath(cgctx);
 
726
              break;
 
727
            default:
 
728
              break;
 
729
            }
 
730
        }
 
731
    }
 
732
}
 
733
 
 
734
- (NSDictionary *) GSReadRect: (NSRect)r
 
735
{
 
736
  NSDebugLLog(@"OpalGState", @"%p (%@): %s", self, [self class], __PRETTY_FUNCTION__);
 
737
  return nil;
 
738
}
 
739
 
 
740
- (void) DPSimage: (NSAffineTransform *)matrix
 
741
                 : (NSInteger)pixelsWide
 
742
                 : (NSInteger)pixelsHigh
 
743
                 : (NSInteger)bitsPerSample // is this used correctly ?
 
744
                 : (NSInteger)samplesPerPixel // < unused
 
745
                 : (NSInteger)bitsPerPixel
 
746
                 : (NSInteger)bytesPerRow
 
747
                 : (BOOL)isPlanar // < unused
 
748
                 : (BOOL)hasAlpha
 
749
                 : (NSString *)colorSpaceName
 
750
                 : (const unsigned char *const[5])data
 
751
{
 
752
  NSDebugLLog(@"OpalGState", @"%p (%@): %s", self, [self class], __PRETTY_FUNCTION__);
 
753
  NSDebugLLog(@"OpalGState", @"         %s - %@ - cgctx %@", __PRETTY_FUNCTION__, _opalSurface, [self CGContext]);
 
754
  NSDebugLLog(@"OpalGState", @"Bits per component : bitspersample = %d", bitsPerSample);
 
755
  NSDebugLLog(@"OpalGState", @"Bits per pixel     : bitsperpixel = %d", bitsPerPixel);
 
756
  NSDebugLLog(@"OpalGState", @"                   : samplesperpixel = %d", samplesPerPixel);
 
757
  NSDebugLLog(@"OpalGState", @"tf: %@ x %@", matrix, [self GSCurrentCTM]);
 
758
 
 
759
  // TODO:
 
760
  // We may want to normalize colorspace names between Opal and -gui,
 
761
  // to avoid this conversion?
 
762
  if ([colorSpaceName isEqualToString: NSCalibratedRGBColorSpace])
 
763
    colorSpaceName = kCGColorSpaceGenericRGB; // SRGB?
 
764
  else if ([colorSpaceName isEqualToString: NSDeviceRGBColorSpace])
 
765
    colorSpaceName = kCGColorSpaceGenericRGB;
 
766
  else if ([colorSpaceName isEqualToString: NSCalibratedWhiteColorSpace])
 
767
    colorSpaceName = kCGColorSpaceGenericGray;
 
768
  else if ([colorSpaceName isEqualToString: NSDeviceWhiteColorSpace])
 
769
    colorSpaceName = kCGColorSpaceGenericGray;
 
770
  else
 
771
    {
 
772
      NSLog(@"Opal backend: Unhandled colorspace: %@", colorSpaceName);
 
773
      return;
 
774
    }
 
775
 
 
776
  CGContextRef cgctx = CGCTX;
 
777
 
 
778
  if (cgctx)
 
779
    {
 
780
      // This depends on CGAffineTransform and NSAffineTransformStruct having
 
781
      // the same in-memory layout.
 
782
      // Here's an elementary check if that is true.
 
783
      // We should probably check this in -back's "configure" script.
 
784
      assert(sizeof(CGAffineTransform) == sizeof(NSAffineTransformStruct));
 
785
      NSAffineTransformStruct nsAT = [matrix transformStruct];
 
786
      CGAffineTransform cgAT = *(CGAffineTransform *)&nsAT;
 
787
 
 
788
      CGContextSaveGState(cgctx);
 
789
      CGContextConcatCTM(cgctx, cgAT);
 
790
 
 
791
      CGColorSpaceRef colorSpace = CGColorSpaceCreateWithName(colorSpaceName);
 
792
      NSData *nsData = [NSData dataWithBytesNoCopy: (void*)*data
 
793
                                            length: pixelsHigh * bytesPerRow
 
794
                                      freeWhenDone: NO];
 
795
      CGDataProviderRef dataProvider = CGDataProviderCreateWithCFData(nsData);
 
796
      CGImageRef img = CGImageCreate(pixelsWide, pixelsHigh, bitsPerSample,
 
797
                                     bitsPerPixel, bytesPerRow, colorSpace,
 
798
                                     hasAlpha ? kCGImageAlphaPremultipliedLast : 0 /* correct? */,
 
799
                                     dataProvider,
 
800
                                     NULL, /* const CGFloat decode[] is what? */
 
801
                                     false, /* shouldInterpolate? */
 
802
                                     kCGRenderingIntentDefault );
 
803
      if (img != nil)
 
804
        {
 
805
          CGContextDrawImage(cgctx, CGRectMake(0, 0, pixelsWide, pixelsHigh), img);
 
806
        }
 
807
 
 
808
      CGImageRelease(img);
 
809
      CGDataProviderRelease(dataProvider);
 
810
      CGColorSpaceRelease(colorSpace);
 
811
      CGContextRestoreGState(cgctx);
 
812
    }
 
813
}
 
814
 
 
815
- (void) compositeGState: (OpalGState *)source
 
816
                fromRect: (NSRect)srcRect
 
817
                 toPoint: (NSPoint)destPoint
 
818
                      op: (NSCompositingOperation)op
 
819
                fraction: (CGFloat)delta
 
820
           destCGContext: (CGContextRef) destCGContext
 
821
{
 
822
  // NOTE: This method seems to need to paint to X11 context, too.
 
823
 
 
824
  NSDebugLLog(@"OpalGState", @"%p (%@): %s - from %@ of gstate %p (cgctx %p) to %@ of %p (cgctx %p)", self, [self class], __PRETTY_FUNCTION__, NSStringFromRect(srcRect), source, [source CGContext], NSStringFromPoint(destPoint), self, [self CGContext]);
 
825
 
 
826
  NSSize ssize = [source->_opalSurface size];
 
827
  srcRect = [source rectInMatrixSpace: srcRect];
 
828
  destPoint = [self pointInMatrixSpace: destPoint];
 
829
 
 
830
  srcRect.origin.y = ssize.height-srcRect.origin.y-srcRect.size.height;
 
831
 
 
832
  CGRect srcCGRect = _CGRectFromNSRect(srcRect);
 
833
  CGRect destCGRect = CGRectMake(destPoint.x, destPoint.y,
 
834
                                 srcRect.size.width, srcRect.size.height);
 
835
  NSDebugLLog(@"OpalGState", @"Source cgctx: %p, self: %p - from %@ to %@ with ctm %@", [source CGContext], self, _CGRectRepr(srcCGRect), _CGRectRepr(destCGRect), [self GSCurrentCTM]);
 
836
  // FIXME: this presumes that the backing CGContext of 'source' is
 
837
  // an OpalSurface with a backing CGBitmapContext
 
838
  CGImageRef backingImage = CGBitmapContextCreateImage([source CGContext]);
 
839
  CGImageRef subImage = CGImageCreateWithImageInRect(backingImage, srcCGRect);
 
840
 
 
841
  CGContextSaveGState(destCGContext);
 
842
  OPContextSetIdentityCTM(destCGContext);
 
843
  OPContextSetCairoDeviceOffset(destCGContext, 0, 0);
 
844
 
 
845
  // TODO: this ignores op
 
846
  // TODO: this ignores delta
 
847
  CGContextDrawImage(destCGContext, destCGRect, subImage);
 
848
 
 
849
  OPContextSetCairoDeviceOffset(CGCTX, -offset.x,
 
850
      offset.y - [_opalSurface size].height);
 
851
 
 
852
  CGContextRestoreGState(destCGContext);
 
853
 
 
854
  CGImageRelease(subImage);
 
855
  CGImageRelease(backingImage);
 
856
}
 
857
 
 
858
- (void) compositeGState: (OpalGState *)source
 
859
                fromRect: (NSRect)srcRect
 
860
                 toPoint: (NSPoint)destPoint
 
861
                      op: (NSCompositingOperation)op
 
862
                fraction: (CGFloat)delta
 
863
{
 
864
  NSDebugLLog(@"OpalGState", @"%p (%@): %s", self, [self class], __PRETTY_FUNCTION__);
 
865
  CGContextRef destContexts[2] = { [_opalSurface backingCGContext], [_opalSurface x11CGContext] };
 
866
 
 
867
  /* x11 context needs to have correct ctm applied */
 
868
  CGContextSaveGState([_opalSurface x11CGContext]);
 
869
  OPContextSetIdentityCTM([_opalSurface x11CGContext]);
 
870
  CGContextConcatCTM([_opalSurface x11CGContext], CGContextGetCTM([_opalSurface backingCGContext]));
 
871
 
 
872
  int i;
 
873
  for (i = 0; i < 1; i++) // not drawing into x11cgctx after all.
 
874
    {
 
875
      CGContextRef ctx = destContexts[i];
 
876
 
 
877
      [self compositeGState: source
 
878
                   fromRect: srcRect
 
879
                    toPoint: destPoint
 
880
                         op: op
 
881
                   fraction: delta
 
882
              destCGContext: ctx];
 
883
    }
 
884
 
 
885
  /* restore x11 context's previous state */
 
886
  CGContextRestoreGState([_opalSurface x11CGContext]);
 
887
}
 
888
 
 
889
/** Unlike -compositeGState, -drawGSstate fully respects the AppKit CTM but
 
890
doesn't support to use the receiver cairo target as the source. */
 
891
/* This method is required if -[OpalContext supportsDrawGState] returns YES */
 
892
- (void) drawGState: (OpalGState *)source
 
893
           fromRect: (NSRect)srcRect
 
894
            toPoint: (NSPoint)destPoint
 
895
                 op: (NSCompositingOperation)op
 
896
           fraction: (CGFloat)delta
 
897
      destCGContext: (CGContextRef)destCGContext
 
898
{
 
899
  // TODO: CairoGState has a lot more complex implementation.
 
900
  // For now, we'll just call compositeGState and live
 
901
  // with the fact that CTM is not respected.
 
902
 
 
903
  NSDebugLLog(@"OpalGState", @"%p (%@): %s", self, [self class], __PRETTY_FUNCTION__);
 
904
 
 
905
  CGRect srcCGRect = CGRectMake(srcRect.origin.x, srcRect.origin.y,
 
906
                                srcRect.size.width, srcRect.size.height);
 
907
  CGRect destCGRect = CGRectMake(destPoint.x, destPoint.y,
 
908
                                 srcRect.size.width, srcRect.size.height);
 
909
  CGImageRef backingImage = CGBitmapContextCreateImage([source CGContext]);
 
910
  CGImageRef subImage = CGImageCreateWithImageInRect(backingImage, srcCGRect);
 
911
  // TODO: this ignores op
 
912
  // TODO: this ignores delta
 
913
  CGContextDrawImage(destCGContext, destCGRect, subImage);
 
914
  CGImageRelease(subImage);
 
915
  CGImageRelease(backingImage);
 
916
}
 
917
 
 
918
- (void) drawGState: (OpalGState *)source
 
919
           fromRect: (NSRect)srcRect
 
920
            toPoint: (NSPoint)destPoint
 
921
                 op: (NSCompositingOperation)op
 
922
           fraction: (CGFloat)delta
 
923
{
 
924
  NSDebugLLog(@"OpalGState", @"%p (%@): %s", self, [self class], __PRETTY_FUNCTION__);
 
925
  CGContextRef destContexts[2] = { [_opalSurface backingCGContext], [_opalSurface x11CGContext] };
 
926
  int i;
 
927
 
 
928
  for (i = 0; i < 1; i++)
 
929
    {
 
930
      CGContextRef ctx = destContexts[i];
 
931
 
 
932
      [self drawGState: source
 
933
              fromRect: srcRect
 
934
               toPoint: destPoint
 
935
                    op: op
 
936
              fraction: delta
 
937
         destCGContext: ctx];
 
938
    }
 
939
}
 
940
 
 
941
- (void) compositerect: (NSRect)aRect
 
942
                    op: (NSCompositingOperation)op
 
943
{
 
944
  NSDebugLLog(@"OpalGState", @"%p (%@): %s - %@", self, [self class], __PRETTY_FUNCTION__, NSStringFromRect(aRect));
 
945
  CGContextRef cgctx = CGCTX;
 
946
 
 
947
  if (cgctx)
 
948
    {
 
949
      CGContextSaveGState(cgctx);
 
950
      OPContextSetIdentityCTM(cgctx);
 
951
      // FIXME: Set operator
 
952
      CGContextFillRect(cgctx,
 
953
                        CGRectMake(aRect.origin.x,
 
954
                                   [_opalSurface size].height -  aRect.origin.y,
 
955
                                   aRect.size.width, aRect.size.height));
 
956
      CGContextRestoreGState(cgctx);
 
957
    }
 
958
}
 
959
 
 
960
@end
 
961
 
 
962
// MARK: Initialization methods
 
963
// MARK: -
 
964
 
 
965
@implementation OpalGState (InitializationMethods)
 
966
 
 
967
- (void) DPSinitgraphics
 
968
{
 
969
  NSDebugLLog(@"OpalGState", @"%p (%@): %s", self, [self class], __PRETTY_FUNCTION__);
 
970
 
 
971
  [super DPSinitgraphics];
 
972
  [self DPSinitmatrix];
 
973
}
 
974
 
 
975
/* SOME NOTES:
 
976
   - GState approximates a cairo context: a drawing state.
 
977
   - Surface approximates a cairo surface: a place to draw things.
 
978
 
 
979
   - CGContext seems to be a mix of these two: surface + state.
 
980
 
 
981
   Should we unite these two somehow? Can we unite these two somehow?
 
982
   Possibly not. We still need to support bitmap contexts, pdf contexts
 
983
   etc which contain both state and contents.
 
984
 
 
985
   So, we will still need surfaces (containing CGContexts, hence including
 
986
   state) and GState as a wrapper around whatever context happens to be
 
987
   the current one.
 
988
 */
 
989
 
 
990
/**
 
991
  Makes the specified surface active in the current graphics state,
 
992
  ready for use. Also, sets the device offset to specified coordinates.
 
993
 **/
 
994
- (void) GSSetSurface: (OpalSurface *)opalSurface
 
995
                     : (int)x
 
996
                     : (int)y
 
997
{
 
998
  NSDebugLLog(@"OpalGState", @"%p (%@): %s - %@ %d %d", self, [self class], __PRETTY_FUNCTION__, opalSurface, x, y);
 
999
 
 
1000
  ASSIGN(_opalSurface, opalSurface);
 
1001
  [self setOffset: NSMakePoint(x, y)];
 
1002
  [self DPSinitgraphics];
 
1003
}
 
1004
 
 
1005
- (void) GSCurrentSurface: (OpalSurface **)surface
 
1006
                         : (int *)x
 
1007
                         : (int *)y
 
1008
{
 
1009
  NSDebugLLog(@"OpalGState", @"%p (%@): %s", self, [self class], __PRETTY_FUNCTION__);
 
1010
 
 
1011
  if (x)
 
1012
    *x = offset.x;
 
1013
  if (y)
 
1014
    *y = offset.y;
 
1015
  if (surface)
 
1016
    {
 
1017
      *surface = _opalSurface;
 
1018
    }
 
1019
}
 
1020
 
 
1021
@end
 
1022
 
 
1023
// MARK: Accessors
 
1024
// MARK: -
 
1025
 
 
1026
@implementation OpalGState (Accessors)
 
1027
 
 
1028
- (CGContextRef) CGContext
 
1029
{
 
1030
  if (!_opalSurface)
 
1031
    {
 
1032
      NSDebugMLLog(@"OpalGState", @"No OpalSurface");
 
1033
      return nil;
 
1034
    }
 
1035
  else
 
1036
    {
 
1037
      CGContextRef context = [_opalSurface CGContext];
 
1038
 
 
1039
      if (!context)
 
1040
        {
 
1041
          NSDebugMLLog(@"OpalGState", @"No OpalSurface CGContext");
 
1042
          return nil;
 
1043
        }
 
1044
      return context;
 
1045
    }
 
1046
}
 
1047
 
 
1048
- (OPGStateRef) OPGState
 
1049
{
 
1050
  return _opGState;
 
1051
}
 
1052
 
 
1053
- (void) setOPGState: (OPGStateRef)opGState
 
1054
{
 
1055
  ASSIGN(_opGState, opGState);
 
1056
}
 
1057
 
 
1058
@end
 
1059
 
 
1060
// MARK: Non-required methods
 
1061
// MARK: -
 
1062
@implementation OpalGState (NonrequiredMethods)
 
1063
 
 
1064
- (void) DPSgsave
 
1065
{
 
1066
  NSDebugLLog(@"OpalGState", @"%p (%@): %s", self, [self class], __PRETTY_FUNCTION__);
 
1067
  if (CGCTX)
 
1068
    {
 
1069
      CGContextSaveGState(CGCTX);
 
1070
    }
 
1071
}
 
1072
 
 
1073
- (void) DPSgrestore
 
1074
{
 
1075
  NSDebugLLog(@"OpalGState", @"%p (%@): %s", self, [self class], __PRETTY_FUNCTION__);
 
1076
  if (CGCTX)
 
1077
    {
 
1078
      CGContextRestoreGState(CGCTX);
 
1079
    }
 
1080
}
 
1081
 
 
1082
@end
 
1083
 
 
1084
@implementation OpalGState (PatternColor)
 
1085
 
 
1086
- (void *) saveClip
 
1087
{
 
1088
  NSDebugLLog(@"OpalGState", @"%p (%@): %s", self, [self class], __PRETTY_FUNCTION__);
 
1089
  CGRect * r = calloc(sizeof(CGRect), 1);
 
1090
  *r = CGContextGetClipBoundingBox(CGCTX);
 
1091
  return r;
 
1092
}
 
1093
 
 
1094
- (void) restoreClip: (void *)savedClip
 
1095
{
 
1096
  NSDebugLLog(@"OpalGState", @"%p (%@): %s", self, [self class], __PRETTY_FUNCTION__);
 
1097
  OPContextResetClip(CGCTX);
 
1098
  CGContextClipToRect(CGCTX, *(CGRect *)savedClip);
 
1099
  free(savedClip);
 
1100
}
 
1101
 
 
1102
@end