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; SetClipArea: PUBLIC PROC [context: Context, area: Path] = { -- Establishes clipped area context.clientClipper _ TransformClipper[ClipperFromPath[area], context.clientTransform]; ValidateCompositeClipper[context]; }; ConcatArea: PUBLIC PROC [context: Context, area: Path, exclude: BOOLEAN _ FALSE] = { context.clientClipper _ ClipClipper[context.clientClipper, TransformClipper[ClipperFromPath[area], context.clientTransform]]; ValidateCompositeClipper[context]; }; TestArea: PUBLIC PROC [context: Context, area: Path] 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; }; ClipArea: PUBLIC PROC [context: Context, area: Path] RETURNS [Path] = { clipper: ClipperRecord _ ClipClipper[context.clipper, ClipperFromPath[area]]; RETURN[ PathFromClipper[clipper] ]; }; SetClipIntRectangle: PUBLIC PROC [context: Context, area: IntRectangle] = { context.clientClipper _ TransformClipper[ClipperFromRectangle[area], context.clientTransform]; ValidateCompositeClipper[context]; }; ConcatIntRectangle: PUBLIC PROC [context: Context, area: IntRectangle] = { 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: IntVec] 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; }; ClipIntRectangle: PUBLIC PROC [context: Context, area: IntRectangle] RETURNS [IntRectangle] = { SELECT context.clipper.type FROM rectangle => RETURN [ RectangleFromClipper[ IntersectClipBoxes[ClipperFromRectangle[area], context.clipper]] ]; 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; }; ConcatRectangle: PUBLIC PROC [context: Context, clipSpace: ImagingSpace, area: IntRectangle] = { SELECT clipSpace FROM client => SELECT context.clientClipper.type FROM rectangle => context.clientClipper _ IntersectClipBoxes[context.clientClipper, ClipperFromRectangle[area]]; path => context.clientClipper _ ClipClipper[context.clientClipper, ClipperFromRectangle[area]]; ENDCASE => ERROR; viewer => SELECT context.viewerClipper.type FROM rectangle => context.clientClipper _ IntersectClipBoxes[context.viewerClipper, ClipperFromRectangle[area]]; path => context.clientClipper _ ClipClipper[context.viewerClipper, ClipperFromRectangle[area]]; ENDCASE => ERROR; device => SELECT context.deviceClipper.type FROM rectangle => context.clientClipper _ IntersectClipBoxes[context.deviceClipper, ClipperFromRectangle[area]]; path => context.clientClipper _ ClipClipper[context.deviceClipper, ClipperFromRectangle[area]]; ENDCASE => ERROR; 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 18, 1983 10:34 am Client-called Procedures Client clipping areas are first transformed to fix them on the viewer Modifies old clipping region by supplied area. The Composite clipper is held in the device space, where clipping actually takes place. Therefore, incoming data is expected in device space (pretransformed). Fast Track procedures Returns subrectangle which lies entirely inside clipping area Each call must be preceded by a successful call to TestArea or TestIntRectangle Unpublicized Procedures Intersect rectangle with existing clipper to define new clipper Internal Procedures Does rectangle-preserving easy transforms only Assemble composite clipper, leave result in device space Κ«˜head™J™J™-šΟk ˜ Jšœ œ ˜Jšœ œ!˜0Jšœœ/˜BJšœœ9˜QJšœœ!˜6Jšœ˜——šœ ˜ Jšœ˜%Jšœ˜J˜Jšœœœ ˜—™J™EunitšΟn œ œ$Οc˜XJšœY˜YJšœ"˜"J˜—šž œ œ(œœ˜TJšœ.™.Jšœ:˜:JšœI˜IJšœ"˜"J˜—LšΟiŸ™Ÿšžœ œ œ˜MJšœ˜Jšœ/˜/Jšœ˜ šœE˜FJšœœœœ˜7Jšœœ˜—Jšœ œŸ˜/Jšœœ˜J˜—šž œ œ œœ˜KJšœ˜ Jšœ œ/œ˜BJšœ3˜6Jšœ3œ˜7Jšœ2˜2Jšœœœœ˜Jšœœœœ˜Jšœ œŸ˜.Jšœœ˜J˜—šžœ œ œ ˜GJšœM˜MJšœ˜#J˜—Lš ™šžœ œ+˜KJšœE˜EJšœ,˜,Jšœ"˜"J˜—šžœ œ*˜JJšœ'˜'Jšœ7˜;JšœQ˜UJšœ"˜"J˜—šžœ œ(œ˜]Jšœ˜Jšœ˜ šœ œJ˜YJšœœœœ˜7Jšœœ˜—Jšœ œ:˜IJšœœ˜J˜—šž œ œ#œœ˜QJšœ˜ Jšœ œ#œ#˜[Jšœ'œ"˜LJšœœœœ˜Jšœœœœ˜Jšœ œŸ˜.Jšœœ˜J˜—šžœ œ(œ˜_J™=Jšœ˜ Jšœ œ˜+JšœJ˜JJšœ œŸ˜.Jšœœ˜Jšœ˜—šžœ œœ˜NJšœ3žœž™OJš œœœœœ˜>Jšœ˜Jšœœœ˜7Jšœ˜——™šž œ œH˜_Jšœ ˜Jšœ-˜-Jšœ+˜+Jšœ+˜+Jšœœ˜Jšœ"˜"J˜—šž œ œH˜_Jšœ ˜Jšœ-˜-Jšœ+˜+Jšœ+˜+Jšœœ˜J˜—šžœ œD˜`J™?Jšœ ˜šœ ˜ Jšœ˜&JšœN˜NJšœ/˜/JšœC˜CJšœ,˜,Jšœœ˜—šœ ˜ Jšœ˜&JšœN˜NJšœ/˜/JšœC˜CJšœ,˜,Jšœœ˜—šœ ˜ Jšœ˜&JšœN˜NJšœ/˜/JšœC˜CJšœ,˜,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šœ˜——…— φ,©