cairo_status_t _cairo_pen_init (cairo_pen_t *pen, double radius, cairo_gstate_t *gstate) { int i; int reflect; double det; if (pen->num_vertices) { /* XXX: It would be nice to notice that the pen is already properly constructed. However, this test would also have to account for possible changes in the transformation matrix. if (pen->radius == radius && pen->tolerance == tolerance) return CAIRO_STATUS_SUCCESS; */ _cairo_pen_fini (pen); } pen->radius = radius; pen->tolerance = gstate->tolerance; _cairo_matrix_compute_determinant (&gstate->ctm, &det); if (det >= 0) { reflect = 0; } else { reflect = 1; } pen->num_vertices = _cairo_pen_vertices_needed (gstate->tolerance, radius, &gstate->ctm); pen->vertices = malloc (pen->num_vertices * sizeof (cairo_pen_vertex_t)); if (pen->vertices == NULL) { return CAIRO_STATUS_NO_MEMORY; } /* * Compute pen coordinates. To generate the right ellipse, compute points around * a circle in user space and transform them to device space. To get a consistent * orientation in device space, flip the pen if the transformation matrix * is reflecting */ for (i=0; i < pen->num_vertices; i++) { double theta = 2 * M_PI * i / (double) pen->num_vertices; double dx = radius * cos (reflect ? -theta : theta); double dy = radius * sin (reflect ? -theta : theta); cairo_pen_vertex_t *v = &pen->vertices[i]; cairo_matrix_transform_distance (&gstate->ctm, &dx, &dy); v->point.x = _cairo_fixed_from_double (dx); v->point.y = _cairo_fixed_from_double (dy); } _cairo_pen_compute_slopes (pen); return CAIRO_STATUS_SUCCESS; }
cairo_status_t _cairo_pen_init (cairo_pen_t *pen, double radius, double tolerance, const cairo_matrix_t *ctm) { int i; int reflect; if (CAIRO_INJECT_FAULT ()) return _cairo_error (CAIRO_STATUS_NO_MEMORY); VG (VALGRIND_MAKE_MEM_UNDEFINED (pen, sizeof (cairo_pen_t))); pen->radius = radius; pen->tolerance = tolerance; reflect = _cairo_matrix_compute_determinant (ctm) < 0.; pen->num_vertices = _cairo_pen_vertices_needed (tolerance, radius, ctm); if (pen->num_vertices > ARRAY_LENGTH (pen->vertices_embedded)) { pen->vertices = _cairo_malloc_ab (pen->num_vertices, sizeof (cairo_pen_vertex_t)); if (unlikely (pen->vertices == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); } else { pen->vertices = pen->vertices_embedded; } /* * Compute pen coordinates. To generate the right ellipse, compute points around * a circle in user space and transform them to device space. To get a consistent * orientation in device space, flip the pen if the transformation matrix * is reflecting */ for (i=0; i < pen->num_vertices; i++) { cairo_pen_vertex_t *v = &pen->vertices[i]; double theta = 2 * M_PI * i / (double) pen->num_vertices, dx, dy; if (reflect) theta = -theta; dx = radius * cos (theta); dy = radius * sin (theta); cairo_matrix_transform_distance (ctm, &dx, &dy); v->point.x = _cairo_fixed_from_double (dx); v->point.y = _cairo_fixed_from_double (dy); } _cairo_pen_compute_slopes (pen); return CAIRO_STATUS_SUCCESS; }
cairo_int_status_t _cairo_compositor_stroke (const cairo_compositor_t *compositor, cairo_surface_t *surface, cairo_operator_t op, const cairo_pattern_t *source, const cairo_path_fixed_t *path, const cairo_stroke_style_t *style, const cairo_matrix_t *ctm, const cairo_matrix_t *ctm_inverse, double tolerance, cairo_antialias_t antialias, const cairo_clip_t *clip) { cairo_composite_rectangles_t extents; cairo_int_status_t status; TRACE ((stderr, "%s\n", __FUNCTION__)); if (_cairo_pen_vertices_needed (tolerance, style->line_width/2, ctm) <= 1) return CAIRO_INT_STATUS_NOTHING_TO_DO; status = _cairo_composite_rectangles_init_for_stroke (&extents, surface, op, source, path, style, ctm, clip); if (unlikely (status)) return status; do { while (compositor->stroke == XNULL) compositor = compositor->delegate; status = compositor->stroke (compositor, &extents, path, style, ctm, ctm_inverse, tolerance, antialias); compositor = compositor->delegate; } while (status == CAIRO_INT_STATUS_UNSUPPORTED); if (status == CAIRO_INT_STATUS_SUCCESS && surface->damage) { TRACE ((stderr, "%s: applying damage (%d,%d)x(%d, %d)\n", __FUNCTION__, extents.unbounded.x, extents.unbounded.y, extents.unbounded.width, extents.unbounded.height)); surface->damage = _cairo_damage_add_rectangle (surface->damage, &extents.unbounded); } _cairo_composite_rectangles_fini (&extents); return status; }
cairo_status_t _cairo_pen_init (cairo_pen_t *pen, double radius, double tolerance, cairo_matrix_t *ctm) { int i; int reflect; double det; pen->radius = radius; pen->tolerance = tolerance; _cairo_matrix_compute_determinant (ctm, &det); if (det >= 0) { reflect = 0; } else { reflect = 1; } pen->num_vertices = _cairo_pen_vertices_needed (tolerance, radius, ctm); pen->vertices = _cairo_malloc_ab (pen->num_vertices, sizeof (cairo_pen_vertex_t)); if (pen->vertices == NULL) { return CAIRO_STATUS_NO_MEMORY; } /* * Compute pen coordinates. To generate the right ellipse, compute points around * a circle in user space and transform them to device space. To get a consistent * orientation in device space, flip the pen if the transformation matrix * is reflecting */ for (i=0; i < pen->num_vertices; i++) { double theta = 2 * M_PI * i / (double) pen->num_vertices; double dx = radius * cos (reflect ? -theta : theta); double dy = radius * sin (reflect ? -theta : theta); cairo_pen_vertex_t *v = &pen->vertices[i]; cairo_matrix_transform_distance (ctm, &dx, &dy); v->point.x = _cairo_fixed_from_double (dx); v->point.y = _cairo_fixed_from_double (dy); } _cairo_pen_compute_slopes (pen); return CAIRO_STATUS_SUCCESS; }