1 /* pamdraw.h - header file for simple drawing routines in libnetpbm.
2 **
3 ** Simple, yes, and also fairly slow if the truth be told; but also very
4 ** flexible and powerful.
5 **
6 ** The two basic concepts are the drawproc and clientdata.  All the drawing
7 ** routines take a drawproc that does the actual drawing.  A drawproc draws
8 ** a single point, and it looks like this:
9 */
10 
11 #include <netpbm/pm_config.h>
12 
13 #ifdef __cplusplus
14 extern "C" {
15 #endif
16 #if 0
17 } /* to fake out automatic code indenters */
18 #endif
19 
20 
21 typedef struct {
22     int x;
23     int y;
24 } pamd_point;
25 
26 static __inline__ pamd_point
pamd_makePoint(int const x,int const y)27 pamd_makePoint(int const x,
28                int const y) {
29 
30     pamd_point p;
31 
32     p.x = x;
33     p.y = y;
34 
35     return p;
36 }
37 
38 void
39 pamd_validateCoord(int const c);
40 
41 void
42 pamd_validatePoint(pamd_point const p);
43 
44 typedef enum {
45     PAMD_PATHLEG_LINE
46 } pamd_pathlegtype;
47 
48 struct pamd_linelegparms {
49     pamd_point end;
50 };
51 
52 typedef struct {
53 /*----------------------------------------------------------------------------
54    A leg of a pamd_path.
55 -----------------------------------------------------------------------------*/
56     pamd_pathlegtype type;
57     union {
58         struct pamd_linelegparms linelegparms;
59     } u;
60 } pamd_pathleg;
61 
62 typedef struct {
63 /*----------------------------------------------------------------------------
64    A closed path
65 -----------------------------------------------------------------------------*/
66     unsigned int version;
67         /* Must be zero.  For future expansion. */
68     pamd_point   begPoint;
69     unsigned int legCount;
70         /* Number of legs in the path; i.e. size of 'legs' array */
71     size_t       legSize;
72         /* Size of storage occupied by one pamd_pathleg.  I.e.
73            sizeof(pamd_pathleg).  Used for
74            binary backward compatibility between callers and libpamd
75            as the definition of pamd_pathleg changes.
76         */
77     pamd_pathleg * legs;
78 } pamd_path;
79 
80 
81 
82 typedef void pamd_drawproc(tuple **, unsigned int, unsigned int, unsigned int,
83                            sample, pamd_point, const void *);
84 
85 pamd_drawproc pamd_point_drawproc;
86 
87 /*
88 ** So, you call a drawing routine, e.g. pamd_line(), and pass it a drawproc;
89 ** it calls the drawproc for each point it wants to draw.  Why so complicated?
90 ** Because you can define your own drawprocs to do more interesting things than
91 ** simply draw the point.  For example, you could make one that calls back into
92 ** another drawing routine, say pamd_circle() to draw a circle at each point
93 ** of a line.
94 **
95 ** Slow?  Well sure, we're talking results here, not realtime.  You can do
96 ** tricks with this arrangement that you couldn't even think of before.
97 ** Still, to speed things up for the 90% case you can use this:
98 */
99 #define PAMD_NULLDRAWPROC NULL
100 /*
101 ** Just like pamd_point_drawproc() it simply draws the point, but it's done
102 ** inline, and clipping is assumed to be handled at a higher level.
103 **
104 ** Now, what about clientdata.  Well, it's an arbitrary pointer, and can
105 ** mean something different to each different drawproc.  For the above two
106 ** drawprocs, clientdata should be a pointer to a tuple holding the color
107 ** to be drawn.  Other drawprocs can use it to point to something else,
108 ** e.g. some structure to be modified, or they can ignore it.
109 */
110 
111 
112 /* Outline drawing routines.  Lines, splines, circles, etc. */
113 
114 int
115 pamd_setlinetype(int const type);
116 
117 #define PAMD_LINETYPE_NORMAL 0
118 #define PAMD_LINETYPE_NODIAGS 1
119 /* If you set NODIAGS, all tuples drawn by pamd_line() will be 4-connected
120 ** instead of 8-connected; in other words, no diagonals.  This is useful
121 ** for some applications, for example when you draw many parallel lines
122 ** and you want them to fit together without gaps.
123 */
124 
125 int
126 pamd_setlineclip(int const clip);
127 
128 #define pamd_setlineclipping(x)     pamd_setlineclip(x)
129 /* Normally, pamd_line() clips to the edges of the pixmap.  You can use this
130 ** routine to disable the clipping, for example if you are using a drawproc
131 ** that wants to do its own clipping.
132 */
133 
134 void
135 pamd_line(tuple **      const tuples,
136           int           const cols,
137           int           const rows,
138           int           const depth,
139           sample        const maxval,
140           pamd_point    const p0,
141           pamd_point    const p1,
142           pamd_drawproc       drawProc,
143           const void *  const clientdata);
144 
145     /* Draws a line from p0 to p1.  */
146 
147 void
148 pamd_spline3(tuple **      const tuples,
149              int           const cols,
150              int           const rows,
151              int           const depth,
152              sample        const maxval,
153              pamd_point    const p0,
154              pamd_point    const p1,
155              pamd_point    const p2,
156              pamd_drawproc       drawProc,
157              const void *  const clientdata);
158 
159     /* Draws a three-point spline from p0 to p2, with p1
160        as the control point.  All drawing is done via pamd_line(),
161        so the routines that control it control pamd_spline3p() as well.
162     */
163 
164 void
165 pamd_polyspline(tuple **      const tuples,
166                 unsigned int  const cols,
167                 unsigned int  const rows,
168                 unsigned int  const depth,
169                 sample        const maxval,
170                 pamd_point    const p0,
171                 unsigned int  const nc,
172                 pamd_point *  const c,
173                 pamd_point    const p1,
174                 pamd_drawproc       drawProc,
175                 const void *  const clientdata);
176 
177     /* Draws a bunch of splines end to end.  p0 and p1 are the initial and
178        final points, and the c[] are the intermediate control points.  nc is
179        the number of these control points.
180     */
181 
182 void
183 pamd_spline4(tuple **      const tuples,
184              unsigned int  const cols,
185              unsigned int  const rows,
186              unsigned int  const depth,
187              sample        const maxval,
188              pamd_point    const endPt0,
189              pamd_point    const endPt1,
190              pamd_point    const ctlPt0,
191              pamd_point    const ctlPt1,
192              pamd_drawproc       drawProc,
193              const void *  const clientdata);
194 
195 void
196 pamd_circle(tuple **      const tuples,
197             unsigned int  const cols,
198             unsigned int  const rows,
199             unsigned int  const depth,
200             sample        const maxval,
201             pamd_point    const center,
202             unsigned int  const radius,
203             pamd_drawproc       drawProc,
204             const void *  const clientData);
205     /* Draws a circle centered at 'center' with radius 'radius' */
206 
207 /* Simple filling routines.  */
208 
209 void
210 pamd_filledrectangle(tuple **      const tuples,
211                      int           const cols,
212                      int           const rows,
213                      int           const depth,
214                      sample        const maxval,
215                      int           const left,
216                      int           const top,
217                      int           const width,
218                      int           const height,
219                      pamd_drawproc       drawProc,
220                      const void *  const clientdata);
221     /* Fills in the rectangle [left, top, width, height]. */
222 
223 
224 void
225 pamd_fill_path(tuple **      const tuples,
226                int           const cols,
227                int           const rows,
228                int           const depth,
229                sample        const maxval,
230                pamd_path *   const pathP,
231                tuple         const color);
232     /* Fills in a closed path.  Not much different from pamd_fill(),
233        but with a different interface.
234     */
235 
236 
237 /* Arbitrary filling routines.  With these you can fill any outline that
238 ** you can draw with the outline routines.
239 */
240 
241 struct fillobj;
242 
243 struct fillobj *
244 pamd_fill_create(void);
245     /* Returns a blank fillhandle. */
246 
247 void
248 pamd_fill_destroy(struct fillobj * fillObjP);
249 
250 void
251 pamd_fill_drawproc(tuple **     const tuples,
252                    unsigned int const cols,
253                    unsigned int const rows,
254                    unsigned int const depth,
255                    sample       const maxval,
256                    pamd_point   const p,
257                    const void * const clientdata);
258     /* Use this drawproc to trace the outline you want filled.  Use
259        the fillhandle as the clientdata.
260     */
261 
262 void
263 pamd_fill(tuple **         const tuples,
264           int              const cols,
265           int              const rows,
266           int              const depth,
267           sample           const maxval,
268           struct fillobj * const fillObjP,
269           pamd_drawproc          drawProc,
270           const void *     const clientdata);
271 
272     /* Once you've traced the outline, give the fillhandle to this routine to
273        do the actual drawing.  As usual, it takes a drawproc and clientdata;
274        you could define drawprocs to do stipple fills and such.
275     */
276 
277 /* Text drawing routines. */
278 
279 void
280 pamd_text(tuple**       const tuples,
281           int           const cols,
282           int           const rows,
283           int           const depth,
284           sample        const maxval,
285           pamd_point    const pos,
286           int           const height,
287           int           const angle,
288           const char *  const sArg,
289           pamd_drawproc       drawProc,
290           const void *  const clientdata);
291 
292     /* Draws the null-terminated string 's' left justified at the point ('x',
293        'y').  The text will be 'height' tuples high and will be aligned on a
294        baseline inclined 'angle' degrees with the X axis.  The supplied
295        drawproc and clientdata are passed to pamd_line() which performs the
296        actual drawing.
297     */
298 
299 void
300 pamd_text_box(int          const height,
301               int          const angle,
302               const char * const s,
303               int *        const leftP,
304               int *        const topP,
305               int *        const rightP,
306               int *        const bottomP);
307     /* Calculates the extents box for text drawn by pamd_text with the given
308        string, size, and orientation.  Most extent box calculations should use
309        an angle specification of zero to calculate the unrotated box enclosing
310        the text.  If you need the extents of rotated text, however, you can
311        call pamd_text_box with a nonzero angle.
312     */
313 
314 #ifdef __cplusplus
315 }
316 #endif
317 
318