	LOAD	'Macros.dump'
	INCLUDE 'Pict.equ'
	INCLUDE	'Driver.equ'

	IMPORT	Q_ChangePictSize
	IMPORT	Q_Copy2
	IMPORT	Q_JustRect
	IMPORT	D_NeedHandle
	IMPORT	Q_Nop
	IMPORT	D_ZeroBlock
	IMPORT	Q_addbytes
	IMPORT	Q_center
	IMPORT	count
	IMPORT	Q_half
	IMPORT	newptr
	IMPORT	oldptr
	IMPORT	Q_pictSCB
	IMPORT	Q_picterr
	IMPORT	Q_printsquare
	IMPORT	Q_square
	import	temp
	IMPORT	thepoint
	IMPORT	what

	ENTRY	Q_FlipHRgn
	ENTRY	Q_FlipVRgn
	ENTRY	MangleRgn
	ENTRY	Q_RotLRgn
	ENTRY	Q_RotRRgn
	ENTRY	Q_flipdx
	ENTRY	flipdy
****************************************************************
*															  ;
*			 Q_Region flipping and rotating routines			;
*______________________________________________________________*
*															  ;
*	Q_MangleRegion(rgn:l,what:w,prerec:l):newrgn:l			  ;
*______________________________________________________________*
*															  ;
*	NOTE!  The Apple Q_Region data structure is proprietary,	;
*	and as such, this code may legally belong to Apple, if	;
*	they ask for it.										  ;
*															  ;
****************************************************************

*--------------------------------------------------------------*
*	   Copy a Q_Region picture opcode and mangle its data	   ;
*--------------------------------------------------------------*
Q_Region	PROC		EXPORT
			;Using	Q_PictData
		EXPORT	Q_JustRgn

		jsl	  Q_Nop			 ; copy the opcode

Q_JustRgn		;		

		cmpw	 [<oldptr],#10
		jeq	  nomore

		spacelong				; get a handle for the Q_Region
		pushword #0			  ; high word of size
		pushword [<oldptr]
		pushword #$8000		  ; X_Locked!
		jsl	  D_NeedHandle
		sta	  Q_picterr
		pulllong <thepoint
		jcs	  abort

		movelong [<thepoint],<temp

		pushlong <oldptr		 ; copy the Q_Region data into the handle
		pushlong <temp
		pushword #0
		pushword [<oldptr]
		_BlockMove

		moveword [<oldptr],<count
		addwl	<count,<oldptr

		cmpw	 <what,#Q_rotr
		blt	  doit
		lda	  Q_pictSCB
		beq	  doit

		pushlong <thepoint
		pushlong #Q_square
		pushlong #Q_half
		_MapRgn

doit	spacelong
		pushlong <thepoint	   ; mangle the Q_Region!
		jtl	  MangleRgn,<what
		sta	  Q_picterr

		pushlong <thepoint	   ; out with the old
		_DisposeHandle
		pulllong <thepoint	   ; ...in with the D_New

		cmpw	 Q_picterr,#1
		jcs	  abort

		cmpw	 <what,#Q_rotr
		blt	  didit
		lda	  Q_pictSCB
		beq	  didit

		pushlong <thepoint
		pushlong #Q_half
		pushlong #Q_square
		_MapRgn

didit	pushlong <thepoint
		_Hlock

		movelong [<thepoint],<temp

		cmpw	 [<temp],<count  ; did the Q_Region size change?
		beq	  samesize

		stz	  Q_addbytes+2
		subword  [<temp],<count,Q_addbytes
		bpl	  changeit
		dec	  Q_addbytes+2

changeit	jsl	  Q_ChangePictSize  ; if so, make room in the pict
		bcs	  abort
		movelong [<thepoint],<temp	  ; (restore temp)
		moveword [<temp],<count

samesize	pushlong <temp		   ; copy the D_New Q_Region into the pict
		pushlong <newptr
		pushword #0
		pushword <count
		_BlockMove

		addwl	<count,<newptr

		pushlong <thepoint
		_DisposeHandle

		bra	  exit

nomore	jsl	  Q_Copy2		   ; copy the size
		jsl	  Q_JustRect		; mangle the bounds

exit	clc
abort	rtl

		ENDP

****************************************************************
*
*   Q_MangleRegion(rgn:l,what:w,prrec:l):newrgn:l -- mangle a Q_Region
*
****************************************************************
Q_MangleRegion	PROC		EXPORT
			;Using	Q_PictData
		EXPORT	MangleRgn

		input	oldrgn:l,how:w,prrec:l
		output   newrgn:l
		local	rptr:l,prptr:l

		begin	+b

		cmpw	 how,#2
		blt	  norot1

		movelong [prrec],prptr
		movelong [prptr]:#4,Q_printsquare+4

		pushlong oldrgn
		pushlong #Q_printsquare
		pushlong #Q_square
		_MapRgn

norot1	pushlong oldrgn
		_Hlock

		movelong [oldrgn],rptr

		addword  [rptr]:#2,[rptr]:#6,Q_center	 ; get the 'Q_center' of
		addword  [rptr]:#4,[rptr]:#8,Q_center+2   ; the old Q_Region

norot	spacelong
		pushlong oldrgn
		jtl	  MangleRgn,how
		sta	  Q_picterr
		pulllong newrgn

		pushlong oldrgn
		_HunLock

		cmpw	 how,#2
		blt	  exit

		pushlong newrgn
		pushlong #Q_square
		pushlong #Q_printsquare
		_MapRgn

exit	return   Q_picterr

MangleRgn		;		

	DC.L	Q_FlipHRgn
	DC.L	Q_FlipVRgn
	DC.L	Q_RotRRgn
	DC.L	Q_RotLRgn

		ENDP

****************************************************************
*
*   Q_FlipHRgn -- flip a Q_Region horizontally about 'Q_center'
*
****************************************************************
Q_FlipHRgn	PROC		EXPORT
			;Using	Q_PictData

		input	oldrgn:l
		output   newrgn:l
		local	oldrptr:l,newrptr:l
		local	roff1:w,roff2:w,xoff:w,doff:w

		begin

		pushlong oldrgn
		_Hlock

		movelong [oldrgn],oldrptr

		spacelong
		pushword #0
		pushword [oldrptr]
		pushword #$8000
		jsl	  D_NeedHandle
		sta	  Q_picterr
		pulllong newrgn
		jcs	  exit

		movelong [newrgn],newrptr

		movelong [oldrptr],[newrptr]
		moveword [oldrptr]:#6,[newrptr]:#6
		subword  Q_center+2,[oldrptr]:#4,[newrptr]:#8
		subword  Q_center+2,[oldrptr]:#8,[newrptr]:#4

		cmpw	 [oldrptr],#10   ; rectangular Q_Region?
		jeq	  exit			; if so, I'm done!

		ldy	  #10
		lda	  [oldrptr],y
*--------------------------------------------------------------*
*			  Loop through the rows of the Q_Region			 ;
*--------------------------------------------------------------*
rloop	sta	  [newrptr],y	 ; copy y coord

		sty	  roff1		   ; y = offset to beginning of row
		sty	  doff
		lda	  #$3fff
endloop	iny
		iny
		cmp	  [oldrptr],y
		bne	  endloop

		sty	  roff2		   ; y = offset to the end of the row
		sty	  xoff

		sta	  [newrptr],y	 ; copy end marker

xloop	dec	  xoff
		dec	  xoff
		cmpw	 xoff,roff1
		beq	  xdone
		inc	  doff
		inc	  doff
		subword  Q_center+2,[oldrptr]:xoff,[newrptr]:doff
		dec	  xoff
		dec	  xoff
		inc	  doff
		inc	  doff
		subword  Q_center+2,[oldrptr]:xoff,[newrptr]:doff
		bra	  xloop

xdone	ldy	  roff2
		iny
		iny
		lda	  [oldrptr],y
		cmp	  #$3fff		  ; end of the Q_Region?
		bne	  rloop

		sta	  [newrptr],y	 ; copy last end marker

		pushlong newrgn		  ; D_Ignore errors
		_HunLock

exit	pushlong oldrgn		  ; that's all!
		_HunLock

		return   Q_picterr

		ENDP

****************************************************************
*
*   Q_FlipVRgn -- flip a Q_Region vertically about 'Q_center'
*
****************************************************************
Q_FlipVRgn	PROC		EXPORT
			;Using	Q_PictData

		input	oldrgn:l
		output   newrgn:l
		local	oldrptr:l,newrptr:l
		local	roff:w,noff:w,xoff:w

		begin

		pushlong oldrgn
		_Hlock

		movelong [oldrgn],oldrptr

		spacelong
		pushword #0
		pushword [oldrptr]
		pushword #$8000
		jsl	  D_NeedHandle
		sta	  Q_picterr
		pulllong newrgn
		jcs	  exit

		movelong [newrgn],newrptr

		moveword [oldrptr],[newrptr]
		moveword [oldrptr]:#4,[newrptr]:#4
		moveword [oldrptr]:#8,[newrptr]:#8
		subword  Q_center,[oldrptr]:#2,[newrptr]:#6
		subword  Q_center,[oldrptr]:#6,[newrptr]:#2

		cmpw	 [oldrptr],#10   ; rectangular Q_Region?
		jeq	  exit			; if so, I'm done!

		moveword #8,noff
		lda	  [oldrptr]	   ; start at the end of the old
		sec
		sbc	  #4			  ; (skip last two end markers)
		tay
*--------------------------------------------------------------*
*			  Loop through the rows of the Q_Region			 ;
*--------------------------------------------------------------*
rloop	dey
		dey
		cpy	  #8
		beq	  gotit
		cmpw	 [oldrptr]:y,#$3fff
		bne	  rloop
gotit	sty	  roff			; y = end of previous row (if any)

		iny
		iny
		sty	  xoff
		inc	  noff
		inc	  noff
		subword  Q_center,[oldrptr]:xoff,[newrptr]:noff   ; fix y coord

xloop	inc	  xoff
		inc	  xoff
		inc	  noff
		inc	  noff
		moveword [oldrptr]:xoff,[newrptr]:noff
		cmp	  #$3fff		  ; stop after copying end marker
		beq	  xdone
		inc	  xoff
		inc	  xoff
		inc	  noff
		inc	  noff
		moveword [oldrptr]:xoff,[newrptr]:noff
		bra	  xloop

xdone	ldy	  roff
		cpy	  #8
		bne	  rloop

		inc	  noff			; put in the end of Q_Region marker
		inc	  noff
		moveword #$3fff,[newrptr]:noff

		pushlong newrgn
		_HunLock

exit	pushlong oldrgn		  ; That's it!
		_HunLock

		return   Q_picterr

		ENDP

****************************************************************
*
*   Q_FlipDRgn -- flip a Q_Region diagonally -- used by RotXRgn
*
****************************************************************
Q_FlipDRgn	PROC		EXPORT
			;Using	Q_PictData
		EXPORT	flipdy
		EXPORT	Q_flipdx

		input	oldrgn:l
		output   newrgn:l
		local	oldrptr:l,newrptr:l,offset:w
		local	tabhnd:l,tabptr:l,taboff:w,tabstart:w
		local	tabsize:w,rgnsize:w,xcoord:w

		begin

		pushlong oldrgn
		_Hlock

		movelong [oldrgn],oldrptr

		cmpw	 [oldrptr],#10		  ; rectangular Q_Region?
		bne	  notrect

		moveword #10,rgnsize
		jsr	  preprgn

		pushlong newrgn
		_HUnLock

		brl	  exit
*--------------------------------------------------------------*
*		   Allocate and initialize the offset table		   ;
*--------------------------------------------------------------*
notrect	moveword [oldrptr]:#4,tabstart
		subword  [oldrptr]:#8,tabstart,tabsize
		inc	  tabsize
		asl	  tabsize

		spacelong
		pushword #0
		pushword tabsize
		pushword #$8000
		jsl	  D_NeedHandle
		sta	  Q_picterr
		pulllong tabhnd
		jcs	  exit

		movelong [tabhnd],tabptr

		pushlong tabptr
		pushword tabsize
		jsl	  D_ZeroBlock
*--------------------------------------------------------------*
*		   Count the occurences of each x coordinate		  ;
*--------------------------------------------------------------*
		ldy	  #8
crloop	iny
		iny
		lda	  [oldrptr],y
		cmp	  #$3fff		  ; end of the Q_Region?
		beq	  gotcount
cxloop	iny
		iny
		lda	  [oldrptr],y
		cmp	  #$3fff		  ; end of the Q_Line?
		beq	  crloop
		tyx
		sec
		sbc	  tabstart		; adjust to 0
		asl	  a			   ; double
		tay
		lda	  [tabptr],y	  ; increment the table entry
		inc	  a
		sta	  [tabptr],y
		txy
		bra	  cxloop
*--------------------------------------------------------------*
*		 Convert counts to offsets into the D_New Q_Region		;
*--------------------------------------------------------------*
gotcount	ldy	  #0
		moveword #10,offset	  ; (I want offsets to starts of rows)

convloop	lda	  [tabptr],y
		beq	  convnext		; (except zeros)

		inc	  a			   ; add space for y-coord
		inc	  a			   ; add space for end marker
		asl	  a			   ; convert to words
		clc
		adc	  offset
		tax					  ; wait....
		lda	  offset
		sta	  [tabptr],y	  ; store the old offset
		stx	  offset		  ; and keep the D_New one

convnext	iny
		iny
		cpy	  tabsize
		blt	  convloop

		addword  offset,#2,rgnsize
*--------------------------------------------------------------*
*	 Allocate the Q_Region and do some preliminary mangling	 ;
*--------------------------------------------------------------*
		jsr	  preprgn
		jcs	  exit2
*--------------------------------------------------------------*
*			D_Write out y coordinates and endmarkers			;
*--------------------------------------------------------------*
		stz	  taboff
		ldy	  #10
		bra	  wstart

wloop	ldy	  taboff		  ; is this a row?
		lda	  [tabptr],y
		beq	  wnext

		tay
		dey
		dey
		lda	  #$3fff		  ; D_Write the preceding end marker
		sta	  [newrptr],y
		iny
		iny

wstart	lda	  taboff		  ; D_Write the y-coordinate
		lsr	  a			   ; convert from words
		clc
		adc	  tabstart
		jsr	  Q_flipdx
		sta	  [newrptr],y	 ; (y = offset to row beginning)

wnext	inc	  taboff
		inc	  taboff
		cmpw	 taboff,tabsize
		bne	  wloop

		ldy	  rgnsize
		lda	  #$3fff		  ; D_Write last end markers
		dey
		dey
		sta	  [newrptr],y
		dey
		dey
		sta	  [newrptr],y
*--------------------------------------------------------------*
* Loop through the Q_Region, mangling y-coords into D_New x-coords ;
*--------------------------------------------------------------*
		ldy	  #8
mrloop	iny
		iny
		lda	  [oldrptr],y
		cmp	  #$3fff		  ; end of the Q_Region?
		beq	  done

		jsr	  flipdy
		sta	  xcoord

mxloop	iny
		iny
		lda	  [oldrptr],y
		cmp	  #$3fff		  ; end of the Q_Line?
		beq	  mrloop

		sty	  offset

		sec
		sbc	  tabstart		; adjust to 0
		asl	  a
		tay
		lda	  [tabptr],y	  ; get offset from table
		inc	  a			   ; increment it
		inc	  a
		sta	  [tabptr],y
		tay
		lda	  xcoord
		sta	  [newrptr],y	 ; store x coord in D_New Q_Region

		ldy	  offset
		bra	  mxloop
*--------------------------------------------------------------*
*					 Clean up and go home					 ;
*--------------------------------------------------------------*
done	pushlong newrgn		  ; D_Ignore errors
		_HunLock

exit2	pushlong tabhnd
		_DisposeHandle

exit	pushlong oldrgn		  ; That's it!
		_HunLock

		return   Q_picterr
*--------------------------------------------------------------*
*				   Q_Point flipping routines.				   ;
*--------------------------------------------------------------*
flipdy		;		

		sta	  Q_Point
		lda	  Q_center+2		; R-rotate the Q_Point around Q_center
		and	  #1			  ; <adjust for creep>
		clc
		adc	  Q_center+2		; pt.x <= pt.y - Q_center.y + Q_center.x
		sec
		sbc	  Q_center
		sta	  temp			; (divide by 2, preserving
		asl	  temp			 ;  the sign)
		ror	  a			   ;
		clc
		adc	  Q_Point
		rts

Q_flipdx		;		

		sta	  Q_Point
		lda	  Q_center		  ; pt.y <= pt.x - Q_center.x + Q_center.y
		and	  #1			  ; <adjust for creep>
		clc
		adc	  Q_center
		sec
		sbc	  Q_center+2
		sta	  temp			; (divide by 2, preserving
		asl	  temp			 ; the sign)
		ror	  a			   ;
		clc
		adc	  Q_Point
		rts

*--------------------------------------------------------------*
preprgn	spacelong
		pushword #0
		pushword rgnsize
		pushword #$8000
		jsl	  D_NeedHandle
		sta	  Q_picterr
		pulllong newrgn
		jcs	  prepped

		movelong [newrgn],newrptr

		moveword rgnsize,[newrptr]	  ; copy the size

		ldy	  #2			  ; mangle the bounding Q_Rect
		lda	  [oldrptr],y
		jsr	  flipdy
		ldy	  #4
		sta	  [newrptr],y

		ldy	  #4
		lda	  [oldrptr],y
		jsr	  Q_flipdx
		ldy	  #2
		sta	  [newrptr],y

		ldy	  #6
		lda	  [oldrptr],y
		jsr	  flipdy
		ldy	  #8
		sta	  [newrptr],y

		ldy	  #8
		lda	  [oldrptr],y
		jsr	  Q_flipdx
		ldy	  #6
		sta	  [newrptr],y

		clc					  ; SIGH
prepped	rts

Q_Point		DS.B 2
temp		DS.B 2

		ENDP

****************************************************************
*
*   Q_RotRRgn -- rotate a Q_Region clockwise
*
****************************************************************
Q_RotRRgn	PROC		EXPORT
			;Using	Q_PictData

		input	oldrgn:l
		output   newrgn:l
		local	tmprgn:l

		begin

		spacelong
		pushlong oldrgn
		jsl	  Q_FlipDRgn
		sta	  Q_picterr
		pulllong tmpRgn
		bcs	  notmp

		spacelong
		pushlong tmprgn
		jsl	  Q_FlipHRgn
		sta	  Q_picterr
		pulllong newrgn

		pushlong tmprgn
		_DisposeHandle

notmp	return   Q_picterr

		ENDP

****************************************************************
*
*   Q_RotLRgn -- rotate a Q_Region anticlockwise
*
****************************************************************
Q_RotLRgn	PROC		EXPORT
			;Using	Q_PictData

		input	oldrgn:l
		output   newrgn:l
		local	tmprgn:l

		begin

		spacelong
		pushlong oldrgn
		jsl	  Q_FlipHRgn
		sta	  Q_picterr
		pulllong tmpRgn
		bcs	  notmp

		spacelong
		pushlong tmprgn
		jsl	  Q_FlipDRgn
		sta	  Q_picterr
		pulllong newrgn

		pushlong tmprgn
		_DisposeHandle

notmp	return   Q_picterr

		ENDP
		END

