/**
This is an abstract class which provides a framework for a device independant drawing.
In addition, this class provides methods to perform the actual drawing. As a convenience, you can also access these through various function interfaces. One is a Display Postscript interface using PS and DPS operations. Another is a Quartz interface (not yet written).
Create a graphics context with attributes, which contains key/value pairs which describe the specifics of how the context is to be initialized.
*/ + (NSGraphicsContext *) graphicsContextWithAttributes: (NSDictionary *)attributes { NSGraphicsContext *ctxt; ctxt = [[self alloc] initWithContextInfo: attributes]; return AUTORELEASE(ctxt); } /** Create graphics context with attributes speficied by aWindow's device description. */ + (NSGraphicsContext *) graphicsContextWithWindow: (NSWindow *)aWindow { return [self graphicsContextWithAttributes: [NSDictionary dictionaryWithObject: aWindow forKey: NSGraphicsContextDestinationAttributeName]]; } + (NSGraphicsContext *) graphicsContextWithBitmapImageRep: (NSBitmapImageRep *)bitmap { return [self graphicsContextWithAttributes: [NSDictionary dictionaryWithObject: bitmap forKey: NSGraphicsContextDestinationAttributeName]]; } + (NSGraphicsContext *) graphicsContextWithGraphicsPort: (void *)port flipped: (BOOL)flag { NSGraphicsContext *ctxt; ctxt = [[self alloc] initWithGraphicsPort: port flipped: flag]; return AUTORELEASE(ctxt); } + (NSGraphicsContext *)graphicsContextWithCGContext: (CGContextRef)context flipped: (BOOL)flipped { return [NSGraphicsContext graphicsContextWithGraphicsPort: (void *)context flipped: flipped]; } + (void) restoreGraphicsState { NSGraphicsContext *ctxt; NSMutableDictionary *dict = [[NSThread currentThread] threadDictionary]; NSMutableArray *stack = [dict objectForKey: NSGraphicsContextStackKey]; if (stack == nil) { [NSException raise: NSGenericException format: @"restoreGraphicsState without previous save"]; } // might be nil, i.e. no current context ctxt = [stack lastObject]; [NSGraphicsContext setCurrentContext: ctxt]; if (ctxt) { [stack removeLastObject]; [ctxt restoreGraphicsState]; } } + (void) saveGraphicsState { NSGraphicsContext *ctxt; NSMutableDictionary *dict = [[NSThread currentThread] threadDictionary]; NSMutableArray *stack = [dict objectForKey: NSGraphicsContextStackKey]; if (stack == nil) { stack = [[NSMutableArray allocWithZone: _globalGSZone] init]; [dict setObject: stack forKey: NSGraphicsContextStackKey]; RELEASE(stack); } // might be nil, i.e. no current context ctxt = GSCurrentContext(); if (ctxt) { [ctxt saveGraphicsState]; [stack addObject: ctxt]; } } + (void) setGraphicsState: (NSInteger)graphicsState { /* FIXME: Need to keep a table of which context goes with a graphicState, or perhaps we could rely on the backend? */ [self notImplemented: _cmd]; } + (id) alloc { return [self allocWithZone: _globalGSZone]; } + (id) allocWithZone: (NSZone*)z { if (self == [NSGraphicsContext class]) { NSAssert(defaultNSGraphicsContextClass, @"Internal Error: No default NSGraphicsContext set\n"); return [defaultNSGraphicsContextClass allocWithZone: z]; } else return [super allocWithZone: z]; } - (void) dealloc { DESTROY(usedFonts); DESTROY(focus_stack); DESTROY(context_data); DESTROY(context_info); DESTROY(_shadow); [super dealloc]; } - (id) init { return [self initWithContextInfo: nil]; } /**Sets the colorspace for fill operations based on values in the supplied dictionary dict.
For device colorspaces (GSDeviceGray, GSDeviceRGB, GSDeviceCMYK), only the name of the colorspace needs to be set using the GSColorSpaceName key.
Other colorspaces will be documented later (Quartz).
*/ - (void) GSSetFillColorspace: (void *)spaceref { [self subclassResponsibility: _cmd]; } /** Sets the colorspace for stroke operations based on the values in the supplied dictionary. See -GSSetFillColorspace: for a description of the values that need to be supplied (Quartz). */ - (void) GSSetStrokeColorspace: (void *)spaceref { [self subclassResponsibility: _cmd]; } /** Sets the current color for fill operations. The values array should have n components, where n corresponds to the number of color components required to specify the color in the current colorspace (Quartz). */ - (void) GSSetFillColor: (const CGFloat *)values { [self subclassResponsibility: _cmd]; } /** Sets the current color for stroke operations. The values array should have n components, where n corresponds to the number of color components required to specify the color in the current colorspace (Quartz). */ - (void) GSSetStrokeColor: (const CGFloat *)values { [self subclassResponsibility: _cmd]; } /* ----------------------------------------------------------------------- */ /* Text operations */ /* ----------------------------------------------------------------------- */ /** Displays a string as in DPSshow, except that (x,y) is added to the advancement of every glyph. An alternative means of achieving the same effect is to use the -GSSetCharacterSpacing: method. Either approach should be more efficient that using -DPSshow: with appropriate -DPSrmoveto:: operations. */ - (void) DPSashow: (CGFloat)x : (CGFloat)y : (const char *)s { [self subclassResponsibility: _cmd]; } /** Displays a string as in a combination of DPSashow and DPSwidthshow: (ax,ay) is added to the advancement of every glyph, while (cx,cy) is also added to the advancement for character c's glyph specifically. Using this method should be more efficient that using -DPSshow: with appropriate -DPSrmoveto:: operations. */ - (void) DPSawidthshow: (CGFloat)cx : (CGFloat)cy : (int)c : (CGFloat)ax : (CGFloat)ay : (const char *)s { [self subclassResponsibility: _cmd]; } /** Appends to the current path a path that is equivalent to the outlines of the glyphs in the string. This results in a path that can be used for stroking, filling or clipping (DPS). */ - (void) DPScharpath: (const char *)s : (int)b { [self subclassResponsibility: _cmd]; } - (void) appendBezierPathWithPackedGlyphs: (const char *)packedGlyphs path: (NSBezierPath*)aPath { [self subclassResponsibility: _cmd]; } /** Display the string s using the current font (DPS). */ - (void) DPSshow: (const char *)s { [self subclassResponsibility: _cmd]; } /** Displays a string as in DPSshow, except that, for character c only, the glpyh x and y advancement is determined by the values (x,y), instead of by the glyph itself. This is often used to adjust the length of a line of text by changing the width of the space character. Using this method should be more efficient than using -DPSshow: with appropriate -DPSrmoveto:: operations. */ - (void) DPSwidthshow: (CGFloat)x : (CGFloat)y : (int)c : (const char *)s { [self subclassResponsibility: _cmd]; } /** Displays a string as in DPSshow, except that the glyph x advancement is determined by the values in numarray, one for each glyph, instead of by the glyphs themselves. size should be equal to the length of s in glyphs. Using this method should be more efficient than using -DPSshow: with appropriate -DPSrmoveto:: operations. */ - (void) DPSxshow: (const char *)s : (const CGFloat*)numarray : (int)size { [self subclassResponsibility: _cmd]; } /** Displays a string as in DPSshow, except that the glyph x and y advancement is determined by the values in numarray, one x and one y for each glyph, in alternating order, instead of by the glyphs themselves. size should be equal to the length of s in glyphs. Using this method should be more efficient than using -DPSshow: with appropriate -DPSrmoveto:: operations. */ - (void) DPSxyshow: (const char *)s : (const CGFloat*)numarray : (int)size { [self subclassResponsibility: _cmd]; } /** Displays a string as in DPSshow, except that the glyph y advancement is determined by the values in numarray, one for each glyph, instead of by the glyphs themselves. size should be equal to the length of s in glyphs. Using this method should be more efficient than using -DPSshow: with appropriate -DPSrmoveto:: operations. */ - (void) DPSyshow: (const char *)s : (const CGFloat*)numarray : (int)size { [self subclassResponsibility: _cmd]; } /** Use this method to set the additional spacing between characters (glyphs). This spacing is added to the normal spacing for each character. Units are in text-space coordinate system. (Quartz). */ - (void) GSSetCharacterSpacing: (CGFloat)extra { [self subclassResponsibility: _cmd]; } /** Set the current font for drawing glyphs. (DPS, Quartz). */ - (void) GSSetFont: (void *)fontref { [self subclassResponsibility: _cmd]; } /** Set the font size of the current NSFont used for drawing glyphs. (DPS, Quartz). */ - (void) GSSetFontSize: (CGFloat)size { [self subclassResponsibility: _cmd]; } /**Returns the transfer function for transforming text from text space to user space. See -GSSetTextCTM: for additiona information. (Quartz).
*/ - (NSAffineTransform *) GSGetTextCTM { [self subclassResponsibility: _cmd]; return nil; } /** Returns the location at which text will be drawn. In text-space coordinates. (Quartz). */ - (NSPoint) GSGetTextPosition { [self subclassResponsibility: _cmd]; return NSMakePoint(0,0); } /**Set the transfer function for transforming text from text space to user space. This transform is only applied to text objects and is in addition to the normal coordinate transform matrix. When drawing text, this transform is applied before the normal CTM.
The text matrix can be changed by either modifying it directly, or just by drawing text, in which case the tx and ty offset veriables are modified to point to the location of the next character that could be rendered (Quartz).
*/ - (void) GSSetTextCTM: (NSAffineTransform *)ctm { [self subclassResponsibility: _cmd]; } /** Set the current text drawing mode. The mode can be one of several values that fill/stroke the text or add it to the current clipping path. (Quartz). */ - (void) GSSetTextDrawingMode: (GSTextDrawingMode)mode { [self subclassResponsibility: _cmd]; } /** Set the location at which text will be drawn, in text-space coordinates. This routine updates the current text coordinate matrix. (Quartz). */ - (void) GSSetTextPosition: (NSPoint)loc { [self subclassResponsibility: _cmd]; } /** Paints text represented by the characters in string in the current font. (Quartz). */ - (void) GSShowText: (const char *)string : (size_t) length { [self subclassResponsibility: _cmd]; } /** Paints the glyphs using the current font. (Quartz). */ - (void) GSShowGlyphs: (const NSGlyph *)glyphs : (size_t) length { [self subclassResponsibility: _cmd]; } /** Paints the glyphs with the specified advances using the current font. (Quartz). */ - (void) GSShowGlyphsWithAdvances: (const NSGlyph *)glyphs : (const NSSize *)advances : (size_t) length { [self subclassResponsibility: _cmd]; } /* ----------------------------------------------------------------------- */ /* Gstate Handling */ /* ----------------------------------------------------------------------- */ /** Pops a previously saved gstate from the gstate stack and makes it current. Drawing information in the previously saved gstate becomes the current information. (DPS, Quartz). */ - (void) DPSgrestore { [self subclassResponsibility: _cmd]; } /** Saves (pushes) a copy of the current gstate information onto the gstate stack. This saves drawing information contained in the gstate, such as the current path, ctm and colors. (DPS, Quartz). */ - (void) DPSgsave { [self subclassResponsibility: _cmd]; } - (void) DPSinitgraphics { [self subclassResponsibility: _cmd]; } /** Makes the gstate indicated by the tag gst the current gstate. Note that the gstate is copied, so that changes to either gstate do not affect the other. (DPS, Quartz). */ - (void) DPSsetgstate: (NSInteger)gst { [self subclassResponsibility: _cmd]; } /** Creates a copy of the current gstate and associates it with a tag, which is given in the return value. This tag can later be used in -DPSsetgstate: to set the gstate as being current again. (DPS, Quartz). */ - (NSInteger) GSDefineGState { [self subclassResponsibility: _cmd]; return 0; } /** Disassociates the tag gst with it's gstate and destroys the gstate object. The tag will no longer be valid and should not be used to refer to the gstate again. (DPS, Quartz). */ - (void) GSUndefineGState: (NSInteger)gst { [self subclassResponsibility: _cmd]; } /** Replaces the gstate refered to by the tag gst with the current gstate. The former gstate is destroyed. (DPS, Quartz). */ - (void) GSReplaceGState: (NSInteger)gst { [self subclassResponsibility: _cmd]; } /* ----------------------------------------------------------------------- */ /* Gstate operations */ /* ----------------------------------------------------------------------- */ /** Returns the current flattness parameter, which controls how curved lines are drawn. (DPS, Quartz). */ - (void) DPScurrentflat: (CGFloat*)flatness { [self subclassResponsibility: _cmd]; } /** Returns the current linecap value. (DPS, Quartz). */ - (void) DPScurrentlinecap: (int*)linecap { [self subclassResponsibility: _cmd]; } /** Returns the current linejoin value. (DPS, Quartz). */ - (void) DPScurrentlinejoin: (int*)linejoin { [self subclassResponsibility: _cmd]; } /** Returns the current line width. (DPS, Quartz). */ - (void) DPScurrentlinewidth: (CGFloat*)width { [self subclassResponsibility: _cmd]; } /** Returns the current linecap value. (DPS, Quartz). */ - (void) DPScurrentmiterlimit: (CGFloat*)limit { [self subclassResponsibility: _cmd]; } /** Returns the current point. (DPS, Quartz). */ - (void) DPScurrentpoint: (CGFloat*)x : (CGFloat*)y { [self subclassResponsibility: _cmd]; } /** Returns the strokeadjust value. (DPS). */ - (void) DPScurrentstrokeadjust: (int*)b { [self subclassResponsibility: _cmd]; } /** Set the pattern for line dashes like the Postscript setdash operator. (DPS, Quartz). */ - (void) DPSsetdash: (const CGFloat*)pat : (NSInteger)size : (CGFloat)offset { [self subclassResponsibility: _cmd]; } /** Sets the current flattness parameter, which controls how curved lines are drawn. (DPS, Quartz). */ - (void) DPSsetflat: (CGFloat)flatness { [self subclassResponsibility: _cmd]; } - (void) DPSsethalftonephase: (CGFloat)x : (CGFloat)y { [self subclassResponsibility: _cmd]; } /** Set the current linecap value. (DPS, Quartz). */ - (void) DPSsetlinecap: (int)linecap { [self subclassResponsibility: _cmd]; } /** Set the current linejoin value. (DPS, Quartz). */ - (void) DPSsetlinejoin: (int)linejoin { [self subclassResponsibility: _cmd]; } /** Set the current line width. (DPS, Quartz). */ - (void) DPSsetlinewidth: (CGFloat)width { [self subclassResponsibility: _cmd]; } /** Set the current meter limit value. (DPS, Quartz). */ - (void) DPSsetmiterlimit: (CGFloat)limit { [self subclassResponsibility: _cmd]; } - (void) DPSsetstrokeadjust: (int)b { [self subclassResponsibility: _cmd]; } /* ----------------------------------------------------------------------- */ /* Matrix operations */ /* ----------------------------------------------------------------------- */ /** Concatenates the coordinate transform represented by the matrix m with the current coordinate transform. (DPS). */ - (void) DPSconcat: (const CGFloat*)m { [self subclassResponsibility: _cmd]; } /** Sets the coordinate transform matrix to the initial values for the particular context */ - (void) DPSinitmatrix { [self subclassResponsibility: _cmd]; } /** Rotate the coordinate system. (DPS). */ - (void) DPSrotate: (CGFloat)angle { [self subclassResponsibility: _cmd]; } /** Scale the coordinate system. (DPS). */ - (void) DPSscale: (CGFloat)x : (CGFloat)y { [self subclassResponsibility: _cmd]; } /** Translate the coordinate system. (DPS). */ - (void) DPStranslate: (CGFloat)x : (CGFloat)y { [self subclassResponsibility: _cmd]; } /** Returns the current coordinate transform matrix. (Quartz). */ - (NSAffineTransform *) GSCurrentCTM { [self subclassResponsibility: _cmd]; return nil; } /** Sets the coordinate transform matrix which describes how graphics will be transformed into device coordinates. (Quartz). */ - (void) GSSetCTM: (NSAffineTransform *)ctm { [self subclassResponsibility: _cmd]; } /** Concatenates the matrix ctm onto the current coordinate transform matrix. (Quartz). */ - (void) GSConcatCTM: (NSAffineTransform *)ctm { [self subclassResponsibility: _cmd]; } /* ----------------------------------------------------------------------- */ /* Paint operations */ /* ----------------------------------------------------------------------- */ - (void) DPSarc: (CGFloat)x : (CGFloat)y : (CGFloat)r : (CGFloat)angle1 : (CGFloat)angle2 { [self subclassResponsibility: _cmd]; } - (void) DPSarcn: (CGFloat)x : (CGFloat)y : (CGFloat)r : (CGFloat)angle1 : (CGFloat)angle2 { [self subclassResponsibility: _cmd]; } - (void) DPSarct: (CGFloat)x1 : (CGFloat)y1 : (CGFloat)x2 : (CGFloat)y2 : (CGFloat)r { [self subclassResponsibility: _cmd]; } /** Clip to the current path. (DPS, Quartz). */ - (void) DPSclip { [self subclassResponsibility: _cmd]; } - (void) DPSclosepath { [self subclassResponsibility: _cmd]; } - (void) DPScurveto: (CGFloat)x1 : (CGFloat)y1 : (CGFloat)x2 : (CGFloat)y2 : (CGFloat)x3 : (CGFloat)y3 { [self subclassResponsibility: _cmd]; } - (void) DPSeoclip { [self subclassResponsibility: _cmd]; } - (void) DPSeofill { [self subclassResponsibility: _cmd]; } /** Fill the current path. (DPS, Quartz). */ - (void) DPSfill { [self subclassResponsibility: _cmd]; } - (void) DPSflattenpath { [self subclassResponsibility: _cmd]; } - (void) DPSinitclip { [self subclassResponsibility: _cmd]; } - (void) DPSlineto: (CGFloat)x : (CGFloat)y { [self subclassResponsibility: _cmd]; } - (void) DPSmoveto: (CGFloat)x : (CGFloat)y { [self subclassResponsibility: _cmd]; } - (void) DPSnewpath { [self subclassResponsibility: _cmd]; } - (void) DPSpathbbox: (CGFloat*)llx : (CGFloat*)lly : (CGFloat*)urx : (CGFloat*)ury { [self subclassResponsibility: _cmd]; } - (void) DPSrcurveto: (CGFloat)x1 : (CGFloat)y1 : (CGFloat)x2 : (CGFloat)y2 : (CGFloat)x3 : (CGFloat)y3 { [self subclassResponsibility: _cmd]; } - (void) DPSrectclip: (CGFloat)x : (CGFloat)y : (CGFloat)w : (CGFloat)h { [self subclassResponsibility: _cmd]; } - (void) DPSrectfill: (CGFloat)x : (CGFloat)y : (CGFloat)w : (CGFloat)h { [self subclassResponsibility: _cmd]; } - (void) DPSrectstroke: (CGFloat)x : (CGFloat)y : (CGFloat)w : (CGFloat)h { [self subclassResponsibility: _cmd]; } - (void) DPSreversepath { [self subclassResponsibility: _cmd]; } - (void) DPSrlineto: (CGFloat)x : (CGFloat)y { [self subclassResponsibility: _cmd]; } - (void) DPSrmoveto: (CGFloat)x : (CGFloat)y { [self subclassResponsibility: _cmd]; } - (void) DPSstroke { [self subclassResponsibility: _cmd]; } - (void) DPSshfill: (NSDictionary *)shaderDictionary { [self subclassResponsibility: _cmd]; } /** Set the bezier path as the current path */ - (void) GSSendBezierPath: (NSBezierPath *)path { [self subclassResponsibility: _cmd]; } /** Append the array of rects to the current clip path (DPS, Quartz). */ - (void) GSRectClipList: (const NSRect *)rects : (int) count { [self subclassResponsibility: _cmd]; } /** Draw and fill the array of rects. (DPS, Quartz) */ - (void) GSRectFillList: (const NSRect *)rects : (int) count { [self subclassResponsibility: _cmd]; } /* ----------------------------------------------------------------------- */ /* Window system ops */ /* ----------------------------------------------------------------------- */ /** This is a private method used between the window server and the context. It should not be used in any application. Typically used by the window server to find out what window the context is drawing graphics to. The device pointer is an opaque type that contains information about the window. The x and y pointers indicate the offset of the origin of the window from the lower left-hand corner */ - (void) GSCurrentDevice: (void **)device : (int *)x : (int *)y { [self subclassResponsibility: _cmd]; } - (void) DPScurrentoffset: (int *)x : (int *)y { [self subclassResponsibility: _cmd]; } /** This is a private method used between the window server and the context. It should not be used in any application. Typically called by the window server to tell the context what window it should draw graphics to. The device pointer is an opaque type that contains information about the window. The x and y values tell the context that it should put the origin of the transform matrix at the indicated x and y values from the lower left-hand corner of the window */ - (void) GSSetDevice: (void *)device : (int)x : (int)y { [self subclassResponsibility: _cmd]; } - (void) DPSsetoffset: (short int)x : (short int)y { [self subclassResponsibility: _cmd]; } /*-------------------------------------------------------------------------*/ /* Graphics Extension Ops */ /*-------------------------------------------------------------------------*/ - (void) DPScomposite: (CGFloat)x : (CGFloat)y : (CGFloat)w : (CGFloat)h : (NSInteger)gstateNum : (CGFloat)dx : (CGFloat)dy : (NSCompositingOperation)op { [self subclassResponsibility: _cmd]; } - (void) DPScompositerect: (CGFloat)x : (CGFloat)y : (CGFloat)w : (CGFloat)h : (NSCompositingOperation)op { [self subclassResponsibility: _cmd]; } - (void) DPSdissolve: (CGFloat)x : (CGFloat)y : (CGFloat)w : (CGFloat)h : (NSInteger)gstateNum : (CGFloat)dx : (CGFloat)dy : (CGFloat)delta { [self subclassResponsibility: _cmd]; } /* As currently not all backends support mixed composite and dissolve operations, this method is here to dispatch to the best suited one implemented */ - (void) GScomposite: (NSInteger)gstateNum toPoint: (NSPoint)aPoint fromRect: (NSRect)srcRect operation: (NSCompositingOperation)op fraction: (CGFloat)delta { [self subclassResponsibility: _cmd]; } /**