<> <> <> <> <<>> DIRECTORY ImagerPixelMap, Commander, FontTuningParameters, BitmapEdit, ViewerOps, ViewerClasses, Imager, Menus, Real, IO, FS, Rope, Process; FontTuningParametersViewerImpl: CEDAR MONITOR IMPORTS ImagerPixelMap, Commander, FontTuningParameters, BitmapEdit, ViewerOps, Imager, Menus, IO, FS, Rope, Process ~ BEGIN ROPE: TYPE ~ Rope.ROPE; Frame: TYPE ~ REF FrameRep; FrameRep: TYPE ~ RECORD [ yScrollAmount: INT _ 0, bitmapViewer: ViewerClasses.Viewer, oldBits: CARDINAL _ CARDINAL.LAST, parameters: FontTuningParameters.Ref ]; subx: INT _ 120; suby: INT _ 45; subsize: INT _ 40; NewBits: ENTRY PROC [viewer: ViewerClasses.Viewer] RETURNS [new: BOOLEAN _ FALSE] ~ { ENABLE UNWIND => NULL; frame: Frame _ NARROW[viewer.data]; IF frame#NIL THEN { pm: ImagerPixelMap.PixelMap _ BitmapEdit.GetBitmap[frame.bitmapViewer].pixelMap; bits: CARDINAL _ Encode[pm]; new _ bits # frame.oldBits; }; }; RefreshProcess: PROC [viewer: ViewerClasses.Viewer] ~ { UNTIL viewer.destroyed DO Process.Pause[Process.MsecToTicks[200]]; IF NewBits[viewer] THEN PaintViewer[viewer]; ENDLOOP; }; ViewerInit: ViewerClasses.InitProc ~ { menu: Menus.Menu _ Menus.CreateMenu[1]; param: FontTuningParameters.Ref _ FontTuningParameters.Load[self.file]; subViewer: ViewerClasses.Viewer _ BitmapEdit.CreateBitmapViewer[bw, bh, [parent: self, wx: subx, wy: suby, wh: subsize, ww: subsize]]; Menus.InsertMenuEntry[menu, Menus.CreateEntry[name: "Zoom", proc: ZoomHit]]; self.menu _ menu; self.data _ NEW[FrameRep _ [ yScrollAmount: 0, bitmapViewer: subViewer, oldBits: 0, parameters: param ]]; TRUSTED {Process.Detach[FORK RefreshProcess[self]]}; }; PaintViewer: PROC[viewer: ViewerClasses.Viewer] ~ { ViewerOps.PaintViewer[viewer, client]; }; ZoomHit: Menus.ClickProc ~ { viewer: ViewerClasses.Viewer _ NARROW[parent]; frame: Frame _ NARROW[viewer.data]; <> <> <> <> <> <<};>> <> <> <<};>> }; ViewerScroll: ViewerClasses.ScrollProc ~ { frame: Frame _ NARROW[self.data]; Action: ENTRY PROC ~ { ENABLE UNWIND => NULL; IF op = thumb THEN {frame.yScrollAmount _ 0; RETURN}; IF op = down THEN amount _ -amount; frame.yScrollAmount _ frame.yScrollAmount - amount; RETURN; }; IF frame = NIL OR self.destroyed OR op = query THEN RETURN [0, 100]; Action[]; PaintViewer[self]; RETURN [0, 100]; }; ViewerPaint: ENTRY ViewerClasses.PaintProc ~ { ENABLE UNWIND => NULL; frame: Frame ~ NARROW[self.data]; yScrollAmount: INT ~ frame.yScrollAmount; PaintFrame[context, frame]; }; bw: INT _ 3; bh: INT _ 3; bitSize: INT _ 3; gray: REAL _ 0.3; PaintItem: PROC [imager: Imager.Context, param: FontTuningParameters.Ref, bits: CARDINAL, x: REAL, y: REAL] ~ { action: PROC ~ { t: CARDINAL _ bits; imager.TranslateT[[x, y]]; FOR yy: INT IN [0..bw) DO FOR xx: INT DECREASING IN [0..bh) DO IF t MOD 2 = 1 THEN imager.MaskRectangle[[xx*bitSize, yy*bitSize, bitSize, bitSize]]; t _ t/2; ENDLOOP; ENDLOOP; IF bits < param.intensity.length THEN { intensity: REAL _ param.intensity[bits]; stdDev: REAL _ param.noisePenalty[bits]; imager.SetGray[gray]; imager.MaskRectangle[[bitSize-2, bh*bitSize+intensity-stdDev/2, bitSize+4, stdDev]]; imager.SetColor[Imager.black]; imager.MaskRectangle[[bitSize, bh*bitSize, bitSize, intensity]]; }; }; imager.DoSaveAll[action]; }; Encode: PROC [pm: ImagerPixelMap.PixelMap] RETURNS [bits: CARDINAL _ 0] ~ { w: ImagerPixelMap.DeviceRectangle ~ pm.Window; FOR s: INTEGER IN [w.sMin..w.sMin+w.sSize) DO FOR f: INTEGER IN [w.fMin..w.fMin+w.fSize) DO bits _ 2*bits + pm.GetPixel[s, f]; ENDLOOP; ENDLOOP; }; FlipX: PROC [bits: CARDINAL] RETURNS [CARDINAL] ~ { a: ARRAY [0..5] OF ARRAY [0..5] OF [0..1]; FOR i: INT DECREASING IN [0..bh) DO FOR j: INT DECREASING IN [0..bw) DO a[i][j] _ bits MOD 2; bits _ bits / 2; ENDLOOP; ENDLOOP; bits _ 0; FOR i: INT IN [0..bh) DO FOR j: INT DECREASING IN [0..bw) DO bits _ 2*bits + a[i][j]; ENDLOOP; ENDLOOP; RETURN [bits] }; FlipY: PROC [bits: CARDINAL] RETURNS [CARDINAL] ~ { a: ARRAY [0..5] OF ARRAY [0..5] OF [0..1]; FOR i: INT DECREASING IN [0..bh) DO FOR j: INT DECREASING IN [0..bw) DO a[i][j] _ bits MOD 2; bits _ bits / 2; ENDLOOP; ENDLOOP; bits _ 0; FOR i: INT DECREASING IN [0..bh) DO FOR j: INT IN [0..bw) DO bits _ 2*bits + a[i][j]; ENDLOOP; ENDLOOP; RETURN [bits] }; PaintFrame: INTERNAL PROC [imager: Imager.Context, frame: Frame] ~ { pm: ImagerPixelMap.PixelMap _ BitmapEdit.GetBitmap[frame.bitmapViewer].pixelMap; bits: CARDINAL _ Encode[pm]; dx: INT ~ 2*bw*bitSize; x0: INT ~ subx+(bw*bitSize)/2-dx; y: INT ~ suby+subsize+bh*bitSize; PaintItem[imager, frame.parameters, bits, x0, y]; PaintItem[imager, frame.parameters, FlipX[bits], x0+dx, y]; PaintItem[imager, frame.parameters, FlipY[bits], x0+2*dx, y]; PaintItem[imager, frame.parameters, FlipX[FlipY[bits]], x0+3*dx, y]; frame.oldBits _ bits; }; viewerClass: ViewerClasses.ViewerClass _ NEW [ViewerClasses.ViewerClassRec _ [ init: ViewerInit, paint: ViewerPaint, scroll: ViewerScroll, icon: tool ]]; flavor: ViewerClasses.ViewerFlavor ~ $FontTuningParametersViewer; Break: PROC [char: CHAR] RETURNS [IO.CharClass] = { IF char = '_ OR char = '; THEN RETURN [break]; IF char = ' OR char = ' OR char = ', OR char = '\n THEN RETURN [sepr]; RETURN [other]; }; GetToken: PROC [stream: IO.STREAM] RETURNS [rope: ROPE _ NIL] = { rope _ stream.GetTokenRope[Break ! IO.EndOfStream => CONTINUE].token; }; ViewFontTuningParametersCommand: Commander.CommandProc ~ { paramName: ROPE _ GetToken[IO.RIS[cmd.commandLine]]; IF paramName.Length = 0 THEN {cmd.out.PutRope[help]; RETURN}; paramName _ FS.ExpandName[paramName.Concat[".fontTune"]].fullFName; [] _ ViewerOps.CreateViewer[$FontTuningParametersViewer, [name: Rope.Concat["Viewing ", paramName], file: paramName] ! FS.Error => {cmd.out.PutRope[error.explanation]; CONTINUE}; FontTuningParameters.BadToken => { cmd.out.PutF["Bad token \"%g\" at location %g of %g.\n", IO.rope[token], IO.int[location], IO.rope[fileName]]; CONTINUE } ]; }; help: ROPE _ "Supply name of font tuning parameters\n"; Commander.Register["ViewFontTuningParameters", ViewFontTuningParametersCommand, help]; ViewerOps.RegisterViewerClass[flavor, viewerClass]; END.