FontTuningParametersViewerImpl:
CEDAR MONITOR
IMPORTS ImagerPixelMap, Commander, FontTuningParameters, BitmapEdit, ViewerOps, Imager, Menus, IO, FS, Rope, Process
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;
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];
IF frame#NIL THEN {
imager: Imager.Context ← frame.context;
Action: ENTRY PROC ~ {
IF mouseButton = red THEN imager.ScaleT[2.0]
ELSE IF mouseButton = blue THEN imager.ScaleT[0.5];
};
Action[];
PaintViewer[viewer];
};
};
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;
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.