mac-rom/Toolbox/ScriptMgr/RomanNewJust.a

2782 lines
102 KiB
Plaintext
Raw Normal View History

;
; File: RomanNewJust.a
;
; Contains: New Roman routines for text drawing, measuring, and hit testing with
; justified text.
;
; Written by: PKE Peter Edberg
;
; Copyright: <09> 1990-1992 by Apple Computer, Inc., all rights reserved.
;
; Change History (most recent first):
;
; <SM4> 9/17/92 kc Fix bug in PortChExtra. The rts was missing, and it was falling
; through to the next procedure. This was benign until we added a
; vector to the end of the procedure.
; <24> 7/8/92 HA #1035313 <PKE>: In NChar2Pixel, when we call StdTxMeas, we use
; the fixed value that is returned in field fontAdj field of QD
; globals . This would make NC2P more accurate and consistent with
; measurements returned by NMeasureJust.
; <23> 4/29/92 FM Get rid of conditionals: smgrSys7Extensions
; <22> 4/14/92 PKE #1026778,<yds>: Adapt for ScriptRecord pointer on stack instead
; of selector.
; <21> 10/8/91 PKE For Cube-E (and Bruges): Fix (N)Pixel2Char so that TRUE for
; leadingEdge is always $FF (not sometimes 1); bug #1012676.
; <20> 4/1/91 PKE JDT, #86037, #86038, #86039, #86068, #86074: Force all slop to
; be allocated to spaces, as in 6.x. This is necessary to fix a
; number of bugs having to do with use of the QuickDraw qdChExtra
; field. Some of these bugs are in printing, but we prevent them
; by doing this.
; <19> 2/1/91 PKE JSM,#PKE-Sys-017,#81409,#59217: Fix NPixel2Char to set
; widthRemaining correctly for large pixelWidth values (this
; change marked with <!>). Have (N)MeasureJust use a custom
; txMeasProc if installed, else measure using width table; stop
; using slimy way of passing scaling parameters to MeasureText via
; ExpandMem. Used heuristic to limit negative values of addSpExtra
; and addChExtra so net character widths don<6F>t get negative; had
; to rearrange CalcSpChExtra somewhat to do this. Reduced code
; size by combining InitFontAndFlags and InitScaleFac into
; InitFontAndScale, and have it also compute output scaling.
; <18> 1/19/91 PKE (ngk) Fix remaining end-of-line and scaled text problems in
; (N)Pixel2Char and (N)Char2Pixel (rest of bug #70716). Also fixed
; a problem introduced in <17> that caused some linebreaking
; problems in TE: leadingEdge was not set correctly for widths
; beyond end of text (needed cmp.l, not cmp.w!).
; <17> 1/14/91 PKE (stb, jh) Fix measuring discrepancies in NChar2Pixel and
; NPixel2Char for scaled text. Speed up NPixel2Char by walking
; width tables, fix its handling of end adjustments and make it
; work with R-to-L line direction. Check FOND to see if it
; disallows interchar spacing, and act accordingly. Fixed handling
; of left and right style runs (each behaved like the other
; should). Use PicComment in NDrawJust to make LaserWriter
; printing work correctly if smgrCharPortion value does not match
; LaserWriter default value (1:10). Rearrange internal routines in
; order to do this: add InitFontAndFlags; rename InitJustData as
; InitWeight to better reflect function; split AdjustSpChExtra
; into CalcSpChExtra and DoSpChExtra; add flags to prevent
; redundant computation if CalcSpChExtra is called a second time
; (for LaserWriter layout calculations). Eliminate
; UseCharExtraTrap and ScaleSMgrCharExtra conditionals used with
; earlier versions of this code.
; <16> 9/19/90 PKE Fix bugs with zero-length strings and protect against divide by
; 0.
; <15> 9/1/90 PKE Need to set up JustDataRec scaling parameters even if slop is 0
; (Pixel2Char was having problems cause hScaleTrue was bogus). To
; do this, break out the code that sets scaling parameters into a
; new routine InitScaleFac called by PortionText and
; AdjustSpChExtra. Also, add branches to avoid useless code if
; addChExtra is 0.
; <14> 8/31/90 PKE For NChar2Pixel and NPixel2Char, need to scale DOWN addChExtra
; by numer/denom to make pen moves at beginning and end of run
; accurate. For NDrawJust and NMeasureJust we don<6F>t scale it.
; <13> 8/30/90 PKE Change interaction of scaling, slop, and charExtra to be
; correct: need to scale down qdChExtra and spExtra by numer/denom
; scaling factor.
; <12> 8/24/90 PKE Remove setting of obsolete smgrCharExtra and smgrSlop (in
; SMgrRecord). Use new names qdChExtra and qdRunSlop instead of
; QDSmgrCharExtra and QDSmgrSlop (in GrafGlobals).
; <11> 8/9/90 PKE If grafProcs are installed, DrawJust should call textProc
; instead of StdText! Otherwise printing doesn<73>t work. (Fixes BRC
; #68148).
; <10> 8/8/90 PKE New parameter to AdjustSpChExtra controls whether we scale
; addChExtra (need to for NDrawJust, NMeasureJust). Now we always
; pass real numer and denom to AdjustSpChExtra, and InitJustData
; computes numer.h/denom.h and saves it in JustDataRec. Use
; fractional pen position for pen moves in NDrawJust for increased
; accuracy. These changes fix BRC #70716 and other problems.
; Deleted code that was conditionalized out.
; <9> 8/2/90 PKE Set smgrCharExtra and smgrSlop value in QD private globals. For
; now, continue to set them in SMgrRecord as well.
; <8> 6/8/90 PKE Scale smgrCharExtra by font size instead of scaling it to
; compensate for StretchBits; this way it is scaled like the
; charExtra field in a color port instead of like the output of
; calcCharExtra. Now we no longer need GetScaledFontInfo call in
; AdjustSpChExtra, so move it to DrawJust instead.
; <7> 6/7/90 PKE Moved GetScaledFontInfo to ScriptMgrExtTail.a, made it use as
; much ROM code as possible. Rearranged parameter order for
; GetScaledFontInfo. Implemented guts of num/denom scaling for
; NMeasureJust, which requires setting up new ExpandMem fields
; emNumer and emDenom that will be used by MeasureText.
; <6> 6/6/90 PKE Implement guts of num/denom scaling for NPixel2Char. Add a
; little optimization for num/denom scaling in NChar2Pixel and
; NPixel2Char.
; <5> 6/1/90 PKE Implement guts of num/denom scaling for NPortionText, NDrawJust,
; NChar2Pixel.
; <4> 5/24/90 PKE Add numer/denom scaling parameters to NPortionText, NDrawJust,
; NMeasureJust, NChar2Pixel, and NPixel2Char. For now, these
; parameters are ignored.
; <3> 4/25/90 PKE Use smgrCharExtra for both B&W and color ports, instead of using
; _CharExtra on new ports.
; <2> 4/25/90 PKE Put slop value in smgrSlop global across calls to DrawText,
; MeasureText, TextWidth so it gets saved in pict. Clear it
; afterwards.
; <1> 4/10/90 PKE New today - extracted from ScriptMgrExtTail.a and
; conditionalized so it can be used with ROM builds too.
;
; Relevant recent comments from ScriptMgrExtTail.a below
; <x5> 2/22/90 PKE For 7.0, moved Char2Pixel, DrawJust, MeasureJust here because we
; patch them out entirely for ROM; added these to NewRomanTable so
; their vectors get filled in. Added new InitJustData,
; AdjustSpChExtra, and RestoreSpChExtra utility routines for
; handling justification parameters with intercharacter spacing,
; using new JustDataRec structure. Added other utility routines
; GetFontSize, DrawGap, SignFixRound. Rewrote (N)PortionText,
; (N)DrawJust, (N)MeasureJust, (N)Char2Pixel and (N)Pixel2Char
; routines to fully implement the new justification model, using
; the above utility routines. Also made the <20>N<EFBFBD> versions standard
; for these routines, so that the old interfaces just redo the
; stack and fall through to the new routines.
; <x2> 1/11/90 PKE Moved Roman PortionText and Pixel2Char here so we can fix them
; later for all systems (deal with color grafPorts, etc.) and also
; to reduce duplication of code in new interfaces. We may move
; other Roman routines here later. Added crude implementations of
; some new interfaces: NPortionText, NDrawJust, NMeasureJust,
; NChar2Pixel, and NPixel2Char. These ignore styleRunPosition, but
; otherwise behave as specified. Added code to expand the
; RomanUtil dispatch table if necessary (i.e. for ROM version of
; ScriptMgr) and fill in vectors for PortionText, Pixel2Char, and
; new interfaces listed above. Updated header to be in BBS format.
;___________________________________________________________________________________________________
; To Do:
;
;___________________________________________________________________________________________________
LOAD 'StandardEqu.d'
include 'ScriptPriv.a'
FixMathNonPortable equ 1 ; We require Mac Plus or newer <x5>
include 'FixMath.a' ; <x5>
include 'ColorEqu.a' ; <x5>
blanks on
string asis
FixedPoint5 equ $00008000 ; Fixed 0.5
;UseCharExtraTrap equ 0 ; 0: Always use qdChExtra instead of _CharExtra <3><17>
;ScaleSMgrCharExtra equ 1 ; 1: Scale qdChExtra by font size (& not num/denom) <8><17>
useInterChar equ 0 ; Give up on interchar spacing for now <20>
; (but make minimum changes to do this)
; ----------------------------------------------------------------------- <x2>
; Function PortionText (
; textPtr : Ptr;
; textLen : Longint
; ): Fixed; {proportion}
;
; Find proportion for line of text. This sets up a call to NPortionText with
; styleRunPosition = smOnlyStyleRun, then falls through into NPortionText.
; ----------------------------------------------------------------------------
; ----------------------------------------------------------------------- <x2><4>
; Function NPortionText (
; textPtr: Ptr;
; textLen: Longint;
; styleRunPosition: JustStyleCode; {Integer}
; numer: Point; {Longint}
; denom: Point {Longint}
; ): Fixed; {proportion}
;
; Find proportion for line of text. This now handles intercharacter spacing
; too, using the smgrCharPortion value in the Script Manager globals.
; ----------------------------------------------------------------------------
proc
export PortionText,NPortionText
import InitFontAndScale,InitWeight,StdUnlink ; <17><19>
;ptRecord record {a6link},decr
;result ds.l 1 ; Fixed result
;ptArgs equ *-8 ; size of arguments.
;textPtr ds.l 1 ; text pointer.
;textLen ds.l 1 ; text length (LongInt).
;scriptRecPtr ds.l 1 ; ScriptRecord ptr <22>
;return ds.l 1 ; return address.
;a6link ds.l 1 ; old a6 register.
;ptLocals equ * ; size of local variables.
; endr
nptRecord record {a6link},decr
result ds.l 1 ; Fixed result
nptArgs equ *-8 ; size of arguments.
textPtr ds.l 1 ; text pointer.
textLen ds.l 1 ; text length (LongInt).
stylRunPos ds.w 1 ; style run position code.
numer ds.l 1 ; Point <4>
denom ds.l 1 ; Point <4>
scriptRecPtr ds.l 1 ; ScriptRecord pointer <22>
return ds.l 1 ; return address.
a6link ds.l 1 ; old a6 register.
jdRec ds JustDataRec ;
nptLocals equ * ; size of local variables.
endr
PortionText
move.l (sp)+,a0 ; pop return address
move.l (sp)+,a1 ; pop ScriptRecord ptr <22>
move.w #smOnlyStyleRun,-(sp) ; no info, so assume only style run <x5>
move.l #$00010001,d0 ; no info, assume 1/1 scaling <4>
move.l d0,-(sp) ; push numer <4>
move.l d0,-(sp) ; push denom <4>
move.l a1,-(sp) ; push ScriptRecord ptr <22>
move.l a0,-(sp) ; push return address
; now we are set up for NPortionText
NPortionText
with nptRecord
link a6,#nptLocals ; link the stack.
; Algorithm for Roman was simply to take (#spaces + #otherChars/8) * rawFontSize / 32.
; Now we call InitFontAndScale which tells us if the font allows interchar spacing and <19>
; sets the scaling factors, InitWeight to set weight; then get weight (s*sp+nc*cp) from
; JustDataRec into d2, multiply that by rawFontSize, and scale for compatibility with
; old numbers.
move.l numer(a6),-(sp) ; push numer <17>
move.l denom(a6),-(sp) ; push denom <17>
pea jdRec(a6) ; push ptr to JustDataRec <17>
bsr InitFontAndScale ; check font <17><19>
move.l textPtr(a6),-(sp) ; push textPtr
move.l textLen(a6),-(sp) ; push textLen
move.w stylRunPos(a6),-(sp) ; push styleRunPosition
pea jdRec(a6) ; push ptr to JustDataRec
bsr InitWeight ; Fill out weight <17>
move.l jdRec.weight(a6),d2 ; Get nc*cp+ns*sp in d2
; get raw font size
move.l (a5),a0 ; grafGlobals
move.l thePort(a0),a0 ; get thePort pointer
move.w txSize(a0),d0 ; get size
bne.s @GotRealSize ; ok?
move.w SysFontSize,d0 ; get size
bne.s @GotRealSize ; ok?
move.w #12,d0 ; ok, give up
@GotRealSize
; Now we have font size (integer) in d0.w and ns*sp+nc*cp (Fixed) in d2.l.
; Divide latter by 32 for compatibility with old numbers, then multiply by
; raw font size.
lsr.l #5,d2 ; divide by 32 <x5>
swap d0 ; make font size fixed
clr.w d0 ; and clear frac part
subq #4,sp ; make space for FixMul result <5><10>
move.l d2,-(sp) ; push scaled weight
move.l d0,-(sp) ; push font size as Fixed
_FixMul ; multiply, leave result on stack
; Now multiply it by previous result by numer.h/denom.h if necessary <5><10>
tst.b jdRec.inScalTrue(a6) ; do we have any scaling? <19>
beq.s @doneScaleAdjust ; skip if not
move.l (sp),-(sp) ; first param & space for result
move.l jdRec.inScaling(a6),-(sp) ; second param = numer/denom <19>
_FixMul ; (numer/denom) * (result of above)
@doneScaleAdjust
; set result, unlink the stack and return to the caller.
move.l (sp)+,result(a6) ; set return value
move.w #nptArgs,d0 ; for std exit
bra StdUnlink ; StdUnlink
endWith
endproc
; ----------------------------------------------------------------------- <x5>
; procedure DrawJust(textPtr: Ptr; textLength,slop: Integer);
; input (sp).l Text pointer.
; (sp).w Text length.
; (sp).w Extra pixel width.
; warning This routine builds a stack frame.
; This routine follows Pascal register conventions.
;
; Draw the given text, fully justified. The justification width is the
; original text width plus the slop. This is equivalent to the QuickDraw
; DrawText trap in ROM.
; -----------------------------------------------------------------------
; ----------------------------------------------------------------------- <x2><4>
; PROCEDURE NDrawJust(
; textPtr: Ptr; {long}
; textLength: Longint; {long}
; slop: Fixed; {long}
; styleRunPosition: JustStyleCode; {Integer}
; numer: Point; {Longint}
; denom: Point {Longint}
; );
;
; notes This routine builds a stack frame.
; This routine follows Pascal register conventions.
;
; Draw the given text, fully justified. The justification width is the
; original text width plus the slop.
; -----------------------------------------------------------------------
proc
export DrawJust,NDrawJust
import InitFontAndScale,CalcSpChExtra,DoSpChExtra,RestoreSpChExtra ; <17><19>
import SignFixRound,StdUnlink
import GetScaledFontInfo ; <8>
import GetFontSize ; <17>
;djRecord record {a6link},decr
;djArgs equ *-8 ; size of arguments.
;textPtr ds.l 1 ; text pointer.
;textLen ds.w 1 ; text length.
;slop ds.w 1 ; extra pixel width.
;scriptRecPtr ds.l 1 ; ScriptRecord ptr <22>
;return ds.l 1 ; return address.
;a6link ds.l 1 ; old a6 register.
;djLocals equ * ; size of local variables.
; endr
ndjRecord record {a6link},decr
ndjArgs equ *-8 ; size of arguments.
textPtr ds.l 1 ; text pointer.
textLen ds.l 1 ; text length (LongInt).
slop ds.l 1 ; extra pixel width (Fixed).
stylRunPos ds.w 1 ; style run position code.
numer ds.l 1 ; Point <4>
denom ds.l 1 ; Point <4>
scriptRecPtr ds.l 1 ; ScriptRecord pointer <22>
return ds.l 1 ; return address.
a6link ds.l 1 ; old a6 register.
jdRec ds JustDataRec ; local record
fntInfo ds.w 4 ; FontInfo record <17>
numerVar ds.l 1 ; For StdTxMeas <17>
denomVar ds.l 1 ; For StdTxMeas <17>
portSpExScal ds.l 1 ; Fixed, port's sp extra, scaled by numer/denom <17>
portChExScal ds.l 1 ; Fixed, port's ch extra, scaled by numer/denom <17>
portSpEx1pt ds.l 1 ; Fixed, port's sp extra, scaled to 1 pt <17>
portChEx1pt ds.l 1 ; Fixed, port's ch extra, scaled to 1 pt <17>
jdRecLaser ds JustDataRec ; local record for LaserWriter stuff
ndjLocals equ * ; size of local variables.
endr
ndjRegs reg a2/d3 ; <17>
DrawJust
move.l (sp)+,a0 ; pop 'n save return addr
move.l (sp)+,a1 ; pop ScriptRecord ptr <22>
move.w (sp)+,d0 ; pop slop
clr.w -(sp) ; zero-extend textLen on stack to long <22>
swap d0 ; make slop a Fixed<65>
clr.w d0 ; clear frac part<72>
move.l d0,-(sp) ; push slop as Fixed
move.w #smOnlyStyleRun,-(sp) ; default styleRunPosition
move.l #$00010001,d0 ; no info, assume 1/1 scaling <4>
move.l d0,-(sp) ; push numer <4>
move.l d0,-(sp) ; push denom <4>
move.l a1,-(sp) ; push ScriptRecord ptr <22>
move.l a0,-(sp) ; restore return address
; Now we are set up like NDrawJust, so just fall through
NDrawJust
; Link the stack and set the drawing params in thePort to correctly fill
; justify the text.
with ndjRecord
link a6,#ndjLocals ; link the stack.
movem.l ndjRegs,-(sp) ; save regs <17>
; set the drawing params
move.l numer(a6),-(sp) ; push numer <17>
move.l denom(a6),-(sp) ; push denom <17>
pea jdRec(a6) ; push ptr to JustDataRec <17>
bsr InitFontAndScale ; check font <17><19>
move.l textPtr(a6),-(sp) ; push text pointer.
move.l textLen(a6),-(sp) ; push text length.
move.l slop(a6),-(sp) ; push slop.
move.w stylRunPos(a6),-(sp) ; push styleRunPosition
move.l numer(a6),-(sp) ; push numer <5>
move.l denom(a6),-(sp) ; push denom <5>
pea jdRec(a6) ; push local JustDatRec addr
bsr CalcSpChExtra ; calculate drawing params <17>
; Handle initial forward pen motion
IF useInterChar THEN ; <20>
tst.l jdRec.addChExtra(a6) ; any add<64>l CharExtra? <15>
beq.s @doneStartMove ; if not, skip this <15>
tst.b jdRec.startNoFwd(a6) ; do we move at beginning
bne.s @doneStartMove ; if TRUE, we don't get add<64>l CharExtra
; Fill out FontInfo Record to get scaled ascent, descent for DrawGap.
pea fntInfo(a6) ; push address of FontInfo rec (VAR param) <7><8><17>
move.l numer(a6),-(sp) ; push numer <5><7>
move.l denom(a6),-(sp) ; push denom <5><7>
bsr GetScaledFontInfo ; handles scaling params too <5>
move.l jdRec.addChExtra(a6),d0 ; additional CharExtra
asr.l #1,d0 ; divide by 2 (signed!)
move.l d0,-(sp) ; push size of move
pea fntInfo(a6) ; push addr of FontInfo rec <17>
bsr DrawGap
@doneStartMove
ENDIF ; <20>
IF useInterChar THEN ; <20>
; Set LaserWriter line layout params (new section). <17>
; Do this either if a pic is open, or if we are drawing to a printer.
; Skip if slop is 0 or font disallows interchar (because LaserWriter is ok for these).
tst.l slop(a6)
beq @donePrinterSetup
tst.b jdRec.noInterCh(a6)
bne @donePrinterSetup
move.l grafGlobals(a5),a0 ; Point to QuickDraw globals
move.l thePort(a0),a0 ; Get current grafport
tst.l picSave(a0) ; Is a picture open?
bne.s @doPrinterSetup ; If so, must do nasty LaserWriter stuff
tst.l grafProcs(a0) ; Do we have grafProcs?
beq @donePrinterSetup ; If not, we can't be printing, <20>
; <20> so skip nasty LaserWriter stuff
; Maybe we can add a better test to see if this is a printing port.
; Note that device field may be 0 even if we are printing.
; We could also check PrintVars to see if it is a LaserWriter<65>
@doPrinterSetup
; Get port's spExtra and chExtra (16.16 Fixed, 1 pt and real sizes).
move.l grafGlobals(a5),a0 ; find the QuickDraw globals.
move.l thePort(a0),a0 ; get thePort pointer
bsr GetFontSize ; assume thePort^ in a0, get font size in d0.w
swap d0 ; make Fixed
clr.w d0 ; clear frac part
move.l d0,d3 ; save in d3
move.l a0,a2 ; save thePort ptr
clr.l portSpEx1pt(a6) ; initialize
move.l spExtra(a2),d1 ; get port's spExtra for txSize
move.l d1,portSpExScal(a6) ; first assume no scaling
beq.s @donePortSpExtra
subq #4,sp ; space for result
move.l d1,-(sp)
move.l d3,-(sp)
_FixDiv
move.l (sp)+,portSpEx1pt(a6) ; get spExtra for 1 pt
tst.b jdRec.inScalTrue(a6) ; do we have any scaling? <19>
beq.s @donePortSpExtra ; skip if not
subq #4,sp ; space for result
move.l spExtra(a2),-(sp) ; unscaled spExtra
move.l jdRec.inScaling(a6),-(sp) ; second param = numer/denom <19>
_FixDiv
move.l (sp)+,portSpExScal(a6) ; now we have scaled version
@donePortSpExtra
clr.l portChEx1pt(a6) ; assume port has no chExtra
clr.l portChExScal(a6) ;
tst.w portVersion(a2) ; negative if cGrafPort
bpl.s @donePortChExtra ; otherwise, get port's chExtra
move.w chExtra(a2),d1 ; get 4.12 fixed format
beq.s @donePortChExtra ; if 0, we are done
ext.l d1 ; extend sign bits
asl.l #4,d1 ; convert to 16.16 format.
move.l d1,portChEx1pt(a6) ; save port's chExtra for 1 pt
subq #4,sp ; space for result
move.l d1,-(sp) ; push chExtra for 1-point size
move.l d3,-(sp) ; push size
_FixMul ; unscaled size on stack
tst.b jdRec.inScalTrue(a6) ; do we have any scaling? <19>
beq.s @stuffChExtra ; skip if not
move.l (sp),-(sp) ; result space and first param
move.l jdRec.inScaling(a6),-(sp) ; second param = numer/denom <19>
_FixDiv
@stuffChExtra
move.l (sp)+,portChExScal(a6) ; get real chExtra for our size
@donePortChExtra
; Get LaserWriter width without slop (using FOND or TrueType metrics).
; Must be before DoSpChExtra.
subq #4,sp ; space for result
move.l textPtr(a6),-(sp) ; push text pointer.
move.l textLen(a6),-(sp) ; push text length.
move.l numer(a6),-(sp) ; push numer
move.l denom(a6),-(sp) ; push denom
move.l portSpEx1pt(a6),-(sp) ; push port spExtra for 1 pt
move.l portChEx1pt(a6),-(sp) ; push port chExtra for 1 pt
pea jdRec(a6) ; push local JustDatRec addr for scaling
bsr LaserWidth ; Fixed width on stack
; Get the screen width without slop.
; Must be before DoSpChExtra.
move.l numer(a6),numerVar(a6)
move.l denom(a6),denomVar(a6)
subq #2,sp ; make room for result
move.w textLen+2(a6),-(sp) ; push byte count
move.l textPtr(a6),-(sp) ; push the text pointer.
pea numerVar(a6) ; VAR numer in
pea denomVar(a6) ; VAR denom in
pea fntInfo(a6) ; VAR info
move.l grafGlobals(a5),a0 ; Point to QuickDraw globals
move.l thePort(a0),a0 ; Get current grafport
move.l grafProcs(a0),d0 ; Is grafprocs NIL?
beq.s @useMeasTrap ; Yes, use std proc
move.l d0,a0 ;
move.l txMeasProc(a0),a0 ; No, get proc ptr
jsr (a0) ; Go to it
bra.s @doneTxMeas ; Measure text with txMeas grafProc
@useMeasTrap ;
_StdTxMeas ; Measure text with std proc
@doneTxMeas ;
move.w (sp)+,d0 ; get integer width
swap d0 ; make it fixed
clr.w d0 ; clear frac part to get screen width
move.w numerVar+h(a6),d1 ; get output numer
move.w denomVar+h(a6),d2 ; get output denom
cmp.w d1,d2 ; same?
beq.s @doneScaleAdjust ; if so, skip adjust
subq #4,sp ; space for FixMul result
move.l d0,-(sp) ; first FixMul param
subq #4,sp ; space for FixRatio result = second FixMul param
move.w d1,-(sp) ; push output numer.h, first FixRatio paramm move.w d2,-(sp) ; push output denom.h, second FixRatio param
_FixRatio ; divide
_FixMul ; multiply
move.l (sp)+,d0 ; get scaled width
@doneScaleAdjust
; Find total desired width of line
add.l slop(a6),d0 ; desired width of line
move.l d0,d3 ; save in d3 for underline length
; do we need to calculate new extra values?
lea jdRec(a6),a2 ; use screen spExtra, chExtra
tst.l (sp) ; valid printer width?
bpl.s @calcNewExtra ; if so, continue normally
addq #4,sp ; otherwise, discard width
bra @setupPicComment ; ready for PicComment
; Copy JustDataRec for printer layout
@calcNewExtra
with JustDataRec
lea jdRecLaser(a6),a1 ; ptr to dest record
move.w #(jdRecSize/4),d1 ; jdRecSize guaranteed to be multiple of 4
bra.s @endCopyLoop
@copyLoop
move.l (a2)+,(a1)+
@endCopyLoop
dbra d1,@copyLoop
; compute new SpExtra and ChExtra for LaserWriter
; at this point, printer width is on stack, total desired width is in d0
sub.l (sp)+,d0 ; subtract LaserWriter width to get its slop
move.l textPtr(a6),-(sp) ; push text pointer.
move.l textLen(a6),-(sp) ; push text length.
move.l d0,-(sp) ; push slop.
move.w stylRunPos(a6),-(sp) ; push styleRunPosition
move.l numer(a6),-(sp) ; push numer
move.l denom(a6),-(sp) ; push denom
pea jdRecLaser(a6) ; push local JustDatRec addr
bsr CalcSpChExtra ; calculate drawing params
lea jdRecLaser(a6),a2 ; use printer spExtra, chExtra
; Compute major (spExtra) and minor (chExtra) for the PicComment.
; - Note that minor applies to all characters, incl space, so we
; must subtract our minor value from the major value.
; - Also note that we must account for any spExtra or chExtra in
; the port too.
; Assume that a2 points to JustDataRec to use
;
; Need to scale down underline len by input numer/denom.
@setupPicComment
tst.b inScalTrue(a2) ; do we have any scaling? <19>
beq.s @doneScaleUL ; skip if not
subq #4,sp ; space for result
move.l d3,-(sp) ; underline length
move.l inScaling(a2),-(sp) ; second param = numer/denom <19>
_FixDiv
move.l (sp)+,d3
@doneScaleUL
move.l portSpExScal(a6),d2 ; get port's spExtra
add.l addSpExScal(a2),d2 ; get total spExtra
move.l portChExScal(a6),d1 ; get port's chExtra
add.l addChExScal(a2),d1 ; get total chExtra
sub.l d1,d2 ; subtract chExtra from spExtra
endwith ;JustDataRec
; Get ClientLLRecord handle from SMgr globals
with ClientLLRecord,SMgrRecord
move.l IntlSpec,a0
move.l smgrClientLLRecHndl(a0),d0 ; get reusable handle
beq.s @donePrinterSetup ; bail if it's not there
move.l d0,a0 ; put handle in a0
; Fill out ClientLLRecord
move.l (a0),a1
move.w textLen+2(a6),chCount(a1)
move.l d2,major(a1)
move.w #$20,spChar(a1)
move.l d1,minor(a1)
move.l d3,ulLength(a1)
; ok, now make the comment
move.w #clientLLComment,-(sp)
move.w #cllRecSize,-(sp)
move.l a0,-(sp) ; handle to ClientLLRecord
_PicComment
endwith ;ClientLLRecord,SMgrRecord
@donePrinterSetup
ENDIF ; <20>
; Setup spacing params. Do this after printer setup, so it doesn't affect <17>
; StdTxMeas in that code.
pea jdRec(a6) ; push local JustDatRec addr <17>
bsr DoSpChExtra ; set drawing params <17>
; Draw the text - change to use StdText (or text grafProc if present) <5>
move.w textLen+2(a6),-(sp) ; push text length as word.
move.l textPtr(a6),-(sp) ; push text pointer.
move.l numer(a6),-(sp) ; push numer <5>
move.l denom(a6),-(sp) ; push denom <5>
move.l grafGlobals(a5),a0 ; Point to QuickDraw globals <11>
move.l thePort(a0),a0 ; Get current grafport <11>
move.l grafProcs(a0),d0 ; Is grafprocs NIL? <11>
beq.s @useTrap ; Yes, use std proc <11>
move.l d0,a0 ; <11>
move.l textProc(a0),a0 ; No, get proc ptr <11>
jsr (a0) ; Go to it <11>
bra.s @doneDrawText ; Draw text with text grafProc <11>
@useTrap ; <11>
_StdText ; Draw text with std proc
@doneDrawText ; <11>
; Restore drawing params (RestoreSpChExtra doesn't modify jdRec)
pea jdRec(a6) ; push local JustDataRec addr
bsr RestoreSpChExtra
; Handle final pen motion <check rounding of negative number>
IF useInterChar THEN ; <20>
move.l jdRec.addChExtra(a6),d0 ; get charExtra
beq.s @doneEndMove ; if 0, no move necessary <15>
tst.b jdRec.endBackup(a6) ;
bne.s @doneCalcEndMove ; if TRUE, we don't divide by 2
asr.l #1,d0 ; divide by 2 (signed!)
@doneCalcEndMove
neg.l d0 ; negate <10>
bsr MovePen ; move pen, preserving fractional info <10>
@doneEndMove ; <15>
ENDIF ; <20>
; Unlink the stack and return to the caller.
movem.l (sp)+,ndjRegs ; restore regs <17>
move.w #ndjArgs,d0 ; for std exit
bra StdUnlink ; StdUnlink
endWith
IF useInterChar THEN ; <20>
; ----------------------------------------------------------------------------- <x5>
; PROCEDURE DrawGap(gapSize: Fixed; info: FontInfo);
;
; This will draw a rect simulating a blank intercharacter text area, using
; current text characteristics, beginning at the current position and continuing
; for gapSize pixels, moving the pen gapSize pixels horizontally from its original
; location.
;
; This is a first pass without any optimization, which it needs.
; We could also use horiz pen fraction for more accurate computation of the
; gapRect.
; -----------------------------------------------------------------------------
; export DrawGap ; comment out <17>
; import SignFixRound,StdUnlink ; comment out <17>
dgRecord record {a6link},decr
dgArgs equ *-8 ; size of arguments.
gapSize ds.l 1 ; gapSize value (Fixed)
infoPtr ds.l 1 ; ptr to filled FontInfo record
return ds.l 1 ; return address.
a6link ds.l 1 ; old a6 register.
gapRect ds.w 4 ; Rect - rect for gap
saveMode ds.w 1 ; saved pnMode
savePat ds.b 8 ; Pattern - saved pnPat or pnPixPat
dgLocals equ * ; size of local variables.
endr
DrawGap
with dgRecord
link a6,#dgLocals ; link the stack.
move.l a2,-(sp) ; save reg
move.l grafGlobals(a5),a0 ; find the QuickDraw globals.
move.l thePort(a0),a2 ; save thePort pointer
move.l infoPtr(a6),a1 ; a1 points to FontInfo record
move.w pnLoc+v(a2),d0 ; current v
move.w d0,d1 ; copy
sub.w ascent(a1),d0 ; top of rect = v-ascent
move.w d0,gapRect+top(a6) ; stuff it
add.w descent(a1),d1 ; bottom of rect = v+descent
move.w d1,gapRect+bottom(a6) ; stuff it
move.w pnLoc+h(a2),d1 ; current h
move.l gapSize(a6),d0 ; get gap as Fixed (signed!)
bsr SignFixRound ; round it
bpl.s @posGap
; gap is negative
move.w d1,gapRect+right(a6) ; right side of rect = h
add.w d0,d1 ; left side of rect = h+gap
move.w d1,gapRect+left(a6) ; stuff it
bra.s @doneSetGap
; gap is positive
@posGap
move.w d1,gapRect+left(a6) ; left side of rect = h
add.w d0,d1 ; right side of rect = h+gap
move.w d1,gapRect+right(a6) ; stuff it
@doneSetGap
; save pnMode, then set it from txMode
move.w pnMode(a2),saveMode(a6) ; save pnMode
move.w txMode(a2),pnMode(a2) ; set pnMode from txMode
; next we have to save the pnPat/pnPixPat, set it from the background, call
; PaintRect, then restore the pnPat/pmPixPat. How we do this depends on
; what kind of port it is. We can't just use _EraseRect, because it ignores
; the pnMode but we care about the pnMode.
tst.w portVersion(a2) ; negative if cGrafPort
bmi.s @colorPort ;
; draw rect in old-style port - save pnPat, set it from bkPat,
; draw rect, restore pnPat.
move.l pnPat(a2),savePat(a6) ; save pnPat
move.l pnPat+4(a2),savePat+4(a6) ; "
move.l bkPat(a2),pnPat(a2) ; set pnPat from bkPat
move.l bkPat+4(a2),pnPat+4(a2) ; "
pea gapRect(a6) ; push rect
_PaintRect
move.l savePat(a6),pnPat(a2) ; restore pnPat
move.l savePat+4(a6),pnPat+4(a2) ; "
bra.s @restorePnMode
; draw rect in color port - save pnPixPat, set it from bkPixPat,
; draw rect, restore pnPixPat.
@colorPort
move.l pnPixPat(a2),savePat(a6) ; save pnPixPat
move.l bkPixPat(a2),pnPixPat(a2) ; set pnPixPat from bkPixPat
pea gapRect(a6) ; push rect
_PaintRect
move.l savePat(a6),pnPixPat(a2) ; restore pnPixPat
; Now restore pnMode
@restorePnMode
move.w saveMode(a6),pnMode(a2) ; restore pnMode
; Now move pen to end of this gap
move.l gapSize(a6),d0 ; get h increment <10>
bsr MovePen ; move pen, preserving fractional info <10>
; all done, return
move.l (sp)+,a2 ; restore reg
move.w #dgArgs,d0 ; for std exit
bra StdUnlink ; StdUnlink
endWith
ENDIF ; <20>
; ----------------------------------------------------------------------------- <10>
; routine: MovePen
; input: d0.l Signed Fixed: horizontal increment for pen movement
;
; Moves pen by setting both integer and fractional parts of horizontal pen
; position.
;
; Trashes a0, a1, d1
; -----------------------------------------------------------------------------
MovePen
move.l grafGlobals(a5),a0 ; find the QuickDraw globals.
move.l thePort(a0),a1 ; save thePort pointer
move.w pnLoc+h(a1),d1 ; get integer part of current pos
swap d1 ; put in Fixed format
tst.w portVersion(a1) ; negative if cGrafPort
bpl.s @notColorPort ;
; for color port
move.w pnLocHFrac(a1),d1 ; get frac part of current pos
add.l d0,d1 ; add pen increment
move.w d1,pnLocHFrac(a1) ; save frac part of new pos
bra.s @common
; for old ports
@notColorPort
move.w pnLocFixed(a0),d1 ; get frac part of current pos
add.l d0,d1 ; add pen increment
move.w d1,pnLocFixed(a0) ; save frac part of new pos
; common finish
@common
swap d1 ; get integer part of new pos
move.w d1,pnLoc+h(a1) ; and save it
rts
IF useInterChar THEN ; <20>
; ----------------------------------------------------------------------------- <17>
; FUNCTION LaserWidth(
; textPtr: Ptr;
; textLen: Long;
; numer: Point;
; denom: Point;
; portSpEx1pt: Fixed;
; portChEx1pt: Fixed;
; jdRecPtr: ^JustDataRec
; ): Fixed;
;
; Returns Fixed width of text computed from metrics that the LaserWriter
; driver will use, including scaling factors obtained from the JustDataRec.
;
; Returns neg value if bitmap font but no FOND or FOND width table.
;
; For more information on what this routine should really be trying to do, see
; the following routines in the LaserWriter sources (thanks, Hugo):
; 1. SetPrWidTab (in the file LpMisc68k.a), which fills out a table of
; printer widths.
; 2. ChangeFont (in the file LpDraft.p), which calls SetPrWidTab.
; The file LpMisc68k.a also has the LaserWriter line layout code.
;
; It would be nice to pre-allocate ThPrWidthTable with pointer in SMgrRecord
; and cache widths for a particular font/style/etc, so we don't recalculate them
; if current request matches last request. However, we have no way to know if
; the width tables used for printing have been changed (we can't get driver's
; value of modFlag in their ThPrWidthTable), so we just recalculate them each
; time. Sigh.
;
; The potSpEx1pt and portChEx1pt values are the spExtra and chExtra values from
; from the port, scaled to 1 pt.
; -----------------------------------------------------------------------------
lwRecord record {a6link},decr
result ds.l 1 ; result: Fixed width
lwArgs equ *-8 ; size of arguments.
textPtr ds.l 1 ; text pointer.
textLen ds.l 1 ; text length.
numer ds.l 1 ; Point
denom ds.l 1 ; Point
portSpEx1pt ds.l 1 ; Fixed
portChEx1pt ds.l 1 ; Fixed
jdRecPtr ds.l 1 ; pointer to JustDataRec
return ds.l 1 ; return address.
a6link ds.l 1 ; old a6 register.
myPrWidTab ds ThPrWidthTable ;
lwLocals equ * ; size of local variables.
endr
lwRegs reg a2/d3-d7
SB_FILLPRINTER_WIDTHS EQU $0003
_SplineCall OPWORD $A854
LaserWidth
with lwRecord,JustDataRec
link a6,#lwLocals ; link the stack.
movem.l lwRegs,-(sp) ; save regs
move.l #-1,result(a6) ; initially assume can't get widths
; Do we have a TrueType font for this?
clr.w -(sp) ; room for current status
_GetOutlinePreferred ; leave result on stack
move.w #-1,-(sp) ; pass TRUE<55>
_SetOutlinePreferred ; we want an outline if possible
clr.w -(sp) ; room for Boolean result
move.l numer(a6),-(sp) ; push numer
move.l denom(a6),-(sp) ; push denom
_IsOutline ; Note: this calls FMWwapFont with needbits=T
tst.w (sp)+ ; use a TrueType font?
bne @getOutlineWidths ; if so, get a different width table
; Get widths from table in FOND
move.l LastFOND,d0 ; Do we have a FOND handle?
beq @cleanup ; bail if not
move.l d0,a0
move.l (a0),a0 ; Get FOND pointer
move.l ffWTabOff(a0),d0 ; Get offset to width table
beq @cleanup ; bail if no table
; initialize local table
move.w #255,d1
lea myPrWidTab.theTable(a6),a1
@clearLoop clr.l (a1)+
dbra d1,@clearLoop
; set up params to search for width table that is best match for style
move.w ffFirst(a0),d6 ; get first char in table
move.w ffLast(a0),d7 ; get last char in table
lea 0(a0,d0.l),a0 ; point to FOND width table
move.l grafGlobals(a5),a1 ; grafGlobals
move.l thePort(a1),a1 ; get thePort pointer
moveq #0,d3 ; for longizing
move.b txFace(a1),d3 ; get style
; search for width table. This code is almost exactly copied from SetPrWidTab.
move.w (a0)+,d5 ; counter
move.l d3,d4 ; initialize remainder
move.l a0,a2 ; initial table choice
move.w d7,a1 ; get to width tables
sub.w d6,a1 ; by LastChar-FirstChar
addq.w #4,a1 ; +3 for missing etc and +1 for style entry
add.l a1,a1 ; two bytes per entry
bra.s @4
@3
add.l a1,a0 ; next width table
move.w (a0),d2 ; get this width table style
jsr MatchStyles ; return with match (a0,a1 preserved)
beq.s @4 ; if zero, its no better than current match
move.l a0,a2 ; found better match so take this table
@4
dbra d5,@3 ; update count
; now a2 points to table in FOND (begins with style code). Copy it into printer
; width table, expanding from 4.12 to 16.16. This code is almost exactly copied
; from SetPrWidTab.
addq.w #2,a2 ; skip style entry
lsl.w #2,d6 ; 4 bytes per entry
lea myPrWidTab.theTable(a6),a0
add.w d6,a0 ; skip to FirstChar in printer width table
@5
move.w (a2)+,d0 ; get width entry
ext.l d0 ; make full longword
asl.l #4,d0 ; make into fixed point format from 4.12 format
move.l d0,(a0)+ ; put down this value
subq.w #1,d7 ; loop count LastChar
cmp.w d7,d6 ; compare with FirstChar
ble.s @5 ; continue till end of table
; now printer width table is set up, go measure text
bra @addWidths
; Get width table for outlines, using private Bass call.
@getOutlineWidths
move.l FOutFontHandle,a2 ; handle to 'sfnt' resource
move.l a2,a0
_HGetState
move.w d0,-(sp) ; save state
move.l a2,a0
_HLock
clr.l -(sp) ; room for result code
pea myPrWidTab.theTable(a6) ; width table ptr
move.l a2,-(sp) ; sfnt handle
moveq #SB_FILLPRINTER_WIDTHS,d0 ; selector for our call, needs to be a long
_SplineCall ; get printer widths
move.l (sp)+,d2 ; get result of call
move.l a2,a0
move.w (sp)+,d0 ; get saved state
_HSetState ; restore it
tst.l d2 ; success?
bne @cleanup ; if not, bail
; Now add up widths
@addWidths
moveq #0,d0 ; initialize width
move.l textPtr(a6),a0
move.l textLen(a6),d1
move.l portSpEx1pt(a6),d4
move.l portChEx1pt(a6),d5
lea myPrWidTab.theTable(a6),a1
moveq #0,d2 ; for longizing char
bra.s @endWidthLoop
@widthLoop
move.b (a0)+,d2
move.l d2,d3
lsl.w #2,d3 ; make a long offset
add.l 0(a1,d3.w),d0 ; add in width
cmp.b #$20,d2
bne.s @addChExtra
add.l d4,d0 ; add in spExtra
bra.s @endWidthLoop
@addChExtra
add.l d5,d0 ; add in chExtra
@endWidthLoop
dbra d1,@widthLoop
; Now we have Fixed width in d0, need to scale it by font size and numer.h/denom.h
subq #4,sp
move.l d0,-(sp) ; push 1-point width
move.l grafGlobals(a5),a0 ; find the QuickDraw globals.
move.l thePort(a0),a0 ; get thePort pointer
bsr GetFontSize ; assume thePort^ in a0, get font size in d0.w
swap d0 ; make Fixed
clr.w d0 ; clear frac part
move.l d0,-(sp) ; push font size
_FixMul ; leave result on stack
move.l jdRecPtr(a6),a0 ; get JustDataRec ptr
tst.b inScalTrue(a0) ; do we have any scaling? <19>
beq.s @doneScale ; skip if not
move.l (sp),-(sp) ; result space and first FixMul param
move.l inScaling(a0),-(sp) ; second param = numer/denom <19>
_FixMul
@doneScale
move.l (sp)+,result(a6) ; get Fixed result
; All done, return
@cleanup
_SetOutlinePreferred ; restore outline pref status
movem.l (sp)+,lwRegs ; restore regs
move.w #lwArgs,d0 ; for std exit
bra StdUnlink ; StdUnlink
endWith ;lwRecord,JustDataRec
;------------------------------------------------------------------------------- <17>
; MatchStyles (exactly copied from SetPrWidTab)
;
; d2 Current
; d3 Desired
; d4 Remainder (may be updated)
;
; Result in cc: eq if we did not find a better match, ne if we did
;
; The Current input is compared against Desired and Remainder parameters.
; If Current is closer to Desired than Remainder, then Remainder is updated.
; Remainder should be initialized to Desired.
;
; This Function can be called continuously over the entire range of styles
; being checked. Before each call only set the value for Current.
; The values for Current should be set in order from default to least likely.
; After the full range has been parsed, then the closest style
; match is given by = Desired-Remainder (i.e. Desired<65><64>Remainder)
;
; Uses d0,d1
;-------------------------------------------------------------------------------
MatchStyles
move.w d2,d0 ; get Current
move.w d3,d1 ; get Desired
not.w d1 ; <20>Desired
and.w d0,d1 ; Current<6E><74>Desired (Current-Desired)
bne.s @1 ; Perfect match if equal to zero
not.w d0 ; <20>Current
and.w d3,d0 ; Desired<65><64>Current (Desired-Current)
move.w d0,d1 ; Save potential new Remainder
not.w d0 ; <20>NewRemainder
and.w d4,d0 ; Remainder<65><72>NewRemainder (Remainder-NewRemainder)
beq.s @1 ; Check New against Old for better
move.w d1,d4 ; we found a better match
moveq #-1,d0 ; return result in d0
@2
rts ; go home
@1
moveq #0,d0 ; return results in d0
bra.s @2
endproc
ENDIF ; <20>
; ----------------------------------------------------------------------- <x5>
; procedure MeasureJust(textPtr: Ptr; textLength,slop: Integer;
; charLocs: Ptr);
; input (sp).l Text pointer.
; (sp).w Text length.
; (sp).w Extra pixel width.
; (sp).l Character location array pointer.
; warning This routine builds a stack frame.
; This routine follows Pascal register conventions.
;
; Measure the given text, fully justified. The cumulative width of each
; character is left in the charLocs array. This is equivalent to the
; QuickDraw MeasureText trap in new ROMs.
; -----------------------------------------------------------------------
; ----------------------------------------------------------------------- <x2><4>
; procedure NMeasureJust(
; textPtr: Ptr;
; textLen: LongInt;
; slop: Fixed;
; charLocs: Ptr;
; styleRunPosition: JustStyleCode; {Integer}
; numer: Point; {Longint}
; denom: Point {Longint}
; );
;
; notes This routine builds a stack frame.
; This routine follows Pascal register conventions.
;
; Measure the given text, fully justified. The cumulative width of each
; character is left in the charLocs array.
;
; At the moment, this just converts the parameters to MeasureJust format
; and then calls MeasureJust.
; -----------------------------------------------------------------------
proc
export MeasureJust,NMeasureJust
import InitFontAndScale,CalcSpChExtra,DoSpChExtra,RestoreSpChExtra ; <17><19>
import SignFixRound,StdUnlink
import GetMeasProc,DoSwapFont,GetPortChExtra ; <19>
;mjRecord record {a6link},decr
;mjArgs equ *-8 ; size of arguments.
;textPtr ds.l 1 ; text pointer.
;textLen ds.w 1 ; text length.
;slop ds.w 1 ; extra pixel width.
;charLocs ds.l 1 ; character location array.
;scriptRecPtr ds.l 1 ; ScriptRecord ptr <22>
;return ds.l 1 ; return address.
;a6link ds.l 1 ; old a6 register.
;mjLocals equ * ; size of local variables.
; endr
nmjRecord record {a6link},decr
nmjArgs equ *-8 ; size of arguments.
textPtr ds.l 1 ; text pointer.
textLen ds.l 1 ; text length (LongInt).
slop ds.l 1 ; extra pixel width (Fixed).
charLocs ds.l 1 ; pointer
stylRunPos ds.w 1 ; style run position code.
numer ds.l 1 ; Point <4>
denom ds.l 1 ; Point <4>
scriptRecPtr ds.l 1 ; ScriptRecord pointer <22>
return ds.l 1 ; return address.
a6link ds.l 1 ; old a6 register.
jdRec ds JustDataRec ; local record
measProc ds.l 1 ; address of current measure proc <19>
customProc ds.w 1 ; flag that custom proc is being used <19>
numerVar ds.l 1 ; Point <19>
denomVar ds.l 1 ; Point <19>
fntInfo ds.w 4 ; FontInfo record <19>
nmjLocals equ * ; size of local variables.
endr
nmjRegs reg a2-a4/d3-d7 ; <19>
MeasureJust
move.l (sp)+,a0 ; pop 'n save return addr
move.l (sp)+,d1 ; pop ScriptRecord ptr <22>
move.l (sp)+,a1 ; pop 'n save charLocs pointer
move.w (sp)+,d0 ; pop slop (word)
clr.w -(sp) ; zero-extend textLen on stack to long <22>
swap d0 ; make slop a Fixed<65>
clr.w d0 ; clear frac part<72>
move.l d0,-(sp) ; push slop as Fixed
move.l a1,-(sp) ; push charLocs pointer
move.w #smOnlyStyleRun,-(sp) ; default styleRunPosition
move.l #$00010001,d0 ; no info, assume 1/1 scaling <4>
move.l d0,-(sp) ; push numer <4>
move.l d0,-(sp) ; push denom <4>
move.l d1,-(sp) ; push ScriptRecord ptr <22>
move.l a0,-(sp) ; restore return address
; Now we are set up like NMeasureJust, so just fall through
NMeasureJust
; Link the stack and fix drawing params in thePort to correctly fill
; justify the text.
with nmjRecord
link a6,#nmjLocals ; link the stack.
movem.l nmjRegs,-(sp) ; save regs <19>
; set up some regs, initialize charLocs[0] new<19>
move.l charLocs(a6),a2 ; get charLocs ptr
clr.w (a2)+ ; width=0 for offset 0
move.l textLen(a6),d7 ; any length?
beq @done ; if not, we are done
move.l textPtr(a6),a3 ; save text ptr
; set the drawing params
move.l numer(a6),-(sp) ; push numer <17>
move.l denom(a6),-(sp) ; push denom <17>
pea jdRec(a6) ; push ptr to JustDataRec <17>
bsr InitFontAndScale ; check font <17><19>
move.l a3,-(sp) ; push text pointer. <19>
move.l d7,-(sp) ; push text length. <19>
move.l slop(a6),-(sp) ; push slop.
move.w stylRunPos(a6),-(sp) ; push styleRunPosition
move.l numer(a6),-(sp) ; push numer <5>
move.l denom(a6),-(sp) ; push denom <5>
pea jdRec(a6) ; push local JustDatRec addr
bsr CalcSpChExtra ; calculate drawing params <17>
pea jdRec(a6) ; push local JustDatRec addr <17>
bsr DoSpChExtra ; set drawing params <17>
;------------
; Rewrote the next section to avoid the slimy way we were using MeasureText, new<19>
; since that wouldn't work for custom txMeasProcs anyway. Code down to next
; dotted line replaces previous code.
; register usage
; a2.l charLocs ptr (already set up)
; a3.l text pointer (already set up)
; a4.l measProc ptr
; d3.l x
; d4.l left end width adjust + rounding amount
; d5.l right end width adjust (will be saved on stack)
; d6.w current character offset
; d7.w text length (already set up)
; Set up for measure loops new<19>
moveq #0,d6 ; initial char offset
moveq #0,d5 ; assume right adjust = 0
move.l #FixedPoint5,d4 ; rounding + left adjust (assumed 0)
; get real start and end adjustments new<19>
IF useInterChar THEN ; <20>
move.l jdRec.addChExtra(a6),d0 ; get charExtra
beq.s @doneEndAdjust ; if 0, no adjustments necessary
asr.l #1,d0 ; divide by 2 (signed!)
tst.b jdRec.startNoFwd(a6) ; adjust widths for left flush?
beq.s @doneStartAdjust ; if no, skip
sub.l d0,d4 ; update start adjust
@doneStartAdjust
tst.b jdRec.endBackup(a6) ; adjust widths for right flush?
beq.s @doneEndAdjust ; if no, skip
move.l d0,d5
@doneEndAdjust
ENDIF ; <20>
move.l d5,-(sp) ; save for later
; Now get address of measuring routine to use, and see if it is not standard new<19>
bsr GetMeasProc ; get flag in d0, addr in a0
tst.w d0 ; use custom proc?
beq.s @useTable ; if not, go use width tables
; Measuring width of text with custom proc. new<19>
move.l a0,a4 ; save proc ptr
@customLoop
add.w #1,d6 ; include next char
move.l numer(a6),numerVar(a6) ; copy numer
move.l denom(a6),denomVar(a6) ; copy denom
subq #2,sp ; make room for result
move.w d6,-(sp) ; push byte count
move.l a3,-(sp) ; push the text pointer.
pea numerVar(a6) ; VAR numer in
pea denomVar(a6) ; VAR denom in
pea fntInfo(a6) ; VAR info
jsr (a4) ; go do measure
move.w (sp)+,d0 ; get width
swap d0 ; make a fixed
clr.w d0
; scale it
tst.b jdRec.outScalTrue(a6) ; any scaling?
beq.s @doneScaleCustom
subq #4,sp ; space for result
move.l d0,-(sp) ; push width
move.l jdRec.outScaling(a6),-(sp) ; push scaling
_FixMul
move.l (sp)+,d0 ; scaled width
@doneScaleCustom
; do left side adjustment, round width, and stuff in charLocs
add.l d4,d0 ; adjust width for left side & add 0.5
cmp.w d7,d6 ; have we reached end of string?
bge @lastChar ;
swap d0 ; get integer part
move.w d0,(a2)+ ; stuff in charLocs
bra.s @customLoop
;
; We'll be using width tables. new<19>
;
; register changes for this section
; a4.l WidthTable ptr
; d3.l current width total (initialized from d4)
; d4.l total chExtra to add (screen scaling)
; d5.l current char
@useTable
; Call SwapFont again to force SpExtra into width tables. new<19>
move.l numer(a6),-(sp) ; push numer
move.l denom(a6),-(sp) ; push denom
pea jdRec(a6) ; push ptr to JustDataRec
bsr DoSwapFont ; reset width table
; Get WidthTablePtr and initialize width accumulator. new<19>
move.l WidthTabHandle,a4 ; handle to global width table
move.l (a4),a4 ; now ptr
move.l d4,d3 ; initialize accum with left adj & rounding value
; Need to get any chExtra from port, then add in our own. new<19>
bsr GetPortChExtra ; get port chExtra in d2
move.l d2,d4 ; save in d4
add.l jdRec.addChExtra(a6),d4 ; add our charExtra to port's
; Loop: for each char, get width from table, scale it, add chExtra if not a space new<19>
moveq #0,d5
@widthLoop
add.w #1,d6 ; include next char
move.b (a3)+,d5
move.w d5,d0
lsl.w #2,d0
move.l 0(a4,d0.w),d0
; scale it
tst.b jdRec.outScalTrue(a6) ; any scaling?
beq.s @doneScaleTableWidth ; skip if none
subq #4,sp ; space for result
move.l d0,-(sp) ; push width
move.l jdRec.outScaling(a6),-(sp) ; push scaling
_FixMul
move.l (sp)+,d0 ; scaled width
@doneScaleTableWidth
; handle chExtra
cmp.b #$20,d5 ; space?
beq.s @doneAddChExtra ; if so, skip chExtra
add.l d4,d0 ; add chExtra to width
@doneAddChExtra
add.l d0,d3 ; add to char width to accum
move.l d3,d0 ; copy here for swap
cmp.w d7,d6 ; have we reached end of string?
bge.s @lastChar
swap d0 ; make rounded integer
move.w d0,(a2)+ ; stuff in charLocs
bra.s @widthLoop
; Now we are back to common code to handle last char new<19>
@lastChar
sub.l (sp)+,d0 ; adjust for right side
swap d0 ; get integer part
move.w d0,(a2) ; stuff in charLocs
; end of new block
;-------------
; Restore drawing params (RestoreSpChExtra doesn't modify jdRec)
pea jdRec(a6) ; push local JustDataRec addr
bsr RestoreSpChExtra
; Unlink the stack and return to the caller.
@done
movem.l (sp)+,nmjRegs ; restore regs <19>
move.w #nmjArgs,d0 ; for std exit
bra StdUnlink ; StdUnlink
endWith
endproc
; ---------------------------------------------------------------------------- <x5>
; function Char2Pixel(textPtr: Ptr; textLen,slop,textOff: Integer;
; direction: Integer): Integer;
; input (sp).l Text pointer.
; (sp).w Text length.
; (sp).w Extra slop pixels.
; (sp).w Text offset.
; (sp).w Direction flag.
; output (sp).w Pixel width.
; warning This routine follows Pascal register conventions.
; This routine builds a stack frame.
;
; Translate a character offset in a string into a pixelWidth. For Roman
; scripts, this is similar to TextWidth. The difference is that Char2Pixel
; allows a slop for justification, which changes the width of the space
; characters.
; ----------------------------------------------------------------------------
; ----------------------------------------------------------------------- <x2><4>
; function NChar2Pixel(
; textPtr: Ptr;
; textLen: Longint;
; slop: Fixed;
; offset: Longint;
; direction: Integer;
; styleRunPosition: JustStyleCode; {Integer}
; numer: Point; {Longint}
; denom: Point {Longint}
; ): Integer; {pixel width}
:
; notes This routine follows Pascal register conventions.
; This routine builds a stack frame.
;
; Translate a character offset in a string into a pixelWidth. For Roman
; scripts, this is similar to TextWidth. The difference is that Char2Pixel
; allows a slop for justification, which changes the width of the space
; characters.
; -----------------------------------------------------------------------
proc
export Char2Pixel,NChar2Pixel
import InitFontAndScale,CalcSpChExtra,DoSpChExtra,RestoreSpChExtra ; <17><19>
import SignFixRound,StdUnlink
;c2pRecord record {a6link},decr
;result ds.w 1 ; pixel width.
;c2pArgs equ *-8 ; size of arguments.
;textPtr ds.l 1 ; textBuf.
;textLen ds.w 1 ; textLen.
;slop ds.w 1 ; pixel slop.
;textOff ds.w 1 ; textOffset.
;direction ds.w 1 ; direction flag.
;scriptRecPtr ds.l 1 ; ScriptRecord ptr <22>
;return ds.l 1 ; return address.
;a6link ds.l 1 ; old a6 register.
;c2pLocals equ * ; size of local variables.
; endr
nc2pRecord record {a6link},decr
result ds.w 1 ; pixel width.
nc2pArgs equ *-8 ; size of arguments.
textPtr ds.l 1 ; text pointer.
textLen ds.l 1 ; text length (LongInt).
slop ds.l 1 ; extra pixel width (Fixed).
textOff ds.l 1 ; offset (LongInt)
direction ds.w 1 ; direction flag.
stylRunPos ds.w 1 ; style run position code.
numer ds.l 1 ; Point <4>
denom ds.l 1 ; Point <4>
scriptRecPtr ds.l 1 ; ScriptRecord pointer <22>
return ds.l 1 ; return address.
a6link ds.l 1 ; old a6 register.
jdRec ds JustDataRec ; local record
fntInfo ds.w 4 ; FontInfo record <17>
nc2pLocals equ * ; size of local variables.
endr
Char2Pixel
move.l (sp)+,a0 ; pop 'n save return addr
move.l (sp)+,a1 ; pop ScriptRecord ptr <22>
move.w (sp)+,d2 ; pop direction
moveq #0,d0 ; for longizing
move.w (sp)+,d0 ; pop textOff, make it long
move.l d0,d1 ; save it in d1 <22>
move.w (sp)+,d0 ; pop slop
swap d0 ; make it a Fixed
clr.w -(sp) ; zero-extend textLen on stack to long <22>
move.l d0,-(sp) ; push slop as Fixed
move.l d1,-(sp) ; push offset as long <22>
move.w d2,-(sp) ; push direction, still a word
move.w #smOnlyStyleRun,-(sp) ; default styleRunPosition
move.l #$00010001,d0 ; no info, assume 1/1 scaling <4>
move.l d0,-(sp) ; push numer <4>
move.l d0,-(sp) ; push denom <4>
move.l a1,-(sp) ; push ScriptRecord ptr <22>
move.l a0,-(sp) ; restore return address
; Now we are set up like NChar2Pixel, so just fall through
NChar2Pixel
; Link the stack, set the new drawing params for thePort.
with nc2pRecord
link a6,#nc2pLocals ; link the stack.
; get font mgr output rec to get output scaling <17>
; (this whole section is new) <17>
move.l numer(a6),-(sp) ; push numer
move.l denom(a6),-(sp) ; push denom
pea jdRec(a6) ; push ptr to JustDataRec
bsr InitFontAndScale ; check font <19>
; set the drawing params
move.l textPtr(a6),-(sp) ; push text pointer.
move.l textLen(a6),-(sp) ; push text length.
move.l slop(a6),-(sp) ; push slop.
move.w stylRunPos(a6),-(sp) ; push styleRunPosition
move.l numer(a6),-(sp) ; push numer <10>
move.l denom(a6),-(sp) ; push denom <10>
pea jdRec(a6) ; push local JustDatRec addr
bsr CalcSpChExtra ; calculate drawing params <17>
pea jdRec(a6) ; push local JustDatRec addr <17>
bsr DoSpChExtra ; set drawing params <17>
; Check the text offset against zero on the left side and the text length
; on the right side. Do these checks with word quantities.
move.w textOff+2(a6),d0 ; text offset >= 0?.
bpl.s @0 ; yes -> skip this.
moveq #0,d0 ; set text offset to zero.
@0 cmp.w textLen+2(a6),d0 ; text offset <= text length?
ble.s @1 ; yes -> skip this.
move.w textLen+2(a6),d0 ; set text offset to length.
@1
; Call StdTxMeas/txMeasProc instead of TextWidth, for correct scaled metrics <17>
; (this section replace the section that called TextWidth) <17>
subq #2,sp ; make room for result
move.w d0,-(sp) ; push byte count
move.l textPtr(a6),-(sp) ; push the text pointer.
pea numer(a6) ; VAR numer in - ok to change now
pea denom(a6) ; VAR denom in - ok to change now
pea fntInfo(a6) ; VAR info
move.l grafGlobals(a5),a0 ; Point to QuickDraw globals
move.l thePort(a0),a0 ; Get current grafport
move.l grafProcs(a0),d0 ; Is grafprocs NIL?
beq.s @useTrap ; Yes, use std proc
move.l d0,a0 ;
move.l txMeasProc(a0),a0 ; No, get proc ptr
jsr (a0) ; Go to it
CLR.W -(SP) ; save fraction of 0 on stack <24>
bra.s @doneTxMeas ; Measure text with txMeas grafProc
@useTrap ;
_StdTxMeas ; Measure text with std proc
MOVE.L grafGlobals(A5),A0 ; get pointer to graf globals <24>
MOVE.L fontAdj(A0),D2 ; load fixed width <24>
MOVE.W D2,-(SP) ; save real frac part on stack <24>
@doneTxMeas ;
; leave pixel width on stack
; Restore drawing params (RestoreSpChExtra doesn't modify jdRec)
pea jdRec(a6) ; push local JustDataRec addr
bsr RestoreSpChExtra
; Make pixel width Fixed<65>
move.l (sp)+,d2 ; get frac part in hi word, integer in low word <xx>
moveq #0,d0 ; assume zero width
move.w textOff+2(a6),d1 ; get textOff as word
ble.s @done ; if <20> 0, nothing to do
swap d2 ; put integer & frac in correct place <10>
;;;;; clr.w d2 ; comment out <10><24>
move.l d2,d0 ; get TextWidth in d0 <15>
; Now adjust Fixed width in d0.l by scaling parameters. <5><10>
; Moved this section up here <18>
tst.b jdRec.outScalTrue(a6) ; do we have any scaling? <10><17><19>
beq.s @doneWidthAdjust ; skip if not <10>
subq #4,sp ; room for FixMul result
move.l d0,-(sp) ; first FixMul param
move.l jdRec.outScaling(a6),-(sp) ; second param = numer/denom <10><17><19>
_FixMul
move.l (sp)+,d0 ; get Fixed result
@doneWidthAdjust
; Pen position adjustments for ends of style run
IF useInterChar THEN ; <20>
move.l jdRec.addChExtra(a6),d2 ; get additional charExtra <15><17><18>
beq.s @doneEndAdjust ; if 0, no adjustment needed <15>
asr.l #1,d2 ; divide by 2 (signed!) <15>
tst.b jdRec.startNoFwd(a6) ; adjust width for left flush?
beq.s @doneStartAdjust ; if no, skip
sub.l d2,d0 ; subtract 0.5 ce from width <10>
@doneStartAdjust
tst.b jdRec.endBackup(a6) ; adjust widths for right flush?
beq.s @doneEndAdjust ; if no, skip
cmp.w textLen+2(a6),d1 ; width to last char?
bne.s @doneEndAdjust ; if not, skip
sub.l d2,d0 ; subtract 0.5 ce from width <10>
@doneEndAdjust
ENDIF ; <20>
; Set result, unlink the stack and return to the caller.
bsr SignFixRound ; round Fixed width to Integer <10>
@done
move.w d0,result(a6)
move.w #nc2pArgs,d0 ; for std exit
bra StdUnlink ; StdUnlink
endWith
endproc
; ----------------------------------------------------------------------- <x2>
; function Pixel2Char(
; textPtr: Ptr;
; textLen: Integer;
; slop: Integer;
; pixelWidth: Integer;
; Var leadingEdge: Boolean
; ): Integer; {character offset}
;
; notes This routine follows Pascal register conventions.
; This routine builds a stack frame.
;
; This routine converts a pixel width and string into a character offset into
; the string and a leadingEdge flag that signals which side of the character
; the pixel fell on.
; ----------------------------------------------------------------------------
; ----------------------------------------------------------------------- <x2><4>
; function NPixel2Char(
; textPtr: Ptr;
; textLen: Longint;
; slop: Fixed;
; pixelWidth: Fixed;
; Var leadingEdge: Boolean;
; Var widthRemaining: Fixed;
; styleRunPosition: JustStyleCode; {Integer}
; numer: Point; {Longint}
; denom: Point {Longint}
; ): Integer; {character offset}
;
; notes This routine follows Pascal register conventions.
; This routine builds a stack frame.
;
; This routine converts a pixel width and string into a character offset into
; the string and a leadingEdge flag that signals which side of the character
; the pixel fell on.
;
; Substantially rewritten to fix bugs, using ideas from Mark Davis's <17>
; SingleByteFastP2C.a code, but adapting it for scaling, slop, custom
; txMeasProcs, etc.
; ----------------------------------------------------------------------------
proc
export Pixel2Char,NPixel2Char
import InitFontAndScale,CalcSpChExtra,DoSpChExtra,RestoreSpChExtra ; <17><19>
import GetFontSize ; <17>
import SignFixRound,StdUnlink
import DoSwapFont,GetMeasProc,GetPortChExtra ; <19>
;p2cRecord record {a6link},decr
;result ds.w 1 ; result, char offset.
;p2cArgs equ *-8 ; size of arguments.
;textPtr ds.l 1 ; text pointer.
;textLen ds.w 1 ; text length.
;slop ds.w 1 ; slop pixels.
;pixelWidth ds.w 1 ; pixel offset.
;leadEdgeAdr ds.l 1 ; leadingEdge address.
;scriptRecPtr ds.l 1 ; ScriptRecord ptr <22>
;return ds.l 1 ; return address.
;a6link ds.l 1 ; old a6 register.
;widRemPtr ds.l 1 ; addr of widthRemaining parm (nil if none) <x2>
;p2cLocals equ * ; size of local variables.
; endr
np2cRecord record {a6link},decr
result ds.w 1 ; result, char offset.
np2cArgs equ *-8 ; size of arguments.
textPtr ds.l 1 ; text pointer.
textLen ds.l 1 ; text length (Longint).
slop ds.l 1 ; slop pixels (Fixed).
pixelWidth ds.l 1 ; pixel offset (Fixed).
leadEdgeAdr ds.l 1 ; address of Boolean leadingEdge.
widRemAdr ds.l 1 ; address of Fixed widthRemaining.
stylRunPos ds.w 1 ; style run position code.
numer ds.l 1 ; Point <4>
denom ds.l 1 ; Point <4>
scriptRecPtr ds.l 1 ; ScriptRecord pointer <22>
return ds.l 1 ; return address.
a6link ds.l 1 ; old a6 register.
jdRec ds JustDataRec ; local record
fntInfo ds.w 4 ; FontInfo record <17>
measProc ds.l 1 ; address of current measure proc <17>
customProc ds.w 1 ; flag that custom proc is being used <17>
lastWidAdj ds.l 1 ; subtract this from width of last char <17>
numerVar ds.l 1 ; Point <17>
denomVar ds.l 1 ; Point <17>
np2cLocals equ * ; size of local variables.
endr
minusOneFixed equ $FFFF0000 ; -1.0 in Fixed format
p2cRegs reg a2-a4/d3-d7 ; <19>
Pixel2Char
move.l (sp)+,a0 ; pop and save return addr
move.l (sp)+,d2 ; pop ScriptRecord ptr <22>
move.l (sp)+,a1 ; pop and save leadingEdge addr
move.w (sp)+,d0 ; pop pixelWidth as Integer
swap d0 ; make it a Fixed<65>
clr.w d0 ; and clear fraction part
move.w (sp)+,d1 ; pop slop as Integer
swap d1 ; make it a Fixed<65>
clr.w d1 ; and clear fraction part
clr.w -(sp) ; zero-extend textLen on stack to long <22>
move.l d1,-(sp) ; push slop as a Fixed
move.l d0,-(sp) ; push pixelWidth as a Fixed
move.l a1,-(sp) ; push leadingEdge addr
clr.l -(sp) ; push nil for widthRemaining addr
move.w #smOnlyStyleRun,-(sp) ; default styleRunPosition
move.l #$00010001,d0 ; no info, assume 1/1 scaling <4>
move.l d0,-(sp) ; push numer <4>
move.l d0,-(sp) ; push denom <4>
move.l d2,-(sp) ; push ScriptRecord ptr <22>
move.l a0,-(sp) ; restore return addr
; Now we are set up like NPixel2Char, so just fall through
; NPixel2Char register usage.
;
; a2.l address of leadingEdge.
; a3.l text pointer.
; a4.l measProc ptr, also used at end
; d3.l pixelWidth, will get scaled.
; d4.w character offset.
; d5.l text width measurement.
; d6.l previous measurement.
; d7.w text length
NPixel2Char
with np2cRecord
link a6,#np2cLocals ; link the stack.
movem.l p2cRegs,-(sp) ; save the registers. <19>
; Initialize widthRemaining to -1 <x5>
move.l widRemAdr(a6),d0 ; should we set widthRemaining? <x5>
beq.s @doneInitWidRem ; skip if not <x5>
move.l d0,a0 ; copy widRemAdr <x5>
move.l #minusOneFixed,(a0) ; initialize widthzemaining to -1 <x5>
@doneInitWidRem
; load up some regs
move.l leadEdgeAdr(a6),a2 ; load leadingEdge pointer.
move.l textPtr(a6),a3 ; load text pointer.
move.l pixelWidth(a6),d3 ; get width. before or at start?
ble p2cBeforeStart ; if we are, go handle <17>
; get font mgr output rec to get output scaling <17>
; (this whole section is new) <17>
move.l numer(a6),-(sp) ; push numer <17>
move.l denom(a6),-(sp) ; push denom <17>
pea jdRec(a6) ; push ptr to JustDataRec <17>
bsr InitFontAndScale ; check font <17><19>
; set drawing/measuring params
move.l a3,-(sp) ; push text pointer.
move.l textLen(a6),-(sp) ; push text length. <x5>
move.l slop(a6),-(sp) ; push slop. <x5>
move.w stylRunPos(a6),-(sp) ; push styleRunPosition <x5>
move.l numer(a6),-(sp) ; push numer <10>
move.l denom(a6),-(sp) ; push denom <10>
pea jdRec(a6) ; push local JustDatRec addr
bsr CalcSpChExtra ; calculate drawing params <17>
pea jdRec(a6) ; push local JustDatRec addr <17>
bsr DoSpChExtra ; set drawing params <17>
; Adjust pixelwidth for left side, save width adjustment for last char <x5><17>
move.l jdRec.addChExtra(a6),d0 ; get additional charExtra <x5><17><18>
IF useInterChar THEN ; <20>
beq.s @doneCalcAdjust ; if 0, no adjustment necessary <15><17>
asr.l #1,d0 ; divide by 2 (signed!) <x5>
tst.b jdRec.startNoFwd(a6) ; adjust width for left flush? <x5>
beq.s @doneStartAdjust ; if no, skip <x5>
add.l d0,d3 ; bump width to hit next char sooner <x5><17>
@doneStartAdjust
; moved this up here <17>
tst.b jdRec.endBackup(a6) ; adjust widths for right flush? <x5>
bne.s @doneCalcAdjust ; if so, don't reset d0 <x5><17>
moveq #0,d0 ; no final width adjust <x5><17>
@doneCalcAdjust ; <17>
ENDIF ; <20>
move.l d0,lastWidAdj(a6) ; subtract this from width of last char <17>
; Get pixelWidth param and scale it down by outnumer.h/outdenom.h <6><10><17>
; Moved down here, and now scale lastWidAdj too. <18>
tst.b jdRec.outScalTrue(a6) ; do we have any output scaling? <10><17><19>
beq.s @doneWidthAdjust ; if not, skip this part <6>
subq #4,sp ; room for FixDiv result <6><10>
move.l d3,-(sp) ; width is first FixDiv arg <6><10>
move.l jdRec.outScaling(a6),-(sp) ; second param = numer/denom <10><17><19>
_FixDiv ; <10>
move.l (sp)+,d3 ; get scaled width <6>
move.l lastWidAdj(a6),d0 ; do we need to scale this too? <18>
beq.s @doneWidthAdjust ; skip if not <18>
subq #4,sp ; room for FixDiv result <18>
move.l d0,-(sp) ; lastWidAdj is first FixDiv arg <18>
move.l jdRec.outScaling(a6),-(sp) ; second param = numer/denom <18><19>
_FixDiv ; <18>
move.l (sp)+,lastWidAdj(a6) ; get scaled width <18>
@doneWidthAdjust
; Now get address of measuring routine to use, and see if it is not standard new<17>
bsr GetMeasProc ; get flag in d0, addr in a0 <19>
move.w d0,customProc(a6) ; set flag <19>
move.l a0,measProc(a6) ; save addr of the proc we want
; Set up to do measuring new<17>
moveq #0,d4 ; initial char offset
moveq #0,d5 ; measurement for current offset
moveq #0,d6 ; measurement for previous offset
move.w textLen+2(a6),d7 ; textLen
ble p2cAfterEnd
tst.w customProc(a6) ; can we use width table?
beq.s @useTable
; Measuring width of text with custom proc. new<17>
move.l measProc(a6),a4 ; get proc ptr <19>
@customLoop
add.w #1,d4 ; include next char
move.l d5,d6 ; save last meast
move.l numer(a6),numerVar(a6) ; copy numer
move.l denom(a6),denomVar(a6) ; copy denom
subq #2,sp ; make room for result
move.w d4,-(sp) ; push byte count
move.l a3,-(sp) ; push the text pointer.
pea numerVar(a6) ; VAR numer in
pea denomVar(a6) ; VAR denom in
pea fntInfo(a6) ; VAR info
jsr (a4) ; go do measure <19>
move.w (sp)+,d5 ; get width
swap d5 ; make a fixed
clr.w d5
cmp.w d7,d4 ; have we reached end of string?
bge @lastChar ; <18>
cmp.l d3,d5
blt.s @customLoop
bra @gotHit ; <18>
; We'll be using width tables.
@useTable
; additional registers for this section
; a1 ptr to width table
; d1.l char from string
; d2.l total chExtra (port's plus ours, scaled to match table)
; Call SwapFont again to force SpExtra into width tables. <17>
; (this whole section is new) <17>
move.l numer(a6),-(sp) ; push numer
move.l denom(a6),-(sp) ; push denom
pea jdRec(a6) ; push ptr to JustDataRec
bsr DoSwapFont ; reset width table <19>
; Need to get any chExtra from port, then add in our own and scale result. new<17>
; Moved part of this into subroutine for code sharing with MeasureJust. <19>
bsr GetPortChExtra ; get port chExtra in d2 <19>
add.l jdRec.addChExtra(a6),d2 ; add our charExtra to port's
tst.b jdRec.outScalTrue(a6) ; do we have any output scaling?
beq.s @doneTotalChExScal ; if not, skip this part
subq #4,sp ; result space
move.l d2,-(sp) ; total chExtra
move.l jdRec.outScaling(a6),-(sp) ; second param = numer/denom
_FixDiv ;
move.l (sp)+,d2 ; get scaled result
@doneTotalChExScal
; Here we have chExtra in d2. Get WidthTablePtr and start adding widths. new<17>
; SpExtra is in table, but have to add in chExtra.
move.l WidthTabHandle,a1 ; handle to global width table
move.l (a1),a1 ; now ptr
moveq #0,d1
@widthLoop
add.w #1,d4 ; include next char
move.l d5,d6 ; save last meast
move.b (a3)+,d1
move.w d1,d0
lsl.w #2,d0
add.l 0(a1,d0.w),d5
cmp.b #$20,d1 ; space?
beq.s @doneAddChExtra
add.l d2,d5
@doneAddChExtra
cmp.w d7,d4 ; have we reached end of string?
bge.s @lastChar
cmp.l d3,d5
blt.s @widthLoop
bra.s @gotHit
; Now we are back to common code to handle last char new<17>
@lastChar
sub.l lastWidAdj(a6),d5 ; adjust for end pen move
cmp.l d3,d5 ; change to .l <18>
blt p2cAfterEnd
; At this point we have a hit with the following:
; d4.w current offset
; d5.l width for current offset
; d6.l width for previous offset
@gotHit
; Determine whether the pixelWidth occurs on the left or right side of
; the character and return the right or left offset accordingly.
sf (a2) ; assume leadingEdge false. <21>
add.l d3,d3 ; double pixelWidth.
add.l d5,d6 ; average measurements.
cmp.l d6,d3 ; compare width to average.
bhi.s DoneP2C ; if width < average,
st (a2) ; set leadingEdge true. <21>
sub.w #1,d4 ; decrement result.
; Restore drawing params (RestoreSpChExtra doesn't modify jdRec).
; Save the P2C result.
DoneP2C
pea jdRec(a6) ; push local JustDataRec addr <x5>
bsr RestoreSpChExtra ; restore orig drawing params <x5>
move.w d4,result(a6) ; return width.
; Restore regs, unlink the stack and return to the caller.
p2cExit
movem.l (sp)+,p2cRegs ; restore the registers. <19>
move.w #np2cArgs,d0 ; for std exit <x5>
bra StdUnlink ; StdUnlink
p2cBeforeStart
; if width <= 0, then before start of the line, so <17>
; return leadingEdge = teSysJust, offset = 0
move.w #0,result(a6) ; <18>
move.b TESysJust,(a2) ; set leading edge
beq.s p2cExit ; if 0, offset ok <18>
move.w textLen+2(a6),result(a6) ; else set it to length <18>
bra.s p2cExit
p2cAfterEnd
; if width exceeds length, then past the end of the line, so <17>
; return leadingEdge = <20>teSysJust, offset = length (should already
; be in d4). Width for offset is in d5.
tst.b TESysJust ; <18>
seq (a2) ; set leadingEdge = <20>teSysJust <18>
beq.s @doneSetLength ; if TESysJust <20>$0, <20> <18>
moveq #0,d4 ; <20> then reset length <18>
@doneSetLength ; <18>
move.l widRemAdr(a6),d1 ; should we set widthRemaining? <x2>
beq.s DoneP2C ; if not, just return length <x2>
move.l d1,a4 ; copy widRemAdr <x2>
sub.l d5,d3 ; remaining width <x2><17>
; we have to scale up remaining width. <17>
tst.b jdRec.outScalTrue(a6) ; do we have any scaling? <19>
beq.s @doneWidthScaleup ; if not, skip this part
subq #4,sp ; room for FixDiv result
move.l d3,-(sp) ; width is first FixMul arg
move.l jdRec.outScaling(a6),-(sp) ; second param = numer/denom <19>
_FixMul ;
move.l (sp)+,d3 ; get scaled width
@doneWidthScaleup
; now set it, then go set offset and return.
move.l d3,(a4) ; set widthRemaining <x2><17><19><!>
bra.s DoneP2C ; go return length. <x2>
endWith
endproc
; ----------------------------------------------------------------------- <17>
; PROCEDURE InitFontAndScale(
; numer: Point;
; denom: Point;
; jdRecPtr: ^JustDataRec
; );
;
; This calls FMSwapFont, checks the FontClass field of the style mapping
; table in the FOND (if present), and sets the noInterCh flag field of the
; JustDataRec, based on this info. It sets up the input and output scaling <19>
; factors and the relevant flags to 0. It also initializes all of the other
; flags (except restoreSE) to 0 (false).
;
; Changed to not clear restoreSE, since it is initialized by DoSpChExtra <18>
; anyway, and since we need to preserve its state when we call this
; routine to force FMSwapFont before getting widths from the width table.
; (Now it doesn't matter, since we call DoSwapFont when we need to preserve <19>
; the state of restoreSE)
;
; PROCEDURE DoSwapFont( <19>
; numer: Point;
; denom: Point;
; jdRecPtr: ^JustDataRec
; );
;
; This just calls SwapFont. The jdRecPtr parameter is not used, but is
; passed for stack frame compatibility so we can share code more easily.
; -----------------------------------------------------------------------
proc
export InitFontAndScale,DoSwapFont
import StdUnlink
ifsRecord record {a6link},decr
ifsArgs equ *-8 ; size of arguments.
numer ds.l 1 ; Point - numer
denom ds.l 1 ; Point - denom
jdRecPtr ds.l 1 ; pointer to JustDataRec
return ds.l 1 ; return address.
a6link ds.l 1 ; old a6 register.
fmInRec ds.b 16 ; FMInput record
ifsLocals equ * ; size of local variables.
endr
smtFontClass equ 0 ; offset of Font Class in style map table
fcNoInterCh equ 10 ; Font Class bit flag for no interchar sp
fixed1 equ $00010000 ; 1.0 in 16.16 Fixed format <19>
InitFontAndScale
with ifsRecord,JustDataRec ; <19>
link a6,#ifsLocals ; link the stack.
; Compute input numer.h/denom.h and set inScaling and inScalTrue.
; This was moved from InitScaleFac routine. <19>
move.l jdRecPtr(a6),a1 ; pointer to JustDataRec
move.l #fixed1,inScaling(a1) ; initially assume 1,1 scaling <19>
sf inScalTrue(a1) ; follows from above <19>
move.w numer+h(a6),d1 ; get numer
move.w denom+h(a6),d2 ; get denom
beq.s @doneInScaling ; if 0, then skip next part <16>
cmp.w d1,d2 ; if they're the same<6D>
beq.s @doneInScaling ; <20>then skip next part
subq #4,sp ; room for FixRatio result
move.w d1,-(sp) ; push numer.h
move.w d2,-(sp) ; push denom.h
_FixRatio ; divide
move.l jdRecPtr(a6),a1 ; restore pointer to JustDataRec
move.l (sp)+,inScaling(a1) ; save computed scaling <19>
st inScalTrue(a1) ; follows from above <19>
@doneInScaling
; Fill font mgr input record, call font mgr to set up FOND handle so we can see if
; FOND allows interchar spacing. Also sets up Width table.
; Common routine returns FMOutRec ptr in a0. <19>
bsr.s CommonSwapFont ; <19>
; Compute output numer.h/denom.h and set outScaling and outScalTrue.
; New section; code to do this used to be duplicated in Char2Pix, Pix2Char, etc. <19>
move.l jdRecPtr(a6),a1 ; pointer to JustDataRec
move.l #fixed1,outScaling(a1) ; initially assume 1,1 scaling
sf outScalTrue(a1) ; follows from above
move.w fmOutNumer+h(a0),d1 ; get numer
move.w fmOutDenom+h(a0),d2 ; get denom
beq.s @doneOutScaling ; if 0, then skip next part
cmp.w d1,d2 ; if they're the same<6D>
beq.s @doneOutScaling ; <20>then skip next part
subq #4,sp ; room for FixRatio result
move.w d1,-(sp) ; push numer.h
move.w d2,-(sp) ; push denom.h
_FixRatio ; divide
move.l jdRecPtr(a6),a1 ; restore pointer to JustDataRec
move.l (sp)+,outScaling(a1) ; save computed scaling
st outScalTrue(a1) ; follows from above
@doneOutScaling
; Check if FOND allows intercharacter spacing
;; move.l jdRecPtr(a6),a1 ; get ptr to passed JustDataRec
sf noInterCh(a1) ; initialize
move.l LastFOND,d0 ; Do we have a FOND handle?
beq.s @doneFONDCheck ; skip this if not
move.l d0,a0
move.l (a0),a0 ; Get FOND pointer
move.l ffStylOff(a0),d0 ; Get offset to style-map table
beq.s @doneFONDCheck ; skip if no table
move.w smtFontClass(a0,d0.l),d0 ; get Font Class from table
btst #fcNoInterCh,d0 ; Does FOND forbid interchar spacing?
sne noInterCh(a1) ; set according to result
@doneFONDCheck
; Initialize other flags to 0
sf startNoFwd(a1)
sf endBackup(a1)
sf haveWeight(a1)
;; sf restoreSE(a1) ; don't do this one <18>
; Restore regs, unlink stack, and return
move.w #ifsArgs,d0 ; for std exit
bra StdUnlink ; StdUnlink
endwith ;ifsRecord,JustDataRec
; Common routine for to set up SwapFont input record and call it. <19>
; Expects stack frame to be set up.
; Returns FMOutRec ptr in a0.
CommonSwapFont
with ifsRecord
lea fmInRec(a6),a1 ; Point to local FMInput record <19>
subq #4,sp ; Room for result (FMOutput ptr) <19>
move.l a1,-(sp) ; push ptr to input record <19>
move.l grafGlobals(a5),a0 ; Point to QuickDraw globals
move.l thePort(a0),a0 ; Get current grafport
move.w txFont(a0),(a1)+ ; Get family from thePort
move.w txSize(a0),(a1)+ ; Get size from thePort
move.b txFace(a0),(a1)+ ; Get face from thePort
sf (a1)+ ; Set needBits false
move.w device(a0),(a1)+ ; Get device from thePort
move.l numer(a6),(a1)+ ; Get numer from input params
move.l denom(a6),(a1) ; Get denom from input params
_FMSwapFont
move.l (sp)+,a0 ; get FMOutPtr <19>
rts
endwith ;ifsRecord
; Little routine just to do the swap font stuff (same parameters) <19>
DoSwapFont
with ifsRecord
link a6,#ifsLocals ; link the stack.
bsr.s CommonSwapFont ;
move.w #ifsArgs,d0 ; for std exit
bra StdUnlink ; StdUnlink
endwith ;ifsRecord
endproc
; ----------------------------------------------------------------------- <x5>
; PROCEDURE InitWeight(
; textPtr: Ptr;
; textLen: Longint;
; styleRunPosition: JustStyleCode;
; jdRecPtr: ^JustDataRec
; );
;
; This initializes some of the fields in a JustDataRec, based on the
; text, the styleRunPosition, and the smgrCharPortion field in the
; SMgrRecord. It sets up the following:
; weight
; charPortion
; spPortion
; startNoFwd
; endBackup
;
; NOTE: trashes a0-a1,d0-d2
; -----------------------------------------------------------------------
proc
export InitWeight ; <17>
import StdUnlink
iwRecord record {a6link},decr
iwArgs equ *-8 ; size of arguments.
textPtr ds.l 1 ; text pointer.
textLen ds.l 1 ; text length.
stylRunPos ds.w 1 ; style run position code.
jdRecPtr ds.l 1 ; pointer to JustDataRec
return ds.l 1 ; return address.
a6link ds.l 1 ; old a6 register.
iwLocals equ * ; size of local variables.
endr
portion100 equ $1000 ; 100% in 4.12 format
InitWeight ; <17>
with iwRecord
link a6,#iwLocals ; link the stack.
movem.l d3-d4,-(sp) ; save regs
; Initialize char portion and space portion to 0% and 100% (moved here) <17>
moveq #0,d3 ; also use for longizing CharPortion
move.l #portion100,d4
IF useInterChar THEN ; <20>
; Check if FOND allows intercharacter spacing (new section) <17>
with JustDataRec ;
move.l jdRecPtr(a6),a0 ; pointer to JustDataRec
tst.b noInterCh(a0) ; interchar forbidden?
bne.s @doneGetPortion ; If so, don't get char portion
endwith ;JustDataRec ;
; Get char portion (cp) in d3, ensure that it is in the range 0.0 to 1.0,
; and then get space portion (sp = 1-cp) in d4.
with SMgrRecord
GetSMgrCore a1 ; get SMgrRecord pointer
move.w smgrCharPortion(a1),d3 ; get CharPortion, 4.12 fixed
cmp.w d4,d3 ; within range 0.0 to 1.0?
bls.s @doneFixPortion ; if so, skip fix
move.w d4,d3 ; fix char proportion
@doneFixPortion
sub.w d3,d4 ; get space proportion in d4
endwith
@doneGetPortion
ENDIF ; <20>
; Now compute #chars*cp + #spaces*sp by looping through the text buffer,
; testing each character, and then adding cp or sp to d2. Here, d2 is a
; 20.12 fixed-point number.
move.l textPtr(a6),a0 ; get text ptr
move.l textLen(a6),d0 ; get text len
move.l a0,a1 ; copy text pointer
moveq #0,d2 ; initialize accumulator
bra.s @testLength ; jump to end of loop
@loopStart
move.b (a0)+,d1 ; get next char
cmp.b #' ',d1 ; space?
bne.s @notSpace ; if not, handle it separately
add.l d4,d2 ; add space proportion
bra.s @testLength ;
@notSpace
add.l d3,d2 ; add char proportion
@testLength
subq.l #1,d0 ; decrement length
bge.s @loopStart ; loop while still chars
; Now, we use StyleRunPosition to adjust d2 and set d0/d1. First, we make
; d2 a 19.13 format fixed, and we can treat d3 as 0.5*cp in 19.13 format.
with JustDataRec
move.l jdRecPtr(a6),a0 ; pointer to JustDataRec
sf startNoFwd(a0) ; initialize startNoFwd <16>
sf endBackup(a0) ; initialize endBackup <16>
add.l d2,d2 ; now accum is 19.13 fixed <16>
beq.s @doneLeftAdjust ; if no chars, skip adjust <16>
move.w stylRunPos(a6),d0 ; get styleRunPosition <16>
; Adjust for right end of style run
btst.l #0,d0 ; any adjustments for right end? <17>
bne.s @doneRightAdjust ; no,,skip
cmp.b #' ',d1 ; was last char a space?
beq.s @doneRightAdjust ; if so, skip
sub.l d3,d2 ; subtract 0.5 cp from accum
st endBackup(a0) ; now move for right end is -1 ce
@doneRightAdjust
; Adjust for left end of style run
btst.l #1,d0 ; any adjustment for left end? <17>
bne.s @doneLeftAdjust
move.b (a1),d1
cmp.b #' ',d1 ; is first char a space?
beq.s @doneLeftAdjust ; if so, skip
sub.l d3,d2 ; subtract 0.5 cp from accum
st startNoFwd(a0) ; now move for left end is 0
@doneLeftAdjust
; Now make d2 and d3 16.16 Fixed and save them
lsl.l #3,d2 ; now accum is 16.16 Fixed.
move.l d2,weight(a0) ; save it
lsl.l #4,d3 ; now cp is 16.16 Fixed
move.l d3,charPortion(a0) ; save it too
lsl.l #4,d4 ; now sp is 16.16 Fixed
move.l d4,spPortion(a0) ; guess what?
; Restore regs, unlink stack, and return
movem.l (sp)+,d3-d4 ; restore regs
move.w #iwArgs,d0 ; for std exit
bra StdUnlink ; StdUnlink
endwith ; JustDataRec
endwith ; iwRecord
endproc
; ----------------------------------------------------------------------------- <x5><17>
; PROCEDURE CalcSpChExtra(
; textPtr: Ptr;
; textLen: Long;
; slop: Fixed; {signed}
; styleRunPosition: JustStyleCode;
; numer: Point;
; denom: Point;
; jdRecPtr: ^JustDataRec;
; );
;
; CalcSpChExtra finds the correct spExtra and charExtra values for the passed
; string, based on its length, the slop value, the styleRunPosition, and the
; scaling factors. It assumes InitFontAndScale has been called to set the <19>
; scaling factor, and calls InitWeight if the slop is nonzero to set the weight.
;
; InitFontAndScale must be called before calling this.
;
; Sets addSpExtra, addSpExScal, addChExtra, addChExScal, runSlop.
; Uses and may modify haveWeight.
;
; NOTE: trashes a0-a1,d0-d2
; -----------------------------------------------------------------------------
proc
export CalcSpChExtra
import StdUnlink
import GetFontSize ; <19>
csceRecord record {a6link},decr
csceArgs equ *-8 ; size of arguments.
textPtr ds.l 1 ; text pointer.
textLen ds.l 1 ; text length.
slop ds.l 1 ; slop pixels.
stylRunPos ds.w 1 ; style run position code.
numer ds.l 1 ; Point - numer <5>
denom ds.l 1 ; Point - denom <5>
jdRecPtr ds.l 1 ; pointer to JustDataRec
return ds.l 1 ; return address.
a6link ds.l 1 ; old a6 register.
csceLocals equ * ; size of local variables.
endr
csceRegs reg a3/d3-d4 ; <19>
CalcSpChExtra
with csceRecord,JustDataRec,SMgrRecord
link a6,#csceLocals ; link the stack.
movem.l csceRegs,-(sp) ; save regs <17><19>
move.l jdRecPtr(a6),a3 ; get ptr to JustDataRec <17>
clr.l addSpExtra(a3) ; Initialize fields we set directly <17>
clr.l addSpExScal(a3) ;
clr.l addChExtra(a3) ;
clr.l addChExScal(a3) ;
move.l slop(a6),runSlop(a3) ;
beq @csceRestoreRegs ; if slop zero, skip this whole mess
tst.b haveWeight(a3) ; have we already done this? <17>
bne.s @gotWeight ; if so, skip <17>
move.l textPtr(a6),-(sp) ; push textPtr
move.l textLen(a6),-(sp) ; push textLen
move.w stylRunPos(a6),-(sp) ; push styleRunPosition
move.l a3,-(sp) ; push ptr to JustDataRec
bsr InitWeight ; Fill out weight <17>
st haveWeight(a3) ; don't do it again <17>
@gotWeight ; <17>
tst.l weight(a3) ; Check nc*cp+ns*sp
beq @csceRestoreRegs ; if 0, nothing to do
; Determine limit on negative spExtra & chExtra. new<19>
; This uses a simple heuristic test. The basic idea is don't let the additional
; Script Mgr spExtra or chExtra be < -3 for an unscaled 12 pt font (with appropriate
; adjustments for font size and scaling). This ignores any existing spExtra or
; chExtra in the port, and doesn't check the actual width of a space or narrow char.
move.l grafGlobals(a5),a0 ; grafGlobals
move.l thePort(a0),a0 ; get thePort pointer
bsr GetFontSize ; expects thePort^ in a0, returns size in d0
swap d0 ; make a Fixed
clr.w d0 ; and clear frac part
tst.b inScalTrue(a3) ; any num/denom scaling?
beq.s @doneSizeAdjust ; if not, skip size adjust
subq #4,sp ; space for FixMul return
move.l d0,-(sp) ; push size
move.l inScaling(a3),-(sp) ; push numer.h/denom.h
_FixMul
move.l (sp)+,d0 ; get scaled size
@doneSizeAdjust
asr.l #2,d0 ; divide by 12/3
neg.l d0 ;
move.l d0,d4 ; save limit
; Make slop/(nc*cp + ns*sp)
subq #4,sp ; make stack space for result
move.l runSlop(a3),-(sp) ; push slop (numerator)
move.l weight(a3),-(sp) ; push weight (denom)
_FixDiv
; Now slop/(nc*cp + ns*sp) is on the stack. If cp is 0, this is slop/ns,
; which is the desired additional spExtra, so skip the unnecessary charExtra
; stuff, skip multiplying slop/weight by sp (which is 1.0), and go straight
; to where we set addSpExtra from result on stack. Otherwise, save slop/weight
; in d3 and then proceed with charExtra stuff.
IF useInterChar THEN ; <20>
move.l charPortion(a3),d0 ; get charPortion
beq.s @setSpExtra ; if 0, skip a lot of stuff
move.l (sp)+,d3 ; get slop/weight
; Determine additional chExtra.
subq #4,sp ; make stack space for result
move.l d0,-(sp) ; push charPortion
move.l d3,-(sp) ; push slop/weight
_FixMul ; get unscaled additional charExtra
move.l (sp)+,d0 ; <19>
move.l d0,addChExtra(a3) ; save in JustDataRec <17><19>
move.l d0,addChExScal(a3) ; initialize this too <19>
cmp.l d4,d0 ; do we exceed limit? <19>
blt.s @recalcExtra ; if so, go recalculate Extra values <19>
; Determine additional spExtra
subq #4,sp ; make stack space for result
move.l spPortion(a3),-(sp) ; push spPortion
move.l d3,-(sp) ; push slop/weight
_FixMul ; get unscaled additional spExtra on stack
@setSpExtra
ENDIF ; <20>
move.l (sp)+,d0 ; get unscaled additional spExtra <19>
move.l d0,addSpExtra(a3) ; save in JustDataRec <17><19>
move.l d0,addSpExScal(a3) ; initialize this too <19>
cmp.l d4,d0 ; do we exceed limit? <19>
bge.s @doScaling ; if not, skip pinning or recalculation <19>
; If charPortion is 0, all we can do is pin spExtra. new<19>
IF useInterChar THEN ; <20>
tst.l charPortion(a3) ; is charPortion zero?
bne.s @recalcExtra ; if no, go recalculate Extra values
ENDIF ; <20>
move.l d4,addSpExtra(a3) ; pin spExtra
move.l d4,addSpExScal(a3) ; this too
IF useInterChar THEN ; <20>
bra.s @doScaling ; now go to scaling
; We have hit a neg limit, and charPortion is not 0. Set spExtra and chExtra to the new<19>
; greater of Extra limit (d4) or slop/(adjusted number of chars).
@recalcExtra
move.l textLen(a6),d0 ; get length
swap d0 ; make Fixed
clr.w d0 ; clear frac part
move.l #FixedPoint5,d1 ; get value for adjusting number of chars
tst.b startNoFwd(a3) ; only .5 chExtra for left char?
beq.s @doneStartAdjust ; skip if not
sub.l d1,d0 ; adjust number of chars
@doneStartAdjust ;
tst.b endBackup(a3) ; only .5 chExtra for right char?
beq.s @doneEndAdjust ; skip if not
sub.l d1,d0 ; adjust number of chars
@doneEndAdjust ;
subq #4,sp ; result space
move.l runSlop(a3),-(sp) ; push slop (numerator)
move.l d0,-(sp) ; push adjusted number of chars (denom)
_FixDiv ;
move.l (sp)+,d0 ; get new value for spExtra and chExtra
cmp.l d4,d0 ; does it exceed limit?
bge.s @stuffNewExtra ; if not, use it
move.l d4,d0 ; else, just pin everything
@stuffNewExtra ;
move.l d0,addChExtra(a3) ; stuff it everywhere
move.l d0,addChExScal(a3) ;
move.l d0,addSpExtra(a3) ;
move.l d0,addSpExScal(a3) ;
ENDIF ; <20>
; Scale spExtra and chExtra by numer/denom (collected here from above) <19>
@doScaling
tst.b inScalTrue(a3) ; do we have any scaling? <10><19>
beq.s @doneScaleExtra ; skip if not <10>
IF useInterChar THEN ; <20>
move.l addChExtra(a3),d0 ; get unscaled value <19>
beq.s @doneScaleChExtra ; skip if 0 <19>
subq #4,sp ; make stack space for result <19>
move.l d0,-(sp) ; push unscaled chExtra <19>
move.l inScaling(a3),-(sp) ; second param = numer/denom <10><19>
_FixDiv ; get (unscaled chExtra)/(numer/denom) <17>
move.l (sp)+,addChExScal(a3) ; save in JustDataRec <10><17><19>
@doneScaleChExtra ; <10>
ENDIF ; <20>
move.l addSpExtra(a3),d0 ; get unscaled value <19>
beq.s @doneScaleExtra ; skip if 0 <19>
subq #4,sp ; make stack space for result <19>
move.l d0,-(sp) ; push unscaled spExtra <19>
move.l inScaling(a3),-(sp) ; second param = numer/denom <13><19>
_FixDiv ; (spExtra)/(num/den) <13>
move.l (sp)+,addSpExScal(a3) ; save in JustDataRec <17><19>
@doneScaleExtra ; <13><19>
; Restore regs, unlink the stack and return to the caller.
@csceRestoreRegs
movem.l (sp)+,csceRegs ; restore regs <17><19>
@csceUnlink
move.w #csceArgs,d0 ; for std exit
bra StdUnlink ; StdUnlink
endwith
endproc
; ----------------------------------------------------------------------------- <17>
; PROCEDURE DoSpChExtra(
; jdRecPtr: ^JustDataRec;
; );
;
; SetSpChExtra sets the spExtra value of the port and the GrafGlobal qdChExtra,
; based on values in the JustDataRec. If addSpExScal is non-zero, the routine
; saves the current value of spExtra, adds in the addSpExScal value, and sets
; the restoreSE flag. The addChExScal value is scaled down by the font size and
; put in qdChExtra. The runSlop is also saved in qdRunSlop.
;
; -----------------------------------------------------------------------------
proc
export DoSpChExtra
import StdUnlink
import GetFontSize
dsceRecord record {a6link},decr
dsceArgs equ *-8 ; size of arguments.
jdRecPtr ds.l 1 ; pointer to JustDataRec
return ds.l 1 ; return address.
a6link ds.l 1 ; old a6 register.
dsceLocals equ * ; size of local variables.
endr
DoSpChExtra
with dsceRecord,JustDataRec
link a6,#dsceLocals ; link the stack.
move.l jdRecPtr(a6),a1 ; get ptr to passed JustDataRec
sf restoreSE(a1) ; initialize restoreSE
move.l grafGlobals(a5),a0 ; grafGlobals
clr.l qdChExtra(a0) ; initialize
move.l runSlop(a1),qdRunSlop(a0) ; put slop in globals so pics can save it
beq.s @dsceUnlink ; if no slop, skip all of this
move.l thePort(a0),a0 ; get thePort pointer
; If addSpExScal is non-zero, add it in to port's value, first saving old value
move.l addSpExScal(a1),d0
beq.s @doneSpExtra
; Now we have scaled spExtra in d0. Save the current spExtra value, then update it.
move.l spExtra(a0),d1 ; get original spExtra
move.l d1,oldSpExtra(a1) ; save original spExtra<72>
st restoreSE(a1) ; and remember to restore it
add.l d0,d1 ; add in scaled extra value
add.l #$00000001,d1 ; old <med> fix for QD bug - it rounds
; differently for measuring and drawing
; (is this fix still needed? does it
; work right for neg spExtra? -pke)
move.l d1,spExtra(a0) ; adjust spExtra
@doneSpExtra
IF useInterChar THEN ; <20>
; If addChExScal is non-zero, scale it by font size (like CharExtra field in port)
; and stuff it in qdChExtra.
move.l addChExScal(a1),d1
beq.s @doneChExtra
; This does essentially the same thing as QuickDraw<61>s CharExtra routine.
bsr GetFontSize ; assume thePort^ in a0, get font size in d0.w
swap d0 ; make it a Fixed
clr.w d0 ; clear the fraction part
subq #4,sp ; space for result
move.l d1,-(sp) ; addChExScal
move.l d0,-(sp) ; font size as Fixed
_FixDiv ; addChExScal/(font size)
move.l grafGlobals(a5),a0 ; grafGlobals
move.l (sp)+,qdChExtra(a0) ; get 16.16 Fixed result for use by QuickDraw
@doneChExtra
ENDIF ; <20>
; Unlink the stack and return to the caller.
@dsceUnlink
move.w #dsceArgs,d0 ; for std exit
bra StdUnlink ; StdUnlink
endwith
endproc
; ----------------------------------------------------------------------------- <x5>
; PROCEDURE RestoreSpChExtra(
; jdRecPtr: ^JustDataRec
; );
;
; This restores the original spExtra value, and clears qdChExtra and qdRunSlop. <17>
; -----------------------------------------------------------------------------
proc
export RestoreSpChExtra
import StdUnlink
rsceRecord record {a6link},decr
rsceArgs equ *-8 ; size of arguments.
jdRecPtr ds.l 1 ; pointer to JustDataRec
return ds.l 1 ; return address.
a6link ds.l 1 ; old a6 register.
rsceLocals equ * ; size of local variables.
endr
RestoreSpChExtra
with rsceRecord,JustDataRec
link a6,#rsceLocals ; link the stack.
move.l grafGlobals(a5),a0 ; grafGlobals <9><17>
clr.l qdChExtra(a0) ; never hurts to clear it <9><12>
clr.l qdRunSlop(a0) ; we're done with this too <9><12>
move.l jdRecPtr(a6),a1 ; get JustDataRec pointer <17>
tst.b restoreSE(a1) ; do we need to bother? <17>
beq.s @doneRestoreSE
move.l thePort(a0),a0 ; get thePort pointer <10><17>
move.l oldSpExtra(a1),spExtra(a0) ; restore old spExtra <10><17>
@doneRestoreSE
move.w #rsceArgs,d0 ; for std exit
bra StdUnlink ; StdUnlink
endWith
endproc
; ----------------------------------------------------------------------------- <19>
; routine GetPortChExtra
;
; input: none
; output: d2.l port's chExtra, converted to 16.16 and scaled back up by font size
; -----------------------------------------------------------------------------
proc
export GetPortChExtra
import GetFontSize
GetPortChExtra
move.l grafGlobals(a5),a0 ; find the QuickDraw globals.
move.l thePort(a0),a0 ; get thePort pointer
moveq #0,d2 ; assume port has no chExtra
tst.w portVersion(a0) ; negative if cGrafPort
bpl.s @donePortChExtra ; otherwise, get port's chExtra
move.w chExtra(a0),d2 ; get 4.12 fixed format
beq.s @donePortChExtra ; if zero, we're done
ext.l d2 ; extend sign bits
asl.l #4,d2 ; convert to 16.16 format.
bsr GetFontSize ; assume thePort^ in a0, get font size in d0.w
swap d0 ; make Fixed
clr.w d0 ; clear frac part
subq #4,sp ; space for result
move.l d0,-(sp) ; push size
move.l d2,-(sp) ; push chExtra for 1-point size
_FixMul ; chExtra on stack
move.l (sp)+,d2 ; get real chExtra for our size
@donePortChExtra ;
rts
endproc
; ----------------------------------------------------------------------------- <x5>
; routine: GetFontSize
; input: a0 Pointer to thePort <8><17>
; output: d0.w Font size
;
; Copied from QD code in CharExtra. <x5>
; -----------------------------------------------------------------------------
proc
export GetFontSize
GetFontSize
MOVE.w txSize(A0),D0 ;get the text size <17>
BNE.S @notZero ;not FMDefault
TST.w txFont(A0) ;system font? <17>
BNE.S @apFont ;if not, use default
MOVE.w SysFontSize,D0 ;if family is zero, use system font size
BNE.S @notZero
@apFont
MOVE.B FMDefaultSize,D0 ;if family nonzero or system font size zero,
BNE.S @notZero ; use the default size
MOVEQ #12,D0 ;if the default is zero, hardcode to 12
@notZero
rts
endproc
; ----------------------------------------------------------------------------- <x5>
; routine: SignFixRound
; input: d0.l signed fixed
; output: d0.w integer produced by rounding
; -----------------------------------------------------------------------------
proc
export SignFixRound
SignFixRound
tst.l d0
bmi.s @neg
add.l #FixedPoint5,d0
swap d0
rts
@neg
sub.l #FixedPoint5,d0
swap d0
rts
endproc
; ----------------------------------------------------------------------------- <19>
; routine: GetMeasProc
; input: none
; output: d0.l 0 if StdTxMeas used, -1 if custom txMeasProc used
; a0.l ptr to meas proc to use
;
; Extracted this from Pixel2Char because it will be used by MeasureJust too
; -----------------------------------------------------------------------------
proc
export GetMeasProc
stdTxMeasTrap equ $A8ED ;
GetMeasProc
move.w #stdTxMeasTrap,d0
_GetTrapAddress ; get address of StdTxMeas in a0
moveq #0,d0 ; set flag: no custom proc
move.l grafGlobals(a5),a1 ; Point to QuickDraw globals
move.l thePort(a1),a1 ; Get current grafport
move.l grafProcs(a1),d1 ; Is grafprocs NIL?
beq.s @gotProc ; if so, we use StdTxMeas
move.l d1,a1 ; else, check grafprocs
move.l txMeasProc(a1),d1 ; get txMeasProc
cmp.l a0,d1 ; is it same as StdTxMeas?
beq.s @gotProc ; if so, skip reset
move.l d1,a0 ; else, we use custom proc
moveq #-1,d0 ; and say so
@gotProc
rts
endproc
;------------------------------------------ <5>
;
; GetScaledFontInfo procedure
;
; Copied from QuickDraw, but modified to accept scaling parameters and
; to use record for stack frame.
; Rearranged parameter order. <7>
; Moved to ScriptMgrExtTail.a <7>
;
end