mirror of
https://github.com/elliotnunn/supermario.git
synced 2024-11-26 01:49:19 +00:00
5690 lines
256 KiB
Plaintext
5690 lines
256 KiB
Plaintext
;
|
||
; 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 we’re 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 Don’t 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.
|
||
; <SM2> 4/16/92 PN Include the right files for ROM build, BigJSR. Eliminated
|
||
; has_color condition and 68000 condition (SuperMario will always
|
||
; run with colorQD and >68000)
|
||
; <71> 9/27/91 JSM Don’t 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 it’s 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 didn’t 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 PKE’s 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 we’re 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 good’ol 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 pixmap’s 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
|
||
|
||
MACHINE MC68020 ;<PN>
|
||
|
||
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
|
||
|
||
;————————————————————————————————————————————————————————————————————————————————————————————————
|
||
;
|
||
; 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 ‘FONT’s, ‘NFNT’s and new spline font
|
||
; ‘sfnt’s.
|
||
;
|
||
;————————————————————————————————————————————————————————————————————————————————————————————————
|
||
|
||
DrText PROC EXPORT
|
||
|
||
; 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
|
||
|
||
;————————————————————————————————————————————————————————————————————————————————————————————————
|
||
; 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
|
||
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
|
||
|
||
;———————————————————————————————————————————————————
|
||
; 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
|
||
JSR (A0) ;MEASURE TEXT
|
||
|
||
;———————————————————————
|
||
; Set up mask table ptr
|
||
;———————————————————————
|
||
|
||
;——————————————————————
|
||
; 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
|
||
|
||
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
|
||
|
||
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, don’t 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
|
||
MOVE.L 0(A2,D5*4),D0 ;Get offset to glyph in D0
|
||
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
|
||
move.l 0(a0,d0.w*4),d0 ; load glyph record offset
|
||
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
|
||
MOVE.L 0(A2,D3*4),D0 ;Get offset to glyph in D0
|
||
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
|
||
MOVE.W 0(A1,D3*4),D0 ;Get the width
|
||
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
|
||
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
|
||
BTST #5,D0 ;arithmetic mode?
|
||
BEQ.S @doneMode ;if not, don’t map if dest. is 1 bit deep
|
||
CMP #1,dstPix+pixelSize(A6) ;1 bit deep destination?
|
||
BNE.S @doneMode ;if not, arithmetic mode is OK
|
||
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>
|
||
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
|
||
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.
|
||
|
||
TST PORTBITS+ROWBYTES(A3) ; is it a new port?
|
||
BPL.S @useOld1 ; no -> don’t 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
|
||
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
|
||
TST PORTBITS+ROWBYTES(A3) ; is it a new port?
|
||
BPL.S @useOld ; no, don’t bother with fraction
|
||
ADD D1,pnLocHFrac(A3)
|
||
@useOld
|
||
;—————————————————————————————
|
||
; 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
|
||
PEA DSTPIX+BOUNDS(A6) ;PUSH PIXMAP BOUNDS
|
||
MOVE.L CLIPRGN(A3),A0 ;GET CLIPRGN HANDLE
|
||
MOVE.L (A0),A0 ;DE-REFERENCE IT
|
||
PEA RGNBBOX(A0) ;PUSH CLIPRGN BBOX
|
||
MOVE.L VISRGN(A3),A0 ;GET VISRGN HANDLE
|
||
MOVE.L (A0),A0 ;DE-REFERENCE IT
|
||
PEA RGNBBOX(A0) ;PUSH VISRGN BBOX
|
||
MOVE #4,-(SP) ;PUSH NRECTS=4
|
||
PEA MINRECT(A6) ;PUSH DST ADDR
|
||
_RSECT ;CALC INTERSECTION
|
||
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
|
||
MOVE.W #-1, -(SP) ;trim = true for BRUCE
|
||
@no32bit
|
||
_TRIMRECT ;CALL TRIMRECT
|
||
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
|
||
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
|
||
;————————————————————————————————————————————————————————————————————————————————————————————————
|
||
; 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
|
||
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
|
||
|
||
ST FASTFLAG(A6) ;REMEMBER WE'RE GOING FAST
|
||
|
||
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
|
||
;————————————————————————————————————————————————————————————————————————————————————————————————
|
||
;
|
||
; 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
|
||
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
|
||
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
|
||
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
|
||
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
|
||
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
|
||
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
|
||
skipChar
|
||
ADD.L 0(A4,D3*4),D4 ;GET FIXED POINT WIDTH
|
||
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
|
||
MOVE.L 0(A3,D3*4),D0 ;Get offset to glyph in D3
|
||
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
|
||
move.l 0(a6,d0.w*4),d0 ; load glyph record offset
|
||
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
|
||
ADD.L 0(A4,D3*4),D4 ;GET FIXED POINT WIDTH
|
||
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
|
||
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 it’s 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
|
||
;————————————————————————————————————————————————————————————————————————————————————————————————
|
||
; 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
|
||
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
|
||
@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
|
||
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 ;
|
||
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
|
||
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
|
||
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
|
||
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.
|
||
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.
|
||
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
|
||
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
|
||
BTST #5,D0 ;arithmetic mode?
|
||
BEQ.S @skipArith ;if not, don’t map if dest. is 1 bit deep
|
||
CMP #1,dstPix+pixelSize(A6) ;1 bit deep destination?
|
||
BNE.S @multideep ;if not, arithmetic mode is OK
|
||
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
|
||
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
|
||
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>
|
||
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
|
||
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.
|
||
|
||
TST PORTBITS+ROWBYTES(A3) ; is it a new port?
|
||
BPL.S @useOld ; no -> don’t 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
|
||
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
|
||
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
|
||
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
|
||
TST PORTBITS+ROWBYTES(A3) ; is it a new port?
|
||
BPL.S @useOld ; no, don’t bother with fraction
|
||
ADD D1,pnLocHFrac(A3)
|
||
@useOld
|
||
;—————————————————————————————
|
||
; 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
|
||
PEA DSTPIX+BOUNDS(A6) ;PUSH PIXMAP BOUNDS
|
||
MOVE.L CLIPRGN(A3),A0 ;GET CLIPRGN HANDLE
|
||
MOVE.L (A0),A0 ;DE-REFERENCE IT
|
||
PEA RGNBBOX(A0) ;PUSH CLIPRGN BBOX
|
||
MOVE.L VISRGN(A3),A0 ;GET VISRGN HANDLE
|
||
MOVE.L (A0),A0 ;DE-REFERENCE IT
|
||
PEA RGNBBOX(A0) ;PUSH VISRGN BBOX
|
||
MOVE #4,-(SP) ;PUSH NRECTS=4
|
||
PEA MINRECT(A6) ;PUSH DST ADDR
|
||
_RSECT ;CALC INTERSECTION
|
||
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
|
||
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
|
||
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
|
||
MOVE.W #-1, -(SP) ;trim = true for BRUCE
|
||
|
||
_TRIMRECT ;CALL TRIMRECT
|
||
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 has32bitQD THEN ;If 32-bit QD was around always we could do this
|
||
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
|
||
|
||
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
|
||
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
|
||
SUB DSTPIX+BOUNDS+LEFT(A6),D0 ;CONVERT TO GLOBAL
|
||
AND #$FFE0,D0 ;TRUNC TO LONG BOUND
|
||
ADD DSTPIX+BOUNDS+LEFT(A6),D0 ;RETURN TO LOCAL COORDS
|
||
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
|
||
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
|
||
|
||
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.
|
||
;—————————————————————————————————————————————————
|
||
_StackAvail ;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
|
||
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
|
||
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
|
||
_StackAvail ;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
|
||
MOVE.L A4,-(SP) ;save a4 <PN>
|
||
BigJSR GetStyleBufHand,A4 ;Expecting size in D0 <PN>
|
||
MOVE.L (SP)+,A4 ;restore a4 <PN>
|
||
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
|
||
_StripAddress ;Make sure it is the right mode
|
||
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
|
||
MOVE.B HiliteMode,saveHilite(A6) ;save original in case stretch is called multiple times
|
||
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
|
||
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
|
||
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
|
||
MOVE.B HiliteMode,saveHilite(A6) ;save original in case stretch is called multiple times
|
||
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
|
||
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
|
||
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
|
||
MOVE.B saveHilite(A6),HiliteMode ;restore hilite bit
|
||
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 ;don’t 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
|
||
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
|
||
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
|
||
|
||
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
|
||
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
|
||
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)
|
||
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
|
||
LEA 16(A2,D0.L*2),A1 ;GET START OF WIDTH TABLE
|
||
MOVE.L A1,WIDTAB(A6) ;SAVE FOR LATER
|
||
|
||
MOVE MAXCHAR(A2),D0 ;GET MAXCHAR
|
||
MOVE MINCHAR(A2),D1 ;GET MINCHAR
|
||
MOVE D1,MINCH(A6) ;STASH MINCHAR FOR LATER
|
||
SUB D1,D0 ;CALC MAXCHAR-MINCHAR
|
||
MOVE D0,MAXMIN(A6) ;SAVE FOR LATER
|
||
|
||
ADD #3,D0 ;CALC MAXMIN+3
|
||
BTST #1,1(A2) ;DOES FONT HAVE WIDTH TABLE ?
|
||
BEQ.S NOWID ;NO, CONTINUE
|
||
ADD D0,D0 ;SKIP WIDTH TABLE
|
||
NOWID
|
||
LEA 0(A1,D0*2),A0 ;POINT TO HEIGHT TABLE
|
||
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
|
||
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
|
||
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
|
||
MOVE 0(A0,D5*2),D3 ;GET OFFSET AND WIDTH BYTES
|
||
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
|
||
MOVE.L 0(A0,D5*4),D4 ;GET FIXED POINT WIDTH
|
||
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
|
||
|
||
MOVE 0(A0,D5*2),D3 ;GET OFFSET AND WIDTH BYTES
|
||
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
|
||
|
||
MOVE 0(A0,D5*2),D1 ;GET SRCLEFT
|
||
MOVE 2(A0,D5*2),D2 ;GET SRCRIGHT
|
||
|
||
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
|
||
MOVE 0(A0,D5*2),TOPHT(A6) ;get this char's top and height
|
||
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)
|
||
;
|
||
;————————————————————————————————————————————————————————————————————————————————————————————————
|
||
|
||
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
|
||
MOVEM.L SRCROW(A6),A2/A4-A5 ;srcRow, srcAddr (src bitmap), bufStart (dst bitmap) <1.4-4april89-CEL>
|
||
MOVE bitShift(A6),D0 ;get font scale factor
|
||
LSL D0,D1
|
||
LSL D0,D2
|
||
LSL D0,D3 ;scale up all three
|
||
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
|
||
;
|
||
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
|
||
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
|
||
_StripAddress ;Make sure it is the right mode
|
||
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
|
||
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
|
||
@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
|
||
MOVE.L 0(A0,D5*4),D4 ;GET FIXED POINT WIDTH
|
||
|
||
MOVE.L glyphArray(A6), A0 ;Get array of glyphs into A0
|
||
MOVE.L 0(A0,D5*4),D0 ;Get offset to glyph in D3
|
||
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
|
||
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
|
||
@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
|
||
MOVE.L 0(A0,D5*4),D4 ;GET FIXED POINT WIDTH
|
||
;——————————————————————
|
||
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
|
||
_StripAddress ;Make sure it is the right mode
|
||
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
|
||
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
|
||
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
|
||
move.l 0(a2,d0.w*4),d0 ; load glyph record offset
|
||
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
|
||
;————————————————————————————————————————————————————————————————————————————————————————————————
|
||
; 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
|
||
;
|
||
;
|
||
;————————————————————————————————————————————————————————————————————————————————————————————————
|
||
|
||
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
|
||
;
|
||
ENDIF ;hasSplineFonts
|
||
|
||
|
||
|
||
;————————————————————————————————————————————————————————————————————————————————————————————————
|
||
;————————————————————————————————————————————————————————————————————————————————————————————————
|
||
; 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, don’t 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 we’re 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, don’t 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 we’re 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, don’t 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 we’re 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
|
||
;————————————————————————————————————————————————————————————————————————————————————————————————
|
||
|
||
|
||
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
|
||
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
|
||
_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
|
||
LSR #2,D3 ;LONGCNT:=ROWBYTES DIV 4
|
||
SUB #1,D3 ;LONGCOUNT-1 FOR DBRA LOOP
|
||
MOVE sHeight(A6),D6 ;INIT ROW COUNTER
|
||
SUB #1,D6 ;Baseline not slanted <38>
|
||
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
|
||
|
||
MOVE D3,D1 ;INIT LOOP TO LONGCNT
|
||
NXTLONG BFEXTU (A0){D5:0},D0 ;GET A SHIFTED LONG OF SRC
|
||
SUB #4,A0 ;BUMP SRCPTR LEFT ONE LONG
|
||
MOVE.L D0,-(A1) ;STORE IN DST AND BUMP DSTPTR
|
||
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
|
||
MOVE.L DSTPIX+BOUNDS(A6),FAKERGN+RGNBBOX(A6)
|
||
MOVE.L DSTPIX+BOUNDS+4(A6),FAKERGN+RGNBBOX+4(A6)
|
||
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 ;
|
||
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
|
||
|
||
;
|
||
; 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
|
||
MOVE.L maskBitsPtr(A6),-(SP) ;a mask?
|
||
BEQ.S @noMask
|
||
MOVE.L 4(SP),(SP) ;replace mask with copy of source
|
||
@noMask
|
||
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
|
||
PEA SRCRECT(A6) ;maskRect same as source rect
|
||
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
|
||
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
|
||
|
||
; 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
|
||
PEA SRCPIX(A6) ;PUSH SRCBITS
|
||
MOVE.L maskBitsPtr(A6),-(SP) ;may be 0 if no mask bitmap
|
||
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
|
||
PEA TEXTRECT(A6) ;maskRect same as source rect
|
||
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
|
||
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
|
||
|
||
;——————————————————————————————————————————————————————————————————————————————————————————————————————
|
||
; We are done so let’s 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
|
||
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
|
||
|
||
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
|
||
BSET #hiliteBit,HiliteMode ;reset hilite override, in case colormap was skipped
|
||
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
|
||
RTD #PARAMSIZE ;Return and pop the stack <1.6-11april89-CEL>
|
||
ENDPROC
|
||
|
||
CalcCharExtra PROC EXPORT
|
||
|
||
;------------------------------------------
|
||
;
|
||
; 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
|