]> Pileus Git - ~andy/gtk/blob - gdk/linux-fb/gdkdrawable-fb2.c
1274f0f219309993fde198db43188715f6b3c4a4
[~andy/gtk] / gdk / linux-fb / gdkdrawable-fb2.c
1 /* GDK - The GIMP Drawing Kit
2  * Copyright (C) 2000 Elliot Lee
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 <config.h>
28 #include "gdkprivate-fb.h"
29 #include "mi.h"
30 #include <string.h>
31 #include <gdkregion-generic.h>
32
33 #include <pango/pangoft2.h>
34 #include <freetype/ftglyph.h>
35
36 #ifndef g_alloca
37 #define g_alloca alloca
38 #endif
39
40 void                gdk_fb_draw_rectangle     (GdkDrawable      *drawable,
41                                                GdkGC            *gc,
42                                                gboolean          filled,
43                                                gint              x,
44                                                gint              y,
45                                                gint              width,
46                                                gint              height);
47 static void         gdk_fb_draw_arc           (GdkDrawable      *drawable,
48                                                GdkGC            *gc,
49                                                gboolean          filled,
50                                                gint              x,
51                                                gint              y,
52                                                gint              width,
53                                                gint              height,
54                                                gint              angle1,
55                                                gint              angle2);
56 static void         gdk_fb_draw_polygon       (GdkDrawable      *drawable,
57                                                GdkGC            *gc,
58                                                gboolean          filled,
59                                                GdkPoint         *points,
60                                                gint              npoints);
61 static void         gdk_fb_draw_text          (GdkDrawable      *drawable,
62                                                GdkFont          *font,
63                                                GdkGC            *gc,
64                                                gint              x,
65                                                gint              y,
66                                                const gchar      *text,
67                                                gint              text_length);
68 static void         gdk_fb_draw_text_wc       (GdkDrawable      *drawable,
69                                                GdkFont          *font,
70                                                GdkGC            *gc,
71                                                gint              x,
72                                                gint              y,
73                                                const GdkWChar   *text,
74                                                gint              text_length);
75 static void         gdk_fb_draw_glyphs        (GdkDrawable      *drawable,
76                                                GdkGC            *gc,
77                                                PangoFont        *font,
78                                                gint              x,
79                                                gint              y,
80                                                PangoGlyphString *glyphs);
81 void                gdk_fb_draw_drawable      (GdkDrawable      *drawable,
82                                                GdkGC            *gc,
83                                                GdkPixmap        *src,
84                                                gint              xsrc,
85                                                gint              ysrc,
86                                                gint              xdest,
87                                                gint              ydest,
88                                                gint              width,
89                                                gint              height);
90 static void         gdk_fb_draw_image         (GdkDrawable      *drawable,
91                                                GdkGC            *gc,
92                                                GdkImage         *image,
93                                                gint              xsrc,
94                                                gint              ysrc,
95                                                gint              xdest,
96                                                gint              ydest,
97                                                gint              width,
98                                                gint              height);
99 static void         gdk_fb_draw_points        (GdkDrawable      *drawable,
100                                                GdkGC            *gc,
101                                                GdkPoint         *points,
102                                                gint              npoints);
103 static void         gdk_fb_draw_segments      (GdkDrawable      *drawable,
104                                                GdkGC            *gc,
105                                                GdkSegment       *segs,
106                                                gint              nsegs);
107 static void         gdk_fb_draw_lines         (GdkDrawable      *drawable,
108                                                GdkGC            *gc,
109                                                GdkPoint         *points,
110                                                gint              npoints);
111 static GdkColormap* gdk_fb_get_colormap       (GdkDrawable      *drawable);
112 static void         gdk_fb_set_colormap       (GdkDrawable      *drawable,
113                                                GdkColormap      *colormap);
114 static gint         gdk_fb_get_depth          (GdkDrawable      *drawable);
115 static GdkScreen*   gdk_fb_get_screen         (GdkDrawable      *drawable);
116 static GdkVisual*   gdk_fb_get_visual         (GdkDrawable      *drawable);
117 static void         gdk_fb_drawable_finalize  (GObject *object);
118
119 #ifdef ENABLE_SHADOW_FB
120 static void         gdk_shadow_fb_draw_rectangle     (GdkDrawable      *drawable,
121                                                       GdkGC            *gc,
122                                                       gboolean          filled,
123                                                       gint              x,
124                                                       gint              y,
125                                                       gint              width,
126                                                       gint              height);
127 static void         gdk_shadow_fb_draw_arc           (GdkDrawable      *drawable,
128                                                       GdkGC            *gc,
129                                                       gboolean          filled,
130                                                       gint              x,
131                                                       gint              y,
132                                                       gint              width,
133                                                       gint              height,
134                                                       gint              angle1,
135                                                       gint              angle2);
136 static void         gdk_shadow_fb_draw_polygon       (GdkDrawable      *drawable,
137                                                       GdkGC            *gc,
138                                                       gboolean          filled,
139                                                       GdkPoint         *points,
140                                                       gint              npoints);
141 static void         gdk_shadow_fb_draw_text          (GdkDrawable      *drawable,
142                                                       GdkFont          *font,
143                                                       GdkGC            *gc,
144                                                       gint              x,
145                                                       gint              y,
146                                                       const gchar      *text,
147                                                       gint              text_length);
148 static void         gdk_shadow_fb_draw_text_wc       (GdkDrawable      *drawable,
149                                                       GdkFont          *font,
150                                                       GdkGC            *gc,
151                                                       gint              x,
152                                                       gint              y,
153                                                       const GdkWChar   *text,
154                                                       gint              text_length);
155 static void         gdk_shadow_fb_draw_glyphs        (GdkDrawable      *drawable,
156                                                       GdkGC            *gc,
157                                                       PangoFont        *font,
158                                                       gint              x,
159                                                       gint              y,
160                                                       PangoGlyphString *glyphs);
161 static void         gdk_shadow_fb_draw_drawable      (GdkDrawable      *drawable,
162                                                       GdkGC            *gc,
163                                                       GdkPixmap        *src,
164                                                       gint              xsrc,
165                                                       gint              ysrc,
166                                                       gint              xdest,
167                                                       gint              ydest,
168                                                       gint              width,
169                                                       gint              height);
170 static void         gdk_shadow_fb_draw_image         (GdkDrawable      *drawable,
171                                                       GdkGC            *gc,
172                                                       GdkImage         *image,
173                                                       gint              xsrc,
174                                                       gint              ysrc,
175                                                       gint              xdest,
176                                                       gint              ydest,
177                                                       gint              width,
178                                                       gint              height);
179 static void         gdk_shadow_fb_draw_points        (GdkDrawable      *drawable,
180                                                       GdkGC            *gc,
181                                                       GdkPoint         *points,
182                                                       gint              npoints);
183 static void         gdk_shadow_fb_draw_segments      (GdkDrawable      *drawable,
184                                                       GdkGC            *gc,
185                                                       GdkSegment       *segs,
186                                                       gint              nsegs);
187 static void         gdk_shadow_fb_draw_lines         (GdkDrawable      *drawable,
188                                                       GdkGC            *gc,
189                                                       GdkPoint         *points,
190                                                       gint              npoints);
191 #endif
192
193
194 static gpointer parent_class = NULL;
195
196 static void
197 gdk_fb_get_size (GdkDrawable *d, gint *width, gint *height)
198 {
199   if (width)
200     *width = GDK_DRAWABLE_FBDATA (d)->width;
201   if (height)
202     *height = GDK_DRAWABLE_FBDATA (d)->height;
203 }
204
205 static void
206 gdk_drawable_impl_fb_class_init (GdkDrawableFBClass *klass)
207 {
208   GdkDrawableClass *drawable_class = GDK_DRAWABLE_CLASS (klass);
209   GObjectClass *object_class = G_OBJECT_CLASS (klass);
210
211   parent_class = g_type_class_peek_parent (klass);
212
213   object_class->finalize = gdk_fb_drawable_finalize;
214   
215   drawable_class->create_gc = _gdk_fb_gc_new;
216   
217 #ifdef ENABLE_SHADOW_FB
218   drawable_class->draw_rectangle = gdk_shadow_fb_draw_rectangle;
219   drawable_class->draw_arc = gdk_shadow_fb_draw_arc;
220   drawable_class->draw_polygon = gdk_shadow_fb_draw_polygon;
221   drawable_class->draw_text = gdk_shadow_fb_draw_text;
222   drawable_class->draw_text_wc = gdk_shadow_fb_draw_text_wc;
223   drawable_class->draw_drawable = gdk_shadow_fb_draw_drawable;
224   drawable_class->draw_points = gdk_shadow_fb_draw_points;
225   drawable_class->draw_segments = gdk_shadow_fb_draw_segments;
226   drawable_class->draw_lines = gdk_shadow_fb_draw_lines;
227   drawable_class->draw_glyphs = gdk_shadow_fb_draw_glyphs;
228   drawable_class->draw_image = gdk_shadow_fb_draw_image;
229 #else
230   drawable_class->draw_rectangle = gdk_fb_draw_rectangle;
231   drawable_class->draw_arc = gdk_fb_draw_arc;
232   drawable_class->draw_polygon = gdk_fb_draw_polygon;
233   drawable_class->draw_text = gdk_fb_draw_text;
234   drawable_class->draw_text_wc = gdk_fb_draw_text_wc;
235   drawable_class->draw_drawable = gdk_fb_draw_drawable;
236   drawable_class->draw_points = gdk_fb_draw_points;
237   drawable_class->draw_segments = gdk_fb_draw_segments;
238   drawable_class->draw_lines = gdk_fb_draw_lines;
239   drawable_class->draw_glyphs = gdk_fb_draw_glyphs;
240   drawable_class->draw_image = gdk_fb_draw_image;
241 #endif
242   
243   drawable_class->set_colormap = gdk_fb_set_colormap;
244   drawable_class->get_colormap = gdk_fb_get_colormap;
245   
246   drawable_class->get_size = gdk_fb_get_size;
247  
248   drawable_class->get_depth = gdk_fb_get_depth;
249   drawable_class->get_screen = gdk_fb_get_screen;
250   drawable_class->get_visual = gdk_fb_get_visual;
251   
252   drawable_class->_copy_to_image = _gdk_fb_copy_to_image;
253 }
254
255 static void
256 gdk_fb_drawable_finalize (GObject *object)
257 {
258   gdk_drawable_set_colormap (GDK_DRAWABLE (object), NULL);
259
260   G_OBJECT_CLASS (parent_class)->finalize (object);
261 }
262
263
264 GType
265 gdk_drawable_impl_fb_get_type (void)
266 {
267   static GType object_type = 0;
268
269   if (!object_type)
270     {
271       static const GTypeInfo object_info =
272       {
273         sizeof (GdkDrawableFBClass),
274         (GBaseInitFunc) NULL,
275         (GBaseFinalizeFunc) NULL,
276         (GClassInitFunc) gdk_drawable_impl_fb_class_init,
277         NULL,           /* class_finalize */
278         NULL,           /* class_data */
279         sizeof (GdkDrawableFBData),
280         0,              /* n_preallocs */
281         (GInstanceInitFunc) NULL,
282       };
283       
284       object_type = g_type_register_static (GDK_TYPE_DRAWABLE,
285                                             "GdkDrawableFB",
286                                             &object_info,
287                                             0);
288     }
289   
290   return object_type;
291 }
292
293 /*****************************************************
294  * FB specific implementations of generic functions *
295  *****************************************************/
296
297 static GdkColormap*
298 gdk_fb_get_colormap (GdkDrawable *drawable)
299 {
300   GdkColormap *retval = GDK_DRAWABLE_FBDATA (drawable)->colormap;
301
302   if (!retval)
303     retval = gdk_colormap_get_system ();
304
305   return retval;
306 }
307
308 static void
309 gdk_fb_set_colormap (GdkDrawable *drawable,
310                      GdkColormap *colormap)
311 {
312   GdkDrawableFBData *private;
313
314   private = GDK_DRAWABLE_FBDATA (drawable);
315
316   if (private->colormap == colormap)
317     return;
318
319   if (private->colormap)
320     gdk_colormap_unref (private->colormap);
321   private->colormap = colormap;
322   if (private->colormap)
323     gdk_colormap_ref (private->colormap);
324 }
325
326 /* Calculates the real clipping region for a drawable, taking into account
327  * other windows, gc clip region and gc clip mask.
328  */
329 GdkRegion *
330 gdk_fb_clip_region (GdkDrawable *drawable,
331                     GdkGC *gc,
332                     gboolean do_clipping,
333                     gboolean do_children,
334                     gboolean full_shapes)
335 {
336   GdkRectangle draw_rect;
337   GdkRegion *real_clip_region, *tmpreg, *shape;
338   gboolean skipit = FALSE;
339   GdkDrawableFBData *private;
340   GdkWindowObject *parent;
341
342   GDK_CHECK_IMPL (drawable);
343   
344   private = GDK_DRAWABLE_FBDATA (drawable);
345   
346   g_assert(!GDK_IS_WINDOW (private->wrapper) ||
347            !GDK_WINDOW_P (private->wrapper)->input_only);
348   
349   draw_rect.x = private->llim_x;
350   draw_rect.y = private->llim_y;
351   if (!GDK_IS_WINDOW (private) ||
352       GDK_WINDOW_IS_MAPPED (private->wrapper))
353     {
354       draw_rect.width = private->lim_x - draw_rect.x;
355       draw_rect.height = private->lim_y - draw_rect.y;
356     }
357   else
358     {
359       draw_rect.width = draw_rect.height = 0;
360       skipit = TRUE;
361     }
362   real_clip_region = gdk_region_rectangle (&draw_rect);
363   if (skipit)
364     return real_clip_region;
365
366   if (GDK_IS_WINDOW (private->wrapper))
367     {
368       parent = GDK_WINDOW_P (private->wrapper);
369       while (parent != (GdkWindowObject *)_gdk_parent_root)
370         {
371           if (full_shapes)
372             {
373               shape = gdk_fb_window_get_abs_shape (GDK_DRAWABLE (parent));
374               if (shape)
375                 {
376                   gdk_region_intersect (real_clip_region, shape);
377                   gdk_region_destroy (shape);
378                 }
379             }
380           else
381             {
382               gint dx, dy;
383               shape = gdk_fb_window_peek_shape (GDK_DRAWABLE (parent), &dx, &dy);
384               if (shape)
385                 {
386                   GdkRectangle rect;
387                   GdkRegion *reg;
388                   
389                   gdk_region_get_clipbox (shape, &rect);
390                   
391                   rect.x += GDK_DRAWABLE_IMPL_FBDATA (parent)->abs_x + dx;
392                   rect.y += GDK_DRAWABLE_IMPL_FBDATA (parent)->abs_y + dy;
393                   
394                   reg = gdk_region_rectangle(&rect);
395                   gdk_region_intersect (real_clip_region, reg);
396                   gdk_region_destroy (reg);
397                 }
398               
399             }
400           parent = parent->parent;
401         }
402     }
403
404   if (gc && GDK_GC_FBDATA(gc)->values.subwindow_mode == GDK_INCLUDE_INFERIORS)
405     do_children = FALSE;
406
407   if (do_clipping &&
408       GDK_IS_WINDOW (private->wrapper) &&
409       GDK_WINDOW_IS_MAPPED (private->wrapper) &&
410       !GDK_WINDOW_P (private->wrapper)->input_only)
411     {
412       GdkWindow *parentwin, *lastwin;
413       GdkDrawableFBData *impl_private;
414
415       lastwin = private->wrapper;
416       if (do_children)
417         parentwin = lastwin;
418       else
419         parentwin = (GdkWindow *)GDK_WINDOW_P (lastwin)->parent;
420
421       /* Remove the areas of all overlapping windows above parentwin in the hiearachy */
422       for (; parentwin; lastwin = parentwin, parentwin = (GdkWindow *)GDK_WINDOW_P (parentwin)->parent)
423         {
424           GList *cur;
425
426           for (cur = GDK_WINDOW_P (parentwin)->children; cur && cur->data != lastwin; cur = cur->next)
427             {
428               if (!GDK_WINDOW_IS_MAPPED (cur->data) || GDK_WINDOW_P (cur->data)->input_only)
429                 continue;
430
431               impl_private = GDK_DRAWABLE_IMPL_FBDATA(cur->data);
432
433               /* This shortcut is really necessary for performance when there are a lot of windows */
434               if (impl_private->llim_x >= real_clip_region->extents.x2 ||
435                   impl_private->lim_x <= real_clip_region->extents.x1 ||
436                   impl_private->llim_y >= real_clip_region->extents.y2 ||
437                   impl_private->lim_y <= real_clip_region->extents.y1)
438                 continue;
439               
440               draw_rect.x = impl_private->llim_x;
441               draw_rect.y = impl_private->llim_y;
442               draw_rect.width = impl_private->lim_x - draw_rect.x;
443               draw_rect.height = impl_private->lim_y - draw_rect.y;
444
445               tmpreg = gdk_region_rectangle (&draw_rect);
446
447               shape = gdk_fb_window_get_abs_shape (impl_private->wrapper);
448               if (shape)
449                 {
450                   gdk_region_intersect (tmpreg, shape);
451                   gdk_region_destroy (shape);
452                 }
453               
454               gdk_region_subtract (real_clip_region, tmpreg);
455               gdk_region_destroy (tmpreg);
456             }
457         }
458     }
459
460   if (gc)
461     {
462       GdkRegion *gc = _gdk_gc_get_clip_region (gc);
463       
464       if (clip_region)
465         {
466           tmpreg = gdk_region_copy (clip_region);
467           gdk_region_offset (tmpreg, private->abs_x + GDK_GC_P (gc)->clip_x_origin,
468                              private->abs_y + GDK_GC_P (gc)->clip_y_origin);
469           gdk_region_intersect (real_clip_region, tmpreg);
470           gdk_region_destroy (tmpreg);
471         }
472
473       if (GDK_GC_FBDATA (gc)->values.clip_mask)
474         {
475           GdkDrawable *cmask = GDK_GC_FBDATA (gc)->values.clip_mask;
476           GdkDrawableFBData *cmask_private;
477
478           cmask_private = GDK_DRAWABLE_IMPL_FBDATA (cmask);
479
480           g_assert (cmask_private->depth == 1);
481           g_assert (cmask_private->abs_x == 0 &&
482                     cmask_private->abs_y == 0);
483
484           draw_rect.x = private->abs_x +
485                         cmask_private->llim_x +
486                         GDK_GC_FBDATA (gc)->values.clip_x_origin;
487           
488           draw_rect.y = private->abs_y +
489                         cmask_private->llim_y +
490                         GDK_GC_FBDATA (gc)->values.clip_y_origin;
491           
492           draw_rect.width = cmask_private->width;
493           draw_rect.height = cmask_private->height;
494
495           tmpreg = gdk_region_rectangle (&draw_rect);
496           gdk_region_intersect (real_clip_region, tmpreg);
497           gdk_region_destroy (tmpreg);
498           /*
499           if (!real_clip_region->numRects)
500             g_warning ("Empty clip region");
501           */
502         }
503     }
504
505   return real_clip_region;
506 }
507
508
509 struct GdkSpanHelper
510 {
511   GdkDrawable *drawable;
512   GdkGC *gc;
513   GdkColor color;
514 };
515
516 static void
517 gdk_fb_fill_span_helper(GdkSpan *span,
518                         gpointer data)
519 {
520   struct GdkSpanHelper *info = (struct GdkSpanHelper *)data;
521   GdkGC * gc = info->gc;
522   
523   (GDK_GC_FBDATA (gc)->fill_span) (info->drawable, gc, span, &info->color);
524 }
525
526 void
527 gdk_fb_fill_spans (GdkDrawable *real_drawable,
528                    GdkGC *gc,
529                    GdkSpan *spans,
530                    int nspans,
531                    gboolean sorted)
532 {
533   int i;
534   struct GdkSpanHelper info;
535   GdkRegion *real_clip_region;
536   gboolean handle_cursor = FALSE;
537   GdkDrawable *drawable;
538   GdkDrawableFBData *private;
539   
540   drawable = real_drawable;
541   private = GDK_DRAWABLE_FBDATA (drawable);
542
543   g_assert (gc);
544
545   if (GDK_IS_WINDOW (private->wrapper) && !GDK_WINDOW_IS_MAPPED (private->wrapper))
546     return;
547   if (GDK_IS_WINDOW (private->wrapper) && GDK_WINDOW_P (private->wrapper)->input_only)
548     g_error ("Drawing on the evil input-only!");
549
550   info.drawable = drawable;
551   info.gc = gc;
552   
553   if (GDK_GC_FBDATA (gc)->values_mask & GDK_GC_FOREGROUND)
554     info.color = GDK_GC_FBDATA (gc)->values.foreground;
555   else if (GDK_IS_WINDOW (private->wrapper))
556     info.color = GDK_WINDOW_P (private->wrapper)->bg_color;
557   else
558     gdk_color_black (private->colormap, &info.color);
559
560   real_clip_region = gdk_fb_clip_region (drawable, gc, TRUE, GDK_GC_FBDATA (gc)->values.function != GDK_INVERT, TRUE);
561
562   if (private->mem == GDK_DRAWABLE_IMPL_FBDATA (_gdk_parent_root)->mem &&
563       gdk_fb_cursor_region_need_hide (real_clip_region))
564     {
565       handle_cursor = TRUE;
566       gdk_fb_cursor_hide ();
567     }
568
569   for (i = 0; i < nspans; i++)
570     {
571       GdkSpan *cur;
572       
573       cur = &spans[i];
574       
575       cur->x += private->abs_x;
576       cur->y += private->abs_y;
577
578       if ( (cur->y < private->llim_y) || (cur->y >= private->lim_y))
579         cur->width = 0;
580       
581       if (cur->x < private->llim_x)
582         {
583           cur->width -= private->llim_x - cur->x;
584           cur->x = private->llim_x;
585         }
586       
587       if (cur->x + cur->width > private->lim_x)
588         {
589           cur->width = private->lim_x - cur->x;
590         }
591
592       if (cur->width <= 0)
593         cur->width = 0;
594     }
595
596   gdk_region_spans_intersect_foreach (real_clip_region,
597                                       spans,
598                                       nspans,
599                                       sorted,
600                                       gdk_fb_fill_span_helper,
601                                       &info);
602
603   gdk_region_destroy (real_clip_region);
604   if (handle_cursor)
605     gdk_fb_cursor_unhide ();
606 }
607
608 void
609 gdk_fb_drawing_context_init (GdkFBDrawingContext *dc,
610                              GdkDrawable *drawable,
611                              GdkGC *gc,
612                              gboolean draw_bg,
613                              gboolean do_clipping)
614 {
615   GdkDrawableFBData *private = GDK_DRAWABLE_FBDATA (drawable);
616   dc->mem = private->mem;
617   dc->rowstride = private->rowstride;
618   dc->handle_cursor = FALSE;
619   dc->bgpm = NULL;
620   dc->bg_relto = private->wrapper;
621   dc->draw_bg = draw_bg;
622
623   GDK_CHECK_IMPL (drawable);
624
625   if (GDK_IS_WINDOW (private->wrapper))
626     {
627       dc->bgpm = GDK_WINDOW_P (private->wrapper)->bg_pixmap;
628       if (dc->bgpm == GDK_PARENT_RELATIVE_BG)
629         {
630           for (; dc->bgpm == GDK_PARENT_RELATIVE_BG && dc->bg_relto; dc->bg_relto = (GdkWindow *)GDK_WINDOW_P (dc->bg_relto)->parent)
631             dc->bgpm = GDK_WINDOW_P (dc->bg_relto)->bg_pixmap;
632         }
633
634       if (dc->bgpm == GDK_NO_BG)
635         dc->bgpm = NULL;
636     }
637   dc->clipxoff = - private->abs_x;
638   dc->clipyoff = - private->abs_y;
639
640   dc->real_clip_region = gdk_fb_clip_region (drawable, gc, do_clipping, TRUE, TRUE);
641
642   if (gc)
643     {
644       dc->clipxoff -= GDK_GC_FBDATA (gc)->values.clip_x_origin;
645       dc->clipyoff -= GDK_GC_FBDATA (gc)->values.clip_y_origin;
646
647       if (GDK_GC_FBDATA (gc)->values.clip_mask)
648         {
649           dc->clipmem = GDK_DRAWABLE_IMPL_FBDATA (GDK_GC_FBDATA (gc)->values.clip_mask)->mem;
650           dc->clip_rowstride = GDK_DRAWABLE_IMPL_FBDATA (GDK_GC_FBDATA (gc)->values.clip_mask)->rowstride;
651         }
652     }
653
654   if (do_clipping &&
655       private->mem == GDK_DRAWABLE_IMPL_FBDATA (_gdk_parent_root)->mem &&
656       gdk_fb_cursor_region_need_hide (dc->real_clip_region))
657     {
658       dc->handle_cursor = TRUE;
659       gdk_fb_cursor_hide ();
660     }
661 }
662
663 void
664 gdk_fb_drawing_context_finalize (GdkFBDrawingContext *dc)
665 {
666   gdk_region_destroy (dc->real_clip_region);
667
668   if (dc->handle_cursor)
669     gdk_fb_cursor_unhide ();
670 }
671
672 void
673 gdk_fb_draw_drawable_2 (GdkDrawable *drawable,
674                         GdkGC       *gc,
675                         GdkPixmap   *src,
676                         gint         xsrc,
677                         gint         ysrc,
678                         gint         xdest,
679                         gint         ydest,
680                         gint         width,
681                         gint         height,
682                         gboolean     draw_bg,
683                         gboolean     do_clipping)
684 {
685   GdkFBDrawingContext *dc, dc_data;
686   dc = &dc_data;
687
688   GDK_CHECK_IMPL (src);
689   GDK_CHECK_IMPL (drawable);
690   
691   gdk_fb_drawing_context_init (dc, drawable, gc, draw_bg, do_clipping);
692   gdk_fb_draw_drawable_3 (drawable, gc, src, dc, xsrc, ysrc, xdest, ydest, width, height);
693   gdk_fb_drawing_context_finalize (dc);
694 }
695
696 void
697 gdk_fb_draw_drawable_3 (GdkDrawable *drawable,
698                         GdkGC       *gc,
699                         GdkPixmap   *src,
700                         GdkFBDrawingContext *dc,
701                         gint         xsrc,
702                         gint         ysrc,
703                         gint         xdest,
704                         gint         ydest,
705                         gint         width,
706                         gint         height)
707 {
708   GdkDrawableFBData *private = GDK_DRAWABLE_FBDATA (drawable);
709   GdkDrawableFBData *src_private = GDK_DRAWABLE_FBDATA (src);
710   GdkRectangle rect;
711   int src_x_off, src_y_off;
712   GdkRegion *tmpreg, *real_clip_region;
713   int i;
714   int draw_direction = 1;
715   gdk_fb_draw_drawable_func *draw_func = NULL;
716   GdkGCFBData *gc_private;
717
718   g_assert (gc);
719
720   GDK_CHECK_IMPL (src);
721   GDK_CHECK_IMPL (drawable);
722
723   if (GDK_IS_WINDOW (private->wrapper))
724     {
725       if (!GDK_WINDOW_IS_MAPPED (private->wrapper))
726         return;
727       if (GDK_WINDOW_P (private->wrapper)->input_only)
728         g_error ("Drawing on the evil input-only!");
729     }
730
731   gc_private = GDK_GC_FBDATA (gc);
732   
733   if (drawable == src)
734     {
735       GdkRegionBox srcb, destb;
736       srcb.x1 = xsrc;
737       srcb.y1 = ysrc;
738       srcb.x2 = xsrc + width;
739       srcb.y2 = ysrc + height;
740       destb.x1 = xdest;
741       destb.y1 = ydest;
742       destb.x2 = xdest + width;
743       destb.y2 = ydest + height;
744
745       if (EXTENTCHECK (&srcb, &destb) && ((ydest > ysrc) || ((ydest == ysrc) && (xdest > xsrc))))
746         draw_direction = -1;
747     }
748
749   switch (src_private->depth)
750     {
751     case 1:
752       draw_func = gc_private->draw_drawable[GDK_FB_SRC_BPP_1];
753       break;
754     case 8:
755       draw_func = gc_private->draw_drawable[GDK_FB_SRC_BPP_8];
756       break;
757     case 16:
758       draw_func = gc_private->draw_drawable[GDK_FB_SRC_BPP_16];
759       break;
760     case 24:
761       draw_func = gc_private->draw_drawable[GDK_FB_SRC_BPP_24];
762       break;
763     case 32:
764       draw_func = gc_private->draw_drawable[GDK_FB_SRC_BPP_32];
765       break;
766     case 77:
767       draw_func = gc_private->draw_drawable[GDK_FB_SRC_BPP_7_AA_GRAYVAL];
768       break;
769     case 78:
770       draw_func = gc_private->draw_drawable[GDK_FB_SRC_BPP_8_AA_GRAYVAL];
771       break;
772     default:
773       g_assert_not_reached ();
774       break;
775     }
776   
777   /* Do some magic to avoid creating extra regions unnecessarily */
778   tmpreg = dc->real_clip_region;
779
780   rect.x = xdest + private->abs_x;
781   rect.y = ydest + private->abs_y;
782   rect.width = width;
783   rect.height = height;
784   real_clip_region = gdk_region_rectangle (&rect);
785   gdk_region_intersect (real_clip_region, tmpreg);
786
787   rect.x = xdest + private->abs_x;
788   rect.y = ydest + private->abs_y;
789   rect.width = MAX (src_private->width - xsrc, 0);
790   rect.height = MAX (src_private->height - ysrc, 0);
791   if (!rect.width || !rect.height)
792     goto out;
793   tmpreg = gdk_region_rectangle (&rect);
794   gdk_region_intersect (real_clip_region, tmpreg);
795   gdk_region_destroy (tmpreg);
796
797   src_x_off = (src_private->abs_x + xsrc) - (private->abs_x + xdest);
798   src_y_off = (src_private->abs_y + ysrc) - (private->abs_y + ydest);
799
800   for (i = (draw_direction>0)?0:real_clip_region->numRects-1; i >= 0 && i < real_clip_region->numRects; i+=draw_direction)
801     {
802       GdkRegionBox *cur = &real_clip_region->rects[i];
803
804       (*draw_func) (drawable,
805                     gc,
806                     src,
807                     dc,
808                     cur->y1,
809                     cur->y2,
810                     cur->x1,
811                     cur->x2,
812                     src_x_off,
813                     src_y_off,
814                     draw_direction);
815     }
816
817  out:
818   gdk_region_destroy (real_clip_region);
819 }
820
821
822 void
823 gdk_fb_draw_drawable (GdkDrawable *drawable,
824                       GdkGC       *gc,
825                       GdkPixmap   *src,
826                       gint         xsrc,
827                       gint         ysrc,
828                       gint         xdest,
829                       gint         ydest,
830                       gint         width,
831                       gint         height)
832 {
833   GdkPixmap   *src_impl;
834
835   if (GDK_IS_DRAWABLE_IMPL_FBDATA (src))
836     src_impl = src;
837   else
838     src_impl = GDK_DRAWABLE_IMPL (src);
839
840   GDK_CHECK_IMPL (drawable);
841   
842   gdk_fb_draw_drawable_2 (drawable, gc, src_impl , xsrc, ysrc, xdest, ydest, width, height, TRUE, TRUE);
843 }
844
845 #ifdef EMULATE_GDKFONT
846 static void
847 gdk_fb_draw_text(GdkDrawable    *drawable,
848                  GdkFont        *font,
849                  GdkGC          *gc,
850                  gint            x,
851                  gint            y,
852                  const gchar    *text,
853                  gint            text_length)
854 {
855   GdkFontPrivateFB *private;
856   guchar *utf8, *utf8_end;
857   PangoGlyphString *glyphs = pango_glyph_string_new ();
858   PangoEngineShape *shaper, *last_shaper;
859   PangoAnalysis analysis;
860   guchar *p, *start;
861   gint x_offset;
862   int i;
863   
864   g_return_if_fail (font != NULL);
865   g_return_if_fail (text != NULL);
866
867   private = (GdkFontPrivateFB*) font;
868
869   utf8 = alloca (text_length*2);
870
871   /* Convert latin-1 to utf8 */
872   p = utf8;
873   for (i = 0; i < text_length; i++)
874     {
875       if (text[i]==0)
876         *p++ = 1; /* Hack to handle embedded nulls */
877       else
878         {
879           if(((guchar)text[i])<128)
880             *p++ = text[i];
881           else
882             {
883               *p++ = ((((guchar)text[i])>>6) & 0x3f) | 0xC0;
884               *p++ = (((guchar)text[i]) & 0x3f) | 0x80;
885             }
886         }
887     }
888   utf8_end = p;
889
890   last_shaper = NULL;
891   shaper = NULL;
892
893   x_offset = 0;
894   p = start = utf8;
895   while (p < utf8_end)
896     {
897       gunichar wc = g_utf8_get_char (p);
898       p = g_utf8_next_char (p);
899       shaper = pango_font_find_shaper (private->pango_font, pango_language_from_string ("fr"), wc);
900       if (shaper != last_shaper)
901         {
902           analysis.shape_engine = shaper;
903           analysis.lang_engine = NULL;
904           analysis.font = private->pango_font;
905           analysis.level = 0;
906           
907           pango_shape (start, p - start, &analysis, glyphs);
908
909           gdk_fb_draw_glyphs (drawable, gc, private->pango_font,
910                               x + PANGO_PIXELS (x_offset), y,
911                               glyphs);
912           
913           for (i = 0; i < glyphs->num_glyphs; i++)
914             x_offset += glyphs->glyphs[i].geometry.width;
915           
916           start = p;
917         }
918
919       last_shaper = shaper;
920     }
921
922   if (p > start)
923     {
924       analysis.shape_engine = shaper;
925       analysis.lang_engine = NULL;
926       analysis.font = private->pango_font;
927       analysis.level = 0;
928       
929       pango_shape (start, p - start, &analysis, glyphs);
930       
931       gdk_fb_draw_glyphs (drawable, gc, private->pango_font,
932                           x + PANGO_PIXELS (x_offset), y,
933                           glyphs);
934     }
935   
936   pango_glyph_string_free (glyphs);
937       
938   return;
939 }
940
941 #else
942 static void
943 gdk_fb_draw_text(GdkDrawable    *drawable,
944                  GdkFont        *font,
945                  GdkGC          *gc,
946                  gint            x,
947                  gint            y,
948                  const gchar    *text,
949                  gint            text_length)
950 {
951   g_warning ("gdk_fb_draw_text NYI");
952 }
953 #endif
954
955 static void
956 gdk_fb_draw_text_wc (GdkDrawable    *drawable,
957                      GdkFont         *font,
958                      GdkGC           *gc,
959                      gint             x,
960                      gint             y,
961                      const GdkWChar *text,
962                      gint             text_length)
963 {
964   g_warning ("gdk_fb_draw_text_wc NYI");
965 }
966
967 void
968 gdk_fb_draw_rectangle (GdkDrawable    *drawable,
969                        GdkGC          *gc,
970                        gboolean        filled,
971                        gint            x,
972                        gint            y,
973                        gint            width,
974                        gint            height)
975 {
976   GdkDrawableFBData *private;
977   
978   private = GDK_DRAWABLE_FBDATA (drawable);
979   
980   if (filled)
981     {
982       gboolean handle_cursor = FALSE;
983       GdkRectangle tmprect;
984       GdkRegion *tmpreg;
985       GdkRegion *real_clip_region;
986       GdkColor color;
987       int i;
988       
989       if (GDK_GC_FBDATA (gc)->values_mask & GDK_GC_FOREGROUND)
990         color = GDK_GC_FBDATA (gc)->values.foreground;
991       else if (GDK_IS_WINDOW (private->wrapper))
992         color = GDK_WINDOW_P (private->wrapper)->bg_color;
993       else
994         gdk_color_black (private->colormap, &color);
995       
996       real_clip_region = gdk_fb_clip_region (drawable, gc, TRUE, GDK_GC_FBDATA (gc)->values.function != GDK_INVERT, TRUE);
997       
998       if (private->mem == GDK_DRAWABLE_IMPL_FBDATA (_gdk_parent_root)->mem &&
999           gdk_fb_cursor_region_need_hide (real_clip_region))
1000         {
1001           handle_cursor = TRUE;
1002           gdk_fb_cursor_hide ();
1003         }
1004       
1005       x += private->abs_x;
1006       y += private->abs_y;
1007   
1008       if (x <  private->llim_x)
1009         {
1010           width -= private->llim_x - x;
1011           x = private->llim_x;
1012         }
1013       if (x + width >  private->lim_x)
1014         width =  private->lim_x - x;
1015       
1016       if (y <  private->llim_y)
1017         {
1018           height -= private->llim_y - y;
1019           y = private->llim_y;
1020         }
1021       if (y + height >  private->lim_y)
1022         height =  private->lim_y - y;
1023
1024       tmprect.x = x;
1025       tmprect.y = y;
1026       tmprect.width = width;
1027       tmprect.height = height;
1028       tmpreg = gdk_region_rectangle (&tmprect);
1029       
1030       gdk_region_intersect (tmpreg, real_clip_region);
1031       
1032       for (i = 0; i < tmpreg->numRects; i++)
1033         {
1034           GdkRectangle r;
1035           r.x = tmpreg->rects[i].x1;
1036           r.y = tmpreg->rects[i].y1;
1037           r.width = tmpreg->rects[i].x2 - tmpreg->rects[i].x1;
1038           r.height = tmpreg->rects[i].y2 - tmpreg->rects[i].y1;
1039
1040           if ((r.width > 0) && (r.height > 0))
1041             (GDK_GC_FBDATA (gc)->fill_rectangle) (drawable, gc, &r, &color);
1042         }
1043       
1044       gdk_region_destroy (tmpreg);
1045       
1046       gdk_region_destroy (real_clip_region);
1047       if (handle_cursor)
1048         gdk_fb_cursor_unhide ();
1049     }
1050   else
1051     {
1052       GdkPoint pts[5];
1053       
1054       pts[0].x = pts[4].x = x;
1055       pts[0].y = pts[4].y = y;
1056       pts[1].x = x + width;
1057       pts[1].y = y;
1058       pts[2].x = x + width;
1059       pts[2].y = y + height;
1060       pts[3].x = x;
1061       pts[3].y = y + height;
1062       gdk_fb_draw_lines (drawable, gc, pts, 5);
1063     }
1064
1065 }
1066
1067 static void
1068 gdk_fb_draw_points (GdkDrawable    *drawable,
1069                     GdkGC          *gc,
1070                     GdkPoint       *points,
1071                     gint            npoints)
1072 {
1073   GdkSpan *spans = g_alloca (npoints * sizeof(GdkSpan));
1074   int i;
1075
1076   for (i = 0; i < npoints; i++)
1077     {
1078       spans[i].x = points[i].x;
1079       spans[i].y = points[i].y;
1080       spans[i].width = 1;
1081     }
1082
1083   gdk_fb_fill_spans (drawable, gc, spans, npoints, FALSE);
1084 }
1085
1086 static void
1087 gdk_fb_draw_arc (GdkDrawable    *drawable,
1088                  GdkGC          *gc,
1089                  gboolean        filled,
1090                  gint            x,
1091                  gint            y,
1092                  gint            width,
1093                  gint            height,
1094                  gint            angle1,
1095                  gint            angle2)
1096 {
1097   miArc arc;
1098
1099   arc.x = x;
1100   arc.y = y;
1101   arc.width = width;
1102   arc.height = height;
1103   arc.angle1 = angle1;
1104   arc.angle2 = angle2;
1105
1106   if (filled)
1107     miPolyFillArc (drawable, gc, 1, &arc);
1108   else
1109     miPolyArc (drawable, gc, 1, &arc);
1110 }
1111
1112 static void
1113 gdk_fb_draw_polygon (GdkDrawable    *drawable,
1114                      GdkGC          *gc,
1115                      gboolean        filled,
1116                      GdkPoint       *points,
1117                      gint            npoints)
1118 {
1119   if (filled)
1120     miFillPolygon (drawable, gc, 0, 0, npoints, points);
1121   else
1122     {
1123       gint tmp_npoints;
1124       gboolean free_points = FALSE;
1125       GdkPoint *tmp_points;
1126
1127       if (points[0].x != points[npoints-1].x || points[0].y != points[npoints-1].y)
1128         {
1129           tmp_npoints = npoints + 1;
1130           tmp_points = g_new (GdkPoint, tmp_npoints);
1131           free_points = TRUE;
1132           memcpy (tmp_points, points, sizeof(GdkPoint) * npoints);
1133           tmp_points[npoints].x = points[0].x;
1134           tmp_points[npoints].y = points[0].y;
1135         }
1136       else
1137         {
1138           tmp_npoints = npoints;
1139           tmp_points = points;
1140         }
1141
1142       gdk_fb_draw_lines (drawable, gc, tmp_points, tmp_npoints);
1143       
1144       if (free_points)
1145         g_free (tmp_points);
1146     }
1147 }
1148
1149 static void
1150 gdk_fb_draw_lines (GdkDrawable    *drawable,
1151                    GdkGC          *gc,
1152                    GdkPoint       *points,
1153                    gint            npoints)
1154 {
1155   GdkGCFBData *private;
1156
1157   private = GDK_GC_FBDATA (gc);
1158   if (private->values.line_width > 0)
1159     {
1160       if ((private->values.line_style != GDK_LINE_SOLID) && private->dash_list)
1161         miWideDash (drawable, gc, 0, npoints, points);
1162       else 
1163         miWideLine (drawable, gc, 0, npoints, points);
1164     }
1165   else
1166     {
1167       if ((private->values.line_style != GDK_LINE_SOLID) && private->dash_list)
1168         miZeroDashLine (drawable, gc, 0, npoints, points);
1169       else 
1170         miZeroLine (drawable, gc, 0, npoints, points);
1171     }
1172 }
1173
1174 static void
1175 gdk_fb_draw_segments (GdkDrawable    *drawable,
1176                       GdkGC          *gc,
1177                       GdkSegment     *segs,
1178                       gint            nsegs)
1179 {
1180   GdkPoint pts[2];
1181   int i;
1182
1183   for(i = 0; i < nsegs; i++)
1184     {
1185       pts[0].x = segs[i].x1;
1186       pts[0].y = segs[i].y1;
1187       pts[1].x = segs[i].x2;
1188       pts[1].y = segs[i].y2;
1189
1190       gdk_fb_draw_lines (drawable, gc, pts, 2);
1191     }
1192 }
1193
1194 void
1195 gdk_fb_drawable_clear (GdkDrawable *d)
1196 {
1197   extern void
1198     _gdk_windowing_window_clear_area (GdkWindow *window,
1199                                       gint       x,
1200                                       gint       y,
1201                                       gint       width,
1202                                       gint       height);
1203
1204   _gdk_windowing_window_clear_area (d, 0, 0, GDK_DRAWABLE_IMPL_FBDATA (d)->width, GDK_DRAWABLE_IMPL_FBDATA (d)->height);
1205 }
1206
1207 static void
1208 _gdk_fb_draw_glyphs (GdkDrawable      *drawable,
1209                      GdkGC           *gc,
1210                      PangoFont        *font,
1211                      gint              x,
1212                      gint              y,
1213                      PangoGlyphString *glyphs,
1214                      GdkRectangle     *bbox)
1215 {
1216   GdkFBDrawingContext fbdc;
1217   GdkPixmapFBData pixmap;
1218   PangoGlyphInfo *gi;
1219   FT_Face face;
1220   FT_UInt glyph_index;
1221   int i, xpos;
1222   int maxy, miny;
1223   int topy;
1224
1225   g_return_if_fail (font);
1226
1227   gdk_fb_drawing_context_init (&fbdc, drawable, gc, FALSE, TRUE);
1228
1229   /* Fake its existence as a pixmap */
1230
1231   ((GTypeInstance *)&pixmap)->g_class = g_type_class_peek (_gdk_pixmap_impl_get_type ());
1232   pixmap.drawable_data.abs_x = 0;
1233   pixmap.drawable_data.abs_y = 0;
1234   pixmap.drawable_data.depth = 78;
1235
1236   maxy = miny = 0;
1237   
1238   gi = glyphs->glyphs;
1239   for (i = 0, xpos = 0; i < glyphs->num_glyphs; i++, gi++)
1240     {
1241       if (gi->glyph)
1242         {
1243           glyph_index = gi->glyph;
1244           face = pango_ft2_font_get_face (font);
1245
1246           if (face)
1247             {
1248               /* Draw glyph */
1249               FT_Load_Glyph (face, glyph_index, FT_LOAD_DEFAULT);
1250               if (face->glyph->format != ft_glyph_format_bitmap)
1251                 FT_Render_Glyph (face->glyph, ft_render_mode_normal);
1252
1253               pixmap.drawable_data.mem = face->glyph->bitmap.buffer;
1254               pixmap.drawable_data.rowstride = face->glyph->bitmap.pitch;
1255               pixmap.drawable_data.width = face->glyph->bitmap.width;
1256               pixmap.drawable_data.height = face->glyph->bitmap.rows;
1257
1258               topy = y - face->glyph->bitmap_top + 1;
1259               miny = MIN (miny, topy);
1260               maxy = MAX (maxy, topy + face->glyph->bitmap.rows);
1261               gdk_fb_draw_drawable_3 (drawable, gc, (GdkPixmap *)&pixmap,
1262                                       &fbdc,
1263                                       0, 0,
1264                                       x + PANGO_PIXELS (xpos) + face->glyph->bitmap_left,
1265                                       topy,
1266                                       face->glyph->bitmap.width, face->glyph->bitmap.rows);
1267             }
1268         }
1269       xpos += glyphs->glyphs[i].geometry.width;
1270     }
1271
1272   gdk_fb_drawing_context_finalize (&fbdc);
1273
1274   if (bbox)
1275     {
1276       bbox->x = x;
1277       bbox->y = miny;
1278       bbox->width = xpos;
1279       bbox->height = maxy - miny;
1280     }
1281 }
1282
1283 static void
1284 gdk_fb_draw_glyphs (GdkDrawable      *drawable,
1285                     GdkGC            *gc,
1286                     PangoFont        *font,
1287                     gint              x,
1288                     gint              y,
1289                     PangoGlyphString *glyphs)
1290 {
1291   _gdk_fb_draw_glyphs (drawable, gc, font, x, y, glyphs, NULL);
1292 }
1293
1294 static void
1295 gdk_fb_draw_image (GdkDrawable *drawable,
1296                    GdkGC       *gc,
1297                    GdkImage    *image,
1298                    gint         xsrc,
1299                    gint         ysrc,
1300                    gint         xdest,
1301                    gint         ydest,
1302                    gint         width,
1303                    gint         height)
1304 {
1305   GdkImagePrivateFB *image_private;
1306   GdkPixmapFBData fbd;
1307
1308   g_return_if_fail (drawable != NULL);
1309   g_return_if_fail (image != NULL);
1310   g_return_if_fail (gc != NULL);
1311
1312   image_private = (GdkImagePrivateFB*) image;
1313
1314   g_return_if_fail (image->type == GDK_IMAGE_NORMAL);
1315
1316   /* Fake its existence as a pixmap */
1317   memset (&fbd, 0, sizeof(fbd));
1318
1319   ((GTypeInstance *)&fbd)->g_class = g_type_class_peek (_gdk_pixmap_impl_get_type ());
1320   
1321   fbd.drawable_data.mem = image->mem;
1322   fbd.drawable_data.rowstride = image->bpl;
1323   fbd.drawable_data.width = fbd.drawable_data.lim_x = image->width;
1324   fbd.drawable_data.height = fbd.drawable_data.lim_y = image->height;
1325   fbd.drawable_data.depth = image->depth;
1326   fbd.drawable_data.window_type = GDK_DRAWABLE_PIXMAP;
1327   fbd.drawable_data.colormap = gdk_colormap_get_system ();
1328   
1329   gdk_fb_draw_drawable_2 (drawable, gc, (GdkPixmap *)&fbd, xsrc, ysrc, xdest, ydest, width, height, TRUE, TRUE);
1330 }
1331
1332 static gint
1333 gdk_fb_get_depth (GdkDrawable *drawable)
1334 {
1335   return GDK_DRAWABLE_FBDATA (drawable)->depth;
1336 }
1337
1338 static GdkScreen*
1339 gdk_fb_get_screen (GdkDrawable *drawable)
1340 {
1341   return gdk_screen_get_default();
1342 }
1343
1344 static GdkVisual*
1345 gdk_fb_get_visual (GdkDrawable    *drawable)
1346 {
1347   return gdk_visual_get_system();
1348 }
1349
1350 #ifdef ENABLE_SHADOW_FB
1351 static void
1352 gdk_shadow_fb_draw_rectangle (GdkDrawable      *drawable,
1353                               GdkGC            *gc,
1354                               gboolean          filled,
1355                               gint              x,
1356                               gint              y,
1357                               gint              width,
1358                               gint              height)
1359 {
1360   GdkDrawableFBData *private;
1361
1362   gdk_fb_draw_rectangle (drawable, gc, filled, x, y, width, height);
1363
1364   private = GDK_DRAWABLE_FBDATA (drawable);
1365   if (GDK_IS_WINDOW (private->wrapper))
1366     {
1367       gint minx, miny, maxx, maxy;
1368       gint extra_width;
1369   
1370       minx = x + private->abs_x;
1371       miny = y + private->abs_y;
1372       maxx = x + width + private->abs_x;
1373       maxy = y + height + private->abs_y;
1374       
1375       if (!filled)
1376         {
1377           extra_width = (GDK_GC_FBDATA (gc)->values.line_width + 1) / 2;
1378           
1379           minx -= extra_width;
1380           miny -= extra_width;
1381           maxx += extra_width;
1382           maxy += extra_width;
1383         }
1384       gdk_shadow_fb_update (minx, miny, maxx, maxy);
1385     }
1386 }
1387
1388 static void
1389 gdk_shadow_fb_draw_arc (GdkDrawable      *drawable,
1390                         GdkGC            *gc,
1391                         gboolean          filled,
1392                         gint              x,
1393                         gint              y,
1394                         gint              width,
1395                         gint              height,
1396                         gint              angle1,
1397                         gint              angle2)
1398 {
1399   GdkDrawableFBData *private;
1400   
1401   gdk_fb_draw_arc (drawable, gc, filled, x, y, width, height, angle1, angle2);
1402
1403   private = GDK_DRAWABLE_FBDATA (drawable);
1404   if (GDK_IS_WINDOW (private->wrapper))
1405     {
1406       gint minx, miny, maxx, maxy;
1407       gint extra_width;
1408   
1409       minx = x + private->abs_x;
1410       miny = y + private->abs_y;
1411       maxx = x + width + private->abs_x;
1412       maxy = y + height + private->abs_y;
1413       
1414       if (!filled)
1415         {
1416           extra_width = (GDK_GC_FBDATA (gc)->values.line_width + 1) / 2;
1417           
1418           minx -= extra_width;
1419           miny -= extra_width;
1420           maxx += extra_width;
1421           maxy += extra_width;
1422         }
1423       gdk_shadow_fb_update (minx, miny, maxx, maxy);
1424     }
1425 }
1426
1427 static void
1428 gdk_shadow_fb_draw_polygon (GdkDrawable      *drawable,
1429                             GdkGC            *gc,
1430                             gboolean          filled,
1431                             GdkPoint         *points,
1432                             gint              npoints)
1433 {
1434   GdkDrawableFBData *private;
1435
1436   gdk_fb_draw_polygon (drawable, gc, filled, points, npoints);
1437
1438   private = GDK_DRAWABLE_FBDATA (drawable);
1439   if (GDK_IS_WINDOW (private->wrapper))
1440     {
1441       gint minx, miny, maxx, maxy;
1442       gint extra_width;
1443       int i;
1444   
1445       minx = maxx = points[0].x;
1446       miny = maxy = points[0].y;
1447
1448       for (i = 1; i < npoints; i++)
1449         {
1450           minx = MIN(minx, points[i].x);
1451           maxx = MAX(maxx, points[i].x);
1452           miny = MIN(miny, points[i].y);
1453           maxy = MAX(maxy, points[i].y);
1454         }
1455       
1456       if (!filled)
1457         {
1458           extra_width = (GDK_GC_FBDATA (gc)->values.line_width + 1) / 2;
1459           
1460           minx -= extra_width;
1461           miny -= extra_width;
1462           maxx += extra_width;
1463           maxy += extra_width;
1464         }
1465       gdk_shadow_fb_update (minx + private->abs_x, miny + private->abs_y,
1466                             maxx + private->abs_x, maxy + private->abs_y);
1467     }
1468 }
1469
1470 static void
1471 gdk_shadow_fb_draw_text (GdkDrawable      *drawable,
1472                          GdkFont          *font,
1473                          GdkGC            *gc,
1474                          gint              x,
1475                          gint              y,
1476                          const gchar      *text,
1477                          gint              text_length)
1478 {
1479   gdk_fb_draw_text (drawable, font, gc, x, y, text, text_length);
1480 }
1481
1482 static void
1483 gdk_shadow_fb_draw_text_wc (GdkDrawable      *drawable,
1484                             GdkFont          *font,
1485                             GdkGC            *gc,
1486                             gint              x,
1487                             gint              y,
1488                             const GdkWChar   *text,
1489                             gint              text_length)
1490 {
1491   gdk_fb_draw_text_wc (drawable, font, gc, x, y, text, text_length);
1492 }
1493
1494 static void
1495 gdk_shadow_fb_draw_glyphs (GdkDrawable      *drawable,
1496                            GdkGC            *gc,
1497                            PangoFont        *font,
1498                            gint              x,
1499                            gint              y,
1500                            PangoGlyphString *glyphs)
1501 {
1502   GdkDrawableFBData *private;
1503   GdkRectangle bbox;
1504   
1505   _gdk_fb_draw_glyphs (drawable, gc, font, x, y, glyphs, &bbox);
1506   
1507   private = GDK_DRAWABLE_FBDATA (drawable);
1508   if (GDK_IS_WINDOW (private->wrapper))
1509     gdk_shadow_fb_update (bbox.x + private->abs_x, bbox.y + private->abs_y,
1510                           bbox.x + private->abs_x + bbox.width, bbox.y + private->abs_y + bbox.height);
1511 }
1512
1513 static void
1514 gdk_shadow_fb_draw_drawable (GdkDrawable      *drawable,
1515                              GdkGC            *gc,
1516                              GdkPixmap        *src,
1517                              gint              xsrc,
1518                              gint              ysrc,
1519                              gint              xdest,
1520                              gint              ydest,
1521                              gint              width,
1522                              gint              height)
1523 {
1524   GdkDrawableFBData *private;
1525   
1526   gdk_fb_draw_drawable (drawable, gc, src, xsrc, ysrc, xdest, ydest, width, height);
1527   
1528   private = GDK_DRAWABLE_FBDATA (drawable);
1529   if (GDK_IS_WINDOW (private->wrapper))
1530     gdk_shadow_fb_update (xdest + private->abs_x, ydest + private->abs_y,
1531                           xdest + private->abs_x + width, ydest + private->abs_y + height);
1532 }
1533
1534 static void
1535 gdk_shadow_fb_draw_image (GdkDrawable      *drawable,
1536                           GdkGC            *gc,
1537                           GdkImage         *image,
1538                           gint              xsrc,
1539                           gint              ysrc,
1540                           gint              xdest,
1541                           gint              ydest,
1542                           gint              width,
1543                           gint              height)
1544 {
1545   GdkDrawableFBData *private;
1546   
1547   gdk_fb_draw_image (drawable, gc, image, xsrc, ysrc, xdest, ydest, width, height);
1548   
1549   private = GDK_DRAWABLE_FBDATA (drawable);
1550   if (GDK_IS_WINDOW (private->wrapper))
1551     gdk_shadow_fb_update (xdest + private->abs_x, ydest + private->abs_y,
1552                           xdest + private->abs_x + width, ydest + private->abs_y + height);
1553 }
1554
1555 static void
1556 gdk_shadow_fb_draw_points (GdkDrawable      *drawable,
1557                            GdkGC            *gc,
1558                            GdkPoint         *points,
1559                            gint              npoints)
1560 {
1561   GdkDrawableFBData *private;
1562
1563   gdk_fb_draw_points (drawable, gc, points, npoints);
1564
1565   private = GDK_DRAWABLE_FBDATA (drawable);
1566   if (GDK_IS_WINDOW (private->wrapper))
1567     {
1568       gint minx, miny, maxx, maxy;
1569       int i;
1570   
1571       minx = maxx = points[0].x;
1572       miny = maxy = points[0].y;
1573
1574       for (i = 1; i < npoints; i++)
1575         {
1576           minx = MIN(minx, points[i].x);
1577           maxx = MAX(maxx, points[i].x);
1578           miny = MIN(miny, points[i].y);
1579           maxy = MAX(maxy, points[i].y);
1580         }
1581       
1582       gdk_shadow_fb_update (minx + private->abs_x, miny + private->abs_y,
1583                             maxx + private->abs_x, maxy + private->abs_y);
1584     }
1585 }
1586
1587 static void
1588 gdk_shadow_fb_draw_segments (GdkDrawable      *drawable,
1589                              GdkGC            *gc,
1590                              GdkSegment       *segs,
1591                              gint              nsegs)
1592 {
1593   GdkDrawableFBData *private;
1594
1595   gdk_fb_draw_segments (drawable, gc, segs, nsegs);
1596
1597   private = GDK_DRAWABLE_FBDATA (drawable);
1598   if (GDK_IS_WINDOW (private->wrapper))
1599     {
1600       gint minx, miny, maxx, maxy;
1601       gint extra_width;
1602       int i;
1603   
1604       minx = maxx = segs[0].x1;
1605       miny = maxy = segs[0].y1;
1606
1607       for (i = 0; i < nsegs; i++)
1608         {
1609           minx = MIN(minx, segs[i].x1);
1610           maxx = MAX(maxx, segs[i].x1);
1611           minx = MIN(minx, segs[i].x2);
1612           maxx = MAX(maxx, segs[i].x2);
1613           
1614           miny = MIN(miny, segs[i].y1);
1615           maxy = MAX(maxy, segs[i].y1);
1616           miny = MIN(miny, segs[i].y2);
1617           maxy = MAX(maxy, segs[i].y2);
1618
1619         }
1620       
1621       extra_width = (GDK_GC_FBDATA (gc)->values.line_width + 1) / 2;
1622       
1623       minx -= extra_width;
1624       miny -= extra_width;
1625       maxx += extra_width;
1626       maxy += extra_width;
1627       
1628       gdk_shadow_fb_update (minx + private->abs_x, miny + private->abs_y,
1629                             maxx + private->abs_x, maxy + private->abs_y);
1630     }
1631 }
1632
1633 static void
1634 gdk_shadow_fb_draw_lines (GdkDrawable      *drawable,
1635                           GdkGC            *gc,
1636                           GdkPoint         *points,
1637                           gint              npoints)
1638 {
1639   GdkDrawableFBData *private;
1640
1641   gdk_fb_draw_lines (drawable, gc, points, npoints);
1642
1643   private = GDK_DRAWABLE_FBDATA (drawable);
1644   if (GDK_IS_WINDOW (private->wrapper))
1645     {
1646       gint minx, miny, maxx, maxy;
1647       gint extra_width;
1648       int i;
1649   
1650       minx = maxx = points[0].x;
1651       miny = maxy = points[0].y;
1652
1653       for (i = 1; i < npoints; i++)
1654         {
1655           minx = MIN(minx, points[i].x);
1656           maxx = MAX(maxx, points[i].x);
1657           miny = MIN(miny, points[i].y);
1658           maxy = MAX(maxy, points[i].y);
1659         }
1660       
1661       extra_width = (GDK_GC_FBDATA (gc)->values.line_width + 1) / 2;
1662           
1663       minx -= extra_width;
1664       miny -= extra_width;
1665       maxx += extra_width;
1666       maxy += extra_width;
1667       
1668       gdk_shadow_fb_update (minx + private->abs_x, miny + private->abs_y,
1669                             maxx + private->abs_x, maxy + private->abs_y);
1670     }
1671 }
1672
1673 #endif
1674
1675 gboolean
1676 gdk_draw_rectangle_alpha_libgtk_only (GdkDrawable *drawable,
1677                                       gint         x,
1678                                       gint         y,
1679                                       gint         width,
1680                                       gint         height,
1681                                       GdkColor    *color,
1682                                       guint16      alpha)
1683 {
1684   return FALSE;
1685 }