2002-03-27 23:44:41 +00:00
|
|
|
/* GSGState - Generic graphic state
|
|
|
|
|
|
|
|
Copyright (C) 1998 Free Software Foundation, Inc.
|
|
|
|
|
|
|
|
Written by: Adam Fedor <fedor@gnu.org>
|
|
|
|
Date: Mar 2002
|
|
|
|
|
|
|
|
This file is part of the GNU Objective C User Interface Library.
|
|
|
|
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
|
|
modify it under the terms of the GNU Library General Public
|
|
|
|
License as published by the Free Software Foundation; either
|
|
|
|
version 2 of the License, or (at your option) any later version.
|
|
|
|
|
|
|
|
This library is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
Library General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU Library General Public
|
|
|
|
License along with this library; if not, write to the Free
|
|
|
|
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
#include <Foundation/NSObjCRuntime.h>
|
|
|
|
#include <AppKit/NSAffineTransform.h>
|
|
|
|
#include <AppKit/NSBezierPath.h>
|
2002-05-10 15:06:17 +00:00
|
|
|
#include <AppKit/NSColor.h>
|
2002-10-09 03:01:09 +00:00
|
|
|
#include <AppKit/GSFontInfo.h>
|
2002-05-10 15:06:17 +00:00
|
|
|
#include <AppKit/NSGraphics.h>
|
2002-03-27 23:44:41 +00:00
|
|
|
#include "gsc/GSContext.h"
|
|
|
|
#include "gsc/GSGState.h"
|
|
|
|
#include "math.h"
|
|
|
|
|
|
|
|
#define CHECK_PATH \
|
|
|
|
if (!path) \
|
|
|
|
{ \
|
|
|
|
path = [NSBezierPath new]; \
|
|
|
|
}
|
|
|
|
|
2002-05-10 15:06:17 +00:00
|
|
|
/* Just temporary until we improve NSColor */
|
|
|
|
@interface NSColor (PrivateColor)
|
2002-10-09 03:01:09 +00:00
|
|
|
+ colorWithValues: (const float *)values colorSpaceName: colorSpace;
|
2002-05-10 15:06:17 +00:00
|
|
|
@end
|
|
|
|
|
|
|
|
@implementation NSColor (PrivateColor)
|
2002-10-09 03:01:09 +00:00
|
|
|
+ colorWithValues: (const float *)values colorSpaceName: colorSpace
|
2002-05-10 15:06:17 +00:00
|
|
|
{
|
|
|
|
NSColor *color = nil;
|
|
|
|
if ([colorSpace isEqual: NSDeviceWhiteColorSpace])
|
|
|
|
color = [NSColor colorWithDeviceWhite: values[0] alpha: values[1]];
|
|
|
|
else if ([colorSpace isEqual: NSDeviceRGBColorSpace])
|
|
|
|
color = [NSColor colorWithDeviceRed: values[0] green: values[1]
|
|
|
|
blue: values[2] alpha: values[3]];
|
|
|
|
else if ([colorSpace isEqual: NSDeviceCMYKColorSpace])
|
|
|
|
color = [NSColor colorWithDeviceCyan: values[0] magenta: values[1]
|
|
|
|
yellow: values[2] black: values[3] alpha: values[4]];
|
|
|
|
else
|
|
|
|
DPS_ERROR(DPSundefined, @"Cannot convert colorspace");
|
|
|
|
return color;
|
|
|
|
}
|
|
|
|
@end
|
|
|
|
|
|
|
|
|
|
|
|
|
2002-03-27 23:44:41 +00:00
|
|
|
@implementation GSGState
|
|
|
|
|
|
|
|
/* Designated initializer. */
|
|
|
|
- initWithDrawContext: (GSContext *)drawContext
|
|
|
|
{
|
|
|
|
[super init];
|
|
|
|
|
|
|
|
drawcontext = drawContext;
|
|
|
|
offset = NSMakePoint(0, 0);
|
2002-05-10 15:06:17 +00:00
|
|
|
path = nil;
|
|
|
|
font = nil;
|
|
|
|
fillColorS = nil;
|
|
|
|
strokeColorS = nil;
|
2002-05-13 03:34:47 +00:00
|
|
|
[self DPSinitgraphics];
|
2002-03-27 23:44:41 +00:00
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) dealloc
|
|
|
|
{
|
|
|
|
TEST_RELEASE(font);
|
|
|
|
TEST_RELEASE(path);
|
|
|
|
RELEASE(ctm);
|
2002-05-10 15:06:17 +00:00
|
|
|
RELEASE(textCtm);
|
|
|
|
RELEASE(fillColorS);
|
|
|
|
RELEASE(strokeColorS);
|
2002-03-27 23:44:41 +00:00
|
|
|
[super dealloc];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (id) deepen
|
|
|
|
{
|
|
|
|
NSZone *zone = GSObjCZone(self);
|
|
|
|
|
|
|
|
if (path)
|
|
|
|
self->path = [path copyWithZone: zone];
|
|
|
|
|
2002-05-10 15:06:17 +00:00
|
|
|
self->ctm = [ctm copyWithZone: zone];
|
|
|
|
self->textCtm = [ctm copyWithZone: zone];
|
2002-03-27 23:44:41 +00:00
|
|
|
|
2002-05-10 15:06:17 +00:00
|
|
|
// Just retain the other objects
|
2002-03-27 23:44:41 +00:00
|
|
|
if (font != nil)
|
|
|
|
RETAIN(font);
|
2002-05-10 15:06:17 +00:00
|
|
|
if (fillColorS != nil)
|
|
|
|
RETAIN(fillColorS);
|
|
|
|
if (strokeColorS != nil)
|
|
|
|
RETAIN(strokeColorS);
|
2002-03-27 23:44:41 +00:00
|
|
|
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
|
|
|
- copyWithZone: (NSZone *)zone
|
|
|
|
{
|
|
|
|
GSGState *new = (GSGState *)NSCopyObject(self, 0, zone);
|
|
|
|
/* Do a deep copy since gstates are isolated from each other */
|
|
|
|
return [new deepen];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) setOffset: (NSPoint)theOffset
|
|
|
|
{
|
|
|
|
offset = theOffset;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (NSPoint) offset
|
|
|
|
{
|
|
|
|
return offset;
|
|
|
|
}
|
|
|
|
|
2002-05-10 15:06:17 +00:00
|
|
|
/** Subclasses should override this method to be notified of changes
|
|
|
|
in the current color */
|
2002-08-25 18:54:07 +00:00
|
|
|
- (void) setColor: (device_color_t *)color state: (color_state_t)cState
|
2002-05-10 15:06:17 +00:00
|
|
|
{
|
|
|
|
float alpha;
|
|
|
|
alpha = fillColor.field[AINDEX];
|
|
|
|
if (cState & COLOR_FILL)
|
2002-08-25 18:54:07 +00:00
|
|
|
fillColor = *color;
|
2002-05-10 15:06:17 +00:00
|
|
|
fillColor.field[AINDEX] = alpha;
|
|
|
|
alpha = strokeColor.field[AINDEX];
|
|
|
|
if (cState & COLOR_STROKE)
|
2002-08-25 18:54:07 +00:00
|
|
|
strokeColor = *color;
|
2002-05-10 15:06:17 +00:00
|
|
|
strokeColor.field[AINDEX] = alpha;
|
|
|
|
cstate = cState;
|
|
|
|
}
|
|
|
|
|
2002-03-27 23:44:41 +00:00
|
|
|
- (void) compositeGState: (GSGState *)source
|
|
|
|
fromRect: (NSRect)aRect
|
|
|
|
toPoint: (NSPoint)aPoint
|
|
|
|
op: (NSCompositingOperation)op
|
|
|
|
{
|
|
|
|
[self subclassResponsibility: _cmd];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) dissolveGState: (GSGState *)source
|
|
|
|
fromRect: (NSRect)aRect
|
|
|
|
toPoint: (NSPoint)aPoint
|
|
|
|
delta: (float)delta
|
|
|
|
{
|
|
|
|
[self subclassResponsibility: _cmd];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) compositerect: (NSRect)aRect
|
|
|
|
op: (NSCompositingOperation)op
|
|
|
|
{
|
|
|
|
[self subclassResponsibility: _cmd];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (NSPoint) pointInMatrixSpace: (NSPoint)aPoint
|
|
|
|
{
|
|
|
|
return [ctm pointInMatrixSpace: aPoint];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (NSPoint) deltaPointInMatrixSpace: (NSPoint)aPoint
|
|
|
|
{
|
|
|
|
return [ctm deltaPointInMatrixSpace: aPoint];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (NSRect) rectInMatrixSpace: (NSRect)rect
|
|
|
|
{
|
|
|
|
return [ctm rectInMatrixSpace: rect];
|
|
|
|
}
|
|
|
|
|
|
|
|
@end
|
|
|
|
|
|
|
|
@implementation GSGState (Ops)
|
|
|
|
|
|
|
|
/* ----------------------------------------------------------------------- */
|
|
|
|
/* Color operations */
|
|
|
|
/* ----------------------------------------------------------------------- */
|
|
|
|
- (void) DPScurrentalpha: (float*)a
|
|
|
|
{
|
2002-05-10 15:06:17 +00:00
|
|
|
*a = fillColor.field[AINDEX];
|
2002-03-27 23:44:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void) DPScurrentcmykcolor: (float*)c : (float*)m : (float*)y : (float*)k
|
|
|
|
{
|
2002-05-10 15:06:17 +00:00
|
|
|
device_color_t new = fillColor;
|
2002-08-25 18:54:07 +00:00
|
|
|
gsColorToCMYK(&new);
|
2002-05-10 15:06:17 +00:00
|
|
|
*c = new.field[0];
|
|
|
|
*m = new.field[1];
|
|
|
|
*y = new.field[2];
|
|
|
|
*k = new.field[3];
|
2002-03-27 23:44:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void) DPScurrentgray: (float*)gray
|
|
|
|
{
|
2002-08-25 18:54:07 +00:00
|
|
|
device_color_t gcolor = fillColor;
|
|
|
|
gsColorToGray(&gcolor);
|
2002-05-10 15:06:17 +00:00
|
|
|
*gray = gcolor.field[0];
|
2002-03-27 23:44:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void) DPScurrenthsbcolor: (float*)h : (float*)s : (float*)b
|
|
|
|
{
|
2002-08-25 18:54:07 +00:00
|
|
|
device_color_t gcolor = fillColor;
|
|
|
|
gsColorToHSB(&gcolor);
|
2002-05-10 15:06:17 +00:00
|
|
|
*h = gcolor.field[0]; *s = gcolor.field[1]; *b = gcolor.field[2];
|
2002-03-27 23:44:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void) DPScurrentrgbcolor: (float*)r : (float*)g : (float*)b
|
|
|
|
{
|
2002-08-25 18:54:07 +00:00
|
|
|
device_color_t gcolor = fillColor;
|
|
|
|
gsColorToRGB(&gcolor);
|
2002-05-10 15:06:17 +00:00
|
|
|
*r = gcolor.field[0]; *g = gcolor.field[1]; *b = gcolor.field[2];
|
2002-03-27 23:44:41 +00:00
|
|
|
}
|
|
|
|
|
2002-05-13 03:09:21 +00:00
|
|
|
#define CLAMP(x) \
|
|
|
|
if (x < 0.0) x = 0.0; \
|
|
|
|
if (x > 1.0) x = 1.0;
|
|
|
|
|
2002-03-27 23:44:41 +00:00
|
|
|
- (void) DPSsetalpha: (float)a
|
|
|
|
{
|
2002-05-13 03:09:21 +00:00
|
|
|
CLAMP(a)
|
2002-05-10 15:06:17 +00:00
|
|
|
fillColor.field[AINDEX] = strokeColor.field[AINDEX] = a;
|
2002-08-25 18:54:07 +00:00
|
|
|
[self setColor: &fillColor state: COLOR_FILL];
|
|
|
|
[self setColor: &strokeColor state: COLOR_STROKE];
|
2002-03-27 23:44:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void) DPSsetcmykcolor: (float)c : (float)m : (float)y : (float)k
|
|
|
|
{
|
2002-08-25 18:54:07 +00:00
|
|
|
device_color_t col;
|
2002-05-13 03:09:21 +00:00
|
|
|
CLAMP(c)
|
|
|
|
CLAMP(m)
|
|
|
|
CLAMP(y)
|
|
|
|
CLAMP(k)
|
2002-08-25 18:54:07 +00:00
|
|
|
gsMakeColor(&col, cmyk_colorspace, c, m, y, k);
|
|
|
|
[self setColor: &col state: COLOR_BOTH];
|
2002-03-27 23:44:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void) DPSsetgray: (float)gray
|
|
|
|
{
|
2002-08-25 18:54:07 +00:00
|
|
|
device_color_t col;
|
2002-05-13 03:09:21 +00:00
|
|
|
CLAMP(gray)
|
2002-08-25 18:54:07 +00:00
|
|
|
gsMakeColor(&col, gray_colorspace, gray, 0, 0, 0);
|
|
|
|
[self setColor: &col state: COLOR_BOTH];
|
2002-03-27 23:44:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void) DPSsethsbcolor: (float)h : (float)s : (float)b
|
|
|
|
{
|
2002-08-25 18:54:07 +00:00
|
|
|
device_color_t col;
|
2002-05-13 03:09:21 +00:00
|
|
|
CLAMP(h)
|
|
|
|
CLAMP(s)
|
|
|
|
CLAMP(b)
|
2002-08-25 18:54:07 +00:00
|
|
|
gsMakeColor(&col, hsb_colorspace, h, s, b, 0);
|
|
|
|
[self setColor: &col state: COLOR_BOTH];
|
2002-03-27 23:44:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void) DPSsetrgbcolor: (float)r : (float)g : (float)b
|
|
|
|
{
|
2002-08-25 18:54:07 +00:00
|
|
|
device_color_t col;
|
2002-05-13 03:09:21 +00:00
|
|
|
CLAMP(r)
|
|
|
|
CLAMP(g)
|
|
|
|
CLAMP(b)
|
2002-08-25 18:54:07 +00:00
|
|
|
gsMakeColor(&col, rgb_colorspace, r, g, b, 0);
|
|
|
|
[self setColor: &col state: COLOR_BOTH];
|
2002-03-27 23:44:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-10-09 03:01:09 +00:00
|
|
|
- (void) GSSetFillColorspace: (void *)spaceref
|
2002-03-27 23:44:41 +00:00
|
|
|
{
|
2002-08-25 18:54:07 +00:00
|
|
|
device_color_t col;
|
2002-05-10 15:06:17 +00:00
|
|
|
float values[6];
|
2002-10-09 03:01:09 +00:00
|
|
|
NSDictionary *dict = (NSDictionary *)spaceref;
|
2002-05-10 15:06:17 +00:00
|
|
|
NSString *colorSpace = [dict objectForKey: GSColorSpaceName];
|
|
|
|
if (fillColorS)
|
|
|
|
RELEASE(fillColorS);
|
|
|
|
memset(values, 0, sizeof(float)*6);
|
|
|
|
fillColorS = [NSColor colorWithValues: values colorSpaceName:colorSpace];
|
|
|
|
RETAIN(fillColorS);
|
2002-08-25 18:54:07 +00:00
|
|
|
gsMakeColor(&col, rgb_colorspace, 0, 0, 0, 0);
|
|
|
|
[self setColor: &col state: COLOR_FILL];
|
2002-03-27 23:44:41 +00:00
|
|
|
}
|
|
|
|
|
2002-10-09 03:01:09 +00:00
|
|
|
- (void) GSSetStrokeColorspace: (void *)spaceref
|
2002-03-27 23:44:41 +00:00
|
|
|
{
|
2002-08-25 18:54:07 +00:00
|
|
|
device_color_t col;
|
2002-05-10 15:06:17 +00:00
|
|
|
float values[6];
|
2002-10-09 03:01:09 +00:00
|
|
|
NSDictionary *dict = (NSDictionary *)spaceref;
|
2002-05-10 15:06:17 +00:00
|
|
|
NSString *colorSpace = [dict objectForKey: GSColorSpaceName];
|
|
|
|
if (strokeColorS)
|
|
|
|
RELEASE(strokeColorS);
|
|
|
|
memset(values, 0, sizeof(float)*6);
|
|
|
|
strokeColorS = [NSColor colorWithValues: values colorSpaceName:colorSpace];
|
|
|
|
RETAIN(strokeColorS);
|
2002-08-25 18:54:07 +00:00
|
|
|
gsMakeColor(&col, rgb_colorspace, 0, 0, 0, 0);
|
|
|
|
[self setColor: &col state: COLOR_STROKE];
|
2002-03-27 23:44:41 +00:00
|
|
|
}
|
|
|
|
|
2002-10-09 03:01:09 +00:00
|
|
|
- (void) GSSetFillColor: (const float *)values
|
2002-03-27 23:44:41 +00:00
|
|
|
{
|
2002-05-10 15:06:17 +00:00
|
|
|
device_color_t dcolor;
|
|
|
|
NSColor *color;
|
|
|
|
NSString *colorSpace;
|
|
|
|
if (fillColorS == nil)
|
|
|
|
{
|
|
|
|
DPS_ERROR(DPSundefined, @"No fill colorspace defined, assume DeviceRGB");
|
|
|
|
colorSpace = NSDeviceRGBColorSpace;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
colorSpace = [fillColorS colorSpaceName];
|
|
|
|
RELEASE(fillColorS);
|
|
|
|
fillColorS = [NSColor colorWithValues: values colorSpaceName:colorSpace];
|
|
|
|
RETAIN(fillColorS);
|
|
|
|
color = [fillColorS colorUsingColorSpaceName: NSDeviceRGBColorSpace];
|
|
|
|
[color getRed: &dcolor.field[0]
|
|
|
|
green: &dcolor.field[1]
|
|
|
|
blue: &dcolor.field[2]
|
|
|
|
alpha: &dcolor.field[AINDEX]];
|
2002-08-25 18:54:07 +00:00
|
|
|
[self setColor: &dcolor state: COLOR_FILL];
|
2002-03-27 23:44:41 +00:00
|
|
|
}
|
|
|
|
|
2002-10-09 03:01:09 +00:00
|
|
|
- (void) GSSetStrokeColor: (const float *)values
|
2002-03-27 23:44:41 +00:00
|
|
|
{
|
2002-05-10 15:06:17 +00:00
|
|
|
device_color_t dcolor;
|
|
|
|
NSColor *color;
|
|
|
|
NSString *colorSpace;
|
|
|
|
if (strokeColorS == nil)
|
|
|
|
{
|
|
|
|
DPS_ERROR(DPSundefined, @"No stroke colorspace defined, assume DeviceRGB");
|
|
|
|
colorSpace = NSDeviceRGBColorSpace;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
colorSpace = [strokeColorS colorSpaceName];
|
|
|
|
RELEASE(strokeColorS);
|
|
|
|
strokeColorS = [NSColor colorWithValues: values colorSpaceName:colorSpace];
|
|
|
|
RETAIN(strokeColorS);
|
|
|
|
color = [strokeColorS colorUsingColorSpaceName: NSDeviceRGBColorSpace];
|
|
|
|
[color getRed: &dcolor.field[0]
|
|
|
|
green: &dcolor.field[1]
|
|
|
|
blue: &dcolor.field[2]
|
|
|
|
alpha: &dcolor.field[AINDEX]];
|
2002-08-25 18:54:07 +00:00
|
|
|
[self setColor: &dcolor state: COLOR_STROKE];
|
2002-03-27 23:44:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* ----------------------------------------------------------------------- */
|
|
|
|
/* Text operations */
|
|
|
|
/* ----------------------------------------------------------------------- */
|
|
|
|
- (void) DPSashow: (float)x : (float)y : (const char*)s
|
|
|
|
{
|
|
|
|
[self subclassResponsibility: _cmd];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) DPSawidthshow: (float)cx : (float)cy : (int)c : (float)ax : (float)ay
|
|
|
|
: (const char*)s
|
|
|
|
{
|
|
|
|
[self subclassResponsibility: _cmd];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) DPScharpath: (const char*)s : (int)b
|
|
|
|
{
|
|
|
|
[self subclassResponsibility: _cmd];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) DPSshow: (const char*)s
|
|
|
|
{
|
|
|
|
[self subclassResponsibility: _cmd];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) DPSwidthshow: (float)x : (float)y : (int)c : (const char*)s
|
|
|
|
{
|
|
|
|
[self subclassResponsibility: _cmd];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) DPSxshow: (const char*)s : (const float*)numarray : (int)size
|
|
|
|
{
|
|
|
|
[self subclassResponsibility: _cmd];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) DPSxyshow: (const char*)s : (const float*)numarray : (int)size
|
|
|
|
{
|
|
|
|
[self subclassResponsibility: _cmd];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) DPSyshow: (const char*)s : (const float*)numarray : (int)size
|
|
|
|
{
|
|
|
|
[self subclassResponsibility: _cmd];
|
|
|
|
}
|
|
|
|
|
2002-05-10 15:06:17 +00:00
|
|
|
- (void) GSSetCharacterSpacing: (float)extra
|
|
|
|
{
|
|
|
|
charSpacing = extra;
|
|
|
|
}
|
|
|
|
|
2002-10-09 03:01:09 +00:00
|
|
|
- (void) GSSetFont: (GSFontInfo *)fontref
|
2002-05-10 15:06:17 +00:00
|
|
|
{
|
2002-10-09 03:01:09 +00:00
|
|
|
if (font == fontref)
|
2002-05-10 15:06:17 +00:00
|
|
|
return;
|
2002-10-09 03:01:09 +00:00
|
|
|
ASSIGN(font, fontref);
|
2002-05-10 15:06:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void) GSSetFontSize: (float)size
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
- (NSAffineTransform *) GSGetTextCTM
|
|
|
|
{
|
|
|
|
return textCtm;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (NSPoint) GSGetTextPosition
|
|
|
|
{
|
|
|
|
return [textCtm pointInMatrixSpace: NSMakePoint(0,0)];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) GSSetTextCTM: (NSAffineTransform *)newCtm
|
|
|
|
{
|
|
|
|
ASSIGN(textCtm, newCtm);
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) GSSetTextDrawingMode: (GSTextDrawingMode)mode
|
|
|
|
{
|
|
|
|
textMode = mode;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) GSSetTextPosition: (NSPoint)loc
|
|
|
|
{
|
|
|
|
[textCtm translateToPoint: loc];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) GSShowText: (const char *)string : (size_t) length
|
|
|
|
{
|
|
|
|
[self subclassResponsibility: _cmd];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) GSShowGlyphs: (const NSGlyph *)glyphs : (size_t) length
|
|
|
|
{
|
|
|
|
[self subclassResponsibility: _cmd];
|
|
|
|
}
|
|
|
|
|
2002-03-27 23:44:41 +00:00
|
|
|
|
|
|
|
/* ----------------------------------------------------------------------- */
|
|
|
|
/* Gstate operations */
|
|
|
|
/* ----------------------------------------------------------------------- */
|
|
|
|
- (void) DPSinitgraphics
|
|
|
|
{
|
2002-05-13 03:34:47 +00:00
|
|
|
DESTROY(path);
|
|
|
|
DESTROY(font);
|
|
|
|
DESTROY(fillColorS);
|
|
|
|
DESTROY(strokeColorS);
|
|
|
|
if (ctm)
|
|
|
|
[ctm makeIdentityMatrix];
|
|
|
|
else
|
|
|
|
ctm = [[NSAffineTransform allocWithZone: GSObjCZone(self)] init];
|
|
|
|
|
|
|
|
/* Initialize colors. By default the same color is used for filling and
|
|
|
|
stroking unless fill and/or stroke color is set explicitly */
|
2002-08-25 18:54:07 +00:00
|
|
|
gsMakeColor(&fillColor, gray_colorspace, 0, 0, 0, 0);
|
2002-05-13 03:34:47 +00:00
|
|
|
fillColor.field[AINDEX] = 1.0;
|
|
|
|
strokeColor.field[AINDEX] = 1.0;
|
2002-08-25 18:54:07 +00:00
|
|
|
[self setColor: &fillColor state: COLOR_BOTH];
|
2002-05-13 03:34:47 +00:00
|
|
|
|
|
|
|
charSpacing = 0;
|
|
|
|
textMode = GSTextFill;
|
|
|
|
if (textCtm)
|
|
|
|
[textCtm makeIdentityMatrix];
|
|
|
|
else
|
|
|
|
textCtm = [[NSAffineTransform allocWithZone: GSObjCZone(self)] init];
|
2002-03-27 23:44:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void)DPScurrentflat: (float *)flatness
|
|
|
|
{
|
|
|
|
if (path)
|
|
|
|
*flatness = [path flatness];
|
|
|
|
else
|
|
|
|
*flatness = 1.0;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) DPScurrentlinecap: (int*)linecap
|
|
|
|
{
|
|
|
|
[self subclassResponsibility: _cmd];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) DPScurrentlinejoin: (int*)linejoin
|
|
|
|
{
|
|
|
|
[self subclassResponsibility: _cmd];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) DPScurrentlinewidth: (float*)width
|
|
|
|
{
|
|
|
|
[self subclassResponsibility: _cmd];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) DPScurrentmiterlimit: (float*)limit
|
|
|
|
{
|
|
|
|
[self subclassResponsibility: _cmd];
|
|
|
|
}
|
|
|
|
|
2002-08-28 22:04:23 +00:00
|
|
|
- (NSPoint) currentPoint
|
2002-03-27 23:44:41 +00:00
|
|
|
{
|
|
|
|
NSAffineTransform *ictm;
|
|
|
|
NSPoint user;
|
|
|
|
|
2002-08-28 22:04:23 +00:00
|
|
|
if (path == nil)
|
|
|
|
{
|
|
|
|
return NSMakePoint(0, 0);
|
|
|
|
}
|
|
|
|
|
2002-03-27 23:44:41 +00:00
|
|
|
// This is rather slow, but it is not used very often
|
|
|
|
ictm = [ctm copyWithZone: GSObjCZone(self)];
|
2002-06-22 15:41:58 +00:00
|
|
|
[ictm invert];
|
2002-08-28 22:04:23 +00:00
|
|
|
user = [ictm transformPoint: [path currentPoint]];
|
2002-03-27 23:44:41 +00:00
|
|
|
RELEASE(ictm);
|
2002-08-28 22:04:23 +00:00
|
|
|
return user;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)DPScurrentpoint: (float *)x : (float *)y
|
|
|
|
{
|
|
|
|
NSPoint user;
|
|
|
|
|
|
|
|
user = [self currentPoint];
|
2002-03-27 23:44:41 +00:00
|
|
|
*x = user.x;
|
|
|
|
*y = user.y;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) DPScurrentstrokeadjust: (int*)b
|
|
|
|
{
|
|
|
|
[self subclassResponsibility: _cmd];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) DPSsetdash: (const float*)pat : (int)size : (float)offset
|
|
|
|
{
|
|
|
|
[self subclassResponsibility: _cmd];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)DPSsetflat: (float)flatness
|
|
|
|
{
|
|
|
|
if (path)
|
|
|
|
[path setFlatness: flatness];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) DPSsetlinecap: (int)linecap
|
|
|
|
{
|
|
|
|
[self subclassResponsibility: _cmd];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) DPSsetlinejoin: (int)linejoin
|
|
|
|
{
|
|
|
|
[self subclassResponsibility: _cmd];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) DPSsetlinewidth: (float)width
|
|
|
|
{
|
|
|
|
[self subclassResponsibility: _cmd];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) DPSsetmiterlimit: (float)limit
|
|
|
|
{
|
|
|
|
[self subclassResponsibility: _cmd];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) DPSsetstrokeadjust: (int)b
|
|
|
|
{
|
|
|
|
[self subclassResponsibility: _cmd];
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ----------------------------------------------------------------------- */
|
|
|
|
/* Matrix operations */
|
|
|
|
/* ----------------------------------------------------------------------- */
|
|
|
|
- (void)DPSconcat: (const float *)m
|
|
|
|
{
|
|
|
|
[ctm concatenateWithMatrix: m];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)DPSinitmatrix
|
|
|
|
{
|
|
|
|
[ctm makeIdentityMatrix];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)DPSrotate: (float)angle
|
|
|
|
{
|
|
|
|
[ctm rotateByDegrees: angle];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)DPSscale: (float)x : (float)y
|
|
|
|
{
|
2002-06-22 15:41:58 +00:00
|
|
|
[ctm scaleXBy: x yBy: y];
|
2002-03-27 23:44:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void)DPStranslate: (float)x : (float)y
|
|
|
|
{
|
|
|
|
[ctm translateToPoint: NSMakePoint(x, y)];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (NSAffineTransform *) GSCurrentCTM
|
|
|
|
{
|
|
|
|
return [ctm copy];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) GSSetCTM: (NSAffineTransform *)newctm
|
|
|
|
{
|
|
|
|
ASSIGN(ctm, newctm);
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) GSConcatCTM: (NSAffineTransform *)newctm
|
|
|
|
{
|
|
|
|
[ctm concatenateWith: newctm];
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ----------------------------------------------------------------------- */
|
|
|
|
/* Paint operations */
|
|
|
|
/* ----------------------------------------------------------------------- */
|
|
|
|
- (void) DPSarc: (float)x : (float)y : (float)r : (float)angle1 : (float)angle2
|
|
|
|
{
|
2002-08-28 22:04:23 +00:00
|
|
|
NSBezierPath *newPath;
|
2002-03-27 23:44:41 +00:00
|
|
|
|
2002-08-28 22:04:23 +00:00
|
|
|
newPath = [[NSBezierPath alloc] init];
|
|
|
|
if ((path != nil) && ([path elementCount] != 0))
|
|
|
|
{
|
|
|
|
[newPath lineToPoint: [self currentPoint]];
|
|
|
|
}
|
|
|
|
[newPath appendBezierPathWithArcWithCenter: NSMakePoint(x, y)
|
|
|
|
radius: r
|
|
|
|
startAngle: angle1
|
|
|
|
endAngle: angle2
|
|
|
|
clockwise: NO];
|
|
|
|
[newPath transformUsingAffineTransform: ctm];
|
2002-03-27 23:44:41 +00:00
|
|
|
CHECK_PATH;
|
2002-08-28 22:04:23 +00:00
|
|
|
[path appendBezierPath: newPath];
|
|
|
|
RELEASE(newPath);
|
2002-03-27 23:44:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void) DPSarcn: (float)x : (float)y : (float)r : (float)angle1 : (float)angle2
|
|
|
|
{
|
2002-08-28 22:04:23 +00:00
|
|
|
NSBezierPath *newPath;
|
2002-03-27 23:44:41 +00:00
|
|
|
|
2002-08-28 22:04:23 +00:00
|
|
|
newPath = [[NSBezierPath alloc] init];
|
|
|
|
if ((path != nil) && ([path elementCount] != 0))
|
|
|
|
{
|
|
|
|
[newPath lineToPoint: [self currentPoint]];
|
|
|
|
}
|
|
|
|
[newPath appendBezierPathWithArcWithCenter: NSMakePoint(x, y)
|
|
|
|
radius: r
|
|
|
|
startAngle: angle1
|
|
|
|
endAngle: angle2
|
|
|
|
clockwise: YES];
|
|
|
|
[newPath transformUsingAffineTransform: ctm];
|
2002-03-27 23:44:41 +00:00
|
|
|
CHECK_PATH;
|
2002-08-28 22:04:23 +00:00
|
|
|
[path appendBezierPath: newPath];
|
|
|
|
RELEASE(newPath);
|
2002-03-27 23:44:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void)DPSarct: (float)x1 : (float)y1 : (float)x2 : (float)y2 : (float)r
|
|
|
|
{
|
2002-08-28 22:04:23 +00:00
|
|
|
NSBezierPath *newPath;
|
|
|
|
|
|
|
|
newPath = [[NSBezierPath alloc] init];
|
|
|
|
if ((path != nil) && ([path elementCount] != 0))
|
|
|
|
{
|
|
|
|
[newPath lineToPoint: [self currentPoint]];
|
|
|
|
}
|
|
|
|
[newPath appendBezierPathWithArcFromPoint: NSMakePoint(x1, y1)
|
|
|
|
toPoint: NSMakePoint(x2, y2)
|
|
|
|
radius: r];
|
|
|
|
[newPath transformUsingAffineTransform: ctm];
|
|
|
|
CHECK_PATH;
|
|
|
|
[path appendBezierPath: newPath];
|
|
|
|
RELEASE(newPath);
|
2002-03-27 23:44:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void) DPSclip
|
|
|
|
{
|
|
|
|
[self subclassResponsibility: _cmd];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)DPSclosepath
|
|
|
|
{
|
|
|
|
CHECK_PATH;
|
|
|
|
[path closePath];
|
|
|
|
}
|
|
|
|
|
2002-05-10 15:06:17 +00:00
|
|
|
- (void)DPScurveto: (float)x1 : (float)y1 : (float)x2 : (float)y2 : (float)x3
|
|
|
|
: (float)y3
|
2002-03-27 23:44:41 +00:00
|
|
|
{
|
|
|
|
NSPoint p1 = [ctm pointInMatrixSpace: NSMakePoint(x1, y1)];
|
|
|
|
NSPoint p2 = [ctm pointInMatrixSpace: NSMakePoint(x2, y2)];
|
|
|
|
NSPoint p3 = [ctm pointInMatrixSpace: NSMakePoint(x3, y3)];
|
|
|
|
|
|
|
|
CHECK_PATH;
|
|
|
|
[path curveToPoint: p3 controlPoint1: p1 controlPoint2: p2];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) DPSeoclip
|
|
|
|
{
|
|
|
|
[self subclassResponsibility: _cmd];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) DPSeofill
|
|
|
|
{
|
|
|
|
[self subclassResponsibility: _cmd];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) DPSfill
|
|
|
|
{
|
|
|
|
[self subclassResponsibility: _cmd];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)DPSflattenpath
|
|
|
|
{
|
|
|
|
if (path)
|
|
|
|
ASSIGN(path, [path bezierPathByFlatteningPath]);
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) DPSinitclip;
|
|
|
|
{
|
|
|
|
[self subclassResponsibility: _cmd];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)DPSlineto: (float)x : (float)y
|
|
|
|
{
|
|
|
|
NSPoint p = [ctm pointInMatrixSpace: NSMakePoint(x, y)];
|
|
|
|
|
|
|
|
CHECK_PATH;
|
|
|
|
[path lineToPoint: p];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)DPSmoveto: (float)x : (float)y
|
|
|
|
{
|
|
|
|
NSPoint p = [ctm pointInMatrixSpace: NSMakePoint(x, y)];
|
|
|
|
|
|
|
|
CHECK_PATH;
|
|
|
|
[path moveToPoint: p];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)DPSnewpath
|
|
|
|
{
|
|
|
|
if (path)
|
|
|
|
[path removeAllPoints];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)DPSpathbbox: (float *)llx : (float *)lly : (float *)urx : (float *)ury
|
|
|
|
{
|
|
|
|
if (path)
|
|
|
|
{
|
|
|
|
NSRect rect = [path controlPointBounds];
|
|
|
|
|
|
|
|
// FIXME Should convert back to user space
|
|
|
|
if (llx)
|
|
|
|
*llx = NSMinX(rect);
|
|
|
|
if (lly)
|
|
|
|
*lly = NSMinY(rect);
|
|
|
|
if (urx)
|
|
|
|
*urx = NSMaxX(rect);
|
|
|
|
if (ury)
|
|
|
|
*ury = NSMaxY(rect);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-05-10 15:06:17 +00:00
|
|
|
- (void)DPSrcurveto: (float)x1 : (float)y1 : (float)x2 : (float)y2 : (float)x3
|
|
|
|
: (float)y3
|
2002-03-27 23:44:41 +00:00
|
|
|
{
|
|
|
|
NSPoint p1 = [ctm deltaPointInMatrixSpace: NSMakePoint(x1, y1)];
|
|
|
|
NSPoint p2 = [ctm deltaPointInMatrixSpace: NSMakePoint(x2, y2)];
|
|
|
|
NSPoint p3 = [ctm deltaPointInMatrixSpace: NSMakePoint(x3, y3)];
|
|
|
|
|
|
|
|
CHECK_PATH;
|
|
|
|
[path relativeCurveToPoint: p3
|
|
|
|
controlPoint1: p1
|
|
|
|
controlPoint2: p2];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) DPSrectclip: (float)x : (float)y : (float)w : (float)h
|
|
|
|
{
|
2002-06-07 23:19:41 +00:00
|
|
|
NSRect rect = [ctm rectInMatrixSpace: NSMakeRect(x, y, w, h)];
|
|
|
|
NSBezierPath *oldPath = path;
|
2002-06-04 13:21:33 +00:00
|
|
|
|
2002-06-07 23:19:41 +00:00
|
|
|
path = [NSBezierPath bezierPathWithRect: rect];
|
2002-06-04 13:21:33 +00:00
|
|
|
[self DPSclip];
|
2002-06-07 23:19:41 +00:00
|
|
|
path = oldPath;
|
2002-03-27 23:44:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void) DPSrectfill: (float)x : (float)y : (float)w : (float)h
|
|
|
|
{
|
2002-06-07 23:19:41 +00:00
|
|
|
NSRect rect = [ctm rectInMatrixSpace: NSMakeRect(x, y, w, h)];
|
|
|
|
NSBezierPath *oldPath = path;
|
2002-06-04 13:21:33 +00:00
|
|
|
|
2002-06-07 23:19:41 +00:00
|
|
|
path = [NSBezierPath bezierPathWithRect: rect];
|
2002-06-04 13:21:33 +00:00
|
|
|
[self DPSfill];
|
2002-06-07 23:19:41 +00:00
|
|
|
path = oldPath;
|
2002-03-27 23:44:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void) DPSrectstroke: (float)x : (float)y : (float)w : (float)h
|
|
|
|
{
|
2002-06-07 23:19:41 +00:00
|
|
|
NSRect rect = [ctm rectInMatrixSpace: NSMakeRect(x, y, w, h)];
|
|
|
|
NSBezierPath *oldPath = path;
|
2002-06-04 13:21:33 +00:00
|
|
|
|
2002-06-07 23:19:41 +00:00
|
|
|
path = [NSBezierPath bezierPathWithRect: rect];
|
2002-06-04 13:21:33 +00:00
|
|
|
[self DPSstroke];
|
2002-06-07 23:19:41 +00:00
|
|
|
path = oldPath;
|
2002-03-27 23:44:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void)DPSreversepath
|
|
|
|
{
|
|
|
|
if (path)
|
|
|
|
ASSIGN(path, [path bezierPathByReversingPath]);
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)DPSrlineto: (float)x : (float)y
|
|
|
|
{
|
|
|
|
NSPoint p = [ctm deltaPointInMatrixSpace: NSMakePoint(x, y)];
|
|
|
|
|
|
|
|
CHECK_PATH;
|
|
|
|
[path relativeLineToPoint: p];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)DPSrmoveto: (float)x : (float)y
|
|
|
|
{
|
|
|
|
NSPoint p = [ctm deltaPointInMatrixSpace: NSMakePoint(x, y)];
|
|
|
|
|
|
|
|
CHECK_PATH;
|
|
|
|
[path relativeMoveToPoint: p];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) DPSstroke;
|
|
|
|
{
|
|
|
|
[self subclassResponsibility: _cmd];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) GSSendBezierPath: (NSBezierPath *)newpath
|
|
|
|
{
|
2002-03-29 19:25:35 +00:00
|
|
|
CHECK_PATH;
|
|
|
|
[path appendBezierPath: path];
|
2002-03-27 23:44:41 +00:00
|
|
|
}
|
|
|
|
|
2002-04-01 20:22:07 +00:00
|
|
|
- (void) GSRectClipList: (const NSRect *)rects : (int) count
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
NSRect union_rect;
|
|
|
|
|
|
|
|
if (count == 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/*
|
|
|
|
The specification is not clear if the union of the rects
|
|
|
|
should produce the new clip rect or if the outline of all rects
|
|
|
|
should be used as clip path.
|
|
|
|
*/
|
|
|
|
union_rect = rects[0];
|
|
|
|
for (i = 1; i < count; i++)
|
|
|
|
union_rect = NSUnionRect(union_rect, rects[i]);
|
|
|
|
|
|
|
|
[self DPSrectclip: NSMinX(union_rect) : NSMinY(union_rect)
|
|
|
|
: NSWidth(union_rect) : NSHeight(union_rect)];
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-03-27 23:44:41 +00:00
|
|
|
- (void) GSRectFillList: (const NSRect *)rects : (int) count
|
|
|
|
{
|
2002-03-29 19:25:35 +00:00
|
|
|
int i;
|
|
|
|
for (i=0; i < count; i++)
|
|
|
|
[self DPSrectfill: NSMinX(rects[i]) : NSMinY(rects[i])
|
|
|
|
: NSWidth(rects[i]) : NSHeight(rects[i])];
|
2002-03-27 23:44:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void)DPSimage: (NSAffineTransform*) matrix
|
|
|
|
: (int) pixelsWide : (int) pixelsHigh
|
|
|
|
: (int) bitsPerSample : (int) samplesPerPixel
|
|
|
|
: (int) bitsPerPixel : (int) bytesPerRow : (BOOL) isPlanar
|
|
|
|
: (BOOL) hasAlpha : (NSString *) colorSpaceName
|
|
|
|
: (const unsigned char *const [5]) data
|
|
|
|
{
|
|
|
|
[self subclassResponsibility: _cmd];
|
|
|
|
}
|
|
|
|
@end
|
|
|
|
|
|
|
|
|