示例#1
0
/**
 * _cairo_traps_extract_region:
 * @traps: a #cairo_traps_t
 * @region: a #cairo_region_t
 *
 * Determines if a set of trapezoids are exactly representable as a
 * cairo region.  If so, the passed-in region is initialized to
 * the area representing the given traps.  It should be finalized
 * with cairo_region_fini().  If not, %CAIRO_INT_STATUS_UNSUPPORTED
 * is returned.
 *
 * Return value: %CAIRO_STATUS_SUCCESS, %CAIRO_INT_STATUS_UNSUPPORTED
 * or %CAIRO_STATUS_NO_MEMORY
 **/
cairo_int_status_t
_cairo_traps_extract_region (cairo_traps_t   *traps,
			     cairo_antialias_t antialias,
			     cairo_region_t **region)
{
    cairo_rectangle_int_t stack_rects[CAIRO_STACK_ARRAY_LENGTH (cairo_rectangle_int_t)];
    cairo_rectangle_int_t *rects = stack_rects;
    cairo_int_status_t status;
    int i, rect_count;

    /* we only treat this a hint... */
    if (antialias != CAIRO_ANTIALIAS_NONE && ! traps->maybe_region)
	return CAIRO_INT_STATUS_UNSUPPORTED;

    if (! _traps_are_pixel_aligned (traps, antialias)) {
	traps->maybe_region = FALSE;
	return CAIRO_INT_STATUS_UNSUPPORTED;
    }

    if (traps->num_traps > ARRAY_LENGTH (stack_rects)) {
	rects = _cairo_malloc_ab (traps->num_traps, sizeof (cairo_rectangle_int_t));

	if (unlikely (rects == NULL))
	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
    }

    rect_count = 0;
    for (i = 0; i < traps->num_traps; i++) {
	int x1, y1, x2, y2;

	if (antialias == CAIRO_ANTIALIAS_NONE) {
	    x1 = _cairo_fixed_integer_round_down (traps->traps[i].left.p1.x);
	    y1 = _cairo_fixed_integer_round_down (traps->traps[i].top);
	    x2 = _cairo_fixed_integer_round_down (traps->traps[i].right.p1.x);
	    y2 = _cairo_fixed_integer_round_down (traps->traps[i].bottom);
	} else {
	    x1 = _cairo_fixed_integer_part (traps->traps[i].left.p1.x);
	    y1 = _cairo_fixed_integer_part (traps->traps[i].top);
	    x2 = _cairo_fixed_integer_part (traps->traps[i].right.p1.x);
	    y2 = _cairo_fixed_integer_part (traps->traps[i].bottom);
	}

	if (x2 > x1 && y2 > y1) {
	    rects[rect_count].x = x1;
	    rects[rect_count].y = y1;
	    rects[rect_count].width  = x2 - x1;
	    rects[rect_count].height = y2 - y1;
	    rect_count++;
	}
    }


    *region = cairo_region_create_rectangles (rects, rect_count);
    status = (*region)->status;

    if (rects != stack_rects)
	free (rects);

    return status;
}
static void
update_shape (GtkWidget* window,
	      gint       radius,
	      gint       shadow_size)
{
	if (g_composited)
	{		
		/* remove any current shape-mask */
		gtk_widget_input_shape_combine_region (window, NULL);
		return;
	}

	int width;
	int height;
	gtk_widget_get_size_request (window, &width, &height);
	const cairo_rectangle_int_t rects[] = {{2, 0, width - 4, height},
										   {1, 1, width - 2, height - 2},
										   {0, 2, width, height - 4}};
	cairo_region_t* region = NULL;

	region = cairo_region_create_rectangles (rects, 3);
	if (cairo_region_status (region) == CAIRO_STATUS_SUCCESS)
	{
		gtk_widget_shape_combine_region (window, NULL);
		gtk_widget_shape_combine_region (window, region);
	}
}
示例#3
0
cairo_region_t *
meta_region_transform (cairo_region_t       *region,
                       MetaMonitorTransform  transform,
                       int                   width,
                       int                   height)
{
  int n_rects, i;
  cairo_rectangle_int_t *rects;
  cairo_region_t *transformed_region;

  if (transform == META_MONITOR_TRANSFORM_NORMAL)
    return cairo_region_copy (region);

  n_rects = cairo_region_num_rectangles (region);

  rects = g_new0 (cairo_rectangle_int_t, n_rects);
  for (i = 0; i < n_rects; i++)
    {
      cairo_region_get_rectangle (region, i, &rects[i]);

      meta_rectangle_transform (&rects[i],
                                transform,
                                width,
                                height,
                                &rects[i]);
    }

  transformed_region = cairo_region_create_rectangles (rects, n_rects);

  g_free (rects);

  return transformed_region;
}
示例#4
0
cairo_region_t *
meta_region_scale (cairo_region_t *region, int scale)
{
  int n_rects, i;
  cairo_rectangle_int_t *rects;
  cairo_region_t *scaled_region;

  if (scale == 1)
    return cairo_region_copy (region);

  n_rects = cairo_region_num_rectangles (region);

  rects = g_malloc (sizeof(cairo_rectangle_int_t) * n_rects);
  for (i = 0; i < n_rects; i++)
    {
      cairo_region_get_rectangle (region, i, &rects[i]);
      rects[i].x *= scale;
      rects[i].y *= scale;
      rects[i].width *= scale;
      rects[i].height *= scale;
    }

  scaled_region = cairo_region_create_rectangles (rects, n_rects);

  g_free (rects);

  return scaled_region;
}
示例#5
0
cairo_region_t *
meta_region_scale_double (cairo_region_t       *region,
                          double                scale,
                          MetaRoundingStrategy  rounding_strategy)
{
  int n_rects, i;
  cairo_rectangle_int_t *rects;
  cairo_region_t *scaled_region;

  g_return_val_if_fail (scale > 0.0, NULL);

  if (scale == 1.0)
    return cairo_region_copy (region);

  n_rects = cairo_region_num_rectangles (region);

  rects = g_malloc (sizeof(cairo_rectangle_int_t) * n_rects);
  for (i = 0; i < n_rects; i++)
    {
      cairo_region_get_rectangle (region, i, &rects[i]);

      meta_rectangle_scale_double (&rects[i], scale, rounding_strategy,
                                   &rects[i]);
    }

  scaled_region = cairo_region_create_rectangles (rects, n_rects);

  g_free (rects);

  return scaled_region;
}
示例#6
0
cairo_region_t *
meta_region_crop_and_scale (cairo_region_t *region,
                            ClutterRect    *src_rect,
                            int             dst_width,
                            int             dst_height)
{
  int n_rects, i;
  cairo_rectangle_int_t *rects;
  cairo_region_t *viewport_region;

  if (src_rect->size.width == dst_width &&
      src_rect->size.height == dst_height &&
      roundf (src_rect->origin.x) == src_rect->origin.x &&
      roundf (src_rect->origin.y) == src_rect->origin.y)
    {
      viewport_region = cairo_region_copy (region);

      if (src_rect->origin.x != 0 || src_rect->origin.y != 0)
        {
          cairo_region_translate (viewport_region,
                                  (int) src_rect->origin.x,
                                  (int) src_rect->origin.y);
        }

      return viewport_region;
    }

  n_rects = cairo_region_num_rectangles (region);

  rects = g_new0 (cairo_rectangle_int_t, n_rects);
  for (i = 0; i < n_rects; i++)
    {
      cairo_region_get_rectangle (region, i, &rects[i]);

      meta_rectangle_crop_and_scale (&rects[i],
                                     src_rect,
                                     dst_width,
                                     dst_height,
                                     &rects[i]);
    }

  viewport_region = cairo_region_create_rectangles (rects, n_rects);

  g_free (rects);

  return viewport_region;
}
示例#7
0
static cairo_region_t *
region_from_rects (BroadwayRect *rects, int n_rects)
{
  cairo_region_t *region;
  cairo_rectangle_int_t *cairo_rects;
  int i;
  
  cairo_rects = g_new (cairo_rectangle_int_t, n_rects);
  for (i = 0; i < n_rects; i++)
    {
      cairo_rects[i].x = rects[i].x;
      cairo_rects[i].y = rects[i].y;
      cairo_rects[i].width = rects[i].width;
      cairo_rects[i].height = rects[i].height;
    }
  region = cairo_region_create_rectangles (cairo_rects, n_rects);
  g_free (cairo_rects);
  return region;
}
/* This special-case filler supports only a path that describes a
 * device-axis aligned rectangle. It exists to avoid the overhead of
 * the general tessellator when drawing very common rectangles.
 *
 * If the path described anything but a device-axis aligned rectangle,
 * this function will abort.
 */
cairo_region_t *
_cairo_path_fixed_fill_rectilinear_to_region (const cairo_path_fixed_t	*path,
					      cairo_fill_rule_t	 fill_rule,
					      const cairo_rectangle_int_t *extents)
{
    cairo_rectangle_int_t rectangle_stack[CAIRO_STACK_ARRAY_LENGTH (cairo_rectangle_int_t)];
    cairo_box_t box;
    cairo_region_t *region = NULL;

    assert (path->maybe_fill_region);
    assert (! path->is_empty_fill);

    if (_cairo_path_fixed_is_box (path, &box)) {
	rectangle_stack[0].x = _cairo_fixed_integer_part (box.p1.x);
	rectangle_stack[0].y = _cairo_fixed_integer_part (box.p1.y);
	rectangle_stack[0].width = _cairo_fixed_integer_part (box.p2.x) -
	                            rectangle_stack[0].x;
	rectangle_stack[0].height = _cairo_fixed_integer_part (box.p2.y) -
	                            rectangle_stack[0].y;
	if (! _cairo_rectangle_intersect (&rectangle_stack[0], extents))
	    region = cairo_region_create ();
	else
	    region = cairo_region_create_rectangle (&rectangle_stack[0]);
    } else if (fill_rule == CAIRO_FILL_RULE_WINDING) {
	cairo_rectangle_int_t *rects = rectangle_stack;
	cairo_path_fixed_iter_t iter;
	int last_cw = -1;
	int size = ARRAY_LENGTH (rectangle_stack);
	int count = 0;

	/* Support a series of rectangles as can be expected to describe a
	 * GdkRegion clip region during exposes.
	 */
	_cairo_path_fixed_iter_init (&iter, path);
	while (_cairo_path_fixed_iter_is_fill_box (&iter, &box)) {
	    int cw = 0;

	    if (box.p1.x > box.p2.x) {
		cairo_fixed_t t;

		t = box.p1.x;
		box.p1.x = box.p2.x;
		box.p2.x = t;

		cw = ! cw;
	    }

	    if (box.p1.y > box.p2.y) {
		cairo_fixed_t t;

		t = box.p1.y;
		box.p1.y = box.p2.y;
		box.p2.y = t;

		cw = ! cw;
	    }

	    if (last_cw < 0)
		last_cw = cw;
	    else if (last_cw != cw)
		goto TESSELLATE;

	    if (count == size) {
		cairo_rectangle_int_t *new_rects;

		size *= 4;
		if (rects == rectangle_stack) {
		    new_rects = _cairo_malloc_ab (size,
						  sizeof (cairo_rectangle_int_t));
		    if (unlikely (new_rects == NULL)) {
			/* XXX _cairo_region_nil */
			break;
		    }
		    memcpy (new_rects, rects, sizeof (rectangle_stack));
		} else {
		    new_rects = _cairo_realloc_ab (rects, size,
						   sizeof (cairo_rectangle_int_t));
		    if (unlikely (new_rects == NULL)) {
			/* XXX _cairo_region_nil */
			break;
		    }
		}
		rects = new_rects;
	    }

	    rects[count].x = _cairo_fixed_integer_part (box.p1.x);
	    rects[count].y = _cairo_fixed_integer_part (box.p1.y);
	    rects[count].width = _cairo_fixed_integer_part (box.p2.x) - rects[count].x;
	    rects[count].height = _cairo_fixed_integer_part (box.p2.y) - rects[count].y;
	    if (_cairo_rectangle_intersect (&rects[count], extents))
		count++;
	}

	if (_cairo_path_fixed_iter_at_end (&iter))
	    region = cairo_region_create_rectangles (rects, count);

TESSELLATE:
	if (rects != rectangle_stack)
	    free (rects);
    }

    if (region == NULL) {
	/* Hmm, complex polygon */
	region = _cairo_path_fixed_fill_rectilinear_tessellate_to_region (path,
									  fill_rule,
									  extents);


    }

    return region;
}
示例#9
0
static gboolean
goc_canvas_draw (GtkWidget *widget, cairo_t *cr)
{
	double x0, y0, x1, y1;
	double ax0, ay0, ax1, ay1;
	double clip_x1, clip_y1, clip_x2, clip_y2;
	GocCanvas *canvas = GOC_CANVAS (widget);
	GdkEventExpose *event = (GdkEventExpose *) gtk_get_current_event ();
	GocCanvasPrivate *priv = (GocCanvasPrivate *) canvas->priv;
	cairo_rectangle_list_t *l = cairo_copy_clip_rectangle_list (cr);
	int i, x, y;

	if (GOC_IS_ITEM (priv->invalidated_item) && priv->invalid_region) {
		/* evaluate the cairo clipped region and compare with the saved one */
		cairo_region_t *region;
		cairo_rectangle_int_t rect[l->num_rectangles];
	    for (i= 0; i  < l->num_rectangles; i++) {
			rect[i].x = l->rectangles[i].x;
			rect[i].y = l->rectangles[i].y;
			rect[i].width = l->rectangles[i].width;
			rect[i].height = l->rectangles[i].height;
		}
		region = cairo_region_create_rectangles (rect, l->num_rectangles);
		if (cairo_region_equal (priv->invalid_region, region)) {
			cairo_rectangle_list_destroy (l);
			cairo_region_destroy (region);
			/* looks like each time we call gtk_widget_queue_draw*,
			   the draw event is fired twice */
			if (priv->done) {
				priv->invalidated_item = NULL;
				cairo_region_destroy (priv->invalid_region);
				priv->invalid_region = NULL;
			} else {
				goc_item_draw (priv->invalidated_item, cr);
				priv->done = TRUE;
			}
			return TRUE;
		}

		cairo_region_destroy (region);
	}

	x = gtk_adjustment_get_value (gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (canvas)));
	y = gtk_adjustment_get_value (gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (canvas)));
	cairo_translate (cr, -x, -y);
	goc_item_get_bounds (GOC_ITEM (canvas->root),&x0, &y0, &x1, &y1);
	for (i= 0; i  < l->num_rectangles; i++) {
		cairo_save (cr);
		cairo_rectangle (cr, l->rectangles[i].x, l->rectangles[i].y,
		                 l->rectangles[i].width, l->rectangles[i].height);
		cairo_clip (cr);
		clip_x1 = l->rectangles[i].x;
		clip_y1 = l->rectangles[i].y;
		clip_x2 = clip_x1 + l->rectangles[i].width;
		clip_y2 = clip_y1 + l->rectangles[i].height;

		if (canvas->direction == GOC_DIRECTION_RTL) {
			ax1 = (double) (canvas->width - clip_x1) / canvas->pixels_per_unit + canvas->scroll_x1;
			ax0 = (double) (canvas->width - clip_x2) / canvas->pixels_per_unit + canvas->scroll_x1;
		} else {
			ax0 = (double) clip_x1 / canvas->pixels_per_unit + canvas->scroll_x1;
			ax1 = ((double) clip_x1 + event->area.width) / canvas->pixels_per_unit + canvas->scroll_x1;
		}
		ay0 = (double) clip_y1 / canvas->pixels_per_unit + canvas->scroll_y1;
		ay1 = (double) clip_y2 / canvas->pixels_per_unit + canvas->scroll_y1;
		if (x0 <= ax1 && x1 >= ax0 && y0 <= ay1 && y1 >= ay0) {
			canvas->cur_event = (GdkEvent *) event;
			goc_item_draw_region (GOC_ITEM (canvas->root), cr, ax0, ay0, ax1, ay1);
		}
		cairo_restore (cr);
	}
	cairo_rectangle_list_destroy (l);
	return TRUE;
}