Bug 845874. Switch to Y-X banded regions. r=roc

Previously our region code was just a simple y,x sorted list of
non-intersecting rectangles. This can cause us to have simple regions
represented in a complex unoptimizable way.

Switching to pixman regions gives us a canonical region implementation.

There are some cases when this can cause performance regressions.

For example, with the old region code we end up with this region:
http://people.mozilla.org/~jmuizelaar/region-pre.html
which is represented like this:
http://people.mozilla.org/~jmuizelaar/region-post.html
with the new code.

We call SimplifyOutward(4) on this. With old regions we can't simplify it so we
end up taking the bounds and get 1 rect. With the new regions we have only 3
rects to start and so we do nothing. The difference between 3 rects and 1 rect
cause D2D to do a PushLayer() instead of a ClipRect() and that seems to be the
causes for the regression.

--HG--
extra : rebase_source : 65e0d29d67b51a3780448eaecfde33dbcb6b99b1
This commit is contained in:
Jeff Muizelaar 2013-11-18 13:01:54 -05:00
parent fbc92cc0f4
commit 0471905a26
10 changed files with 581 additions and 1754 deletions

View File

@ -362,130 +362,4 @@
#define cairo_xlib_surface_get_xrender_format _moz_cairo_xlib_surface_get_xrender_format
#define cairo_xlib_surface_set_drawable _moz_cairo_xlib_surface_set_drawable
#define cairo_xlib_surface_set_size _moz_cairo_xlib_surface_set_size
#ifdef MOZ_TREE_PIXMAN
#define pixman_region_set_static_pointers _moz_pixman_region_set_static_pointers
#define pixman_region_init _moz_pixman_region_init
#define pixman_region_init_rect _moz_pixman_region_init_rect
#define pixman_region_init_rects _moz_pixman_region_init_rects
#define pixman_region_init_with_extents _moz_pixman_region_init_with_extents
#define pixman_region_fini _moz_pixman_region_fini
#define pixman_region_translate _moz_pixman_region_translate
#define pixman_region_copy _moz_pixman_region_copy
#define pixman_region_intersect _moz_pixman_region_intersect
#define pixman_region_union _moz_pixman_region_union
#define pixman_region_union_rect _moz_pixman_region_union_rect
#define pixman_region_subtract _moz_pixman_region_subtract
#define pixman_region_inverse _moz_pixman_region_inverse
#define pixman_region_contains_point _moz_pixman_region_contains_point
#define pixman_region_contains_rectangle _moz_pixman_region_contains_rectangle
#define pixman_region_not_empty _moz_pixman_region_not_empty
#define pixman_region_extents _moz_pixman_region_extents
#define pixman_region_n_rects _moz_pixman_region_n_rects
#define pixman_region_rectangles _moz_pixman_region_rectangles
#define pixman_region_equal _moz_pixman_region_equal
#define pixman_region_selfcheck _moz_pixman_region_selfcheck
#define pixman_region_reset _moz_pixman_region_reset
#define pixman_region32_init _moz_pixman_region32_init
#define pixman_region32_init_rect _moz_pixman_region32_init_rect
#define pixman_region32_init_rects _moz_pixman_region32_init_rects
#define pixman_region32_init_with_extents _moz_pixman_region32_init_with_extents
#define pixman_region32_fini _moz_pixman_region32_fini
#define pixman_region32_translate _moz_pixman_region32_translate
#define pixman_region32_copy _moz_pixman_region32_copy
#define pixman_region32_intersect _moz_pixman_region32_intersect
#define pixman_region32_union _moz_pixman_region32_union
#define pixman_region32_union_rect _moz_pixman_region32_union_rect
#define pixman_region32_subtract _moz_pixman_region32_subtract
#define pixman_region32_inverse _moz_pixman_region32_inverse
#define pixman_region32_contains_point _moz_pixman_region32_contains_point
#define pixman_region32_contains_rectangle _moz_pixman_region32_contains_rectangle
#define pixman_region32_not_empty _moz_pixman_region32_not_empty
#define pixman_region32_extents _moz_pixman_region32_extents
#define pixman_region32_n_rects _moz_pixman_region32_n_rects
#define pixman_region32_rectangles _moz_pixman_region32_rectangles
#define pixman_region32_equal _moz_pixman_region32_equal
#define pixman_region32_selfcheck _moz_pixman_region32_selfcheck
#define pixman_region32_reset _moz_pixman_region32_reset
#define pixman_blt _moz_pixman_blt
#define pixman_fill _moz_pixman_fill
#define pixman_transform_point_3d _moz_pixman_transform_point_3d
#define pixman_version _moz_pixman_version
#define pixman_version_string _moz_pixman_version_string
#define pixman_format_supported_destination _moz_pixman_format_supported_destination
#define pixman_format_supported_source _moz_pixman_format_supported_source
#define pixman_image_create_solid_fill _moz_pixman_image_create_solid_fill
#define pixman_image_create_linear_gradient _moz_pixman_image_create_linear_gradient
#define pixman_image_create_radial_gradient _moz_pixman_image_create_radial_gradient
#define pixman_image_create_conical_gradient _moz_pixman_image_create_conical_gradient
#define pixman_image_create_bits _moz_pixman_image_create_bits
#define pixman_image_ref _moz_pixman_image_ref
#define pixman_image_unref _moz_pixman_image_unref
#define pixman_image_set_clip_region _moz_pixman_image_set_clip_region
#define pixman_image_set_clip_region32 _moz_pixman_image_set_clip_region32
#define pixman_image_set_has_client_clip _moz_pixman_image_set_has_client_clip
#define pixman_image_set_transform _moz_pixman_image_set_transform
#define pixman_image_set_repeat _moz_pixman_image_set_repeat
#define pixman_image_set_filter _moz_pixman_image_set_filter
#define pixman_image_set_source_clipping _moz_pixman_image_set_source_clipping
#define pixman_image_set_alpha_map _moz_pixman_image_set_alpha_map
#define pixman_image_set_component_alpha _moz_pixman_image_set_component_alpha
#define pixman_image_set_accessors _moz_pixman_image_set_accessors
#define pixman_image_set_indexed _moz_pixman_image_set_indexed
#define pixman_image_get_data _moz_pixman_image_get_data
#define pixman_image_get_width _moz_pixman_image_get_width
#define pixman_image_get_height _moz_pixman_image_get_height
#define pixman_image_get_stride _moz_pixman_image_get_stride
#define pixman_image_get_depth _moz_pixman_image_get_depth
#define pixman_image_fill_rectangles _moz_pixman_image_fill_rectangles
#define pixman_compute_composite_region _moz_pixman_compute_composite_region
#define pixman_image_composite _moz_pixman_image_composite
#define pixman_sample_ceil_y _moz_pixman_sample_ceil_y
#define pixman_sample_floor_y _moz_pixman_sample_floor_y
#define pixman_edge_step _moz_pixman_edge_step
#define pixman_edge_init _moz_pixman_edge_init
#define pixman_line_fixed_edge_init _moz_pixman_line_fixed_edge_init
#define pixman_rasterize_edges _moz_pixman_rasterize_edges
#define pixman_add_traps _moz_pixman_add_traps
#define pixman_add_trapezoids _moz_pixman_add_trapezoids
#define pixman_rasterize_trapezoid _moz_pixman_rasterize_trapezoid
#define pixman_disable_out_of_bounds_workaround _moz_pixman_disable_out_of_bounds_workaround
#define pixman_f_transform_bounds _moz_pixman_f_transform_bounds
#define pixman_f_transform_from_pixman_transform _moz_pixman_f_transform_from_pixman_transform
#define pixman_f_transform_init_identity _moz_pixman_f_transform_init_identity
#define pixman_f_transform_init_rotate _moz_pixman_f_transform_init_rotate
#define pixman_f_transform_init_scale _moz_pixman_f_transform_init_scale
#define pixman_f_transform_init_translate _moz_pixman_f_transform_init_translate
#define pixman_f_transform_invert _moz_pixman_f_transform_invert
#define pixman_f_transform_multiply _moz_pixman_f_transform_multiply
#define pixman_f_transform_point _moz_pixman_f_transform_point
#define pixman_f_transform_point_3d _moz_pixman_f_transform_point_3d
#define pixman_f_transform_rotate _moz_pixman_f_transform_rotate
#define pixman_f_transform_scale _moz_pixman_f_transform_scale
#define pixman_f_transform_translate _moz_pixman_f_transform_translate
#define pixman_image_composite32 _moz_pixman_image_composite32
#define pixman_image_fill_boxes _moz_pixman_image_fill_boxes
#define pixman_image_get_component_alpha _moz_pixman_image_get_component_alpha
#define pixman_image_get_destroy_data _moz_pixman_image_get_destroy_data
#define pixman_image_get_format _moz_pixman_image_get_format
#define pixman_image_set_destroy_function _moz_pixman_image_set_destroy_function
#define pixman_region_init_from_image _moz_pixman_region_init_from_image
#define pixman_region_intersect_rect _moz_pixman_region_intersect_rect
#define pixman_region32_init_from_image _moz_pixman_region32_init_from_image
#define pixman_region32_intersect_rect _moz_pixman_region32_intersect_rect
#define pixman_transform_bounds _moz_pixman_transform_bounds
#define pixman_transform_from_pixman_f_transform _moz_pixman_transform_from_pixman_f_transform
#define pixman_transform_init_identity _moz_pixman_transform_init_identity
#define pixman_transform_init_rotate _moz_pixman_transform_init_rotate
#define pixman_transform_init_scale _moz_pixman_transform_init_scale
#define pixman_transform_init_translate _moz_pixman_transform_init_translate
#define pixman_transform_invert _moz_pixman_transform_invert
#define pixman_transform_is_identity _moz_pixman_transform_is_identity
#define pixman_transform_is_int_translate _moz_pixman_transform_is_int_translate
#define pixman_transform_is_inverse _moz_pixman_transform_is_inverse
#define pixman_transform_is_scale _moz_pixman_transform_is_scale
#define pixman_transform_multiply _moz_pixman_transform_multiply
#define pixman_transform_point _moz_pixman_transform_point
#define pixman_transform_rotate _moz_pixman_transform_rotate
#define pixman_transform_scale _moz_pixman_transform_scale
#define pixman_transform_translate _moz_pixman_transform_translate
#endif
#include "pixman-rename.h"

View File

@ -13,6 +13,7 @@ EXPORTS.cairo += [
'cairo-tee.h',
'cairo-version.h',
'cairo.h',
'pixman-rename.h',
]
if CONFIG['MOZ_WIDGET_TOOLKIT'] not in ('cocoa', 'uikit'):

View File

@ -0,0 +1,128 @@
#ifdef MOZ_TREE_PIXMAN
#define pixman_region_set_static_pointers _moz_pixman_region_set_static_pointers
#define pixman_region_init _moz_pixman_region_init
#define pixman_region_init_rect _moz_pixman_region_init_rect
#define pixman_region_init_rects _moz_pixman_region_init_rects
#define pixman_region_init_with_extents _moz_pixman_region_init_with_extents
#define pixman_region_fini _moz_pixman_region_fini
#define pixman_region_translate _moz_pixman_region_translate
#define pixman_region_copy _moz_pixman_region_copy
#define pixman_region_intersect _moz_pixman_region_intersect
#define pixman_region_union _moz_pixman_region_union
#define pixman_region_union_rect _moz_pixman_region_union_rect
#define pixman_region_subtract _moz_pixman_region_subtract
#define pixman_region_inverse _moz_pixman_region_inverse
#define pixman_region_contains_point _moz_pixman_region_contains_point
#define pixman_region_contains_rectangle _moz_pixman_region_contains_rectangle
#define pixman_region_not_empty _moz_pixman_region_not_empty
#define pixman_region_extents _moz_pixman_region_extents
#define pixman_region_n_rects _moz_pixman_region_n_rects
#define pixman_region_rectangles _moz_pixman_region_rectangles
#define pixman_region_equal _moz_pixman_region_equal
#define pixman_region_selfcheck _moz_pixman_region_selfcheck
#define pixman_region_reset _moz_pixman_region_reset
#define pixman_region32_init _moz_pixman_region32_init
#define pixman_region32_init_rect _moz_pixman_region32_init_rect
#define pixman_region32_init_rects _moz_pixman_region32_init_rects
#define pixman_region32_init_with_extents _moz_pixman_region32_init_with_extents
#define pixman_region32_init_from_image _moz_pixman_region32_init_from_image
#define pixman_region32_fini _moz_pixman_region32_fini
#define pixman_region32_translate _moz_pixman_region32_translate
#define pixman_region32_copy _moz_pixman_region32_copy
#define pixman_region32_intersect _moz_pixman_region32_intersect
#define pixman_region32_intersect_rect _moz_pixman_region32_intersect_rect
#define pixman_region32_union _moz_pixman_region32_union
#define pixman_region32_union_rect _moz_pixman_region32_union_rect
#define pixman_region32_subtract _moz_pixman_region32_subtract
#define pixman_region32_inverse _moz_pixman_region32_inverse
#define pixman_region32_contains_point _moz_pixman_region32_contains_point
#define pixman_region32_contains_rectangle _moz_pixman_region32_contains_rectangle
#define pixman_region32_not_empty _moz_pixman_region32_not_empty
#define pixman_region32_extents _moz_pixman_region32_extents
#define pixman_region32_n_rects _moz_pixman_region32_n_rects
#define pixman_region32_rectangles _moz_pixman_region32_rectangles
#define pixman_region32_equal _moz_pixman_region32_equal
#define pixman_region32_selfcheck _moz_pixman_region32_selfcheck
#define pixman_region32_reset _moz_pixman_region32_reset
#define pixman_region32_clear _moz_pixman_region32_clear
#define pixman_blt _moz_pixman_blt
#define pixman_fill _moz_pixman_fill
#define pixman_transform_point_3d _moz_pixman_transform_point_3d
#define pixman_version _moz_pixman_version
#define pixman_version_string _moz_pixman_version_string
#define pixman_format_supported_destination _moz_pixman_format_supported_destination
#define pixman_format_supported_source _moz_pixman_format_supported_source
#define pixman_image_create_solid_fill _moz_pixman_image_create_solid_fill
#define pixman_image_create_linear_gradient _moz_pixman_image_create_linear_gradient
#define pixman_image_create_radial_gradient _moz_pixman_image_create_radial_gradient
#define pixman_image_create_conical_gradient _moz_pixman_image_create_conical_gradient
#define pixman_image_create_bits _moz_pixman_image_create_bits
#define pixman_image_ref _moz_pixman_image_ref
#define pixman_image_unref _moz_pixman_image_unref
#define pixman_image_set_clip_region _moz_pixman_image_set_clip_region
#define pixman_image_set_clip_region32 _moz_pixman_image_set_clip_region32
#define pixman_image_set_has_client_clip _moz_pixman_image_set_has_client_clip
#define pixman_image_set_transform _moz_pixman_image_set_transform
#define pixman_image_set_repeat _moz_pixman_image_set_repeat
#define pixman_image_set_filter _moz_pixman_image_set_filter
#define pixman_image_set_source_clipping _moz_pixman_image_set_source_clipping
#define pixman_image_set_alpha_map _moz_pixman_image_set_alpha_map
#define pixman_image_set_component_alpha _moz_pixman_image_set_component_alpha
#define pixman_image_set_accessors _moz_pixman_image_set_accessors
#define pixman_image_set_indexed _moz_pixman_image_set_indexed
#define pixman_image_get_data _moz_pixman_image_get_data
#define pixman_image_get_width _moz_pixman_image_get_width
#define pixman_image_get_height _moz_pixman_image_get_height
#define pixman_image_get_stride _moz_pixman_image_get_stride
#define pixman_image_get_depth _moz_pixman_image_get_depth
#define pixman_image_fill_rectangles _moz_pixman_image_fill_rectangles
#define pixman_compute_composite_region _moz_pixman_compute_composite_region
#define pixman_image_composite _moz_pixman_image_composite
#define pixman_sample_ceil_y _moz_pixman_sample_ceil_y
#define pixman_sample_floor_y _moz_pixman_sample_floor_y
#define pixman_edge_step _moz_pixman_edge_step
#define pixman_edge_init _moz_pixman_edge_init
#define pixman_line_fixed_edge_init _moz_pixman_line_fixed_edge_init
#define pixman_rasterize_edges _moz_pixman_rasterize_edges
#define pixman_add_traps _moz_pixman_add_traps
#define pixman_add_trapezoids _moz_pixman_add_trapezoids
#define pixman_rasterize_trapezoid _moz_pixman_rasterize_trapezoid
#define pixman_disable_out_of_bounds_workaround _moz_pixman_disable_out_of_bounds_workaround
#define pixman_f_transform_bounds _moz_pixman_f_transform_bounds
#define pixman_f_transform_from_pixman_transform _moz_pixman_f_transform_from_pixman_transform
#define pixman_f_transform_init_identity _moz_pixman_f_transform_init_identity
#define pixman_f_transform_init_rotate _moz_pixman_f_transform_init_rotate
#define pixman_f_transform_init_scale _moz_pixman_f_transform_init_scale
#define pixman_f_transform_init_translate _moz_pixman_f_transform_init_translate
#define pixman_f_transform_invert _moz_pixman_f_transform_invert
#define pixman_f_transform_multiply _moz_pixman_f_transform_multiply
#define pixman_f_transform_point _moz_pixman_f_transform_point
#define pixman_f_transform_point_3d _moz_pixman_f_transform_point_3d
#define pixman_f_transform_rotate _moz_pixman_f_transform_rotate
#define pixman_f_transform_scale _moz_pixman_f_transform_scale
#define pixman_f_transform_translate _moz_pixman_f_transform_translate
#define pixman_image_composite32 _moz_pixman_image_composite32
#define pixman_image_fill_boxes _moz_pixman_image_fill_boxes
#define pixman_image_get_component_alpha _moz_pixman_image_get_component_alpha
#define pixman_image_get_destroy_data _moz_pixman_image_get_destroy_data
#define pixman_image_get_format _moz_pixman_image_get_format
#define pixman_image_set_destroy_function _moz_pixman_image_set_destroy_function
#define pixman_region_init_from_image _moz_pixman_region_init_from_image
#define pixman_region_intersect_rect _moz_pixman_region_intersect_rect
#define pixman_transform_bounds _moz_pixman_transform_bounds
#define pixman_transform_from_pixman_f_transform _moz_pixman_transform_from_pixman_f_transform
#define pixman_transform_init_identity _moz_pixman_transform_init_identity
#define pixman_transform_init_rotate _moz_pixman_transform_init_rotate
#define pixman_transform_init_scale _moz_pixman_transform_init_scale
#define pixman_transform_init_translate _moz_pixman_transform_init_translate
#define pixman_transform_invert _moz_pixman_transform_invert
#define pixman_transform_is_identity _moz_pixman_transform_is_identity
#define pixman_transform_is_int_translate _moz_pixman_transform_is_int_translate
#define pixman_transform_is_inverse _moz_pixman_transform_is_inverse
#define pixman_transform_is_scale _moz_pixman_transform_is_scale
#define pixman_transform_multiply _moz_pixman_transform_multiply
#define pixman_transform_point _moz_pixman_transform_point
#define pixman_transform_rotate _moz_pixman_transform_rotate
#define pixman_transform_scale _moz_pixman_transform_scale
#define pixman_transform_translate _moz_pixman_transform_translate
#endif

View File

@ -85,7 +85,19 @@
/* In libxul builds we don't ever want to export pixman symbols */
#if 1
# define PIXMAN_EXPORT cairo_public
#include "prcpucfg.h"
#ifdef HAVE_VISIBILITY_HIDDEN_ATTRIBUTE
#define CVISIBILITY_HIDDEN __attribute__((visibility("hidden")))
#elif defined(__SUNPRO_C) && (__SUNPRO_C >= 0x550)
#define CVISIBILITY_HIDDEN __hidden
#else
#define CVISIBILITY_HIDDEN
#endif
/* In libxul builds we don't ever want to export cairo symbols */
#define PIXMAN_EXPORT extern CVISIBILITY_HIDDEN
#else
/* GCC visibility */

View File

@ -69,7 +69,10 @@ SOFTWARE.
#ifndef PIXMAN_H__
#define PIXMAN_H__
#include "cairo-platform.h"
#ifdef MOZILLA_VERSION
#include "cairo/pixman-rename.h"
#endif
#include <pixman-version.h>

File diff suppressed because it is too large Load Diff

View File

@ -19,122 +19,144 @@
class nsIntRegion;
/**
* Implementation of regions.
* A region is represented as circular double-linked list of nsRegion::RgnRect structures.
* Rectangles in this list do not overlap and are sorted by (y, x) coordinates.
#include "pixman.h"
/* For information on the internal representation look at pixman-region.c
*
* nsRegions use nscoord coordinates and nsRects.
* This replaces an older homebrew implementation of nsRegion. The
* representation used here may use more rectangles than nsRegion however, the
* representation is canonical. This means that there's no need for an
* Optimize() method because for a paticular region there is only one
* representation. This means that nsIntRegion will have more predictable
* performance characteristics than the old nsRegion and should not become
* degenerate.
*
* The pixman region code originates from X11 which has spread to a variety of
* projects including Qt, Gtk, Wine. It should perform reasonably well.
*/
class NS_GFX nsRegion
class nsRegionRectIterator;
class nsRegion
{
friend class nsRegionRectIterator;
friend class RgnRectMemoryAllocator;
// Special version of nsRect structure for speed optimizations in nsRegion code.
// Most important functions could be made inline and be sure that passed rectangles
// will always be non-empty.
//
// Do not add any new member variables to this structure!
// Otherwise it will break casts from nsRect to nsRectFast, which expect data parts to be identical.
struct nsRectFast : public nsRect
{
nsRectFast () {} // No need to call parent constructor to set default values
nsRectFast (int32_t aX, int32_t aY, int32_t aWidth, int32_t aHeight) : nsRect (aX, aY, aWidth, aHeight) {}
nsRectFast (const nsRect& aRect) : nsRect (aRect) {}
// Override nsRect methods to make them inline. Do not check for emptiness.
inline bool Contains (const nsRect& aRect) const;
inline bool Intersects (const nsRect& aRect) const;
inline bool IntersectRect (const nsRect& aRect1, const nsRect& aRect2);
inline void UnionRect (const nsRect& aRect1, const nsRect& aRect2);
};
struct RgnRect : public nsRectFast
{
RgnRect* prev;
RgnRect* next;
RgnRect () {} // No need to call parent constructor to set default values
RgnRect (int32_t aX, int32_t aY, int32_t aWidth, int32_t aHeight) : nsRectFast (aX, aY, aWidth, aHeight) {}
RgnRect (const nsRectFast& aRect) : nsRectFast (aRect) {}
void* operator new (size_t) CPP_THROW_NEW;
void operator delete (void* aRect, size_t);
RgnRect& operator = (const RgnRect& aRect) // Do not overwrite prev/next pointers
{
x = aRect.x;
y = aRect.y;
width = aRect.width;
height = aRect.height;
return *this;
}
};
public:
nsRegion () { Init (); }
nsRegion (const nsRect& aRect) { Init (); Copy (aRect); }
nsRegion (const nsRegion& aRegion) { Init (); Copy (aRegion); }
~nsRegion () { SetToElements (0); }
nsRegion () { pixman_region32_init(&mImpl); }
nsRegion (const nsRect& aRect) { pixman_region32_init_rect(&mImpl,
aRect.x,
aRect.y,
aRect.width,
aRect.height); }
nsRegion (const nsRegion& aRegion) { pixman_region32_init(&mImpl); pixman_region32_copy(&mImpl,aRegion.Impl()); }
~nsRegion () { pixman_region32_fini(&mImpl); }
nsRegion& operator = (const nsRect& aRect) { Copy (aRect); return *this; }
nsRegion& operator = (const nsRegion& aRegion) { Copy (aRegion); return *this; }
nsRegion& And (const nsRegion& aRgn1, const nsRegion& aRgn2);
nsRegion& And (const nsRegion& aRegion, const nsRect& aRect);
nsRegion& And (const nsRect& aRect, const nsRegion& aRegion)
bool operator==(const nsRegion& aRgn) const
{
return And (aRegion, aRect);
return IsEqual(aRgn);
}
nsRegion& And (const nsRect& aRect1, const nsRect& aRect2)
static
nsresult InitStatic()
{
return NS_OK;
}
static
void ShutdownStatic() {}
nsRegion& And(const nsRegion& aRgn1, const nsRegion& aRgn2)
{
pixman_region32_intersect(&mImpl, aRgn1.Impl(), aRgn2.Impl());
return *this;
}
nsRegion& And(const nsRect& aRect, const nsRegion& aRegion)
{
return And(aRegion, aRect);
}
nsRegion& And(const nsRegion& aRegion, const nsRect& aRect)
{
pixman_region32_intersect_rect(&mImpl, aRegion.Impl(), aRect.x, aRect.y, aRect.width, aRect.height);
return *this;
}
nsRegion& And(const nsRect& aRect1, const nsRect& aRect2)
{
nsRect TmpRect;
TmpRect.IntersectRect (aRect1, aRect2);
return Copy (TmpRect);
TmpRect.IntersectRect(aRect1, aRect2);
return Copy(TmpRect);
}
nsRegion& Or (const nsRegion& aRgn1, const nsRegion& aRgn2);
nsRegion& Or (const nsRegion& aRegion, const nsRect& aRect);
nsRegion& Or (const nsRect& aRect, const nsRegion& aRegion)
nsRegion& Or(const nsRegion& aRgn1, const nsRegion& aRgn2)
{
return Or (aRegion, aRect);
pixman_region32_union(&mImpl, aRgn1.Impl(), aRgn2.Impl());
return *this;
}
nsRegion& Or (const nsRect& aRect1, const nsRect& aRect2)
nsRegion& Or(const nsRegion& aRegion, const nsRect& aRect)
{
pixman_region32_union_rect(&mImpl, aRegion.Impl(), aRect.x, aRect.y, aRect.width, aRect.height);
return *this;
}
nsRegion& Or(const nsRect& aRect, const nsRegion& aRegion)
{
return Or(aRegion, aRect);
}
nsRegion& Or(const nsRect& aRect1, const nsRect& aRect2)
{
Copy (aRect1);
return Or (*this, aRect2);
}
nsRegion& Xor (const nsRegion& aRgn1, const nsRegion& aRgn2);
nsRegion& Xor (const nsRegion& aRegion, const nsRect& aRect);
nsRegion& Xor (const nsRect& aRect, const nsRegion& aRegion)
nsRegion& Xor(const nsRegion& aRgn1, const nsRegion& aRgn2)
{
return Xor (aRegion, aRect);
// this could be implemented better if pixman had direct
// support for xoring regions.
nsRegion p;
p.Sub(aRgn1, aRgn2);
nsRegion q;
q.Sub(aRgn2, aRgn1);
return Or(p, q);
}
nsRegion& Xor (const nsRect& aRect1, const nsRect& aRect2)
nsRegion& Xor(const nsRegion& aRegion, const nsRect& aRect)
{
Copy (aRect1);
return Xor (*this, aRect2);
return Xor(aRegion, nsRegion(aRect));
}
nsRegion& Xor(const nsRect& aRect, const nsRegion& aRegion)
{
return Xor(nsRegion(aRect), aRegion);
}
nsRegion& Xor(const nsRect& aRect1, const nsRect& aRect2)
{
return Xor(nsRegion(aRect1), nsRegion(aRect2));
}
nsRegion& Sub (const nsRegion& aRgn1, const nsRegion& aRgn2);
nsRegion& Sub (const nsRegion& aRegion, const nsRect& aRect);
nsRegion& Sub (const nsRect& aRect, const nsRegion& aRegion)
nsRegion ToAppUnits (nscoord aAppUnitsPerPixel) const;
nsRegion& Sub(const nsRegion& aRgn1, const nsRegion& aRgn2)
{
return Sub (nsRegion (aRect), aRegion);
pixman_region32_subtract(&mImpl, aRgn1.Impl(), aRgn2.Impl());
return *this;
}
nsRegion& Sub (const nsRect& aRect1, const nsRect& aRect2)
nsRegion& Sub(const nsRegion& aRegion, const nsRect& aRect)
{
Copy (aRect1);
return Sub (*this, aRect2);
return Sub(aRegion, nsRegion(aRect));
}
nsRegion& Sub(const nsRect& aRect, const nsRegion& aRegion)
{
return Sub(nsRegion(aRect), aRegion);
}
nsRegion& Sub(const nsRect& aRect1, const nsRect& aRect2)
{
Copy(aRect1);
return Sub(*this, aRect2);
}
bool Contains (const nsRect& aRect) const;
bool Contains (const nsRect& aRect) const
{
pixman_box32_t box = RectToBox(aRect);
return pixman_region32_contains_rectangle(Impl(), &box) == PIXMAN_REGION_IN;
}
bool Contains (const nsRegion& aRgn) const;
bool Intersects (const nsRect& aRect) const;
@ -142,18 +164,20 @@ public:
{
MoveBy (nsPoint (aXOffset, aYOffset));
}
void MoveBy (nsPoint aPt);
void MoveBy (nsPoint aPt) { pixman_region32_translate(&mImpl, aPt.x, aPt.y); }
void SetEmpty ()
{
SetToElements (0);
mBoundRect.SetRect (0, 0, 0, 0);
pixman_region32_clear(&mImpl);
}
bool IsEmpty () const { return mRectCount == 0; }
bool IsComplex () const { return mRectCount > 1; }
bool IsEqual (const nsRegion& aRegion) const;
uint32_t GetNumRects () const { return mRectCount; }
const nsRect& GetBounds () const { return mBoundRect; }
bool IsEmpty () const { return !pixman_region32_not_empty(Impl()); }
bool IsComplex () const { return GetNumRects() > 1; }
bool IsEqual (const nsRegion& aRegion) const
{
return pixman_region32_equal(Impl(), aRegion.Impl());
}
uint32_t GetNumRects () const { return pixman_region32_n_rects(Impl()); }
const nsRect GetBounds () const { return BoxToRect(mImpl.extents); }
uint64_t Area () const;
// Converts this region from aFromAPP, an appunits per pixel ratio, to
// aToAPP. This applies nsRect::ConvertAppUnitsRoundOut/In to each rect of
@ -189,95 +213,91 @@ public:
* original region.
*/
void SimplifyInward (uint32_t aMaxRects);
/**
* Efficiently try to remove a rectangle from this region. The actual
* area removed could be some sub-area contained by the rectangle
* (even possibly nothing at all).
*
* We remove all rectangles that are contained by aRect.
*/
void SimpleSubtract (const nsRect& aRect);
/**
* Efficiently try to remove a region from this region. The actual
* area removed could be some sub-area contained by aRegion
* (even possibly nothing at all).
*
* We remove all rectangles of this region that are contained by
* a rectangle of aRegion.
*/
void SimpleSubtract (const nsRegion& aRegion);
nsCString ToString() const;
/**
* Initialize any static data associated with nsRegion.
*/
static nsresult InitStatic();
/**
* Deinitialize static data.
*/
static void ShutdownStatic();
private:
uint32_t mRectCount;
RgnRect* mCurRect;
RgnRect mRectListHead;
nsRectFast mBoundRect;
pixman_region32_t mImpl;
void Init ();
nsRegion& Copy (const nsRegion& aRegion);
nsRegion& Copy (const nsRect& aRect);
void InsertBefore (RgnRect* aNewRect, RgnRect* aRelativeRect);
void InsertAfter (RgnRect* aNewRect, RgnRect* aRelativeRect);
void SetToElements (uint32_t aCount);
RgnRect* Remove (RgnRect* aRect);
void InsertInPlace (RgnRect* aRect, bool aOptimizeOnFly = false);
inline void SaveLinkChain ();
inline void RestoreLinkChain ();
void Optimize ();
void SubRegion (const nsRegion& aRegion, nsRegion& aResult) const;
void SubRect (const nsRectFast& aRect, nsRegion& aResult, nsRegion& aCompleted) const;
void SubRect (const nsRectFast& aRect, nsRegion& aResult) const
{ SubRect (aRect, aResult, aResult); }
void Merge (const nsRegion& aRgn1, const nsRegion& aRgn2);
void MoveInto (nsRegion& aDestRegion, const RgnRect* aStartRect);
void MoveInto (nsRegion& aDestRegion)
{ MoveInto (aDestRegion, mRectListHead.next); }
nsIntRegion ToPixels(nscoord aAppUnitsPerPixel, bool aOutsidePixels) const;
nsRegion& Copy (const nsRegion& aRegion)
{
pixman_region32_copy(&mImpl, aRegion.Impl());
return *this;
}
nsRegion& Copy (const nsRect& aRect)
{
pixman_box32_t box = RectToBox(aRect);
pixman_region32_reset(&mImpl, &box);
return *this;
}
static inline pixman_box32_t RectToBox(const nsRect &aRect)
{
pixman_box32_t box = { aRect.x, aRect.y, aRect.XMost(), aRect.YMost() };
return box;
}
static inline pixman_box32_t RectToBox(const nsIntRect &aRect)
{
pixman_box32_t box = { aRect.x, aRect.y, aRect.XMost(), aRect.YMost() };
return box;
}
static inline nsRect BoxToRect(const pixman_box32_t &aBox)
{
return nsRect(aBox.x1, aBox.y1,
aBox.x2 - aBox.x1,
aBox.y2 - aBox.y1);
}
pixman_region32_t* Impl() const
{
return const_cast<pixman_region32_t*>(&mImpl);
}
};
// Allow read-only access to region rectangles by iterating the list
class NS_GFX nsRegionRectIterator
{
const nsRegion* mRegion;
const nsRegion::RgnRect* mCurPtr;
int i;
int n;
nsRect rect;
pixman_box32_t *boxes;
public:
nsRegionRectIterator (const nsRegion& aRegion)
{
mRegion = &aRegion;
mCurPtr = &aRegion.mRectListHead;
i = 0;
boxes = pixman_region32_rectangles(aRegion.Impl(), &n);
}
const nsRect* Next ()
{
mCurPtr = mCurPtr->next;
return (mCurPtr != &mRegion->mRectListHead) ? mCurPtr : nullptr;
if (i == n)
return nullptr;
rect = nsRegion::BoxToRect(boxes[i]);
i++;
return &rect;
}
const nsRect* Prev ()
{
mCurPtr = mCurPtr->prev;
return (mCurPtr != &mRegion->mRectListHead) ? mCurPtr : nullptr;
if (i == -1)
return nullptr;
rect = nsRegion::BoxToRect(boxes[i]);
i--;
return &rect;
}
void Reset ()
{
mCurPtr = &mRegion->mRectListHead;
i = 0;
}
};
@ -287,6 +307,7 @@ public:
class NS_GFX nsIntRegion
{
friend class nsIntRegionRectIterator;
friend class nsRegion;
public:
nsIntRegion () {}
@ -449,29 +470,6 @@ public:
{
mImpl.SimplifyInward (aMaxRects);
}
/**
* Efficiently try to remove a rectangle from this region. The actual
* area removed could be some sub-area contained by the rectangle
* (even possibly nothing at all).
*
* We remove all rectangles that are contained by aRect.
*/
void SimpleSubtract (const nsIntRect& aRect)
{
mImpl.SimpleSubtract (ToRect (aRect));
}
/**
* Efficiently try to remove a region from this region. The actual
* area removed could be some sub-area contained by aRegion
* (even possibly nothing at all).
*
* We remove all rectangles of this region that are contained by
* a rectangle of aRegion.
*/
void SimpleSubtract (const nsIntRegion& aRegion)
{
mImpl.SimpleSubtract (aRegion.mImpl);
}
nsCString ToString() const { return mImpl.ToString(); }
@ -519,5 +517,4 @@ public:
mImpl.Reset ();
}
};
#endif

View File

@ -124,3 +124,50 @@ TEST(Gfx, RegionTestContainsSpecifiedOverflowingRect) {
TestLargestRegion::TestContainsSpecifiedOverflowingRect();
}
TEST(Gfx, RegionScaleToInside) {
{ // no rectangles
nsRegion r;
nsIntRegion scaled = r.ScaleToInsidePixels(1, 1, 60);
nsIntRegion result;
EXPECT_TRUE(result.IsEqual(scaled)) <<
"scaled result incorrect";
}
{ // one rectangle
nsRegion r(nsRect(0,44760,19096,264));
nsIntRegion scaled = r.ScaleToInsidePixels(1, 1, 60);
nsIntRegion result(nsIntRect(0,746,318,4));
EXPECT_TRUE(result.IsEqual(scaled)) <<
"scaled result incorrect";
}
{ // the first rectangle gets adjusted
nsRegion r(nsRect(0,44760,19096,264));
r.Or(r, nsRect(0,45024,19360,1056));
nsIntRegion scaled = r.ScaleToInsidePixels(1, 1, 60);
nsIntRegion result(nsIntRect(0,746,318,5));
result.Or(result, nsIntRect(0,751,322,17));
EXPECT_TRUE(result.IsEqual(scaled)) <<
"scaled result incorrect";
}
{ // the second rectangle gets adjusted
nsRegion r(nsRect(0,44760,19360,264));
r.Or(r, nsRect(0,45024,19096,1056));
nsIntRegion scaled = r.ScaleToInsidePixels(1, 1, 60);
nsIntRegion result(nsIntRect(0,746,322,4));
result.Or(result, nsIntRect(0,750,318,18));
EXPECT_TRUE(result.IsEqual(scaled)) <<
"scaled result incorrect";
}
}

View File

@ -486,6 +486,30 @@ _moz_pixman_image_set_transform
_moz_pixman_image_unref
_moz_pixman_transform_from_pixman_f_transform
_moz_pixman_transform_invert
_moz_pixman_region32_reset
_moz_pixman_region32_init
_moz_pixman_region32_init_rect
_moz_pixman_region32_init_rects
_moz_pixman_region32_init_with_extents
_moz_pixman_region32_fini
_moz_pixman_region32_translate
_moz_pixman_region32_copy
_moz_pixman_region32_intersect
_moz_pixman_region32_intersect_rect
_moz_pixman_region32_union
_moz_pixman_region32_union_rect
_moz_pixman_region32_subtract
_moz_pixman_region32_inverse
_moz_pixman_region32_contains_point
_moz_pixman_region32_contains_rectangle
_moz_pixman_region32_not_empty
_moz_pixman_region32_extents
_moz_pixman_region32_n_rects
_moz_pixman_region32_rectangles
_moz_pixman_region32_equal
_moz_pixman_region32_selfcheck
_moz_pixman_region32_reset
_moz_pixman_region32_clear
#endif
cairo_d2d_create_device
cairo_d2d_create_device_from_d3d10device

View File

@ -42,7 +42,7 @@ LOCAL_INCLUDES += -I$(srcdir)/win
endif
ifdef MOZ_ENABLE_DBUS
LOCAL_INCLUDES += $(TK_CFLAGS) $(MOZ_DBUS_CFLAGS)
OS_INCLUDES += $(TK_CFLAGS) $(MOZ_DBUS_CFLAGS)
endif
include $(topsrcdir)/config/rules.mk