cairo_status_t _cairo_pen_add_points (cairo_pen_t *pen, cairo_point_t *point, int num_points) { cairo_pen_vertex_t *vertices; int num_vertices; int i; num_vertices = pen->num_vertices + num_points; vertices = realloc (pen->vertices, num_vertices * sizeof (cairo_pen_vertex_t)); if (vertices == NULL) return CAIRO_STATUS_NO_MEMORY; pen->vertices = vertices; pen->num_vertices = num_vertices; /* initialize new vertices */ for (i=0; i < num_points; i++) pen->vertices[pen->num_vertices-num_points+i].point = point[i]; _cairo_hull_compute (pen->vertices, &pen->num_vertices); _cairo_pen_compute_slopes (pen); return CAIRO_STATUS_SUCCESS; }
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_status_t _cairo_pen_add_points (cairo_pen_t *pen, cairo_point_t *point, int num_points) { cairo_status_t status; int num_vertices; int i; if (CAIRO_INJECT_FAULT ()) return _cairo_error (CAIRO_STATUS_NO_MEMORY); num_vertices = pen->num_vertices + num_points; if (num_vertices > ARRAY_LENGTH (pen->vertices_embedded) || pen->vertices != pen->vertices_embedded) { cairo_pen_vertex_t *vertices; if (pen->vertices == pen->vertices_embedded) { vertices = _cairo_malloc_ab (num_vertices, sizeof (cairo_pen_vertex_t)); if (unlikely (vertices == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); memcpy (vertices, pen->vertices, pen->num_vertices * sizeof (cairo_pen_vertex_t)); } else { vertices = _cairo_realloc_ab (pen->vertices, num_vertices, sizeof (cairo_pen_vertex_t)); if (unlikely (vertices == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); } pen->vertices = vertices; } pen->num_vertices = num_vertices; /* initialize new vertices */ for (i=0; i < num_points; i++) pen->vertices[pen->num_vertices-num_points+i].point = point[i]; status = _cairo_hull_compute (pen->vertices, &pen->num_vertices); if (unlikely (status)) return status; _cairo_pen_compute_slopes (pen); return CAIRO_STATUS_SUCCESS; }
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; }