<> <> <> 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.