DIRECTORY BasicTime, BiScrollers, FunctionCache, FS, Geom2D, Imager, ImagerArtwork, ImagerBackdoor, ImagerColor, ImagerInterpress, ImagerMemory, ImagerPixel, ImagerPixelArray, ImagerTransformation, InputFocus, InterpressInterpreter, IO, MessageWindow, PPreView, PPreViewClient, RasterEncodingStandardIO, Real, Rope, SF, Vector2, ViewerAbort, ViewerClasses, ViewerGroupLocks, ViewerLocks, ViewerPrivate, ViewerTools; PPreViewImpl: CEDAR MONITOR IMPORTS BiScrollers, FunctionCache, FS, Geom2D, Imager, ImagerArtwork, ImagerBackdoor, ImagerColor, ImagerInterpress, ImagerMemory, ImagerPixel, ImagerPixelArray, ImagerTransformation, InputFocus, InterpressInterpreter, IO, MessageWindow, PPreView, PPreViewClient, Real, Rope, SF, Vector2, ViewerAbort, ViewerGroupLocks, ViewerLocks, ViewerPrivate, ViewerTools EXPORTS PPreView ~ BEGIN Data: TYPE ~ PPreView.Data; IPData: TYPE ~ PPreView.IPData; AISData: TYPE ~ PPreView.AISData; RESData: TYPE ~ PPreView.RESData; PaintOp: TYPE ~ PPreView.PaintOp; Context: TYPE ~ Imager.Context; Rectangle: TYPE ~ Imager.Rectangle; Transformation: TYPE ~ ImagerTransformation.Transformation; Viewer: TYPE ~ ViewerClasses.Viewer; Vec: TYPE ~ Geom2D.Vec; PProc: TYPE ~ PROC [Context]; CacheKey: TYPE ~ REF CacheKeyRep; CacheKeyRep: TYPE ~ RECORD [ fileName: Rope.ROPE, created: BasicTime.GMT, pageNumber: INTEGER ]; globalCache: FunctionCache.Cache ¬ FunctionCache.GlobalCache[]; screenResolution: REAL ~ 72.0; -- points per inch pointsPerInch: REAL ~ 72.0; oneOverPointsPerInch: REAL ~ 1.0/72.0; pointsPerMica: REAL ~ 72.0/2540.0; micasPerPoint: REAL ~ 2540.0/72.0; pointsPerMeter: REAL ~ 72.0/.0254; metersPerPoint: REAL ~ .0254/72.0; grey: CARDINAL ¬ 122645B; xorStipple: Imager.Color ~ ImagerBackdoor.MakeStipple[stipple: grey, xor: TRUE]; borderWidth: REAL ¬ 2.0; fudge: REAL ¬ 2.0; useMessageWindow: BOOL ¬ FALSE; Message: PROC [message: Rope.ROPE, clearFirst, blink: BOOL ¬ TRUE] ~ { MessageWindow.Append[Rope.Concat["PreView: ", message], clearFirst]; IF blink THEN MessageWindow.Blink[]; }; RectangleFromXYs: PUBLIC PROC [x0, y0, x1, y1: REAL] RETURNS [r: Imager.Rectangle] ~ { IF x0 > x1 THEN {t: REAL ¬ x0; x0 ¬ x1; x1 ¬ t}; IF y0 > y1 THEN {t: REAL ¬ y0; y0 ¬ y1; y1 ¬ t}; r ¬ [x0, y0, x1-x0, y1-y0]; }; PVNotify: PUBLIC ViewerClasses.NotifyProc ~ {-- [self: Viewer, input: LIST OF REF ANY] ENABLE UNWIND => NULL; NewMouse: PROC ~ { IF InputFocus.GetInputFocus[].owner # self THEN InputFocus.SetInputFocus[self]; IF b.all THEN { dif: Imager.VEC ¬ Vector2.Sub[[mouseX, mouseY], b.origin]; b.p0 ¬ Vector2.Add[b.p0, dif]; b.p1 ¬ Vector2.Add[b.p1, dif]; b.origin ¬ [mouseX, mouseY]; } ELSE { IF b.x0 THEN b.p0.x ¬ mouseX ELSE IF b.x1 THEN b.p1.x ¬ mouseX; IF b.y0 THEN b.p0.y ¬ mouseY ELSE IF b.y1 THEN b.p1.y ¬ mouseY; }; b.rect ¬ RectangleFromXYs[b.p0.x, b.p0.y, b.p1.x, b.p1.y]; PVFeedback[data: data, v: self, op: change]; --paint grey box }; mouseX, mouseY: REAL ¬ 0.0; data: Data ¬ NARROW[BiScrollers.ClientDataOfViewer[self]]; b: PPreView.BBoxState ¬ data.bBox; IF data.painting THEN RETURN; -- ignore input while painting FOR list: LIST OF REF ANY ¬ input, list.rest UNTIL list = NIL DO WITH list.first SELECT FROM x: ATOM => SELECT x FROM $Abort => { IF b.active THEN PVFeedback[data: data, v: self, op: remove]; -- kill grey bbox b­ ¬ []; -- initialization default values cancel current clipping rectangle }; $Down => { -- determine user interaction (corner, edge, or center?) once: BOOL ¬ FALSE; wOver4, hOver4: REAL; b.x0 ¬ b.x1 ¬ b.y0 ¬ b.y1 ¬ b.all ¬ FALSE; IF NOT b.active THEN { b.x1 ¬ b.y1 ¬ TRUE; b.p0 ¬ b.p1 ¬ [mouseX, mouseY]; b.active ¬ TRUE; -- turn it on and leave it on RETURN; }; IF b.p0.x > b.p1.x THEN {t: REAL ¬ b.p0.x; b.p0.x ¬ b.p1.x; b.p1.x ¬ t}; IF b.p0.y > b.p1.y THEN {t: REAL ¬ b.p0.y; b.p0.y ¬ b.p1.y; b.p1.y ¬ t}; wOver4 ¬ (b.p1.x-b.p0.x)/4; hOver4 ¬ (b.p1.y-b.p0.y)/4; SELECT mouseX FROM < b.p0.x+wOver4 => b.x0 ¬ TRUE; > b.p1.x-wOver4 => b.x1 ¬ TRUE; ENDCASE => once ¬ TRUE; SELECT mouseY FROM < b.p0.y+hOver4 => b.y0 ¬ TRUE; > b.p1.y-hOver4 => b.y1 ¬ TRUE; ENDCASE => IF once THEN { b.all ¬ TRUE; b.origin ¬ [mouseX, mouseY]; }; NewMouse[]; }; $Move => NewMouse[]; $EndMove, $ShowSelection => PPreViewClient.ShowSelection[data, self]; ENDCASE => NULL; z: BiScrollers.ClientCoords => { -- TYPE = REF Vec mouseX ¬ z.x; -- mouseX in BiScroller coords mouseY ¬ z.y; -- mouseY in BiScroller coords IF useMessageWindow THEN Message[IO.PutFR["%g, %g", IO.real[z.x], IO.real[z.y]], TRUE, FALSE]; }; ENDCASE => Message["unknown input Notify operation"]; ENDLOOP; }; PVFeedback: PUBLIC PROC [data: Data, v: Viewer, op: PPreView.PaintOp ¬ paint] ~ { ENABLE UNWIND => data.bBox­ ¬ []; -- kill selection in desperation Action: PROC [context: Context] ~ { -- this context in viewer coords Show: PROC [r: Rectangle, updateDimensions: BOOL ¬ FALSE] ~ { ctv: Transformation ¬ PPreViewClient.GetTransformation[v]; r ¬ ImagerTransformation.TransformRectangle[m: ctv, r: r]; Imager.MaskRectangle[context, [r.x-5.0, r.y-5.0, 5.0, r.h+10.0]]; -- left side Imager.MaskRectangle[context, [r.x+r.w, r.y-5.0, 5.0, r.h+10.0]]; -- right side Imager.MaskRectangle[context, [r.x, r.y-5.0, r.w, 5.0]]; -- top side Imager.MaskRectangle[context, [r.x, r.y+r.h, r.w, 5.0]]; -- bottom side IF updateDimensions THEN { ViewerTools.SetContents[data.selectionWViewer, IO.PutFR1["%6.3f", IO.real[oneOverPointsPerInch*r.w]]]; ViewerTools.SetContents[data.selectionHViewer, IO.PutFR1["%6.3f", IO.real[oneOverPointsPerInch*r.h]]]; }; }; IF data.bBox.prev = data.bBox.rect AND op = change THEN RETURN; -- no change Imager.SetColor[context, xorStipple]; SELECT op FROM paint => Show[data.bBox.rect]; remove => { IF data.abort THEN data.abort ¬ FALSE ELSE IF data.bBox.prev # [0., 0., 0., 0.] THEN Show[data.bBox.prev]; -- remove old box data.bBox.prev ¬ [0.0, 0.0, 0.0, 0.0]; }; change => { IF data.abort THEN data.abort ¬ FALSE ELSE IF data.bBox.prev # [0., 0., 0., 0.] THEN Show[data.bBox.prev]; -- remove old box Show[data.bBox.rect, TRUE]; -- show new box }; ENDCASE => Message["unknown feedback operation"]; data.bBox.prev ¬ data.bBox.rect; }; DirectPaint[viewer: v, action: Action]; }; DoFileOps: PUBLIC PROC [ op: PPreView.BBoxOp, viewer: Viewer, data: Data, fileName: Rope.ROPE, clip: BOOL ¬ TRUE] ~ { ctv: Transformation ¬ PPreViewClient.GetTransformation[viewer]; r: Rectangle ¬ ImagerTransformation.TransformRectangle[m: ctv, r: data.bBox.rect]; clipRect: REF Rectangle ¬ IF NOT clip THEN NIL ELSE NEW[Rectangle ¬ ImagerTransformation.InverseTransformRectangle[ctv, r]]; SELECT op FROM stuff => { -- stuff requires clip to be TRUE and bBox valid DoStuff: PROC [context: Context] ~ { DoIt: PROC ~ { Imager.ConcatT[context, ctv]; DoPainting[context: context, data: data, viewer: viewer, clipRect: clipRect]; }; Imager.TranslateT[context, [-r.x, -r.y]]; Imager.DoSaveAll[context, DoIt]; IF data.stuffWithBorders THEN { Imager.SetStrokeWidth[context, borderWidth]; Imager.SetGray[context, 1]; Imager.MaskVector[context, [r.x, r.y], [r.x, r.y+r.h]]; -- left side Imager.MaskVector[context, [r.x, r.y], [r.x+r.w, r.y]]; -- bottom side Imager.MaskVector[context, [r.x+r.w, r.y], [r.x+r.w, r.y+r.h]]; -- right side Imager.MaskVector[context, [r.x, r.y+r.h], [r.x+r.w, r.y+r.h]]; -- top side }; }; m: Transformation ¬ ImagerArtwork.Points[]; ImagerArtwork.PasteArtwork[DoStuff, [0, 0, r.w, r.h], m, TRUE, data.stuffWithFit]; }; ipMaster => { DoIPMaster: PROC [context: Context] ~ { Imager.ScaleT[context, metersPerPoint]; IF clip THEN { Imager.TranslateT[context, [-r.x, -r.y]]; Imager.ClipRectangle[context, r]; }; Imager.ConcatT[context, ctv]; DoPainting[context: context, data: data, viewer: viewer, clipRect: clipRect]; }; ref: ImagerInterpress.Ref ¬ ImagerInterpress.Create[fileName: fileName ! FS.Error => { Message[Rope.Concat[error.explanation, " creating IPMaster"]]; GOTO Quit; }]; ImagerInterpress.DoPage[self: ref, action: DoIPMaster ! Imager.Error => { Message[Rope.Concat[error.explanation, " creating IPMaster"]]; ImagerInterpress.Close[ref]; GOTO Quit; }]; ImagerInterpress.Close[ref]; EXITS Quit => data.abort ¬ TRUE; }; ENDCASE; }; DirectPaint: PROC [viewer: Viewer, action: PProc] ~ { CallLocked: PROC ~ {ViewerPrivate.PaintClient[viewer, action ! ABORTED => CONTINUE]}; IF viewer = NIL OR viewer.destroyed OR viewer.paintingWedged THEN RETURN; ViewerGroupLocks.CallRootUnderWriteLock[CallLocked, viewer ! ViewerLocks.Wedged => {viewer.paintingWedged ¬ TRUE; CONTINUE}]; }; DoPainting: PROC [context: Context, data: Data, viewer: Viewer, clipRect: REF Rectangle ¬ NIL] ~ { IF data.clientPaint # NIL THEN [] ¬ data.clientPaint[viewer, context, data.clientData, TRUE] ELSE WITH data SELECT FROM ipData: IPData => PaintIP[context: context, ipData: ipData]; --kills context variables, but ok resData: RESData => PaintRES[context: context, resData: resData, clipRect: clipRect]; aisData: AISData => PaintAIS[context: context, aisData: aisData, clipRect: clipRect]; ENDCASE => Message["unknown paint operation"]; }; PaintIP: PROC [context: Context, ipData: IPData] ~ { ENABLE { Imager.Error => { Message[Rope.Concat[error.explanation, ". Use -M switch to preview this file."]]; GOTO Null; -- return cleanly from painting }; Imager.Warning => RESUME; }; IF ipData.ipMaster # NIL THEN SELECT TRUE FROM ipData.switches['M] => { -- M switch means use no ImagerMemory selected: BOOL ¬ FALSE; Imager.SetGray[context, 1]; Imager.ScaleT[context, pointsPerMeter]; -- establish IP coord system InterpressInterpreter.DoPage[ipData.ipMaster, ipData.pageNumber, context, PPreView.IPLogError]; }; ipData.pageInMem=ipData.pageNumber => { -- iMemContext is current ImagerMemory.Replay[c: ipData.iMemContext, into: context]; }; ipData.pageInMem#ipData.pageNumber => { -- memory context may be cached PageCompareProc: FunctionCache.CompareProc ~ { RETURN[NARROW[argument, CacheKey]­ = cacheKey­]; }; cacheKey: CacheKey ¬ NEW[CacheKeyRep ¬ [ipData.fileInfo.fullFName, ipData.fileInfo.created, ipData.pageNumber]]; IF (ipData.iMemContext ¬ NARROW[FunctionCache.Lookup[x: globalCache, compare: PageCompareProc, clientID: $PVPage].value, Imager.Context])#NIL THEN { -- hit ImagerMemory.Replay[c: ipData.iMemContext, into: context]; ipData.pageInMem ¬ ipData.pageNumber; } ELSE { -- miss ipData.iMemContext ¬ ImagerMemory.NewMemoryContext[]; Imager.SetGray[ipData.iMemContext, 1]; Imager.ScaleT[ipData.iMemContext, pointsPerMeter]; -- establish IP coord system InterpressInterpreter.DoPage[ ipData.ipMaster, ipData.pageNumber, ipData.iMemContext, PPreView.IPLogError]; FunctionCache.Insert[x: globalCache, argument: cacheKey, value: ipData.iMemContext, size: ImagerMemory.GetContextSize[ipData.iMemContext], clientID: $PVPage]; ipData.pageInMem ¬ ipData.pageNumber; ImagerMemory.Replay[c: ipData.iMemContext, into: context]; }; }; ENDCASE => NULL; EXITS Null => NULL; }; < { Message[Atom.GetPName[code]]; pressData.abort ¬ TRUE; CONTINUE; }]; }; >> < Imager.DrawBitmap[ context: context, bitmap: handle.bitmap, position: [0,pdData.pdhandle.herald.imageSSize]]; ENDCASE => ERROR; }; IF pdData.scalePD THEN Imager.Scale2T[context, pdData.scaleFactors];-- do only once (outside of paintAction) IF PDImageReader.ResetToImage[pdData: pdData]#NIL THEN [] ¬ PDImageReader.InterpretImage[handle: pdData.pdhandle, viewer: viewer, paintAction: PaintIt]; --this guy eventually calls PaintIt. }; >> ClipPixelArray: PROC [pa: ImagerPixelArray.PixelArray, clipRectangle: Rectangle] RETURNS [new: ImagerPixelArray.PixelArray] ~ { MaxSample: PROC [i: NAT] RETURNS [ImagerPixel.Sample] ~ { RETURN [ImagerPixelArray.MaxSampleValue[pa, i]] }; paRect: Rectangle ¬ ImagerTransformation.InverseTransformRectangle[m: pa.m, r: clipRectangle]; paBox: SF.Box = SF.Intersect[[max: [pa.sSize, pa.fSize]], [min: [s: Real.Floor[paRect.x], f: Real.Floor[paRect.y]], max: [s: Real.Ceiling[paRect.x+paRect.w], f: Real.Ceiling[paRect.y+paRect.h]]]]; pixelMap: ImagerPixel.PixelMap = ImagerPixel.NewPixelMap[samplesPerPixel: pa.samplesPerPixel, box: paBox, maxSample: MaxSample]; FOR i: NAT IN [0..pixelMap.samplesPerPixel) DO ImagerPixelArray.Transfer[pa: pa, i: i, s: paBox.min.s, f: paBox.min.f, dst: pixelMap[i], dstMin: paBox.min, size: SF.Size[paBox]]; ENDLOOP; new ¬ ImagerPixelArray.FromPixelMap[pixelMap: pixelMap, box: paBox, scanMode: [slow: right, fast: up], immutable: TRUE]; new.m ¬ ImagerTransformation.PreTranslate[pa.m, [paBox.min.s, paBox.min.f]]; }; PaintAIS: PROC [context: Context, aisData: AISData, clipRect: REF Rectangle] ~ { state: PPreView.AISState ¬ aisData.state; pa: ImagerPixelArray.PixelArray ¬ state.pa; IF state.active THEN { IF clipRect#NIL THEN { pa ¬ ClipPixelArray[pa, clipRect­] }; IF state.op = NIL THEN { Imager.SetGray[context, 1]; Imager.MaskPixel[context: context, pa: pa] } ELSE Imager.DrawSampledColor[context: context, pa: pa, colorOperator: state.op]; }; }; PaintRES: PROC [context: Context, resData: RESData, clipRect: REF Rectangle] ~ { res: RasterEncodingStandardIO.RES = resData.image; maskImage: ImagerPixelArray.PixelArray ¬ res.maskImage; colorImage: ImagerPixelArray.PixelArray ¬ res.colorImage; MaskPABounds: PROC [pa: ImagerPixelArray.PixelArray] ~ { Inner: PROC ~ { Imager.ConcatT[context, pa.m]; Imager.MaskRectangle[context, [0, 0, pa.sSize, pa.fSize]]; }; Imager.DoSave[context, Inner]; }; IF clipRect#NIL THEN { IF maskImage # NIL THEN maskImage ¬ ClipPixelArray[maskImage, clipRect­]; IF colorImage # NIL THEN colorImage ¬ ClipPixelArray[colorImage, clipRect­]; }; SELECT TRUE FROM colorImage # NIL AND maskImage=NIL AND res.colorOperator # NIL AND res.colorOperator.samplesPerPixelIn = 1 AND ImagerPixelArray.MaxSampleValue[colorImage, 0] = 1 => { sample: CARDINAL ¬ 0; Pixel: PROC [NAT] RETURNS [REAL] ~ { RETURN [sample] }; maskImage ¬ colorImage; colorImage ¬ NIL; sample ¬ 0; Imager.SetColor[context, ImagerColor.ColorFromPixel[res.colorOperator, Pixel]]; MaskPABounds[maskImage]; sample ¬ 1; Imager.SetColor[context, ImagerColor.ColorFromPixel[res.colorOperator, Pixel]]; }; colorImage = NIL OR res.colorOperator = NIL => { Imager.SetGray[context, 1]; }; ENDCASE => { Imager.SetSampledColor[context, colorImage, NIL, res.colorOperator] }; IF maskImage=NIL THEN Imager.MaskRectangle[context, ImagerTransformation.TransformRectangle[m: colorImage.m, r: [0, 0, colorImage.sSize, colorImage.fSize]]] ELSE Imager.MaskPixel[context, maskImage]; }; < { -- M switch means use no ImagerMemory Imager.ScaleT[context, pointsPerMica]; -- establish Griffin coord. system Imager.SetStrokeJoint[context, round]; -- avoid miter problems GriffinImageUtils.GriffinToImagerCalls[context, gData.image]; }; gData.pageInMem=gData.pageNumber => { -- iMemContext is current ImagerMemory.Replay[c: gData.iMemContext, into: context]; }; gData.pageInMem#gData.pageNumber => { -- memory context may be cached PageCompareProc: FunctionCache.CompareProc ~ { RETURN[NARROW[argument, CacheKey]­ = cacheKey­]; }; cacheKey: CacheKey ¬ NEW[CacheKeyRep ¬ [gData.fileInfo.fullFName, gData.fileInfo.created, gData.pageNumber]]; IF (gData.iMemContext ¬ NARROW[FunctionCache.Lookup[x: globalCache, compare: PageCompareProc, clientID: $PVPage].value, Context])#NIL THEN { --hit ImagerMemory.Replay[c: gData.iMemContext, into: context]; gData.pageInMem ¬ gData.pageNumber; } ELSE { -- miss gData.iMemContext ¬ ImagerMemory.NewMemoryContext[]; Imager.ScaleT[gData.iMemContext, pointsPerMica]; -- establish Griffin coord. system Imager.SetStrokeJoint[gData.iMemContext, round]; -- avoid miter problems GriffinImageUtils.GriffinToImagerCalls[gData.iMemContext, gData.image]; FunctionCache.Insert[x: globalCache, argument: cacheKey, value: gData.iMemContext, size: ImagerMemory.GetContextSize[gData.iMemContext], clientID: $PVPage]; gData.pageInMem ¬ gData.pageNumber; ImagerMemory.Replay[c: gData.iMemContext, into: context]; }; }; ENDCASE => NULL; }; >> < { -- M switch means use no ImagerMemory Imager.ScaleT[context, pointsPerInch]; -- establish GG coord. system GGForPV.DrawData[context, pvData.data]; }; pvData.pageInMem=pvData.pageNumber => { -- iMemContext is current ImagerMemory.Replay[c: pvData.iMemContext, into: context]; }; pvData.pageInMem#pvData.pageNumber => { -- memory context may be cached PageCompareProc: FunctionCache.CompareProc ~ { RETURN[NARROW[argument, CacheKey]­ = cacheKey­]; }; cacheKey: CacheKey ¬ NEW[CacheKeyRep ¬ [pvData.fileInfo.fullFName, pvData.fileInfo.created, pvData.pageNumber]]; IF (pvData.iMemContext ¬ NARROW[FunctionCache.Lookup[x: globalCache, compare: PageCompareProc, clientID: $PVPage].value, Context])#NIL THEN { --hit ImagerMemory.Replay[c: pvData.iMemContext, into: context]; pvData.pageInMem ¬ pvData.pageNumber; } ELSE { -- miss pvData.iMemContext ¬ ImagerMemory.NewMemoryContext[]; Imager.ScaleT[pvData.iMemContext, pointsPerInch]; -- establish GG coord. system GGForPV.DrawData[pvData.iMemContext, pvData.data]; FunctionCache.Insert[x: globalCache, argument: cacheKey, clientID: $PVPage, size: ImagerMemory.GetContextSize[pvData.iMemContext], value: pvData.iMemContext]; pvData.pageInMem ¬ pvData.pageNumber; ImagerMemory.Replay[c: pvData.iMemContext, into: context]; }; }; ENDCASE => NULL; }; >> PVPaint: PUBLIC ENTRY ViewerClasses.PaintProc ~ TRUSTED { ENABLE ABORTED => GOTO Finished; -- return and unlock viewers data: Data ¬ NARROW[BiScrollers.ClientDataOfViewer[self]]; BEGIN ENABLE UNWIND => data.painting ¬ FALSE; -- abort is set, painting gets cleared PVPaintWithAbort: PROC ~ TRUSTED { data.abort ¬ data.painting ¬ TRUE; DoPainting[context: context, data: data, viewer: self]; data.abort ¬ data.painting ¬ FALSE; IF data.bBox.active THEN PVFeedback[data: data, v: self, op: paint]; }; ViewerAbort.CallWithAbortEnabled[self, PVPaintWithAbort]; END; EXITS Finished => NULL; }; PVDestroy: PUBLIC ENTRY ViewerClasses.DestroyProc ~ { -- [self: Viewer] ENABLE UNWIND => NULL; data: Data ¬ NARROW[BiScrollers.ClientDataOfViewer[self]]; WITH data SELECT FROM ipData: IPData => { IF ipData.ipMaster # NIL THEN InterpressInterpreter.Close[master: ipData.ipMaster]; ipData.ipMaster ¬ NIL; }; resData: RESData => { resData.image ¬ NIL; }; aisData: AISData => { aisData.state.pa ¬ NIL; aisData.state.op ¬ NIL; }; ENDCASE => Message["unknown destroy operation"]; }; PVGetName: PUBLIC ViewerClasses.GetProc ~ { RETURN[NARROW[BiScrollers.ClientDataOfViewer[self], Data].container.file]; }; PVBasicTransformProc: PUBLIC PROC [bs: BiScrollers.BiScroller] RETURNS [Transformation] ~ { actionArea: Viewer ¬ bs.style.QuaViewer[bs: bs, inner: TRUE]; data: Data ¬ NARROW[BiScrollers.ClientDataOfViewer[actionArea]]; height: REAL ¬ data.pageHeight; width: REAL ¬ data.pageWidth; ww: REAL ¬ actionArea.ww; wh: REAL ¬ actionArea.wh; RETURN[ImagerTransformation.Translate[[(ww-width)/2.0, (wh-height)/2.0]]]; }; PVExtremaProc: PUBLIC PROC [clientData: REF ANY, direction: Vec] RETURNS [min, max: Vec] ~ { --BiScrollers.ExtremaProc data: Data ¬ NARROW[clientData]; area: Geom2D.Rect ¬ [x: 0.0, y: 0.0, w: data.pageWidth, h: data.pageHeight]; [min, max] ¬ Geom2D.ExtremaOfRect[r: area, n: direction]; }; END. .. Old Preview.tip SELECT TRIGGER FROM Mouse WHILE Red Down => Coords, Move; Red Down => SELECT ENABLE FROM Yellow Down => Abort; ENDCASE => Coords, Move; Yellow Down => Abort; Red Up => EndMove; Blue Up => ShowSelection; ENDCASE. d PPreViewImpl.mesa Copyright Σ 1989, 1992 by Xerox Corporation. All rights reserved. Pier, January 4, 1991 4:28 pm PST Carl Hauser, August 18, 1989 4:35:28 pm PDT Michael Plass, March 25, 1992 12:20 pm PST pressData: PressData => PaintPress[context: context, pressData: pressData]; pdData: PDData => PaintPD[context: context, pdData: pdData, viewer: viewer]; gData: GData => PaintGriffin[context: context, gData: gData]; pvData: PVData => PaintGG[context: context, pvData: pvData]; PROC [argument: Domain] RETURNS [good: BOOL]; This routine may be called many times; it shouldn't do destructive operations on context state Reset the handle in pdData to the image in pdData.pageNumber, then interpret the image IF PDImageReader.ResetToImage[pdData: pdData]#NIL THEN IF NOT pdData.abort THEN [] _ PDImageReader.InterpretImage[handle: pdData.pdhandle, viewer: viewer, paintAction: PaintIt]; --this guy eventually calls PaintIt. PROC [argument: Domain] RETURNS [good: BOOL]; PROC [argument: Domain] RETURNS [good: BOOL]; [self: Viewer, context: Context, whatChanged: REF ANY, clear: BOOL]; AIS.CloseFile[aisData.state.openFile]; aisData.state.openFile _ NIL; pressData: PressData => { ShowPress.Close[pressData.presshandle]; pressData.presshandle _ NIL; }; pdData: PDData => { PDFileReader.Close[pdData.pdhandle]; pdData.pdhandle _ NIL; pdData.image _ NIL; }; gData: GData => { gData.image _ NIL; }; pvData: PVData => { pvData.data _ NIL; }; SafeStorage.ReclaimCollectibleObjects[suspendMe: FALSE]; -- good citizenship [self: Viewer, op: ATOM] RETURNS [data: REF ANY] This PROC for the benefit of XTSetter, which calls this when the InputFocus is in the previewer and the XTSetter GET button is clicked BiScrollers.TransformGenerator Put the center of the client specified size in the middle of the window. This proc is required by BiScrollers to return the extremes of the displayed data Κ?–(cedarcode) style•NewlineDelimiter ™code™Kšœ Οeœ7™BK™!K™+K™*—K˜šΟk ˜ Kšœžœžœ΅žœ΄˜•—K˜šΟn œžœž˜Kšžœ žœžœ΅žœŠ˜θšžœ ž˜K˜——Kšœžœ˜Kšœžœ˜Kšœžœ˜!Kšœžœ˜!Kšœžœ˜!Kšœžœ˜Kšœ žœ˜#Kšœžœ'˜;Kšœžœ˜$šœžœ˜K˜—Kšœžœžœ ˜Kšœ žœžœ ˜!šœ žœžœ˜Kšœžœ˜Kšœžœ˜Kšœ ž˜K˜K˜—K˜?Kšœžœ Οc˜2Kšœžœ˜Kšœžœ ˜&Kšœžœ˜"Kšœžœ˜"Kšœžœ˜"Kšœžœ˜"Kšœž œ ˜KšœJžœ˜PKšœ žœ˜Kšœžœ˜šœžœžœ˜K˜—š Ÿœžœžœžœžœ˜FK˜DKšžœžœ˜$K˜K˜—šŸœž œžœžœ˜VKšžΟsœ‘ž‘œžœ‘œ‘œ‘œ‘œ˜0Kšž‘œ‘ž‘œžœ‘œ‘œ‘œ‘œ˜0K˜K˜K˜—šŸœžœ Πcs ˜VKšžœžœžœ˜šŸœžœ˜šžœ)žœ ˜Ošžœ˜šžœ˜Kšœ žœ+˜:K˜K˜K˜K˜—šžœ˜Kš žœžœžœžœžœ˜?Kš žœžœžœžœžœ˜?K˜——K˜:Kšœ, ˜=K˜——Kšœžœ˜Kšœ žœ'˜:K˜"Kšžœžœžœ ˜<šžœžœžœžœžœžœžœž˜@šžœ žœž˜šœžœžœž˜˜ Kšžœ žœ- ˜OKšœ  B˜KK˜—šœ  8˜DKšœžœžœ˜Kšœžœ˜Kšœ$žœ˜*šžœžœ ˜šžœ˜Kšœžœ˜K˜Kšœ žœ  ˜2Kšžœ˜K˜——Kšž‘œ‘ž‘œžœ ‘œ‘œ ‘œ‘œ˜HKšž‘œ‘ž‘œž‘œ ‘œ‘œ ‘œ‘œ˜HK˜K˜šžœž˜Kšœžœ˜Kšœžœ˜Kšžœ žœ˜—šžœž˜Kšœžœ˜Kšœžœ˜šžœžœžœ˜Kšœžœ˜ K˜K˜——K˜ K˜—K˜K˜EKšžœžœ˜—šœ! ’ ’ ˜2Kšœ ˜,Kšœ ˜,šžœ˜Kš žœ žœžœ žœ žœžœ˜J—K˜—Kšžœ.˜5—Kšžœ˜—K˜K˜—šŸ œžœžœ:˜QKšžœžœ  ˜BšŸœžœ  ˜DšŸœžœ"žœžœ˜=K˜:K˜:KšœB  ˜NKšœB  ˜OKšœ<  ˜GKšœ< ˜Jšžœžœ˜šœ.žœ˜AKšžœ"˜$—šœ.žœ˜AKšžœ"˜$—K˜—K˜—Kš žœ!žœ žœžœ  ˜LK˜%šžœž˜K˜˜ šžœ ˜ Kšžœž˜Kšžœžœ#žœ ˜V—K˜&K˜—˜ šžœ ˜ Kšžœž˜Kšžœžœ#žœ ˜V—Kšœžœ ˜,K˜—Kšžœ*˜1—K˜ K˜—K˜'K˜K˜—šŸ œžœžœ˜Kšœ@žœžœžœ˜XK˜K˜?K•StartOfExpansionO[m: ImagerTransformation.Transformation, r: ImagerTransformation.Rectangle]˜Rš œ žœ žœžœžœž˜.KšžœžœE˜M—šžœž˜šœ  0˜;šŸœžœ˜$šŸœžœ˜K˜K˜MK˜—K˜)KšœŸœ˜ šžœžœ˜K–;[context: Imager.Context, color: ImagerColorDefs.Color]˜,K–;[context: Imager.Context, color: ImagerColorDefs.Color]˜Kšœ;  ˜GKšœ; ˜IKšœ@  ˜MKšœ?  ˜LK˜—K˜—K˜+KšœŸœžœ˜RK˜—˜ šΠbn œžœ˜'K˜'šžœžœ˜K˜)K˜!K˜—K˜K˜MK˜—–([fileName: ROPE, header: ROPE _ NIL]šœIžœ ˜VK˜>Kšžœ˜ K˜—˜IK˜>K˜Kšžœ˜ K˜—K˜šž˜Kšœžœ˜—K˜—Kšžœ˜—K˜K˜—šŸ œžœ$˜5Kš£ œžœ/žœžœ˜UKš žœ žœžœžœžœžœ˜I˜:Kšœ1žœžœ˜B—K˜K˜—šŸ œžœ:žœ žœ˜^K˜šžœž˜Kšžœ9žœ˜Bšžœžœžœž˜Kšœ= !˜^K˜UK˜UK™KK™LK™=K™Kšœ žœžœ˜K˜Kšœ( ˜DK˜_K˜—šœ( ˜AK˜:K˜—šœ( ˜Gš£œ˜.Kš‘œ‘œ‘œ™-Kšžœžœ#˜0K˜—šœžœ˜&K˜I—šžœžœkž˜šžœ ˜ K˜:K˜%K˜—šžœ ˜K˜5K˜&Kšœ3 ˜O˜K˜M—˜SK˜J—K˜%K˜:K˜——K˜—Kšžœžœ˜—šž˜Kšœžœ˜ —K˜K˜—šŸ œžœ-˜?K˜Kšœ' ˜F˜L˜K˜Kšœžœ˜Kšžœ˜ —K˜—K˜KšŸ˜—šŸ œžœ7˜FšŸœžœžœžœ˜6K™^Kšœžœ'˜>šžœ žœž˜˜2K˜Z—Kšžœžœ˜—K˜—šžœ˜Kšžœ. (˜Z—K™VKšžœ,žœžœc $˜½Kš žœ,žœžœžœžœžœc $™ΦK˜KšŸ˜—K˜šŸœžœ<˜PKšžœ#˜*K˜–K[samplesPerPixel: NAT, box: SF.Box, maxSample: ImagerPixel.PixelProc]šŸ œžœžœžœ˜9Kšžœ)˜/K˜—K–D[m: ImagerTransformation.Transformation, r: ImagerBox.Rectangle]˜^Kšœžœžœ²˜ΔK˜€šžœžœžœž˜.K–„[pa: ImagerPixelArray.PixelArray, i: NAT _ 0, s: INT _ 0, f: INT _ 0, dst: ImagerSample.SampleMap, dstMin: SF.Vec _ [s: 0, f: 0], size: SF.Vec _ [s: 32767, f: 32767], function: ImagerSample.Function _ [dstFunc: null, srcFunc: null]]šœsžœ˜ƒKšžœ˜—K–w[pixelMap: ImagerPixel.PixelMap, box: SF.Box, scanMode: ImagerTransformation.ScanMode, immutable: BOOL _ FALSE]šœržœ˜xK˜LK˜K˜—šŸœžœ0žœ˜PK˜)K˜+šžœžœ˜Kšžœ žœžœ(˜<šžœ ž˜–…[context: Imager.Context, pa: ImagerPixelArray.PixelArray, m: ImagerTransformation.Transformation _ NIL, clear: BOOL _ FALSE]šžœ˜K˜K˜*K˜—KšžœL˜P—K˜—K˜K˜—šŸœžœ0žœ˜PKšœžœ˜2K˜7K˜9šŸ œžœ&˜8šŸœžœ˜K˜K˜:K˜—K˜K˜—šžœ žœžœ˜Kšžœ žœžœ2˜IKšžœžœžœ4˜LK˜—šžœžœž˜šœ žœžœ žœžœžœžœ)žœ8˜¦Kšœžœ˜Kš Ÿœžœžœžœžœžœ ˜7K˜Kšœ žœ˜K˜ K˜OK˜K˜ K˜OK˜—šœ žœžœžœ˜0K˜K˜—Kšžœ2žœ˜S—šžœ ž˜K–D[m: ImagerTransformation.Transformation, r: ImagerBox.Rectangle]šžœ‡˜‹Kšžœ&˜*—K˜K˜—šŸœžœ%˜9šžœžœž˜šœ %˜=Kšœ' "˜IKšœ' ˜>K˜=K˜—šœ& ˜?K˜9K˜—šœ& ˜Eš£œ˜.Kš‘œ‘œ‘œ™-Kšžœžœ#˜0K˜—KšœžœU˜mš žœžœdžœžœ ˜’K˜9K˜#K˜—šžœ ˜K˜4Kšœ1 "˜SKšœ1 ˜HK˜GK˜œK˜#K˜9K˜—K˜—Kšžœžœ˜—K˜KšŸ˜—šŸ œžœ'˜6šžœžœž˜šœ %˜>Kšœ' ˜DKšœŸœ˜'K˜—šœ( ˜AK˜:K˜—šœ( ˜Gš£œ˜.Kš‘œ‘œ‘œ™-Kšžœžœ#˜0K˜—šœžœ˜&K˜I—šžœžœdž˜†šžœ ˜ K˜:K˜%K˜—šžœ ˜K˜5Kšœ2 ˜OK˜2K˜žK˜%K˜:K˜——K˜—Kšžœžœ˜—K˜KšŸ˜—šΠanœžœžœžœ˜9Kšœ.žœžœ žœ™DKšžœžœžœ  ˜=Kšœ žœ'˜:šΠbk˜Kšžœžœžœ &˜NšŸœžœžœ˜"Kšœžœ˜"KšΟb œ-˜7Kšœžœ˜#Kšžœžœ,˜DK˜—Kšœ'¦œ˜9Kš₯œ˜—šž˜Kšœ žœ˜—K˜K˜—š€ œžœžœ ˜GKšžœžœžœ˜Kšœ žœ'˜:šžœžœž˜˜K–[master: Interpress.Master]šžœžœžœ6˜SKšœžœ˜K˜—˜Kšœžœ˜K˜—˜KšΠkyΟy#™&Kš¨§¨™Kšœžœ˜Kšœžœ˜K˜—™K™'Kšœžœ™K™—™K™$Kšœžœ™Kšœžœ™K™—™Kšœžœ™K™—™Kšœžœ™K™—Kšžœ)˜0—Kšœ1žœ ™LK˜K˜—šŸ œžœ˜+K™0K™†Kšžœžœ=˜JK˜K˜—šŸœžœžœžœ˜[K™Kšœ7žœ˜=Kšœ žœ-˜@K™HKšœžœ˜Kšœžœ˜Kšœžœ˜Kšœžœ˜KšžœD˜JK˜K˜—š Ÿ œžœžœžœžœžœ˜XKšœ ˜K™QKšœ žœ ˜ K˜LK˜9K˜K˜—Kšžœ˜˜K˜šΠblœ˜Kšžœžœž˜˜šœžœ˜%K˜—šœ žœžœž˜K˜Kšžœ˜K˜—K˜K˜K˜K˜Kšžœ˜—K˜K˜———…—Mκl