]> Pileus Git - ~andy/gtk/blob - gdk/quartz/gdkpixmap-quartz.c
Initial client-side-windows work
[~andy/gtk] / gdk / quartz / gdkpixmap-quartz.c
1 /* gdkpixmap-quartz.c
2  *
3  * Copyright (C) 2005 Imendio AB
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  */
20
21 #include "config.h"
22
23 #include "gdkpixmap.h"
24 #include "gdkprivate-quartz.h"
25
26 static gpointer parent_class;
27
28 static void
29 gdk_pixmap_impl_quartz_init (GdkPixmapImplQuartz *impl)
30 {
31 }
32
33 static void
34 gdk_pixmap_impl_quartz_get_size (GdkDrawable *drawable,
35                                 gint        *width,
36                                 gint        *height)
37 {
38   if (width)
39     *width = GDK_PIXMAP_IMPL_QUARTZ (drawable)->width;
40   if (height)
41     *height = GDK_PIXMAP_IMPL_QUARTZ (drawable)->height;
42 }
43
44 static CGContextRef
45 gdk_pixmap_impl_quartz_get_context (GdkDrawable *drawable,
46                                     gboolean     antialias)
47 {
48   GdkPixmapImplQuartz *impl = GDK_PIXMAP_IMPL_QUARTZ (drawable);
49   CGContextRef cg_context;
50   size_t height;
51
52   cg_context = CGBitmapContextCreate (impl->data,
53                                       CGImageGetWidth (impl->image),
54                                       CGImageGetHeight (impl->image),
55                                       CGImageGetBitsPerComponent (impl->image),
56                                       CGImageGetBytesPerRow (impl->image),
57                                       CGImageGetColorSpace (impl->image),
58                                       CGImageGetBitmapInfo (impl->image));
59   CGContextSetAllowsAntialiasing (cg_context, antialias);
60
61   /* convert coordinates from core graphics to gtk+ */
62   height = CGImageGetHeight (impl->image);
63
64   CGContextTranslateCTM (cg_context, 0, height);
65   CGContextScaleCTM (cg_context, 1.0, -1.0);
66
67   return cg_context;
68 }
69
70 static void
71 gdk_pixmap_impl_quartz_finalize (GObject *object)
72 {
73   GdkPixmapImplQuartz *impl = GDK_PIXMAP_IMPL_QUARTZ (object);
74
75   CGImageRelease (impl->image);
76
77   _gdk_quartz_drawable_finish (GDK_DRAWABLE (impl));
78
79   G_OBJECT_CLASS (parent_class)->finalize (object);
80 }
81
82 static void
83 gdk_pixmap_impl_quartz_class_init (GdkPixmapImplQuartzClass *klass)
84 {
85   GObjectClass *object_class = G_OBJECT_CLASS (klass);
86   GdkDrawableClass *drawable_class = GDK_DRAWABLE_CLASS (klass);
87   GdkDrawableImplQuartzClass *drawable_quartz_class = GDK_DRAWABLE_IMPL_QUARTZ_CLASS (klass);
88   
89   parent_class = g_type_class_peek_parent (klass);
90
91   object_class->finalize = gdk_pixmap_impl_quartz_finalize;
92
93   drawable_class->get_size = gdk_pixmap_impl_quartz_get_size;
94
95   drawable_quartz_class->get_context = gdk_pixmap_impl_quartz_get_context;
96 }
97
98 GType
99 _gdk_pixmap_impl_quartz_get_type (void)
100 {
101   static GType object_type = 0;
102
103   if (!object_type)
104     {
105       static const GTypeInfo object_info =
106       {
107         sizeof (GdkPixmapImplQuartzClass),
108         (GBaseInitFunc) NULL,
109         (GBaseFinalizeFunc) NULL,
110         (GClassInitFunc) gdk_pixmap_impl_quartz_class_init,
111         NULL,           /* class_finalize */
112         NULL,           /* class_data */
113         sizeof (GdkPixmapImplQuartz),
114         0,              /* n_preallocs */
115         (GInstanceInitFunc) gdk_pixmap_impl_quartz_init
116       };
117       
118       object_type = g_type_register_static (GDK_TYPE_DRAWABLE_IMPL_QUARTZ,
119                                             "GdkPixmapImplQuartz",
120                                             &object_info,
121                                             0);
122     }
123   
124   return object_type;
125 }
126
127 GType
128 _gdk_pixmap_impl_get_type (void)
129 {
130   return _gdk_pixmap_impl_quartz_get_type ();
131 }
132
133 static void
134 data_provider_release (void *info, const void *data, size_t size)
135 {
136   g_free (info);
137 }
138
139 GdkPixmap*
140 _gdk_pixmap_new (GdkDrawable *drawable,
141                  gint         width,
142                  gint         height,
143                  gint         depth)
144 {
145   GdkPixmap *pixmap;
146   GdkDrawableImplQuartz *draw_impl;
147   GdkPixmapImplQuartz *pix_impl;
148   gint window_depth;
149   CGColorSpaceRef colorspace;
150   CGDataProviderRef data_provider;
151   CGImageAlphaInfo alpha_info;
152   gint bytes_per_row, bits_per_pixel;
153
154   g_return_val_if_fail (drawable == NULL || GDK_IS_DRAWABLE (drawable), NULL);
155   g_return_val_if_fail ((drawable != NULL) || (depth != -1), NULL);
156   g_return_val_if_fail ((width != 0) && (height != 0), NULL);
157
158   if (GDK_IS_WINDOW (drawable) && GDK_WINDOW_DESTROYED (drawable))
159     return NULL;
160
161   if (!drawable)
162     drawable = gdk_screen_get_root_window (gdk_screen_get_default ());
163
164   window_depth = gdk_drawable_get_depth (GDK_DRAWABLE (drawable));
165
166   if (depth == -1)
167     depth = window_depth;
168
169   switch (depth)
170     {
171     case 24:
172       alpha_info = kCGImageAlphaNoneSkipLast;
173       bytes_per_row = width * 4;
174       bits_per_pixel = 32;
175       colorspace = CGColorSpaceCreateDeviceRGB ();
176       break;
177     case 32:
178       alpha_info = kCGImageAlphaPremultipliedFirst;
179       bytes_per_row = width * 4;
180       bits_per_pixel = 32;
181       colorspace = CGColorSpaceCreateDeviceRGB ();
182       break;
183     case 1:
184       alpha_info = kCGImageAlphaNone;
185       bytes_per_row = width;
186       bits_per_pixel = 8;
187       colorspace = CGColorSpaceCreateDeviceGray ();
188       break;
189     default:
190       g_warning ("Unsupported bit depth %d\n", depth);
191       return NULL;
192     }
193
194   pixmap = g_object_new (gdk_pixmap_get_type (), NULL);
195   draw_impl = GDK_DRAWABLE_IMPL_QUARTZ (GDK_PIXMAP_OBJECT (pixmap)->impl);
196   pix_impl = GDK_PIXMAP_IMPL_QUARTZ (GDK_PIXMAP_OBJECT (pixmap)->impl);
197   draw_impl->wrapper = GDK_DRAWABLE (pixmap);
198
199   g_assert (depth == 24 || depth == 32 || depth == 1);
200
201   pix_impl->data = g_malloc (height * bytes_per_row);
202   data_provider = CGDataProviderCreateWithData (pix_impl->data, pix_impl->data, 
203                                                 height * bytes_per_row, data_provider_release);
204   pix_impl->image = CGImageCreate (width, height, 8, bits_per_pixel, 
205                                    bytes_per_row, colorspace,
206                                    alpha_info,
207                                    data_provider, NULL, FALSE, 
208                                    kCGRenderingIntentDefault);
209   CGDataProviderRelease (data_provider);
210   CGColorSpaceRelease (colorspace);
211
212   pix_impl->width = width;
213   pix_impl->height = height;
214   GDK_PIXMAP_OBJECT (pixmap)->depth = depth;
215
216   if (depth == window_depth) {
217     GdkColormap *colormap = gdk_drawable_get_colormap (drawable);
218
219     if (colormap)
220       gdk_drawable_set_colormap (pixmap, colormap);
221   }
222
223   return pixmap;
224 }
225
226 GdkPixmap *
227 _gdk_bitmap_create_from_data (GdkDrawable *window,
228                               const gchar *data,
229                               gint         width,
230                               gint         height)
231 {
232   GdkPixmap *pixmap;
233   GdkPixmapImplQuartz *impl;
234   int x, y, bpl;
235
236   g_return_val_if_fail (data != NULL, NULL);
237   g_return_val_if_fail ((width != 0) && (height != 0), NULL);
238   g_return_val_if_fail (window == NULL || GDK_IS_DRAWABLE (window), NULL);
239
240   pixmap = gdk_pixmap_new (window, width, height, 1);
241   impl = GDK_PIXMAP_IMPL_QUARTZ (GDK_PIXMAP_OBJECT (pixmap)->impl);
242
243   g_assert (CGImageGetBytesPerRow (impl->image) == width);
244
245   /* Bytes per line: Each line consumes an integer number of bytes, possibly
246    * ignoring any excess bits. */
247   bpl = (width + 7) / 8;
248   for (y = 0; y < height; y++)
249     {
250       guchar *dst = impl->data + y * width;
251       const gchar *src = data + (y * bpl);   
252       for (x = 0; x < width; x++)
253         {
254           if ((src[x / 8] >> x % 8) & 1)
255             *dst = 0xff;
256           else
257             *dst = 0;
258
259           dst++;
260         }
261     }
262
263   return pixmap;
264 }
265
266 GdkPixmap*
267 _gdk_pixmap_create_from_data (GdkDrawable    *drawable,
268                               const gchar    *data,
269                               gint            width,
270                               gint            height,
271                               gint            depth,
272                               const GdkColor *fg,
273                               const GdkColor *bg)
274 {       
275   /* FIXME: Implement */
276   return NULL;
277 }
278
279 GdkPixmap *
280 gdk_pixmap_foreign_new_for_display (GdkDisplay      *display,
281                                     GdkNativeWindow  anid)
282 {
283   return NULL;
284 }
285
286 GdkPixmap*
287 gdk_pixmap_foreign_new (GdkNativeWindow anid)
288 {
289    return NULL;
290 }
291
292 GdkPixmap *
293 gdk_pixmap_foreign_new_for_screen (GdkScreen       *screen,
294                                    GdkNativeWindow  anid,
295                                    gint             width,
296                                    gint             height,
297                                    gint             depth)
298 {
299   return NULL;
300 }
301
302 GdkPixmap*
303 gdk_pixmap_lookup (GdkNativeWindow anid)
304 {
305   return NULL;
306 }
307
308 GdkPixmap*
309 gdk_pixmap_lookup_for_display (GdkDisplay *display, GdkNativeWindow anid)
310 {
311   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
312   return NULL;
313 }