示例#1
0
cairo_int_status_t
_cairo_region_init_boxes (cairo_region_t *region,
			  cairo_box_int_t *boxes,
			  int count)
{
    pixman_box32_t stack_pboxes[CAIRO_STACK_ARRAY_LENGTH (pixman_box32_t)];
    pixman_box32_t *pboxes = stack_pboxes;
    cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
    int i;

    if (count > ARRAY_LENGTH (stack_pboxes)) {
	pboxes = _cairo_malloc_ab (count, sizeof (pixman_box32_t));
	if (unlikely (pboxes == NULL))
	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
    }

    for (i = 0; i < count; i++) {
	pboxes[i].x1 = boxes[i].p1.x;
	pboxes[i].y1 = boxes[i].p1.y;
	pboxes[i].x2 = boxes[i].p2.x;
	pboxes[i].y2 = boxes[i].p2.y;
    }

    if (! pixman_region32_init_rects (&region->rgn, pboxes, count))
	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);

    if (pboxes != stack_pboxes)
	free (pboxes);

    return status;
}
示例#2
0
/**
 * cairo_region_create_rectangles:
 * @rects: an array of @count rectangles
 * @count: number of rectangles
 *
 * Allocates a new region object containing the union of all given @rects.
 *
 * Return value: A newly allocated #cairo_region_t. Free with
 *   cairo_region_destroy(). This function always returns a
 *   valid pointer; if memory cannot be allocated, then a special
 *   error object is returned where all operations on the object do nothing.
 *   You can check for this with cairo_region_status().
 *
 * Since: 1.10
 **/
cairo_region_t *
cairo_region_create_rectangles (const cairo_rectangle_int_t *rects,
				int count)
{
    pixman_box32_t stack_pboxes[CAIRO_STACK_ARRAY_LENGTH (pixman_box32_t)];
    pixman_box32_t *pboxes = stack_pboxes;
    cairo_region_t *region;
    int i;

    region = _cairo_malloc (sizeof (cairo_region_t));
    if (unlikely (region == NULL))
	return _cairo_region_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));

    CAIRO_REFERENCE_COUNT_INIT (&region->ref_count, 1);
    region->status = CAIRO_STATUS_SUCCESS;

    if (count == 1) {
	pixman_region32_init_rect (&region->rgn,
				   rects->x, rects->y,
				   rects->width, rects->height);

	return region;
    }

    if (count > ARRAY_LENGTH (stack_pboxes)) {
	pboxes = _cairo_malloc_ab (count, sizeof (pixman_box32_t));
	if (unlikely (pboxes == NULL)) {
	    free (region);
	    return _cairo_region_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
	}
    }

    for (i = 0; i < count; i++) {
	pboxes[i].x1 = rects[i].x;
	pboxes[i].y1 = rects[i].y;
	pboxes[i].x2 = rects[i].x + rects[i].width;
	pboxes[i].y2 = rects[i].y + rects[i].height;
    }

    i = pixman_region32_init_rects (&region->rgn, pboxes, count);

    if (pboxes != stack_pboxes)
	free (pboxes);

    if (unlikely (i == 0)) {
	free (region);
	return _cairo_region_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
    }

    return region;
}
示例#3
0
nsRegion& nsRegion::Transform (const gfx3DMatrix &aTransform)
{
  int n;
  pixman_box32_t *boxes = pixman_region32_rectangles(&mImpl, &n);
  for (int i=0; i<n; i++) {
    nsRect rect = BoxToRect(boxes[i]);
    boxes[i] = RectToBox(nsIntRegion::ToRect(TransformRect(nsIntRegion::FromRect(rect), aTransform)));
  }

  pixman_region32_t region;
  // This will union all of the rectangles and runs in about O(n lg(n))
  pixman_region32_init_rects(&region, boxes, n);

  pixman_region32_fini(&mImpl);
  mImpl = region;
  return *this;
}
示例#4
0
void nsRegion::Inflate(const nsMargin& aMargin)
{
  int n;
  pixman_box32_t *boxes = pixman_region32_rectangles(&mImpl, &n);
  for (int i=0; i<n; i++) {
    nsRect rect = BoxToRect(boxes[i]);
    rect.Inflate(aMargin);
    boxes[i] = RectToBox(rect);
  }

  pixman_region32_t region;
  // This will union all of the rectangles and runs in about O(n lg(n))
  pixman_region32_init_rects(&region, boxes, n);

  pixman_region32_fini(&mImpl);
  mImpl = region;
}
示例#5
0
nsRegion& nsRegion::ScaleInverseRoundOut (float aXScale, float aYScale)
{
  int n;
  pixman_box32_t *boxes = pixman_region32_rectangles(&mImpl, &n);
  for (int i=0; i<n; i++) {
    nsRect rect = BoxToRect(boxes[i]);
    rect.ScaleInverseRoundOut(aXScale, aYScale);
    boxes[i] = RectToBox(rect);
  }

  pixman_region32_t region;
  // This will union all of the rectangles and runs in about O(n lg(n))
  pixman_region32_init_rects(&region, boxes, n);

  pixman_region32_fini(&mImpl);
  mImpl = region;
  return *this;
}
示例#6
0
cairo_region_t *
_cairo_region_create_from_boxes (const cairo_box_t *boxes, int count)
{
    cairo_region_t *region;

    region = _cairo_malloc (sizeof (cairo_region_t));
    if (unlikely (region == NULL))
	return _cairo_region_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));

    CAIRO_REFERENCE_COUNT_INIT (&region->ref_count, 1);
    region->status = CAIRO_STATUS_SUCCESS;

    if (! pixman_region32_init_rects (&region->rgn,
				      (pixman_box32_t *)boxes, count)) {
	free (region);
	return _cairo_region_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
    }

    return region;
}
示例#7
0
nsIntRegion nsRegion::ToPixels (nscoord aAppUnitsPerPixel, bool aOutsidePixels) const
{
  nsRegion region = *this;
  int n;
  pixman_box32_t *boxes = pixman_region32_rectangles(&region.mImpl, &n);
  for (int i=0; i<n; i++) {
    nsRect rect = BoxToRect(boxes[i]);
    nsIntRect deviceRect;
    if (aOutsidePixels)
      deviceRect = rect.ToOutsidePixels(aAppUnitsPerPixel);
    else
      deviceRect = rect.ToNearestPixels(aAppUnitsPerPixel);

    boxes[i] = RectToBox(deviceRect);
  }

  nsIntRegion intRegion;
  pixman_region32_fini(&intRegion.mImpl.mImpl);
  // This will union all of the rectangles and runs in about O(n lg(n))
  pixman_region32_init_rects(&intRegion.mImpl.mImpl, boxes, n);

  return intRegion;
}
示例#8
0
nsRegion nsRegion::ConvertAppUnitsRoundIn (int32_t aFromAPP, int32_t aToAPP) const
{
  if (aFromAPP == aToAPP) {
    return *this;
  }

  nsRegion region = *this;
  int n;
  pixman_box32_t *boxes = pixman_region32_rectangles(&region.mImpl, &n);
  for (int i=0; i<n; i++) {
    nsRect rect = BoxToRect(boxes[i]);
    rect = rect.ConvertAppUnitsRoundIn(aFromAPP, aToAPP);
    boxes[i] = RectToBox(rect);
  }

  pixman_region32_t pixmanRegion;
  // This will union all of the rectangles and runs in about O(n lg(n))
  pixman_region32_init_rects(&pixmanRegion, boxes, n);

  pixman_region32_fini(&region.mImpl);
  region.mImpl = pixmanRegion;
  return region;
}
示例#9
0
int
main ()
{
    pixman_region32_t r1;
    pixman_region32_t r2;
    pixman_region32_t r3;
    pixman_box32_t boxes[] = {
	{ 10, 10, 20, 20 },
	{ 30, 30, 30, 40 },
	{ 50, 45, 60, 44 },
    };
    pixman_box32_t boxes2[] = {
	{ 2, 6, 7, 6 },
	{ 4, 1, 6, 7 },
    };
    pixman_box32_t boxes3[] = {
	{ 2, 6, 7, 6 },
	{ 4, 1, 6, 1 },
    };
    int i, j;
    pixman_box32_t *b;
    pixman_image_t *image, *fill;
    pixman_color_t white = {
	0xffff,
	0xffff,
	0xffff,
	0xffff
    };

    /* This used to go into an infinite loop before pixman-region.c
     * was fixed to not use explict "short" variables
     */
    pixman_region32_init_rect (&r1, 0, 0, 20, 64000);
    pixman_region32_init_rect (&r2, 0, 0, 20, 64000);
    pixman_region32_init_rect (&r3, 0, 0, 20, 64000);

    pixman_region32_subtract (&r1, &r2, &r3);


    /* This would produce a region containing an empty
     * rectangle in it. Such regions are considered malformed,
     * but using an empty rectangle for initialization should
     * work.
     */
    pixman_region32_init_rects (&r1, boxes, 3);

    b = pixman_region32_rectangles (&r1, &i);

    assert (i == 1);
    
    while (i--)
    {
	assert (b[i].x1 < b[i].x2);
	assert (b[i].y1 < b[i].y2);
    }

    /* This would produce a rectangle containing the bounding box
     * of the two rectangles. The correct result is to eliminate
     * the broken rectangle.
     */
    pixman_region32_init_rects (&r1, boxes2, 2);

    b = pixman_region32_rectangles (&r1, &i);

    assert (i == 1);

    assert (b[0].x1 == 4);
    assert (b[0].y1 == 1);
    assert (b[0].x2 == 6);
    assert (b[0].y2 == 7);

    /* This should produce an empty region */
    pixman_region32_init_rects (&r1, boxes3, 2);

    b = pixman_region32_rectangles (&r1, &i);

    assert (i == 0);

    fill = pixman_image_create_solid_fill (&white);
    for (i = 0; i < 100; i++)
    {
	int image_size = 128;

	pixman_region32_init (&r1);

	/* Add some random rectangles */
	for (j = 0; j < 64; j++)
	    pixman_region32_union_rect (&r1, &r1,
					lcg_rand_n (image_size),
					lcg_rand_n (image_size),
					lcg_rand_n (25),
					lcg_rand_n (25));

	/* Clip to image size */
	pixman_region32_init_rect (&r2, 0, 0, image_size, image_size);
	pixman_region32_intersect (&r1, &r1, &r2);
	pixman_region32_fini (&r2);

	/* render region to a1 mask */
	image = pixman_image_create_bits (PIXMAN_a1, image_size, image_size, NULL, 0);
	pixman_image_set_clip_region32 (image, &r1);
	pixman_image_composite32 (PIXMAN_OP_SRC,
				  fill, NULL, image,
				  0, 0, 0, 0, 0, 0,
				  image_size, image_size);
	pixman_region32_init_from_image (&r2, image);

	pixman_image_unref (image);

	assert (pixman_region32_equal (&r1, &r2));
	pixman_region32_fini (&r1);
	pixman_region32_fini (&r2);

    }
    pixman_image_unref (fill);

    return 0;
}
示例#10
0
int
main ()
{
    pixman_region32_t r1;
    pixman_region32_t r2;
    pixman_region32_t r3;
    pixman_box32_t boxes[] = {
	{ 10, 10, 20, 20 },
	{ 30, 30, 30, 40 },
	{ 50, 45, 60, 44 },
    };
    pixman_box32_t boxes2[] = {
	{ 2, 6, 7, 6 },
	{ 4, 1, 6, 7 },
    };
    pixman_box32_t boxes3[] = {
	{ 2, 6, 7, 6 },
	{ 4, 1, 6, 1 },
    };
    int i;
    pixman_box32_t *b;

    /* This used to go into an infinite loop before pixman-region.c
     * was fixed to not use explict "short" variables
     */
    pixman_region32_init_rect (&r1, 0, 0, 20, 64000);
    pixman_region32_init_rect (&r2, 0, 0, 20, 64000);
    pixman_region32_init_rect (&r3, 0, 0, 20, 64000);

    pixman_region32_subtract (&r1, &r2, &r3);


    /* This would produce a region containing an empty
     * rectangle in it. Such regions are considered malformed,
     * but using an empty rectangle for initialization should
     * work.
     */
    pixman_region32_init_rects (&r1, boxes, 3);

    b = pixman_region32_rectangles (&r1, &i);

    assert (i == 1);
    
    while (i--)
    {
	assert (b[i].x1 < b[i].x2);
	assert (b[i].y1 < b[i].y2);
    }

    /* This would produce a rectangle containing the bounding box
     * of the two rectangles. The correct result is to eliminate
     * the broken rectangle.
     */
    pixman_region32_init_rects (&r1, boxes2, 2);

    b = pixman_region32_rectangles (&r1, &i);

    assert (i == 1);

    assert (b[0].x1 == 4);
    assert (b[0].y1 == 1);
    assert (b[0].x2 == 6);
    assert (b[0].y2 == 7);

    /* This should produce an empty region */
    pixman_region32_init_rects (&r1, boxes3, 2);

    b = pixman_region32_rectangles (&r1, &i);

    assert (i == 0);

    return 0;
}
示例#11
0
nsIntRegion nsRegion::ScaleToInsidePixels (float aScaleX, float aScaleY,
                                           nscoord aAppUnitsPerPixel) const
{
  /* When scaling a rect, walk forward through the rect list up until the y value is greater
   * than the current rect's YMost() value.
   *
   * For each rect found, check if the rects have a touching edge (in unscaled coordinates),
   * and if one edge is entirely contained within the other.
   *
   * If it is, then the contained edge can be moved (in scaled pixels) to ensure that no
   * gap exists.
   *
   * Since this could be potentially expensive - O(n^2), we only attempt this algorithm
   * for the first rect.
   */

  // make a copy of this region so that we can mutate it in place
  nsRegion region = *this;
  int n;
  pixman_box32_t *boxes = pixman_region32_rectangles(&region.mImpl, &n);

  nsIntRegion intRegion;
  if (n) {
    nsRect first = BoxToRect(boxes[0]);
    nsIntRect firstDeviceRect =
      first.ScaleToInsidePixels(aScaleX, aScaleY, aAppUnitsPerPixel);

    for (int i=1; i<n; i++) {
      nsRect rect = nsRect(boxes[i].x1, boxes[i].y1,
	  boxes[i].x2 - boxes[i].x1,
	  boxes[i].y2 - boxes[i].y1);
      nsIntRect deviceRect =
	rect.ScaleToInsidePixels(aScaleX, aScaleY, aAppUnitsPerPixel);

      if (rect.y <= first.YMost()) {
	if (rect.XMost() == first.x && rect.YMost() <= first.YMost()) {
	  // rect is touching on the left edge of the first rect and contained within
	  // the length of its left edge
	  deviceRect.SetRightEdge(firstDeviceRect.x);
	} else if (rect.x == first.XMost() && rect.YMost() <= first.YMost()) {
	  // rect is touching on the right edge of the first rect and contained within
	  // the length of its right edge
	  deviceRect.SetLeftEdge(firstDeviceRect.XMost());
	} else if (rect.y == first.YMost()) {
	  // The bottom of the first rect is on the same line as the top of rect, but
	  // they aren't necessarily contained.
	  if (rect.x <= first.x && rect.XMost() >= first.XMost()) {
	    // The top of rect contains the bottom of the first rect
	    firstDeviceRect.SetBottomEdge(deviceRect.y);
	  } else if (rect.x >= first.x && rect.XMost() <= first.XMost()) {
	    // The bottom of the first contains the top of rect
	    deviceRect.SetTopEdge(firstDeviceRect.YMost());
	  }
	}
      }

      boxes[i] = RectToBox(deviceRect);
    }

    boxes[0] = RectToBox(firstDeviceRect);

    pixman_region32_fini(&intRegion.mImpl.mImpl);
    // This will union all of the rectangles and runs in about O(n lg(n))
    pixman_region32_init_rects(&intRegion.mImpl.mImpl, boxes, n);
  }
  return intRegion;

}