[gtk+/gtk-2-22] Rework GdkPixmapImplQuartz to create CGImage on-demand
- From: Kristian Rietveld <kristian src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/gtk-2-22] Rework GdkPixmapImplQuartz to create CGImage on-demand
- Date: Mon, 18 Oct 2010 23:10:05 +0000 (UTC)
commit 6d77b7d5fafa76a9e679a7e3f462a4a7a2ad71bb
Author: Kristian Rietveld <kris gtk org>
Date: Tue Oct 19 00:47:33 2010 +0200
Rework GdkPixmapImplQuartz to create CGImage on-demand
If the data that backs a bitmap context changes, then the CGImage that
is backed by this data might not always update due to caching effects.
By creating the CGImage on-demand, we ascertain ourselves that the
CGImage is up to date.
gdk/quartz/gdkdrawable-quartz.c | 5 +-
gdk/quartz/gdkgc-quartz.c | 33 ++++---
gdk/quartz/gdkpixmap-quartz.c | 194 ++++++++++++++++++++++++++++-----------
gdk/quartz/gdkpixmap-quartz.h | 3 +-
gdk/quartz/gdkprivate-quartz.h | 3 +
5 files changed, 170 insertions(+), 68 deletions(-)
---
diff --git a/gdk/quartz/gdkdrawable-quartz.c b/gdk/quartz/gdkdrawable-quartz.c
index 2f03f2e..393658c 100644
--- a/gdk/quartz/gdkdrawable-quartz.c
+++ b/gdk/quartz/gdkdrawable-quartz.c
@@ -380,6 +380,7 @@ gdk_quartz_draw_drawable (GdkDrawable *drawable,
{
GdkPixmapImplQuartz *pixmap_impl = GDK_PIXMAP_IMPL_QUARTZ (src_impl);
CGContextRef context = gdk_quartz_drawable_get_context (drawable, FALSE);
+ CGImageRef image;
if (!context)
return;
@@ -392,9 +393,11 @@ gdk_quartz_draw_drawable (GdkDrawable *drawable,
pixmap_impl->height);
CGContextScaleCTM (context, 1.0, -1.0);
+ image = _gdk_pixmap_get_cgimage (src);
CGContextDrawImage (context,
CGRectMake (0, 0, pixmap_impl->width, pixmap_impl->height),
- pixmap_impl->image);
+ image);
+ CGImageRelease (image);
gdk_quartz_drawable_release_context (drawable, context);
}
diff --git a/gdk/quartz/gdkgc-quartz.c b/gdk/quartz/gdkgc-quartz.c
index 9cddd74..eaf4be3 100644
--- a/gdk/quartz/gdkgc-quartz.c
+++ b/gdk/quartz/gdkgc-quartz.c
@@ -84,7 +84,7 @@ create_clip_mask (GdkPixmap *source_pixmap)
* future, we would look into doing this by hand on the actual raw
* data.
*/
- source = GDK_PIXMAP_IMPL_QUARTZ (GDK_PIXMAP_OBJECT (source_pixmap)->impl)->image;
+ source = _gdk_pixmap_get_cgimage (source_pixmap);
width = CGImageGetWidth (source);
height = CGImageGetHeight (source);
@@ -322,8 +322,7 @@ _gdk_windowing_gc_copy (GdkGC *dst_gc,
}
if (src_quartz_gc->clip_mask)
- dst_quartz_gc->clip_mask =
- CGImageCreateCopy (GDK_PIXMAP_IMPL_QUARTZ (GDK_PIXMAP_OBJECT (src_quartz_gc->clip_mask)->impl)->image);
+ dst_quartz_gc->clip_mask = _gdk_pixmap_get_cgimage (GDK_PIXMAP (src_quartz_gc->clip_mask));
dst_quartz_gc->line_width = src_quartz_gc->line_width;
dst_quartz_gc->line_style = src_quartz_gc->line_style;
@@ -364,7 +363,7 @@ gdk_quartz_draw_tiled_pattern (void *info,
CGImageRef pattern_image;
size_t width, height;
- pattern_image = GDK_PIXMAP_IMPL_QUARTZ (GDK_PIXMAP_OBJECT (_gdk_gc_get_tile (gc))->impl)->image;
+ pattern_image = _gdk_pixmap_get_cgimage (GDK_PIXMAP_OBJECT (_gdk_gc_get_tile (gc))->impl);
width = CGImageGetWidth (pattern_image);
height = CGImageGetHeight (pattern_image);
@@ -372,6 +371,7 @@ gdk_quartz_draw_tiled_pattern (void *info,
CGContextDrawImage (context,
CGRectMake (0, 0, width, height),
pattern_image);
+ CGImageRelease (pattern_image);
}
static void
@@ -384,7 +384,7 @@ gdk_quartz_draw_stippled_pattern (void *info,
CGRect rect;
CGColorRef color;
- pattern_image = GDK_PIXMAP_IMPL_QUARTZ (GDK_PIXMAP_OBJECT (_gdk_gc_get_stipple (gc))->impl)->image;
+ pattern_image = _gdk_pixmap_get_cgimage (GDK_PIXMAP_OBJECT (_gdk_gc_get_stipple (gc))->impl);
rect = CGRectMake (0, 0,
CGImageGetWidth (pattern_image),
CGImageGetHeight (pattern_image));
@@ -396,6 +396,8 @@ gdk_quartz_draw_stippled_pattern (void *info,
CGColorRelease (color);
CGContextFillRect (context, rect);
+
+ CGImageRelease (pattern_image);
}
static void
@@ -408,7 +410,7 @@ gdk_quartz_draw_opaque_stippled_pattern (void *info,
CGRect rect;
CGColorRef color;
- pattern_image = GDK_PIXMAP_IMPL_QUARTZ (GDK_PIXMAP_OBJECT (_gdk_gc_get_stipple (gc))->impl)->image;
+ pattern_image = _gdk_pixmap_get_cgimage (GDK_PIXMAP_OBJECT (_gdk_gc_get_stipple (gc))->impl);
rect = CGRectMake (0, 0,
CGImageGetWidth (pattern_image),
CGImageGetHeight (pattern_image));
@@ -427,6 +429,8 @@ gdk_quartz_draw_opaque_stippled_pattern (void *info,
CGColorRelease (color);
CGContextFillRect (context, rect);
+
+ CGImageRelease (pattern_image);
}
void
@@ -611,12 +615,12 @@ _gdk_quartz_gc_update_cg_context (GdkGC *gc,
{
if (!private->ts_pattern)
{
- CGImageRef pattern_image = NULL;
gfloat width, height;
gboolean is_colored = FALSE;
CGPatternCallbacks callbacks = { 0, NULL, NULL };
struct PatternCallbackInfo *info;
CGPoint phase;
+ GdkPixmapImplQuartz *pix_impl = NULL;
info = g_new (struct PatternCallbackInfo, 1);
/* Won't ref to avoid circular dependencies */
@@ -628,17 +632,23 @@ _gdk_quartz_gc_update_cg_context (GdkGC *gc,
switch (fill)
{
case GDK_TILED:
- pattern_image = GDK_PIXMAP_IMPL_QUARTZ (GDK_PIXMAP_OBJECT (_gdk_gc_get_tile (gc))->impl)->image;
+ pix_impl = GDK_PIXMAP_IMPL_QUARTZ (GDK_PIXMAP_OBJECT (_gdk_gc_get_tile (gc))->impl);
+ width = pix_impl->width;
+ height = pix_impl->height;
is_colored = TRUE;
callbacks.drawPattern = gdk_quartz_draw_tiled_pattern;
break;
case GDK_STIPPLED:
- pattern_image = GDK_PIXMAP_IMPL_QUARTZ (GDK_PIXMAP_OBJECT (_gdk_gc_get_stipple (gc))->impl)->image;
+ pix_impl = GDK_PIXMAP_IMPL_QUARTZ (GDK_PIXMAP_OBJECT (_gdk_gc_get_stipple (gc))->impl);
+ width = pix_impl->width;
+ height = pix_impl->height;
is_colored = FALSE;
callbacks.drawPattern = gdk_quartz_draw_stippled_pattern;
break;
case GDK_OPAQUE_STIPPLED:
- pattern_image = GDK_PIXMAP_IMPL_QUARTZ (GDK_PIXMAP_OBJECT (_gdk_gc_get_stipple (gc))->impl)->image;
+ pix_impl = GDK_PIXMAP_IMPL_QUARTZ (GDK_PIXMAP_OBJECT (_gdk_gc_get_stipple (gc))->impl);
+ width = pix_impl->width;
+ height = pix_impl->height;
is_colored = TRUE;
callbacks.drawPattern = gdk_quartz_draw_opaque_stippled_pattern;
break;
@@ -646,9 +656,6 @@ _gdk_quartz_gc_update_cg_context (GdkGC *gc,
break;
}
- width = CGImageGetWidth (pattern_image);
- height = CGImageGetHeight (pattern_image);
-
phase = CGPointApplyAffineTransform (CGPointMake (gc->ts_x_origin, gc->ts_y_origin), CGContextGetCTM (context));
CGContextSetPatternPhase (context, CGSizeMake (phase.x, phase.y));
diff --git a/gdk/quartz/gdkpixmap-quartz.c b/gdk/quartz/gdkpixmap-quartz.c
index 5818d7c..9bf318e 100644
--- a/gdk/quartz/gdkpixmap-quartz.c
+++ b/gdk/quartz/gdkpixmap-quartz.c
@@ -41,27 +41,105 @@ gdk_pixmap_impl_quartz_get_size (GdkDrawable *drawable,
*height = GDK_PIXMAP_IMPL_QUARTZ (drawable)->height;
}
+static void
+gdk_pixmap_impl_quartz_get_image_parameters (GdkPixmap *pixmap,
+ gint *bits_per_component,
+ gint *bits_per_pixel,
+ gint *bytes_per_row,
+ CGColorSpaceRef *colorspace,
+ CGImageAlphaInfo *alpha_info)
+{
+ GdkPixmapImplQuartz *impl = GDK_PIXMAP_IMPL_QUARTZ (GDK_PIXMAP_OBJECT (pixmap)->impl);
+ gint depth = GDK_PIXMAP_OBJECT (pixmap)->depth;
+
+ switch (depth)
+ {
+ case 24:
+ if (bits_per_component)
+ *bits_per_component = 8;
+
+ if (bits_per_pixel)
+ *bits_per_pixel = 32;
+
+ if (bytes_per_row)
+ *bytes_per_row = impl->width * 4;
+
+ if (colorspace)
+ *colorspace = CGColorSpaceCreateDeviceRGB ();
+
+ if (alpha_info)
+ *alpha_info = kCGImageAlphaNoneSkipLast;
+ break;
+
+ case 32:
+ if (bits_per_component)
+ *bits_per_component = 8;
+
+ if (bits_per_pixel)
+ *bits_per_pixel = 32;
+
+ if (bytes_per_row)
+ *bytes_per_row = impl->width * 4;
+
+ if (colorspace)
+ *colorspace = CGColorSpaceCreateDeviceRGB ();
+
+ if (alpha_info)
+ *alpha_info = kCGImageAlphaPremultipliedFirst;
+ break;
+
+ case 1:
+ if (bits_per_component)
+ *bits_per_component = 8;
+
+ if (bits_per_pixel)
+ *bits_per_pixel = 8;
+
+ if (bytes_per_row)
+ *bytes_per_row = impl->width;
+
+ if (colorspace)
+ *colorspace = CGColorSpaceCreateDeviceGray ();
+
+ if (alpha_info)
+ *alpha_info = kCGImageAlphaNone;
+ break;
+
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+}
+
static CGContextRef
gdk_pixmap_impl_quartz_get_context (GdkDrawable *drawable,
gboolean antialias)
{
GdkPixmapImplQuartz *impl = GDK_PIXMAP_IMPL_QUARTZ (drawable);
CGContextRef cg_context;
- size_t height;
+ gint bits_per_component, bytes_per_row;
+ CGColorSpaceRef colorspace;
+ CGImageAlphaInfo alpha_info;
+
+ gdk_pixmap_impl_quartz_get_image_parameters (GDK_DRAWABLE_IMPL_QUARTZ (drawable)->wrapper,
+ &bits_per_component,
+ NULL,
+ &bytes_per_row,
+ &colorspace,
+ &alpha_info);
cg_context = CGBitmapContextCreate (impl->data,
- CGImageGetWidth (impl->image),
- CGImageGetHeight (impl->image),
- CGImageGetBitsPerComponent (impl->image),
- CGImageGetBytesPerRow (impl->image),
- CGImageGetColorSpace (impl->image),
- CGImageGetBitmapInfo (impl->image));
+ impl->width, impl->height,
+ bits_per_component,
+ bytes_per_row,
+ colorspace,
+ alpha_info);
CGContextSetAllowsAntialiasing (cg_context, antialias);
- /* convert coordinates from core graphics to gtk+ */
- height = CGImageGetHeight (impl->image);
+ CGColorSpaceRelease (colorspace);
- CGContextTranslateCTM (cg_context, 0, height);
+ /* convert coordinates from core graphics to gtk+ */
+ CGContextTranslateCTM (cg_context, 0, impl->height);
CGContextScaleCTM (cg_context, 1.0, -1.0);
return cg_context;
@@ -72,7 +150,7 @@ gdk_pixmap_impl_quartz_finalize (GObject *object)
{
GdkPixmapImplQuartz *impl = GDK_PIXMAP_IMPL_QUARTZ (object);
- CGImageRelease (impl->image);
+ CGDataProviderRelease (impl->data_provider);
_gdk_quartz_drawable_finish (GDK_DRAWABLE (impl));
@@ -130,6 +208,45 @@ _gdk_pixmap_impl_get_type (void)
return _gdk_pixmap_impl_quartz_get_type ();
}
+static inline gboolean
+depth_supported (int depth)
+{
+ if (depth != 24 && depth != 32 && depth != 1)
+ {
+ g_warning ("Unsupported bit depth %d\n", depth);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+CGImageRef
+_gdk_pixmap_get_cgimage (GdkPixmap *pixmap)
+{
+ GdkPixmapImplQuartz *impl = GDK_PIXMAP_IMPL_QUARTZ (GDK_PIXMAP_OBJECT (pixmap)->impl);
+ gint bits_per_component, bits_per_pixel, bytes_per_row;
+ CGColorSpaceRef colorspace;
+ CGImageAlphaInfo alpha_info;
+ CGImageRef image;
+
+ gdk_pixmap_impl_quartz_get_image_parameters (pixmap,
+ &bits_per_component,
+ &bits_per_pixel,
+ &bytes_per_row,
+ &colorspace,
+ &alpha_info);
+
+ image = CGImageCreate (impl->width, impl->height,
+ bits_per_component, bits_per_pixel,
+ bytes_per_row, colorspace,
+ alpha_info,
+ impl->data_provider, NULL, FALSE,
+ kCGRenderingIntentDefault);
+ CGColorSpaceRelease (colorspace);
+
+ return image;
+}
+
static void
data_provider_release (void *info, const void *data, size_t size)
{
@@ -146,10 +263,7 @@ _gdk_pixmap_new (GdkDrawable *drawable,
GdkDrawableImplQuartz *draw_impl;
GdkPixmapImplQuartz *pix_impl;
gint window_depth;
- CGColorSpaceRef colorspace;
- CGDataProviderRef data_provider;
- CGImageAlphaInfo alpha_info;
- gint bytes_per_row, bits_per_pixel;
+ gint bytes_per_row;
g_return_val_if_fail (drawable == NULL || GDK_IS_DRAWABLE (drawable), NULL);
g_return_val_if_fail ((drawable != NULL) || (depth != -1), NULL);
@@ -166,30 +280,8 @@ _gdk_pixmap_new (GdkDrawable *drawable,
if (depth == -1)
depth = window_depth;
- switch (depth)
- {
- case 24:
- alpha_info = kCGImageAlphaNoneSkipLast;
- bytes_per_row = width * 4;
- bits_per_pixel = 32;
- colorspace = CGColorSpaceCreateDeviceRGB ();
- break;
- case 32:
- alpha_info = kCGImageAlphaPremultipliedFirst;
- bytes_per_row = width * 4;
- bits_per_pixel = 32;
- colorspace = CGColorSpaceCreateDeviceRGB ();
- break;
- case 1:
- alpha_info = kCGImageAlphaNone;
- bytes_per_row = width;
- bits_per_pixel = 8;
- colorspace = CGColorSpaceCreateDeviceGray ();
- break;
- default:
- g_warning ("Unsupported bit depth %d\n", depth);
- return NULL;
- }
+ if (!depth_supported (depth))
+ return NULL;
pixmap = g_object_new (gdk_pixmap_get_type (), NULL);
draw_impl = GDK_DRAWABLE_IMPL_QUARTZ (GDK_PIXMAP_OBJECT (pixmap)->impl);
@@ -198,21 +290,21 @@ _gdk_pixmap_new (GdkDrawable *drawable,
g_assert (depth == 24 || depth == 32 || depth == 1);
- pix_impl->data = g_malloc (height * bytes_per_row);
- data_provider = CGDataProviderCreateWithData (pix_impl->data, pix_impl->data,
- height * bytes_per_row, data_provider_release);
- pix_impl->image = CGImageCreate (width, height, 8, bits_per_pixel,
- bytes_per_row, colorspace,
- alpha_info,
- data_provider, NULL, FALSE,
- kCGRenderingIntentDefault);
- CGDataProviderRelease (data_provider);
- CGColorSpaceRelease (colorspace);
-
pix_impl->width = width;
pix_impl->height = height;
GDK_PIXMAP_OBJECT (pixmap)->depth = depth;
+ gdk_pixmap_impl_quartz_get_image_parameters (pixmap,
+ NULL, NULL,
+ &bytes_per_row,
+ NULL, NULL);
+
+ pix_impl->data = g_malloc (height * bytes_per_row);
+ pix_impl->data_provider = CGDataProviderCreateWithData (pix_impl->data,
+ pix_impl->data,
+ height * bytes_per_row,
+ data_provider_release);
+
if (depth == window_depth) {
GdkColormap *colormap = gdk_drawable_get_colormap (drawable);
@@ -240,8 +332,6 @@ _gdk_bitmap_create_from_data (GdkDrawable *window,
pixmap = gdk_pixmap_new (window, width, height, 1);
impl = GDK_PIXMAP_IMPL_QUARTZ (GDK_PIXMAP_OBJECT (pixmap)->impl);
- g_assert (CGImageGetBytesPerRow (impl->image) == width);
-
/* Bytes per line: Each line consumes an integer number of bytes, possibly
* ignoring any excess bits. */
bpl = (width + 7) / 8;
diff --git a/gdk/quartz/gdkpixmap-quartz.h b/gdk/quartz/gdkpixmap-quartz.h
index bb2122a..13cb99f 100644
--- a/gdk/quartz/gdkpixmap-quartz.h
+++ b/gdk/quartz/gdkpixmap-quartz.h
@@ -48,8 +48,7 @@ struct _GdkPixmapImplQuartz
gint height;
void *data;
-
- CGImageRef image;
+ CGDataProviderRef data_provider;
};
struct _GdkPixmapImplQuartzClass
diff --git a/gdk/quartz/gdkprivate-quartz.h b/gdk/quartz/gdkprivate-quartz.h
index ab80332..56379a9 100644
--- a/gdk/quartz/gdkprivate-quartz.h
+++ b/gdk/quartz/gdkprivate-quartz.h
@@ -209,4 +209,7 @@ void _gdk_quartz_window_queue_translation (GdkWindow *window,
gboolean _gdk_quartz_window_queue_antiexpose (GdkWindow *window,
GdkRegion *area);
+/* Pixmap */
+CGImageRef _gdk_pixmap_get_cgimage (GdkPixmap *pixmap);
+
#endif /* __GDK_PRIVATE_QUARTZ_H__ */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]