forked from AuroraMiddleware/gtk
eabac453e6
The history before this was kind of twisted as several different approaches were tested, so that was all squashed into this initial commit to hide the uninteresting changes and files that were later removed.
314 lines
8.6 KiB
C
314 lines
8.6 KiB
C
/* gdkpixmap-quartz.c
|
|
*
|
|
* Copyright (C) 2005 Imendio AB
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the
|
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
* Boston, MA 02111-1307, USA.
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include "gdkpixmap.h"
|
|
#include "gdkprivate-quartz.h"
|
|
|
|
static gpointer parent_class;
|
|
|
|
static void
|
|
gdk_pixmap_impl_quartz_init (GdkPixmapImplQuartz *impl)
|
|
{
|
|
}
|
|
|
|
static void
|
|
gdk_pixmap_impl_quartz_get_size (GdkDrawable *drawable,
|
|
gint *width,
|
|
gint *height)
|
|
{
|
|
if (width)
|
|
*width = GDK_PIXMAP_IMPL_QUARTZ (drawable)->width;
|
|
if (height)
|
|
*height = GDK_PIXMAP_IMPL_QUARTZ (drawable)->height;
|
|
}
|
|
|
|
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;
|
|
|
|
cg_context = CGBitmapContextCreate (impl->data,
|
|
CGImageGetWidth (impl->image),
|
|
CGImageGetHeight (impl->image),
|
|
CGImageGetBitsPerComponent (impl->image),
|
|
CGImageGetBytesPerRow (impl->image),
|
|
CGImageGetColorSpace (impl->image),
|
|
CGImageGetBitmapInfo (impl->image));
|
|
CGContextSetAllowsAntialiasing (cg_context, antialias);
|
|
|
|
/* convert coordinates from core graphics to gtk+ */
|
|
height = CGImageGetHeight (impl->image);
|
|
|
|
CGContextTranslateCTM (cg_context, 0, height);
|
|
CGContextScaleCTM (cg_context, 1.0, -1.0);
|
|
|
|
return cg_context;
|
|
}
|
|
|
|
static void
|
|
gdk_pixmap_impl_quartz_finalize (GObject *object)
|
|
{
|
|
GdkPixmapImplQuartz *impl = GDK_PIXMAP_IMPL_QUARTZ (object);
|
|
|
|
CGImageRelease (impl->image);
|
|
|
|
_gdk_quartz_drawable_finish (GDK_DRAWABLE (impl));
|
|
|
|
G_OBJECT_CLASS (parent_class)->finalize (object);
|
|
}
|
|
|
|
static void
|
|
gdk_pixmap_impl_quartz_class_init (GdkPixmapImplQuartzClass *klass)
|
|
{
|
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
GdkDrawableClass *drawable_class = GDK_DRAWABLE_CLASS (klass);
|
|
GdkDrawableImplQuartzClass *drawable_quartz_class = GDK_DRAWABLE_IMPL_QUARTZ_CLASS (klass);
|
|
|
|
parent_class = g_type_class_peek_parent (klass);
|
|
|
|
object_class->finalize = gdk_pixmap_impl_quartz_finalize;
|
|
|
|
drawable_class->get_size = gdk_pixmap_impl_quartz_get_size;
|
|
|
|
drawable_quartz_class->get_context = gdk_pixmap_impl_quartz_get_context;
|
|
}
|
|
|
|
GType
|
|
_gdk_pixmap_impl_quartz_get_type (void)
|
|
{
|
|
static GType object_type = 0;
|
|
|
|
if (!object_type)
|
|
{
|
|
static const GTypeInfo object_info =
|
|
{
|
|
sizeof (GdkPixmapImplQuartzClass),
|
|
(GBaseInitFunc) NULL,
|
|
(GBaseFinalizeFunc) NULL,
|
|
(GClassInitFunc) gdk_pixmap_impl_quartz_class_init,
|
|
NULL, /* class_finalize */
|
|
NULL, /* class_data */
|
|
sizeof (GdkPixmapImplQuartz),
|
|
0, /* n_preallocs */
|
|
(GInstanceInitFunc) gdk_pixmap_impl_quartz_init
|
|
};
|
|
|
|
object_type = g_type_register_static (GDK_TYPE_DRAWABLE_IMPL_QUARTZ,
|
|
"GdkPixmapImplQuartz",
|
|
&object_info,
|
|
0);
|
|
}
|
|
|
|
return object_type;
|
|
}
|
|
|
|
GType
|
|
_gdk_pixmap_impl_get_type (void)
|
|
{
|
|
return _gdk_pixmap_impl_quartz_get_type ();
|
|
}
|
|
|
|
static void
|
|
data_provider_release (void *info, const void *data, size_t size)
|
|
{
|
|
g_free (info);
|
|
}
|
|
|
|
GdkPixmap*
|
|
_gdk_pixmap_new (GdkDrawable *drawable,
|
|
gint width,
|
|
gint height,
|
|
gint depth)
|
|
{
|
|
GdkPixmap *pixmap;
|
|
GdkDrawableImplQuartz *draw_impl;
|
|
GdkPixmapImplQuartz *pix_impl;
|
|
gint window_depth;
|
|
CGColorSpaceRef colorspace;
|
|
CGDataProviderRef data_provider;
|
|
CGImageAlphaInfo alpha_info;
|
|
gint bytes_per_row, bits_per_pixel;
|
|
|
|
g_return_val_if_fail (drawable == NULL || GDK_IS_DRAWABLE (drawable), NULL);
|
|
g_return_val_if_fail ((drawable != NULL) || (depth != -1), NULL);
|
|
g_return_val_if_fail ((width != 0) && (height != 0), NULL);
|
|
|
|
if (GDK_IS_WINDOW (drawable) && GDK_WINDOW_DESTROYED (drawable))
|
|
return NULL;
|
|
|
|
if (!drawable)
|
|
drawable = gdk_screen_get_root_window (gdk_screen_get_default ());
|
|
|
|
window_depth = gdk_drawable_get_depth (GDK_DRAWABLE (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;
|
|
}
|
|
|
|
pixmap = g_object_new (gdk_pixmap_get_type (), NULL);
|
|
draw_impl = GDK_DRAWABLE_IMPL_QUARTZ (GDK_PIXMAP_OBJECT (pixmap)->impl);
|
|
pix_impl = GDK_PIXMAP_IMPL_QUARTZ (GDK_PIXMAP_OBJECT (pixmap)->impl);
|
|
draw_impl->wrapper = GDK_DRAWABLE (pixmap);
|
|
|
|
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;
|
|
|
|
if (depth == window_depth) {
|
|
GdkColormap *colormap = gdk_drawable_get_colormap (drawable);
|
|
|
|
if (colormap)
|
|
gdk_drawable_set_colormap (pixmap, colormap);
|
|
}
|
|
|
|
return pixmap;
|
|
}
|
|
|
|
GdkPixmap *
|
|
_gdk_bitmap_create_from_data (GdkDrawable *window,
|
|
const gchar *data,
|
|
gint width,
|
|
gint height)
|
|
{
|
|
GdkPixmap *pixmap;
|
|
GdkPixmapImplQuartz *impl;
|
|
int x, y, bpl;
|
|
|
|
g_return_val_if_fail (data != NULL, NULL);
|
|
g_return_val_if_fail ((width != 0) && (height != 0), NULL);
|
|
g_return_val_if_fail (window == NULL || GDK_IS_DRAWABLE (window), NULL);
|
|
|
|
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;
|
|
for (y = 0; y < height; y++)
|
|
{
|
|
guchar *dst = impl->data + y * width;
|
|
const gchar *src = data + (y * bpl);
|
|
for (x = 0; x < width; x++)
|
|
{
|
|
if ((src[x / 8] >> x % 8) & 1)
|
|
*dst = 0xff;
|
|
else
|
|
*dst = 0;
|
|
|
|
dst++;
|
|
}
|
|
}
|
|
|
|
return pixmap;
|
|
}
|
|
|
|
GdkPixmap*
|
|
_gdk_pixmap_create_from_data (GdkDrawable *drawable,
|
|
const gchar *data,
|
|
gint width,
|
|
gint height,
|
|
gint depth,
|
|
const GdkColor *fg,
|
|
const GdkColor *bg)
|
|
{
|
|
/* FIXME: Implement */
|
|
return NULL;
|
|
}
|
|
|
|
GdkPixmap *
|
|
gdk_pixmap_foreign_new_for_display (GdkDisplay *display,
|
|
GdkNativeWindow anid)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
GdkPixmap*
|
|
gdk_pixmap_foreign_new (GdkNativeWindow anid)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
GdkPixmap *
|
|
gdk_pixmap_foreign_new_for_screen (GdkScreen *screen,
|
|
GdkNativeWindow anid,
|
|
gint width,
|
|
gint height,
|
|
gint depth)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
GdkPixmap*
|
|
gdk_pixmap_lookup (GdkNativeWindow anid)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
GdkPixmap*
|
|
gdk_pixmap_lookup_for_display (GdkDisplay *display, GdkNativeWindow anid)
|
|
{
|
|
g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
|
|
return NULL;
|
|
}
|