object Shape is p0:Point and InterpolationStyle; description: (*The point, a set of X and Y coordinate components, is the position of the shape on the canvas, the upper left corner of its smallest enclosing rectangle. Specialized shapes define additional coordinates as appropriate. The interpolation style determines how multiple points are joined. *); end Shape; object Point is x:XCoord and y:YCoord; object XCoord is integer; object YCoord is integer; object InterpolationStyle is components: Bezier or Smoothing or Linear; description: (*The interpolation style determines how the points of shapes with multiple defining points are joined. *); end InterpolationStyle; object Layer is Shape* and Properties and s:Slide; description: (*A layer may contain zero or more shapes. The properties of a layer refer to layer opacity and layer size. Each layer is associated with a slide, which defines its bounds. *); end Layer; object Properties is Opacity and Color and Public and LayerIndex; object Opacity; object Color; object Public is boolean; object LayerIndex is int; operation MoveLayer is inputs: l: Layer, p: Properties, li: LayerIndex; outputs: l'Layer; pre: (*the layer exists *); (l != nil) and p.LayerIndex <= li; post: (*the layer with a new index *); p'.LayerIndex != p.LayerIndex; description: (*Moves the layer position *); end MoveLayer; operation SetOpacity is inputs: op: Opacity; outputs: op': Opacity; pre: (* *); post: (*output of the new opacity *); (*The output is not the same as previous*) op' != op; description: (*Changes the opacity of a given layer. *); end SetOpacity; operation SetColor is inputs: co:Color, l:Layer; outputs: l':Layer pre: (*the layer exists and the user has specified a change in the properties, specifically color, of the layer *); (co != nil); post: (*the layer's properties, specifically color, is set to the user-specified value *); co' = co; description: (*Changes the color of a given layer. *); end SetColor; operation SetPublic is inputs: pb:Public, l:Layer; outputs: l':Layer pre: (*the layer exists and the user has specified a change in the properties, specifically visibility, of the layer *); post: (*the layer's properties, specifically visibility, is set to the user-specified value *); description: (*Changes the visibility of a given layer. *); end SetPublic; object Line inherits from Shape is pL:Point; description: (*A line is defined by two points with a linear interpolation style. *); end Line; object Curve inherits from Shape is pZ:Point*; description: (*A curve is defined by multiple points with a Bezier interpolation style. *); end Curve; object Oval inherits from Shape is pC:Point and r1:Radius; description: (*An oval is defined by two points and a radius with a smoothing interpolation style. *); end Oval; object Rectangle inherits from Shape is p1:Point and p2:Point and p3:Point; description: (*A rectangle is defined by four points for the corners with a linear interpolation style. *); end Line; object Triangle inherits from Shape is pT:Point and pS:Point; description: (*A triangle is defined by three points with a linear interpolation style. *); end Line; object FreeForm inherits from Shape is pF:Point*; description: (*A free-form, or user-defined, object is defined by multiple points with a Bezier interpolation style. *); end Line; object Note is Anchor and Rectangle and Text; object Anchor is Point; object Text is string; operation DrawLine is inputs: ln:Line, l:Layer; outputs: l':Layer; pre: (*points of ln are within, or equal to, the bounds of l*) InBounds(ln.p0, l) and InBounds(ln.pL, 1); post: (*ln is in l'*) forall (ln':Line) (ln' in l') iff ((ln' = ln) or (ln' in l)); description: (*Draws a line on the active layer. *); end DrawLine; operation DrawCurve is inputs: c:Curve, l:Layer; outputs: l':Layer; pre: (*points of c are within, or equal to, the bounds of l*) InBounds(c.p0, l) and InBounds(c.pZ, l); post: (*c is in l'*) forall (c':Curve) (c' in l') iff ((c' = c) or (c' in l)); description: (*Draws a curve on the active layer. *); end DrawCurve; operation DrawOval is inputs: o:Oval, l:Layer; outputs: l':Layer; pre: (*points of o are within, or equal to, the bounds of l*) InBounds(o.p0, l) and InBounds(o.pC, l) and InBounds(o.r1, l); post: (*o is in l'*) forall (o':Oval) (o' in l') iff ((o' = o) or (o' in l)); description: (*Draws an oval on the active layer. *); end DrawOval; operation DrawRect is inputs: r:Rectangle, l:Layer; outputs: l':Layer; pre: (*points of r are within, or equal to, the bounds of l*) InBounds(r.p0, l) and InBounds(r.p1, l) and InBounds(r.p2, l) and InBounds(r.p3, l); post: (*r is in l'*) forall (r':Rectangle) (r' in l') iff ((r' = r) or (r' in l)); description: (*Draws a rectangle on the active layer. *); end DrawRect; operation DrawTri is inputs: t:Triangle, l:Layer; outputs: l':Layer; pre: (*points of t are within, or equal to, the bounds of l*) InBounds(t.p0, l) and InBounds(t.pT, l) and InBounds(t.pS, l); post: (*t is in l'*) forall (t':Triangle) (t' in l') iff ((t' = t) or (t' in l)); description: (*Draws a triangle on the active layer. *); end DrawOval; operation FreeDraw is inputs: fr:FreeForm, l:Layer; outputs: l':Layer; pre: (*points of fr are within, or equal to, the bounds of l*) InBounds(fr.p0, l) and InBounds(fr.pF, l); post: (*fr is in l'*) forall (fr':FreeForm) (fr' in l') iff ((fr' = fr) or (fr' in l)); description: (*Draws a user-defined object on the active layer. *); end FreeDraw; operation MakeNote is inputs: n:Note, l:Layer; outputs: l':Layer; pre: (*coordinates of n are within, or equal to, the bounds of l *); post: (*n is in l' *); description: (*Creates a note on the active layer. *); end MakeNote; function InBounds(p:Point, l:Layer) = p.x >= 0 and p.x <= l.s.lower_right.x and p.y >= 0 and p.y <= l.s.lower_right.y;