DIRECTORY Imager USING [ImagingDevice, Context, FIXED, Vec, Transformation, TransformRep, TransformSpace], RealFns USING [SinDeg, CosDeg], Scaled USING [Value, PLUS, zero, FromReal, FromInt]; ImagerImpl: CEDAR PROGRAM IMPORTS RealFns, Scaled EXPORTS Imager = BEGIN OPEN Imager; Create: PUBLIC PROC [imagingDevice: ImagingDevice] RETURNS [Context] = { RETURN[NIL]; }; Translate: PUBLIC PROC [context: Context, x, y: REAL] = { transform: Transformation _ NEW[ TransformRep _ [1., 0., 0., 1., 0., 0., Scaled.zero, Scaled.zero, identity]]; transform.e _ x; transform.f _ y; transform.tx _ Scaled.FromReal[x]; transform.ty _ Scaled.FromReal[y]; ConcatToContext[context, client, transform]; }; Rotate: PUBLIC PROC [context: Context, degrees: REAL] = { transform: Transformation _ NEW[ TransformRep _ [1., 0., 0., 1., 0., 0., Scaled.zero, Scaled.zero, identity]]; WHILE degrees < 0. DO degrees _ degrees + 360.; ENDLOOP; -- Ridiculous numbers cost WHILE degrees > 360 DO degrees _ degrees - 360.; ENDLOOP; SELECT degrees FROM 90. => transform^ _ [0., 1., -1., 0., 0., 0., Scaled.zero, Scaled.zero, rot90]; 270. => transform^ _ [0., -1., 1., 0., 0., 0., Scaled.zero, Scaled.zero, rot270]; 180. => transform^ _ [-1., 0., 0., -1., 0., 0., Scaled.zero, Scaled.zero, rot180]; 0. => transform.type _ identity; ENDCASE => transform.type _ hard; SELECT transform.type FROM hard => { transform.a _ transform.d _ RealFns.CosDeg[degrees]; transform.b _ RealFns.SinDeg[degrees]; transform.c _ -transform.b; ConcatToContext[context, client, transform]; }; identity => NULL; ENDCASE => ConcatToContext[context, client, transform]; }; Scale: PUBLIC PROC [context: Context, s: REAL] = { transform: Transformation _ NEW[ TransformRep _ [1., 0., 0., 1., 0., 0., Scaled.zero, Scaled.zero, identity]]; transform.type _ hard; transform.a _ transform.d _ s; ConcatToContext[context, client, transform]; }; Scale2: PUBLIC PROC [context: Context, sx, sy: REAL] = { transform: Transformation _ NEW[ TransformRep _ [1., 0., 0., 1., 0., 0., Scaled.zero, Scaled.zero, hard]]; IF sx = -1. -- Catch the Mirror transforms THEN IF sy = 1. THEN transform^ _ [-1., 0., 0., 1., 0., 0., Scaled.zero, Scaled.zero, mirrorX] ELSE IF sy = -1. THEN transform^ _ [-1., 0., 0., -1., 0., 0., Scaled.zero, Scaled.zero, rot180]; IF sx = 1. THEN IF sy = -1. THEN transform^ _ [1., 0., 0., -1., 0., 0., Scaled.zero, Scaled.zero, mirrorY] ELSE IF sy = 1. THEN transform.type _ identity; SELECT transform.type FROM hard => { transform.a _ sx; transform.d _ sy; ConcatToContext[context, client, transform]; }; identity => NULL; ENDCASE => ConcatToContext[context, client, transform]; }; IntTranslate: PUBLIC PROC [context: Context, x, y: INT] = { transform: Transformation _ NEW[ TransformRep _ [1., 0., 0., 1., 0., 0., Scaled.zero, Scaled.zero, identity]]; transform.e _ x; transform.f _ y; transform.tx _ Scaled.FromInt[x]; transform.ty _ Scaled.FromInt[y]; ConcatToContext[context, client, transform]; }; ConcatToContext: PUBLIC PROC [context: Context, transformSpace: TransformSpace, transform: Transformation] = { SELECT transformSpace FROM client => context.clientTransform _ Concat[context.clientTransform, transform]; view => context.viewTransform _ Concat[context.viewTransform, transform]; device => context.deviceTransform _ Concat[context.deviceTransform, transform]; ENDCASE => ERROR; context.validCompositeTransform _ FALSE; }; SetTransform: PUBLIC PROC [context: Context, transformSpace: TransformSpace, transform: Transformation] = TRUSTED { context.clientTransform _ transform; context.validCompositeTransform _ FALSE; }; GetTransform: PUBLIC PROC [context: Context, transformSpace: TransformSpace] RETURNS [Transformation] = { transform: Transformation _ NEW[ TransformRep _ [1., 0., 0., 1., 0., 0., Scaled.zero, Scaled.zero, identity]]; SELECT transformSpace FROM client => transform _ context.clientTransform; view => transform _ context.viewTransform; device => transform _ context.deviceTransform; ENDCASE => ERROR; RETURN[transform]; }; Concat: PUBLIC PROC [m, n: Transformation] RETURNS [Transformation] = { transform: Transformation _ NEW[ TransformRep _ [1., 0., 0., 1., 0., 0., Scaled.zero, Scaled.zero, identity]]; SELECT n.type FROM identity => { transform.e _ m.e + n.e; transform.tx _ Scaled.PLUS[m.tx, n.tx]; transform.f _ m.f + n.f; transform.ty _ Scaled.PLUS[m.tx, n.ty]; }; ENDCASE => { transform.a _ m.a*n.a + m.b*n.c; transform.b _ m.a*n.b + m.b*n.d; transform.c _ m.c*n.a + m.d*n.c; transform.d _ m.c*n.b + m.d*n.d; transform.e _ m.e*n.a + m.f*n.c + n.e; transform.tx _ Scaled.FromReal[transform.e]; transform.f _ m.e*n.b + m.f*n.d + n.f; transform.ty _ Scaled.FromReal[transform.f]; transform.type _ hard; }; RETURN[transform]; }; Invert: PUBLIC PROC [m: Transformation] RETURNS [Transformation] = { transform: Transformation _ NEW[ TransformRep _ [1., 0., 0., 1., 0., 0., Scaled.zero, Scaled.zero, identity]]; det: REAL; det _ m.a*m.d - m.b*m.c; -- compute determinant transform.a _ m.d / det; transform.b _ -m.b / det; transform.c _ -m.c / det; transform.d _ m.a / det; transform.e _ (m.c * m.f - m.d * m.e) / det; transform.f _ (m.b * m.e - m.a * m.f) / det; transform.tx _ Scaled.FromReal[transform.e]; transform.ty _ Scaled.FromReal[transform.f]; transform.type _ hard; RETURN[transform]; }; MakeNonHard: PUBLIC PROC [m: Transformation, epsilon: REAL] RETURNS [Transformation] = { -- Make non-hard if a, b, c, d all within epsilon of values for one of the non-hard cases transform: Transformation _ NEW[ TransformRep _ [1., 0., 0., 1., 0., 0., Scaled.zero, Scaled.zero, identity]]; IF (ABS[m.a] < epsilon -- test for rotation or axis interchange ops AND ABS[m.d] < epsilon AND (ABS[ABS[m.b] - 1.0] < epsilon) AND (ABS[ABS[m.c] - 1.0] < epsilon) ) THEN IF m.b > 0 THEN IF m.c > 0 THEN transform^ _ [0., 1., 1., 0., 0., 0., Scaled.zero, Scaled.zero, mirror45Deg] ELSE transform^ _ [0., 1., -1., 0., 0., 0., Scaled.zero, Scaled.zero, rot90] ELSE IF m.c > 0 THEN transform^ _ [0., -1., 1., 0., 0., 0., Scaled.zero, Scaled.zero, rot270] ELSE transform^ _ [0., -1., -1., 0., 0., 0., Scaled.zero, Scaled.zero, mirror135Deg] ELSE IF (ABS[m.b] < epsilon -- test for null or mirror ops AND ABS[m.c] < epsilon AND (ABS[ABS[m.a] - 1.0] < epsilon) AND (ABS[ABS[m.d] - 1.0] < epsilon) ) THEN IF m.a > 0 THEN IF m.d > 0 THEN transform^ _ [1., 0., 0., 1., m.e, m.f, m.tx, m.ty, identity] ELSE transform^ _ [1., 0., 0., -1., m.e, m.f, m.tx, m.ty, mirrorY] ELSE IF m.d > 0 THEN transform^ _ [-1., 0., 0., 1., m.e, m.f, m.tx, m.ty, mirrorX] ELSE transform^ _ [-1., 0., 0., -1., m.e, m.f, m.tx, m.ty, rot180] ELSE transform _ m; -- can't make it non-hard RETURN[transform]; }; ValidateCompositeTransform: PUBLIC PROC [context: Context] = TRUSTED { epsilonHardness: REAL _ .0001; -- How far from non-hard you can get and still be easy context.compositeTransform _ MakeNonHard[Concat[Concat[context.clientTransform, context.viewTransform], context.deviceTransform], epsilonHardness]; context.validCompositeTransform _ TRUE; }; Transform: PUBLIC PROC [m: Transformation, p: Vec] RETURNS [Vec] = { SELECT m.type FROM identity => RETURN[p]; rot90 => RETURN[ [ x: -p.y + m.e, y: p.x + m.f] ]; rot180 => RETURN[ [ x: -p.x + m.e, y: -p.y + m.f] ]; rot270 => RETURN[ [ x: p.y + m.e, y: -p.x + m.f] ]; mirrorX => RETURN[ [ x: -p.x + m.e, y: p.y + m.f] ]; mirrorY => RETURN[ [ x: p.x + m.e, y: -p.y + m.f] ]; mirror45Deg => RETURN[ [ x: p.y + m.e, y: p.x + m.f] ]; mirror135Deg => RETURN[ [ x: -p.y + m.e, y: -p.x + m.f] ]; hard => RETURN[ [ x: p.x * m.a + p.y * m.c + m.e, y: p.x * m.b + p.y * m.d + m.f ] ]; ENDCASE => ERROR; }; InverseTransform: PUBLIC PROC [m: Transformation, p: Vec] RETURNS [Vec] = { SELECT m.type FROM identity => RETURN[p]; rot90 => RETURN[ [ x: p.y - m.f, y: -p.x + m.e] ]; rot180 => RETURN[ [ x: -p.x + m.e, y: -p.y + m.f] ]; rot270 => RETURN[ [ x: -p.y + m.f, y: p.x - m.e] ]; mirrorX => RETURN[ [ x: -p.x + m.e, y: p.y - m.f] ]; mirrorY => RETURN[ [ x: p.x - m.e, y: -p.y + m.f] ]; mirror45Deg => RETURN[ [ x: p.y - m.f, y: p.x - m.e] ]; mirror135Deg => RETURN[ [ x: -p.y + m.f, y: -p.x + m.e] ]; hard => RETURN[ Transform[Invert[m],p] ]; ENDCASE => ERROR; }; TransformVec: PUBLIC PROC [m: Transformation, p: Vec] RETURNS [Vec] = { SELECT m.type FROM identity => RETURN[p]; rot90 => RETURN[ [ x: -p.y, y: p.x] ]; rot180 => RETURN[ [ x: -p.x, y: -p.y] ]; rot270 => RETURN[ [ x: p.y, y: -p.x] ]; mirrorX => RETURN[ [ x: -p.x, y: p.y] ]; mirrorY => RETURN[ [ x: p.x, y: -p.y] ]; mirror45Deg => RETURN[ [ x: p.y, y: p.x] ]; mirror135Deg => RETURN[ [ x: -p.y, y: -p.x] ]; hard => RETURN[ [ x: p.x * m.a + p.y * m.c, y: p.x * m.b + p.y * m.d ] ]; ENDCASE => ERROR; }; InverseTransformVec: PUBLIC PROC [m: Transformation, p: Vec] RETURNS [Vec] = { SELECT m.type FROM identity => RETURN[p]; rot90 => RETURN[ [ x: p.y, y: -p.x] ]; rot180 => RETURN[ [ x: -p.x, y: -p.y] ]; rot270 => RETURN[ [ x: -p.y, y: p.x] ]; mirrorX => RETURN[ [ x: -p.x, y: p.y] ]; mirrorY => RETURN[ [ x: p.x, y: -p.y] ]; mirror45Deg => RETURN[ [ x: p.y, y: p.x] ]; mirror135Deg => RETURN[ [ x: -p.y, y: -p.x] ]; hard => RETURN[ TransformVec[Invert[m],p] ]; ENDCASE => ERROR; }; END. †ImagerImpl.mesa Created March 11, 1983 Last Edit By: Plass, March 14, 1983 2:16 pm Last Edited by: Crow, March 17, 1983 5:41 pm ΚΙ˜J™J™™ J™—J™,šΟk ˜ Jšœœœ<˜gJšœœ˜Jšœœ œ˜6—šœ  ˜Jšœ˜Jšœ˜Jšœœœ˜šΟnœ œ œ˜HJšœœ˜ Jšœ˜—šž œœœœ˜9JšœœT˜sJ˜'J˜EJšœ,˜,Jšœ˜—šžœ œœ˜9JšœœT˜sJšœœœΟc˜UJšœœœ˜9šœ ˜JšœR˜RJšœT˜TJšœT˜TJšœ#˜#Jšœ˜!—šœ˜šœA˜AJšœ*˜*Jšœ˜Jšœ4˜4—Jšœ œ˜Jšœ0˜7—Jšœ˜—šžœ œœ˜3JšœœT˜sJ˜Jšœ˜Jšœ,˜,Jšœ˜—šžœ œœ˜9JšœœV˜uJšœŸ˜7šœœ ˜JšœœK˜Pšœœœ ˜JšœœL˜R——Jšœ ˜ šœœ ˜JšœJ˜Pšœœ ˜Jšœœ˜$——šœ˜šœ1˜1Jšœ5˜5—Jšœ œ˜Jšœ0˜7—Jšœ˜—unitšž œ œœ˜;JšœœT˜sJ˜&J˜CJšœ,˜,Jšœ˜—šžœœœR˜nšœ˜JšœP˜PJšœJ˜JJšœP˜PJšœœ˜—Jšœ"œ˜(Jšœ˜—šž œœœQœ˜sJšœ$˜$Jšœ"œ˜(Jšœ˜—šž œ œ3œ˜iJšœœT˜sšœ˜Jšœ/˜/Jšœ+˜+Jšœ/˜/Jšœœ˜—Jšœ ˜Jšœ˜—šžœ œœ˜GJšœœT˜sJšœ˜šœ œ˜Jšœ/œ ˜@Jšœ/œ ˜@Jšœ˜—šœ˜ JšœA˜AJšœA˜AJšœS˜SJšœS˜SJšœ˜J˜—Jšœ ˜Jšœ˜—šžœ œœ˜DJšœœT˜sJšœœ˜ JšœŸ˜1Jšœ3˜3Jšœ3˜3Jšœ-˜-Jšœ-˜-Jšœ,˜,Jšœ,˜,Jšœ˜Jšœ ˜Jšœ˜—Kš ž œœœœœ˜VšœŸY˜]KšœœZ˜yšœœœŸ,˜DJšœœ˜Jšœœœ˜$Jšœœœ˜%—šœœ ˜šœ˜Jšœ œM˜\JšœœH˜P—šœ˜Jšœ œI˜XJšœœU˜]——šœœœŸ˜=Jšœœ˜Jšœœœ˜$Jšœœœ˜%šœœ ˜šœ˜Jšœ œ>˜MJšœœ>˜F—šœ˜Jšœ œ>˜MJšœœC˜K——JšœŸ˜3—Jšœ ˜JšœŸœ˜—šžœ œœ˜FJšœœ Ÿ6˜UJšœO˜OJšœJ˜JJšœ"œ˜'J˜—šž œ œ œ ˜Dšœ˜Jšœœ˜Jšœ œ$˜6Jšœ œ$˜6Jšœ œ$˜6Jšœ œ$˜7Jšœ œ$˜7Jšœœ$˜:Jšœœ$˜;Jšœ œœ˜4Jšœ,˜,Jšœ˜—Jšœ˜—šžœ œ œ ˜Kšœ˜Jšœ œ˜Jšœ œ$˜6Jšœ œ$˜6Jšœ œ$˜6Jšœ œ$˜7Jšœ œ$˜7Jšœœ$˜:Jšœœ$˜;Jšœ œ˜,Jšœ˜—Jšœ˜—šž œ œ œ ˜Gšœ˜Jšœœ˜Jšœ œ˜*Jšœ œ˜*Jšœ œ˜*Jšœ œ˜+Jšœ œ˜+Jšœœ˜.Jšœœ˜/Jšœ œœ˜.Jšœ&˜&Jšœ˜—Jšœ˜—šžœ œ œ ˜Nšœ˜Jšœ œ˜Jšœ œ˜*Jšœ œ˜*Jšœ œ˜*Jšœ œ˜+Jšœ œ˜+Jšœœ˜.Jšœœ˜/Jšœ œ˜/Jšœ˜—Jšœ˜—Jšœ˜——…—%.]