Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
  2. /* cairo - a vector graphics library with display and print output
  3.  *
  4.  * Copyright © 2002 University of Southern California
  5.  * Copyright © 2013 Intel Corporation
  6.  *
  7.  * This library is free software; you can redistribute it and/or
  8.  * modify it either under the terms of the GNU Lesser General Public
  9.  * License version 2.1 as published by the Free Software Foundation
  10.  * (the "LGPL") or, at your option, under the terms of the Mozilla
  11.  * Public License Version 1.1 (the "MPL"). If you do not alter this
  12.  * notice, a recipient may use your version of this file under either
  13.  * the MPL or the LGPL.
  14.  *
  15.  * You should have received a copy of the LGPL along with this library
  16.  * in the file COPYING-LGPL-2.1; if not, write to the Free Software
  17.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  18.  * You should have received a copy of the MPL along with this library
  19.  * in the file COPYING-MPL-1.1
  20.  *
  21.  * The contents of this file are subject to the Mozilla Public License
  22.  * Version 1.1 (the "License"); you may not use this file except in
  23.  * compliance with the License. You may obtain a copy of the License at
  24.  * http://www.mozilla.org/MPL/
  25.  *
  26.  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
  27.  * OF ANY KIND, either express or implied. See the LGPL or the MPL for
  28.  * the specific language governing rights and limitations.
  29.  *
  30.  * The Original Code is the cairo graphics library.
  31.  *
  32.  * The Initial Developer of the Original Code is University of Southern
  33.  * California.
  34.  *
  35.  * Contributor(s):
  36.  *      Carl D. Worth <cworth@cworth.org>
  37.  *      Chris Wilson <chris@chris-wilson.co.uk>
  38.  */
  39.  
  40. #include "cairoint.h"
  41.  
  42. #include "cairo-box-inline.h"
  43. #include "cairo-path-fixed-private.h"
  44. #include "cairo-slope-private.h"
  45. #include "cairo-stroke-dash-private.h"
  46. #include "cairo-traps-private.h"
  47.  
  48. #include <float.h>
  49.  
  50. struct stroker {
  51.     const cairo_stroke_style_t  *style;
  52.  
  53.     const cairo_matrix_t *ctm;
  54.     const cairo_matrix_t *ctm_inverse;
  55.     double spline_cusp_tolerance;
  56.     double half_line_width;
  57.     double tolerance;
  58.     double ctm_determinant;
  59.     cairo_bool_t ctm_det_positive;
  60.     cairo_line_join_t line_join;
  61.  
  62.     cairo_traps_t *traps;
  63.  
  64.     cairo_pen_t pen;
  65.  
  66.     cairo_point_t first_point;
  67.  
  68.     cairo_bool_t has_initial_sub_path;
  69.  
  70.     cairo_bool_t has_current_face;
  71.     cairo_stroke_face_t current_face;
  72.  
  73.     cairo_bool_t has_first_face;
  74.     cairo_stroke_face_t first_face;
  75.  
  76.     cairo_stroker_dash_t dash;
  77.  
  78.     cairo_bool_t has_bounds;
  79.     cairo_box_t tight_bounds;
  80.     cairo_box_t line_bounds;
  81.     cairo_box_t join_bounds;
  82. };
  83.  
  84. static cairo_status_t
  85. stroker_init (struct stroker            *stroker,
  86.               const cairo_path_fixed_t  *path,
  87.               const cairo_stroke_style_t        *style,
  88.               const cairo_matrix_t      *ctm,
  89.               const cairo_matrix_t      *ctm_inverse,
  90.               double                     tolerance,
  91.               cairo_traps_t             *traps)
  92. {
  93.     cairo_status_t status;
  94.  
  95.     stroker->style = style;
  96.     stroker->ctm = ctm;
  97.     stroker->ctm_inverse = NULL;
  98.     if (! _cairo_matrix_is_identity (ctm_inverse))
  99.         stroker->ctm_inverse = ctm_inverse;
  100.     stroker->line_join = style->line_join;
  101.     stroker->half_line_width = style->line_width / 2.0;
  102.     stroker->tolerance = tolerance;
  103.     stroker->traps = traps;
  104.  
  105.     /* To test whether we need to join two segments of a spline using
  106.      * a round-join or a bevel-join, we can inspect the angle between the
  107.      * two segments. If the difference between the chord distance
  108.      * (half-line-width times the cosine of the bisection angle) and the
  109.      * half-line-width itself is greater than tolerance then we need to
  110.      * inject a point.
  111.      */
  112.     stroker->spline_cusp_tolerance = 1 - tolerance / stroker->half_line_width;
  113.     stroker->spline_cusp_tolerance *= stroker->spline_cusp_tolerance;
  114.     stroker->spline_cusp_tolerance *= 2;
  115.     stroker->spline_cusp_tolerance -= 1;
  116.  
  117.     stroker->ctm_determinant = _cairo_matrix_compute_determinant (stroker->ctm);
  118.     stroker->ctm_det_positive = stroker->ctm_determinant >= 0.0;
  119.  
  120.     status = _cairo_pen_init (&stroker->pen,
  121.                               stroker->half_line_width,
  122.                               tolerance, ctm);
  123.     if (unlikely (status))
  124.         return status;
  125.  
  126.     stroker->has_current_face = FALSE;
  127.     stroker->has_first_face = FALSE;
  128.     stroker->has_initial_sub_path = FALSE;
  129.  
  130.     _cairo_stroker_dash_init (&stroker->dash, style);
  131.  
  132.     stroker->has_bounds = traps->num_limits;
  133.     if (stroker->has_bounds) {
  134.         /* Extend the bounds in each direction to account for the maximum area
  135.          * we might generate trapezoids, to capture line segments that are outside
  136.          * of the bounds but which might generate rendering that's within bounds.
  137.          */
  138.         double dx, dy;
  139.         cairo_fixed_t fdx, fdy;
  140.  
  141.         stroker->tight_bounds = traps->bounds;
  142.  
  143.         _cairo_stroke_style_max_distance_from_path (stroker->style, path,
  144.                                                     stroker->ctm, &dx, &dy);
  145.  
  146.         _cairo_stroke_style_max_line_distance_from_path (stroker->style, path,
  147.                                                          stroker->ctm, &dx, &dy);
  148.  
  149.         fdx = _cairo_fixed_from_double (dx);
  150.         fdy = _cairo_fixed_from_double (dy);
  151.  
  152.         stroker->line_bounds = stroker->tight_bounds;
  153.         stroker->line_bounds.p1.x -= fdx;
  154.         stroker->line_bounds.p2.x += fdx;
  155.         stroker->line_bounds.p1.y -= fdy;
  156.         stroker->line_bounds.p2.y += fdy;
  157.  
  158.         _cairo_stroke_style_max_join_distance_from_path (stroker->style, path,
  159.                                                          stroker->ctm, &dx, &dy);
  160.  
  161.         fdx = _cairo_fixed_from_double (dx);
  162.         fdy = _cairo_fixed_from_double (dy);
  163.  
  164.         stroker->join_bounds = stroker->tight_bounds;
  165.         stroker->join_bounds.p1.x -= fdx;
  166.         stroker->join_bounds.p2.x += fdx;
  167.         stroker->join_bounds.p1.y -= fdy;
  168.         stroker->join_bounds.p2.y += fdy;
  169.     }
  170.  
  171.     return CAIRO_STATUS_SUCCESS;
  172. }
  173.  
  174. static void
  175. stroker_fini (struct stroker *stroker)
  176. {
  177.     _cairo_pen_fini (&stroker->pen);
  178. }
  179.  
  180. static void
  181. translate_point (cairo_point_t *point, cairo_point_t *offset)
  182. {
  183.     point->x += offset->x;
  184.     point->y += offset->y;
  185. }
  186.  
  187. static int
  188. join_is_clockwise (const cairo_stroke_face_t *in,
  189.                    const cairo_stroke_face_t *out)
  190. {
  191.     return _cairo_slope_compare (&in->dev_vector, &out->dev_vector) < 0;
  192. }
  193.  
  194. static int
  195. slope_compare_sgn (double dx1, double dy1, double dx2, double dy2)
  196. {
  197.     double c = dx1 * dy2 - dx2 * dy1;
  198.     if (c > 0) return 1;
  199.     if (c < 0) return -1;
  200.     return 0;
  201. }
  202.  
  203. static cairo_bool_t
  204. stroker_intersects_join (const struct stroker *stroker,
  205.                          const cairo_point_t *in,
  206.                          const cairo_point_t *out)
  207. {
  208.     cairo_line_t segment;
  209.  
  210.     if (! stroker->has_bounds)
  211.         return TRUE;
  212.  
  213.     segment.p1 = *in;
  214.     segment.p2 = *out;
  215.     return _cairo_box_intersects_line_segment (&stroker->join_bounds, &segment);
  216. }
  217.  
  218. static void
  219. join (struct stroker *stroker,
  220.       cairo_stroke_face_t *in,
  221.       cairo_stroke_face_t *out)
  222. {
  223.     int clockwise = join_is_clockwise (out, in);
  224.     cairo_point_t *inpt, *outpt;
  225.  
  226.     if (in->cw.x == out->cw.x &&
  227.         in->cw.y == out->cw.y &&
  228.         in->ccw.x == out->ccw.x &&
  229.         in->ccw.y == out->ccw.y)
  230.     {
  231.         return;
  232.     }
  233.  
  234.     if (clockwise) {
  235.         inpt = &in->ccw;
  236.         outpt = &out->ccw;
  237.     } else {
  238.         inpt = &in->cw;
  239.         outpt = &out->cw;
  240.     }
  241.  
  242.     if (! stroker_intersects_join (stroker, inpt, outpt))
  243.             return;
  244.  
  245.     switch (stroker->line_join) {
  246.     case CAIRO_LINE_JOIN_ROUND:
  247.         /* construct a fan around the common midpoint */
  248.         if ((in->dev_slope.x * out->dev_slope.x +
  249.              in->dev_slope.y * out->dev_slope.y) < stroker->spline_cusp_tolerance)
  250.         {
  251.             int start, stop;
  252.             cairo_point_t tri[3];
  253.             cairo_pen_t *pen = &stroker->pen;
  254.  
  255.             tri[0] = in->point;
  256.             tri[1] = *inpt;
  257.             if (clockwise) {
  258.                 _cairo_pen_find_active_ccw_vertices (pen,
  259.                                                      &in->dev_vector, &out->dev_vector,
  260.                                                      &start, &stop);
  261.                 while (start != stop) {
  262.                     tri[2] = in->point;
  263.                     translate_point (&tri[2], &pen->vertices[start].point);
  264.                     _cairo_traps_tessellate_triangle (stroker->traps, tri);
  265.                     tri[1] = tri[2];
  266.  
  267.                     if (start-- == 0)
  268.                         start += pen->num_vertices;
  269.                 }
  270.             } else {
  271.                 _cairo_pen_find_active_cw_vertices (pen,
  272.                                                     &in->dev_vector, &out->dev_vector,
  273.                                                     &start, &stop);
  274.                 while (start != stop) {
  275.                     tri[2] = in->point;
  276.                     translate_point (&tri[2], &pen->vertices[start].point);
  277.                     _cairo_traps_tessellate_triangle (stroker->traps, tri);
  278.                     tri[1] = tri[2];
  279.  
  280.                     if (++start == pen->num_vertices)
  281.                         start = 0;
  282.                 }
  283.             }
  284.             tri[2] = *outpt;
  285.             _cairo_traps_tessellate_triangle (stroker->traps, tri);
  286.             break;
  287.         }
  288.  
  289.     case CAIRO_LINE_JOIN_MITER:
  290.     default: {
  291.         /* dot product of incoming slope vector with outgoing slope vector */
  292.         double in_dot_out = (-in->usr_vector.x * out->usr_vector.x +
  293.                              -in->usr_vector.y * out->usr_vector.y);
  294.         double ml = stroker->style->miter_limit;
  295.  
  296.         /* Check the miter limit -- lines meeting at an acute angle
  297.          * can generate long miters, the limit converts them to bevel
  298.          *
  299.          * Consider the miter join formed when two line segments
  300.          * meet at an angle psi:
  301.          *
  302.          *         /.\
  303.          *        /. .\
  304.          *       /./ \.\
  305.          *      /./psi\.\
  306.          *
  307.          * We can zoom in on the right half of that to see:
  308.          *
  309.          *          |\
  310.          *          | \ psi/2
  311.          *          |  \
  312.          *          |   \
  313.          *          |    \
  314.          *          |     \
  315.          *        miter    \
  316.          *       length     \
  317.          *          |        \
  318.          *          |        .\
  319.          *          |    .     \
  320.          *          |.   line   \
  321.          *           \    width  \
  322.          *            \           \
  323.          *
  324.          *
  325.          * The right triangle in that figure, (the line-width side is
  326.          * shown faintly with three '.' characters), gives us the
  327.          * following expression relating miter length, angle and line
  328.          * width:
  329.          *
  330.          *      1 /sin (psi/2) = miter_length / line_width
  331.          *
  332.          * The right-hand side of this relationship is the same ratio
  333.          * in which the miter limit (ml) is expressed. We want to know
  334.          * when the miter length is within the miter limit. That is
  335.          * when the following condition holds:
  336.          *
  337.          *      1/sin(psi/2) <= ml
  338.          *      1 <= ml sin(psi/2)
  339.          *      1 <= ml² sin²(psi/2)
  340.          *      2 <= ml² 2 sin²(psi/2)
  341.          *                              2·sin²(psi/2) = 1-cos(psi)
  342.          *      2 <= ml² (1-cos(psi))
  343.          *
  344.          *                              in · out = |in| |out| cos (psi)
  345.          *
  346.          * in and out are both unit vectors, so:
  347.          *
  348.          *                              in · out = cos (psi)
  349.          *
  350.          *      2 <= ml² (1 - in · out)
  351.          *
  352.          */
  353.         if (2 <= ml * ml * (1 - in_dot_out)) {
  354.             double              x1, y1, x2, y2;
  355.             double              mx, my;
  356.             double              dx1, dx2, dy1, dy2;
  357.             cairo_point_t       outer;
  358.             cairo_point_t       quad[4];
  359.             double              ix, iy;
  360.             double              fdx1, fdy1, fdx2, fdy2;
  361.             double              mdx, mdy;
  362.  
  363.             /*
  364.              * we've got the points already transformed to device
  365.              * space, but need to do some computation with them and
  366.              * also need to transform the slope from user space to
  367.              * device space
  368.              */
  369.             /* outer point of incoming line face */
  370.             x1 = _cairo_fixed_to_double (inpt->x);
  371.             y1 = _cairo_fixed_to_double (inpt->y);
  372.             dx1 = in->usr_vector.x;
  373.             dy1 = in->usr_vector.y;
  374.             cairo_matrix_transform_distance (stroker->ctm, &dx1, &dy1);
  375.  
  376.             /* outer point of outgoing line face */
  377.             x2 = _cairo_fixed_to_double (outpt->x);
  378.             y2 = _cairo_fixed_to_double (outpt->y);
  379.             dx2 = out->usr_vector.x;
  380.             dy2 = out->usr_vector.y;
  381.             cairo_matrix_transform_distance (stroker->ctm, &dx2, &dy2);
  382.  
  383.             /*
  384.              * Compute the location of the outer corner of the miter.
  385.              * That's pretty easy -- just the intersection of the two
  386.              * outer edges.  We've got slopes and points on each
  387.              * of those edges.  Compute my directly, then compute
  388.              * mx by using the edge with the larger dy; that avoids
  389.              * dividing by values close to zero.
  390.              */
  391.             my = (((x2 - x1) * dy1 * dy2 - y2 * dx2 * dy1 + y1 * dx1 * dy2) /
  392.                   (dx1 * dy2 - dx2 * dy1));
  393.             if (fabs (dy1) >= fabs (dy2))
  394.                 mx = (my - y1) * dx1 / dy1 + x1;
  395.             else
  396.                 mx = (my - y2) * dx2 / dy2 + x2;
  397.  
  398.             /*
  399.              * When the two outer edges are nearly parallel, slight
  400.              * perturbations in the position of the outer points of the lines
  401.              * caused by representing them in fixed point form can cause the
  402.              * intersection point of the miter to move a large amount. If
  403.              * that moves the miter intersection from between the two faces,
  404.              * then draw a bevel instead.
  405.              */
  406.  
  407.             ix = _cairo_fixed_to_double (in->point.x);
  408.             iy = _cairo_fixed_to_double (in->point.y);
  409.  
  410.             /* slope of one face */
  411.             fdx1 = x1 - ix; fdy1 = y1 - iy;
  412.  
  413.             /* slope of the other face */
  414.             fdx2 = x2 - ix; fdy2 = y2 - iy;
  415.  
  416.             /* slope from the intersection to the miter point */
  417.             mdx = mx - ix; mdy = my - iy;
  418.  
  419.             /*
  420.              * Make sure the miter point line lies between the two
  421.              * faces by comparing the slopes
  422.              */
  423.             if (slope_compare_sgn (fdx1, fdy1, mdx, mdy) !=
  424.                 slope_compare_sgn (fdx2, fdy2, mdx, mdy))
  425.             {
  426.                 /*
  427.                  * Draw the quadrilateral
  428.                  */
  429.                 outer.x = _cairo_fixed_from_double (mx);
  430.                 outer.y = _cairo_fixed_from_double (my);
  431.  
  432.                 quad[0] = in->point;
  433.                 quad[1] = *inpt;
  434.                 quad[2] = outer;
  435.                 quad[3] = *outpt;
  436.  
  437.                 _cairo_traps_tessellate_convex_quad (stroker->traps, quad);
  438.                 break;
  439.             }
  440.         }
  441.         /* fall through ... */
  442.     }
  443.  
  444.     case CAIRO_LINE_JOIN_BEVEL: {
  445.         cairo_point_t tri[3];
  446.         tri[0] = in->point;
  447.         tri[1] = *inpt;
  448.         tri[2] = *outpt;
  449.  
  450.         _cairo_traps_tessellate_triangle (stroker->traps, tri);
  451.         break;
  452.     }
  453.     }
  454. }
  455.  
  456. static void
  457. add_cap (struct stroker *stroker, cairo_stroke_face_t *f)
  458. {
  459.     switch (stroker->style->line_cap) {
  460.     case CAIRO_LINE_CAP_ROUND: {
  461.         int start, stop;
  462.         cairo_slope_t in_slope, out_slope;
  463.         cairo_point_t tri[3];
  464.         cairo_pen_t *pen = &stroker->pen;
  465.  
  466.         in_slope = f->dev_vector;
  467.         out_slope.dx = -in_slope.dx;
  468.         out_slope.dy = -in_slope.dy;
  469.         _cairo_pen_find_active_cw_vertices (pen, &in_slope, &out_slope,
  470.                                             &start, &stop);
  471.         tri[0] = f->point;
  472.         tri[1] = f->cw;
  473.         while (start != stop) {
  474.             tri[2] = f->point;
  475.             translate_point (&tri[2], &pen->vertices[start].point);
  476.             _cairo_traps_tessellate_triangle (stroker->traps, tri);
  477.  
  478.             tri[1] = tri[2];
  479.             if (++start == pen->num_vertices)
  480.                 start = 0;
  481.         }
  482.         tri[2] = f->ccw;
  483.         _cairo_traps_tessellate_triangle (stroker->traps, tri);
  484.         break;
  485.     }
  486.  
  487.     case CAIRO_LINE_CAP_SQUARE: {
  488.         double dx, dy;
  489.         cairo_slope_t fvector;
  490.         cairo_point_t quad[4];
  491.  
  492.         dx = f->usr_vector.x;
  493.         dy = f->usr_vector.y;
  494.         dx *= stroker->half_line_width;
  495.         dy *= stroker->half_line_width;
  496.         cairo_matrix_transform_distance (stroker->ctm, &dx, &dy);
  497.         fvector.dx = _cairo_fixed_from_double (dx);
  498.         fvector.dy = _cairo_fixed_from_double (dy);
  499.  
  500.         quad[0] = f->cw;
  501.         quad[1].x = f->cw.x + fvector.dx;
  502.         quad[1].y = f->cw.y + fvector.dy;
  503.         quad[2].x = f->ccw.x + fvector.dx;
  504.         quad[2].y = f->ccw.y + fvector.dy;
  505.         quad[3] = f->ccw;
  506.  
  507.         _cairo_traps_tessellate_convex_quad (stroker->traps, quad);
  508.         break;
  509.     }
  510.  
  511.     case CAIRO_LINE_CAP_BUTT:
  512.     default:
  513.         break;
  514.     }
  515. }
  516.  
  517. static void
  518. add_leading_cap (struct stroker     *stroker,
  519.                  cairo_stroke_face_t *face)
  520. {
  521.     cairo_stroke_face_t reversed;
  522.     cairo_point_t t;
  523.  
  524.     reversed = *face;
  525.  
  526.     /* The initial cap needs an outward facing vector. Reverse everything */
  527.     reversed.usr_vector.x = -reversed.usr_vector.x;
  528.     reversed.usr_vector.y = -reversed.usr_vector.y;
  529.     reversed.dev_vector.dx = -reversed.dev_vector.dx;
  530.     reversed.dev_vector.dy = -reversed.dev_vector.dy;
  531.     t = reversed.cw;
  532.     reversed.cw = reversed.ccw;
  533.     reversed.ccw = t;
  534.  
  535.     add_cap (stroker, &reversed);
  536. }
  537.  
  538. static void
  539. add_trailing_cap (struct stroker *stroker, cairo_stroke_face_t *face)
  540. {
  541.     add_cap (stroker, face);
  542. }
  543.  
  544. static inline double
  545. normalize_slope (double *dx, double *dy)
  546. {
  547.     double dx0 = *dx, dy0 = *dy;
  548.  
  549.     if (dx0 == 0.0 && dy0 == 0.0)
  550.         return 0;
  551.  
  552.     if (dx0 == 0.0) {
  553.         *dx = 0.0;
  554.         if (dy0 > 0.0) {
  555.             *dy = 1.0;
  556.             return dy0;
  557.         } else {
  558.             *dy = -1.0;
  559.             return -dy0;
  560.         }
  561.     } else if (dy0 == 0.0) {
  562.         *dy = 0.0;
  563.         if (dx0 > 0.0) {
  564.             *dx = 1.0;
  565.             return dx0;
  566.         } else {
  567.             *dx = -1.0;
  568.             return -dx0;
  569.         }
  570.     } else {
  571.         double mag = hypot (dx0, dy0);
  572.         *dx = dx0 / mag;
  573.         *dy = dy0 / mag;
  574.         return mag;
  575.     }
  576. }
  577.  
  578. static void
  579. compute_face (const cairo_point_t *point,
  580.               const cairo_slope_t *dev_slope,
  581.               struct stroker *stroker,
  582.               cairo_stroke_face_t *face)
  583. {
  584.     double face_dx, face_dy;
  585.     cairo_point_t offset_ccw, offset_cw;
  586.     double slope_dx, slope_dy;
  587.  
  588.     slope_dx = _cairo_fixed_to_double (dev_slope->dx);
  589.     slope_dy = _cairo_fixed_to_double (dev_slope->dy);
  590.     face->length = normalize_slope (&slope_dx, &slope_dy);
  591.     face->dev_slope.x = slope_dx;
  592.     face->dev_slope.y = slope_dy;
  593.  
  594.     /*
  595.      * rotate to get a line_width/2 vector along the face, note that
  596.      * the vector must be rotated the right direction in device space,
  597.      * but by 90° in user space. So, the rotation depends on
  598.      * whether the ctm reflects or not, and that can be determined
  599.      * by looking at the determinant of the matrix.
  600.      */
  601.     if (stroker->ctm_inverse) {
  602.         cairo_matrix_transform_distance (stroker->ctm_inverse, &slope_dx, &slope_dy);
  603.         normalize_slope (&slope_dx, &slope_dy);
  604.  
  605.         if (stroker->ctm_det_positive) {
  606.             face_dx = - slope_dy * stroker->half_line_width;
  607.             face_dy = slope_dx * stroker->half_line_width;
  608.         } else {
  609.             face_dx = slope_dy * stroker->half_line_width;
  610.             face_dy = - slope_dx * stroker->half_line_width;
  611.         }
  612.  
  613.         /* back to device space */
  614.         cairo_matrix_transform_distance (stroker->ctm, &face_dx, &face_dy);
  615.     } else {
  616.         face_dx = - slope_dy * stroker->half_line_width;
  617.         face_dy = slope_dx * stroker->half_line_width;
  618.     }
  619.  
  620.     offset_ccw.x = _cairo_fixed_from_double (face_dx);
  621.     offset_ccw.y = _cairo_fixed_from_double (face_dy);
  622.     offset_cw.x = -offset_ccw.x;
  623.     offset_cw.y = -offset_ccw.y;
  624.  
  625.     face->ccw = *point;
  626.     translate_point (&face->ccw, &offset_ccw);
  627.  
  628.     face->point = *point;
  629.  
  630.     face->cw = *point;
  631.     translate_point (&face->cw, &offset_cw);
  632.  
  633.     face->usr_vector.x = slope_dx;
  634.     face->usr_vector.y = slope_dy;
  635.  
  636.     face->dev_vector = *dev_slope;
  637. }
  638.  
  639. static void
  640. add_caps (struct stroker *stroker)
  641. {
  642.     /* check for a degenerative sub_path */
  643.     if (stroker->has_initial_sub_path &&
  644.         !stroker->has_first_face &&
  645.         !stroker->has_current_face &&
  646.         stroker->style->line_cap == CAIRO_LINE_CAP_ROUND)
  647.     {
  648.         /* pick an arbitrary slope to use */
  649.         cairo_slope_t slope = { CAIRO_FIXED_ONE, 0 };
  650.         cairo_stroke_face_t face;
  651.  
  652.         /* arbitrarily choose first_point
  653.          * first_point and current_point should be the same */
  654.         compute_face (&stroker->first_point, &slope, stroker, &face);
  655.  
  656.         add_leading_cap (stroker, &face);
  657.         add_trailing_cap (stroker, &face);
  658.     }
  659.  
  660.     if (stroker->has_first_face)
  661.         add_leading_cap (stroker, &stroker->first_face);
  662.  
  663.     if (stroker->has_current_face)
  664.         add_trailing_cap (stroker, &stroker->current_face);
  665. }
  666.  
  667. static cairo_bool_t
  668. stroker_intersects_edge (const struct stroker *stroker,
  669.                          const cairo_stroke_face_t *start,
  670.                          const cairo_stroke_face_t *end)
  671. {
  672.     cairo_box_t box;
  673.  
  674.     if (! stroker->has_bounds)
  675.         return TRUE;
  676.  
  677.     if (_cairo_box_contains_point (&stroker->tight_bounds, &start->cw))
  678.         return TRUE;
  679.     box.p2 = box.p1 = start->cw;
  680.  
  681.     if (_cairo_box_contains_point (&stroker->tight_bounds, &start->ccw))
  682.         return TRUE;
  683.     _cairo_box_add_point (&box, &start->ccw);
  684.  
  685.     if (_cairo_box_contains_point (&stroker->tight_bounds, &end->cw))
  686.         return TRUE;
  687.     _cairo_box_add_point (&box, &end->cw);
  688.  
  689.     if (_cairo_box_contains_point (&stroker->tight_bounds, &end->ccw))
  690.         return TRUE;
  691.     _cairo_box_add_point (&box, &end->ccw);
  692.  
  693.     return (box.p2.x > stroker->tight_bounds.p1.x &&
  694.             box.p1.x < stroker->tight_bounds.p2.x &&
  695.             box.p2.y > stroker->tight_bounds.p1.y &&
  696.             box.p1.y < stroker->tight_bounds.p2.y);
  697. }
  698.  
  699. static void
  700. add_sub_edge (struct stroker *stroker,
  701.               const cairo_point_t *p1, const cairo_point_t *p2,
  702.               const cairo_slope_t *dev_slope,
  703.               cairo_stroke_face_t *start, cairo_stroke_face_t *end)
  704. {
  705.     cairo_point_t rectangle[4];
  706.  
  707.     compute_face (p1, dev_slope, stroker, start);
  708.  
  709.     *end = *start;
  710.     end->point = *p2;
  711.     rectangle[0].x = p2->x - p1->x;
  712.     rectangle[0].y = p2->y - p1->y;
  713.     translate_point (&end->ccw, &rectangle[0]);
  714.     translate_point (&end->cw, &rectangle[0]);
  715.  
  716.     if (p1->x == p2->x && p1->y == p2->y)
  717.         return;
  718.  
  719.     if (! stroker_intersects_edge (stroker, start, end))
  720.         return;
  721.  
  722.     rectangle[0] = start->cw;
  723.     rectangle[1] = start->ccw;
  724.     rectangle[2] = end->ccw;
  725.     rectangle[3] = end->cw;
  726.  
  727.     _cairo_traps_tessellate_convex_quad (stroker->traps, rectangle);
  728. }
  729.  
  730. static cairo_status_t
  731. move_to (void *closure, const cairo_point_t *point)
  732. {
  733.     struct stroker *stroker = closure;
  734.  
  735.     /* Cap the start and end of the previous sub path as needed */
  736.     add_caps (stroker);
  737.  
  738.     stroker->first_point = *point;
  739.     stroker->current_face.point = *point;
  740.  
  741.     stroker->has_first_face = FALSE;
  742.     stroker->has_current_face = FALSE;
  743.     stroker->has_initial_sub_path = FALSE;
  744.  
  745.     return CAIRO_STATUS_SUCCESS;
  746. }
  747.  
  748. static cairo_status_t
  749. move_to_dashed (void *closure, const cairo_point_t *point)
  750. {
  751.     /* reset the dash pattern for new sub paths */
  752.     struct stroker *stroker = closure;
  753.  
  754.     _cairo_stroker_dash_start (&stroker->dash);
  755.     return move_to (closure, point);
  756. }
  757.  
  758. static cairo_status_t
  759. line_to (void *closure, const cairo_point_t *point)
  760. {
  761.     struct stroker *stroker = closure;
  762.     cairo_stroke_face_t start, end;
  763.     const cairo_point_t *p1 = &stroker->current_face.point;
  764.     const cairo_point_t *p2 = point;
  765.     cairo_slope_t dev_slope;
  766.  
  767.     stroker->has_initial_sub_path = TRUE;
  768.  
  769.     if (p1->x == p2->x && p1->y == p2->y)
  770.         return CAIRO_STATUS_SUCCESS;
  771.  
  772.     _cairo_slope_init (&dev_slope, p1, p2);
  773.     add_sub_edge (stroker, p1, p2, &dev_slope, &start, &end);
  774.  
  775.     if (stroker->has_current_face) {
  776.         /* Join with final face from previous segment */
  777.         join (stroker, &stroker->current_face, &start);
  778.     } else if (!stroker->has_first_face) {
  779.         /* Save sub path's first face in case needed for closing join */
  780.         stroker->first_face = start;
  781.         stroker->has_first_face = TRUE;
  782.     }
  783.     stroker->current_face = end;
  784.     stroker->has_current_face = TRUE;
  785.  
  786.     return CAIRO_STATUS_SUCCESS;
  787. }
  788.  
  789. /*
  790.  * Dashed lines.  Cap each dash end, join around turns when on
  791.  */
  792. static cairo_status_t
  793. line_to_dashed (void *closure, const cairo_point_t *point)
  794. {
  795.     struct stroker *stroker = closure;
  796.     double mag, remain, step_length = 0;
  797.     double slope_dx, slope_dy;
  798.     double dx2, dy2;
  799.     cairo_stroke_face_t sub_start, sub_end;
  800.     const cairo_point_t *p1 = &stroker->current_face.point;
  801.     const cairo_point_t *p2 = point;
  802.     cairo_slope_t dev_slope;
  803.     cairo_line_t segment;
  804.     cairo_bool_t fully_in_bounds;
  805.  
  806.     stroker->has_initial_sub_path = stroker->dash.dash_starts_on;
  807.  
  808.     if (p1->x == p2->x && p1->y == p2->y)
  809.         return CAIRO_STATUS_SUCCESS;
  810.  
  811.     fully_in_bounds = TRUE;
  812.     if (stroker->has_bounds &&
  813.         (! _cairo_box_contains_point (&stroker->join_bounds, p1) ||
  814.          ! _cairo_box_contains_point (&stroker->join_bounds, p2)))
  815.     {
  816.         fully_in_bounds = FALSE;
  817.     }
  818.  
  819.     _cairo_slope_init (&dev_slope, p1, p2);
  820.  
  821.     slope_dx = _cairo_fixed_to_double (p2->x - p1->x);
  822.     slope_dy = _cairo_fixed_to_double (p2->y - p1->y);
  823.  
  824.     if (stroker->ctm_inverse)
  825.         cairo_matrix_transform_distance (stroker->ctm_inverse, &slope_dx, &slope_dy);
  826.     mag = normalize_slope (&slope_dx, &slope_dy);
  827.     if (mag <= DBL_EPSILON)
  828.         return CAIRO_STATUS_SUCCESS;
  829.  
  830.     remain = mag;
  831.     segment.p1 = *p1;
  832.     while (remain) {
  833.         step_length = MIN (stroker->dash.dash_remain, remain);
  834.         remain -= step_length;
  835.         dx2 = slope_dx * (mag - remain);
  836.         dy2 = slope_dy * (mag - remain);
  837.         cairo_matrix_transform_distance (stroker->ctm, &dx2, &dy2);
  838.         segment.p2.x = _cairo_fixed_from_double (dx2) + p1->x;
  839.         segment.p2.y = _cairo_fixed_from_double (dy2) + p1->y;
  840.  
  841.         if (stroker->dash.dash_on &&
  842.             (fully_in_bounds ||
  843.              (! stroker->has_first_face && stroker->dash.dash_starts_on) ||
  844.              _cairo_box_intersects_line_segment (&stroker->join_bounds, &segment)))
  845.         {
  846.             add_sub_edge (stroker,
  847.                           &segment.p1, &segment.p2,
  848.                           &dev_slope,
  849.                           &sub_start, &sub_end);
  850.  
  851.             if (stroker->has_current_face) {
  852.                 /* Join with final face from previous segment */
  853.                 join (stroker, &stroker->current_face, &sub_start);
  854.  
  855.                 stroker->has_current_face = FALSE;
  856.             } else if (! stroker->has_first_face && stroker->dash.dash_starts_on) {
  857.                 /* Save sub path's first face in case needed for closing join */
  858.                 stroker->first_face = sub_start;
  859.                 stroker->has_first_face = TRUE;
  860.             } else {
  861.                 /* Cap dash start if not connecting to a previous segment */
  862.                 add_leading_cap (stroker, &sub_start);
  863.             }
  864.  
  865.             if (remain) {
  866.                 /* Cap dash end if not at end of segment */
  867.                 add_trailing_cap (stroker, &sub_end);
  868.             } else {
  869.                 stroker->current_face = sub_end;
  870.                 stroker->has_current_face = TRUE;
  871.             }
  872.         } else {
  873.             if (stroker->has_current_face) {
  874.                 /* Cap final face from previous segment */
  875.                 add_trailing_cap (stroker, &stroker->current_face);
  876.  
  877.                 stroker->has_current_face = FALSE;
  878.             }
  879.         }
  880.  
  881.         _cairo_stroker_dash_step (&stroker->dash, step_length);
  882.         segment.p1 = segment.p2;
  883.     }
  884.  
  885.     if (stroker->dash.dash_on && ! stroker->has_current_face) {
  886.         /* This segment ends on a transition to dash_on, compute a new face
  887.          * and add cap for the beginning of the next dash_on step.
  888.          *
  889.          * Note: this will create a degenerate cap if this is not the last line
  890.          * in the path. Whether this behaviour is desirable or not is debatable.
  891.          * On one side these degenerate caps can not be reproduced with regular
  892.          * path stroking.
  893.          * On the other hand, Acroread 7 also produces the degenerate caps.
  894.          */
  895.         compute_face (point, &dev_slope, stroker, &stroker->current_face);
  896.  
  897.         add_leading_cap (stroker, &stroker->current_face);
  898.  
  899.         stroker->has_current_face = TRUE;
  900.     } else
  901.         stroker->current_face.point = *point;
  902.  
  903.     return CAIRO_STATUS_SUCCESS;
  904. }
  905.  
  906. static cairo_status_t
  907. spline_to (void *closure,
  908.            const cairo_point_t *point,
  909.            const cairo_slope_t *tangent)
  910. {
  911.     struct stroker *stroker = closure;
  912.     cairo_stroke_face_t face;
  913.  
  914.     if ((tangent->dx | tangent->dy) == 0) {
  915.         cairo_point_t t;
  916.  
  917.         face = stroker->current_face;
  918.  
  919.         face.usr_vector.x = -face.usr_vector.x;
  920.         face.usr_vector.y = -face.usr_vector.y;
  921.         face.dev_slope.x = -face.dev_slope.x;
  922.         face.dev_slope.y = -face.dev_slope.y;
  923.         face.dev_vector.dx = -face.dev_vector.dx;
  924.         face.dev_vector.dy = -face.dev_vector.dy;
  925.  
  926.         t = face.cw;
  927.         face.cw = face.ccw;
  928.         face.ccw = t;
  929.  
  930.         join (stroker, &stroker->current_face, &face);
  931.     } else {
  932.         cairo_point_t rectangle[4];
  933.  
  934.         compute_face (&stroker->current_face.point, tangent, stroker, &face);
  935.  
  936.         join (stroker, &stroker->current_face, &face);
  937.  
  938.         rectangle[0] = face.cw;
  939.         rectangle[1] = face.ccw;
  940.  
  941.         rectangle[2].x = point->x - face.point.x;
  942.         rectangle[2].y = point->y - face.point.y;
  943.         face.point = *point;
  944.         translate_point (&face.ccw, &rectangle[2]);
  945.         translate_point (&face.cw, &rectangle[2]);
  946.  
  947.         rectangle[2] = face.ccw;
  948.         rectangle[3] = face.cw;
  949.  
  950.         _cairo_traps_tessellate_convex_quad (stroker->traps, rectangle);
  951.     }
  952.  
  953.     stroker->current_face = face;
  954.  
  955.     return CAIRO_STATUS_SUCCESS;
  956. }
  957.  
  958. static cairo_status_t
  959. curve_to (void *closure,
  960.           const cairo_point_t *b,
  961.           const cairo_point_t *c,
  962.           const cairo_point_t *d)
  963. {
  964.     struct stroker *stroker = closure;
  965.     cairo_line_join_t line_join_save;
  966.     cairo_spline_t spline;
  967.     cairo_stroke_face_t face;
  968.     cairo_status_t status;
  969.  
  970.     if (stroker->has_bounds &&
  971.         ! _cairo_spline_intersects (&stroker->current_face.point, b, c, d,
  972.                                     &stroker->line_bounds))
  973.         return line_to (closure, d);
  974.  
  975.     if (! _cairo_spline_init (&spline, spline_to, stroker,
  976.                               &stroker->current_face.point, b, c, d))
  977.         return line_to (closure, d);
  978.  
  979.     compute_face (&stroker->current_face.point, &spline.initial_slope,
  980.                   stroker, &face);
  981.  
  982.     if (stroker->has_current_face) {
  983.         /* Join with final face from previous segment */
  984.         join (stroker, &stroker->current_face, &face);
  985.     } else {
  986.         if (! stroker->has_first_face) {
  987.             /* Save sub path's first face in case needed for closing join */
  988.             stroker->first_face = face;
  989.             stroker->has_first_face = TRUE;
  990.         }
  991.         stroker->has_current_face = TRUE;
  992.     }
  993.     stroker->current_face = face;
  994.  
  995.     /* Temporarily modify the stroker to use round joins to guarantee
  996.      * smooth stroked curves. */
  997.     line_join_save = stroker->line_join;
  998.     stroker->line_join = CAIRO_LINE_JOIN_ROUND;
  999.  
  1000.     status = _cairo_spline_decompose (&spline, stroker->tolerance);
  1001.  
  1002.     stroker->line_join = line_join_save;
  1003.  
  1004.     return status;
  1005. }
  1006.  
  1007. static cairo_status_t
  1008. curve_to_dashed (void *closure,
  1009.                  const cairo_point_t *b,
  1010.                  const cairo_point_t *c,
  1011.                  const cairo_point_t *d)
  1012. {
  1013.     struct stroker *stroker = closure;
  1014.     cairo_spline_t spline;
  1015.     cairo_line_join_t line_join_save;
  1016.     cairo_spline_add_point_func_t func;
  1017.     cairo_status_t status;
  1018.  
  1019.     func = (cairo_spline_add_point_func_t)line_to_dashed;
  1020.  
  1021.     if (stroker->has_bounds &&
  1022.         ! _cairo_spline_intersects (&stroker->current_face.point, b, c, b,
  1023.                                     &stroker->line_bounds))
  1024.         return func (closure, d, NULL);
  1025.  
  1026.     if (! _cairo_spline_init (&spline, func, stroker,
  1027.                               &stroker->current_face.point, b, c, d))
  1028.         return func (closure, d, NULL);
  1029.  
  1030.     /* Temporarily modify the stroker to use round joins to guarantee
  1031.      * smooth stroked curves. */
  1032.     line_join_save = stroker->line_join;
  1033.     stroker->line_join = CAIRO_LINE_JOIN_ROUND;
  1034.  
  1035.     status = _cairo_spline_decompose (&spline, stroker->tolerance);
  1036.  
  1037.     stroker->line_join = line_join_save;
  1038.  
  1039.     return status;
  1040. }
  1041.  
  1042. static cairo_status_t
  1043. _close_path (struct stroker *stroker)
  1044. {
  1045.     if (stroker->has_first_face && stroker->has_current_face) {
  1046.         /* Join first and final faces of sub path */
  1047.         join (stroker, &stroker->current_face, &stroker->first_face);
  1048.     } else {
  1049.         /* Cap the start and end of the sub path as needed */
  1050.         add_caps (stroker);
  1051.     }
  1052.  
  1053.     stroker->has_initial_sub_path = FALSE;
  1054.     stroker->has_first_face = FALSE;
  1055.     stroker->has_current_face = FALSE;
  1056.     return CAIRO_STATUS_SUCCESS;
  1057. }
  1058.  
  1059. static cairo_status_t
  1060. close_path (void *closure)
  1061. {
  1062.     struct stroker *stroker = closure;
  1063.     cairo_status_t status;
  1064.  
  1065.     status = line_to (stroker, &stroker->first_point);
  1066.     if (unlikely (status))
  1067.         return status;
  1068.  
  1069.     return _close_path (stroker);
  1070. }
  1071.  
  1072. static cairo_status_t
  1073. close_path_dashed (void *closure)
  1074. {
  1075.     struct stroker *stroker = closure;
  1076.     cairo_status_t status;
  1077.  
  1078.     status = line_to_dashed (stroker, &stroker->first_point);
  1079.     if (unlikely (status))
  1080.         return status;
  1081.  
  1082.     return _close_path (stroker);
  1083. }
  1084.  
  1085. cairo_int_status_t
  1086. _cairo_path_fixed_stroke_to_traps (const cairo_path_fixed_t     *path,
  1087.                                    const cairo_stroke_style_t   *style,
  1088.                                    const cairo_matrix_t         *ctm,
  1089.                                    const cairo_matrix_t         *ctm_inverse,
  1090.                                    double                        tolerance,
  1091.                                    cairo_traps_t                *traps)
  1092. {
  1093.     struct stroker stroker;
  1094.     cairo_status_t status;
  1095.  
  1096.     status = stroker_init (&stroker, path, style,
  1097.                            ctm, ctm_inverse, tolerance,
  1098.                            traps);
  1099.     if (unlikely (status))
  1100.         return status;
  1101.  
  1102.     if (stroker.dash.dashed)
  1103.         status = _cairo_path_fixed_interpret (path,
  1104.                                               move_to_dashed,
  1105.                                               line_to_dashed,
  1106.                                               curve_to_dashed,
  1107.                                               close_path_dashed,
  1108.                                               &stroker);
  1109.     else
  1110.         status = _cairo_path_fixed_interpret (path,
  1111.                                               move_to,
  1112.                                               line_to,
  1113.                                               curve_to,
  1114.                                               close_path,
  1115.                                               &stroker);
  1116.     assert(status == CAIRO_STATUS_SUCCESS);
  1117.     add_caps (&stroker);
  1118.  
  1119.     stroker_fini (&stroker);
  1120.  
  1121.     return traps->status;
  1122. }
  1123.