DIRECTORY Real USING [Float], Imager USING [PathFromIntRectangle, Context], ImagerBasic USING [Path, Vec, IntVec, IntRectangle, Visibility], ImagerInternalDefs USING [ImagingSpace, Clipper, ClipperRecord, TransformRecord], ImagerTransform USING [IntTransform, TransformIntVec], ImagerClipper; ImagerClipperImpl: CEDAR PROGRAM IMPORTS Imager, ImagerTransform, Real EXPORTS Imager, ImagerClipper = BEGIN OPEN ImagerBasic; ClipPath: PUBLIC PROC [context: Context, outline: Path, exclude: BOOLEAN _ FALSE] = { context.clientClipper _ ClipClipper[context.clientClipper, TransformClipper[ClipperFromPath[area], context.clientTransform]]; ValidateCompositeClipper[context]; }; ClipRectangle: PROC [context: Context, outline: Rectangle, exclude: BOOLEAN _ FALSE]; TestRectangle: PUBLIC PROC [context: Context, area: Rectangle] RETURNS [Visibility] = { state: Visibility; clipper: ClipperRecord _ ClipperFromPath[area]; SELECT context.clipper.type FROM rectangle => { state _ TestClipperRectangle[clipper, context.clipper]; IF state = visible THEN context.noClipArmed _ TRUE; RETURN [ state ]; }; path => ERROR; -- until M. Plass works here ENDCASE => ERROR; }; TestPoint: PUBLIC PROC [context: Context, point: Vec] RETURNS [BOOLEAN] = { SELECT context.clipper.type FROM rectangle => IF (point.x <= Real.Float[context.clipper.xMax]) AND (point.x >= Real.Float[context.clipper.xMin]) AND (point.y <= Real.Float[context.clipper.yMax]) AND (point.y >= Real.Float[context.clipper.yMin]) THEN RETURN[ TRUE ] ELSE RETURN[ FALSE ]; path => ERROR; -- until M. Plass works here ENDCASE => ERROR; }; ClipIntRectangle: PUBLIC PROC [context: Context, outline: IntRectangle, exclude: BOOLEAN _ FALSE] = { IF context.clientTransform.type = hard THEN ConcatArea[context, Imager.PathFromIntRectangle[area]] ELSE ConcatRectangle[context, client, EZTfmRectangle[area, context.clientTransform]]; ValidateCompositeClipper[context]; }; TestIntRectangle: PUBLIC PROC [context: Context, area: IntRectangle] RETURNS [Visibility] = { state: Visibility; SELECT context.clipper.type FROM rectangle => { state _ TestClipperRectangle[ClipperFromRectangle[area], context.clipper]; IF state = visible THEN context.noClipArmed _ TRUE; RETURN [ state ]; }; path => RETURN [ TestArea[context, Imager.PathFromIntRectangle[area]] ]; ENDCASE => ERROR; }; TestIntPoint: PUBLIC PROC [context: Context, point: IntPair] RETURNS [BOOLEAN] = { SELECT context.clipper.type FROM rectangle => IF (point.x <= context.clipper.xMax) AND (point.x >= context.clipper.xMin) AND (point.y <= context.clipper.yMax) AND (point.y >= context.clipper.yMin) THEN RETURN[ TRUE ] ELSE RETURN[ FALSE ]; path => ERROR; -- until M. Plass works here ENDCASE => ERROR; }; DoWithoutClipping: PUBLIC PROC [context: Context, callBack: PROC[Context]] = { IF context.noClipArmed THEN context.noClip _ TRUE ELSE ERROR; callBack[ context ]; context.noClipArmed _ FALSE; context.noClip _ FALSE; }; SetClipper: PUBLIC PROC [context: Context, clipSpace: ImagingSpace, clipper: ClipperRecord] = { SELECT clipSpace FROM client => context.clientClipper _ clipper; viewer => context.viewerClipper _ clipper; device => context.deviceClipper _ clipper; ENDCASE => ERROR; ValidateCompositeClipper[context]; }; GetClipper: PUBLIC PROC [context: Context, clipSpace: ImagingSpace, clipper: ClipperRecord] = { SELECT clipSpace FROM client => clipper _ context.clientClipper; viewer => clipper _ context.viewerClipper; device => clipper _ context.deviceClipper; ENDCASE => ERROR; }; IntersectClipBoxes: PROC [clpr1, clpr2: ClipperRecord] RETURNS [ClipperRecord] = { clipper: ClipperRecord; clipper.xMin _ MAX[clpr1.xMin, clpr2.xMin]; clipper.xMax _ MIN[clpr1.xMax, clpr2.xMax]; clipper.yMin _ MAX[clpr1.yMin, clpr2.yMin]; clipper.yMax _ MIN[clpr1.yMax, clpr2.yMax]; IF (clipper.xMin >= clipper.xMax) OR (clipper.yMin >= clipper.yMax) -- disjoint areas? THEN { clipper.xMax _ clipper.xMin; clipper.yMax _ clipper.yMin; }; -- make null clipper.type _ rectangle; RETURN[clipper]; }; TestClipperRectangle: PROC [clippee, clipper: ClipperRecord] RETURNS [Visibility] = { IF (clippee.xMax <= clipper.xMin) OR (clippee.xMin >= clipper.xMax) OR (clippee.yMax <= clipper.yMin) OR (clippee.yMin >= clipper.yMax) THEN RETURN[ invisible ] ELSE IF (clippee.xMax <= clipper.xMax) AND (clippee.xMin >= clipper.xMax) AND (clippee.yMax <= clipper.yMax) AND (clippee.yMin >= clipper.yMin) THEN RETURN[ visible ] ELSE RETURN[ partlyVisible ]; }; ClipClipper: PROC [clipper1, clipper2: ClipperRecord] RETURNS [ClipperRecord] = { IF (clipper1.type = rectangle) AND (clipper2.type = rectangle) THEN RETURN [ IntersectClipBoxes[clipper1, clipper2] ] ELSE ERROR; -- M. Plass needed here }; ClipperFromPath: PROC [area: Path] RETURNS [ClipperRecord] = { clipper: ClipperRecord; clipper.type _ none; -- until M. Plass works here RETURN[clipper]; }; PathFromClipper: PROC [clipper: ClipperRecord] RETURNS [Path] = { path: Path; RETURN[path]; -- until M. Plass works here }; ClipperFromRectangle: PROC [area: IntRectangle] RETURNS [ClipperRecord] = { clipper: ClipperRecord; { OPEN clipper; type _ rectangle; xMin _ MIN[area.x, area.x + area.w]; xMax _ MAX[area.x, area.x + area.w]; yMin _ MIN[area.y, area.y + area.h]; yMax _ MAX[area.y, area.y + area.h]; clipper _ NIL; }; RETURN[clipper]; }; RectangleFromClipper: PROC [clipper: ClipperRecord] RETURNS [IntRectangle] = { OPEN clipper; RETURN [ IntRectangle[xMin, yMin, xMax - xMin, yMax - yMin] ]; }; EZTfmRectangle: PROC [area: IntRectangle, transform: TransformRecord] RETURNS [IntRectangle] = { rect: IntRectangle; IF (transform.type = hard) OR (transform.type = none) THEN ERROR; [[rect.x, rect.y]] _ ImagerTransform.IntTransform[transform, IntVec[area.x, area.y]]; [[rect.w, rect.h]] _ ImagerTransform.TransformIntVec[transform, IntVec[area.w, area.h]]; RETURN[ rect ]; }; TransformClipper: PROC [clipper: ClipperRecord, transform: TransformRecord] RETURNS [ClipperRecord] = { IF (transform.type # hard) AND (clipper.type = rectangle) THEN RETURN [ ClipperFromRectangle[ EZTfmRectangle[RectangleFromClipper[clipper], transform]] ] ELSE ERROR; -- M. Plass needed here }; ValidateCompositeClipper: PROC [context: Context] = { context.clipper _ ClipClipper[ TransformClipper[ ClipClipper[ TransformClipper[context.clientClipper, context.viewerTransform], context.viewerClipper], context.deviceTransform], context.deviceClipper]; }; END. ˜ImagerClipperImpl.mesa Created April 28, 1983 Last Edited by: Crow, June 20, 1983 8:46 pm Client-called Procedures Client clipping areas are first transformed to fix them on the viewer Modifies old clipping region by supplied outline. Exclude sets clipping outside path rather than inside. The Composite clipper is held in the device space, where clipping actually takes place. Therefore, incoming data is expected in device space (pretransformed). Modifies old clipping region by supplied outline. Exclude sets clipping outside path rather than inside. Fast Track procedures Modifies old clipping region by supplied outline. Exclude sets clipping outside path rather than inside. Each call must be preceded by a successful call to TestArea or TestIntRectangle Unpublicized Procedures Internal Procedures Does rectangle-preserving easy transforms only Assemble composite clipper, leave result in device space Κ8˜head™J™J™,šΟk ˜ Jšœ œ ˜Jšœ œ!˜0Jšœœ/˜BJšœœ9˜QJšœœ!˜6Jšœ˜——šœ ˜ Jšœ˜%Jšœ˜J˜Jšœœœ ˜—™J™EunitšΟnœ œ+œœ˜UJšœi™iJšœ:˜:JšœI˜IJšœ"˜"J˜—LšΟiŸ™Ÿšž œœ1œœ˜UJšœi™i—šž œ œ%œ˜WJšœ˜Jšœ/˜/Jšœ˜ šœE˜FJšœœœœ˜7Jšœœ˜—Jšœ œΟc˜/Jšœœ˜J˜—šž œ œ œœ˜KJšœ˜ Jšœ œ/œ˜BJšœ3˜6Jšœ3œ˜7Jšœ2˜2Jšœœœœ˜Jšœœœœ˜Jšœ œ ˜.Jšœœ˜J˜—LšŸ™šžœ œ3œœ˜eJšœi™iJšœ'˜'Jšœ7˜;JšœQ˜UJšœ"˜"J˜—šžœ œ(œ˜]Jšœ˜Jšœ˜ šœ œJ˜YJšœœœœ˜7Jšœœ˜—Jšœ œ:˜IJšœœ˜J˜—šž œ œ$œœ˜RJšœ˜ Jšœ œ#œ#˜[Jšœ'œ"˜LJšœœœœ˜Jšœœœœ˜Jšœ œ ˜.Jšœœ˜J˜—šžœ œœ˜NJšœ3žœž™OJš œœœœœ˜>Jšœ˜Jšœœœ˜7Jšœ˜——™šž œ œH˜_Jšœ ˜Jšœ-˜-Jšœ+˜+Jšœ+˜+Jšœœ˜Jšœ"˜"J˜—šž œ œH˜_Jšœ ˜Jšœ-˜-Jšœ+˜+Jšœ+˜+Jšœœ˜J˜——™šžœœœ˜RJšœ˜Jšœœ˜+Jšœœ˜+Jšœœ˜+Jšœœ˜+Jšœ œ! ˜WJšœF  ˜VJšœ˜Jšœ ˜Jšœ˜—šžœœ#œ˜UJšœ"œ ˜HJšœ"œ ˜DJšœœ ˜Jšœœ œ ˜MJšœ"œ˜DJšœœ ˜Jšœœ˜J˜—šž œœ%œ˜QJšœœ˜?Jšœœ+˜6Jšœœ  ˜,J˜—šžœœœ˜>Jšœ˜Jšœ ˜5Jšœ ˜J˜—šžœœœ ˜AJ˜ Jšœ ˜0Jšœ˜—šžœœœ˜KJšœ˜šœ ˜Jšœ˜Jšœœ˜$Jšœœ˜$Jšœœ˜$Jšœœ˜$Jšœ œ˜Jšœ˜—Jšœ ˜J˜—šžœœœ˜NJšœ ˜ Jšœ8˜>Jšœ˜—Lšžœœ2˜Fšœœ˜!J™.Jšœ˜Jšœœœœ˜AJšœU˜UJšœX˜XJšœ ˜Jšœ˜—Lšžœœ6˜Lšœœ˜!Jšœœ˜:Jšœœ˜#JšœC˜CJšœœ  ˜,Jšœ˜—šžœœ˜5J™8šœ˜šœ ˜ šœ˜šœ ˜ šœA˜AJšœ˜—Jšœ˜—Jšœ˜———Jšœ˜—J˜Jšœ˜——…—$`