DIRECTORY Basics, PDFileFormat, PDFileReader, PDReaderPage, ImagerPixelMap, IO, ShowPD, ViewerClasses, ViewerOps ; PDReaderPageImpl: CEDAR PROGRAM IMPORTS PDFileReader, IO, ImagerPixelMap, ViewerOps EXPORTS PDReaderPage = { bitsPerWord: NAT = Basics.bitsPerWord; bytesPerWord: NAT = Basics.bytesPerWord; PageRecRef: TYPE = PDReaderPage.PageRecRef; PageRec: TYPE = PDReaderPage.PageRec; LeftoverRef: TYPE = REF Leftover; Leftover: TYPE = RECORD [ link: LeftoverRef _ NIL, command: REF ANY, colorType: PDFileReader.ColorType, colorTileLoadAddress: INT _ -1, priority: INT ]; InterpretPage: PUBLIC PROC [handle: PDFileReader.Handle, viewer: ViewerClasses.Viewer, pages: PageRecRef] RETURNS [ok: BOOLEAN _ FALSE] = { ENABLE IO.EndOfStream, IO.Error => GOTO Quit; --Viewers closed the stream imageHandle: PDReaderPage.Handle_NIL; showData: ShowPD.ShowData_NARROW[viewer.data]; readHead, writeHead, writeTail: LeftoverRef _ NIL; --heads and tail of leftover lists currentColorType: PDFileReader.ColorType; currentColorTileLoadAddress: INT _ -1; currentPriority: INT _ -1; leftovers: BOOLEAN; --can't be filled in until StartImage has happened commandRef: REF ANY; band: ImagerPixelMap.PixelMap; bandMaxS: INT; cachedColorTile: ImagerPixelMap.Tile; cachedColorReference: INT _ -1; GetColorTile: PROC = { IF currentColorTileLoadAddress # cachedColorReference THEN { cachedColorTile _ PDFileReader.ColorTileFromLoad[handle, cachedColorReference _ currentColorTileLoadAddress]; }; }; TransferRectangle: PROC [rectangle: ImagerPixelMap.DeviceRectangle] = { SELECT currentColorType FROM none => ERROR; clear => ImagerPixelMap.Fill[band, rectangle, 0]; ink => ImagerPixelMap.Fill[band, rectangle, 1]; opaqueTile => { GetColorTile[]; ImagerPixelMap.TransferTile[band.Clip[rectangle], cachedColorTile]; }; transparentTile => { GetColorTile[]; ImagerPixelMap.TransferTile[band.Clip[rectangle], cachedColorTile, [or, null]]; }; ENDCASE => ERROR; }; DoLine: PROCEDURE [sMin,fMin,fSize: CARDINAL] = { SELECT currentColorType FROM none => ERROR; clear => ImagerPixelMap.Fill[band, [sMin: sMin, fMin: fMin, sSize: 1, fSize: fSize], 0]; opaqueTile, ink => ImagerPixelMap.Fill[band, [sMin: sMin, fMin: fMin, sSize: 1, fSize: fSize], 1]; transparentTile => ImagerPixelMap.TransferTile[band.Clip[[sMin: sMin, fMin: fMin, sSize: 1, fSize: fSize]], cachedColorTile, [or, null]]; ENDCASE => ERROR; }; TempColor: PROC [rectangle: ImagerPixelMap.DeviceRectangle] = { SELECT currentColorType FROM none => ERROR; clear => NULL; ink => NULL; opaqueTile => { GetColorTile[]; ImagerPixelMap.TransferTile[band.Clip[rectangle], cachedColorTile, [xor, complement]]; }; transparentTile => GetColorTile[]; ENDCASE => ERROR; }; AddLeftover: PROC = { []_PDFileReader.Keep[handle: handle, ref: commandRef]; IF writeHead=NIL THEN writeHead_writeTail_NEW[Leftover _[link: NIL, command: commandRef, colorType: currentColorType, colorTileLoadAddress: currentColorTileLoadAddress, priority: currentPriority]] ELSE { writeTail.link_NEW[Leftover _[link: NIL, command: commandRef, colorType: currentColorType, colorTileLoadAddress: currentColorTileLoadAddress, priority: currentPriority]]; writeTail_writeTail.link; }; }; DO ENABLE UNWIND => {readHead_writeHead_writeTail_NIL; handle.Close[];}; IF readHead#NIL AND readHead.priority { SELECT stateChange.whatChanged FROM imageStart => { showData.image_imageHandle _ StartImage[fileHandle: handle, oldPixelMap: IF imageHandle#NIL THEN imageHandle.pixelMap ELSE [,,,,,,NIL] ]; band _ imageHandle.pixelMap; bandMaxS_band.sOrigin+band.sMin+band.sSize; leftovers _ handle.image.leftOverMode; showData.clearClient_TRUE; ViewerOps.PaintViewer[viewer: viewer, hint: all, clearClient: TRUE, whatChanged: NIL]; }; imageEnd => { ViewerOps.PaintViewer[viewer: viewer, hint: all, clearClient: FALSE, whatChanged: imageHandle]; readHead_writeHead_writeTail_NIL; RETURN [TRUE]; }; priorityChange => NULL; colorChange => NULL; bandChange => { showData.clearClient_FALSE; ViewerOps.PaintViewer[viewer: viewer, hint: all, clearClient: FALSE, whatChanged: imageHandle]; imageHandle.pixelMap.sOrigin _ handle.herald.bandSSize*(handle.bandNumber+handle.image.passBands); ImagerPixelMap.Clear[imageHandle.pixelMap]; band _ imageHandle.pixelMap; bandMaxS_band.sOrigin+band.sMin+band.sSize; IF readHead#NIL THEN ERROR; --DEBUGGING CHECK !! readHead_writeHead; writeHead_NIL; }; loadChange => NULL; documentEnd => RETURN [FALSE]; ENDCASE => ERROR; }; maskRectangle: PDFileReader.MaskRectangle => { TransferRectangle[[maskRectangle.sMin, maskRectangle.fMin, maskRectangle.sSize, maskRectangle.fSize]]; IF leftovers AND maskRectangle.sMin+maskRectangle.sSize>bandMaxS THEN AddLeftover[]; }; maskTrapezoid: PDFileReader.MaskTrapezoid => { EdgeBlock: TYPE = RECORD [fPos, fIncr: Basics.LongNumber]; MakeEdge: PROC[fMinLast, fMin, sSize: CARDINAL] RETURNS [edge: EdgeBlock] = { edge.fPos.highbits _ fMin; edge.fPos.lowbits _ 0; edge.fIncr.highbits _ fMinLast - fMin; edge.fIncr.lowbits _ 0; IF sSize > 1 THEN edge.fIncr.li _ edge.fIncr.li/sSize; }; fMinBox: CARDINAL_MIN[maskTrapezoid.fMin, maskTrapezoid.fMinLast]; fMaxBox: CARDINAL_MAX[maskTrapezoid.fMin+maskTrapezoid.fSize, maskTrapezoid.fMinLast+maskTrapezoid.fSizeLast]; fSizeBox: CARDINAL_fMaxBox-fMinBox; trapMaxS: CARDINAL _ maskTrapezoid.sMin+maskTrapezoid.sSize; s: CARDINAL _ maskTrapezoid.sMin; sMinBand: CARDINAL _ MIN[band.sOrigin+band.sMin, maskTrapezoid.sMin+maskTrapezoid.sSize]; sMaxBand: CARDINAL _ MIN[bandMaxS, trapMaxS]; minEdge: EdgeBlock _ MakeEdge[fMinLast: maskTrapezoid.fMinLast, fMin: maskTrapezoid.fMin, sSize: maskTrapezoid.sSize]; maxEdge: EdgeBlock _ MakeEdge[fMinLast: maskTrapezoid.fMinLast+maskTrapezoid.fSizeLast, fMin: maskTrapezoid.fMin+maskTrapezoid.fSize, sSize: maskTrapezoid.sSize]; TempColor[[sMin: maskTrapezoid.sMin, fMin: fMinBox, sSize: maskTrapezoid.sSize, fSize: fSizeBox]]; WHILE s < sMinBand DO minEdge.fPos.lc _ minEdge.fPos.lc + minEdge.fIncr.li; maxEdge.fPos.lc _ maxEdge.fPos.lc + maxEdge.fIncr.li; s _ s + 1; ENDLOOP; WHILE s < sMaxBand DO DoLine[sMin: s, fMin: minEdge.fPos.highbits, fSize: maxEdge.fPos.highbits-minEdge.fPos.highbits]; minEdge.fPos.lc _ minEdge.fPos.lc + minEdge.fIncr.li; maxEdge.fPos.lc _ maxEdge.fPos.lc + maxEdge.fIncr.li; s _ s + 1; ENDLOOP; TempColor[[sMin: maskTrapezoid.sMin, fMin: fMinBox, sSize: maskTrapezoid.sSize, fSize: fSizeBox]]; IF leftovers AND trapMaxS>bandMaxS THEN AddLeftover[]; }; maskRunGroup: PDFileReader.MaskRunGroup => TRUSTED { s: CARDINAL _ maskRunGroup.sMin; sMinBand: CARDINAL _ MIN[band.sOrigin+band.sMin, maskRunGroup.sMin+maskRunGroup.sSize]; sMaxBand: CARDINAL _ MIN[band.sOrigin+band.sMin+band.sSize, maskRunGroup.sMin+maskRunGroup.sSize]; run: LONG POINTER TO PDFileFormat.Run _ maskRunGroup.pointer; TempColor[[maskRunGroup.sMin, maskRunGroup.fMin, maskRunGroup.sSize, maskRunGroup.fSize]]; WHILE s < sMinBand DO IF run.lastRun THEN s _ s + 1; run _ run + SIZE[PDFileFormat.Run]; ENDLOOP; WHILE s < sMaxBand DO DoLine[sMin: s, fMin: run.fMin+maskRunGroup.fOffset, fSize: run.fSize]; IF run.lastRun THEN s _ s + 1; run _ run + SIZE[PDFileFormat.Run]; ENDLOOP; TempColor[[maskRunGroup.sMin, maskRunGroup.fMin, maskRunGroup.sSize, maskRunGroup.fSize]]; IF leftovers AND maskRunGroup.loadAddress>=0 AND maskRunGroup.sMin+maskRunGroup.sSize>bandMaxS THEN { maskRunGroup.sSize_maskRunGroup.sSize-(s-maskRunGroup.sMin); maskRunGroup.sMin_s; maskRunGroup.runCount _ -1; --unused, eventually eliminate from DEF maskRunGroup.pointer_run; AddLeftover[]; }; }; maskSamples: PDFileReader.MaskSamples => { rectangle: ImagerPixelMap.DeviceRectangle _ ImagerPixelMap.Window[maskSamples.samples]; TempColor[rectangle]; SELECT currentColorType FROM none => ERROR; clear => ImagerPixelMap.Transfer[band, maskSamples.samples, [and, complement]]; opaqueTile, ink => ImagerPixelMap.Transfer[band, maskSamples.samples, [or, null]]; transparentTile => { bounds: ImagerPixelMap.DeviceRectangle _ ImagerPixelMap.Intersect[rectangle, ImagerPixelMap.Window[band]]; destDesc: ImagerPixelMap.PixelMap_ImagerPixelMap.Create[lgBitsPerPixel: 0, bounds: bounds]; GetColorTile[]; ImagerPixelMap.TransferTile[dest: destDesc, tile: cachedColorTile]; ImagerPixelMap.Transfer[dest: destDesc, source: maskSamples.samples, function: [and, null]]; ImagerPixelMap.Transfer[dest: band, source: destDesc, function: [or, null]]; }; ENDCASE => ERROR; TempColor[rectangle]; IF leftovers AND maskSamples.loadAddress>=0 AND maskSamples.samples.sOrigin+maskSamples.samples.sMin+maskSamples.samples.sSize > bandMaxS THEN AddLeftover[]; }; colorSamples: PDFileReader.ColorSamples => { ImagerPixelMap.Transfer[band, colorSamples.samples]; }; deviceCommand: PDFileReader.DeviceCommand => { }; ENDCASE => NULL; ENDLOOP; EXITS Quit => NULL; }; StartImage: PROC [fileHandle: PDFileReader.Handle, oldPixelMap: ImagerPixelMap.PixelMap_[,,,,,,NIL] ] RETURNS [handle: PDReaderPage.Handle] = TRUSTED { handle_NEW[PDReaderPage.Rep]; IF oldPixelMap.refRep=NIL THEN handle.pixelMap_ImagerPixelMap.Create[lgBitsPerPixel: 0, bounds: [sMin: 0, fMin: 0, sSize: fileHandle.herald.bandSSize, fSize: fileHandle.herald.imageFSize]] ELSE handle.pixelMap_ImagerPixelMap.Reshape[refRep: oldPixelMap.refRep, lgBitsPerPixel: 0, bounds: [sMin: 0, fMin: fileHandle.image.fMinPage, sSize: fileHandle.herald.bandSSize, fSize: fileHandle.image.fSizePage]]; handle.pixelMap.sOrigin _ fileHandle.herald.bandSSize*fileHandle.image.passBands; ImagerPixelMap.Clear[handle.pixelMap]; }; GetPageStructure: PUBLIC PROC [handle: PDFileReader.Handle] RETURNS [PageRecRef, INT] ~ { pages, pageTail: PageRecRef_NIL; currentPageNumber: INT_0; copyHandle: PDFileReader.Handle_NEW[PDFileReader.Rep _ handle^]; streamInitialIndex: INT_handle.stream.GetIndex[]; handle.stream.SetIndex[SIZE[PDFileFormat.Herald]*bytesPerWord];--start of file just past Herald DO WITH copyHandle.Get[scanning: TRUE] SELECT FROM stateChange: PDFileReader.StateChange => { SELECT stateChange.whatChanged FROM imageStart => { IF copyHandle.image.nBands>0 THEN { newPage: PageRecRef_NEW[PageRec _[link: NIL, type: imageStart, pageNumber: (currentPageNumber_currentPageNumber+1), index: copyHandle.stream.GetIndex[]-(SIZE[PDFileFormat.StartImage]+SIZE[PDFileFormat.Command])*bytesPerWord]]; IF pages=NIL THEN pages_pageTail_newPage ELSE {pageTail.link_newPage; pageTail_newPage}; }; }; imageEnd => NULL; priorityChange => NULL; colorChange => NULL; bandChange => NULL; loadChange => { newPage: PageRecRef_NEW[PageRec _[link: NIL, type: loadChange, pageNumber: -1, index: copyHandle.stream.GetIndex[]-(SIZE[PDFileFormat.StoreLoad]+SIZE[PDFileFormat.Command]+stateChange.loadChangeLength)*bytesPerWord]]; IF pages=NIL THEN pages_pageTail_newPage ELSE {pageTail.link_newPage; pageTail_newPage; }; }; documentEnd => { handle.stream.SetIndex[streamInitialIndex]; --restore PD stream RETURN [pages, currentPageNumber]; }; ENDCASE => PDFileReader.Error[handle: handle, code: unrecognisedControlCommand, wordIndex: -1, wordCount: -1, description: "Page structure Get error"]; }; ENDCASE => NULL; ENDLOOP; }; ResetToPage: PUBLIC PROC [data: REF ANY] RETURNS [PageRecRef] ~ { rebuildLoad: BOOLEAN _ TRUE; showData: ShowPD.ShowData _ NARROW[data]; handle: PDFileReader.Handle _ showData.show; pageNumber: INT _ showData.pageNumber; nextPage: PageRecRef _ showData.pageStructure; handle.priority_0; handle.colorType_none; --fake the reader into rebuilding the load IF showData.atPage#NIL AND showData.atPage.pageNumber >= pageNumber THEN rebuildLoad_FALSE; UNTIL nextPage=NIL DO SELECT nextPage.type FROM imageStart => IF nextPage.pageNumber=pageNumber THEN { handle.stream.SetIndex[nextPage.index]; --set stream to point to StartImage command showData.atPage _ nextPage; RETURN[nextPage]; }; loadChange => { IF rebuildLoad THEN { handle.stream.SetIndex[nextPage.index]; --set stream to point to storeLoad command WITH handle.Get[scanning: FALSE] SELECT FROM --handle.Get[] has the side effect of building the load!! sc: PDFileReader.StateChange => SELECT sc.whatChanged FROM loadChange => NULL; --found the expected loadChange command ENDCASE => PDFileReader.Error[handle: handle, code: unrecognisedControlCommand, wordIndex: -1, wordCount: -1, description: "Page structure index error"]; --found a StateChange which was not a loadChange ENDCASE => PDFileReader.Error[handle: handle, code: unrecognisedControlCommand, wordIndex: -1, wordCount: -1, description: "Page structure index error"]; --pages tried to point to a loadChange but reader didn't find one }; }; ENDCASE => PDFileReader.Error[handle: handle, code: unrecognisedControlCommand, wordIndex: -1, wordCount: -1, description: "Page structure type error"]; nextPage_nextPage.link; ENDLOOP; RETURN[NIL]; --never found the requested pageNumber }; }. --END x--PDReaderPageImpl.mesa --Last edited by Ken Pier, July 8, 1985 3:51:58 pm PDT --Last edited by Michael Plass, March 13, 1984 2:07:32 pm PST Leftover list types Interprets one page (may be multiple passes ??), and paints it in viewer. May raise PDFileReader.Warning or PDFileReader.Error. Returns FALSE upon document end. now remove this record from readList update pixelMap in handle calculate initial edges: assumes filestream is available from Handle and Gets can be executed safely a DUMB routine to reconstruct the load for the given page requires that a page structure has already been built using GetPageStructure Ê æ˜Jšœ™Jšœ6™6Jšœ=™=J™šÏk ˜ Jšœ˜Jšœ ˜ Jšœ ˜ Jšœ ˜ Jšœ˜Jšœ˜Jšœ˜Jšœ˜J˜ Jšœ˜—unitšœœ˜Jšœœœ˜NJ˜—Jšœ œ˜&Jšœœ˜(Jšœ œ˜+Jšœ œ˜%J˜J™Jšœ œœ ˜!šœ œœ˜Jšœœ˜Jšœ œœ˜Jšœ"˜"Jšœœ˜ Jšœ ˜ J˜—J˜š Ïn œœœPœœœ˜‹J™IJšœW™WJ™Jš œœœ œÏc˜IJ˜Jšœ!œ˜%Jšœœ˜.Jšœ.œŸ"˜UJšœ)˜)Jšœœ˜&Jšœœ˜Jšœ œŸ2˜FJšœ œœ˜Jšœ˜Jšœ œ˜J˜%Jšœœ˜šž œœ˜šœ4œ˜œœ˜VJ˜—šœ ˜ šœ>œ˜DJšœ˜—Jšœœ˜!Jšœœ˜J˜—Jšœœ˜Jšœœ˜šœ˜Jšœœ˜šœ>œ˜DJšœ˜—Jšœ™Jšœc˜cJšœ+˜+Jšœ˜Jšœ+˜+Jš œ œœœŸ˜0Jšœ˜Jšœ œ˜Jšœ˜—Jšœœ˜Jšœœœ˜Jšœœ˜—Jšœ˜—šœ.˜.Jšœf˜fJšœ œ1œ˜TJšœ˜—šœ.˜.Iašœ œœ"˜:šžœœœœ˜MJšœ˜Jšœ˜Jšœ&˜&Jšœ˜Jšœ œ&˜7Jšœ˜—Jšœ œœ-˜BJšœ œœY˜nJšœ œ˜#Jšœ œ*˜