]> Pileus Git - ~andy/gtk/blob - gdk/gdkpixmap.c
d73647fbe0b705561e8ba10947db7a8fc0553f83
[~andy/gtk] / gdk / gdkpixmap.c
1 /* GDK - The GIMP Drawing Kit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 /*
21  * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
22  * file for a list of people on the GTK+ Team.  See the ChangeLog
23  * files for a list of changes.  These files are distributed with
24  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
25  */
26
27 #include "gdkpixmap.h"
28 #include "gdkinternals.h"
29 #include "gdkpixbuf.h"
30 #include "gdkscreen.h"
31
32 static GdkGC *gdk_pixmap_create_gc      (GdkDrawable     *drawable,
33                                          GdkGCValues     *values,
34                                          GdkGCValuesMask  mask);
35 static void   gdk_pixmap_draw_rectangle (GdkDrawable     *drawable,
36                                          GdkGC           *gc,
37                                          gboolean         filled,
38                                          gint             x,
39                                          gint             y,
40                                          gint             width,
41                                          gint             height);
42 static void   gdk_pixmap_draw_arc       (GdkDrawable     *drawable,
43                                          GdkGC           *gc,
44                                          gboolean         filled,
45                                          gint             x,
46                                          gint             y,
47                                          gint             width,
48                                          gint             height,
49                                          gint             angle1,
50                                          gint             angle2);
51 static void   gdk_pixmap_draw_polygon   (GdkDrawable     *drawable,
52                                          GdkGC           *gc,
53                                          gboolean         filled,
54                                          GdkPoint        *points,
55                                          gint             npoints);
56 static void   gdk_pixmap_draw_text      (GdkDrawable     *drawable,
57                                          GdkFont         *font,
58                                          GdkGC           *gc,
59                                          gint             x,
60                                          gint             y,
61                                          const gchar     *text,
62                                          gint             text_length);
63 static void   gdk_pixmap_draw_text_wc   (GdkDrawable     *drawable,
64                                          GdkFont         *font,
65                                          GdkGC           *gc,
66                                          gint             x,
67                                          gint             y,
68                                          const GdkWChar  *text,
69                                          gint             text_length);
70 static void   gdk_pixmap_draw_drawable  (GdkDrawable     *drawable,
71                                          GdkGC           *gc,
72                                          GdkPixmap       *src,
73                                          gint             xsrc,
74                                          gint             ysrc,
75                                          gint             xdest,
76                                          gint             ydest,
77                                          gint             width,
78                                          gint             height);
79 static void   gdk_pixmap_draw_points    (GdkDrawable     *drawable,
80                                          GdkGC           *gc,
81                                          GdkPoint        *points,
82                                          gint             npoints);
83 static void   gdk_pixmap_draw_segments  (GdkDrawable     *drawable,
84                                          GdkGC           *gc,
85                                          GdkSegment      *segs,
86                                          gint             nsegs);
87 static void   gdk_pixmap_draw_lines     (GdkDrawable     *drawable,
88                                          GdkGC           *gc,
89                                          GdkPoint        *points,
90                                          gint             npoints);
91 static void   gdk_pixmap_draw_glyphs    (GdkDrawable      *drawable,
92                                          GdkGC            *gc,
93                                          PangoFont        *font,
94                                          gint              x,
95                                          gint              y,
96                                          PangoGlyphString *glyphs);
97 static void   gdk_pixmap_draw_image     (GdkDrawable     *drawable,
98                                          GdkGC           *gc,
99                                          GdkImage        *image,
100                                          gint             xsrc,
101                                          gint             ysrc,
102                                          gint             xdest,
103                                          gint             ydest,
104                                          gint             width,
105                                          gint             height);
106 static void   gdk_pixmap_draw_pixbuf    (GdkDrawable     *drawable,
107                                          GdkGC           *gc,
108                                          GdkPixbuf       *pixbuf,
109                                          gint             src_x,
110                                          gint             src_y,
111                                          gint             dest_x,
112                                          gint             dest_y,
113                                          gint             width,
114                                          gint             height,
115                                          GdkRgbDither     dither,
116                                          gint             x_dither,
117                                          gint             y_dither);
118
119
120 static void   gdk_pixmap_real_get_size  (GdkDrawable     *drawable,
121                                          gint            *width,
122                                          gint            *height);
123
124 static GdkImage* gdk_pixmap_copy_to_image (GdkDrawable *drawable,
125                                            GdkImage    *image,
126                                            gint         src_x,
127                                            gint         src_y,
128                                            gint         dest_x,
129                                            gint         dest_y,
130                                            gint         width,
131                                            gint         height);
132
133 static GdkVisual*   gdk_pixmap_real_get_visual   (GdkDrawable *drawable);
134 static gint         gdk_pixmap_real_get_depth    (GdkDrawable *drawable);
135 static void         gdk_pixmap_real_set_colormap (GdkDrawable *drawable,
136                                                   GdkColormap *cmap);
137 static GdkColormap* gdk_pixmap_real_get_colormap (GdkDrawable *drawable);
138 static GdkScreen*   gdk_pixmap_real_get_screen   (GdkDrawable *drawable);
139
140 static void gdk_pixmap_init       (GdkPixmapObject      *pixmap);
141 static void gdk_pixmap_class_init (GdkPixmapObjectClass *klass);
142 static void gdk_pixmap_finalize   (GObject              *object);
143
144 static gpointer parent_class = NULL;
145
146 GType
147 gdk_pixmap_get_type (void)
148 {
149   static GType object_type = 0;
150
151   if (!object_type)
152     {
153       static const GTypeInfo object_info =
154       {
155         sizeof (GdkPixmapObjectClass),
156         (GBaseInitFunc) NULL,
157         (GBaseFinalizeFunc) NULL,
158         (GClassInitFunc) gdk_pixmap_class_init,
159         NULL,           /* class_finalize */
160         NULL,           /* class_data */
161         sizeof (GdkPixmapObject),
162         0,              /* n_preallocs */
163         (GInstanceInitFunc) gdk_pixmap_init,
164       };
165       
166       object_type = g_type_register_static (GDK_TYPE_DRAWABLE,
167                                             "GdkPixmap",
168                                             &object_info, 0);
169     }
170   
171   return object_type;
172 }
173
174 static void
175 gdk_pixmap_init (GdkPixmapObject *pixmap)
176 {
177   /* 0-initialization is good for all other fields. */
178   pixmap->impl = g_object_new (_gdk_pixmap_impl_get_type (), NULL);
179 }
180
181 static void
182 gdk_pixmap_class_init (GdkPixmapObjectClass *klass)
183 {
184   GObjectClass *object_class = G_OBJECT_CLASS (klass);
185   GdkDrawableClass *drawable_class = GDK_DRAWABLE_CLASS (klass);
186   
187   parent_class = g_type_class_peek_parent (klass);
188
189   object_class->finalize = gdk_pixmap_finalize;
190
191   drawable_class->create_gc = gdk_pixmap_create_gc;
192   drawable_class->draw_rectangle = gdk_pixmap_draw_rectangle;
193   drawable_class->draw_arc = gdk_pixmap_draw_arc;
194   drawable_class->draw_polygon = gdk_pixmap_draw_polygon;
195   drawable_class->draw_text = gdk_pixmap_draw_text;
196   drawable_class->draw_text_wc = gdk_pixmap_draw_text_wc;
197   drawable_class->draw_drawable = gdk_pixmap_draw_drawable;
198   drawable_class->draw_points = gdk_pixmap_draw_points;
199   drawable_class->draw_segments = gdk_pixmap_draw_segments;
200   drawable_class->draw_lines = gdk_pixmap_draw_lines;
201   drawable_class->draw_glyphs = gdk_pixmap_draw_glyphs;
202   drawable_class->draw_image = gdk_pixmap_draw_image;
203   drawable_class->draw_pixbuf = gdk_pixmap_draw_pixbuf;
204   drawable_class->get_depth = gdk_pixmap_real_get_depth;
205   drawable_class->get_screen = gdk_pixmap_real_get_screen;
206   drawable_class->get_size = gdk_pixmap_real_get_size;
207   drawable_class->set_colormap = gdk_pixmap_real_set_colormap;
208   drawable_class->get_colormap = gdk_pixmap_real_get_colormap;
209   drawable_class->get_visual = gdk_pixmap_real_get_visual;
210   drawable_class->_copy_to_image = gdk_pixmap_copy_to_image;
211 }
212
213 static void
214 gdk_pixmap_finalize (GObject *object)
215 {
216   GdkPixmapObject *obj = (GdkPixmapObject *) object;
217
218   g_object_unref (obj->impl);
219   obj->impl = NULL;
220   
221   G_OBJECT_CLASS (parent_class)->finalize (object);
222 }
223
224 static GdkGC *
225 gdk_pixmap_create_gc (GdkDrawable     *drawable,
226                       GdkGCValues     *values,
227                       GdkGCValuesMask  mask)
228 {
229   return gdk_gc_new_with_values (((GdkPixmapObject *) drawable)->impl,
230                                  values, mask);
231 }
232
233 static void
234 gdk_pixmap_draw_rectangle (GdkDrawable *drawable,
235                            GdkGC       *gc,
236                            gboolean     filled,
237                            gint         x,
238                            gint         y,
239                            gint         width,
240                            gint         height)
241 {
242   GdkPixmapObject *private = (GdkPixmapObject *)drawable;
243
244   gdk_draw_rectangle (private->impl, gc, filled,
245                       x, y, width, height);
246 }
247
248 static void
249 gdk_pixmap_draw_arc (GdkDrawable *drawable,
250                      GdkGC       *gc,
251                      gboolean     filled,
252                      gint         x,
253                      gint         y,
254                      gint         width,
255                      gint         height,
256                      gint         angle1,
257                      gint         angle2)
258 {
259   GdkPixmapObject *private = (GdkPixmapObject *)drawable;
260
261   gdk_draw_arc (private->impl, gc, filled,
262                 x, y,
263                 width, height, angle1, angle2);
264 }
265
266 static void
267 gdk_pixmap_draw_polygon (GdkDrawable *drawable,
268                          GdkGC       *gc,
269                          gboolean     filled,
270                          GdkPoint    *points,
271                          gint         npoints)
272 {
273   GdkPixmapObject *private = (GdkPixmapObject *)drawable;
274
275   gdk_draw_polygon (private->impl, gc, filled, points, npoints);
276 }
277
278 static void
279 gdk_pixmap_draw_text (GdkDrawable *drawable,
280                       GdkFont     *font,
281                       GdkGC       *gc,
282                       gint         x,
283                       gint         y,
284                       const gchar *text,
285                       gint         text_length)
286 {
287   GdkPixmapObject *private = (GdkPixmapObject *)drawable;
288
289   gdk_draw_text (private->impl, font, gc,
290                  x, y, text, text_length);
291 }
292
293 static void
294 gdk_pixmap_draw_text_wc (GdkDrawable    *drawable,
295                          GdkFont        *font,
296                          GdkGC          *gc,
297                          gint            x,
298                          gint            y,
299                          const GdkWChar *text,
300                          gint            text_length)
301 {
302   GdkPixmapObject *private = (GdkPixmapObject *)drawable;
303
304   gdk_draw_text_wc (private->impl, font, gc,
305                     x, y, text, text_length);
306 }
307
308 static void
309 gdk_pixmap_draw_drawable (GdkDrawable *drawable,
310                           GdkGC       *gc,
311                           GdkPixmap   *src,
312                           gint         xsrc,
313                           gint         ysrc,
314                           gint         xdest,
315                           gint         ydest,
316                           gint         width,
317                           gint         height)
318 {
319   GdkPixmapObject *private = (GdkPixmapObject *)drawable;
320
321   gdk_draw_drawable (private->impl, gc, src, xsrc, ysrc,
322                      xdest, ydest,
323                      width, height);
324 }
325
326 static void
327 gdk_pixmap_draw_points (GdkDrawable *drawable,
328                         GdkGC       *gc,
329                         GdkPoint    *points,
330                         gint         npoints)
331 {
332   GdkPixmapObject *private = (GdkPixmapObject *)drawable;
333
334   gdk_draw_points (private->impl, gc, points, npoints);
335 }
336
337 static void
338 gdk_pixmap_draw_segments (GdkDrawable *drawable,
339                           GdkGC       *gc,
340                           GdkSegment  *segs,
341                           gint         nsegs)
342 {
343   GdkPixmapObject *private = (GdkPixmapObject *)drawable;
344
345   gdk_draw_segments (private->impl, gc, segs, nsegs);
346 }
347
348 static void
349 gdk_pixmap_draw_lines (GdkDrawable *drawable,
350                        GdkGC       *gc,
351                        GdkPoint    *points,
352                        gint         npoints)
353 {
354   GdkPixmapObject *private = (GdkPixmapObject *)drawable;
355
356   gdk_draw_lines (private->impl, gc, points, npoints);
357 }
358
359 static void
360 gdk_pixmap_draw_glyphs (GdkDrawable      *drawable,
361                         GdkGC            *gc,
362                         PangoFont        *font,
363                         gint              x,
364                         gint              y,
365                         PangoGlyphString *glyphs)
366 {
367   GdkPixmapObject *private = (GdkPixmapObject *)drawable;
368
369   gdk_draw_glyphs (private->impl, gc, font, x, y, glyphs);
370 }
371
372 static void
373 gdk_pixmap_draw_image (GdkDrawable     *drawable,
374                        GdkGC           *gc,
375                        GdkImage        *image,
376                        gint             xsrc,
377                        gint             ysrc,
378                        gint             xdest,
379                        gint             ydest,
380                        gint             width,
381                        gint             height)
382 {
383   GdkPixmapObject *private = (GdkPixmapObject *)drawable;
384
385   gdk_draw_image (private->impl, gc, image, xsrc, ysrc, xdest, ydest,
386                   width, height);
387 }
388
389 static void
390 gdk_pixmap_draw_pixbuf (GdkDrawable     *drawable,
391                         GdkGC           *gc,
392                         GdkPixbuf       *pixbuf,
393                         gint             src_x,
394                         gint             src_y,
395                         gint             dest_x,
396                         gint             dest_y,
397                         gint             width,
398                         gint             height,
399                         GdkRgbDither     dither,
400                         gint             x_dither,
401                         gint             y_dither)
402 {
403   GdkPixmapObject *private = (GdkPixmapObject *)drawable;
404
405   gdk_draw_pixbuf (private->impl, gc, pixbuf,
406                    src_x, src_y, dest_x, dest_y, width, height,
407                    dither, x_dither, y_dither);
408 }
409
410 static void
411 gdk_pixmap_real_get_size (GdkDrawable *drawable,
412                           gint *width,
413                           gint *height)
414 {
415   g_return_if_fail (GDK_IS_PIXMAP (drawable));
416
417   gdk_drawable_get_size (GDK_DRAWABLE (((GdkPixmapObject*)drawable)->impl),
418                          width, height);
419 }
420
421 static GdkVisual*
422 gdk_pixmap_real_get_visual (GdkDrawable *drawable)
423 {
424   GdkColormap *colormap;
425
426   g_return_val_if_fail (GDK_IS_PIXMAP (drawable), NULL);
427
428   colormap = gdk_drawable_get_colormap (drawable);
429   return colormap ? gdk_colormap_get_visual (colormap) : NULL;
430 }
431
432 static gint
433 gdk_pixmap_real_get_depth (GdkDrawable *drawable)
434 {
435   gint depth;
436   
437   g_return_val_if_fail (GDK_IS_PIXMAP (drawable), 0);
438
439   depth = GDK_PIXMAP_OBJECT (drawable)->depth;
440
441   return depth;
442 }
443
444 static void
445 gdk_pixmap_real_set_colormap (GdkDrawable *drawable,
446                               GdkColormap *cmap)
447 {
448   g_return_if_fail (GDK_IS_PIXMAP (drawable));  
449   
450   gdk_drawable_set_colormap (((GdkPixmapObject*)drawable)->impl, cmap);
451 }
452
453 static GdkColormap*
454 gdk_pixmap_real_get_colormap (GdkDrawable *drawable)
455 {
456   g_return_val_if_fail (GDK_IS_PIXMAP (drawable), NULL);
457   
458   return gdk_drawable_get_colormap (((GdkPixmapObject*)drawable)->impl);
459 }
460
461 static GdkImage*
462 gdk_pixmap_copy_to_image (GdkDrawable     *drawable,
463                           GdkImage        *image,
464                           gint             src_x,
465                           gint             src_y,
466                           gint             dest_x,
467                           gint             dest_y,
468                           gint             width,
469                           gint             height)
470 {
471   g_return_val_if_fail (GDK_IS_PIXMAP (drawable), NULL);
472   
473   return _gdk_drawable_copy_to_image (((GdkPixmapObject*)drawable)->impl,
474                                       image,
475                                       src_x, src_y, dest_x, dest_y,
476                                       width, height);
477 }
478
479 static GdkBitmap *
480 make_solid_mask (GdkScreen *screen, gint width, gint height)
481 {
482   GdkBitmap *bitmap;
483   GdkGC *gc;
484   GdkGCValues gc_values;
485   
486   bitmap = gdk_pixmap_new (gdk_screen_get_root_window (screen),
487                            width, height, 1);
488
489   gc_values.foreground.pixel = 1;
490   gc = gdk_gc_new_with_values (bitmap, &gc_values, GDK_GC_FOREGROUND);
491   
492   gdk_draw_rectangle (bitmap, gc, TRUE, 0, 0, width, height);
493   
494   g_object_unref (gc);
495   
496   return bitmap;
497 }
498
499 #define PACKED_COLOR(c) ((((c)->red   & 0xff00)  << 8) |   \
500                           ((c)->green & 0xff00)        |   \
501                           ((c)->blue             >> 8))
502
503 static GdkPixmap *
504 gdk_pixmap_colormap_new_from_pixbuf (GdkColormap *colormap,
505                                      GdkBitmap  **mask,
506                                      GdkColor    *transparent_color,
507                                      GdkPixbuf   *pixbuf)
508 {
509   GdkPixmap *pixmap;
510   GdkPixbuf *render_pixbuf;
511   GdkGC *tmp_gc;
512   GdkScreen *screen = gdk_colormap_get_screen (colormap);
513   
514   pixmap = gdk_pixmap_new (gdk_screen_get_root_window (screen),
515                            gdk_pixbuf_get_width (pixbuf),
516                            gdk_pixbuf_get_height (pixbuf),
517                            gdk_colormap_get_visual (colormap)->depth);
518   gdk_drawable_set_colormap (pixmap, colormap);
519   
520   if (transparent_color)
521     {
522       guint32 packed_color = PACKED_COLOR (transparent_color);
523       render_pixbuf = gdk_pixbuf_composite_color_simple (pixbuf,
524                                                          gdk_pixbuf_get_width (pixbuf),
525                                                          gdk_pixbuf_get_height (pixbuf),
526                                                          GDK_INTERP_NEAREST,
527                                                          255, 16, packed_color, packed_color);
528     }
529   else
530     render_pixbuf = pixbuf;
531
532   tmp_gc = gdk_gc_new (pixmap);
533   gdk_draw_pixbuf (pixmap, tmp_gc, render_pixbuf, 0, 0, 0, 0,
534                    gdk_pixbuf_get_width (render_pixbuf),
535                    gdk_pixbuf_get_height (render_pixbuf),
536                    GDK_RGB_DITHER_NORMAL, 0, 0);
537   g_object_unref (tmp_gc);
538
539   if (render_pixbuf != pixbuf)
540     g_object_unref (render_pixbuf);
541
542   if (mask)
543     gdk_pixbuf_render_pixmap_and_mask_for_colormap (pixbuf, colormap, NULL, mask, 128);
544
545   if (mask && !*mask)
546     *mask = make_solid_mask (screen,
547                              gdk_pixbuf_get_width (pixbuf),
548                              gdk_pixbuf_get_height (pixbuf));
549
550   return pixmap;
551 }
552
553 GdkPixmap*
554 gdk_pixmap_colormap_create_from_xpm (GdkWindow   *window,
555                                      GdkColormap *colormap,
556                                      GdkBitmap  **mask,
557                                      GdkColor    *transparent_color,
558                                      const gchar *filename)
559 {
560   GdkPixbuf *pixbuf;
561   GdkPixmap *pixmap;
562
563   g_return_val_if_fail (window != NULL || colormap != NULL, NULL);
564   g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), NULL);
565   g_return_val_if_fail (colormap == NULL || GDK_IS_COLORMAP (colormap), NULL);
566
567   if (colormap == NULL)
568     colormap = gdk_drawable_get_colormap (window);
569   
570   pixbuf = gdk_pixbuf_new_from_file (filename, NULL);
571   if (!pixbuf)
572     return NULL;
573
574   pixmap = gdk_pixmap_colormap_new_from_pixbuf (colormap, mask, transparent_color, pixbuf);
575
576   g_object_unref (pixbuf);
577   
578   return pixmap;
579 }
580
581 GdkPixmap*
582 gdk_pixmap_create_from_xpm (GdkWindow  *window,
583                             GdkBitmap **mask,
584                             GdkColor   *transparent_color,
585                             const gchar *filename)
586 {
587   return gdk_pixmap_colormap_create_from_xpm (window, NULL, mask,
588                                               transparent_color, filename);
589 }
590
591 GdkPixmap*
592 gdk_pixmap_colormap_create_from_xpm_d (GdkWindow  *window,
593                                        GdkColormap *colormap,
594                                        GdkBitmap **mask,
595                                        GdkColor   *transparent_color,
596                                        gchar     **data)
597 {
598   GdkPixbuf *pixbuf;
599   GdkPixmap *pixmap;
600
601   g_return_val_if_fail (window != NULL || colormap != NULL, NULL);
602   g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), NULL);
603   g_return_val_if_fail (colormap == NULL || GDK_IS_COLORMAP (colormap), NULL);
604
605   if (colormap == NULL)
606     colormap = gdk_drawable_get_colormap (window);
607   
608   pixbuf = gdk_pixbuf_new_from_xpm_data ((const char **)data);
609   if (!pixbuf)
610     return NULL;
611
612   pixmap = gdk_pixmap_colormap_new_from_pixbuf (colormap, mask, transparent_color, pixbuf);
613
614   g_object_unref (pixbuf);
615
616   return pixmap;
617 }
618
619 GdkPixmap*
620 gdk_pixmap_create_from_xpm_d (GdkWindow  *window,
621                               GdkBitmap **mask,
622                               GdkColor   *transparent_color,
623                               gchar     **data)
624 {
625   return gdk_pixmap_colormap_create_from_xpm_d (window, NULL, mask,
626                                                 transparent_color, data);
627 }
628
629 static GdkScreen*
630 gdk_pixmap_real_get_screen (GdkDrawable *drawable)
631 {
632     return gdk_drawable_get_screen (GDK_PIXMAP_OBJECT (drawable)->impl);
633 }