Subversion Repositories planix.SVN

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
/* Copyright (C) 1989, 1995, 1996, 1997, 1999 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: gsline.c,v 1.4 2002/02/21 22:24:52 giles Exp $ */
18
/* Line parameter operators for Ghostscript library */
19
#include "math_.h"
20
#include "memory_.h"
21
#include "gx.h"
22
#include "gserrors.h"
23
#include "gxfixed.h"		/* ditto */
24
#include "gxmatrix.h"		/* for gzstate */
25
#include "gzstate.h"
26
#include "gscoord.h"		/* for currentmatrix, setmatrix */
27
#include "gsline.h"		/* for prototypes */
28
#include "gzline.h"
29
 
30
/* ------ Device-independent parameters ------ */
31
 
32
#define pgs_lp gs_currentlineparams_inline(pgs)
33
 
34
/* setlinewidth */
35
int
36
gs_setlinewidth(gs_state * pgs, floatp width)
37
{
38
    gx_set_line_width(pgs_lp, width);
39
    return 0;
40
}
41
 
42
/* currentlinewidth */
43
float
44
gs_currentlinewidth(const gs_state * pgs)
45
{
46
    return gx_current_line_width(pgs_lp);
47
}
48
 
49
/* setlinecap */
50
int
51
gs_setlinecap(gs_state * pgs, gs_line_cap cap)
52
{
53
    if ((uint) cap > gs_line_cap_max)
54
	return_error(gs_error_rangecheck);
55
    pgs_lp->cap = cap;
56
    return 0;
57
}
58
 
59
/* currentlinecap */
60
gs_line_cap
61
gs_currentlinecap(const gs_state * pgs)
62
{
63
    return pgs_lp->cap;
64
}
65
 
66
/* setlinejoin */
67
int
68
gs_setlinejoin(gs_state * pgs, gs_line_join join)
69
{
70
    if ((uint) join > gs_line_join_max)
71
	return_error(gs_error_rangecheck);
72
    pgs_lp->join = join;
73
    return 0;
74
}
75
 
76
/* currentlinejoin */
77
gs_line_join
78
gs_currentlinejoin(const gs_state * pgs)
79
{
80
    return pgs_lp->join;
81
}
82
 
83
/* setmiterlimit */
84
int
85
gx_set_miter_limit(gx_line_params * plp, floatp limit)
86
{
87
    if (limit < 1.0)
88
	return_error(gs_error_rangecheck);
89
    plp->miter_limit = limit;
90
    /*
91
     * Compute the miter check value.  The supplied miter limit is an
92
     * upper bound on 1/sin(phi/2); we convert this to a lower bound on
93
     * tan(phi).  Note that if phi > pi/2, this is negative.  We use the
94
     * half-angle and angle-sum formulas here to avoid the trig functions.
95
     * We also need a special check for phi/2 close to pi/4.
96
     * Some C compilers can't handle this as a conditional expression....
97
     */
98
    {
99
	double limit_squared = limit * limit;
100
 
101
	if (limit_squared < 2.0001 && limit_squared > 1.9999)
102
	    plp->miter_check = 1.0e6;
103
	else
104
	    plp->miter_check =
105
		sqrt(limit_squared - 1) * 2 / (limit_squared - 2);
106
    }
107
    return 0;
108
}
109
int
110
gs_setmiterlimit(gs_state * pgs, floatp limit)
111
{
112
    return gx_set_miter_limit(pgs_lp, limit);
113
}
114
 
115
/* currentmiterlimit */
116
float
117
gs_currentmiterlimit(const gs_state * pgs)
118
{
119
    return pgs_lp->miter_limit;
120
}
121
 
122
/* setdash */
123
int
124
gx_set_dash(gx_dash_params * dash, const float *pattern, uint length,
125
	    floatp offset, gs_memory_t * mem)
126
{
127
    uint n = length;
128
    const float *dfrom = pattern;
129
    bool ink = true;
130
    int index = 0;
131
    float pattern_length = 0.0;
132
    float dist_left;
133
    float *ppat = dash->pattern;
134
 
135
    /* Check the dash pattern. */
136
    while (n--) {
137
	float elt = *dfrom++;
138
 
139
	if (elt < 0)
140
	    return_error(gs_error_rangecheck);
141
	pattern_length += elt;
142
    }
143
    if (length == 0) {		/* empty pattern */
144
	dist_left = 0.0;
145
	if (mem && ppat) {
146
	    gs_free_object(mem, ppat, "gx_set_dash(old pattern)");
147
	    ppat = 0;
148
	}
149
    } else {
150
	uint size = length * sizeof(float);
151
 
152
	if (pattern_length == 0)
153
	    return_error(gs_error_rangecheck);
154
	/* Compute the initial index, ink_on, and distance left */
155
	/* in the pattern, according to the offset. */
156
#define f_mod(a, b) ((a) - floor((a) / (b)) * (b))
157
	if (length & 1) {	/* Odd and even repetitions of the pattern */
158
	    /* have opposite ink values! */
159
	    float length2 = pattern_length * 2;
160
 
161
	    dist_left = f_mod(offset, length2);
162
	    if (dist_left >= pattern_length)
163
		dist_left -= pattern_length, ink = !ink;
164
	} else
165
	    dist_left = f_mod(offset, pattern_length);
166
	while ((dist_left -= pattern[index]) >= 0 &&
167
	       (dist_left > 0 || pattern[index] != 0)
168
	    )
169
	    ink = !ink, index++;
170
	if (mem) {
171
	    if (ppat == 0)
172
		ppat = (float *)gs_alloc_bytes(mem, size,
173
					       "gx_set_dash(pattern)");
174
	    else if (length != dash->pattern_size)
175
		ppat = gs_resize_object(mem, ppat, size,
176
					"gx_set_dash(pattern)");
177
	    if (ppat == 0)
178
		return_error(gs_error_VMerror);
179
	}
180
	memcpy(ppat, pattern, length * sizeof(float));
181
    }
182
    dash->pattern = ppat;
183
    dash->pattern_size = length;
184
    dash->offset = offset;
185
    dash->pattern_length = pattern_length;
186
    dash->init_ink_on = ink;
187
    dash->init_index = index;
188
    dash->init_dist_left = -dist_left;
189
    return 0;
190
}
191
int
192
gs_setdash(gs_state * pgs, const float *pattern, uint length, floatp offset)
193
{
194
    return gx_set_dash(&pgs_lp->dash, pattern, length, offset,
195
		       pgs->memory);
196
}
197
 
198
/* currentdash */
199
uint
200
gs_currentdash_length(const gs_state * pgs)
201
{
202
    return pgs_lp->dash.pattern_size;
203
}
204
const float *
205
gs_currentdash_pattern(const gs_state * pgs)
206
{
207
    return pgs_lp->dash.pattern;
208
}
209
float
210
gs_currentdash_offset(const gs_state * pgs)
211
{
212
    return pgs_lp->dash.offset;
213
}
214
 
215
/* Internal accessor for line parameters */
216
const gx_line_params *
217
gs_currentlineparams(const gs_imager_state * pis)
218
{
219
    return gs_currentlineparams_inline(pis);
220
}
221
 
222
/* ------ Device-dependent parameters ------ */
223
 
224
/* setflat */
225
int
226
gs_imager_setflat(gs_imager_state * pis, floatp flat)
227
{
228
    if (flat <= 0.2)
229
	flat = 0.2;
230
    else if (flat > 100)
231
	flat = 100;
232
    pis->flatness = flat;
233
    return 0;
234
}
235
int
236
gs_setflat(gs_state * pgs, floatp flat)
237
{
238
    return gs_imager_setflat((gs_imager_state *) pgs, flat);
239
}
240
 
241
/* currentflat */
242
float
243
gs_currentflat(const gs_state * pgs)
244
{
245
    return pgs->flatness;
246
}
247
 
248
/* setstrokeadjust */
249
int
250
gs_setstrokeadjust(gs_state * pgs, bool stroke_adjust)
251
{
252
    pgs->stroke_adjust = stroke_adjust;
253
    return 0;
254
}
255
 
256
/* currentstrokeadjust */
257
bool
258
gs_currentstrokeadjust(const gs_state * pgs)
259
{
260
    return pgs->stroke_adjust;
261
}
262
 
263
/* ------ Extensions ------ */
264
 
265
/* Device-independent */
266
 
267
/* setdashadapt */
268
void
269
gs_setdashadapt(gs_state * pgs, bool adapt)
270
{
271
    pgs_lp->dash.adapt = adapt;
272
}
273
 
274
/* currentdashadapt */
275
bool
276
gs_imager_currentdashadapt(const gs_imager_state * pis)
277
{
278
    return gs_currentlineparams_inline(pis)->dash.adapt;
279
}
280
bool
281
gs_currentdashadapt(const gs_state * pgs)
282
{
283
    return gs_imager_currentdashadapt((const gs_imager_state *)pgs);
284
}
285
 
286
/* setcurvejoin */
287
int
288
gs_setcurvejoin(gs_state * pgs, int join)
289
{
290
    if (join < -1 || join > gs_line_join_max)
291
	return_error(gs_error_rangecheck);
292
    pgs_lp->curve_join = join;
293
    return 0;
294
}
295
 
296
/* currentcurvejoin */
297
int
298
gs_currentcurvejoin(const gs_state * pgs)
299
{
300
    return pgs_lp->curve_join;
301
}
302
 
303
/* Device-dependent */
304
 
305
/* setaccuratecurves */
306
void
307
gs_setaccuratecurves(gs_state * pgs, bool accurate)
308
{
309
    pgs->accurate_curves = accurate;
310
}
311
 
312
/* currentaccuratecurves */
313
bool
314
gs_imager_currentaccuratecurves(const gs_imager_state * pis)
315
{
316
    return pis->accurate_curves;
317
}
318
bool
319
gs_currentaccuratecurves(const gs_state * pgs)
320
{
321
    return gs_imager_currentaccuratecurves((const gs_imager_state *)pgs);
322
}
323
 
324
/* setdotlength */
325
int
326
gx_set_dot_length(gx_line_params * plp, floatp length, bool absolute)
327
{
328
    if (length < 0)
329
	return_error(gs_error_rangecheck);
330
    plp->dot_length = length;
331
    plp->dot_length_absolute = absolute;
332
    return 0;
333
}
334
int
335
gs_setdotlength(gs_state * pgs, floatp length, bool absolute)
336
{
337
    return gx_set_dot_length(pgs_lp, length, absolute);
338
}
339
 
340
/* currentdotlength */
341
float
342
gs_currentdotlength(const gs_state * pgs)
343
{
344
    return pgs_lp->dot_length;
345
}
346
bool
347
gs_currentdotlength_absolute(const gs_state * pgs)
348
{
349
    return pgs_lp->dot_length_absolute;
350
}
351
 
352
/* setdotorientation */
353
int
354
gs_setdotorientation(gs_state *pgs)
355
{
356
    if (is_xxyy(&pgs->ctm) || is_xyyx(&pgs->ctm))
357
	return gs_currentmatrix(pgs, &pgs_lp->dot_orientation);
358
    return_error(gs_error_rangecheck);
359
}
360
 
361
/* dotorientation */
362
int
363
gs_dotorientation(gs_state *pgs)
364
{
365
    return gs_setmatrix(pgs, &pgs_lp->dot_orientation);
366
}