{Begin SubSec Implementation of Image Streams} {Title Implementation of Image Streams} {Text {Index *PRIMARY* Device-independent graphics} {Index *PRIMARY* DIG (Device-Independent Graphics) Term} Interlisp does all image creation through a set of functions and data structures for device-independent graphics, known popularly as DIG. DIG is implemented through the use of a special type of stream, known as an image stream. An image stream, by convention, is any stream that has its {lisp IMAGEOPS} field (described in detail below) set to a vector of meaningful graphical operations. Using image streams, you can write programs that draw and print on an output stream without regard to the underlying device, be it a window, a disk, or a printer. To define a new image stream type, it is necessary to put information on the variable {var IMAGESTREAMTYPES}: {VarDef {Name IMAGESTREAMTYPES} {Text This variable describes how to create a stream for a given image stream type. The value of {var IMAGESTREAMTYPES} is an association list, indexed by the image stream type (e.g., {lisp DISPLAY}, {lisp INTERPRESS}, etc.). The format of a single association list item is: {lispcode ({arg IMAGETYPE} (OPENSTREAM {arg OPENSTREAMFN}) (FONTCREATE {arg FONTCREATEFN}) (FONTSAVAILABLE {arg FONTSAVAILABLEFN}))} {arg OPENSTREAMFN}, {arg FONTCREATEFN}, and {arg FONTSAVAILABLEFN} are "image stream methods," device-dependent functions used to implement generic image stream operations. For Interpress image streams, the association list entry is: {lispcode (INTERPRESS (OPENSTREAM OPENIPSTREAM) (FONTCREATE \CREATEINTERPRESSFONT) (FONTSAVAILABLE \SEARCHINTERPRESSFONTS))} }} {Def {Type (Image Stream Method)} {Name OPENSTREAMFN} {Args FILE OPTIONS} {Text {arg FILE} is the file name as it was passed to {fn OPENIMAGESTREAM}, and {arg OPTIONS} is the {arg OPTIONS} property list passed to {fn OPENIMAGESTREAM}. The result must be a stream of the appropriate image type. }} {Def {Type (Image Stream Method)} {Name FONTCREATEFN} {Args FAMILY SIZE FACE ROTATION DEVICE} {Text {arg FAMILY} is the family name for the font, e.g., {lisp MODERN}. {arg SIZE} is the body size of the font, in printer's points. {arg FACE} is a three-element list describing the weight, slope, and expansion of the face desired, e.g., {lisp (MEDIUM ITALIC EXPANDED)}. {arg ROTATION} is how much the font is to be rotated from the normal orientation, in minutes of arc. For example, to print a landscape page, fonts have the rotation 5400 (90 degrees). The function's result must be a {lisp FONTDESCRIPTOR} with the fields filled in appropriately. }} {Def {Type (Image Stream Method)} {Name FONTSAVAILABLEFN} {Args FAMILY SIZE FACE ROTATION DEVICE} {Text This function returns a list of all fonts agreeing with the {arg FAMILY}, {arg SIZE}, {arg FACE}, and {arg ROTATION} arguments; any of them may be wild-carded (i.e., equal to {lisp *}, which means any value is acceptable). Each element of the list should be a quintuple of the form {lisp ({arg FAMILY} {arg SIZE} {arg FACE} {arg ROTATION} {arg DEVICE})}. Where the function looks is an implementation decision: the {arg FONTSAVAILABLEFN} for the display device looks at {var DISPLAYFONTDIRECTORIES}, the Interpress code looks on {var INTERPRESSFONTDIRECTORIES}, and implementors of new devices should feel free to introduce new search path variables. }} As indicated above, image streams use a field that no other stream uses: {lisp IMAGEOPS}.{index IMAGEOPS (Stream Field)} {lisp IMAGEOPS} is an instance of the {lisp IMAGEOPS}{index IMAGEOPS (Data type)} data type and contains a vector of the stream's graphical methods. The methods contained in the {lisp IMAGEOPS} object can make arbitrary use of the stream's {lisp IMAGEDATA}{index IMAGEDATA (Stream Field)} field, which is provided for their use, and may contain any data needed. The {lisp IMAGEOPS} data type has the following fields: {Def {Type (IMAGEOPS Field)} {Name IMAGETYPE} {Text Value is the name of an image type. Monochrome display streams have an {lisp IMAGETYPE} of {lisp DISPLAY}; color display streams are identified as {lisp (COLOR DISPLAY)}. The {lisp IMAGETYPE} field is informational and can be set to anything you choose. }} {Def {Type (IMAGEOPS Field)} {Name IMFONTCREATE} {Text Value is the device name to pass to {fn FONTCREATE} when fonts are created for the stream. }} The remaining fields are all image stream methods, whose value should be a device-dependent function that implements the generic operation. Most methods are called by a similarly-named function, e.g. the function {fn DRAWLINE} calls the {lisp IMDRAWLINE} method. All coordinates that refer to points in a display device's space are measured in the device's units. (The {lisp IMSCALE}{index IMSCALE (Image Stream Method)} method provides access to a device's scale.) For arguments that have defaults (such as the {arg BRUSH} argument of {fn DRAWCURVE}), the default is substituted for the {lisp NIL} argument before it is passed to the image stream method. Therefore, image stream methods do not have to handle defaults. {Def {Type (Image Stream Method)} {Name IMCLOSEFN} {Args STREAM} {Text Called before a stream is closed with {fn CLOSEF}. This method should flush buffers, write header or trailer information, etc. }} {Def {Type (Image Stream Method)} {Name IMDRAWLINE} {Args STREAM X{sub 1} Y{sub 1} X{sub 2} Y{sub 2} WIDTH OPERATION COLOR DASHING} {Text Draws a line of width {arg WIDTH} from {lisp ({arg X{sub 1}}, {arg Y{sub 1}})} to {lisp ({arg X{sub 2}}, Y{sub 2})}. See {fn DRAWLINE}, {PageRef Fn DRAWLINE}. }} {Def {Type (Image Stream Method)} {Name IMDRAWCURVE} {Args STREAM KNOTS CLOSED BRUSH DASHING} {Text Draws a curve through {arg KNOTS}. See {fn DRAWCURVE}, {PageRef Fn DRAWCURVE}. }} {Def {Type (Image Stream Method)} {Name IMDRAWCIRCLE} {Args STREAM CENTERX CENTERY RADIUS BRUSH DASHING} {Text Draws a circle of radius {arg RADIUS} around {lisp ({arg CENTERX}, {arg CENTERY})}. See {fn DRAWCIRCLE}, {PageRef Fn DRAWCIRCLE}. }} {Def {Type (Image Stream Method)} {Name IMDRAWELLIPSE} {Args STREAM CENTERX CENTERY SEMIMINORRADIUS SEMIMAJORRADIUS ORIENTATION BRUSH DASHING} {Text Draws an ellipse around {lisp ({arg CENTERX}, {arg CENTERY})}. See {fn DRAWELLIPSE}, {PageRef Fn DRAWELLIPSE}. }} {Def {Type (Image Stream Method)} {Name IMFILLPOLYGON} {Args STREAM POINTS TEXTURE} {Text Fills in the {index Polygons}polygon outlined by {arg POINTS} on the image stream {arg STREAM}, using the texture {arg TEXTURE}. See {fn FILLPOLYGON}, {PageRef Fn FILLPOLYGON}. }} {Def {Type (Image Stream Method)} {Name IMFILLCIRCLE} {Args STREAM CENTERX CENTERY RADIUS TEXTURE} {Text Draws a circle filled with texture {arg TEXTURE} around {lisp ({arg CENTERX}, {arg CENTERY})}. See {fn FILLCIRCLE}, {PageRef Fn FILLCIRCLE}. }} {Def {Type (Image Stream Method)} {Name IMBLTSHADE} {Args TEXTURE STREAM DESTINATIONLEFT DESTINATIONBOTTOM WIDTH HEIGHT OPERATION CLIPPINGREGION} {Text The texture-source case of {fn BITBLT} ({PageRef Fn BITBLT}). {arg DESTINATIONLEFT}, {arg DESTINATIONBOTTOM}, {arg WIDTH}, {arg HEIGHT}, and {arg CLIPPINGREGION} are measured in {arg STREAM}'s units. This method is invoked by the functions {fn BITBLT} and {fn BLTSHADE} ({PageRef Fn BLTSHADE}). }} {Def {Type (Image Stream Method)} {Name IMBITBLT} {Args SOURCEBITMAP SOURCELEFT SOURCEBOTTOM STREAM DESTINATIONLEFT DESTINATIONBOTTOM WIDTH HEIGHT SOURCETYPE OPERATION TEXTURE CLIPPINGREGION CLIPPEDSOURCELEFT CLIPPEDSOURCEBOTTOM SCALE} {Text Contains the bit-map-source cases of {fn BITBLT} ({PageRef Fn BITBLT}). {arg SOURCELEFT}, {arg SOURCEBOTTOM}, {arg CLIPPEDSOURCELEFT}, {arg CLIPPEDSOURCEBOTTOM}, {arg WIDTH}, and {arg HEIGHT} are measured in pixels; {arg DESTINATIONLEFT}, {arg DESTINATIONBOTTOM}, and {arg CLIPPINGREGION} are in the units of the destination stream. }} {Def {Type (Image Stream Method)} {Name IMSCALEDBITBLT} {Args SOURCEBITMAP SOURCELEFT SOURCEBOTTOM STREAM DESTINATIONLEFT DESTINATIONBOTTOM WIDTH HEIGHT SOURCETYPE OPERATION TEXTURE CLIPPINGREGION CLIPPEDSOURCELEFT CLIPPEDSOURCEBOTTOM SCALE} {Text A scaled version of {lisp IMBITBLT}. Each pixel in {arg SOURCEBITMAP} is replicated {arg SCALE} times in the X and Y directions; currently, {arg SCALE} must be an integer. }} {Def {Type (Image Stream Method)} {Name IMMOVETO} {Args STREAM X Y} {Text Moves to {lisp ({arg X},{arg Y})}. This method is invoked by the function {fn MOVETO} ({PageRef Fn MOVETO}). If {lisp IMMOVETO} is not supplied, a default method composed of calls to the {lisp IMXPOSITION} and {lisp IMYPOSITION} methods is used. }} {Def {Type (Image Stream Method)} {Name IMSTRINGWIDTH} {Args STREAM STR RDTBL} {Text Returns the width of string {arg STR} in {arg STREAM}'s units, using {arg STREAM}'s current font. This is envoked when {fn STRINGWIDTH} ({PageRef Fn STRINGWIDTH}) is passed a stream as its {arg FONT} argument. If {lisp IMSTRINGWIDTH} is not supplied, it defaults to calling {fn STRINGWIDTH} on the default font of {arg STREAM}. }} {Def {Type (Image Stream Method)} {Name IMCHARWIDTH} {Args STREAM CHARCODE} {Text Returns the width of character {arg CHARCODE} in {arg STREAM}'s units, using {arg STREAM}'s current font. This is invoked when {fn CHARWIDTH} ({PageRef Fn CHARWIDTH}) is passed a stream as its {arg FONT} argument. If {lisp IMCHARWIDTH} is not supplied, it defaults to calling {fn CHARWIDTH} on the default font of {arg STREAM}. }} {Def {Type (Image Stream Method)} {Name IMCHARWIDTHY} {Args STREAM CHARCODE} {Text Returns the Y componant of the width of character {arg CHARCODE} in {arg STREAM}'s units, using {arg STREAM}'s current font. This is envoked when {fn CHARWIDTHY} ({PageRef Fn CHARWIDTHY}) is passed a stream as its {arg FONT} argument. If {lisp IMCHARWIDTHY} is not supplied, it defaults to calling {fn CHARWIDTHY} on the default font of {arg STREAM}. }} {Def {Type (Image Stream Method)} {Name IMBITMAPSIZE} {Args STREAM BITMAP DIMENSION} {Text Returns the size that {arg BITMAP} will be when {fn BITBLT}ed to {arg STREAM}, in {arg STREAM}'s units. {arg DIMENSION} can be one of {lisp WIDTH}, {lisp HEIGHT}, or {lisp NIL}, in which case the dotted pair {lisp ({arg WIDTH} . {arg HEIGHT})} will be returned. This is envoked by {fn BITMAPIMAGESIZE} ({PageRef Fn BITMAPIMAGESIZE}). If {lisp IMBITMAPSIZE} is not supplied, it defaults to a method that multiplies the bitmap height and width by the scale of {arg STREAM}. }} {Def {Type (Image Stream Method)} {Name IMNEWPAGE} {Args STREAM} {Text Causes a new page to be started. The X position is set to the left margin, and the Y position is set to the top margin plus the linefeed. If not supplied, defaults to {lisp (\OUTCHAR {arg STREAM} (CHARCODE ↑L))}. Envoked by {fn DSPNEWPAGE} ({PageRef Fn DSPNEWPAGE}). }} {Def {Type (Image Stream Method)} {Name IMTERPRI} {Args STREAM} {Text Causes a new line to be started. The X position is set to the left margin, and the Y position is set to the current Y position plus the linefeed. If not supplied, defaults to {lisp (\OUTCHAR {arg STREAM} (CHARCODE EOL))}. Envoked by {fn TERPRI} ({PageRef Fn TERPRI}). }} {Def {Type (Image Stream Method)} {Name IMRESET} {Args STREAM} {Text Resets the X and Y position of {arg STREAM}. The X coordinate is set to its left margin; the Y coordinate is set to the top of the clipping region minus the font ascent. Envoked by {fn DSPRESET}, {PageRef Fn DSPRESET}. }} The following methods all have corresponding {lisp DSP{arg xx}} functions (e.g., {lisp IMYPOSITION} corresponds to {fn DSPYPOSITION}) that invoke them. They also have the property of returning their previous value; when called with {lisp NIL} they return the old value without changing it. {Def {Type (Image Stream Method)} {Name IMCLIPPINGREGION} {Args STREAM REGION} {Text Sets a new clipping region on {arg STREAM}. }} {Def {Type (Image Stream Method)} {Name IMXPOSITION} {Args STREAM XPOSITION} {Text Sets the X-position on {arg STREAM}. }} {Def {Type (Image Stream Method)} {Name IMYPOSITION} {Args STREAM YPOSITION} {Text Sets a new Y-position on {arg STREAM}. }} {Def {Type (Image Stream Method)} {Name IMFONT} {Args STREAM FONT} {Text Sets {arg STREAM}'s font to be {arg FONT}. }} {Def {Type (Image Stream Method)} {Name IMLEFTMARGIN} {Args STREAM LEFTMARGIN} {Text Sets {arg STREAM}'s left margin to be {arg LEFTMARGIN}. The left margin is defined as the X-position set after the new line. }} {Def {Type (Image Stream Method)} {Name IMRIGHTMARGIN} {Args STREAM RIGHTMARGIN} {Text Sets {arg STREAM}'s right margin to be {arg RIGHTMARGIN}. The right margin is defined as the maximum X-position at which characters are printed; printing beyond it causes a new line. }} {Def {Type (Image Stream Method)} {Name IMTOPMARGIN} {Args STREAM YPOSITION} {Text Sets {arg STREAM}'s top margin (the Y-position of the tops of characters that is set after a new page) to be {arg YPOSITION}. }} {Def {Type (Image Stream Method)} {Name IMBOTTOMMARGIN} {Args STREAM YPOSITION} {Text Sets {arg STREAM}'s bottom margin (the Y-position beyond which any printing causes a new page) to be {arg YPOSITION}. }} {Def {Type (Image Stream Method)} {Name IMLINEFEED} {Args STREAM DELTA} {Text Sets {arg STREAM}'s line feed distance (distance to move vertically after a new line) to be {arg DELTA}. }} {Def {Type (Image Stream Method)} {Name IMSCALE} {Args STREAM SCALE} {Text Returns the number of device points per screen point (a screen point being ~1/72 inch). {arg SCALE} is ignored. }} {Def {Type (Image Stream Method)} {Name IMSPACEFACTOR} {Args STREAM FACTOR} {Text Sets the amount by which to multiply the natural width of all following space characters on {arg STREAM}; this can be used for the justification of text. The default value is 1. For example, if the natural width of a space in {arg STREAM}'s current font is 12 units, and the space factor is set to two, spaces appear 24 units wide. The values returned by {fn STRINGWIDTH} and {fn CHARWIDTH} are also affected. }} {Def {Type (Image Stream Method)} {Name IMOPERATION} {Args STREAM OPERATION} {Text Sets the default {fn BITBLT} {arg OPERATION} argument (see {PageRef (BITBLT argument) OPERATION}). }} {Def {Type (Image Stream Method)} {Name IMBACKCOLOR} {Args STREAM COLOR} {Text Sets the background color of {arg STREAM}. }} {Def {Type (Image Stream Method)} {Name IMCOLOR} {Args STREAM COLOR} {Text Sets the default color of {arg STREAM}. }} In addition to the {lisp IMAGEOPS} methods described above, there are two other important methods, which are contained in the stream itself. These fields can be installed using a form like {lisp (replace (STREAM OUTCHARFN) of STREAM with (FUNCTION MYOUTCHARFN))}. Note: You need to have loaded the Interlisp-D system declarations to manipulate the fields of {lisp STREAM}s. The declarations can be loaded by loading the Lisp Library package {lisp SYSEDIT}. {Def {Type (Stream Method)} {Name STRMBOUTFN} {Args STREAM CHARCODE} {Text The function called by {fn BOUT}. }} {Def {Type (Stream Method)} {Name OUTCHARFN} {Args STREAM CHARCODE} {Text The function that is called to output a single byte. This is like {lisp STRMBOUTFN}, except for being one level higher: it is intended for text output. Hence, this function should convert {lisp (CHARCODE EOL)} into the stream's actual end-of-line sequence and should adjust the stream's {lisp CHARPOSITION} appropriately before invoking the stream's {lisp STRMBOUTFN} (by calling {fn BOUT}) to actually put the character. Defaults to {index *PRIMARY* \FILEOUTCHARFN Fn}{indexx {Name FILEOUTCHARFN} {Type Function} {Text {lisp \FILEOUTCHARFN}} }{fn \FILEOUTCHARFN}, which is probably incorrect for an image stream. }} }{End Subsec Implementation of Image Streams}