DIRECTORY AISFileFormat, FS, Real, Rope, SirPress, TSArtwork, TSOutputPress, TextNode, TSGraphic, IO, TSOutput, TSTypes USING [Dimn, zeroDimn, RealDimn, DimnRatio, bp, Dimensions]; TSIncludeAISImpl: CEDAR PROGRAM IMPORTS FS, Real, Rope, SirPress, TSArtwork, TextNode, IO, TSTypes = BEGIN OPEN TSTypes; bytesPerPage: NAT ~ 512; -- as per press file format. micasPerPoint: REAL = 2540.0/72.0; pointsPerMica: REAL = 72.0/2540.0; ObjectFromBranchProc: TYPE = TSArtwork.ObjectFromBranchProc; ROPE: TYPE = Rope.ROPE; IncludeAISRec: TYPE = RECORD [aisFileName: ROPE, height, width: REAL _ -1, indent: REAL _ 0, screen: INT _ 85, screenAngle: INT _ 0, aisStream: IO.STREAM, wordOffset: INT, rasterPart: AISFileFormat.RasterPart, uca: AISFileFormat.UCACoding]; Break: PROC [char: CHAR] RETURNS [IO.CharClass] = { IF char = ': THEN RETURN [break]; IF char = ' OR char = ' OR char = ', OR char = '; OR char = '\n THEN RETURN [sepr]; RETURN [other]; }; GetName: PROC [stream: IO.STREAM] RETURNS [name: ROPE] ~ { name _ NIL; name _ IO.GetTokenRope[stream, Break ! IO.EndOfStream => CONTINUE].token; }; GetBP: PROC [stream: IO.STREAM] RETURNS [REAL] = { r: REAL _ IO.GetReal[stream]; unit: ROPE _ GetName[stream]; multipler: REAL _ SELECT TRUE FROM unit.Equal["in"] => 72.0, unit.Equal["pt"] => 72.0/72.27, unit.Equal["cm"] => 72.0/2.54, unit.Equal["mm"] => 72.0/25.4, unit.Equal["bp"] => 1.0, ENDCASE => 0.0; IF multipler = 0.0 THEN ERROR; RETURN [r*multipler]; }; ReadBlock: UNSAFE PROC [stream: IO.STREAM, destPointer: LONG POINTER, wordCount: INT] = UNCHECKED { bytes: INT _ IO.UnsafeGetBlock[stream, [destPointer, 0, wordCount*2]]; IF bytes # wordCount*2 THEN ERROR; }; IncludeAISFromBranch: ObjectFromBranchProc = { data: REF IncludeAISRec _ NEW[IncludeAISRec]; textNode: TextNode.RefTextNode _ TextNode.NarrowToTextNode[node]; nodeContents: ROPE _ textNode.rope; stream: IO.STREAM _ IO.RIS[nodeContents]; header: AISFileFormat.AttributeHeader; rasterPartHeader: AISFileFormat.PartHeader; rasterPart: AISFileFormat.RasterPart; uca: AISFileFormat.UCACoding; dotSize: REAL _ 0; imageWidth, imageHeight: CARDINAL _ 0; byteIndex: INT _ 0; data.aisFileName _ GetName[stream]; UNTIL IO.EndOf[stream] DO keyword: ROPE _ GetName[stream]; colon: ROPE _ GetName[stream]; IF colon.Equal[":"] THEN NULL ELSE ERROR; SELECT TRUE FROM keyword.Equal["Height", FALSE] => data.height _ GetBP[stream]; keyword.Equal["Width", FALSE] => data.width _ GetBP[stream]; keyword.Equal["Indent", FALSE] => data.indent _ GetBP[stream]; keyword.Equal["DotSize", FALSE] => dotSize _ GetBP[stream]; keyword.Equal["Screen", FALSE] => data.screen _ IO.GetInt[stream]; keyword.Equal["Angle", FALSE] => data.screenAngle _ IO.GetInt[stream]; ENDCASE => ERROR; ENDLOOP; data.aisStream _ FS.StreamOpen[data.aisFileName]; TRUSTED {ReadBlock[data.aisStream, @header, SIZE[AISFileFormat.AttributeHeader]]}; IF header.password # AISFileFormat.passwordValue THEN ERROR; -- not an AIS file. data.wordOffset _ header.length; byteIndex _ IO.GetIndex[data.aisStream]; DO TRUSTED {ReadBlock[data.aisStream, @rasterPartHeader, SIZE[AISFileFormat.PartHeader]]}; IF rasterPartHeader.length = 0 THEN ERROR; byteIndex _ byteIndex + 2*rasterPartHeader.length; IF byteIndex/2 > header.length THEN ERROR; IF rasterPartHeader.type = raster THEN { TRUSTED {ReadBlock[data.aisStream, @rasterPart, SIZE[AISFileFormat.RasterPart]]}; EXIT; }; IO.SetIndex[data.aisStream, byteIndex]; ENDLOOP; IF rasterPart.codingType # uca THEN ERROR; -- not the kind we expected TRUSTED {ReadBlock[data.aisStream, @uca, SIZE[AISFileFormat.UCACoding]]}; data.rasterPart _ rasterPart; data.uca _ uca; IF rasterPart.scanDirection MOD 4 < 2 THEN { imageWidth _ rasterPart.scanCount; imageHeight _ rasterPart.scanLength; } ELSE { imageWidth _ rasterPart.scanLength; imageHeight _ rasterPart.scanCount; }; IF data.height < 0 AND data.width < 0 THEN { IF dotSize <= 0 THEN ERROR; --must specify dotSize if height and width are omitted. data.height _ dotSize*imageHeight; data.width _ dotSize*imageWidth; }; IF data.height < 0 THEN data.height _ (data.width * imageHeight)/imageWidth; IF data.width < 0 THEN data.width _ (data.height * imageWidth)/imageHeight; object _ NEW[TSGraphic.ObjectRec]; object.paintProc _ IncludeAISPaint; object.layoutProc _ IncludeAISLayout; object.data _ data; }; IncludeAISLayout: TSGraphic.LayoutProc = { data: REF IncludeAISRec _ NARROW[self.data]; extent _ [zeroDimn, RealDimn[data.width+data.indent, bp], zeroDimn, RealDimn[data.height, bp]]; }; IncludeAISPaint: TSGraphic.PaintProc = TRUSTED { data: REF IncludeAISRec ~ NARROW[self.data]; handle: TSOutput.Handle ~ NARROW[context]; x: INT ~ Real.RoundLI[(DimnRatio[originX, bp]+data.indent)*micasPerPoint]; y: INT ~ Real.RoundLI[(DimnRatio[originY, bp])*micasPerPoint]; pressState: TSOutputPress.PressState ~ NARROW[handle.outputState]; pressHandle: SirPress.PressHandle ~ pressState.pressHandle; windowWidth: INT ~ Real.RoundLI[data.width*micasPerPoint]; windowHeight: INT ~ Real.RoundLI[data.height*micasPerPoint]; bytesPerLine: INT ~ data.uca.wordsPerScanLine*2; ScratchRec: TYPE ~ RECORD [SEQUENCE length: NAT OF WORD]; scratch: REF ScratchRec _ NEW[ScratchRec[data.uca.wordsPerScanLine]]; pressHandle.BeginScannedRectangle[ x: x, y: y-windowHeight, dotsPerLine: data.rasterPart.scanLength, numberOfLines: data.rasterPart.scanCount, width: windowWidth, height: windowHeight, nextLineDirection: LOOPHOLE[data.rasterPart.scanDirection MOD 4], nextDotDirection: LOOPHOLE[data.rasterPart.scanDirection / 4], coding: SELECT data.uca.bitsPerSample FROM 0 => bitMap, 1 => bitSampled, 2 => bitBitSampled, 4 => nybbleSampled, 8 => byteSampled, ENDCASE => ERROR, samplingProperties: [screenAngle: data.screenAngle, screenFrequency: data.screen] ]; scratch[bytesPerLine/2-1] _ 0; -- make sure array is big enough IO.SetIndex[data.aisStream, data.wordOffset*2]; FOR i: INT IN [0..data.rasterPart.scanCount) DO TRUSTED {ReadBlock[data.aisStream, @scratch[0], scratch.length]}; TRUSTED {pressHandle.UnsafeShowLine[@scratch[0]]}; ENDLOOP; pressHandle.EndScannedRectangle; IO.Close[data.aisStream]; }; TSArtwork.Register["IncludeAIS", IncludeAISFromBranch]; END. άTSIncludeAISImpl.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. Michael Plass, April 25, 1985 12:35:50 pm PST Tim Diebert: May 22, 1984 12:02:17 pm PDT Rick Beach, May 31, 1985 10:18:25 am PDT Κ Γ˜code– "cedar" stylešœ™K– "cedar" stylešœ Οmœ1™Kšœžœ ˜Kšœžœ˜;Kšœžœ%˜BKšœžœ*˜FKšžœžœ˜—Kšžœ˜—Kšœ1˜1Kšžœ%žœ"˜RKšžœ/žœžœ ˜PKšœ ˜ Kšœ žœ˜(šž˜Kšžœ/žœ˜WKšžœžœžœ˜*Kšœ2˜2Kšžœžœžœ˜*šžœ žœ˜(Kšžœ)žœ˜QKšžœ˜Kšœ˜—Kšžœ%˜'Kšžœ˜—Kšžœžœžœ ˜GKšžœ"žœ˜IKšœ˜Kšœ˜šžœžœžœ˜,Kšœ"˜"Kšœ$˜$K˜—šžœ˜Kšœ#˜#Kšœ#˜#K˜—šžœžœžœ˜,Kš žœžœžœ œ œ œ  ˜SKšœ"˜"Kšœ ˜ K˜—Kšžœžœ5˜LKšžœžœ5˜KKšœ žœ˜"Kšœ#˜#Kšœ%˜%Kšœ˜Kšœ˜K– "cedar" style˜—– "cedar" styleš‘œ˜*Kšœžœžœ ˜,Kšœ_˜_Kšœ˜K– "cedar" style˜—– "cedar" styleš‘œžœ˜0Kšœžœžœ ˜,Kšœžœ ˜*KšœžœD˜JKšœžœ8˜>Kšœ'žœ˜BKšœ;˜;K– "cedar" stylešœ žœ*˜:K– "cedar" stylešœžœ+˜– "cedar" stylešœžœž˜*K– "cedar" stylešœ ˜ K– "cedar" stylešœ˜K– "cedar" stylešœ˜K– "cedar" stylešœ˜K– "cedar" stylešœ˜K– "cedar" stylešžœž˜—K– "cedar" stylešœQ˜QK˜—Kšœ  ˜?Kšžœ-˜/šžœžœžœ ž˜/Kšžœ:˜AKšžœ+˜2Kšžœ˜—K– "cedar" stylešœ ˜ Kšžœ˜Kšœ˜K– "cedar" style˜—K– "cedar" stylešœ7˜7—K– "cedar" style˜K– "cedar" stylešžœ˜K˜—…—$―