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
/
Copy pathDrawText.a
933 lines (851 loc) · 46.2 KB
/
DrawText.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
.INCLUDE GRAFTYPES.TEXT
;--------------------------------------------------------------
;
; --> DRAWTEXT.TEXT
;
; QuickDraw Character Generator
;
; Completely reworked 29 Apr 85 by Bill Atkinson to get 50% speed up.
; Takes advantage of optional height table at end of font.
;
.PROC DrText,4
.REF RightMask,MaskTab,RSect,ShieldCursor,ShowCursor
.REF StdTxMeas,RectInRgn,MapRect,StretchBits,TrimRect
;------------------------------------------------------------
;
; PROCEDURE DrText(count: INTEGER; textAddr: Ptr; numer,denom: Point);
;
; DRAWS CHARACTERS INTO THE CURRENT PORT'S BITMAP.
; THE FONT AND ATTRIBUTES ARE GIVEN IN THE CURRENT PORT'S CHARSTYLE.
;
;-------------------------------------------
;
; KERNED STRIKE FONT FORMAT OFFSETS:
;
FORMAT .EQU 0 ;WORD
MINCHAR .EQU 2 ;WORD
MAXCHAR .EQU 4 ;WORD
MAXWD .EQU 6 ;WORD
FBBOX .EQU 8 ;WORD
FBBOY .EQU 10 ;WORD
FBBDX .EQU 12 ;WORD
FBBDY .EQU 14 ;WORD
LENGTH .EQU 16 ;WORD
ASCENT .EQU 18 ;WORD
DESCENT .EQU 20 ;WORD
XOFFSET .EQU 22 ;WORD
RASTER .EQU 24 ;WORD
;------------------------------------------------------
;
; A6 OFFSETS OF PARAMETERS AFTER LINK:
;
PARAMSIZE .EQU 14 ;SIZE OF PARAMETERS
COUNT .EQU PARAMSIZE+8-2 ;WORD
TEXTADDR .EQU COUNT-4 ;LONG
NUMER .EQU TEXTADDR-4 ;LONG, POINT
DENOM .EQU NUMER-4 ;LONG, POINT
;-----------------------------------------------------------
;
; A6 OFFSETS OF LOCAL VARIABLES AFTER LINK:
;
SAVESTK .EQU -4 ;LONG
TEXTRECT .EQU SAVESTK-8 ;RECT
TEXTR2 .EQU TEXTRECT-8 ;RECT
MINRECT .EQU TEXTR2-8 ;RECT
BUFEND .EQU MINRECT-4 ;LONG
BUFSTART .EQU BUFEND-4 ;LONG
BUFSIZE .EQU BUFSTART-2 ;WORD
BUFROW .EQU BUFSIZE-2 ;WORD
BUFLEFT .EQU BUFROW-2 ;WORD
BUF2START .EQU BUFLEFT-4 ;LONG
BUF2END .EQU BUF2START-4 ;LONG
HEIGHT .EQU BUF2END-2 ;WORD
SRCBITS .EQU HEIGHT-14 ;BITMAP
DSTBITS .EQU SRCBITS-14 ;BITMAP
FAKERGN .EQU DSTBITS-10 ;RECTANGULAR REGION
FAKEPTR .EQU FAKERGN-4 ;LONG, FAKE MASTER POINTER
SRCADDR .EQU FAKEPTR-4 ;LONG
SRCROW .EQU SRCADDR-2 ;WORD
FASTFLAG .EQU SRCROW-2 ;BYTE
PENLOC .EQU FASTFLAG-4 ;POINT
SRCPTR .EQU PENLOC-4 ;LONG
DSTPTR .EQU SRCPTR-4 ;LONG
STRETCH .EQU DSTPTR-2 ;BOOLEAN
FROMRECT .EQU STRETCH-8 ;RECT
TORECT .EQU FROMRECT-8 ;RECT
SRCRECT .EQU TORECT-8 ;RECT
DSTRECT .EQU SRCRECT-8 ;RECT
SPWIDTH .EQU DSTRECT-4 ;FIXED POINT
CHARLOC .EQU SPWIDTH-4 ;FIXED POINT
INFO .EQU CHARLOC-8 ;4 WORDS
HEIGHTAB .EQU INFO-4 ;LONG
WIDTAB .EQU HEIGHTAB-4 ;LONG
LOCTAB .EQU WIDTAB-4 ;LONG
TOPHT .EQU LOCTAB-2 ;word
HEIGHTFLAG .EQU TOPHT-2 ;byte
MAXMIN .EQU HEIGHTFLAG-2 ;word
MINCH .EQU MAXMIN-2 ;word
SAVEA5 .EQU MINCH-4 ;LONG
NUMER2 .EQU SAVEA5-4 ;Point
DENOM2 .EQU NUMER2-4 ;Point
VARSIZE .EQU DENOM2 ;SIZE OF VARIABLES
LINK A6,#VARSIZE ;ALLOCATE TEMP VARS
MOVEM.L D0-D7/A1-A4,-(SP) ;SAVE REGS
MOVE.L SP,SAVESTK(A6) ;REMEMBER WHERE STACK WAS
MOVE.L A5,SAVEA5(A6) ;REMEMBER GLOBAL PTR
MOVE.L GRAFGLOBALS(A5),A4 ;POINT TO QUICKDRAW GLOBALS
MOVE.L THEPORT(A4),A3 ;GET CURRENT GRAFPORT
MOVE.L NUMER(A6),NUMER2(A6) ;SAVE ORIGINAL NUMER
MOVE.L DENOM(A6),DENOM2(A6) ;SAVE ORIGINAL DENOM
;
; Call StdTxMeas to swap font and measure width.
;
CLR -(SP) ;ROOM FOR FCN RESULT
MOVE COUNT(A6),-(SP) ;PUSH COUNT
BLE GOHOME ;QUIT IF COUNT <= 0
;STACK CLEANED UP BY SAVESTK
MOVE.L TEXTADDR(A6),-(SP) ;PUSH TEXTADDR
PEA NUMER(A6) ;PUSH VAR NUMER
PEA DENOM(A6) ;PUSH VAR DENOM
PEA INFO(A6) ;PUSH VAR INFO
JSR StdTxMeas ;MEASURE TEXT
MOVE (SP)+,D1 ;POP UNSCALED WIDTH RESULT
;
; StdTxMeas also stashes FMOutPtr in QD global FONTPTR,
; and unscaled fixed point text width inn FixTxWid.
;
MOVE.L FONTPTR(A4),A4 ;POINT TO FMOUTPUT
MOVE.L 2(A4),A2 ;GET FONT HANDLE
MOVE.L (A2),A2 ;DE-REFERENCE IT
MOVE FBBDY(A2),TOPHT(A6) ;INIT TOPHT IN CASE OLD FONT
BTST #0,1(A2) ;DOES FONT HAVE HEIGHT TABLE ?
SNE HEIGHTFLAG(A6) ;REMEMBER FOR LATER
;
; Setup textRect, the rectangle bounding the entire string.
;
MOVE.L PNLOC(A3),D2 ;GET PEN LOCATION
MOVE.L D2,PENLOC(A6) ;SAVE FOR LATER
MOVE.W D2,TEXTRECT+LEFT(A6) ;TEXTRECT.LEFT := PNLOC.H
ADD.W D1,D2 ;right := left + width
MOVEQ #7,D0 ;get mode mask
AND TXMODE(A3),D0 ;is txMode = srcCopy ?
BEQ.S NOSLOP ;yes, don't add slop
CMP #3,D0 ;is textMode > srcBic ?
BGT.S NOSLOP ;yes, don't add slop
ADD.W #32,D2 ;SLOP FOR ITALIC,BOLD,OVERSTRIKE
NOSLOP MOVE.W D2,TEXTRECT+RIGHT(A6) ;STORE IN TEXTRECT.RIGHT
SWAP D2 ;GET PNLOC.V
SUB ASCENT(A2),D2 ;SUBTRACT ASCENT
MOVE D2,TEXTRECT+TOP(A6) ;TEXTRECT.TOP := PNLOC.V - ASCENT
ADD FBBDY(A2),D2 ;ADD HEIGHT
MOVE D2,TEXTRECT+BOTTOM(A6) ;TEXTRECT.BOTTOM := TOP + HEIGHT
MOVE.L TEXTRECT(A6),TEXTR2(A6) ;MAKE AN EXTRA COPY
MOVE.L TEXTRECT+4(A6),TEXTR2+4(A6) ;OF TEXTRECT IN TEXTR2
;
; Check for stretching
;
MOVE.L NUMER(A6),D0 ;GET NUMERATOR
CMP.L DENOM(A6),D0 ;ARE WE STRETCHING ?
SNE STRETCH(A6) ;REMEMBER THE ANSWER
BEQ.S NOSTRCH ;CONTINUE IF NOT STRETCHING
;
; We will be stretching. Setup fromRect and toRect and map textR2.
;
MULU D0,D1 ;MULT WIDTH BY NUMER.H
DIVU DENOM+H(A6),D1 ;DIV BY DENOM.H
MOVE.L PENLOC(A6),D0 ;GET PENLOC
MOVE.L D0,TORECT+TOPLEFT(A6) ;SET UP TORECT TOPLEFT
ADD.W NUMER+H(A6),D0 ;CALC PENLOC.H + NUMER.H
MOVE D0,TORECT+RIGHT(A6) ;SET UP TORECT RIGHT
SWAP D0 ;GET PENLOC.V
ADD NUMER+V(A6),D0 ;CALC PENLOC.V + NUMER.V
MOVE D0,TORECT+BOTTOM(A6) ;SET UP TORECT BOTTOM
MOVE.L PENLOC(A6),D0 ;GET PENLOC
MOVE.L D0,FROMRECT+TOPLEFT(A6) ;SET UP FROMRECT TOPLEFT
ADD.W DENOM+H(A6),D0 ;CALC PENLOC.H + DENOM.H
MOVE D0,FROMRECT+RIGHT(A6) ;SET UP FROMRECT RIGHT
SWAP D0 ;GET PENLOC.V
ADD DENOM+V(A6),D0 ;CALC PENLOC.V + DENOM.V
MOVE D0,FROMRECT+BOTTOM(A6) ;SET UP FROMRECT BOTTOM
PEA TEXTR2(A6) ;PUSH TEXTR2
PEA FROMRECT(A6) ;PUSH FROMRECT
PEA TORECT(A6) ;PUSH TORECT
JSR MAPRECT ;MAP TEXTR2 (PRESERVES ALL REGS)
NOSTRCH ADD D1,PNLOC+H(A3) ;BUMP PEN BY (SCALED) TEXT WIDTH
;
; Quit if the pen is hidden
;
TST PNVIS(A3) ;IS PNVIS < 0 ?
BLT GOHOME ;YES, QUIT
;
; Calc minRect: the intersection of textRect, bitMap bounds,
; clipRgn and visRgn bounding boxes. Quit if no intersection.
;
PEA TEXTR2(A6) ;PUSH (MAPPED) TEXTRECT
PEA PORTBOUNDS(A3) ;PUSH BITMAP BOUNDS
MOVE.L CLIPRGN(A3),A0 ;GET CLIPRGN HANDLE
MOVE.L (A0),A0 ;DE-REFERENCE IT
PEA RGNBBOX(A0) ;PUSH CLIPRGN BBOX
MOVE.L VISRGN(A3),A0 ;GET VISRGN HANDLE
MOVE.L (A0),A0 ;DE-REFERENCE IT
PEA RGNBBOX(A0) ;PUSH VISRGN BBOX
MOVE #4,-(SP) ;PUSH NRECTS=4
PEA MINRECT(A6) ;PUSH DST ADDR
JSR RSECT ;CALC INTERSECTION
BEQ GOHOME ;QUIT IF NO INTERSECTION
;
; Set up srcAddr, srcRow, and height
;
LEA 26(A2),A0 ;GET START OF FONT BITMAP
MOVE.L A0,SRCADDR(A6) ;SAVE FOR LATER
MOVE RASTER(A2),D1 ;GET WORDS PER ROW IN FONT
ADD D1,D1 ;DOUBLE FOR BYTES PER ROW
MOVE D1,SRCROW(A6) ;REMEMBER FOR LATER
MOVE FBBDY(A2),HEIGHT(A6) ;SETUP HEIGHT FOR LATER
;
; Test for fast case:
; not stretched, no color mapping, txMode = srcOr,
; not bold, italic, underlined, outlined or shadowed,
; visRgn and clipRgn both rectangular.
;
TST.W 6(A4) ;TEST BOLD AND ITALIC
BNE NOTFAST ;NOT FAST UNLESS BOTH ZERO
CMP #1,TXMODE(A3) ;IS TEXT MODE SRCOR ?
BNE NOTFAST ;NO, NOT FAST
TST.W 10(A4) ;TEST ULTHICK AND SHADOW
BNE NOTFAST ;NOT FAST UNLESS BOTH ZERO
TST.B STRETCH(A6) ;IS TEXT STRETCHED ?
BNE NOTFAST ;YES, NOT FAST
MOVE COLRBIT(A3),D1 ;ARE WE COLOR MAPPING ?
BEQ.S NOCOLOR ;NO, CONTINUE
MOVE.L BKCOLOR(A3),D0 ;YES GET BACKGROUND COLOR
NOT.L D0 ;INVERT IT
AND.L FGCOLOR(A3),D0 ;AND WITH FOREGROUND COLOR
BTST D1,D0 ;IS THAT PLANE NORMAL ?
BEQ NOTFAST ;NO, NOT FAST
NOCOLOR MOVE.L CLIPRGN(A3),A0 ;GET CLIPRGN HANDLE
MOVE.L (A0),A0 ;DE-REFERENCE IT
MOVEQ #10,D0
CMP RGNSIZE(A0),D0 ;IS CLIPRGN RECTANGULAR ?
BNE.S NOTFAST ;NO, NOT FAST
MOVE.L VISRGN(A3),A1 ;GET VISRGN HANDLE
MOVE.L (A1),A0 ;DE-REFERENCE IT
CMP RGNSIZE(A0),D0 ;IS VISRGN RECTANGULAR ?
BEQ.S FAST ;YES, TAKE FAST OPTIMIZATION
;
; All systems go except for VisRgn not rectangular.
; Check if visRgn sect minRect is rectangular.
; IF TrimRect(visRgn,minRect) THEN take the fast way.
;
MOVE.L A1,-(SP) ;PUSH VISRGN
PEA MINRECT(A6) ;PUSH MINRECT
JSR TRIMRECT ;CALL TRIMRECT
BLT GOHOME ;quit if intersection empty
BGT.S NOTFAST ;continue if non-rectangular
;
; Fast case, go directly to screen.
; If text is clipped vertically, then clear heightflag and update TOPHT
;
FAST ST FASTFLAG(A6) ;REMEMBER WE'RE GOING FAST
MOVE MINRECT+TOP(A6),D0 ;GET MINRECT.TOP
MOVE MINRECT+BOTTOM(A6),D1 ;GET MINRECT.BOTTOM
SUB TEXTRECT+TOP(A6),D0 ;was top clipped ?
BNE.S VCLIP ;yes, handle clip
CMP TEXTRECT+BOTTOM(A6),D1 ;was bottom clipped ?
BEQ.S VCLIPOK ;no, continue
VCLIP CLR.B HEIGHTFLAG(A6) ;can't use height table
MOVE.B D0,TOPHT(A6) ;use adjusted top
SUB MINRECT+TOP(A6),D1 ;calc clipped height
MOVE.B D1,TOPHT+1(A6) ;replace TOPHT
VCLIPOK MOVE TEXTRECT+TOP(A6),D0 ;GET DST TOP
SUB PORTBOUNDS+TOP(A3),D0 ;CONVERT TO GLOBAL COORDINATES
MULU PORTBITS+ROWBYTES(A3),D0 ;MULT BY ROWBYTES
ADD.L PORTBITS+BASEADDR(A3),D0 ;ADD START OF DST BITMAP
MOVE.L D0,BUFSTART(A6) ;SET UP BUFSTART FOR LATER
MOVE PORTBITS+ROWBYTES(A3),BUFROW(A6) ;SET UP BUFROW FOR LATER
MOVE PORTBOUNDS+LEFT(A3),BUFLEFT(A6) ;REMEMBER BUFLEFT
PEA MINRECT(A6) ;PUSH SHIELD RECT
MOVE.L PORTBOUNDS+TOPLEFT(A3),-(SP) ;PUSH DELTA TO CONVERT TO GLOBAL
JSR SHIELDCURSOR ;HIDE CURSOR IF IT INTERSECTS
BRA GETPTRS
;
; Slow case: Setup for an off-screen buffer.
;
; Calc bufLeft: (word-align to avoid shift)
;
NOTFAST CLR.B FASTFLAG(A6) ;NOT GOING DIRECTLY TO SCREEN
MOVE TEXTRECT+LEFT(A6),D0 ;GET TEXTRECT LEFT
SUB PORTBOUNDS+LEFT(A3),D0 ;CONVERT TO GLOBAL
AND #$FFF0,D0 ;TRUNC TO WORD BOUND
SUB #32,D0 ;32 DOT SLOP FOR SLANT & SHADOW
ADD PORTBOUNDS+LEFT(A3),D0 ;RETURN TO LOCAL COORDS
MOVE D0,BUFLEFT(A6) ;REMEMBER FOR LATER
;
; Calculate buffer size
;
MOVE TEXTRECT+RIGHT(A6),D1 ;BUFRIGHT := TEXTRECT RIGHT
SUB D0,D1 ;WIDTH:=BUFRIGHT-BUFLEFT
LSR #5,D1 ;CONVERT DOTS TO LONGS
ADD #2,D1 ;ROUND UP PLUS EXTRA LONG
MOVE HEIGHT(A6),D3 ;GET HEIGHT
MULU D1,D3 ;BUFSIZE:=HEIGHT*BUFROW LONGS
MOVE D3,BUFSIZE(A6) ;SAVE FOR LATER
LSL #2,D1 ;QUAD BUFROW FOR BYTES
MOVE D1,BUFROW(A6) ;SAVE FOR LATER
;
; Calculate total stack requirements for off-screen buffers.
;
MOVE.L D3,D2 ;GET BUFSIZE LONGS
TST.B 11(A4) ;ARE WE SHADOWING ?
BEQ @1 ;NO, CONTINUE
ADD.L D2,D2 ;YES, CALC 2*BUFSIZE
EXT.L D1 ;SIGN EXTEND BUFROW
ADD.L D1,D2 ;CALC TOTAL LONGS
@1 LSL.L #2,D2 ;CALC TOTAL STACK BYTES NEEDED
ADD.L #1024,D2 ;ADD 1 KBYTE SLOP
;
; If stack is too small to allocate buffer(s), then recursively call
; DrText with the left half and the right half of the text string.
;
_StackAvail ;Get StackAvail IN D0
CMP.L D0,D2 ;IS stackNeeded > stackAvail ?
BLE.S STACKOK ;NO, CONTINUE
MOVE.L PENLOC+H(A6),PNLOC+H(A3) ;RESTORE PNLOC TO ORIGINAL
MOVE COUNT(A6),D7 ;GET CHARACTER COUNT
LSR #1,D7 ;DIVIDE IN HALF
BEQ GOHOME ;GIVE UP IF COUNT WAS ONLY ONE
MOVE D7,-(SP) ;PUSH NEW COUNT
MOVE.L TEXTADDR(A6),-(SP) ;PUSH TEXTADDR
MOVE.L NUMER2(A6),-(SP) ;PUSH ORIGINAL NUMER
MOVE.L DENOM2(A6),-(SP) ;PUSH ORIGINAL DENOM
JSR DrText ;DRAW THE FIRST HALF
MOVE COUNT(A6),D0 ;GET ORIGINAL CHARACTER COUNT
SUB D7,D0 ;SUBTRACT CHARS ALREADY DONE
MOVE D0,-(SP) ;PUSH NEW COUNT
MOVE.L TEXTADDR(A6),A0 ;GET ORIGINAL TEXTADDR
ADD D7,A0 ;BUMP PAST CHARS ALREADY DONE
MOVE.L A0,-(SP) ;PUSH NEW TEXTADDR
MOVE.L NUMER2(A6),-(SP) ;PUSH ORIGINAL NUMER
MOVE.L DENOM2(A6),-(SP) ;PUSH ORIGINAL DENOM
JSR DrText ;DRAW THE SECOND HALF
BRA GOHOME ;AND QUIT !
;
; Allocate and clear an off-screen buffer
;
STACKOK SUB #1,D3 ;INIT DBRA LOOP COUNT
CLR.L -(SP) ;PAD BUFFER WITH AN EXTRA ZERO
MOVE.L SP,BUFEND(A6) ;REMEMBER WHERE BUFFER ENDS
CLRLOOP CLR.L -(SP)
DBRA D3,CLRLOOP ;ALLOCATE AND CLEAR BUFFER
MOVE.L SP,BUFSTART(A6) ;REMEMBER START OF BUFFER
CLR.L -(SP) ;PAD BUFFER WITH AN EXTRA ZERO
;
; Get pointers to location table, width table, and height table in font
;
GETPTRS LEA 26(A2),A0 ;GET START OF FONT BITMAP
MOVE FBBDY(A2),D0 ;GET HEIGHT OF FONT BITMAP
MULU SRCROW(A6),D0 ;CALC TOTAL SIZE OF STRIKE
ADD.L D0,A0 ;A1 := START OF LOC TABLE
MOVE.L A0,LOCTAB(A6) ;SAVE FOR LATER
CLR.L D0 ;get ready for unsigned word
MOVE LENGTH(A2),D0 ;HOW MANY WORDS IN STRIKE BODY
ADD.L D0,D0 ;DOUBLE FOR BYTECOUNT
LEA 16(A2,D0.L),A1 ;GET START OF WIDTH TABLE
MOVE.L A1,WIDTAB(A6) ;SAVE FOR LATER
MOVE MAXCHAR(A2),D0 ;GET MAXCHAR
MOVE MINCHAR(A2),D1 ;GET MINCHAR
MOVE D1,MINCH(A6) ;STASH MINCHAR FOR LATER
SUB D1,D0 ;CALC MAXCHAR-MINCHAR
MOVE D0,MAXMIN(A6) ;SAVE FOR LATER
ADD #3,D0 ;CALC MAXMIN+3
ADD D0,D0 ;CALC 2*(MAX-MIN+3)
BTST #1,1(A2) ;DOES FONT HAVE WIDTH TABLE ?
BEQ.S NOWID ;NO, CONTINUE
ADD D0,D0 ;YES, SKIP OVER WIDTH TABLE
NOWID LEA 0(A1,D0),A0 ;POINT TO HEIGHT TABLE
MOVE.L A0,HEIGHTAB(A6) ;SAVE FOR LATER
;
; Set up space width
;
MOVE.L widthPtr,A0 ;point to width table
MOVE.L 128(A0),SPWIDTH(A6) ;get width of the space char
;
; Setup misc stuff in registers for speed
;
MOVE BUFLEFT(A6),D1 ;GET BUFLEFT
MOVE PENLOC+H(A6),D0 ;GET PEN LOCATION
ADD FBBOX(A2),D0 ;ADJUST FOR KERNING
SUB D1,D0 ;MAKE CHARLOC RELATIVE TO BUFLEFT
MOVE.W D0,CHARLOC(A6) ;INIT INT PART OF CHARLOC
MOVE #$8000,CHARLOC+2(A6) ;SET FRACT PART TO ONE HALF
SUB D1,MINRECT+LEFT(A6) ;MAKE MINRECT.LEFT AND
SUB D1,MINRECT+RIGHT(A6) ;MINRECT.RIGHT BUFFER RELATIVE
MOVE.L TEXTADDR(A6),A1 ;GET TEXTPTR
BRA.S NEXTCH ;GO TO LOOP START
;---------------------------------------------------
;
; Here's the main character drawing loop:
;
SPACECH MOVE.L SPWIDTH(A6),D1 ;GET SPACE WIDTH
ADD.L D1,CHARLOC(A6) ;BUMP CHARLOC
SKIPCH SUB #1,COUNT(A6) ;DECREMENT CHAR COUNT
BLE STRDONE ;QUIT IF CHARCOUNT <= 0
NEXTCH CLR D0 ;get ready for byte
MOVE.B (A1)+,D0 ;GET NEXT CHAR
CMP.B #32,D0 ;IS IT A SPACE ?
BEQ SPACECH ;YES, HANDLE IT
MOVE.L WidthPtr,A0 ;POINT TO WIDTH TABLE
MOVE D0,D4 ;COPY CHARACTER
LSL #2,D4 ;QUAD FOR TABLE OFFSET
MOVE.L 0(A0,D4),D4 ;GET FIXED POINT WIDTH
SUB MINCH(A6),D0 ;SUBTRACT SAVED MINCHAR
CMP MAXMIN(A6),D0 ;IS CH BETWEEN MINCHAR AND MAXCHAR ?
BLS.S OKCHAR ;YES, CONTINUE
MISSING MOVE MAXMIN(A6),D0 ;NO, USE MISSING SYMBOL
ADD #1,D0 ;WHICH IS ONE PAST MAXCHAR
ADD D0,D0 ;INDEX := 2*(MISSING-MINCHAR)
MOVE.L WIDTAB(A6),A0 ;POINT TO WIDTH TABLE
MOVE 0(A0,D0),D3 ;GET OFFSET AND WIDTH BYTES
BPL.S NOTMISS ;IS MISSING CHAR MISSING ?
BRA NEXTCH ;YES, SKIP THIS CHAR
OKCHAR ADD D0,D0 ;INDEX := 2*(ASCII-MINCHAR)
MOVE.L WIDTAB(A6),A0 ;POINT TO WIDTH TABLE
MOVE 0(A0,D0),D3 ;GET OFFSET AND WIDTH BYTES
BMI MISSING ;OFFSET NEG = MISSING CHAR
NOTMISS LSR #8,D3 ;GET OFFSET BYTE
ADD.W CHARLOC(A6),D3 ;DSTLEFT := CHARLOC.INT + OFFSET
ADD.L D4,CHARLOC(A6) ;ADD FIXED POINT WIDTH TO CHARLOC
MOVE.L LOCTAB(A6),A0 ;POINT TO LOCATION TABLE
MOVE 0(A0,D0),D1 ;GET SRCLEFT
MOVE 2(A0,D0),D2 ;GET SRCRIGHT
SUB D1,D2 ;CALC WIDTH OF BITS
BLE SKIPCH ;SKIP CHARBLT IF WIDTH <= 0
ADD D3,D2 ;DSTRIGHT := DSTLEFT + WIDTH
TST.B HEIGHTFLAG(A6) ;does font have height table ?
BEQ.S NOHEIGHT ;no, continue
MOVE.L HEIGHTAB(A6),A0 ;get height table
MOVE 0(A0,D0),TOPHT(A6) ;get this char's top and height
NOHEIGHT
;-----------------------------------------------------------------------
;
; Horizontal clip only if FastFlag: (else stretch,outline,shadow,italic die)
;
; skip if hidden on left, string done if hidden on right.
;
; at this point: D1: srcLeft
; D2: dstRight
; D3: dstLeft
;
TST.B FastFlag(A6) ;ARE WE GOING FAST ?
BEQ.S HORIZOK ;NO, DON'T CLIP
CMP MINRECT+LEFT(A6),D3 ;IS DSTLEFT < MINRECT.LEFT ?
BGE.S LEFTOK ;NO, CONTINUE
CMP MINRECT+LEFT(A6),D2 ;IS DSTRIGHT <= MINRECT.LEFT ?
BLE SKIPCH ;YES, SKIP THIS CHAR
TRIMLFT MOVE MINRECT+LEFT(A6),D0 ;NO, GET MINRECT.LEFT
SUB D3,D0 ;DISCARD:=MINRECT.LEFT-DSTLEFT
ADD D0,D1 ;SRCLEFT:=SRCLEFT+DISCARD
ADD D0,D3 ;DSTLEFT:=DSTLEFT+DISCARD
CMP MINRECT+RIGHT(A6),D2 ;IS DSTRIGHT > MINRECT.RIGHT ?
BLE.S HORIZOK ;NO, CONTINUE
BRA.S TRIMRT ;YES, TRIM RIGHT
LEFTOK CMP MINRECT+RIGHT(A6),D2 ;IS DSTRIGHT <= MINRECT.RIGHT ?
BLE.S HORIZOK ;YES, CONTINUE
CMP MINRECT+RIGHT(A6),D3 ;IS DSTLEFT >= MINRECT.RIGHT ?
BGE STRDONE ;YES, IGNORE REST OF STRING
TRIMRT MOVE MINRECT+RIGHT(A6),D2 ;NO, TRIM DSTRIGHT
HORIZOK
;--------------------------------------------------------------
;
; Inputs to local block CharBlt:
;
; srcAddr(A6)
; srcRow(A6)
; bufStart(A6) = dstAddr
; bufRow(A6) = dstRow
; D1 = srcLeft
; D2 = dstRight relative to buffer, > dstLeft
; D3 = dstLeft relative to buffer
; TOPHT(A6) top and height
;
; CLOBBERS: D0,D1,D2,D3,D4,D5,D6,D7,A0,A2,A3,A4,A5
; PRESERVES: A1,A6,A7
;
;
; Setup shift count in D5 (relative shift between src and dst)
;
MOVE D3,D5 ;COPY DSTLEFT
SUB D1,D5 ;SUB SRC LEFT
MOVEQ #$F,D0 ;get a 4 bit mask
AND D0,D5 ;SHIFTCNT:=DELTA HORIZ MOD 16
;
; Setup srcAddr in A4, address of leftmost word
;
MOVE.L SRCADDR(A6),A4 ;GET START OF SRC BITMAP
ADD D5,D1 ;CALC SRCLEFT+SHIFTCNT
ASR #4,D1 ;CONVERT FROM DOTS TO WORDS
ADD D1,D1 ;DOUBLE FOR BYTES
SUB #2,D1 ;BACK UP 1 WORD SINCE PICKING UP LONG
ADD D1,A4 ;LEAVE SRCPTR IN A4
;
; Setup dstPtr in A5, address of leftmost dst word
;
MOVE.L BUFSTART(A6),A5 ;GET START OF DST BITMAP
MOVE D3,D1 ;GET A COPY OF DSTLEFT
ASR #4,D1 ;CONVERT FROM DOTS TO WORDS
ADD D1,A5 ;ADD TO DSTPTR
ADD D1,A5 ;TWICE FOR BYTES
;
; Setup leftMask in D3 and rightMask in D4
;
LEA MaskTab,A0 ;point to mask table
AND D0,D3 ;get bottom 4 bits of dstLeft
ADD D3,D3 ;double for table index
MOVE 0(A0,D3),D3 ;get mask word from table
NOT D3 ;invert it for leftMask
MOVE D2,D6 ;copy dstRight
AND D0,D2 ;get bottom 4 bits of dstRight
ADD D2,D2 ;double for table index
MOVE 0(A0,D2),D4 ;get rightMask from table
;
; Get srcRow, dstRow, and char height into regs
;
MOVE SRCROW(A6),A2
MOVE BUFROW(A6),A3
MOVE.W #255,D7 ;GET -1 BYTE, CLEAR HI BYTE
ADD.B TOPHT+1(A6),D7 ;CALC HEIGHT-1 FOR DBRA LOOP
BMI SKIPCH ;OOPS HEIGHT WAS ZERO !
;
; Adjust srcPtr and dstPtr for charTop
;
CLR.W D0 ;get ready for byte
MOVE.B TOPHT(A6),D0 ;get char top
MOVE A2,D2 ;get srcRow in D-reg
MULU D0,D2 ;calc charTop * srcRow
ADD.L D2,A4 ;add to srcPtr
MOVE A3,D2 ;get dstRow in D-reg
MULU D0,D2 ;calc charTop * dstRow
ADD.L D2,A5 ;add to dstPtr
;
; Branch based on total number of dst words
;
ASR #4,D6 ;CALC (DSTRIGHT) DIV 16
SUB D1,D6 ;CALC TOTAL NUMBER OF WORDS-1
BEQ.S WORD1 ;BR IF DST ALL IN ONE WORD
SUB #1,D6
BEQ.S LONG1 ;BR IF DST ALL IN ONE LONG
ADD #1,D7 ;COMPENSATE FOR EXTRA DBRA
BRA.S WIDE1 ;DST WIDER THAN ONE LONG
;
; Slow loop only taken in wierd cases where dst wider than a long.
;
MAIN1 MOVE.L (A4),D0 ;GET SRC FROM BITMAP
ADD #2,A4 ;BUMP SRCPTR RIGHT
LSR.L D5,D0 ;ALIGN TO DST
AND D1,D0 ;MASK EXTRA TO ZEROS
OR D0,(A5)+ ;OR SRC INTO DST
MOVEQ #-1,D1 ;FLUSH MASK
DBRA D2,MAIN1 ;LOOP TILL LAST WORD
MOVE.L (A4),D0 ;GET SRC FROM BITMAP
LSR.L D5,D0 ;ALIGN TO DST
AND D4,D0 ;MASK WITH RIGHTMASK
OR D0,(A5) ;OR SRC INTO DST
MOVE.L SRCPTR(A6),A4 ;RESTORE SRCPTR TO LEFT
ADD A2,A4 ;BUMP TO NEXT ROW
MOVE.L DSTPTR(A6),A5 ;RESTORE DSTPTR TO LEFT
ADD A3,A5 ;BUMP DST TO NEXT ROW
WIDE1 MOVE.L A4,SRCPTR(A6) ;REMEMBER SRCPTR AT LEFT
MOVE.L A5,DSTPTR(A6) ;REMEMBER DSTPTR AT LEFT
MOVE D3,D1 ;MASK:=LEFTMASK
MOVE D6,D2 ;GET WORDCOUNT
DBRA D7,MAIN1 ;LOOP ALL ROWS
SUB #1,COUNT(A6) ;DECREMENT CHAR COUNT
BGT NEXTCH ;LOOP IF MORE CHARS LEFT
BRA STRDONE ;QUIT IF CHARCOUNT <= 0
;
; Optimize if dst fits in one long. (30% of normal characters do)
;
LONG1 SUB #2,A3 ;ADJUST DSTEND FOR WORD BUMP
LONG1A MOVE.L (A4),D0 ;GET SRC DATA
LSR.L D5,D0 ;ALIGN TO DST
AND D3,D0 ;MASK EXTRA WITH LEFTMASK
OR D0,(A5)+ ;OR RESULT INTO DST
MOVE.L 2(A4),D0 ;GET SECOND WORD OF SRC
LSR.L D5,D0 ;ALIGN IT
AND D4,D0 ;MASK EXTRA WITH RIGHTMASK
OR D0,(A5) ;OR RESULT INTO DST
ADD A2,A4 ;BUMP SRCPTR TO NEXT ROW
ADD A3,A5 ;BUMP DSTPTR TO NEXT ROW
DBRA D7,LONG1A ;LOOP ALL ROWS
SUB #1,COUNT(A6) ;DECREMENT CHAR COUNT
BGT NEXTCH ;LOOP IF MORE CHARS LEFT
BRA STRDONE ;QUIT IF CHARCOUNT <= 0
;
; Optimize if dst fits in one word. (70% of normal characters do)
;
WORD1 AND D4,D3 ;COMBINE LEFT AND RIGHT MASKS
WORD1B MOVE.L (A4),D0 ;GET SRC DATA
LSR.L D5,D0 ;ALIGN TO DST
AND D3,D0 ;MASK EXTRA TO ZEROS
OR D0,(A5) ;OR RESULT INTO DST
ADD A2,A4 ;BUMP SRCPTR TO NEXT ROW
ADD A3,A5 ;BUMP DSTPTR TO NEXT ROW
DBRA D7,WORD1B ;LOOP ALL ROWS
SUB #1,COUNT(A6) ;DECREMENT CHAR COUNT
BGT NEXTCH ;LOOP IF MORE CHARS LEFT
STRDONE MOVE.L SAVEA5(A6),A5 ;RESTORE GLOBAL PTR
TST.B FASTFLAG(A6) ;WERE WE GOING DIRECT TO SCREEN ?
BEQ.S @1 ;NO, CONTINUE
JSR SHOWCURSOR ;YES, RESTORE CURSOR
BRA GOHOME ;AND QUIT
@1 MOVE.L GRAFGLOBALS(A5),A0 ;POINT TO QUICKDRAW GLOBALS
MOVE.L THEPORT(A0),A3 ;GET CURRENT GRAFPORT
MOVE.L FONTPTR(A0),A4 ;POINT TO FMOUTPUT
MOVE.L 2(A4),A2 ;GET FONT HANDLE
MOVE.L (A2),A2 ;DE-REFERENCE IT
MOVE CHARLOC(A6),D7 ;GET FINAL CHARLOC INT PART
SUB FBBOX(A2),D7 ;UN-ADJUST FROM KERNING
;
; Make buffer bold if necessary:
;
CKBOLD CLR D2 ;GET READY FOR BYTE
MOVE.B 6(A4),D2 ;GET NUMBER OF OVERSTRIKES
BRA.S NXTBOLD ;BOLD BUFFER IF ANY
BOLDIT MOVE.L BUFSTART(A6),A0 ;POINT TO START OF BUFFER
MOVE BUFSIZE(A6),D1 ;HOW MANY LONGS IN BUF
SUB D0,D0 ;CLEAR X-BIT
BOLDLP MOVE.L (A0),D0 ;GET ONE LONG
ROXR.L #1,D0 ;ROTATE RIGHT WITH EXTEND
OR.L D0,(A0)+ ;OR BACK INTO BUFFER
DBRA D1,BOLDLP ;LOOP ENTIRE BUFFER
NXTBOLD DBRA D2,BOLDIT ;LOOP FOR EACH OVERSTRIKE
;
; Slant the buffer if necessary:
; Work from bottom of buffer up, shifting each row right.
; Work right to left to avoid clobbering src.
;
CLR D2 ;GET READY FOR BYTE
MOVE.B 7(A4),D2 ;DO WE NEED ITALIC ?
BEQ.S CHECKUL ;NO, CONTINUE
MOVE.L BUFEND(A6),A1 ;DSTPTR:=END OF BUFFER
MOVE BUFROW(A6),D3 ;GET BUFFER ROWBYTES
SUB D3,A1 ;BACK UP DSTPTR TO END OF 2ND ROW
LSR #1,D3 ;WORDCNT:=ROWBYTES DIV 2
SUB #1,D3 ;WORDCOUNT-1 FOR DBRA LOOP
MOVE HEIGHT(A6),D6 ;INIT ROW COUNTER
CLR D4 ;INIT OFFSET
BRA.S DOSLANT ;GO TO LOOP START
NXTROW ADD D2,D4 ;OFFSET:=OFFSET+ITALIC
MOVE D4,D0 ;COPY OFFSET
LSR #4,D0 ;DELTA := OFFSET SCALED BY 16
MOVEQ #$F,D5
AND D0,D5 ;SHIFTCNT:=DELTA MOD 16
LSR #4,D0 ;DELWORD:=DELTA DIV 16
MOVE.L A1,A0 ;SRCPTR:=DSTPTR
SUB #4,A0 ;BACK UP ONE LONG
SUB D0,A0 ;SUBTRACT DELWORD
SUB D0,A0 ;TWICE BECAUSE WORDS
MOVE D3,D1 ;INIT LOOP TO WORDCNT
NXTWORD MOVE.L (A0),D0 ;GET A LONG OF SRC
SUB #2,A0 ;BUMP SRCPTR LEFT ONE WORD
LSR.L D5,D0 ;SHIFT SRC TO ALIGN WITH DST
MOVE D0,-(A1) ;STORE IN DST AND BUMP DSTPTR
DBRA D1,NXTWORD ;LOOP ALL WORDS THIS ROW
DOSLANT DBRA D6,NXTROW ;LOOP FOR ALL ROWS IN BUFFER
;
; Underline characters in buffer if necessary.
;
; Use characters in buffer to hide parts of the underline.
;
CHECKUL TST.B 10(A4) ;IS ULTHICK ZERO ?
BEQ NOTUL ;YES, CONTINUE
MOVE.L BUFSTART(A6),A0 ;POINT TO BUFFER START
MOVE BUFROW(A6),D1 ;GET BYTES PER ROW OF BUFFER
MOVE ASCENT(A2),D0 ;GET ASCENT
MOVE DESCENT(A2),D2 ;GET DESCENT
MULU D1,D0
ADD.L D0,A0 ;POINT TO BASELINE ROW
MOVE.L A0,A1
MOVE.L A0,A2
ADD D1,A1 ;POINT TO BASELINE+1
CMP #2,D2 ;IS DESCENT AT LEAST 2 ?
BLT.S NOTUL ;NO, SKIP UNDERLINE
BEQ.S ONLY2 ;ONLY USE 2 IF DESCENT=2
ADD D1,A2
ADD D1,A2 ;POINT TO BASELINE+2
ONLY2 SUB D1,SP ;ALLOCATE TEMP SCANBUF
MOVE.L A3,-(SP) ;SAVE GRAFPORT
LEA 4(SP),A3 ;POINT TO START OF TEMP
LSR #2,D1 ;CONVERT BYTES TO LONGS
SUB #1,D1 ;INIT DBRA LOOP COUNT
MOVE D1,D2 ;COPY LOOP COUNT
SUB D0,D0 ;CLEAR X-BIT
UL1 MOVE.L (A0)+,D0 ;GET FROM BASELINE
OR.L (A1)+,D0 ;OR WITH BASELINE+1
OR.L (A2)+,D0 ;OR WITH BASELINE+2
MOVE.L D0,(A3) ;PUT RESULT TO TEMP
ROXR.L #1,D0 ;SHIFT WITH CARRY
OR.L D0,(A3)+ ;OR INTO TEMP
DBRA D1,UL1 ;LOOP ALL LONGS IN ROW
MOVE.L A1,A0 ;COPY END PTR
SUB D0,D0 ;CLEAR X-BIT
UL2 MOVE.L -(A3),D0 ;GET FROM TEMP
ROXL.L #1,D0 ;SHIFT LEFT WITH CARRY
OR.L (A3),D0 ;OR WITH TEMP
NOT.L D0 ;INVERT
OR.L D0,-(A1) ;DRAW SOME UNDERLINE
DBRA D2,UL2 ;LOOP ALL LONGS IN ROW
MOVE.L (SP)+,A3 ;RESTORE GRAFPORT
;
; Trim right edge of underline. (left edge trimmed by StretchBits)
;
MOVE BUFROW(A6),D0 ;GET BYTES PER ROW OF BUFFER
LSL #3,D0 ;TIMES 8 FOR DOTS WIDE
SUB D7,D0 ;OVERSHOOT:=BUFRIGHT-LASTRIGHT
SUB #1,D0 ;BACK UP 1 SO MASK COMES OUT RIGHT
LSR #4,D0 ;CONVERT DOTS TO WORDCOUNT
BRA.S UL3 ;GO TO LOOP START
ULTRIM CLR -(A0) ;ERASE SOME UNDERLINE
UL3 DBRA D0,ULTRIM ;LOOP ALL FULL WORDS
ADD BUFLEFT(A6),D7 ;UNDO BUFFER RELATIVE
MOVE D7,D0 ;GET LAST RIGHT COORD
SUB PORTBOUNDS+LEFT(A3),D0 ;CONVERT TO GLOBAL COORDS
JSR RIGHTMASK ;COMPUTE A MASK
AND D0,-(A0) ;ERASE LAST PARTIAL WORD
;
; Setup fakeRgn, a dummy rectangular region
;
NOTUL MOVE #10,FAKERGN+RGNSIZE(A6) ;SIZE=10 BYTES FOR RECT RGN
MOVE.L PORTBOUNDS(A3),FAKERGN+RGNBBOX(A6)
MOVE.L PORTBOUNDS+4(A3),FAKERGN+RGNBBOX+4(A6)
LEA FAKERGN(A6),A0 ;GET ADDR OF FAKERGN
MOVE.L A0,FAKEPTR(A6) ;POINT FAKE MASTERPTR TO IT
;
; Setup bitMaps to transfer from buffer to screen.
;
; srcBits := buffer
;
LEA SRCBITS(A6),A0 ;POINT TO SRCBITS
MOVE.L BUFSTART(A6),(A0)+ ;SET UP BASEADDR
MOVE BUFROW(A6),(A0)+ ;SET UP ROWBYTES
MOVE TEXTRECT+TOP(A6),(A0)+ ;SET UP BOUNDS TOP
MOVE BUFLEFT(A6),(A0)+ ;SET UP BOUNDS LEFT
MOVE.L TEXTRECT+BOTRIGHT(A6),(A0)+ ;SET UP BOTTOM RIGHT
;
; dstBits := portBits
;
LEA PORTBITS(A3),A2 ;POINT TO PORTBITS
LEA DSTBITS(A6),A0 ;POINT TO DSTBITS
MOVE.L (A2)+,(A0)+ ;COPY BASEADDR
MOVE (A2)+,(A0)+ ;COPY ROWBYTES
MOVE.L (A2)+,(A0)+ ;COPY BOUNDS.TOPLEFT
MOVE.L (A2)+,(A0)+ ;COPY BOUNDS.BOTRIGHT
;
; check if any shadowing:
;
CLR D3 ;GET READY FOR BYTE
MOVE.B 11(A4),D3 ;GET SHADOW COUNT
BEQ NOSHAD ;SKIP IF NO SHADOWING
;
; Shadowing will be used. Allocate buf2, 4 scans taller than BUF1.
; Clear out new 4 scanlines, and copy BUF1 into the rest.
;
MOVE BUFROW(A6),D0 ;GET 4 * NUMBER OF LONGS PER ROW
SUB #1,D0 ;INIT LOOP COUNTER
CLR.L -(SP) ;ALLOW ONE LONG OF SLOP
MOVE.L SP,BUF2END(A6) ;REMEMBER END OF BUF2
CLR2 CLR.L -(SP) ;ALLOCATE AND CLEAR A LONG
DBRA D0,CLR2 ;CLEAR 4 SCANLINES WORTH
MOVE BUFSIZE(A6),D0 ;GET NUMBER OF LONGS IN BUF1
SUB #1,D0 ;INIT DBRA COUNTER
MOVE.L BUFEND(A6),A0 ;POINT TO END OF BUF1
COPYLP MOVE.L -(A0),-(SP) ;COPY FROM BUF1 TO NEW BUF2
DBRA D0,COPYLP ;COPY ALL OF BUF1
MOVE.L SP,BUF2START(A6) ;REMEMBER START OF BUF2
CLR.L -(SP) ;ALLOW ONE LONG OF SLOP
;
; Bold buf2 across to the right enough for shadow.
;
AND #3,D3 ;RESTRICT SHADOW COUNT TO 1..3
MOVE D3,D2 ;INIT BOLD COUNTER
ACROSS1 MOVE.L BUF2START(A6),A0 ;POINT TO START OF BUFFER2
MOVE BUFSIZE(A6),D1 ;INIT COUNT OF LONGS
SUB D0,D0 ;CLEAR X-BIT
ACROSS2 MOVE.L (A0),D0 ;GET A LONG FROM BUF2
ROXR.L #1,D0 ;SHIFT IT RIGHT EXTENDED
OR.L D0,(A0)+ ;OR IT BACK INTO BUFFER
DBRA D1,ACROSS2 ;LOOP FOR ALL LONGS
DBRA D2,ACROSS1 ;BOLD RIGHT 2,3, OR 4 TIMES
;
; Bold BUF2 down enough for shadow.
;
MOVE.L BUF2START(A6),A2 ;GET LIMIT POINTER
DOWN1 MOVE.L BUF2END(A6),A1 ;DSTPTR:=END OF BUF2
MOVE.L A1,A0
SUB SRCBITS+ROWBYTES(A6),A0 ;SRCPTR:=END - 1 SCANLINE
DOWN2 MOVE.L -(A0),D0 ;GET A LONG FROM LINE ABOVE
OR.L D0,-(A1) ;OR INTO THIS LINE
CMP.L A2,A0 ;IS SRCPTR <= BUF2START ?
BGT DOWN2 ;NO, LOOP ALL LONGS
DBRA D3,DOWN1 ;BOLD DOWN 2,3, OR 4 TIMES
;
; Alter srcBits to use BUF2
;
MOVE.L A2,SRCBITS+BASEADDR(A6) ;SRC BASEADDR:=BUF2START
ADD #4,SRCBITS+BOUNDS+BOTTOM(A6) ;4 SCANS TALLER
;
; Push params and call StretchBits to transfer shadow to screen
;
MOVE.L TEXTRECT(A6),SRCRECT(A6) ;SRCRECT := TEXTRECT
MOVE.L TEXTRECT+4(A6),SRCRECT+4(A6)
ADD #4,SRCRECT+BOTTOM(A6) ;PLUS 4 SCANS TALLER
MOVE.L SRCRECT(A6),DSTRECT(A6) ;DSTRECT := SRCRECT
MOVE.L SRCRECT+4(A6),DSTRECT+4(A6)
LEA DSTRECT+TOP(A6),A0 ;OFFSET BY (-1,-1)
SUB #1,(A0)+ ;TOP
SUB #1,(A0)+ ;LEFT
SUB #1,(A0)+ ;BOTTOM
SUB #1,(A0)+ ;RIGHT
TST.B STRETCH(A6)
BEQ.S @1
PEA DSTRECT(A6)
PEA FROMRECT(A6)
PEA TORECT(A6)
JSR MAPRECT ;THEN MAPPED FOR SCALING
@1
PEA SRCBITS(A6) ;PUSH SRCBITS
PEA DSTBITS(A6) ;PUSH DSTBITS
PEA SRCRECT(A6) ;PUSH SRCRECT
PEA DSTRECT(A6) ;PUSH DSTRECT
MOVEQ #7,D0 ;GET A 3-BIT MASK
AND TXMODE(A3),D0 ;GET TEXTMODE MOD 7
MOVE D0,-(SP) ;PUSH SHADOW MODE
MOVE.L CLIPRGN(A3),-(SP) ;PUSH CLIPRGN HANDLE
MOVE.L VISRGN(A3),-(SP) ;PUSH VISRGN HANDLE
PEA FAKEPTR(A6) ;PUSH FAKE HANDLE
JSR StretchBits ;TRANSFER BUFFER TO SCREEN
;
; restore altered srcBits
;
MOVE.L BUFSTART(A6),SRCBITS+BASEADDR(A6)
SUB #4,SRCBITS+BOUNDS+BOTTOM(A6)
;
; Push params and call StretchBits to transfer buffer to screen
;
NOSHAD PEA SRCBITS(A6) ;PUSH SRCBITS
PEA DSTBITS(A6) ;PUSH DSTBITS
PEA TEXTRECT(A6) ;PUSH SRCRECT = TEXTRECT
PEA TEXTR2(A6) ;PUSH DSTRECT = TEXTR2
MOVE TXMODE(A3),-(SP) ;PUSH TEXTMODE
TST.B 11(A4) ;ARE WE USING SHADOW ?
BEQ.S MODEOK ;NO, CONTINUE
MOVE #2,(SP) ;YES, USE XOR MODE
MODEOK AND #7,(SP) ;TREAT MODE MOD 8
MOVE.L CLIPRGN(A3),-(SP) ;PUSH CLIPRGN HANDLE
MOVE.L VISRGN(A3),-(SP) ;PUSH VISRGN HANDLE
PEA FAKEPTR(A6) ;PUSH FAKE HANDLE
JSR StretchBits ;TRANSFER BUFFER TO SCREEN
GOHOME MOVE.L SAVESTK(A6),SP ;STRIP BUFFER
MOVEM.L (SP)+,D0-D7/A1-A4 ;RESTORE REGS
UNLINK PARAMSIZE,'DRTEXT '
.END