-- Graphics.mesa -- Last changed by Doug Wyatt, August 30, 1982 5:38 pm -- The principal client interface to the Cedar Graphics package DIRECTORY GraphicsBasic USING [baseMark, black, Box, Color, DeviceRef, FontRef, ImageRef, Mark, nullMark, PaintMode, Path, StrokeEnds, Texture, white, YMode], Rope USING [MaxLen, ROPE]; Graphics: CEDAR DEFINITIONS = { ------ Types ------ Context: TYPE = REF ContextRep; -- A display context ContextRep: TYPE = RECORD[procs: REF GraphicsProcs, data: REF ANY]; Path: TYPE = GraphicsBasic.Path; -- A path container DeviceRef: TYPE = GraphicsBasic.DeviceRef; -- A display device FontRef: TYPE = GraphicsBasic.FontRef; -- A font ImageRef: TYPE = GraphicsBasic.ImageRef; -- An image source Box: TYPE = GraphicsBasic.Box; -- A rectangular box -- RECORD[xmin,ymin,xmax,ymax: REAL] ------ Signals ------ WarningType: TYPE = {fontNotFound, notImplemented, temporarilyOutOfOrder, other}; ErrorType: TYPE = {singularTransformation, bug}; Warning: SIGNAL[type: WarningType]; -- may be resumed Error: ERROR[type: ErrorType]; ------ Procedures ------ -- Contexts -- NewContext: PROC[device: DeviceRef _ NIL] RETURNS[Context]; -- Return a new display context for the given device. -- The initial clipping boundary is the entire screen. -- The initial transformation puts the origin in the lower left corner -- and establishes a coordinate system measured in points. -- If device is NIL, NewContext returns a Context for the default display. CopyContext: PROC[self: Context] RETURNS[Context]; -- Make a new context, copying the state of the given context. -- Position -- -- A display context maintains a current position (CP). The CP is a location on the display -- which is used to position characters and images. It is by altering the CP that an operator -- displaying a character specifies where the next character on the text line should usually lie. GetCP: PROC[self: Context, rounded: BOOLEAN _ FALSE] RETURNS[x,y: REAL] = INLINE { RETURN self.procs.GetCP[self, rounded] }; -- Return CP in user coordinates. -- Note the effect of modifying the coordinate system: the position of CP -- remains fixed on the display, but GetCP will return new coordinates. -- May raise ERROR Error[singularTransformation] SetCP: PROC[self: Context, x, y: REAL, rel: BOOLEAN _ FALSE] = INLINE { self.procs.SetCP[self, x, y, rel] }; -- Set CP to (x, y). -- rel => use (CPx+x, CPy+y) instead of (x, y). -- Paths -- -- Paths provide a mechanism for describing complex shapes. A path consists -- of one or more trajectories; each trajectory is a connected sequence of -- links; each link is a straight line segment or cubic curve segment. -- A completed path can be interpreted as the centerline of a stroke or -- as the outline(s) of a filled area. -- A path always has a defined last point (LP). LP of an empty path is (0, 0). NewPath: PROC[size: INT _ 0] RETURNS[Path]; -- Create a new path; its LP is (0, 0). -- size is an optional hint for the number of points the path will hold LastPoint: PROC[self: Path] RETURNS[x, y: REAL]; -- Return the path's current LP. FlushPath: PROC[self: Path]; -- Empty the path; new LP is (0, 0). MoveTo: PROC[self: Path, x, y: REAL, flush: BOOLEAN _ TRUE]; -- Begin a new trajectory at (x, y); new LP is (x, y). -- flush => empty the path first LineTo: PROC[self: Path, x, y: REAL]; -- Extend a straight line from LP to (x, y); new LP is (x, y). CurveTo: PROC[self: Path, x1, y1, x2, y2, x3, y3: REAL]; -- Extend a cubic curve from LP to (x3, y3); new LP is (x3, y3). -- The curve is defined by four Bezier control points: LP, (x1, y1), (x2, y2), (x3, y3). Rectangle: PROC[self: Path, x0, y0, x1, y1: REAL]; -- Add a rectangular trajectory to the path; new LP is (x0, y0). -- The corners of the rectangle are (x0,y0) (x1,y0) (x1,y1) (x0,y1). -- Equivalent to: self.MoveTo[x0, y0, FALSE]; self.LineTo[x1, y0]; -- self.LineTo[x1, y1]; self.LineTo[x0, y1]; self.LineTo[x0, y0]; -- Drawing routines -- DrawTo: PROC[self: Context, x, y: REAL, rel: BOOLEAN _ FALSE] = INLINE { self.procs.DrawTo[self, x, y, rel] }; -- Draw a thin line from CP to (x, y); new CP is (x, y). -- rel => use (CPx+x, CPy+y) instead of (x, y) StrokeEnds: TYPE = GraphicsBasic.StrokeEnds; -- {butt, square, round} DrawStroke: PROC[self: Context, path: Path, width: REAL _ 0, closed: BOOLEAN _ FALSE, ends: StrokeEnds _ butt] = INLINE { self.procs.DrawStroke[self, path, width, closed, ends] }; -- Draw a stroke of the given width centered along the given path. -- If width=0, the "fat" flag (see below) is implicitly set, so the stroke will be visible. -- closed => draw a closed stroke, connecting the last point to the first point -- The ends parameter controls the treatment of the ends of the stroke: -- butt => simply square off each end at its endpoint -- square => extend the stroke by half its width at each end, then square off -- round => form a semicircular cap at each end -- Connections between straight segments of the stroke will be mitered. -- If the stroke is closed, ends is ignored. (A closed stroke has no ends.) DrawArea: PROC[self: Context, path: Path, parityFill: BOOLEAN _ FALSE] = INLINE { self.procs.DrawArea[self, path, parityFill] }; -- Draw the area outlined by the given path. All trajectories are -- considered closed. If the path intersects itself or has overlapping -- trajectories, a wrap number rule determines what points comprise -- the interior: those with odd wrap number, if parityFill is TRUE, -- nonzero wrap number otherwise. DrawBox: PROC[self: Context, box: Box] = INLINE { self.procs.DrawBox[self, box] }; -- Draw the area inside the specified box. DrawImage: PROC[self: Context, image: ImageRef, raw: BOOLEAN _ FALSE] = INLINE { self.procs.DrawImage[self, image, raw] }; -- Draw the entire specified image, aligning its origin with CP. -- raw => [Wizards only] store the uninterpreted image into the frame buffer -- Mapping -- Translate: PROC[self: Context, tx,ty: REAL, round: BOOLEAN _ FALSE] = INLINE { self.procs.Translate[self, tx,ty, round] }; -- Subsequent objects will be translated by tx,ty. -- If round=TRUE, the translated origin will be rounded to integers -- in the output device's coordinate system. Scale: PROC[self: Context, sx,sy: REAL] = INLINE { self.procs.Concat[self, sx, 0, 0, sy] }; -- Subsequent objects will be magnified in x and y by sx,sy respectively. Rotate: PROC[self: Context, angle: REAL]; -- Subsequent objects will be rotated anticlockwise by angle degrees. Concat: PROC[self: Context, m11,m12,m21,m22: REAL] = INLINE { self.procs.Concat[self, m11,m12,m21,m22] }; -- The given transformation will be applied to subsequent objects. Map: PROC[sc,dc: Context, sx,sy: REAL] RETURNS[dx,dy: REAL]; -- Map a point from one context coordinate system to another. -- The source point (sx,sy) is interpreted in the source context (sc). -- The resulting point (dx,dy) is the same point expressed in the -- coordinate system of the destination context (dc). -- May raise ERROR Error[singularTransformation] WorldToUser: PROC[self: Context, wx,wy: REAL] RETURNS[x,y: REAL] = INLINE { RETURN self.procs.WorldToUser[self, wx,wy] }; -- Transform a point from world to user coordinates. -- May raise ERROR Error[singularTransformation] UserToWorld: PROC[self: Context, x,y: REAL] RETURNS[wx,wy: REAL] = INLINE { RETURN self.procs.UserToWorld[self, x,y] }; -- Transform a point from user to world coordinates. -- Fill -- Color: TYPE = GraphicsBasic.Color; -- A color value black: Color = GraphicsBasic.black; white: Color = GraphicsBasic.white; -- Some day, a Color will be a device-independent specification of a solid color. -- For now, only black and white are guaranteed to work for all devices. SetColor: PROC[self: Context, color: Color] = INLINE { self.procs.SetColor[self, color] }; -- Set a constant color for area filling. GetColor: PROC[self: Context] RETURNS[Color] = INLINE { RETURN self.procs.GetColor[self] }; -- Return the current color value. SetStipple: PROC[self: Context, pattern: CARDINAL] = INLINE { self.procs.SetColor[self, [tag: stipple, r: 0, g: pattern/256, b: pattern MOD 256]] }; -- Set a 4 by 4 bit stipple pattern for area filling. -- This is an interim hack for producing various gray effects on bitmap displays; the -- stipple pattern is simply aligned with the device pixels and tiled to fill the area. -- Better conventions for sampled color are coming. PaintMode: TYPE = GraphicsBasic.PaintMode; -- {opaque, transparent, invert} SetPaintMode: PROC[self: Context, mode: PaintMode] RETURNS[PaintMode] = INLINE { RETURN self.procs.SetPaintMode[self, mode] }; -- Set the painting mode used to display an object: -- opaque => all parts of the object replace the previous display -- transparent => "white" parts of the object do not affect the display -- invert => "black" parts of the object invert the previous display -- Return the previous painting mode. SetFat: PROC[self: Context, fat: BOOLEAN] RETURNS[BOOLEAN] = INLINE { RETURN self.procs.SetFat[self, fat] }; -- If fat is TRUE, low resolution devices will overscan so that very -- small areas and thin lines will not disappear; however, objects may -- extend outside the clipping region by as much as a pixel. -- Text -- MakeFont: PROC[name: Rope.ROPE] RETURNS[FontRef]; -- Return a FontRef for the specified font. -- Example: font _ MakeFont["Helvetica10"]; -- Currently, fonts must be in "ks" (preferred) or "strike" format. -- If the given name does not contain '., tries appending ".ks" -- to obtain a file name for the font. -- Raises SIGNAL Warning[fontNotFound] if no font file is found. -- Returns a FontRef for a built in default font if the signal is RESUMEd. GetDefaultFont: PROC[self: Context] RETURNS[FontRef] = INLINE { RETURN self.procs.GetDefaultFont[self] }; -- Return the current default font for the given context. SetDefaultFont: PROC[self: Context, font: FontRef] = INLINE { self.procs.SetDefaultFont[self, font] }; -- Set the default font for the given context. DrawRope: PROC[self: Context, rope: Rope.ROPE, start: INT _ 0, len: INT _ Rope.MaxLen, font: FontRef _ NIL]; -- Display a rope in the specified font (use the default font if font=NIL). -- For each character in the given range: -- place the reference point of the character at the current position, -- then advance the current position by the character width. DrawChar: PROC[self: Context, char: CHARACTER, font: FontRef _ NIL]; -- Display a single character. RopeBox: PROC[font: FontRef, rope: Rope.ROPE, start: INT _ 0, len: INT _ Rope.MaxLen] RETURNS[xmin,ymin,xmax,ymax: REAL]; -- Return the bounding box for the given (sub)string. -- If the given text is placed at position [x,y], -- it will lie within the box [x+xmin,y+ymin,x+xmax,y+ymax]. RopeWidth: PROC[font: FontRef, rope: Rope.ROPE, start: INT _ 0, len: INT _ Rope.MaxLen] RETURNS[xw,yw: REAL]; -- Return the width vector for the given (sub)string. -- If the given text is placed at position [x,y], -- following text will be placed at [x+xw,y+yw]. CharBox: PROC[font: FontRef, char: CHARACTER] RETURNS[xmin,ymin,xmax,ymax: REAL]; -- Return the bounding box for a single character. CharWidth: PROC[font: FontRef, char: CHARACTER] RETURNS[xw,yw: REAL]; -- Return the width vector for a single character. FontBox: PROC[font: FontRef] RETURNS[xmin,ymin,xmax,ymax: REAL]; -- Return the bounding box for all the characters of the font superimposed. -- The "font height" is ymax-ymin; "ascent" is ymax; "descent" is -ymin. -- Clipping -- ClipArea: PROC[self: Context, path: Path, parityFill: BOOLEAN _ FALSE, exclude: BOOLEAN _ FALSE] = INLINE { self.procs.ClipArea[self, path, parityFill, exclude] }; -- Define a new clipping region. -- If exclude is FALSE, the new region is that portion of the current -- clipping region which lies inside the area specified by the given path. -- If exclude is TRUE, the new region is that portion of the current -- clipping region which lies OUTSIDE the area specified by the given path. ClipBox: PROC[self: Context, box: Box, exclude: BOOLEAN _ FALSE] = INLINE { self.procs.ClipBox[self, box, exclude] }; -- Define a new clipping region. -- Similar to ClipArea; uses the specified box instead of a path. IsPointVisible: PROC[self: Context, x,y: REAL] RETURNS[BOOLEAN] = INLINE { RETURN self.procs.IsPointVisible[self, x, y] }; -- Return TRUE iff the given point is within the context's clipping region. IsRectangular: PROC[self: Context] RETURNS[BOOLEAN] = INLINE { RETURN self.procs.IsRectangular[self] }; -- Return TRUE iff the context's clipping region is a single rectangle. GetBounds: PROC[self: Context] RETURNS[Box] = INLINE { RETURN self.procs.GetBounds[self] }; -- Return a bounding box for the current clipping area. Visible: PROC[self: Context] RETURNS[BOOLEAN] = INLINE { RETURN self.procs.Visible[self] }; -- Return TRUE iff the current clipping region is nonempty. -- Saving and Restoring Mark: TYPE = GraphicsBasic.Mark; -- RECORD[CARDINAL] nullMark: Mark = GraphicsBasic.nullMark; baseMark: Mark = GraphicsBasic.baseMark; Save: PROC[self: Context] RETURNS[Mark] = INLINE { RETURN self.procs.Save[self] }; -- Note the current state of the display context, and -- return a mark value which can later be passed to Restore. -- This call simply enables a copy-on-write mechanism; Save and Restore -- are quite cheap if the context state is not actually changed. -- The Save-Restore mechanism covers the following context state: -- transformation ("Mapper") and YMode -- clipping region ("Clipper") -- color, paint mode, and "fat" flag -- N.B.: the current position is NOT included. Restore: PROC[self: Context, mark: Mark _ nullMark] = INLINE { self.procs.Restore[self, mark] }; -- Restore the state of the display context to its condition -- prior to the call on Save that returned the given mark. -- Defaulting the mark means restore to the most recent Save. GraphicsProcs: TYPE = RECORD[ GetCP: PROC[self: Context, rounded: BOOLEAN] RETURNS[x,y: REAL], SetCP: PROC[self: Context, x,y: REAL, rel: BOOLEAN], DrawTo: PROC[self: Context, x,y: REAL, rel: BOOLEAN], DrawStroke: PROC[self: Context, path: Path, width: REAL, closed: BOOLEAN, ends: StrokeEnds], DrawArea: PROC[self: Context, path: Path, parityFill: BOOLEAN], DrawBox: PROC[self: Context, box: Box], DrawImage: PROC[self: Context, image: ImageRef, raw: BOOLEAN], Translate: PROC[self: Context, tx,ty: REAL, round: BOOLEAN], Concat: PROC[self: Context, m11,m12,m21,m22: REAL], WorldToUser: PROC[self: Context, wx,wy: REAL] RETURNS[x,y: REAL], UserToWorld: PROC[self: Context, x,y: REAL] RETURNS[wx,wy: REAL], SetColor: PROC[self: Context, color: Color], GetColor: PROC[self: Context] RETURNS[Color], SetPaintMode: PROC[self: Context, mode: PaintMode] RETURNS[PaintMode], SetFat: PROC[self: Context, fat: BOOLEAN] RETURNS[BOOLEAN], GetDefaultFont: PROC[self: Context] RETURNS[FontRef], SetDefaultFont: PROC[self: Context, font: FontRef], DrawChars: PROC[self: Context, font: FontRef, map: PROC[PROC[CHAR] RETURNS[BOOL]]], ClipArea: PROC[self: Context, path: Path, parityFill: BOOLEAN, exclude: BOOLEAN], ClipBox: PROC[self: Context, box: Box, exclude: BOOLEAN], IsPointVisible: PROC[self: Context, x,y: REAL] RETURNS[BOOLEAN], IsRectangular: PROC[self: Context] RETURNS[BOOLEAN], GetBounds: PROC[self: Context] RETURNS[Box], Visible: PROC[self: Context] RETURNS[BOOLEAN], Save: PROC[self: Context] RETURNS[Mark], Restore: PROC[self: Context, mark: Mark], DrawBits: UNSAFE PROC[self: Context, base: LONG POINTER, raster: CARDINAL, bitsPerPixel: [0..16), x, y, w, h: CARDINAL, xorigin, yorigin: INTEGER], UserToDevice: PROC[self: Context, x, y: REAL, rel: BOOLEAN] RETURNS[tx, ty: REAL], DeviceToUser: PROC[self: Context, tx, ty: REAL, rel: BOOLEAN] RETURNS[x, y: REAL], GetYMode: PROC[self: Context] RETURNS[GraphicsBasic.YMode], SetYMode: PROC[self: Context, mode: GraphicsBasic.YMode], DrawTexturedBox: PROC[self: Context, box: Box, texture: GraphicsBasic.Texture], Disable: PROC[self: Context], MoveDeviceRectangle: PROC[self: Context, width, height, fromX, fromY, toX, toY: NAT] ]; }. Ê–– "Mesa" style˜Iprocš¤ÏcHœ@œÏk œžœžœ žœžœœ žœžœ œ žœžœžœžœžœ žœœ žœœ žœ œ žœœžœžœžœœ œžœLžœ+žœœžœœœœÏn œžœžœžœ »œŸ œžœžœ ?œœœœŸœžœžœžœžœžœžœžœ$土œžœžœžœžœžœ(Fœ œœŸœžœžœžœqœŸ œžœ žœžœ!œŸ œžœ%œŸœžœžœ žœžœYœŸœžœžœ?œŸœžœ%žœšœŸ œžœžœ˜œžœœ>œœŸœžœžœ žœžœžœ)iœ žœœŸ œžœ#žœžœžœžœ=ƒœŸœžœ(žœžœžœ2³œŸœžœžœ$+œŸ œžœ&žœžœžœ-œ œŸ œžœžœ žœžœžœ/¥œŸœžœžœžœ,JœŸœžœžœFœŸœžœ!žœžœ/CœŸœžœžœžœžœ®œŸ œžœžœžœžœžœžœ(fœŸ œžœžœžœžœžœžœ&5œ œ žœœHcœœ)œŸœžœ"žœ'*œŸœžœžœ žœžœ#œŸ œžœžœžœMžœ ˜œ žœœœŸ œžœ!žœžœžœ(¯œŸœžœžœžœžœžœžœ!Éœ œŸœžœ žœžœ œŸœžœžœžœžœ$:œŸœžœ#žœ,/œŸœžœžœ žœ žœ"žœþœŸœžœž œžœœŸœžœžœ žœ žœžœžœ¥œŸ œžœžœ žœ žœžœžœ™œŸœžœž œžœžœ3œŸ œžœž œžœžœ3œŸœžœžœžœ•œœŸœžœ(žœžœ žœžœžœ;ÃœŸœžœ%žœžœžœ-cœŸœžœžœžœžœžœžœ*LœŸ œžœžœžœžœžœ#HœŸ œžœžœ žœžœ8œŸœžœžœžœžœžœ<œœžœžœžœ žœ(žœ Ÿœžœžœ žœžœÞœŸœžœ+žœ%¶œžœžœŸœžœžœžœžœŸœžœžœžœŸœžœžœžœŸ œžœ#žœ žœŸœžœ(žœŸœžœŸ œžœ&žœŸ œžœžœ žœŸœžœ!žœŸ œžœžœžœžœŸ œžœžœžœžœŸœžœ!Ÿœžœžœ Ÿ œžœ!žœŸœžœžœžœžœŸœžœžœ Ÿœžœ"Ÿ œžœ$žœžœžœžœžœŸœžœ(žœ žœŸœžœ#žœŸœžœžœžœžœŸ œžœžœžœŸ œžœžœ ŸœžœžœžœŸœžœžœ ŸœžœŸœžœžœžœžœ žœ)žœžœŸ œžœžœžœžœ žœŸ œžœžœžœžœžœŸœžœžœŸœžœ.Ÿœžœ=ŸœžœŸœžœ7žœ ˜‘—…—?”G0