DIRECTORY ImagerRaster, FontTune, Basics, Process, DynamicBits, Imager, ImagerPixelMap, ImagerTransformation, Real, Rope, GridModulation, FontTuningParameters, ImagerPixelSeq, ImagerMaskCapture, ImagerBackdoor, ImagerOps; FontTuneImpl: CEDAR PROGRAM IMPORTS Process, DynamicBits, Imager, ImagerPixelMap, ImagerTransformation, Real, Rope, GridModulation, FontTuningParameters, ImagerPixelSeq, ImagerMaskCapture, ImagerBackdoor, ImagerOps EXPORTS FontTune ~ BEGIN PixelMap: TYPE ~ ImagerPixelMap.PixelMap; DeviceRectangle: TYPE ~ ImagerPixelMap.DeviceRectangle; FontTuner: TYPE ~ ImagerRaster.FontTuner; Transformation: TYPE ~ ImagerTransformation.Transformation; Data: TYPE ~ REF DataRep; DataRep: TYPE ~ RECORD [ param: FontTuningParameters.Ref, model: DynamicBits.Model, runSizeMap: GridModulation.RunSizeMap, antialiasingFilter: PixelMap, pmScratch: REF ImagerPixelMap.PixelMapRep _ NIL ]; maxBitSize: NAT _ 600; CreateFontTuner: PUBLIC PROC [name: Rope.ROPE] RETURNS [FontTuner] ~ { param: FontTuningParameters.Ref ~ FontTuningParameters.Load[Rope.Concat[name, ".fontTune"]]; printerModel: DynamicBits.PrinterModel ~ { intensity: REAL _ param.intensity[encoding]; scaledIntensity: REAL _ (intensity-minMeanIntensity) / (maxMeanIntensity-minMeanIntensity); RETURN [Real.RoundLI[scaledIntensity*DynamicBits.Intensity.LAST], Real.RoundLI[param.noiseWeight*param.noisePenalty[encoding]]] }; minMeanIntensity: REAL _ 9999999999.9; maxMeanIntensity: REAL _ 0; FOR c: NAT IN [0..param.intensity.length) DO minMeanIntensity _ MIN[minMeanIntensity, param.intensity[c]]; maxMeanIntensity _ MAX[maxMeanIntensity, param.intensity[c]]; ENDLOOP; RETURN [NEW[ImagerRaster.FontTunerRep _ [ proc: MyFontTunerProc, data: NEW[DataRep _ [ param: param, model: DynamicBits.CreatePrinterModel[param.printerModelNeighborhood, printerModel, param.comparisonKernel], runSizeMap: GridModulation.SimpleRunSizeMap[maxBitSize, param.gridReductionFactor], antialiasingFilter: GridModulation.ComputeConvolutionKernel[param.gridReductionFactor] ]], propList: NIL ]]] }; MyFontTunerProc: ImagerRaster.FontTunerProc ~ { data: Data ~ NARROW[self.data]; param: FontTuningParameters.Ref ~ data.param; T: Transformation ~ ImagerTransformation.TranslateTo[ImagerBackdoor.GetT[context], [0,0]]; bigT: Transformation ~ ImagerTransformation.PreScale[T, param.gridReductionFactor]; bigChar: PixelMap ~ ImagerMaskCapture.CaptureBitmap[charProc, bigT]; IF bigChar.sSize > maxBitSize OR bigChar.fSize > maxBitSize THEN {charProc[context]} ELSE { smallChar: PixelMap ~ ConvertPixelMap[bigChar, data]; pa: Imager.PixelArray ~ ImagerOps.PixelArrayFromPixelMaps[LIST[smallChar], NIL]; mask: PROC ~ { Imager.ConcatT[context, ImagerTransformation.Invert[T]]; Imager.MaskPixel[context, pa]; }; metrics: PROC ~ { Imager.SetNoImage[context, TRUE]; charProc[context]; -- ugh. Do not need this if the 3.0 font stuff is right. }; Imager.DoSave[context, mask]; Imager.DoSave[context, metrics]; }; }; VideoInvert: PROC [pm: PixelMap] RETURNS [PixelMap] ~ { pm.Fill[pm.Window, CARDINAL.LAST, [xor, null]]; RETURN [pm]; }; Threshold: PROC [pm: PixelMap] RETURNS [PixelMap] ~ { bb: DeviceRectangle _ pm.Window; new: PixelMap _ ImagerPixelMap.Create[0, bb]; seq: ImagerPixelSeq.PixelSeq _ ImagerPixelSeq.ObtainScratch[bb.fSize]; FOR s: INTEGER IN [bb.sMin..bb.sMin+bb.sSize) DO seq.LoadF[s, bb.fMin, bb.fSize, pm]; FOR j: NAT IN [0..bb.fSize) DO seq[j] _ seq[j] / 128; ENDLOOP; seq.StoreF[s, bb.fMin, bb.fSize, new]; ENDLOOP; ImagerPixelSeq.ReleaseScratch[seq]; RETURN [new]; }; alternating: BOOL _ TRUE; ConvertPixelMap: PROC [pixelMap: PixelMap, data: Data] RETURNS [PixelMap] ~ { param: FontTuningParameters.Ref ~ data.param; antialiasingFilter: PixelMap ~ GridModulation.ComputeConvolutionKernel[param.gridReductionFactor]; sScratch: GridModulation.EdgeProjection _ GridModulation.CreateEdgeProjection[TRUE, 0, pixelMap.sSize, param.gridReductionFactor]; fScratch: GridModulation.EdgeProjection _ GridModulation.CreateEdgeProjection[FALSE, 0, pixelMap.fSize, param.gridReductionFactor]; model: DynamicBits.Model ~ data.model; rawGray: PixelMap _ GridModulation.ConvertGrayPixelMap[ pixelMap: pixelMap, reductionFactor: param.gridReductionFactor, param: param.gridParam, runSizeMap: data.runSizeMap, kernel: antialiasingFilter, sScratch: sScratch, fScratch: fScratch, pmScratch: data.pmScratch ]; gray: PixelMap _ VideoInvert[DynamicBits.AddBorder[rawGray.Trim[0], 2, 0]]; new: PixelMap _ Threshold[gray]; fixedBits: PixelMap; scratch: REF _ NIL; DoTestPass: PROC [passNumber: NAT] ~ { w: DeviceRectangle ~ gray.Window; swath: DeviceRectangle _ [w.sMin, w.fMin, w.sSize, param.swathWidth]; IF alternating AND passNumber MOD 2 = 1 THEN { FOR f: INT DECREASING IN [w.fMin..w.fMin+w.fSize-param.swathWidth) DO swath: DeviceRectangle _ [w.sMin, f, w.sSize, param.swathWidth]; scratch _ DynamicBits.TuneSwath[blurred, new, fixedBits, swath, model, scratch]; Process.CheckForAbort[]; ENDLOOP; } ELSE { FOR f: INT IN [w.fMin..w.fMin+w.fSize-param.swathWidth) DO swath: DeviceRectangle _ [w.sMin, f, w.sSize, param.swathWidth]; scratch _ DynamicBits.TuneSwath[blurred, new, fixedBits, swath, model, scratch]; Process.CheckForAbort[]; ENDLOOP; }; }; blurred: PixelMap _ gray.Copy; DynamicBits.Convolve[blurred, model.kernel, 255]; fixedBits _ DynamicBits.FindFixedBits[blurred, -model.neighborhood.sMin-model.kernel.sOrigin]; FOR i: INT IN [0..param.tuningPasses) DO DoTestPass[i]; ENDLOOP; new _ VideoInvert[new]; RETURN [new]; }; END. ΦFontTuneImpl.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. Michael Plass, November 27, 1985 6:17:44 pm PST [self: ImagerRaster.FontTuner, charProc: PROC [...], context: Imager.Context] Κo˜code™Kšœ Οmœ1™