; Copyright 1996 Acorn Computers Ltd ; ; Licensed under the Apache License, Version 2.0 (the "License"); ; you may not use this file except in compliance with the License. ; You may obtain a copy of the License at ; ; http://www.apache.org/licenses/LICENSE-2.0 ; ; Unless required by applicable law or agreed to in writing, software ; distributed under the License is distributed on an "AS IS" BASIS, ; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ; See the License for the specific language governing permissions and ; limitations under the License. ; ; > $.Source.VduGrafC ; ; ARTHUR OPERATING SYSTEM - Vdu Drivers ; ======================= ; ; Vdu driver code - Ellipse outline & fill ; ; Author R C Manby ; Date 29.9.86 ; ; ; ; ;------------------------------------------------------------------------------ ; ; EllipseOutline ; ============== ; ; On entry, OldCs is centre of the ellipse ; ICursor is a point giving the width of the ellipse ; NewPt is the highest/lowest point on the ellipse ; ; On exit, R0..R11 corrupt ; EllipseOutline SaveRetAdr BL GenEllParm B EllipseOut20 EllipseOut10 BL AdvEllParm EllipseOut20 ; Registers hold ; R4 , R5 , R6 , R7 , R8 , R9 , R10 ; ellY,prevL,prevR,thisL,thisR,nextL,nextR MOV R0,R7 ;Left line runs from thisL rightwards MOV R1,R4 Greatest R3,R5,R9 SUB R3,R3,#1 Greatest R3,R3,R7 ; to max(thisL, max(prevL-1,nextL-1)) MOV R2,R8 ;Right line runs from thisR leftwards Least R4,R6,R10 ADD R4,R4,#1 Least R4,R4,R8 ; to min(thisR, min(prevR+1,nextR+1)) BL EllDoubleHLine ;Any overlap handled by EllDoubleHLine LDR R0,[WsPtr,#EllBlkSliceCnt] CMP R0,#0 BGE EllipseOut10 B EllipseFi30 ;Use common code with ellipse fill for ; last scanline ; ; ; ; ;------------------------------------------------------------------------------ ; ; EllipseFill ; =========== ; ; On entry, OldCs is centre of the ellipse ; ICursor is a point giving the width of the ellipse ; NewPt is the highest/lowest point on the ellipse ; ; On exit, R0..R11 corrupt ; EllipseFill SaveRetAdr BL GenEllParm B EllipseFi20 EllipseFi10 BL AdvEllParm EllipseFi20 ; Registers hold ; R4 , R5 , R6 , R7 , R8 , R9 , R10 ; ellY,prevL,prevR,thisL,thisR,nextL,nextR MOV R0,R7 ;Draw slice thisL -> thisR MOV R1,R4 MOV R2,R8 BL EllHLine LDR R0,[WsPtr,#EllBlkSliceCnt] CMP R0,#0 BGE EllipseFi10 EllipseFi30 LDR R0,[WsPtr,#EllNextL] ;Last slice nextL -> nextR LDR R1,[WsPtr,#EllBlkEllY] ADD R1,R1,#1 LDR R2,[WsPtr,#EllNextR] BL EllHLine Return ; ; ; ; EllHLine - Draw a slice then reflect around ellipse origin ; ======== ; ; On entry, R0 (X) - Left point of line ; R1 (Y) - Y ordinate of line ; R2 (X) - Right point of line ; ; On exit, R0..R11 corrupt ; EllHLine SaveRetAdr LDR R3,[WsPtr,#OldCsX] ;All points relative to OldCs LDR R4,[WsPtr,#OldCsY] ADD R11,WsPtr,#EllHLineWs ;Save points given plus centre of STMIA R11,{R0-R4} ; ellipse for later use ADD R0,R3,R0 ;OldCsX + LeftX ADD R1,R4,R1 ;OldCsY + Y ADD R2,R3,R2 ;OldCsX + RightX BL NewHLine ;Draw top slice ADD R11,WsPtr,#EllHLineWs LDMIA R11,{R3-R7} CMP R4,#0 ;If EllY = 0 Return EQ ; then quit to prevent double plotting ; else reflect around ellipse origin SUB R0,R6,R5 ;OldCsX - RightY SUB R1,R7,R4 ;OldCsY - Y SUB R2,R6,R3 ;OldCsX - LeftY BL NewHLine Return ; ; ; ; EllDoubleHLine ; ============== ; ; On entry, R0 (X) - Left most point ; R1 (Y) - y ordinate of line ; R2 (X) - Right most point ; R3 (X) - end of left most line ; R4 (X) - start of right most line ; EllDoubleHLine CMP R3,R4 ;If end of left line overlaps ; start of right BGE EllHLine ;then draw and reflect R0->R2 ;else SaveRetAdr ADD R11,WsPtr,#EllDoubleHLineWs STMIA R11,{R0-R4} MOV R2,R3 ;Draw and reflect R0->R3 BL EllHLine ADD R11,WsPtr,#EllDoubleHLineWs LDMIA R11,{R0-R4} MOV R0,R4 BL EllHLine ;Draw and reflect R4->R2 Return ; ; ; ;------------------------------------------------------------------------------ ; ; GenEllParm - Generate a control block for an ellipse ; ========== ; ; On entry, OldCs is centre of the ellipse ; ICursor is a point giving the width of the ellipse ; NewPt is the highest/lowest point on the ellipse ; ; On exit, EllBlk holds the ellipse parameter block ; ; EllThisL..EllNextR setup ; ; R4 - EllY ; R5, R6 - prevL,prevR ; R7, R8 - thisL,thisR ; R9, R10 - nextL,nextR ; ; ; Format of ellipse parameter block ; ; Var R0 - SliceCnt count of slices remaining ; R1 - EllYSqr square of current slice height ; R2 - OddNo used to give next EllYSqr value ; R3 - XOffset [bb.bb] offset in X dirn along shear line ; R4 - EllY ; Const R5 - ShearX [bb.bb] shear factor per scanline ; R6 - SliceX [0bb.b] axis ratio ; R7 - MaxYSqr [bbbb] ; ; ; GenEllParm SaveRetAdr ADD R11,WsPtr,#OldCsX LDMIA R11,{R0,R1, R2,R3, R4,R5} ;OldCs, ICursor, NewPt SUBS R6,R2,R0 RSBLT R6,R6,#0 ;R6 := ABS(width of slice) ;R6 is sliceX (ie maxwidth) SUBS R7,R5,R1 MOV R8,R7 RSBLT R7,R7,#0 ;R7 := ABS(height of ellipse) ; ; Leave R0,R1,R2 intact upto here ; R6 is ABS(width of slice) BEQ EllipseZeroHeight ;If NewPtY=OldCsY draw a single line SUBS R5,R4,R0 EOR R8,R8,R5 RSBLT R5,R5,#0 ;R5 := ABS(shear at top of ellipse) ; ; R5 holds shear in x dirn ; R6 holds width ; R7 holds height (also shearY) ; R8 sign bit is slope of shearline ; MOV R0,R7 ;Setup SliceCnt MOV R9,R5,LSL #16 DivRem R5,R9,R7,R10,norem ;R5 := totalshear/ellipseheight CMP R8,#0 RSBLT R5,R5,#0 ;Correct for negative slope MOV R7,R0 ;Div R6,R6,R0 using R7,R9,R10 MOV R9,R6,LSL #8 DivRem R6,R9,R7,R10,norem ;R6 := slicewidth/ellipseheight ; R5 holds shear per scanline ; R6 ratio of ellipse axis MUL R7,R0,R0 ;MaxYSqr MOV R1,#0 ;EllYSqr MOV R2,#1 ;Oddno MOV R3,#0 ;XOffset MOV R4,#-2 ;EllY ADD R11,WsPtr,#EllBlk STMIA R11,{R0-R7} BL AdvEllP20 ;Start by calculating first two slices STR R9,[WsPtr,#EllThisL] ;Limits passed back in R9,R10 STR R10,[WsPtr,#EllThisR] BL AdvEllP20 ADD R11,WsPtr,#EllThisL LDMIA R11,{R7,R8} RSB R5,R10,#0 ;prevL := -nextR RSB R6,R9,#0 ;prevR := -nextL ; Stretch slice if disconnected Least R7,R7,R6 ; thisL := min(thisL,prevR) Least R7,R7,R10 ; thisL := min(thisL,nextR) Greatest R8,R8,R5 ; thisR := max(thisR,prevL) Greatest R8,R8,R9 ; thisR := max(thisR,nextL) STMIA R11,{R7,R8,R9,R10} Return ; On return, registers hold ; R4 , R5 , R6 , R7 , R8 , R9 , R10 ; ellY,prevL,prevR,thisL,thisR,nextL,nextR ; ; ; ; EllipseZeroHeight - Draw a single line, no pips ; ================= ; ; On entry, R0 (X), R1 (Y) holds centre of ellipse ; R6 is ABS(width of slice/2) ; EllipseZeroHeight ADD R2,R0,R6 SUB R0,R0,R6 Pull Link ;Return address into ellipse code Pull Link ;Return address to whoever called ; ellipses B NewHLine ;Sorted coords ;This will return to whoever called ; the ellipse code ; ; ; ;------------------------------------------------------------------------------ ; ; AdvEllParm ; ========== ; ; On entry, R11 points to ellipse parameter block ; ; On exit, EllBlk, EllThisL..EllNextR updated ; ; R4 - EllY ; R5, R6 - prevL,prevR ; R7, R8 - thisL,thisR ; R9, R10 - nextL,nextR ; ; ; Format of ellipse parameter block ; ; Var R0 - SliceCnt count of slices remaining ; R1 - EllYSqr square of current slice height ; R2 - OddNo used to give next EllYSqr value ; R3 - XOffset [bb.bb] offset in X dirn along shear line ; R4 - EllY ; Const R5 - ShearX [bb.bb] shear factor per scanline ; R6 - SliceX [0bb.b] axis ratio ; R7 - MaxYSqr [bbbb] ; ; ; AdvEllParm SaveRetAdr BL AdvEllP20 ;Advance scanline ; On return, registers hold ; R4 , R9 , R10 ; ellY, nextL,nextR ;Shuffle points ;R9/R10 -> nextLR ;nextLR -> thisLR - stretch if disconnected ;thisLR -> prevLR ADD R11,WsPtr,#EllThisL LDMIA R11,{R5,R6, R7,R8} ; Stretch slice if disconnected Greatest R8,R8,R9 ; thisR := max(thisR,nextL) Least R7,R7,R10 ; thisL := min(thisL,nextR) STMIA R11,{R7,R8, R9,R10} Return ; R4 , R5 , R6 , R7 , R8 , R9 , R10 ; ellY,prevL,prevR,thisL,thisR,nextL,nextR ; ; ; ; ; ; ; AdvEllP20 SaveRetAdr ADD R11,WsPtr,#EllBlk LDMIA R11,{R0-R7} ;Load ellipse parm block SUB R7,R7,R1 ;Sqroot(MaxYSqr-EllYSqr) MOV R11,#24 ;Use 24 instead of 16 iterations in the BL SquareRootAlt ; SquareRoot routine, gives result [0bb.b] ;Mult by axis ratio MOV R7,R6 ; [0bb.b] * [0bb.b] MUL R9,R7,R8 ; Result in R9 is [bb.bb] ADD R10,R3,R9 ;NextR [bb.bb] ADD R10,R10,#&8000 MOV R10,R10,ASR #16 ; [00bb] SUB R9,R3,R9 ;NextL [bb.bb] ADD R9,R9,#&8000 MOV R9,R9,ASR #16 ; [00bb] ADD R1,R1,R2 ;New value of EllYSqr by adding oddno ADD R2,R2,#2 ;Next oddno in sequence ADD R3,R3,R5 ;XOffSet for next scanline SUB R0,R0,#1 ;Decrement count of slices left ADD R4,R4,#1 ;Increment EllY ADD R11,WsPtr,#EllBlk STMIA R11,{R0,R1,R2,R3,R4} ;Save updated section Return ; R4 , R9 , R10 ; ellY, nextL,nextR ; ; ; ;------------------------------------------------------------------------------ END