The Apple Computer PICT file format and Tech Info From: Developer CD - 6/93 - Reference Library Edition The PICT file is a data fork file with a 512-byte header, followed by a picture (see Figure 7). This data fork file contains a QuickDraw (and now, Color QuickDraw) data structure within which a graphic application, using standard QuickDraw calls, places drawing opcodes to represent an object or image graphic data. In the QuickDraw picture format, pictures consist of opcodes followed by picture data. ¥¥¥Refer to Figure 7.¥¥¥ Figure 7ÐPICT file format. _______________________________________________________________________________ ÈPicture Parsing The first 512 bytes of a PICT data file contain application-specific header information. Each QuickDraw (and Color QuickDraw) picture definition consists of a fixed-size header containing information about the size, scaling, and version of the picture, followed by the opcodes and picture data defining the objects drawn between the OpenPicture and ClosePicture calls. When the OpenPicture routine is called and the port is an old grafPort, a version 1 picture is opened. When the OpenPicture routine is called and the port is a cGrafPort, then a version 2 picture is opened. If any fields in the grafPort are different than the default entries, those fields that are different get recorded in the picture. Version 4.1 of the Macintosh System file incorporates a patch to QuickDraw that will enable QuickDraw (on machines with 128K or larger ROMs) to parse a version 2 PICT file, read it completely, attempt to convert all Color QuickDraw color opcodes to a suitable black-and-white representation, and draw the picture in an old grafPort. If you are trying to display a version 2 picture on a Macintosh without the system patch, QuickDraw wonÕt be able to draw the picture. _______________________________________________________________________________ ÈPicture Record Structure The Pascal record structure of version 1 and version 2 pictures is exactly the same. In both, the picture begins with a picSize, then a picFrame (rect), followed by the picture definition data. Since a picture may include any sequence of drawing commands, its data structure is a variable-length entity. It consists of two fixed-length fields followed by a variable-length field: TYPE Picture = RECORD picSize: INTEGER; {low order 16 bits of picture } { size} picFrame: Rect; {picture frame, used as } { reference for scaling when } { the picture is drawn } {picture definition data} END; To maintain compatibility with the original picture format, the picSize field has not been changed in version 2 pictures. However, the information in this field is only useful if your application supports version 1 pictures not exceeding 32K bytes in size. Because pictures can be much larger than the 32K limit imposed by the 2-byte picSize field, use the GetHandleSize call to determine picture size if the picture is in memory or the file size returned in pBFGetInfo if the picture resides in a file. The picFrame field is the picture frame that surrounds the picture and gives a frame of reference for scaling when the picture is played back. The rest of the structure contains a compact representation of the image defined by the opcodes. The picture definition data consists of a sequence of the opcodes listed in Table 3 in the Pict Opcodes section, each followed by zero or more bytes of data. Every opcode has an implicit or explicit size associated with it that indicates the number of data bytes following that opcode, ranging from 2 to 2^32 bytes (this maximum number of bytes applies to version 2 pictures only). _______________________________________________________________________________ ÈPicture Spooling In the past, images rarely exceeded the 32K practical limit placed on resources. Today, with the advent of scanners and other image input products, images may easily exceed this size. This increase in image size necessitates a means for handling pictures that are too large to reside entirely in memory. One solution is to place the picture in the data fork of a PICT file, and spool it in as needed. To read the file, an application can simply replace the QuickDraw default getPicProc routine with a procedure (getPICTData) that reads the picture data from a disk file; the disk access would be transparent. Note that this technique applies equally to version 1 (byte-opcode) and version 2 (word-opcode) pictures. ÈSpooling a Picture From Disk In order to display pictures of arbitrary size, an application must be able to import a QuickDraw picture from a file of type PICT. (This is the file type produced by a Save As command from MacDraw¨ with the PICT option selected.) What follows is a small program fragment that demonstrates how to spool in a picture from the data fork of a PICT file. The picture can be larger than the historical 32K resource size limitation. { The following variable and procedure must be at the } { main level of the program } VAR globalRef: INTEGER; PROCEDURE GetPICTData(dataPtr: Ptr; byteCount: INTEGER); {replacement for getPicProc routine} VAR err : INTEGER; longCount: LONGINT; BEGIN longCount := byteCount; {longCount is a Pascal VAR parameter and must be a LONGINT} err := FSRead(globalRef,longCount,dataPtr); {ignore errors here since it is unclear how to handle them} END; PROCEDURE GetandDrawPICTFile; {procedure to draw in a picture from a PICT file selected by the user} VAR wher: Point; {where to display dialog} reply: SFReply; {reply record} myFileTypes: SFTypeList; {more of the Standard File goodies} NumFileTypes: INTEGER; err: OSErr; myProcs: QDProcs; {use CQDProcs for a CGrafPort (a color } { window)} PICTHand: PicHandle; {we need a picture handle for DrawPicture} longCount: LONGINT; myPB: ParamBlockRec; BEGIN wher.h := 20; wher.v := 20; NumFileTypes := 1; {Display PICT files} myFileTypes[0] := 'PICT'; SFGetFile(wher,'',NIL,NumFileTypes,myFileTypes,NIL,reply); IF reply.good THEN BEGIN err := FSOpen(reply.fname,reply.vrefnum,globalRef); SetStdProcs(myProcs); {use SetStdCProcs for a CGrafPort} myWindow^.grafProcs := @myProcs; myProcs.getPicProc := @GetPICTData; PICTHand := PicHandle(NewHandle(SizeOf(Picture))); {get one the size of (size word + frame rectangle)} {skip (so to speak) the MacDraw header block} err := SetFPos(globalRef,fsFromStart,512); longCount := SizeOf(Picture); {read in the (obsolete) size word and the picture frame} err := FSRead(globalRef,longCount,Ptr(PICTHand^)); DrawPicture(PICTHand,PICTHand^^.picFrame); {inside of DrawPicture, QD makes repeated calls to } { getPicProc to get actual picture opcodes and data. Since } { we have intercepted GetPicProc, QD will call myProcs to } { get getPicProc, instead of calling the default procedure} err := FSClose(globalRef); myWindow^.grafProcs := NIL; DisposHandle(Handle(PICTHand)); END; {IF reply.good} END; ÈSpooling a Picture to a File Spooling a picture out to a file is equally straightforward. By replacing the standard putPicProc with your own procedure, you can create a PICT file and spool the picture data out to the file. Here is a sample of code to use as a guide: {these variables and PutPICTData must be at the main program level} VAR PICTcount: LONGINT; {the current size of the picture} globalRef: INTEGER; {the file system reference number} newPICThand: PicHandle; {this is the replacement for the StdPutPic routine} PROCEDURE PutPICTData(dataPtr: Ptr; byteCount: INTEGER); VAR longCount: LONGINT; err: INTEGER; BEGIN {unfortunately, we don't know what to do with errors} longCount := byteCount; PICTCount := PICTCount + byteCount; err := FSWrite(globalRef, longCount, dataPtr); {ignore errorÉ} IF newPICTHand <> NIL THEN newPICTHand^^.picSize := PICTCount; {update so QD can track the size for oddness and pad out to full words} END; {Note that this assumes the picture is entirely in memory which wouldn't } { always be the case. You could (in effect) be feeding the StdGetPic } { procedure at the same time, or simply spooling while drawing.} PROCEDURE SpoolOutPICTFile(PICTHand: PicHandle {the picture to spool}); VAR err: OSErr; i: INTEGER; wher: Point; { where to display dialog } longCount, Zero: LONGINT; pframe: Rect; reply: SFReply; { reply record } myProcs: QDProcs; {use CQDProcs for a CGrafPort (a color window)} BEGIN wher.h := 20; wher.v := 20; {get a file to output to} SFPutFile(wher, 'Save the PICT as:', 'untitled', NIL, reply); IF reply.good THEN BEGIN err := Create(reply.fname, reply.vrefnum, '????', 'PICT'); IF (err = noerr) | (err = dupfnerr) THEN BEGIN {now open the target file and prepare to spool to it} signal(FSOpen(reply.fname, reply.vrefnum, globalRef)); SetStdProcs(myProcs); {use SetStdCProcs for a CGrafPort} myWindow^.grafProcs := @myProcs; myProcs.putPicProc := @putPICTdata; Zero := 0; longCount := 2; PICTCount := SizeOf(Picture); {now write out the 512 byte header and zero (initially) the} { Picture structure} FOR i := 1 TO (512 + SizeOf(Picture)) DIV longCount DO Signal(FSWrite(globalRef, longCount, @Zero)); {open a new picture and draw the old one to it; this will convert} { the old picture to fit the type of GrafPort to which we are} { currently set} pFrame := PICThand^^.picFrame; newPICTHand := NIL; newPICTHand := OpenPicture(pFrame); DrawPicture(PICTHand, pFrame); {draw the picture so the bottleneck will be used. In real life you could be spooling while doing drawing commands (you might not use DrawPicture)} ClosePicture; Signal(SetFPos(globalRef, fsFromStart, 512)); {skip the MacDraw header} longCount := SizeOf(Picture); {write out the correct (low word of the) size and the frame at} { the beginning} Signal(FSWrite(globalRef, longCount, Ptr(newPICTHand^))); Signal(FSClose(globalRef)); myWindow^.grafProcs := NIL; KillPicture(newPICTHand); END ELSE Signal(err); END; {IF reply.good} END; {OutPICT} ÈDrawing to an Offscreen Pixel Map With the advent of high resolution output devices such as laser printers, it has become necessary to support bitmap images at resolutions higher than those supported by the screen. To speed up the interactive manipulation of high-resolution pixel map images, developers may want to first draw them into an off screen pixel map at screen resolution and retain this screen version as long as the document is open. Note:ÊÊYou can use the formula shown in the section ÒSample PICT fileÓ to calculate the resolution of the source data. How to draw into an offscreen pixmap is described in Macintosh Technical Note #120, ÒDrawing Into an Off-Screen Pixel MapÓ; the Graphics Devices chapter also contains a section describing how to draw to an offscreen device. _______________________________________________________________________________ ÈNew GrafProcs Record The entire opcode space has been defined or reserved, as shown in the PICT Opcodes section in Table 3, and a new set of routines has been added to the grafProcs record. These changes provide support for anticipated future enhancements in a way that wonÕt cause old applications to crash. It works like this: when Color QuickDraw encounters an unused opcode, it calls the new opcodeProc routine to parse the opcode data. By default, this routine simply ignores the data, since no new opcodes are defined (other than HeaderOp, which is also ignored). Color QuickDraw has replaced the QDProcs record with a CQDProcs record. In a new grafPort, you should never use the SetStdProcs routine. If you do, it will return the old QDProcs record, which wonÕt contain an entry for the stdOpcodeProc. If you donÕt use the new SetStdCProcs routine, the first color picture that you try to display may crash your system. The CQDProcs record structure is shown below. Only the last seven fields are new; the rest of the fields are the same as those in the QDProcs record. CQDProcsPtr = ^CQDProcs CQDProcs = RECORD textProc: Ptr; lineProc: Ptr; rectProc: Ptr; rRectProc: Ptr; ovalProc: Ptr; arcProc: Ptr; polyProc: Ptr; rgnProc: Ptr; bitsProc: Ptr; commentProc: Ptr; txMeasProc: Ptr; getPicProc: Ptr; putPicProc: Ptr; opcodeProc: Ptr; {fields added to QDProcs} newProc1: Ptr; {reserved for future use} newProc2: Ptr; {reserved for future use} newProc3: Ptr; {reserved for future use} newProc4: Ptr; {reserved for future use} newProc5: Ptr; {reserved for future use} newProc6: Ptr; {reserved for future use} END; _______________________________________________________________________________ ÈPicture Compatibility Many applications already support PICT resources larger than 32K. The 128K ROMs (and later) allow pictures as large as memory (or spooling) will accommodate. This was made possible by having QuickDraw ignore the size word and simply read the picture until the end-of-picture opcode is reached. Note: For maximum safety and convenience, let QuickDraw generate and interpret your pictures. While the PICT data formats described in this section allow you to read or write picture data directly, itÕs best to let DrawPicture or OpenPicture and ClosePicture process the opcodes. One reason to read a picture directly by scanning the opcodes is to disassemble it; for example, extracting a Color QuickDraw pixel map to store in a private data structure. This shouldnÕt normally be necessary, unless your application is running on a CPU other than the Macintosh. You wouldnÕt need to do it, of course, if you were using Color QuickDraw. If your application does use the picture data, be sure it checks the version information. You may want to include an alert box in your application, indicating to users whether a picture was created using a later version of the picture format than is currently recognized by your application, and letting them know that some elements of the picture canÕt be displayed. If the version information indicates a QuickDraw picture version later than the one recognized by your application, your program should skip over the new opcodes and only attempt to parse the opcodes it knows. As with reading picture data directly, itÕs best to use QuickDraw to create data in the PICT format. If you need to create PICT format data directly, itÕs essential that you understand and follow the format presented in Table 3 and thoroughly test the data produced on both color and black and white Macintosh machines. _______________________________________________________________________________ ÈPicture Format This section describes the internal structure of the QuickDraw picture, consisting of a fixed-length header (which is different for version 1 and version 2 pictures), followed by variable-sized picture data. Your picture structure must follow the order shown in the examples below. The two fixed-length fields, picSize and picFrame, are the same for version 1 and version 2 pictures. picSize: INTEGER; {low-order 16 bits of picture size} picFrame: RECT; {picture frame, used as scaling reference} Following these fields is a variable amount of opcode-driven data. Opcodes represent drawing commands and parameters that affect those drawing commands in the picture. The first opcode in any picture must be the version opcode, followed by the version number of the picture. ÈPicture Definition: Version 1 In a version 1 picture, the version opcode is $11, which is followed by version number $01. When parsing a version 1 picture, Color QuickDraw (or a patched QuickDraw) assumes itÕs reading an old picture, fetching a byte at a time as opcodes. An end-of-picture byte ($FF) after the last opcode or data byte in the file signals the end of the data stream. Picture Header (fixed size of 2 bytes): $11 BYTE {version opcode} $01 BYTE {version number of picture} Picture Definition Data (variable sized): opcode BYTE {one drawing command} data . . . opcode BYTE {one drawing command} data . . . $FF {end-of-picture opcode} ÈPicture Definition: Version 2 In a version 2 picture, the first opcode is a two-byte version opcode ($0011). This is followed by a two-byte version number ($02FF). On machines without the 4.1 System file, the first $00 byte is skipped, then the $11 is interpreted as a version opcode. On a Macintosh II (or a Macintosh with System file 4.1 or later), this field identifies the picture as a version 2 picture, and all subsequent opcodes are read as words (which are word-aligned within the picture). On a Macintosh without the 4.1 System patch, the $02 is read as the version number, then the $FF is read and interpreted as the end-of-picture opcode. For this reason, DrawPicture terminates without drawing anything. Picture Header (fixed size of 30 bytes): $0011 WORD {version opcode} $02FF WORD {version number of new picture} $0C00 WORD {reserved header opcode} 24 bytes of data {reserved for future Apple use} Picture Definition Data (variable sized): opcode WORD {one drawing command} data . . . opcode WORD {one drawing command} data . . . $00FF WORD {end-of-picture opcode} For future expandibility, the second opcode in every version 2 picture must be a reserved header opcode, followed by 24 bytes of data that arenÕt used by your application. ÈPicComments If your application requires capability beyond that provided by the picture opcodes, the picComment opcode allows data or commands to be passed directly to the output device. PicComments enable MacDraw, for example, to reconstruct graphics primitives not found in QuickDraw (such as rotated text) that are received either from the Clipboard or from another application. PicComments are also used as a means of communicating more effectively with the LaserWriter and with other applications via the scrap or the PICT data file. Because some operations (like splines and rotated text) can be implemented more efficiently by the LaserWriter, some of the picture comments are designed to be issued along with QuickDraw commands that simulate the commented commands on the Macintosh screen. If the printer you are using has not implemented the comment commands, it ignores them and simulates the operations using the accompanying QuickDraw commands. Otherwise, it uses the comments to implement the desired effect and ignores the appropriate QuickDraw-simulated commands. If you are going to produce or modify your own picture, the structure and use of these comments must be precise. The comments and the embedded QuickDraw commands must come in the correct sequence in order to work properly. Note: Apple is currently investigating a method to register picComments. If you intend to use new picComments in your application, you must contact AppleÕs Developer Technical Support to avoid conflict with picComment numbers used by other developers. ÈSample PICT File An example of a version 2 picture data file that can display a single image is shown in Table 1. Applications that generate picture data should set the resolution of the image source data in the hRes and vRes fields of the PICT file. ItÕs recommended, however, that you calculate the image resolution anyway, using the values for srcRect and dstRect according to the following formulas: horizontal resolution (hRes) = width of srcRect x 72 ________________ width of dstRect vertical resolution (vRes) = height of srcRect x 72 _________________ height of dstRect Table 1ÐPICT file example _______________________________________________________________________________ Size Name Description (in bytes) 2 picSize low word of picture size 8 picFrame rectangular bounding box of picture, at 72 dpi Picture Definition Data: 2 version op version opcode = $0011 2 version version number = $02FF 2 Header op header opcode = $0C00 4 size total size of picture in bytes (Ð1 for version 2 pictures) 16 fBBox fixed-point bounding box (Ð1 for version 2 pictures) 4 reserved reserved for future Apple use (Ð1 for version 2 pictures) 2 opbitsRect bitMap opcode = $0090 2 rowBytes integer, must have high bit set to signal pixMap 8 bounds rectangle, bounding rectangle at source resolution 2 pmVersion integer, pixMap version number 2 packType integer, defines packing format 4 packSize LongInt, length of pixel data 4 hRes fixed, horizontal resolution (dpi) of source data 4 vRes fixed, vertical resolution (dpi) of source data 2 pixelType integer, defines pixel type 2 pixelSize integer, number of bits in pixel 2 cmpCount integer, number of components in pixel 2 cmpSize integer, number of bits per component 4 planeBytes LongInt, offset to next plane pmTable color table = 0 pmReserved reserved = 0 4 ctSeed LongInt, color table seed 2 ctFlags integer, flags for color table 2 ctSize integer, number of entries in ctTable Ð1 (ctSize+1) * 8 ctTable color lookup table data 8 srcRect rectangle, source rectangle at source resolution 8 dstRect rectangle, destination rectangle at 72 dpi resolution 2 mode integer, transfer mode see Table 5 pixData pixel data 2 endPICT op end-of-picture opcode = $00FF _______________________________________________________________________________ ÈColor Picture Routines FUNCTION OpenPicture (picFrame: Rect) : PicHandle; The OpenPicture routine has been modified to take advantage of QuickDrawÕs new color capabilities. If the current port is a cGrafPort, then OpenPicture automatically opens a version 2 picture, as described in the previous section. As before, you close the picture using ClosePicture and draw the picture using DrawPicture. _______________________________________________________________________________ ¾KY PICTÉOpcodes ¾C ÈPICT OPCODES ColorQuickDraw _______________________________________________________________________________ The opcode information in Table 3 is provided for the purpose of debugging application-generated PICT files. Your application should generate and read PICT files only by using standard QuickDraw or Color QuickDraw routines (OpenPicture, ClosePicture). The data types listed in Table 2 are used in the Table 3 opcode definitions. Data formats are described in Volume I. Table 2ÐData types _______________________________________________________________________________ Type Size v1 opcode 1 byte v2 opcode 2 bytes integer 2 bytes long integer 4 bytes mode 2 bytes point 4 bytes 0..255 1 byte Ð128..127 1 byte (signed) rect 8 bytes (top, left, bottom, right: integer) poly 10+ bytes region 10+ bytes fixed-point number 4 bytes pattern 8 bytes rowbytes 2 bytes (always an even quantity) _______________________________________________________________________________ Valid picture opcodes are listed in Table 3. New opcodes or those altered for version 2 picture files are indicated by a leading asterisk (*). The unused opcodes found throughout the table are reserved for Apple use. The length of the data that follows these opcodes is pre-defined, so if they are encountered in pictures, they can simply be skipped. By default, Color QuickDraw reads and then ignores these opcodes. Table 3ÐPICT opcodes _______________________________________________________________________________ Opcode Name Description Data Size (in bytes) $0000 NOP nop 0 $0001 Clip clip region size $0002 BkPat background pattern 8 $0003 TxFont text font (word) 2 $0004 TxFace text face (byte) 1 $0005 TxMode text mode (word) 2 $0006 SpExtra space extra (fixed point) 4 $0007 PnSize pen size (point) 4 $0008 PnMode pen mode (word) 2 $0009 PnPat pen pattern 8 $000A FillPat fill pattern 8 $000B OvSize oval size (point) 4 $000C Origin dh, dv (word) 4 $000D TxSize text size (word) 2 $000E FgColor foreground color (long) 4 $000F BkColor background color (long) 4 $0010 TxRatio numer (point), denom (point) 8 $0011 Version version (byte) 1 $0012 *BkPixPat color background pattern variable: see Table 4 $0013 *PnPixPat color pen pattern variable: see Table 4 $0014 *FillPixPat color fill pattern variable: see Table 4 $0015 *PnLocHFrac fractional pen position 2 $0016 *ChExtra extra for each character 2 $0017 *reserved for Apple use opcode 0 $0018 *reserved for Apple use opcode 0 $0019 *reserved for Apple use opcode 0 $001A *RGBFgCol RGB foreColor variable: see Table 4 $001B *RGBBkCol RGB backColor variable: see Table 4 $001C *HiliteMode hilite mode flag 0 $001D *HiliteColor RGB hilite color variable: see Table 4 $001E *DefHilite Use default hilite color 0 $001F *OpColor RGB OpColor for variable: arithmetic modes see Table 4 $0020 Line pnLoc (point), newPt (point) 8 $0021 LineFrom newPt (point) 4 $0022 ShortLine pnLoc (point, dh, dv 6 (-128..127) $0023 ShortLineFrom dh, dv (-128..127) 2 $0024 *reserved for Apple use opcode + 2 bytes data 2+ data length + data length $0025 *reserved for Apple use opcode + 2 bytes data 2+ data length + data length $0026 *reserved for Apple use opcode + 2 bytes data 2+ data length + data length $0027 *reserved for Apple use opcode + 2 bytes data 2+ data length + data length $0028 LongText txLoc (point), count 5 + text (0..255), text $0029 DHText dh (0..255), count 2 + text (0..255), text $002A DVText dv (0..255), count 2 + text (0..255), text $002B DHDVText dh, dv (0..255), count 3 + text (0..255), text $002C *reserved for Apple use opcode + 2 bytes data 2+ data length + data length $002D *reserved for Apple use opcode + 2 bytes data 2+ data length + data length $002E *reserved for Apple use opcode + 2 bytes data 2+ data length + data length $002F *reserved for Apple use opcode + 2 bytes data 2+ data length + data length $0030 frameRect rect 8 $0031 paintRect rect 8 $0032 eraseRect rect 8 $0033 invertRect rect 8 $0034 fillRect rect 8 $0035 *reserved for Apple use opcode + 8 bytes data 8 $0036 *reserved for Apple use opcode + 8 bytes data 8 $0037 *reserved for Apple use opcode + 8 bytes data 8 $0038 frameSameRect rect 0 $0039 paintSameRect rect 0 $003A eraseSameRect rect 0 $003B invertSameRect rect 0 $003C fillSameRect rectangle 0 $003D *reserved for Apple use opcode 0 $003E *reserved for Apple use opcode 0 $003F *reserved for Apple use opcode 0 $0040 frameRRect rect (see Note # 5 ) 8 $0041 paintRRect rect (see Note # 5 ) 8 $0042 eraseRRect rect (see Note # 5 ) 8 $0043 invertRRect rect (see Note # 5 ) 8 $0044 fillRRect rect (see Note # 5 ) 8 $0045 *reserved for Apple use opcode + 8 bytes data 8 $0046 *reserved for Apple use opcode + 8 bytes data 8 $0047 *reserved for Apple use opcode + 8 bytes data 8 $0048 frameSameRRect rect 0 $0049 paintSameRRect rect 0 $004A eraseSameRRect rect 0 $004B invertSameRRect rect 0 $004C fillSameRRect rect 0 $004D *reserved for Apple use opcode 0 $004E *reserved for Apple use opcode 0 $004F *reserved for Apple use opcode 0 $0050 frameOval rect 8 $0051 paintOval rect 8 $0052 eraseOval rect 8 $0053 invertOval rect 8 $0054 fillOval rect 8 $0055 *reserved for Apple use opcode + 8 bytes data 8 $0056 *reserved for Apple use opcode + 8 bytes data 8 $0057 *reserved for Apple use opcode + 8 bytes data 8 $0058 frameSameOval rect 0 $0059 paintSameOval rect 0 $005A eraseSameOval rect 0 $005B invertSameOval rect 0 $005C fillSameOval rect 0 $005D *reserved for Apple use opcode 0 $005E *reserved for Apple use opcode 0 $005F *reserved for Apple use opcode 0 $0060 frameArc rect, startAngle, arcAngle 12 $0061 paintArc rect, startAngle, arcAngle 12 $0062 eraseArc rect, startAngle, arcAngle 12 $0063 invertArc rect, startAngle, arcAngle 12 $0064 fillArc rect, startAngle, arcAngle 12 $0065 *reserved for Apple use opcode + 12 bytes 12 $0066 *reserved for Apple use opcode + 12 bytes 12 $0067 *reserved for Apple use opcode + 12 bytes 12 $0068 frameSameArc rect 4 $0069 paintSameArc rect 4 $006A eraseSameArc rect 4 $006B invertSameArc rect 4 $006C fillSameArc rect 4 $006D *reserved for Apple use opcode + 4 bytes 4 $006E *reserved for Apple use opcode + 4 bytes 4 $006F *reserved for Apple use opcode + 4 bytes 4 size $0070 framePoly poly polygon size $0071 paintPoly poly polygon size $0072 erasePoly poly polygon size $0073 invertPoly poly polygon size $0074 fillPoly poly polygon size $0075 *reserved for Apple use opcode + poly $0076 *reserved for Apple use opcode + poly $0077 *reserved for Apple use opcode word + poly $0078 frameSamePoly (not yet implemented: 0 same as 70, etc) $0079 paintSamePoly (not yet implemented) 0 $007A eraseSamePoly (not yet implemented) 0 $007B invertSamePoly (not yet implemented) 0 $007C fillSamePoly (not yet implemented) 0 $007D *reserved for Apple use opcode 0 $007E *reserved for Apple use opcode 0 $007F *reserved for Apple use opcode 0 $0080 frameRgn rgn region size $0081 paintRgn rgn region size $0082 eraseRgn rgn region size $0083 invertRgn rgn region size $0084 fillRgn rgn region size $0085 *reserved for Apple use opcode + rgn region size $0086 *reserved for Apple use opcode + rgn region size $0087 *reserved for Apple use opcode + rgn region size $0088 frameSameRgn (not yet implemented: 0 same as 80, etc.) $0089 paintSameRgn (not yet implemented) 0 $008A eraseSameRgn (not yet implemented) 0 $008B invertSameRgn (not yet implemented) 0 $008C fillSameRgn (not yet implemented) 0 $008D *reserved for Apple use opcode 0 $008E *reserved for Apple use opcode 0 $008F *reserved for Apple use opcode 0 $0090 *BitsRect copybits, rect clipped variable: see Table 4 $0091 *BitsRgn copybits, rgn clipped variable: see Table 4 $0092 *reserved for Apple use opcode + 2 bytes data 2+ data length + data length $0093 *reserved for Apple use opcode + 2 bytes data 2+ data length + data length $0094 *reserved for Apple use opcode + 2 bytes data 2+ data length + data length $0095 *reserved for Apple use opcode + 2 bytes data 2+ data length + data length $0096 *reserved for Apple use opcode + 2 bytes data 2+ data length + data length $0097 *reserved for Apple use opcode word + 2 bytes 2+ data data length + data length $0098 *PackBitsRect packed copybits, rect variable: clipped see Table 4 $0099 *PackBitsRgn packed copybits, rgn variable: clipped see Table 4 $009A *reserved for Apple use opcode + 2 bytes data 2+ data length + data length $009B *reserved for Apple use opcode + 2 bytes data 2+ data length + data length $009C *reserved for Apple use opcode + 2 bytes data 2+ data length + data length $009D *reserved for Apple use opcode + 2 bytes data 2+ data length + data length $009E *reserved for Apple use opcode + 2 bytes data 2+ data length + data length $009F *reserved for Apple use opcode + 2 bytes data 2+ data length + data length $00A0 ShortComment kind (word) 2 $00A1 LongComment kind (word), size 4+data (word), data $00A2 *reserved for Apple use opcode + 2 bytes data 2+ data length + data length : : : : : : $00AF *reserved for Apple use opcode + 2 bytes data 2+ data length + data length $00B0 *reserved for Apple use opcode 0 : : : : : : $00CF *reserved for Apple use opcode 0 $00D0 *reserved for Apple use opcode + 4 bytes data 4+ data length + data length : : : : : : $00FE *reserved for Apple use opcode + 4 bytes data 4+ data length + data length $00FF opEndPic end of picture 2 $0100 *reserved for Apple use opcode + 2 bytes data 2 : : : : : : $01FF *reserved for Apple use opcode + 2 bytes data 2 $0200 *reserved for Apple use opcode + 4 bytes data 4 : : : $0BFF *reserved for Apple use opcode + 4 bytes data 22 $0C00 HeaderOp opcode 24 $0C01 *reserved for Apple use opcode + 4 bytes data 24 : : : $7F00 *reserved for Apple use opcode + 254 bytes data 254 : : : $7FFF *reserved for Apple use opcode + 254 bytes data 254 $8000 *reserved for Apple use opcode 0 : : : $80FF *reserved for Apple use opcode 0 $8100 *reserved for Apple use opcode + 4 bytes data 4+ data length + data length : : : $FFFF *reserved for Apple use opcode + 4 bytes data 4+ data length + data length _______________________________________________________________________________ Notes to Table 3 1. The opcode value has been extended to a word for version 2 pictures. Remember, opcode size = 1 byte for version 1. 2. Because opcodes must be word aligned in version 2 pictures, a byte of 0 (zero) data is added after odd-size data. 3. The size of reserved opcodes has been defined. They can occur only in version 2 pictures. 4. All unused opcodes are reserved for future Apple use and should not be used. 5. For opcodes $0040Ð$0044: rounded-corner rectangles use the setting of the ovSize point (refer to opcode $000B) 6. For opcodes $0090 and $0091: data is unpacked. These opcodes can only be used for rowbytes less than 8. 7. For opcodes $0100Ð$7FFF: the amount of data for opcode $nnXX = 2 * nn bytes. _______________________________________________________________________________ ÈThe New Opcodes: Expanded Format The expanded format of the version 2 PICT opcodes is shown in Table 4 below. Table 4ÐData Format of Version 2 PICT Opcodes _______________________________________________________________________________ Opcode Name Description Reference to Notes $0012 BkPixPat color background pattern See Note 1 $0013 PnPixPat color pen pattern See Note 1 $0014 FillPixPat color fill pattern See Note 1 $0015 PnLocHFrac fractional pen If pnLocHFrac <> 1/2, it position (word) is always put to the picture before each text drawing operation. $0016 ChExtra extra for each After chExtra changes, character (word) it is put to picture before next text drawing operation. $001A RGBFgCol RGB foreColor (RBGColor) desired RGB for foreground $001B RGBBkCol RGB backColor (RGBColor) desired RGB for background $001D HiliteColor RGB hilite color $001F OpColor RGB OpColor for arithmetic modes $001C HiliteMode hilite mode flag No data; this opcode is sent before a drawing operation that uses the hilite mode. $001E DefHilite Use default hilite No data; set hilite color to default (from low memory). $0090 BitsRect copybits, rect See Note 2,4,5 clipped $0091 BitsRgn copybits, rgn See Note 3,4,5 clipped $0098 PackBitsRect packed copybits, See Note 2,4 rect clipped $0099 PackBitsRgn packed copybits, See Note 3,4 rgn clipped _______________________________________________________________________________ Notes to Table 4 1. if patType = ditherPat then PatType: word; {pattern type = 2} Pat1Data: Pattern; {old pattern data} RGB: RGBColor; {desired RGB for pattern} else PatType: word; {pattern type = 1} Pat1Data: Pattern; {old pattern data} pixMap: {described in Table 5} colorTable: {described in Table 5} pixData: {described in Table 5} end; 2. pixMap: {described in Table 5} colorTable: {described in Table 5} srcRect: Rect; {source rectangle} dstRect: Rect; {destination rectangle} mode: Word; {transfer mode (may include new transfer } { modes)} PixData: {described in Table 5} 3. pixMap: {described in Table 5 } colorTable: {described in Table 5 } srcRect: Rect; {source rectangle} dstRect: Rect; {destination rectangle} mode: Word; {transfer mode (may include new transfer } { modes)} maskRgn: Rgn; {region for masking} PixData: {described in Table 5} 4. These four opcodes ($0090, $0091, $0098, $0099) are modifications of existing (version 1) opcodes. The first word following the opcode is the rowBytes. If the high bit of the rowBytes is set, then it is a pixMap containing multiple bits per pixel; if it is not set, it is a bitMap containing one bit per pixel. In general, the difference between version 1 and version 2 formats is that the pixMap replaces the bitMap, a color table has been added, and pixData replaces the bitData. 5. Opcodes $0090 and $0091 are used only for rowbytes less than 8. Table 5ÐData Types Found Within New PICT Opcodes Listed in Table 4 _______________________________________________________________________________ Data Type Field Definitions Comments pixMap = baseAddr: long; {unused = 0} rowBytes: word; {rowBytes w/high byte set} Bounds: rect; {bounding rectangle} version: word; {version number = 0} packType: word; {packing format = 0} packSize: long; {packed size = 0} hRes: fixed; {horizontal resolution (default = } { $0048.0000)} vRes: fixed; {vertical resolution (default= } { $0048.0000)} pixelType: word; {chunky format = 0} pixelSize: word; {# bits per pixel (1,2,4,8)} cmpCount: word; {# components in pixel = 1} cmpSize: word; {size of each component = pixelSize } { for chunky} planeBytes: long; {offset to next plane = 0} pmTable: long; {color table = 0} pmReserved: long; {reserved = 0} end; colorTable = ctSeed: long; {id number for color table = 0} ctFlags: word; {flags word = 0} ctSize: word; {number of ctTable entries-1 } { ctSize + 1 color table entries } { each entry = pixel value, red, } { green, blue: word} end; pixData: {the following pseudocode describes the pixData data type} If rowBytes < 8 then data is unpacked data size = rowBytes*(bounds.bottom-bounds.top); If rowBytes >= 8 then data is packed. Image contains (bounds.bottom-bounds.top) packed scanlines. Packed scanlines are produced by the PackBits routine. Each scanline consists of [byteCount] [data]. If rowBytes > 250 then byteCount is a word, else it is a byte. end; _______________________________________________________________________________ ¾KY SummaryÉofÉColorÉQuickDraw ¾C ÈSUMMARY OF COLOR QUICKDRAW ColorQuickDraw _______________________________________________________________________________ Constants CONST { Old-style grafPort colors } ÊblackColor Ê =Ê33; ÊwhiteColor Ê=Ê30; ÊredColor Ê=Ê209; ÊgreenColor Ê=Ê329; ÊblueColor =Ê389; ÊcyanColor =Ê269; ÊmagentaColorÊ=Ê149; ÊyellowColor =Ê89; { Arithmetic transfer modes } blend = 32; addPin = 33; addOver = 34; subPin = 35; adMax = 37; subOver = 38; adMin = 39; { Transparent mode constant } transparent = 36; { Text mask constant } mask = 64; { Highlight constants } hilite = 50; pHiliteBit = 0; {this is the correct value for use when } { calling the BitClear trap. BClr must use } { the assembly language equate hiliteBit} { Constant for resource IDs } defQDColors = 127; _______________________________________________________________________________ Data Types TYPE RGBColor = RECORD red: INTEGER; {red component} green: INTEGER; {green component} blue: INTEGER {blue component} END; ColorSpec = RECORD value: INTEGER; {index or other value} rgb: RGBColor {true color} END; cSpecArray : ARRAY [0..0] of ColorSpec; CTabHandle = ^CTabPtr; CTabPtr = ^ColorTable; ColorTable = RECORD ctSeed: LONGINT; {unique identifier from table} ctFlags: INTEGER; {high bit is 1 for device, 0 } { for pixMap} ctSize: INTEGER; {number of entries -1 in } { ctTable} ctTable: cSpecArray END; CGrafPtr = ^CGrafPort; CGrafPort = RECORD device: INTEGER; {device ID for font selection} portPixMap: PixMapHandle; {port's pixel map} portVersion: INTEGER; {highest 2 bits always set} grafVars: Handle; {handle to more fields} chExtra: INTEGER; {extra characters placed} { on the end of a string} pnLocHFrac: INTEGER; {pen fraction} portRect: Rect; {port rectangle} visRgn: RgnHandle; {visible region} clipRgn: RgnHandle; {clipping region} bkPixPat: PixPatHandle; {background pattern} rgbFgColor: RGBColor; {requested foreground color} rgbBkColor: RGBColor; {requested background color} pnLoc: Point; {pen location} pnSize: Point; {pen size} pnMode: INTEGER; {pen transfer mode} pnPixPat: PixPatHandle; {pen pattern} fillPixPat: PixPatHandle; {fill pattern} pnVis: INTEGER; {pen visibility} txFont: INTEGER; {font number for text} txFace: Style; {text's character style} txMode: INTEGER; {text's transfer mode} txSize: INTEGER; {font size for text} spExtra: Fixed; {extra space} fgColor: LONGINT; {actual foreground color} bkColor: LONGINT; {actual background color} colrBit: INTEGER; {plane being drawn} patStretch: INTEGER; {used internally} picSave: Handle; {picture being saved} rgnSave: Handle; {region being saved} polySave: Handle; {polygon being saved} grafProcs: CQDProcsPtr {low-level drawing routines} END; GrafVars = RECORD rgbOpColor: RGBColor; {color for addPin, } { subPin, and blend} rgbHiliteColor: RGBColor; {color for hiliting} pmFgColor: Handle; {palette handle for } { foreground color} pmFgIndex: INTEGER; {index value for foreground} pmBkColor: Handle; {palette handle for } { background color} pmBkIndex: INTEGER; {index value for background} pmFlags: INTEGER; {flags for Palette Manager} END; PixMapHandle = ^PixMapPtr; PixMapPtr = ^PixMap; PixMap = RECORD baseAddr: Ptr; {pointer to pixMap data} rowBytes: INTEGER; {offset to next row} bounds: Rect; {boundary rectangle} pmVersion: INTEGER; {color QuickDraw version number} packType: INTEGER; {packing format} packSize: LONGINT; {size of data in packed state} hRes: Fixed; {horizontal resolution} vRes: Fixed; {vertical resolution} pixelType: INTEGER; {format of pixel image} pixelSize: INTEGER; {physical bits per pixel} cmpCount: INTEGER; {logical components per pixel} cmpSize: INTEGER; {logical bits per component} planeBytes: LONGINT; {offset to next plane} pmTable: CTabHandle; {absolute colors for this image} pmReserved: LONGINT {reserved for future expansion} END; PixPatHandle = ^PixPatPtr; PixPatPtr = ^PixPat; PixPat = RECORD patType: INTEGER; {pattern type} patMap: PixMapHandle; {pattern characteristics} patData: Handle; {pixel image defining pattern} patXData: Handle; {expanded pixel image} patXValid: INTEGER; {flags for expanded pattern data} patXMap: Handle; {handle to expanded pattern data} pat1Data: Pattern; {old-style pattern/RGB color} END; CCrsrHandle = ^CCrsrPtr; CCrsrPtr = ^CCrsr; CCrsr = RECORD crsrType: INTEGER; {type of cursor} crsrMap: PixMapHandle; {the cursor's pixMap} crsrData: Handle; {cursor's data} crsrXData: Handle; {expanded cursor data} crsrXValid: INTEGER; {depth of expanded data} crsrXHandle: Handle; {reserved for future use} crsr1Data: Bits16; {one-bit cursor} crsrMask: Bits16; {cursor's mask} crsrHotSpot: Point; {cursor's hotspot} crsrXTable: LONGINT; {private} crsrID: LONGINT; {ctSeed for expanded cursor} END; CIconHandle = ^CIconPtr; CIconPtr = ^CIcon; CIcon = RECORD iconPMap: PixMap; {the icon's pixMap} iconMask: BitMap; {the icon's mask bitMap} iconBMap: BitMap; {the icon's bitMap} iconData: Handle; {the icon's data} iconMaskData: ARRAY[0..0] OF INTEGER; {icon's } { mask and bitMap data} END; MatchRec = RECORD red: INTEGER; {red component} green: INTEGER; {green component} blue: INTEGER; {blue component} matchData: LONGINT; END; CQDProcsPtr = ^CQDProcs CQDProcs = RECORD textProc: Ptr; lineProc: Ptr; rectProc: Ptr; rRectProc: Ptr; ovalProc: Ptr; arcProc: Ptr; polyProc: Ptr; rgnProc: Ptr; bitsProc: Ptr; commentProc: Ptr; txMeasProc: Ptr; getPicProc: Ptr; putPicProc: Ptr; opcodeProc: Ptr; {fields added to QDProcs} newProc1: Ptr; {reserved for future use} newProc2: Ptr; {reserved for future use} newProc3: Ptr; {reserved for future use} newProc4: Ptr; {reserved for future use} newProc5: Ptr; {reserved for future use} newProc6: Ptr; {reserved for future use} END; _______________________________________________________________________________ Routines Operations on cGrafPorts PROCEDURE OpenCPort (port: CGrafPtr); PROCEDURE InitCPort (port: CGrafPtr); PROCEDURE CloseCPort (port: CGrafPtr); Setting the Foreground and Background Colors PROCEDURE RGBForeColor (color : RGBColor); PROCEDURE RGBBackColor (color : RGBColor); PROCEDURE GetForeColor (VAR color : RGBColor); PROCEDURE GetBackColor (VAR color : RGBColor); Creating Pixel Maps FUNCTION NewPixMap : PixMapHandle; PROCEDURE DisposPixMap (pm: PixMapHandle); PROCEDURE CopyPixMap (srcPM,dstPM: PixMapHandle); Operations on Pixel Maps PROCEDURE CopyBits (srcBits, dstBits: BitMap; srcRect, dstRect: Rect; mode: INTEGER; maskRgn: RgnHandle); PROCEDURE CopyMask (srcBits,maskBits,dstBits: BitMap; srcRect, maskRect, dstRect: Rect); PROCEDURE SeedCFill (srcBits, dstBits: BitMap; srcRect, dstRect: Rect; seedH, seedV: INTEGER; matchProc: ProcPtr; matchData: LONGINT); PROCEDURE CalcCMask (srcBits, dstBits: BitMap; srcRect, dstRect: Rect; seedRGB: RGBColor; matchProc: ProcPtr; matchData: LONGINT); Operations on Pixel Patterns FUNCTION NewPixPat : PixPatHandle; PROCEDURE DisposPixPat (ppat: PixPatHandle); FUNCTION GetPixPat (patID: INTEGER): PixPatHandle; PROCEDURE CopyPixPat (srcPP,dstPP: PixPatHandle); PROCEDURE MakeRGBPat (ppat: PixPatHandle; myColor: RGBColor); PROCEDURE PenPixPat (ppat: PixPatHandle); PROCEDURE BackPixPat (ppat: PixPatHandle); Color Drawing Operations PROCEDURE FillCRect (r: Rect; ppat: PixPatHandle); PROCEDURE FillCOval (r: Rect; ppat: PixPatHandle); PROCEDURE FillCRoundRect (r: Rect; ovWd,ovHt: INTEGER; ppat: PixPatHandle); PROCEDURE FillCArc (r: Rect; startAngle,arcAngle: INTEGER; ppat: PixPatHandle); PROCEDURE FillCRgn (rgn: RgnHandle; ppat: PixPatHandle); PROCEDURE FillCPoly (poly: PolyHandle; ppat: PixPatHandle); PROCEDURE GetCPixel (h,v: INTEGER; VAR cPix: RGBColor); PROCEDURE SetCPixel (h,v: INTEGER; cPix: RGBColor); Operations on Color Cursors FUNCTION GetCCursor (crsrID: INTEGER): CCrsrHandle; PROCEDURE SetCCursor (cCrsr: CCrsrHandle); PROCEDURE DisposCCursor (cCrsr: CCrsrHandle); PROCEDURE AllocCursor; Operations on Icons FUNCTION GetCIcon (id: INTEGER): CIconHandle; PROCEDURE DisposCIcon (theIcon: CIconHandle); PROCEDURE PlotCIcon (theRect: Rect; theIcon: CIconHandle); Operations on cGrafPort Fields PROCEDURE SetPortPix (pm: PixMapHandle); PROCEDURE OpColor (color: RGBColor); PROCEDURE HiliteColor (color:RGBColor); PROCEDURE CharExtra (extra:Fixed); PROCEDURE SetStdCProcs (VAR cProcs: CQDProcs); Operations on Color Tables FUNCTION GetCTable (ctID: INTEGER): CTabHandle; PROCEDURE DisposCTable (ctTab: CTabHandle); Color Picture Operations FUNCTION OpenPicture (picFrame: Rect) : PicHandle; _______________________________________________________________________________ Global Variables HiliteMode {if the hilite mode is set, highlighting is on} HiliteRGB {default highlight color for the system} _______________________________________________________________________________ Assembly-Language Interface HiLite Constant hiliteBit EQU 7 ;flag bit in HiliteMode ; this is the correct value for use in assembler ; programs Equates for Resource IDs defQDColors EQU 127 ;resource ID of clut for default QDColors RGBColor structure red EQU $0 ;[word] red channel intensity green EQU $2 ;[word] green channel intensity blue EQU $4 ;[word] blue channel intensity rgbColor EQU $6 ;size of record ColorSpec structure value EQU $0 ;[short] value field rgb EQU $2 ;[rgbColor] rgb values colorSpecSize EQU $8 ;size of record Additional Offsets in a cGrafPort portPixMap EQU portBits ;[long] pixelMap handle portVersion EQU portPixMap+4 ;[word] port version number grafVars EQU portVersion+2 ;[long] handle to new fields chExtra EQU grafVars+4 ;[word] extra characters placed at ; the end of a string pnLocHFrac EQU chExtra+2 ;[word] pen fraction bkPixPat EQU bkPat ;[long] handle to bk pattern rgbFgColor EQU bkPixPat+4 ;[6 bytes] RGB components of fg color rgbBkColor EQU RGBFgColor+6 ;[6 bytes] RGB components of bk color pnPixPat EQU $3A ;[long] handle to pen's pattern fillPixPat EQU pnPixPat+4 ;[long] handle to fill pattern Offsets Within GrafVars rgbOpColor EQU 0 ;[6 bytes] color for addPin, ; subPin, and blend rgbHiliteColor EQU rgbOpColor+6 ;[6 bytes] color for hiliting pmFgColor EQU rgbHiliteColor+6 ;[4 bytes] Palette handle for ; foreground color pmFgIndex EQU pmFgColor+4 ;[2 bytes] index value for ; foreground pmBkColor EQU pmFgIndex+2 ;[4 bytes] Palette handle for ; background color pmBkIndex EQU pmBkColor+4 ;[2 bytes] index value for ; background pmFlags EQU pmBkIndex+2 ;[2 bytes] Flags for Palette ; manager grafVarRec EQU pmFlags+2 ;size of grafVar record PixMap field offsets pmBaseAddr EQU $0 ;[long] pmNewFlag EQU $4 ;[1 bit] upper bit of rowbytes is flag pmRowBytes EQU $4 ;[word] pmBounds EQU $6 ;[rect] pmVersion EQU $E ;[word] pixMap version number pmPackType EQU $10 ;[word] defines packing format pmPackSize EQU $12 ;[long] size of pixel data pmHRes EQU $16 ;[fixed] h. resolution (ppi) pmVRes EQU $1A ;[fixed] v. resolution (ppi) pmPixelType EQU $1E ;[word] defines pixel type pmPixelSize EQU $20 ;[word] # bits in pixel pmCmpCount EQU $22 ;[word] # components in pixel pmCmpSize EQU $24 ;[word] # bits per field pmPlaneBytes EQU $26 ;[long] offset to next plane pmTable EQU $2A ;[long] color map pmReserved EQU $2E ;[long] must be 0 pmRec EQU $32 ; size of pixMap record PixPat field offsets patType EQU $0 ;[word] type of pattern patMap EQU $2 ;[long] handle to pixmap patData EQU $6 ;[long] handle to data patXData EQU $A ;[long] handle to expanded pattern data patXValid EQU $E ;[word] flags whether expanded pattern valid patXMap EQU $10 ;[long] handle to expanded pattern data pat1Data EQU $14 ;[8 bytes] old-style pattern/RGB color ppRec EQU $1C ; size of pixPat record Pattern Types oldPat EQU 0 ;foreground/background pattern newPat EQU 1 ;self-contained color pattern ditherPat EQU 2 ;rgb value to be dithered oldCrsrPat EQU $8000 ;old-style cursor CCrsrPat EQU $8001 ;new-style cursor CCrsr (Color Cursor) field offsets crsrType EQU 0 ;[word] cursor type crsrMap EQU crsrType+2 ;[long] handle to cursor's pixmap crsrData EQU crsrMap+4 ;[long] handle to cursor's color data crsrXData EQU crsrData+4 ;[long] handle to expanded data crsrXValid EQU crsrXData+4 ;[word] handle to expanded data (0 if none) crsrXHandle EQU crsrXValid+2 ;[long] handle for future use crsr1Data EQU crsrXHandle+4 ;[16 words] one-bit data crsrMask EQU crsr1Data+32 ;[16 words] one-bit mask crsrHotSpot EQU crsrMask+32 ;[point] hot-spot for cursor crsrXTable EQU crsrHotSpot+4 ;[long] private crsrID EQU crsrXTable+4 ;[long] color table seed for ; expanded cursor crsrRec EQU crsrID+4 ;size of cursor save area CIcon (Color Icon) field offsets iconPMap EQU 0 ;[pixmap] icon's pixMap iconMask EQU iconPMap+pmRec ;[bitmap] 1-bit version of icon ; 1-bit mask iconBMap EQU iconMask+bitmapRec ;[bitmap] 1-bit version of icon iconData EQU iconBMap+bitmapRec ;[long] Handle to pixMap data ; followed by bMap and mask data iconRec EQU iconData+4 ;size of icon header Extensions to the QDProcs record opcodeProc EQU $34 ;[pointer] newProc1 EQU $38 ;[pointer] newProc2 EQU $3C ;[pointer] newProc3 EQU $40 ;[pointer] newProc4 EQU $44 ;[pointer] newProc5 EQU $48 ;[pointer] newProc6 EQU $4C ;[pointer] cqdProcsRec EQU $50 ; size of QDProcs record MatchRec structure red EQU $0 ; [word] defined in RGBColor green EQU $2 ; [word] defined in RGBColor blue EQU $4 ; [word] defined in RGBColor matchData EQU $6 ; [long] matchRecSize EQU $A ;size of record Global Variables HiliteMode EQU $938 ;if the hilite bit is set, highlighting is on HiliteRGB EQU $DA0 ;default highlight color for the system --------------------------------------------------------------------------------------- QuickDrawÕs Internal Picture Definition Imaging M.IM.QuickDrawsInternalPictDef Revised by: Rick Blair November 1986 March 1988 Written by: Ginger Jenigan April 1985 This technical note describes the internal format of the QuickDraw picture data structure. This revision corrects some errors in the opcode descriptions and provides some examples. This technical note describes the internal definition of the QuickDraw picture. The information given here only applies to QuickDraw picture format version 1.0 (which is always created by Macintoshes without Color QuickDraw). Picture format version 2.0 is documented in the Color QuickDraw chapter of Inside Macintosh. This information should not be used to write your own picture bottleneck procedures; if we add new objects to the picture definition, your program will not be able to operate on pictures created using standard QuickDraw. Your program will not know the size of the new objects and will, therefore, not be able to proceed past the new objects. (What this ultimately means is that you canÕt process a new picture with an old bottleneck proc.) Terms An opcode is a number that DrawPicture uses to determine what object to draw or what mode to change for subsequent drawing. The following list gives the opcode, the name of the object (or mode), the associated data, and the total size of the opcode and data. To better interpret the sizes, please refer to page I-91 of the Using Assembly Language chapter of Inside Macintosh. For types not described there, here is a quick list: opcode byte mode word point 4 bytes 0..255 byte Ð128..127 signed byte rect 8 bytes poly 10+ bytes (starts with word size for poly (incl. size word) region 10+ bytes (starts with word size for region (incl. size word) fixed point long pattern 8 bytes rowbytes word (always even) bit data rowbytes * (bounds.bottom - bounds.top) bytes Each picture definition begins with a picsize (word), then a picframe (rect), and then the picture definition, which consists of a combination of the following opcodes: Opcode Name Additional Data Total Size (bytes) 00 NOP none 1 01 clipRgn rgn 1+rgn 02 bkPat pattern 9 03 txFont font (word) 3 04 txFace face (byte) 2 05 txMode mode (word) 3 06 spExtra extra (fixed point) 5 07 pnSize pnSize (point) 5 08 pnMode mode (word) 3 09 pnPat pattern 9 0A thePat pattern 9 0B ovSize point 5 0C origin dh, dv (words) 5 0D txSize size (word) 3 0E fgColor color (long) 5 0F bkColor color (long) 5 10 txRatio numer (point), denom (point) 9 11 picVersion version (byte) 2 20 line pnLoc ( point ), newPt ( point ) 9 21 line from newPt ( point ) 5 22 short line pnLoc ( point ); dh, dv (-128..127) 7 23 short line from dh, dv (-128..127) 3 28 long text txLoc ( point ), count (0..255), text 6+text 29 DH text dh (0..255), count (0..255), text 3+text 2A DV text dv (0..255), count (0..255), text 3+text 2B DHDV text dh, dv (0..255), count (0..255), text 4+text 30 frameRect rect 9 31 paintRect rect 9 32 eraseRect rect 9 33 invertRect rect 9 34 fillRect rect 9 38 frameSameRect rect 1 39 paintSameRect rect 1 3A eraseSameRect rect 1 3B invertSameRect rect 1 3C fillSameRect rect 1 40 frameRRect rect ( ovalwidth, height; see 1, below ) 9 41 paintRRect rect ( ovalwidth, height; see 1, below ) 9 42 eraseRRect rect ( ovalwidth, height; see 1, below ) 9 43 invertRRect rect ( ovalwidth, height; see 1, below ) 9 44 fillRRect rect ( ovalwidth, height; see 1, below ) 9 48 frameSameRRect rect 1 49 paintSameRRect rect 1 Opcode (cont.) Name Additional Data Total Size (bytes) 4A eraseSameRRect rect 1 4B invertSameRRect rect 1 4C fillSameRRect rect 1 50 frameOval rect 9 51 paintOval rect 9 52 eraseOval rect 9 53 invertOval rect 9 54 fillOval rect 9 58 frameSameOval rect 1 59 paintSameOval rect 1 5A eraseSameOval rect 1 5B invertSameOval rect 1 5C fillSameOval rect 1 60 frameArc rect, startAngle, arcAngle 13 61 paintArc rect, startAngle, arcAngle 13 62 eraseArc rect, startAngle, arcAngle 13 63 invertArc rect, startAngle, arcAngle 13 64 fillArc rect, startAngle, arcAngle 13 68 frameSameArc startAngle, arcAngle 5 69 paintSameArc startAngle, arcAngle 5 6A eraseSameArc startAngle, arcAngle 5 6B invertSameArc startAngle, arcAngle 5 6C fillSameArc startAngle, arcAngle 5 70 framePoly poly 1+poly 71 paintPoly poly 1+poly 72 erasePoly poly 1+poly 73 invertPoly poly 1+poly 74 fillPoly poly 1+poly 78 frameSamePoly (not yet implementedÑsame as 70, etc.) 1 79 paintSamePoly (not yet implemented) 1 7A eraseSamePoly (not yet implemented) 1 7B invertSamePoly (not yet implemented) 1 7C fillSamePoly (not yet implemented) 1 80 frameRgn rgn 1+rgn 81 paintRgn rgn 1+rgn 82 eraseRgn rgn 1+rgn 83 invertRgn rgn 1+rgn 84 fillRgn rgn 1+rgn 88 frameSameRgn (not yet implementedÑsame as 80, etc.) 1 89 paintSameRgn (not yet implemented) 1 8A eraseSameRgn (not yet implemented) 1 8B invertSameRgn (not yet implemented) 1 8C fillSameRgn (not yet implemented) 1 Opcode (cont.) Name Additional Data Total Size (bytes) 90 BitsRect rowBytes, bounds, srcRect, dstRect, mode, 29+unpacked unpacked bitData bitData 91 BitsRgn rowBytes, bounds, srcRect, dstRect, mode, 29+rgn+ maskRgn, unpacked bitData bitData 98 PackBitsRect rowBytes, bounds, srcRect, dstRect, mode, 29+packed packed bitData for each row bitData 99 PackBitsRgn rowBytes, bounds, srcRect, dstRect, mode, 29+rgn+ maskRgn, packed bitData for each row packed bitData A0 shortComment kind(word) 3 A1 longComment kind(word), size(word), data 5+data FF EndOfPicture none 1 Notes Rounded-corner rectangles use the setting of the ovSize point (see opcode $0B, above). OpenPicture and DrawPicture set up a default set of port characteristics when they start. When drawing occurs, if the userÕs settings donÕt match the defaults, mode opcodes are generated. This is why there is usually a clipRgn code after the picVersion: the default clip region is an empty rectangle. The only savings that the ÒsameÓ opcodes achieve under the current implementation is for rectangles. DrawPicture keeps track of the last rectangle used and if a ÒsameÓ opcode is encountered that requests a rectangle, the last rect. will be used (and no rectangle will appear in the opcodeÕs data). This last section contains some Pascal program fragments that generate pictures. Each section starts out with the picture itself (yes, theyÕre dull) followed by the code to create and draw it, and concludes with a commented hex dump of the picture. {variables used in all examples} VAR err: OSErr; ph: PicHandle; h: Handle; r: Rect; smallr: Rect; orgr: Rect; pstate: PenState; {are they in the Rose Bowl, or the state pen?}  I. {Rounded-corner rectangle} SetRect(r, 20, 10, 120, 175); ClipRect(myWindow^.portRect); ph := OpenPicture(r); FrameRoundRect (r, 5, 4); {r,width,height} ClosePicture; DrawPicture(ph, r); 'PICT' (1) 0026 {size} 000A 0014 00AF 0078 {picFrame} 1101 {version 1} 01 000A 0000 0000 00FA 0190 {clipRgn Ñ 10 byte region} 0B 0004 0005 {ovSize point} 40 000A 0014 00AF 0078 {frameRRect rectangle} FF {fin} __________________________________________________________________________________________  II. {Overpainted arc} GetPenState(pstate); {save} SetRect(r, 20, 10, 120, 175); ClipRect(myWindow^.portRect); ph := OpenPicture(r); PaintArc(r, 3, 45); {r,startangle,endangle} PenPat(gray); PenMode(patXor); {turn the black to gray} PaintArc(r, 3, 45); {r,startangle,endangle} ClosePicture; SetPenState(pstate); {restore} DrawPicture(ph, r); data 'PICT' (2) 0036 {size} 000A 0014 00AF 0078 {picFrame} 1101 {version 1} 01 000A 0000 0000 00FA 0190 {clipRgn Ñ 10 byte region} 61 000A 0014 00AF 0078 0003 002D {paintArc rectangle,startangle,endangle} 08 000A {pnMode patXor Ñ note that the pnMode comes before the pnPat} 09 AA55 AA55 AA55 AA55 {pnPat gray} 69 0003 002D {paintSameArc startangle,endangle} FF {fin}  III. {CopyBits nopack, norgn, nowoman, nocry} GetPenState(pstate); SetRect(r, 20, 10, 120, 175); SetRect(smallr, 20, 10, 25, 15); SetRect(orgr, 0, 0, 30, 20); ClipRect(myWindow^.portRect); ph := OpenPicture(r); PaintRect(r); CopyBits (myWindow^.portBits, myWindow^.portBits, smallr, orgr, notSrcXor, NIL); {note: result BitMap is 8 bits wide instead of the 5 specified by smallr} ClosePicture; SetPenState(pstate); {restore the port's original pen state} DrawPicture(ph, r); data 'PICT' (3) 0048 {size} 000A 0014 00AF 0078 {picFrame} 1101 {version 1} 01 000A 0000 0000 00FA 0190 {clipRgn Ñ 10 byte region} 31 000A 0014 00AF 0078 {paintRect rectangle} 90 0002 000A 0014 000F 001C {BitsRect rowbytes bounds (note that bounds is wider than smallr)} 000A 0014 000F 0019 {srcRect} 0000 0000 0014 001E {dstRect} 00 06 {mode=notSrcXor} 0000 0000 0000 0000 0000 {5 rows of empty bitmap (we copied from a still-blank window)} FF {fin} Further Reference: ¥ QuickDraw ¥ Color QuickDraw ¥ Using Assembly Language ¥ Technical Note #59ÑPictures and Clip Regions