DIRECTORY Basics USING [bitsPerWord, bytesPerWord, LongMult, LongNumber], CountedVM USING [Allocate, Handle], FS USING [defaultStreamOptions, StreamOpen, StreamOptions], ImagerPixelMap USING [Create, CreateTile, PixelMap, PixelMapRep, Tile], IO USING [Close, GetIndex, SetIndex, STREAM, UnsafeGetBlock], PDFileFormat USING [ColorSamples, Command, Herald, MaskRectangle, MaskRunGroup, MaskRunGroupRef, MaskSamples, MaskSamplesRef, MaskTrapezoid, passwordValue, Priority, Run, RunGroup, SampleArray, SetColorTile, StartImage, StoreLoad, Tile, versionValue], PDFileReader USING [ColorSamples, ColorSamplesRep, DeviceCommand, DeviceCommandRep, ErrorCode, Handle, MaskRectangle, MaskRectangleRep, MaskRunGroup, MaskRunGroupRep, MaskSamples, MaskSamplesRep, MaskTrapezoid, MaskTrapezoidRep, Rep, StateChange, StateChangeRep], Rope USING [ROPE], SafeStorage USING [ReclaimCollectibleObjects]; PDFileReaderImpl: CEDAR PROGRAM IMPORTS Basics, CountedVM, FS, IO, ImagerPixelMap, SafeStorage EXPORTS PDFileReader ~ BEGIN OPEN PDFileReader; ROPE: TYPE ~ Rope.ROPE; bitsPerWord: NAT ~ Basics.bitsPerWord; Private: TYPE ~ REF PrivateRep; PrivateRep: TYPE ~ RECORD [ maskRectangle: MaskRectangle _ NIL, maskTrapezoid: MaskTrapezoid _ NIL, maskRunGroup: MaskRunGroup _ NIL, maskSamples: MaskSamples _ NIL, colorSamples: ColorSamples _ NIL, stateChange: StateChange _ NIL, loadStorage: CountedVM.Handle, tempRefRep: REF ImagerPixelMap.PixelMapRep, -- temp for building tiles runStorage: DeviceCommand _ NIL ]; ColorTileFromLoad: PUBLIC PROC [handle: Handle, colorTileLoadAddress: INT, scratch: REF ImagerPixelMap.PixelMapRep] RETURNS [colorTile: ImagerPixelMap.Tile] ~ TRUSTED { private: Private _ NARROW[handle.private]; pixelMap: ImagerPixelMap.PixelMap _ [0,0,0,0,0,0,private.tempRefRep]; words: INT; tile: LONG POINTER TO PDFileFormat.Tile; IF colorTileLoadAddress < 0 OR colorTileLoadAddress > handle.loadWords OR colorTileLoadAddress + SIZE[PDFileFormat.Tile] > handle.loadWords THEN RaisePDError[handle, badLoadReference, 0]; tile _ private.loadStorage.pointer + colorTileLoadAddress; words _ Basics.LongMult[tile.sSize, (tile.fSize+(bitsPerWord-1))/bitsPerWord]; IF colorTileLoadAddress + SIZE[PDFileFormat.Tile] + words > handle.loadWords THEN RaisePDError[handle, badLoadReference, 0]; pixelMap.sOrigin _ tile.sMin; pixelMap.fOrigin _ tile.fMin; pixelMap.sSize _ tile.sSize; pixelMap.fSize _ tile.fSize; pixelMap.refRep.pointer _ private.loadStorage.pointer + colorTileLoadAddress + SIZE[PDFileFormat.Tile]; pixelMap.refRep.words _ words; pixelMap.refRep.rast _ (tile.fSize+(bitsPerWord-1))/bitsPerWord; pixelMap.refRep.lines _ tile.sSize; colorTile _ ImagerPixelMap.CreateTile[pixelMap, tile.phase, 100, scratch]; }; RawStreamOptions: PROC RETURNS [options: FS.StreamOptions _ FS.defaultStreamOptions] ~ INLINE {options[tiogaRead] _ FALSE}; Open: PUBLIC PROC [fileName: ROPE] RETURNS [Handle] ~ { stream: IO.STREAM _ FS.StreamOpen[fileName: fileName, streamOptions: RawStreamOptions[]]; RETURN [FromStream[stream]]; }; FromStream: PUBLIC PROC [stream: IO.STREAM] RETURNS [handle: Handle] ~ { private: Private _ NEW[PrivateRep]; handle _ NEW[Rep]; handle.private _ private; handle.stream _ stream; handle.colorType _ none; handle.colorTileLoadAddress _ -1; handle.priority _ 0; handle.warningCount _ 0; ReadHerald[handle]; AllocateLoadSpace[handle]; private.tempRefRep _ NEW[ImagerPixelMap.PixelMapRep _ [ ref: private.loadStorage, pointer: NIL, words: 0, lgBitsPerPixel: 0, rast: 0, lines: 0 ]]; }; ReadHerald: PROC [handle: Handle] ~ TRUSTED { herald: PDFileFormat.Herald; ReadBlock[handle, @herald, SIZE[PDFileFormat.Herald]]; IF herald.password # PDFileFormat.passwordValue THEN { RaisePDError[handle, invalidPassword, SIZE[PDFileFormat.Herald]]; }; IF herald.version # PDFileFormat.versionValue THEN { RaisePDWarning[handle, wrongFormatVersion, SIZE[PDFileFormat.Herald]]; }; IF NOT (herald.sResolution IN [10..10000]) OR NOT (herald.fResolution IN [10..10000]) THEN { RaisePDWarning[handle, unreasonableResolution, SIZE[PDFileFormat.Herald]]; }; IF NOT (herald.bandSSize IN [8..32767]) THEN { RaisePDWarning[handle, unreasonableBandSSize, SIZE[PDFileFormat.Herald]]; }; IF NOT (herald.imageSSize IN [80..32767]) OR NOT (herald.imageFSize IN [80..32767]) THEN { RaisePDWarning[handle, unreasonableImageSize, SIZE[PDFileFormat.Herald]]; }; IF herald.maxLoadWord > 60000 THEN { RaisePDWarning[handle, unreasonableLoadSize, SIZE[PDFileFormat.Herald]]; }; IF NOT (herald.copies IN [1..200]) THEN { RaisePDWarning[handle, unreasonableNumberOfCopies, SIZE[PDFileFormat.Herald]]; }; handle.herald _ herald; handle.sSizeBand _ herald.bandSSize; }; AllocateLoadSpace: PROC [handle: Handle] ~ { private: Private _ NARROW[handle.private]; IF handle.herald.maxLoadWord > 0 THEN private.loadStorage _ CountedVM.Allocate[handle.herald.maxLoadWord]; }; Close: PUBLIC PROC [handle: Handle] ~ { IF handle.stream # NIL THEN {IO.Close[handle.stream]; handle.stream_NIL}; IF handle.private # NIL THEN { private: Private _ NARROW[handle.private]; private.tempRefRep.ref _ NIL; private.tempRefRep _ NIL; private.loadStorage _ NIL; private.runStorage _ NIL; handle.private _ NIL; }; SafeStorage.ReclaimCollectibleObjects[]; }; ReadBlock: UNSAFE PROC [handle: Handle, dest: LONG POINTER, words: CARDINAL] ~ UNCHECKED { bytes: INT _ words*Basics.bytesPerWord; bytesRead: INT _ 0; bytesRead _ IO.UnsafeGetBlock[handle.stream, [dest, 0, bytes]]; IF bytesRead < bytes THEN RaisePDError[handle, unexpectedEOF, bytesRead/2]; }; CheckBB: PROC [handle: Handle, sMin, fMin, sSize, fSize: CARDINAL, errorWordCount: INT] ~ { IF LONG[sMin] + sSize > handle.herald.imageSSize OR LONG[fMin] + fSize > handle.herald.imageFSize OR fMin < handle.image.fMinPage OR fMin + fSize > handle.image.fMinPage + handle.image.fSizePage THEN RaisePDError[handle, objectOutOfBounds, errorWordCount]; IF sMin + sSize <= handle.sMinBand OR sMin >= handle.sMinBand+handle.sSizeBand THEN { RaisePDWarning[handle, objectOutOfBand, errorWordCount]; }; }; Get: PUBLIC PROC [handle: Handle, scanning: BOOLEAN _ FALSE] RETURNS [REF] ~ TRUSTED { private: Private _ NARROW[handle.private]; command: PDFileFormat.Command; BadLoadReference: PROC [dataWords: INT] ~ CHECKED { RaisePDError[handle, badLoadReference, SIZE[PDFileFormat.Command]+dataWords]; }; IF handle.priority = LAST[INT] THEN { ans: StateChange _ IF private.stateChange # NIL THEN private.stateChange ELSE (private.stateChange_NEW[StateChangeRep]); ans.loadChangeStart _ ans.loadChangeLength _ 0; handle.sMinBand _ handle.sMinBand + handle.sSizeBand; handle.bandNumber _ handle.bandNumber + 1; handle.priority _ 0; handle.colorType _ ink; ans.whatChanged _ bandChange; IF handle.bandNumber = handle.image.nBands THEN { ans.whatChanged _ imageEnd; handle.colorType _ none; }; RETURN [ans]; }; ReadBlock[handle, @command, SIZE[PDFileFormat.Command]]; WITH command SELECT FROM imagingCommand: PDFileFormat.Command.imaging => { IF handle.colorType = none THEN { RaisePDError[handle, missingStartImage, SIZE[PDFileFormat.Command]]; ERROR }; SELECT imagingCommand.com FROM maskSamplesRef => { ans: MaskSamples _ IF private.maskSamples # NIL THEN private.maskSamples ELSE (private.maskSamples_NEW[MaskSamplesRep]); maskSamplesRef: PDFileFormat.MaskSamplesRef; loadAddress: Basics.LongNumber; samples: LONG POINTER TO PDFileFormat.SampleArray; words: INT; refRep: REF ImagerPixelMap.PixelMapRep _ IF ans.samples.refRep = NIL THEN NEW[ImagerPixelMap.PixelMapRep _ [ ref: private.loadStorage, pointer: NIL, words: 0, rast: 0, lines: 0, lgBitsPerPixel: 0 ]] ELSE ans.samples.refRep; ReadBlock[handle, @maskSamplesRef, SIZE[PDFileFormat.MaskSamplesRef]]; loadAddress.highbits _ imagingCommand.addrHighBits; loadAddress.lowbits _ maskSamplesRef.addrLowBits; ans.loadAddress _ loadAddress.li; IF ans.loadAddress < 0 OR ans.loadAddress + SIZE[PDFileFormat.SampleArray] > handle.loadWords THEN BadLoadReference[SIZE[PDFileFormat.MaskSamplesRef]]; samples _ private.loadStorage.pointer + loadAddress.li; words _ Basics.LongMult[samples.sSize, (samples.fSize+(bitsPerWord-1))/bitsPerWord]; IF ans.loadAddress + SIZE[PDFileFormat.SampleArray] + words > handle.loadWords THEN BadLoadReference[SIZE[PDFileFormat.MaskSamplesRef]]; CheckBB[handle, maskSamplesRef.sMin, maskSamplesRef.fMin, samples.sSize, samples.fSize, SIZE[PDFileFormat.Command]+SIZE[PDFileFormat.MaskSamplesRef]]; refRep.pointer _ samples+SIZE[PDFileFormat.SampleArray]; refRep.words _ words; refRep.rast _ (samples.fSize+(bitsPerWord-1))/bitsPerWord; refRep.lines _ samples.sSize; ans.samples _ [sOrigin: maskSamplesRef.sMin, fOrigin: maskSamplesRef.fMin, sMin: 0, fMin: 0, sSize: samples.sSize, fSize: samples.fSize, refRep: refRep]; RETURN [ans]; }; maskRunGroupRef => { ans: MaskRunGroup _ IF private.maskRunGroup # NIL THEN private.maskRunGroup ELSE (private.maskRunGroup_NEW[MaskRunGroupRep]); maskRunGroupRef: PDFileFormat.MaskRunGroupRef; loadAddress: Basics.LongNumber; runGroup: LONG POINTER TO PDFileFormat.RunGroup; run: LONG POINTER TO PDFileFormat.Run; s: CARDINAL _ 0; runCount: CARDINAL _ 0; words: INT _ 0; fSize: CARDINAL _ 0; ReadBlock[handle, @maskRunGroupRef, SIZE[PDFileFormat.MaskRunGroupRef]]; loadAddress.highbits _ imagingCommand.addrHighBits; loadAddress.lowbits _ maskRunGroupRef.addrLowBits; ans.ref _ private.loadStorage; ans.loadAddress _ loadAddress.li; IF ans.loadAddress < 0 OR ans.loadAddress + SIZE[PDFileFormat.RunGroup] > handle.loadWords THEN BadLoadReference[SIZE[PDFileFormat.MaskRunGroupRef]]; runGroup _ private.loadStorage.pointer + loadAddress.li; ans.pointer _ run _ private.loadStorage.pointer + loadAddress.li + SIZE[PDFileFormat.RunGroup]; WHILE s < runGroup.sSize DO IF INT[run-private.loadStorage.pointer] >= handle.loadWords THEN BadLoadReference[SIZE[PDFileFormat.MaskRunGroupRef]]; IF LONG[run.fMin] + run.fSize > fSize THEN fSize _ LONG[run.fMin] + run.fSize; IF run.lastRun THEN s _ s + 1; run _ run + SIZE[PDFileFormat.Run]; runCount _ runCount + 1; ENDLOOP; ans.runCount _ runCount; CheckBB[handle, maskRunGroupRef.sMin, maskRunGroupRef.fMin, runGroup.sSize, fSize, SIZE[PDFileFormat.Command]+SIZE[PDFileFormat.MaskRunGroupRef]]; ans.sMin _ maskRunGroupRef.sMin; ans.fMin _ ans.fOffset _ maskRunGroupRef.fMin; ans.sSize _ runGroup.sSize; ans.fSize _ fSize; RETURN [ans]; }; maskRectangle => { ans: MaskRectangle _ IF private.maskRectangle # NIL THEN private.maskRectangle ELSE (private.maskRectangle_NEW[MaskRectangleRep]); maskRectangle: PDFileFormat.MaskRectangle; ReadBlock[handle, @maskRectangle, SIZE[PDFileFormat.MaskRectangle]]; CheckBB[handle, maskRectangle.sMin, maskRectangle.fMin, maskRectangle.sSize, maskRectangle.fSize, SIZE[PDFileFormat.Command]+SIZE[PDFileFormat.MaskRectangle]]; ans.sMin _ maskRectangle.sMin; ans.fMin _ maskRectangle.fMin; ans.sSize _ maskRectangle.sSize; ans.fSize _ maskRectangle.fSize; RETURN [ans]; }; maskTrapezoid => { ans: MaskTrapezoid _ IF private.maskTrapezoid # NIL THEN private.maskTrapezoid ELSE (private.maskTrapezoid_NEW[MaskTrapezoidRep]); maskTrapezoid: PDFileFormat.MaskTrapezoid; fMin, fMax: INT; ReadBlock[handle, @maskTrapezoid, SIZE[PDFileFormat.MaskTrapezoid]]; fMin _ MIN[maskTrapezoid.fMin, maskTrapezoid.fMinLast]; fMax _ MAX[LONG[maskTrapezoid.fMin] + maskTrapezoid.fSize, LONG[maskTrapezoid.fMinLast] + maskTrapezoid.fSizeLast]; CheckBB[handle, maskTrapezoid.sMin, fMin, maskTrapezoid.sSize, fMax-fMin, SIZE[PDFileFormat.Command]+SIZE[PDFileFormat.MaskTrapezoid]]; ans.sMin _ maskTrapezoid.sMin; ans.fMin _ maskTrapezoid.fMin; ans.fMinLast _ maskTrapezoid.fMinLast; ans.sSize _ maskTrapezoid.sSize; ans.fSize _ maskTrapezoid.fSize; ans.fSizeLast _ maskTrapezoid.fSizeLast; RETURN [ans]; }; maskRunGroup => { ans: MaskRunGroup _ IF private.maskRunGroup # NIL THEN private.maskRunGroup ELSE (private.maskRunGroup_NEW[MaskRunGroupRep]); maskRunGroup: PDFileFormat.MaskRunGroup; runGroup: PDFileFormat.RunGroup; run: PDFileFormat.Run; s: CARDINAL _ 0; runCount: INT _ 0; words: INT _ 0; fMin: CARDINAL _ LAST[CARDINAL]; fMax: CARDINAL _ FIRST[CARDINAL]; runGroupStart: INT; ReadBlock[handle, @maskRunGroup, SIZE[PDFileFormat.MaskRunGroup]]; ReadBlock[handle, @runGroup, SIZE[PDFileFormat.RunGroup]]; runGroupStart _ IO.GetIndex[handle.stream]; WHILE s < runGroup.sSize DO ReadBlock[handle, @run, SIZE[PDFileFormat.Run]]; IF run.fMin < fMin THEN fMin _ run.fMin; IF LONG[run.fMin] + run.fSize > fMax THEN fMax _ LONG[run.fMin] + run.fSize; IF run.lastRun THEN s _ s + 1; runCount _ runCount + 1; ENDLOOP; ans.runCount _ runCount; ans.loadAddress _ -1; IF runCount = 0 THEN { ans.pointer _ NIL; ans.ref _ NIL; RaisePDWarning[handle, emptyRunGroup, SIZE[PDFileFormat.MaskRunGroup]+SIZE[PDFileFormat.RunGroup]]; fMin _ fMax; } ELSE IF scanning THEN { ans.pointer _ NIL; ans.ref _ NIL; } ELSE { wordsNeeded: NAT _ runCount*SIZE[PDFileFormat.Run]; storage: DeviceCommand _ IF private.runStorage#NIL AND private.runStorage.wordCount>=wordsNeeded THEN private.runStorage ELSE (private.runStorage _ NEW[DeviceCommandRep[wordsNeeded]]); handle.stream.SetIndex[runGroupStart]; ans.ref _ storage; ans.pointer _ LOOPHOLE[@(storage[0])]; ReadBlock[handle, ans.pointer, wordsNeeded]; CheckBB[handle, maskRunGroup.sMin, fMin, runGroup.sSize, fMax-fMin, SIZE[PDFileFormat.Command]+SIZE[PDFileFormat.MaskRunGroup]] }; ans.sMin _ maskRunGroup.sMin; ans.fMin _ fMin; ans.fOffset _ 0; ans.sSize _ runGroup.sSize; ans.fSize _ fMax; RETURN [ans]; }; maskSamples => { ans: MaskSamples _ IF private.maskSamples # NIL THEN private.maskSamples ELSE (private.maskSamples_NEW[MaskSamplesRep]); maskSamples: PDFileFormat.MaskSamples; samples: PDFileFormat.SampleArray; words: LONG CARDINAL; ReadBlock[handle, @maskSamples, SIZE[PDFileFormat.MaskSamples]]; ReadBlock[handle, @samples, SIZE[PDFileFormat.SampleArray]]; CheckBB[handle, maskSamples.sMin, maskSamples.fMin, samples.sSize, samples.fSize, SIZE[PDFileFormat.Command]+SIZE[PDFileFormat.MaskSamples]+SIZE[PDFileFormat.SampleArray]]; words _ Basics.LongMult[samples.sSize, (samples.fSize+(bitsPerWord-1))/bitsPerWord]; ans.loadAddress _ -1; IF scanning THEN { handle.stream.SetIndex[handle.stream.GetIndex[]+words*Basics.bytesPerWord] } ELSE { ans.samples _ ImagerPixelMap.Create[0, [maskSamples.sMin, maskSamples.fMin, samples.sSize, samples.fSize]]; IF ans.samples.refRep.words < words THEN ERROR; ReadBlock[handle, ans.samples.refRep.pointer, words]; }; RETURN [ans]; }; colorSamples => { ans: ColorSamples _ IF private.colorSamples # NIL THEN private.colorSamples ELSE (private.colorSamples_NEW[ColorSamplesRep]); colorSamples: PDFileFormat.ColorSamples; samples: PDFileFormat.SampleArray; words: LONG CARDINAL; ReadBlock[handle, @colorSamples, SIZE[PDFileFormat.ColorSamples]]; ReadBlock[handle, @samples, SIZE[PDFileFormat.SampleArray]]; CheckBB[handle, colorSamples.sMin, colorSamples.fMin, samples.sSize, samples.fSize, SIZE[PDFileFormat.Command]+SIZE[PDFileFormat.ColorSamples]+SIZE[PDFileFormat.SampleArray]]; words _ Basics.LongMult[samples.sSize, (samples.fSize+(bitsPerWord-1))/bitsPerWord]; IF scanning THEN{ handle.stream.SetIndex[handle.stream.GetIndex[]+words*Basics.bytesPerWord] } ELSE { ans.samples _ ImagerPixelMap.Create[0, [colorSamples.sMin, colorSamples.fMin, samples.sSize, samples.fSize]]; IF ans.samples.refRep.words < words THEN ERROR; ReadBlock[handle, ans.samples.refRep.pointer, words] }; RETURN [ans]; }; ENDCASE => { RaisePDError[handle, unrecognisedImagingCommand, SIZE[PDFileFormat.Command]]; ERROR}; }; controlCommand: PDFileFormat.Command.control => { ans: StateChange _ IF private.stateChange # NIL THEN private.stateChange ELSE (private.stateChange_NEW[StateChangeRep]); ans.loadChangeStart _ ans.loadChangeLength _ 0; IF handle.colorType = none THEN SELECT controlCommand.com FROM startImage, deviceCommand, storeLoad, endDocument => NULL; ENDCASE => { RaisePDError[handle, missingStartImage, SIZE[PDFileFormat.Command]]; ERROR }; SELECT controlCommand.com FROM startImage => { startImage: PDFileFormat.StartImage; ReadBlock[handle, @startImage, SIZE[PDFileFormat.StartImage]]; IF startImage.filler # 0 THEN { RaisePDWarning[handle, nonZeroFill, SIZE[PDFileFormat.Command]+SIZE[PDFileFormat.StartImage]]; }; IF (LONG[startImage.passBands]+startImage.nBands)*handle.sSizeBand >= handle.herald.imageSSize+handle.sSizeBand OR LONG[startImage.fMinPage]+startImage.fSizePage > handle.herald.imageFSize THEN { RaisePDWarning[handle, imageBoundsExceedPageBounds, SIZE[PDFileFormat.Command]+SIZE[PDFileFormat.StartImage]]; }; IF handle.colorType # none AND handle.bandNumber < handle.image.nBands THEN RaisePDWarning[handle, tooFewBands, SIZE[PDFileFormat.Command]+SIZE[PDFileFormat.StartImage]]; handle.image _ startImage; ans.whatChanged _ imageStart; handle.priority _ 0; handle.colorType _ ink; handle.bandNumber _ 0; handle.sMinBand _ startImage.passBands*handle.sSizeBand; RETURN [ans] }; setPriority => { priorityLow: PDFileFormat.Priority; priority: Basics.LongNumber; ReadBlock[handle, @priorityLow, SIZE[PDFileFormat.Priority]]; priority.highbits _ controlCommand.rest; priority.lowbits _ priorityLow; handle.priority _ priority.li; ans.whatChanged _ priorityChange; RETURN [ans] }; setColorInk => { handle.colorType _ ink; ans.whatChanged _ colorChange; RETURN [ans] }; setColorClear => { handle.colorType _ clear; ans.whatChanged _ colorChange; RETURN [ans] }; setColorTile => { tile: LONG POINTER TO PDFileFormat.Tile; words: INT; setColorTile: PDFileFormat.SetColorTile; ReadBlock[handle, @setColorTile, SIZE[PDFileFormat.SetColorTile]]; handle.colorTileLoadAddress _ setColorTile.addr; IF handle.colorTileLoadAddress < 0 OR handle.colorTileLoadAddress > handle.loadWords OR handle.colorTileLoadAddress + SIZE[PDFileFormat.Tile] > handle.loadWords THEN BadLoadReference[SIZE[PDFileFormat.SetColorTile]]; tile _ private.loadStorage.pointer + setColorTile.addr; words _ Basics.LongMult[tile.sSize, (tile.fSize+(bitsPerWord-1))/bitsPerWord]; IF INT[setColorTile.addr] + SIZE[PDFileFormat.Tile] + words > handle.loadWords THEN BadLoadReference[SIZE[PDFileFormat.SetColorTile]]; SELECT controlCommand.rest FROM 0 => handle.colorType _ opaqueTile; 1 => handle.colorType _ transparentTile; ENDCASE => { handle.colorType _ opaqueTile; RaisePDWarning[handle, unknownColorTileFlag, SIZE[PDFileFormat.Command]]; }; ans.whatChanged _ colorChange; RETURN [ans]; }; endBand => { handle.priority _ LAST[INT]; ans.whatChanged _ priorityChange; RETURN [ans] }; endDocument => { ans.whatChanged _ documentEnd; RETURN [ans]; }; storeLoad => { storeLoad: PDFileFormat.StoreLoad; ReadBlock[handle, @storeLoad, SIZE[PDFileFormat.StoreLoad]]; IF storeLoad.firstAddress > LAST[LONG CARDINAL]/256 OR storeLoad.firstAddress + storeLoad.wordCount > handle.herald.maxLoadWord THEN {RaisePDError[handle, loadOutOfBounds, SIZE[PDFileFormat.Command]+SIZE[PDFileFormat.StoreLoad]]; ERROR}; ReadBlock[handle, private.loadStorage.pointer+storeLoad.firstAddress, storeLoad.wordCount]; ans.whatChanged _ loadChange; ans.loadChangeStart _ storeLoad.firstAddress; ans.loadChangeLength _ storeLoad.wordCount; handle.loadWords _ MAX[handle.loadWords, ans.loadChangeStart + ans.loadChangeLength]; RETURN [ans]; }; deviceCommand => { deviceCommand: DeviceCommand; wordCount: CARDINAL; ReadBlock[handle, @wordCount, SIZE[CARDINAL]]; deviceCommand _ NEW[DeviceCommandRep[wordCount]]; IF wordCount > 0 THEN { ReadBlock[handle, @(deviceCommand[0]), wordCount]; }; RETURN [deviceCommand]; }; ENDCASE => {RaisePDError[handle, unrecognisedControlCommand, SIZE[PDFileFormat.Command]]; ERROR}; }; ENDCASE => {RaisePDError[handle, unrecognisedCommandType, SIZE[PDFileFormat.Command]]; ERROR}; }; Keep: PUBLIC PROC [handle: Handle, ref: REF] RETURNS [REF] ~ { private: Private _ NARROW[handle.private]; SELECT ref FROM private.maskRectangle => private.maskRectangle _ NIL; private.maskTrapezoid => private.maskTrapezoid _ NIL; private.maskRunGroup => private.maskRunGroup _ NIL; private.maskSamples => private.maskSamples _ NIL; private.colorSamples => private.colorSamples _ NIL; private.stateChange => private.stateChange _ NIL; ENDCASE => NULL; RETURN [ref] }; Error: PUBLIC ERROR [handle: Handle, code: ErrorCode, wordIndex, wordCount: INT, description: ROPE] ~ CODE; Warning: PUBLIC SIGNAL [handle: Handle, code: ErrorCode, wordIndex, wordCount: INT, description: ROPE] ~ CODE; RaisePDError: PROC [handle: Handle, code: ErrorCode, words: INT] ~ { index: INT _ IO.GetIndex[handle.stream]; wordIndex: INT _ index/Basics.bytesPerWord - words; IO.SetIndex[handle.stream, wordIndex*Basics.bytesPerWord]; ERROR Error[handle, code, wordIndex, words, descriptionFor[code]]; }; RaisePDWarning: PROC [handle: Handle, code: ErrorCode, words: INT] ~ { index: INT _ IO.GetIndex[handle.stream]; wordIndex: INT _ index/Basics.bytesPerWord - words; IO.SetIndex[handle.stream, wordIndex*Basics.bytesPerWord]; handle.warningCount _ handle.warningCount + 1; SIGNAL Warning[handle, code, wordIndex, words, descriptionFor[code]]; IO.SetIndex[handle.stream, index]; }; descriptionFor: ARRAY ErrorCode OF ROPE ~ [ invalidPassword: "Invalid PD file password", objectOutOfBounds: "Object exceeds page boundaries", missingStartImage: "This command must be in the scope of a StartImage command", badLoadReference: "Reference to load exceeds load bounds", unrecognisedImagingCommand: "Unrecognised imaging command", loadOutOfBounds: "Attempt to exceed load size declared in herald", unrecognisedControlCommand: "Unrecognised control command", unrecognisedCommandType: "Unrecognised command type", unexpectedEOF: "Unexpected end of file", wrongFormatVersion: "The version of the PD file format does not match the software version", unreasonableResolution: "The resolution is not in a reasonable range", unreasonableBandSSize: "The band size is not in a reasonable range", unreasonableImageSize: "The image size is not in a reasonable range", unreasonableLoadSize: "The load size is not in a reasonable range", unreasonableNumberOfCopies: "The requested number of copies is not in a reasonable range", objectOutOfBand: "Object does not touch band in which it is used", emptyRunGroup: "Run group has zero runs", nonZeroFill: "Fill bits in startImage command are non-zero", imageBoundsExceedPageBounds: "Image bounds in startImage command exceed page boundaries", tooFewBands: "Too few bands in image", unknownColorTileFlag: "Unknown flag byte in setColorTile command" ]; END. θPDFileReaderImpl.mesa Copyright c 1983, 1984, 1985 by Xerox Corporation. All rights reserved. Ken Pier, September 17, 1985 2:06:20 pm PDT Michael Plass, April 6, 1984 1:03:55 pm PST Doug Wyatt, March 7, 1985 6:29:25 pm PST ΚΧ˜code™Kšœ Οmœ=™HK™+K™+K™(K™—šΟk ˜ Kšœžœ3˜?Kšœ žœ˜#Kšžœžœ3˜;Kšœžœ3˜GKšžœžœžœ˜=Kšœ žœι˜ϋKšœ žœυ˜‡Kšœžœžœ˜Kšœ žœ˜.K˜—KšΠblœž ˜Kšžœžœžœ˜>Kšžœ ˜Kšœžœžœ˜K˜Kšžœžœžœ˜K˜Kšœ žœ˜&K˜Kšœ žœžœ ˜šœ žœžœ˜Kšœžœ˜#Kšœžœ˜#Kšœžœ˜!Kšœžœ˜Kšœžœ˜!Kšœžœ˜Kšœžœ˜Kšœ žœΟc˜FKšœž˜Kšœ˜K˜—šΟnœžœžœ(žœ žœžœ$žœ˜¨Kšœžœ˜*KšœE˜EKšœžœ˜ Kšœžœžœžœ˜(Kš žœžœ)žœžœ'žœ+˜»Kšœ:˜:KšœN˜NKšžœžœ/žœ+˜|Kšœ˜Kšœ˜Kšœ˜Kšœ˜KšœOžœ˜gKšœ˜Kšœ@˜@Kšœ#˜#KšœJ˜JKšœ˜K˜—Kš‘œžœžœ žœžœžœžœ˜{K˜š ‘œžœžœ žœžœ ˜7KšœžœžœžœC˜YKšžœ˜Kšœ˜K˜—š ‘ œžœžœ žœžœžœ˜HKšœžœ ˜#Kšœ žœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ!˜!Kšœ˜Kšœ˜Kšœ˜Kšœ˜šœžœ˜7Kšœ˜Kšœ žœ˜ Kšœ ˜ Kšœ˜Kšœ˜Kšœ˜Kšœ˜—Kšœ˜K˜—š‘ œžœžœ˜-Kšœ˜Kšœžœ˜6šžœ.žœ˜6Kšœ&žœ˜AKšœ˜—šžœ,žœ˜4Kšœ+žœ˜FKšœ˜—Kšžœžœžœ ˜*šžœžœžœžœ˜1Kšœ/žœ˜JKšœ˜—šžœžœžœ žœ˜.Kšœ.žœ˜IKšœ˜—Kšžœžœžœ ˜)šžœžœžœžœ˜0Kšœ.žœ˜IKšœ˜—šžœžœ˜$Kšœ-žœ˜HKšœ˜—šžœžœžœ žœ˜)Kšœ3žœ˜NKšœ˜—Kšœ˜Kšœ$˜$Kšœ˜K˜—š‘œžœ˜,Kšœžœ˜*KšžœžœE˜jKšœ˜K˜—š‘œžœžœ˜'Kš žœžœžœžœ%žœ˜Išžœžœžœ˜Kšœžœ˜*Kšœžœ˜Kšœžœ˜Kšœžœ˜Kšœžœ˜Kšœžœ˜Kšœ˜—K˜(Kšœ˜K˜—š‘ œžœžœžœžœ žœž œ˜ZKšœžœ˜'Kšœ žœ˜Kšœ žœ1˜?Kšžœžœ2˜KKšœ˜K˜—š‘œžœ,žœžœ˜[Kšžœžœ)˜0Kšžœžœ)˜0Kšžœ˜Kšžœ>˜@Kšžœ9˜=Kšžœ ˜"šžœ*žœ˜2Kšœ8˜8Kšœ˜—Kšœ˜K˜—š‘œžœžœžœžœžœžœžœ˜VKšœžœ˜*Kšœ˜š‘œžœ žœžœ˜3Kšœ'žœ"˜MKšœ˜—šžœžœžœžœ˜%Kš œžœžœžœžœžœ˜xKšœ/˜/Kšœ5˜5Kšœ*˜*Kšœ˜Kšœ˜Kšœ˜šžœ)žœ˜1Kšœ˜Kšœ˜Kšœ˜—Kšžœ˜ Kšœ˜—Kšœžœ˜8šžœ žœž˜š‘œ#˜1šžœžœ˜!Kšœ(žœ˜DKšž˜Kšœ˜—šžœž˜š‘œ˜Kš œžœžœžœžœžœ˜xKšœ,˜,K˜Kšœ žœžœžœ˜2Kšœžœ˜ šœžœ˜(šžœžœžœ˜CKšœ˜Kšœ žœ˜ Kšœ ˜ K˜K˜ Kšœ˜Kšœ˜—Kšžœ˜—Kšœ#žœ˜FKšœ3˜3Kšœ1˜1Kšœ!˜!Kš žœžœžœ.žœžœ˜—Kšœ7˜7KšœT˜TKšžœžœ6žœžœ˜ˆKšœXžœžœ˜–Kšœžœ˜8Kšœ˜Kšœ:˜:Kšœ˜Kšœ™˜™Kšžœ˜ Kšœ˜—š‘œ˜Kš œžœžœžœžœžœ˜}Kšœ.˜.K˜Kšœ žœžœžœ˜0Kšœžœžœžœ˜&Kšœžœ˜Kšœ žœ˜Kšœžœ˜Kšœžœ˜Kšœ$žœ ˜HKšœ3˜3Kšœ2˜2Kšœ˜Kšœ!˜!Kš žœžœžœ+žœžœ ˜•Kšœ8˜8KšœCžœ˜_šžœž˜Kšžœžœ6žœžœ ˜vKšžœžœžœ žœ˜NKšžœ žœ ˜Kšœ žœ˜#Kšœ˜Kšžœ˜—Kšœ˜KšœSžœžœ ˜’Kšœ ˜ Kšœ.˜.Kšœ˜Kšœ˜Kšžœ˜ Kšœ˜—š‘ œ˜Kš œžœžœžœžœžœ˜‚Kšœ*˜*Kšœ"žœ˜DKšœbžœžœ˜ŸKšœ˜Kšœ˜Kšœ ˜ Kšœ ˜ Kšžœ˜ Kšœ˜—š‘ œ˜Kš œžœžœžœžœžœ˜‚Kšœ*˜*Kšœ žœ˜Kšœ"žœ˜DKšœžœ-˜7Kšœžœžœ,žœ4˜sKšœJžœžœ˜‡Kšœ˜Kšœ˜Kšœ&˜&Kšœ ˜ Kšœ ˜ Kšœ(˜(Kšžœ˜ Kšœ˜—š‘ œ˜Kš œžœžœžœžœžœ˜}Kšœ(˜(Kšœ ˜ Kšœ˜Kšœžœ˜Kšœ žœ˜Kšœžœ˜Kšœžœžœžœ˜ Kšœžœžœžœ˜!Kšœžœ˜Kšœ!žœ˜BKšœžœ˜:Kšœžœ˜+šžœž˜Kšœžœ˜0Kšžœžœ˜(Kšžœžœžœžœ˜LKšžœ žœ ˜Kšœ˜Kšžœ˜—Kšœ˜Kšœ˜šžœžœ˜Kšœžœ˜Kšœ žœ˜Kšœ&žœžœ˜cKšœ ˜ Kšœ˜—šžœžœ žœ˜Kšœžœ˜Kšœ žœ˜Kšœ˜—šžœ˜Kšœ žœ žœ˜3Kš œžœžœžœ+žœžœžœ!˜ΉKšœ&˜&Kšœ˜Kšœžœ˜&Kšœ,˜,KšœDžœžœ˜Kšœ˜—Kšœ˜Kšœ˜K˜Kšœ˜Kšœ˜Kšžœ˜ Kšœ˜—š‘ œ˜Kš œžœžœžœžœžœ˜xKšœ&˜&Kšœ"˜"Kšœžœžœ˜Kšœ žœ˜@Kšœžœ˜Kšœ5žœ˜:šžœ˜ Kšœ(žœ˜DKšž˜Kšœ˜——šžœž˜š‘ œ˜Kšœ$˜$Kšœžœ˜>šžœžœ˜Kšœ$žœžœ˜^Kšœ˜—Kšžœžœg˜ošžœžœFžœ˜SKšœ4žœžœ˜nKšœ˜—šžœžœ)ž˜KKšœ$žœžœ˜^—Kšœ˜Kšœ˜Kšœ˜K˜Kšœ˜Kšœ8˜8Kšžœ˜ Kšœ˜—š‘ œ˜Kšœ#˜#Kšœ˜Kšœ žœ˜=Kšœ(˜(Kšœ˜Kšœ˜Kšœ!˜!Kšžœ˜ Kšœ˜—š‘ œ˜K˜Kšœ˜Kšžœ˜ Kšœ˜—š‘ œ˜K˜Kšœ˜Kšžœ˜ Kšœ˜—š‘ œ˜Kšœžœžœžœ˜(Kšœžœ˜ Kšœ(˜(Kšœ!žœ˜BKšœ0˜0Kš žœ!žœ0žœžœ'žœžœ˜ΨKšœ7˜7KšœN˜NKš žœžœžœ/žœžœ˜†šžœž˜K˜#Kšœ(˜(šžœ˜ K˜Kšœ-žœ˜IKšœ˜——Kšœ˜Kšžœ˜ Kšœ˜—š‘œ˜ Kšœžœžœ˜Kšœ!˜!Kšžœ˜ Kšœ˜—š‘ œ˜Kšœ˜Kšžœ˜ Kšœ˜—š‘ œ˜Kšœ"˜"Kšœžœ˜Kšœžœ˜*šžœž˜Kšœ1žœ˜5Kšœ1žœ˜5Kšœ/žœ˜3Kšœ-žœ˜1Kšœ/žœ˜3Kšœ-žœ˜1Kšžœžœ˜—Kšžœ˜ Kšœ˜K˜—š‘œžœž˜Kšœ8žœžœžœ˜WK˜—š‘œžœž˜Kšœ8žœžœžœ˜WK˜—š‘ œžœ*žœ˜DKšœžœžœ˜(Kšœ žœ%˜3Kšžœ8˜:Kšžœ=˜BKšœ˜K˜—š‘œžœ*žœ˜FKšœžœžœ˜(Kšœ žœ%˜3Kšžœ8˜:Kšœ.˜.Kšžœ?˜EKšžœ ˜"Kšœ˜K˜—šœžœ žœžœ˜+Kšœ,˜,Kšœ4˜4KšœO˜OKšœ:˜:Kšœ;˜;KšœB˜BKšœ;˜;Kšœ5˜5Kšœ(˜(Kšœ\˜\KšœF˜FKšœD˜DKšœE˜EKšœC˜CKšœZ˜ZKšœB˜BKšœ)˜)Kšœ<˜