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 © 2011 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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. #define _BSD_SOURCE /* for hypot() */
  41. #include "cairoint.h"
  42.  
  43. #include "cairo-box-inline.h"
  44. #include "cairo-boxes-private.h"
  45. #include "cairo-contour-inline.h"
  46. #include "cairo-contour-private.h"
  47. #include "cairo-error-private.h"
  48. #include "cairo-path-fixed-private.h"
  49. #include "cairo-slope-private.h"
  50.  
  51. #define DEBUG 0
  52.  
  53. struct stroker {
  54.     cairo_stroke_style_t style;
  55.  
  56. #if DEBUG
  57.     cairo_contour_t path;
  58. #endif
  59.  
  60.     struct stroke_contour {
  61.         /* Note that these are not strictly contours as they may intersect */
  62.         cairo_contour_t contour;
  63.     } cw, ccw;
  64.     cairo_uint64_t contour_tolerance;
  65.     cairo_polygon_t *polygon;
  66.  
  67.     const cairo_matrix_t *ctm;
  68.     const cairo_matrix_t *ctm_inverse;
  69.     double tolerance;
  70.     double spline_cusp_tolerance;
  71.     double half_line_width;
  72.     cairo_bool_t ctm_det_positive;
  73.  
  74.     cairo_pen_t pen;
  75.  
  76.     cairo_point_t first_point;
  77.  
  78.     cairo_bool_t has_initial_sub_path;
  79.  
  80.     cairo_bool_t has_current_face;
  81.     cairo_stroke_face_t current_face;
  82.  
  83.     cairo_bool_t has_first_face;
  84.     cairo_stroke_face_t first_face;
  85.  
  86.     cairo_bool_t has_bounds;
  87.     cairo_box_t bounds;
  88. };
  89.  
  90. static inline double
  91. normalize_slope (double *dx, double *dy);
  92.  
  93. static void
  94. compute_face (const cairo_point_t *point,
  95.               const cairo_slope_t *dev_slope,
  96.               struct stroker *stroker,
  97.               cairo_stroke_face_t *face);
  98.  
  99. static cairo_uint64_t
  100. point_distance_sq (const cairo_point_t *p1,
  101.                         const cairo_point_t *p2)
  102. {
  103.     int32_t dx = p1->x - p2->x;
  104.     int32_t dy = p1->y - p2->y;
  105.     return _cairo_int32x32_64_mul (dx, dx) + _cairo_int32x32_64_mul (dy, dy);
  106. }
  107.  
  108. static cairo_bool_t
  109. within_tolerance (const cairo_point_t *p1,
  110.               const cairo_point_t *p2,
  111.               cairo_uint64_t tolerance)
  112. {
  113.     return FALSE;
  114.     return _cairo_int64_lt (point_distance_sq (p1, p2), tolerance);
  115. }
  116.  
  117. static void
  118. contour_add_point (struct stroker *stroker,
  119.                    struct stroke_contour *c,
  120.                    const cairo_point_t *point)
  121. {
  122.     if (! within_tolerance (point, _cairo_contour_last_point (&c->contour),
  123.                         stroker->contour_tolerance))
  124.         _cairo_contour_add_point (&c->contour, point);
  125.     //*_cairo_contour_last_point (&c->contour) = *point;
  126. }
  127.  
  128. static void
  129. translate_point (cairo_point_t *point, const cairo_point_t *offset)
  130. {
  131.     point->x += offset->x;
  132.     point->y += offset->y;
  133. }
  134.  
  135. static int
  136. slope_compare_sgn (double dx1, double dy1, double dx2, double dy2)
  137. {
  138.     double  c = (dx1 * dy2 - dx2 * dy1);
  139.  
  140.     if (c > 0) return 1;
  141.     if (c < 0) return -1;
  142.     return 0;
  143. }
  144.  
  145. static inline int
  146. range_step (int i, int step, int max)
  147. {
  148.     i += step;
  149.     if (i < 0)
  150.         i = max - 1;
  151.     if (i >= max)
  152.         i = 0;
  153.     return i;
  154. }
  155.  
  156. /*
  157.  * Construct a fan around the midpoint using the vertices from pen between
  158.  * inpt and outpt.
  159.  */
  160. static void
  161. add_fan (struct stroker *stroker,
  162.          const cairo_slope_t *in_vector,
  163.          const cairo_slope_t *out_vector,
  164.          const cairo_point_t *midpt,
  165.          cairo_bool_t clockwise,
  166.          struct stroke_contour *c)
  167. {
  168.     cairo_pen_t *pen = &stroker->pen;
  169.     int start, stop;
  170.  
  171.     if (stroker->has_bounds &&
  172.         ! _cairo_box_contains_point (&stroker->bounds, midpt))
  173.         return;
  174.  
  175.     assert (stroker->pen.num_vertices);
  176.  
  177.     if (clockwise) {
  178.         _cairo_pen_find_active_cw_vertices (pen,
  179.                                             in_vector, out_vector,
  180.                                             &start, &stop);
  181.         while (start != stop) {
  182.             cairo_point_t p = *midpt;
  183.             translate_point (&p, &pen->vertices[start].point);
  184.             contour_add_point (stroker, c, &p);
  185.  
  186.             if (++start == pen->num_vertices)
  187.                 start = 0;
  188.         }
  189.     } else {
  190.         _cairo_pen_find_active_ccw_vertices (pen,
  191.                                              in_vector, out_vector,
  192.                                              &start, &stop);
  193.         while (start != stop) {
  194.             cairo_point_t p = *midpt;
  195.             translate_point (&p, &pen->vertices[start].point);
  196.             contour_add_point (stroker, c, &p);
  197.  
  198.             if (start-- == 0)
  199.                 start += pen->num_vertices;
  200.         }
  201.     }
  202. }
  203.  
  204. static int
  205. join_is_clockwise (const cairo_stroke_face_t *in,
  206.                    const cairo_stroke_face_t *out)
  207. {
  208.     return _cairo_slope_compare (&in->dev_vector, &out->dev_vector) < 0;
  209. }
  210.  
  211. static void
  212. inner_join (struct stroker *stroker,
  213.             const cairo_stroke_face_t *in,
  214.             const cairo_stroke_face_t *out,
  215.             int clockwise)
  216. {
  217. #if 0
  218.     cairo_point_t last;
  219.     const cairo_point_t *p, *outpt;
  220.     struct stroke_contour *inner;
  221.     cairo_int64_t d_p, d_last;
  222.     cairo_int64_t half_line_width;
  223.     cairo_bool_t negate;
  224.  
  225.     /* XXX line segments shorter than line-width */
  226.  
  227.     if (clockwise) {
  228.         inner = &stroker->ccw;
  229.         outpt = &out->ccw;
  230.         negate = 1;
  231.     } else {
  232.         inner = &stroker->cw;
  233.         outpt = &out->cw;
  234.         negate = 0;
  235.     }
  236.  
  237.     half_line_width = CAIRO_FIXED_ONE*CAIRO_FIXED_ONE/2 * stroker->style.line_width * out->length + .5;
  238.  
  239.     /* On the inside, the previous end-point is always
  240.      * closer to the new face by definition.
  241.      */
  242.     last = *_cairo_contour_last_point (&inner->contour);
  243.     d_last = distance_from_face (out, &last, negate);
  244.     _cairo_contour_remove_last_point (&inner->contour);
  245.  
  246. prev:
  247.     if (inner->contour.chain.num_points == 0) {
  248.         contour_add_point (stroker, inner, outpt);
  249.         return;
  250.     }
  251.     p = _cairo_contour_last_point (&inner->contour);
  252.     d_p = distance_from_face (out, p, negate);
  253.     if (_cairo_int64_lt (d_p, half_line_width) &&
  254.         !_cairo_int64_negative (distance_along_face (out, p)))
  255.     {
  256.         last = *p;
  257.         d_last = d_p;
  258.         _cairo_contour_remove_last_point (&inner->contour);
  259.         goto prev;
  260.     }
  261.  
  262.     compute_inner_joint (&last, d_last, p, d_p, half_line_width);
  263.     contour_add_point (stroker, inner, &last);
  264. #else
  265.     const cairo_point_t *outpt;
  266.     struct stroke_contour *inner;
  267.  
  268.     if (clockwise) {
  269.         inner = &stroker->ccw;
  270.         outpt = &out->ccw;
  271.     } else {
  272.         inner = &stroker->cw;
  273.         outpt = &out->cw;
  274.     }
  275.     contour_add_point (stroker, inner, &in->point);
  276.     contour_add_point (stroker, inner, outpt);
  277. #endif
  278. }
  279.  
  280. static void
  281. inner_close (struct stroker *stroker,
  282.              const cairo_stroke_face_t *in,
  283.              cairo_stroke_face_t *out)
  284. {
  285. #if 0
  286.     cairo_point_t last;
  287.     const cairo_point_t *p, *outpt, *inpt;
  288.     struct stroke_contour *inner;
  289.     struct _cairo_contour_chain *chain;
  290.  
  291.     /* XXX line segments shorter than line-width */
  292.  
  293.     if (join_is_clockwise (in, out)) {
  294.         inner = &stroker->ccw;
  295.         outpt = &in->ccw;
  296.         inpt = &out->ccw;
  297.     } else {
  298.         inner = &stroker->cw;
  299.         outpt = &in->cw;
  300.         inpt = &out->cw;
  301.     }
  302.  
  303.     if (inner->contour.chain.num_points == 0) {
  304.         contour_add_point (stroker, inner, &in->point);
  305.         contour_add_point (stroker, inner, inpt);
  306.         *_cairo_contour_first_point (&inner->contour) =
  307.             *_cairo_contour_last_point (&inner->contour);
  308.         return;
  309.     }
  310.  
  311.     line_width = stroker->style.line_width/2;
  312.     line_width *= CAIRO_FIXED_ONE;
  313.  
  314.     d_last = sign * distance_from_face (out, outpt);
  315.     last = *outpt;
  316.  
  317.     for (chain = &inner->contour.chain; chain; chain = chain->next) {
  318.         for (i = 0; i < chain->num_points; i++) {
  319.             p = &chain->points[i];
  320.             if ((d_p = sign * distance_from_face (in, p)) >= line_width &&
  321.                 distance_from_edge (stroker, inpt, &last, p) < line_width)
  322.             {
  323.                 goto out;
  324.             }
  325.  
  326.             if (p->x != last.x || p->y != last.y) {
  327.                 last = *p;
  328.                 d_last = d_p;
  329.             }
  330.         }
  331.     }
  332. out:
  333.  
  334.     if (d_p != d_last) {
  335.         double dot = (line_width - d_last) / (d_p - d_last);
  336.         last.x += dot * (p->x - last.x);
  337.         last.y += dot * (p->y - last.y);
  338.     }
  339.     *_cairo_contour_last_point (&inner->contour) = last;
  340.  
  341.     for (chain = &inner->contour.chain; chain; chain = chain->next) {
  342.         for (i = 0; i < chain->num_points; i++) {
  343.             cairo_point_t *pp = &chain->points[i];
  344.             if (pp == p)
  345.                 return;
  346.             *pp = last;
  347.         }
  348.     }
  349. #else
  350.     const cairo_point_t *inpt;
  351.     struct stroke_contour *inner;
  352.  
  353.     if (join_is_clockwise (in, out)) {
  354.         inner = &stroker->ccw;
  355.         inpt = &out->ccw;
  356.     } else {
  357.         inner = &stroker->cw;
  358.         inpt = &out->cw;
  359.     }
  360.  
  361.     contour_add_point (stroker, inner, &in->point);
  362.     contour_add_point (stroker, inner, inpt);
  363.     *_cairo_contour_first_point (&inner->contour) =
  364.         *_cairo_contour_last_point (&inner->contour);
  365. #endif
  366. }
  367.  
  368. static void
  369. outer_close (struct stroker *stroker,
  370.              const cairo_stroke_face_t *in,
  371.              const cairo_stroke_face_t *out)
  372. {
  373.     const cairo_point_t *inpt, *outpt;
  374.     struct stroke_contour *outer;
  375.     int clockwise;
  376.  
  377.     if (in->cw.x == out->cw.x && in->cw.y == out->cw.y &&
  378.         in->ccw.x == out->ccw.x && in->ccw.y == out->ccw.y)
  379.     {
  380.         return;
  381.     }
  382.  
  383.     clockwise = join_is_clockwise (in, out);
  384.     if (clockwise) {
  385.         inpt = &in->cw;
  386.         outpt = &out->cw;
  387.         outer = &stroker->cw;
  388.     } else {
  389.         inpt = &in->ccw;
  390.         outpt = &out->ccw;
  391.         outer = &stroker->ccw;
  392.     }
  393.  
  394.     if (within_tolerance (inpt, outpt, stroker->contour_tolerance)) {
  395.         *_cairo_contour_first_point (&outer->contour) =
  396.             *_cairo_contour_last_point (&outer->contour);
  397.         return;
  398.     }
  399.  
  400.     switch (stroker->style.line_join) {
  401.     case CAIRO_LINE_JOIN_ROUND:
  402.         /* construct a fan around the common midpoint */
  403.         if ((in->dev_slope.x * out->dev_slope.x +
  404.              in->dev_slope.y * out->dev_slope.y) < stroker->spline_cusp_tolerance)
  405.         {
  406.             add_fan (stroker,
  407.                      &in->dev_vector, &out->dev_vector, &in->point,
  408.                      clockwise, outer);
  409.             break;
  410.         }
  411.  
  412.     case CAIRO_LINE_JOIN_MITER:
  413.     default: {
  414.         /* dot product of incoming slope vector with outgoing slope vector */
  415.         double  in_dot_out = in->dev_slope.x * out->dev_slope.x +
  416.                              in->dev_slope.y * out->dev_slope.y;
  417.         double  ml = stroker->style.miter_limit;
  418.  
  419.         /* Check the miter limit -- lines meeting at an acute angle
  420.          * can generate long miters, the limit converts them to bevel
  421.          *
  422.          * Consider the miter join formed when two line segments
  423.          * meet at an angle psi:
  424.          *
  425.          *         /.\
  426.          *        /. .\
  427.          *       /./ \.\
  428.          *      /./psi\.\
  429.          *
  430.          * We can zoom in on the right half of that to see:
  431.          *
  432.          *          |\
  433.          *          | \ psi/2
  434.          *          |  \
  435.          *          |   \
  436.          *          |    \
  437.          *          |     \
  438.          *        miter    \
  439.          *       length     \
  440.          *          |        \
  441.          *          |        .\
  442.          *          |    .     \
  443.          *          |.   line   \
  444.          *           \    width  \
  445.          *            \           \
  446.          *
  447.          *
  448.          * The right triangle in that figure, (the line-width side is
  449.          * shown faintly with three '.' characters), gives us the
  450.          * following expression relating miter length, angle and line
  451.          * width:
  452.          *
  453.          *      1 /sin (psi/2) = miter_length / line_width
  454.          *
  455.          * The right-hand side of this relationship is the same ratio
  456.          * in which the miter limit (ml) is expressed. We want to know
  457.          * when the miter length is within the miter limit. That is
  458.          * when the following condition holds:
  459.          *
  460.          *      1/sin(psi/2) <= ml
  461.          *      1 <= ml sin(psi/2)
  462.          *      1 <= ml² sin²(psi/2)
  463.          *      2 <= ml² 2 sin²(psi/2)
  464.          *                              2·sin²(psi/2) = 1-cos(psi)
  465.          *      2 <= ml² (1-cos(psi))
  466.          *
  467.          *                              in · out = |in| |out| cos (psi)
  468.          *
  469.          * in and out are both unit vectors, so:
  470.          *
  471.          *                              in · out = cos (psi)
  472.          *
  473.          *      2 <= ml² (1 - in · out)
  474.          *
  475.          */
  476.         if (2 <= ml * ml * (1 + in_dot_out)) {
  477.             double              x1, y1, x2, y2;
  478.             double              mx, my;
  479.             double              dx1, dx2, dy1, dy2;
  480.             double              ix, iy;
  481.             double              fdx1, fdy1, fdx2, fdy2;
  482.             double              mdx, mdy;
  483.  
  484.             /*
  485.              * we've got the points already transformed to device
  486.              * space, but need to do some computation with them and
  487.              * also need to transform the slope from user space to
  488.              * device space
  489.              */
  490.             /* outer point of incoming line face */
  491.             x1 = _cairo_fixed_to_double (inpt->x);
  492.             y1 = _cairo_fixed_to_double (inpt->y);
  493.             dx1 = in->dev_slope.x;
  494.             dy1 = in->dev_slope.y;
  495.  
  496.             /* outer point of outgoing line face */
  497.             x2 = _cairo_fixed_to_double (outpt->x);
  498.             y2 = _cairo_fixed_to_double (outpt->y);
  499.             dx2 = out->dev_slope.x;
  500.             dy2 = out->dev_slope.y;
  501.  
  502.             /*
  503.              * Compute the location of the outer corner of the miter.
  504.              * That's pretty easy -- just the intersection of the two
  505.              * outer edges.  We've got slopes and points on each
  506.              * of those edges.  Compute my directly, then compute
  507.              * mx by using the edge with the larger dy; that avoids
  508.              * dividing by values close to zero.
  509.              */
  510.             my = (((x2 - x1) * dy1 * dy2 - y2 * dx2 * dy1 + y1 * dx1 * dy2) /
  511.                   (dx1 * dy2 - dx2 * dy1));
  512.             if (fabs (dy1) >= fabs (dy2))
  513.                 mx = (my - y1) * dx1 / dy1 + x1;
  514.             else
  515.                 mx = (my - y2) * dx2 / dy2 + x2;
  516.  
  517.             /*
  518.              * When the two outer edges are nearly parallel, slight
  519.              * perturbations in the position of the outer points of the lines
  520.              * caused by representing them in fixed point form can cause the
  521.              * intersection point of the miter to move a large amount. If
  522.              * that moves the miter intersection from between the two faces,
  523.              * then draw a bevel instead.
  524.              */
  525.  
  526.             ix = _cairo_fixed_to_double (in->point.x);
  527.             iy = _cairo_fixed_to_double (in->point.y);
  528.  
  529.             /* slope of one face */
  530.             fdx1 = x1 - ix; fdy1 = y1 - iy;
  531.  
  532.             /* slope of the other face */
  533.             fdx2 = x2 - ix; fdy2 = y2 - iy;
  534.  
  535.             /* slope from the intersection to the miter point */
  536.             mdx = mx - ix; mdy = my - iy;
  537.  
  538.             /*
  539.              * Make sure the miter point line lies between the two
  540.              * faces by comparing the slopes
  541.              */
  542.             if (slope_compare_sgn (fdx1, fdy1, mdx, mdy) !=
  543.                 slope_compare_sgn (fdx2, fdy2, mdx, mdy))
  544.             {
  545.                 cairo_point_t p;
  546.  
  547.                 p.x = _cairo_fixed_from_double (mx);
  548.                 p.y = _cairo_fixed_from_double (my);
  549.  
  550.                 *_cairo_contour_last_point (&outer->contour) = p;
  551.                 *_cairo_contour_first_point (&outer->contour) = p;
  552.                 return;
  553.             }
  554.         }
  555.         break;
  556.     }
  557.  
  558.     case CAIRO_LINE_JOIN_BEVEL:
  559.         break;
  560.     }
  561.     contour_add_point (stroker, outer, outpt);
  562. }
  563.  
  564. static void
  565. outer_join (struct stroker *stroker,
  566.             const cairo_stroke_face_t *in,
  567.             const cairo_stroke_face_t *out,
  568.             int clockwise)
  569. {
  570.     const cairo_point_t *inpt, *outpt;
  571.     struct stroke_contour *outer;
  572.  
  573.     if (in->cw.x == out->cw.x && in->cw.y == out->cw.y &&
  574.         in->ccw.x == out->ccw.x && in->ccw.y == out->ccw.y)
  575.     {
  576.         return;
  577.     }
  578.     if (clockwise) {
  579.         inpt = &in->cw;
  580.         outpt = &out->cw;
  581.         outer = &stroker->cw;
  582.     } else {
  583.         inpt = &in->ccw;
  584.         outpt = &out->ccw;
  585.         outer = &stroker->ccw;
  586.     }
  587.  
  588.     switch (stroker->style.line_join) {
  589.     case CAIRO_LINE_JOIN_ROUND:
  590.         /* construct a fan around the common midpoint */
  591.         add_fan (stroker,
  592.                  &in->dev_vector, &out->dev_vector, &in->point,
  593.                  clockwise, outer);
  594.         break;
  595.  
  596.     case CAIRO_LINE_JOIN_MITER:
  597.     default: {
  598.         /* dot product of incoming slope vector with outgoing slope vector */
  599.         double  in_dot_out = in->dev_slope.x * out->dev_slope.x +
  600.                              in->dev_slope.y * out->dev_slope.y;
  601.         double  ml = stroker->style.miter_limit;
  602.  
  603.         /* Check the miter limit -- lines meeting at an acute angle
  604.          * can generate long miters, the limit converts them to bevel
  605.          *
  606.          * Consider the miter join formed when two line segments
  607.          * meet at an angle psi:
  608.          *
  609.          *         /.\
  610.          *        /. .\
  611.          *       /./ \.\
  612.          *      /./psi\.\
  613.          *
  614.          * We can zoom in on the right half of that to see:
  615.          *
  616.          *          |\
  617.          *          | \ psi/2
  618.          *          |  \
  619.          *          |   \
  620.          *          |    \
  621.          *          |     \
  622.          *        miter    \
  623.          *       length     \
  624.          *          |        \
  625.          *          |        .\
  626.          *          |    .     \
  627.          *          |.   line   \
  628.          *           \    width  \
  629.          *            \           \
  630.          *
  631.          *
  632.          * The right triangle in that figure, (the line-width side is
  633.          * shown faintly with three '.' characters), gives us the
  634.          * following expression relating miter length, angle and line
  635.          * width:
  636.          *
  637.          *      1 /sin (psi/2) = miter_length / line_width
  638.          *
  639.          * The right-hand side of this relationship is the same ratio
  640.          * in which the miter limit (ml) is expressed. We want to know
  641.          * when the miter length is within the miter limit. That is
  642.          * when the following condition holds:
  643.          *
  644.          *      1/sin(psi/2) <= ml
  645.          *      1 <= ml sin(psi/2)
  646.          *      1 <= ml² sin²(psi/2)
  647.          *      2 <= ml² 2 sin²(psi/2)
  648.          *                              2·sin²(psi/2) = 1-cos(psi)
  649.          *      2 <= ml² (1-cos(psi))
  650.          *
  651.          *                              in · out = |in| |out| cos (psi)
  652.          *
  653.          * in and out are both unit vectors, so:
  654.          *
  655.          *                              in · out = cos (psi)
  656.          *
  657.          *      2 <= ml² (1 - in · out)
  658.          *
  659.          */
  660.         if (2 <= ml * ml * (1 + in_dot_out)) {
  661.             double              x1, y1, x2, y2;
  662.             double              mx, my;
  663.             double              dx1, dx2, dy1, dy2;
  664.             double              ix, iy;
  665.             double              fdx1, fdy1, fdx2, fdy2;
  666.             double              mdx, mdy;
  667.  
  668.             /*
  669.              * we've got the points already transformed to device
  670.              * space, but need to do some computation with them and
  671.              * also need to transform the slope from user space to
  672.              * device space
  673.              */
  674.             /* outer point of incoming line face */
  675.             x1 = _cairo_fixed_to_double (inpt->x);
  676.             y1 = _cairo_fixed_to_double (inpt->y);
  677.             dx1 = in->dev_slope.x;
  678.             dy1 = in->dev_slope.y;
  679.  
  680.             /* outer point of outgoing line face */
  681.             x2 = _cairo_fixed_to_double (outpt->x);
  682.             y2 = _cairo_fixed_to_double (outpt->y);
  683.             dx2 = out->dev_slope.x;
  684.             dy2 = out->dev_slope.y;
  685.  
  686.             /*
  687.              * Compute the location of the outer corner of the miter.
  688.              * That's pretty easy -- just the intersection of the two
  689.              * outer edges.  We've got slopes and points on each
  690.              * of those edges.  Compute my directly, then compute
  691.              * mx by using the edge with the larger dy; that avoids
  692.              * dividing by values close to zero.
  693.              */
  694.             my = (((x2 - x1) * dy1 * dy2 - y2 * dx2 * dy1 + y1 * dx1 * dy2) /
  695.                   (dx1 * dy2 - dx2 * dy1));
  696.             if (fabs (dy1) >= fabs (dy2))
  697.                 mx = (my - y1) * dx1 / dy1 + x1;
  698.             else
  699.                 mx = (my - y2) * dx2 / dy2 + x2;
  700.  
  701.             /*
  702.              * When the two outer edges are nearly parallel, slight
  703.              * perturbations in the position of the outer points of the lines
  704.              * caused by representing them in fixed point form can cause the
  705.              * intersection point of the miter to move a large amount. If
  706.              * that moves the miter intersection from between the two faces,
  707.              * then draw a bevel instead.
  708.              */
  709.  
  710.             ix = _cairo_fixed_to_double (in->point.x);
  711.             iy = _cairo_fixed_to_double (in->point.y);
  712.  
  713.             /* slope of one face */
  714.             fdx1 = x1 - ix; fdy1 = y1 - iy;
  715.  
  716.             /* slope of the other face */
  717.             fdx2 = x2 - ix; fdy2 = y2 - iy;
  718.  
  719.             /* slope from the intersection to the miter point */
  720.             mdx = mx - ix; mdy = my - iy;
  721.  
  722.             /*
  723.              * Make sure the miter point line lies between the two
  724.              * faces by comparing the slopes
  725.              */
  726.             if (slope_compare_sgn (fdx1, fdy1, mdx, mdy) !=
  727.                 slope_compare_sgn (fdx2, fdy2, mdx, mdy))
  728.             {
  729.                 cairo_point_t p;
  730.  
  731.                 p.x = _cairo_fixed_from_double (mx);
  732.                 p.y = _cairo_fixed_from_double (my);
  733.  
  734.                 *_cairo_contour_last_point (&outer->contour) = p;
  735.                 return;
  736.             }
  737.         }
  738.         break;
  739.     }
  740.  
  741.     case CAIRO_LINE_JOIN_BEVEL:
  742.         break;
  743.     }
  744.     contour_add_point (stroker,outer, outpt);
  745. }
  746.  
  747. static void
  748. add_cap (struct stroker *stroker,
  749.          const cairo_stroke_face_t *f,
  750.          struct stroke_contour *c)
  751. {
  752.     switch (stroker->style.line_cap) {
  753.     case CAIRO_LINE_CAP_ROUND: {
  754.         cairo_slope_t slope;
  755.  
  756.         slope.dx = -f->dev_vector.dx;
  757.         slope.dy = -f->dev_vector.dy;
  758.  
  759.         add_fan (stroker, &f->dev_vector, &slope, &f->point, FALSE, c);
  760.         break;
  761.     }
  762.  
  763.     case CAIRO_LINE_CAP_SQUARE: {
  764.         cairo_slope_t fvector;
  765.         cairo_point_t p;
  766.         double dx, dy;
  767.  
  768.         dx = f->usr_vector.x;
  769.         dy = f->usr_vector.y;
  770.         dx *= stroker->half_line_width;
  771.         dy *= stroker->half_line_width;
  772.         cairo_matrix_transform_distance (stroker->ctm, &dx, &dy);
  773.         fvector.dx = _cairo_fixed_from_double (dx);
  774.         fvector.dy = _cairo_fixed_from_double (dy);
  775.  
  776.         p.x = f->ccw.x + fvector.dx;
  777.         p.y = f->ccw.y + fvector.dy;
  778.         contour_add_point (stroker, c, &p);
  779.  
  780.         p.x = f->cw.x + fvector.dx;
  781.         p.y = f->cw.y + fvector.dy;
  782.         contour_add_point (stroker, c, &p);
  783.     }
  784.  
  785.     case CAIRO_LINE_CAP_BUTT:
  786.     default:
  787.         break;
  788.     }
  789.     contour_add_point (stroker, c, &f->cw);
  790. }
  791.  
  792. static void
  793. add_leading_cap (struct stroker *stroker,
  794.                  const cairo_stroke_face_t *face,
  795.                  struct stroke_contour *c)
  796. {
  797.     cairo_stroke_face_t reversed;
  798.     cairo_point_t t;
  799.  
  800.     reversed = *face;
  801.  
  802.     /* The initial cap needs an outward facing vector. Reverse everything */
  803.     reversed.usr_vector.x = -reversed.usr_vector.x;
  804.     reversed.usr_vector.y = -reversed.usr_vector.y;
  805.     reversed.dev_vector.dx = -reversed.dev_vector.dx;
  806.     reversed.dev_vector.dy = -reversed.dev_vector.dy;
  807.  
  808.     t = reversed.cw;
  809.     reversed.cw = reversed.ccw;
  810.     reversed.ccw = t;
  811.  
  812.     add_cap (stroker, &reversed, c);
  813. }
  814.  
  815. static void
  816. add_trailing_cap (struct stroker *stroker,
  817.                   const cairo_stroke_face_t *face,
  818.                   struct stroke_contour *c)
  819. {
  820.     add_cap (stroker, face, c);
  821. }
  822.  
  823. static inline double
  824. normalize_slope (double *dx, double *dy)
  825. {
  826.     double dx0 = *dx, dy0 = *dy;
  827.     double mag;
  828.  
  829.     assert (dx0 != 0.0 || dy0 != 0.0);
  830.  
  831.     if (dx0 == 0.0) {
  832.         *dx = 0.0;
  833.         if (dy0 > 0.0) {
  834.             mag = dy0;
  835.             *dy = 1.0;
  836.         } else {
  837.             mag = -dy0;
  838.             *dy = -1.0;
  839.         }
  840.     } else if (dy0 == 0.0) {
  841.         *dy = 0.0;
  842.         if (dx0 > 0.0) {
  843.             mag = dx0;
  844.             *dx = 1.0;
  845.         } else {
  846.             mag = -dx0;
  847.             *dx = -1.0;
  848.         }
  849.     } else {
  850.         mag = hypot (dx0, dy0);
  851.         *dx = dx0 / mag;
  852.         *dy = dy0 / mag;
  853.     }
  854.  
  855.     return mag;
  856. }
  857.  
  858. static void
  859. compute_face (const cairo_point_t *point,
  860.               const cairo_slope_t *dev_slope,
  861.               struct stroker *stroker,
  862.               cairo_stroke_face_t *face)
  863. {
  864.     double face_dx, face_dy;
  865.     cairo_point_t offset_ccw, offset_cw;
  866.     double slope_dx, slope_dy;
  867.  
  868.     slope_dx = _cairo_fixed_to_double (dev_slope->dx);
  869.     slope_dy = _cairo_fixed_to_double (dev_slope->dy);
  870.     face->length = normalize_slope (&slope_dx, &slope_dy);
  871.     face->dev_slope.x = slope_dx;
  872.     face->dev_slope.y = slope_dy;
  873.  
  874.     /*
  875.      * rotate to get a line_width/2 vector along the face, note that
  876.      * the vector must be rotated the right direction in device space,
  877.      * but by 90° in user space. So, the rotation depends on
  878.      * whether the ctm reflects or not, and that can be determined
  879.      * by looking at the determinant of the matrix.
  880.      */
  881.     if (! _cairo_matrix_is_identity (stroker->ctm_inverse)) {
  882.         /* Normalize the matrix! */
  883.         cairo_matrix_transform_distance (stroker->ctm_inverse,
  884.                                          &slope_dx, &slope_dy);
  885.         normalize_slope (&slope_dx, &slope_dy);
  886.  
  887.         if (stroker->ctm_det_positive) {
  888.             face_dx = - slope_dy * stroker->half_line_width;
  889.             face_dy = slope_dx * stroker->half_line_width;
  890.         } else {
  891.             face_dx = slope_dy * stroker->half_line_width;
  892.             face_dy = - slope_dx * stroker->half_line_width;
  893.         }
  894.  
  895.         /* back to device space */
  896.         cairo_matrix_transform_distance (stroker->ctm, &face_dx, &face_dy);
  897.     } else {
  898.         face_dx = - slope_dy * stroker->half_line_width;
  899.         face_dy = slope_dx * stroker->half_line_width;
  900.     }
  901.  
  902.     offset_ccw.x = _cairo_fixed_from_double (face_dx);
  903.     offset_ccw.y = _cairo_fixed_from_double (face_dy);
  904.     offset_cw.x = -offset_ccw.x;
  905.     offset_cw.y = -offset_ccw.y;
  906.  
  907.     face->ccw = *point;
  908.     translate_point (&face->ccw, &offset_ccw);
  909.  
  910.     face->point = *point;
  911.  
  912.     face->cw = *point;
  913.     translate_point (&face->cw, &offset_cw);
  914.  
  915.     face->usr_vector.x = slope_dx;
  916.     face->usr_vector.y = slope_dy;
  917.  
  918.     face->dev_vector = *dev_slope;
  919. }
  920.  
  921. static void
  922. add_caps (struct stroker *stroker)
  923. {
  924.     /* check for a degenerative sub_path */
  925.     if (stroker->has_initial_sub_path &&
  926.         ! stroker->has_first_face &&
  927.         ! stroker->has_current_face &&
  928.         stroker->style.line_cap == CAIRO_LINE_CAP_ROUND)
  929.     {
  930.         /* pick an arbitrary slope to use */
  931.         cairo_slope_t slope = { CAIRO_FIXED_ONE, 0 };
  932.         cairo_stroke_face_t face;
  933.  
  934.         /* arbitrarily choose first_point */
  935.         compute_face (&stroker->first_point, &slope, stroker, &face);
  936.  
  937.         add_leading_cap (stroker, &face, &stroker->ccw);
  938.         add_trailing_cap (stroker, &face, &stroker->ccw);
  939.  
  940.         /* ensure the circle is complete */
  941.         _cairo_contour_add_point (&stroker->ccw.contour,
  942.                                   _cairo_contour_first_point (&stroker->ccw.contour));
  943.  
  944.         _cairo_polygon_add_contour (stroker->polygon, &stroker->ccw.contour);
  945.         _cairo_contour_reset (&stroker->ccw.contour);
  946.     } else {
  947.         if (stroker->has_current_face)
  948.             add_trailing_cap (stroker, &stroker->current_face, &stroker->ccw);
  949.  
  950. #if DEBUG
  951.         {
  952.             FILE *file = fopen ("contours.txt", "a");
  953.             _cairo_debug_print_contour (file, &stroker->path);
  954.             _cairo_debug_print_contour (file, &stroker->cw.contour);
  955.             _cairo_debug_print_contour (file, &stroker->ccw.contour);
  956.             fclose (file);
  957.             _cairo_contour_reset (&stroker->path);
  958.         }
  959. #endif
  960.  
  961.         _cairo_polygon_add_contour (stroker->polygon, &stroker->ccw.contour);
  962.         _cairo_contour_reset (&stroker->ccw.contour);
  963.  
  964.         if (stroker->has_first_face) {
  965.             _cairo_contour_add_point (&stroker->ccw.contour,
  966.                                       &stroker->first_face.cw);
  967.             add_leading_cap (stroker, &stroker->first_face, &stroker->ccw);
  968. #if DEBUG
  969.             {
  970.                 FILE *file = fopen ("contours.txt", "a");
  971.                 _cairo_debug_print_contour (file, &stroker->ccw.contour);
  972.                 fclose (file);
  973.             }
  974. #endif
  975.  
  976.             _cairo_polygon_add_contour (stroker->polygon,
  977.                                         &stroker->ccw.contour);
  978.             _cairo_contour_reset (&stroker->ccw.contour);
  979.         }
  980.  
  981.         _cairo_polygon_add_contour (stroker->polygon, &stroker->cw.contour);
  982.         _cairo_contour_reset (&stroker->cw.contour);
  983.     }
  984. }
  985.  
  986. static cairo_status_t
  987. close_path (void *closure);
  988.  
  989. static cairo_status_t
  990. move_to (void *closure,
  991.          const cairo_point_t *point)
  992. {
  993.     struct stroker *stroker = closure;
  994.  
  995.     /* Cap the start and end of the previous sub path as needed */
  996.     add_caps (stroker);
  997.  
  998.     stroker->has_first_face = FALSE;
  999.     stroker->has_current_face = FALSE;
  1000.     stroker->has_initial_sub_path = FALSE;
  1001.  
  1002.     stroker->first_point = *point;
  1003.  
  1004. #if DEBUG
  1005.     _cairo_contour_add_point (&stroker->path, point);
  1006. #endif
  1007.  
  1008.     stroker->current_face.point = *point;
  1009.  
  1010.     return CAIRO_STATUS_SUCCESS;
  1011. }
  1012.  
  1013. static cairo_status_t
  1014. line_to (void *closure,
  1015.          const cairo_point_t *point)
  1016. {
  1017.     struct stroker *stroker = closure;
  1018.     cairo_stroke_face_t start;
  1019.     cairo_point_t *p1 = &stroker->current_face.point;
  1020.     cairo_slope_t dev_slope;
  1021.  
  1022.     stroker->has_initial_sub_path = TRUE;
  1023.  
  1024.     if (p1->x == point->x && p1->y == point->y)
  1025.         return CAIRO_STATUS_SUCCESS;
  1026.  
  1027. #if DEBUG
  1028.     _cairo_contour_add_point (&stroker->path, point);
  1029. #endif
  1030.  
  1031.     _cairo_slope_init (&dev_slope, p1, point);
  1032.     compute_face (p1, &dev_slope, stroker, &start);
  1033.  
  1034.     if (stroker->has_current_face) {
  1035.         int clockwise = _cairo_slope_compare (&stroker->current_face.dev_vector,
  1036.                                               &start.dev_vector);
  1037.         if (clockwise) {
  1038.             clockwise = clockwise < 0;
  1039.             /* Join with final face from previous segment */
  1040.             if (! within_tolerance (&stroker->current_face.ccw, &start.ccw,
  1041.                                     stroker->contour_tolerance) ||
  1042.                 ! within_tolerance (&stroker->current_face.cw, &start.cw,
  1043.                                     stroker->contour_tolerance))
  1044.             {
  1045.                 outer_join (stroker, &stroker->current_face, &start, clockwise);
  1046.                 inner_join (stroker, &stroker->current_face, &start, clockwise);
  1047.             }
  1048.         }
  1049.     } else {
  1050.         if (! stroker->has_first_face) {
  1051.             /* Save sub path's first face in case needed for closing join */
  1052.             stroker->first_face = start;
  1053.             stroker->has_first_face = TRUE;
  1054.         }
  1055.         stroker->has_current_face = TRUE;
  1056.  
  1057.         contour_add_point (stroker, &stroker->cw, &start.cw);
  1058.         contour_add_point (stroker, &stroker->ccw, &start.ccw);
  1059.     }
  1060.  
  1061.     stroker->current_face = start;
  1062.     stroker->current_face.point = *point;
  1063.     stroker->current_face.ccw.x += dev_slope.dx;
  1064.     stroker->current_face.ccw.y += dev_slope.dy;
  1065.     stroker->current_face.cw.x += dev_slope.dx;
  1066.     stroker->current_face.cw.y += dev_slope.dy;
  1067.  
  1068.     contour_add_point (stroker, &stroker->cw, &stroker->current_face.cw);
  1069.     contour_add_point (stroker, &stroker->ccw, &stroker->current_face.ccw);
  1070.  
  1071.     return CAIRO_STATUS_SUCCESS;
  1072. }
  1073.  
  1074. static cairo_status_t
  1075. spline_to (void *closure,
  1076.            const cairo_point_t *point,
  1077.            const cairo_slope_t *tangent)
  1078. {
  1079.     struct stroker *stroker = closure;
  1080.     cairo_stroke_face_t face;
  1081.  
  1082. #if DEBUG
  1083.     _cairo_contour_add_point (&stroker->path, point);
  1084. #endif
  1085.     if ((tangent->dx | tangent->dy) == 0) {
  1086.         const cairo_point_t *inpt, *outpt;
  1087.         struct stroke_contour *outer;
  1088.         cairo_point_t t;
  1089.         int clockwise;
  1090.  
  1091.         face = stroker->current_face;
  1092.  
  1093.         face.usr_vector.x = -face.usr_vector.x;
  1094.         face.usr_vector.y = -face.usr_vector.y;
  1095.         face.dev_vector.dx = -face.dev_vector.dx;
  1096.         face.dev_vector.dy = -face.dev_vector.dy;
  1097.  
  1098.         t = face.cw;
  1099.         face.cw = face.ccw;
  1100.         face.ccw = t;
  1101.  
  1102.         clockwise = join_is_clockwise (&stroker->current_face, &face);
  1103.         if (clockwise) {
  1104.             inpt = &stroker->current_face.cw;
  1105.             outpt = &face.cw;
  1106.             outer = &stroker->cw;
  1107.         } else {
  1108.             inpt = &stroker->current_face.ccw;
  1109.             outpt = &face.ccw;
  1110.             outer = &stroker->ccw;
  1111.         }
  1112.  
  1113.         add_fan (stroker,
  1114.                  &stroker->current_face.dev_vector,
  1115.                  &face.dev_vector,
  1116.                  &stroker->current_face.point,
  1117.                  clockwise, outer);
  1118.     } else {
  1119.         compute_face (point, tangent, stroker, &face);
  1120.  
  1121.         if ((face.dev_slope.x * stroker->current_face.dev_slope.x +
  1122.              face.dev_slope.y * stroker->current_face.dev_slope.y) < stroker->spline_cusp_tolerance)
  1123.         {
  1124.             const cairo_point_t *inpt, *outpt;
  1125.             struct stroke_contour *outer;
  1126.             int clockwise = join_is_clockwise (&stroker->current_face, &face);
  1127.  
  1128.             stroker->current_face.cw.x += face.point.x - stroker->current_face.point.x;
  1129.             stroker->current_face.cw.y += face.point.y - stroker->current_face.point.y;
  1130.             contour_add_point (stroker, &stroker->cw, &stroker->current_face.cw);
  1131.  
  1132.             stroker->current_face.ccw.x += face.point.x - stroker->current_face.point.x;
  1133.             stroker->current_face.ccw.y += face.point.y - stroker->current_face.point.y;
  1134.             contour_add_point (stroker, &stroker->ccw, &stroker->current_face.ccw);
  1135.  
  1136.             if (clockwise) {
  1137.                 inpt = &stroker->current_face.cw;
  1138.                 outpt = &face.cw;
  1139.                 outer = &stroker->cw;
  1140.             } else {
  1141.                 inpt = &stroker->current_face.ccw;
  1142.                 outpt = &face.ccw;
  1143.                 outer = &stroker->ccw;
  1144.             }
  1145.             add_fan (stroker,
  1146.                      &stroker->current_face.dev_vector,
  1147.                      &face.dev_vector,
  1148.                      &stroker->current_face.point,
  1149.                      clockwise, outer);
  1150.         }
  1151.  
  1152.         contour_add_point (stroker, &stroker->cw, &face.cw);
  1153.         contour_add_point (stroker, &stroker->ccw, &face.ccw);
  1154.     }
  1155.  
  1156.     stroker->current_face = face;
  1157.  
  1158.     return CAIRO_STATUS_SUCCESS;
  1159. }
  1160.  
  1161. static cairo_status_t
  1162. curve_to (void *closure,
  1163.           const cairo_point_t *b,
  1164.           const cairo_point_t *c,
  1165.           const cairo_point_t *d)
  1166. {
  1167.     struct stroker *stroker = closure;
  1168.     cairo_spline_t spline;
  1169.     cairo_stroke_face_t face;
  1170.  
  1171.     if (stroker->has_bounds &&
  1172.         ! _cairo_spline_intersects (&stroker->current_face.point, b, c, d,
  1173.                                     &stroker->bounds))
  1174.         return line_to (closure, d);
  1175.  
  1176.     if (! _cairo_spline_init (&spline, spline_to, stroker,
  1177.                               &stroker->current_face.point, b, c, d))
  1178.         return line_to (closure, d);
  1179.  
  1180.     compute_face (&stroker->current_face.point, &spline.initial_slope,
  1181.                   stroker, &face);
  1182.  
  1183.     if (stroker->has_current_face) {
  1184.         int clockwise = join_is_clockwise (&stroker->current_face, &face);
  1185.         /* Join with final face from previous segment */
  1186.         outer_join (stroker, &stroker->current_face, &face, clockwise);
  1187.         inner_join (stroker, &stroker->current_face, &face, clockwise);
  1188.     } else {
  1189.         if (! stroker->has_first_face) {
  1190.             /* Save sub path's first face in case needed for closing join */
  1191.             stroker->first_face = face;
  1192.             stroker->has_first_face = TRUE;
  1193.         }
  1194.         stroker->has_current_face = TRUE;
  1195.  
  1196.         contour_add_point (stroker, &stroker->cw, &face.cw);
  1197.         contour_add_point (stroker, &stroker->ccw, &face.ccw);
  1198.     }
  1199.     stroker->current_face = face;
  1200.  
  1201.     return _cairo_spline_decompose (&spline, stroker->tolerance);
  1202. }
  1203.  
  1204. static cairo_status_t
  1205. close_path (void *closure)
  1206. {
  1207.     struct stroker *stroker = closure;
  1208.     cairo_status_t status;
  1209.  
  1210.     status = line_to (stroker, &stroker->first_point);
  1211.     if (unlikely (status))
  1212.         return status;
  1213.  
  1214.     if (stroker->has_first_face && stroker->has_current_face) {
  1215.         /* Join first and final faces of sub path */
  1216.         outer_close (stroker, &stroker->current_face, &stroker->first_face);
  1217.         inner_close (stroker, &stroker->current_face, &stroker->first_face);
  1218. #if 0
  1219.         *_cairo_contour_first_point (&stroker->ccw.contour) =
  1220.             *_cairo_contour_last_point (&stroker->ccw.contour);
  1221.  
  1222.         *_cairo_contour_first_point (&stroker->cw.contour) =
  1223.             *_cairo_contour_last_point (&stroker->cw.contour);
  1224. #endif
  1225.  
  1226.         _cairo_polygon_add_contour (stroker->polygon, &stroker->cw.contour);
  1227.         _cairo_polygon_add_contour (stroker->polygon, &stroker->ccw.contour);
  1228.  
  1229. #if DEBUG
  1230.         {
  1231.             FILE *file = fopen ("contours.txt", "a");
  1232.             _cairo_debug_print_contour (file, &stroker->path);
  1233.             _cairo_debug_print_contour (file, &stroker->cw.contour);
  1234.             _cairo_debug_print_contour (file, &stroker->ccw.contour);
  1235.             fclose (file);
  1236.  
  1237.             _cairo_contour_reset (&stroker->path);
  1238.         }
  1239. #endif
  1240.         _cairo_contour_reset (&stroker->cw.contour);
  1241.         _cairo_contour_reset (&stroker->ccw.contour);
  1242.     } else {
  1243.         /* Cap the start and end of the sub path as needed */
  1244.         add_caps (stroker);
  1245.     }
  1246.  
  1247.     stroker->has_initial_sub_path = FALSE;
  1248.     stroker->has_first_face = FALSE;
  1249.     stroker->has_current_face = FALSE;
  1250.  
  1251.     return CAIRO_STATUS_SUCCESS;
  1252. }
  1253.  
  1254. cairo_status_t
  1255. _cairo_path_fixed_stroke_to_polygon (const cairo_path_fixed_t   *path,
  1256.                                      const cairo_stroke_style_t *style,
  1257.                                      const cairo_matrix_t       *ctm,
  1258.                                      const cairo_matrix_t       *ctm_inverse,
  1259.                                      double              tolerance,
  1260.                                      cairo_polygon_t *polygon)
  1261. {
  1262.     struct stroker stroker;
  1263.     cairo_status_t status;
  1264.  
  1265.     if (style->num_dashes) {
  1266.         return _cairo_path_fixed_stroke_dashed_to_polygon (path,
  1267.                                                            style,
  1268.                                                            ctm,
  1269.                                                            ctm_inverse,
  1270.                                                            tolerance,
  1271.                                                            polygon);
  1272.     }
  1273.  
  1274.     stroker.has_bounds = polygon->num_limits;
  1275.     if (stroker.has_bounds) {
  1276.         /* Extend the bounds in each direction to account for the maximum area
  1277.          * we might generate trapezoids, to capture line segments that are
  1278.          * outside of the bounds but which might generate rendering that's
  1279.          * within bounds.
  1280.          */
  1281.         double dx, dy;
  1282.         cairo_fixed_t fdx, fdy;
  1283.         int i;
  1284.  
  1285.         stroker.bounds = polygon->limits[0];
  1286.         for (i = 1; i < polygon->num_limits; i++)
  1287.              _cairo_box_add_box (&stroker.bounds, &polygon->limits[i]);
  1288.  
  1289.         _cairo_stroke_style_max_distance_from_path (style, path, ctm, &dx, &dy);
  1290.         fdx = _cairo_fixed_from_double (dx);
  1291.         fdy = _cairo_fixed_from_double (dy);
  1292.  
  1293.         stroker.bounds.p1.x -= fdx;
  1294.         stroker.bounds.p2.x += fdx;
  1295.         stroker.bounds.p1.y -= fdy;
  1296.         stroker.bounds.p2.y += fdy;
  1297.     }
  1298.  
  1299.     stroker.style = *style;
  1300.     stroker.ctm = ctm;
  1301.     stroker.ctm_inverse = ctm_inverse;
  1302.     stroker.tolerance = tolerance;
  1303.     stroker.half_line_width = style->line_width / 2.;
  1304.     /* To test whether we need to join two segments of a spline using
  1305.      * a round-join or a bevel-join, we can inspect the angle between the
  1306.      * two segments. If the difference between the chord distance
  1307.      * (half-line-width times the cosine of the bisection angle) and the
  1308.      * half-line-width itself is greater than tolerance then we need to
  1309.      * inject a point.
  1310.      */
  1311.     stroker.spline_cusp_tolerance = 1 - tolerance / stroker.half_line_width;
  1312.     stroker.spline_cusp_tolerance *= stroker.spline_cusp_tolerance;
  1313.     stroker.spline_cusp_tolerance *= 2;
  1314.     stroker.spline_cusp_tolerance -= 1;
  1315.     stroker.ctm_det_positive =
  1316.         _cairo_matrix_compute_determinant (ctm) >= 0.0;
  1317.  
  1318.     stroker.pen.num_vertices = 0;
  1319.     if (path->has_curve_to ||
  1320.         style->line_join == CAIRO_LINE_JOIN_ROUND ||
  1321.         style->line_cap == CAIRO_LINE_CAP_ROUND) {
  1322.         status = _cairo_pen_init (&stroker.pen,
  1323.                                   stroker.half_line_width,
  1324.                                   tolerance, ctm);
  1325.         if (unlikely (status))
  1326.             return status;
  1327.  
  1328.         /* If the line width is so small that the pen is reduced to a
  1329.            single point, then we have nothing to do. */
  1330.         if (stroker.pen.num_vertices <= 1)
  1331.             return CAIRO_STATUS_SUCCESS;
  1332.     }
  1333.  
  1334.     stroker.has_current_face = FALSE;
  1335.     stroker.has_first_face = FALSE;
  1336.     stroker.has_initial_sub_path = FALSE;
  1337.  
  1338. #if DEBUG
  1339.     remove ("contours.txt");
  1340.     remove ("polygons.txt");
  1341.     _cairo_contour_init (&stroker.path, 0);
  1342. #endif
  1343.     _cairo_contour_init (&stroker.cw.contour, 1);
  1344.     _cairo_contour_init (&stroker.ccw.contour, -1);
  1345.     tolerance *= CAIRO_FIXED_ONE;
  1346.     tolerance *= tolerance;
  1347.     stroker.contour_tolerance = tolerance;
  1348.     stroker.polygon = polygon;
  1349.  
  1350.     status = _cairo_path_fixed_interpret (path,
  1351.                                           move_to,
  1352.                                           line_to,
  1353.                                           curve_to,
  1354.                                           close_path,
  1355.                                           &stroker);
  1356.     /* Cap the start and end of the final sub path as needed */
  1357.     if (likely (status == CAIRO_STATUS_SUCCESS))
  1358.         add_caps (&stroker);
  1359.  
  1360.     _cairo_contour_fini (&stroker.cw.contour);
  1361.     _cairo_contour_fini (&stroker.ccw.contour);
  1362.     if (stroker.pen.num_vertices)
  1363.         _cairo_pen_fini (&stroker.pen);
  1364.  
  1365. #if DEBUG
  1366.     {
  1367.         FILE *file = fopen ("polygons.txt", "a");
  1368.         _cairo_debug_print_polygon (file, polygon);
  1369.         fclose (file);
  1370.     }
  1371. #endif
  1372.  
  1373.     return status;
  1374. }
  1375.