<> <> <> <> DIRECTORY Imager, ImagerBasic USING [PixelArray], ImagerTransform USING [InverseTransform, Contents], ImagerPD USING[PDFileDescription, PDFileDescriptionRep, Hornet], PDFileFormat, Real USING [Fix], SampledColors USING[bitmap, DrawImage], UFFileManager USING[KeyOf], UFPressFontReader USING[Size, Range, Family, Face, Resolution, GetCharInfo, GetCharRaster, CharInfo, NumberOfFontsInFile], Font USING [Key, CreateScaled, FONT, Box, FormattingBox], Rope USING [ROPE, Cat, Substr], Convert USING [RopeFromInt], FS USING [ExpandName, ComponentPositions], IO USING [time, rope, real, int, PutFR], BasicTime, PrintAC; PrintACImpl: CEDAR PROGRAM IMPORTS Imager, SampledColors, Rope, ImagerTransform, Real, UFFileManager, UFPressFontReader, Font, Convert, ImagerPD, FS, IO, BasicTime EXPORTS = BEGIN OPEN PrintAC; ROPE: TYPE = Rope.ROPE; <> doChars: BOOLEAN _ TRUE; doPages: BOOLEAN _ FALSE; PrintACChars: PUBLIC PROC[name: ROPE, device: DeviceType, scale: REAL, chars: ROPE] RETURNS [pd: ROPE]; <> PrintACCodes: PUBLIC PROC[name: ROPE, device: DeviceType, scale: REAL, codes0, codes1, codes2, codes3, codes4: Subrange _ [0,0]] RETURNS [pd: ROPE]; <> PrintACFile: PUBLIC PROC[name: ROPE, device: DeviceType, scale: REAL] RETURNS [ROPE] = { <> acFont: InternalFont; base, wdir, label: ROPE; maxH, maxW, gl, gt: REAL _ 0; areaW, areaH, boxW, boxH: REAL; nw, nh: INT; bc, nchars: NAT; ctx: Imager.Context; [base, wdir] _ GetName[name]; acFont _ LoadAC[Rope.Cat[wdir,base,".ac"]]; ctx _ OpenPD[Rope.Cat[wdir,base,".pd"], device]; maxW _ acFont.maxW*scale; --max size a function of scale maxH _ (acFont.ascent+acFont.descent)*scale; <> areaW _ pageW-right-left-5*captions.nwidth; --in points areaH _ pageH-top-bottom-4*captions.height; [[boxW, boxH]] _ ImagerTransform.InverseTransform[[maxW, maxH], ctx.state.T]; --in points boxW _ boxW+8; boxH _ boxH+8; --add the gridline space plus some white space nw _ Real.Fix[areaW/boxW]; --determine the count nh _ Real.Fix[areaH/boxH]; label _ IO.PutFR["%g.ac, scale=%g, time= %g", IO.rope[base], IO.real[scale], IO.time[]]; bc _ VAL[acFont.bc]; nchars _ ORD[acFont.ec-VAL[bc]]; IF nchars > nw*nh THEN { -- print multiple pages page: INT _ 1; UNTIL nw*nh >= nchars DO [gl, gt] _ GridAndTitle[ctx, bc, nw, nh, boxW, boxH, IO.PutFR["%g page = %g", IO.rope[label], IO.int[page]]]; PrintChars[ctx, acFont, VAL[bc], gl, gt, nw, nh, boxW, boxH, scale]; [] _ Imager.SpecialOp[ctx, $NewPage, NIL]; --resets the context ctx.ScaleT[0.0254/72]; --meters to points bc _ bc+nw*nh; nchars _ ORD[acFont.ec-VAL[bc]]; page _ page+1; ENDLOOP; label _ IO.PutFR["%g page = %g", IO.rope[label], IO.int[page]]; --for last page }; <> IF nw*nh > nchars THEN {nh _ nchars/nw; IF nh*nw"]; wdir _ Rope.Cat[wdir, Rope.Substr[full, cp.subDirs.start, cp.subDirs.length], ">"]; }; PrintChars: PROC [ctx: Imager.Context, acFont: InternalFont, bc: CHAR, gl, gt: REAL, nw, nh: INT, boxW,boxH, scale: REAL] = { <> bitsW, bitsH, sx, sy: REAL; char: CHAR _ bc; DoRow: PROC = { FOR i: INT IN [0..nw) DO IF acFont.charRep[char].pixels#NIL THEN { dx: REAL _ (bitsW-acFont.charRep[char].width)/2.0; --center it Imager.TranslateT[ctx, dx, 0]; SampledColors.DrawImage[ctx,acFont.charRep[char].pixels,SampledColors.bitmap]; Imager.TranslateT[ctx,bitsW-dx,0]; } ELSE Imager.TranslateT[ctx, bitsW, 0]; char _ char+1; IF char > acFont.ec THEN EXIT; ENDLOOP; }; <> Imager.TranslateT[ctx, gl+1, gt-2-3]; <> [[sx, , , ,sy, ]] _ ImagerTransform.Contents[ctx.state.T]; bitsW _ sx*boxW/scale; bitsH _ sy*boxH/scale; Imager.Scale2T[ctx, scale/sx, scale/sy]; --Convert to scaled bits Imager.TranslateT[ctx, 0, -acFont.ascent]; --drop down by the maximum ascent FOR i: INT IN [0..nh) DO Imager.DoSaveAll[ctx, DoRow]; IF char > acFont.ec THEN EXIT; Imager.TranslateT[ctx, 0, -bitsH]; ENDLOOP; }; OpenPD: PROC[name: ROPE, device: DeviceType] RETURNS [ctx: Imager.Context] = { pdDescr: ImagerPD.PDFileDescription _ SELECT device FROM hornet => ImagerPD.Hornet[name], platemaker => PlatemakerPD[name], versatec => VersatecPD[name], ENDCASE => ERROR; ctx _ Imager.Create[$PD, pdDescr]; ctx.ScaleT[0.0254/72]; --meters to points }; GridAndTitle: PROC [ctx: Imager.Context, first: NAT, nw, nh: INT, boxW,boxH: REAL, label: ROPE] RETURNS [gridLeft, gridTop: REAL]= { <> gw,gh: REAL; val: NAT; showVal: PROC = { Imager.ShowCharacters[ctx,Convert.RopeFromInt[from: val, base: 8, showRadix: TRUE]]}; Imager.SetFont[ctx, captions.font]; Imager.SetXY[ctx,[left, bottom]]; Imager.ShowCharacters[ctx,label]; --font name label <> gridLeft _ left+5*captions.nwidth; gridTop _ pageH-top-2*captions.height; gw _ nw*boxW+2; gh _ nh*boxH; FOR i: INT IN [0..nh] DO Imager.MaskRectangle[ctx,gridLeft, gridTop-i*boxH, gw, 2]; ENDLOOP; FOR i: INT IN [0..nw] DO Imager.MaskRectangle[ctx,gridLeft+i*boxW, gridTop-gh, 2, gh]; ENDLOOP; Imager.SetXY[ctx,[gridLeft+boxW/2-captions.nwidth, gridTop+captions.height]]; val _ 0; FOR i: INT IN [0..nw) DO --top line Imager.DoSaveAll[ctx,showVal]; Imager.SetXYRel[ctx,[boxW, 0]]; val _ val+1; ENDLOOP; Imager.SetXY[ctx,[left, gridTop-boxH/2-captions.height/2]]; val _ first; FOR i: INT IN [0..nh) DO Imager.DoSaveAll[ctx,showVal]; Imager.SetXYRel[ctx,[0, -boxH]]; val _ val+nw; ENDLOOP; RETURN[gridLeft, gridTop] }; FontNotFound: SIGNAL = CODE; <> InternalFont: TYPE ~ REF InternalFontRep; InternalFontRep: TYPE ~ RECORD [ family: Rope.ROPE _ NIL, face: [0..255] _ 0, descent, ascent, maxW: REAL _ 0, bc, ec: CHAR, charRep: ARRAY CHAR OF InternalCharRep ]; InternalCharRep: TYPE ~ RECORD [ width: REAL, pixels: ImagerBasic.PixelArray ]; LoadAC: PROC [fileName: Rope.ROPE] RETURNS [font: InternalFont] ~ TRUSTED { fileKey: Font.Key _ UFFileManager.KeyOf[fileName]; sizeInMeters, bitsPerEmQuad: REAL; IF UFPressFontReader.NumberOfFontsInFile[fileKey] = 0 THEN SIGNAL FontNotFound; sizeInMeters _ UFPressFontReader.Size[[fileKey, 0]]; font _ NEW [InternalFontRep]; [font.bc, font.ec] _ UFPressFontReader.Range[[fileKey, 0]]; font.family _ UFPressFontReader.Family[[fileKey, 0]]; font.face _ UFPressFontReader.Face[[fileKey, 0]]; bitsPerEmQuad _ sizeInMeters*UFPressFontReader.Resolution[[fileKey, 0]].xRes/0.0254; FOR char: CHAR IN [font.bc..font.ec] DO info: UFPressFontReader.CharInfo _ UFPressFontReader.GetCharInfo[[fileKey, 0], char]; pixelArray: ImagerBasic.PixelArray _ UFPressFontReader.GetCharRaster[[fileKey, 0], char]; font.charRep[char] _ [ width: (info.maxX-info.minX)*bitsPerEmQuad, pixels: pixelArray ]; IF font.charRep[char].width > font.maxW THEN font.maxW _ font.charRep[char].width; IF info.maxY > font.ascent THEN font.ascent _ info.maxY; IF ABS[info.minY] > font.descent THEN font.descent _ ABS[info.minY]; ENDLOOP; font.ascent _ font.ascent*bitsPerEmQuad; font.descent _ font.descent*bitsPerEmQuad; }; PlatemakerPD: PROC[name: ROPE] RETURNS [ImagerPD.PDFileDescription] = { param: ImagerPD.PDFileDescription _ NEW[ImagerPD.PDFileDescriptionRep _ PlatemakerTemplate]; param.fileName _ name; RETURN[param]; }; VersatecPD: PROC[name: ROPE] RETURNS [ImagerPD.PDFileDescription] = { param: ImagerPD.PDFileDescription _ NEW[ImagerPD.PDFileDescriptionRep _ VersatecTemplate]; param.fileName _ name; RETURN[param]; }; PlatemakerTemplate: ImagerPD.PDFileDescriptionRep _ [ fileName: NIL, deviceCode: mig, sResolution: 1200, fResolution: 1200, imageSSize: 13200, imageFSize: 10200, nColors: 1, bandSSize: 16, maxLoadWords: 60000, leftovers: TRUE, copies: 1 ]; VersatecTemplate: ImagerPD.PDFileDescriptionRep _ [ fileName: NIL, deviceCode: mig, sResolution: 200, fResolution: 200, imageSSize: 20000, imageFSize: 8000, nColors: 1, bandSSize: 64, maxLoadWords: 60000, leftovers: FALSE, copies: 1 ]; captions: RECORD [ font: Imager.FONT, nwidth: REAL, height: REAL ]; left: REAL _ .5*72; top: REAL _ .75*72; right: REAL _ .5*72; bottom: REAL _ .75*72; pageH: REAL _ 11*72; pageW: REAL _ 8.5*72; Init: PROC = { box: Font.Box; captions.font _ Font.CreateScaled["Xerox/PressFonts/Helvetica/MRR", 10]; box _ Font.FormattingBox[captions.font,'0]; captions.nwidth _ box.xmax-box.xmin; captions.height _ box.ymax-box.ymin; }; END.