// S C A L E (PREPRESS)
// catalog number ???
//
// Scales characters in CDtemp file carefully -- either up
// or down.
get "ix.dfs"
// outgoing procedures
external
[
Scale
]
// outgoing statics
//external
// [
// ]
//static
// [
// ]
// incoming procedures
external
[
//WINDOW
WindowRead
WindowReadBlock
WindowWrite
WindowWriteBlock
WindowGetPosition
WindowSetPosition
//MAPCDTEMP
MapCDtemp
//PREPRESS
CheckParams
//PREPRESSUTIL
MulFull
MulDiv
DPCop
FSGetX
FSPut
Scream
RoundFP
//FLOAT
FLDI;FDV;FLDDP;FSTDP;FLD
FML;FAD;FTR;FSB;FST;FCM
//OS
Zero
DoubleAdd
CallSwat
]
// incoming statics
external
[
params
resolutionx
xfp
yfp
]
// internal statics
//static
// [
// ]
// File-wide structure and manifest declarations.
let Scale() be
[
unless CheckParams(gotfactors) then finish
MapCDtemp(ScaleIx, ScaleChar)
]
and ScaleIx(ix) be
[
ix>>IX.resolutionx=ScaleInteger(ix>>IX.resolutionx, 1)
ix>>IX.resolutiony=ScaleInteger(ix>>IX.resolutiony, 2)
]
and ScaleChar(p, si, so) be
[
WindowRead(si) //Past FHEAD word
let hb=p>>CharWidth.H
let hw=(hb+15)/16
let ns=p>>CharWidth.W
let ons=ScaleInteger(ns, 1) //Output number of scan-lines
let ohb=ScaleInteger(hb, 2) //Output number of bits high
let ohb2=ohb*2
let ohw=(ohb+15)/16
let outVec=FSGetX(ohw*ons)
let inVec=FSGetX(hw) //For input scan-line
let sumVec=FSGetX(ohb2) //For summing black bits
let minBlackS=ons //Bounding box of output character
let maxBlackS=-1
let minBlackB=ohb
let maxBlackB=-1
// Threshold = percent/ (100 * xfp * yfp), saved as a double-precision number.
let negThreshold=vec 1
let percent=50
if (params&gotresolution) ne 0 then percent=resolutionx
FLDI(1, -percent) //negative
FLDI(2, 100)
FDV(1,2)
FDV(1, xfp); FDV(1, yfp)
FSTDP(1, negThreshold)
// Phase increments are amount to march in INPUT character
// for each step in output character.
let SPhaseIncrement=vec 1
FLDI(1, 1); FDV(1, xfp); FSTDP(1, SPhaseIncrement)
let BPhaseIncrement=vec 1
FLDI(1, 1); FDV(1, yfp); FSTDP(1, BPhaseIncrement)
let currentSPhase=vec 1
let nextSPhase=vec 1
let currentBPhase=vec 1
let nextBPhase=vec 1
let finalNs=nil
let finalHb=nil
Zero(nextSPhase, 2)
let inVecHolds=-1
for s=0 to ons-1 do
[sOut
Zero(sumVec, ohb2)
DPCop(currentSPhase, nextSPhase)
DoubleAdd(nextSPhase, SPhaseIncrement)
for slIn=currentSPhase!0 to nextSPhase!0 do
[
if slIn ne inVecHolds then
[
inVecHolds=inVecHolds+1
if slIn ne inVecHolds then CallSwat("Bug")
WindowReadBlock(si, inVec, hw)
]
// Calculate amount of input scan-line in image of output scan-line
let sInAmount=177777b
if slIn eq nextSPhase!0 then sInAmount=nextSPhase!1
if slIn eq currentSPhase!0 then sInAmount=sInAmount-currentSPhase!1
Zero(nextBPhase, 2)
for b=0 to ohb-1 do
[bOut
let sumP=sumVec+b+b
DPCop(currentBPhase, nextBPhase)
DoubleAdd(nextBPhase, BPhaseIncrement)
for bIn=currentBPhase!0 to nextBPhase!0 do
[
let bw=bIn/16+inVec
if (@bw & (#100000 rshift (bIn))) ne 0 then
[black
// Calculate mount of input bit in image of output bit
let bInAmount=177777b
if bIn eq nextBPhase!0 then bInAmount=nextBPhase!1
if bIn eq currentBPhase!0 then bInAmount=bInAmount-currentBPhase!1
// Calculate total "area" of input bit involved in output bit, and sum
let tmp=vec 1
tmp!0=0
tmp!1=MulDiv(sInAmount, bInAmount, 177777b)
DoubleAdd(sumP, tmp)
]black
]
]bOut
] //Loop on relevant input scan-lines
// Threshold the output scan-line
let outP=outVec+s*ohw
Zero(outP, ohw)
let blackSeen=false
for i=0 to ohb-1 do
[
let sumP=sumVec+i+i
DoubleAdd(sumP, negThreshold)
if sumP!0 ge 0 then
[
let ow=outP+i/16
@ow=@ow % (100000b rshift (i))
if i ls minBlackB then minBlackB=i
if i gr maxBlackB then maxBlackB=i
blackSeen=true
]
]
if blackSeen then
[
if s ls minBlackS then minBlackS=s
if s gr maxBlackS then maxBlackS=s
]
]sOut
// Prepare FHEAD word for output:
let finalHb=(maxBlackB-minBlackB+1)
let finalNs=(maxBlackS-minBlackS+1)
if finalHb le 0 % finalNs le 0 then [ finalHb=0; finalNs=0 ]
let finalHw=(finalHb+15)/16
let a=nil
a<<FHEAD.hw=finalHw
a<<FHEAD.ns=finalNs
WindowWrite(so, a)
//Now write character, shifting to adjust bounding box
let phase=minBlackB
for s=0 to finalNs-1 do
[
let p=outVec+(s+minBlackS)*ohw+minBlackB/16
for b=0 to finalHw-1 do
[
let nextw=p!(b+1)
if b eq finalHw-1 then nextw=0
WindowWrite(so, ((p!b) lshift phase)+(nextw rshift (16-phase)))
]
]
//Now patch up the character description
FLDDP(1, lv p>>CharWidth.WX)
FML(1, xfp)
FSTDP(1, lv p>>CharWidth.WX)
FLDDP(1, lv p>>CharWidth.WY)
FML(1, yfp)
FSTDP(1, lv p>>CharWidth.WY)
p>>CharWidth.H=finalHb
p>>CharWidth.W=finalNs
test finalHb eq 0 then
[
p>>CharWidth.XL=0
p>>CharWidth.YB=0
]
or [
p>>CharWidth.XL=ScaleInteger(p>>CharWidth.XL, 1)+minBlackS
p>>CharWidth.YB=ScaleInteger(p>>CharWidth.YB, 2)+minBlackB
]
FSPut(inVec)
FSPut(sumVec)
FSPut(outVec)
]
// Scale an integer by a factor, governed by abs(which):
// 1 = x, 2 = y.
and ScaleInteger(x, which) = valof
[
FLDI(1, x)
let a=yfp
if (which&1) ne 0 then a=xfp
FML(1, a)
resultis RoundFP(1)
]