~ubuntu-branches/ubuntu/hardy/ghostscript/hardy

« back to all changes in this revision

Viewing changes to src/gxstroke.c

  • Committer: Bazaar Package Importer
  • Author(s): Till Kamppeter
  • Date: 2007-11-22 12:17:43 UTC
  • mfrom: (1.1.7 upstream)
  • Revision ID: james.westby@ubuntu.com-20071122121743-cd70s3ypq0r243mp
Tags: 8.61.dfsg.1-0ubtuntu1
* New upstream release
  o Final 8.61 release
* debian/patches/09_ijs_krgb_support.dpatch: Adapted to upstream changes.
* debian/rules: Updated CUPS-related variables for "make install" calls.
* debian/rules: Remove /usr/include/ghostscript from the ghostscript
  package, they go into lings-dev.

Show diffs side-by-side

added added

removed removed

Lines of Context:
11
11
   San Rafael, CA  94903, U.S.A., +1(415)492-9861, for further information.
12
12
*/
13
13
 
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 */
16
16
#include "math_.h"
17
17
#include "gx.h"
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.
84
84
 */
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);
86
86
int
87
87
gx_stroke_path_expansion(const gs_imager_state * pis, const gx_path * ppath,
88
88
                         gs_fixed_point * ppt)
155
155
 
156
156
    return result;
157
157
}
158
 
private float
 
158
static float
159
159
join_expansion_factor(const gs_imager_state *pis, gs_line_join join)
160
160
{
161
161
    switch (join) {
208
208
  ((pp)->x = (p).x, (pp)->y = (p).y)
209
209
 
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,
217
217
                             bool reflected);
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 *,
220
220
                       int, bool);
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] */ );
224
224
 
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));
262
262
 
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);
269
269
 
276
276
 
277
277
/*
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.
280
280
 *
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.
284
284
 */
285
 
private int
 
285
static int
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)
405
405
    if (pcpath)
406
406
        gx_cpath_inner_box(pcpath, &cbox);
407
407
    else if (pdevc)
408
 
        (*dev_proc(dev, get_clipping_box)) (dev, &cbox);
 
408
        (*dev_proc(pdev, get_clipping_box)) (pdev, &cbox);
409
409
    else {
410
410
        /* This is strokepath, not stroke.  Don't clip. */
411
411
        cbox = ibox;
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.
436
 
         *
 
436
         */
 
437
        /*
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.
 
443
         * 
 
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.
438
448
         */
439
 
        if (pcpath) {
440
 
            gx_make_clip_device(&cdev, gx_cpath_list(pcpath));
441
 
            cdev.target = dev;
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;
445
453
        }
446
454
    }
447
455
    fill_params.rule = gx_rule_winding_number;
758
766
                                     uniform, join, initial_matrix_reflected);
759
767
                if (code < 0)
760
768
                    goto exit;
761
 
                FILL_STROKE_PATH(always_thin);
 
769
                FILL_STROKE_PATH(pdev, always_thin, pcpath);
762
770
            } else
763
771
                pl_first = pl;
764
772
            pl_prev = pl;
780
788
                                 initial_matrix_reflected);
781
789
            if (code < 0)
782
790
                goto exit;
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);
787
795
                if (code < 0)
788
796
                    goto exit;
789
 
                FILL_STROKE_PATH(always_thin);
 
797
                FILL_STROKE_PATH(pdev, always_thin, pcpath);
790
798
            }
791
799
        }
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.
834
842
 */
835
 
private bool
 
843
static bool
836
844
width_is_thin(pl_ptr plp)
837
845
{
838
846
    fixed dx, dy, wx = plp->width.x, wy = plp->width.y;
869
877
}
870
878
 
871
879
/* Adjust the endpoints and width of a stroke segment along a specified axis */
872
 
private void
 
880
static void
873
881
adjust_stroke_transversal(pl_ptr plp, const gs_imager_state * pis, bool thin, bool horiz)
874
882
{
875
883
    fixed *pw;
917
925
    }
918
926
}
919
927
 
920
 
private void 
 
928
static void 
921
929
adjust_stroke_longitude(pl_ptr plp, const gs_imager_state * pis, bool thin, bool horiz)
922
930
{
923
931
 
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. */
969
 
private void
 
977
static void
970
978
adjust_stroke(pl_ptr plp, const gs_imager_state * pis, bool thin, bool adjust_longitude)
971
979
{
972
980
    bool horiz;
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. */
993
 
private int
 
1001
static int
994
1002
line_intersect(
995
1003
                  p_ptr pp1,    /* point on 1st line */
996
1004
                  p_ptr pd1,    /* slope of 1st line (dx,dy) */
1036
1044
 
1037
1045
/* Set up the width and delta parameters for a thin line. */
1038
1046
/* We only approximate the width and height. */
1039
 
private void
 
1047
static void
1040
1048
set_thin_widths(register pl_ptr plp)
1041
1049
{
1042
1050
    fixed dx = plp->e.p.x - plp->o.p.x, dy = plp->e.p.y - plp->o.p.y;
1054
1062
 
1055
1063
/* Draw a line on the device. */
1056
1064
/* Treat no join the same as a bevel join. */
1057
 
private int
 
1065
static int
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,
1154
1162
}
1155
1163
 
1156
1164
/* Add a segment to the path.  This handles all the complex cases. */
1157
 
private int
 
1165
static int
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,
1223
1231
}
1224
1232
 
1225
1233
/* Add a CPSI-compatible segment to the path.  This handles all the complex cases. */
1226
 
private int
 
1234
static int
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,
1323
1331
}
1324
1332
 
1325
1333
/* Add a CPSI-compatible segment to the path.  This handles all the complex cases. */
1326
 
private int
 
1334
static int
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)
1366
1374
}
1367
1375
 
1368
1376
/* Add lines with a possible initial moveto. */
1369
 
private int
 
1377
static int
1370
1378
add_points(gx_path * ppath, const gs_fixed_point * points, int npoints,
1371
1379
           bool moveto_first)
1372
1380
{
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. */
1396
 
private int
 
1404
static int
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)
1600
1608
 
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. */
1603
 
private void
 
1611
static void
1604
1612
compute_caps(pl_ptr plp)
1605
1613
{
1606
1614
    fixed wx2 = plp->width.x;
1636
1644
 
1637
1645
/* Add a round cap to a path. */
1638
1646
/* Assume the current point is the cap origin (endp->co). */
1639
 
private int
 
1647
static int
1640
1648
add_round_cap(gx_path * ppath, const_ep_ptr endp)
1641
1649
{
1642
1650
    int code;
1665
1673
 
1666
1674
/* Compute the points for a non-round cap. */
1667
1675
/* Return the number of points. */
1668
 
private int
 
1676
static int
1669
1677
cap_points(gs_line_cap type, const_ep_ptr endp, gs_fixed_point *pts /*[3]*/)
1670
1678
{
1671
1679
#define PUT_POINT(i, px, py)\