コード例 #1
0
ファイル: cairo-contour.c プロジェクト: alexgcastro/cairo
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;
}
コード例 #2
0
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;
}
コード例 #3
0
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;
}
コード例 #4
0
ファイル: cairo-boxes.c プロジェクト: lxcypp/cario
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);
}
コード例 #5
0
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;
}
コード例 #6
0
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;
}
コード例 #7
0
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;
}
コード例 #8
0
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;
}
コード例 #9
0
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;
}
コード例 #10
0
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;
}
コード例 #11
0
ファイル: cairo-polygon-reduce.c プロジェクト: 1833183060/wke
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;
}