Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
/* Copyright (C) 1989, 2000 Aladdin Enterprises.  All rights reserved.
2
 
3
  This software is provided AS-IS with no warranty, either express or
4
  implied.
5
 
6
  This software is distributed under license and may not be copied,
7
  modified or distributed except as expressly authorized under the terms
8
  of the license contained in the file LICENSE in this distribution.
9
 
10
  For more information about licensing, please refer to
11
  http://www.ghostscript.com/licensing/. For information on
12
  commercial licensing, go to http://www.artifex.com/licensing/ or
13
  contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14
  San Rafael, CA  94903, U.S.A., +1(415)492-9861.
15
*/
16
 
17
/*$Id: gzpath.h,v 1.37 2004/03/13 18:28:52 igor Exp $ */
18
/* Structure and internal procedure definitions for paths */
19
/* Requires gxfixed.h */
20
 
21
#ifndef gzpath_INCLUDED
22
#  define gzpath_INCLUDED
23
 
24
#include "gxpath.h"
25
#include "gsmatrix.h"
26
#include "gsrefct.h"
27
#include "gsstype.h"		/* for extern_st */
28
 
29
/*
30
 * Paths are represented as a linked list of line or curve segments,
31
 * similar to what pathforall reports.
32
 */
33
 
34
/*
35
 * Define path segment types: segment start, line, or Bezier curve.
36
 * We have a special type for the line added by closepath.
37
 */
38
typedef enum {
39
    s_start,
40
    s_line,
41
    s_line_close,
42
    s_curve
43
} segment_type;
44
 
45
/* Define the common structure for all segments. */
46
#define segment_common\
47
	segment *prev;\
48
	segment *next;\
49
	ushort /*segment_type*/ type;\
50
	ushort /*segment_notes*/ notes;\
51
	gs_fixed_point pt;		/* initial point for starts, */\
52
				/* final point for others */
53
 
54
/* Forward declarations for structure types */
55
#ifndef segment_DEFINED
56
#  define segment_DEFINED
57
typedef struct segment_s segment;
58
 
59
#endif
60
typedef struct subpath_s subpath;
61
 
62
/*
63
 * Define a generic segment.  This is never instantiated,
64
 * but we define a descriptor anyway for the benefit of subclasses.
65
 */
66
struct segment_s {
67
    segment_common
68
};
69
 
70
#define private_st_segment()	/* in gxpath.c */\
71
  gs_private_st_ptrs2(st_segment, struct segment_s, "segment",\
72
    segment_enum_ptrs, segment_reloc_ptrs, prev, next)
73
 
74
/* Line segments have no special data. */
75
typedef struct {
76
    segment_common
77
} line_segment;
78
 
79
#define private_st_line()	/* in gxpath.c */\
80
  gs_private_st_suffix_add0(st_line, line_segment, "line",\
81
    line_enum_ptrs, line_reloc_ptrs, st_segment)
82
 
83
/* Line_close segments are for the lines appended by closepath. */
84
/* They point back to the subpath being closed. */
85
typedef struct {
86
    segment_common
87
    subpath * sub;
88
} line_close_segment;
89
 
90
#define private_st_line_close()	/* in gxpath.c */\
91
  gs_private_st_suffix_add1(st_line_close, line_close_segment, "close",\
92
    close_enum_ptrs, close_reloc_ptrs, st_segment, sub)
93
 
94
/*
95
 * We use two different representations for curve segments: one defined by
96
 * two endpoints (p0, p3) and two control points (p1, p2), and one defined
97
 * by two sets of parametric cubic coefficients (ax ... dy).  Here is how
98
 * they are related (v = x or y).  We spell out some multiplies by 3 for
99
 * the benefit of compilers too simple to optimize this.
100
 */
101
#define curve_points_to_coefficients(v0, v1, v2, v3, a, b, c, t01, t12)\
102
  (/*d = (v0),*/\
103
   t01 = (v1) - (v0), c = (t01 << 1) + t01,\
104
   t12 = (v2) - (v1), b = (t12 << 1) + t12 - c,\
105
   a = (v3) - b - c - (v0))
106
/*
107
 * or conversely
108
 */
109
#define curve_coefficients_to_points(a, b, c, d, v1, v2, v3)\
110
  (/*v0 = (d),*/\
111
   v1 = (d) + ((c) / 3),\
112
   v2 = v1 + (((b) + (c)) / 3),\
113
   v3 = (a) + (b) + (c) + (d))
114
 
115
/* Curve segments store the control points. */
116
typedef struct {
117
    segment_common
118
    gs_fixed_point p1, p2;
119
} curve_segment;
120
 
121
#define private_st_curve()	/* in gxpath.c */\
122
  gs_private_st_suffix_add0_local(st_curve, curve_segment, "curve",\
123
    segment_enum_ptrs, segment_reloc_ptrs, st_segment)
124
 
125
/*
126
 * Define a start segment.  This serves as the head of a subpath.
127
 * The closer is only used temporarily when filling,
128
 * to close an open subpath.
129
 */
130
struct subpath_s {
131
    segment_common
132
    segment * last;		/* last segment of subpath, */
133
    /* points back to here if empty */
134
    int curve_count;		/* # of curves */
135
    line_close_segment closer;
136
    char /*bool */ is_closed;	/* true if subpath is closed */
137
};
138
 
139
#define private_st_subpath()	/* in gxpath.c */\
140
  gs_private_st_suffix_add1(st_subpath, subpath, "subpath",\
141
    subpath_enum_ptrs, subpath_reloc_ptrs, st_segment, last)
142
 
143
/* Test whether a subpath is a rectangle; if so, also return */
144
/* the start of the next subpath. */
145
gx_path_rectangular_type
146
gx_subpath_is_rectangular(const subpath * pstart, gs_fixed_rect * pbox,
147
			  const subpath ** ppnext);
148
 
149
#define gx_subpath_is_rectangle(pstart, pbox, ppnext)\
150
  (gx_subpath_is_rectangular(pstart, pbox, ppnext) != prt_none)
151
 
152
/* Curve manipulation */
153
 
154
/* Return the smallest value k such that 2^k segments will approximate */
155
/* the curve to within the desired flatness. */
156
int gx_curve_log2_samples(fixed, fixed, const curve_segment *, fixed);
157
 
158
/*
159
 * If necessary, find the values of t (never more than 2) which split the
160
 * curve into monotonic parts.  Return the number of split points.
161
 */
162
int gx_curve_monotonic_points(fixed, fixed, fixed, fixed, double[2]);
163
 
164
/* Monotonize a curve, by splitting it if necessary. */
165
int gx_curve_monotonize(gx_path * ppath, const curve_segment * pc);
166
 
167
/* Flatten a partial curve by sampling (internal procedure). */
168
int gx_subdivide_curve(gx_path *, int, curve_segment *, segment_notes);
169
/*
170
 * Define the maximum number of points for sampling if we want accurate
171
 * rasterizing.  2^(k_sample_max*3)-1 must fit into a uint with a bit
172
 * to spare; also, we must be able to compute 1/2^(3*k) by table lookup.
173
 */
174
#define k_sample_max min((size_of(int) * 8 - 1) / 3, 10)
175
 
176
 
177
/*
178
 * The path state flags reflect the most recent operation on the path
179
 * as follows:
180
 *      Operation       position_valid  subpath_open    is_drawing
181
 *      newpath         no              no              no
182
 *      moveto          yes             yes             no
183
 *      lineto/curveto  yes             yes             yes
184
 *      closepath       yes             no              no
185
 * If position_valid is true, outside_range reflects whether the most
186
 * recent operation went outside of the representable coordinate range.
187
 * If this is the case, the corresponding member of position (x and/or y)
188
 * is min_fixed or max_fixed, and outside_position is the true position.
189
 */
190
/*
191
 */
192
typedef enum {
193
    /* Individual flags.  These may be or'ed together, per above. */
194
    psf_position_valid = 1,
195
    psf_subpath_open = 2,
196
    psf_is_drawing = 4,
197
    psf_outside_range = 8,
198
    /* Values stored by path building operations. */
199
    psf_last_newpath = 0,
200
    psf_last_moveto = psf_position_valid | psf_subpath_open,
201
    psf_last_draw = psf_position_valid | psf_subpath_open | psf_is_drawing,
202
    psf_last_closepath = psf_position_valid
203
} gx_path_state_flags;
204
 
205
/*
206
 * Individual tests
207
 */
208
#define path_position_valid(ppath)\
209
  (((ppath)->state_flags & psf_position_valid) != 0)
210
#define path_subpath_open(ppath)\
211
  (((ppath)->state_flags & psf_subpath_open) != 0)
212
#define path_is_drawing(ppath)\
213
  (((ppath)->state_flags & psf_is_drawing) != 0)
214
#define path_outside_range(ppath)\
215
  (((ppath)->state_flags & psf_outside_range) != 0)
216
/*
217
 * Composite tests
218
 */
219
#define path_last_is_moveto(ppath)\
220
  (((ppath)->state_flags & ~psf_outside_range) == psf_last_moveto)
221
#define path_position_in_range(ppath)\
222
  (((ppath)->state_flags & (psf_position_valid + psf_outside_range)) ==\
223
   psf_position_valid)
224
#define path_start_outside_range(ppath)\
225
  ((ppath)->state_flags != 0 &&\
226
   ((ppath)->start_flags & psf_outside_range) != 0)
227
/*
228
 * Updating operations
229
 */
230
#define path_update_newpath(ppath)\
231
  ((ppath)->state_flags = psf_last_newpath)
232
#define path_update_moveto(ppath)\
233
  ((ppath)->state_flags = (ppath)->start_flags = psf_last_moveto)
234
#define path_update_draw(ppath)\
235
  ((ppath)->state_flags = psf_last_draw)
236
#define path_update_closepath(ppath)\
237
  ((ppath)->state_flags = psf_last_closepath)
238
 
239
/*
240
 * In order to be able to reclaim path segments at the right time, we need
241
 * to reference-count them.  To minimize disruption, we would like to do
242
 * this by creating a structure (gx_path_segments) consisting of only a
243
 * reference count that counts the number of paths that share the same
244
 * segments.  (Logically, we should put the segments themselves --
245
 * first/last_subpath, subpath/curve_count -- in this object, but that would
246
 * cause too much disruption to existing code.)  However, we need to put at
247
 * least first_subpath and current_subpath in this structure so that we can
248
 * free the segments when the reference count becomes zero.
249
 */
250
typedef struct gx_path_segments_s {
251
    rc_header rc;
252
    struct psc_ {
253
	subpath *subpath_first;
254
	subpath *subpath_current;
255
    } contents;
256
} gx_path_segments;
257
 
258
#define private_st_path_segments()	/* in gxpath.c */\
259
  gs_private_st_ptrs2(st_path_segments, gx_path_segments, "path segments",\
260
    path_segments_enum_ptrs, path_segments_reloc_ptrs,\
261
    contents.subpath_first, contents.subpath_current)
262
 
263
/* Record how a path was allocated, so freeing will do the right thing. */
264
typedef enum {
265
    path_allocated_on_stack,	/* on stack */
266
    path_allocated_contained,	/* inside another object */
267
    path_allocated_on_heap	/* on the heap */
268
} gx_path_allocation_t;
269
 
270
/*
271
 * Define virtual path interface functions.
272
 * This is a minimal set of functions required by
273
 * Type 1,2, TrueType interpreters.
274
 */
275
typedef struct gx_path_procs_s {
276
    int (*add_point)(gx_path *, fixed, fixed);
277
    int (*add_line)(gx_path *, fixed, fixed, segment_notes);
278
    int (*add_curve)(gx_path *, fixed, fixed, fixed, fixed, fixed, fixed, segment_notes);
279
    int (*close_subpath)(gx_path *, segment_notes);
280
    byte (*state_flags)(gx_path *, byte);
281
} gx_path_procs;
282
 
283
/* Here is the actual structure of a path. */
284
struct gx_path_s {
285
    /*
286
     * In order to be able to have temporary paths allocated entirely
287
     * on the stack, we include a segments structure within the path,
288
     * used only for this purpose.  In order to avoid having the
289
     * path's segments pointer point into the middle of an object,
290
     * the segments structure must come first.
291
     *
292
     * Note that since local_segments is used only for temporary paths
293
     * on the stack, and not for path structures in allocated memory,
294
     * we don't declare any pointers in it for the GC.  (As it happens,
295
     * there aren't any such pointers at the moment, but this could
296
     * change.)
297
     */
298
    gx_path_segments local_segments;
299
    gs_memory_t *memory;
300
    gx_path_allocation_t allocation;	/* how this path was allocated */
301
    gx_path_segments *segments;
302
    gs_fixed_rect bbox;		/* bounding box (in device space) */
303
    segment *box_last;		/* bbox incorporates segments */
304
				/* up to & including this one */
305
#define first_subpath segments->contents.subpath_first	/* (hack) */
306
#define current_subpath segments->contents.subpath_current	/* (ditto) */
307
    /*
308
     * Note: because of bugs in the AIX 4.3.1 xlc compiler, the byte-valued
309
     * members must not be the last ones in the structure.
310
     */
311
    byte /*gx_path_state_flags*/ start_flags;		/* flags of moveto */
312
    byte /*gx_path_state_flags*/ state_flags;		/* (see above) */
313
    byte /*bool*/ bbox_set;	/* true if setbbox is in effect */
314
    byte /*bool*/ bbox_accurate;/* true if bbox is accurate */
315
    byte _pad;			/* just in case the compiler doesn't do it */
316
    int subpath_count;
317
    int curve_count;
318
    gs_fixed_point position;	/* current position */
319
    gx_path_procs *procs;
320
};
321
 
322
/* st_path should be private, but it's needed for the clip_path subclass. */
323
extern_st(st_path);
324
#define public_st_path()	/* in gxpath.c */\
325
  gs_public_st_ptrs2(st_path, gx_path, "path",\
326
    path_enum_ptrs, path_reloc_ptrs, segments, box_last)
327
#define st_path_max_ptrs 2
328
 
329
/* Path enumeration structure */
330
struct gs_path_enum_s {
331
    gs_memory_t *memory;
332
    gs_matrix mat;		/* CTM for inverse-transforming points */
333
    const segment *pseg;
334
    const gx_path *path;	/* path being enumerated */
335
    gx_path *copied_path;	/* if the path was copied, this is the */
336
    /* the same as path, to be released */
337
    /* when done enumerating */
338
    bool moveto_done;		/* have we reported a final moveto yet? */
339
    segment_notes notes;	/* notes from most recent segment */
340
};
341
 
342
/* We export st_path_enum only so that st_cpath_enum can subclass it. */
343
extern_st(st_path_enum);
344
#define public_st_path_enum()	/* in gxpath2.c */\
345
  gs_public_st_ptrs3(st_path_enum, gs_path_enum, "gs_path_enum",\
346
    path_enum_enum_ptrs, path_enum_reloc_ptrs, pseg, path, copied_path)
347
 
348
/* Inline path accessors. */
349
#define gx_path_has_curves_inline(ppath)\
350
  ((ppath)->curve_count != 0)
351
#define gx_path_has_curves(ppath)\
352
  gx_path_has_curves_inline(ppath)
353
#define gx_path_is_void_inline(ppath)\
354
  ((ppath)->segments != 0 && (ppath)->first_subpath == 0)
355
#define gx_path_is_void(ppath)\
356
  gx_path_is_void_inline(ppath)
357
#define gx_path_subpath_count(ppath)\
358
  ((ppath)->subpath_count)
359
#define gx_path_is_shared(ppath)\
360
  ((ppath)->segments != 0 && (ppath)->segments->rc.ref_count > 1)
361
 
362
/* Macros equivalent to a few heavily used procedures. */
363
/* Be aware that these macros may evaluate arguments more than once. */
364
#define gx_path_current_point_inline(ppath,ppt)\
365
 ( !path_position_valid(ppath) ? gs_note_error(gs_error_nocurrentpoint) :\
366
   ((ppt)->x = ppath->position.x, (ppt)->y = ppath->position.y, 0) )
367
 
368
/* An iterator of flattened segments for a minotonic curve. */
369
typedef struct gx_flattened_iterator_s gx_flattened_iterator;
370
struct gx_flattened_iterator_s {
371
    /* private : */
372
    fixed x0, y0, x3, y3;
373
    fixed cx, bx, ax, cy, by, ay;
374
    fixed x, y;
375
    uint i, k;
376
    uint rmask;			/* M-1 */
377
    fixed idx, idy, id2x, id2y, id3x, id3y;	/* I */
378
    uint rx, ry, rdx, rdy, rd2x, rd2y, rd3x, rd3y;	/* R */
379
    /* public : */
380
    bool curve;
381
    fixed lx0, ly0, lx1, ly1;
382
};
383
 
384
bool gx_flattened_iterator__init(gx_flattened_iterator *this, 
385
	    fixed x0, fixed y0, const curve_segment *pc, int k);
386
bool gx_flattened_iterator__init_line(gx_flattened_iterator *this, 
387
	    fixed x0, fixed y0, fixed x1, fixed y1);
388
void gx_flattened_iterator__switch_to_backscan(gx_flattened_iterator *this, bool not_first);
389
bool gx_flattened_iterator__next(gx_flattened_iterator *this);
390
bool gx_flattened_iterator__prev(gx_flattened_iterator *this);
391
 
392
bool curve_coeffs_ranged(fixed x0, fixed x1, fixed x2, fixed x3, 
393
		    fixed y0, fixed y1, fixed y2, fixed y3, 
394
		    fixed *ax, fixed *bx, fixed *cx, 
395
		    fixed *ay, fixed *by, fixed *cy, 
396
		    int k);
397
 
398
#endif /* gzpath_INCLUDED */