; ; Hacks to match MacOS (most recent first): ; ; 8/3/92 Elliot make this change ; 9/2/94 SuperMario ROM source dump (header preserved below) ; ; ; File: Patterns.a ; ; Contains: More QuickDraw ; ; Written by: xxx put name of writer here (or delete the whole line) xxx ; ; Copyright: © 1981-1990, 1992-1993 by Apple Computer, Inc., all rights reserved. ; ; ; Change History (most recent first): ; ; 9/12/93 SAM Changed all instances of _Translate24to32 to _rTranslate24to32 ; so they can conditionalized out of the build. ; 8/18/92 CSS Update from Reality: ; <16> 8/18/92 SAH #1040323 : Fixed Indexed SeedCFill bug by making ; MakeScaleTbl check to see if fg color is black and bg color is ; white before it inverts the bg color when drawing to a one bit ; destination. ; 7/16/92 CSS Update from Reality: ; <15> 6/10/92 SAH Fixed problem where code to invert bg color when going to a one ; bit dst was not making local copies of the fg and bg colors ; before calling Color2Index. Also fixed a problem where register ; d2 was getting trashed across the calls to Color2Index. ; <14> 6/8/92 SAH #1031825: Changed MakeScaleTbl so that it checks if the ; destination is one bit and the fg and bg colors map to the same ; index. If so, and the fg and bg colors are different, invert the ; bg color. ; 6/11/92 stb stb Synch with QDciPatchROM.a; Added comments to ; PatExpand, PatConvert, DirectPixPat, MakeScaleTbl, GETCICON, ; COPYPIXPAT. ; 5/21/92 kc Change the name of QuickDraws wrapper for NewHandle to ; NewHandleWrapper to avoid name conflict with the glue. ; <13> 1/15/92 KC Fix "If last BRA.S to import is to next instruction, BAD CODE ; will be generated" assembler warning. ; <12> 3/6/91 KON CEL: WKSHT B5-MTM-009 Calculation for location of where to begin ; search for unused colors was incorrect. This was a problem only ; if the value $7FFFFFFF happened to be on the stack since this is ; what is used to flag an unused entry. ; <11> 10/31/90 SMC Fixed alpha channel bugs with BAL. ; <10> 10/16/90 KON First time throught PatExpand, LastCTable was getting set to ; random value. This is not harmful, but forces the pattern to ; expand the second time through when it doesn't have to. [with ; SMC] ; <9> 9/18/90 BG Removed <5>. 040s are behaving more reliably now. ; <8> 7/24/90 KON Zero pmVersion after getting devices pixmap incase it's a gWorld ; and pmVersion was set indicating the baseAddr is a handle. ; <7> 7/20/90 gbm Change some identifiers, to avoid assembly errors ; <6> 7/13/90 DVB Fix PatDither, ; <5> 6/26/90 BG Added EclipseNOPs for flakey 040s. ; <4> 5/24/90 KON Setup translation table to handle colorizing for indexed ; sources. Also fixed stretch so that indexed things are no longer ; colorized. ; <3> 1/28/90 BAL Changed MakeScaleTbl to clear QDErr in case ColorThing2Index set ; it. ; <2> 1/15/90 DVB MakeScaleTbl works when pixelSize disagrees w/clutsize ; ; To Do: ; ;EASE$$$ READ ONLY COPY of file “patterns.a” ; 1.8 BAL 11/01/1989 Fix a bug in getCIcon which would size the data handle pixelSize times too big. ;•1.7 BAL 07/14/1989 For Aurora: Final CQD ; 1.6 BAL 07/14/1989 For Aurora: Incorporated devloop in plotCIcon; Added direct pixpat support. ; 1.5 GGD 07/06/1989 Changed the JSR GetDevPix to a BSR.L so that it can reach when alignment ; is turned on. ;•1.4 BAL 05/29/1989 Blasting in 32-Bit QuickDraw version 1.0 Final ;•1.3 BAL 04/12/1989 Blasting in 32-Bit QuickDraw 1.0B1 BLANKS ON STRING ASIS MACHINE MC68020 ;------------------------------------------------------------------ ; ; --> PATTERNS.A ; ; Routines for manipulating color Patterns ; ;------------------------------------------------------------------ ; ; MODIFICATION HISTORY: ; ; 3OCT86 EHB Added routine GetCCursor ; 3Jan87 CRC modified makeScaleTbl to take mode param, maps all but arith. modes to b/w ; ;---------------------------- Macintosh II ROMs ----------------------------- ; ; 26May87 EHB Rolled in patch to plotCIcon to force fgColor to black ; ; 08Nov87 DAF Fixed DisposPixPat/DisposCCursor to test for NIL handles. ; ; NOTES: In the old world, patterns were always drawn using the ; foreground and background colors. New patterns can have more ; colors in them, and need to be created with CSubTables that indicate ; the intended colors. When used in old drawing modes, the fg and bk ; colors must be shoved into the tables (or simply used when the pat ; is expanded). In new drawing modes, the new colors can be used. ; ; 09May88 BAL Altered MakeScaleTbl to build a table of longs instead of words ; 18Sep88 BAL Altered PatExpand to use common stack frame file 'Drawing Vars.a' GetCCursor PROC EXPORT IMPORT PATSHARE ;------------------------------------------------------------- ; ; FUNCTION GetCCursor(CRSRID: INTEGER): CCrsrHandle; ; ; GetCCursor gets a resource of type 'crsr' with the specified ID, places ; all the data fields into handles, installs the handles into the CCRSR, ; resizes it, and then returns the data structure as a CCrsrHandle. ; It shares common code with GetPixPat to do all of the work. MOVE 4(SP),D0 ; get the cursor's resource ID MOVE.L #'crsr',D1 ; get the desired resource type MOVEQ #CRSRRec,D2 ; get size of cursor record BRA.S PATSHARE NOP ; silence the assembler <13> GETPIXPAT PROC EXPORT EXPORT PATSHARE IMPORT NEWPIXPAT,COPYPIXPAT,GetCTSeed,CopyHandle, RSetHSize ;------------------------------------------------------------- ; ; FUNCTION GetPixPat(CPatID: INTEGER): PixPatHandle; ; ; GetPixPat gets a resource of type 'ppat' with the specified ID, places ; all the data fields into handles, installs the handles into the ppat, ; resizes it, and then returns the data structure as a pixPatHandle. ; ; The resource format consists of a pixPat followed by it's pixMap, the ; pixel data and finally the color table data. The pixPat field contains ; an offset to the pixel data from the beginning of the resource data. The patData ; field contains the offset to the pixel data from the beginning of the res data. ; The pmTable field contains the offset to the color table data from the beginning ; of the resource data. The size of the pixel data is calculated by ; subtracting the offset to the pixel data from the offset to the color table data. ; PARAMSIZE EQU 2 ; RESULT EQU PARAMSIZE+8 ; pixPatHandle RESULT PPatID EQU PARAMSIZE+8-2 ; pattern ID MOVE 4(SP),D0 ; get the pattern's resource ID MOVE.L #'ppat',D1 ; get the desired resource type MOVEQ #PPRec,D2 ; get the size of the pattern PATSHARE LINK A6,#0 ; build stack frame MOVEM.L D3/A2-A4,-(SP) ; preserve a work register MOVE.L D2,D3 ; save record size in D3 CLR.L RESULT(A6) ; set result to NIL SUBQ #4,SP ; make space for result MOVE.L D1,-(SP) ; push resource type MOVE D0,-(SP) ; push resource ID _GetResource ; get the resource MOVE.L (SP)+,A0 ; keep handle in A0 <1.5> BAL MOVE.L A0,D0 ; did we get one? <1.5> BAL BEQ NoGetNew ; if not, don't allocate one ; copy resource data to the main pattern/cursor data structure, keep in A3. ; use HandToHand since src is purgeable. _HandToHand ; and allocate a new handle <1.5> BAL BNE NoGetNew ; => couldn't get one move.l A0,A3 ; get new handle into A3 <1.5> BAL _HLock ; and lock it down <1.5> BAL ; at this point we're done with the resource. Just leave it lying around ; (it should be purgeable). ; Create the pixMap handle and install it MOVE.L (A3),A2 ; point to the resource data MOVE.L A2,A0 ; point to the resource data ADD.L patMap(A2),A0 ; get pointer to data MOVEQ #PMRec,D0 ; get size of pixMap _PtrToHand ; go get a new handle BNE NoGetNew ; => couldn't get one MOVE.L A0,A4 ; keep pixMap in A4 move.l (A4),A1 ; point to the pixMap <1.5> BAL clr.l pmTable(A1) ; zero color table in case direct data <1.5> BAL ; Create the color table and install it MOVE.L A2,A0 ; point to the resource data MOVE.L A2,A1 ; spare pointer to the resource data ADD.L patMap(A2),A1 ; point to the pixMap cmp.w #16,pixelType(a1) ; direct data ? <1.5> BAL beq.s @skipCLUT ; yes, no clut to install <1.5> BAL ADD.L pmTable(A1),A0 ; point to the pixMap's color table data MOVE CTSize(A0),D0 ; get number of entries in table ADDQ #1,D0 ; make it one based MULU #CTEntrySize,D0 ; get size of entries ADD #CTRec,D0 ; add in size of header EXT.L D0 ; long for PtrToHand _PtrToHand ; go get a new handle BNE NoGetNew ; => couldn't get one MOVE.L (A4),A1 ; point to the pixMap MOVE.L A0,pmTable(A1) ; install color table into pixMap CLR.L -(SP) ; make room for function result _GetCTSeed ; go get seed for new color table MOVE.L (A0),A0 ; point to color table MOVE.L (SP)+,CTSeed(A0) ; and set seed value @skipCLUT ; Create the pixel data handle and install it MOVE.L A2,A0 ; point to the resource data MOVE.L A2,A1 ; spare pointer to the resource data ADD.L patMap(A2),A1 ; point to the pixMap MOVE.L pmTable(A1),D0 ; get offset to color table data SUB.L patData(A2),D0 ; calc size of pattern data ADD.L patData(A2),A0 ; point to pattern data _PtrToHand ; go get a new handle BNE NoGetNew ; => couldn't get one MOVE.L A0,patData(A2) ; install data into pixPat ; Allocate a dummy handle for expanded data and install it MOVEQ #2,D0 ; get a dummy size _NewHandle ; go get a handle BNE NoGetNew ; => couldn't get one MOVE.L A0,patXData(A2) ; install expand data handle into pixPat ; If pattern, allocate a handle for expanded info and install it CMP #CRSRRec,D3 ; is it a cursor? BEQ.S @Cursor ; => yes, no expanded info MOVEQ #ppXInfo,D0 ; get size of info record _NewHandle ; go get a handle BNE NoGetNew ; => couldn't get one MOVE.L A0,patXMap(A2) ; install expand data handle into pixPat @Cursor MOVE.L A4,patMap(A2) ; install pixMap into PixPat MOVE.L A3,A0 ; get the pixPat handle _HUnlock ; and unlock it MOVE.L D3,D0 ; get final size of PixPat/cursor record JSR RSetHSize ; and set the size ; if it is a cursor, give it a unique identifier CMP #CRSRRec,D3 ; is it a cursor? BNE.S IsPat ; => no, it's a pattern CLR.L -(SP) ; make room for function result _GetCTSeed ; go get seed for new cursor MOVE.L (A3),A0 ; point to cursor MOVE.L (SP)+,crsrID(A0) ; and set seed value BRA.S DONE ; =>jump around pattern stuff IsPat MOVE #-1,patXValid(A2) ; say pattern not expanded DONE MOVE.L A3,RESULT(A6) ; update function result NoGetNew MOVEM.L (SP)+,D3/A2-A4 ; restore working registers UNLINK PARAMSIZE,'GETPIXPA' ; strip params and return NEWPIXPAT PROC EXPORT IMPORT NewHandleWrapper,NEWPIXMAP ;------------------------------------------------------------- ; ; FUNCTION NewPixPat : PixPatHandle; ; ; Create a new, uninitialized pixel pattern and return a handle to it. ; The pixPat's pixMap is initialized to the current depth. ; CLR.L -(SP) ; make room for function result MOVE #PPXINFO,-(SP) ; get size of patXMap handle JSR NewHandleWrapper ; allocate pixel pattern,leave on stack CLR.L -(SP) ; make room for function result MOVE #PPREC,-(SP) ; get size of pixelpat JSR NewHandleWrapper ; allocate pixel pattern,leave on stack CLR.L -(SP) ; make room for function result _NEWPIXMAP ; get initialized pixMap, leave on stack MOVE.L (SP),A0 ; get the handle CLR.L -(SP) ; make room for function result MOVE #8,-(SP) ; default size for old patterns JSR NewHandleWrapper ; get handle for pattern data CLR.L -(SP) ; make room for function result CLR -(SP) ; size = 0 JSR NewHandleWrapper ; get handle for expanded data MOVE.L (SP)+,D2 ; get expanded data handle MOVE.L (SP)+,D1 ; get pattern data handle MOVE.L (SP)+,D0 ; get pixMap handle MOVE.L (SP)+,A1 ; get pixpat handle MOVE.L A1,8(SP) ; return result MOVE.L (A1),A0 ; get pixel pat pointer MOVE.L D0,patMap(A0) ; install pixMap into pixPat MOVE.L D1,patData(A0) ; install handle for data MOVE.L D2,patXData(A0) ; install handle for expanded data MOVE.L (SP)+,patXMap(A0) ; install handle for expanded info MOVE.L #$AA55AA55,D0 ; get 50% gray MOVE.L D0,pat1Data(A0) ; put as default 1-bit data MOVE.L D0,pat1Data+4(A0) ; both halves MOVE #1,patType(A0) ; assume it's a color type MOVE #-1,patXValid(A0) ; make patXValid invalid RTS ; and return DisposCCursor PROC EXPORT DisposPixPat PROC EXPORT IMPORT DisposPixMap,OldPatToNew ;------------------------------------------------------------- ; ; PROCEDURE DisposPixPat (PPH: PixPatHandle); ; ; Dispose of a pixel pattern ; MOVE.L 4(SP),D0 ; get pixPat handle BEQ.S Done ; if NIL, then do nothing DAF MOVE.L D0,A1 ; get in A-reg DAF MOVE.L (A1),D0 ; get pixPat pointer DAF BEQ.S Done ; if NIL, then do nothing DAF MOVE.L D0,A1 ; get in A-reg DAF MOVE patType(A1),-(SP) ; save type on stack, test for cursor BMI.S @Cursor ; => yes, don't dispose expanded handle MOVE.L patXMap(A1),A0 ; else get handle to expanded data _DisposHandle ; and dispose it @Cursor MOVE.L patData(A1),A0 ; get handle to data _DisposHandle ; and dispose of them MOVE.L patXData(A1),A0 ; get handle to expanded data _DisposHandle ; and Close them too MOVE.L patMap(A1),-(SP) ; get the pixMap _DisposPixMap ; and dispose of it MOVE.L 6(SP),A0 ; get handle to pixPat MOVE.L A0,D2 ; save in D2 _DisposHandle ; and dispose of it TST (SP)+ ; was it a cursor BMI.S DONE ; =>yes, all done ; if the pattern is referenced in any port, clear that reference MOVE.L PORTLIST,A1 ; get the portList MOVE.L (A1),A1 ; point to it MOVE (A1)+,D0 ; get the number of ports BRA.S ChkPort ; => check for ports NxtPort MOVE.L (A1)+,A0 ; get the port TST PORTBITS+ROWBYTES(A0) ; is it a new port? BPL.S ChkPort ; => no, check next port CMP.L pnPixPat(A0),D2 ; is it the pen pat? BNE.S @0 ; => no, check the bkpat CLR.L pnPixPat(A0) ; clear the pen pat @0 CMP.L bkPixPat(A0),D2 ; is it the bk Pat? BNE.S @1 ; => no, check the fillPat CLR.L bkPixPat(A0) ; clear the bk pat @1 CMP.L fillPixPat(A0),D2 ; is it the fill pat? BNE.S ChkPort ; => no, check next port CLR.L fillPixPat(A0) ; clear the fill pat ChkPort DBRA D0,NxtPort ; => loop for each port DONE MOVE.L (SP)+,(SP) ; strip parameter RTS ; and return DAF SETFILLPAT PROC EXPORT IMPORT PhilPixPat ;--------------------------------------------------------------- ; ; PROCEDURE SETFILLPAT (PAT:PATTERN); ; ; Called by: FillRect, FillCRect, FillOval, FillCOval, FillRoundRect, FillCRoundRect ; FillArc, FillCArc, FillRgn, FillCRgn, FillPoly, FillCPoly ; ; On Entry: D0 = 0 Called by old fill routine ; D0 = 1 Called by color fill routine ; ; If called by old routine, install old-style pattern into FillPat (if old port) ; or FillPixPat (if new port). If called by new routine, install new-style pattern ; into FillPixPat. MOVE.L 4(SP),A1 ;GET PATTERN POINTER/HANDLE MOVE.L GRAFGLOBALS(A5),A0 ;GET GRAFGLOBALS MOVE.L THEPORT(A0),A0 ;GET THE PORT TST D0 ;OLD PATTERN OR NEW BEQ.S @OldPat ;=>SET OLD PATTERN MOVE.L A1,-(SP) ;PUSH PIXPAT HANDLE JSR PhilPixPat ;AND SET IT BRA.S DONE ;=>AND RETURN @OldPat TST PORTBITS+ROWBYTES(A0) ;IS IT A COLOR GRAFPORT? BPL.S SETOLD ;=>NO, SET OLD PATTERN MOVE.L A1,-(SP) ;ELSE PUSH PATTERN PEA FILLPIXPAT(A0) ;AND PIXPAT HANDLE _OLDPATTONEW ;AND CONVERT TO COLOR PATTERN BRA.S DONE SETOLD LEA FILLPAT(A0),A0 ;POINT TO DST MOVE.L (A1)+,(A0)+ ;COPY PAT INTO FILLPAT MOVE.L (A1)+,(A0)+ ;ALL EIGHT BYTES DONE RTD #4 ;STRIP PARAMS AND RETURN PenPixPat PROC EXPORT EXPORT BackPixPat,PhilPixPat IMPORT DISPOSPIXPAT,PATCONVERT,PUTGRAY ;------------------------------------------------------------- ; ; PROCEDURE PenPixPat (PPH: PixPatHandle); ; ; SET THE PNPAT TO THE SPECIFIED PIXEL PATTERN MOVEQ #PNPIXPAT,D0 ;GET OFFSET TO NEW PATTERN MOVEQ #PNPAT,D1 ;GET OFFSET TO OLD PATTERN BRA.S CPATSHARE PhilPixPat ;------------------------------------------------------------- ; ; PROCEDURE PhilPixPat (PPH: PixPatHandle); ; ; SET THE PNPAT TO THE SPECIFIED PIXEL PATTERN MOVEQ #FILLPIXPAT,D0 ;GET OFFSET TO NEW PATTERN MOVEQ #FILLPAT,D1 ;GET OFFSET TO OLD PATTERN BRA.S CPATSHARE BackPixPat ;------------------------------------------------------------- ; ; PROCEDURE BackPixPat (PPH: PixPatHandle); ; ; SET THE BKPAT TO THE SPECIFIED PIXEL PATTERN MOVEQ #BKPIXPAT,D0 ;GET OFFSET TO NEW PATTERN MOVEQ #BKPAT,D1 ;GET OFFSET TO OLD PATTERN CPATSHARE MOVE.L GRAFGLOBALS(A5),A0 ;GET GLOBAL POINTER MOVE.L THEPORT(A0),A0 ;GET THE PORT TST PORTBITS+ROWBYTES(A0) ;IS IT A COLOR PORT? BMI.S @COLOR ;=>YES, SET COLOR PORT ; IF OLD GRAFPORT, THEN EXTRACT THE ONE-BIT DATA AND PLACE INTO THE PROPER FIELD MOVE.L 4(SP),A1 ;GET THE NEW PATTERN MOVE.L (A1),A1 ;POINT TO IT CMP #DITHERPAT,PATTYPE(A1) ;IS IT AN RGB PATTERN? BEQ.S @DITHER ;=>YES, GO MAKE DITHER LEA PAT1DATA(A1),A1 ;POINT TO ONE-BIT DATA LEA 0(A0,D1),A0 ;POINT TO FIELD IN GRAFPORT MOVE.L (A1)+,(A0)+ ;COPY 1ST HALF PATTERN MOVE.L (A1)+,(A0)+ ;COPY 2ND HALF PATTERN BRA.S DONE ;=>AND RETURN @DITHER MOVE.L PATMAP(A1),A1 ;GET HANDLE TO PATTERN'S PIXMAP MOVE.L (A1),A1 ;POINT TO PATTERN'S PIXMAP MOVE.L PMTABLE(A1),A1 ;GET HANDLE TO ITS COLOR TABLE MOVE.L (A1),A1 ;POINT TO THE COLOR TABLE PEA CTTABLE+RGB+(4*CTENTRYSIZE)(A1) ;PUSH THE RGB PEA 0(A0,D1) ;PUSH PATTERN IN GRAFPORT JSR PUTGRAY ;PUT PROPER GRAY TO GRAFPORT BRA.S DONE ;=>AND RETURN ; IF NO PATTERN OR NEW PATTERN, JUST INSTALL SPECIFIED PATTERN @COLOR MOVE.L 0(A0,D0),D1 ;GET WHAT IS CURRENTLY THERE BEQ.S PUTPAT ;=>NOTHING, JUST PUT NEW ONE MOVE.L D1,A0 ;GET THE PATTERN HANDLE MOVE.L (A0),A0 ;GET THE PATTERN POINTER TST PATTYPE(A0) ;OLD OR NEW PATTERN? BNE.S PUTPAT ;=>NEW ONE, JUST PUT NEW ONE ; IF PREVIOUS PNPAT WAS AN OLD PATTERN, THEN DISPOSE OF IT MOVE D0,-(SP) ;SAVE PATTERN OFFSET MOVE.L D1,-(SP) ;PUSH THE HANDLE _DISPOSPIXPAT ;AND DISPOSE OF THE PIXPAT MOVE (SP)+,D0 ;RESTORE PATTERN OFFSET ; INSTALL SPECIFIED HANDLE AND RETURN PUTPAT MOVE.L GRAFGLOBALS(A5),A0 ;GET GLOBAL POINTER MOVE.L THEPORT(A0),A0 ;GET THE PORT MOVE.L 4(SP),0(A0,D0) ;INSTALL HANDLE INTO PORT DONE MOVE.L (SP)+,(SP) ;STRIP PARAMETER RTS ;AND RETURN COPYPIXPAT PROC EXPORT IMPORT COPYPIXMAP,COPYHANDLE ;------------------------------------------------------------- ; ; PROCEDURE COPYPIXPAT (SRCPP,DSTPP: PixPatHandle); ; ; COPY THE SRC PIXPAT'S DATA TO THE DST PIXPAT'S HANDLES ; ; if you’re looking for the QDciPatchROM.a patch to COPYPIXPAT, stb ; try looking in Pictures.a at PutPicPixPat. It was a come-from patch. stb PARAMSIZE EQU 8 SRCPP EQU PARAMSIZE DSTPP EQU SRCPP-4 MOVEQ #(PPREC-PAT1DATA)/2,D0 ;NUMBER OF WORDS PAST HANDLES MOVE.L SRCPP(SP),A0 ;GET HANDLE TO SRC PIXPAT MOVE.L (A0),A0 ;GET POINTER TO SRC PIXPAT MOVE.L DSTPP(SP),A1 ;GET HANDLE TO DST PIXPAT MOVE.L (A1),A1 ;GET POINTER TO DST PIXPAT MOVE (A0)+,(A1)+ ;COPY PATTYPE MOVE.L (A0)+,-(SP) ;PUSH SRC PATMAP MOVE.L (A1)+,-(SP) ;PUSH DST PATMAP MOVE.L (A0)+,-(SP) ;PUSH SRC PATDATA MOVE.L (A1)+,-(SP) ;PUSH DST PATDATA MOVE.L (A0)+,-(SP) ;PUSH SRC PATXDATA MOVE.L (A1)+,-(SP) ;PUSH DST PATXDATA MOVE (A0)+,(A1)+ ;COPY PATXVALID MOVE.L (A0)+,-(SP) ;PUSH SRC PATXMAP MOVE.L (A1)+,-(SP) ;PUSH DST PATXMAP MOVE.L (A0)+,(A1)+ ;COPY PAT1DATA MOVE.L (A0)+,(A1)+ ;BOTH HALVES _COPYHANDLE ;COPY PATXMAP _COPYHANDLE ;COPY PATXDATA _COPYHANDLE ;COPY PATDATA _COPYPIXMAP ;COPY PATMAP MOVE.L (SP)+,A0 ;GET RETURN ADDRESS ADDQ #8,SP ;STRIP PARAMS JMP (A0) ;AND RETURN OldPatToNew PROC EXPORT IMPORT OneBitCTable,COPYPMAP,OneBitData ;------------------------------------------------------------- ; ; PROCEDURE OldPatToNew (pat: pattern; PPHP: PixPatHandlePtr); ; ; Copy the specified pattern into a pixPat. ; If the pixPat handle is NIL, then create a new pixPat. ; If the handle contains a new pattern, create a new pixPat and replace it. ; If the handle contains an old-style pattern, then re-use it. ; ; NOTE: This structure is invalid as a pixMap. There is no BaseAddr ; and the rowBytes is set to one (should be multiple of 2). ; ; The data will be tweaked to transform it into a valid pixMap before ; drawing takes place. ; ; NOTE: WE ASSUME THAT THE PAT IS A POINTER THAT WILL NOT MOVE. ; PARAMSIZE EQU 8 ; total bytes of params PAT EQU PARAMSIZE+8-4 ; pattern pointer PPHP EQU PAT-4 ; pixPat handle LINK A6,#0 ; no local vars MOVEM.L A2/A3,-(SP) ; save work registers MOVE.L PPHP(A6),A0 ; get handle pointer MOVE.L (A0),D0 ; is there a handle? BEQ.S GetHandle ; => no, go get one MOVE.L D0,A3 ; get the pixpat handle MOVE.L (A3),A1 ; point to pixpat TST PatType(A1) ; is it an old one? BEQ.S GotHandle ; =>yes, just reuse it ; IF THERE WAS NO PIXPAT HANDLE, CREATE ONE AND INSTALL IT IN PPHP GetHandle CLR.L -(SP) ; make room for a handle _NewPixPat ; create a new one MOVE.L PPHP(A6),A0 ; get handle pointer MOVE.L (SP)+,(A0) ; return new handle MOVE.L (A0),A3 ; get the pixpat handle MOVE.L (A3),A1 ; point to pixpat CLR PATTYPE(A1) ; flags that it's an old pattern MOVE.L patMap(A1),A1 ; get pixMap handle MOVE.L (A1),A1 ; get pixMap pointer MOVE.L pmTable(A1),-(SP) ; push color table handle JSR OneBitCTable ; initialize one-bit color table MOVE.L (A3),A1 ; point to pixpat ; INVALIDATE THE CURRENT PATTERN EXPAND AREA BY SETTING patXValid TO -1 ; WE KNOW THAT PATDATA IS 8 BYTES LONG (SET BY NEWPIXPAT) GotHandle MOVE #-1,patXValid(A1) ; INVAL patXValid MOVE.L patData(A1),A0 ; finally get the data handle MOVE.L (A0),A0 ; get pointer to data MOVE.L PAT(A6),A1 ; get pattern data MOVE.L (A1)+,(A0)+ ; put one long MOVE.L (A1)+,(A0)+ ; and second long of pattern MOVE.L (A3),A2 ; get PixPat pointer MOVE.L patMap(A2),A2 ; get pixMap handle MOVE.L (A2),A2 ; A2 is pixMap pointer MOVE.L A2,A3 ; A3 is pixMap pointer MOVE.L pmTable(A3),-(SP) ; save color table LEA OneBitData,A1 ; point to one bit data JSR CopyPMap ; and copy into pixMap ptr in A2 ; clobbers A1, A2 MOVE.W #1,pRowBytes(A3) ; 1 byte per row (not a valid pixMap) CLR.L pBounds+topLeft(A3) ; bounds = (0,0,8,8) MOVE.L #$00080008,pBounds+botRight(A3) MOVE.L (SP)+,pmTable(A3) ; restore the color table ; and leave on stack as param MOVEM.L (SP)+,A2/A3 ; restore work registers UNLINK PARAMSIZE,'OLDPATTO' ; strip params and return ; as seen in QDciPatchROM.a stb PatExpand PROC EXPORT IMPORT PATCONVERT, RSetHSize ;---------------------------------------------------------- ; ; EXPAND THE CURRENT PATTERN IF NECESSARY ; ; CALLED ONLY FROM STRETCH,DRAWLINE,DRAWARC. ; ; INPUTS: LOCMODE(A6) ;THE (ALTERED) DRAWING MODE ; DSTPIX+BOUNDS+LEFT(A6) ;THE GLOBAL-LOCAL OFFSET (PIXELS) ; FCOLOR(A6) ;THE CURRENT FG COLOR ; BCOLOR(A6) ;THE CURRENT BK COLOR ; DSTSHIFT(A6) ;THE SHIFT FOR PIXEL DEPTH ; LOCPAT(A6) ;THE (ALTERED) PATTERN ; NEWPATTERN(A6) ;TRUE IF NEW PATTERN ; A5: PASCAL GLOBAL PTR ; D7: -1 TO INVERT, ELSE 0 ; patStretch AND PATALIGN ; ; OUTPUTS: POINTER TO EXPANDED PATTERN IN EXPAT(A6) ; ; CLOBBERS: D0,D1,D2,A0,A1 ; ; DRAWING WITH COLOR PATTERNS: ; ; IF COPY MODE, COLOR IS ADDED TO THE PATTERN IN THIS ROUTINE AND THEN LATER ; BLITTED DIRECTLY TO THE SCREEN (FOR SPEED). OTHERWISE THE PATTERN IS LEFT AS A ; FOREGROUND/BACKGROUND MASK AND COLOR IS ADDED WITHIN THE BLT ROUTINE IF ; NECESSARY. IF XOR MODE, THE DST IS SIMPLY XOR'D AND THE COLORS ARE IGNORED. ; IF OR MODE, THE FOREGROUND COLOR IS APPLIED TO THE PATTERN AND OR'D INTO THE ; DST. IF BIC MODE, THE BACKGROUND COLOR IS APPLIED TO THE PATTERN AND OR'D INTO ; THE DST. ; ; A6 OFFSETS OF LOCAL VARIABLES OF CALLER: ; ; STACK FRAME VARS USED BY SEEKMASK (CALLED BY STRETCHBITS, RGNBLT, DRAWARC, DRAWLINE) ; ;------------------------------------------------------------- &CurFile SETC 'PATEXPAND' INCLUDE 'DrawingVars.a' ;------------------------------------------------------------- PARAMSIZE EQU 0 TWOPAT EQU -16 ;ROOM FOR TWO COPIES OF PAT SAVESTK EQU TWOPAT-4 ;ROOM TO SAVE STACK POINTER ROTSIZE EQU SAVESTK-2 ;SCANLINE SIZE FOR ROTATION ROTSHIFT EQU ROTSIZE-2 ;ROTATE AMOUNT GGLOBALS EQU ROTSHIFT-4 ;POINTER TO GRAFGLOBALS SAVEA5 EQU GGLOBALS-4 ;PLACE TO SAVE A5 VARSIZE EQU SAVEA5 ;TOTAL BYTES OF LOCAL VARS ;------------------------------------------------------------------ ; ; IF OLD PATTERN, ALLOCATE A BUFFER ON THE STACK AND POINT TO IT. ; IF NEW PATTERN, GO EXPAND IF NECESSARY. ; TST.B NEWPATTERN(A6) ;IS IT A NEW PATTERN? BNE NEWPATEXPAND ;=>YES, EXPAND PIXELPAT ; ALLOCATE AN EXPAND BUFFER ON THE STACK FOR USE BY CALLER DOOLD MOVE.L (SP)+,A0 ;GET RETURN ADDRESS MOVEQ #64,D0 ;MINIMUM BUFFER IS 64 BYTES MOVE DSTSHIFT(A6),D1 ;GET DEPTH SHIFT subq #3,D1 ;DEPTHS 1-8 OK @@@@ BAL 10Apr88 ble.S GETBUF ;=>SO GET THE PATTERN BUFFER @@@@ BAL 10Apr88 LSL D1,D0 ;ELSE DOUBLE FOR 16, QUAD FOR 32 GETBUF SUB D0,SP ;MAKE THE BUFFER (LONG ALIGNED) MOVE.L SP,EXPAT(A6) ;POINT TO PATTERN BUFFER MOVE.L A0,-(SP) ;REPLACE RETURN ADDRESS PSHARE LINK A4,#VARSIZE ;ALLOCATE STACK FRAME MOVEM.L D3-D6/A2-A3/A5,-(SP) ;SAVE REGS MOVE LOCMODE(A6),D0 ;GET MODE MOVE DSTPIX+BOUNDS+LEFT(A6),D2 ;GET GLOBAL-LOCAL OFFSET (PIXELS) MOVE.L FCOLOR(A6),D3 ;GET CURRENT FG COLOR MOVE.L BCOLOR(A6),D4 ;GET CURRENT BK COLOR MOVE DSTSHIFT(A6),D5 ;GET SHIFT FOR PIXEL DEPTH MOVE.L LOCPAT(A6),A0 ;GET PATTERN LEA PATROW(A6),A1 ;AND DATA DST AND #$F3,D0 ;TURN OFF PAT, INVERT BITS BEQ.S GOTCOPY ;=>IT'S COPY MODE BTST #5,D0 ;is it a new mode? BNE.S GotCopy MOVE.L alphaMask(A6),D3 ;ELSE FGCOLOR = BLACK <11> MOVEQ #0,D4 ;AND BKCOLOR = WHITE GOTCOPY MOVE.L GRAFGLOBALS(A5),A3 ;POINT TO QUICKDRAW GLOBALS ; ; IF PATALIGN VERT NON-ZERO, COPY PAT TWICE AND REPLACE A0 ; MOVEQ #7,D0 AND PATALIGN(A3),D0 ;GET PATALIGN MOD 8 BEQ.S VERTOK ;SKIP IF ZERO MOVE.L (A0),TWOPAT(A4) ;MAKE TWO COPIES OF PATTERN MOVE.L (A0)+,TWOPAT+8(A4) MOVE.L (A0),TWOPAT+4(A4) MOVE.L (A0),TWOPAT+12(A4) LEA TWOPAT(A4),A0 ADD D0,A0 VERTOK ADD PATALIGN+H(A3),D2 ;ADJUST FOR PATALIGN HORIZ MOVEQ #7,D6 ;SOURCE PAT IS 8 BYTES LONG AND D6,D2 ;TREAT SHIFTCOUNT MOD 8 TST D5 ;ONE BIT PER PIXEL? BNE.S NEWWAY ;=>NO, DO NEW WAY OLDWAY MOVE.L THEPORT(A3),A3 ;GET CURRENT GRAFPORT MOVE patStretch(A3),D0 ;GET patStretch CMP #-2,D0 ;IS PAT STRETCH = -2 ? BEQ.S THIN ;YES, STRETCH THIN CMP #2,D0 ;IS patStretch = 2 ? BEQ.S DOUBLE ;=>YES, DOUBLE THE DATA ; NEW WAY: EXPAND DATA TO MINIMUM NEEDED EXPANDED SIZE. ; DEPTH = 1-4: EXPAND 8*8 PATTERN TO 16 ROWS * 1 LONG (USE OLD BLT ROUTINES) ; DEPTH = 8: EXPAND 8*8 PATTERN TO 8 ROWS * 2 LONGS (USE NEW BLT ROUTINES) ; DEPTH = 16: EXPAND 8*8 PATTERN TO 8 ROWS * 4 LONGS ; DEPTH = 32: EXPAND 8*8 PATTERN TO 8 ROWS * 8 LONGS (64 LONGS MAX SIZE) ; EXPAND ROUTINES IN FILE STRETCH.A TO SHARE COMMON TABLES. NEWWAY move.l PatExTblPtr,A2 ;POINT TO ROUTINE TABLE add.l 0(A2,D5*4),A2 ;USE PIXSHIFT TO SELECT ROUTINE JSR (A2) ;EXPAND DIRECTLY INTO BUFFER BRA.S DONE ;=>ALL FINISHED ;----------------------------------------------------------- ; ; STRETCHED BY TWO: DOUBLE EACH BIT HORIZONTALLY AND VERTICALLY ; DOUBLE CLR.W (A1)+ ;CLEAR PATROW CLR.L (A1)+ ;CLEAR PATHMASK, PATVMASK MOVE.L (A1),A1 ;GET EXPAT POINTER CLR D0 ;CLEAR OUT HI BYTE DLOOP MOVE.B (A0)+,D0 ;GET A BYTE OF PATTERN EOR.B D7,D0 ;INVERT IT IF MODE BIT 2 ROL.B D2,D0 ;ALIGN TO LOCAL COORDS MOVE.B D0,-(SP) ;STASH FOR A WHILE LSR.B #4,D0 ;GET HI NIBBLE MOVE.B STRETCH(D0),(A1)+ ;PUT ONE BYTE MOVEQ #$F,D0 ;MASK FOR LO NIBBLE AND.B (SP)+,D0 ;GET THE LO NIBBLE MOVE.B STRETCH(D0),(A1)+ ;PUT ANOTHER TO MAKE A WORD MOVE.W -2(A1),(A1)+ ;STRETCH WORD OUT TO LONG MOVE.L -4(A1),(A1)+ ;STRETCH LONG TO TWO LONGS DBRA D6,DLOOP ;LOOP ALL 8 INPUT BYTES BRA.S DONE ;----------------------------------------------------------- ; ; STRETCH BY TWO AND THIN OUT THE BITS. ADD EXTRA WHITE DOTS. ; THIN CLR.W (A1)+ ;CLEAR PATROW CLR.L (A1)+ ;CLEAR PATHMASK, PATVMASK MOVE.L (A1),A1 ;GET EXPAT POINTER CLR D0 ;CLEAR OUT HI BYTE THINLP MOVE.B (A0)+,D0 ;GET A BYTE OF PATTERN EOR.B D7,D0 ;INVERT IT IF MODE BIT 2 ROL.B D2,D0 ;ALIGN TO LOCAL COORDS MOVE.B D0,-(SP) ;STASH FOR A WHILE LSR.B #4,D0 ;GET HI NIBBLE MOVE.B THINSTR(D0),(A1)+ ;PUT ONE BYTE MOVEQ #$F,D0 ;MASK FOR LO NIBBLE AND.B (SP)+,D0 ;GET THE LO NIBBLE MOVE.B THINSTR(D0),(A1)+ ;PUT ANOTHER TO MAKE A WORD MOVE.W -2(A1),(A1)+ ;STRETCH WORD OUT TO LONG CLR.L (A1)+ ;STRETCH LONG TO TWO LONGS DBRA D6,THINLP ;LOOP ALL 8 INPUT BYTES DONE MOVEM.L (SP)+,D3-D6/A2-A3/A5 ;RESTORE REGS UNLK A4 ;REMOVE STACK FRAME RTS ;JUST RETURN ;---------------------------------------------------------------- ; ; BIT DOUBLING TABLE FOR 0..15 INPUT --> BYTE OUTPUT ; STRETCH DC.B $00,$03,$0C,$0F,$30,$33,$3C,$3F DC.B $C0,$C3,$CC,$CF,$F0,$F3,$FC,$FF ; ; TABLE FOR THIN DOUBLING. ; THINSTR DC.B $00,$01,$04,$05,$10,$11,$14,$15 DC.B $40,$41,$44,$45,$50,$51,$54,$55 NEWPATEXPAND ;---------------------------------------------------------------- ; ; NEWPATEXPAND -- EXPAND A PIXELPAT, IF NECESSARY ; ; NOTE: STACK FRAME LINKED USING A4 SO NORMAL FRAME STILL IN A6 ; LINK A4,#VARSIZE ;ALLOCATE STACK FRAME MOVEM.L D3-D6/A2-A3/A5,-(SP) ;SAVE REGS MOVE.L SP,SAVESTK(A4) ;SAVE STACK POINTER MOVE.L GRAFGLOBALS(A5),A3 ;POINT TO QUICKDRAW GLOBALS MOVE.L A3,GGLOBALS(A4) ;SAVE IN STACK FRAME MOVE.L A5,SAVEA5(A4) ;AND SAVE GLOBAL POINTER MOVE.L LOCPAT(A6),A0 ;GET THE PIXPAT HANDLE POINTER MOVE.L (A0),A0 ;GET THE PIXPAT HANDLE MOVE.L (A0),A0 ;GET THE PIXPAT POINTER TST PATTYPE(A0) ;IS IT AN OLD PATTERN? BNE.S NOTOLD ;=>NO, CHECK FOR EXPANSION OF NEW PAT ;--------------------------------------------------------- ; ; IF OLD PATTERN, USE SHARED CODE TO EXPAND IT ; MOVE.L PATXDATA(A0),A0 ;GET THE EXPANDED DATA HANDLE MOVEQ #64,D0 ;MINIMUM BUFFER IS 64 BYTES MOVE DSTSHIFT(A6),D1 ;GET DEPTH SHIFT subq #3,D1 ;DEPTHS 1-8 OK @@@@ BAL 10Apr88 ble.S BUFOK ;=>SO GET THE PATTERN BUFFER @@@@ BAL 10Apr88 LSL.L D1,D0 ;ELSE DOUBLE FOR 16, QUAD FOR 32 BUFOK JSR RSetHSize MOVE.L (A0),d0 ;get master pointer @@@@ BAL 10Apr88 _rTranslate24To32 ;mask off high byte @@@@ BAL 10Apr88 move.l d0,EXPAT(A6) ;SAVE POINTER TO EXPAND DATA AREA ;*** LEAVE IT UNLOCKED MOVE.L LOCPAT(A6),A0 ;GET PIXPAT HANDLE POINTER MOVE.L A0,-(SP) ;SAVE PIXPAT HANDLE POINTER MOVE.L (A0),A0 ;GET HANDLE TO PIXPAT MOVE.L (A0),A0 ;GET POINTER TO PIXPAT MOVE.L PATDATA(A0),A0 ;GET HANDLE TO DATA MOVE.L (A0),A0 ;GET POINTER TO DATA MOVE.L A0,LOCPAT(A6) ;SET UP POINTER TO SRC DATA JSR PSHARE ;AND CALL COMMON CODE MOVE.L (SP)+,LOCPAT(A6) ;RESTORE PATTERN HANDLE NEWDONE MOVE.L SAVESTK(A4),SP ;RESTORE STACK POINTER BRA DONE ;AND RETURN ; IF THE DEPTH OR COLOR TABLE HAS CHANGED, EXPAND PATTERN TO CURRENT DEPTH NOTOLD MOVE.L LOCPAT(A6),A0 ;GET THE PIXPAT HANDLE POINTER MOVE.L (A0),A0 ;A0 = PIXPAT HANDLE MOVE.L (A0),A2 ;A2 = PIXPAT POINTER MOVE.L THEGDEVICE,A1 ;GET HANDLE TO CURRENT DEVICE MOVE.L (A1),A1 ;POINT TO CURRENT DEVICE MOVE.L GDPMAP(A1),A1 ;GET HANDLE TO DEVICE'S PIXMAP MOVE.L (A1),A1 ;POINT TO DEVICE'S PIXMAP MOVE PIXELSIZE(A1),D1 ;GET PIXEL DEPTH OF DEVICE ; ; Will need current ctSeed value below for updating LastCTable ; MOVE.L PMTABLE(A1),A1 ;GET HANDLE TO COLOR TABLE MOVE.L (A1),A1 ;POINT TO COLOR TABLE MOVE.L CTSEED(A1),D0 ;GET CURRENT COLOR TABLE ID IN D0 MOVE.L PATXMAP(A2),A5 ;GET HANDLE TO EXPANDED MAP MOVE.L (A5),A5 ;POINT TO IT CMP patXValid(A2),D1 ;HAS DEPTH CHANGED? BNE.S CONVERT ;=>YES, CONVERT TO CURRENT DEPTH cmp.w #8,d1 ;is src=dst > 8 bits/pixel <1.5> BAL bgt.s NOCNVRT ;don't check seeds on direct data <1.5> BAL ; MOVE.L PMTABLE(A1),A1 ;GET HANDLE TO COLOR TABLE ; MOVE.L (A1),A1 ;POINT TO COLOR TABLE ; MOVE.L CTSEED(A1),D0 ;GET CURRENT COLOR TABLE ID IN D0 CMP.L LASTCTABLE(A5),D0 ;HAS COLOR TABLE CHANGED? BEQ.S NOCNVRT ;=>NO, DON'T CONVERT CONVERT MOVE.L D0,LASTCTABLE(A5) ;UPDATE COLOR TABLE SEED MOVE D1,patXValid(A2) ;UPDATE DEPTH MOVE.L A0,-(SP) ;PUSH THE PIXPAT HANDLE MOVE.L SAVEA5(A4),A5 ;RESTORE A5 _PATCONVERT ;EXPAND PATTERN TO CURRENT DEPTH ; CALC STATE VARIABLES FOR STACK FRAME NOCNVRT MOVE.L LOCPAT(A6),A0 ;GET THE PIXPAT HANDLE POINTER MOVE.L (A0),A0 ;GET THE PIXPAT HANDLE MOVE.L (A0),A0 ;A0 = PIXPAT POINTER MOVE.L PATXMAP(A0),A5 ;GET HANDLE TO EXPANDED MAP MOVE.L (A5),A5 ;POINT TO IT MOVE.L ([PATXDATA,A0]),d0 ;COPY POINTER TO EXPANDED DATA @@@@ BAL 10Apr88 _rTranslate24To32 ;mask off high byte @@@@ BAL 10Apr88 move.l d0,EXPAT(A6) ;SAVE POINTER TO EXPAND DATA AREA MOVE PATXROW(A5),PATROW(A6) ;COPY EXPANDED ROWBYTES MOVE PATXHMASK(A5),PATHMASK(A6) ;COPY HORIZONTAL MASK MOVE PATXVMASK(A5),PATVMASK(A6) ;COPY VERTICAL MASK ;--------------------------------------------------------- ; ; HAS PATTERN'S ENVIRONMENT CHANGED SINCE LAST TIME? ; LEA LASTOFST(A5),A2 ;POINT TO SAVED GLOBAL-LOCAL OFFSET MOVE.L THEPORT(A3),A1 ;GET CURRENT GRAFPORT MOVE (A2)+,D0 ;GET LASTOFST CMP DSTPIX+BOUNDS+LEFT(A6),D0 ;HAS IT CHANGED? BNE.S DOPAT ;=>YES, rotate PATTERN CMP.L (A2)+,D7 ;HAS LASTINVERT CHANGED? BNE.S DOPAT ;=>YES, EXPAND PATTERN MOVE PATALIGN+V(A3),D0 ;GET ALIGN VERTICAL CMP (A2)+,D0 ;HAS LASTALIGN VERTICAL CHANGED? BNE.S DOPAT ;=>YES, EXPAND PATTERN MOVE PATALIGN+H(A3),D0 ;GET ALIGN HORIZONTAL CMP (A2)+,D0 ;HAS LASTALIGN HORIZONTAL CHANGED? BNE.S DOPAT ;=>ROTATE WITH ALIGN MOVE PATSTRETCH(A1),D0 ;GET STRETCH CMP (A2)+,D0 ;HAS LASTSTRETCH CHANGED? BEQ DONE ;=>NO, JUST RETURN SAVESTATE ;LASTOFST ALREADY UPDATED LEA LASTINVERT(A5),A2 ;POINT TO START OF SAVE AREA MOVE.L D7,(A2)+ ;SAVE INVERT MOVE.L GGLOBALS(A4),A3 ;POINT TO QUICKDRAW GLOBALS MOVE.L PATALIGN(A3),(A2)+ ;SAVE LASTALIGN MOVE.L THEPORT(A3),A1 ;GET CURRENT GRAFPORT MOVE PATSTRETCH(A1),(A2)+ ;SAVE LASTSTRETCH BRA NEWDONE ;=>STRIP STACK AND RETURN DOPAT ; GET WIDTH OF PATTERN AND ALLOCATE SCANLINE BUFFER ON STACK MOVE PATXROW(A5),D0 ;GET ROWBYTES OF EXPANDED PATTERN BNE.S NOSMALL ;=> NOT AN OLD SIZED PATTERN MOVEQ #4,D0 ;ELSE ROWBYTES := 4 NOSMALL MOVE.L PATMAP(A0),A1 ;GET THE PATTERN'S PIXMAP HANDLE MOVE.L (A1),A1 ;POINT TO THE PIXMAP MOVE DSTSHIFT(A6),D1 ;GET SHIFT FOR PIXEL DEPTH LSL #3,D0 ;CONVERT BYTES TO BITS MOVE D0,D3 ;D3 = WIDTH IN BITS MOVE D0,D4 ;SAVE WIDTH FOR BELOW LSR D1,D4 ;D4 = WIDTH IN PIXELS LSR #5,D0 ;CONVERT BITS TO LONGS NXTLNG0 CLR.L -(SP) ;CLEAR A LONG DBRA D0,NXTLNG0 ;LOOP UNTIL DONE ; SINCE PATTERN MIGHT ALREADY BE SHIFTED, CALC NEW OFFSET - OLD OFFSET MOVE DSTPIX+BOUNDS+LEFT(A6),D2 ;GET NEW GLOBAL-LOCAL OFFSET ADD PATALIGN+H(A3),D2 ;ADD HORIZONTAL ALIGNMENT MOVE D2,D0 ;SAVE A COPY SUB LASTOFST(A5),D2 ;SHIFT := NEW OFFSET - OLD OFFSET MOVE D0,LASTOFST(A5) ;SAVE NEW OFFSET SUBQ #1,D4 ;GET WIDTH-1 AS MASK AND D4,D2 ;MASK THE OFFSET BEQ.S SAVESTATE ;=>SAME ALIGNMENT, RETURN LSL D1,D2 ;DEPTH*OFFSET = SHIFT AMOUNT ; SET UP ROTATE INFO MOVE D2,ROTSHIFT(A4) ;SAVE SHIFT AMOUNT MOVE D3,ROTSIZE(A4) ;SAVE SCANLINE SIZE MOVE.L PATXDATA(A0),A3 ;GET HANDLE TO EXPANDED DATA MOVE.L (A3),A3 ;POINT AT EXPANDED DATA MOVEQ #32,D6 ;GET A USEFUL NUMBER IN D6 MOVEQ #16,D5 ;ASSUME OLD-STYLE PATTERN TST PATXROW(A5) ;IS IT? BEQ.S CHKSCAN ;=>YES MOVE BOUNDS+BOTTOM(A1),D5 ;GET BOTTOM SUB BOUNDS+TOP(A1),D5 ;GET NUMBER OF SCANS TO DO MOVEQ #0,D3 ;INIT D3 TO 0 BRA.S CHKSCAN ;CHECK FOR INVALID HEIGHTS AND LOOP ; ROTATE NEXT ROW INTO THE SCANLINE BUFFER STARTING AT OFFSET INTO SRC NXTSCAN MOVE.L SP,A2 ;POINT TO SCANLINE BUFFER MOVE ROTSIZE(A4),D3 ;GET SIZE OF SCANLINE MOVE ROTSHIFT(A4),D2 ;GET SHIFT AMOUNT MOVE D2,D7 ;USE AS START OFFSET INTO SRC EXT.L D7 ;LONG FOR BFEXTU SUB D7,D3 ;SCANSIZE-START IS # BITS TO DO ; PART 1: WRITE LONGS UNTIL WE HIT THE END OF THE SRC NXTLNG1 BFEXTU (A3){D7:0},D0 ;GET 32 BITS OF SRC ADD.L D6,D7 ;BUMP SRC OFFSET SUB D6,D3 ;UPDATE NUMBER OF BITS TO DO BMI.S NOTLONG ;=>IF PAST END, DON'T DO LONG MOVE.L D0,(A2)+ ;ELSE PUT LONG TO DST BRA.S NXTLNG1 ; PART 2: WRITE THE FRACTIONAL PARTS FROM THE END AND THE START OF THE SRC NOTLONG MOVE.L D6,D1 ;GET 32 ADD D3,D1 ;GET NUMBER OF LEFTOVER BITS (LONG) ROL.L D1,D0 ;PUT LEFTOVERS INTO LOW PART OF D0 BFINS D0,(A2){0:D1} ;INSERT BITS FROM END OF SRC NEG D3 ;GET NUMBER OF BITS TO DO BFEXTU (A3){0:D3},D0 ;GET THAT MANY BITS BFINS D0,(A2){D1:D3} ;AND PUT TO DST ADD.W #4,A2 ;DONE WITH THAT LONG SUB D3,D2 ;SAY WE'VE DONE THOSE BITS BLE.S DONESCAN ;=>DONE WITH SCAN (*** NEEDED?) ; PART3: WRITE LONGS UNTIL WE'VE EXHAUSTED ALL SRC BITS. NXTLNG2 BFEXTU (A3){D3:0},D0 ;GET 32 BITS OF SRC ADD.L D6,D3 ;GO TO NEXT LONG SUB D6,D2 ;SAY WE'VE DONE THOSE BITS BMI.S DONESCAN ;=>COUNT EXHAUSTED, DONE W/SCAN MOVE.L D0,(A2)+ ;ELSE PUT TO DST BRA.S NXTLNG2 ;AND LOOP UNTIL DONE DONESCAN MOVE.L SP,A2 ;POINT TO SCANLINE BUFFER MOVE ROTSIZE(A4),D0 ;GET NUMBER OF BITS TO DO SUBQ #1,D0 ;FOR LONG ROUNDING LSR #5,D0 ;CONVERT TO LONGS NXTLNG3 MOVE.L (A2)+,(A3)+ ;COPY A LONG DBRA D0,NXTLNG3 ;LOOP FOR ALL LONGS CHKSCAN DBRA D5,NXTSCAN ;=>DO NEXT SCANLINE BRA SAVESTATE ;AND RETURN PATCONVERT PROC EXPORT IMPORT GetDevPix,PatDither,MakeScaleTbl, RSetHSize ;------------------------------------------------------------------ ; ; PROCEDURE PATCONVERT (PAT: PixPatHandle); ; ; Convert the specified pattern to the current depth and color table. ; Note: This routine is shared by patterns and cursors, which are parallel ; structures. Expand data for the pattern is kept in the patXMap handle, which ; is carefully unused if the structure is a cursor. ; ; This routine reflects the patch code in QDciPatchROM.a which stb ; makes direct pixpats work for offscreen gWorlds. stb PARAMSIZE EQU 4 PAT EQU PARAMSIZE+8-4 ; handle to pattern SAVESTK EQU -4 ; save the stack WIDCNT EQU SAVESTK-2 ; width of pattern in pixels HTCNT EQU WIDCNT-2 ; height of pattern in scans HREPCNT EQU HTCNT-2 ; horizontal repetitions of pattern VREPCNT EQU HREPCNT-2 ; vertical repetitions of pattern PATROW EQU VREPCNT-2 ; rowbytes of src pattern DstPix EQU PATROW-PMREC ; dst pixmap for calling stretch <1.5> BAL VARSIZE EQU DstPix ; local vars <1.5> BAL LINK A6,#VARSIZE ; allocate stack frame MOVEM.L D3-D7/A0/A2-A4,-(SP) ; save all registers ; A0 saved for SetFillPat MOVE.L SP,SAVESTK(A6) ; save stack pointer ; get the dst pixel size in D6 and the src pixel size in D7 bsr.l GetDevPix ; get pointer to GDevice in A0 MOVE PixelSize(A0),D6 ; get dst pixel size EXT.L D6 ; make long for translate loop MOVE.L PAT(A6),A4 ; get the PixPat Handle MOVE.L (A4),A1 ; point to the pixPat MOVE patType(A1),D0 ; get the type of pattern BMI.S NoDither ; => it's a cursor, no offset to set MOVE.L patXMap(A1),A0 ; get handle to patXMap MOVE.L (A0),A0 ; point to patXMap CLR LastOfst(A0) ; we're expanding with offset 0 CMP #ditherPat,D0 ; does pat need to be dithered? BNE.S NoDither ; => no, don't adjust MOVE.L A4,-(SP) ; push pixPat handle _PatDither ; create best-match dither MOVE.L (A4),A1 ; point to the pixPat NoDither MOVE.L PatMap(A1),A3 ; get the pixmap handle MOVE.L (A3),A0 ; point to the pixmap MOVE pixelSize(A0),D7 ; get source pixel size EXT.L D7 ; make long for translate loop ; set up patXRow, patXHMask, patXVMask MOVE rowBytes(A0),D0 ; get src rowbytes AND #nuRBMask,D0 ; clear flag bits MOVE D0,patRow(A6) ; save for expand loop CLR HREPCNT(A6) ; assume no horizontal reps CLR VREPCNT(A6) ; assume no vertical reps LEA bounds+right(A0),A2 ; point to end of bounds MOVE (A2),D4 ; get right MOVE -(A2),D3 ; get bottom SUB -(A2),D4 ; get width in pixels in D4 SUB -(A2),D3 ; get height in D3 MOVE D4,D0 ; get src width in pixels SUBQ #1,D0 ; make it 0 based MOVE D0,WIDCNT(A6) ; save src width in pixels MOVE D3,D0 ; get height SUBQ #1,D0 ; make it 0 based MOVE D0,HTCNT(A6) ; save src height in pixels ; if the pattern is a cursor, skip repeat stuff MOVE patType(A1),D0 ; get the type of pattern BPL.S NoCrsr ; => not a cursor, get reps LSR #3,D4 ; convert dst bits to bytes MULU D6,D4 ; stretch to dst depth BRA.S GotReps ; => don't replicate cursors ; If the pattern will fit into a long, repeat, if necessary, to fill the whole ; word. Also make the pattern 16 scans high. Set patXRow to 0 to indicate a 32*16 pattern. NoCrsr MOVE.L patXMap(A1),A2 ; get handle to expanded info MOVE.L (A2),A2 ; point to expanded info MULU D6,D4 ; get dst width in bits MOVEQ #32,D0 ; get number of bits in a long DIVU D4,D0 ; get times to repeat to fit into long SUBQ #1,D0 ; make repeat count 0 based BMI.S NOREPS ; => no horizontal repetitions MOVE D0,HREPCNT(A6) ; and set horizontal rep count ; pattern fits into a long, so set CLR PATXROW(A2) ; flag to use the old blt routines MOVEQ #4,D4 ; and set rowbytes to 4 MOVEQ #16,D0 ; get minimum number of vert lines DIVU D3,D0 ; get 16 DIV height CMP #1,D0 ; is it 1 or less? BLT.S NOREPS2 ; => yes, no repetitions MULU D0,D3 ; multiply height by repcount SUBQ #1,D0 ; make VRepCnt 0 based MOVE D0,VREPCNT(A6) ; and set vertical rep count BRA.S REPS ; => patXRow already cleared NOREPS LSR #3,D4 ; convert dst bits to bytes NOREPS2 MOVE D4,PATXROW(A2) ; save expanded rowbytes REPS MOVE D4,D0 ; copy expanded rowBytes SUBQ #1,D0 ; HMASK := $FFFC AND (rowbytes-1) AND #$FFFC,D0 ; mask to long boundary MOVE D0,PatXHMask(A2) ; save HMask MOVE D4,D0 ; get (adjusted) rowbytes MULU D3,D0 ; VMASK := rowbytes*height - 1 SUBQ #1,D0 ; make it a mask MOVE D0,PatXVMask(A2) ; save VMask ; Calc total size of the dst and set the size of patXData GotReps MOVE D4,D0 ; get (adjusted) width in bytes MULU D3,D0 ; multiply by (adjusted) height MOVE.L (A4),A0 ; point to the pixPat MOVE.L patXData(A0),A0 ; get the handle to expanded bits JSR RSetHSize ; set to proper size ; Allocate pixel translate table on top of stack and initialize cmp.W #8,d7 ; is src direct data? <1.5> BAL bgt.s DirectPixPat ; yes, go call stretchbits <1.5> BAL MOVE.L (A3),-(SP) ; push pixMap pointer MOVE #$20,-(SP) ; pass srcAverage as a mode (so colors are used) _MakeScaleTbl ; make translate table ; For each pixel, translate and write out MOVE.L (A4),A1 ; point to the pixPat MOVE.L ([patXData,A1]),A2 ; point to the dst MOVEQ #0,D5 ; position to start of dst NXTPASS MOVE.L (A4),A1 ; point to the pixPat MOVE.L ([patData,A1]),A3 ; point to the src data MOVE HTCNT(A6),D3 ; get number of scans to do NXTSCAN MOVE HREPCNT(A6),D2 ; get horizontal repeat count NXTREP MOVEQ #0,D4 ; position to start of src scan MOVE WIDCNT(A6),D1 ; get width of src NXTPXL BFEXTU (A3){D4:D7},D0 ; extract a source pixel move.l 0(SP,D0*4),D0 ; translate it @@@@ BFINS D0,(A2){D5:D6} ; and put to dst ADD.L D7,D4 ; bump to next src pixel ADD.L D6,D5 ; bump to next dst pixel DBRA D1,NXTPXL ; => repeat for each pixel in src DBRA D2,NXTREP ; => repeat so expanded pat 32 wide ADD patRow(A6),A3 ; else bump to next scan of src DBRA D3,NXTSCAN ; => and repeat for each scanline SUBQ #1,VREPCNT(A6) ; need to repeat vertically? BPL.S NXTPASS ; => yes, take it from the top ; restore everything and return Out MOVE.L SAVESTK(A6),SP ; restore the stack pointer MOVEM.L (SP)+,D3-D7/A0/A2-A4 ; restore work registers UNLINK PARAMSIZE,'PATCONVE' ; unlink and return ; ; Src is 16 or 32 bits/pixel so call stretch to depth convert to dst depth <1.5> BAL ; ; Enter with pixpat handle in a4 and src pixmap handle in a3. ; Dst rowBytes in D4. ; ; This routine contains the fix from the patch code in QDciPatchROM.a stb ; It makes direct pixpats work for offscreen gWorlds stb DirectPixPat MOVE.L (A4),A0 ; point to the pixPat MOVE.L patData(A0),A0 ; get the src data handle MOVE.L (a0),a0 ; get the src data ptr MOVE.L (A3),A1 ; point to the pixmap MOVE.L a0,baseAddr(a1) ; point the baseAddr to the patData bsr.l GetDevPix ; get pointer to GDevice in A0 lea dstPix(a6),a1 ; point to dst pixMap MOVEQ #PMREC/2-1,D0 ; make a local copy of dst gdpmap @NXTWORD MOVE (A0)+,(A1)+ ; DBRA D0,@NXTWORD ; lea dstPix+bounds+top(a6),a0 ; set up dstPix for patXData clr.l (a0)+ ; top,left = 0,0 move.w HtCnt(a6),(a0) ; addq.w #1,(a0)+ ; bottom = height move.w WidCnt(a6),(a0) ; addq.w #1,(a0)+ ; right = width <24JUL90 KON> ; the following line is better than clr.w dstPix+pmVersion(a6), stb ; in case you’re wondering where the line went stb clr.w (a0) ; clear pmVersion <24JUL90 KON> MOVE.L (A4),A1 ; point to the pixPat MOVE.L patXData(A1),A0 ; get the dst data handle MOVE.L (a0),a0 ; get the dst data ptr MOVE.L a0,dstPix+baseAddr(a6) ; point dstPix to the patXData OR.W #$8000,d4 ; set pixmap flag MOVE.W d4,dstPix+rowBytes(a6) ; set Dst rowbytes ; set up parameters to stretchBits move.l (a3),a0 ; point at srcPix move.l (a3),-(sp) ; srcPix clr.l -(sp) ; maskPix pea dstPix(a6) ; dstPix pea bounds(a0) ; srcrect pea dstPix+bounds(a6) ; maskrect pea dstPix+bounds(a6) ; dstrect clr.w -(sp) ; srcCopy mode btst #1,patType+1(a1) ; use dithering? beq.s @modeOK ; no, use srcCopy add.w #64,(sp) ; yes, use ditherCopy mode @modeOK clr.l -(sp) ; pattern ptr move.l GRAFGLOBALS(A5),A0 ; point to QD globals move.l WIDEOPEN(A0),-(sp) ; push rgnA = wideOpen move.l (sp),-(sp) ; push rgnB = wideOpen move.l (sp),-(sp) ; push rgnC = wideOpen st -(sp) ; multColor = true _stretchBits ; go for it ; Now replicate the Xpattern data horizontally and then vertically as needed MOVE.L (A4),A1 ; point to the pixPat MOVE.L ([patXData,A1]),A2 ; point to the src move.w WidCnt(a6),d7 ; get pixel width-1 addq #1,d7 mulu d6,d7 ; get bit offset to right edge in d7 and.w #nuRBMask,dstPix+rowbytes(A6) ; remove pixmap flag MOVE HTCNT(A6),D3 ; get number of scans to do @NXTSCAN MOVEQ #0,D5 ; position to start of src move.l d7,d4 ; copy bitwidth to d4 MOVE HREPCNT(A6),D2 ; get horizontal repeat count bra.s @nxtH @NXTREP MOVE WIDCNT(A6),D1 ; get width of src @NXTPXL BFEXTU (A2){D5:D6},D0 ; extract a source pixel BFINS D0,(A2){D4:D6} ; and put to dst ADD.L D6,D4 ; bump to next src pixel ADD.L D6,D5 ; bump to next dst pixel DBRA D1,@NXTPXL ; => repeat for each pixel in src @nxtH DBRA D2,@NXTREP ; => repeat so expanded pat 32 wide ADD dstPix+rowbytes(A6),A2 ; else bump to next scan of src/dst DBRA D3,@NXTSCAN ; => and repeat for each scanline MOVE.L ([patXData,A1]),A0 ; point to the src move dstPix+rowbytes(a6),d1 ; move HtCnt(a6),d2 ; addq #1,d2 ; get height mulu d2,d1 ; get bytes of src lsr.l #2,d1 ; make into count of longs subq #1,d1 ; zero based for dbra move.w VRepCnt(a6),d2 ; # of copies to make bra.s @nxtV @NXTPASS move.w d1,d0 ; bytes to copy @nxtLong move.l (a0)+,(a2)+ dbra d0,@nxtLong ; make a full copy of the src @nxtV dbra d2,@NXTPASS ; repeat as needed bra Out ; as seen in QDciPatchROM.a verbatim stb MakeScaleTbl PROC EXPORT ;--------------------------------------------------------------- ; ; PROCEDURE MakeScaleTbl (PMP: PixMapPtr); ; ; Allocates a translate table on the stack and returns with SP at the ; start of the table. The translate table contains one entry for each ; possible pixel value in the source pixMap (PMP); each entry contains the ; value to be written to the destination pixMap to best approximate that color. ; The translation table has 32 bits per entry. @@@@ ; redHigh EQU 8 greenHigh EQU 4 blueHigh EQU 0 MOVE.L (SP)+,A0 ; get return address MOVE.w (SP)+,D2 ; should we do colorizing here flag in bit 5 MOVE.L (SP)+,A1 ; get pixMap handle MOVE pixelSize(A1),D1 ; get size of pixels MOVEQ #1,D0 ; # entries = 2^pixelsize LSL D1,D0 ; # entries = 2^pixelsize MOVE D0,D1 ; save possible # of colors SUBQ #1,D0 ; make zero based for DBRA NXTWORD move.l #$7fffffff,-(SP) ; allocate one entry per long @@@@ DBRA D0,NXTWORD ; leave table on stack, save work regs, etc., on top of it TBLOFST EQU 9*4+12 ; ret addr, save regs, RGBSpec, Back and ForeColor MOVE.L A0,-(SP) ; push return address MOVEM.L A2/D3-D7,-(SP) ; save work registers MOVEQ #0,D5 ; clear high word MOVE D1,D5 ; save # of available colors SUBQ #6,SP ; allocate VAR ColorSpec on stack clr.w -(sp) ; force default color space to RGB ; ; Allocate forecolor and back color on stack for colorizing and for use later ; move.l a1,a2 ;save pixmap handle MOVEQ #-1,D0 ;GET WHITE MOVE.L D0,-(SP) ;PUSH R,G,B FOR WHITE MOVE D0,-(SP) CLR.L -(SP) ;PUSH R,G,B FOR BLACK CLR -(SP) ScaleColorBit EQU 3 SwapFGBGBit EQU 4 UseStretchBit EQU 5 InvertItBit EQU 7 ColorizeInModeCaseBit EQU 8 ColorizeInSrcBufBit EQU 9 btst #ScaleColorBit,d2 ;should we colorize? beq @useDefault ;skip if no. moveq #6,d4 btst #swapfgbgBit,d2 ;swap fg/bk colors? beq.s @dontswap moveq #0,d4 @dontswap PEA (SP,d4) _GetBackColor ;get fg, bg to do colorizing eor.w #6,d4 PEA (sp,d4) _GetForeColor ; ; Check to see if destination device is 1 bit deep. If so, we need to see if the fg and bg ; colors map to the same thing. If they do, then check to see if the colors themselves are ; the same. If not, then we invert the bg color <08JUN92 SAH> ; ; <16> <18AUG92 SAH> ; NOTE: This check is not correct. It should check to see if the destination is 1 or 2 ; bits deep and is a new port. There is also a major bug where we colorize with the inverted ; background color rather than just setting the background index. In particular, this breaks ; SeedCFill for indexed pixmaps. For the purposes of Cube-E, we will do an explicit check to ; see if the background color is white and the foreground is black, if so we won't invert. ; move.l ([theGDevice]),A0 ;get a pointer to the device move.l ([gdPMap,a0]),a0 ;get a pointer to its pixmap cmp.w #1,pixelSize(a0) bne.s @fgBgColorsOK ;not one bit, we don't have to worry move.w d2,d3 ;save d2 here from _Color2Index <09JUN92 SAH> ; now do the check for fg = black, bg = white <18AUG92 SAH> tst.l (sp) ;look at fg red and green <16> bne.s @doInvertCheck ;not black, so bail <16> tst.w 4(sp) ;look at fg blue <16> bne.s @doInvertCheck ;not black, so bail <16> moveq #-1,d0 ;get a white long <16> cmp.l 6(sp),d0 ;compare with bg red and green <16> bne.s @doInvertCheck ;not white, so bail <16> cmp.w 10(sp),d0 ;compare with bg blue <16> beq.s @fgBgColorsOK ;equal, so don't do invert <16> @doInvertCheck ; get copies of our colors on the stack <09JUN92 SAH> ; it starts out like this. Make sure we copy things in the right order! ; RRRRGGGG 0 ; BBBBrrrr 4 ; ggggbbbb 8 move.l 8(sp),-(sp) ;do ggggbbbb move.l 8(sp),-(sp) ;do BBBBrrrr move.l 8(sp),-(sp) ;do RRRRGGGG ;now we have another copy of the above subq.l #4,sp ;room for index pea 4(sp) ;ptr to the bg color _Color2Index subq.l #4,sp ;room for index pea 14(sp) ;ptr to the fg color _Color2Index move.w d3,d2 ;get our d2 back from _Color2Index <09JUN92 SAH> move.l (sp)+,d0 ;get the fg color cmp.l (sp)+,d0 ;compare against the bg color add.w #12,sp ;get rid of our private colors bne.s @fgBgColorsOK ;we're ok ;now, the two map to the same thing, so we need to check of the colors themselves ;are the same. If so, we don't do anything. move.l 0(sp),d0 cmp.l 6(sp),d0 bne.s @invertbg move.w 4(sp),d0 cmp.w 10(sp),d0 beq.s @fgBgColorsOK @invertbg pea 6(sp) ;push ptr to bg color _InvertColor ;and invert it @fgBgColorsOK ; ; if foreground black and background white, don't colorize. ; move.l 0(sp),d4 ;get long of fg color bne.s @useDefault ;abort if not black move.w 4(sp),d4 ;get high word of fg color bne.s @useDefault ;abort if not black ; ; check fg color ; move.l 6(sp),d4 ;get long of bg color addq #1,d4 ;check for white bne.s @useDefault move.w $0A(sp),d4 ;check high word add.w #1,d4 bne.s @useDefault bclr #ScaleColorBit,d2 ;fg black, bk white, don't colorize @useDefault ; ; Build pixel translation table ; move.l a2,a1 ;get pm handle back MOVEQ #-1,D6 ; assume no colors in color table MOVE.L pmTable(A1),D0 ; does it exist? BEQ noPredefinedColors MOVE.L D0,A2 ; get color table handle MOVE ([A2],CTSize),D4 ; get size of table in entries cmp D5,D4 ; more entries than bits allow? blo.s @notTooMany ; no, fine move D5,D4 ; yes, pin to depth subq #1,D4 ; make zero-based @notTooMany MOVE ([a2],TransIndex),D3 ; get ctFlags btst #14,d3 ; are they palette references? bne brink ; yes call dave MOVEQ #0,D6 ; zero high word MOVE D4,D6 ; remember number of colors btst #ScaleColorBit,d2 ;should we colorize? beq.s noColorizeLoop ;skip if no. @nxtEntry MOVE.L (A2),A0 ; get color table pointer MOVE D4,D3 ; assume entry = index TST TransIndex(A0) ; look for flag in transIndex BMI.S @UseIndex ; => flag set, use index MOVE.w CTTable+value(A0,D4*8),D3 ; get value of current entry @UseIndex MOVE CTTable+rgb+red(A0,D4*8),d0 ; get red ; ; colorize the red ; MOVE.w D0,d1 ;COPY SRC move.w 6(sp),d2 ;get red of bk color into low 16 bits AND.w D2,D0 ;ADD FG COLOR TO SRC NOT.w D1 ;GET NOT SRC move 0(sp),d2 ;get red of fg color into low 16 bits AND.w D2,D1 ;ADD BK COLOR TO NOT SRC OR.w D1,D0 ;COMBINE FG/BK DATA move.w d0,rgb+red+12(sp) MOVE.L CTTable+rgb+green(A0,D4*8),d0 ; copy green,blue ; ; colorize the green and blue at the same time ; MOVE.l D0,d1 ;COPY SRC move.l 8(sp),d2 ;get blue and green of bk color AND.l D2,D0 ;ADD FG COLOR TO SRC NOT.l D1 ;GET NOT SRC move.l 2(sp),d2 ;get blue and green of fg color AND.l D2,D1 ;ADD BK COLOR TO NOT SRC OR.l D1,D0 ;COMBINE FG/BK DATA move.l d0,rgb+green+12(SP) CLR.L -(SP) ; make room for function result PEA rgb+4+12(SP) ; point to VAR RGBColor _Color2Index ; convert to index MOVE.L (SP)+,D0 ; get result move.l D0,TBLOFST(SP,D3*4) ; put returned value in table @@@@ DBRA D4,@nxtEntry ; => repeat until done bra.s noPredefinedColors noColorizeLoop @nxtEntry MOVE.L (A2),A0 ; get color table pointer MOVE D4,D3 ; assume entry = index TST TransIndex(A0) ; look for flag in transIndex BMI.S @UseIndex ; => flag set, use index MOVE.w CTTable+value(A0,D4*8),D3 ; get value of current entry @UseIndex MOVE CTTable+rgb+red(A0,D4*8),rgb+red+12(sp) MOVE.L CTTable+rgb+green(A0,D4*8),rgb+green+12(SP) CLR.L -(SP) ; make room for function result PEA rgb+4+12(SP) ; point to VAR RGBColor _Color2Index ; convert to index MOVE.L (SP)+,D0 ; get result move.l D0,TBLOFST(SP,D3*4) ; put returned value in table @@@@ DBRA D4,@nxtEntry ; => repeat until done bra.s noPredefinedColors brink MOVEQ #0,D6 ; zero high word MOVE D4,D6 ; remember number of colors @nxtPEntry MOVE.L (a2),A0 ; get color table pointer MOVE D4,D3 ; assume entry = index MOVE.w CTTable+value(A0,D4*8),12(sp) ; put pmIndex in colorSpec MOVE.L (SP)+,D0 ; get result move.l D0,TBLOFST(SP,D3*4) ; put returned value in table @@@@ DBRA D4,@nxtPEntry ; => repeat until done clr.w QDErr ;remove any lingering error from ColorThing2Index ; ; leave ColorSpec on stack noPredefinedColors ; figure the number of unused colors ADDQ.L #1,D6 ; make the number of colors 1 based SUB.L D5,D6 ; figure difference between bit depth and colors defined NEG.L D6 ; figure number of unused colors (zero based) bgt.s @continue ; if negative or zero, strip foreground and background colors off stack: all done add #12,sp ;throw away fore and back colors bra @noRelativeColors ; ; At this point forecolor is on top of stack ; @continue MOVE.L SP,A1 MOVE.L A1,A2 ; save a copy of where the foreground is MOVEQ #2,D0 ; three colors, two based @startColor MOVE #$8000,-(SP) ; put 1/2 on stack MOVE (A1)+,-(SP) ; save integer on stack DBRA D0,@startColor MOVE.L A2,A1 ; start back with forecolor LEA TBLOFST+12(SP,D5*4),A2 ; start of stack based table + (6 words of $00008000) <12> SUBQ #1,D6 ; number of new colors, zero based BEQ.S @skipDivision ; if only 1 color left, no need to interpolate LEA 6(A1),A0 ; get start of real background color MOVEQ #2,D0 ; three colors, one based @nextColor MOVEQ #0,D1 ; clear high word MOVE (A0)+,D1 ; background color component SUB (A1)+,D1 ; change from foreground SLO D7 ; remember if it was negated BHS.S @orderedOK NEG D1 ; flip if subtraction would overflow @orderedOK SWAP D1 ; multiply high word times 65K DIVU.L D6,D1 ; figure fixed point color increment TST.B D7 BEQ.S @notFlipped NEG.L D1 ; flip it @notFlipped MOVE.L D1,-(SP) ; save it DBRA D0,@nextColor MOVEM.L (SP)+,D3-D5 ; load red, blue, green increments into registers @skipDivision @findUnused cmp.l #$7fffffff,-(A2) ; is it unused? @@@@ bne.s @findUnused ; if not, plow onward @@@@ MOVE redHigh(SP),red+12(SP) ; >> redHigh = 8 MOVE greenHigh(SP),green+12(SP) ; >> greenHigh = 4 MOVE blueHigh(SP),blue+12(SP) ; >> blueHigh = 0 CLR.L -(SP) ; make room for function result PEA 16(SP) ; location of RGBColor _Color2Index MOVE.L (SP)+,D0 ; get long result move.l D0,(A2) ; save away index @@@@ MOVEM.L (SP)+,D0-D2 ; last colors ADD.L D3,D0 ADD.L D4,D1 ADD.L D5,D2 ; increment red, blue green MOVEM.L D0-D2,-(SP) ; save them for next time DBRA D6,@findUnused ADD #24,SP ; throw away 3 long colors @noRelativeColors MOVEM.L (SP)+,A2/D0-D1/D3-D7 ; toss 8 on stack (D0,D1) & restore work registers RTS ;---------------------------------------------------------------------------------------- ; IF 1 THEN ; ; Here begins the new, improved patDither code as furnished by Keith McGreggor <12Mar89> ; PatDither PROC EXPORT IMPORT Color2Index,Index2Color ;------------------ ; PROCEDURE PatDither( PPH : PixPatHandle ); PARAMSIZE EQU 4 PPH EQU PARAMSIZE+8-4 rcolor EQU -6 acolor EQU rcolor-6 ecolor3 EQU acolor-6 ecolor2 EQU ecolor3-6 ecolor1 EQU ecolor2-6 totals EQU ecolor1-12 ; three longwords for running error value VARSIZE EQU totals LINK A6,#VARSIZE MOVEM.L A4,-(SP) ; ??? should we preserve A2? MOVE.L PPH(A6),A0 MOVE.L (A0),A2 CMP #DitherPat,patType(A2) BNE DONE MOVE.L PatMap(A2),A0 MOVE.L (A0),A0 MOVE.L PMTable(A0),A0 MOVE.L (A0),A0 LEA CTTable+(4*CTEntrySize)(A0),A0 LEA rcolor(A6),A2 MOVE.L rgb+red(A0),(A2)+ MOVE.W rgb+blue(A0),(A2) if 0 then ; keith CLR.L -(SP) PEA rcolor(A6) _Color2Index PEA acolor(A6) _Index2Color MOVE rcolor+red(A6),D0 MOVE acolor+red(A6),D1 BSR.S hocuspocus MOVE D0,ecolor1+red(A6) MOVE rcolor+green(A6),D0 MOVE acolor+green(A6),D1 BSR.S hocuspocus MOVE D0,ecolor1+green(A6) MOVE rcolor+blue(A6),D0 MOVE acolor+blue(A6),D1 BSR.S hocuspocus MOVE D0,ecolor1+blue(A6) CLR.L -(SP) PEA ecolor1(A6) _Color2Index PEA ecolor2(A6) _Index2Color MOVE ecolor1+red(A6),D0 MOVE ecolor2+red(A6),D1 BSR.S hocuspocus MOVE D0,ecolor2+red(A6) MOVE ecolor1+green(A6),D0 MOVE ecolor2+green(A6),D1 BSR.S hocuspocus MOVE D0,ecolor2+green(A6) MOVE ecolor1+blue(A6),D0 MOVE ecolor2+blue(A6),D1 BSR.S hocuspocus MOVE D0,ecolor2+blue(A6) CLR.L -(SP) PEA ecolor2(A6) _Color2Index PEA ecolor3(A6) _Index2Color bra.s continue hocuspocus ADD D0,D0 BCS.S notfine SUB D1,D0 BCC.S fine MOVEQ #0,D0 RTS notfine SUB D1,D0 BCS.S fine MOVEQ #-1,D0 fine RTS continue MOVE ecolor2+red(A6),D0 MOVE ecolor3+red(A6),D1 BSR.S hocuspocus MOVE D0,ecolor3+red(A6) MOVE ecolor2+green(A6),D0 MOVE ecolor3+green(A6),D1 BSR.S hocuspocus MOVE D0,ecolor3+green(A6) MOVE ecolor2+blue(A6),D0 MOVE ecolor3+blue(A6),D1 BSR.S hocuspocus MOVE D0,ecolor3+blue(A6) CLR.L -(SP) PEA ecolor3(A6) _Color2Index PEA ecolor3(A6) _Index2Color else ;dvb CLR.L totals(A6) CLR.L totals+4(A6) CLR.L totals+8(A6) LEA aColor(A6),A2 ; A2 -> where to put best fit BSR.S @hocus LEA eColor1(A6),A2 BSR.S @hocus LEA eColor3(A6),A2 BSR.S @hocus LEA eColor2(A6),A2 BSR.S @hocus BRA.S @around @hocus ; Add the desired color (rColor) to the running error ; totals (totals) and get the best fit. Then, subtract that from the ; totals. Put the answer in color at A2 LEA totals(A6),A0 ; A0 -> red error component (longs) LEA rColor(A6),A1 ; A1 -> desired color red component (words) MOVEQ #2,D1 ; Loop 3 times for rgb @hocLoop CLR.L D0 MOVE (A1)+,D0 ADD.L (A0),D0 ; D0 = desired component + running error MOVE.L D0,(A0)+ ; keep error, with overflow, in totals SWAP D0 ; Check out the high word TST.W D0 ; If zero, we're in range BEQ.S @compOK EXT.L D0 ; Pin all - to -1, and all + to 0 NOT.L D0 ; And swap, so - -> 0, and + -> ffff @compOK SWAP D0 ; Get low part back MOVE D0,(A2)+ ; Save result component DBRA D1,@hocLoop ; Got all three pinned components SUBQ #6,A2 ; Bump A2 back to beginning of color SUBQ #4,SP ; result MOVE.L A2,-(SP) ; rgbColor _Color2Index MOVE.L A2,-(SP) _Index2Color ; Get actual best fit color LEA totals(A6),A0 ; A0 -> component errors (longs) MOVEQ #2,D1 ; Loop thrice for RGB @hocLoop2 CLR.L D0 MOVE (A2)+,D0 NEG.L D0 ADD.L (A0),D0 MOVE.L D0,(A0)+ ; and stash back into totals DBRA D1,@hocLoop2 RTS @around endif MOVE.L PPH(A6),A2 MOVE.L (A2),A2 MOVE.L PatMap(A2),A2 MOVE.L (A2),A2 MOVE.L PMTable(A2),A2 MOVE.L (A2),A2 LEA CTTable(A2),A2 MOVE #0,(A2)+ MOVE.L acolor+red(A6),(A2)+ MOVE acolor+blue(A6),(A2)+ MOVE #1,(A2)+ MOVE.L ecolor1+red(A6),(A2)+ MOVE ecolor1+blue(A6),(A2)+ MOVE #2,(A2)+ MOVE.L ecolor2+red(A6),(A2)+ MOVE ecolor2+blue(A6),(A2)+ MOVE #3,(A2)+ MOVE.L ecolor3+red(A6),(A2)+ MOVE ecolor3+blue(A6),(A2)+ DONE MOVEM.L (SP)+,A4 UNLK A6 RTS ELSE ; ; Here begins the old patDither code which originally shipped with the Mac II ; PatDither PROC EXPORT IMPORT GetDevPix,Color2Index,Index2Color ;--------------------------------------------------------------- ; ; PROCEDURE PatDither (PPH: PixPatHandle); ; ; Called with a pattern of patType = ditherPat (an RGB to be dithered), ; which has the desired RGB as the fifth entry in the color table. The data is already ; set up to be an 8*8*2 pattern containing a repeating 2*2 dither. All ; this routine does is decide which four color table values should be ; assigned to those pixel values. ; This routine assumes the data and color table are the right size. PARAMSIZE EQU 4 PPH EQU PARAMSIZE+8-4 ; handle to pattern VARSIZE EQU 0 ; no locals LINK A6,#VARSIZE ; allocate stack frame MOVEM.L D3/A2,-(SP) ; save all registers MOVE.L PPH(A6),A0 ; get handle to pixPat MOVE.L (A0),A2 ; point to pixPat CMP #DitherPat,patType(A2) ; is it a dither pattern? BNE DONE ; => no, just return ; GET EACH RGB COMPONENT AS A 16.16 FIXED NUMBER ; THE RGB IS THE FIFTH ENTRY IN THE COLOR TABLE MOVE.L PatMap(A2),A0 ; get handle to pixMap MOVE.L (A0),A0 ; point to pixMap MOVE.L PMTable(A0),A0 ; get handle to color table MOVE.L (A0),A0 ; point to color table LEA CTTable+(4*CTEntrySize)(A0),A0 ; point to RGB MOVE.L rgb+red(A0),D0 ; get red, green components MOVE D0,D1 ; copy green component CLR D0 ; clear low word of red SWAP D1 ; get green into high word for fixed CLR D1 ; clear low word of green MOVE rgb+blue(A0),D2 ; get blue component SWAP D2 ; into high word for fixed CLR D2 ; clear low word ; DIVIDE EACH COMPONENT INTO LEVELS OF INTENSITY (13 LEVELS FOR 8 BPP; 5 OTHERWISE) LEA DthrTbl13,A0 ; use 13 levels if 8 bit per pixel MOVE.L #$13B13B13,D3 ; $10000/13 = $13B1.3B13 (Fixed) MOVE.L theGDevice,A1 ; get handle to the gDevice MOVE.L (A1),A1 ; point to the gDevice MOVE.L GDPMap(A1),A1 ; get handle to pixMap MOVE.L (A1),A1 ; get pointer to pixMap CMP #8,pixelSize(A1) ; is depth 8 (or greater)? BGE.S FullRes ; => yes, use 13 levels LEA DthrTbl5,A0 ; else use 5 levels of color MOVE.L #$33333333,D3 ; $10000/5 = $3333.3333 (Fixed) FullRes DIVU.L D3,D0 ; divide into 5 or 13 levels DIVU.L D3,D1 ; divide into 5 or 13 levels DIVU.L D3,D2 ; divide into 5 or 13 levels ; GET THE COLOR TABLE AND PREPARE TO STUFF ENTRIES MOVE.L patMap(A2),A2 ; get handle to pattern's pixMap MOVE.L (A2),A2 ; point to pixMap MOVE.L PMTable(A2),A2 ; get handle to color table MOVE.L (A2),A2 ; point to color table LEA CTTable(A2),A2 ; point to first entry in color table ; levels for first pixel in 2*2 dither are in leftmost column of DthrTbl MOVE #0,(A2)+ ; pixel value = 0 MOVE 0(A0,D0*8),(A2)+ ; write red component MOVE 0(A0,D1*8),(A2)+ ; write green component MOVE 0(A0,D2*8),(A2)+ ; write blue component ; levels for second pixel in 2*2 dither are in second column of DthrTbl MOVE #1,(A2)+ ; pixel value = 1 MOVE 2(A0,D0*8),(A2)+ ; write red component MOVE 2(A0,D1*8),(A2)+ ; write green component MOVE 2(A0,D2*8),(A2)+ ; write blue component ; levels for third pixel in 2*2 dither are in third column of DthrTbl MOVE #2,(A2)+ ; pixel value = 2 MOVE 4(A0,D0*8),(A2)+ ; write red component MOVE 4(A0,D1*8),(A2)+ ; write green component MOVE 4(A0,D2*8),(A2)+ ; write blue component ; levels for last pixel in 2*2 dither are in last column of DthrTbl MOVE #3,(A2)+ ; pixel value = 3 MOVE 6(A0,D0*8),(A2)+ ; write red component MOVE 6(A0,D1*8),(A2)+ ; write green component MOVE 6(A0,D2*8),(A2)+ ; write blue component DONE MOVEM.L (SP)+,D3/A2 ; restore work registers UNLINK PARAMSIZE,'PATDITHE' ; unlink and return ; DthrTbl13 assumes that there are 4 possible levels of a color component ; ($0000,$5555,$AAAA,$FFFF). It uses a two-by-two dither of these four ; levels to create an effective 13 levels of that component. This process ; is repeated for all three components, giving a range of 13*13*13 possible ; patterns (colors). DthrTbl13 DC.W $0000,$0000,$0000,$0000 ; level 0 DC.W $5555,$0000,$0000,$0000 ; level 1 DC.W $5555,$0000,$0000,$5555 ; level 2 DC.W $5555,$5555,$0000,$5555 ; level 3 DC.W $5555,$5555,$5555,$5555 ; level 4 DC.W $AAAA,$5555,$5555,$5555 ; level 5 DC.W $AAAA,$5555,$5555,$AAAA ; level 6 DC.W $AAAA,$AAAA,$5555,$AAAA ; level 7 DC.W $AAAA,$AAAA,$AAAA,$AAAA ; level 8 DC.W $FFFF,$AAAA,$AAAA,$AAAA ; level 9 DC.W $FFFF,$AAAA,$AAAA,$FFFF ; level 10 DC.W $FFFF,$FFFF,$AAAA,$FFFF ; level 11 DC.W $FFFF,$FFFF,$FFFF,$FFFF ; level 12 ; DthrTbl5 assumes that there are 2 possible levels of a color component ; ($0000,$FFFF). It uses a two-by-two dither of these two ; levels to create an effective 5 levels of that component. This process ; is repeated for all three components, giving a range of 5*5*5 possible ; patterns (colors). DthrTbl5 DC.W $0000,$0000,$0000,$0000 ; level 0 DC.W $FFFF,$0000,$0000,$0000 ; level 1 DC.W $FFFF,$0000,$0000,$FFFF ; level 2 DC.W $FFFF,$FFFF,$0000,$FFFF ; level 3 DC.W $FFFF,$FFFF,$FFFF,$FFFF ; level 4 ENDIF MAKERGBPAT PROC EXPORT IMPORT OneBitData,CopyPMap, RSetHSize ;--------------------------------------------------------------- ; ; PROCEDURE MakeRGBPat (PPH: PixPatHandle; myRGB: RGBColor); ; ; Alters specified pattern to be type ditherPat (patType = 2). ; A ditherPat is an 8*8*2 pattern (16 bytes of data) with a color ; table having 4 entries. The specified entry is kept in the fifth ; entry in the pattern's color table. ; ; Note that the pixel values for the dither are specifed here. The ; color table values for those pixels are determined at patConvert ; time (when it calls PatDither). ; PARAMSIZE EQU 8 PPH EQU PARAMSIZE+8-4 ; pixPatHandle myRGB EQU PPH-4 ; RGB VARSIZE EQU 0 ; no vars LINK A6,#VARSIZE MOVEM.L A2-A3,-(SP) ; save work register MOVE.L PPH(A6),A1 ; get the pix pat handle MOVE.L (A1),A0 ; point at the pix pat MOVE #ditherPat,patType(A0) ; set type to ditherPat MOVE #-1,patXValid(A0) ; INVALIDATE PATTERN MOVE.L #$AA55AA55,D0 ; set default one bit MOVE.L D0,pat1Data(A0) ; pattern to gray MOVE.L D0,pat1Data+4(A0) ; SET COLOR TABLE TO 5 ENTRIES, INITIALIZE HEADER ONLY MOVE.L patMap(A0),A3 ; get the pixMap handle MOVE.L (A3),A0 ; point at the pix map MOVE.L pmTable(A0),A0 ; get the color table handle MOVEQ #CTRec+(5*CTEntrySize),D0 ; size = header + 5 entries JSR RSetHSize ; set color table size MOVE.L (A0),A0 ; point at the color table CLR.L -(SP) ; make room for long result _GetCTSeed ; get a new seed MOVE.L (SP)+,CTSeed(A0) ; and set it to unique value CLR transIndex(A0) ; clear transIndex MOVE #4,CTSize(A0) ; say there are 4 entries ; STORE THE REQUESTED RGB IN THE FIFTH ENTRY IN THE COLOR TABLE LEA CTTable+(4*CTEntrySize)(A0),A0 ; point to RGB MOVE.L myRGB(A6),A2 ; get pointer to RGB MOVE #4,(A0)+ ; put index field MOVE.L (A2)+,(A0)+ ; copy red, green MOVE (A2)+,(A0) ; copy blue ; SET PATTERN DATA TO 8*8*2 AND INITIALIZE IT MOVE.L (A1),A0 ; point at the pix pat MOVE.L patData(A0),A0 ; get the data handle MOVEQ #16,D0 ; pattern is 16 bytes JSR RSetHSize ; so set the size MOVE.L (A0),A0 ; point to the data MOVE.L #$1111BBBB,D0 ; get repeating pixel pattern ; row even = 0,1,0,1,0,1,0,1 ; row odd = 2,3,2,3,2,3,2,3 MOVE.L D0,(A0)+ ; set two rows of pattern MOVE.L D0,(A0)+ ; set two rows of pattern MOVE.L D0,(A0)+ ; set two rows of pattern MOVE.L D0,(A0)+ ; set two rows of pattern ; SET PATTERN'S PIXMAP FOR 8*8*2 PATTERN DATA MOVE.L (A3),A2 ; point at the pix map MOVE.L pmTable(A2),-(SP) ; save the color table handle LEA OneBitData,A1 ; point to one bit data JSR CopyPMap ; copy data into pixMap ; clobbers A1, A2 ; also clobbers color table MOVE.L (A3),A2 ; get back pixMap pointer MOVE.L (SP)+,pmTable(A2) ; restore color table MOVE #2,pRowBytes(A2) ; 2 bytes per row CLR.L pBounds+topLeft(A2) ; bounds = (0,0,8,8) MOVE.L #$00080008,pBounds+botRight(A2) MOVE #2,pixelsize(A2) ; two bits per pixel MOVE #2,cmpSize(A2) ; two bits per component MOVEM.L (SP)+,A2-A3 ; restore work register UNLINK PARAMSIZE,'MAKERGBP' ; unlink and return ENDPROC ; as seen in QDciPatchROM.a stb GETCICON PROC EXPORT IMPORT GetCTSeed, RSetHSize ;------------------------------------------------------------- ; ; FUNCTION GetCIcon(cIconID: INTEGER): cIconHandle; ; ; GetCIcon gets a resource of type 'cicn' with the specified ID, places ; all the data fields into handles, installs the handles into the cicn, ; resizes it, and then returns the data structure as a CIconHandle. ; ; The image of an icon is an arbitrary pixMap of arbitrary depth and color ; table. When it is drawn, it is remapped to the current depth and color table, ; if necessary. The bounds fields of the pixMap, bitMap, and mask are expected ; to be equal. The height and width of the icon are defined to be: ; height := IconPMap^^.bounds.bottom-IconPMap^^.bounds.top ; width := IconPMap^^.bounds.right-IconPMap^^.bounds.left. ; ; When the icon is drawn, the bounds rect is used as the image's source rect. ; The icon and mask will both be stretched to the destination rect. ; At the time the icon is drawn, the icon is locked down, and the baseAddr fields ; of the PMap, BMap, and Mask fields are set. ; ; The resource format is: ; ; field name structure size ; ; IconPMap pixMap (pmrec bytes) ; IconMask bitMap (bitMapRec bytes) ; IconBMap bitMap (bitMapRec bytes) ; IconData handle (4 bytes) ; MaskData data (IconMask.rowbytes*height bytes) ; BMapData data (IconBMap.rowbytes*height bytes) ; PMapCTab data (ctRec+(ctSize+1)*CTEntrySize bytes) ; PMapData data (IconPMap.rowbytes*height bytes) ; ; The icon's bitMap is defined to be NIL if its rowbytes field = 0 ; PARAMSIZE EQU 2 result EQU PARAMSIZE+8 ; cIconHandle RESULT cIconID EQU PARAMSIZE+8-2 ; icon ID LINK A6,#0 ; build stack frame MOVEM.L D3-D4/A2-A4,-(SP) ; preserve work registers CLR.L RESULT(A6) ; set result to NIL ; Load the data, detach from resource manager and lock it down SUBQ #4,SP ; make space for result MOVE.L #'cicn',-(SP) ; push resource type MOVE cIconID(A6),-(SP) ; push resource ID _GetResource ; get the resource MOVE.L (SP)+,A0 ; keep handle in A0 <1.5> BAL MOVE.L A0,D0 ; did we get one? <1.5> BAL BEQ NoGetNew ; if not, don't allocate one ; copy resource data to the main pattern/cursor data structure, keep in A4 ; The resource should be purgeable. Just leave it lying around. _HandToHand ; create a copy without purgeing src <1.5> BAL move.l A0,A4 ; get new handle into A4 <1.5> BAL _HLock ; and lock it down ; Point to the color table MOVE.L (A4),A3 ; keep pointer in A3 MOVE iconPMap+bounds+bottom(A3),D4 ; get bottom SUB iconPMap+bounds+top(A3),D4 ; calc height, keep in D4 LEA iconRec(A3),A2 ; point to the mask data MOVE iconMask+rowbytes(A3),D0 ; get mask's rowbytes MULU D4,D0 ; get size of mask data ADD D0,A2 ; point to bitmap table MOVE iconBMap+rowbytes(A3),D0 ; get bitMap's rowbytes MULU D4,D0 ; get size of bitmap data ADD D0,A2 ; point to color table ; Install the color table CLR.L -(SP) ; make room for function result _GetCTSeed ; go get seed for new color table MOVE.L (SP)+,CTSeed(A2) ; and set seed value MOVE.L A2,A0 ; point to the color table data MOVE CTSize(A2),D0 ; get number of entries in table ADDQ #1,D0 ; make it one based MULU #CTEntrySize,D0 ; get size of entries ADD #CTRec,D0 ; add in size of header EXT.L D0 ; long for PtrToHand MOVE.L D0,D3 ; save size in D4 _PtrToHand ; get a new handle into A0 BNE NoGetNew ; =>exit if no memory MOVE.L A0,iconPMap+pmTable(A3) ; install color table into pixMap ; Create the pixMap's data handle and install it MOVE.L A2,A0 ; point to the color table ADD.L D3,A0 ; bump to beginning of pixel data MOVE iconPMap+rowBytes(A3),D0 ; get the pixMap rowbytes AND #nuRBMask,D0 ; clear flag bits MULU D4,D0 ; multiply rowbytes * height ; MULU iconPMap+pixelSize(A3),D0 ; and multiply by depth for size (silly mistake!!) _PtrToHand ; go get a new handle BNE NoGetNew ; =>exit if no memory MOVE.L A0,iconData(A3) ; install data into pixPat MOVE.L A4,A0 ; get the handle _HUnlock ; and unlock it ; resize the icon record to the proper size MOVE.L A2,D0 ; get size of record SUB.L A3,D0 ; (everything before color table) MOVE.L A4,A0 ; get handle to record JSR RSetHSize ; and strip off the extra data MOVE.L A4,RESULT(A6) ; update function result NoGetNew MOVEM.L (SP)+,D3-D4/A2-A4 ; restore working registers UNLINK PARAMSIZE,'GETCICON' ; strip params and return ENDPROC PlotCIcon PROC EXPORT IMPORT PortToMap,copyCIcon ;------------------------------------------------------------- ; ; PROCEDURE PlotCIcon(theRect: Rect; cIcon: cIconHandle); ; PARAMSIZE EQU 8 theRect EQU PARAMSIZE+8-4 ; rectangle cIcon EQU theRect-4 saveFore EQU -6 ; saved fgColor <27May87 EHB> saveBack EQU saveFore-6 ; saved bkColor <27May87 EHB> DSTPIX EQU saveBack-(PMREC+CTREC+20) ;PIXMAP+COLOR TABLE <27May87 EHB> globalRect EQU DSTPIX-8 ;global version of theRect DstRectRgn EQU globalRect-10 ;data for rect region DstRgnPtr EQU DstRectRgn-4 ;pointer to above VARSIZE EQU DstRgnPtr LINK A6,#VARSIZE ; build stack frame MOVEM.L D3/A2-A4,-(SP) ; preserve work registers PEA saveFore(A6) ; save it here <27May87 EHB> _GetForeColor ; save fgColor <27May87 EHB> PEA saveBack(A6) ; save it here <27May87 EHB> _GetBackColor ; save bkColor <27May87 EHB> MOVEQ #BlackColor,D0 ; get black <27May87 EHB> MOVE.L D0,-(SP) ; push black <27May87 EHB> _ForeColor ; set fg to black <27May87 EHB> MOVEQ #WhiteColor,D0 ; get white <27May87 EHB> MOVE.L D0,-(SP) ; push white <27May87 EHB> _BackColor ; set bk to white <27May87 EHB> MOVE.L cIcon(A6),A4 ; get the icon handle MOVE.L A4,A0 ; get handle in A0 _HLock ; and lock it down MOVE.L (A4),A3 ; keep pointer in A3 MOVE iconPMap+bounds+bottom(A3),D3 ; get bottom SUB iconPMap+bounds+top(A3),D3 ; calc height, keep in D3 ; set the base addresses of the pixMap, the mask, and the bitMap LEA iconRec(A3),A0 ; point to the mask data MOVE.L A0,iconMask+baseAddr(A3) ; and set the mask's base address MOVE iconMask+rowBytes(A3),D0 ; get mask's rowbytes MULU D3,D0 ; get size of mask ADD.L D0,A0 ; point to BitMap data MOVE.L A0,iconBMap+baseAddr(A3) ; and set the b/w icon's base address MOVE.L iconData(A3),A0 ; get the pixmap data handle _HLock MOVE.L (A0),A0 ; point at the data MOVE.L A0,iconPMap+baseAddr(A3) ; and set the color icon's base address MOVE.L grafGlobals(A5),A0 ; get quickDraw globals MOVE.L thePort(A0),A0 ; point to the grafport LEA PortBits(A0),A1 ; point to port's bit/pixMap LEA dstPix(A6),A2 ; point to local copy of pixMap _BitsToPix ; get dstBits/dstPix in dstPix,d2=screen flag move.w dstPix+pixelSize(A6),d0 ; preload dst depth in case not screen sub.l a0,a0 ; clear maskrgn in case not screen move.w d2,d3 ; remember screen flag in d3 beq.s NotScreen1 MOVE.L DEVICELIST,A2 ; GET FIRST ELEMENT IN DEVICE LIST MOVE.L (A2),A1 ; POINT TO DEVICE TST.L GDNEXTGD(A1) ; CHECK NEXT DEVICE beq.s NotScreen1 ; only 1 device so skip devloop ; Copy dst rect and convert to global coordinates move.l theRect(a6),a0 ; point at local rect lea globalRect(a6),a1 ; point at our copy move.l (a0)+,(a1)+ ; copy topleft move.l (a0),(a1)+ ; copy botRight move.l dstPix+bounds+top(a6),d0 ; get topleft move.w d0,d1 ; get left swap d0 ; get top sub.w d1,-(a1) ; convert right to global sub.w d0,-(a1) ; convert bottom to global sub.w d1,-(a1) ; convert left to global sub.w d0,-(a1) ; convert top to global lea DstRectRgn(a6),A0 move.l a0,DstRgnPtr(a6) ; build master pointer move.w #10,(a0) ; set region size NEXTGD MOVE.L (A2),A0 ; POINT TO DEVICE TST GDFLAGS(A0) ; IS IT ACTIVE? BPL.S SKIPGD ; =>NO, SKIP IT CLR.B -(SP) ; MAKE ROOM FOR BOOLEAN RESULT PEA globalRect(A6) ; PUSH SPECIFIED RECTANGLE PEA gdRect(A0) ; PUSH DEVICE'S RECTANGLE PEA dstRectRgn+rgnBBox(A6) ; PUSH DESTINATION RECT _SECTRECT ; IS THE RECT IN THE DEVICE TST.B (SP)+ ; TEST RESULT BEQ.S SKIPGD ; => NO INTERSECTION move.l dstPix+bounds+top(a6),d0 ; get topleft move.w d0,d1 ; get left swap d0 ; get top lea dstRectRgn+rgnBBox(a6),a0 ; point to rect add.w d0,(a0)+ ; convert top to local coords add.w d1,(a0)+ ; convert left to local coords add.w d0,(a0)+ ; convert bottom to local coords add.w d1,(a0) ; convert right to local coords MOVE.L (A2),A0 ; POINT TO DEVICE MOVE.L GDPMAP(A0),A0 ; GET PIXMAP MOVE.L (A0),A0 ; POINT TO PIXMAP MOVE PIXELSIZE(A0),D0 ; GET PIXEL DEPTH lea DstRgnPtr(a6),a0 ; clip to intersection with this device NotScreen1 LEA iconBMap(A3),A1 ; assume we're using one-bit icon TST rowBytes(A1) ; is there a one bit icon? BEQ.S noOneBit ; => no, use color one CMP #2,d0 ; two bits per pixel or less? BLE.S OneBit ; => yes, use one-bit icon noOneBit MOVE.L A3,A1 ; else get icon's pixMap OneBit MOVE.L A1,-(SP) ; push srcBits PEA iconMask(A3) ; push maskBits PEA dstPix(A6) ; push dstBits PEA bounds(A1) ; push srcRect PEA iconMask+bounds(A3) ; push maskRect MOVE.L theRect(A6),-(SP) ; push dstRect bsr CopyCIcon ; call copyMask clipped to rgn in A0 tst.w d3 ; check screen flag in d3 beq.s NotScreen2 ; break out of devloop if not screen SKIPGD MOVE.L (A2),A0 ; GET DEVICE MOVE.L GDNEXTGD(A0),D0 ; GET NEXT DEVICE MOVE.L D0,A2 ; SAVE IT BNE.S NEXTGD NotScreen2 MOVE.L iconData(A3),A0 ; get handle to color icon data _HUnlock ; and unlock it MOVE.L A4,A0 ; get handle in A0 _HUnLock ; and unlock it PEA saveFore(A6) ; point to saved fg <27May87 EHB> _RGBForeColor ; and restore it <27May87 EHB> PEA saveBack(A6) ; point to saved bk <27May87 EHB> _RGBBackColor ; and restore it <27May87 EHB> MOVEM.L (SP)+,D3/A2-A4 ; restore working registers UNLINK PARAMSIZE,'PLOTCICO' ; strip params and return DisposCIcon PROC EXPORT ;------------------------------------------------------------- ; ; FUNCTION DisposCIcon(cIcon: cIconHandle); ; ; DisposCIcon disposes of a color icon ; MOVE.L (SP)+,A1 ; get return address MOVE.L (SP),A0 ; get icon handle MOVE.L (A0),A0 ; point to icon MOVE.L IconPMap+pmTable(A0),-(SP) ; save color table handle MOVE.L IconData(A0),A0 ; get data handle _DisposHandle ; dispose data handle MOVE.L (SP)+,A0 ; get color table handle _DisposHandle ; dispose color table handle MOVE.L (SP)+,A0 ; get icon _DisposHandle ; dispose icon JMP (A1) ; and return ENDPROC