cairo_status_t _cairo_pen_init_copy (cairo_pen_t *pen, const cairo_pen_t *other) { VG (VALGRIND_MAKE_MEM_UNDEFINED (pen, sizeof (cairo_pen_t))); *pen = *other; if (CAIRO_INJECT_FAULT ()) return _cairo_error (CAIRO_STATUS_NO_MEMORY); pen->vertices = pen->vertices_embedded; if (pen->num_vertices) { 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); } memcpy (pen->vertices, other->vertices, pen->num_vertices * sizeof (cairo_pen_vertex_t)); } return CAIRO_STATUS_SUCCESS; }
/* make room for at least one more edge */ static cairo_bool_t _cairo_polygon_grow (cairo_polygon_t *polygon) { cairo_edge_t *new_edges; int old_size = polygon->edges_size; int new_size = 4 * old_size; if (CAIRO_INJECT_FAULT ()) { polygon->status = _cairo_error (CAIRO_STATUS_NO_MEMORY); return FALSE; } if (polygon->edges == polygon->edges_embedded) { new_edges = _cairo_malloc_ab (new_size, sizeof (cairo_edge_t)); if (new_edges != NULL) memcpy (new_edges, polygon->edges, old_size * sizeof (cairo_edge_t)); } else { new_edges = _cairo_realloc_ab (polygon->edges, new_size, sizeof (cairo_edge_t)); } if (unlikely (new_edges == NULL)) { polygon->status = _cairo_error (CAIRO_STATUS_NO_MEMORY); return FALSE; } polygon->edges = new_edges; polygon->edges_size = new_size; return TRUE; }
/* Given a set of vertices, compute the convex hull using the Graham scan algorithm. */ cairo_status_t _cairo_hull_compute (cairo_pen_vertex_t *vertices, int *num_vertices) { cairo_hull_t hull_stack[CAIRO_STACK_ARRAY_LENGTH (cairo_hull_t)]; cairo_hull_t *hull; int num_hull = *num_vertices; if (CAIRO_INJECT_FAULT ()) return _cairo_error (CAIRO_STATUS_NO_MEMORY); if (num_hull > ARRAY_LENGTH (hull_stack)) { hull = _cairo_malloc_ab (num_hull, sizeof (cairo_hull_t)); if (unlikely (hull == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); } else { hull = hull_stack; } _cairo_hull_init (hull, vertices, num_hull); qsort (hull + 1, num_hull - 1, sizeof (cairo_hull_t), _cairo_hull_vertex_compare); _cairo_hull_eliminate_concave (hull, num_hull); _cairo_hull_to_pen (hull, vertices, num_vertices); if (hull != hull_stack) free (hull); 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_array_grow_by: * @array: a #cairo_array_t * * Increase the size of @array (if needed) so that there are at least * @additional free spaces in the array. The actual size of the array * is always increased by doubling as many times as necessary. **/ cairo_status_t _cairo_array_grow_by (cairo_array_t *array, unsigned int additional) { char *new_elements; unsigned int old_size = array->size; unsigned int required_size = array->num_elements + additional; unsigned int new_size; assert (! array->is_snapshot); /* check for integer overflow */ if (required_size > INT_MAX || required_size < array->num_elements) return _cairo_error (CAIRO_STATUS_NO_MEMORY); if (CAIRO_INJECT_FAULT ()) return _cairo_error (CAIRO_STATUS_NO_MEMORY); if (required_size <= old_size) return CAIRO_STATUS_SUCCESS; if (old_size == 0) new_size = 1; else new_size = old_size * 2; while (new_size < required_size) new_size = new_size * 2; if (array->elements == NULL) { array->elements = malloc (sizeof (char *)); if (unlikely (array->elements == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); *array->elements = NULL; } array->size = new_size; new_elements = _cairo_realloc_ab (*array->elements, array->size, array->element_size); if (unlikely (new_elements == NULL)) { array->size = old_size; return _cairo_error (CAIRO_STATUS_NO_MEMORY); } *array->elements = new_elements; return CAIRO_STATUS_SUCCESS; }
static cairo_status_t _cairo_rectilinear_stroker_add_segment (cairo_rectilinear_stroker_t *stroker, const cairo_point_t *p1, const cairo_point_t *p2, unsigned flags) { if (CAIRO_INJECT_FAULT ()) return _cairo_error (CAIRO_STATUS_NO_MEMORY); if (stroker->num_segments == stroker->segments_size) { int new_size = stroker->segments_size * 2; segment_t *new_segments; if (stroker->segments == stroker->segments_embedded) { new_segments = _cairo_malloc_ab (new_size, sizeof (segment_t)); if (unlikely (new_segments == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); memcpy (new_segments, stroker->segments, stroker->num_segments * sizeof (segment_t)); } else { new_segments = _cairo_realloc_ab (stroker->segments, new_size, sizeof (segment_t)); if (unlikely (new_segments == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); } stroker->segments_size = new_size; stroker->segments = new_segments; } stroker->segments[stroker->num_segments].p1 = *p1; stroker->segments[stroker->num_segments].p2 = *p2; stroker->segments[stroker->num_segments].flags = flags; stroker->num_segments++; return CAIRO_STATUS_SUCCESS; }