11
11
San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information.
14
/* $Id: gxstroke.c 8022 2007-06-05 22:23:38Z giles $ */
14
/* $Id: gxstroke.c 8286 2007-10-10 23:02:18Z leonardo $ */
15
15
/* Path stroking procedures for Ghostscript library */
82
82
* check and covers many common cases. Clients that care always have the
83
83
* option of using strokepath to get an exact result.
85
private float join_expansion_factor(const gs_imager_state *, gs_line_join);
85
static float join_expansion_factor(const gs_imager_state *, gs_line_join);
87
87
gx_stroke_path_expansion(const gs_imager_state * pis, const gx_path * ppath,
88
88
gs_fixed_point * ppt)
208
208
((pp)->x = (p).x, (pp)->y = (p).y)
210
210
/* Other forward declarations */
211
private bool width_is_thin(pl_ptr);
212
private void adjust_stroke(pl_ptr, const gs_imager_state *, bool, bool);
213
private int line_join_points(const gx_line_params * pgs_lp,
211
static bool width_is_thin(pl_ptr);
212
static void adjust_stroke(pl_ptr, const gs_imager_state *, bool, bool);
213
static int line_join_points(const gx_line_params * pgs_lp,
214
214
pl_ptr plp, pl_ptr nplp,
215
215
gs_fixed_point * join_points,
216
216
const gs_matrix * pmat, gs_line_join join,
218
private void compute_caps(pl_ptr);
219
private int add_points(gx_path *, const gs_fixed_point *,
218
static void compute_caps(pl_ptr);
219
static int add_points(gx_path *, const gs_fixed_point *,
221
private int add_round_cap(gx_path *, const_ep_ptr);
222
private int cap_points(gs_line_cap, const_ep_ptr,
221
static int add_round_cap(gx_path *, const_ep_ptr);
222
static int cap_points(gs_line_cap, const_ep_ptr,
223
223
gs_fixed_point * /*[3] */ );
225
225
/* Define the default implementation of the device stroke_path procedure. */
236
236
/* Fill a partial stroked path. Free variables: */
237
237
/* to_path, stroke_path_body, fill_params, always_thin, pis, dev, pdevc, */
238
238
/* code, ppath, exit(label). */
239
#define FILL_STROKE_PATH(thin)\
239
#define FILL_STROKE_PATH(dev, thin, pcpath)\
240
240
if(to_path==&stroke_path_body && !gx_path_is_void(&stroke_path_body)) {\
241
241
fill_params.adjust.x = STROKE_ADJUSTMENT(thin, pis, x);\
242
242
fill_params.adjust.y = STROKE_ADJUSTMENT(thin, pis, y);\
260
260
gs_line_join, bool)
261
261
typedef stroke_line_proc((*stroke_line_proc_t));
263
private stroke_line_proc(stroke_add);
264
private stroke_line_proc(stroke_add_compat);
265
private stroke_line_proc(stroke_fill);
266
private int stroke_add_initial_cap_compat(gx_path * ppath, pl_ptr plp, bool adlust_longitude,
263
static stroke_line_proc(stroke_add);
264
static stroke_line_proc(stroke_add_compat);
265
static stroke_line_proc(stroke_fill);
266
static int stroke_add_initial_cap_compat(gx_path * ppath, pl_ptr plp, bool adlust_longitude,
267
267
const gx_device_color * pdevc, gx_device * dev,
268
268
const gs_imager_state * pis);
278
278
* Stroke a path. If to_path != 0, append the stroke outline to it;
279
* if to_path == 0, draw the strokes on dev.
279
* if to_path == 0, draw the strokes on pdev.
281
281
* Note that gx_stroke_path_only with to_path != NULL may clip the path to
282
282
* the clipping path, as for to_path == NULL. This is almost never
283
283
* what is wanted.
286
286
gx_stroke_path_only_aux(gx_path * ppath, gx_path * to_path, gx_device * pdev,
287
287
const gs_imager_state * pis, const gx_stroke_params * params,
288
288
const gx_device_color * pdevc, const gx_clip_path * pcpath)
406
406
gx_cpath_inner_box(pcpath, &cbox);
408
(*dev_proc(dev, get_clipping_box)) (dev, &cbox);
408
(*dev_proc(pdev, get_clipping_box)) (pdev, &cbox);
410
410
/* This is strokepath, not stroke. Don't clip. */
433
433
* If we had to flatten the path, this is where we would
434
434
* recompute its bbox and make the tests again,
435
435
* but we don't bother right now.
437
438
* If there is a clipping path, set up a clipping device.
439
* for stroke_fill because, because the latter uses low level methods
440
* which don't accept a clipping path.
441
* Note that in some cases stroke_fill appends the path to stroke_path_body
442
* instead a real painting, and it is painted with FILL_STROKE_PATH.
444
* Contrary to that, FILL_STROKE_PATH paints a path with
445
* the fill_path method, which handles a clipping path,
446
* so we don't pass the clipper device to FILL_STROKE_PATH
447
* to prevent an appearence of superposing clippers.
440
gx_make_clip_device(&cdev, gx_cpath_list(pcpath));
442
cdev.max_fill_band = dev->max_fill_band;
443
dev = (gx_device *) & cdev;
444
(*dev_proc(dev, open_device)) (dev);
449
if (pcpath && line_proc == stroke_fill) {
450
gx_make_clip_device_on_stack(&cdev, pcpath, pdev);
451
cdev.max_fill_band = pdev->max_fill_band;
452
dev = (gx_device *)&cdev;
447
455
fill_params.rule = gx_rule_winding_number;
758
766
uniform, join, initial_matrix_reflected);
761
FILL_STROKE_PATH(always_thin);
769
FILL_STROKE_PATH(pdev, always_thin, pcpath);
780
788
initial_matrix_reflected);
783
FILL_STROKE_PATH(always_thin);
791
FILL_STROKE_PATH(pdev, always_thin, pcpath);
784
792
if (CPSI_mode && lptr == 0 && pgs_lp->cap != gs_cap_butt) {
785
793
/* Create the initial cap at last. */
786
794
code = stroke_add_initial_cap_compat(to_path, &pl_first, index == 1, pdevc, dev, pis);
789
FILL_STROKE_PATH(always_thin);
797
FILL_STROKE_PATH(pdev, always_thin, pcpath);
792
800
psub = (const subpath *)pseg;
832
840
* Unfortunately, the width values we computed are perpendicular to the
833
841
* line in *user* space, so we may have to do some extra work.
836
844
width_is_thin(pl_ptr plp)
838
846
fixed dx, dy, wx = plp->width.x, wy = plp->width.y;
966
974
/* Adjust the endpoints and width of a stroke segment */
967
975
/* to achieve more uniform rendering. */
968
976
/* Only o.p, e.p, e.cdelta, and width have been set. */
970
978
adjust_stroke(pl_ptr plp, const gs_imager_state * pis, bool thin, bool adjust_longitude)
990
998
/* If the lines are (nearly) parallel, return -1 without setting *pi; */
991
999
/* otherwise, return 0 if the intersection is beyond *pp1 and *pp2 in */
992
1000
/* the direction determined by *pd1 and *pd2, and 1 otherwise. */
995
1003
p_ptr pp1, /* point on 1st line */
996
1004
p_ptr pd1, /* slope of 1st line (dx,dy) */
1037
1045
/* Set up the width and delta parameters for a thin line. */
1038
1046
/* We only approximate the width and height. */
1040
1048
set_thin_widths(register pl_ptr plp)
1042
1050
fixed dx = plp->e.p.x - plp->o.p.x, dy = plp->e.p.y - plp->o.p.y;
1055
1063
/* Draw a line on the device. */
1056
1064
/* Treat no join the same as a bevel join. */
1058
1066
stroke_fill(gx_path * ppath, int first, register pl_ptr plp, pl_ptr nplp,
1059
1067
const gx_device_color * pdevc, gx_device * dev,
1060
1068
const gs_imager_state * pis, const gx_stroke_params * params,
1156
1164
/* Add a segment to the path. This handles all the complex cases. */
1158
1166
stroke_add(gx_path * ppath, int first, pl_ptr plp, pl_ptr nplp,
1159
1167
const gx_device_color * pdevc, gx_device * dev,
1160
1168
const gs_imager_state * pis, const gx_stroke_params * params,
1225
1233
/* Add a CPSI-compatible segment to the path. This handles all the complex cases. */
1227
1235
stroke_add_compat(gx_path * ppath, int first, pl_ptr plp, pl_ptr nplp,
1228
1236
const gx_device_color * pdevc, gx_device * dev,
1229
1237
const gs_imager_state * pis, const gx_stroke_params * params,
1325
1333
/* Add a CPSI-compatible segment to the path. This handles all the complex cases. */
1327
1335
stroke_add_initial_cap_compat(gx_path * ppath, pl_ptr plp, bool adlust_longitude,
1328
1336
const gx_device_color * pdevc, gx_device * dev,
1329
1337
const gs_imager_state * pis)
1393
1401
/* Treat no join the same as a bevel join. */
1394
1402
/* If pmat != 0, we must inverse-transform the distances for */
1395
1403
/* the miter check. */
1397
1405
line_join_points(const gx_line_params * pgs_lp, pl_ptr plp, pl_ptr nplp,
1398
1406
gs_fixed_point * join_points, const gs_matrix * pmat,
1399
1407
gs_line_join join, bool reflected)
1601
1609
/* Compute the endpoints of the two caps of a segment. */
1602
1610
/* Only o.p, e.p, width, and cdelta have been set. */
1604
1612
compute_caps(pl_ptr plp)
1606
1614
fixed wx2 = plp->width.x;
1666
1674
/* Compute the points for a non-round cap. */
1667
1675
/* Return the number of points. */
1669
1677
cap_points(gs_line_cap type, const_ep_ptr endp, gs_fixed_point *pts /*[3]*/)
1671
1679
#define PUT_POINT(i, px, py)\