1(* Ulm's Oberon Library
2   Copyright (C) 1989-2004 by University of Ulm, SAI, D-89069 Ulm, Germany
3   ----------------------------------------------------------------------------
4   Ulm's Oberon Library is free software; you can redistribute it
5   and/or modify it under the terms of the GNU Library General Public
6   License as published by the Free Software Foundation; either version
7   2 of the License, or (at your option) any later version.
8
9   Ulm's Oberon Library is distributed in the hope that it will be
10   useful, but WITHOUT ANY WARRANTY; without even the implied warranty
11   of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12   Library General Public License for more details.
13
14   You should have received a copy of the GNU Library General Public
15   License along with this library; if not, write to the Free Software
16   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17   ----------------------------------------------------------------------------
18   E-mail contact: oberon@mathematik.uni-ulm.de
19   ----------------------------------------------------------------------------
20   $Id: Plotters.om,v 1.1 2004/04/08 12:30:29 borchert Exp borchert $
21   ----------------------------------------------------------------------------
22   $Log: Plotters.om,v $
23   Revision 1.1  2004/04/08 12:30:29  borchert
24   Initial revision
25
26   ----------------------------------------------------------------------------
27*)
28
29MODULE ulmPlotters;
30
31   IMPORT Events := ulmEvents, Objects := ulmObjects, Resources := ulmResources, Services := ulmServices, SYS := ulmSYSTEM, Types := ulmTypes;
32
33   TYPE
34      Plotter* = POINTER TO PlotterRec;
35
36   CONST
37      solid* = 0;
38      dotted* = 1;
39      dotdashed* = 2;
40      shortdashed* = 3;
41      longdashed* = 4;
42      lineModes* = 5;
43   TYPE
44      LineMode* = Types.Int8; (* solid ... *)
45
46   CONST
47      setspace* = 0;
48      erase* = 1;
49      string* = 2;
50      linemodes* = 3;
51      linewidth* = 4;
52   TYPE
53      CapabilitySet* = Types.Set; (* OF setspace, erase ... *)
54
55   TYPE
56      Description* = POINTER TO DescriptionRec;
57      DescriptionRec* =
58	 RECORD
59	    (Objects.ObjectRec)
60	    xmin*, ymin, xmax, ymax: Types.Int32; (* maximal supported range *)
61	 END;
62
63   TYPE
64      GetSpaceProc* = PROCEDURE (
65	 plotter: Plotter;
66	 VAR xmin, ymin, xmax, ymax: Types.Int32);
67      SetSpaceProc* = PROCEDURE (
68	 plotter: Plotter;
69	 xmin, ymin, xmax, ymax: Types.Int32);
70      EraseProc* = PROCEDURE (plotter: Plotter);
71      MoveProc* = PROCEDURE (plotter: Plotter; xto, yto: Types.Int32);
72      LineProc* = PROCEDURE (plotter: Plotter; xfrom, yfrom, xto, yto: Types.Int32);
73      ArcProc* = PROCEDURE (
74	 plotter: Plotter;
75	 xcenter, ycenter, xstart, ystart, xend, yend: Types.Int32);
76      CircleProc* = PROCEDURE (
77         plotter: Plotter; xcenter, ycenter, radius: Types.Int32);
78      StringProc* = PROCEDURE (plotter: Plotter; str: ARRAY OF CHAR);
79      SetLineModeProc* = PROCEDURE (plotter: Plotter; mode: LineMode);
80      SetLineWidthProc* = PROCEDURE (plotter: Plotter; width: Types.Int32);
81      CloseProc* = PROCEDURE (plotter: Plotter);
82   TYPE
83      Interface* = POINTER TO InterfaceRec;
84      InterfaceRec* =
85	 RECORD
86	    (Objects.ObjectRec)
87	    setSpace*: SetSpaceProc;
88	    erase*: EraseProc;
89	    move*: MoveProc;
90	    cont*: MoveProc;
91	    point*: MoveProc;
92	    line*: LineProc;
93	    arc*: ArcProc;
94	    circle*: CircleProc;
95	    string*: StringProc;
96	    setLineMode*: SetLineModeProc;
97	    setLineWidth*: SetLineWidthProc;
98	    close*: CloseProc;
99	 END;
100
101   TYPE
102      PlotterRec* =
103	 RECORD
104	    (Services.ObjectRec)
105	    if: Interface;
106	    caps: CapabilitySet;
107	    desc: Description;
108	    xmin, ymin, xmax, ymax: Types.Int32; (* current range *)
109	    terminated: BOOLEAN;
110	 END;
111   VAR
112      plotterType: Services.Type;
113
114   PROCEDURE InitModule;
115   BEGIN
116      Services.CreateType(plotterType, "Plotters.Plotter", "");
117   END InitModule;
118
119   PROCEDURE ^ Close*(plotter: Plotter);
120
121   PROCEDURE TerminationHandler(event: Events.Event);
122      VAR
123	 plotter: Plotter;
124   BEGIN
125      WITH event: Resources.Event DO
126	 IF event.change IN {Resources.terminated, Resources.unreferenced} THEN
127	    Close(event.resource(Plotter));
128	 END;
129      END;
130   END TerminationHandler;
131
132   PROCEDURE Init*(plotter: Plotter; if: Interface;
133		  caps: CapabilitySet; desc: Description);
134      VAR
135	 eventType: Events.EventType;
136   BEGIN
137      ASSERT((if # NIL) & (if.move # NIL) & (if.cont # NIL) &
138	 (if.point # NIL) & (if.line # NIL) & (if.arc # NIL) &
139	 (if.circle # NIL));
140      ASSERT(~(setspace IN caps) OR (if.setSpace # NIL));
141      ASSERT(~(erase IN caps) OR (if.erase # NIL));
142      ASSERT(~(string IN caps) OR (if.string # NIL));
143      ASSERT(~(linemodes IN caps) OR (if.setLineMode # NIL));
144      ASSERT(~(linewidth IN caps) OR (if.setLineWidth # NIL));
145      ASSERT((desc.xmin < desc.xmax) & (desc.ymin < desc.ymax));
146      plotter.if := if;
147      plotter.caps := caps;
148      plotter.desc := desc;
149      plotter.xmin := desc.xmin;
150      plotter.xmax := desc.xmax;
151      plotter.ymin := desc.ymin;
152      plotter.ymax := desc.ymax;
153      plotter.terminated := FALSE;
154      Resources.TakeInterest(plotter, eventType);
155      Events.Handler(eventType, TerminationHandler);
156   END Init;
157
158   PROCEDURE GetCapabilities*(plotter: Plotter) : CapabilitySet;
159   BEGIN
160      RETURN plotter.caps
161   END GetCapabilities;
162
163   PROCEDURE GetSpace*(plotter: Plotter;
164                      VAR xmin, ymin,
165		      xmax, ymax: Types.Int32);
166   BEGIN
167      xmin := plotter.xmin;
168      xmax := plotter.xmax;
169      ymin := plotter.ymin;
170      ymax := plotter.ymax;
171   END GetSpace;
172
173   PROCEDURE GetMaxSpace*(plotter: Plotter;
174                         VAR xmin, ymin,
175		         xmax, ymax: Types.Int32);
176   BEGIN
177      xmin := plotter.desc.xmin;
178      xmax := plotter.desc.xmax;
179      ymin := plotter.desc.ymin;
180      ymax := plotter.desc.ymax;
181   END GetMaxSpace;
182
183   PROCEDURE SetSpace*(plotter: Plotter;
184                      xmin, ymin,
185		      xmax, ymax: Types.Int32);
186   BEGIN
187      ASSERT((xmin < xmax) & (ymin < ymax));
188      ASSERT((xmin >= plotter.desc.xmin) &
189             (xmax <= plotter.desc.xmax) &
190	     (ymin >= plotter.desc.ymin) &
191	     (ymax <= plotter.desc.ymax));
192      ASSERT(setspace IN plotter.caps);
193      plotter.if.setSpace(plotter, xmin, ymin, xmax, ymax);
194      plotter.xmin := xmin;
195      plotter.ymin := ymin;
196      plotter.xmax := xmax;
197      plotter.ymax := ymax;
198   END SetSpace;
199
200   PROCEDURE Erase*(plotter: Plotter);
201   BEGIN
202      ASSERT(erase IN plotter.caps);
203      plotter.if.erase(plotter);
204   END Erase;
205
206   PROCEDURE Move*(plotter: Plotter; xto, yto: Types.Int32);
207   BEGIN
208      plotter.if.move(plotter, xto, yto);
209   END Move;
210
211   PROCEDURE Cont*(plotter: Plotter; xto, yto: Types.Int32);
212   BEGIN
213      plotter.if.cont(plotter, xto, yto);
214   END Cont;
215
216   PROCEDURE Point*(plotter: Plotter; xpoint, ypoint: Types.Int32);
217   BEGIN
218      plotter.if.point(plotter, xpoint, ypoint);
219   END Point;
220
221   PROCEDURE Line*(plotter: Plotter; xfrom, yfrom, xto, yto: Types.Int32);
222   BEGIN
223      plotter.if.line(plotter, xfrom, yfrom, xto, yto);
224   END Line;
225
226   PROCEDURE Arc*(plotter: Plotter;
227                 xcenter, ycenter, xstart, ystart, xend, yend: Types.Int32);
228   BEGIN
229      plotter.if.arc(plotter, xcenter, ycenter, xstart, ystart, xend, yend);
230   END Arc;
231
232   PROCEDURE Circle*(plotter: Plotter; xcenter, ycenter, radius: Types.Int32);
233   BEGIN
234      plotter.if.circle(plotter, xcenter, ycenter, radius);
235   END Circle;
236
237   PROCEDURE String*(plotter: Plotter; str: ARRAY OF CHAR);
238   BEGIN
239      ASSERT(string IN plotter.caps);
240      plotter.if.string(plotter, str);
241   END String;
242
243   PROCEDURE SetLineMode*(plotter: Plotter; mode: LineMode);
244   BEGIN
245      ASSERT((linemodes IN plotter.caps) & (mode >= 0) & (mode < lineModes));
246      plotter.if.setLineMode(plotter, mode);
247   END SetLineMode;
248
249   PROCEDURE SetLineWidth*(plotter: Plotter; width: Types.Int32);
250   BEGIN
251      ASSERT((linewidth IN plotter.caps) & (width > 0));
252      plotter.if.setLineWidth(plotter, width);
253   END SetLineWidth;
254
255   PROCEDURE Close*(plotter: Plotter);
256   BEGIN
257      IF ~SYS.TAS(plotter.terminated) THEN
258	 IF plotter.if.close # NIL THEN
259	    plotter.if.close(plotter);
260	 END;
261	 Resources.Notify(plotter, Resources.terminated);
262	 plotter.if := NIL; plotter.desc := NIL;
263      END;
264   END Close;
265
266BEGIN
267   InitModule;
268END ulmPlotters.
269