{Begin Subsec Image Streams} {Title Image Streams} {Text Previously, the only documented way of printing text and graphics on Press or Interpress printers was to use one of the supported tools, such as Tedit. While these tools are sufficient for many needs, there was a need for functions that users could call from their programs to print arbitrary text and graphics. As part of a long-range effort to provide a simple, device-independent interface to the various graphics display routines, "image streams" were created. An image stream is an output stream which "knows" how to process graphic commands. It can be passed as the {arg FILE/STREAM} argument to the ordinary character-output functions ({fn PRINT}, etc.) and to the graphic functions as well ({fn DSPXPOSITION}, {fn DRAWCIRCLE}, etc.). Some image streams, such as display and local-printer streams, may simply execute the appropriate operations to cause the desired image to appear immediately on the output medium. Other image streams ({lisp PRESS}, {lisp INTERPRESS}, etc.) interpret the graphic commands by saving information in a file of the appropriate format. If this file is on the {lisp {bracket LPT}} device, it will automatically be transmitted to a printer device when it is closed by {fn CLOSEF}. Non-{lisp LPT} files can be transmitted later by explicit calls to {fn LISTFILES} and {fn SEND.FILE.TO.PRINTER}. Image streams are created by the following function: {FnDef {Name OPENIMAGESTREAM} {Args FILE IMAGETYPE OPTIONS} {Text Opens and returns an output stream of type {arg IMAGETYPE} on a destination specified by {arg FILE}. {arg IMAGETYPE} can currently be either {lisp PRESS}, {lisp INTERPRESS}, or {lisp DISPLAY}. Eventually, other image types will be implemented for other devices. {arg FILE} can name a file either on a normal storage device or on a printer device. In the latter case, the file is sent to the printer when the stream is closed. {arg FILE} = {lisp NIL} is equivalent to {arg FILE} = {lisp {bracket LPT}}. Names for printer files are of the form {lisp {bracket LPT}{arg PRINTERNAME}.{arg TYPE}}, where {arg PRINTERNAME}, {arg TYPE}, or both may be omitted. {arg PRINTERNAME} is the name of the particular printer to which the file will be transmitted on closing; it defaults to the first printer on {var DEFAULTPRINTINGHOST} that can print {arg IMAGETYPE} files. The {arg TYPE} extension supplies the {arg IMAGETYPE} when it is defaulted (see below). {fn OPENIMAGESTREAM} will generate an error if the specified printer does not accept the kind of file specified by {arg IMAGETYPE}. If {arg IMAGETYPE} is {lisp NIL}, the image type is inferred from the extension field of {arg FILE} and the {lisp EXTENSIONS} properties in the list {var PRINTFILETYPES}.{index PRINTFILETYPES Var} Thus, a {lisp PRESS} extension denotes a Press-format stream, while {lisp IP}, {lisp IPR}, and {lisp INTERPRESS} indicate Interpress format. If {arg FILE} is a printer file with no extension (of the form {lisp {bracket LPT}{arg PRINTERNAME}}), then {arg IMAGETYPE} will be the type that the indicated printer can print. If {arg FILE} has no extension but is not on the printer device {lisp {bracket LPT}}, then {arg IMAGETYPE} will default to the type accepted by the first printer on {var DEFAULTPRINTINGHOST}. Example: Assuming that {lisp IP:} is an Interpress printer, {lisp P} is a Press printer, and {var DEFAULTPRINTINGHOST} is {lisp (IP: P)}: {lisp (OPENIMAGESTREAM)} returns an Interpress image stream on printer {lisp IP:}. {lisp (OPENIMAGESTREAM NIL 'PRESS)} returns a Press stream on {lisp P}. {lisp (OPENIMAGESTREAM '{bracket LPT}.INTERPRESS)} returns an Interpress stream on {lisp IP:}. {lisp (OPENIMAGESTREAM '{bracket CORE}FOO.PRESS)} returns a Press stream on the file {lisp {bracket CORE}FOO.PRESS}. If {arg IMAGETYPE} is {lisp DISPLAY}, then the user is prompted for a window to open. The file name in this case will be used as the title of the window. {arg OPTIONS} is a list in property list format that may be used to specify certain attributes of the image stream; not all attributes are meaningful or interpreted by all types of streams. Among the properties are: {Begin labeledlist OPENIMAGESTREAM options} {Label {lisp REGION}} {Text Value is the region on the page (in stream scale units, 0,0 being the lower-left corner of the page) that text will fill up. It establishes the initial values for {fn DSPLEFTMARGIN}, {fn DSPRIGHTMARGIN}, {fn DSPBOTTOMMARGIN} (the point at which carriage returns cause page advancement) and {fn DSPTOPMARGIN} (where the stream is positioned at the beginning of a new page).} {Label {lisp FONTS}} {Text Value is a list of fonts that are expected to be used in the stream. Some streams (e.g. Interpress) are more efficient if the expected fonts are called out in advance, but this is not necessary. The first font in this list will be the initial font of the stream, otherwise the {fn DEFAULTFONT} for that image type will be used.} {Label {lisp HEADING}} {Text The heading to be placed automatically on each page. {lisp NIL} means no heading.} {End labeledlist OPENIMAGESTREAM options} }} Other functions that are part of the device-independent graphics interface: {FnDef {Name IMAGESTREAMP} {Args X IMAGETYPE} {Text Returns {arg X} (possibly coerced to a stream) if it is an output image stream of type {arg IMAGETYPE} (or of any type if {arg IMAGETYPE}={lisp NIL}), otherwise NIL. }} {FnDef {Name IMAGESTREAMTYPE} {Args STREAM} {Text Returns the image type of {arg STREAM}. }} {FnDef {Name IMAGESTREAMTYPEP} {Args STREAM TYPE} {Text Returns {lisp T} if {arg STREAM} is an image stream of type {arg TYPE}. }} {FnDef {Name DSPSCALE} {Args SCALE STREAM} {Text Returns the scale of the image stream {arg STREAM}, a number indicating how many units in the streams coordinate system correspond to one screen point. For example, {fn DSPSCALE} returns 1 for display streams, and 35.27778 for Press and Interpress streams (the number of micas per screen point). In order to be device-independent, user graphics programs must either not specify position values absolutely, or must multiply absolute screen-point quantities by the {fn DSPSCALE} of the destination stream. (The {arg SCALE} argument to {fn DSPSCALE} is currently ignored; in future releases it will enable the scale of the stream to be changed under user control, so that the necessary multiplication will be done internal to the stream interface). }} Note: Not all graphics operations can be properly executed for all image types. Currently, only display streams support {fn BITBLT}, {fn FILLCIRCLE}, and the dashing argument to {fn DRAWCURVE}. This functionality is still being developed, but even in the long run some operations may be beyond the physical or logical capabilities of some devices or image file formats. In these cases, the stream will approximate the specified image as best it can. {Begin Subsec Previewing Hardcopy on the Display} {Title Previewing Hardcopy on the Display} {Text The fonts used in the printers are not exactly the same as the display fonts, because low-resolution screen fonts don't look good when printed on high-resolution printers. In particular, the character widths are not the same (even when scaled to take account of the printer resolution). Because of this, it is difficult to format text on the display so that it is EXACTLY where you want it, since it will be slightly different when printed. In order to allow users to "preview" hardcopy without actually printing it, the following functions are useful: {FnDef {Name MAKEHARDCOPYSTREAM} {Args DISPLAYSTREAM IMAGETYPE} {Text Changes the display stream so that measurements of character widths are consistent with the hardcopy device {arg IMAGETYPE} ({lisp PRESS}, {lisp INTERPRESS}, etc.). This is useful for seeing on the screen how an image will look when it is hardcopied. Caveat: This doesn't work for TEdit windows. }} {FnDef {Name UNMAKEHARDCOPYSTREAM} {Args DISPLAYSTREAM} {Text Changes a "hardcopy display stream" back into a regular display stream. }} Note: When printing to a "hardcopy display stream", the text will not look as good as it will when printed. In particular, the characters may look crunched together. However, it accurately displays the relative positions of the letters, for formatting purposes. }{End Subsec Previewing Hardcopy on the Display} {Begin SubSec Implementation of Image Streams} {Title Implementation of Image Streams} {Text 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 flavor of stream, known as an image stream. An image stream, by convention, is any stream that has its 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 Dover, 8044, or Diablo printer. For example, the following devices are supported by image streams: windows, Press streams, Interpress streams, and Iris streams. 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 type. The value of {var IMAGESTREAMTYPES} is an association list, indexed by the image-stream type name (e.g., {lisp DISPLAY}, {lisp INTERPRESS}, etc.). Each item of the list associates 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"). 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} 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. With the exception of {lisp IMCLOSEFN},{index IMCLOSEFN (Image Stream Method)} each method has a corresponding function that consists of the method's name with the "{lisp IM}" prefix removed. 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.) {Def {Type (Image Stream Method)} {Name IMCLOSEFN} {Args STREAM} {Text Called before a stream is {fn CLOSEF}ed, e.g., to 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} {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})}. (Dashing is currently handled at a higher level, and thus is not an argument.) }} {Def {Type (Image Stream Method)} {Name IMDRAWCURVE} {Args STREAM KNOTS CLOSED BRUSH DASHING} {Text Draws a curve through {arg KNOTS}. }} {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})}. }} {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})}. }} {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})}. }} {Def {Type (Image Stream Method)} {Name IMBLTSHADE} {Args TEXTURE STREAM DESTINATIONLEFT DESTINATIONBOTTOM WIDTH HEIGHT OPERATION CLIPPINGREGION} {Text The texture-source case of {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}. }} {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}. {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 functions {fn MOVETO} and {fn RELMOVETO}. 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. If {lisp IMSTRINGWIDTH} is not supplied, it defaults to calling {fn \STRINGWIDTH.GENERIC}.{index \STRINGWIDTH.GENERIC Fn} }} {Def {Type (Image Stream Method)} {Name IMCHARWIDTH} {Args STREAM CHARCODE} {Text Returns the width of character {arg CHARCODE} in {arg STREAM}'s units. If {lisp IMCHARWIDTH} is not supplied, it defaults to calling {fn \STRINGWIDTH.GENERIC}.{index \STRINGWIDTH.GENERIC Fn} }} 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 IMXPOSITION} {Args STREAM XPOSITION} {Text Sets a new 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 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 IMNEWPAGE} {Args STREAM} {Text Causes a new page to be started. The position is set to X={lisp (DSPLEFTMARGIN NIL {arg STREAM})}, Y={lisp (DSPTOPMARGIN NIL {arg STREAM})}. If not supplied, defaults to {lisp (\OUTCHAR {arg STREAM} (CHARCODE ^L))}. }} {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 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 IMSPACEFACTOR} {Args STREAM FACTOR} {Text Sets the amount by which to multiply the natural width of all following space characters on {arg STREAM}; is used for 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 {fn BITBLT} ({PageRef Fn BITBLT}) for more information. }} {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}-borne 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))}. {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 {fn \FILEOUTCHARFN},{index \FILEOUTCHARFN Fn} which is probably incorrect for an image stream. }} }{End Subsec Implementation of Image Streams} }{End Subsec Image Streams}