sys7.1-doc-wip/QuickDraw/DrawText.a

6244 lines
266 KiB
Plaintext
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

;
; Hacks to match MacOS (most recent first):
;
; <Sys7.1> 8/3/92 Elliot make this change
; 9/2/94 SuperMario ROM source dump (header preserved below)
;
;
; File: DrawText.a
;
; Contains: QuickDraw Character Generator
;
; Copyright: © 1983-1993 by Apple Computer, Inc., all rights reserved.
;
; Change History (most recent first):
;
; <SM6> 9/12/93 SAM Changed all instances of _Translate24to32 to _rTranslate24to32
; so they can conditionalized out of the build.
; <SM5> 5/21/93 CSS Fix some things with hasDoubleByte.
; <SM4> 8/28/92 CSS Update from Reality:
; <77> 8/21/92 csd Reentered fix <76> since the file got messed up with garbage
; data when it was checked in.
; <76> 8/21/92 DTY #1039679 <JH>: #1039679 <JH>: Underlining TrueType characters
; would overrun the width of the string due to some code added for
; double byte TrueType support. This new code adds some slop to
; the rectangle that QuickDraw draws text into. When QuickDraw
; goes to underline the text, it draws a line the width of this
; rectangle, which is wider than the width of the text, because of
; this extra slop. Added a check to not add this slop if were not
; drawing with a double byte TrueType font. This returns the code
; path to what it was under 7.0, while leaving the code path there
; for double byte TrueType fonts.
; <SM3> 7/16/92 CSS Update from Reality:
; <75> 6/8/92 SAH #1031825: Changed way the multColor flag is passed to
; StretchBits. Bit 0 now means the source is black and white only.
; Bit 1 means the source contains colour (not used).
; <74> 4/24/92 DTY Case Obj still sucks. Put the spline font conditionals back in
; until I can get this stupid case sensitivity stuff worked out so
; the ROM keeps building.
; <73> 4/24/92 DTY Dont INCLUDE anything except for SysPrivateEqu.a and
; LinkedPatchMacros.a for ROM builds, since this file is included
; into CQD.a.
; <72> 4/24/92 DTY Remove all Spline_Fonts conditionals.
; <71> 9/27/91 JSM Dont define hasDoubleByte for ROM builds.
; <70> 9/25/91 jlf Rolled in Pacific TrueType modifications and removed
; DOUBLE_BYTE conditional code. New doublebyte code is
; bracketed with hasDoubleByte conditional.
; <69> 7/10/91 JSM Remove obsolete SysVers conditionals.
; <68> 6/12/91 LN added #include 'SysPrivateEqu.a'
; <67> 4/30/91 dba move GWorldFlag equate inside PROC to get rid of warning
; <66> 3/27/91 KON MRR,gbm, WRKSHT#TitleBugTriggered: Colorized OR text mode to
; 1-bit source with bass font goes through text blit loop which
; does not know how to colorize OR mode. The fix is to force the
; drawing through stretch if going to 1-bit and the foreground
; color is not black.
; <65> 2/28/91 CL (KON)(RB)#82681 related bug. Need to make cache non purgeable
; during the memory call for offscreen text and then restore the
; state.
; <64> 1/18/91 CL (RB)Making the getmasktable conditional consistent with the
; original. Setting to NOT HAS_COLOR instead of NOT NOT_68000.
; This will fix the Mac32 build.
; <63> 1/16/91 gbm (csd) Fix total screwup by Chaz and KON. Checking in files that
; will NOT assemble is a heinous crime. Do it again, and its off
; to Saudi Arabia...
; <62> 1/16/91 CL (KON)Moving call to getmasktable from the inner blit loop to the
; set up instead. Setting it up on the stack.
; <61> 1/15/91 CL (MR)Now safecount must be set to -2 if the pen loc needs to be
; added inside of stdtxmeas.
; <60> 1/14/91 SMB (jdt) Removing initialization of overflow count since added to
; StdTxMeas.
; <59> 1/9/91 RB (CEL/PKE/GM/DA) Fixing long string overflow bug by truncating
; the count.
; <58> 12/13/90 CL (RB) Left overhang calculation did not work correctly unless the
; glyph was cached. A soft error of no_bits occured and the left
; overhang was skipped.
; <57> 12/13/90 CL (RB)In the deepChar blit loops when a character has no bitmap the
; pin needed to be advanced.
; <56> 11/27/90 CL (SMC) GC card cached the offscreen gworld. Must get and use the
; gc card cache addr.
; <55> 11/8/90 KON Call stretchbits trap for B&W machines if 7.0. [CEL]
; <54> 10/22/90 CL (BKR)Adding minimum memory mode to band characters and support
; minimum cache sizes. (SMC)Added in optimization for blit
; expansion loops.
; <53> 10/10/90 CL Adding call to preflight routine when banding to make sure we
; can get enough memory for the banded character.
; <52> 10/8/90 CL When figuring out how much space was needed for the offscreen
; buffer an ext.l was used to a unsigned word which turned into a
; negative number. Bad news! Not enough memory would be allocated
; and the heap got corrupted. Now a moveq before is used to clear
; the long.
; <50> 10/1/90 CL Added check to make sure the cache got loaded by the FontMgr.
; <49> 9/21/90 CL (BAL) A bug was introduced in the charextra code that treated
; chExtra as a unsigned character. It did a asl.l on a negative
; value making the space tremendous. An ext.l fixes the problem.
; <48> 9/18/90 CL No longer calling sbSearchForCache everytime since the
; fontMgr should load the cache in everytime
; <47> 9/17/90 BG Removed <29>, <33> and <38>. 040s are now behaving more
; reliably.
; <46> 9/4/90 CL Memory model changed a little for the cachehandle. The cacheHandle
; could change when a sbretrieveglyph call is made since it may place
; the block in another heap. So after call is made, re-init the cachehand
; via the splinekey. sb_shrinkbitmap is no longer called for cached contours
; so the bytewidth must be retrieved from the stack after calling the
; sbretrieveglyph call. No longer using the tempbitmapHand so
; there is no need for the check to dispose.
; <45> 8/27/90 RB A branch to decCount caused a warning since decCount is right
; next store and it turns to a NOP. Got rid of branch.
; <44> 8/24/90 CL Added back in changes in <39> version with bug fix to make sure
; the dither flag go set up. Also made 16 and 32 bit fonts work by
; making sure a color table was really truely pointed to by the
; source pixmap.
; <43> 8/24/90 PKE (per JT) Use new Script Mgr line layout values in GrafGlobals
; instead of soon-to-be-obsolete values in Script Mgr globals.
; <42> 8/18/90 RB Temporarily revert to version 38 so fonts work at all sizes
; again.
; <41> 8/18/90 RB Many sizes don't render to the screen
; <40> 8/17/90 gbm fix a warning about branching to the next instruction
; <39> 8/16/90 CL Color Fonts just didnt work! First of all the Font DA/Mover
; never moved 'fctb's. Voila, no color. DrText assumed a 1 bit
; font to create the mask but could get a 2, 4, or 8 bit font.
; This created a bad mask. When shrinking the bits from a greater
; pointsize, text looked really bad. So on depths greater than one
; and we are shrinking, we use the Dither mode which looks pretty
; darn good.
; <38> 8/15/90 BG Found another place for an EclipseNOP.
; <37> 7/31/90 PKE (really CL on PKEs machine) Needed to scale D3 value of the
; char code when the glyph does not exist. This caused an address
; error.
; <36> 7/30/90 CL Somehow the descent kerning adjustment code got deleted… So I am
; adding it back in.
; <35> 7/27/90 CL Needed to add cmpSize to the color pixmap.
; <34> 7/26/90 gbm change noCache to noCaching to avoid assembly conflict, collapse
; two conditional blocks together
; <33> 7/20/90 BG Found another place that an EclipseNOP was needed.
; <32> 7/20/90 DTY Bass: The Linked Patch. Changed loads of junk to make Bass work
; as a linked patch. Added conditional black and white procedure
; names, since were effectively carrying around two copies of
; DrawText in Bass, and we need to keep the procedure names
; unique. Also added check for Bass_Init for code that gets
; compiled when hasSplineFonts is true, since hasSplineFonts is
; not true when building Gaudi for System 6.0.x. Changed jumps
; into ROM to use the jmpROM macro.
; <31> 7/17/90 CL Did not need to call swapmmumode while going offscreen.
; <30> 6/29/90 CL Always calling sb_searchforcache to insure correct font cache is
; loaded for blitting.
; <29> 6/26/90 BG Rolled in 040-related changes.
; <28> 6/25/90 CL fontPrivate should only be included in this file when it is a
; splinefont build.
; <27> 6/22/90 CL Fixed up include files to use new fontPrivate.a, toolEqu.a and
; qdhooks.
; <26> 6/20/90 KON Despite the intials on this comment, JT fixed a bug in the
; character extra calculations. I was using the wrong register to
; find the current GrafPort, so the chExtra value for new ports
; was incorrect. This led to interesting, but potentially
; disasterous layout of text.
; <25> 6/18/90 CL Fixed Outline Font Clipping bug on the 68000 class machines.
; <24> 6/13/90 CL Fixing Outline & Italic Horizontal clipping bug.
; <23> 6/12/90 JT Got loose with the kerning adjustment. We now keep both the
; kerning adjustment for the pen and a separate kerning bounds for
; the left edge of the off-screen bit image that is then copied to
; the screen. The kerning adjustment for the pen works as before
; (the full fKernMax is used) but the kerning bounds for the
; offscreen bit image only includes that part of the first
; character in the string that actually kerns. I add the offset of
; the first character to the fKernMax and pin the value at zero to
; calculate the kerning bounds. All this only applies to bitmap
; fonts.
; <22> 6/12/90 JT Added alternate code for keeping the width fraction when scaling
; a bitmap font. This code replaces the nasty fixed-point trap
; routines mentioned in the previous comment.
; <21> 6/9/90 JT Removed some active and some commented out debugging traps. Also
; removed all commented out references to the old 32-bit flags.
; Sorry Chazz, I just couldn't help myself.
; <20> 6/9/90 JT Late-night session yields all kinds of interesting changes.
; First, the CalcCharExtra routine has been moved here from Text.a
; since it is now used by both the classic and the color versions
; of QuickDraw. Second, the classic version of QuickDraw now uses
; the fixed-point result of a StdTxMeas call by looking at the
; fontAdj value in the QuickDraw globals. It used to use the
; integer value that was returned as the result of the StdTxMeas
; call. Third, there is a big hack in the bitMap stretching code
; where we scale the width of the text by the horizontal numerator
; and denominator. For 68020 machines we use the double-register
; multiply and divide routines to properly scale the fixed-point
; text width by the integer numerator and denominator. But for
; 68000 machines we just toss the fractional part of the width and
; use standard single-register multiply and divide routines to do
; the scaling. As a result, stretched drawing results in truncated
; pen motions. That is, the fractional part of the pen motion is
; lost if we are drawing on an old machine and we do not have a
; font strike for the requested size and scaling parameters.
; Anyway, I put in a hack to use the fixed-point trap routines to
; do the correct scaling, but I think this probably causes some
; (don't laugh) performace degradation. Some arithmetic god should
; look into this.
; <19> 6/9/90 JT Now scale the horizontal pen fraction by the point size
; specified in the grafPort. This is the same treatment that Color
; QuickDraw normally gives the chExtra value. Note that two values
; are added together before the scaling occurs.
; <18> 5/31/90 CL Fixing QDDone parameters so the goodol GC card works properly.
; <17> 5/30/90 JT For old grafPorts use the pnLocFixed value from the QuickDraw
; globals to created a fixed-point pen location. Added the
; penLocFixed local to record the value and restore it across
; recursive drawing operations on long strings.
; <16> 5/29/90 CL Fixed stretch bug in bitmap text.
; <15> 4/18/90 CL Needs32bit only is tested for a byte so set a byte instead of a
; word. The TrueType init does not contain the new bitstopix so we
; must set up the needs32bit flag up for the init. CrsrFlag broke
; the 68000 machines. It was included in the 68000 machines but
; never was initialized.
; <14> 4/16/90 HJR Correct some conditionals. Change SPLINE_FONTS to
; hasSplineFonts.
; <13> 4/16/90 KON File got trashed at rev 11, could be network weirdness or old
; ethertalk card.
; <12> 4/16/90 KON Make it build (equate problems).
; <11> 4/13/90 HJR Fix some case sensitive problem in Mac32 build.
; <10> 4/11/90 CL Added conditional for ROM to leave out is32QD flag since it is
; not needed and the splinekey since it does not exist.
; <9> 4/10/90 CL Fixing outline Text clipping bug. Conditionalize for ROM. Adding
; Double byte international coding.
; <8> 4/9/90 KON Fixed conditionals for ROM build. Script Manager char
; extra addition.
; <8> 4/9/90 KON Fixed problems with drawing to 32-bit addressed pixmaps that are
; not the screen. With BAL.
; <7> 3/21/90 CL Fixed conditionals for ROM build. Script Manager char extra
; addition.
; <6> 3/20/90 CL International character extra is added into QD char extra for
; $700 or greater systems. Non-rectangular visrgn clip did not
; work correctly. Bug in SE - did not scale up the glyphid in
; error case for the retrieval of the width char. Stack was not
; calculate correctly. Added positive value instead of negative.
; <5> 2/28/90 CL Can not do bit depth expansion when going to local off screen
; buffer. Fixes algorithmic boldening and other not fast cases
; <4> 2/27/90 CL Finishing previous comment. 2, 4 & 8-bit only uses 1bit source
; (saves tons of memory). 8 bit - ≈120% faster. 2 and 4 - 110-120%
; faster. 16-bit - 200 to 300% faster. 32-bit - 400-500% faster. 1
; bit on Portable and SE - ≈182% faster.
; <3> 2/27/90 CL Optimized clip spline blit loops (10% faster). Wrote new fast
; loops for splines in 1, 2, 4, 8, 16 and 32 bit depth levels.
; Optimized pathway setup. Timings for 12 pt. Text on the CI
; compared to 6.0.4 systems are as follows: 1 bit is - 200%
; faster
; <1> 1/3/90 BAL Added a notice for Chazz.
; <2.8> 11/28/89 CEL Characters can have zero widths. Took out check to skip
; character if it has a zero advance width. Especially caused
; problems for International.
; <2.7> 11/14/89 CEL Added Device left side bearing.
; <2.6> 10/27/89 BAL Only define hasSplineFonts if currently undefined. Also
; translate24to32 thePort.
; <2.5> 10/10/89 CEL Fixed the notsrccopy and mask transfer mode for bitmaps.
; <2.4> 9/25/89 CEL Took out left italic descent adjustment. This adjustment to the
; over hang could cause clipping of the string before it.
; <2.3> 9/15/89 CEL Took out tempAscent and tempDescent. Use the always blit flag
; instead. Added in some new blitting code that is not turned on
; yet. Cursor bug: when 32-bit QD was not around BitsToPix did not
; return d2 value for crsrflag.
; <2.2> 8/28/89 CEL Only used byte of spline flag.
; <2.1> 8/14/89 CEL Added support for temp memory for spline bitmaps. Now works
; better in finder mode. Added in ability to set line height for
; splines. Usage from the SetLineHeight function.
; <2.0> 8/1/89 CEL Somehow SUBQ turned into SUBA while checking in…
; <1.9> 8/1/89 CEL Only effects spline font builds: Re-organized spline define
; structures. Cleaned up stack and took out conditionals. Fixed
; mask mode for splines. Fixed kerning adjusting values. Added in
; more comments. Added banding to styles. Merged B&W code to take
; advantage of the Color QD iteration, Banding code in low memory
; and Multi-Finder memory usage. Now DrText works for over 10,000
; point for styles. Have tried 13,000 point in Shadow and works
; fine. Works at 32,767 point for plain. Used assembly record
; structures for easier mods. Added some code review changes.
; <1.8> 6/10/89 CEL Moved Private.a QuickDraw Equates into proper QuickDraw private
; file (colorequ.a), got rid of QuickDraw nFiles dependencies and
; fixed up necessary files…
; <•1.7> 5/29/89 BAL Blasting in 32-Bit QuickDraw version 1.0 Final
; <•1.6> 5/3/89 CEL Bass rolled into ROM. NOTE:Spline Fonts are conditionalized out.
; Blasting in correct file
; <•1.4> 5/1/89 cel Rolled in Bass…
; <•1.2> 2/14/89 CCH Rolling in 32-Bit color quickdraw sources from Bruce Leak and
; Dave Fung.
; 9/19/88 BAL Altered to get CRSRFLAG value from _BitsToPix;
; 7/4/88 BAL Fixed offscreen drawing to compute bkcol with long result of
; color2index
; 5/8/88 BAL Altered to use 32 bit addressing mode and allow 32 bit deep
; pixels
; 1/21/88 BAL changed pnLocHFrac(a3) to PenLocHFrac(A6) so fractional position
; is restored
; 11/6/87 CRC changed to take fast branch case correctly (branch to GetPtrs,
; not NotScreen)
; 6/4/87 CRC reordered shadow draw to draw outline and then center in old
; port cases
; 1/12/87 CRC rewrote recursive part to avoid reallocating stack frame each
; time through
; 1/6/87 CRC only change the source pixmaps color table if the source is not
; 1 deep
; 1/3/87 CRC pass color param to stretch, estimate stack usage better, new
; outline/shadow allow initial left kerning, better right hand
; trim for outline
; 12/12/86 CRC Added support for arithmetic modes, character extra
; 12/8/86 CRC Faster case for characters contained in source longs
; 11/23/86 EHB Merged in multiple device changes
; 10/13/86 EHB Added MaskPix and MaskRect to stretchbits call
; 10/7/86 CRC Better measure of italic widths; italic character forces left
; kerning allow for larger strikes w/ long calcs.
; 9/29/86 CRC Changed WidthPtr to WidthTabHandle, added multibit font support
; 6/22/86 EHB Use BIC mode to clear out inner part of outline fonts. (XOR
; looked cool but was wrong).
; 6/18/86 EHB Added pattern to stretchbits calls
; 6/18/86 EHB Removed 68020 enhancements from charblt
; 6/17/86 EHB Added DSTPIX so we could access fields in cGrafPorts
; 6/15/86 EHB Make sure stack is longword aligned (for fast buffers)
; 6/10/86 EHB Modified to use longs and 68020 instructions
; 6/5/86 EHB Cleared flag bits in references to rowBytes
;
;————————————————————————————————————————————————————————————————————————————————————————————————
IF (&TYPE('hasSplineFonts') = 'UNDEFINED') THEN
hasSplineFonts EQU 0
ENDIF
IF (&TYPE('HAS_COLOR') = 'UNDEFINED') THEN
HAS_COLOR EQU hasCQD
ENDIF
IF (&TYPE('has32bitQD') = 'UNDEFINED') THEN
has32bitQD EQU 0 ;Once bits to pix is fixed we can turn this on and do
ENDIF ;some conditionals in compiling
IF (&TYPE('TIME_SPEED') = 'UNDEFINED') THEN
TIME_SPEED EQU 0
ENDIF
IF (&TYPE('INITVERSION') = 'UNDEFINED') THEN
Gaudi EQU 0
ELSE
Gaudi EQU 1
ENDIF
IF (&TYPE('hasDoubleByte') = 'UNDEFINED') THEN
IF forROM THEN
hasDoubleByte EQU 0
ELSE
hasDoubleByte EQU 1
ENDIF
ENDIF
IF (&TYPE('SCRIPT_CHAR_EXTRA') = 'UNDEFINED') THEN
IF forROM THEN
SCRIPT_CHAR_EXTRA EQU 0
ELSE
SCRIPT_CHAR_EXTRA EQU 1
ENDIF
ENDIF
IF (&TYPE('hasPenFraction') = 'UNDEFINED') THEN
IF forROM THEN
hasPenFraction EQU 0
ELSE
hasPenFraction EQU 1
ENDIF
ENDIF
IF (&TYPE('hasFullKerning') = 'UNDEFINED') THEN
IF forROM THEN
hasFullKerning EQU 0
ELSE
hasFullKerning EQU 1
ENDIF
ENDIF
IF HAS_COLOR THEN
MACHINE MC68020 ;<PN>
ELSE
MACHINE MC68000
ENDIF
IF (NOT forROM) THEN ; <31> DTY <PN> <SM3> CSS
CASE OBJ
ENDIF
IF (NOT forROM) THEN ;<1.6-11april89-CEL> & <31> DTY
;—————————————————————————————————————————————————————
; Include files…
;—————————————————————————————————————————————————————
INCLUDE 'sysequ.a' ;for SplineKey low mem
INCLUDE 'Traps.a'
INCLUDE 'Quickequ.a'
INCLUDE 'ColorEqu.a'
INCLUDE 'ToolEqu.a'
INCLUDE 'QDHooks.a'
INCLUDE 'SplineDefines.a'
INCLUDE 'fontPrivate.a'
INCLUDE 'SysPrivateEqu.a'
;—————————————————————————————————————————————————————
ENDIF ;<1.6-11april89-CEL>
INCLUDE 'LinkedPatchMacros.a' ; <31> DTY
INCLUDE 'InternalOnlyEqu.a' ; <PN>
if (hasDoubleByte) then
include 'Script.a'
endif
ROMTrimRect ROMBIND (SE, $1692A), (Plus, $C1BA), (Portable, $23A10)
ROMRSect ROMBIND (SE, $14880), (Plus, $A110), (Portable, $212C6)
;————————————————————————————————————————————————————————————————————————————————————————————————
;
; 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.
;
; DrText will handle both bitmap FONTs, NFNTs and new spline font
; sfnts.
;
;————————————————————————————————————————————————————————————————————————————————————————————————
IF HAS_COLOR THEN
DrText PROC EXPORT
ELSE
BWDrText PROC EXPORT
ENDIF
; If the portVersion/rowBytes of any port has the following bits set, it is a GWorld
GWorldFlag equ $C001 ; isPixMap+isCPort+isGWorld
IF TIME_SPEED THEN
IMPORT INITTIMER, READTIMER, RESETTIMER
ENDIF
IMPORT ArithMode
IMPORT GetStyleBufHand
IMPORT CalcCharExtra
IF &TYPE('JStdTxMeas') = 'UNDEFINED' THEN
IMPORT JStdTxMeas
ENDIF
;————————————————————————————————————————————————————————————————————————————————————————————————
; Font structure for bitmaps
;
; 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 fKernMax
FBBOY EQU 10 ;WORD save as nDescent; unused except as high owTLoc
FBBDX EQU 12 ;WORD fRectWidth
FBBDY EQU 14 ;WORD fRectHeight
LENGTH EQU 16 ;WORD owTLoc
locASCENT EQU 18 ;WORD Conflict with other Ascent and Descent defines
locDESCENT EQU 20 ;WORD
XOFFSET EQU 22 ;WORD leading
RASTER EQU 24 ;WORD rowWords
;————————————————————————————————————————————————————————————————————————————————————————————————
; Input parameters
;
; 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
;————————————————————————————————————————————————————————————————————————————————————————————————
; Stack Frame for locals
;
; A6 OFFSETS OF LOCAL VARIABLES AFTER LINK:
;
SAVESTK EQU -4 ;long stack before allocating buffers
TEXTRECT EQU SAVESTK-8 ;RECT original bounding rect
TEXTR2 EQU TEXTRECT-8 ;RECT copy of textRext used by maprect
SRCRECT EQU TEXTR2-8 ;RECT original shadow bounding rect
DSTRECT EQU SRCRECT-8 ;RECT copy of srcRect used by maprect
MINRECT EQU DSTRECT-8 ;RECT minimum rect for clipping
BUFEND EQU MINRECT-4 ;LONG where the offscreen buffer ends
BUFSIZE EQU BUFEND-4 ;LONG the size of the offscreen buffer
BUFROW EQU BUFSIZE-2 ;WORD the rowBytes for the offscreen buffer
BUF2START EQU BUFROW-4 ;LONG second buffer used for shadow
BUF2END EQU BUF2START-4 ;LONG where shadow buffer ends
BUFLEFT EQU BUF2END-2 ;WORD output left edge
sHeight EQU BUFLEFT-2 ;WORD font fRectHeight copy
SRCPTR EQU sHeight-4 ;LONG used only in wide character case as temp
DSTPTR EQU SRCPTR-4 ;LONG used only in wide character case as temp
maskStart EQU DSTPTR-4 ;LONG \ start of mask buffer
maskAddr EQU maskStart-4 ;LONG >- these 3 grouped: address of mask bits
mSrcRow EQU maskAddr-4 ;LONG / rowbytes of mask bits
FROMRECT EQU mSrcRow-8 ;RECT mapRect parameter
TORECT EQU FROMRECT-8 ;RECT mapRect parameter
PENLOC EQU TORECT-4 ;POINT copy of original pnLoc
SPWIDTH EQU PENLOC-4 ;FIXED POINT width of space
CHARLOC EQU SPWIDTH-4 ;FIXED POINT fractional pen position
HEIGHTAB EQU CHARLOC-4 ;LONG pointer to font height table
WIDTAB EQU HEIGHTAB-4 ;LONG pointer to font offset/width table
LOCTAB EQU WIDTAB-4 ;LONG pointer to font location table
SAVEA5 EQU LOCTAB-4 ;LONG register saved so can be reused
characterExtra EQU SAVEA5-4 ;LONG fixed point extra added to each character
maskBitsPtr EQU characterExtra-4 ;LONG pointer to maskBits, sourcePix, or 0
bkCol EQU maskBitsPtr-4 ;LONG full of the background color
leftBack EQU bkCol-4 ;LONG bkCol masked to the left part of the character
rightBack EQU leftBack-4 ;LONG bkCol masked to the right part of the character
realBounds EQU rightBack-4 ;LONG USED FOR SHIELDCURSOR
leftOffset EQU realBounds-8 ;2 LONGs offset used by bit field instructions in charblt
maskSize EQU leftOffset-2 ;WORD size of mask buffer
mBufRow EQU maskSize-2 ;WORD \ these 2 mask buffer row size
maskBlts EQU mBufRow-6 ;3 WORDS / grouped: saved state for mask blit
FAKERGN EQU maskBlts-10 ;RECTANGULAR REGION
FAKEPTR EQU FAKERGN-4 ;LONG, FAKE MASTER POINTER
INFO EQU FAKEPTR-8 ;4 WORDS font info record returned by txMeasure (unused)
numer2 EQU INFO-4 ;Point copy of numer for iterative case
denom2 EQU numer2-4 ;Point copy of denom for iterative case
charsRemain EQU denom2-2 ;word remaining characters to draw in iterative case
srcBits EQU charsRemain-14 ;bitMap input to shadow stretchBits, bitsToPix
srcPix EQU srcBits-(pmRec+ctRec+20) ;pixMap input to normal stretchbits
maskBits EQU srcPix-14 ;bitMap input to bitsToPix for font mask
DSTPIX EQU maskBits-(pmRec+ctRec+20) ;pixMap destination
FASTFLAG EQU DSTPIX-1 ;BYTE flag set if source ORing to screen is OK
maskFont EQU FASTFLAG-1 ;byte flag set if a maskFont is available + requested
Stretch EQU maskFont-1 ;BOOLEAN flag set if numerator not equal denominator
heightFlag EQU Stretch-1 ;byte flag set if font has a height table
topHt EQU heightFlag-2 ;word character top & height from font or clip
maxMin EQU topHt-2 ;word number of characters in font
minCh EQU maxMin-2 ;word first character in font
bitDepth EQU minCh-2 ;word \ These two bits per pixel in font
bkCol1 EQU bitDepth-2 ;word / grouped. 1 pixel worth of background color
kernAdjust EQU bkCol1-2 ;word pen adjustment to kerning and italic
kernBounds EQU kernAdjust-2 ;word boundary adjustment due to kerning and italic
penLocHFrac EQU kernBounds-2 ;word fractional pen position for recursive calls
penLocFixed EQU penLocHFrac-2 ;word fractional pen position for recursive calls
longCount EQU penLocFixed-2 ;word loop counter for doMove
charWidth EQU longCount-2 ;word width in pixels of current character blt
stackOffset EQU charWidth-2 ;word 2 if stack was word aligned before link
countCopy EQU stackOffset-2 ;word copy of character count, decremented as drawn
CRSRFLAG EQU countCopy-1 ;BYTE set if crsr is shielded (to screen) <1.6-11april89-CEL>
MMUSave EQU CRSRFLAG-1 ;BYTE MMU mode on entry to drawText <1.6-11april89-CEL>
locMode EQU MMUSave-2 ;word copy of text mode, adjusted if arith. + 1 bit <1.6-11april89-CEL>
bitShift EQU locMode-2 ;word how far to shift to multiply by bitDepth
orNotOK EQU bitShift-1 ;Boolean true if bit extract/insert must be used instead
notMaskPass EQU orNotOK-1 ;Boolean true if blit is not creating font mask
textCopyMode EQU notMaskPass-1 ;Boolean true if blit must use extract/insert
orMode EQU textCopyMode-1 ;Boolean true if mode is srcOr & forecolor is black
colorSource EQU orMode-1 ;Boolean true if font contains colors (nonblack/white)
saveHilite EQU colorSource-1 ;byte saved hilite flag for iterative state
unused1 EQU saveHilite-1 ;byte extra byte for somebody maybe Snapper-Head Joe
is32QD EQU unused1-1 ;32 bit QD is around
sAscent EQU is32QD-2 ;word for Ascent
sDescent EQU sAscent-2 ;word for Descent
rExtraHang EQU sDescent-2 ;word Right over hang max
repeatBands EQU rExtraHang-2 ;word repeat banding for clipping regions off stack
LItalicExtra EQU repeatBands-2 ;word Left italic extra
RItalicExtra EQU LItalicExtra-2 ;word Right italic extra
isSpline EQU RItalicExtra-1 ;byte for flag
cacheState EQU isSpline-1 ;byte memory state for cache
fontState EQU cacheState-2 ;word Save the state of the font
clipStorage EQU fontState-4 ;long pointer to top of stack for clipping
origCharCount EQU clipStorage-2 ;long pointer to top of stack for clipping
saveMode EQU origCharCount-2 ;Transfer mode safe copy
origTopClip EQU saveMode-2 ;WORD yMax Clipping
origBotClip EQU origTopClip-2 ;WORD yMin Clipping
bufHeight EQU origBotClip-2 ;Height of buffer needed
currentEnd EQU bufHeight-4 ;Current end of style buffer for allocation
bufferPtr EQU currentEnd-4 ;Pointer to style buffer
stackHandle EQU bufferPtr-4 ;Handle to style buffer
trimSrcRect EQU stackHandle-8 ;RECT trimmed source rect for init
cacheHand EQU trimSrcRect-4 ;Handle to the cache
cachePtr EQU cacheHand-4 ;Pointer to the cache
glyphArray EQU cachePtr-4 ;Pointer to the glyph array
topAdjust EQU glyphArray-2 ;(word)Top adjustment to calc destination
widTabPtr EQU topAdjust-4 ;(long)Pointer to the fixed width table
STARTTIME EQU widTabPtr-4 ;reserved for Chazz-man TIMINGS
READADJ EQU STARTTIME-4 ;reserved for Chazz-man TIMINGS
wordFunc EQU READADJ-4 ;pointer to word blit routine
bigWordFunc EQU wordFunc-4 ;pointer to big word blit routine
longFunc EQU bigWordFunc-4 ;pointer to long blit routine
bigLongFunc EQU longFunc-4 ;pointer to big long blit routine
overLongFunc EQU bigLongFunc-4 ;pointer to over long blit routine
destShift EQU overLongFunc-2 ;word destination shift value
textPtr EQU destShift-4 ;copy of text addr
a4Check EQU textPtr-4 ;Temporary may rip out later - only checking for stack crash
a6Check EQU a4Check-4 ;Temporary may rip out later - only checking for stack crash
needs32Bit EQU a6Check-1 ;used by KON-mon, device deeds to be addressed in 32-bit mode
notFastFlag EQU needs32Bit-1 ;do not go fast if set
rOverHMax EQU notFastFlag-2 ;word right overhang maximum
lowByte EQU rOverHMax-1 ;(boolean) is this a double-byte font?
highByte EQU lowByte-1 ;(byte) low-byte of double-byte character.
encodingTable EQU highByte-4 ;(pointer) encoding table address.
FREEBYTE EQU encodingTable-1 ;(byte)
doDither EQU FREEBYTE-1 ;(byte) Set if dither is needed
synFont EQU doDither-1 ;(byte) Set if this is a synthetic font
fluff EQU synFont-1 ;(byte)
myPort EQU fluff-4 ;The current grafport
maskTabPtr EQU myPort-4 ;ptr to mask table <62-CEL>
resvLong1 EQU maskTabPtr-4 ;reserved for Chazz-man <62-CEL>
resvLong2 EQU resvLong1-4 ;reserved for Bruce-dude
resvLong3 EQU resvLong2-4 ;reserved for Kon-chap
resvLong4 EQU resvLong3-4 ;reserved for Kindness
resvLong5 EQU resvLong4-4 ;reserved for Joe-schmoe
;———————————————————————————————————————
;sb_Retrieves input struct - Do not split this record up!!!
;###WARNING: If this changes, then change the same record in OutlineMetrics.a
bufStart EQU resvLong5-4 ;(long) _ \ start of bits buffer <jdt 14Mar90>
srcAddr EQU bufStart-4 ;(long) | >- these 3 grouped: ptr to bits
srcRow EQU srcAddr-4 ;(long) |/ rowbytes of font bits
bitWidth EQU srcRow-2 ;(word) | for Width of char in bits
entryOffset EQU bitWidth-4 ;(long) | entry offset of glyph
fillBYTE EQU entryOffset-1 ;(Boolean) |
nextBand EQU fillBYTE-1 ;(Boolean) | Another character band?
nextTopBand EQU nextBand-2 ;(word) | next top character band
nextBotBand EQU nextTopBand-2 ;(word) | next bot character band
bandScan EQU nextBotBand-2 ;(word) | band size of char band
scan EQU bandScan-2 ;(word) | number of scan lines
devLSB EQU scan-2 ;(short) | Device for the LSB (short)
lsb EQU devLSB-4 ;(long) | for the LSB (fixed)
yMax EQU lsb-2 ;(word) | for the y min (short)
yMin EQU yMax-2 ;(word) | for the y max (short)
topClip EQU yMin-2 ;(word) | yMax Clipping
botClip EQU topClip-2 ;(word) | yMin Clipping
clipHorz EQU botClip-1 ;(Boolean) \ | Is it clipped horizontally
clipVert EQU clipHorz-1 ;(Boolean) / | Is it clipped vertically
destDepth EQU clipVert-2 ;(word) | depth of destination **CAN take out
ptSize EQU destDepth-2 ;(word) | pixels per em **CAN take out
glyphID EQU ptSize-2 ;(word) | glyph code
fontID EQU glyphID-2 ;(word) _ font id code *** get rid of unwanted vars
;End of Structure
;———————————————————————————————————————
VARSIZE EQU ((fontID-3)/4)*4 ;SIZE OF VARIABLES long aligned <6> CEL
;————————————————————————————————————————————————————————————————————————————————————————————————
; Aligning the Stack
;
; MAKE SURE THE STACK IS ON A LONGWORD BOUNDARY (FOR FASTBUFFERS)
;
; Register Use:
; A3 = thePort
; A4 = QuickDraw Globals
; A6 = Stack frame
; A5 = Grafport handle
;
; Clobbers:
; D0
;
MOVE.L D0,A0 ;save D0 $$$ WHY
MOVE.L SP,D0 ;GET THE STACK POINTER
ASR #2,D0 ;WORD BOUNDARY?
SCS D0 ;remember balance
BCC.S STKOK ;=>NO, GOT LONG BOUNDARY
SUBQ #2,SP ;ELSE MAKE STACK LONG ALIGNED
STKOK
LINK A6,#VARSIZE ;ALLOCATE TEMP VARS
AND #2,D0 ;amount stack was adjusted by
MOVE D0,stackOffset(A6)
MOVE.L A0,D0 ;restore D0 $$$ WHY
MOVEM.L D0-D7/A1-A4,-(SP) ;SAVE REGS
MOVE.L SP,SAVESTK(A6) ;remember where the 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
IF (hasSplineFonts OR Gaudi) THEN
MOVE.L expandMem,A0 ; get low memory expand pointer. <61-CEL/RWB>
MOVE.L ExpandMemRec.emSplineKey(A0),A0 ; get handle to splineKey globals. <61-CEL/RWB>
MOVE.L (A0), A0 ; get pointer to splineKey globals. <61-CEL/RWB>
MOVE.W #-2, splineKeyRec.safeCount(A0) ;init to -1 for flagging <61-CEL/RWB>
ENDIF
IF HAS_COLOR THEN
MOVE.B splineKeyRec.is32bit(A0),is32QD(A6) ; get 32 bit CQD flag in CCR.
MOVE.L TheGDevice,LastTxGDevice ;save the text device for next time
;————————————————————————————————————————————————————————————————————————————————————————————————
;
; CONVERT DSTBITS (THE PORT) TO A PIXMAP
; (A5 must contain global ptr)
;
LEA PORTBITS(A3),A1 ;GET PORTBITS POINTER
LEA DSTPIX(A6),A2 ;GET DSTPIX POINTER
_BitsToPix ;CONVERT BITMAP
MOVE.L D1,REALBOUNDS(A6) ;SAVE REAL DST BOUNDS.TOPLEFT
IF NOT Gaudi THEN
MOVE.B D2,CRSRFLAG(A6) ;REMEMBER IF DST IS SCREEN <BAL 18Sep88>
swap d2 ; <9Apr90 KON>
move.b d2,needs32Bit(a6) ;save whether device needs 32-bit addressing<7Apr90 KON>
ELSE
CLR.B needs32Bit(a6) ;Set if 32-bit
TST.B is32QD(A6) ;check for 32 bit QD
BEQ.S @no32QD ;no so do it the old way
MOVE.B D2,CRSRFLAG(A6) ;REMEMBER IF DST IS SCREEN <BAL 18Sep88>
BNE.S @checkScreen ;yes -> check gdevice
LEA DSTPIX(A6),A2 ;GET DSTPIX POINTER
MOVE.W pmVersion(A2), D0 ;if flags are set check if 32-bit addressing
BEQ.S @doneSetFlag ;not needing 32 bit addressing so branch
BTST #2,D0 ;32-bit clean address?
SNE needs32Bit(A6) ;Set if 32-bit
BRA.S @doneSetFlag
@checkScreen
MOVE.L THEGDEVICE,A0 ;GET HANDLE TO THE GDEVICE
MOVE.L (A0),A0 ;GET POINTER TO THE GDEVICE
BTST #ext32Device,gdFlags(A0) ;does it need 32-bit addressing?
SNE needs32Bit(a6) ;Set if 32-bit
BRA.S @doneSetFlag
@no32QD
MOVE.L TheGDevice, A0 ;Get the gdevice
MOVE.L (A0), A0 ;Point at it
MOVE.L GDPMAP(A0), A0 ;Get its pixmap
MOVE.L (A0),A0 ;Point at it
MOVE.L BASEADDR(A0),D0 ;Get base of screen
CMP.L DSTPIX+BASEADDR(A6),D0 ;Drawing to the screen
SEQ CRSRFLAG(A6) ;If so, set it
@doneSetFlag
ENDIF ;Gaudi
ENDIF ;HAS_COLOR
;———————————————————————————————————————————————————
; Load the matching Font and Measure the string
;
;
MOVE stackOffset(A6),D0 ;either zero if stack was long aligned, or two if not
CLR -(SP) ;ROOM FOR FCN RESULT
MOVE.L numer(A6,D0),numer2(A6)
MOVE.L denom(A6,D0),denom2(A6) ;save original numer, denom for iterative case
MOVE COUNT(A6,D0),D1 ;get count
MOVE D1,-(SP) ;PUSH COUNT
MOVE D1,countCopy(A6) ;save copy of count
IF (hasSplineFonts) OR (Gaudi) THEN ; <31> DTY
MOVE D1,origCharCount(A6) ;save copy of count
ENDIF
MOVE.L TEXTADDR(A6,D0), A0
MOVE.L A0, textPtr(A6) ;Keep a copy for later use
MOVE.L A0, -(SP) ;PUSH TEXTADDR
PEA NUMER(A6,D0) ;PUSH VAR NUMER
PEA DENOM(A6,D0) ;PUSH VAR DENOM
PEA INFO(A6) ;PUSH VAR INFO
lea JStdTxMeas,A0 ;get piece of trap table <31> DTY Changed from move.l
move.l (a0),a0
IF NOT HAS_COLOR THEN
MOVE.L (A0),A0
ENDIF
JSR (A0) ;MEASURE TEXT
;———————————————————————
; Set up mask table ptr
;———————————————————————
IF NOT HAS_COLOR THEN
_GetMaskTable
move.l a0,maskTabPtr(a6)
ENDIF
;——————————————————————
; Fix for overflow of stdtxmeas
;——————————————————————
IF (hasSplineFonts OR Gaudi) THEN ; <31> DTY <59-CEL/RWB>
MOVE.L expandMem,A0 ; get low memory expand pointer. <59-CEL/RWB>
MOVE.L ExpandMemRec.emSplineKey(A0),A0 ; get handle to splineKey globals. <59-CEL/RWB>
MOVE.L (A0), A0 ; get pointer to splineKey globals. <59-CEL/RWB>
CMP.B #-1, splineKeyRec.safeCount(A0) ; check to see if count changed <59-CEL/RWB>
BEQ.S @noOverFlow ; <59-CEL/RWB>
MOVE.W splineKeyRec.safeCount(A0), D1 ;get safe count in reg for assigns <59-CEL/RWB>
MOVE stackOffset(A6),D0 ;either zero if stack was long aligned, or two if not <59-CEL/RWB>
MOVE D1, COUNT(A6,D0) ;new count <59-CEL/RWB>
MOVE D1, countCopy(A6) ;save copy of count <59-CEL/RWB>
MOVE D1, origCharCount(A6) ;save copy of count <59-CEL/RWB>
@noOverFlow ; <59-CEL/RWB>
ENDIF
;——————————————————————
; Get the Width in D1
;——————————————————————
ADDQ #2,SP ;POP (and ignore) UNSCALED WIDTH RESULT
MOVE.L fontAdj(A4),D1 ;get fixed point width
MOVE.L fontPtr(A4),A4 ;Point to FmOutput record
IF HAS_COLOR THEN
TST.B is32QD(A6)
BEQ.S @1
move portVersion(a3),d0 ; get the port's portVersion/rowBytes
and #GWorldFlag,d0 ; mask all other bits than the GWorldFlag
cmp #GWorldFlag,d0 ; is it exactly equal to GWorldFlag?
BNE.S @1
MOVEM.L A0-A1/D0-D2,-(SP) ;Save registers
clr.l -(sp) ; leave room for Ptr result
move.l portPixMap(a3),-(sp) ; push handle to pixmap
_GetPixBaseAddr ; get address of offscreen buffer
move.l (sp)+,d0 ; put it in d0
MOVE.L D0, DSTPIX+BASEADDR(A6) ;
MOVEM.L (SP)+, A0-A1/D0-D2 ;Restore registers
ST needs32Bit(A6) ; sending 32-bit data
@1 MOVE.W dstPix+pixelSize(A6),destDepth(A6) ;Get the pixel depth
ELSE
MOVE.W #1,destDepth(A6)
ENDIF
IF (hasSplineFonts) OR (Gaudi) THEN ; <31> DTY
;———————————————————————————————————————————————————
; DO FORK
;
; Check if splines or bitmaps and make the fork!!!
;
;
if (hasDoubleByte) then
clr.l encodingTable(a6) ; assume no encoding table.
endif
MOVE.L WidthTabHandle, A1 ;Get the Width Table
MOVE.L (A1), A1 ;Dereference the table
TST.B WidthIsSpline(A1) ;Is it a spline font
BEQ BitVarSetUp ;Not spline then branch
;————————————————————————————————————————————————————————————————————————————————————————————————
; STARTING hasSplineFonts SETUP
;————————————————————————————————————————————————————————————————————————————————————————————————
;————————————————————————————————————————————————————————————————————————————————————————————————
; SPLINE Stack Variable SetUp
;
; Registers on Entry:
; A4 = Graf globals
;
; Registers used:
; A1 = WidthPtr
; A6 = Stack frame
; A4 = FmOutput record ptr
;
; Preserves:
; D1 = Width of string (We could save it on the stack to be safe!!!
;
; CLOBBERS: D0, D2, D3
;
;————————————————————————————————————————————————————————————————————————————————————————————————
;————————————————————————————————————
; Set flags
;————————————————————————————————————
ST isSpline(A6) ;Set is a spline font
SF clipVert(A6) ;Init to no clip <6> CEL
SF doDither(A6) ;No dither for 1-bit splines
SF clipHorz(A6) ;Init to no clip <6> CEL
SF nextBand(A6) ;init to no next char band
CLR.L maskBitsPtr(A6) ;assume no mask
CLR.L stackHandle(A6) ;clear stackHandle
CLR.W repeatBands(A6) ;no banding at first
CLR.W bitShift(A6) ;Incoming 1 deep
CLR.W kernAdjust(A6) ;init kern value
CLR.W rExtraHang(A6) ;init rExtraHang value
CLR.B stretch(A6) ;set up bit insert/extract flag
CLR.B colorSource(A6) ;if so, pass info to stretch later
MOVE.W #1,bitDepth(A6) ;bits per pixel
MOVE.B WidthNotFast(A1), notFastFlag(A6) ;Looks like fast if set
;————————————————————————————————————
; get cache and Save metrics on stack
;————————————————————————————————————
WITH cache ; <47-CEL>
MOVE.L expandMem, A2 ; get low mem expand <47-CEL>
MOVE.L ExpandMemRec.emSplineKey(A2), A2 ; Handle to splineKey <47-CEL>
MOVE.L (A2), A2 ; pointer to splinekey <47-CEL>
MOVE.L splineKeyRec.cacheHand(A2), D2 ; Do we even have a cache???
BEQ GOHOME ; bail since we have no cache
MOVE.L D2, A2 ;cacheHand in Addr reg
MOVE.L A2, cacheHand(A6) ;get a copy of cache hand
MOVE.L (A2), D2 ;cache pointer
BEQ GOHOME ;is purged? <65-CEL>
MOVE.L D2, A2 ;pointer to the cache in addr reg
if (hasDoubleByte) then
move.l fEncodingTablePointer(a2),encodingTable(a6) ; load encoding table pointer.
endif
MOVE.W yMax(A2), sAscent(A6) ;set stack Ascent
MOVE.W yMin(A2), sDescent(A6) ;Place descent on stack
MOVE.W height(A2), sHeight(A6) ;Place Height on stack
;—————————————————
; OverHang calcs
;—————————————————
;regs used:
; D2 = cachePtr
; A2 = glyphArrayPtr
;
MOVEQ #0,D5
MOVEQ #0,D3
if (hasDoubleByte) then
tst.l encodingTable(a6) ; <SM4> CSS <76> Is this a double byte font?
bz.s @getFirstAndLastCharacters ; <SM4> CSS <76> If not, dont add these overhang values
move.w rOverHMax(a2),d0 ; get right overhang value
add.w rightItalic(a2),d0 ; add in possible italic overhang
move.w d0,rExtraHang(a6) ; initialize total right overhang
endif
ENDWITH
@getFirstAndLastCharacters
MOVE.L textPtr(A6),A0 ;pointer to the text
MOVE countCopy(A6),D0 ;get count <6> CEL use d0 instead of d3
SUBQ.W #1, D0 ;count-1 is last char index
MOVE.B (A0),D5 ;first character
MOVE.B (A0,D0),D3 ;last character <6> CEL
if (hasDoubleByte) then
move.b d5,highByte(a6) ; save the high byte for later use.
clr.b lowByte(a6) ; clear the low byte for now
tst.l encodingTable(a6) ; is this a double byte font?
beq.s @normalFont ; no, skip low byte loading
move.l encodingTable(a6),a2 ; load the encoding table
tst.b 0(a2,d5.w) ; is this a double byte character?
beq.s @normalCharacter ; no, skip low byte loading
move.w countCopy(a6),d0 ; get the text length
cmpi.w #1,d0 ; is there a low byte character?
bls @remapCharacterToNull ; no, remap the high byte
adda.w #256,a2 ; offset to the lowByte encoding table.
clr.w d0 ; clear high byte of low word
move.b 1(a0),d0 ; grab the low byte.
tst.b 0(a2,d0.w) ; is this a valid low byte?
beq @remapCharacterToNull ; no, remap the high byte
move.b d0,lowByte(a6) ; save the valid low byte for later use
bra @normalCharacter ; continue normally.
@remapCharacterToNull
move.b #1,d5 ; remap the high byte character
move.b d5,highByte(a6) ; save the remapped value in the stack for later use
bra @doRSB ; skip the rest of this stuff
@normalCharacter
@normalFont
endif
MOVE.L D2, A0 ;cache pointer
LEA cache.glyphArray(A0), A2 ;Get array of glyphs into A2
IF &SETTING('MACHINE') <> 'MC68000' THEN
MOVE.L 0(A2,D5*4),D0 ;Get offset to glyph in D0
ELSE
MOVE.W D5,D0
ADD.W D0,D0
ADD.W D0,D0
MOVE.L 0(A2,D0),D0
ENDIF
BGT.S @okayGlyph
BTST.L #30, D0 ;Check if there is an error
BNE.S @doRSB ;branch if error
AND.L #$3FFFFFFF, D0 ;Clear contour entry bit flag
BNE.S @okayGlyph ;Got the info
BSR renderChar ;get the glyph and returns non-zero error
BEQ.S @doRSB ;skip this glyph <58-CEL>
BRA.S @checkLSB ;did not get the offset <58-CEL>
@okayGlyph
ADD.L D2, D0 ;glyphrec = cache + offset
MOVE.L D0, A0 ;in address reg
if (hasDoubleByte) then
clr.l d0 ; clear a long for the character code
move.b lowByte(a6),d0 ; double byte character?
beq.s @checkLSB ; no, skip this
IF &SETTING('MACHINE') <> 'MC68000' THEN
move.l 0(a0,d0.w*4),d0 ; load glyph record offset
ELSE
add.w d0, d0
add.w d0, d0
move.l 0(a0,d0.w),d0
ENDIF
bgt.s @haveGlyphOffset ; skip checks if positive
btst.l #30,d0 ; error rendering glyph?
bne.s @doRSB ; yes, skip this glyph
and.l #$3fffffff,d0 ; clear contour and error flags
bne.s @haveGlyphOffset ; skip rendering if positive
bsr renderChar ; can render the glyph?
beq.s @doRSB ; no, skip this glyph
bra.s @checkLSB ; already have the offset
@haveGlyphOffset
add.l d2,d0 ; convert offset to pointer
move.l d0,a0 ; load glyph record pointer
endif
@checkLSB
MOVE.W glyph.devLSB(A0), D0 ;Get integralized left side bearing
BGE.S @doRSB
ADD.W D0, kernAdjust(A6) ;Save extra copy that can contain italic extra
@doRSB
if (hasDoubleByte) then
tst.l encodingTable(a6) ; is this a double byte font?
bne.s @doneOverHang ; yes, skip overhang calculations
endif
MOVE.W D3, D5 ;copy of D3
IF &SETTING('MACHINE') <> 'MC68000' THEN
MOVE.L 0(A2,D3*4),D0 ;Get offset to glyph in D0
ELSE
ADD.W D3, D3
ADD.W D3, D3
MOVE.L 0(A2,D3),D0
ENDIF
BGT.S @okayGlyph2
BTST.L #30, D0 ;Check if there is an error
BNE.S @doneOverHang
AND.L #$3FFFFFFF, D0 ;Clear contour entry bit flag
BNE.S @okayGlyph2 ;Got the info
MOVE.W D5, D0 ;D0 for renderchar
BSR renderChar ;get the glyph and returns non-zero error
BEQ.S @doneOverHang ;skip this glyph <58-CEL>
BRA.S @calcROverHang ;got the glyph <58-CEL>
@okayGlyph2
ADD.L D2, D0 ;add offset and point to glyph data
MOVE.L D0, A0 ;Get in address reg
@calcROverHang
IF &SETTING('MACHINE') <> 'MC68000' THEN
MOVE.W 0(A1,D3*4),D0 ;Get the width
ELSE
MOVE.W 0(A1,D3),D0
ENDIF
MOVE.W glyph.devLSB(A0), D3 ;Get integralized left side bearing
ADD.W glyph.bitWidth(A0), D3 ;RoverHang = (lsb+bitwidth)-Width
SUB.W D0, D3 ;
BLE.S @doneOverHang
MOVE.W D3, rExtraHang(A6)
;—————————————————
; End OverHang calcs
;—————————————————
@doneOverHang
MOVE.W sAscent(A6), topClip(A6) ;Assign Ascent as top clip initially
MOVE.W sDescent(A6), botClip(A6) ;opened up bot clip
MOVE.W botClip(A6), origBotClip(A6);Init for fakergn check
MOVE.W topClip(A6), origTopClip(A6);Init for fakergn check
MOVE txMode(A3),D0
AND #$FFF7,D0 ;clear pattern bit (let stretch reject invalid modes)
MOVE D0,locMode(A6) ;initialize copy
IF HAS_COLOR THEN
BTST #6,D0 ;bit 6 if set says use a mask
SNE D3 ;remember it
BEQ.S @notMask
LEA srcPix(A6),A0 ;assume no mask font needed; just use source instead
MOVE.L A0,maskBitsPtr(A6) ;pass mask to stretch bits
@notMask
MOVE.B D3,maskFont(A6) ;0 if mask bit clear, no mask font, or incoming 1 deep
MOVE.B D3,textCopyMode(A6) ;set up bit insert/extract flag
ENDIF
BTST #5,D0 ;arithmetic mode?
BEQ.S @doneMode ;if not, dont map if dest. is 1 bit deep
IF HAS_COLOR THEN
CMP #1,dstPix+pixelSize(A6) ;1 bit deep destination?
BNE.S @doneMode ;if not, arithmetic mode is OK
ENDIF
LEA ArithMode,A0 ;get mode map
AND #7,D0 ;look at each different arith mode
MOVE.B 0(A0,D0),D0 ;map into 1 bit safe mode
MOVE D0,locMode(A6) ;alter mode properly for 1 bit depth
@doneMode
;————————————————————————————————————————————————————————————————————————————————————————————————
; Bounding Rect set up
;
; Setup textRect, the rectangle bounding the entire string.
;
; Registers on Entry:
; A2 = Font Ptr
; A3 = thePort
; A4 = FmOutput record ptr
; A6 = Stack frame
;
; D1 = Width of string
;
; Register Use:
; D2 = PenLocation (Set up as fixed)
;
; Clobbers:
; D0, D3
;
;————————————————————————————————————————————————————————————————————————————————————————————————
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
SWAP D2
IF hasPenFraction THEN
move.l grafGlobals(a5),a0 ; load quickDraw globals.
move.w pnLocFixed(a0),d2 ; append pen fraction.
move.w d2,penLocFixed(a6) ; save pen fraction for recursive drawing.
ELSE
move.w #$8000,d2 ; append default fraction.
ENDIF
;———————————————————————————————————————————————————————————————
; set flag to note if mode is srcOr & foreColor is black
; set up characterExtra if new port or script manager around
; set up pnLocHFrac if new port
;———————————————————————————————————————————————————————————————
CMP #srcOr,locMode(A6) ;is the mode srcOr?
SEQ orMode(A6)
BCLR #6,locMode+1(A6) ;was mask set?
BEQ.S @noMaskMode
TST locMode(A6) ;is it srcCopy + mask?
SEQ orMode(A6) ;that can go fast, too.
@noMaskMode
moveq #0, d0 ; clear the character extra. <49>
IF HAS_COLOR THEN
tst.b portBits+rowBytes(a3) ; is this an old grafPort?
bpl.s @oldGrafPort ; yes -> skip this.
move.w chExtra(a3),d0 ; load the character extra.
ext.l d0 ; for sign bits <49>
asl.l #4,d0 ; convert to 16.16 format.
@oldGrafPort
ENDIF
IF SCRIPT_CHAR_EXTRA THEN
move.l grafGlobals(a5),a0 ; load quickDraw globals. <43>
add.l qdChExtra(a0),d0 ; add in the character extra. <43>
ENDIF
tst.l d0 ; have zero character extra?
beq.s @zeroCharExtra ; yes -> skip call to scale.
bsr CalcCharExtra ; scale by point size, etc.
@zeroCharExtra
move.l d0,characterExtra(a6) ; store scaled character extra.
IF HAS_COLOR THEN
TST PORTBITS+ROWBYTES(A3) ; is it a new port?
BPL.S @useOld1 ; no -> dont set up fraction
MOVE pnLocHFrac(A3),D2 ; set up with proper fraction
MOVE D2,penLocHFrac(A6) ; save for later as well for recursive drawing
;———————————————————————————————————————————————————————————————————————————————————————
; ForeGround - BackGround check
;
; This next part is a little tricky:
; If the source does not contain any colors (that is, regardless of whether the source is
; one bit per pixel or more, the pixels are either black or white) then we can go fast if
; the forecolor is black, regardless of the background color. If the font does contain colors,
; then we can go fast if the background is white, regardless of the foreground colors.
;
; But, if the foreground and background pixels are equal (but the font is a 1 bit font), then go
; slow. ColorMap will be called later to sort out whether the foreground color needs to be
; remapped or not.
;———————————————————————————————————————————————————————————————————————————————————————
;———————————————————————————————————
; This is the real code
;———————————————————————————————————
MOVE.L fgColor(A3),D0
MOVE dstPix+pixelSize(A6),D3 ;bits per pixel
CMP.W #1, D3 ;1 bit depth???
BNE.S @multiDepth
CMP.L bkColor(A3),D0 ;same as background? <66>
beq.s @goSlow ; <66>
tst.l d0 ;forecolor white? <66>
BNE.S @doneCheck ;We are okay
BRA.S @goSlow ;forecolor white, use stretch <66>
@multiDepth
CMP.W #16, D3 ;16 or 32 bit???
BLT.S @not16or32
TST.L D0 ;If zero then black
BEQ.S @doneCheck ;Do not change mode if black
CLR.B orMode(A6) ;Do not do fast case
BRA.S @doneCheck ;done so continue
@not16or32
CMP.L bkColor(A3),D0 ;same as background?
BEQ.S @goSlow ;if so, go slow
ADDQ.L #1,D0 ;now equal to number of colors, if black
LSR.L D3,D0 ;1 if black, 0 if other color
@goSlow
SNE D0 ;remember if black (or if fg/bk pixels are not equal)
BRA.S @oldCommon
@useOld1
ENDIF ;HAS_COLOR
BTST #5,fgColor+3(A3) ;is the foreground color black?
SNE D0 ;set to zero if not
@oldCommon
AND.B D0,orMode(A6) ;true if or mode and black monochrome or white multi.
@doneCheck
ADD.L D1,D2 ;right := left + width
SWAP D2 ;just look at high word
TST.B fmOutCurStyle(A4)
BEQ @noSlop ;if no style, certainly no slop
MOVEQ #0,D0 ;clear out high word
ADD.B fmOutBold(A4),D0 ;add boldness
EXT D0 ;make it a word
MOVEQ #4,D3 ;restrict shadow in the range of 0 .. 3 (+1 if shadow)
CMP.B fmOutShadow(A4),D3 ;is it less or same?
BLE.S @pinShadow ;if so, pin at limit
MOVE.B fmOutShadow(A4),D3 ;otherwise, pass actual value
BEQ.S @pinShadow
ADDQ #1,D3 ;plus 1 for character insides shifted to right
@pinShadow
ADD D3,D0 ;combine shadow with italic slop count
ADD D0,D2 ;SLOP FOR ITALIC,BOLD,OVERSTRIKE
@noSlop
MOVE.W kernAdjust(A6), D0 ;reg for add
ADD.W D0,textRect+left(A6) ;include kerning in text rectangle
ADD.W rExtraHang(A6), D2 ;Add in extra for right over hang max
MOVE.W D2,TEXTRECT+RIGHT(A6) ;STORE IN TEXTRECT.RIGHT
MOVE PENLOC(A6),D2 ;GET PNLOC.V
SUB sAscent(A6),D2 ;Use the stack Ascent
MOVE D2,TEXTRECT+TOP(A6) ;TEXTRECT.TOP := PNLOC.V - ASCENT
ADD sHeight(A6),D2 ;Height metric off stack
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
ANDI #$0F,CCR ; need to clear 'x' flag
IF hasPenFraction THEN
move.l grafGlobals(a5),a0 ; load quickDraw globals.
add.w d1,pnLocFixed(a0) ; add width fraction to location fraction.
ENDIF
IF HAS_COLOR THEN
TST PORTBITS+ROWBYTES(A3) ; is it a new port?
BPL.S @useOld ; no, dont bother with fraction
ADD D1,pnLocHFrac(A3)
@useOld
ENDIF
;—————————————————————————————
; Move pen by the scaled text width
;—————————————————————————————
SWAP D1 ;Make integer
MOVE PNLOC+H(A3),D0 ;Get the current pen location
ADDX D1,D0 ;New Pen Loc = OldPenLoc + TextWidth
MOVE D0,PNLOC+H(A3) ;Save new pen location
;————————————————————————————
; Quit if the pen is hidden
;————————————————————————————
TST PNVIS(A3) ;IS PNVIS < 0 ?
BLT GOHOME ;YES, QUIT
;————————————————————————————————————————————————————————————————————————————————————————————————
; END Bounding Rect set up
;————————————————————————————————————————————————————————————————————————————————————————————————
;————————————————————————————————————————————————————————————————————————————————————————————————
; Calculate the MinRect
;
; Calc minRect: the intersection of textRect, bitMap bounds,
; clipRgn and visRgn bounding boxes. Quit if no intersection.
; The right bounds of the destination rect is set to the max to allow right kerning
; (Right kerning only works (without trailing spaces) in OR mode.
;
; Registers on Entry:
; A2 = Font Ptr
; A3 = thePort
; A4 = FmOutput record ptr
; A6 = Stack frame
;
; Clobbers:
; A0, A1
; D0, D1, D2, D3
;
;————————————————————————————————————————————————————————————————————————————————————————————————
MOVE textR2+right(A6),-(SP) ;preserve existing right
MOVE #32000,textR2+right(A6) ;get right from other rects
PEA TEXTR2(A6) ;PUSH (MAPPED) TEXTRECT
IF HAS_COLOR THEN
PEA DSTPIX+BOUNDS(A6) ;PUSH PIXMAP BOUNDS
ELSE
PEA PORTBITS+BOUNDS(A3) ;PUSH PIXMAP BOUNDS
ENDIF
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
IF HAS_COLOR THEN
_RSECT ;CALC INTERSECTION
ELSE
jsrROM ROMRSect
ENDIF
BEQ GOHOME ;QUIT IF NO INTERSECTION
MOVE (SP)+,textR2+right(A6) ;restore text right
;———————————————————————————————
MOVE.L VISRGN(A3),A1 ;GET VISRGN HANDLE <6> CEL
MOVE.L (A1),A0 ;DE-REFERENCE IT
CMP #10,RGNSIZE(A0) ;IS VISRGN RECTANGULAR ?
BEQ.S @rectRgn ;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
IF HAS_COLOR THEN
TST.B is32QD(A6)
BEQ.S @no32bit
MOVE.W #-1, -(SP) ;trim = true for BRUCE
@no32bit
_TRIMRECT ;CALL TRIMRECT
ELSE
jsrROM ROMTrimRect
ENDIF
BEQ.S @rectRgn
BLT GOHOME ;quit if intersection empty
ST clipHorz(A6) ;It was clipped so mark it
BRA NOTFAST ;continue if non-rectangular
@rectRgn
;GET VISRGN HANDLE <6> CEL
;———————————————————————————————
;———————————————————————————
; Spline Clip Value Set up
;———————————————————————————
MOVE.W MINRECT+TOP(A6),D0 ;GET MINRECT.TOP
SUB.W TEXTRECT+TOP(A6),D0 ;Get Text Top
BLE.S @checkBottom
ST clipVert(A6) ;It was clipped so mark it
SUB.W D0, topClip(A6) ;Adjust the top clipping value
@checkBottom
MOVE.W TEXTRECT+BOTTOM(A6),D0 ;GET MINRECT.BOTTOM
SUB.W MINRECT+BOTTOM(A6),D0 ;Is there clipping
BLE.S @checkHorz ;check horz clip
ST clipVert(A6) ;It was clipped so mark it
ADD.W D0, botClip(A6) ;Adjust the bottom clip
@checkHorz
MOVE.W botClip(A6), origBotClip(A6) ;Init for fakergn check
MOVE.W topClip(A6), origTopClip(A6) ;Init for fakergn check
MOVE.W TEXTRECT+LEFT(A6), D0 ;Get the left
CMP.W MINRECT+LEFT(A6), D0 ;clipped on left???
BGE.S @checkRight ;
ST clipHorz(A6) ;clipping on left
@checkRight
MOVE.W TEXTRECT+RIGHT(A6), D0 ;Get the right
CMP.W MINRECT+RIGHT(A6), D0 ;clipped on right???
BLE.S @doneRight
ST clipHorz(A6) ;clipping on left
@doneRight
TST.B notFastFlag(A6) ;combines the style and stretch checks
BNE NotFast ;NOT FAST
TST.B orMode(A6) ;IS TEXT MODE SRCOR ? (or srcCopy + mask, see above)
BEQ NotFast ;NO, NOT FAST
MOVE.L CLIPRGN(A3),A0 ; Get clip region
MOVE.L (A0),A0 ; Dereference handle
MOVEQ #10,D0
CMP RGNSIZE(A0),D0 ;IS CLIPRGN RECTANGULAR ?
BNE NotFast ;NO, NOT FAST
IF HAS_COLOR THEN
CMP #1, destDepth(A6) ;****1-bit we can go fast
BEQ.S @depthFast
TST.W clipVert(A6) ;Vertically or horizontally clipped then go do norm loops
BNE NotFast ;check to see if one bit only
@depthFast
ENDIF
;————————————————————————————————————————————————————————————————————————————————————————————————
; END Calculate the MinRect
;————————————————————————————————————————————————————————————————————————————————————————————————
;————————————————————————————————————————————————————————————————————————————————————————————————
; FAST case Setup
;
; Fast case, go directly to screen.
; If text is clipped vertically, then clear heightflag and update TOPHT
;
; Registers on Entry:
; A2 = Font Ptr
; A3 = thePort
; A4 = FmOutput record ptr
; A6 = Stack frame
;
; Saves & Restores:
; A2
;
; Clobbers:
;
; D0, D1
;
;————————————————————————————————————————————————————————————————————————————————————————————————
sFAST
IF HAS_COLOR THEN
TST.B is32QD(A6)
BEQ.S @not32bit
MOVEM.L A0-A1/D0-D2,-(SP) ;Save registers
@tryAgain CLR.B -(SP) ;result
MOVE.L A3, -(SP) ;needs the current grafport
_QDDone ;Is accelerator really done and ready for us to blit???
TST.B (SP)+ ;Check result
BEQ.S @tryAgain ;Check until ready!
MOVEM.L (SP)+, A0-A1/D0-D2 ;Restore registers
@not32bit
ENDIF
ST FASTFLAG(A6) ;REMEMBER WE'RE GOING FAST
IF HAS_COLOR THEN
MOVE sAscent(A6), topAdjust(A6) ;Get ascent into D0
MOVE TEXTRECT+TOP(A6),D0 ;GET DST TOP
SUB DSTPIX+BOUNDS+TOP(A6),D0 ;CONVERT TO GLOBAL COORDINATES
MOVE DSTPIX+ROWBYTES(A6),D1 ;GET ROWBYTES
AND #nuRBMask,D1 ;CLEAR OFF FLAG BITS
MULS D1,D0 ;MULT BY ROWBYTES
ADD.L DSTPIX+BASEADDR(A6),D0 ;ADD START OF DST BITMAP
MOVE.L D0,BUFSTART(A6) ;SET UP BUFSTART FOR LATER
MOVE D1,BUFROW(A6) ;SET UP BUFROW FOR LATER
MOVE DSTPIX+BOUNDS+LEFT(A6),BUFLEFT(A6) ;REMEMBER BUFLEFT
TST.B CRSRFLAG(A6) ;IS DST TO A SCREEN? <BAL 19Sep88>
BEQ @Check32Bit ;=>NO <9Apr90 KON>
PEA MINRECT(A6) ;PUSH SHIELD RECT
MOVE.L REALBOUNDS(A6),-(SP) ;PUSH DELTA FOR GLOBAL
_SHIELDCURSOR ;HIDE CURSOR IF IT INTERSECTS
@Check32Bit
tst.b needs32bit(a6) ;<9Apr90 KON>
beq.s @skip32bit ;<9Apr90 KON>
move.l a3,d0 ;get thePort ptr
_rTranslate24To32 ;mask off high byte BAL/MCF 03Dec88
move.l d0,a3 ;clean thePort ptr
MOVE stackOffset(A6),D1
MOVE.L textPtr(A6),D0 ;GET TEXTPTR
_rTranslate24To32 ;mask off high byte BAL/MCF 03Dec88
MOVE.L d0,textPtr(A6) ;SAVE FOR LATER
moveq #true32b,d0 ;switch to 32 bit addressing
_rSwapMMUMode ;get previous mode in d0.b (can trash a0/a1/a2, d0/d1/d2)
move.b d0,MMUsave(a6) ;save previous state for later
@skip32bit
ELSE
MOVE sAscent(A6), topAdjust(A6)
MOVE TEXTRECT+TOP(A6),D0
SUB PORTBITS+BOUNDS+TOP(A3),D0
MULS PORTBITS+ROWBYTES(A3),D0
ADD.L PORTBITS+BASEADDR(A3),D0
MOVE.L D0,BUFSTART(A6)
MOVE PORTBITS+ROWBYTES(A3),BUFROW(A6)
MOVE PORTBITS+BOUNDS+LEFT(A3),BUFLEFT(A6)
PEA MINRECT(A6)
MOVE.L PORTBITS+BOUNDS(A3),-(SP)
_SHIELDCURSOR
ENDIF
;————————————————————————————————————————————————————————————————————————————————————————————————
;
; Get pointers to location table, width table, and height table in font
;
;————————————————————————————————————————————————————————————————————————————————————————————————
TST.W clipVert(A6) ;Can we try the fast blitting routine???
BNE sGetPtrs ;go to clipping blit loop
fastBlit
;————————————————————————————————————————————————————————————————————————————————————————————————
; NEW FAST blit loop
;————————————————————————————————————————————————————————————————————————————————————————————————
; Registers Use:
; D0 = scratch A0 = scratch
; D1 = scratch A1 = TextPtr.l
; D2 = shift.w A2 = bitsPtr.l
; D3 = scan.w & nextBand.w(high bit) A3 = glyphArray.l
; D4 = charLoc.l A4 = widTabPtr.l
; D5 = cachePtr.l A5 = DestPtr.l
; D6 = #chars.w A6 = stack frame.l
; D7 = destRowBytes.w A7 = stack pointer.l
;————————————————————————————————————————————————————————————————————————————————————————————————
;———————————————————————-
; Figure out Charloc
;———————————————————————-
MOVE bufLeft(A6),D1 ;get bufleft in register
MOVE penLoc+H(A6),D4 ;Horz pen location
SUB D1,D4 ;charloc relative to the buffer
SWAP D4 ;turn into fixed
IF HAS_COLOR THEN
TST PORTBITS+ROWBYTES(A3) ;is it a new port?
BPL.S @useOld ;no, set fraction to 1/2
MOVE penLocHFrac(A6),D4 ;set up fractional part
BRA.S @goOn
@useOld
ENDIF
MOVE #$8000,D4 ;Treat so it will round
@goOn
;———————————————————————-
; Register setup
;———————————————————————-
MOVEQ #0, D3 ;Init for nextBand to false
MOVE.L cacheHand(A6), A0 ;Handle to the cache
IF HAS_COLOR THEN
MOVE.L (A0), D0 ;pointer to the cache
_StripAddress ;Make sure it is the right mode
MOVE.L D0, D5 ;save it for later
MOVE.L D0, A0 ;get in address register
ELSE
MOVE.L (A0), D5
MOVE.L D5, A0
ENDIF
LEA cache.glyphArray(A0), A3 ;Get array of glyphs into A0
MOVE.L widthTabHandle,A0 ;point to width table
MOVE.L (A0),A4 ;Save pointer to the width table
MOVE.L textPtr(A6),A1 ;get textPtr
MOVE.W countCopy(A6), D6 ;decrement partial draw character count
SUBQ.W #1,D6 ;make it a DBRA count
MOVE.L bufStart(A6), A5 ;BufStart (dst bitmap)
MOVE.W bufRow(A6), D7 ;Copy of rowbytes
IF HAS_COLOR | SCRIPT_CHAR_EXTRA THEN ;<7> CEL
MOVE.L characterExtra(A6),D1 ;add in character extra, if any
ENDIF
IF HAS_COLOR THEN
CMP.W #1, destDepth(A6) ;is it 1 deep
BEQ.S @depth1 ;Multi-depth blits
TST.B FastFlag(A6) ;If not fast then do 1-bit to buffer <5>CEL
BEQ.S @depth1 ;do 1-bit
TST.B orMode(A6) ;If not src or then do 1 bit and buffer
BNE deepChar ;It is deep char
@depth1
ENDIF
MOVE.L A6,-(SP) ;REMEMBER Stack frame ptr
BRA.S NextChar
doNextBand
ADDQ.W #1, D6 ;bump count since we are banding
MOVE.L (SP), A6 ;restore stack frame
MOVE.W glyphID(A6), D3 ;put glyphID into d3 for renderIt
BSR renderIt ;Get the glyph
MOVE.L A0, A6 ;restore glyphDataPtr in A6
BEQ gotGlyph ;go blit it
BRA.S skipBand
renderIt1
BTST.L #30, D0 ;Check if there is an error
BNE.S skipChar ;Still an error so skip it
MOVE.W #0, D3
MOVE.L (SP), A6 ;restore stack frame
if (hasDoubleByte) then
move.b highByte(a6),d3 ; load high byte of single byte character
else
move.b -1(a1),d3 ; load single byte character
endif
@render BSR renderIt ;Get the glyph
MOVE.L A0, A6 ;glyphDataPtr in A6
BEQ gotGlyph ;go blit it
skipBand
IF &SETTING('MACHINE') <> 'MC68000' THEN
skipChar
ADD.L 0(A4,D3*4),D4 ;GET FIXED POINT WIDTH
ELSE
ADD.W D3, D3
ADD.W D3, D3
skipChar
ADD.L 0(A4,D3),D4
ENDIF
IF HAS_COLOR | SCRIPT_CHAR_EXTRA THEN ;<7> CEL
ADD.L D1,D4 ;add in character extra, if any
ENDIF
BRA.S decCharCount ;continue to nextChar
spaceChar
ADD.L 128(A4), D4 ;Advance a space
decCharCount
SUBQ.W #1, D6
BLT doneStr
;————————————————————————————————————————————————————————————————————————————————————————————————
; Registers Use:
; D0 = scratch A0 = scratch
; D1 = characterExtra A1 = TextPtr.l
; D2 = shift.w A2 = bitsPtr.l
; D3 = scan.w & nextBand.w(high) A3 = glyphArray.l
; D4 = charLoc.l A4 = widTabPtr.l
; D5 = cachePtr.l A5 = DestPtr.l
; D6 = #chars.w A6 = glyphdataPtr.l
; D7 = destRowBytes.w (A7) = Save a6
;————————————————————————————————————————————————————————————————————————————————————————————————
NextChar
TST.L D3 ;another char band then call retrieve!!!
BMI.S doNextBand ;do the next char band
MOVEQ #0,D3
MOVE.B (A1)+,D3 ;get the next character
if (hasDoubleByte) then
move.l (sp),a6 ; reload the stack frame pointer
move.b d3,highByte(a6) ; save the high byte for later use
clr.b lowByte(a6) ; clear the low byte for now
tst.l encodingTable(a6) ; is this a double byte font?
beq.s @normalFont ; no, skip low byte loading
move.l encodingTable(a6),a0 ; grab pointer to high byte mapping table
tst.b 0(a0,d3.w) ; is this a double byte character?
beq @normalCharacter ; no, skip low byte loading
tst.w d6 ; more bytes left in text?
ble @remapCharacterToNull ; no, remap the high byte
subq.w #1,d6 ; decrement the character count
clr.w d0 ; clear high byte of low word
move.b (a1)+,d0 ; grab the low byte and bump the text pointer
adda.w #256,a0 ; offset to the low byte encoding table
tst.b 0(a0,d0.w) ; is this a valid low byte?
beq @remapCharacterToNull ; no, remap the high byte character
move.b d0,lowByte(a6) ; save the valid low byte for later use
bra @normalCharacter ; continue normally
@remapCharacterToNull
move.b #1,d3 ; remap the high byte character to the missing glyph
move.b d3,highByte(a6) ; save the remapped value in the stack
@normalCharacter
@normalFont
endif
CMP.B #32,D3 ;IS IT A SPACE ?
BEQ.S spaceChar ;Skip the char extra
IF &SETTING('MACHINE') <> 'MC68000' THEN
MOVE.L 0(A3,D3*4),D0 ;Get offset to glyph in D3
ELSE
ADD.W D3,D3
ADD.W D3,D3
MOVE.L 0(A3,D3),D0
ENDIF
BLE.S renderIt1 ;Must render it
ADD.L D5, D0 ;Add in cacheptr address
MOVE.L D0, A6 ;glyphrec = cache + offset
if (hasDoubleByte) then
clr.l d0 ; clear a long for the character code
move.l (sp),a0 ; reload the stack frame pointer
move.b lowByte(a0),d0 ; double byte character?
beq.s @haveGlyphRecord ; no, skip this
IF &SETTING('MACHINE') <> 'MC68000' THEN
move.l 0(a6,d0.w*4),d0 ; load glyph record offset
ELSE
add.w d0,d0
add.w d0,d0
move.l 0(a6,d0.w),d0
ENDIF
ble.s renderIt1 ; render if error or not cached
add.l d5,d0 ; convert offset to pointer
move.l d0,a6 ; load glyph record pointer
@haveGlyphRecord
endif
LEA glyph.cacheData(A6), A2 ;Get address
gotGlyph
MOVE.L D4,D2 ;charloc in D2
SWAP D2 ;Just use integer portion
ADD.W glyph.devLSB(A6), D2 ;Get integralized left side bearing
;••• spot for skipping advance if char banding!!!
TST.L D3 ;do not advance since the is more of char
BMI.S @skipAdvance ;another band of char
IF &SETTING('MACHINE') <> 'MC68000' THEN
ADD.L 0(A4,D3*4),D4 ;GET FIXED POINT WIDTH
ELSE
ADD.L 0(A4,D3),D4
ENDIF
IF HAS_COLOR OR SCRIPT_CHAR_EXTRA THEN ;char extra used in 700 and/or color - not B&W < $700
ADD.L D1,D4 ;add in character extra, if any
ENDIF
@skipAdvance
MOVE.L A5,A0 ;copy of destPtr
MOVE.W glyph.adjustTop(A6), D0 ;Subtract the YMax
MULS.W D7,D0 ;Vertical offset value
ADD.L D0,A0 ;Add in the vert offset
MOVE.W glyph.bitWidth(A6),D3 ;shift count plus width
CMP.W #16,D3 ;bigger than 16?
BGT.S overWord ;We are bigger than a word
MOVE.W D2, D0 ;Use D0 to calc horz dest adjust
LSR.W #4,D0 ;convert to words
ADD.W D0,D0 ;convert to bytes (Horz. offset)
ADD.W D0,A0 ;Add in the horz offset
AND.W #15,D2 ;allow a shift of 0 to 15
ADD.W D2,D3 ;shift + bitwidth
CMP.W #16,D3 ;bigger than 16?
BGT.S bigWord
;———————————————————
; blit loops
;———————————————————
;————————————————————————
; Word Blit
;Regs used:
; D0 = BlitSource.l
; D2 = ShiftAdjust.w
; D3 = Scan.w
; D6 = charNum.w
; D7 = destRow.w
; A0 = DestPtr.l
; A2 = SourcePtr.l
word
MOVE.W glyph.scan(A6), D3 ;Height of character
SUBQ.W #1,D3
@mid MOVE.W (A2)+,D0 ;this particular example is or mode
LSR D2,D0 ;shift into place
OR.W D0,(A0) ;add the bits
ADD.W D7,A0 ;advance to the next dest row
DBRA D3,@mid
skipIt DBRA D6,NextChar
TST.L D3 ;another char band then call retrieve!!!
BMI.S doNextBand ;do the next char band
doneStr MOVE.L (SP)+,A6 ;Restore Stack frame ptr
BRA strDone ;no more chars to do…
;————————————————————————
; BigWord Blit
;Regs used:
; D0 = BlitSource.l
; D2 = ShiftAdjust.w
; D3 = Scan.w
; D6 = charNum.w
; D7 = destRow.w
; A0 = DestPtr.l
; A2 = SourcePtr.l
; here, the character spans a word boundary, so must be handled with a long loop on 68K machines
bigWord
MOVE.W glyph.scan(A6), D3 ;Height of character
SUBQ.W #1,D3
@mid MOVE.L (A2),D0 ;this particular example is a or mode
CLR D0 ;clear the low word
LSR.L D2,D0 ;shift into place
OR.L D0,(A0) ;add the bits
ADD.W D7,A0 ;advance to the next dest row
ADDQ #2, A2 ;advance to the next src row
DBRA D3,@mid
DBRA D6,NextChar
TST.L D3 ;another char band then call retrieve!!!
BMI.S doNextBand ;do the next char band
MOVE.L (SP)+,A6 ;Restore Stack frame ptr
BRA strDone ;no more chars to do…
OverWord
MOVE.W D2, D0 ;Use D0 to calc horz dest adjust
LSR #5,D0 ;convert to longs
ADD.W D0,D0 ;convert to words (Horz. offset)
ADD.W D0,D0 ;convert to bytes (Horz. offset)
ADD.W D0,A0 ;Add in the horz offset
CMP.W #32,D3 ;bigger than 32?
BGT.S overLong ;Got more than one long
AND.W #31,D2 ;allow a shift of 0 to 31
ADD.W D2, D3 ;shift + bitwidth
CMP.W #32,D3 ;bigger than 32?
BGT.S bigLong ;Shift and width is greater than a long
;————————————————————————
; long Blit
;Regs used:
; D0 = BlitSource.l
; D2 = ShiftAdjust.w
; D3 = Scan.w
; D6 = charNum.w
; D7 = destRow.w
; A0 = DestPtr.l
; A2 = SourcePtr.l
; We fit inside a long with the shift
long
MOVE.W glyph.scan(A6), D3 ;Height of character
SUBQ #1,D3
@mid
MOVE.L (A2)+,D0 ;this particular example is a or mode
LSR.L D2,D0 ;shift into place
OR.L D0,(A0) ;add the bits
ADD.W D7,A0 ;advance to the next dest row
DBRA D3,@mid
DBRA D6,NextChar
TST.L D3 ;another char band then call retrieve!!!
BMI.S doNextBand ;do the next char band
MOVE.L (SP)+,A6 ;Restore Stack frame ptr
BRA strDone ;no more chars to do…
;————————————————————————
; bigLong Blit
;Regs used:
; D0 = BlitSource.l
; D1 = Left Shift.w
; D2 = Right Shift.w
; D3 = Scan.w
; D6 = charNum.w
; D7 = destRow.w
; A0 = DestPtr.l
; A2 = SourcePtr.l
bigLong
MOVE.L D1, -(SP) ;save d1
MOVE.W glyph.scan(A6), D3 ;Height of character
SUBQ.W #1,D3
MOVE.W #32, D1 ;get number of long bits
SUB.W D2, D1 ;Get the shift next long shift
SUBQ.W #4, D7 ;Advance one long less for dest
@mid
MOVE.L (A2),D0 ;this particular example is a or mode
LSR.L D2,D0 ;shift into place
OR.L D0,(A0)+ ;add the bits
MOVE.L (A2)+,D0 ;get second piece of the long
LSL.L D1,D0 ;shift into place
OR.L D0,(A0) ;Next long
ADD.W D7,A0 ;advance to the next dest row
DBRA D3,@mid
ADDQ.W #4, D7 ;restore true value of dest row bytes
MOVE.L (SP)+, D1 ;restore d1
DBRA D6,NextChar
TST.L D3 ;another char band then call retrieve!!!
BMI.S doNextBand ;do the next char band
MOVE.L (SP)+,A6 ;Restore Stack frame ptr
BRA strDone ;no more chars to do…
;————————————————————————
; bigLong Blit
;Regs used:
; D0 = BlitSource.l
; D1 = Left Shift.w
; D2 = Right Shift.w
; D3 = Scan.w
; D5 = longsInScan.w
; D6 = charNum.w & rowBytesAdjust.w
; D7 = destRow.w
; A0 = DestPtr.l
; A2 = SourcePtr.l
; A6 = copy of longsInScan.w
overLong
;Many Longs to move
MOVEM.L D1/D5, -(SP) ;save regs
SWAP D6 ;less longs to advance dest
MOVE.W glyph.scan(A6), D3 ;Height of character
SUBQ.W #1,D3
MOVE.W glyph.byteWidth+2(A6),D6 ;src byte width in D5
SUB.W D6, D7 ;Advance one long less for dest
MOVE.W D6, D5 ;# of src bytes
LSR #2, D5 ;# of longs for inner loop
SUBQ.W #1, D5 ;init for dbra
MOVE.W D5, A6 ;Keep a copy for re-initialization
AND.W #31,D2 ;allow a shift of 0 to 31
MOVE.W #32, D1 ;get number of long bits
SUB.W D2, D1 ;Get the shift next long shift
@mid
MOVE.L (A2),D0 ;this particular example is a or mode
LSR.L D2,D0 ;shift into place
OR.L D0,(A0)+ ;add the bits
MOVE.L (A2)+,D0 ;get second piece of the long
LSL.L D1,D0 ;shift into place
OR.L D0,(A0) ;Next long
DBRA D5,@mid ;# of longs in a scan line
MOVE.W A6, D5 ;# of src bytes
ADD.W D7,A0 ;advance to the next dest row
DBRA D3,@mid
ADD.W D6, D7 ;restore true value of dest row bytes
SWAP D6 ;Restore # of chars
MOVEM.L (SP)+, D1/D5 ;restore regs
DBRA D6,NextChar
TST.L D3 ;another char band then call retrieve!!!
BMI.S doNextBand ;do the next char band
MOVE.L (SP)+,A6 ;Restore Stack frame ptr
BRA strDone ;no more chars to do…
;————————————————————————————————————————————————————————————————————————————————————————————————
; MULTI-bit blit routine CHOICE
;————————————————————————————————————————————————————————————————————————————————————————————————
; Registers Use:
; D0 = scratch A0 = scratch
; D1 = bitdepth A1 = TextPtr.l
; D2 = shift.w A2 = bitsPtr.l
; D3 = scan.w A3 = glyphArray.l
; D4 = charLoc.l A4 = widTabPtr.l
; D5 = char*4.w & longInScan A5 = DestPtr.l
; D6 = #chars.w A6 = stack frame.l
; D7 = destRowBytes.w A7 = stack pointer.l
;————————————————————————————————————————————————————————————————————————————————————————————————
IF 0 THEN
blitJmpTable
DC.W word-blitJmpTable ;0 1-bit blit functions
DC.W bigWord-blitJmpTable ;2
DC.W long-blitJmpTable ;4
DC.W bigLong-blitJmpTable ;6
DC.W overLong-blitJmpTable ;8
DC.W word2-blitJmpTable ;0 2-bit blit functions
DC.W bigWord2-blitJmpTable ;2
DC.W long2-blitJmpTable ;4
DC.W bigLong2-blitJmpTable ;6
DC.W overLong2-blitJmpTable ;8
DC.W word4-blitJmpTable ;0 4-bit blit functions
DC.W bigWord4-blitJmpTable ;2
DC.W long4-blitJmpTable ;4
DC.W bigLong4-blitJmpTable ;6
DC.W overLong4-blitJmpTable ;8
DC.W word8-blitJmpTable ;0 8-bit blit functions
DC.W bigWord8-blitJmpTable ;2
DC.W long8-blitJmpTable ;4
DC.W bigLong8-blitJmpTable ;6
DC.W overLong8-blitJmpTable ;8
DC.W word16-blitJmpTable ;0 16-bit blit functions
DC.W bigWord16-blitJmpTable ;2
DC.W long16-blitJmpTable ;4
DC.W bigLong16-blitJmpTable ;6
DC.W overLong16-blitJmpTable ;8
DC.W word32-blitJmpTable ;0 32-bit blit functions
DC.W bigWord32-blitJmpTable ;2
DC.W long32-blitJmpTable ;4
DC.W bigLong32-blitJmpTable ;6
DC.W overLong32-blitJmpTable ;8
ENDIF
IF HAS_COLOR THEN
deepChar
;———————————————————————————————-
; Set up blit function pointers
;———————————————————————————————-
MOVEQ #0, D7 ;
MOVE.W destDepth(A6), D0 ;get depth in D0
CMP.W #8, D0 ;is it 8 deep
BNE @chk2 ;eight deep will not use function ptrs
MOVE.W #3, destShift(A6) ;Shift for multiply
BRA @doneFuncPtrs
@chk2 MOVEQ #-1, D7 ;negate is 1 bit flag for faster check
CMP.W #2, D0 ;is it 2 deep
BNE.S @chk4
MOVE.W #1, destShift(A6) ;Shift for multiply
LEA word2, A0 ;pointer to the function
MOVE.L A0, wordFunc(A6) ;save it away
LEA bigWord2, A0 ;pointer to the function
MOVE.L A0, bigWordFunc(A6) ;save it away
LEA long2, A0 ;pointer to the function
MOVE.L A0, longFunc(A6) ;save it away
LEA bigLong2, A0 ;pointer to the function
MOVE.L A0, bigLongFunc(A6) ;save it away
LEA overLong2, A0 ;pointer to the function
MOVE.L A0, overLongFunc(A6) ;save it away
BRA @doneFuncPtrs
@chk4 CMP.W #4, D0 ;is it 4 deep
BNE.S @chk16
MOVE.W #2, destShift(A6) ;Shift for multiply
LEA word4, A0 ;pointer to the function
MOVE.L A0, wordFunc(A6) ;save it away
LEA bigWord4, A0 ;pointer to the function
MOVE.L A0, bigWordFunc(A6) ;save it away
LEA long4, A0 ;pointer to the function
MOVE.L A0, longFunc(A6) ;save it away
LEA bigLong4, A0 ;pointer to the function
MOVE.L A0, bigLongFunc(A6) ;save it away
LEA overLong4, A0 ;pointer to the function
MOVE.L A0, overLongFunc(A6) ;save it away
BRA @doneFuncPtrs
@chk16 CMP.W #16, D0 ;is it 16 deep
BNE.S @chk32
MOVE.W #4, destShift(A6) ;Shift for multiply
LEA word16, A0 ;pointer to the function
MOVE.L A0, wordFunc(A6) ;save it away
LEA bigWord16, A0 ;pointer to the function
MOVE.L A0, bigWordFunc(A6) ;save it away
LEA long16, A0 ;pointer to the function
MOVE.L A0, longFunc(A6) ;save it away
LEA bigLong16, A0 ;pointer to the function
MOVE.L A0, bigLongFunc(A6) ;save it away
LEA overLong16, A0 ;pointer to the function
MOVE.L A0, overLongFunc(A6) ;save it away
BRA.S @doneFuncPtrs
@chk32 MOVE.W #5, destShift(A6) ;Shift for multiply
LEA word32, A0 ;pointer to the function
MOVE.L A0, wordFunc(A6) ;save it away
LEA bigWord32, A0 ;pointer to the function
MOVE.L A0, bigWordFunc(A6) ;save it away
LEA long32, A0 ;pointer to the function
MOVE.L A0, longFunc(A6) ;save it away
LEA bigLong32, A0 ;pointer to the function
MOVE.L A0, bigLongFunc(A6) ;save it away
LEA overLong32, A0 ;pointer to the function
MOVE.L A0, overLongFunc(A6) ;save it away
@doneFuncPtrs
MOVE.W bufRow(A6), D7 ;Copy of rowbytes
BRA.S NextChar8
doNextBand8
ADDQ.W #1, D6 ;bump count since we are banding
MOVE.W glyphID(A6), D3 ;put glyphID into d3 for renderIt
BSR renderIt ;Get the glyph
BEQ gotGlyph8 ;go blit it
BRA skipIt8
renderIt8
BTST.L #30, D0 ;Check if there is an error
BNE skipChar8 ;Still an error so skip it <57-CEL>
BSR renderIt ;Get the glyph
BEQ gotGlyph8 ;go blit it
skipChar8
ADD.L 0(A4,D3*4),D4 ;Add fixed point width <57-CEL>
ADD.L characterExtra(A6),D4 ;add in character extra, if any
BRA.S decCharCount8 ;continue to nextChar
spaceChar8
ADD.L 128(A4), D4 ;Advance a space
decCharCount8
SUBQ.W #1, D6
BLT strDone
NextChar8
MOVE.W #0,D3
MOVE.B (A1)+,D3 ;get the next character
if (hasDoubleByte) then
move.b d3,highByte(a6) ; save the high byte for later use
clr.b lowByte(a6) ; clear the low byte for now
tst.l encodingTable(a6) ; is this a double byte font?
beq.s @normalFont ; no, skip low byte loading
move.l encodingTable(a6),a0 ; load the encoding table
tst.b 0(a0,d3.w) ; is this a double byte character?
beq.s @normalCharacter ; no, skip low byte loading
tst.w d6 ; more bytes left in text?
ble.s @remapCharacterToNull ; no, remap the high byte
subq.w #1,d6 ; decrement the character count
clr.w d0 ; clear high byte of low word
move.b (a1)+,d0 ; grab the low byte and bump the text pointer
adda.w #256,a0 ; offset to the low byte encoding table
tst.b 0(a0,d0.w) ; is this a valid low byte?
beq @remapCharacterToNull ; no, remap the high byte character
move.b d0,lowByte(a6) ; save the valid low byte for later use
bra @normalCharacter ; continue normally
@remapCharacterToNull
move.b #1,d3 ; remap the high byte character to the missing glyph
move.b d3,highByte(a6) ; save the remapped value in the stack
@normalCharacter
@normalFont
endif
CMP.B #32,D3 ;IS IT A SPACE ?
BEQ spaceChar8 ;Skip the char extra
MOVE.L 0(A3,D3*4),D0 ;Get offset to glyph in D0
BLE renderIt8 ;Must render it
ADD.L D5, D0 ;Add in cacheptr address
MOVE.L D0, A0 ;glyphrec = cache + offset
if (hasDoubleByte) then
clr.l d0 ; clear a long for the character code
move.b lowByte(a6),d0 ; double byte character?
beq.s @haveGlyphRecord ; no, skip this
move.l 0(a0,d0.w*4),d0 ; load glyph record offset
ble renderIt8 ; render if error or not cached
add.l d5,d0 ; convert offset to pointer
move.l d0,a0 ; load glyph record pointer
@haveGlyphRecord
endif
LEA glyph.cacheData(A0), A2 ;Get address
gotGlyph8
MOVE.L D4,D2 ;charloc in D2
SWAP D2 ;Just use integer portion
ADD.W glyph.devLSB(A0), D2 ;Get integralized left side bearing
;••• spot for skipping advance if char banding!!!
TST.L D3 ;do not advance since the is more of char
BMI.S @skipAdvance ;another band of char
ADD.L 0(A4,D3*4),D4 ;Add fixed point width
ADD.L characterExtra(A6),D4 ;add in character extra, if any
@skipAdvance
MOVE.W glyph.scan(A0), D3 ;Height of character
SUBQ.W #1,D3
MOVE.W glyph.adjustTop(A0), D0 ;Subtract the YMax
MULS.W D7,D0 ;Vertical offset value
MOVE.W glyph.bitWidth(A0),D1 ;shift count plus width
TST.L D7 ;if negative then multi-bit
BLT notEight ;Multi-depth blits
CMP.W #16,D1 ;bigger than 16?
BGT overWord8 ;We are bigger than a word
MOVEM.L D4/D6, -(SP) ;Save regs
MOVEQ #$F, D4 ;Low 4-bit mask
MOVE.L A5,A0 ;get top screen destination copy
ADD.L D0,A0 ;Add in the vert offset
MOVEQ #0, D0 ;long ready
MOVE.W D2, D0 ;Use D0 to calc horz dest adjust
LSR.W #4,D0 ;convert to words
ADD.W D0,D0 ;convert to bytes (Horz. offset)
MOVE.W destShift(A6), D6 ;Get the destination shift value
LSL.W D6, D0 ;Multiply by dest depth
ADD.W D0,A0 ;Add in the horz offset
AND.W #15,D2 ;allow a shift of 0 to 15
ADD.W D2,D1 ;shift + bitwidth
CMP.W #16,D1 ;bigger than 16?
BGT bigWord8
;———————————————————
;blitting loops
;———————————————————
word8
ADD.L #12, A0 ;Advance to last long of scan line
@mid MOVE.W (A2)+,D0 ;this particular example is or mode
LSR D2,D0 ;shift into place
MOVE.W D0, D1 ;Get a copy
AND.W D4, D1 ;Get lower four bits
BEQ.S @1 ;nothing to blit
MOVE.L bitTable8(D1*4), D1 ;Add the bits
OR.L D1, (A0) ;Add the bits
@1 LSR.W #4, D0 ;Next four bits
MOVE.W D0, D1 ;Get a copy
AND.W D4, D1 ;Get lower four bits
BEQ.S @2 ;nothing to blit
MOVE.L bitTable8(D1*4), D1 ;Add the bits
OR.L D1, -4(A0) ;Add the bits
@2 LSR.W #4, D0 ;Next four bits
MOVE.B D0, D1 ;Get a copy
AND.W D4, D1 ;Get lower four bits
BEQ.S @3 ;nothing to blit
MOVE.L bitTable8(D1*4), D1 ;Add the bits
OR.L D1, -8(A0) ;Add the bits
@3 LSR.W #4, D0 ;Next four bits
BEQ.S @4 ;nothing to blit
MOVE.L bitTable8(D0*4), D1 ;Add the bits
OR.L D1, -12(A0) ;Add the bits
@4 ADD D7,A0 ;advance to the next dest row
DBRA D3,@mid
MOVEM.L (SP)+, D4/D6 ;Save regs
skipIt8
DBRA D6,NextChar8
TST.L D3 ;another char band then call retrieve!!!
BMI.S doNextBand8 ;do the next char band
BRA strDone ;no more chars to do…
MACRO
_blit8long
MOVE.W D0, D1 ;Get a copy
AND.W D4, D1 ;Get lower four bits
BEQ.S @1 ;nothing to blit
MOVE.L 0(A1, D1*4), D1 ;Add the bits
OR.L D1, (A0) ;Add the bits
@1 LSR.W #4, D0 ;Next four bits
MOVE.W D0, D1 ;Get a copy
AND.W D4, D1 ;Get lower four bits
BEQ.S @2 ;nothing to blit
MOVE.L 0(A1, D1*4), D1 ;Add the bits
OR.L D1, -4(A0) ;Add the bits
@2 LSR.W #4, D0 ;Next four bits
MOVE.W D0, D1 ;Get a copy
AND.W D4, D1 ;Get lower four bits
BEQ.S @3 ;nothing to blit
MOVE.L 0(A1, D1*4), D1 ;Add the bits
OR.L D1, -8(A0) ;Add the bits
@3 LSR.W #4, D0 ;Next four bits
BEQ.S @4 ;nothing to blit
MOVE.L 0(A1, D0*4), D1 ;Add the bits
OR.L D1, -12(A0) ;Add the bits
@4 SWAP D0 ;Next four bits
MOVE.W D0, D1 ;Get a copy
AND.W D4, D1 ;Get lower four bits
BEQ.S @5 ;nothing to blit
MOVE.L 0(A1, D1*4), D1 ;Add the bits
OR.L D1, -16(A0) ;Add the bits
@5 LSR.W #4, D0 ;Next four bits
MOVE.W D0, D1 ;Get a copy
AND.W D4, D1 ;Get lower four bits
BEQ.S @6 ;nothing to blit
MOVE.L 0(A1, D1*4), D1 ;Add the bits
OR.L D1, -20(A0) ;Add the bits
@6 LSR.W #4, D0 ;Next four bits
MOVE.W D0, D1 ;Get a copy
AND.W D4, D1 ;Get lower four bits
BEQ.S @7 ;nothing to blit
MOVE.L 0(A1, D1*4), D1 ;Add the bits
OR.L D1, -24(A0) ;Add the bits
@7 LSR.W #4, D0 ;Next four bits
BEQ.S @8 ;nothing to blit
MOVE.L 0(A1, D0*4), D1 ;Add the bits
OR.L D1, -28(A0) ;Add the bits
@8
ENDM
align 4 ;Make long word aligned <54>
bitTable8
DC.L $00000000, $000000FF, $0000FF00, $0000FFFF, $00FF0000, $00FF00FF, $00FFFF00, $00FFFFFF
DC.L $FF000000, $FF0000FF, $FF00FF00, $FF00FFFF, $FFFF0000, $FFFF00FF, $FFFFFF00, $FFFFFFFF
bigWord8
; here, the character spans a word boundary, so must be handled with a long loop on 68K machines
MOVE.L A1, -(SP) ;Save regs
LEA bitTable8, A1 ;Table to the blit longs
ADD.L #28, A0 ;Advance to last long
@mid
MOVE.L (A2),D0 ;this particular example is a copy mode
CLR D0 ;clear the low word
LSR.L D2,D0 ;shift into place
_blit8long ;move src long
ADD D7,A0 ;advance to the next dest row
ADD #2,A2 ;advance to the next src row
DBRA D3,@mid
MOVE.L (SP)+, A1 ;Restore regs
MOVEM.L (SP)+, D4/D6 ;Save regs
DBRA D6,NextChar8
TST.L D3 ;another char band then call retrieve!!!
BMI.S doNextBand8 ;do the next char band
BRA strDone ;no more chars to do…
overWord8
CMP.W #32,D1 ;bigger than 32?
BGT overLong8 ;Got more than one long
MOVEM.L D4/D6/D7/A1, -(SP) ;Save regs
MOVEQ #$F, D4 ;Low 4-bit mask
MOVE.L A5,A0 ;get top screen destination copy
ADD.L D0,A0 ;Add in the vert offset
MOVEQ #0, D0 ;long ready
MOVE.W D2, D0 ;Use D0 to calc horz dest adjust
LSR #5,D0 ;convert to longs
ADD.W D0,D0 ;convert to bytes (Horz. offset)
ADD.W D0,D0 ;convert to bytes (Horz. offset)
MOVE.W destShift(A6), D6 ;Get the destination shift value
LSL.W D6, D0 ;Multiply by dest depth
ADD.W D0,A0 ;Add in the horz offset
AND.W #31,D2 ;allow a shift of 0 to 31
ADD.W D2, D1 ;shift + bitwidth
CMP.W #32,D1 ;bigger than 32?
BGT bigLong8 ;Shift and width is greater than a long
; We fit inside a long with the shift
long8
LEA bitTable8, A1 ;Table to the blit longs
ADD.L #28, A0 ;Advance to last long of scan line
@mid
MOVE.L (A2)+,D0 ;this particular example is a or mode
LSR.L D2,D0 ;shift into place
_blit8long ;move src long
ADD.W D7,A0 ;advance to the next dest row
DBRA D3,@mid
MOVEM.L (SP)+, D4/D6/D7/A1 ;Restore regs
DBRA D6,NextChar8
TST.L D3 ;another char band then call retrieve!!!
BMI.S doNextBand8 ;do the next char band
BRA strDone ;no more chars to do…
bigLong8
MOVE.W #32, D1 ;get number of long bits
SUB.W D2, D1 ;Get the shift next long shift
SWAP D1 ;rightShift in high-word
MOVE D2, D1 ;leftShift in low-word
MOVE.L D1, D2 ;Leave shift in D2
LEA bitTable8, A1 ;Table to the blit longs
ADD.L #28, A0 ;Advance to last long of scan line
SUB.W #32, D7 ;Advance one long less for dest
@mid
MOVE.L (A2),D0 ;this particular example is a or mode
LSR.L D2,D0 ;shift into place
_blit8long ;move src long
SWAP D2 ;get the rightShift
MOVE.L (A2)+,D0 ;get second piece of the long
LSL.L D2,D0 ;shift into place
ADD.W #32, A0 ;next long
_blit8long ;move src long
SWAP D2 ;restore the leftShift
ADD.W D7,A0 ;advance to the next dest row
DBRA D3,@mid
MOVEM.L (SP)+, D4/D6/D7/A1 ;Save regs
DBRA D6,NextChar8
TST.L D3 ;another char band then call retrieve!!!
BMI.S doNextBand8 ;do the next char band
BRA strDone ;no more chars to do…
overLong8
;Many Longs to move
MOVEM.L D4-D7/A1/A4, -(SP) ;Save regs
MOVEQ #$F, D4 ;Low 4-bit mask
SWAP D6 ;less longs to advance dest
MOVE.W destShift(A6), D1 ;Get the destination shift value
MOVE.W glyph.byteWidth+2(A0),D5 ;# of src bytes
MOVEQ #4, D6 ;Calculate less long adjustment
LSR #2, D5 ;# of longs for inner loop
LSL D1, D6 ;Long less adjustment
MULU D5, D6 ;multiply by number of longs
SUB.W D6, D7 ;Advance one long less for dest
SUBQ.W #1, D5 ;init for dbra
MOVE.W D5, A4 ;Keep a copy for re-initialization
MOVE.L A5,A0 ;get top screen destination copy
ADD.L D0,A0 ;Add in the vert offset
MOVEQ #0, D0 ;long ready
MOVE.W D2, D0 ;Use D0 to calc horz dest adjust
LSR #5,D0 ;convert to longs
ADD.W D0,D0 ;convert to words (Horz. offset)
ADD.W D0,D0 ;convert to bytes (Horz. offset)
LSL.W D1, D0 ;Multiply by dest depth
ADD.W D0,A0 ;Add in the horz offset
AND.W #31,D2 ;allow a shift of 0 to 31
MOVE.W #32, D1 ;get number of long bits
SUB.W D2, D1 ;Get the shift next long shift
SWAP D1 ;rightShift in high-word
MOVE D2, D1 ;leftShift in low-word
MOVE.L D1, D2 ;Leave shift in D2
LEA bitTable8, A1 ;Table to the blit longs
ADD.L #28, A0 ;Advance to last long of scan line
@mid
MOVE.L (A2),D0 ;this particular example is a or mode
LSR.L D2,D0 ;shift into place
_blit8long ;move src long
SWAP D2 ;get the rightShift
MOVE.L (A2)+,D0 ;get second piece of the long
LSL.L D2,D0 ;shift into place
ADD.W #32, A0 ;next long
_blit8long ;move src long
SWAP D2 ;restore the leftShift
DBRA D5,@mid ;# of longs in a scan line
MOVE.W A4, D5 ;# of src bytes
ADD.W D7,A0 ;advance to the next dest row
DBRA D3,@mid
ADD.W D6, D7 ;Next row
MOVEM.L (SP)+, D4-D7/A1/A4 ;Save regs
DBRA D6,NextChar8
TST.L D3 ;another char band then call retrieve!!!
BMI.S doNextBand8 ;do the next char band
BRA strDone ;no more chars to do…
;————————————————————————————————————————————————————————————————————————————————————————————————
; Not eight bit but it is multi bit
;————————————————————————————————————————————————————————————————————————————————————————————————
notEight
MOVEM.L D4-D7/A1/A4, -(SP) ;Save regs
CMP.W #16,D1 ;bigger than 16?
BGT.S @overWord ;We are bigger than a word
MOVE.L A5,A0 ;get top screen destination copy
ADD.L D0,A0 ;Add in the vert offset
MOVEQ #0, D0 ;long ready
MOVE.W D2, D0 ;Use D0 to calc horz dest adjust
LSR.W #4,D0 ;convert to words
ADD.W D0,D0 ;convert to bytes (Horz. offset)
MOVE.W destShift(A6), D6 ;Get the destination shift value
LSL.W D6, D0 ;Multiply by dest depth
ADD.W D0,A0 ;Add in the horz offset
AND.W #15,D2 ;allow a shift of 0 to 15
ADD.W D2,D1 ;shift + bitwidth
CMP.W #16,D1 ;bigger than 16?
BGT.S @bigWord
MOVE.L wordFunc(A6), A1 ;point to blit function
BRA @blitIt
@bigWord
MOVE.L bigWordFunc(A6), A1 ;point to blit function
BRA @blitIt
@overWord
CMP.W #32,D1 ;bigger than 32?
BGT.S @overLong ;Got more than one long
MOVE.L A5,A0 ;get top screen destination copy
ADD.L D0,A0 ;Add in the vert offset
MOVEQ #0, D0 ;long ready
MOVE.W D2, D0 ;Use D0 to calc horz dest adjust
LSR #5,D0 ;convert to longs
ADD.W D0,D0 ;convert to bytes (Horz. offset)
ADD.W D0,D0 ;convert to bytes (Horz. offset)
MOVE.W destShift(A6), D6 ;Get the destination shift value
LSL.W D6, D0 ;Multiply by dest depth
ADD.W D0,A0 ;Add in the horz offset
AND.W #31,D2 ;allow a shift of 0 to 31
ADD.W D2, D1 ;shift + bitwidth
CMP.W #32,D1 ;bigger than 32?
BGT.S @bigLong ;Shift and width is greater than a long
MOVE.L longFunc(A6), A1 ;point to blit function
BRA.S @blitIt
@bigLong
MOVE.W #32, D1 ;get number of long bits
SUB.W D2, D1 ;Get the shift next long shift
SWAP D1 ;rightShift in high-word
MOVE D2, D1 ;leftShift in low-word
MOVE.L D1, D2 ;Leave shift in D2
MOVE.L bigLongFunc(A6), A1 ;point to blit function
BRA.S @blitIt
@overLong
SWAP D6 ;less longs to advance dest
MOVE.W destShift(A6), D1 ;Get the destination shift value
MOVE.W glyph.byteWidth+2(A0),D5 ;# of src bytes
MOVEQ #4, D6 ;Calculate less long adjustment
LSR #2, D5 ;# of longs for inner loop
LSL D1, D6 ;Long less adjustment
MULU D5, D6 ;multiply by number of longs
SUB.W D6, D7 ;Advance one long less for dest
SUBQ.W #1, D5 ;init for dbra
MOVE.W D5, A4 ;Keep a copy for re-initialization
MOVE.L A5,A0 ;get top screen destination copy
ADD.L D0,A0 ;Add in the vert offset
MOVEQ #0, D0 ;long ready
MOVE.W D2, D0 ;Use D0 to calc horz dest adjust
LSR #5,D0 ;convert to longs
ADD.W D0,D0 ;convert to words (Horz. offset)
ADD.W D0,D0 ;convert to bytes (Horz. offset)
LSL.W D1, D0 ;Multiply by dest depth
ADD.W D0,A0 ;Add in the horz offset
AND.W #31,D2 ;allow a shift of 0 to 31
MOVE.W #32, D1 ;get number of long bits
SUB.W D2, D1 ;Get the shift next long shift
SWAP D1 ;rightShift in high-word
MOVE D2, D1 ;leftShift in low-word
MOVE.L D1, D2 ;Leave shift in D2
MOVE.L overLongFunc(A6), A1 ;point to blit function
@blitIt
JSR (A1) ;go blit it
MOVEM.L (SP)+, D4-D7/A1/A4 ;Save regs
DBRA D6,NextChar8
TST.L D3 ;another char band then call retrieve!!!
BMI.S doNextBand8 ;do the next char band
BRA strDone ;no more chars to do…
;————————————————————————————————————————————————————————————————————————————————————————————————
; 2-bit NEW FAST blit loop
;————————————————————————————————————————————————————————————————————————————————————————————————
; Registers Use:
; D0 = scratch A0 = scratch
; D1 = scratch A1 = TextPtr.l
; D2 = shift.w A2 = bitsPtr.l
; D3 = scan.w A3 = glyphArray.l
; D4 = charLoc.l A4 = widTabPtr.l
; D5 = char*4.w A5 = DestPtr.l
; D6 = #chars.w A6 = stack frame.l
; D7 = rowBytes.w A7 = stack pointer.l
;————————————————————————————————————————————————————————————————————————————————————————————————
align 4 ;Make long word aligned <54>
Table2
DC $0000,$0003,$000c,$000f,$0030,$0033,$003c,$003f
DC $00c0,$00c3,$00cc,$00cf,$00f0,$00f3,$00fc,$00ff
DC $0300,$0303,$030c,$030f,$0330,$0333,$033c,$033f
DC $03c0,$03c3,$03cc,$03cf,$03f0,$03f3,$03fc,$03ff
DC $0c00,$0c03,$0c0c,$0c0f,$0c30,$0c33,$0c3c,$0c3f
DC $0cc0,$0cc3,$0ccc,$0ccf,$0cf0,$0cf3,$0cfc,$0cff
DC $0f00,$0f03,$0f0c,$0f0f,$0f30,$0f33,$0f3c,$0f3f
DC $0fc0,$0fc3,$0fcc,$0fcf,$0ff0,$0ff3,$0ffc,$0fff
DC $3000,$3003,$300c,$300f,$3030,$3033,$303c,$303f
DC $30c0,$30c3,$30cc,$30cf,$30f0,$30f3,$30fc,$30ff
DC $3300,$3303,$330c,$330f,$3330,$3333,$333c,$333f
DC $33c0,$33c3,$33cc,$33cf,$33f0,$33f3,$33fc,$33ff
DC $3c00,$3c03,$3c0c,$3c0f,$3c30,$3c33,$3c3c,$3c3f
DC $3cc0,$3cc3,$3ccc,$3ccf,$3cf0,$3cf3,$3cfc,$3cff
DC $3f00,$3f03,$3f0c,$3f0f,$3f30,$3f33,$3f3c,$3f3f
DC $3fc0,$3fc3,$3fcc,$3fcf,$3ff0,$3ff3,$3ffc,$3fff
DC $c000,$c003,$c00c,$c00f,$c030,$c033,$c03c,$c03f
DC $c0c0,$c0c3,$c0cc,$c0cf,$c0f0,$c0f3,$c0fc,$c0ff
DC $c300,$c303,$c30c,$c30f,$c330,$c333,$c33c,$c33f
DC $c3c0,$c3c3,$c3cc,$c3cf,$c3f0,$c3f3,$c3fc,$c3ff
DC $cc00,$cc03,$cc0c,$cc0f,$cc30,$cc33,$cc3c,$cc3f
DC $ccc0,$ccc3,$cccc,$cccf,$ccf0,$ccf3,$ccfc,$ccff
DC $cf00,$cf03,$cf0c,$cf0f,$cf30,$cf33,$cf3c,$cf3f
DC $cfc0,$cfc3,$cfcc,$cfcf,$cff0,$cff3,$cffc,$cfff
DC $f000,$f003,$f00c,$f00f,$f030,$f033,$f03c,$f03f
DC $f0c0,$f0c3,$f0cc,$f0cf,$f0f0,$f0f3,$f0fc,$f0ff
DC $f300,$f303,$f30c,$f30f,$f330,$f333,$f33c,$f33f
DC $f3c0,$f3c3,$f3cc,$f3cf,$f3f0,$f3f3,$f3fc,$f3ff
DC $fc00,$fc03,$fc0c,$fc0f,$fc30,$fc33,$fc3c,$fc3f
DC $fcc0,$fcc3,$fccc,$fccf,$fcf0,$fcf3,$fcfc,$fcff
DC $ff00,$ff03,$ff0c,$ff0f,$ff30,$ff33,$ff3c,$ff3f
DC $ffc0,$ffc3,$ffcc,$ffcf,$fff0,$fff3,$fffc,$ffff
;———————————————————
;blitting loops
;———————————————————
MACRO
_blitWord2
MOVE.B D0,D4 ;Get a copy
LSR.W #8,D0 ;Next four bits
MOVE.L 0(A1,D0*2),D0 ;Add the bits
MOVE.W 0(A1,D4*2),D0 ;Add the bits
OR.L D0,(A0) ;Add the bits
ENDM
MACRO
_blitLong2
MOVE.B D0,D4
LSR.W #8,D0 ;Next bytes worth
MOVE.L 0(A1,D0*2),D1 ;get the bits
MOVE.W 0(A1,D4*2),D1 ;get the next word
OR.L D1,(A0) ;Add the bits
SWAP D0 ;High Word
MOVE.B D0,D4
LSR.W #8,D0 ;Next bytes worth
MOVE.L 0(A1,D0*2),D1 ;get the bits
MOVE.W 0(A1,D4*2),D1 ;get the next word
OR.L D1,-4(A0) ;Add the bits
ENDM
word2 LEA table2, A1 ;Table to the blit longs
MOVEQ #0, D4 ;ready for blitloop
@mid MOVE.W (A2)+,D0 ;this particular example is or mode
LSR D2,D0 ;shift into place
_blitWord2
ADD D7,A0 ;advance to the next dest row
DBRA D3,@mid
RTS
bigWord2
; here, the character spans a word boundary, so must be handled with a long loop on 68K machines
MOVEQ #0, D4 ;ready for blitloop
LEA table2, A1 ;Table to the blit longs
ADD.L #4, A0 ;Advance to last long of scan line
@mid2
MOVE.L (A2),D0 ;this particular example is a copy mode
CLR D0 ;clear the low word
LSR.L D2,D0 ;shift into place
_blitLong2 ;blit one source long to dest
ADD D7,A0 ;advance to the next dest row
ADD #2,A2 ;advance to the next src row
DBRA D3,@mid2
RTS
long2
; We fit inside a long with the shift
MOVEQ #0, D4 ;ready for blitloop
LEA table2, A1 ;Table to the blit longs
ADD.L #4, A0 ;Advance to last long of scan line
@mid
MOVE.L (A2)+,D0 ;this particular example is a or mode
LSR.L D2,D0 ;shift into place
_blitLong2 ;blit one source long to dest
ADD.W D7,A0 ;advance to the next dest row
DBRA D3,@mid
RTS
bigLong2
MOVEQ #0, D4 ;ready for blitloop
LEA table2, A1 ;Table to the blit longs
ADD.L #4, A0 ;Advance to last long of scan line
SUBQ.W #8, D7 ;Advance one long less for dest
@mid
MOVE.L (A2),D0 ;this particular example is a or mode
LSR.L D2,D0 ;shift into place
_blitLong2 ;blit one source long to dest
SWAP D2 ;get the rightShift
MOVE.L (A2)+,D0 ;get second piece of the long
LSL.L D2,D0 ;shift into place
ADDQ.W #8, A0 ;next long
_blitLong2 ;blit one source long to dest
SWAP D2 ;restore the leftShift
ADD.W D7,A0 ;advance to the next dest row
DBRA D3,@mid
RTS
overLong2
;Many Longs to move
MOVEQ #0, D4 ;ready for blitloop
LEA table2, A1 ;Table to the blit longs
ADD.L #4, A0 ;Advance to last long of scan line
@mid MOVE.L (A2),D0 ;this particular example is a or mode
LSR.L D2,D0 ;shift into place
_blitLong2 ;blit one source long to dest
SWAP D2 ;get the rightShift
ADDQ.W #8, A0 ;next long
MOVE.L (A2)+,D0 ;get second piece of the long
LSL.L D2,D0 ;shift into place
_blitLong2 ;blit one source long to dest
SWAP D2 ;restore the leftShift
DBRA D5,@mid ;# of longs in a scan line
MOVE.W A4, D5 ;# of src bytes
ADD.W D7,A0 ;advance to the next dest row
DBRA D3,@mid
ADD.W D6,D7 ;re-adjust the rowbytes to its original value
SWAP D6 ;Restore # of chars
RTS
;————————————————————————————————————————————————————————————————————————————————————————————————
; End 2-bit NEW FAST blit loop
;————————————————————————————————————————————————————————————————————————————————————————————————
;————————————————————————————————————————————————————————————————————————————————————————————————
; 4-bit NEW FAST blit loop
;————————————————————————————————————————————————————————————————————————————————————————————————
; Registers Use:
; D0 = scratch A0 = scratch
; D1 = scratch A1 = TextPtr.l
; D2 = shift.w A2 = bitsPtr.l
; D3 = scan.w A3 = glyphArray.l
; D4 = charLoc.l A4 = widTabPtr.l
; D5 = char*4.w A5 = DestPtr.l
; D6 = #chars.w A6 = stack frame.l
; D7 = rowBytes.w A7 = stack pointer.l
;————————————————————————————————————————————————————————————————————————————————————————————————
;———————————————————
;blitting loops
;———————————————————
align 4 ;Make long word aligned <54>
TABLE4 DC.L $00000000,$0000000F,$000000F0,$000000FF ;QUADRUPLING TABLE
DC.L $00000F00,$00000F0F,$00000FF0,$00000FFF
DC.L $0000F000,$0000F00F,$0000F0F0,$0000F0FF
DC.L $0000FF00,$0000FF0F,$0000FFF0,$0000FFFF
DC.L $000F0000,$000F000F,$000F00F0,$000F00FF ;QUADRUPLING TABLE
DC.L $000F0F00,$000F0F0F,$000F0FF0,$000F0FFF
DC.L $000FF000,$000FF00F,$000FF0F0,$000FF0FF
DC.L $000FFF00,$000FFF0F,$000FFFF0,$000FFFFF
DC.L $00F00000,$00F0000F,$00F000F0,$00F000FF ;QUADRUPLING TABLE
DC.L $00F00F00,$00F00F0F,$00F00FF0,$00F00FFF
DC.L $00F0F000,$00F0F00F,$00F0F0F0,$00F0F0FF
DC.L $00F0FF00,$00F0FF0F,$00F0FFF0,$00F0FFFF
DC.L $00FF0000,$00FF000F,$00FF00F0,$00FF00FF ;QUADRUPLING TABLE
DC.L $00FF0F00,$00FF0F0F,$00FF0FF0,$00FF0FFF
DC.L $00FFF000,$00FFF00F,$00FFF0F0,$00FFF0FF
DC.L $00FFFF00,$00FFFF0F,$00FFFFF0,$00FFFFFF
DC.L $0F000000,$0F00000F,$0F0000F0,$0F0000FF ;QUADRUPLING TABLE
DC.L $0F000F00,$0F000F0F,$0F000FF0,$0F000FFF
DC.L $0F00F000,$0F00F00F,$0F00F0F0,$0F00F0FF
DC.L $0F00FF00,$0F00FF0F,$0F00FFF0,$0F00FFFF
DC.L $0F0F0000,$0F0F000F,$0F0F00F0,$0F0F00FF ;QUADRUPLING TABLE
DC.L $0F0F0F00,$0F0F0F0F,$0F0F0FF0,$0F0F0FFF
DC.L $0F0FF000,$0F0FF00F,$0F0FF0F0,$0F0FF0FF
DC.L $0F0FFF00,$0F0FFF0F,$0F0FFFF0,$0F0FFFFF
DC.L $0FF00000,$0FF0000F,$0FF000F0,$0FF000FF ;QUADRUPLING TABLE
DC.L $0FF00F00,$0FF00F0F,$0FF00FF0,$0FF00FFF
DC.L $0FF0F000,$0FF0F00F,$0FF0F0F0,$0FF0F0FF
DC.L $0FF0FF00,$0FF0FF0F,$0FF0FFF0,$0FF0FFFF
DC.L $0FFF0000,$0FFF000F,$0FFF00F0,$0FFF00FF ;QUADRUPLING TABLE
DC.L $0FFF0F00,$0FFF0F0F,$0FFF0FF0,$0FFF0FFF
DC.L $0FFFF000,$0FFFF00F,$0FFFF0F0,$0FFFF0FF
DC.L $0FFFFF00,$0FFFFF0F,$0FFFFFF0,$0FFFFFFF
DC.L $F0000000,$F000000F,$F00000F0,$F00000FF ;QUADRUPLING TABLE
DC.L $F0000F00,$F0000F0F,$F0000FF0,$F0000FFF
DC.L $F000F000,$F000F00F,$F000F0F0,$F000F0FF
DC.L $F000FF00,$F000FF0F,$F000FFF0,$F000FFFF
DC.L $F00F0000,$F00F000F,$F00F00F0,$F00F00FF ;QUADRUPLING TABLE
DC.L $F00F0F00,$F00F0F0F,$F00F0FF0,$F00F0FFF
DC.L $F00FF000,$F00FF00F,$F00FF0F0,$F00FF0FF
DC.L $F00FFF00,$F00FFF0F,$F00FFFF0,$F00FFFFF
DC.L $F0F00000,$F0F0000F,$F0F000F0,$F0F000FF ;QUADRUPLING TABLE
DC.L $F0F00F00,$F0F00F0F,$F0F00FF0,$F0F00FFF
DC.L $F0F0F000,$F0F0F00F,$F0F0F0F0,$F0F0F0FF
DC.L $F0F0FF00,$F0F0FF0F,$F0F0FFF0,$F0F0FFFF
DC.L $F0FF0000,$F0FF000F,$F0FF00F0,$F0FF00FF ;QUADRUPLING TABLE
DC.L $F0FF0F00,$F0FF0F0F,$F0FF0FF0,$F0FF0FFF
DC.L $F0FFF000,$F0FFF00F,$F0FFF0F0,$F0FFF0FF
DC.L $F0FFFF00,$F0FFFF0F,$F0FFFFF0,$F0FFFFFF
DC.L $FF000000,$FF00000F,$FF0000F0,$FF0000FF ;QUADRUPLING TABLE
DC.L $FF000F00,$FF000F0F,$FF000FF0,$FF000FFF
DC.L $FF00F000,$FF00F00F,$FF00F0F0,$FF00F0FF
DC.L $FF00FF00,$FF00FF0F,$FF00FFF0,$FF00FFFF
DC.L $FF0F0000,$FF0F000F,$FF0F00F0,$FF0F00FF ;QUADRUPLING TABLE
DC.L $FF0F0F00,$FF0F0F0F,$FF0F0FF0,$FF0F0FFF
DC.L $FF0FF000,$FF0FF00F,$FF0FF0F0,$FF0FF0FF
DC.L $FF0FFF00,$FF0FFF0F,$FF0FFFF0,$FF0FFFFF
DC.L $FFF00000,$FFF0000F,$FFF000F0,$FFF000FF ;QUADRUPLING TABLE
DC.L $FFF00F00,$FFF00F0F,$FFF00FF0,$FFF00FFF
DC.L $FFF0F000,$FFF0F00F,$FFF0F0F0,$FFF0F0FF
DC.L $FFF0FF00,$FFF0FF0F,$FFF0FFF0,$FFF0FFFF
DC.L $FFFF0000,$FFFF000F,$FFFF00F0,$FFFF00FF ;QUADRUPLING TABLE
DC.L $FFFF0F00,$FFFF0F0F,$FFFF0FF0,$FFFF0FFF
DC.L $FFFFF000,$FFFFF00F,$FFFFF0F0,$FFFFF0FF
DC.L $FFFFFF00,$FFFFFF0F,$FFFFFFF0,$FFFFFFFF
MACRO
_Blit4word
MOVE.B D0,D4
BEQ.S @1
MOVE.L 0(A1,D4*4),D1
OR.L D1,(A0)
@1 LSR.W #8,D0
BEQ.S @2
MOVE.L 0(A1,D0*4),D1
OR.L D1,-4(A0)
@2
ENDM
MACRO
_Blit4long ;move src long
MOVE.B D0, D4 ;Get a copy
BEQ.S @1 ;nothing to blit
MOVE.L 0(A1,D4*4), D1 ;Add the bits
OR.L D1, (A0) ;Add the bits
@1 LSR.W #8, D0 ;Next four bits
BEQ.S @2 ;nothing to blit
MOVE.L 0(A1,D0*4), D1 ;Add the bits
OR.L D1, -4(A0) ;Add the bits
@2 SWAP D0
MOVE.B D0, D4 ;Get a copy
BEQ.S @3 ;nothing to blit
MOVE.L 0(A1,D4*4), D1 ;Add the bits
OR.L D1, -8(A0) ;Add the bits
@3 LSR.W #8, D0 ;Next four bits
BEQ.S @4 ;nothing to blit
MOVE.L 0(A1,D0*4), D1 ;Add the bits
OR.L D1, -12(A0) ;Add the bits
@4
ENDM
word4 MOVEQ #0, D4 ;ready for blit macro
LEA table4, A1 ;Table to the blit longs
ADD.L #4 , A0 ;Advance to last long of scan line
@mid MOVE.W (A2)+,D0 ;this particular example is or mode
LSR.W D2,D0 ;shift into place
_Blit4word
ADD D7,A0 ;advance to the next dest row
DBRA D3,@mid
RTS
bigWord4
; here, the character spans a word boundary, so must be handled with a long loop on 68K machines
MOVEQ #0, D4 ;ready for blit macro
LEA table4, A1 ;Table to the blit longs
ADD.L #12, A0 ;Advance to last long of scan line
@mid2
MOVE.L (A2),D0 ;this particular example is a copy mode
CLR D0 ;clear the low word
LSR.L D2,D0 ;shift into place
_Blit4long ;move src long
ADD D7,A0 ;advance to the next dest row
ADD #2,A2 ;advance to the next src row
DBRA D3,@mid2
RTS
long4
; We fit inside a long with the shift
MOVEQ #0, D4 ;ready for blit macro
LEA table4, A1 ;Table to the blit longs
ADD.L #12, A0 ;Advance to last long of scan line
@mid
MOVE.L (A2)+,D0 ;this particular example is a or mode
LSR.L D2,D0 ;shift into place
_Blit4long ;move src long
ADD.W D7,A0 ;advance to the next dest row
DBRA D3,@mid
RTS
bigLong4
MOVEQ #0, D4 ;ready for blit macro
LEA table4, A1 ;Table to the blit longs
ADD.L #12, A0 ;Advance to last long of scan line
SUB.W #16, D7 ;Advance one long less for dest
@mid
MOVE.L (A2),D0 ;this particular example is a or mode
LSR.L D2,D0 ;shift into place
_Blit4long ;move src long
SWAP D2 ;get the rightShift
MOVE.L (A2)+,D0 ;get second piece of the long
LSL.L D2,D0 ;shift into place
ADD.W #16, A0 ;next long
_Blit4long ;move src long
SWAP D2 ;restore the leftShift
ADD.W D7,A0 ;advance to the next dest row
DBRA D3,@mid
RTS
overLong4
;Many Longs to move
MOVEQ #0, D4 ;ready for blit macro
LEA table4, A1 ;Table to the blit longs
ADD.L #12, A0 ;Advance to last long of scan line
@mid
MOVE.L (A2),D0 ;this particular example is a or mode
LSR.L D2,D0 ;shift into place
_Blit4long ;move src long
SWAP D2 ;get the rightShift
ADD.W #16, A0 ;next long
MOVE.L (A2)+,D0 ;get second piece of the long
LSL.L D2,D0 ;shift into place
_Blit4long ;move src long
SWAP D2 ;restore the leftShift
DBRA D5,@mid ;# of longs in a scan line
MOVE.W A4, D5 ;# of src bytes
ADD.W D7,A0 ;advance to the next dest row
DBRA D3,@mid
ADD.W D6, D7 ;restore true value of dest row bytes
SWAP D6 ;Restore # of chars
RTS
;————————————————————————————————————————————————————————————————————————————————————————————————
; End 4-bit NEW FAST blit loop
;————————————————————————————————————————————————————————————————————————————————————————————————
;————————————————————————————————————————————————————————————————————————————————————————————————
; 16-bit NEW FAST blit loop
;————————————————————————————————————————————————————————————————————————————————————————————————
; Registers Use:
; D0 = scratch A0 = scratch
; D1 = scratch A1 = TextPtr.l
; D2 = shift.w A2 = bitsPtr.l
; D3 = scan.w A3 = glyphArray.l
; D4 = charLoc.l A4 = widTabPtr.l
; D5 = char*4.w A5 = DestPtr.l
; D6 = #chars.w A6 = stack frame.l
; D7 = rowBytes.w A7 = stack pointer.l
;————————————————————————————————————————————————————————————————————————————————————————————————
;———————————————————
;blitting loops
;———————————————————
MACRO
_blit16word
MOVEQ #1, D4 ;for inner loop
@inner ADDX.W D0,D0 ;if extended then blit
BCC.S @1
MOVE.W D1, (A0) ;Make 16-bit black bit
@1 ADDX.W D0,D0 ;if extended then blit
BCC.S @2
MOVE.W D1, 2(A0) ;Make 16-bit black bit
@2 ADDX.W D0,D0 ;if extended then blit
BCC.S @3
MOVE.W D1, 4(A0) ;Make 16-bit black bit
@3 ADDX.W D0,D0 ;if extended then blit
BCC.S @4
MOVE.W D1, 6(A0) ;Make 16-bit black bit
@4 ADDX.W D0,D0 ;if extended then blit
BCC.S @5
MOVE.W D1, 8(A0) ;Make 16-bit black bit
@5 ADDX.W D0,D0 ;if extended then blit
BCC.S @6
MOVE.W D1, 10(A0) ;Make 16-bit black bit
@6 ADDX.W D0,D0 ;if extended then blit
BCC.S @7
MOVE.W D1, 12(A0) ;Make 16-bit black bit
@7 ADDX.W D0,D0 ;if extended then blit
BCC.S @8
MOVE.W D1, 14(A0) ;Make 16-bit black bit
@8 ADD #16, A0 ;Bump to next set
DBRA D4,@inner
ENDM
MACRO
_blit16long
MOVEQ #3, D4 ;for inner loop
@inner ADDX.L D0,D0 ;if extended then blit
BCC.S @1
MOVE.W D1, (A0) ;Make 16-bit black bit
@1 ADDX.L D0,D0 ;if extended then blit
BCC.S @2
MOVE.W D1, 2(A0) ;Make 16-bit black bit
@2 ADDX.L D0,D0 ;if extended then blit
BCC.S @3
MOVE.W D1, 4(A0) ;Make 16-bit black bit
@3 ADDX.L D0,D0 ;if extended then blit
BCC.S @4
MOVE.W D1, 6(A0) ;Make 16-bit black bit
@4 ADDX.L D0,D0 ;if extended then blit
BCC.S @5
MOVE.W D1, 8(A0) ;Make 16-bit black bit
@5 ADDX.L D0,D0 ;if extended then blit
BCC.S @6
MOVE.W D1, 10(A0) ;Make 16-bit black bit
@6 ADDX.L D0,D0 ;if extended then blit
BCC.S @7
MOVE.W D1, 12(A0) ;Make 16-bit black bit
@7 ADDX.L D0,D0 ;if extended then blit
BCC.S @8
MOVE.W D1, 14(A0) ;Make 16-bit black bit
@8 ADD #16, A0 ;Bump to next set
DBRA D4,@inner
ENDM
bigWord16
word16 SUB.W #32,D7 ;adjust the rowbytes for loop
ADD.W D2,D2 ;NOT NEEDED AFTER SHIFT ADJUSTMENTS MADE ABOVE
ADD.W D2,A0 ;NOT NEEDED AFTER SHIFT ADJUSTMENTS MADE ABOVE
MOVEQ #0,D1 ;for dest black
@mid MOVE.W (A2)+,D0 ;this particular example is or mode
_blit16word ;Blit the bits
ADD D7,A0 ;advance to the next dest row
DBRA D3,@mid
RTS
bigLong16
long16 SUB.W #64,D7 ;adjust the rowbytes for loop
ADD.W D2,D2 ;NOT NEEDED AFTER SHIFT ADJUSTMENTS MADE ABOVE
ADD.W D2,A0 ;NOT NEEDED AFTER SHIFT ADJUSTMENTS MADE ABOVE
MOVEQ #0,D1 ;for dest black
@mid MOVE.L (A2)+,D0 ;this particular example is a or mode
_blit16long ;Blit the bits
ADD.W D7,A0 ;advance to the next dest row
DBRA D3,@mid
RTS
overLong16
ADD.W D2,D2 ;NOT NEEDED AFTER SHIFT ADJUSTMENTS MADE ABOVE
ADD.W D2,A0 ;NOT NEEDED AFTER SHIFT ADJUSTMENTS MADE ABOVE
MOVEQ #0,D1 ;for dest black
@mid MOVE.L (A2)+,D0 ;this particular example is a or mode
BEQ.S @skip
_blit16long ;Blit the bits
DBRA D5,@mid ;# of longs in a scan line
MOVE.W A4,D5 ;# of src bytes
ADD.W D7,A0 ;advance to the next dest row
DBRA D3,@mid
RTS
@skip ADD.W #64,A0
DBRA D5,@mid ;# of longs in a scan line
MOVE.W A4,D5 ;# of src bytes
ADD.W D7,A0 ;advance to the next dest row
DBRA D3,@mid
RTS
;————————————————————————————————————————————————————————————————————————————————————————————————
; END 16-bit NEW FAST blit loop
;————————————————————————————————————————————————————————————————————————————————————————————————
;————————————————————————————————————————————————————————————————————————————————————————————————
; 32-bit NEW FAST blit loop
;————————————————————————————————————————————————————————————————————————————————————————————————
; Registers Use:
; D0 = scratch A0 = scratch
; D1 = scratch A1 = TextPtr.l
; D2 = shift.w A2 = bitsPtr.l
; D3 = scan.w A3 = glyphArray.l
; D4 = charLoc.l A4 = widTabPtr.l
; D5 = char*4.w A5 = DestPtr.l
; D6 = #chars.w A6 = stack frame.l
; D7 = rowBytes.w A7 = stack pointer.l
;————————————————————————————————————————————————————————————————————————————————————————————————
;———————————————————
;blitting loops
;———————————————————
MACRO
_blit32word
MOVEQ #1, D4 ;for inner loop
@inner ADDX.W D0,D0 ;if extended then blit
BCC.S @1
MOVE.L D1, (A0) ;Make 16-bit black bit
@1 ADDX.W D0,D0 ;if extended then blit
BCC.S @2
MOVE.L D1, 4(A0) ;Make 16-bit black bit
@2 ADDX.W D0,D0 ;if extended then blit
BCC.S @3
MOVE.L D1, 8(A0) ;Make 16-bit black bit
@3 ADDX.W D0,D0 ;if extended then blit
BCC.S @4
MOVE.L D1, 12(A0) ;Make 16-bit black bit
@4 ADDX.W D0,D0 ;if extended then blit
BCC.S @5
MOVE.L D1, 16(A0) ;Make 16-bit black bit
@5 ADDX.W D0,D0 ;if extended then blit
BCC.S @6
MOVE.L D1, 20(A0) ;Make 16-bit black bit
@6 ADDX.W D0,D0 ;if extended then blit
BCC.S @7
MOVE.L D1, 24(A0) ;Make 16-bit black bit
@7 ADDX.W D0,D0 ;if extended then blit
BCC.S @8
MOVE.L D1, 28(A0) ;Make 16-bit black bit
@8 ADD #32, A0 ;Bump to next set
DBRA D4,@inner
ENDM
MACRO
_blit32long
MOVEQ #3, D4 ;for inner loop
@inner ADDX.L D0,D0 ;if extended then blit
BCC.S @1
MOVE.L D1, (A0) ;Make 16-bit black bit
@1 ADDX.L D0,D0 ;if extended then blit
BCC.S @2
MOVE.L D1, 4(A0) ;Make 16-bit black bit
@2 ADDX.L D0,D0 ;if extended then blit
BCC.S @3
MOVE.L D1, 8(A0) ;Make 16-bit black bit
@3 ADDX.L D0,D0 ;if extended then blit
BCC.S @4
MOVE.L D1, 12(A0) ;Make 16-bit black bit
@4 ADDX.L D0,D0 ;if extended then blit
BCC.S @5
MOVE.L D1, 16(A0) ;Make 16-bit black bit
@5 ADDX.L D0,D0 ;if extended then blit
BCC.S @6
MOVE.L D1, 20(A0) ;Make 16-bit black bit
@6 ADDX.L D0,D0 ;if extended then blit
BCC.S @7
MOVE.L D1, 24(A0) ;Make 16-bit black bit
@7 ADDX.L D0,D0 ;if extended then blit
BCC.S @8
MOVE.L D1, 28(A0) ;Make 16-bit black bit
@8 ADD #32, A0 ;Bump to next set
DBRA D4,@inner
ENDM
bigWord32
word32 SUB.W #64,D7 ;adjust the rowbytes for loop
LSL.W #2,D2 ;NOT NEEDED AFTER SHIFT ADJUSTMENTS MADE ABOVE
ADD.W D2,A0 ;NOT NEEDED AFTER SHIFT ADJUSTMENTS MADE ABOVE
MOVEQ #0, D1 ;for dest black
@mid MOVE.W (A2)+,D0 ;this particular example is or mode
_blit32word ;Blit the bits
ADD D7,A0 ;advance to the next dest row
DBRA D3,@mid
RTS
bigLong32
long32 SUB.W #128,D7 ;adjust the rowbytes for loop
LSL.W #2,D2 ;NOT NEEDED AFTER SHIFT ADJUSTMENTS MADE ABOVE
ADD.W D2,A0 ;NOT NEEDED AFTER SHIFT ADJUSTMENTS MADE ABOVE
MOVEQ #0,D1 ;for dest black
@mid MOVE.L (A2)+,D0 ;this particular example is a or mode
_blit32long ;Blit the bits
ADD.W D7,A0 ;advance to the next dest row
DBRA D3,@mid
RTS
overLong32
LSL.W #2,D2 ;NOT NEEDED AFTER SHIFT ADJUSTMENTS MADE ABOVE
ADD.W D2,A0 ;NOT NEEDED AFTER SHIFT ADJUSTMENTS MADE ABOVE
MOVEQ #0,D1 ;for dest black
@mid MOVE.L (A2)+,D0 ;this particular example is a or mode
BEQ.S @skip
_blit32long ;Blit the bits
DBRA D5,@mid ;# of longs in a scan line
MOVE.W A4,D5 ;# of src bytes
ADD.W D7,A0 ;advance to the next dest row
DBRA D3,@mid
RTS
@skip ADD.W #128,A0
DBRA D5,@mid ;# of longs in a scan line
MOVE.W A4,D5 ;# of src bytes
ADD.W D7,A0 ;advance to the next dest row
DBRA D3,@mid
RTS
ENDIF
;————————————————————————————————————————————————————————————————————————————————————————————————
; END 32-bit NEW FAST blit loop
;————————————————————————————————————————————————————————————————————————————————————————————————
;————————————————————————————————————————————————————————————————————————————————————————————————
; CACHE RETRIEVAL
;————————————————————————————————————————————————————————————————————————————————————————————————
; Input:
; D3 = glyphID
;
renderIt
MOVEM.L A1/D0-D2,-(SP) ;Save off all registers before JSR
SUBQ #4,SP ;make room for result
MOVE.W D3, glyphID(A6) ;put glyphID into sp_Glyph
if (hasDoubleByte) then
tst.l encodingTable(a6) ; is this a double byte font?
beq.s @singleByteFont ; no, skip loading low byte
move.b highByte(a6),glyphID(a6) ; save the high byte
move.b lowByte(a6),glyphID+1(a6) ; save the low byte
@singleByteFont
endif
MOVE.L WidthTabHandle, -(SP) ;2) Push the Width Table Handle onto the stack
PEA fontID(A6) ;1) Push the Glyph Rec Ptr
IF HAS_COLOR THEN
TST.B FASTFLAG(A6) ;if slow no need for 32-bit stuff
BEQ.S @skip32 ;
TST.B needs32bit(A6) ;running 32 bit clean
BEQ.S @skip32 ;NOPE, so skip it
move.b MMUsave(a6),d0 ;get previous MMU state in d0
_rSwapMMUMode ;get previous mode in d0.b (can trash a0/a1/a2, d0/d1/d2)
_sbRetrieveGlyph ;Call the routine via SplineDispatch
moveq #true32b,d0 ;switch to 32 bit addressing
_rSwapMMUMode ;get previous mode in d0.b (can trash a0/a1/a2, d0/d1/d2)
MOVE.L srcAddr(A6), A2 ;Get the address
MOVE.L A2, D0 ;get 24 bit base addr
_rTranslate24To32 ;mask off high byte
MOVE.L D0,A2 ;SAVE FOR LATER
BRA.S @skip24
ENDIF
@skip32
_sbRetrieveGlyph ;Call the routine via SplineDispatch
MOVE.L srcAddr(A6), A2 ;Get the address
@skip24
;——————————————————
; Set up pointers
;——————————————————
TST.B nextBand(A6) ;another band?
BEQ.S @noBands ;no so continue
BSET.L #31, D3 ;set continue bit
BRA.S @1
@noBands
BCLR.L #31, D3 ;no new bands
@1
MOVE.L WidthTabHandle,A0 ;Get the handle
MOVE.L (A0),A4 ;restore the width table pointer
;The cacheHand may have change if we got
;Memory somewhere else
MOVE.L expandMem,A0 ; get low memory expand pointer.
MOVE.L ExpandMemRec.emSplineKey(A0),A0 ; get handle to splineKey globals.
MOVE.L (A0), A0 ; get pointer to splineKey globals.
MOVE.L splineKeyRec.cacheHand(A0),A0 ; Get the handle in case it changed.
MOVE.L A0, cacheHand(A6) ;restore cacheHand
IF HAS_COLOR THEN
MOVE.L (A0), D0 ;pointer to the cache
_StripAddress ;Make sure it is the right mode
MOVE.L D0, D5 ;restore cache pointer
MOVE.L D0, A0 ;
ELSE
MOVE.L (A0), D5 ;pointer to the cache
MOVE.L D5, A0 ;
ENDIF
LEA cache.glyphArray(A0), A3 ;Get array of glyphs into A3
;——————————————————
TST.L (SP)+ ;Any Errors
MOVEM.L (SP)+, A1/D0-D2 ;Restore all registers on return
BNE @skipGlyph
IF NOT HAS_COLOR THEN
ADD.W D3, D3
ADD.W D3, D3
ENDIF
MOVE.L entryOffset(A6), D0
ADD.L D0, A0 ;point to glyph record
MOVEQ #0, D0 ;No error
@skipGlyph
RTS
;————————————————————————————————————————————————————————————————————————————————————————————————
; END CACHE RETRIEVAL
;————————————————————————————————————————————————————————————————————————————————————————————————
renderChar
MOVEM.L D0-D1,-(SP) ;Save off all registers before JSR
MOVE.W D5, glyphID(A6) ;put glyphID into sp_Glyph
if (hasDoubleByte) then
tst.l encodingTable(a6) ; is this a double byte font?
beq.s @singleByteFont ; no, skip loading low byte
move.b highByte(a6),glyphID(a6) ; save the high byte
move.b lowByte(a6),glyphID+1(a6) ; save the low byte
@singleByteFont
endif
MOVE.W #0, topClip(A6) ;do not need the bits
MOVE.W #0, botClip(A6) ;do not need the bits
SUBQ #4,SP ;make room for result
MOVE.L WidthTabHandle, -(SP) ;2) Push the Width Table Handle onto the stack
PEA fontID(A6) ;1) Push the Glyph Rec Ptr
_sbRetrieveGlyph ;Call the routine via SplineDispatch
;———————————————————
; Re-establish ptrs
;———————————————————
;The cacheHand may have change if we got
;Memory somewhere else
MOVE.L expandMem,A0 ; get low memory expand pointer.
MOVE.L ExpandMemRec.emSplineKey(A0),A0 ; get handle to splineKey globals.
MOVE.L (A0), A0 ; get pointer to splineKey globals.
MOVE.L splineKeyRec.cacheHand(A0),A0 ; Get the handle in case it changed.
MOVE.L A0, cacheHand(A6) ;restore cacheHand
MOVE.L (A0), A0 ;pointer to the cache
MOVE.L A0, D2 ;pointer to the cache
LEA cache.glyphArray(A0), A2 ;Get array of glyphs into A0
MOVE.L WidthTabHandle,A1 ;Get the handle
MOVE.L (A1),A1 ;restore the width table pointer
;———————————————————
ADDQ #4, SP ;Ignore errors <58-CEL>
MOVEM.L (SP)+, D0-D1 ;Restore all registers on return
IF NOT HAS_COLOR THEN
ADD.W D5, D5
ADD.W D5, D5
ENDIF
MOVE.L entryOffset(A6), D0
BEQ @errExit ;if zero then no info <58-CEL>
ADD.L D2, D0 ;add offset and point to glyph data
MOVE.L D0, A0 ;Get in address reg
@errExit
RTS
;————————————————————————————————————————————————————————————————————————————————————————————————
; END NEW FAST BLIT loop
;————————————————————————————————————————————————————————————————————————————————————————————————
ENDIF ;hasSplineFonts
;————————————————————————————————————————————————————————————————————————————————————————————————
; END hasSplineFonts… BEGIN BITMAPS
;————————————————————————————————————————————————————————————————————————————————————————————————
BitVarSetUp
MOVE stackOffset(A6),D0 ;either zero if stack was long aligned, or two if not
; MOVE.L numer(A6,D0),numer2(A6)
; MOVE.L denom(A6,D0),denom2(A6) ;save original numer, denom for iterative case
CLR charsRemain(A6) ;for iterative case
BRA.S goBitSetUp
;————————————————————————————————————————————————————————————————————————————————————————————————
; Iterate
;
; Entry point when subdividing a string
;
Iterate
MOVE stackOffset(A6),D0 ;either zero if stack was long aligned, or two if not
CLR -(SP) ;ROOM FOR FCN RESULT
MOVE COUNT(A6,D0),D1 ;get count
MOVE D1,-(SP) ;PUSH COUNT
BLE GOHOME ;QUIT IF COUNT <= 0
;STACK CLEANED UP BY SAVESTK
MOVE D1,countCopy(A6) ;save copy of count
IF (hasSplineFonts) OR (Gaudi) THEN ; <31> DTY
MOVE D1,origCharCount(A6) ;save copy of count
ENDIF ;
;————————————————————————————————————————————————————————————————————————————————————————————————
; CALL to StdTxMeas
;
; Routine will load font and return width. StdTxMeas stashes FMOutPtr in
; QD global FONTPTR. Unscaled fixed point text width is stored in FontAdj
; for CQD not B&W.
;
MOVE.L textPtr(A6),-(SP) ;PUSH TEXTADDR
PEA NUMER(A6,D0) ;PUSH VAR NUMER
PEA DENOM(A6,D0) ;PUSH VAR DENOM
PEA INFO(A6) ;PUSH VAR INFO
lea JStdTxMeas,A0 ;get piece of trap table
move.l (a0),a0 ; <31> DTY changed from move.l
IF NOT HAS_COLOR THEN
MOVE.L (A0),A0
ENDIF
JSR (A0) ;MEASURE TEXT
;————————————————————————————————————————————————————————————————————————————————————————————————
; Stack Variable SetUp
;
; Registers on Entry:
; A4 = Graf globals
;
; Registers used:
; A1 = WidthPtr
; A2 = Font strike ptr
; A6 = Stack frame
; A4 = FmOutput record ptr
;
; Preserves:
; D1 = Width of string
;
; CLOBBERS: A0, D0, D2, D3
;
;————————————————————————————————————————————————————————————————————————————————————————————————
;————————————————————————————————————————————————————————————————————————————————————————
; Get the text width in D1.
;————————————————————————————————————————————————————————————————————————————————————————
ADDQ #2,SP ;POP (and ignore) UNSCALED WIDTH RESULT
MOVE.L fontAdj(A4),D1 ;get fixed point width
MOVE.L fontPtr(A4),A4 ;Point to FmOutput record
;————————————————————————————————————————————————————————————————————————————————————————
; Common entry point for iteration or first pass. Same register setup as above, with
; the FMOutput pointer already loaded into A4. Load the font strike pointer into A2.
;————————————————————————————————————————————————————————————————————————————————————————
goBitSetUp
CLR.L maskBitsPtr(A6) ;assume no mask
IF (hasSplineFonts) OR (Gaudi) THEN ; <31> DTY
CLR.L stackHandle(A6) ;clear stackHandle
SF isSpline(A6) ;Set not spline font
ENDIF
MOVE.L fmOutFontH(A4),A2 ;Font Handle in register
MOVE.L (A2),A2 ;Dereference for Font Ptr
;————————————————————————————————————————————————————————————————————————————————————————
; Check font flag bits and set local flags.
;————————————————————————————————————————————————————————————————————————————————————————
CLR.B doDither(A6) ;init to no dither <CEL-39>
MOVE stackOffset(A6),D4 ;0 if no offset, 2 if word offset
MOVE fFontType(A2),D0 ;font flags
BTST #8,D0 ;synthetic font ? <CEL-44>
SNE synFont(A6) ;used for check if orig fctb is needed <CEL-44>
BTST #9,D0 ;contains colors?
SNE colorSource(A6) ;if so, pass info to stretch later
BEQ.S @noDither ;do not set the dither bit <CEL-39>
MOVE.W numer(A6,D4),D2 ;get the numer.v <CEL-39>
CMP.W denom(A6,D4), D2 ;Check if shrinking <CEL-39>
SLT doDither(A6) ;Do the dither if shrinking <CEL-39>
@noDither ; <CEL-39>
LSR #2,D0 ;toss bottom two bits
AND #$7,D0 ;0 … 5 (bit depth of 1 … 32)
SNE D2 ;note that the incoming font is not 1 deep
MOVE D0,bitShift(A6) ;bits per pixel shift count
MOVEQ #1,D3
LSL D0,D3
MOVE D3,bitDepth(A6) ;bits per pixel
BTST #0,fFontType+1(A2) ;DOES FONT HAVE HEIGHT TABLE ?
SNE HEIGHTFLAG(A6) ;REMEMBER FOR LATER
MOVE.L numer(A6,D4),D0 ;Numer in reg <CEL-44>
CMP.L denom(A6,D4),D0 ;Is denom different <CEL-44>
SNE stretch(A6) ;Different then set the flag
;————————————————————————————————————————————————————————————————————————————————————————
; Set up the kerning properties. If this font has kerning, we only want to adjust by
; the kerning amount plus the offset for the first character in the text.
;————————————————————————————————————————————————————————————————————————————————————————
clr.w kernBounds(a6) ; clear kerning boundary.
move.w fKernMax(a2),kernAdjust(a6) ; have a kerning adjustment?
IF hasFullKerning THEN
bpl.s @noKerning ; no -> skip kerning stuff.
move.l textPtr(a6),a0 ; load the text pointer.
clr.l d0 ; clear a long.
move.b (a0),d0 ; load the first character.
move.w fNDescent(a2),d2 ; extended offset/width table location?
bpl.s @0 ; yes -> use as the high word.
clr.l d2 ; no -> clear the high word.
@0 swap d2 ; move to the high word.
move.w LENGTH(a2),d2 ; load the low word too.
IF &SETTING('MACHINE') <> 'MC68000' THEN
lea 16(a2,d2.l*2),a0 ; load pointer to offset/width table.
move.w 0(a0,d0.w*2),d0 ; load character offset/width.
ELSE
add.l d2,d2
lea 16(a2,d2.l),a0
add.w d0,d0
move.w 0(a0,d0.w),d0
ENDIF
cmp.w #-1,d0 ; missing character?
bne.s @1 ; no -> skip this.
move.w (a0),d0 ; load missing character offset/width.
@1 lsr.w #8,d0 ; isolate the offset byte.
add.w fKernMax(a2),d0 ; kerning adjustment > 0?
bgt.s @noKerning ; yes -> use kerning adjustment.
move.w d0,kernBounds(a6) ; save the kerning adjustment.
@noKerning
ENDIF
MOVE.W fDescent(A2), D0
NEG D0
MOVE.W D0, sDescent(A6) ;Descent val on stack
MOVE.W locASCENT(A2), sAscent(A6) ;Ascent val on stack
MOVE.W FBBDY(A2), sHeight(A6) ;Height val on stack
MOVE.W FBBDY(A2), TOPHT(A6) ;Top and Height vals on stack
@noItalic
MOVE txMode(A3),D0
AND #$FFF7,D0 ;clear pattern bit (let stretch reject invalid modes)
TST.B colorSource(A6) ;does the source contain colors?
BEQ.S @noColors
CMP #srcOr,D0 ;is it srcOr?
BNE.S @noColors
MOVEQ #64,D0 ;set it to srcCopy + mask
@noColors
MOVE D0,locMode(A6) ;initialize copy
IF HAS_COLOR THEN
BTST #6,D0 ;bit 6 if set says use a mask
SNE D3 ;remember it
BEQ.S @skipMask
LEA srcPix(A6),A0 ;assume no mask font needed; just use source instead
MOVE.L A0,maskBitsPtr(A6) ;pass mask to stretch bits
@skipMask
ENDIF
BTST #5,D0 ;arithmetic mode?
BEQ.S @skipArith ;if not, dont map if dest. is 1 bit deep
IF HAS_COLOR THEN
CMP #1,dstPix+pixelSize(A6) ;1 bit deep destination?
BNE.S @multideep ;if not, arithmetic mode is OK
ENDIF
LEA ArithMode,A0 ;get mode map
AND #7,D0 ;look at each different arith mode
MOVE.B 0(A0,D0),D0 ;map into 1 bit safe mode
MOVE D0,locMode(A6) ;alter mode properly for 1 bit depth
@skipArith
@multideep
AND.B D2,D3 ;build mask characters if incoming is not 1 deep
IF HAS_COLOR THEN
BEQ.S @noMask
MOVE.L widTabFont(A1),A0 ;Add offset
MOVE.L (A0),D0 ;Get pointer
SNE D3
BEQ.S @noMask
MOVE.L D0,A0 ;get address of font
MOVEQ #0,D0
MOVE fRowWords(A0),D0 ;width of strike bit map in words
ADD.L D0,D0 ;convert to bytes
MOVE.L D0,mSrcRow(A6) ;save it
LEA 26(A0),A0
MOVE.L A0,maskAddr(A6) ;address of mask bits
LEA maskBits(A6),A0 ;pointer to mask bitmap
MOVE.L A0,maskBitsPtr(A6) ;pass mask to stretch bits
@noMask
ENDIF
MOVE.B D3,maskFont(A6) ;0 if mask bit clear, no mask font, or incoming 1 deep
OR.B colorSource(A6),D3 ;if color source or mask font, do bit insert/extract
MOVE.B D3,textCopyMode(A6) ;set up bit insert/extract flag
;————————————————————————————————————————————————————————————————————————————————————————————————
; END Stack Variable SetUp
;————————————————————————————————————————————————————————————————————————————————————————————————
;————————————————————————————————————————————————————————————————————————————————————————————————
; Bounding Rect set up
;
; Setup textRect, the rectangle bounding the entire string.
;
; Registers on Entry:
; A2 = Font Ptr
; A3 = thePort
; A4 = FmOutput record ptr
; A6 = Stack frame
;
; D1 = Width of string
;
; Register Use:
; D2 = PenLocation (Set up as fixed)
;
; Clobbers:
; D0, D3
;
;————————————————————————————————————————————————————————————————————————————————————————————————
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
SWAP D2
IF hasPenFraction THEN
move.l grafGlobals(a5),a0 ; load quickDraw globals.
move.w pnLocFixed(a0),d2 ; append pen fraction.
move.w d2,penLocFixed(a6) ; save pen fraction for recursive drawing.
ELSE
move.w #$8000,d2 ; append default fraction.
ENDIF
;———————————————————————————————————————————————————————————————
; set flag to note if mode is srcOr & foreColor is black
; set up characterExtra if new port or script manager around
; set up pnLocHFrac if new port
;———————————————————————————————————————————————————————————————
CMP #srcOr,locMode(A6) ;is the mode srcOr?
SEQ orMode(A6)
BCLR #6,locMode+1(A6) ;was mask set?
BEQ.S @noMaskMode
TST locMode(A6) ;is it srcCopy + mask?
SEQ orMode(A6) ;that can go fast, too.
@noMaskMode
moveq #0, d0 ; clear the character extra. <49>
IF HAS_COLOR THEN
tst.b portBits+rowBytes(a3) ; is this an old grafPort?
bpl.s @oldGrafPort ; yes -> skip this.
move.w chExtra(a3),d0 ; load the character extra.
ext.l d0 ; extend sign bits <49>
asl.l #4,d0 ; convert to 16.16 format.
@oldGrafPort
ENDIF
IF SCRIPT_CHAR_EXTRA THEN
move.l grafGlobals(a5),a0 ; load quickDraw globals. <43>
add.l qdChExtra(a0),d0 ; add in the character extra. <43>
ENDIF
tst.l d0 ; have zero character extra?
beq.s @zeroCharExtra ; yes -> skip call to scale.
bsr CalcCharExtra ; scale by point size, etc.
@zeroCharExtra
move.l d0,characterExtra(a6) ; store scaled character extra.
IF HAS_COLOR THEN
TST PORTBITS+ROWBYTES(A3) ; is it a new port?
BPL.S @useOld ; no -> dont set up fraction
MOVE pnLocHFrac(A3),D2 ; set up with proper fraction
MOVE D2,penLocHFrac(A6) ; save for later as well for recursive drawing
;———————————————————————————————————————————————————————————————————————————————————————
; ForeGround - BackGround check
;
; This next part is a little tricky:
; If the source does not contain any colors (that is, regardless of whether the source is
; one bit per pixel or more, the pixels are either black or white) then we can go fast if
; the forecolor is black, regardless of the background color. If the font does contain colors,
; then we can go fast if the background is white, regardless of the foreground colors.
;
; But, if the foreground and background pixels are equal (but the font is a 1 bit font), then go
; slow. ColorMap will be called later to sort out whether the foreground color needs to be
; remapped or not.
;———————————————————————————————————————————————————————————————————————————————————————
;———————————————————————————————————
; This is the real code
;———————————————————————————————————
MOVE.L fgColor(A3),D0
CMP.L bkColor(A3),D0 ;same as background?
BEQ.S @goSlow ;if so, go slow
ADDQ.L #1,D0 ;now equal to number of colors, if black
MOVE dstPix+pixelSize(A6),D3 ;bits per pixel
LSR.L D3,D0 ;1 if black, 0 if other color
@goSlow
SNE D0 ;remember if black (or if fg/bk pixels are not equal)
TST.B colorSource(A6) ;is the source multicolored?
BEQ.S @oldCommon ;just worry about black
TST.L bkColor(A3) ;if colored source, must worry about bk = white also
BRA.S @oldBackCommon ;share with old mode
@useOld
ENDIF
BTST #5,fgColor+3(A3) ;is the foreground color black?
SNE D0 ;set to zero if not
TST.B colorSource(A6) ;is the source multicolored?
BEQ.S @oldCommon
BTST #0,bkColor+3(A3) ;is the background white?
@oldBackCommon
SEQ D0 ;true if white
@oldCommon
AND.B D0,orMode(A6) ;true if or mode and black monochrome or white multi.
ADD.L D1,D2 ;right := left + width
SWAP D2 ;just look at high word
TST.B fmOutCurStyle(A4)
BEQ noSlop ;if no style, certainly no slop
MOVEQ #0,D0 ;clear out high word
MOVE.B fmOutItalic(A4),D0 ;figure out italic
EXT.W D0 ;Make it a word
MOVE sAscent(A6),D3 ;Use the stack Ascent
SUBQ #1,D3 ;the line above the baseline is not shifted
MULU D3,D0 ;maximum italic = char ascent * FOutItalic
ASR #4,D0 ;italic factor is divided by 16 (normally 8)
@2 ADD.B fmOutBold(A4),D0 ;add boldness
SUB.B fmOutExtra(A4),D0 ;less total extra added
EXT D0 ;make it a word
MOVEQ #4,D3 ;restrict shadow in the range of 0 .. 3 (+1 if shadow)
CMP.B fmOutShadow(A4),D3 ;is it less or same?
BLE.S @pinShadow ;if so, pin at limit
MOVE.B fmOutShadow(A4),D3 ;otherwise, pass actual value
BEQ.S @pinShadow
ADDQ #1,D3 ;plus 1 for character insides shifted to right
@pinShadow
ADD D3,D0 ;combine shadow with italic slop count
ADD D0,D2 ;SLOP FOR ITALIC,BOLD,OVERSTRIKE
MOVEQ #0, D0
MOVE.B fmOutItalic(A4),D0 ;get the bit size below the baseline
MULU fDescent(A2),D0 ;maximum italic = char descent * FOutItalic
ASR #4,D0 ;which is based on 16 = 1 dot per line
IF hasFullKerning THEN
SUB D0, kernBounds(A6) ;include italic in calculating kerning
ELSE
SUB D0, kernAdjust(A6)
ENDIF
NOSLOP
IF hasFullKerning THEN
move.w kernBounds(a6),d0 ; load kerning boundary.
ELSE
move.w kernAdjust(a6),d0 ; load kerning adjustment.
ENDIF
ADD.W D0,textRect+left(A6) ;include kerning in text rectangle
MOVE.W D2,TEXTRECT+RIGHT(A6) ;STORE IN TEXTRECT.RIGHT
MOVE PENLOC(A6),D2 ;GET PNLOC.V
SUB sAscent(A6),D2 ;Use the stack Ascent
MOVE D2,TEXTRECT+TOP(A6) ;TEXTRECT.TOP := PNLOC.V - ASCENT
ADD sHeight(A6),D2 ;Height metric off stack
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
;———————————————————————
TST.B Stretch(A6) ;Are we stretching?
BEQ NOSTRCH ;Skip stretching
;—————————————————————————————————————————————————————————————————
; Set up for stretching
;
; We will be stretching. Setup fromRect and toRect and map textR2.
;
MOVE stackOffset(A6),D3 ;0 if no offset, 2 if word offset
IF &SETTING('MACHINE') <> 'MC68000' THEN
MOVE.L NUMER(A6,D3),D0 ;GET NUMERATOR
SWAP D0
CLR D0 ;make it fixed point
MULU.L D0,D0:D1 ;MULT WIDTH BY NUMER.H
MOVEQ #0,D2
MOVE Denom+H(A6,D3),D2
SWAP D2
DIVU.L D2,D0:D1 ;DIV BY DENOM.H
ELSE
MOVE.W D1,D0
SWAP D1
MULU.W NUMER+2(A6,D3),D0
MULU.W NUMER+2(A6,D3),D1
TST.W D0
BPL.S @noCarry
ADD.L #$10000,D0
@noCarry
CLR D0
SWAP D0
ADD.L D1,D0
DIVU.W DENOM+2(A6,D3),D0
MOVE.W D0,D1
CLR D0
DIVU.W DENOM+2(A6,D3),D0
SWAP D1
MOVE.W D0,D1
SWAP D0
ADD.W D0,D0
CMP.W DENOM+2(A6,D3),D0
BLE.S @noCarry2
ADD.L #1,D1
@noCarry2
ENDIF
MOVE.L PENLOC(A6),D0 ;GET PENLOC
MOVE.L D0,TORECT+TOPLEFT(A6) ;SET UP TORECT TOPLEFT
ADD.W NUMER+H(A6,D3),D0 ;CALC PENLOC.H + NUMER.H
MOVE D0,TORECT+RIGHT(A6) ;SET UP TORECT RIGHT
SWAP D0 ;GET PENLOC.V
ADD NUMER+V(A6,D3),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,D3),D0 ;CALC PENLOC.H + DENOM.H
MOVE D0,FROMRECT+RIGHT(A6) ;SET UP FROMRECT RIGHT
SWAP D0 ;GET PENLOC.V
ADD DENOM+V(A6,D3),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
_MAPRECT ;MAP TEXTR2 (PRESERVES ALL REGS)
NOSTRCH
ANDI #$0F,CCR ; need to clear 'x' flag
IF hasPenFraction THEN
move.l grafGlobals(a5),a0 ; load quickDraw globals.
add.w d1,pnLocFixed(a0) ; add width fraction to location fraction.
ENDIF
IF HAS_COLOR THEN
TST PORTBITS+ROWBYTES(A3) ; is it a new port?
BPL.S @useOld ; no, dont bother with fraction
ADD D1,pnLocHFrac(A3)
@useOld
ENDIF
;—————————————————————————————
; Move pen by the scaled text width
;—————————————————————————————
SWAP D1 ;Make integer
MOVE PNLOC+H(A3),D0 ;Get the current pen location
ADDX D1,D0 ;New Pen Loc = OldPenLoc + TextWidth
MOVE D0,PNLOC+H(A3) ;Save new pen location
;————————————————————————————
; Quit if the pen is hidden
;————————————————————————————
TST PNVIS(A3) ;IS PNVIS < 0 ?
BLT GOHOME ;YES, QUIT
;————————————————————————————————————————————————————————————————————————————————————————————————
; END Bounding Rect set up
;————————————————————————————————————————————————————————————————————————————————————————————————
;————————————————————————————————————————————————————————————————————————————————————————————————
; Calculate the MinRect
;
; Calc minRect: the intersection of textRect, bitMap bounds,
; clipRgn and visRgn bounding boxes. Quit if no intersection.
; The right bounds of the destination rect is set to the max to allow right kerning
; (Right kerning only works (without trailing spaces) in OR mode.
;
; Registers on Entry:
; A2 = Font Ptr
; A3 = thePort
; A4 = FmOutput record ptr
; A6 = Stack frame
;
; Clobbers:
; A0, A1
; D0, D1, D2, D3
;
;————————————————————————————————————————————————————————————————————————————————————————————————
MOVE textR2+right(A6),-(SP) ;preserve existing right
MOVE #32000,textR2+right(A6) ;get right from other rects
PEA TEXTR2(A6) ;PUSH (MAPPED) TEXTRECT
IF HAS_COLOR THEN
PEA DSTPIX+BOUNDS(A6) ;PUSH PIXMAP BOUNDS
ELSE
PEA PORTBITS+BOUNDS(A3)
ENDIF
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
IF HAS_COLOR THEN
_RSECT ;CALC INTERSECTION
ELSE
jsrROM ROMRSect
ENDIF
BEQ GOHOME ;QUIT IF NO INTERSECTION
MOVE (SP)+,textR2+right(A6) ;restore text right
;—————————————————————————————————————————————
; Bitmap Font Ptrs SetUp
;
; Set up srcAddr, srcRow, and height
;—————————————————————————————————————————————
LEA 26(A2),a0 ;GET START OF FONT BITMAP
MOVE.L a0,SRCADDR(A6) ;SAVE FOR LATER
MOVEQ #0,D1 ;zero high word
MOVE RASTER(A2),D1 ;GET WORDS PER ROW IN FONT
MOVE bitShift(A6),D0
LSL.L D0,D1 ;scale up font rowWords
ADD.L D1,D1 ;DOUBLE FOR BYTES PER ROW
MOVE.L D1,SRCROW(A6) ;REMEMBER FOR LATER
;—————————————————————————————————————————————————————————————————————
; FAST or NOTFAST check
;
; Test for fast case:
; not stretched, no color mapping, txMode = srcOr, same bits per pixel
; not bold, italic, underlined, outlined or shadowed,
; visRgn and clipRgn both rectangular.
;—————————————————————————————————————————————————————————————————————
TST.B fmOutItalic(A4) ;TEST BOLD $$$
BNE NOTFAST ;NOT FAST UNLESS BOTH ZERO
TST.B fmOutBold(A4) ;TEST BOLD
BNE NOTFAST ;NOT FAST
TST.W fmOutULThick(A4) ;Test ULTHICK and SHADOW (fmOutULThick,fmOutShadow)
BNE NOTFAST ;NOT FAST UNLESS BOTH ZERO
TST.B Stretch(A6) ;IS TEXT STRETCHED ?
BNE NOTFAST ;YES, NOT FAST
TST.B orMode(A6) ;IS TEXT MODE SRCOR ? (or srcCopy + mask, see above)
BEQ NOTFAST ;NO, NOT FAST
MOVE.L CLIPRGN(A3),A0 ; Get clip region
MOVE.L (A0),A0 ; Dereference handle
MOVEQ #10,D0
CMP RGNSIZE(A0),D0 ;IS CLIPRGN RECTANGULAR ?
BNE NOTFAST ;NO, NOT FAST
IF HAS_COLOR THEN
MOVEQ #1,D0
MOVE bitShift(A6),D1 ;get the depth of the source map
LSL D1,D0 ;turn into 1 … 8
CMP DSTPIX+PIXELSIZE(A6),D0 ;same depth per pixel?
BNE NOTFAST ;=>NOPE
cmp #16,dstPix+pixelType(A6) ;is it a direct device? @@@@ BAL 16Jun88
bne.s modeok
seq textCopyMode(a6) ;yes, can't go fast for now @@@@ BAL 16Jun88
clr locmode(a6) ;this essentially alters mode to srcCopy
bra NotFast
modeok
ENDIF
MOVE.L VISRGN(A3),A1 ;GET VISRGN HANDLE
MOVE.L (A1),A0 ;DE-REFERENCE IT
CMP #10,RGNSIZE(A0) ;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
IF HAS_COLOR THEN
TST.B is32QD(A6)
BEQ.S @not32bit
MOVE.W #-1, -(SP) ;trim = true for BRUCE
@not32bit
_TRIMRECT ;CALL TRIMRECT
ELSE
jsrROM ROMTrimRect
ENDIF
BLT GOHOME ;quit if intersection empty
BGT NOTFAST ;continue if non-rectangular
;————————————————————————————————————————————————————————————————————————————————————————————————
; END Calculate the MinRect
;————————————————————————————————————————————————————————————————————————————————————————————————
;————————————————————————————————————————————————————————————————————————————————————————————————
; FAST case Setup
;
; Fast case, go directly to screen.
; If text is clipped vertically, then clear heightflag and update TOPHT
;
; Registers on Entry:
; A2 = Font Ptr
; A3 = thePort
; A4 = FmOutput record ptr
; A6 = Stack frame
;
; Saves & Restores:
; A2
;
; Clobbers:
;
; D0, D1
;
;————————————————————————————————————————————————————————————————————————————————————————————————
FAST
IF HAS_COLOR THEN
TST.B is32QD(A6)
BEQ.S @not32bit
MOVEM.L A0-A1/D0-D2,-(SP) ;Save registers
@tryAgain CLR.B -(SP) ;result
MOVE.L A3, -(SP) ;needs the current grafport
_QDDone ;Is accelerator really done and ready for us to blit???
TST.B (SP)+ ;Check result
BEQ.S @tryAgain ;Check until ready!
MOVEM.L (SP)+, A0-A1/D0-D2 ;Restore registers
ENDIF
@not32bit
ST FASTFLAG(A6) ;REMEMBER WE'RE GOING FAST
;—————————————————————————————
; Clipping set up
;—————————————————————————————
CLR.B maskFont(A6) ;no need for second mask pass in fast case
CLR.L bkCol(A6) ;zero out back color long
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
IF HAS_COLOR THEN
VCLIPOK MOVE TEXTRECT+TOP(A6),D0 ;GET DST TOP
SUB DSTPIX+BOUNDS+TOP(A6),D0 ;CONVERT TO GLOBAL COORDINATES
MOVE DSTPIX+ROWBYTES(A6),D1 ;GET ROWBYTES
AND #nuRBMask,D1 ;CLEAR OFF FLAG BITS
MULS D1,D0 ;MULT BY ROWBYTES
ADD.L DSTPIX+BASEADDR(A6),D0 ;ADD START OF DST BITMAP
MOVE.L D0,BUFSTART(A6) ;SET UP BUFSTART FOR LATER
MOVE D1,BUFROW(A6) ;SET UP BUFROW FOR LATER
MOVE DSTPIX+BOUNDS+LEFT(A6),BUFLEFT(A6) ;REMEMBER BUFLEFT
TST.B CRSRFLAG(A6) ;IS DST TO A SCREEN? <BAL 19Sep88>
BEQ @Check32Bit ;=>NO <9Apr90 KON>
PEA MINRECT(A6) ;PUSH SHIELD RECT
MOVE.L REALBOUNDS(A6),-(SP) ;PUSH DELTA FOR GLOBAL
_SHIELDCURSOR ;HIDE CURSOR IF IT INTERSECTS
@Check32Bit
tst.b needs32bit(a6) ;<9Apr90 KON>
beq.s @skip32bit ;<9Apr90 KON>
;———————————————————————————————————————
;
; Clean pointers and then
; Switch to 32 bit addressing mode
;———————————————————————————————————————
MOVE.L SRCADDR(A6),d0 ;get 24 bit base addr
_rTranslate24To32 ;mask off high byte BAL/MCF 03Dec88
MOVE.L d0,SRCADDR(A6) ;SAVE FOR LATER
move.l a2,d0 ;get FontPtr
_rTranslate24To32 ;mask off high byte BAL/MCF 03Dec88
move.l d0,a2 ;clean font ptr
move.l a3,d0 ;get thePort ptr
_rTranslate24To32 ;mask off high byte BAL/MCF 03Dec88
move.l d0,a3 ;clean thePort ptr
MOVE.L textPtr(A6),D0 ;GET TEXTPTR
_rTranslate24To32 ;mask off high byte BAL/MCF 03Dec88
MOVE.L d0,textPtr(A6) ;SAVE FOR LATER
moveq #true32b,d0 ;switch to 32 bit addressing
move.l a2,-(sp) ;save FontPtr
_rSwapMMUMode ;get previous mode in d0.b (can trash a0/a1/a2, d0/d1/d2)
move.l (sp)+,a2 ;restore FontPtr
move.b d0,MMUsave(a6) ;save previous state for later
@skip32bit
ELSE
VCLIPOK MOVE TEXTRECT+TOP(A6),D0
SUB PORTBITS+BOUNDS+TOP(A3),D0
MULS.W 6(A3),D0
ADD.L PORTBITS+BASEADDR(A3),D0
MOVE.L D0,BUFSTART(A6)
MOVE 6(A3),BUFROW(A6)
MOVE PORTBITS+BOUNDS+LEFT(A3),BUFLEFT(A6)
PEA MINRECT(A6)
MOVE.L PORTBITS+BOUNDS(A3),-(SP)
_SHIELDCURSOR
ENDIF
BRA GETPTRS
;————————————————————————————————————————————————————————————————————————————————————————————————
; END FAST case Setup
;————————————————————————————————————————————————————————————————————————————————————————————————
;————————————————————————————————————————————————————————————————————————————————————————————————
; Slow case Set up
;
; Slow case: Setup for an off-screen buffer.
;
; Calc bufLeft: (LONG-align to avoid shift)
;
; Registers on Entry:
; A2 = Font Ptr
; A3 = thePort
; A4 = FmOutput record ptr
; A6 = Stack frame
;
; Clobbers:
; A0, A1
; D0, D1, D2, D3, D4
;
;————————————————————————————————————————————————————————————————————————————————————————————————
NOTFAST
SF FASTFLAG(A6) ;NOT GOING DIRECTLY TO SCREEN
IF (hasSplineFonts AND 0) OR (Gaudi AND 0) THEN
;—————————————————————————————
; Horizontal buffer use that is not yet used
;—————————————————————————————
TST.B isSpline(A6) ;Is it a spline
BEQ.S @skipNewTextRect ;Do not adjust the textrect
MOVE MINRECT+LEFT(A6), D0 ;Min left in D0
MOVE MINRECT+RIGHT(A6), D1 ;Min Right in D1
TST.B fmOutShadow(A4)
BEQ.S @noExtraOnEnds
SUB #3, D0
ADD #3, D1
@noExtraOnEnds
CMP TEXTRECT+LEFT(A6), D0 ;Is TextRect Left Greater
BLT.S @noSubLeft
MOVE D0, TEXTRECT+LEFT(A6) ;New TextRect Left used for buffer calc
@noSubLeft
CMP TEXTRECT+RIGHT(A6), D1 ;Is TextRect Left Greater
BGT.S @skipNewTextRect
MOVE D1, TEXTRECT+RIGHT(A6) ;New TextRect Right used for buffer calc
@skipNewTextRect
ENDIF
MOVE TEXTRECT+LEFT(A6),D0 ;GET TEXTRECT LEFT
IF HAS_COLOR THEN
SUB DSTPIX+BOUNDS+LEFT(A6),D0 ;CONVERT TO GLOBAL
ELSE
SUB PORTBITS+BOUNDS+LEFT(A3),D0
ENDIF
AND #$FFE0,D0 ;TRUNC TO LONG BOUND
IF HAS_COLOR THEN
ADD DSTPIX+BOUNDS+LEFT(A6),D0 ;RETURN TO LOCAL COORDS
ELSE
ADD PORTBITS+BOUNDS+LEFT(A3),D0
ENDIF
MOVE D0,BUFLEFT(A6) ;REMEMBER FOR LATER
;————————————————————————
; Calculate buffer size
;————————————————————————
CLR.L D1 ;clear high word
MOVE TEXTRECT+RIGHT(A6),D1 ;BUFRIGHT := TEXTRECT RIGHT
SUB D0,D1 ;WIDTH:=BUFRIGHT-BUFLEFT
MOVE D1,D2 ;mask depth as well
MOVE bitShift(A6),D4 ;convenient constant
LSL.L D4,D1 ;scale up by pixel size + 1 for mask
LSR.L #5,D1 ;CONVERT DOTS TO LONGS
ADD #2,D1 ;ROUND UP PLUS EXTRA LONG
IF (hasSplineFonts) OR (Gaudi) THEN ; <31> DTY
TST.B isSpline(A6) ;is it a spline
BEQ.S @fullHeight ;skip bitmap clipping
MOVE.W botClip(A6), origBotClip(A6)
MOVE.W topClip(A6), origTopClip(A6)
TST.B fmOutShadow(A4)
BEQ.S @doneAdjustTop
MOVE.W botClip(A6), D3
SUB.W #2, D3
CMP.W sDescent(A6), D3
BGE.S @doneAdjustBot ;Do not adjust bottom
MOVE.W sDescent(A6), D3
@doneAdjustBot
MOVE.W D3, botClip(A6)
MOVE.W topClip(A6), D3
ADD.W #3, D3
CMP.W sAscent(A6), D3
BGE.S @setTopSame ;Do not adjust bottom
MOVE.W D3, topClip(A6)
BRA.S @doneAdjustTop
@setTopSame
MOVE.W sAscent(A6), topClip(A6)
@doneAdjustTop
MOVE.W topClip(A6), D3 ;Get the top clipping height
MOVE.W D3, topAdjust(A6) ;Get top adjust for dest adjustment
SUB.W botClip(A6), D3 ;Not missing but really clipped out
BLE.W GOHOME ;Done if zero
ADD.W #1, D3 ;height = topClip - botClip + 1
MOVE.W D3, bufHeight(A6) ;Save it away
BRA.S @skipFullHeight ;Do not get full height for buffer
ENDIF ;$$$NEW
@fullHeight
MOVE sHeight(A6),D3 ;GET HEIGHT
@skipFullHeight
MULU D1,D3 ;BUFSIZE:=HEIGHT*BUFROW LONGS
IF 0 THEN
IF (hasSplineFonts) OR (Gaudi) THEN ; <31> DTY
TST.B isSpline(A6) ;skip check if spline
BNE.S @noCompare ;Do not compare
ENDIF
;—————————————————————————————————————————————————
; if the intermediate result is too big, stop before going any further
;
; Why does this happen???
;—————————————————————————————————————————————————
CMP.L #$1C00,D3 ;is it bigger than 28K? (unit is longs)
BGT DoSubDivide ;if so, draw fewer characters at a time
@noCompare
ENDIF
MOVE.L D3,BUFSIZE(A6) ;Made a long SAVE FOR LATER
EXT.L D1 ;Make it a long
ADD.L D1,D3 ;add for stretch srcBuf
LSL #2,D1 ;QUAD BUFROW FOR BYTES
MOVE D1,BUFROW(A6) ;SAVE FOR LATER
MOVE TEXTR2+RIGHT(A6),D5
SUB TEXTR2+LEFT(A6),D5
LSR #5,D5 ;convert to longs
ADDQ #2,D5 ;account for slop
MOVE D5,D0
EXT.L D0 ;Make it a long
ADD.L D0,D3 ;in case clip is nonrectangular
ADD.L D0,D3 ;in case vis is nonrectangular
LSL D4,D0 ;scale up by source depth
ADD.L D0,D3 ;add stretch destination buffer size
IF HAS_COLOR THEN
MULU dstPix+pixelSize(A6),D5 ;size of composite mask
EXT.L D5 ;$$$ Make it a long
ADD.L D5,D3 ;include it
;—————————————————————————————————————————————————
;if srcDepth not equal to dstDepth, add stretch dest. buf. again
;—————————————————————————————————————————————————
ADD.L D5,D3 ;include space for scale buffer
;—————————————————————————————————————————————————
;set up maskSize, maskRow
;—————————————————————————————————————————————————
TST.B maskFont(A6) ;do we need a mask to pass to stretchBits?
BEQ.S @noMask
LSR #5,D2 ;CONVERT DOTS TO LONGS
ADD #2,D2 ;ROUND UP PLUS EXTRA LONG
ADD D2,D1 ;total number of longs
IF (hasSplineFonts) OR (Gaudi) THEN ; <31> DTY
TST.B isSpline(A6) ;is it a spline
BEQ.S @useNormalHeight ;use the normal height
MOVE bufHeight(A6), D0 ;use bufHeight
BRA.S @contCalc
@useNormalHeight
MOVE sHeight(A6),D0 ;GET HEIGHT
@contCalc
ELSE
MOVE sHeight(A6),D0 ;GET HEIGHT
ENDIF
MULU D2,D0 ;BUFSIZE:=HEIGHT*BUFROW LONGS
MOVE D0,maskSize(A6) ;SAVE FOR LATER
LSL #2,D2 ;QUAD BUFROW FOR BYTES
MOVE D2,mBufRow(A6) ;SAVE FOR LATER
ADD.L D0,D3 ;add for stack check calculation
EXT.L D2
ADD.L D2,D3 ;add for stretch srcMaskBuf
MOVE TEXTR2+RIGHT(A6),D0
SUB TEXTR2+LEFT(A6),D0
LSR #5,D0 ;convert from dots to longs
EXT.L D0 ;Make it a long
ADD.L D0,D3 ;add stretch mask destination buffer size
@noMask
ELSE
EXT.L D5
ADD.L D5,D3
ADD.L D5,D3
ENDIF
IF (hasSplineFonts) OR (Gaudi) THEN ; <31> DTY
TST.B isSpline(A6) ;Is it a spline
BNE.S @doNewAlloc ;Then subdivide
ENDIF
;—————————————————————————————————————————————————
; Calculate total stack requirements for off-screen buffers.
;—————————————————————————————————————————————————
TST.B fmOutShadow(A4) ;ARE WE SHADOWING ?
BEQ.S @1 ;NO, CONTINUE
ADD.L bufSize(A6),D3 ;(long) YES, CALC 2*BUFSIZE
EXT.L D1 ;make long for long add
ADD.L D1,D3 ;add in 4 * source rows for shadow
@1 LSL.L #2,D3 ;CALC TOTAL STACK BYTES NEEDED
;—————————————————————————————————————————————————
; how much slop? size of scale table (256 bytes maximum)
; size of stretch stack frame (750 bytes for parameters, local stack frame, saved regs),
; and about 1K for interrupts.
;—————————————————————————————————————————————————
ADD.L #2048,D3 ;ADD 2 KBYTE SLOP
;—————————————————————————————————————————————————
; If stack is too small to allocate buffer(s), then draw half as many characters at a time.
;—————————————————————————————————————————————————
MOVE.L $594,A0
JSR (A0) ;Get StackAvail IN D0
CMP.L D0,D3 ;IS stackNeeded > stackAvail ?
BLE StackAlmost ;NO, CONTINUE
BRA DoSubDivide
@doNewAlloc
IF (hasSplineFonts) OR (Gaudi) THEN ; <31> DTY
;—————————————————————————————————————————————————
; Calculate the buffer size
;—————————————————————————————————————————————————
MOVE.L bufSize(A6),D0 ;Get size of buffer to initialize
ADD.L #2, D0 ;Add 2 padding buffer on each end
IF HAS_COLOR THEN
TST.B maskFont(A6)
BEQ.S @skipMaskAlloc
MOVEQ #0, D1 ;clear the long
MOVE maskSize(A6),D1 ;Get maskSize
ADD.L D1,D0 ;Adding in maskSize
ADD.L #2, D0 ;Add 2 padding buffer on each end
@skipMaskAlloc
ENDIF
TST.B fmOutShadow(A4) ;Is there shadow
BEQ.S @noShadBuf ;SKIP IF NO SHADOWING
ADD.L bufSize(A6),D0 ;GET NUMBER OF LONGS IN BUF1
MOVE BUFROW(A6),D1 ;GET 4 * NUMBER OF LONGS PER ROW
EXT.L D1
ADD.L D1,D0 ;GET 4 * NUMBER OF LONGS PER ROW
ADD.L #2, D0 ;Add 2 padding buffer on each end
@noShadBuf
LSL.L #2, D0 ;longs to bytes
MOVE.L D0, D3 ;Save value away
CMP.L #$7000,D3 ;is it bigger than 28K? (unit is longs)
BGT.S @otherAlloc ;Try to get memory from other places
MOVE.L $594,A0
JSR (A0) ;Get StackAvail IN D0
MOVE.L D3, D2 ;get needed space
ADD.L #3346, D2 ;make sure there is an extra 2.5k bytes
CMP.L D0,D2 ;IS stackNeeded > stackAvail ?
BGT.S @otherAlloc ;NEW Changed to word branch - NO, CONTINUE
SUB.L D3, SP ;Allocate the sucker
MOVE.L SP, bufferPtr(A6) ;Save away the buffer pointer
BRA @gotIt ;<65-CEL>
@otherAlloc
MOVE.L fmOutFontH(A4),A0 ;GET FONT HANDLE
_HGetState ;get the purge state
MOVE.B D0,fontState(A6) ;preserve it until the next change
_HNoPurge ;Make it non-purgeable
MOVE.L cacheHand(A6),A0 ;GET cache HANDLE <65-CEL>
_HGetState ;get the purge state <65-CEL>
MOVE.B D0,cacheState(A6) ;preserve it until the next change <65-CEL>
_HNoPurge ;Make it non-purgeable <65-CEL>
MOVE.L stackHandle(A6), D0 ;Check if exists
BEQ.S @skipReSize
MOVE.L D0, A0 ;Get handle in A0
_HUnlock
MOVE.L D3, D0 ;restore size
_SetHandleSize ;try a sethandlesize first
BEQ.S @gotMem ;No problems we got it
_DisposHandle ;Get rid of buffer - could be MF temp handle
CLR.L stackHandle(A6) ;Zero out handle
@skipReSize
MOVE.L D3, D0 ;restore size
jsr GetStyleBufHand ;Expecting size in D0
BEQ.S @subDivide ;go and band
MOVE.L A0, stackHandle(A6) ;save away for later
@gotMem
MOVEM.L A0-A1/D0-D2,-(SP) ;Save off all registers before JSR
SUBQ #4,SP ;make room for result
MOVE.L widthTabHandle,A0 ;point to width table
MOVE.L A0, -(SP) ;Push the WidthTable
MOVE.L (A0),A0 ;Ptr to widthtable
MOVE.L WidTabFont(A0), -(SP) ;font handle
MOVE.W bufHeight(A6), -(SP) ;Scan lines
MOVE.W WidthASize(A0), -(SP) ;ppem
_sbPreFlightFontMem ;Call the routine via SplineDispatch
TST.L (SP)+ ;Check the errors
MOVEM.L (SP)+, A0-A1/D0-D2 ;Restore all registers on return
BNE.S @subDivide ;
_MoveHHi ;Move it high
_HLock ;Lock it down for now
MOVE.L (A0), D0 ;pointer to the cache
IF HAS_COLOR THEN
_StripAddress ;Make sure it is the right mode
ENDIF
MOVE.L D0, bufferPtr(A6) ;Save away the buffer pointer
MOVE.L fmOutFontH(A4),A0 ;GET FONT HANDLE
MOVE.B fontState(A6), D0 ;preserve it until the next change
_HSetState ;restore purgability of original strike
MOVE.L cacheHand(A6),A0 ;GET FONT HANDLE <65-CEL>
MOVE.B cacheState(A6), D0 ;preserve it until the next change <65-CEL>
_HSetState ;restore purgability of original strike <65-CEL>
@gotIt BRA StackAlmost ; We are in business
@subDivide
MOVE.L fmOutFontH(A4),A0 ;GET FONT HANDLE
MOVE.B fontState(A6), D0 ;preserve it until the next change
_HSetState ;restore purgability of original strike
ENDIF
;——————————————————————————————————————————————————————————————————————————————————————————————————
; SUB-dividing routine
;
; Not enough memory - Divide area
;
; Currently there are two types of sub-dividing.
; 1) splitting the string in half
; 2) Banding vertically
;
; Banding vertically will render the characters correctly for all styles
; It seems as though splitting the string could have bad effects in italics
; in certain modes (e.g., srccopy). The sub-dividing of strings may go away
; In the case for splines, banding vertically will only take place. Splitting
; the string may also run out of memory and still need to be banded vertically.
; Banding vertically seems to be the best approach. Note: By banding vertically
; StdTxmeas will not need to be called again. The setup does not need to be re-done
;
; Registers on Entry:
; A2 = Font Ptr
; A3 = thePort
; A4 = FmOutput record ptr
; A6 = Stack frame
;
; Clobbers:
; A0, A1
; D0, D3, D6, D7
;
;——————————————————————————————————————————————————————————————————————————————————————————————————
DoSubDivide
IF (hasSplineFonts) OR (Gaudi) THEN ; <31> DTY
TST.B isSpline(A6) ;is it a spline
BEQ.S @contNormSplit ;skip bitmap clipping
ST clipVert(A6) ;banding so set clip vertical flag <51>
MOVE.W origTopClip(A6), D3 ;Get original value
SUB.W origBotClip(A6), D3 ;Get original height to divide
LSR.W #1, D3 ;Divide by 2 is new Height
MOVE.W origBotClip(A6), -(SP) ;nextBotClip = botClip
MOVE.W origTopClip(A6), D0 ;Get topclip
SUB.W D3, D0 ;Get new botClip
MOVE.W D0, -(SP) ;nextTopClip = newBotClip-1
MOVE.W D0, botClip(A6) ;newBotClip = (topClip - (oldHeight / 2)) + 1
@noNew
MOVE.L SP, clipStorage(A6) ;Save Address on variable for later cleanup
ADD.W #1, repeatBands(A6) ;Bump up by one
IF HAS_COLOR THEN
MOVE.B HiliteMode,saveHilite(A6) ;save original in case stretch is called multiple times
ENDIF
MOVE.L PENLOC(A6),PNLOC(A3) ;RESTORE PNLOC TO ORIGINAL
IF hasPenFraction THEN
move.l grafGlobals(a5),a0 ; load quickDraw globals.
move.w penLocFixed(a6),pnLocFixed(a0) ; restore fractional pen location.
ENDIF
IF HAS_COLOR THEN
TST PORTBITS+ROWBYTES(A3) ; is it a new port?
BPL.S @useOld2 ; no, no fraction to restore
MOVE PenLocHFrac(A6),pnLocHFrac(A3) ;restore fraction if applicable
@useOld2
ENDIF
BRA NOTFAST ;do new divide
@contNormSplit
ENDIF
;————————————————————————————————————————————————————
; Here is the bitmap subdivide of the string
;————————————————————————————————————————————————————
MOVE stackOffset(A6),D6 ;2 if stack was not aligned, otherwise, 0
MOVE count(A6,D6),D0 ;how many characters to draw
MOVE.W D0,D7 ;figure half
LSR #1,D7
BNE.S @subDivide ;if more than 1 left, can subdivide problem
SUBQ #1,charsRemain(A6) ;pretend the one character was drawn
BRA GoHome ;if only 1 character, punt
@subDivide
; *** look for space character? Could adjust D7 to coincide with a space if any, making
; *** drawing look better (for italics, kerns)
TST charsRemain(A6) ;if zero, this is the first time through
BNE.S @notFirst
IF HAS_COLOR THEN
MOVE.B HiliteMode,saveHilite(A6) ;save original in case stretch is called multiple times
ENDIF
MOVE D0,charsRemain(A6) ;initialize partial count drawing location
@notFirst
MOVE.L PENLOC(A6),PNLOC(A3) ;RESTORE PNLOC TO ORIGINAL
IF hasPenFraction THEN
move.l grafGlobals(a5),a0 ; load quickDraw globals.
move.w penLocFixed(a6),pnLocFixed(a0) ; restore fractional pen location.
ENDIF
IF HAS_COLOR THEN
TST PORTBITS+ROWBYTES(A3) ; is it a new port?
BPL.S @useOld ; no, no fraction to restore
MOVE PenLocHFrac(A6),pnLocHFrac(A3) ;restore fraction if applicable
@useOld
ENDIF
MOVE D7,count(A6,D6) ;reset count to draw
doIterate
MOVE.L grafGlobals(A5),A4 ;set up grafGlobals pointer for getting real width
MOVE.L numer2(A6),numer(A6,D6) ;restore numerator
MOVE.L denom2(A6),denom(A6,D6) ;restore denominator
IF HAS_COLOR THEN
MOVE.B saveHilite(A6),HiliteMode ;restore hilite bit
ENDIF
JMP Iterate ;draw first half of string
; draw the second half of the string, but drawing no more characters than could be successfully
; drawn by the first half.
secondHalf
MOVEQ #0,D7 ;zero high word
MOVE stackOffset(A6),D6 ;2 if stack was not aligned, otherwise, 0
MOVE count(A6,D6),D7 ;number of characters drawn last
MOVE charsRemain(A6),D0 ;how many characters remain?
CMP D0,D7 ;dont try to draw more than worked last
BLE.S @ok
MOVE D0,count(A6,D6) ;draw what remains for the second half
@ok
ADD.L D7,textPtr(A6) ;bump source address by half already drawn
BRA.S doIterate
; ————————————————————————————————————————————————————————————————————————————————————————————
; END SUB-dividing routine
; ————————————————————————————————————————————————————————————————————————————————————————————
; ————————————————————————————————————————————————————————————————————————————————————————————
; Off-Screen Allocation
;
; Allocate and clear an off-screen buffer
;
; If the source font is only 1 bit deep, clear the screen to white. Also, if the transfer
; mode is xor, bic, or, clear the screen to white. If an arithmetic mode or copy and
; source is multibits deep, assume depth of source font is equal to destination depth.
; Also assume that background of buffer must be colored the same as the port background color.
;
;
; ————————————————————————————————————————————————————————————————————————————————————————————
StackAlmost
MOVEQ #0,D0 ;get a long of white
IF HAS_COLOR THEN
CMP.W #16, destDepth(A6) ;get destination bits per pixel
BGE.S @whiteBackCol ;16 or 32 bit will not happen
TST bitShift(A6) ;is source 1 bit?
BEQ.S @whiteBackCol ;
CMP #srcXor,locMode(A6) ;srcXor?
BEQ.S @whiteBackCol ;even if font contains colors, leave background white
TST.B colorSource(A6) ;font contains color?
BNE.S @useBackCol ;if so, must color the buffer
CMP #$32,locMode(A6) ;hilite?
BEQ.S @whiteBackCol ;leave background white if so
BTST #5,locMode+1(A6) ;arithmetic?
BEQ.S @whiteBackCol ;if copy, or leave background white
@useBackCol
SUBQ #6,SP ;allocate VAR RGBColor
MOVE.L SP,-(SP) ;point to VAR RGBColor
_GetBackColor ;ask for the background color
CLR.L -(SP) ;make room for function result
PEA 4(SP) ;point to VAR RGBColor
_Color2Index
MOVEQ #0,D0
MOVEQ #32,D1 ;
MOVE bitDepth(A6),D2 ;get destination bits per pixel
@nxtPixel
ASL.L D2,D0
OR.l (SP),D0 ;or in result of color2Index <BAL 04July88>
SUB D2,D1
BGT.S @nxtPixel
ADD #10,SP ;strip RGBColor and long result
@whiteBackCol
ENDIF
MOVE.L D0,bkCol(A6) ;save for comparing with background, later
STACKOK
IF (hasSplineFonts) OR (Gaudi) THEN ; <31> DTY
TST.B isSpline(A6)
BEQ.S oldAlloc ;Go to old way of allocating
MOVE.L bufferPtr(A6), A0 ;Point to the buffer
MOVE.L D0,(A0)+ ;PAD BUFFER WITH AN EXTRA ZERO
MOVE.L A0, BUFSTART(A6) ;Save the start of the buffer
MOVE.L bufSize(A6),D3 ;Get size of buffer to initialize
SUBQ #1,D3 ;INIT DBRA LOOP COUNT
CLRLP MOVE.L D0,(A0)+
SUB.L #1, D3 ;Decrement count
TST.L D3 ;Is it done looping
BGT.S CLRLP ;Done looping
MOVE.L A0, bufEnd(A6) ;point to end of buffer
MOVE.L D0,(A0)+ ;PAD BUFFER WITH AN EXTRA ZERO
IF HAS_COLOR THEN
TST.B maskFont(A6)
BEQ.S @noMask
CLR.L (A0)+
MOVE.L A0, maskStart(A6) ;Set the maskStart pointer
MOVE maskSize(A6),D3 ;Get the size of the mask
SUB #1, D3 ;Init loop count
@clrMask
CLR.L (A0)+
DBRA D3,@clrMask
@noMask
ENDIF
MOVE.L A0, currentEnd(A6) ;current end of allocated buffer
BRA.S doneNEW1
oldAlloc
MOVE.L bufSize(A6),D3
SUBQ #1,D3 ;INIT DBRA LOOP COUNT
MOVE.L D0,-(SP) ;PAD BUFFER WITH AN EXTRA ZERO
MOVE.L SP,BUFEND(A6) ;REMEMBER WHERE BUFFER ENDS
CLRLOOP MOVE.L D0,-(SP)
DBRA D3,CLRLOOP ;ALLOCATE AND CLEAR BUFFER
MOVE.L SP,BUFSTART(A6) ;REMEMBER START OF BUFFER
MOVE.L D0,-(SP) ;PAD BUFFER WITH AN EXTRA ZERO
IF HAS_COLOR THEN
TST.B maskFont(A6)
BEQ.S @noMask
MOVE maskSize(A6),D3
SUBQ #1,D3
CLR.L -(SP)
@clrMask
CLR.L -(SP)
DBRA D3,@clrMask
MOVE.L SP,maskStart(A6)
@noMask
ENDIF
CLR.L -(SP)
doneNEW1
ELSE
MOVE.L bufSize(A6),D3
SUBQ #1,D3 ;INIT DBRA LOOP COUNT
MOVE.L D0,-(SP) ;PAD BUFFER WITH AN EXTRA ZERO
MOVE.L SP,BUFEND(A6) ;REMEMBER WHERE BUFFER ENDS
CLRLOOP MOVE.L D0,-(SP)
DBRA D3,CLRLOOP ;ALLOCATE AND CLEAR BUFFER
MOVE.L SP,BUFSTART(A6) ;REMEMBER START OF BUFFER
MOVE.L D0,-(SP) ;PAD BUFFER WITH AN EXTRA ZERO
TST.B maskFont(A6)
BEQ.S @noMask
MOVE maskSize(A6),D3
SUBQ #1,D3
CLR.L -(SP)
@clrMask
CLR.L -(SP)
DBRA D3,@clrMask
MOVE.L SP,maskStart(A6)
@noMask
CLR.L -(SP)
ENDIF
IF (hasSplineFonts) OR (Gaudi) THEN ; <31> DTY
TST.B isSpline(A6) ;Is it a spline
BEQ.S @1 ;no so continue to bitmap getptrs
TST.W clipVert(A6) ;Horz or Vert clipped
BNE sGetPtrs ;take clipping loops
BRA FastBlit ;go really fast
@1
ENDIF
;————————————————————————————————————————————————————————————————————————————————————————————————
; END Off-Screen Allocation
;————————————————————————————————————————————————————————————————————————————————————————————————
;————————————————————————————————————————————————————————————————————————————————————————————————
; END Slow case Set up
;————————————————————————————————————————————————————————————————————————————————————————————————
;————————————————————————————————————————————————————————————————————————————————————————————————
;
; Get pointers to location table, width table, and height table in font
;
;————————————————————————————————————————————————————————————————————————————————————————————————
GETPTRS
LEA 26(A2),A0 ;GET START OF FONT BITMAP
MOVEQ #0,D0 ;zero high word
MOVE sHeight(A6),D0 ;GET HEIGHT OF FONT BITMAP
MOVE.L SRCROW(A6), D1 ;Get Source in D1 to use as word, never a long
MULU.W D1,D0 ;CALC TOTAL SIZE OF STRIKE
ADD.L D0,A0 ;A1 := START OF LOC TABLE
MOVE.L A0,LOCTAB(A6) ;SAVE FOR LATER
MOVE.W fNDescent(A2),D0 ;possibly the high word of owTLoc
SWAP D0 ;put it in the high word
BPL.S @notNegative
MOVEQ #0,D0 ;old fonts have negative of ascent here
@notNegative
MOVE LENGTH(A2),D0 ;HOW MANY WORDS IN STRIKE BODY
IF &SETTING('MACHINE') <> 'MC68000' THEN
LEA 16(A2,D0.L*2),A1 ;GET START OF WIDTH TABLE
ELSE
ASL.L #1,D0
LEA 16(A2,D0.L),A1
ENDIF
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
BTST #1,1(A2) ;DOES FONT HAVE WIDTH TABLE ?
BEQ.S NOWID ;NO, CONTINUE
ADD D0,D0 ;SKIP WIDTH TABLE
NOWID
IF &SETTING('MACHINE') <> 'MC68000' THEN
LEA 0(A1,D0*2),A0 ;POINT TO HEIGHT TABLE
ELSE
ASL.W #1,D0
LEA 0(A1,D0),A0
ENDIF
MOVE.L A0,HEIGHTAB(A6) ;SAVE FOR LATER
skipBitTables ;Skipped the bitmap table setup
;
; Set up space width
;
MOVE.L widthTabHandle,A0 ;point to width table
MOVE.L (A0),A0
MOVE.L A0, widTabPtr(A6) ;Save pointer to the 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 kernAdjust(A6),D0 ;ADJUST FOR KERNING
SUB D1,D0 ;MAKE CHARLOC RELATIVE TO BUFLEFT
MOVE.W D0,CHARLOC(A6) ;LOAD INTEGER PART
IF hasPenFraction THEN
move.w penLocFixed(a6),charLoc+2(a6) ; use saved fraction.
ELSE
move.w #$8000,charLoc+2(a6) ; default fraction to 1/2.
ENDIF
IF HAS_COLOR THEN
TST PORTBITS+ROWBYTES(A3) ; is it a new port?
BPL.S @useOld ; no -> skip this.
MOVE penLocHFrac(A6),CHARLOC+2(A6) ; use saved fraction.
@useOld
ENDIF
SUB D1,MINRECT+LEFT(A6) ;MAKE MINRECT.LEFT AND
SUB D1,MINRECT+RIGHT(A6) ;MINRECT.RIGHT BUFFER RELATIVE
MOVE.L textPtr(A6),A1 ;GET TEXTPTR
BRA.S NEXTCH ;GO TO LOOP START
;————————————————————————————————————————————————————————————————————————————————————————————————
;
; Here's the main character drawing loop:
;
;————————————————————————————————————————————————————————————————————————————————————————————————
MISSING
MOVE MAXMIN(A6),D5 ;NO, USE MISSING SYMBOL
ADD #1,D5 ;WHICH IS ONE PAST MAXCHAR
MOVE.L WIDTAB(A6),A0 ;POINT TO WIDTH TABLE
IF &SETTING('MACHINE') <> 'MC68000' THEN
MOVE 0(A0,D5*2),D3 ;GET OFFSET AND WIDTH BYTES
ELSE
MOVE.W D5,D3
ASL.W #1,D3
MOVE 0(A0,D3),D3
ENDIF
CMP #-1,D3 ;missing?
BNE NOTMISS ;IS MISSING CHAR MISSING ?
BRA.S NEXTCH ;YES, SKIP THIS CHAR
SPACECH MOVE.L SPWIDTH(A6),D1 ;GET SPACE WIDTH
ADD.L D1,CHARLOC(A6) ;BUMP CHARLOC
SKIPCH SUBQ.W #1,charsRemain(A6) ;decrement total character count
SUBQ.W #1,countCopy(A6) ;decrement partial draw character count
BLE STRDONE ;QUIT IF CHARCOUNT <= 0
NEXTCH MOVEQ #0, D5 ;get ready for byte
MOVE.B (A1)+,D5 ;GET NEXT CHAR
CMP.B #32,D5 ;IS IT A SPACE ?
BEQ.S SPACECH ;YES, HANDLE IT
MOVE.L widTabPtr(A6),A0 ;Point to the width table
IF &SETTING('MACHINE') <> 'MC68000' THEN
MOVE.L 0(A0,D5*4),D4 ;GET FIXED POINT WIDTH
ELSE
MOVE.W D5,D4
ASL.W #2,D4
MOVE.L 0(A0,D4),D4
ENDIF
ADD.L characterExtra(A6),D4 ;add in character extra, if any
SUB MINCH(A6),D5 ;SUBTRACT SAVED MINCHAR
CMP MAXMIN(A6),D5 ;IS CH BETWEEN MINCHAR AND MAXCHAR ?
BHI MISSING ;Missing so skip it
OKCHAR MOVE.L WIDTAB(A6),A0 ;POINT TO WIDTH TABLE
IF &SETTING('MACHINE') <> 'MC68000' THEN
MOVE 0(A0,D5*2),D3 ;GET OFFSET AND WIDTH BYTES
ELSE
MOVE.W D5,D3
ASL.W #1,D3
MOVE 0(A0,D3),D3
ENDIF
CMP #-1,D3 ;missing?
BEQ 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
MOVEQ #0,D1 ; *** clear top word
IF &SETTING('MACHINE') <> 'MC68000' THEN
MOVE 0(A0,D5*2),D1 ;GET SRCLEFT
MOVE 2(A0,D5*2),D2 ;GET SRCRIGHT
ELSE
MOVE.W D5,D5
ASL.W #1,D5
MOVE 0(A0,D5),D1
MOVE 2(A0,D5),D2
ENDIF
SUB D1,D2 ;CALC WIDTH OF BITS
BLE SKIPCH ;SKIP CHARBLT IF WIDTH <= 0
MOVE D2,charWidth(A6) ;save for later
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
IF &SETTING('MACHINE') <> 'MC68000' THEN
MOVE 0(A0,D5*2),TOPHT(A6) ;get this char's top and height
ELSE
MOVE 0(A0,D5),TOPHT(A6)
ENDIF
NOHEIGHT
;————————————————————————————————————————————————————————————————————————————————————————————————
; Horizontal Clipping
;
; 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 fixCharWidth ;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
fixCharWidth
MOVE D2,D0 ;char width has been trimmed left, right, or both
SUB D3,D0 ;so recalculate char width to draw
MOVE D0,charWidth(A6) ;and save this tidbit of info. for later
HORIZOK
;————————————————————————————————————————————————————————————————————————————————————————————————
; Blit loop for the 68020+ machines
;
; 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)
;
;————————————————————————————————————————————————————————————————————————————————————————————————
IF HAS_COLOR THEN
MOVEM D1-D3,maskBlts(A6)
MOVE.B textCopyMode(A6),orNotOK(A6) ;if copy or if mask mode, do bit moves instead of OR
ST notMaskPass(A6) ;use the bitDepth this pass
ELSE
MOVE.W D3,D5
SUB.W D1,D5
MOVEQ #15,D0
AND.W D0,D5
ENDIF
MOVE BUFROW(A6),A3
MOVEM.L SRCROW(A6),A2/A4-A5 ;srcRow, srcAddr (src bitmap), bufStart (dst bitmap) <1.4-4april89-CEL>
IF HAS_COLOR THEN
MOVE bitShift(A6),D0 ;get font scale factor
LSL D0,D1
LSL D0,D2
LSL D0,D3 ;scale up all three
ELSE
ADD.W D5,D1
ASR.W #4,D1
ADD.W D1,D1
SUB.W #2,D1
ADD.W D1,A4
MOVE.W D3,D1
ASR.W #4,D1
ADD.W D1,A5
ADD.W D1,A5
MOVE.L -$234(A6),A0
AND.W D0,D3
ADD.W D3,D3
MOVE.W (A0,D3),D3
NOT.W D3
MOVE.W D2,D6
AND.W D0,D2
ADD.W D2,D2
MOVE.W (A0,D2),D4
MOVE.L -$254(A6),A2
MOVE.W -$36(A6),A3
ENDIF
maskBlt
;
; Get char height into D7
;
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
;
IF HAS_COLOR THEN
MOVEQ #0,D0 ;get ready for byte
MOVE.B TOPHT(A6),D0 ;get char top
MOVE.L A2,D4 ;get srcRow in D-reg
MULU.L D0,D4 ;calc charTop * srcRow
ADD.L D4,A4 ;add to srcPtr
MOVE A3,D4 ;get dstRow in D-reg
MULU D0,D4 ;calc charTop * dstRow
ADD.L D4,A5 ;add to dstPtr
ELSE
CLR.W D0
MOVE.B TOPHT(A6),D0
MOVE.L A2,D2
MULU.W D0,D2
ADD.L D2,A4
MOVE A3,D2
MULU D0,D2
ADD.L D2,A5
ENDIF
BRA pastBitMapPointers
;————————————————————————————————————————————————————————————————————————————————————————————————
;
; SPLINE DRAWING LOOP
;
; Registers Use:
; D0 = xxxxxxx A0 = xxxxxxx
; D1 = xxxxxxx A1 = TextPtr
; D2 = xxxxxxx A2 = xxxxxxx
; D3 = xxxxxxx A3 = xxxxxxx
; D4 = Advance Width A4 = xxxxxxx
; D5 = Char Code A5 = xxxxxxx
; D6 = xxxxxxx A6 = stack frame
; D7 = xxxxxxx A7 = xxxxxxx
;
;
;————————————————————————————————————————————————————————————————————————————————————————————————
IF (hasSplineFonts) OR (Gaudi) THEN ; <31> DTY
sGETPTRS
MOVE stackOffset(A6),D0
MOVE.L textPtr(A6),A1 ;GET TEXTPTR
MOVE.L cacheHand(A6), A0 ;Handle to the cache
MOVE.L (A0), D0 ;pointer to the cache
IF HAS_COLOR THEN
_StripAddress ;Make sure it is the right mode
ENDIF
MOVE.L D0, cachePtr(A6) ;save it for later
MOVE.L D0, A0
LEA cache.glyphArray(A0), A0 ;Get array of glyphs into A0
MOVE.L A0, glyphArray(A6) ;Save the glyph array pointer
;
; Set up space width
;
MOVE.L widthTabHandle,A0 ;point to width table
MOVE.L (A0),A0
MOVE.L A0, widTabPtr(A6) ;Save pointer to the 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
SUB D1,D0 ;MAKE CHARLOC RELATIVE TO BUFLEFT
MOVE.W D0,CHARLOC(A6) ;INIT INT PART OF CHARLOC
IF HAS_COLOR THEN
TST PORTBITS+ROWBYTES(A3) ;is it a new port?
BPL.S @useOld ;no, set fraction to 1/2
MOVE penLocHFrac(A6),CHARLOC+2(A6) ;set up fractional part <PB362> BAL
BRA.S @goOn
ENDIF
@useOld
MOVE #$8000,CHARLOC+2(A6)
@goOn
SUB D1,MINRECT+LEFT(A6) ;MAKE MINRECT.LEFT AND
SUB D1,MINRECT+RIGHT(A6) ;MINRECT.RIGHT BUFFER RELATIVE
BRA.S sNextCh ;Start first character
sNextBand
MOVE.W glyphID(A6), D5 ;put glyphID into d5 for renderIt
BRA doBand ;take care of the band
sMiss
IF HAS_COLOR | SCRIPT_CHAR_EXTRA THEN ;<7> CEL
CMP.B #32,D5 ;IS IT A SPACE ?
BEQ.S sSPACECH ;YES, HANDLE IT
ADD.L characterExtra(A6),D4 ;add in character extra, if any
sSPACECH
ENDIF
ADD.L D4, CHARLOC(A6) ;Add fixed point width to CharLoc
sSKIPCH SUBQ.W #1,countCopy(A6) ;decrement partial draw character count
BLE STRDONE ;QUIT IF CHARCOUNT <= 0
sNextCh
TST.B nextBand(A6) ;another char band then call retrieve!!!
BNE.S sNextBand ;do the next char band
MOVEQ #0, D5 ;get ready for byte
MOVE.B (A1)+,D5 ;GET NEXT CHAR
if (hasDoubleByte) then
move.b d5,highByte(a6) ; save the high byte for later use
clr.b lowByte(a6) ; clear the low byte for now
tst.l encodingTable(a6) ; is this a double byte font?
beq.s @normalFont ; no, skip low byte loading
move.l encodingTable(a6),a0 ; grab pointer to high byte mapping table
tst.b 0(a0,d5.w) ; is this a double byte character?
beq @normalCharacter ; no, skip low byte loading
tst.w countCopy(a6) ; more bytes left in text?
ble.s @remapCharacterToNull ; no, remap the high byte
subq.w #1,countCopy(a6) ; decrement the character count
clr.w d0 ; clear high byte of low word
move.b (a1)+,d0 ; grab the low byte and bump the text pointer
adda.w #256,a0 ; offset to the low byte encoding table
tst.b 0(a0,d0.w) ; is this a valid low byte?
beq @remapCharacterToNull ; no, remap the high byte character
move.b d0,lowByte(a6) ; save the valid low byte for later use
bra @normalCharacter ; continue normally
@remapCharacterToNull
move.b #1,d5 ; remap the high byte character to the missing glyph
move.b d5,highByte(a6) ; save the remapped value in the stack
@normalCharacter
@normalFont
endif
MOVE.L widTabPtr(A6),A0 ;Point to the width table
IF &SETTING('MACHINE') <> 'MC68000' THEN
MOVE.L 0(A0,D5*4),D4 ;GET FIXED POINT WIDTH
ELSE
MOVE.W D5,D4
ADD.W D4,D4
ADD.W D4,D4
MOVE.L 0(A0,D4),D4
ENDIF
MOVE.L glyphArray(A6), A0 ;Get array of glyphs into A0
IF &SETTING('MACHINE') <> 'MC68000' THEN
MOVE.L 0(A0,D5*4),D0 ;Get offset to glyph in D3
ELSE
MOVE.W D5,D0
ADD.W D0,D0
ADD.W D0,D0
MOVE.L 0(A0,D0),D0
ENDIF
BGT isCached
;————————————————————————————————————————————————————————————————————————————————————————————————
; calling _sbRetrieveGlyph
;————————————————————————————————————————————————————————————————————————————————————————————————
errorOrNotCached
BTST.L #30, D0 ;Check if there is an error
BNE.S sMiss ;Got an error so skip character
doBand
MOVEM.L A1/D2,-(SP) ;Save off all registers before JSR
SUBQ #4,SP ;make room for result
MOVE D5, glyphID(A6) ;put glyphID into sp_Glyph
if (hasDoubleByte) then
tst.l encodingTable(a6) ; is this a double byte font?
beq.s @singleByteFont ; no, skip loading low byte
move.b highByte(a6),glyphID(a6) ; save the high byte
move.b lowByte(a6),glyphID+1(a6) ; save the low byte
@singleByteFont
endif
MOVE.L WidthTabHandle, -(SP) ;2) Push the Width Table Handle onto the stack
PEA fontID(A6) ;1) Push the Glyph Rec Ptr
IF HAS_COLOR THEN
TST.B FASTFLAG(A6) ;WERE WE GOING DIRECT TO SCREEN ?
BEQ.S @skip32 ;NO, CONTINUE
TST.B needs32bit(A6) ;running 32 bit clean
BEQ.S @skip32 ;NOPE, so skip it
move.b MMUsave(a6),d0 ;get previous MMU state in d0
_rSwapMMUMode ;get previous mode in d0.b (can trash a0/a1/a2, d0/d1/d2)
_sbRetrieveGlyph ;Call the routine via SplineDispatch
moveq #true32b,d0 ;switch to 32 bit addressing
_rSwapMMUMode ;get previous mode in d0.b (can trash a0/a1/a2, d0/d1/d2)
BRA.S @skip24
ENDIF
@skip32
_sbRetrieveGlyph ;Call the routine via SplineDispatch
@skip24
;——————————————————————
; Re-establish pointers
;——————————————————————
MOVE.L WidthTabHandle,A0 ;Get the handle
MOVE.L (A0),widTabPtr(A6) ;restore the width table pointer
;The cacheHand may have change if we got
;Memory somewhere else
;——————————————————————
; May have banded for memory
; restore advance width
;——————————————————————
MOVE.L widTabPtr(A6),A0 ;Point to the width table
IF &SETTING('MACHINE') <> 'MC68000' THEN
MOVE.L 0(A0,D5*4),D4 ;GET FIXED POINT WIDTH
ELSE
MOVE.W D5,D4
ADD.W D4,D4
ADD.W D4,D4
MOVE.L 0(A0,D4),D4
ENDIF
;——————————————————————
MOVE.L expandMem,A0 ; get low memory expand pointer.
MOVE.L ExpandMemRec.emSplineKey(A0),A0 ; get handle to splineKey globals.
MOVE.L (A0), A0 ; get pointer to splineKey globals.
MOVE.L splineKeyRec.cacheHand(A0),A0 ; Get the handle in case it changed.
MOVE.L A0, cacheHand(A6) ;restore cacheHand
MOVE.L (A0), D0 ;pointer to the cache
IF HAS_COLOR THEN
_StripAddress ;Make sure it is the right mode
ENDIF
MOVE.L D0, cachePtr(A6) ;restore cache pointer
MOVE.L D0, A2
LEA cache.glyphArray(A2), A0 ;Get array of glyphs into A0
MOVE.L A0, glyphArray(A6) ;restore the glyph array pointer
;——————————————————————
TST.L (SP)+ ;Any Errors
MOVEM.L (SP)+, A1/D2 ;Restore all registers on return
BNE sMiss ;No bitmap so print missing character
MOVE.L entryOffset(A6), D0
ADD.L D0, A2 ;Point to the data
MOVE.L srcAddr(A6), A4 ;Get the address
IF HAS_COLOR THEN
TST.B needs32bit(A6) ;running 32 bit clean
BEQ.S @no32 ;=>IF NOT, JUST RETURN
MOVEM.L A0-A1/D0-D2,-(SP) ;Save off all registers before JSR
MOVE.L A4, D0 ;get 24 bit base addr
_rTranslate24To32 ;mask off high byte
MOVE.L D0,A4 ;SAVE FOR LATER
MOVEM.L (SP)+, A0-A1/D0-D2 ;Restore all registers on return
@no32
ENDIF
MOVE.W yMax(A6), D6 ;Save yMax in D6
MOVE.W scan(A6), D7 ;Save the scan lines
MOVE.W yMin(A6), D3 ;Get ymin for later
MOVE.L srcRow(A6), D5 ;byteWidth in D5 for now <45-CEL>
BRA.S noClipping
;————————————————————————————————————————————————————————————————————————————————————————————————
; End _sbRetrieveGlyph call
;————————————————————————————————————————————————————————————————————————————————————————————————
isCached
MOVE.L cachePtr(A6), A2 ;Get pointer to cache
ADD.L D0, A2 ;add offset and point to glyph data
if (hasDoubleByte) then
clr.l d0 ; clear a long for the character code
move.b lowByte(a6),d0 ; double byte character?
beq.s @haveGlyphRecord ; no, skip this
IF &SETTING('MACHINE') <> 'MC68000' THEN
move.l 0(a2,d0.w*4),d0 ; load glyph record offset
ELSE
add.w d0,d0
add.w d0,d0
move.l 0(a2,d0.w),d0
ENDIF
ble errorOrNotCached ; fall into common error case
move.l cachePtr(a6),a2 ; load pointer to cache
add.l d0,a2 ; add offfset for glyph pointer
@haveGlyphRecord
endif
LEA glyph.cacheData(A2), A4 ;Get address
MOVE.W glyph.yMax(A2), D6 ;Save yMax in D6
MOVE.W glyph.scan(A2), D7 ;Save the scan lines
MOVE.W glyph.yMin(A2), D3 ;Save the scan lines
MOVE.L glyph.byteWidth(A2), D5 ;byteWidth in D2 for now <45-CEL>
TST.B clipVert(A6) ;are we clipping
BEQ.S noClipping ;nope so continue
MOVEQ #0, D1 ;d1 long ready
MOVE.W D6, D1 ;Get the bottom clipping area
SUB.W topClip(A6), D1 ;clipping value = yMax - topClip
BLE.S @noTopClip ;Top not clipped
MOVE.W topClip(A6), D6 ;New yMax from topclip value
MOVE.L glyph.byteWidth(A2), D0 ;
MULU D0, D1 ;Get Adjusment to srcAddr
ADD.L D1, A4 ;Add adjustment to top
@noTopClip
CMP.W botClip(A6), D3 ;get the bottom clipping value
BGE.S @noBotClip
MOVE.W botClip(A6), D3 ;get new ymin
@noBotClip
MOVE.W D6, D7 ;Get the YMax value
SUB.W D3, D7 ;scan = yMax - yMin
noClipping
SUBQ.W #1, D7 ;
BMI sMiss ;nothing to blit so skip character
MOVE.L CHARLOC(A6), D3 ;D3 = DestLeft (LSB + CharLoc)
SWAP D3 ;Only use low order word
ADD.W glyph.devLSB(A2), D3 ;Get integralized left side bearing
TST.B nextBand(A6) ;skip the advance???
BNE.S @noAdvance ;
;••• spot for skipping advance if char banding!!!
IF HAS_COLOR | SCRIPT_CHAR_EXTRA THEN ;<7> CEL
ADD.L characterExtra(A6),D4 ;add in character extra, if any
ENDIF
ADD.L D4, CHARLOC(A6) ;Add fixed point width to CharLoc
@noAdvance
MOVE.W glyph.bitWidth(A2), D2 ;
MOVE.L D5, A2 ;byteWidth in A2 <45-CEL>
MOVE.W topAdjust(A6), D4 ;Use the topadjust previous calculated
SUB.W D6, D4 ;D4 is dest adjustment
MOVE.W D2, charWidth(A6) ;Save for later
ADD.W D3, D2 ;DSTRIGHT := DSTLEFT + WIDTH
MOVEQ #0, D1 ;D1 = SrcLeft for blit equals 0
;————————————————————————————————————————————————————————————————————————————————————————————————
; On Entry
; Registers On Entry:
; D0 = scratch A0 = xxxxxxx
; D1 = SrcLeft.w A1 = xxxxxxx
; D2 = DstRight.w A2 = srcRow.l
; D3 = DstLeft.w A3 = xxxxxxx
; D4 = DstAdjust .w A4 = srcAddr.l
; D5 = xxxxxxx A5 = xxxxxxx
; D6 = yMax.w A6 = stack frame
; D7 = scan A7 = xxxxxxx
;
;————————————————————————————————————————————————————————————————————————————————————————————————
;$$$ Horizontal Clipping
TST.B FastFlag(A6) ;ARE WE GOING FAST ?
BEQ.S sHORIZOK ;NO, DON'T CLIP
CMP MINRECT+LEFT(A6),D3 ;IS DSTLEFT < MINRECT.LEFT ?
BGE.S sLEFTOK ;NO, CONTINUE
CMP MINRECT+LEFT(A6),D2 ;IS DSTRIGHT <= MINRECT.LEFT ?
BLE sSKIPCH ;YES, SKIP THIS CHAR
sTRIMLFT 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 sfixCharWidth ;NO, CONTINUE
BRA.S sTRIMRT ;YES, TRIM RIGHT
sLEFTOK CMP MINRECT+RIGHT(A6),D2 ;IS DSTRIGHT <= MINRECT.RIGHT ?
BLE.S sHORIZOK ;YES, CONTINUE
CMP MINRECT+RIGHT(A6),D3 ;IS DSTLEFT >= MINRECT.RIGHT ?
BGE STRDONE ;YES, IGNORE REST OF STRING
sTRIMRT MOVE MINRECT+RIGHT(A6),D2 ;NO, TRIM DSTRIGHT
sfixCharWidth
MOVE D2,D0 ;char width has been trimmed left, right, or both
SUB D3,D0 ;so recalculate char width to draw
MOVE D0,charWidth(A6) ;and save this tidbit of info. for later
sHORIZOK
ENDIF ;hasSplineFonts
;————————————————————————————————————————————————————————————————————————————————————————————————
; Blit loop for the 68020+ machines
;
; Inputs to local block CharBlt:
;
; Registers Use:
; D0 = xxxxxxx A0 = xxxxxxx
; D1 = SrcLeft.l A1 = TextPtr.l
; D2 = DstRight.w A2 = srcRow.l
; D3 = DstLeft.w A3 = dstRow.w
; D4 = DstAdjust .w A4 = srcAddr.l
; D5 = xxxxxxx A5 = dstPtr.l
; D6 = yMax.w A6 = stack frame.l
; D7 = scan.w A7 = stack pointer.l
;
; dstLeft relative to buffer
; dstRight relative to buffer, > dstLeft
;
; CLOBBERS: D0,D1,D2,D3,D4,D5,D6,D7,A0,A2,A3,A4,A5
; PRESERVES: A1,A6,A7
;
;
;————————————————————————————————————————————————————————————————————————————————————————————————
IF &SETTING('MACHINE') <> 'MC68000' THEN
MOVEM D1-D3,maskBlts(A6)
MOVE.B textCopyMode(A6),orNotOK(A6) ;if copy or if mask mode, do bit moves instead of OR
ST notMaskPass(A6) ;use the bitDepth this pass
MOVE BUFROW(A6),A3
MOVE.L bufStart(A6), A5 ;BufStart (dst bitmap)
smaskBlt
; sfnt adjustment of the destination pointer
MOVE A3,D0 ;get dstRow in D-reg
MULS.W D4,D0 ;calc charTop * dstRow
ADD.L D0,A5 ;add to dstPtr
; Put glyph height - 1 into D7 for blit loop
;
;————————————————————————————————————————————————————————————————————————————————————————————————
;————————————————————————————————————————————————————————————————————————————————————————————————
; Setup shift count in D5 (relative shift between src and dst)
;
;————————————————————————————————————————————————————————————————————————————————————————————————
pastBitMapPointers ;skipped past bitmap pointer setup
;
; figure alignment offset in source so that dest is long aligned
;
MOVEQ #$1F,D0 ;get a 5 bit mask, needed later
MOVE.L D1,D5
;
; Setup dstPtr in A5, address of leftmost dst word
;
MOVE.W D3,D6 ;GET A COPY OF DSTLEFT
ASR #5,D6 ;CONVERT FROM DOTS TO LONGS
MOVE.W D6,D4 ;copy dest left in longs for later
LSL #2,D6 ;quad for bytes
ADD.W D6,A5 ;move dest pointer to start of character
;
; figure number of longs to move
;
MOVE.W D2,D6 ;copy dstRight
ASR #5,D6
SUB.W D4,D6 ;if same, it fits into a single long
BEQ fitsInLong ;most 1 bit deep characters fit into a long
;——————————————————————————————————————————————————————————————————————————————————————
; SPANS LONG
;
; Character spans long in destination, so it must be moved in pieces.
;
; Registers Use:
; D0 = 5 bit mask.w A0 = xxxxxxx
; D1 = SrcLeft.w A1 = TextPtr.l
; D2 = DstRight.w A2 = srcRow.l
; D3 = DstLeft.w A3 = destRow.l
; D4 = xxxxxxx A4 = srcRowPtr.l
; D5 = SrcLeft.w A5 = dstPtr.l
; D6 = longs to move.w A6 = stack frame.l
; D7 = scan.w A7 = stack pointer.l
;——————————————————————————————————————————————————————————————————————————————————————
NEG D3 ;negate for bit counting
AND D0,D3 ;get bottom 5 bits of dstLeft
BNE.S @skip32
MOVEQ #32,D3 ;if 0, make it 32
@skip32
MOVE.W D6,D4 ;total longs (not including left part)
LSL #2,D4 ;make it a byte count
SUB D4,A2 ;adjust source bump count
SUB D4,A3 ;adjust dest. bump count
SUBQ.W #1,D6 ;number of whole longs, less left & right parts
ADD D3,D1 ;the right hand start
MOVEQ #32,D4
SUB.L D4,D1
;
; if not 1 bit font & mode is not srcOr, do moves instead
;
TST.B orNotOK(A6)
BNE.S DoMove
;
; OR words to the screen; set up right mask
;
AND D0,D2 ;get bottom 5 bits of dstRight
MOVEQ #1,D4
ROR.L #1,D4 ;set the high bit
ASR.L D2,D4 ;$80000000 to $FFFFFFFF
ASL.L #1,D4 ;$00000000 to $FFFFFFFE
MOVE.W D6,D2 ;initialize whole long count
MOVE.W D6,A0 ;save long count for later
MOVE.L D5,D6
ADD.W D3,D6
MOVEQ #32,D0
SUB.L D0,D6
;——————————————————————————————————————————————————————————————————
; SLOW LOOP
;
; Slow loop only taken in wierd cases where dst wider than a long.
; Or the more common case that the font is more than 1 bit deep
;——————————————————————————————————————————————————————————————————
MAIN1
BFEXTU (A4){D5:D3},D0 ;GET SRC FROM BITMAP
BRA.S @checkLong ;see if there is some number of longs to do
@main2
BFEXTU (A4){D6:0},D0 ;GET SRC FROM BITMAP
@checkLong
OR.L D0,(A5)+ ;OR SRC INTO DST
ADDQ #4,A4 ;BUMP SRCPTR RIGHT
DBRA D2,@main2 ;LOOP TILL LAST long
BFEXTU (A4){D1:0},D0 ;GET SRC FROM BITMAP
AND.L D4,D0
OR.L D0,(A5) ;OR SRC INTO DST
ADD.L A2,A4 ;BUMP TO NEXT ROW
ADD.L A3,A5 ;BUMP DST TO NEXT ROW
WIDE1 MOVE A0,D2 ;GET long count
DBRA D7,MAIN1 ;LOOP ALL ROWS
BRA decCount ;skip mask blt part
;
; Handle case of drawing into the offscreen bit map in color separately
;
DoMove
MOVE D2,D4 ;copy dstRight
AND D0,D4 ;get bottom 5 bits of dstRight
MOVE D6,longCount(A6) ;save # of whole longs
MOVE D6,D2 ;set up first loop count
MOVE.L bkCol(A6),D6 ;get a long full of the background color
BFEXTU D6{0:D3},D0 ;background color & left mask
MOVE.L D0,leftBack(A6) ;save for quick compare
BFEXTU D6{0:D4},D0 ;background color & right mask
MOVE.L D0,rightBack(A6) ;right mask color compare
MOVE bitDepth(A6),D0 ;bits in a single pixel
BFEXTU D6{0:D0},D0 ;get a single pixel of the background color
MOVE D0,bkCol1(A6) ;a single background color for quick compare
MOVEQ #32,D6 ;
SUB D3,D6 ;
MOVE.L D5,A0
ADD D3,A0
SUB #32,A0 ;set up center move offset
;
; Slow loop taken in cases where dst wider than a long (common for fonts more than 1 bit
; deep.) Need to move only the pixels that are not colored same as background.
;
MoveLeft
BFEXTU (A5){D6:D3},D0 ;get current background of destination
CMP.L leftBack(A6),D0 ;compare it against the background color AND leftMask
BNE.S leftOnePix ;if different, must move 1 pixel at a time
;
; Here the destination has only background color pixels, so the whole thing can be moved
;
BFEXTU (A4){D5:D3},D0 ;GET SRC FROM BITMAP
BFINS D0,(A5){D6:D3}
checkLong
EXG A0,D5 ;set up center move offset
midChkLong
ADDQ #4,A5 ;bump destination
BRA.S checkMLong ;see if there is some number of longs to do
MoveMid
MOVE.L bkCol(A6),D0
CMP.L (A5),D0 ;same as background color?
BNE.S midOnePix ;if different, move 1 at a time
BFEXTU (A4){D5:0},D0 ;GET SRC FROM BITMAP
MOVE.L D0,(A5)+ ;OR SRC INTO DST
checkMLong
ADDQ #4,A4 ;BUMP SRCPTR RIGHT
DBRA D2,MoveMid ;LOOP TILL LAST WORD
MoveRight
EXG A0,D5 ;set up left move offset
TST D4
BEQ.S nextRow
BFEXTU (A5){0:D4},D0 ;look at the destination
CMP.L rightBack(A6),D0 ;compare it against the background AND rightMask
BNE.S rightOnePix ;if different, must move 1 pixel at a time
;
; Here the destination has only background color pixels, so the whole thing can be moved
;
BFEXTU (A4){D1:D4},D0 ;get the right part of the character
BFINS D0,(A5){0:D4} ;move it to the destination
nextRow
ADD.L A2,A4 ;BUMP TO NEXT ROW
ADD.L A3,A5 ;BUMP DST TO NEXT ROW
offMove
MOVE longCount(A6),D2 ;GET long count
DBRA D7,MoveLeft ;LOOP ALL ROWS
BRA decCount ;out of here for next char
;
; need to move only the pixels that are not colored same as background
;
leftOnePix
MOVEM.L D1/D3-D6,-(SP) ;save temporary registers
MOVEM bkCol1(A6),D0/D1 ;D0 = back color D1 = pixel width
@nxtPixel
BFEXTU (A4){D5:D1},D4 ;pick up a source pixel
CMP D4,D0 ;is it the same as the back color?
BEQ.S @skipInsert ;if so, dont add to destination
BFINS D4,(A5){D6:D1} ;if not, copy it to the destination
@skipInsert
ADD.L D1,D5 ;move to next source pixel
ADD D1,D6 ;move to next destination pixel
SUB D1,D3 ;decrement count
BGT.S @nxtPixel ;do until were done
MOVEM.L (SP)+,D1/D3-D6 ;restore bkCol, left & right widths, src & dest offsets
BRA.S checkLong
midOnePix
MOVEQ #32,D0 ;full long size in bits
MOVEM.L D1/D3-D6,-(SP) ;save temporary registers
MOVEQ #0,D6
MOVEM bkCol1(A6),D1/D3 ;D1 = back color D3 = pixel width
@nxtPixel
BFEXTU (A4){D5:D3},D4 ;pick up a source pixel
CMP D4,D1 ;is it the same as the back color?
BEQ.S @skipInsert ;if so, dont add to destination
BFINS D4,(A5){D6:D3} ;if not, copy it to the destination
@skipInsert
ADD.L D3,D5 ;move to next source pixel
ADD D3,D6 ;move to next destination pixel
SUB D3,D0 ;decrement count
BGT.S @nxtPixel ;do until were done
MOVEM.L (SP)+,D1/D3-D6 ;restore bkCol, left & right widths, src & dest offsets
BRA midChkLong
rightOnePix
MOVEM.L D1/D3-D6,-(SP) ;save temporary registers
MOVEQ #0,D6
MOVEM bkCol1(A6),D3/D5 ;D3 = back color D5 = pixel width
@nxtPixel
BFEXTU (A4){D1:D5},D0 ;pick up a source pixel
CMP D0,D3 ;is it the same as the back color?
BEQ.S @skipInsert ;if so, dont add to destination
BFINS D0,(A5){D6:D5} ;if not, copy it to the destination
@skipInsert
ADD.L D5,D1 ;move to next source pixel
ADD D5,D6 ;move to next destination pixel
SUB D5,D4 ;decrement count
BGT.S @nxtPixel ;do until were done
MOVEM.L (SP)+,D1/D3-D6 ;restore bkCol, left & right widths, src & dest offsets
BRA nextRow
;—————————————————————————————————————————————————————————————————————————————————————————————————
; FASTER LOOPS
;
; Here, the character does not cross a long boundary, so faster loops are in order.
;
; Registers Use:
; D0 = 5 bit mask.w A0 = xxxxxxx
; D1 = src Offset.w A1 = TextPtr.l
; D2 = dstRight.w A2 = srcRowSize.l
; D3 = dstLeft.w A3 = destRowPtr.l
; D4 = xxxxxxx A4 = srcRowPtr.l
; D5 = src Offset.w A5 = destRowPtr.l
; D6 = longs to move.w A6 = stack frame.l
; D7 = scan.w A7 = stack Pointer.l
;—————————————————————————————————————————————————————————————————————————————————————————————————
fitsInLong
MOVE.W charWidth(A6),D3 ;set up character width in bits
TST.B notMaskPass(A6) ;if dest is 1 bit, or this is the mask,
BEQ.S @skipMul ;then skip the mul scale
MOVE bitShift(A6),D4 ;set up bit depth
LSL D4,D3
@skipMul
TST.B orNotOK(A6) ;can we OR?
BNE.S offLong ;if not, bit extract/insert instead
;
; Optimize if dst fits in one long. (most 1 bit deep characters do)
;
LONG1
;
; OR words to the screen; set up right mask
MOVE D2,D1 ;copy dest right
NEG D1 ;figure not bits from left but bits from right
AND D0,D1 ;but only from 0 to 31
ADD D1,D3 ;add right mask to extract width
AND D0,D2 ;get bottom 5 bits of dstRight
MOVEQ #1,D4
ROR.L #1,D4 ;set the high bit
ASR.L D2,D4 ;$80000000 to $FFFFFFFF
ASL.L #1,D4 ;$00000000 to $FFFFFFFE
; if D5 + D3 < 32, use a faster set of code:
longLoop
BFEXTU (A4){D5:D3},D0 ;GET SRC DATA
AND.L D4,D0
OR.L D0,(A5) ;OR RESULT INTO DST
ADD.L A2,A4 ;BUMP SRCPTR TO NEXT ROW
ADD.L A3,A5 ;BUMP DSTPTR TO NEXT ROW
DBRA D7,longLoop ;LOOP ALL ROWS
BRA decCount
;
; Optimize if dst fits in one long. (most normal characters do)
;
offLong
MOVE D2,D6
AND.L D0,D6
SUB D3,D6
BFEXTU bkCol(A6){0:D3},D2
MOVEM.L D5/D6,leftOffset(A6) ;save source left, destination left offsets
MOVE D5,D0 ;source left offset less
ADD D3,D0 ; width of pixels to be moved
MOVE D0,longCount(A6) ; determines inner loop bounds
MOVE bitDepth(A6),D4 ;get source depth
BFEXTU D2{0:D4},D1 ;set up 1 pixel of background color
offLongLoop
; check to see if existing destination is untouched (equal to background) so that there is no
; concern about obliterating over a part of a character that kerns into this space.
BFEXTU (A5){D6:D3},D0 ;get the existing background
CMP.L D2,D0 ;is it background colored?
BEQ.S @okToBlast ;if so, it is safe to cut and fill
; inner loop taken if some kerning has occured so that bits can not be moved directly over bkground
@nxtPixel
BFEXTU (A4){D5:D4},D0
CMP D0,D1
BEQ.S @skipInsert
BFINS D0,(A5){D6:D4}
@skipInsert
ADD D4,D6
ADD D4,D5
CMP longCount(A6),D5 ;where to stop with the mask
BLT.S @nxtPixel
MOVEM.L leftOffset(A6),D5/D6 ;restore source left, destination left offsets
BRA.S @nextRow
; if no kerning, data can be moved without concern for what is already there.
@okToBlast
BFEXTU (A4){D5:D3},D0 ;GET SRC DATA
BFINS D0,(A5){D6:D3} ;move to destination
@nextRow
ADD.L A2,A4 ;BUMP SRCPTR TO NEXT ROW
ADD.L A3,A5 ;BUMP DSTPTR TO NEXT ROW
DBRA D7,offLongLoop ;LOOP ALL ROWS
;
; here, set up things for mask blt
;
; BRA.S decCount ;Always Branch
;————————————————————————————————————————————————————————————————————————————————————————————————
; END Blit loop for the 68020+ machines
;————————————————————————————————————————————————————————————————————————————————————————————————
;————————————————————————————————————————————————————————————————————————————————————————————————
; Blit loop for the 68000 machines
;————————————————————————————————————————————————————————————————————————————————————————————————
ELSE ;68000
MOVE.W D3,D5
SUB.W D1,D5
MOVEQ #$F,D0
AND.W D0,D5
MOVE.W -$36(A6),A3
MOVE.L -$24C(A6),A5
ADD.W D5,D1
ASR.W #4,D1
ADD.W D1,D1
SUB.W #2,D1
ADD.W D1,A4
MOVE.W A3,D1
MULS.W D1,D4
ADD.L D4,A5
MOVE.W D3,D1
ASR.W #4,D1
ADD.W D1,A5
ADD.W D1,A5
MOVE.L -$234(A6),A0
AND.W D0,D3
ADD.W D3,D3
MOVE.W (A0,D3),D3
NOT.W D3
MOVE.W D2,D6
AND.W D0,D2
ADD.W D2,D2
MOVE.W (A0,D2),D4
pastBitMapPointers
ASR.W #4,D6
SUB.W D1,D6
BEQ.S @5
SUB.W #1,D6
BEQ.S @3
ADDQ.W #1,D7
BRA.S @2
@1
MOVE.L (A4),D0
ADDQ.W #2,A4
LSR.L D5,D0
AND.W D1,D0
OR.W D0,(A5)+
MOVEQ #-1,D1
DBRA D2,@1
MOVE.L (A4),D0
LSR.L D5,D0
AND.W D4,D0
OR.W D0,(A5)
MOVE.L -$46(A6),A4
ADD.L A2,A4
MOVE.L -$4A(A6),A5
ADD.W A3,A5
@2
MOVE.L A4,-$46(A6)
MOVE.L A5,-$4A(A6)
MOVE.W D3,D1
MOVE.W D6,D2
DBRA D7,@1
BRA.S decCount
@3
SUB.W #2,A3
@4
MOVE.L (A4),D0
LSR.L D5,D0
AND.W D3,D0
OR.W D0,(A5)+
MOVE.L 2(A4),D0
LSR.L D5,D0
AND.W D4,D0
OR.W D0,(A5)
ADD.L A2,A4
ADD.W A3,A5
DBRA D7,@4
BRA.S decCount
@5
AND.W D4,D3
@6
MOVE.L (A4),D0
LSR.L D5,D0
AND.W D3,D0
OR.W D0,(A5)
ADD.L A2,A4
ADD.W A3,A5
DBRA D7,@6
ENDIF ;68000
;————————————————————————————————————————————————————————————————————————————————————————————————
; END Blit loop for the 68000 machines
;————————————————————————————————————————————————————————————————————————————————————————————————
decCount
IF (hasSplineFonts) OR (Gaudi) THEN ; <31> DTY
TST.B isSpline(A6)
BEQ.S @1
TST.B nextBand(A6) ;another char band then call retrieve!!!
BNE sNextBand ;do the next char band
SUBQ.W #1,countCopy(A6) ;decrement partial draw character count
BGT sNextCh ;LOOP IF MORE CHARS LEFT
BRA.S STRDONE
ENDIF
@1 SUBQ.W #1,charsRemain(A6) ;decrement total character count
SUBQ.W #1,countCopy(A6) ;decrement partial draw character count
BGT NEXTCH ;LOOP IF MORE CHARS LEFT
;------
STRDONE
MOVE.L SAVEA5(A6),A5 ;RESTORE GLOBAL PTR
IF HAS_COLOR THEN
TST.B FASTFLAG(A6) ;WERE WE GOING DIRECT TO SCREEN ?
BEQ.S @1 ;NO, CONTINUE
TST.B needs32Bit(A6) ;device need 32-bit addressing <7Apr90 KON>
BEQ.S @0 ;=>IF NOT, JUST RETURN
move.b MMUsave(a6),d0 ;get previous MMU state in d0
_rSwapMMUMode ;get previous mode in d0.b (can trash a0/a1/a2, d0/d1/d2)
@0 tst.b crsrFlag(a6) ;is dst to a screen <7Apr90 KON>
beq.s @NoShow ;no, then don't show cursor
ELSE
tst.b FastFlag(a6)
beq.s @1
ENDIF
_SHOWCURSOR ;YES, RESTORE CURSOR
@NoShow 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 fmOutFontH(A4),A2 ;GET FONT HANDLE
MOVE.L (A2),A2 ;DE-REFERENCE IT
;
; Make buffer bold if necessary:
;
CKBOLD CLR D2 ;GET READY FOR BYTE
MOVE.B fmOutBold(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.L 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.
;
MOVEQ #0,D2 ;GET READY FOR BYTE
IF (hasSplineFonts) OR (Gaudi) THEN ; <31> DTY
TST.B isSpline(A6) ;is it a spline
BNE.S CHECKUL ;Splines already italic, no italic needed
ENDIF ;<1.6-11april89-CEL>
MOVE.B fmOutItalic(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
IF HAS_COLOR THEN
LSR #2,D3 ;LONGCNT:=ROWBYTES DIV 4
ELSE
LSR #1,D3
ENDIF
SUB #1,D3 ;LONGCOUNT-1 FOR DBRA LOOP
MOVE sHeight(A6),D6 ;INIT ROW COUNTER
SUB #1,D6 ;Baseline not slanted <38>
IF HAS_COLOR THEN
MOVEQ #0,D4 ;INIT OFFSET
BRA.S DOSLANT ;GO TO LOOP START
NXTROW ADD.L D2,D4 ;OFFSET:=OFFSET+ITALIC
MOVE.L D4,D5 ;COPY OFFSET
LSR.L #4,D5 ;DELTA := OFFSET SCALED BY 16
NEG.L D5 ;make negative for BFEXTU
MOVE.L A1,A0 ;SRCPTR:=DSTPTR
SUB #4,A0 ;POINT TO LAST LONG
ELSE
CLR D4
BRA.S DOSLANT
NXTROW ADD D2,D4
MOVE D4,D0
LSR #4,D0
MOVEQ #$F,D5
AND.W D0,D5
LSR #4,D0
MOVE.L A1,A0
SUB #4,A0
SUB.W D0,A0
SUB.W D0,A0
ENDIF
MOVE D3,D1 ;INIT LOOP TO LONGCNT
IF &SETTING('MACHINE') <> 'MC68000' THEN
NXTLONG BFEXTU (A0){D5:0},D0 ;GET A SHIFTED LONG OF SRC
SUB #4,A0 ;BUMP SRCPTR LEFT ONE LONG
ELSE
NXTLONG MOVE.L (A0),D0 ;GET A SHIFTED LONG OF SRC
SUB #2,A0 ;BUMP SRCPTR LEFT ONE LONG
LSR.L D5,D0
ENDIF
IF HAS_COLOR THEN
MOVE.L D0,-(A1) ;STORE IN DST AND BUMP DSTPTR
ELSE
MOVE.W D0,-(A1)
ENDIF
DBRA D1,NXTLONG ;LOOP ALL LONG 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 fmOutULThick(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
IF (hasSplineFonts) OR (Gaudi) THEN ; <31> DTY
TST.B isSpline(A6) ;is it a spline
BEQ.S @doOldAssign ;Splines already stretch, no stretchbits needed
MOVE topClip(A6), D0 ;Use topClip and botClip since this is real size of buffer
TST.W D0
BLT.S NOTUL ;If ascent is negative do not do it
MOVE botClip(A6), D2 ;Real size of buffer
BRA.S @skipOldAssign
@doOldAssign
ENDIF ;<1.6-11april89-CEL>
MOVE sASCENT(A6),D0 ;stack ascent
MOVE sDESCENT(A6),D2 ;
@skipOldAssign
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 ?
BGT.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
;
; Setup fakeRgn, a dummy rectangular region
;
NOTUL MOVE #10,FAKERGN+RGNSIZE(A6) ;SIZE=10 BYTES FOR RECT RGN
IF HAS_COLOR THEN
MOVE.L DSTPIX+BOUNDS(A6),FAKERGN+RGNBBOX(A6)
MOVE.L DSTPIX+BOUNDS+4(A6),FAKERGN+RGNBBOX+4(A6)
ELSE
MOVE.L PORTBITS+BOUNDS(A3),FAKERGN+RGNBBOX(A6)
MOVE.L PORTBITS+BOUNDS+4(A3),FAKERGN+RGNBBOX+4(A6)
ENDIF
IF (hasSplineFonts) OR (Gaudi) THEN ; <31> DTY
TST.B isSpline(A6) ;is it a spline
BEQ.S @skipBandClip ;
TST.B clipVert(A6) ;Can we try the fast blitting routine???
BEQ.S @skipBandClip ;go to clipping blit loop
MOVE.W TEXTR2(A6), D1 ;get top
MOVE.W D1, D2 ;Make a copy
MOVE.W sAscent(A6), D0 ;place in reg for compare
SUB.W origTopClip(A6), D0 ;
BNE.S @topIsClipped ;top is clipped so do not add shadow extra
TST.B fmOutShadow(A6) ;no shadowing so skip adjustment for it
BEQ.S @noShadowSUB
SUB.W #1, D1 ;adding to ymax value
@noShadowSUB
BRA.S @gotNewTop
@topIsClipped
ADD.W D0, D1
@gotNewTop
MOVE.W D1, FAKERGN+RGNBBOX+TOP(A6) ;Fake top
MOVE.W origBotClip(A6), D0 ;get the bottom clip
CMP.W sDescent(A6), D0 ;are they the same
BNE.S @noExtra ;no extra for shadow
TST.B fmOutShadow(A6) ;no shadowing so skip adjustment for it
BEQ.S @noExtra
SUB.W #2, D0 ;add in for shadow
@noExtra
MOVE.W sAscent(A6), D1 ;place in reg for compare
SUB.W D0, D1 ;subtract bottom clip
ADD.W D1, D2 ;Add to TextR2 top
MOVE.W D2, FAKERGN+RGNBBOX+BOTTOM(A6) ;Fake bottom
ENDIF ;
@skipBandClip
LEA FAKERGN(A6),A0 ;GET ADDR OF FAKERGN
MOVE.L A0,FAKEPTR(A6) ;POINT FAKE MASTERPTR TO IT
;
; SET UP SOURCE BITMAP TO TRANSFER TO SCREEN
;
; SRCPIX := buffer
;
LEA SRCBITS(A6),A0 ;POINT TO source bits
MOVE.L A0,A1
MOVE.L BUFSTART(A6),(A0)+ ;SET UP BASEADDR
MOVE BUFROW(A6),(A0)+ ;SET UP ROWBYTES
IF (hasSplineFonts) OR (Gaudi) THEN ; <31> DTY
TST.B isSpline(A6) ;is it a spline
BEQ.S @skipAdjust ;Splines already stretch, no stretchbits needed
MOVE sAscent(A6), D0 ;Get the ascent in D0
SUB topClip(A6), D0 ;What is the difference for adjustment
ADD TEXTRECT+TOP(A6),D0 ;SET UP BOUNDS TOP
MOVE D0,(A0)+ ;SET UP BOUNDS TOP
BRA.S @skipNorm
@skipAdjust
MOVE TEXTRECT+TOP(A6),(A0)+ ;SET UP BOUNDS TOP
@skipNorm
ELSE
MOVE TEXTRECT+TOP(A6),(A0)+ ;SET UP BOUNDS TOP
ENDIF ;NEW
MOVE BUFLEFT(A6),(A0)+ ;SET UP BOUNDS LEFT
IF (hasSplineFonts) OR (Gaudi) THEN ; <31> DTY
TST.B isSpline(A6) ;is it a spline
BEQ.S @skipTheAdjust ;Splines already stretch, no stretchbits needed
MOVE sAscent(A6), D0 ;Get the ascent in D0
SUB topClip(A6), D0 ;What is the difference for adjustment
ADD.W TEXTRECT+BOTRIGHT(A6), D0 ;Get the bottom
MOVE.W D0,(A0)+ ;SET UP BOTTOM
MOVE.W TEXTRECT+RIGHT(A6), (A0)+ ;Set up right
BRA.S @skipNormPath
@skipTheAdjust
MOVE.L TEXTRECT+BOTRIGHT(A6),(A0)+ ;SET UP BOTTOM RIGHT
@skipNormPath
ELSE ;
MOVE.L TEXTRECT+BOTRIGHT(A6),(A0)+ ;SET UP BOTTOM RIGHT
ENDIF ;
IF HAS_COLOR THEN
LEA SRCPIX(A6),A2
_BitsToPix
TST.B maskFont(A6)
BEQ @finishSrcPix ; <CEL-39>
LEA maskBits(A6),A0 ;POINT TO mask bits
MOVE.L maskStart(A6),(A0)+ ;SET UP BASEADDR
MOVE mBufRow(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
TST bitShift(A6) ;is the bit depth 1? <CEL-39>
BEQ.S @finishSrcPix
;—————————————————————————————————————————————————————————————————————————————————————————————————
; make fill loop <CEL-39>
;
; Registers Use:
; D0 = xxxxxxx A0 = SrcPtr
; D1 = temp WidthInPixels A1 = DstPtr
; D2 = (2**PixelSize)-1.w A2 = Src rowBytes.l
; D3 = Dst Offset A3 = Dest rowBytes.w
; D4 = Src Offset A4 = xxxxxxx
; D5 = Src PixelSize.w A5 = xxxxxxx
; D6 = Height.w A6 = xxxxxxx
; D7 = Width In Pixels A7 = xxxxxxx
;—————————————————————————————————————————————————————————————————————————————————————————————————
MOVE.L A3, -(SP) ;Save A3
MOVE.W bitDepth(A6), D5 ;bits per pixel
MOVEQ #1, D2 ;2 to be shifted
LSL.W D5, D2 ;2**Pixel Size
SUB.W #1, D2 ;(2*PixelSize)-1
MOVE.W sHeight(A6), D6 ;
SUB.W #1, D6 ;for the dbra
MOVE.W mBufRow(A6), A3 ;row bytes of mask
MOVE.W A3,D7 ;Shift by pixel depth
LSL.W #3, D7 ;pixels=rowbytes*8
SUB.W #1, D7 ;for dbra
MOVE.L bufStart(A6), A0 ;SrcPtr
MOVE.L maskStart(A6), A1 ;DstPtr
MOVE.W bufRow(A6), A2 ;Src rowBytes
@nxtScan
MOVE.W D7, D1 ;D1 for loop of the width
MOVEQ #0, D3 ;Clear offset
MOVEQ #0, D4 ;Clear offset
@nxtPix
BFEXTU (A0){D4,D5}, D0 ;get a pixel
ADD.W D2, D0 ;create a carry bit if non zero
LSR.W D5, D0 ;Shift to get black pixel in bottom
BFINS D0, (A1){D3,1} ;Insert the bit into the mask
ADD.W D5, D4 ;Increment the offset
ADDQ #1, D3 ;Increment mask Pixel offset
DBRA D1, @nxtPix ;cont to next pixel
ADD.L A2, A0 ;bump to next row
ADD.W A3, A1 ;bump to next row
DBRA D6, @nxtScan ;cont to next scan
MOVE.L (SP)+, A3 ;Restore A3
;—————————————————————————————————————————————————————————————————————————————————————————————————
;—————————————————————————————————————————————————————————————————————————————————————————————————
@finishSrcPix
TST bitShift(A6) ;is the bit depth 1? <CEL-44>
BEQ.S @skipColorJam ; <CEL-44>
MOVE bitDepth(A6),srcPix+pixelSize(A6) ;set up bit depth <CEL-44>
MOVE bitDepth(A6),srcPix+cmpSize(A6) ;set up bit depth <CEL-44>
MOVE.L dstPix+pmTable(A6),srcPix+pmTable(A6) ;set up color table <CEL-44>
TST.B synFont(A6) ;is it a syn font??? <CEL-44>
BNE.S @skipColorJam ;use the dest color table <CEL-44>
MOVE.L WidthTabHandle,A0 ;Get the handle <CEL-44>
MOVE.L (A0), A0 ;Ptr <CEL-44>
MOVE.L widthNFNT(A0),D0 ;get resource ID in low word, NFNT bit in high word <CEL-44>
SUBQ #4,SP ;make space for function result <CEL-44>
MOVE.L #'fctb',-(SP) ;pass resource type <CEL-44>
MOVE D0,-(SP) ;pass resource ID <CEL-44>
_GetResource ;only uses D0,A0 <CEL-44>
MOVE.L (SP)+,D0 ;if it fails, then no color table to pass to MakeScaleTbl <CEL-44>
BEQ.S @skipColorJam ; <CEL-44>
MOVE.L D0,srcPix+pmTable(A6) ;set up color table, if any <CEL-44>
@skipColorJam
ENDIF
;
; check if any shadowing:
;
CLR D3 ;GET READY FOR BYTE
MOVE.B fmOutShadow(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.
;
IF (hasSplineFonts) OR (Gaudi) THEN ; <31> DTY
TST.B isSpline(A6)
BEQ.S oldAlloc2 ;Go to old way of allocating
MOVE.L currentEnd(A6), A0 ;Get the current end of the buffer
CLR.L (A0)+ ;ALLOW ONE LONG OF SLOP
MOVE.L A0, buf2Start(A6) ;REMEMBER START OF BUF2
MOVE.L bufStart(A6),A1 ;POINT to first buffer
MOVE.L bufSize(A6),D0 ;GET NUMBER OF LONGS IN BUF1
SUB.L #1,D0 ;INIT DBRA COUNTER
MOVE.L D0, D1 ;Get copy of size
SWAP D1 ;Get high order word for outer loop
CpyBuff MOVE.L (A1)+,(A0)+ ;COPY FROM BUF1 TO NEW BUF2
DBRA D0,CpyBuff ;COPY ALL OF BUF1
DBRA D1,CpyBuff ;COPY ALL OF BUF1
CLR.L (A0)+ ;ALLOW ONE LONG OF SLOP
MOVE BUFROW(A6),D0 ;GET 4 * NUMBER OF LONGS PER ROW
SUB #1,D0 ;INIT LOOP COUNTER
clrBuf2 CLR.L (A0)+ ;ALLOCATE AND CLEAR A LONG
DBRA D0,clrBuf2 ;CLEAR 4 SCANLINES WORTH
MOVE.L A0, buf2End(A6) ;REMEMBER END OF BUF2
CLR.L (A0)+ ;ALLOW ONE LONG OF SLOP
BRA.S doneNEW2
oldAlloc2
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.L 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
doneNEW2
ELSE
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.L 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
ENDIF
;
; 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.L BUFSIZE(A6),D1 ;Init for first time of inner loop
MOVE.L D1,D4 ;Get copy of bufSize
SWAP D4 ;Get high order word
SUB D0,D0 ;CLEAR X-BIT
outAcross
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 D4,outAcross ;Outer loop for inner loop
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
MOVE SRCBITS+ROWBYTES(A6),D2 ;GET SRC ROWBYTES
SUB D2,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.S DOWN2 ;NO, LOOP ALL LONGS
DBRA D3,DOWN1 ;BOLD DOWN 2,3, OR 4 TIMES
; XOR the plain text into the shadow buffer
MOVE.L bufStart(A6),A0 ;start of plain text
MOVE.L A2,A1 ;start of shadowed text
ADD D2,A1 ;bump down a line in the shadowed text
MOVE.L bufSize(A6),D1 ;size of buffers in longs
MOVE.L D1,D2 ;Get a copy of size
SWAP D2 ;Get high word of long
SUB D0,D0 ;clear x bit
@xor
MOVE.L (A0)+,D0 ;a line of plain text
ROXR.L #1,D0 ;shift it right, extended
EOR.L D0,(A1)+ ;combine with shadowed text
DBRA D1,@xor ;repeat for all longs
DBRA D2,@xor ;repeat outer loop with high order word
;
; 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) ;DSTRECT := SRCRECT
MOVE.L TEXTRECT+4(A6),SRCRECT+4(A6)
ADD #4,SRCRECT+BOTTOM(A6) ;PLUS 4 SCANS TALLER
MOVE.L SRCRECT(A6),DSTRECT(A6)
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)
_MAPRECT ;THEN MAPPED FOR SCALING
@1
PEA SRCBITS(A6) ;PUSH SRCPIX
IF HAS_COLOR THEN
MOVE.L maskBitsPtr(A6),-(SP) ;a mask?
BEQ.S @noMask
MOVE.L 4(SP),(SP) ;replace mask with copy of source
@noMask
ENDIF
PEA PORTBITS(A3) ;TRANSFER TO SCREEN
IF Gaudi THEN ;fix intersection if ColorQD and Bass init
TST.B isSpline(A6) ;is it a spline
BEQ.S @doOld ;skip special stretchbit fix
TST.B repeatBands(A6) ;if not banding then do nothing
BEQ.S @doOld
PEA DSTRECT(A6) ;PUSH DSTRECT = TEXTR2
PEA FAKERGN+RGNBBOX(A6) ;
MOVE #2,-(SP) ;PUSH NRECTS=4
PEA FAKERGN+RGNBBOX(A6) ;Place results in FakRgn
_RSECT ;CALC INTERSECTION
MOVE.L FAKERGN+RGNBBOX(A6), trimSrcRect(A6)
MOVE.L FAKERGN+RGNBBOX+4(A6), trimSrcRect+4(A6)
PEA trimSrcRect(A6) ;Make new source rect for Banding
PEA DSTRECT(A6)
PEA SRCRECT(A6)
_MAPRECT ;THEN MAPPED FOR SCALING
PEA trimSrcRect(A6) ;Make new source rect for Banding
IF HAS_COLOR THEN
PEA trimSrcRect(A6) ;maskRect same as source rect
ENDIF
PEA FAKERGN+RGNBBOX(A6) ;Use calculated dst rect
BRA.S @contArgs
ENDIF
@doOld PEA SRCRECT(A6) ;PUSH SRCRECT = TEXTRECT
IF HAS_COLOR THEN
PEA SRCRECT(A6) ;maskRect same as source rect
ENDIF
PEA DSTRECT(A6) ;PUSH DSTRECT = TEXTR2
@contArgs
MOVE locMode(A6),-(SP) ;PUSH TEXTMODE
TST.B doDither(A6) ;Should we add in Dither??? <CEL-39>
BEQ.S @noDither ; <CEL-39>
OR.W #$40, (SP) ;Or in the dither bit <CEL-39>
@noDither
IF HAS_COLOR THEN
CLR.L -(SP) ;NO PATTERN FOR NOW
MOVE.L CLIPRGN(A3),-(SP) ;PUSH CLIPRGN HANDLE
MOVE.L VISRGN(A3),-(SP) ;PUSH VISRGN HANDLE
PEA FAKEPTR(A6) ;PUSH FAKE HANDLE
CLR -(SP) ;pass multicolor flag false
_StretchBits ;TRANSFER BUFFER TO SCREEN
ELSE
MOVE.L CLIPRGN(A3),-(SP) ;PUSH CLIPRGN HANDLE
MOVE.L VISRGN(A3),-(SP) ;PUSH VISRGN HANDLE
PEA FAKEPTR(A6) ;PUSH FAKE HANDLE
DC.W $AB27
ENDIF
; if old port, srcOr, draw center part in bic; if bic, in srcOr
; (This is done for compatibility with older applications like MacProject and MacDraw that
; expect to put text on an arbitrary background, relying on the center of the shadow to show.)
TST portBits+rowBytes(A3) ;a new port?
BMI GOHOME
MOVE locMode(A6),D0
CMP #srcOr,D0
BEQ.S @useBic
CMP #srcBic,D0
BNE GOHOME
@useBic
; restored altered srcBits
MOVE.L bufStart(A6),srcBits+baseAddr(A6)
SUB #4,srcBits+bounds+bottom(A6)
; adjust params for center portion StretchBits
CLR.L maskBitsPtr(A6) ;no mask
EOR #2,D0 ;change or to bic, bic to or
MOVE D0,locMode(A6) ;adjust textmode
;
; Push params and call StretchBits to transfer buffer to screen
;
NOSHAD
IF HAS_COLOR THEN
PEA SRCPIX(A6) ;PUSH SRCBITS
MOVE.L maskBitsPtr(A6),-(SP) ;may be 0 if no mask bitmap
ELSE
PEA SRCBITS(A6)
ENDIF ;HAS_COLOR
PEA PORTBITS(A3) ;TRANSFER TO SCREEN
IF Gaudi THEN
TST.B isSpline(A6) ;is it a spline
BEQ @doOld ;skip special stretchbit fix
TST.B repeatBands(A6) ;if not banding then do nothing
BEQ.S @doOld
PEA TEXTR2(A6) ;PUSH DSTRECT = TEXTR2
PEA FAKERGN+RGNBBOX(A6) ;
MOVE #2,-(SP) ;PUSH NRECTS=2
PEA FAKERGN+RGNBBOX(A6) ;Place results in FakRgn
_RSECT ;CALC INTERSECTION
MOVE.L FAKERGN+RGNBBOX(A6), trimSrcRect(A6)
MOVE.L FAKERGN+RGNBBOX+4(A6), trimSrcRect+4(A6)
PEA trimSrcRect(A6) ;Make new source rect for Banding
PEA TEXTR2(A6)
PEA TEXTRECT(A6)
_MAPRECT ;THEN MAPPED FOR SCALING
PEA trimSrcRect(A6) ;Make new source rect for Banding
PEA trimSrcRect(A6) ;maskRect same as source rect
PEA FAKERGN+RGNBBOX(A6) ;Use calculated dst rect
BRA.S @contArgs
ENDIF
@doOld PEA TEXTRECT(A6) ;PUSH SRCRECT = TEXTRECT
IF HAS_COLOR THEN
PEA TEXTRECT(A6) ;maskRect same as source rect
ENDIF ;HAS_COLOR
PEA TEXTR2(A6) ;PUSH DSTRECT = TEXTR2
@contArgs
MOVE locMode(A6),-(SP) ;PUSH TEXTMODE
TST.B doDither(A6) ;Should we add in Dither??? <CEL-39>
BEQ.S @noDither ; <CEL-39>
OR.W #$40, (SP) ;Or in the dither bit <CEL-39>
@noDither
IF HAS_COLOR THEN
CLR.L -(SP) ;NO PATTERN FOR NOW
MOVE.L CLIPRGN(A3),-(SP) ;PUSH CLIPRGN HANDLE
MOVE.L VISRGN(A3),-(SP) ;PUSH VISRGN HANDLE
PEA FAKEPTR(A6) ;PUSH FAKE HANDLE
; <07JUN92 SAH>
; The new way for text. The old multColor is now a bitfield, where bit 0 means that the
; src is Black/White only. multColor is now called drawFlags.
moveq #0,d0 ; clear all flags <08JUN92 SAH>
tst.b colorSource(a6) ; is it in fact color <08JUN92 SAH>
bne.s @setColor ; yes, so set bit color mapped bit <08JUN92 SAH>
moveq #1,d0 ; set b/w src bit <08JUN92 SAH>
bra.s @callStretch ; and draw it <08JUN92 SAH>
@setColor
moveq #2,d0 ; set color mapped bit <08JUN92 SAH>
@callStretch
move.w d0,-(sp) ; push drawFlags <08JUN92 SAH>
_StretchBits ;TRANSFER BUFFER TO SCREEN
ELSE
MOVE.L CLIPRGN(A3),-(SP)
MOVE.L VISRGN(A3),-(SP)
PEA FAKEPTR(A6)
DC.W $AB27
ENDIF
;——————————————————————————————————————————————————————————————————————————————————————————————————————
; We are done so lets cleanup…
;——————————————————————————————————————————————————————————————————————————————————————————————————————
GOHOME
MOVE.L saveStk(A6),SP ;throw away the buffers
IF (hasSplineFonts) OR (Gaudi) THEN ; <31> DTY
TST.B isSpline(A6) ;is it a spline
BEQ @checkBitDivide ;skip spline cleanup
TST.W repeatBands(A6) ;repeat bands left
BEQ @splineClean ;we are done if none
MOVE.L clipStorage(A6), SP ;Save Address on variable for later cleanup
MOVE.W (SP)+, topClip(A6) ;Get new topClip
MOVE.W (SP)+, botClip(A6) ;Get new botClip
MOVE.W origCharCount(A6),D1 ;Re-Assign count
MOVE.W D1,countCopy(A6) ;Re-Assign count
MOVE stackOffset(A6),D0 ;either zero if stack was long aligned, or two if not
MOVE.W D1,count(A6,D0) ;Re-Assign count
MOVE.L SAVEA5(A6),A5 ;RESTORE GLOBAL PTR
MOVE.L grafGlobals(A5),A4 ;set up grafGlobals pointer for getting real width
MOVE.L fontPtr(A4),A4 ;POINT TO FMOUTPUT
MOVE txMode(A3),D0
AND #$FFF7,D0 ;clear pattern bit (let stretch reject invalid modes)
MOVE D0,locMode(A6) ;initialize copy
MOVE.L PENLOC(A6), PNLOC(A3) ;RESTORE PNLOC TO ORIGINAL
IF hasPenFraction THEN
move.l grafGlobals(a5),a0 ; load quickDraw globals.
move.w penLocFixed(a6),pnLocFixed(a0) ; restore fractional pen location.
ENDIF
IF HAS_COLOR THEN
TST PORTBITS+ROWBYTES(A3) ; is it a new port?
BPL.S @useOld3 ; no, no fraction to restore
MOVE PenLocHFrac(A6),pnLocHFrac(A3) ;restore fraction if applicable
@useOld3
MOVE.B saveHilite(A6),HiliteMode ;restore hilite bit
ENDIF
SUBQ.W #1, repeatBands(A6) ;Decrement band count
ADDQ.L #4, clipStorage(A6) ;Bump by a long for next top and Bottom clip
BRA NOTFAST ;Go and band the sucker encore
@splineClean
TST.L stackHandle(A6) ;Does it exist
BEQ.S @cleanUp
MOVE.L stackHandle(A6), A0 ;Get the handle in A0 for dispose routine
_HUnlock ;Unlock the baby
_DisposHandle ;Get rid of memory
BRA.S @cleanUp
ENDIF ;<1.6-11april89-CEL>
@checkBitDivide
MOVE charsRemain(A6),D0
SUB countCopy(A6),D0
MOVE D0,charsRemain(A6) ;if iterative, this will be greater than zero
BGT secondHalf ;so there are more characters to draw
@cleanUp
IF HAS_COLOR THEN
BSET #hiliteBit,HiliteMode ;reset hilite override, in case colormap was skipped
ENDIF
MOVEM.L (SP)+,D0-D7/A1-A4 ;RESTORE REGS
TST.W stackOffset(A6) ;was the stack aligned?
UNLK A6
BEQ.S @skipAlign
ADDQ #2,SP
@skipAlign
IF &SETTING('MACHINE') <> 'MC68000' THEN
RTD #PARAMSIZE ;Return and pop the stack <1.6-11april89-CEL>
ELSE
MOVE.L (SP)+,A0
LEA PARAMSIZE(SP),SP
JMP (A0)
ENDIF
ENDPROC
IF HAS_COLOR THEN
CalcCharExtra PROC EXPORT
ELSE
CalcCharExtra PROC ENTRY
ENDIF
;------------------------------------------
;
; CalcCharExtra, given a 4.12 fixed point in D0 for a 1 point font, scales by the
; actual font point size, and by the scaling numerator and denominator returned by
; the font manager. The scaled extra is returned in 16.16 format in D0. Here the
; charExtra * size is scaled by denom/numer, since stretch will scale the resulting
; widths by numer/denom. Called by StdTxWidth, DrawText, TextMeasure.
;
; FMInNumer.h FOutDenom.h
; charExtra = ——————————— * ——————————— * input charExtra * requested pt. size
; FMInDenom.h FOutNumer.h
fSize EQU $40E ;sorry, no width table offsets in globals (yet)
MOVEM.L D1-D2/A0-A1,-(SP) ;preserve registers
SUB.W #8,SP ;make space on stack for final fixMul and first fixMul
MOVE.L D0,-(SP) ;push input charExtra
MOVE.L WidthPtr,A0 ;point at width table
MOVEQ #0,D0 ;zero high word
MOVE fSize(A0),D0 ;scale up by requested point size
SWAP D0 ;make into a fixed point number
MOVE.L D0,-(SP) ;push requested point size
_FixMul ;product on stack is charExtra * point size
SUB #8,SP ;make room for result of fixRatio and next fixMul
MOVE.W CurFMNumer+H,-(SP) ;push x input numer
MOVE.W CurFMDenom+H,-(SP) ;push x input denom
_FixRatio ;compute ratio input numer/denom
SUBQ #4,SP ;make space for result
MOVE.W FOutDenom+H,-(SP) ;push x output denom
MOVE.W FOutNumer+H,-(SP) ;push x output numer
_FixRatio ;compute ratio output denom/numer
_FixMul ;calculate scale factor
_FixMul ;scale by input charExtra
MOVEM.L (SP)+,D0-D2/A0-A1 ;get result in D0, restore registers
RTS ;home, James
ENDPROC
CASE OFF