cairo_int_status_t __cairo_contour_add_point (cairo_contour_t *contour, const cairo_point_t *point) { cairo_contour_chain_t *tail = contour->tail; cairo_contour_chain_t *next; assert (tail->next == NULL); next = _cairo_malloc_ab_plus_c (tail->size_points*2, sizeof (cairo_point_t), sizeof (cairo_contour_chain_t)); if (unlikely (next == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); next->size_points = tail->size_points*2; next->num_points = 1; next->points = (cairo_point_t *)(next+1); next->next = NULL; tail->next = next; contour->tail = next; next->points[0] = *point; return CAIRO_INT_STATUS_SUCCESS; }
static cairo_path_buf_t * _cairo_path_buf_create (int buf_size) { cairo_path_buf_t *buf; /* adjust buf_size to ensure that buf->points is naturally aligned */ buf_size += sizeof (double) - ((buf_size + sizeof (cairo_path_buf_t)) & (sizeof (double)-1)); buf = _cairo_malloc_ab_plus_c (buf_size, sizeof (cairo_path_op_t) + 2 * sizeof (cairo_point_t), sizeof (cairo_path_buf_t)); if (buf) { buf->next = NULL; buf->prev = NULL; buf->num_ops = 0; buf->num_points = 0; buf->buf_size = buf_size; buf->op = (cairo_path_op_t *) (buf + 1); buf->points = (cairo_point_t *) (buf->op + buf_size); } return buf; }
cairo_int_status_t _cairo_truetype_index_to_ucs4 (cairo_scaled_font_t *scaled_font, unsigned long index, uint32_t *ucs4) { cairo_status_t status = CAIRO_INT_STATUS_UNSUPPORTED; const cairo_scaled_font_backend_t *backend; tt_cmap_t *cmap; char buf[4]; int num_tables, i; unsigned long size; backend = scaled_font->backend; if (!backend->load_truetype_table) return CAIRO_INT_STATUS_UNSUPPORTED; size = 4; status = backend->load_truetype_table (scaled_font, TT_TAG_cmap, 0, (unsigned char *) &buf, &size); if (unlikely (status)) return status; cmap = (tt_cmap_t *) buf; num_tables = be16_to_cpu (cmap->num_tables); size = 4 + num_tables*sizeof(tt_cmap_index_t); cmap = _cairo_malloc_ab_plus_c (num_tables, sizeof (tt_cmap_index_t), 4); if (unlikely (cmap == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); status = backend->load_truetype_table (scaled_font, TT_TAG_cmap, 0, (unsigned char *) cmap, &size); if (unlikely (status)) goto cleanup; /* Find a table with Unicode mapping */ for (i = 0; i < num_tables; i++) { if (be16_to_cpu (cmap->index[i].platform) == 3 && be16_to_cpu (cmap->index[i].encoding) == 1) { status = _cairo_truetype_reverse_cmap (scaled_font, be32_to_cpu (cmap->index[i].offset), index, ucs4); if (status != CAIRO_INT_STATUS_UNSUPPORTED) break; } } cleanup: free (cmap); return status; }
static void _cairo_boxes_add_internal (cairo_boxes_t *boxes, const cairo_box_t *box) { struct _cairo_boxes_chunk *chunk; if (unlikely (boxes->status)) return; chunk = boxes->tail; if (unlikely (chunk->count == chunk->size)) { int size; size = chunk->size * 2; chunk->next = _cairo_malloc_ab_plus_c (size, sizeof (cairo_box_t), sizeof (struct _cairo_boxes_chunk)); if (unlikely (chunk->next == NULL)) { boxes->status = _cairo_error (CAIRO_STATUS_NO_MEMORY); return; } chunk = chunk->next; boxes->tail = chunk; chunk->next = NULL; chunk->count = 0; chunk->size = size; chunk->base = (cairo_box_t *) (chunk + 1); } chunk->base[chunk->count++] = *box; boxes->num_boxes++; if (boxes->is_pixel_aligned) boxes->is_pixel_aligned = _cairo_box_is_pixel_aligned (box); }
cairo_status_t _cairo_bentley_ottmann_tessellate_boxes (const cairo_boxes_t *in, cairo_fill_rule_t fill_rule, cairo_boxes_t *out) { rectangle_t stack_rectangles[CAIRO_STACK_ARRAY_LENGTH (rectangle_t)]; rectangle_t *stack_rectangles_ptrs[ARRAY_LENGTH (stack_rectangles) + 3]; rectangle_t *rectangles, **rectangles_ptrs; rectangle_t *stack_rectangles_chain[CAIRO_STACK_ARRAY_LENGTH (rectangle_t *) ]; rectangle_t **rectangles_chain = NULL; const struct _cairo_boxes_chunk *chunk; cairo_status_t status; int i, j, y_min, y_max; if (unlikely (in->num_boxes == 0)) { _cairo_boxes_clear (out); return CAIRO_STATUS_SUCCESS; } if (in->num_boxes == 1) { if (in == out) { cairo_box_t *box = &in->chunks.base[0]; if (box->p1.x > box->p2.x) { cairo_fixed_t tmp = box->p1.x; box->p1.x = box->p2.x; box->p2.x = tmp; } } else { cairo_box_t box = in->chunks.base[0]; if (box.p1.x > box.p2.x) { cairo_fixed_t tmp = box.p1.x; box.p1.x = box.p2.x; box.p2.x = tmp; } _cairo_boxes_clear (out); status = _cairo_boxes_add (out, CAIRO_ANTIALIAS_DEFAULT, &box); assert (status == CAIRO_STATUS_SUCCESS); } return CAIRO_STATUS_SUCCESS; } y_min = INT_MAX; y_max = INT_MIN; for (chunk = &in->chunks; chunk != NULL; chunk = chunk->next) { const cairo_box_t *box = chunk->base; for (i = 0; i < chunk->count; i++) { if (box[i].p1.y < y_min) y_min = box[i].p1.y; if (box[i].p1.y > y_max) y_max = box[i].p1.y; } } y_min = _cairo_fixed_integer_floor (y_min); y_max = _cairo_fixed_integer_floor (y_max) + 1; y_max -= y_min; if (y_max < in->num_boxes) { rectangles_chain = stack_rectangles_chain; if (y_max > ARRAY_LENGTH (stack_rectangles_chain)) { rectangles_chain = _cairo_malloc_ab (y_max, sizeof (rectangle_t *)); if (unlikely (rectangles_chain == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); } memset (rectangles_chain, 0, y_max * sizeof (rectangle_t*)); } rectangles = stack_rectangles; rectangles_ptrs = stack_rectangles_ptrs; if (in->num_boxes > ARRAY_LENGTH (stack_rectangles)) { rectangles = _cairo_malloc_ab_plus_c (in->num_boxes, sizeof (rectangle_t) + sizeof (rectangle_t *), 3*sizeof (rectangle_t *)); if (unlikely (rectangles == NULL)) { if (rectangles_chain != stack_rectangles_chain) free (rectangles_chain); return _cairo_error (CAIRO_STATUS_NO_MEMORY); } rectangles_ptrs = (rectangle_t **) (rectangles + in->num_boxes); } j = 0; for (chunk = &in->chunks; chunk != NULL; chunk = chunk->next) { const cairo_box_t *box = chunk->base; for (i = 0; i < chunk->count; i++) { int h; if (box[i].p1.x < box[i].p2.x) { rectangles[j].left.x = box[i].p1.x; rectangles[j].left.dir = 1; rectangles[j].right.x = box[i].p2.x; rectangles[j].right.dir = -1; } else { rectangles[j].right.x = box[i].p1.x; rectangles[j].right.dir = 1; rectangles[j].left.x = box[i].p2.x; rectangles[j].left.dir = -1; } rectangles[j].left.right = NULL; rectangles[j].right.right = NULL; rectangles[j].top = box[i].p1.y; rectangles[j].bottom = box[i].p2.y; if (rectangles_chain) { h = _cairo_fixed_integer_floor (box[i].p1.y) - y_min; rectangles[j].left.next = (edge_t *)rectangles_chain[h]; rectangles_chain[h] = &rectangles[j]; } else { rectangles_ptrs[j+2] = &rectangles[j]; } j++; } } if (rectangles_chain) { j = 2; for (y_min = 0; y_min < y_max; y_min++) { rectangle_t *r; int start = j; for (r = rectangles_chain[y_min]; r; r = (rectangle_t *)r->left.next) rectangles_ptrs[j++] = r; if (j > start + 1) _rectangle_sort (rectangles_ptrs + start, j - start); } if (rectangles_chain != stack_rectangles_chain) free (rectangles_chain); j -= 2; } else { _rectangle_sort (rectangles_ptrs + 2, j); } _cairo_boxes_clear (out); status = _cairo_bentley_ottmann_tessellate_rectangular (rectangles_ptrs+2, j, fill_rule, FALSE, out); if (rectangles != stack_rectangles) free (rectangles); return status; }
cairo_status_t _cairo_bentley_ottmann_tessellate_rectangular_traps (cairo_traps_t *traps, cairo_fill_rule_t fill_rule) { rectangle_t stack_rectangles[CAIRO_STACK_ARRAY_LENGTH (rectangle_t)]; rectangle_t *stack_rectangles_ptrs[ARRAY_LENGTH (stack_rectangles) + 3]; rectangle_t *rectangles, **rectangles_ptrs; cairo_status_t status; int i; assert (traps->is_rectangular); if (unlikely (traps->num_traps <= 1)) { if (traps->num_traps == 1) { cairo_trapezoid_t *trap = traps->traps; if (trap->left.p1.x > trap->right.p1.x) { cairo_line_t tmp = trap->left; trap->left = trap->right; trap->right = tmp; } } return CAIRO_STATUS_SUCCESS; } dump_traps (traps, "bo-rects-traps-in.txt"); rectangles = stack_rectangles; rectangles_ptrs = stack_rectangles_ptrs; if (traps->num_traps > ARRAY_LENGTH (stack_rectangles)) { rectangles = _cairo_malloc_ab_plus_c (traps->num_traps, sizeof (rectangle_t) + sizeof (rectangle_t *), 3*sizeof (rectangle_t *)); if (unlikely (rectangles == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); rectangles_ptrs = (rectangle_t **) (rectangles + traps->num_traps); } for (i = 0; i < traps->num_traps; i++) { if (traps->traps[i].left.p1.x < traps->traps[i].right.p1.x) { rectangles[i].left.x = traps->traps[i].left.p1.x; rectangles[i].left.dir = 1; rectangles[i].right.x = traps->traps[i].right.p1.x; rectangles[i].right.dir = -1; } else { rectangles[i].right.x = traps->traps[i].left.p1.x; rectangles[i].right.dir = 1; rectangles[i].left.x = traps->traps[i].right.p1.x; rectangles[i].left.dir = -1; } rectangles[i].left.right = NULL; rectangles[i].right.right = NULL; rectangles[i].top = traps->traps[i].top; rectangles[i].bottom = traps->traps[i].bottom; rectangles_ptrs[i+2] = &rectangles[i]; } /* XXX incremental sort */ _rectangle_sort (rectangles_ptrs+2, i); _cairo_traps_clear (traps); status = _cairo_bentley_ottmann_tessellate_rectangular (rectangles_ptrs+2, i, fill_rule, TRUE, traps); traps->is_rectilinear = TRUE; traps->is_rectangular = TRUE; if (rectangles != stack_rectangles) free (rectangles); dump_traps (traps, "bo-rects-traps-out.txt"); return status; }
static cairo_status_t _create_dc_and_bitmap (cairo_win32_display_surface_t *surface, HDC original_dc, cairo_format_t format, int width, int height, unsigned char **bits_out, int *rowstride_out) { cairo_status_t status; BITMAPINFO *bitmap_info = NULL; struct { BITMAPINFOHEADER bmiHeader; RGBQUAD bmiColors[2]; } bmi_stack; void *bits; int num_palette = 0; /* Quiet GCC */ int i; surface->win32.dc = NULL; surface->bitmap = NULL; surface->is_dib = FALSE; switch (format) { default: case CAIRO_FORMAT_INVALID: case CAIRO_FORMAT_RGB16_565: case CAIRO_FORMAT_RGB30: return _cairo_error (CAIRO_STATUS_INVALID_FORMAT); case CAIRO_FORMAT_ARGB32: case CAIRO_FORMAT_RGB24: num_palette = 0; break; case CAIRO_FORMAT_A8: num_palette = 256; break; case CAIRO_FORMAT_A1: num_palette = 2; break; } if (num_palette > 2) { bitmap_info = _cairo_malloc_ab_plus_c (num_palette, sizeof(RGBQUAD), sizeof(BITMAPINFOHEADER)); if (!bitmap_info) return _cairo_error (CAIRO_STATUS_NO_MEMORY); } else { bitmap_info = (BITMAPINFO *)&bmi_stack; } bitmap_info->bmiHeader.biSize = sizeof (BITMAPINFOHEADER); bitmap_info->bmiHeader.biWidth = width == 0 ? 1 : width; bitmap_info->bmiHeader.biHeight = height == 0 ? -1 : - height; /* top-down */ bitmap_info->bmiHeader.biSizeImage = 0; bitmap_info->bmiHeader.biXPelsPerMeter = PELS_72DPI; /* unused here */ bitmap_info->bmiHeader.biYPelsPerMeter = PELS_72DPI; /* unused here */ bitmap_info->bmiHeader.biPlanes = 1; switch (format) { case CAIRO_FORMAT_INVALID: case CAIRO_FORMAT_RGB16_565: case CAIRO_FORMAT_RGB30: ASSERT_NOT_REACHED; /* We can't create real RGB24 bitmaps because something seems to * break if we do, especially if we don't set up an image * fallback. It could be a bug with using a 24bpp pixman image * (and creating one with masks). So treat them like 32bpp. * Note: This causes problems when using BitBlt/AlphaBlend/etc! * see end of file. */ case CAIRO_FORMAT_RGB24: case CAIRO_FORMAT_ARGB32: bitmap_info->bmiHeader.biBitCount = 32; bitmap_info->bmiHeader.biCompression = BI_RGB; bitmap_info->bmiHeader.biClrUsed = 0; /* unused */ bitmap_info->bmiHeader.biClrImportant = 0; break; case CAIRO_FORMAT_A8: bitmap_info->bmiHeader.biBitCount = 8; bitmap_info->bmiHeader.biCompression = BI_RGB; bitmap_info->bmiHeader.biClrUsed = 256; bitmap_info->bmiHeader.biClrImportant = 0; for (i = 0; i < 256; i++) { bitmap_info->bmiColors[i].rgbBlue = i; bitmap_info->bmiColors[i].rgbGreen = i; bitmap_info->bmiColors[i].rgbRed = i; bitmap_info->bmiColors[i].rgbReserved = 0; } break; case CAIRO_FORMAT_A1: bitmap_info->bmiHeader.biBitCount = 1; bitmap_info->bmiHeader.biCompression = BI_RGB; bitmap_info->bmiHeader.biClrUsed = 2; bitmap_info->bmiHeader.biClrImportant = 0; for (i = 0; i < 2; i++) { bitmap_info->bmiColors[i].rgbBlue = i * 255; bitmap_info->bmiColors[i].rgbGreen = i * 255; bitmap_info->bmiColors[i].rgbRed = i * 255; bitmap_info->bmiColors[i].rgbReserved = 0; } break; } surface->win32.dc = CreateCompatibleDC (original_dc); if (!surface->win32.dc) goto FAIL; surface->bitmap = CreateDIBSection (surface->win32.dc, bitmap_info, DIB_RGB_COLORS, &bits, NULL, 0); if (!surface->bitmap) goto FAIL; surface->is_dib = TRUE; GdiFlush(); surface->saved_dc_bitmap = SelectObject (surface->win32.dc, surface->bitmap); if (!surface->saved_dc_bitmap) goto FAIL; if (bitmap_info && num_palette > 2) free (bitmap_info); if (bits_out) *bits_out = bits; if (rowstride_out) { /* Windows bitmaps are padded to 32-bit (dword) boundaries */ switch (format) { case CAIRO_FORMAT_INVALID: case CAIRO_FORMAT_RGB16_565: case CAIRO_FORMAT_RGB30: ASSERT_NOT_REACHED; case CAIRO_FORMAT_ARGB32: case CAIRO_FORMAT_RGB24: *rowstride_out = 4 * width; break; case CAIRO_FORMAT_A8: *rowstride_out = (width + 3) & ~3; break; case CAIRO_FORMAT_A1: *rowstride_out = ((width + 31) & ~31) / 8; break; } } surface->win32.flags = _cairo_win32_flags_for_dc (surface->win32.dc); return CAIRO_STATUS_SUCCESS; FAIL: status = _cairo_win32_print_gdi_error (__FUNCTION__); if (bitmap_info && num_palette > 2) free (bitmap_info); if (surface->saved_dc_bitmap) { SelectObject (surface->win32.dc, surface->saved_dc_bitmap); surface->saved_dc_bitmap = NULL; } if (surface->bitmap) { DeleteObject (surface->bitmap); surface->bitmap = NULL; } if (surface->win32.dc) { DeleteDC (surface->win32.dc); surface->win32.dc = NULL; } return status; }
cairo_status_t _cairo_bentley_ottmann_tessellate_rectilinear_traps (cairo_traps_t *traps, cairo_fill_rule_t fill_rule) { cairo_bo_event_t stack_events[CAIRO_STACK_ARRAY_LENGTH (cairo_bo_event_t)]; cairo_bo_event_t *events; cairo_bo_event_t *stack_event_ptrs[ARRAY_LENGTH (stack_events) + 1]; cairo_bo_event_t **event_ptrs; cairo_bo_edge_t stack_edges[ARRAY_LENGTH (stack_events)]; cairo_bo_edge_t *edges; cairo_status_t status; int i, j, k; if (unlikely (traps->num_traps == 0)) return CAIRO_STATUS_SUCCESS; assert (traps->is_rectilinear); i = 4 * traps->num_traps; events = stack_events; event_ptrs = stack_event_ptrs; edges = stack_edges; if (i > ARRAY_LENGTH (stack_events)) { events = _cairo_malloc_ab_plus_c (i, sizeof (cairo_bo_event_t) + sizeof (cairo_bo_edge_t) + sizeof (cairo_bo_event_t *), sizeof (cairo_bo_event_t *)); if (unlikely (events == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); event_ptrs = (cairo_bo_event_t **) (events + i); edges = (cairo_bo_edge_t *) (event_ptrs + i + 1); } for (i = j = k = 0; i < traps->num_traps; i++) { edges[k].edge.top = traps->traps[i].top; edges[k].edge.bottom = traps->traps[i].bottom; edges[k].edge.line = traps->traps[i].left; edges[k].edge.dir = 1; edges[k].deferred_trap.right = NULL; edges[k].prev = NULL; edges[k].next = NULL; event_ptrs[j] = &events[j]; events[j].type = CAIRO_BO_EVENT_TYPE_START; events[j].point.y = traps->traps[i].top; events[j].point.x = traps->traps[i].left.p1.x; events[j].edge = &edges[k]; j++; event_ptrs[j] = &events[j]; events[j].type = CAIRO_BO_EVENT_TYPE_STOP; events[j].point.y = traps->traps[i].bottom; events[j].point.x = traps->traps[i].left.p1.x; events[j].edge = &edges[k]; j++; k++; edges[k].edge.top = traps->traps[i].top; edges[k].edge.bottom = traps->traps[i].bottom; edges[k].edge.line = traps->traps[i].right; edges[k].edge.dir = -1; edges[k].deferred_trap.right = NULL; edges[k].prev = NULL; edges[k].next = NULL; event_ptrs[j] = &events[j]; events[j].type = CAIRO_BO_EVENT_TYPE_START; events[j].point.y = traps->traps[i].top; events[j].point.x = traps->traps[i].right.p1.x; events[j].edge = &edges[k]; j++; event_ptrs[j] = &events[j]; events[j].type = CAIRO_BO_EVENT_TYPE_STOP; events[j].point.y = traps->traps[i].bottom; events[j].point.x = traps->traps[i].right.p1.x; events[j].edge = &edges[k]; j++; k++; } _cairo_traps_clear (traps); status = _cairo_bentley_ottmann_tessellate_rectilinear (event_ptrs, j, fill_rule, TRUE, traps); traps->is_rectilinear = TRUE; if (events != stack_events) free (events); return status; }
cairo_status_t _cairo_bentley_ottmann_tessellate_rectilinear_polygon_to_boxes (const cairo_polygon_t *polygon, cairo_fill_rule_t fill_rule, cairo_boxes_t *boxes) { cairo_status_t status; cairo_bo_event_t stack_events[CAIRO_STACK_ARRAY_LENGTH (cairo_bo_event_t)]; cairo_bo_event_t *events; cairo_bo_event_t *stack_event_ptrs[ARRAY_LENGTH (stack_events) + 1]; cairo_bo_event_t **event_ptrs; cairo_bo_edge_t stack_edges[ARRAY_LENGTH (stack_events)]; cairo_bo_edge_t *edges; int num_events; int i, j; if (unlikely (polygon->num_edges == 0)) return CAIRO_STATUS_SUCCESS; num_events = 2 * polygon->num_edges; events = stack_events; event_ptrs = stack_event_ptrs; edges = stack_edges; if (num_events > ARRAY_LENGTH (stack_events)) { events = _cairo_malloc_ab_plus_c (num_events, sizeof (cairo_bo_event_t) + sizeof (cairo_bo_edge_t) + sizeof (cairo_bo_event_t *), sizeof (cairo_bo_event_t *)); if (unlikely (events == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); event_ptrs = (cairo_bo_event_t **) (events + num_events); edges = (cairo_bo_edge_t *) (event_ptrs + num_events + 1); } for (i = j = 0; i < polygon->num_edges; i++) { edges[i].edge = polygon->edges[i]; edges[i].deferred_trap.right = NULL; edges[i].prev = NULL; edges[i].next = NULL; event_ptrs[j] = &events[j]; events[j].type = CAIRO_BO_EVENT_TYPE_START; events[j].point.y = polygon->edges[i].top; events[j].point.x = polygon->edges[i].line.p1.x; events[j].edge = &edges[i]; j++; event_ptrs[j] = &events[j]; events[j].type = CAIRO_BO_EVENT_TYPE_STOP; events[j].point.y = polygon->edges[i].bottom; events[j].point.x = polygon->edges[i].line.p1.x; events[j].edge = &edges[i]; j++; } status = _cairo_bentley_ottmann_tessellate_rectilinear (event_ptrs, j, fill_rule, FALSE, boxes); if (events != stack_events) free (events); return status; }
cairo_status_t _cairo_polygon_intersect (cairo_polygon_t *a, int winding_a, cairo_polygon_t *b, int winding_b) { cairo_status_t status; cairo_bo_start_event_t stack_events[CAIRO_STACK_ARRAY_LENGTH (cairo_bo_start_event_t)]; cairo_bo_start_event_t *events; cairo_bo_event_t *stack_event_ptrs[ARRAY_LENGTH (stack_events) + 1]; cairo_bo_event_t **event_ptrs; int num_events; int i, j; /* XXX lazy */ if (winding_a != CAIRO_FILL_RULE_WINDING) { status = _cairo_polygon_reduce (a, winding_a); if (unlikely (status)) return status; } if (winding_b != CAIRO_FILL_RULE_WINDING) { status = _cairo_polygon_reduce (b, winding_b); if (unlikely (status)) return status; } if (unlikely (0 == a->num_edges)) return CAIRO_STATUS_SUCCESS; if (unlikely (0 == b->num_edges)) { a->num_edges = 0; return CAIRO_STATUS_SUCCESS; } events = stack_events; event_ptrs = stack_event_ptrs; num_events = a->num_edges + b->num_edges; if (num_events > ARRAY_LENGTH (stack_events)) { events = _cairo_malloc_ab_plus_c (num_events, sizeof (cairo_bo_start_event_t) + sizeof (cairo_bo_event_t *), sizeof (cairo_bo_event_t *)); if (unlikely (events == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); event_ptrs = (cairo_bo_event_t **) (events + num_events); } j = 0; for (i = 0; i < a->num_edges; i++) { event_ptrs[j] = (cairo_bo_event_t *) &events[j]; events[j].type = CAIRO_BO_EVENT_TYPE_START; events[j].point.y.ordinate = a->edges[i].top; events[j].point.y.approx = EXACT; events[j].point.x.ordinate = _line_compute_intersection_x_for_y (&a->edges[i].line, events[j].point.y.ordinate); events[j].point.x.approx = EXACT; events[j].edge.a_or_b = 0; events[j].edge.edge = a->edges[i]; events[j].edge.deferred.other = NULL; events[j].edge.prev = NULL; events[j].edge.next = NULL; j++; } for (i = 0; i < b->num_edges; i++) { event_ptrs[j] = (cairo_bo_event_t *) &events[j]; events[j].type = CAIRO_BO_EVENT_TYPE_START; events[j].point.y.ordinate = b->edges[i].top; events[j].point.y.approx = EXACT; events[j].point.x.ordinate = _line_compute_intersection_x_for_y (&b->edges[i].line, events[j].point.y.ordinate); events[j].point.x.approx = EXACT; events[j].edge.a_or_b = 1; events[j].edge.edge = b->edges[i]; events[j].edge.deferred.other = NULL; events[j].edge.prev = NULL; events[j].edge.next = NULL; j++; } assert (j == num_events); #if 0 { FILE *file = fopen ("clip_a.txt", "w"); _cairo_debug_print_polygon (file, a); fclose (file); } { FILE *file = fopen ("clip_b.txt", "w"); _cairo_debug_print_polygon (file, b); fclose (file); } #endif a->num_edges = 0; status = intersection_sweep (event_ptrs, num_events, a); if (events != stack_events) free (events); #if 0 { FILE *file = fopen ("clip_result.txt", "w"); _cairo_debug_print_polygon (file, a); fclose (file); } #endif return status; }
cairo_status_t _cairo_polygon_reduce (cairo_polygon_t *polygon, cairo_fill_rule_t fill_rule) { cairo_status_t status; cairo_bo_start_event_t stack_events[CAIRO_STACK_ARRAY_LENGTH (cairo_bo_start_event_t)]; cairo_bo_start_event_t *events; cairo_bo_event_t *stack_event_ptrs[ARRAY_LENGTH (stack_events) + 1]; cairo_bo_event_t **event_ptrs; int num_limits; int num_events; int i; num_events = polygon->num_edges; if (unlikely (0 == num_events)) return CAIRO_STATUS_SUCCESS; if (DEBUG_POLYGON) { FILE *file = fopen ("reduce_in.txt", "w"); _cairo_debug_print_polygon (file, polygon); fclose (file); } events = stack_events; event_ptrs = stack_event_ptrs; if (num_events > ARRAY_LENGTH (stack_events)) { events = _cairo_malloc_ab_plus_c (num_events, sizeof (cairo_bo_start_event_t) + sizeof (cairo_bo_event_t *), sizeof (cairo_bo_event_t *)); if (unlikely (events == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); event_ptrs = (cairo_bo_event_t **) (events + num_events); } for (i = 0; i < num_events; i++) { event_ptrs[i] = (cairo_bo_event_t *) &events[i]; events[i].type = CAIRO_BO_EVENT_TYPE_START; events[i].point.y = polygon->edges[i].top; events[i].point.x = _line_compute_intersection_x_for_y (&polygon->edges[i].line, events[i].point.y); events[i].edge.edge = polygon->edges[i]; events[i].edge.deferred.right = NULL; events[i].edge.prev = NULL; events[i].edge.next = NULL; } num_limits = polygon->num_limits; polygon->num_limits = 0; polygon->num_edges = 0; status = _cairo_bentley_ottmann_tessellate_bo_edges (event_ptrs, num_events, fill_rule, polygon); polygon->num_limits = num_limits; if (events != stack_events) free (events); if (DEBUG_POLYGON) { FILE *file = fopen ("reduce_out.txt", "w"); _cairo_debug_print_polygon (file, polygon); fclose (file); } return status; }