<> <> <> <<>> DIRECTORY Basics, AIS, FS, ImagerPixelMaps, IO, IPMaster, RasterFontWriter, Real, Rope, PDFileWriter; IPRasterFontSampleImpl: CEDAR PROGRAM IMPORTS Basics, AIS, FS, ImagerPixelMaps, IO, IPMaster, RasterFontWriter, Real, Rope, PDFileWriter ~ BEGIN OPEN IPMaster; ROPE: TYPE ~ Rope.ROPE; InternalFont: TYPE ~ RasterFontWriter.InternalFont; PixelMap: TYPE ~ ImagerPixelMaps.PixelMap; SetUpTransformation: PROC [stream: STREAM] ~ { PutRational[stream, 254, 3000000]; -- Want to talk in 300 units per inch PutOp[stream, scale]; PutOp[stream, concatt]; }; DoUnderTranslate: PROC [stream: STREAM, x, y: INT, proc: PROC] ~ { PutOp[stream, dosavesimplebody]; PutOp[stream, beginBody]; PutInt[stream, x]; PutInt[stream, y]; PutOp[stream, translate]; PutOp[stream, concatt]; proc[]; PutOp[stream, endBody]; }; Open: PROC [name: ROPE] RETURNS [STREAM] ~ { stream: STREAM ~ FS.StreamOpen[name, $create]; IO.PutRope[stream, "Interpress/Xerox/2.1 "]; PutOp[stream, beginBlock]; PutOp[stream, beginBody]; PutOp[stream, endBody]; PutOp[stream, beginBody]; SetUpTransformation[stream]; RETURN[stream]; }; NewPage: PROC [stream: STREAM] ~ { PutOp[stream, endBody]; PutOp[stream, beginBody]; SetUpTransformation[stream]; }; PutRectangle: PROC [stream: STREAM, x, y, w, h: INT] ~ { PutInt[stream, x]; PutInt[stream, y]; PutInt[stream, w]; PutInt[stream, h]; PutOp[stream, maskrectangle]; }; PutPixelMap: PROC [stream: STREAM, pixelMap: ImagerPixelMaps.PixelMap] ~ TRUSTED { w: ImagerPixelMaps.DeviceRectangle ~ pixelMap.Window; PutInt[stream, w.sSize]; -- xPixels PutInt[stream, (w.fSize+31)/32*32]; -- yPixels PutInt[stream, 1]; -- samplesPerPixel PutInt[stream, 1]; -- maxSampleValue PutInt[stream, 1]; -- samplesInterleaved PutInt[stream, -90]; PutOp[stream, rotate]; PutInt[stream, w.sMin]; -- x translation PutInt[stream, w.fMin]; -- y translation PutOp[stream, translate]; PutOp[stream, concat]; -- m PutBits[ stream: stream, base: pixelMap.refRep.pointer, wordsPerLine: pixelMap.refRep.rast, sMin: pixelMap.sMin, fMin: pixelMap.fMin, sSize: pixelMap.sSize, fSize: pixelMap.fSize ]; -- bits, bits, bits PutOp[stream, makepixelarray]; }; Finish: PROC [stream: STREAM] ~ { PutOp[stream, endBody]; PutOp[stream, endBlock]; IO.Close[stream]; }; MakeSample: PROC [ipFileName: ROPE] ~ { stream: STREAM _ Open[ipFileName]; k: NAT _ 1; leftMargin: INT _ 0; bottomMargin: INT _ 0; columnMargin: INT _ 0; baseline: INT _ 0; baselineStart: INT _ 0; inch: INT _ 300; wPixels: INT _ 85*inch/10; hPixels: INT _ 11*inch; linewidth: INT _ Real.RoundLI[lineInches*inch]; IF landscape THEN { PutInt[stream, wPixels]; PutInt[stream, 0]; PutOp[stream, translate]; PutOp[stream, concatt]; PutInt[stream, 90]; PutOp[stream, rotate]; PutOp[stream, concatt]; }; baseline _ baselineStart _ (IF landscape THEN wPixels ELSE hPixels) - inch; leftMargin _ inch; columnMargin _ leftMargin/2; bottomMargin _ inch; k _ 1; FOR p: LIST OF RopePair _ rasterFontFileNames, p.rest UNTIL p = NIL DO myText: ROPE _ text.Concat[p.first.id]; length: INT _ myText.Length; start: INT _ 0; font: RasterFontWriter.InternalFont _ RasterFontWriter.Load[p.first.name]; baselineskip: INT _ Real.RoundLI[(1.0+leading)*font.bitsPerEmQuad]; WHILE start < length DO lineChars: INT _ FindLineBreak[myText, start, linewidth, font]; sWidth: REAL _ 0; fWidth: REAL _ 0; FOR i: INT IN [start..start+lineChars) DO c: CHAR _ myText.Fetch[i]; charRep: RasterFontWriter.InternalCharRep _ font.charRep[c]; pm: ImagerPixelMaps.PixelMap ~ charRep.pixels.Trim; y: INT _ baseline-Real.RoundLI[sWidth]; x: INT _ leftMargin+Real.RoundLI[fWidth]; proc: PROC ~ { PutPixelMap[stream, pm]; PutOp[stream, maskpixel]; }; IF pm.sSize # 0 AND pm.fSize # 0 THEN DoUnderTranslate[stream, x, y, proc]; sWidth _ sWidth + charRep.sWidth; fWidth _ fWidth + charRep.fWidth; ENDLOOP; start _ start + lineChars; baseline _ baseline - baselineskip; IF baseline <= bottomMargin THEN { baseline _ baselineStart; leftMargin _ leftMargin + linewidth + columnMargin; }; ENDLOOP; k _ k + 1; baseline _ baseline - baselineskip; ENDLOOP; Finish[stream]; }; fontPerColumn: BOOLEAN _ TRUE; lineInches: REAL _ 6.5; MakeSamplePixels: PROC [action: PROC [pm: ImagerPixelMaps.PixelMap], inch: INT, pageBB: ImagerPixelMaps.DeviceRectangle] ~ { k: NAT _ 1; wPixels: INT _ pageBB.fSize; hPixels: INT _ pageBB.sSize; linewidth: INT _ Real.RoundLI[lineInches*inch]; leftMargin: INT _ 0; bottomMargin: INT _ 0; columnMargin: INT _ 0; baseline: INT _ 0; baselineStart: INT _ 0; top: INT ~ (IF landscape THEN wPixels ELSE hPixels); baseline _ baselineStart _ top - inch; leftMargin _ inch; columnMargin _ leftMargin/2; bottomMargin _ inch; k _ 1; FOR p: LIST OF RopePair _ rasterFontFileNames, p.rest UNTIL p = NIL DO myText: ROPE _ text.Concat[p.first.id]; length: INT _ myText.Length; start: INT _ 0; font: RasterFontWriter.InternalFont _ RasterFontWriter.Load[p.first.name]; baselineskip: INT _ Real.RoundLI[(1.0+leading)*font.bitsPerEmQuad]; WHILE start < length DO lineChars: INT _ FindLineBreak[myText, start, linewidth, font]; sWidth: REAL _ 0; fWidth: REAL _ 0; FOR i: INT IN [start..start+lineChars) DO c: CHAR _ myText.Fetch[i]; charRep: RasterFontWriter.InternalCharRep _ font.charRep[c]; pm: ImagerPixelMaps.PixelMap ~ charRep.pixels.Trim; y: INT _ baseline-Real.RoundLI[sWidth]; x: INT _ leftMargin+Real.RoundLI[fWidth]; IF c # ' AND c # '\n AND pm.sSize # 0 AND pm.fSize # 0 THEN action[pm.ShiftMap[top-y, x]]; sWidth _ sWidth + charRep.sWidth; fWidth _ fWidth + charRep.fWidth; ENDLOOP; start _ start + lineChars; baseline _ baseline - baselineskip; IF baseline <= bottomMargin THEN { baseline _ baselineStart; leftMargin _ leftMargin + linewidth + columnMargin; }; ENDLOOP; k _ k + 1; baseline _ baseline - baselineskip; IF fontPerColumn THEN { baseline _ baselineStart; leftMargin _ leftMargin + linewidth + columnMargin; }; ENDLOOP; }; StorePixelMap: PROC [aisFileName: ROPE, source: ImagerPixelMaps.PixelMap, bitmap: BOOLEAN _ TRUE, comment: ROPE _ NIL] ~ TRUSTED { output: AIS.FRef _ AIS.CreateFile[name: aisFileName, raster: NEW[AIS.RasterPart _ [ scanCount: source.sSize, scanLength: source.fSize, scanMode: rd, bitsPerPixel: IF source.refRep.lgBitsPerPixel = 0 AND bitmap THEN 0 ELSE Basics.BITSHIFT[1, source.refRep.lgBitsPerPixel], linesPerBlock: -1, paddingPerBlock: 65535 ]]]; outputWindow: AIS.WRef _ AIS.OpenWindow[output]; lineMap: ImagerPixelMaps.PixelMap _ ImagerPixelMaps.Create[source.refRep.lgBitsPerPixel, [source.sOrigin+source.sMin, source.fOrigin+source.fMin, 1, source.fSize]]; lineBufferDesc: AIS.Buffer _ [length: lineMap.refRep.words, addr: lineMap.refRep.pointer]; AIS.WriteComment[output, comment]; FOR i: NAT IN [0..source.sSize) DO lineMap.Clear; lineMap.Transfer[source]; lineMap.sOrigin _ lineMap.sOrigin + 1; AIS.UnsafeWriteLine[outputWindow, lineBufferDesc, i]; ENDLOOP; AIS.CloseFile[output]; }; MultipleOf32: PROC [nat: NAT] RETURNS [NAT] ~ { RETURN [Basics.BITAND[nat + 31, CARDINAL.LAST-31]] }; FindBB: PROC [inch: INT, pageBB: ImagerPixelMaps.DeviceRectangle] RETURNS [ImagerPixelMaps.DeviceRectangle] ~ { sMin: INT _ INT.LAST; fMin: INT _ INT.LAST; sMax: INT _ INT.FIRST; fMax: INT _ INT.FIRST; action: PROC [pm: ImagerPixelMaps.PixelMap] ~ { sMin _ MIN[sMin, pm.sOrigin+pm.sMin]; sMax _ MAX[sMax, pm.sOrigin+pm.sMin+pm.sSize]; fMin _ MIN[fMin, pm.fOrigin+pm.fMin]; fMax _ MAX[fMax, pm.fOrigin+pm.fMin+pm.fSize]; }; MakeSamplePixels[action, inch, pageBB]; IF sMin > sMax THEN RETURN [[0, 0, 0, 0]] ELSE RETURN [[sMin, fMin, MultipleOf32[sMax-sMin], MultipleOf32[fMax-fMin]]] }; MakeSampleAIS: PROC [aisFileName: ROPE, comment: ROPE, inch: INT, longEdgeFeed: BOOLEAN _ TRUE] ~ { pageBB: ImagerPixelMaps.DeviceRectangle ~ IF longEdgeFeed THEN [0, 0, 85*inch/10, 11*inch] ELSE [0, 0, 11*inch, 85*inch/10]; w: ImagerPixelMaps.DeviceRectangle ~ FindBB[inch, pageBB]; pixelMap: ImagerPixelMaps.PixelMap _ ImagerPixelMaps.Create[0, w]; action: PROC [pm: ImagerPixelMaps.PixelMap] ~ {pixelMap.Transfer[pm, [or, null]]}; pixelMap.Clear; MakeSamplePixels[action, inch, pageBB]; StorePixelMap[aisFileName, pixelMap, TRUE, comment]; }; tileBits: ARRAY [0..16) OF PACKED ARRAY [0..16) OF {O,X} _ [ [X,X,X,X,X,X,X,X,O,O,O,O,O,O,O,O], [X,X,X,X,X,X,X,X,O,O,O,O,O,O,O,O], [X,X,X,X,X,X,X,X,O,O,O,O,O,O,O,O], [X,X,X,X,X,X,X,X,O,O,O,O,O,O,O,O], [X,X,X,X,X,X,X,X,O,O,O,O,O,O,O,O], [X,X,X,X,X,X,X,X,O,O,O,O,O,O,O,O], [X,X,X,X,X,X,X,X,O,O,O,O,O,O,O,O], [X,X,X,X,X,X,X,X,O,O,O,O,O,O,O,O], [O,O,O,O,O,O,O,O,X,X,X,X,X,X,X,X], [O,O,O,O,O,O,O,O,X,X,X,X,X,X,X,X], [O,O,O,O,O,O,O,O,X,X,X,X,X,X,X,X], [O,O,O,O,O,O,O,O,X,X,X,X,X,X,X,X], [O,O,O,O,O,O,O,O,X,X,X,X,X,X,X,X], [O,O,O,O,O,O,O,O,X,X,X,X,X,X,X,X], [O,O,O,O,O,O,O,O,X,X,X,X,X,X,X,X], [O,O,O,O,O,O,O,O,X,X,X,X,X,X,X,X] ]; MakeSamplePD: PROC [pdFileName: ROPE, res: INT _ 300, longEdgeFeed: BOOLEAN _ TRUE] ~ { pageBB: ImagerPixelMaps.DeviceRectangle ~ IF longEdgeFeed THEN [0, 0, 85*res/10, 11*res] ELSE [0, 0, 11*res, 85*res/10]; pd: PDFileWriter.PDState _ PDFileWriter.Create[fileName: pdFileName, deviceCode: hornet, sResolution: res, fResolution: res, imageSSize: pageBB.sSize, imageFSize: pageBB.fSize]; scratch: REF ImagerPixelMaps.PixelMapRep _ NIL; action: PROC [pm: ImagerPixelMaps.PixelMap] ~ { w: ImagerPixelMaps.DeviceRectangle _ (pm _ pm.Clip[pageBB].Copy[scratch]).Window; p: LONG POINTER _ pm.refRep.pointer; rast: LONG CARDINAL _ pm.refRep.rast; deliverProc: PROC [line: PROC [LONG POINTER]] ~ TRUSTED { THROUGH [0..w.sSize) DO line[p]; p _ p + rast; ENDLOOP; }; IF w.sSize = 0 THEN RETURN; pd.MaskSamples[w.sMin, w.fMin, w.sSize, w.fSize, deliverProc]; scratch _ pm.refRep; }; barwidth: NAT _ res/2; tileReference: LONG CARDINAL; TRUSTED {tileReference _ pd.LoadContiguousColorTile[0, 0, 0, 16, 16, @tileBits]}; MakeSamplePixels[action, res, pageBB]; pd.SetColorTile[black, tileReference]; pd.MaskRectangle[0, 0, barwidth, pageBB.fSize]; pd.MaskRectangle[0, 0, pageBB.sSize, barwidth]; pd.MaskRectangle[0, pageBB.fSize-barwidth, pageBB.sSize, barwidth]; pd.MaskRectangle[pageBB.sSize-barwidth, 0, barwidth, pageBB.fSize]; pd.EndPage; pd.Close; }; FindLineBreak: PROC [myText: ROPE, start: INT, width: REAL, font: RasterFontWriter.InternalFont] RETURNS [charCount: INT _ 0] ~ { FOR i: INT IN [0..myText.Length-start) DO c: CHAR _ myText.Fetch[start+i]; charRep: RasterFontWriter.InternalCharRep _ font.charRep[c]; width _ width - charRep.fWidth; IF width <= 0 THEN { IF charCount = 0 THEN charCount _ MAX[i+1, 1]; WHILE start+charCount < myText.Length AND myText.Fetch[start+charCount] = ' DO charCount _ charCount + 1; ENDLOOP; RETURN; }; IF c = '\n THEN { charCount _ i+1; RETURN; }; IF c = ' THEN charCount _ i+1; ENDLOOP; charCount _ myText.Length-start; }; AddFont: PROC [rasterFontFileName: ROPE, id: ROPE _ NIL] ~ { IF id = NIL THEN id _ Rope.Concat["\n", rasterFontFileName]; rasterFontFileNames _ CONS[[rasterFontFileName, id], rasterFontFileNames]; }; RopePair: TYPE ~ RECORD [name, id: ROPE]; rasterFontFileNames: LIST OF RopePair; leading: REAL _ 0.2; -- in ems landscape: BOOLEAN _ FALSE; zapf: ROPE _ "I think that there is no question that we have to create a new concept in the typographic field. This indicates the common trend which is part of our present day and future living. There is a permanent movement in so many fields towards the future. We too often look backwards in our love for the oldtimers in types; we are sometimes still captured by false romanticism, and we should spend part of our activities for new developments. -- Hermann Zapf ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz 0123456789 !@#$%~&*()-+=|\\{}[]:;\"\'<>,.?/"; grimm: ROPE _ "In olden times when wishing still helped one, there lived a king whose daughters were all beautiful, but the youngest was so beautiful that the sun itself, which has seen so much, was astonished whenever it shone in her face. Close by the king's castle lay a great dark forest, and under an old lime-tree in the forest was a well, and when the day was very warm, the king's child went out into the forest and sat down by the side of the cool fountain, and when she was bored she took a golden ball, and threw it up on high and caught it, and this ball was her favorite plaything."; text: ROPE _ grimm; END.