[gtk/wip/chergert/macos-fixes] macos: precalculate clip regions as CGRect
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/wip/chergert/macos-fixes] macos: precalculate clip regions as CGRect
- Date: Fri, 4 Feb 2022 17:33:01 +0000 (UTC)
commit 8ea0a4fc5096907df8dc3be9a9216891a5cda6a4
Author: Christian Hergert <christian hergert me>
Date: Fri Feb 4 09:31:37 2022 -0800
macos: precalculate clip regions as CGRect
We can make our drawRect do less work if we precalculate the clip
and damage regions upfront by intersecting them with the bounds.
gdk/macos/GdkMacosCairoSubview.c | 87 ++++++++++++++++++++++------------------
gdk/macos/GdkMacosCairoSubview.h | 9 +++--
2 files changed, 53 insertions(+), 43 deletions(-)
---
diff --git a/gdk/macos/GdkMacosCairoSubview.c b/gdk/macos/GdkMacosCairoSubview.c
index af22e89887..fddb0ed0c0 100644
--- a/gdk/macos/GdkMacosCairoSubview.c
+++ b/gdk/macos/GdkMacosCairoSubview.c
@@ -32,7 +32,8 @@
-(void)dealloc
{
- g_clear_pointer (&self->clip, cairo_region_destroy);
+ g_clear_pointer (&self->clip, g_array_unref);
+ g_clear_pointer (&self->damage, g_array_unref);
g_clear_pointer (&self->image, CGImageRelease);
[super dealloc];
}
@@ -75,21 +76,18 @@
* to the self->clip region. This is usually just on the views
* for the shadow areas.
*/
+ CGContextAddRect (cgContext, [self bounds]);
if (self->clip != NULL)
{
- guint n_rects = cairo_region_num_rectangles (self->clip);
-
- for (guint i = 0; i < n_rects; i++)
- {
- cairo_rectangle_int_t area;
-
- cairo_region_get_rectangle (self->clip, i, &area);
- CGContextAddRect (cgContext,
- CGRectMake (area.x, area.y, area.width, area.height));
- }
-
- CGContextClip (cgContext);
+ for (guint i = 0; i < self->clip->len; i++)
+ CGContextAddRect (cgContext, g_array_index (self->clip, CGRect, i));
}
+ if (self->damage != NULL)
+ {
+ for (guint i = 0; i < self->damage->len; i++)
+ CGContextAddRect (cgContext, g_array_index (self->damage, CGRect, i));
+ }
+ CGContextClip (cgContext);
/* Scale/Translate so that the CGImageRef draws in proper format/placement */
scale = CGSizeMake (1.0, 1.0);
@@ -115,28 +113,7 @@
image = CGImageRetain (theImage);
}
- if (region != NULL)
- {
- NSView *root_view = [[self window] contentView];
- NSRect abs_bounds = [self convertRect:[self bounds] toView:root_view];
- guint n_rects = cairo_region_num_rectangles (region);
-
- for (guint i = 0; i < n_rects; i++)
- {
- cairo_rectangle_int_t rect;
- NSRect nsrect;
-
- cairo_region_get_rectangle (region, i, &rect);
- nsrect = NSMakeRect (rect.x, rect.y, rect.width, rect.height);
-
- if (NSIntersectsRect (abs_bounds, nsrect))
- {
- nsrect.origin.x -= abs_bounds.origin.x;
- nsrect.origin.y -= abs_bounds.origin.y;
- [self setNeedsDisplayInRect:nsrect];
- }
- }
- }
+ [self convertRegion:region toArray:&self->damage andDisplay:YES];
for (id view in [self subviews])
[(GdkMacosCairoSubview *)view setImage:theImage withDamage:region];
@@ -147,14 +124,44 @@
self->_isOpaque = opaque;
}
--(void)setClip:(cairo_region_t*)region
+-(void)convertRegion:(const cairo_region_t *)region
+ toArray:(GArray **)array
+ andDisplay:(BOOL)display
{
- if (region != self->clip)
+ NSView *root_view;
+ CGRect abs_bounds;
+ guint n_rects;
+
+ if (*array == NULL)
+ *array = g_array_new (FALSE, FALSE, sizeof (CGRect));
+ else
+ g_array_set_size (*array, 0);
+
+ root_view = [[self window] contentView];
+ abs_bounds = [self convertRect:[self bounds] toView:root_view];
+ n_rects = cairo_region_num_rectangles (region);
+
+ for (guint i = 0; i < n_rects; i++)
{
- g_clear_pointer (&self->clip, cairo_region_destroy);
- if (region != NULL)
- self->clip = cairo_region_reference (region);
+ cairo_rectangle_int_t rect;
+ CGRect nsrect;
+
+ cairo_region_get_rectangle (region, i, &rect);
+ nsrect = CGRectIntersection (abs_bounds, CGRectMake (rect.x, rect.y, rect.width, rect.height));
+
+ if (!CGRectIsNull (nsrect))
+ g_array_append_val (*array, nsrect);
+
+ if (display)
+ [self setNeedsDisplayInRect:CGRectMake (rect.x - abs_bounds.origin.x,
+ rect.y - abs_bounds.origin.y,
+ rect.width, rect.height)];
}
}
+-(void)setClip:(cairo_region_t*)region
+{
+ [self convertRegion:region toArray:&self->clip andDisplay:NO];
+}
+
@end
diff --git a/gdk/macos/GdkMacosCairoSubview.h b/gdk/macos/GdkMacosCairoSubview.h
index e6fda6ac43..e03b47727d 100644
--- a/gdk/macos/GdkMacosCairoSubview.h
+++ b/gdk/macos/GdkMacosCairoSubview.h
@@ -19,14 +19,17 @@
*/
#include <AppKit/AppKit.h>
+#include <cairo.h>
+#include <glib.h>
#define GDK_IS_MACOS_CAIRO_SUBVIEW(obj) ((obj) && [obj isKindOfClass:[GdkMacosCairoSubview class]])
@interface GdkMacosCairoSubview : NSView
{
- BOOL _isOpaque;
- cairo_region_t *clip;
- CGImageRef image;
+ BOOL _isOpaque;
+ GArray *clip;
+ GArray *damage;
+ CGImageRef image;
}
-(void)setOpaque:(BOOL)opaque;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]