4
* Copyright (C) 2003 Free Software Foundation, Inc.
6
* Written by Banlu Kemiyatorn <object at gmail dot com>
7
* Rewrite: Fred Kiefer <fredkiefer@gmx.de>
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.
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.
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.
4
Copyright (C) 2003 Free Software Foundation, Inc.
7
Written by Banlu Kemiyatorn <object at gmail dot com>
8
Rewrite: Fred Kiefer <fredkiefer@gmx.de>
11
This file is part of GNUstep.
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.
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.
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.
25
30
#include <AppKit/NSAffineTransform.h>
26
31
#include <AppKit/NSBezierPath.h>
92
123
CairoGState *copy = (CairoGState *)[super copyWithZone: zone];
97
129
cairo_status_t status;
98
cairo_matrix_t local_matrix;
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);
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
120
134
status = cairo_status(copy->_ct);
121
135
if (status != CAIRO_STATUS_SUCCESS)
123
NSLog(@"Cairo status %s in copy", cairo_status_to_string(status));
137
NSLog(@"Cairo status '%s' in copy", cairo_status_to_string(status));
143
cairo_matrix_t local_matrix;
144
#if CAIRO_VERSION > CAIRO_VERSION_ENCODE(1, 4, 0)
145
cairo_rectangle_list_t *clip_rects;
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)
154
NSLog(@"Cairo status '%s' in set matrix", cairo_status_to_string(status));
157
cpath = cairo_copy_path(_ct);
158
status = cpath->status;
159
if (status != CAIRO_STATUS_SUCCESS)
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).
167
// NSLog(@"Cairo status '%s' in copy path", cairo_status_to_string(status));
171
cairo_append_path(copy->_ct, cpath);
173
cairo_path_destroy(cpath);
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));
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);
190
GS_BEGINITEMBUF(dashes, num_dashes, double);
192
cairo_get_dash(_ct, dashes, &dash_offset);
193
cairo_set_dash (copy->_ct, dashes, num_dashes, dash_offset);
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)
202
NSLog(@"Cairo status '%s' in copy clip", cairo_status_to_string(status));
208
for (i = 0; i < clip_rects->num_rectangles; i++)
210
cairo_rectangle_t rect = clip_rects->rectangles[i];
211
NSSize size = [_surface size];
213
cairo_rectangle(copy->_ct, rect.x,
214
#if CAIRO_VERSION > CAIRO_VERSION_ENCODE(1, 6, 0)
217
// This strange computation is due to the device offset.
218
rect.y + 2*(offset.y - size.height),
220
rect.width, rect.height);
221
cairo_clip(copy->_ct);
224
cairo_rectangle_list_destroy(clip_rects);
132
- (void) GSCurrentDevice: (void **)device: (int *)x : (int *)y
232
- (void) GSCurrentSurface: (CairoSurface **)surface: (int *)x : (int *)y
142
*device = _surface->gsDevice;
151
- (void) GSSetDevice: (void *)device : (int)x : (int)y
244
- (void) GSSetSurface: (CairoSurface *)surface : (int)x : (int)y
154
_surface = [[CairoSurface alloc] initWithDevice: device];
246
ASSIGN(_surface, surface);
155
247
[self setOffset: NSMakePoint(x, y)];
156
248
[self DPSinitgraphics];
159
251
- (void) setOffset: (NSPoint)theOffset
161
NSSize size = {0, 0};
163
253
if (_surface != nil)
165
size = [_surface size];
255
NSSize size = [_surface size];
257
cairo_surface_set_device_offset([_surface surface], -theOffset.x,
258
theOffset.y - size.height);
167
260
[super setOffset: theOffset];
168
cairo_surface_set_device_offset([_surface surface], -theOffset.x,
169
theOffset.y - size.height);
267
cairo_show_page(_ct);
469
cairo_set_miter_limit(_ct, limit);
631
cairo_set_miter_limit(_ct, floatFromUserSpace(ctm, limit));
473
635
- (void) DPSsetstrokeadjust: (int)b
479
641
* Path operations
644
- (void) _adjustPath: (float)offs
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}};
651
int index, last_index;
653
for (i = 0; i < count; i++)
655
type = [path elementAtIndex:i associatedPoints:points];
657
if (type == NSCurveToBezierPathElement) break;
659
points[0].x = floorf(points[0].x) + offs;
660
points[0].y = floorf(points[0].y) + offs;
665
if (type == NSClosePathBezierPathElement)
668
[path elementAtIndex:0 associatedPoints:points];
669
if (fabs(last_points[0].x - points[0].x) < 1.0)
671
last_points[0].x = floorf(last_points[0].x) + offs;
672
points[0].x = last_points[0].x;
674
else if (fabs(last_points[0].y - points[0].y) < 1.0)
676
last_points[0].y = floorf(last_points[0].y) + offs;
677
points[0].y = last_points[0].y;
684
else if (fabs(last_points[0].x - points[0].x) < 1.0)
686
points[0].x = floorf(points[0].x) + offs;
687
points[0].y = floorf(points[0].y);
688
if (type == NSLineToBezierPathElement)
690
last_points[0].x = points[0].x;
693
else if (fabs(last_points[0].y - points[0].y) < 1.0)
695
points[0].x = floorf(points[0].x);
696
points[0].y = floorf(points[0].y) + offs;
697
if (type == NSLineToBezierPathElement)
699
last_points[0].y = points[0].y;
703
// Save adjusted values into NSBezierPath
705
[path setAssociatedPoints:points atIndex:index];
707
[path setAssociatedPoints:last_points atIndex:last_index];
709
last_points[0].x = points[0].x;
710
last_points[0].y = points[0].y;
714
- (void) _setPath: (BOOL)fillOrClip
484
716
unsigned count = [path elementCount];
486
718
SEL elmsel = @selector(elementAtIndex:associatedPoints:);
487
719
IMP elmidx = [path methodForSelector: elmsel];
725
if ((remainderf(cairo_get_line_width(_ct), 2.0) == 0.0)
726
|| fillOrClip == YES)
731
[self _adjustPath:offs];
734
// reset current cairo path
489
736
for (i = 0; i < count; i++)
491
738
NSBezierPathElement type;
494
741
type = (NSBezierPathElement)(*elmidx)(path, elmsel, i, points);
497
case NSMoveToBezierPathElement:
498
cairo_move_to(_ct, points[0].x, points[0].y);
500
case NSLineToBezierPathElement:
501
cairo_line_to(_ct, points[0].x, points[0].y);
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);
508
case NSClosePathBezierPathElement:
509
cairo_close_path(_ct);
744
case NSMoveToBezierPathElement:
745
cairo_move_to(_ct, points[0].x, points[0].y);
747
case NSLineToBezierPathElement:
748
cairo_line_to(_ct, points[0].x, points[0].y);
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);
755
case NSClosePathBezierPathElement:
756
cairo_close_path(_ct);
766
1033
switch (bitsPerPixel)
1036
tmp = objc_malloc(pixels * 4);
1039
NSLog(@"Could not allocate drawing space for image");
769
1043
rowData = (unsigned char *)data[0];
770
tmp = objc_malloc(pixels * 4);
773
1046
for (i = 0; i < pixelsHigh; i++)
775
unsigned char *d = rowData;
1048
unsigned char *d = rowData;
777
for (j = 0; j < pixelsWide; j++)
1050
for (j = 0; j < pixelsWide; j++)
779
1052
#if GS_WORDS_BIGENDIAN
1053
tmp[index++] = d[3];
1054
tmp[index++] = d[0];
1055
tmp[index++] = d[1];
1056
tmp[index++] = d[2];
1058
tmp[index++] = d[2];
1059
tmp[index++] = d[1];
1060
tmp[index++] = d[0];
1061
tmp[index++] = d[3];
792
rowData += bytesPerRow;
1065
rowData += bytesPerRow;
794
1067
format = CAIRO_FORMAT_ARGB32;
1070
tmp = objc_malloc(pixels * 4);
1073
NSLog(@"Could not allocate drawing space for image");
797
1077
rowData = (unsigned char *)data[0];
798
tmp = objc_malloc(pixels * 4);
801
1080
for (i = 0; i < pixelsHigh; i++)
803
unsigned char *d = rowData;
1082
unsigned char *d = rowData;
805
for (j = 0; j < pixelsWide; j++)
1084
for (j = 0; j < pixelsWide; j++)
807
1086
#if GS_WORDS_BIGENDIAN
1088
tmp[index++] = d[0];
1089
tmp[index++] = d[1];
1090
tmp[index++] = d[2];
1092
tmp[index++] = d[2];
1093
tmp[index++] = d[1];
1094
tmp[index++] = d[0];
820
rowData += bytesPerRow;
1099
rowData += bytesPerRow;
822
1101
format = CAIRO_FORMAT_RGB24;
937
1215
cairo_pattern_t *cpattern;
938
1216
cairo_matrix_t local_matrix;
1217
BOOL copyOnSelf = NO;
940
1219
if (!_ct || !source->_ct)
1226
* we check if we copy on ourself, if that's the case
1227
* we'll use the groups trick...
949
1230
src = cairo_get_target(source->_ct);
950
1231
if (src == cairo_get_target(_ct))
953
1233
NSRect targetRect;
955
1235
targetRect.origin = aPoint;
956
1236
targetRect.size = aRect.size;
958
1238
if (!NSIsEmptyRect(NSIntersectionRect(aRect, targetRect)))
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]));
971
With this bit of code enable scrolling works correctly, but images in cells get displayed wrongly.
1246
if (copyOnSelf) cairo_push_group(_ct);
1248
cairo_new_path(_ct);
1251
if (viewIsFlipped && !copyOnSelf)
974
aPoint.y += NSHeight(aRect);
1253
aPoint.y -= aRect.size.height;
1259
newRect.origin = aPoint;
1260
newRect.size = aRect.size;
1261
[ctm boundingRectFor: newRect result: &newRect];
1262
aPoint = newRect.origin;
977
1265
[source->ctm boundingRectFor: aRect result: &aRect];
978
aPoint = [ctm transformPoint: aPoint];
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);