This repository has been archived by the owner on Nov 29, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
DrawArc.a
1086 lines (928 loc) · 46.2 KB
/
DrawArc.a
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
.INCLUDE GRAFTYPES.TEXT
;-----------------------------------------------------------
;
; --> DRAWARC.TEXT
;
; Routine to draw solid or hollow Ovals, RoundRects or Arcs.
;
;------------------------------------------------------
;
; OFFSETS IN AN OVAL STATE RECORD:
;
OVALTOP .EQU 0 ;INTEGER
OVALBOT .EQU OVALTOP+2 ;INTEGER
OVALY .EQU OVALBOT+2 ;INTEGER
RSQYSQ .EQU OVALY+2 ;LONGINT
SQUARE .EQU RSQYSQ+4 ;64 BIT LONGFIX
ODDNUM .EQU SQUARE+8 ;64 BIT LONGFIX
ODDBUMP .EQU ODDNUM+8 ;64 BIT LONGFIX
LEFTEDGE .EQU ODDBUMP+8 ;32 BIT FIXED POINT
RIGHTEDGE .EQU LEFTEDGE+4 ;32 BIT FIXED POINT
ONEHALF .EQU RIGHTEDGE+4 ;32 BIT FIXED POINT
OVALSIZE .EQU ONEHALF+4 ;SIZE OF AN OVALREC
.PROC DrawArc,8
.REF InitOval,BumpOval,SlopeFromAngle
.REF RSect,ShieldCursor,ShowCursor,TrimRect
.REF InitRgn,SeekRgn,PatExpand,ColorMap
.REF XorSlab,DrawSlab,SlabMode,FastSlabMode,MaskTab
;----------------------------------------------------------------
;
; PROCEDURE DrawArc(dstRect: Rect;
; hollow: BOOLEAN;
; ovalWidth,ovalHeight,mode: INTEGER;
; pat: Pattern;
; startAngle,arcAngle: INTEGER);
;
;------------------------------------------------
;
; A6 OFFSETS OF PARAMETERS AFTER LINK:
;
PARAMSIZE .EQU 20 ;TOTAL SIZE OF PARAMETERS
DSTRECT .EQU PARAMSIZE+8-4 ;ADDR OF RECT
HOLLOW .EQU DSTRECT-2 ;BOOLEAN
OVALWIDTH .EQU HOLLOW-2 ;INTEGER
OVALHEIGHT .EQU OVALWIDTH-2 ;INTEGER
MODE .EQU OVALHEIGHT-2 ;INTEGER
PAT .EQU MODE-4 ;LONG, ADDR OF PATTERN
STARTANGLE .EQU PAT-2 ;INTEGER
ARCANGLE .EQU STARTANGLE-2 ;INTEGER
;-------------------------------------------------
;
; A6 OFFSETS OF LOCAL VARIABLES AFTER LINK:
;
EXPAT .EQU -64 ;16 LONGS
MINRECT .EQU EXPAT-8 ;RECT
STATEA .EQU MINRECT-RGNREC ;RGN STATE RECORD
STATEB .EQU STATEA-RGNREC ;RGN STATE RECORD
STATEC .EQU STATEB-RGNREC ;RGN STATE RECORD
SAVESTK .EQU STATEC-4 ;LONG
RECTFLAG .EQU SAVESTK-2 ;WORD
MASKBUF .EQU RECTFLAG-4 ;LONG
BUFLEFT .EQU MASKBUF-2 ;WORD
BUFSIZE .EQU BUFLEFT-2 ;WORD
MODECASE .EQU BUFSIZE-4 ;LONG
DSTLEFT .EQU MODECASE-4 ;LONG
SAVEA5 .EQU DSTLEFT-4 ;LONG
PORT .EQU SAVEA5-4 ;LONG
FASTFLAG .EQU PORT-2 ;BYTE
TEMPRECT .EQU FASTFLAG-8 ;RECT
INNEROVAL .EQU TEMPRECT-OVALSIZE ;OVAL RECORD
OUTEROVAL .EQU INNEROVAL-OVALSIZE ;OVAL RECORD
SKIPTOP .EQU OUTEROVAL-2 ;WORD
SKIPBOT .EQU SKIPTOP-2 ;WORD
ARCFLAG .EQU SKIPBOT-1 ;BYTE FLAG
SKIPFLAG .EQU ARCFLAG-1 ;BYTE FLAG
STOPANGLE .EQU SKIPFLAG-2 ;INTEGER
MIDVERT .EQU STOPANGLE-2 ;INTEGER
MIDHORIZ .EQU MIDVERT-2 ;INTEGER
WIDTH .EQU MIDHORIZ-2 ;INTEGER
HEIGHT .EQU WIDTH-2 ;INTEGER
SLOPE1 .EQU HEIGHT-4 ;LONG, FIXED POINT
SLOPE2 .EQU SLOPE1-4 ;LONG, FIXED POINT
LINE1 .EQU SLOPE2-4 ;LONG, FIXED POINT
LINE2 .EQU LINE1-4 ;LONG, FIXED POINT
FLAG1 .EQU LINE2-2 ;WORD
FLAG2 .EQU FLAG1-2 ;WORD
OUTERLEFT .EQU FLAG2-2 ;WORD
OUTERRIGHT .EQU OUTERLEFT-2 ;WORD
INNERLEFT .EQU OUTERRIGHT-2 ;WORD
INNERRIGHT .EQU INNERLEFT-2 ;WORD
PATINDEX .EQU INNERRIGHT-2 ;WORD
VARSIZE .EQU PATINDEX ;SIZE OF LOCAL VARIABLES
LINK A6,#VARSIZE ;ALLOCATE LOCAL VARS
MOVEM.L D0-D7/A1-A5,-(SP) ;SAVE REGS
MOVE.L SP,SAVESTK(A6) ;REMEMBER STACK FOR LATER
MOVE.L A5,SAVEA5(A6) ;REMEMBER GLOBAL PTR
MOVE.L GRAFGLOBALS(A5),A0 ;POINT TO QUICKDRAW GLOBALS
MOVE.L THEPORT(A0),A3 ;GET CURRENT GRAFPORT
TST PNVIS(A3) ;IS PNVIS NEG ?
BLT GOHOME ;YES, QUIT
MOVE.L A3,PORT(A6) ;SAVE CURRENT GRAFPORT
;-------------------------------------------------------
;
; QUIT IF MODE NOT IN 8..15
;
MOVEQ #-8,D0 ;MASK TO KILL BOTTOM 3 BITS
AND MODE(A6),D0 ;GET ALL BUT 3 BITS OF MODE
CMP #8,D0 ;IS PEN MODE 8..15 ?
BNE GOHOME ;NO, QUIT
;----------------------------------------------------------------
;
; ADJUST MODE AND PATTERN IF COLOR FILTERING.
;
TST COLRBIT(A3) ;IS COLORBIT = 0 ?
BEQ.S NOCOLOR ;YES, DON'T MAP
MOVE MODE(A6),-(SP) ;PUSH INPUT MODE
MOVE.L PAT(A6),-(SP) ;PUSH ADDR OF INPUT PATTERN
JSR COLORMAP ;ALTER BY THECOLOR, THEFILTER
MOVE.L (SP)+,PAT(A6) ;GET (ALTERED) PATTERN
MOVE (SP)+,MODE(A6) ;GET (ALTERED) MODE
NOCOLOR MOVE.L A3,A5 ;PUT GRAFPORT IN A5
;---------------------------------------------------------
;
; GET CLIPRGN AND VISRGN HANDLES AND DE-REFERENCE THEM
;
MOVE.L CLIPRGN(A5),A2 ;GET CLIPRGN HANDLE
MOVE.L (A2),A2 ;GET CLIPRGN POINTER
MOVE.L VISRGN(A5),A3 ;GET VISRGN HANDLE
MOVE.L (A3),A3 ;GET VISRGN POINTER
;-----------------------------------------------------------------------
;
; CALC MINRECT, THE INTERSECTION OF DSTRECT, BITMAP BOUNDS,
; CLIPRGN BBOX, AND VISRGN BBOX. QUIT IF NO INTERSECTION.
;
MOVE.L DSTRECT(A6),-(SP) ;PUSH DSTRECT
PEA PORTBITS+BOUNDS(A5) ;PUSH BITMAP BOUNDS
PEA RGNBBOX(A2) ;PUSH CLIPRGN BBOX
PEA RGNBBOX(A3) ;PUSH VISRGN BBOX
MOVE #4,-(SP) ;PUSH NRECTS=4
PEA MINRECT(A6) ;PUSH DST ADDR
JSR RSECT ;CALC INTERSECTION
BEQ GOHOME ;QUIT IF NO INTERSECT
;
; CHECK FOR BOTH VISRGN AND CLIPRGN RECTANGULAR
;
CLR.B FASTFLAG(A6) ;FASTFLAG := FALSE
CMP #10,RGNSIZE(A2) ;IS CLIPRGN RECTANGULAR ?
BNE.S FLAGOK ;NO, CONTINUE
CMP #10,RGNSIZE(A3) ;IS VISRGN RECTANGULAR ?
BEQ.S CKPAT ;YES, CONTINUE
;
; If only visRgn is non-rectangular, then check if
; its intersection with minrect would be rectangular.
; IF TrimRect(visRgn,minRect) then treat as rectangular.
;
MOVE.L visRgn(A5),-(SP) ;push rgnHandle
PEA minRect(A6) ;push addr of minRect
JSR TrimRect ;call trimRect
BLT GOHOME ;quit if intersection empty
BGT.S FLAGOK ;continue if non-rectangular
;
; CHECK FOR BLACK OR WHITE PATTERN
;
CKPAT MOVE.L PAT(A6),A0 ;POINT TO PATTERN
MOVE.L (A0)+,D0 ;GET 1ST HALF OF PATTERN
CMP.L (A0)+,D0 ;IS IT SAME AS 2ND HALF ?
BNE.S FLAGOK ;NO, CONTINUE
NOT.L D0 ;IS PATTERN BLACK ?
BEQ.S YESFLAG ;YES, WE MADE IT
NOT.L D0 ;IS PATTERN WHITE ?
BNE.S FLAGOK ;NO, CONTINUE
EOR #4,MODE(A6) ;YES, ALTER MODE AS IF BLACK
YESFLAG ST FASTFLAG(A6) ;REMEMBER RECT CLIPPED AND BLACK
;
; fast case: map mode into black,xor,white, or do-nothing
;
MOVEQ #7,D0 ;GET 3 BIT MASK
AND MODE(A6),D0 ;GET 3 BITS OF MODE
MOVE.B MODEMAP(D0),D0 ;MAP TO BLACK,XOR,WHITE,NOP
BMI GOHOME ;QUIT IF DO-NOTHING MODE
MOVE D0,MODE(A6) ;UPDATE MODE
BRA.S FLAGOK ;AND CONTINUE
MODEMAP .BYTE 0,0,1,2,2,255,255,255
FLAGOK
CLR.B SKIPFLAG(A6) ;INIT TO NOT SKIPPING
;--------------------------------------------------
;
; ADJUST IF ARCANGLE NEGATIVE, QUIT IF ARC = 0
; NOTE WHETHER FULL CIRCLE OR ARC
;
MOVE ARCANGLE(A6),D0 ;GET ARC ANGLE
BEQ GOHOME ;QUIT IF ARC ANGLE = 0
BPL.S POSANG ;IS ANGLE NEG ?
ADD D0,STARTANGLE(A6) ;YES, ADJUST START ANGLE
NEG D0 ;AND MAKE ARC ANGLE POSITIVE
MOVE D0,ARCANGLE(A6) ;UPDATE INPUT PARAM
POSANG CMP #360,D0 ;IS ARC ANGLE < 360 ?
SLT ARCFLAG(A6) ;REMEMBER FOR LATER
BGE NOTARC ;NO, SKIP SETUP
;---------------------------------------------------------------
;
; IF ARCANGLE < 360 THEN SET UP ARC STUFF
;
; TREAT STARTANGLE MOD 360
;
MOVE STARTANGLE(A6),D0 ;GET STARTANGLE
EXT.L D0 ;SIGN EXTEND FOR DIVIDE
DIVS #360,D0 ;TREAT STARTANGLE MOD 360
SWAP D0 ;GET THE REMAINDER
TST D0 ;WAS IT NEGATIVE ?
BPL.S STARTOK ;NO, CONTINUE
ADD #360,D0 ;YES, PUT IN RANGE 0..359
STARTOK MOVE D0,STARTANGLE(A6) ;REPLACE INPUT PARAM
ADD ARCANGLE(A6),D0 ;CALC STOPANGLE
CMP #360,D0 ;IS IT >= 360 ?
BLT.S STOPOK ;NO, CONTINUE
SUB #360,D0 ;YES, PUT IN RANGE 0..359
STOPOK MOVE D0,STOPANGLE(A6) ;SAVE STOPANGLE FOR LATER
MOVE.L DSTRECT(A6),A0 ;POINT TO DSTRECT
MOVE TOP(A0),D0
ADD BOTTOM(A0),D0
ASR #1,D0
MOVE D0,MIDVERT(A6) ;MID VERT := (DSTBOT+DSTTOP)/2
MOVE LEFT(A0),D0
ADD RIGHT(A0),D0
ASR #1,D0
MOVE D0,MIDHORIZ(A6) ;MID HORIZ := (DSTLEFT+DSTRIGHT)/2
MOVE RIGHT(A0),D0
SUB LEFT(A0),D0
MOVE D0,WIDTH(A6) ;WIDTH := DSTRIGHT - DSTLEFT
MOVE BOTTOM(A0),D0
SUB TOP(A0),D0
MOVE D0,HEIGHT(A6) ;HEIGHT := DSTBOTTOM -DSTTOP
CLR.L -(SP) ;MAKE ROOM FOR FCN RESULT
MOVE WIDTH(A6),-(SP)
MOVE HEIGHT(A6),-(SP)
_FixRatio ;CALC ASPECT RATIO
MOVE.L (SP)+,D7 ;SAVE RESULT IN D7
;--------------------------------------------
;
; CALC SLOPE1 FROM STARTANGLE
;
CLR.L -(SP) ;MAKE ROOM FOR FCN RESULT
MOVE STARTANGLE(A6),-(SP) ;PUSH STARTANG
JSR SlopeFromAngle ;CALC SLOPE1
MOVE.L (SP)+,D0 ;POP SLOPE1
CLR.L -(SP) ;ROOM FOR FCN RESULT
MOVE.L D0,-(SP) ;PUSH SLOPE1
MOVE.L D7,-(SP) ;PUSH ASPECT RATIO
_FixMul ;scale slope1
MOVE.L (SP)+,SLOPE1(A6) ;SAVE RESULT FOR LATER
;--------------------------------------------
;
; CALC SLOPE2 FROM STOPANGLE
;
CLR.L -(SP) ;MAKE ROOM FOR FCN RESULT
MOVE STOPANGLE(A6),-(SP) ;PUSH STOPANGLE
JSR SlopeFromAngle ;CALC SLOPE2
MOVE.L (SP)+,D0 ;POP SLOPE2
CLR.L -(SP) ;ROOM FOR FCN RESULT
MOVE.L D0,-(SP) ;PUSH SLOPE
MOVE.L D7,-(SP) ;PUSH ASPECT RATIO
_FixMul ;SCALE SLOPE2
MOVE.L (SP)+,SLOPE2(A6) ;SAVE RESULT FOR LATER
;---------------------------------------------------------
;
; CALC HORIZ COORDS OF LINE1 AND LINE2 AT TOP OF DSTRECT
;
MOVE MIDHORIZ(A6),D6
SWAP D6
CLR.W D6 ;CALC MIDHORIZ*64K
MOVE HEIGHT(A6),D7
LSR #1,D7 ;CALC HEIGHT DIV 2
MOVE SLOPE1+2(A6),D0 ;GET LO WORD OF SLOPE
MULU D7,D0 ;CALC LO PARTIAL PRODUCT
MOVE.L D0,LINE1(A6) ;ACCUMULATE IT
MOVE.W SLOPE1(A6),D0 ;GET HI WORD OF SLOPE
MULS D7,D0 ;CALC HI PARTIAL PRODUCT
ADD.W D0,LINE1(A6) ;ADD TO HI WORD OF ACCUMULATOR
MOVE.L D6,D0 ;COPY MIDHORIZ*64K
SUB.L LINE1(A6),D0 ;CALC MIDH*64K-SLOPE*(HT DIV 2)
MOVE.L D0,LINE1(A6) ;STORE AS LINE1 HORIZ AT TOP
MOVE SLOPE2+2(A6),D0 ;GET LO WORD OF SLOPE
MULU D7,D0 ;CALC LO PARTIAL PRODUCT
MOVE.L D0,LINE2(A6) ;ACCUMULATE IT
MOVE.W SLOPE2(A6),D0 ;GET HI WORD OF SLOPE
MULS D7,D0 ;CALC HI PARTIAL PRODUCT
ADD.W D0,LINE2(A6) ;ADD TO HI WORD OF ACCUMULATOR
SUB.L LINE2(A6),D6 ;CALC MIDH*64K-SLOPE*(HT DIV 2)
MOVE.L D6,LINE2(A6) ;STORE AS LINE2 HORIZ AT TOP
;----------------------------------------------------------
;
; SET UP FLAG1 AND FLAG2 TO TELL WHICH HALF EACH LINE IS ACTIVE IN:
; CODE IS: NEG = ACTIVE IN TOP, POS = ACTIVE IN BOTTOM, 0 = HORIZONTAL
;
MOVE STARTANGLE(A6),D0
CMP #180,D0 ;IS STARTANGLE < 180 ?
BGE.S @1 ;NO, CONTINUE
SUB #90,D0 ;YES, FLAG1:=STARTANGLE-90
BRA.S @2 ;CONTINUE
@1 SUB #270,D0
NEG D0 ;FLAG1 := 270-STARTANGLE
@2 MOVE D0,FLAG1(A6) ;SAVE FOR LATER
MOVE STOPANGLE(A6),D0
CMP #180,D0 ;IS STOPANGLE < 180 ?
BGE.S @3 ;NO, CONTINUE
SUB #90,D0 ;YES, FLAG2:=STOPANGLE-90
BRA.S @4 ;CONTINUE
@3 SUB #270,D0
NEG D0 ;FLAG2 := 270-STOPANGLE
@4 MOVE D0,FLAG2(A6) ;SAVE FOR LATER
;
; SET UP SKIPFLAG TO SKIP OVER UNUSED ARC PORTIONS
;
MOVE ARCANGLE(A6),D0
CMP #180,D0 ;IS ARC ANGLE > 180 ?
BGT.S OBTUSE ;SKIP IF ANGLE > 180
BLT.S ACUTE ;DEAL WITH ACUTE ANGLE
CMP #90,STARTANGLE(A6) ;OTHERWISE ANGLE=180
SEQ SKIPFLAG(A6) ;SO SKIP IF START=90
BRA.S OBTUSE
ACUTE MOVE FLAG1(A6),D0
OR FLAG2(A6),D0
SPL SKIPFLAG(A6) ;SKIP:=FLAG1 AND FLAG2 BOTH >= 0
OBTUSE
NOTARC
;---------------------------------------------------------------
;
; INIT OUTER OVAL STATE RECORD
;
MOVE.L DSTRECT(A6),A0 ;POINT TO DSTRECT
LEA OUTEROVAL(A6),A1 ;POINT TO OUTER OVAL RECORD
MOVE OVALHEIGHT(A6),D1 ;GET OVALHEIGHT
MOVE OVALWIDTH(A6),D2 ;GET OVALWIDTH
JSR INITOVAL ;INITIALIZE OUTER OVAL RECORD
MOVE OVALHEIGHT(A6),D0 ;GET OVALHEIGHT
ASR #1,D0 ;CALC OVAL HEIGHT DIV 2
ADD OUTEROVAL+OVALTOP(A6),D0 ;ADD OUTEROVAL TOP
MOVE D0,SKIPTOP(A6) ;SAVE SKIPTOP
MOVE.L DSTRECT(A6),A0 ;POINT TO DSTRECT
ADD BOTTOM(A0),D0 ;ADD BOTTOM
SUB TOP(A0),D0 ;SUBTRACT TOP
SUB OVALHEIGHT(A6),D0 ;SUBTRACT OVALHEIGHT
MOVE D0,SKIPBOT(A6) ;SAVE SKIPBOT
;---------------------------------------------------
;
; IF THIS IS A HOLLOW OVAL, THEN CALC DSTRECT INSET BY PENSIZE,
; AND INIT INNEROVAL. (IF INNEROVAL EMPTY, SWITCH TO SOLID).
;
MOVE #32767,INNEROVAL+OVALTOP(A6) ;INIT INNEROVAL NOT USED
TST.B HOLLOW(A6) ;IS HOLLOWFLAG TRUE ?
BEQ.S SOLID ;NO, SKIP INNER OVAL
MOVE.L DSTRECT(A6),A0 ;POINT TO DSTRECT
MOVEM.W (A0),D0-D3 ;GET DSTRECT INTO REGS
MOVE.L PNSIZE(A5),D4 ;GET THEPORT^.PNSIZE
ADD D4,D1 ;LEFT := DSTLEFT + PENWIDTH
SUB D4,D3 ;RIGHT := DSTRIGHT - PENWIDTH
CMP D3,D1 ;IS LEFT >= TOP ?
BGE.S SOLID ;YES, EMPTY RECT
SWAP D4 ;GET PNSIZE.V
ADD D4,D0 ;TOP := DSTTOP + PENHEIGHT
SUB D4,D2 ;BOTTOM := DSTBOTTOM - PENHEIGHT
CMP D2,D0 ;IS TOP >= BOTTOM ?
BGE.S SOLID ;YES, EMPTY RECT
MOVEM.W D0-D3,TEMPRECT(A6) ;STORE RESULTS INTO TEMPRECT
LEA TEMPRECT(A6),A0 ;POINT TO DSTRECT INSET BY PENSIZE
LEA INNEROVAL(A6),A1 ;POINT TO INNER OVAL RECORD
MOVE OVALHEIGHT(A6),D1
SUB D4,D1 ;INNER HEIGHT:=OUTER-2*PENHEIGHT
SUB D4,D1
MOVE OVALWIDTH(A6),D2
SWAP D4 ;GET PEN WIDTH
SUB D4,D2 ;INNER WIDTH:=OUTER-2*PENWIDTH
SUB D4,D2
JSR INITOVAL ;INITIALIZE INNER OVAL RECORD
SOLID
;----------------------------------------------------------------
;
; HIDE CURSOR IF CURSOR INTERSECTS MINRECT.
;
PEA MINRECT(A6) ;PUSH SHIELDRECT PARAMETER
MOVE.L PORTBITS+BOUNDS+TOPLEFT(A5),-(SP) ;PUSH DELTA TO CONVERT TO GLOBAL
MOVE.L SAVEA5(A6),A5 ;GET GLOBAL PTR
JSR SHIELDCURSOR ;HIDE CURSOR IF IT INTERSECTS
MOVE.L PORT(A6),A5 ;RESTORE GRAFPORT IN A5
;------------------------------------
;
; CALC BUFLEFT
;
MOVE MINRECT+LEFT(A6),D2 ;GET MINRECT LEFT
SUB PORTBITS+BOUNDS+LEFT(A5),D2 ;CONVERT TO GLOBAL COORDS
AND #$FFF0,D2 ;TRUNC TO MULT OF 16
ADD PORTBITS+BOUNDS+LEFT(A5),D2 ;CONVERT BACK TO GLOBAL
MOVE D2,BUFLEFT(A6) ;SAVE AS BUFLEFT
;
; IF FASTFLAG, THEN SKIP REGION SETUP
;
TST.B FASTFLAG(A6) ;RECT CLIPPED AND BLACK ?
BNE SKIPSETUP ;YES, DON'T WASTE TIME WITH SETUP
;
; CALC BUFSIZE
;
MOVE MINRECT+RIGHT(A6),D0 ;GET MINRECT RIGHT
SUB D2,D0 ;CALC MAXH-BUFLEFT
LSR #5,D0 ;DIV BY 32 FOR LONGS
MOVE D0,BUFSIZE(A6) ;BUFSIZE = # LONGS - 1
;-------------------------------------------------------------------------
;
; ALLOCATE AND CLEAR A SCANLINE BUFFER FOR THE COMPOSITE MASK
;
CLRMASK CLR.L -(SP) ;ALLOCATE AND CLEAR ONE LONG
DBRA D0,CLRMASK ;LOOP TILL DONE
MOVE.L SP,MASKBUF(A6) ;REMEMBER WHERE MASKBUF IS
;-------------------------------------------------------------------------
;
; INIT STATE RECORDS AND ALLOCATE BUFFERS FOR EACH NON-RECTANGULAR REGION
;
CLR D5 ;INIT BOTH ARE RECT
MOVE #-32767,STATEA+THISV(A6) ;INIT REGION STATEA
MOVE #32767,STATEA+NEXTV(A6) ;TO HARMLESS IN CASE RECT
CMP #10,RGNSIZE(A2) ;IS CLIPRGN RECTANGULAR ?
BEQ.S ARECT ;YES, CONTINUE
ADD #2,D5 ;NO, SET ITS FLAG
MOVE.L A2,A0 ;POINT TO CLIPRGN
LEA STATEA(A6),A1 ;POINT TO STATE RECORD A
BSR.S INITONE ;INIT STATE, ALLOC BUFFER
ARECT
MOVE #-32767,STATEB+THISV(A6) ;INIT REGION STATEB
MOVE #32767,STATEB+NEXTV(A6) ;TO HARMLESS IN CASE RECT
CMP #10,RGNSIZE(A3) ;IS VISRGN RECTANGULAR ?
BEQ.S BRECT ;YES, CONTINUE
ADD #4,D5 ;NO, SET ITS FLAG
MOVE.L A3,A0 ;POINT TO VISRGN
LEA STATEB(A6),A1 ;POINT TO STATE RECORD B
PEA BRECT ;PUSH FAKE RETURN ADDR
INITONE MOVE MINRECT+LEFT(A6),D0 ;GET MINH
MOVE MINRECT+RIGHT(A6),D1 ;GET MAXH
MOVE BUFLEFT(A6),D2 ;GET BUFLEFT
JMP INITRGN ;INIT STATE, ALLOC BUFFER
BRECT
;--------------------------------------------------------------------
;
; IF BOTH REGIONS ARE RECTANGULAR, THEN DRAW MINRECT INTO MASK BUFFER
;
MOVE.W D5,RECTFLAG(A6) ;ARE ALL RGNS RECT ?
BNE.S NOTRECT ;NO, CONTNUE
MOVE.L MASKBUF(A6),A0 ;YES, POINT TO MASK BUFFER
MOVE MINRECT+LEFT(A6),D3 ;SET UP LEFT
SUB BUFLEFT(A6),D3 ;MAKE IT BUFFER RELATIVE
MOVE MINRECT+RIGHT(A6),D4 ;SET UP RIGHT
SUB BUFLEFT(A6),D4 ;MAKE IT BUFFER RELATIVE
JSR XorSlab ;AND XOR BETWEEN THEM
NOTRECT
SKIPSETUP
;------------------------------------
;
; CALC STARTING DSTLEFT
;
MOVE MINRECT+TOP(A6),D1 ;GET MINRECT TOP
SUB PORTBITS+BOUNDS+TOP(A5),D1 ;CONVERT TO GLOBAL COORDS
MULU PORTBITS+ROWBYTES(A5),D1 ;MULT BY DST ROWBYTES
ADD.L PORTBITS+BASEADDR(A5),D1 ;ADD START OF BITMAP
SUB PORTBITS+BOUNDS+LEFT(A5),D2 ;CONVERT BUFLEFT TO GLOBAL
LSR #3,D2 ;CALC BUFLEFT DIV 8
EXT.L D2 ;CLR HI WORD
ADD.L D2,D1 ;ADD HORIZ BYTE OFFSET
MOVE.L D1,DSTLEFT(A6) ;SAVE AS DSTLEFT
;----------------------------------------------------
;
; MAKE ALL HORIZONTAL COORDINATES RELATIVE TO BUFFER
;
MOVE BUFLEFT(A6),D1
SUB D1,MINRECT+LEFT(A6)
SUB D1,MINRECT+RIGHT(A6)
SUB.W D1,OUTEROVAL+LEFTEDGE(A6) ;ADJUST OUTEROVAL LEFTEDGE.INT
SUB.W D1,OUTEROVAL+RIGHTEDGE(A6) ;ADJUST OUTEROVAL RIGHTEDGE.INT
SUB.W D1,INNEROVAL+LEFTEDGE(A6) ;ADJUST INNEROVAL LEFTEDGE.INT
SUB.W D1,INNEROVAL+RIGHTEDGE(A6) ;ADJUST INNEROVAL RIGHTEDGE.INT
SUB.W D1,LINE1(A6) ;ADJUST LINE1
SUB.W D1,LINE2(A6) ;ADJUST LINE2
;---------------------------------------------------
;
; SET UP CASE JUMP BASED ON MODE AND FASTFLAG
;
MOVE MODE(A6),D2 ;GET (ALTERED) PEN MODE
TST.B FastFlag(A6) ;Rect clipoped and black ?
BEQ.S @1 ;no, use slow drawslab loop
JSR FastSlabMode ;yes, get fast modeCase in A4
MOVE.L A4,MODECASE(A6) ;SAVE FOR LATER
CLR PATINDEX(A6) ;MAKE UNUSED PATINDEX EVEN
BRA GOFORIT ;SKIP PATTERN STUFF
@1 JSR SlabMode ;get slow modeCase in A4
MOVE.L A4,MODECASE(A6) ;SAVE FOR LATER
;------------------------------------------------------------------
;
; EXPAND 8 BYTE PATTERN TO 16 LONGS AND INIT PATTERN SELECTOR
;
CLR.L D7 ;SAY NOT INVERTED
MOVE MODE(A6),D2 ;GET MODE
BCLR #2,D2 ;TEST AND CLR INVERT BIT
BEQ.S NOTINV ;SKIP IF NOT INVERTED
NOT.L D7 ;INVERTED; D7 GETS ALL 1'S
NOTINV MOVE PORTBITS+BOUNDS+LEFT(A5),D2 ;GET GLOBAL-LOCAL OFFSET
MOVE.L PAT(A6),A0 ;POINT TO BYTE WIDE PATTERN
LEA EXPAT(A6),A1 ;POINT TO EXPANDED PATTERN
MOVE.L SAVEA5(A6),A5 ;GET GLOBAL PTR
JSR PATEXPAND ;EXPAND 8 BYTE PATTERN TO 16 LONGS
MOVE.L PORT(A6),A5 ;RESTORE GRAFPORT IN A5
MOVEQ #$F,D0 ;TREAT COORD MOD 16
AND MINRECT+TOP(A6),D0 ;GET TOP VERT LOCAL COORD
LSL #2,D0 ;QUAD FOR 4 BYTE PATTERNS
MOVE D0,PATINDEX(A6) ;SET UP PATTERN INDEX
;------------------------------------------------------------
;
; BUMP OVAL STATE RECORDS UNLESS VERT IS BETWEEN SKIPTOP AND SKIPBOT
;
GOFORIT MOVE OUTEROVAL+OVALTOP(A6),D7 ;START VERT:= OUTER OVAL TOP
NEXTROW CMP SKIPTOP(A6),D7 ;IS VERT < SKIPTOP ?
BLT.S YESBUMP ;YES, OK TO BUMP OVALS
CMP SKIPBOT(A6),D7 ;IS VERT >= SKIPBOT ?
BLT.S NOBUMP ;NO, SKIP BUMPING
YESBUMP MOVE D7,-(SP) ;STASH CURRENT VERT
MOVE D7,D0 ;COPY CURRENT VERTICAL
LEA OUTEROVAL(A6),A3 ;POINT TO OUTER OVAL STATE RECORD
JSR BUMPOVAL ;BUMP IT TO NEXT SCANLINE
MOVE (SP),D0 ;COPY CURRENT VERT
LEA INNEROVAL(A6),A3 ;POINT TO INNER OVAL STATE RECORD
JSR BUMPOVAL ;BUMP IT TO NEXT SCANLINE
MOVE (SP)+,D7 ;RECOVER SAVED CURRENT VERT
;--------------------------------------------------
;
; ADJUST ARC STUFF AS WE CROSS THE MIDDLE VERTICALLY
;
NOBUMP CMP MIDVERT(A6),D7 ;IS CURRENT VERT = MIDVERT ?
BNE.S NOTMID ;NO, CONTINUE
TST.B ARCFLAG(A6) ;ARE WE DOING AN ARC ?
BEQ.S NOTMID ;NO, SKIP
NEG FLAG1(A6) ;YES, INVERT FLAGS AS WE CROSS
NEG FLAG2(A6)
;
; RE-CALCULATE SKIPFLAG, AND QUIT IF IT BECOMES TRUE
;
CLR.B SKIPFLAG(A6)
MOVE ARCANGLE(A6),D0
CMP #180,D0 ;IS ARC ANGLE > 180 ?
BGT.S OBTUSE1 ;SKIP IF ANGLE > 180
BLT.S ACUTE1 ;DEAL WITH ACUTE ANGLE
CMP #270,STARTANGLE(A6) ;IS STARTANGLE = 270 ?
BNE.S OBTUSE1 ;NO, CONTINUE
BRA DONE ;YES, WE'RE ALL DONE
ACUTE1 MOVE FLAG1(A6),D0
OR FLAG2(A6),D0
BPL DONE ;QUIT IF BOTH FLAG1 AND FLAG2>=0
OBTUSE1
;
; NOW SWAP THE ROLES OF LINE1 AND LINE2 AS THEY CROSS THE MIDDLE
;
MOVE FLAG1(A6),D0 ;SWAP FLAG1 AND FLAG2
MOVE FLAG2(A6),FLAG1(A6)
MOVE D0,FLAG2(A6)
MOVE.L LINE1(A6),D0 ;SWAP LINE1 AND LINE2
MOVE.L LINE2(A6),LINE1(A6)
MOVE.L D0,LINE2(A6)
MOVE.L SLOPE1(A6),D0 ;SWAP SLOPE1 AND SLOPE2
MOVE.L SLOPE2(A6),SLOPE1(A6)
MOVE.L D0,SLOPE2(A6)
NOTMID CMP MINRECT+TOP(A6),D7 ;IS CURRENT VERT < MINV ?
BLT NODRAW ;YES, DON'T DRAW
TST.B SKIPFLAG(A6) ;ARE WE SKIPPING ?
BNE NEXTPAT ;YES, SKIP
;------------------------------------------------
;
; SEEK MASK TO THE CURRENT VERTICAL, AND
; BRANCH BASED ON SOLID OR HOLLOW OVAL OR ARC.
;
TST.B FASTFLAG(A6) ;RECT CLIPPED AND BLACK ?
BNE.S NOMASK ;YES, DON'T BOTHER WITH MASK
BSR SEEKMASK ;MAKE MASKBUF CURRENT
NOMASK TST.B ARCFLAG(A6) ;ARE WE DOING AN ARC ?
BNE.S DOARC ;YES, GO TO IT
CMP INNEROVAL+OVALTOP(A6),D7 ;IS VERT >= INNEROVAL OVALTOP ?
BLT SOVAL ;NO, TREAT AS SOLID OVAL
CMP INNEROVAL+OVALBOT(A6),D7 ;IS VERT < INNEROVAL OVALTOP ?
BGE SOVAL ;NO, TREAT AS SOLID OVAL
BRA HOVAL ;YES, PROCESS HOLLOW OVAL
;----------------------------------------------
;
; SOLID OR HOLLOW ARC: CALC OUTERLEFT AND OUTERRIGHT
;
DOARC MOVE.W OUTEROVAL+LEFTEDGE(A6),D1 ;GET HI WORD OF OUTEROVAL LEFT
TST FLAG1(A6) ;IS LINE1 ACTIVE ?
BPL.S @1 ;NO, CONTINUE
CMP.W LINE1(A6),D1 ;YES, CHECK LINE1 HORIZ COORD
BGE.S @1
MOVE.W LINE1(A6),D1 ;CALC MAX(OVALLEFT,LINE1)
@1 MOVE D1,OUTERLEFT(A6) ;SAVE OUTER LEFT
MOVE.W OUTEROVAL+RIGHTEDGE(A6),D2 ;GET HI WORD OF OUTEROVAL RIGHT
TST FLAG2(A6) ;IS LINE2 ACTIVE ?
BPL.S @2 ;NO, CONTINUE
CMP.W LINE2(A6),D2 ;YES, CHECK LINE2 HORIZ COORD
BLE.S @2
MOVE.W LINE2(A6),D2 ;CALC MIN(OVALRIGHT,LINE2)
@2 MOVE D2,OUTERRIGHT(A6) ;SAVE OUTER RIGHT
CMP INNEROVAL+OVALTOP(A6),D7 ;IS VERT >= INNEROVAL OVALTOP ?
BLT SARC ;NO, PROCESS SOLID ARC
CMP INNEROVAL+OVALBOT(A6),D7 ;IS VERT < INNEROVAL OVALTOP ?
BGE SARC ;NO, PROCESS SOLID ARC
;--------------------------------------------------
;
; HOLLOW ARC: CALC INNERLEFT AND INNERRIGHT
;
HARC MOVE.W INNEROVAL+LEFTEDGE(A6),D0 ;GET HI WORD OF INNEROVAL LEFT
TST FLAG2(A6) ;IS LINE2 ACTIVE ?
BPL.S @1 ;NO, CONTINUE
CMP.W LINE2(A6),D0 ;YES, CHECK LINE2 HORIZ COORD
BLE.S @1
MOVE.W LINE2(A6),D0 ;CALC MIN(OVALLEFT,LINE2)
@1 MOVE D0,INNERLEFT(A6) ;SAVE INNER LEFT
MOVE.W INNEROVAL+RIGHTEDGE(A6),D0 ;GET HI WORD OF INNEROVAL RIGHT
TST FLAG1(A6) ;IS LINE1 ACTIVE ?
BPL.S @2 ;NO, CONTINUE
CMP.W LINE1(A6),D0 ;YES, CHECK LINE1 HORIZ COORD
BGE.S @2
MOVE.W LINE1(A6),D0 ;CALC MAX(OVALRIGHT,LINE1)
@2 MOVE D0,INNERRIGHT(A6) ;SAVE INNER RIGHT
;--------------------------------------------------
;
; IF OUTERLEFT < OUTERRIGHT THEN PAINT TWO SLABS
;
CMP D2,D1 ;IS OUTERLEFT < OUTERRIGHT ?
BGE.S @3 ;NO, CONTINUE
MOVE INNERLEFT(A6),D2
BSR.S ONESLAB
MOVE INNERRIGHT(A6),D1
MOVE OUTERRIGHT(A6),D2
BRA DOSLAB
@3
;
; ELSE IF BOTH LINES ACTIVE AND ANGLE > 180 THEN PAINT TWO OR THREE SLABS
;
MOVE FLAG1(A6),D0
AND FLAG2(A6),D0 ;ARE BOTH LINES ACTIVE ?
BPL NEXTPAT ;NO, CONTINUE
CMP #180,ARCANGLE(A6) ;IS THE ANGLE > 180 ?
BLE NEXTPAT ;NO, CONTINUE
CMP INNERLEFT(A6),D2 ;IS INNERLEFT=OUTERRIGHT?
BNE.S @4 ;NO, CONTINUE
MOVE.W INNEROVAL+LEFTEDGE(A6),D2 ;YES DRAW A THIRD SLAB
BRA.S @5
@4 MOVE OUTERLEFT(A6),D0
CMP INNERRIGHT(A6),D0 ;IS INNERRIGHT=OUTERLEFT ?
BNE.S NOT3 ;NO, CONTINUE
MOVE.W INNEROVAL+RIGHTEDGE(A6),D1 ;YES, DRAW A THIRD SLAB
MOVE OUTERRIGHT(A6),D2
@5 BSR.S ONESLAB
NOT3
MOVE OUTEROVAL+LEFTEDGE(A6),D1
MOVE INNERLEFT(A6),D2
BSR.S ONESLAB
MOVE INNERRIGHT(A6),D1
MOVE.W OUTEROVAL+RIGHTEDGE(A6),D2
BRA.S DOSLAB
;---------------------------------------------------------
;
; LOCAL PROCEDURE TO SET UP AND DRAW ONE SLAB
;
ONESLAB MOVEQ #$3F,D6 ;GET WRAP-AROUND MASK
AND PATINDEX(A6),D6 ;GET PATINDEX MOD 64
MOVE.L EXPAT(A6,D6),D6 ;GET THIS ROW'S PATTERN
LEA MaskTab,A0 ;POINT TO MASK TABLE
MOVE.L DSTLEFT(A6),A1 ;INIT DSTPTR TO LEFT
MOVE.L MASKBUF(A6),A2 ;INIT MASKPTR TO LEFT
LEA MINRECT(A6),A3 ;POINT TO MINRECT
MOVE.L MODECASE(A6),A4 ;GET MODE CASE JUMP
JMP DrawSlab
;----------------------------------------------------
;
; SOLID ARC: IF OUTERLEFT < OUTERRIGHT THEN PAINT ONE SLAB
;
SARC CMP D2,D1 ;IS OUTERLEFT < OUTERRIGHT ?
BLT.S DOSLAB ;YES, DO ONE SLAB BETWEEN THEM
;
; ELSE IF BOTH LINES ACTIVE AND ANGLE > 180 THEN PAINT TWO SLABS
;
MOVE FLAG1(A6),D0
AND FLAG2(A6),D0 ;ARE BOTH LINES ACTIVE ?
BPL.S NEXTPAT ;NO, CONTINUE
CMP #180,ARCANGLE(A6) ;IS THE ANGLE > 180 ?
BLE.S NEXTPAT ;NO, CONTINUE
MOVE OUTEROVAL+LEFTEDGE(A6),D1
BSR ONESLAB
MOVE OUTERLEFT(A6),D1
MOVE.W OUTEROVAL+RIGHTEDGE(A6),D2
BRA.S DOSLAB
;--------------------------------------------------
;
; HOLLOW OVAL: DRAW TWO SLABS BETWEEN OUTER AND INNER OVALS
;
HOVAL MOVE.W OUTEROVAL+LEFTEDGE(A6),D1 ;GET OUTEROVAL LEFTEDGE.INT
MOVE.W INNEROVAL+LEFTEDGE(A6),D2 ;GET INNEROVAL LEFTEDGE.INT
BSR ONESLAB ;DRAW HORIZ SLAB BETWEEN THEM
MOVE.W INNEROVAL+RIGHTEDGE(A6),D1 ;GET OUTEROVAL RIGHTEDGE.INT
MOVE.W OUTEROVAL+RIGHTEDGE(A6),D2 ;GET INNEROVAL RIGHTEDGE.INT
BSR ONESLAB ;DRAW HORIZ SLAB BETWEEN THEM
BRA.S NEXTPAT
;----------------------------------------------------
;
; SOLID OVAL: DRAW ONE SLAB BETWEEN LEFT AND RIGHT EDGES OF OUTER OVAL
;
SOVAL MOVE.W OUTEROVAL+LEFTEDGE(A6),D1 ;GET OUTEROVAL LEFTEDGE.INT
MOVE.W OUTEROVAL+RIGHTEDGE(A6),D2 ;GET OUTEROVAL RIGHTEDGE.INT
DOSLAB BSR ONESLAB ;DRAW HORIZ SLAB BETWEEN THEM
;-------------------------------------------------------------------
;
; BUMP DESTINATION VERTICALLY AND LOOP FOR ALL SCAN LINES
;
NEXTPAT ADD #4,PATINDEX(A6) ;BUMP PATTERN INDEX
MOVE PORTBITS+ROWBYTES(A5),D0 ;GET DST ROWBYTES
EXT.L D0 ;MAKE IT LONG
ADD.L D0,DSTLEFT(A6) ;BUMP DST TO NEXT ROW
NODRAW MOVE.L SLOPE1(A6),D0 ;BUMP LINE1 AND LINE2
ADD.L D0,LINE1(A6)
MOVE.L SLOPE2(A6),D0
ADD.L D0,LINE2(A6)
ADD #1,D7 ;BUMP CURRENT VERT
CMP MINRECT+BOTTOM(A6),D7 ;HAVE WE REACHED THE BOTTOM YET ?
BLT NEXTROW ;NO, LOOP FOR MORE
DONE MOVE.L SAVEA5(A6),A5 ;GET GLOBAL PTR
JSR SHOWCURSOR ;RESTORE CURSOR
GOHOME MOVE.L SAVESTK(A6),SP ;STRIP BUFFER
MOVEM.L (SP)+,D0-D7/A1-A5 ;RESTORE REGISTERS
UNLINK PARAMSIZE,'DRAWARC '
;-----------------------------------------------------------------------------
;
; LOCAL ROUTINE TO UPDATE THE MASK BUFFER
; BASED ON WHICH REGIONS ARE RECTANGULAR
;
SEEKMASK MOVE D7,D0 ;GET CURRENT VERT COORD
MOVE RECTFLAG(A6),D1 ;GET RECTFLAG = 0,2,4
MOVE RECTJMP(D1),D1 ;GET OFFSET FROM TABLE
JMP RECTJMP(D1) ;TAKE CASE JUMP
RECTJMP .WORD IGNORE-RECTJMP ;DO NOTHING IF BOTH RECT
.WORD A-RECTJMP
.WORD B-RECTJMP
.WORD AB-RECTJMP
;
; ONLY REGION A IS NON RECTANGULAR. UPDATE IT AND USE IT AS THE MASK
;
A LEA STATEA(A6),A1
JSRSEEK JSR SEEKRGN
MOVE.L SCANBUF(A1),MASKBUF(A6)
IGNORE RTS
;
; ONLY REGION B IS NON RECTANGULAR. UPDATE IT AND USE IT AS THE MASK
;
B LEA STATEB(A6),A1
BRA.S JSRSEEK
;
; REGIONS A AND B ARE NON-RECTANGULAR. UPDATE EACH,
; THEN FORM INTERSECTION IN THE MASK BUFFER.
;
AB LEA STATEA(A6),A1
JSR SEEKRGN
LEA STATEB(A6),A1
JSR SEEKRGN
MOVE.L STATEA+SCANBUF(A6),A0
MOVE.L STATEB+SCANBUF(A6),A1
MOVE.L MASKBUF(A6),A2
MOVE BUFSIZE(A6),D1
ABLOOP MOVE.L (A0)+,D0
AND.L (A1)+,D0
MOVE.L D0,(A2)+
DBRA D1,ABLOOP
RTS
.PROC INITOVAL,4
;------------------------------------------------------------
;
; PROCEDURE InitOval(dstRect: Rect; VAR oval: OvalRec;
; ovalWidth,ovalHeight: INTEGER);
;
; initialize an oval state record to fit the given rectangle.
;
; INPUTS: A0: dstRect
; A1: ovalRec
; D1: ovalHeight
; D2: ovalWidth
;
; CLOBBERS D0,D1,D2
;
;-----------------------------------------------------------
;
; INIT OVAL TOP AND BOTTOM TO DSTRECT TOP AND BOTTOM
;
MOVE TOP(A0),OVALTOP(A1) ;INIT OVAL TOP
MOVE BOTTOM(A0),OVALBOT(A1) ;INIT OVAL BOTTOM
; CHECK OVALWIDTH AND OVALHEIGHT, PIN AT 0
TST D2 ;IS OVALWIDTH NEGATIVE ?
BPL.S OK1 ;NO, CONTINUE
CLR D2 ;YES, PIN IT TO 0
OK1 TST D1 ;IS OVALHEIGHT NEGATIVE ?
BPL.S OK2 ;NO, CONTINUE
CLR D1 ;YES, PIN IT TO 0
OK2
; CHECK OVALWIDTH AND OVALHEIGHT, TRIM IF BIGGER THAN DSTRECT
MOVE RIGHT(A0),D0
SUB LEFT(A0),D0 ;CALC DSTRECT WIDTH
CMP D0,D2 ;IS OVALWIDTH > DSTWIDTH ?
BLE.S OK3 ;NO,CONTINUE
MOVE D0,D2 ;YES, OVALWIDTH:= DSTWIDTH
OK3 MOVE BOTTOM(A0),D0
SUB TOP(A0),D0 ;CALC DSTRECT HEIGHT
CMP D0,D1 ;IS OVALHEIGHT > DSTHEIGHT ?
BLE.S OK4 ;NO,CONTINUE
MOVE D0,D1 ;YES, OVALHEIGHT:= DSTHEIGHT
OK4
; SET UP OVAL LEFT EDGE AND OVAL RIGHT EDGE, FIXED POINT NUMBERS
MOVE.W RIGHT(A0),RIGHTEDGE(A1) ;RIGHTEDGE.INT := DSTRECT.RIGHT
CLR.W RIGHTEDGE+2(A1) ;RIGHTEDGE.FRACT := 0
MOVE.W LEFT(A0),LEFTEDGE(A1) ;LEFTEDGE.INT := DSTRECT.LEFT
CLR.W LEFTEDGE+2(A1) ;LEFTEDGE.FRACT := 0
MOVE D2,D0 ;GET OVAL WIDTH
SWAP D0 ;PUT IN HI WORD
CLR D0 ;CLEAR LO WORD FOR FIXED POINT
LSR.L #1,D0 ;CALC OVAL WIDTH DIV 2
ADD.L D0,LEFTEDGE(A1) ;ADD OVALWD/2 TO LEFTEDGE
SUB.L D0,RIGHTEDGE(A1) ;SUBTRACT OVALWD/2 FROM LEFTEDGE
MOVE.L #$00008000,D0 ;GET FIXED POINT 1/2
MOVE.L D0,ONEHALF(A1) ;SAVE IN OVAL STATE RECORD
ADD.L D0,RIGHTEDGE(A1) ;BIAS RIGHT EDGE +1/2
; INIT OVALY TO -OVALHEIGHT + 1 (SCALED BY 2, BIASED 1/2 SCANLINE)
MOVEQ #1,D0
SUB D1,D0
MOVE D0,OVALY(A1) ;OVALY:=1-HEIGHT
; INIT RSQYSQ TO 2*OVALHEIGHT-1
MOVE D1,D0 ;GET HEIGHT
EXT.L D0 ;CLEAR OUT HI WORD
ADD.L D0,D0 ;CALC 2*HEIGHT
SUB.L #1,D0 ;CALC 2*HEIGHT - 1
MOVE.L D0,RSQYSQ(A1) ;RSQYSQ:=2*HEIGHT-1
; INIT SQUARE TO 0.0
CLR.L SQUARE(A1) ;SQUARE:=0
CLR.L SQUARE+4(A1) ;FRACT PART := 0 TOO
; ODDNUM:= 1 TIMES ASPECT RATIO SQUARED
CLR.L -(SP) ;GET READY FOR FUNCTION RESULT
MOVE D1,-(SP) ;PUSH NUMERATOR=HEIGHT
MOVE D2,-(SP) ;PUSH DENOMINATOR=WIDTH
_FixRatio ;CALC FIXED POINT HEIGHT/WIDTH
MOVE.L (SP),-(SP) ;DUPLICATE RESULT
PEA ODDNUM(A1) ;PUSH ADDR FOR RESULT
_LongMul ;CALC 64BIT (HEIGHT/WIDTH) SQUARED
; ODDBUMP:= 2 TIMES ASPECT RATIO SQUARED
MOVE.L ODDNUM+4(A1),D0 ;GET LO LONG OF RESULT
ADD.L D0,D0 ;DOUBLE IT
MOVE.L D0,ODDBUMP+4(A1) ;STORE INTO LO LONG OF ODDBUMP
MOVE.L ODDNUM(A1),D0
ADDX.L D0,D0 ;DOUBLE HI LONG WITH CARRY
MOVE.L D0,ODDBUMP(A1)
RTS