mac-rom/QuickDraw/Patterns.a

2426 lines
86 KiB
Plaintext

;
; 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):
;
; <SM8> 9/12/93 SAM Changed all instances of _Translate24to32 to _rTranslate24to32
; so they can conditionalized out of the build.
; <SM7> 1/15/93 kc Change JSR to JMP to fix bug introduced in last checkin.
; <SM6> 1/13/93 kc Change BSR ot JSR to appease the Linker gods.
; <SM4> 8/18/92 CSS Update from Reality:
; <16> 8/18/92 SAH #1040323 <KON>: 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.
; <SM4> 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.
; <SM3> 6/11/92 stb <sm 6/9/92>stb Synch with QDciPatchROM.a; Added comments to
; PatExpand, PatConvert, DirectPixPat, MakeScaleTbl, GETCICON,
; COPYPIXPAT.
; <SM2> 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 <bal,
; too>
;
; 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
JMP 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 ; <C464>
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 <C954/08Nov87> DAF
MOVE.L D0,A1 ; get in A-reg <C954/08Nov87> DAF
MOVE.L (A1),D0 ; get pixPat pointer <C954/08Nov87> DAF
BEQ.S Done ; if NIL, then do nothing <C954/08Nov87> DAF
MOVE.L D0,A1 ; get in A-reg <C954/08Nov87> 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 <C954/08Nov87> 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, <sm 6/9/92>stb
; try looking in Pictures.a at PutPicPixPat. It was a come-from patch. <sm 6/9/92>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 <sm 6/9/92>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 <KON 11Oct90>
;
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 <sm 6/9/92>stb
; makes direct pixpats work for offscreen gWorlds. <sm 6/9/92>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 <BAL 09May88> @@@@
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 <sm 6/9/92>stb
;ÊIt makes direct pixpats work for offscreen gWorlds <sm 6/9/92>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), <sm 6/9/92>stb
;Êin case youÕre wondering where the line went <sm 6/9/92>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 <sm 6/9/92>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. <BAL 09May88> @@@@
;
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 <BAL 09May88> @@@@
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 <BAL/dvb 23Feb89>
;
; 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 <BAL 10Mar89>
btst #14,d3 ; are they palette references? <BAL 10Mar89>
bne brink ; yes call dave <BAL 10Mar89>
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 <BAL/dvb 23Feb89>
@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 <KON 28Apr90>
_Color2Index ; convert to index <BAL/dvb 23Feb89>
MOVE.L (SP)+,D0 ; get result
move.l D0,TBLOFST(SP,D3*4) ; put returned value in table <BAL 09May88> @@@@
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 <BAL/dvb 23Feb89>
@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 <KON 28Apr90>
_Color2Index ; convert to index <BAL/dvb 23Feb89>
MOVE.L (SP)+,D0 ; get result
move.l D0,TBLOFST(SP,D3*4) ; put returned value in table <BAL 09May88> @@@@
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 <KON 28Apr90
MOVE CTTable+rgb+red(A0,D4*8),rgb+red+12(SP) ; copy value, red <KON 28Apr90
MOVE.L CTTable+rgb+green(A0,D4*8),rgb+green+12(SP) ; copy green,blue <KON 28Apr90
CLR.L -(SP) ; make room for function result
PEA 4+12(SP) ; point to VAR ColorSpec <KON 28Apr90
_ColorThing2Index ; convert to index <BAL/dvb 23Feb89>
MOVE.L (SP)+,D0 ; get result
move.l D0,TBLOFST(SP,D3*4) ; put returned value in table <BAL 09May88> @@@@
DBRA D4,@nxtPEntry ; => repeat until done
clr.w QDErr ;remove any lingering error from ColorThing2Index
; <BAL 28Jan90>
; 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? <HACK> <BAL 09May88> @@@@
bne.s @findUnused ; if not, plow onward <BAL 09May88> @@@@
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 <BAL 09May88> @@@@
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 <sm 6/9/92>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 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 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
lea globalRect(a6),a1
move.l a1,d0
move.l a1,-(sp)
jsr ([$FC0]) ; _LocalToGlobal?
add #4,d0
move.l d0,-(sp)
jsr ([$FC0]) ; _LocalToGlobal?
lea.l DstRectRgn(a6),a0
move.l a0,DstRgnPtr(a6)
move #10,(a0)
NEXTGD move.l (a2),a0
tst $14(a0)
bpl.s SKIPGD
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
JSR ([$10A8]) ; SECTRECT -- IS THE RECT IN THE DEVICE
TST.B (SP)+ ; TEST RESULT
BEQ.S SKIPGD ; => NO INTERSECTION
lea dstRectRgn+rgnBBox(A6),a0
move.l a0,d0
move.l a0,-(sp)
jsr ([$FC4]) ; _GlobalToLocal?
add #4,d0
move.l d0,-(sp)
jsr ([$FC4]) ; _GlobalToLocal?
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