gtk/gdk/quartz/gdkpixmap-quartz.c
Alexander Larsson eabac453e6 Initial client-side-windows work
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.
2009-04-02 10:14:01 +02:00

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;
}