]> Pileus Git - ~andy/gtk/blob - gdk/linux-fb/gdkrender-fb.c
Take thickness into account in the size allocation of the child widgets in
[~andy/gtk] / gdk / linux-fb / gdkrender-fb.c
1 /* GDK - The GIMP Drawing Kit
2  * Copyright (C) 2000 Alexander Larsson
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 <string.h>
30 #include <signal.h>
31 #include <sys/time.h>
32
33 /*
34  * Reading pixel values from a generic drawable.
35  */
36
37 static GetPixelRet
38 gdk_fb_drawable_get_color (GdkDrawable *drawable,
39                            GdkGC *gc,
40                            int x,
41                            int y,
42                            GdkColor *spot)
43 {
44   GetPixelRet retval = GPR_NONE;
45   GdkDrawableFBData *private = GDK_DRAWABLE_FBDATA (drawable);
46   guchar *mem = private->mem;
47   guint rowstride = private->rowstride;
48
49   switch (private->depth)
50     {
51     case 1:
52       {
53         guchar foo = mem[(x >> 3) + y * rowstride];
54         if (foo & (1 << (x % 8)))
55           *spot = GDK_GC_FBDATA (gc)->values.foreground;
56         else
57           {
58             retval = GPR_USED_BG;
59             *spot = GDK_GC_FBDATA (gc)->values.background;
60           }
61       }
62       break;
63     case 71:
64       if (mem[x + y * rowstride])
65         *spot = GDK_GC_FBDATA (gc)->values.foreground;
66       else
67         *spot = GDK_GC_FBDATA (gc)->values.background;
68       break;
69     case 77:
70       retval = GPR_AA_GRAYVAL;
71       spot->pixel = mem[x + y * rowstride] << 1;
72       spot->red = spot->green = spot->blue = spot->pixel << 8;
73       break;
74     case 78: /* AA mode */
75       retval = GPR_AA_GRAYVAL;
76       spot->pixel = mem[x + y * rowstride];
77       spot->red = spot->green = spot->blue = spot->pixel << 8;
78       break;
79     case 8:
80       spot->pixel = mem[x + y * rowstride];
81       *spot = private->colormap->colors[spot->pixel];
82       break;
83     case 16:
84       {
85         guint16 val16 = *((guint16 *)&mem[x*2 + y*rowstride]);
86
87         spot->red = (((1<<gdk_display->modeinfo.red.length) - 1) & (val16 >> gdk_display->modeinfo.red.offset)) << (16 - gdk_display->modeinfo.red.length);
88         spot->green = (((1<<gdk_display->modeinfo.green.length) - 1) & (val16 >> gdk_display->modeinfo.green.offset)) << (16 - gdk_display->modeinfo.green.length);
89         spot->blue = (((1<<gdk_display->modeinfo.blue.length) - 1) & (val16 >> gdk_display->modeinfo.blue.offset)) << (16 - gdk_display->modeinfo.blue.length);
90
91         spot->pixel = val16;
92       }
93       break;
94     case 24:
95       {
96         guchar *smem = &mem[x*3 + y*rowstride];
97         spot->red = smem[gdk_display->red_byte] << 8;
98         spot->green = smem[gdk_display->green_byte] << 8;
99         spot->blue = smem[gdk_display->blue_byte] << 8;
100 #if (G_BYTE_ORDER == G_BIG_ENDIAN)
101         spot->pixel = (smem[0]<<16)|(smem[1]<<8)|smem[2];
102 #else
103         spot->pixel = smem[0]|(smem[1]<<8)|(smem[2]<<16);
104 #endif
105       }
106       break;
107     case 32:
108       {
109         guchar *smem = &mem[x*4 + y*rowstride];
110         spot->red = smem[gdk_display->red_byte] << 8;
111         spot->green = smem[gdk_display->green_byte] << 8;
112         spot->blue = smem[gdk_display->blue_byte] << 8;
113         spot->pixel = *(guint32 *)smem;
114       }
115       break;
116     }
117
118   return retval;
119 }
120
121 /*************************************
122  * gc->get_color() implementations
123  *************************************/
124
125 static GetPixelRet
126 gdk_fb_get_color_1 (GdkDrawable *drawable,
127                     GdkGC *gc,
128                     int x,
129                     int y,
130                     GdkColor *color)
131 {
132   GetPixelRet retval = GPR_NONE;
133   GdkDrawableFBData *private = GDK_DRAWABLE_FBDATA (drawable);
134   guchar *mem = private->mem;
135   guint rowstride = private->rowstride;
136   guchar foo;
137
138   g_assert (private->depth == GDK_GC_FBDATA (gc)->depth);
139   
140   foo = mem[(x >> 3) + y * rowstride];
141   if (foo & (1 << (x % 8)))
142     *color = GDK_GC_FBDATA (gc)->values.foreground;
143   else
144     {
145       retval = GPR_USED_BG;
146
147       *color = GDK_GC_FBDATA (gc)->values.background;
148     }
149   
150   return retval;
151 }
152
153 static GetPixelRet
154 gdk_fb_get_color_8 (GdkDrawable *drawable,
155                     GdkGC *gc,
156                     int x,
157                     int y,
158                     GdkColor *color)
159 {
160   GdkDrawableFBData *private = GDK_DRAWABLE_FBDATA (drawable);
161   guchar *mem = private->mem;
162   guint rowstride = private->rowstride;
163   gint pixel;
164
165   g_assert (private->depth == GDK_GC_FBDATA (gc)->depth);
166   
167   pixel = mem[x + y * rowstride];
168   *color = private->colormap->colors[pixel];
169
170   return GPR_NONE;
171 }
172
173 static GetPixelRet
174 gdk_fb_get_color_16 (GdkDrawable *drawable,
175                      GdkGC *gc,
176                      int x,
177                      int y,
178                      GdkColor *color)
179 {
180   GdkDrawableFBData *private = GDK_DRAWABLE_FBDATA (drawable);
181   guchar *mem = private->mem;
182   guint rowstride = private->rowstride;
183   guint16 val16;
184
185   g_assert (private->depth == GDK_GC_FBDATA (gc)->depth);
186
187   val16 = *((guint16 *)&mem[x*2 + y*rowstride]);
188
189   color->red = (((1<<gdk_display->modeinfo.red.length) - 1) & (val16 >> gdk_display->modeinfo.red.offset)) << (16 - gdk_display->modeinfo.red.length);
190   color->green = (((1<<gdk_display->modeinfo.green.length) - 1) & (val16 >> gdk_display->modeinfo.green.offset)) << (16 - gdk_display->modeinfo.green.length);
191   color->blue = (((1<<gdk_display->modeinfo.blue.length) - 1) & (val16 >> gdk_display->modeinfo.blue.offset)) << (16 - gdk_display->modeinfo.blue.length);
192
193   color->pixel = val16;
194
195   return GPR_NONE;
196 }
197
198 static GetPixelRet
199 gdk_fb_get_color_24 (GdkDrawable *drawable,
200                      GdkGC *gc,
201                      int x,
202                      int y,
203                      GdkColor *color)
204 {
205   GdkDrawableFBData *private = GDK_DRAWABLE_FBDATA (drawable);
206   guchar *mem = private->mem;
207   guint rowstride = private->rowstride;
208   guchar *smem;
209
210   g_assert (private->depth == GDK_GC_FBDATA (gc)->depth);
211
212   smem = &mem[x*3 + y*rowstride];
213   color->red = smem[gdk_display->red_byte] << 8;
214   color->green = smem[gdk_display->green_byte] << 8;
215   color->blue = smem[gdk_display->blue_byte] << 8;
216 #if (G_BYTE_ORDER == G_BIG_ENDIAN)
217   color->pixel = (smem[0]<<16)|(smem[1]<<8)|smem[2];
218 #else
219   color->pixel = smem[0]|(smem[1]<<8)|(smem[2]<<16);
220 #endif
221
222   return GPR_NONE;
223 }
224
225 static GetPixelRet
226 gdk_fb_get_color_32 (GdkDrawable *drawable,
227                      GdkGC *gc,
228                      int x,
229                      int y,
230                      GdkColor *color)
231 {
232   GdkDrawableFBData *private = GDK_DRAWABLE_FBDATA (drawable);
233   guchar *mem = private->mem;
234   guint rowstride = private->rowstride;
235   guchar *smem;
236
237   g_assert (private->depth == GDK_GC_FBDATA (gc)->depth);
238   
239   smem = &mem[x*4 + y*rowstride];
240   color->red = smem[gdk_display->red_byte] << 8;
241   color->green = smem[gdk_display->green_byte] << 8;
242   color->blue = smem[gdk_display->blue_byte] << 8;
243   color->pixel = *(guint32 *)smem;
244
245   return GPR_NONE;
246 }
247
248 /*************************************
249  * gc->set_pixel() implementations
250  *************************************/
251
252 static void
253 gdk_fb_set_pixel_1(GdkDrawable *drawable,
254                    GdkGC *gc,
255                    int x,
256                    int y,
257                    gulong pixel)
258 {
259   GdkDrawableFBData *private = GDK_DRAWABLE_FBDATA (drawable);
260   guchar *mem = private->mem;
261   guint rowstride = private->rowstride;
262   guchar *ptr;
263
264   if (!_gdk_fb_is_active_vt)
265     return;
266
267   g_assert (private->depth == GDK_GC_FBDATA (gc)->depth);
268   
269   ptr = mem + (y*rowstride) + (x >> 3);
270
271   if (pixel)
272     *ptr |= (1 << (x % 8));
273   else
274     *ptr &= ~(1 << (x % 8));
275 }
276
277 static void
278 gdk_fb_set_pixel_8(GdkDrawable *drawable,
279                    GdkGC *gc,
280                    int x,
281                    int y,
282                    gulong pixel)
283 {
284   GdkDrawableFBData *private = GDK_DRAWABLE_FBDATA (drawable);
285   guchar *mem = private->mem;
286   guint rowstride = private->rowstride;
287
288   if (!_gdk_fb_is_active_vt)
289     return;
290
291   g_assert (private->depth == GDK_GC_FBDATA (gc)->depth);
292
293   mem[x + y*rowstride] = pixel;
294 }
295
296 static void
297 gdk_fb_set_pixel_16(GdkDrawable *drawable,
298                     GdkGC *gc,
299                     int x,
300                     int y,
301                     gulong pixel)
302 {
303   GdkDrawableFBData *private = GDK_DRAWABLE_FBDATA (drawable);
304   guchar *mem = private->mem;
305   guint rowstride = private->rowstride;
306   guint16 *ptr;
307
308   if (!_gdk_fb_is_active_vt)
309     return;
310
311   g_assert (private->depth == GDK_GC_FBDATA (gc)->depth);
312   
313   ptr = (guint16 *)&mem[x*2 + y*rowstride];
314   *ptr = pixel;
315 }
316
317 static void
318 gdk_fb_set_pixel_24(GdkDrawable *drawable,
319                     GdkGC *gc,
320                     int x,
321                     int y,
322                     gulong pixel)
323 {
324   GdkDrawableFBData *private = GDK_DRAWABLE_FBDATA (drawable);
325   guchar *mem = private->mem;
326   guint rowstride = private->rowstride;
327   guchar *smem;
328   
329   if (!_gdk_fb_is_active_vt)
330     return;
331
332   g_assert (private->depth == GDK_GC_FBDATA (gc)->depth);
333   
334   smem = &mem[x*3 + y*rowstride];
335   smem[0] = pixel & 0xff;
336   smem[1] = (pixel >> 8) & 0xff;
337   smem[2] = (pixel >> 16) & 0xff;
338 }
339
340 static void
341 gdk_fb_set_pixel_32(GdkDrawable *drawable,
342                     GdkGC *gc,
343                     int x,
344                     int y,
345                     gulong pixel)
346 {
347   GdkDrawableFBData *private = GDK_DRAWABLE_FBDATA (drawable);
348   guchar *mem = private->mem;
349   guint rowstride = private->rowstride;
350   guint32 *smem;
351
352   if (!_gdk_fb_is_active_vt)
353     return;
354
355   g_assert (private->depth == GDK_GC_FBDATA (gc)->depth);
356   
357   smem = (guint32 *)&mem[x*4 + y*rowstride];
358   *smem = pixel;
359 }
360
361
362 /*************************************
363  * gc->fill_span() implementations
364  *************************************/
365
366 static void
367 gdk_fb_fill_span_generic (GdkDrawable *drawable,
368                           GdkGC       *gc,
369                           GdkSpan     *span,
370                           GdkColor    *color)
371 {
372   int curx;
373   GdkColor spot = *color;
374   GdkGCFBData *gc_private;
375   GdkDrawableFBData *private;
376   gint left, right, y;
377   int clipxoff, clipyoff; /* Amounts to add to curx & cury to get x & y in clip mask */
378   int tsxoff, tsyoff;
379   GdkDrawable *cmask;
380   guchar *clipmem;
381   guint mask_rowstride;
382   GdkPixmap *ts = NULL;
383   GdkDrawableFBData *ts_private;
384   gboolean solid_stipple;
385   GdkFunction func;
386
387   if (!_gdk_fb_is_active_vt)
388     return;
389
390   private = GDK_DRAWABLE_FBDATA (drawable);
391   gc_private = GDK_GC_FBDATA (gc);
392
393   g_assert (gc);
394
395   y = span->y;
396   left = span->x;
397   right = span->x + span->width;
398   
399   func = gc_private->values.function;
400     
401   cmask = gc_private->values.clip_mask;
402   clipxoff = clipyoff = tsxoff = tsyoff = 0;
403   mask_rowstride = 0;
404   solid_stipple = FALSE;
405   clipmem = NULL;
406   
407   if (cmask)
408     {
409       GdkDrawableFBData *cmask_private;
410       
411       cmask_private = GDK_DRAWABLE_IMPL_FBDATA (cmask);
412       
413       clipmem = cmask_private->mem;
414       clipxoff = cmask_private->abs_x - gc_private->values.clip_x_origin - private->abs_x;
415       clipyoff = cmask_private->abs_y - gc_private->values.clip_y_origin - private->abs_y;
416       mask_rowstride = cmask_private->rowstride;
417     }
418   
419   if (gc_private->values.fill == GDK_TILED &&
420       gc_private->values.tile)
421     {
422       gint xstep;
423       gint relx, rely;
424       int drawh;
425       GdkFBDrawingContext *dc, dc_data;
426
427       dc = &dc_data;
428       
429       gdk_fb_drawing_context_init (dc, drawable, gc, FALSE, TRUE);
430       
431       ts = gc_private->values.tile;
432       ts_private = GDK_DRAWABLE_IMPL_FBDATA (ts);
433       
434       rely = y - private->abs_y;
435       drawh = (rely - gc_private->values.ts_y_origin) % ts_private->height;
436       if (drawh < 0)
437         drawh += ts_private->height;
438       
439       for (curx = left; curx < right; curx += xstep)
440         {
441           int draww;
442           
443           relx = curx - private->abs_x;
444           
445           draww = (relx - gc_private->values.ts_x_origin) % ts_private->width;
446           if (draww < 0)
447             draww += ts_private->width;
448           
449           xstep = MIN (ts_private->width - draww, right - relx);
450           
451           gdk_fb_draw_drawable_3 (drawable, gc, GDK_DRAWABLE_IMPL (ts),
452                                   dc,
453                                   draww, drawh,
454                                   relx, rely,
455                                   xstep, 1);
456         }
457       
458       gdk_fb_drawing_context_finalize (dc);
459       
460       return;
461     }
462   else if ((gc_private->values.fill == GDK_STIPPLED ||
463             gc_private->values.fill == GDK_OPAQUE_STIPPLED) &&
464            gc_private->values.stipple)
465     {
466       ts = gc_private->values.stipple;
467       tsxoff = - GDK_DRAWABLE_IMPL_FBDATA (ts)->abs_x - gc_private->values.ts_x_origin - private->abs_x;
468       tsyoff = - GDK_DRAWABLE_IMPL_FBDATA (ts)->abs_y - gc_private->values.ts_y_origin - private->abs_y;
469       solid_stipple = (gc_private->values.fill == GDK_OPAQUE_STIPPLED);
470     }
471   
472   for (curx = left; curx < right; curx++)
473     {
474       int maskx = curx+clipxoff, masky = y + clipyoff;
475       guchar foo;
476       
477       if (cmask)
478         {
479           foo = clipmem[masky*mask_rowstride + (maskx >> 3)];
480           
481           if (!(foo & (1 << (maskx % 8))))
482             continue;
483         }
484       
485       if (func == GDK_INVERT)
486         {
487           (gc_private->get_color) (drawable, gc, curx, y, &spot);
488           spot.pixel = ~spot.pixel;
489           spot.red = ~spot.red;
490           spot.green = ~spot.green;
491           spot.blue = ~spot.blue;
492         }
493       else if (func == GDK_XOR)
494         {
495           (gc_private->get_color) (drawable, gc, curx, y, &spot);
496           spot.pixel ^= gc_private->values.foreground.pixel;
497         }
498       else if (func != GDK_COPY)
499         {
500           g_warning ("Unsupported GdkFunction %d\n", func);
501         }
502       else if (ts)
503         {
504           int wid, hih;
505           
506           ts_private = GDK_DRAWABLE_IMPL_FBDATA (ts);
507           
508           wid = ts_private->width;
509           hih = ts_private->height;
510           
511           maskx = (curx+tsxoff)%wid;
512           masky = (y+tsyoff)%hih;
513           if (maskx < 0)
514             maskx += wid;
515           if (masky < 0)
516             masky += hih;
517           
518           foo = ts_private->mem[(maskx >> 3) + ts_private->rowstride*masky];
519           if (foo & (1 << (maskx % 8)))
520             {
521               spot = gc_private->values.foreground;
522             }
523           else if (solid_stipple)
524             {
525               spot = gc_private->values.background;
526             }
527           else
528             continue;
529         }
530       
531       (gc_private->set_pixel) (drawable, gc, curx, y, spot.pixel);
532     }
533 }
534
535 static void
536 gdk_fb_fill_span_simple_1 (GdkDrawable *drawable,
537                            GdkGC       *gc,
538                            GdkSpan     *span,
539                            GdkColor    *color)
540 {
541   int curx;
542   GdkGCFBData *gc_private;
543   GdkDrawableFBData *private;
544   guchar *mem, *ptr;
545   guint rowstride;
546   gint left, right, y;
547
548   if (!_gdk_fb_is_active_vt)
549     return;
550
551   private = GDK_DRAWABLE_FBDATA (drawable);
552   gc_private = GDK_GC_FBDATA (gc);
553
554   g_assert (gc);
555
556   g_assert (!gc_private->values.clip_mask &&
557             !gc_private->values.tile &&
558             !gc_private->values.stipple &&
559             gc_private->values.function != GDK_INVERT);
560
561   y = span->y;
562   left = span->x;
563   right = span->x + span->width;
564   
565   mem = private->mem;
566   rowstride = private->rowstride;
567
568   {
569     int fromx = MIN ((left+7)&(~7), right);
570     int begn = fromx - left, begoff = left % 8, endn;
571     guchar begmask, endmask;
572     int body_end = right & ~7;
573     int body_len = (body_end - fromx)/8;
574     
575     begmask = ((1 << (begn + begoff)) - 1)
576       & ~((1 << (begoff)) - 1);
577     endn = right - body_end;
578     endmask = (1 << endn) - 1;
579     
580     ptr = mem + y*rowstride + (left >> 3);
581         
582     if (color->pixel)
583       *ptr |= begmask;
584     else
585       *ptr &= ~begmask;
586     
587     curx = fromx;
588     
589     if (curx < right)
590       {
591         ptr = mem + y*rowstride + (curx >> 3);
592         memset (ptr, color->pixel?0xFF:0, body_len);
593         
594         if (endn)
595           {
596             ptr = mem + y*rowstride + (body_end >> 3);
597             if (color->pixel)
598               *ptr |= endmask;
599             else
600               *ptr &= ~endmask;
601           }
602       }
603   }
604 }
605
606 static void
607 gdk_fb_fill_span_simple_8 (GdkDrawable *drawable,
608                            GdkGC       *gc,
609                            GdkSpan     *span,
610                            GdkColor    *color)
611 {
612   GdkGCFBData *gc_private;
613   GdkDrawableFBData *private;
614   guchar *mem, *ptr;
615   guint rowstride;
616
617   if (!_gdk_fb_is_active_vt)
618     return;
619
620   private = GDK_DRAWABLE_FBDATA (drawable);
621   gc_private = GDK_GC_FBDATA (gc);
622
623   g_assert (gc);
624
625   g_assert (!gc_private->values.clip_mask &&
626             !gc_private->values.tile &&
627             !gc_private->values.stipple &&
628             gc_private->values.function != GDK_INVERT);
629
630   mem = private->mem;
631   rowstride = private->rowstride;
632
633   ptr = mem + span->y*rowstride + span->x;
634   memset (ptr, color->pixel, span->width);
635 }
636
637 static void
638 gdk_fb_fill_span_simple_16 (GdkDrawable *drawable,
639                             GdkGC       *gc,
640                             GdkSpan     *span,
641                             GdkColor    *color)
642 {
643   GdkGCFBData *gc_private;
644   GdkDrawableFBData *private;
645   guchar *mem;
646   guint rowstride;
647   guint16 *p16;
648   int n;
649   int i;
650
651   if (!_gdk_fb_is_active_vt)
652     return;
653
654   private = GDK_DRAWABLE_FBDATA (drawable);
655   gc_private = GDK_GC_FBDATA (gc);
656
657   g_assert (gc);
658
659   g_assert (!gc_private->values.clip_mask &&
660             !gc_private->values.tile &&
661             !gc_private->values.stipple &&
662             gc_private->values.function != GDK_INVERT);
663
664   mem = private->mem;
665   rowstride = private->rowstride;
666
667   n = span->width;
668   p16 = (guint16 *)(mem + span->y * rowstride + span->x*2);
669   for (i = 0; i < n; i++)
670     *(p16++) = color->pixel;
671 }
672
673 static void
674 gdk_fb_fill_span_simple_24 (GdkDrawable *drawable,
675                             GdkGC       *gc,
676                             GdkSpan     *span,
677                             GdkColor    *color)
678 {
679   GdkGCFBData *gc_private;
680   GdkDrawableFBData *private;
681   guchar *mem, *ptr;
682   guint rowstride;
683   int n;
684   guchar redval, greenval, blueval;
685   guchar *firstline, *ptr_end;
686
687   if (!_gdk_fb_is_active_vt)
688     return;
689
690   private = GDK_DRAWABLE_FBDATA (drawable);
691   gc_private = GDK_GC_FBDATA (gc);
692
693   g_assert (gc);
694
695   g_assert (!gc_private->values.clip_mask &&
696             !gc_private->values.tile &&
697             !gc_private->values.stipple &&
698             gc_private->values.function != GDK_INVERT);
699
700   mem = private->mem;
701   rowstride = private->rowstride;
702
703   redval = color->red>>8;
704   greenval = color->green>>8;
705   blueval = color->blue>>8;
706     
707   n = span->width*3;
708     
709   firstline = ptr = mem + span->y * rowstride + span->x*3;
710   ptr_end = ptr+n;
711   while (ptr < ptr_end)
712     {
713       ptr[gdk_display->red_byte] = redval;
714       ptr[gdk_display->green_byte] = greenval;
715       ptr[gdk_display->blue_byte] = blueval;
716       ptr += 3;
717     }
718 }
719
720 static void
721 gdk_fb_fill_span_simple_32 (GdkDrawable *drawable,
722                             GdkGC       *gc,
723                             GdkSpan     *span,
724                             GdkColor    *color)
725 {
726   GdkGCFBData *gc_private;
727   GdkDrawableFBData *private;
728   guchar *mem;
729   guint rowstride;
730   guint32 *p32;
731   int n;
732   int i;
733
734   if (!_gdk_fb_is_active_vt)
735     return;
736
737   private = GDK_DRAWABLE_FBDATA (drawable);
738   gc_private = GDK_GC_FBDATA (gc);
739
740   g_assert (gc);
741
742   g_assert (!gc_private->values.clip_mask &&
743             !gc_private->values.tile &&
744             !gc_private->values.stipple &&
745             gc_private->values.function != GDK_INVERT);
746
747   mem = private->mem;
748   rowstride = private->rowstride;
749
750   n = span->width;
751   p32 = (guint32 *)(mem + span->y * rowstride + span->x*4);
752   for (i = 0; i < n; i++)
753     *(p32++) = color->pixel;
754 }
755
756
757 /*************************************
758  * gc->draw_drawable() implementations
759  *************************************/
760
761 static void
762 gdk_fb_draw_drawable_generic (GdkDrawable *drawable,
763                               GdkGC       *gc,
764                               GdkPixmap   *src,
765                               GdkFBDrawingContext *dc,
766                               gint         start_y,
767                               gint         end_y,
768                               gint         start_x,
769                               gint         end_x,
770                               gint         src_x_off,
771                               gint         src_y_off,
772                               gint         draw_direction)
773 {
774   GdkDrawableFBData *private = GDK_DRAWABLE_FBDATA (drawable);
775   int cur_x, cur_y;
776
777   if (draw_direction < 0)
778     {
779       int tmp;
780       tmp = start_y;
781       start_y = end_y;
782       end_y = tmp;
783       start_y--;
784       end_y--;
785       
786       tmp = start_x;
787       start_x = end_x;
788       end_x = tmp;
789       start_x--;
790       end_x--;
791     }
792
793   for (cur_y = start_y; cur_y != end_y; cur_y+=draw_direction)
794     {
795       for (cur_x = start_x; cur_x != end_x; cur_x+=draw_direction)
796         {
797           GdkColor spot;
798           
799           if (GDK_GC_FBDATA(gc)->values.clip_mask)
800             {
801               int maskx = cur_x + dc->clipxoff, masky = cur_y + dc->clipyoff;
802               guchar foo;
803               
804               foo = dc->clipmem[masky*dc->clip_rowstride + (maskx >> 3)];
805               
806               if (!(foo & (1 << (maskx % 8))))
807                 continue;
808             }
809           
810           switch (gdk_fb_drawable_get_color (src, gc, cur_x + src_x_off, cur_y + src_y_off, &spot))
811             {
812             case GPR_AA_GRAYVAL:
813               {
814                 GdkColor realspot, fg;
815                 guint graylevel = spot.pixel;
816                 gint tmp;
817                 
818                 if (private->depth == 1)
819                   {
820                     if (spot.pixel > 192)
821                       spot = GDK_GC_FBDATA (gc)->values.foreground;
822                     else
823                       spot = GDK_GC_FBDATA (gc)->values.background;
824                     break;
825                   }
826                 else
827                   {
828                     if (graylevel >= 254)
829                       {
830                         spot = GDK_GC_FBDATA (gc)->values.foreground;
831                       }
832                     else if (graylevel <= 2)
833                       {
834                         if (!dc->draw_bg)
835                           continue;
836                         
837                         spot = GDK_GC_FBDATA (gc)->values.background;
838                       }
839                     else
840                       {
841                         switch ((GDK_GC_FBDATA (gc)->get_color) (drawable, gc, cur_x, cur_y, &realspot))
842                           {
843                           case GPR_USED_BG:
844                             {
845                               int bgx, bgy;
846                               
847                               bgx = (cur_x - GDK_DRAWABLE_IMPL_FBDATA (dc->bg_relto)->abs_x) % GDK_DRAWABLE_IMPL_FBDATA (dc->bgpm)->width + private->abs_x;
848                               bgy = (cur_y - GDK_DRAWABLE_IMPL_FBDATA (dc->bg_relto)->abs_y) % GDK_DRAWABLE_IMPL_FBDATA (dc->bgpm)->height + private->abs_y;
849                               gdk_fb_drawable_get_color (dc->bgpm, gc, bgx, bgy, &realspot);
850                             }
851                             break;
852                           case GPR_NONE:
853                             break;
854                           default:
855                             g_assert_not_reached ();
856                             break;
857                           }
858                         
859                         fg = GDK_GC_FBDATA (gc)->values.foreground;
860
861                         /* Now figure out what 'spot' should actually look like */
862                         fg.red >>= 8;
863                         fg.green >>= 8;
864                         fg.blue >>= 8;
865                         realspot.red >>= 8;
866                         realspot.green >>= 8;
867                         realspot.blue >>= 8;
868
869                                 
870                         tmp = (fg.red - realspot.red) * graylevel;
871                         spot.red = realspot.red + ((tmp + (tmp >> 8) + 0x80) >> 8);
872                         spot.red <<= 8;
873                         
874                         tmp = (fg.green - realspot.green) * graylevel;
875                         spot.green = realspot.green + ((tmp + (tmp >> 8) + 0x80) >> 8);
876                         spot.green <<= 8;
877                         
878                         tmp = (fg.blue - realspot.blue) * graylevel;
879                         spot.blue = realspot.blue + ((tmp + (tmp >> 8) + 0x80) >> 8);
880                         spot.blue <<= 8;
881                         
882                         /* Now find the pixel for this thingie */
883                         switch (private->depth)
884                           {
885                           case 8:
886                             if (!gdk_colormap_alloc_color (private->colormap, &spot, FALSE, TRUE))
887                               {
888                                 g_error ("Can't allocate AA color!");
889                               }
890                             break;
891                           case 16:
892                             spot.pixel = (spot.red >> (16 - gdk_display->modeinfo.red.length)) << gdk_display->modeinfo.red.offset;
893                             spot.pixel |= (spot.green >> (16 - gdk_display->modeinfo.green.length)) << gdk_display->modeinfo.green.offset;
894                             spot.pixel |= (spot.blue >> (16 - gdk_display->modeinfo.blue.length)) << gdk_display->modeinfo.blue.offset;
895                             break;
896                           case 24:
897                           case 32:
898                             spot.pixel = ((spot.red & 0xFF00) >> 8  << (gdk_display->modeinfo.red.offset))
899                               | ((spot.green & 0xFF00) >> 8 << (gdk_display->modeinfo.green.offset))
900                               | ((spot.blue & 0xFF00) >> 8 << (gdk_display->modeinfo.blue.offset));
901                             break;
902                           }
903                       }
904                   }
905               }
906               break;
907             case GPR_USED_BG:
908               if (!dc->draw_bg)
909                 continue;
910               break;
911             case GPR_NONE:
912               break;
913             default:
914               g_assert_not_reached ();
915               break;
916             }
917           
918           (GDK_GC_FBDATA (gc)->set_pixel) (drawable, gc, cur_x, cur_y, spot.pixel);
919         }
920     }
921
922 }
923
924 void
925 gdk_fb_draw_drawable_memmove (GdkDrawable *drawable,
926                               GdkGC       *gc,
927                               GdkPixmap   *src,
928                               GdkFBDrawingContext *dc,
929                               gint         start_y,
930                               gint         end_y,
931                               gint         start_x,
932                               gint         end_x,
933                               gint         src_x_off,
934                               gint         src_y_off,
935                               gint         draw_direction)
936 {
937   GdkDrawableFBData *src_private = GDK_DRAWABLE_FBDATA (src);
938   guint depth = src_private->depth;
939   guint src_rowstride = src_private->rowstride;
940   guchar *srcmem = src_private->mem;
941   int linelen = (end_x - start_x)*(depth>>3);
942   gint cur_y;
943
944   if (!_gdk_fb_is_active_vt)
945     return;
946
947   if (draw_direction < 0)
948     {
949       int tmp;
950       tmp = start_y;
951       start_y = end_y;
952       end_y = tmp;
953       start_y--;
954       end_y--;
955     }
956
957   for(cur_y = start_y; cur_y != end_y; cur_y += draw_direction)
958     {
959       memmove (dc->mem + (cur_y * dc->rowstride) + start_x*(depth>>3),
960                srcmem + ((cur_y + src_y_off)*src_rowstride) + (start_x + src_x_off)*(depth>>3),
961                linelen);
962     }
963
964 }
965
966 static void
967 gdk_fb_draw_drawable_aa_24 (GdkDrawable *drawable,
968                             GdkGC       *gc,
969                             GdkPixmap   *src,
970                             GdkFBDrawingContext *dc,
971                             gint         start_y,
972                             gint         end_y,
973                             gint         start_x,
974                             gint         end_x,
975                             gint         src_x_off,
976                             gint         src_y_off,
977                             gint         draw_direction)
978 {
979   GdkDrawableFBData *private = GDK_DRAWABLE_FBDATA (drawable);
980   int x, y;
981   GdkGCFBData *gc_private;
982   guchar *dmem = private->mem;
983   guint dst_rowstride = private->rowstride;
984   guchar *smem = GDK_DRAWABLE_FBDATA (src)->mem;
985   guint src_rowstride = GDK_DRAWABLE_FBDATA (src)->rowstride;
986   guchar *dst;
987   guint grayval;
988   gint r, g, b, tmp;
989   GdkColor fg;
990   gint fg_r, fg_g, fg_b;
991   
992   if (!_gdk_fb_is_active_vt)
993     return;
994
995   gc_private = GDK_GC_FBDATA (gc);
996
997   fg = GDK_GC_FBDATA (gc)->values.foreground;
998   fg_r = fg.red >> 8;
999   fg_g = fg.green >> 8;
1000   fg_b = fg.blue >> 8;
1001
1002   if (draw_direction < 0)
1003     {
1004       int tmp;
1005       tmp = start_y;
1006       start_y = end_y;
1007       end_y = tmp;
1008       start_y--;
1009       end_y--;
1010       
1011       tmp = start_x;
1012       start_x = end_x;
1013       end_x = tmp;
1014       start_x--;
1015       end_x--;
1016     }
1017
1018   for (y = start_y; y != end_y; y+=draw_direction)
1019     {
1020       for (x = start_x; x != end_x; x+=draw_direction)
1021         {
1022           grayval = smem[x + src_x_off + (y + src_y_off) * src_rowstride];
1023
1024           if ((grayval <= 2) && (!dc->draw_bg))
1025             continue;
1026
1027           dst = &dmem[x*3 + y*dst_rowstride];
1028           
1029           if (grayval >= 254)
1030             {
1031               dst[gdk_display->red_byte] = fg_r;
1032               dst[gdk_display->green_byte] = fg_g;
1033               dst[gdk_display->blue_byte] = fg_b;
1034             }
1035           else if (grayval <= 2)
1036             {
1037               dst[gdk_display->red_byte] = GDK_GC_FBDATA (gc)->values.background.red >> 8;
1038               dst[gdk_display->green_byte] = GDK_GC_FBDATA (gc)->values.background.green >> 8;
1039               dst[gdk_display->blue_byte] = GDK_GC_FBDATA (gc)->values.background.blue >> 8;
1040             }
1041           else
1042             {
1043               r = dst[gdk_display->red_byte];
1044               tmp = (fg_r - r) * (gint)grayval;
1045               r = r + ((tmp + (tmp >> 8) + 0x80) >> 8);
1046               dst[gdk_display->red_byte] = r;
1047
1048               g = dst[gdk_display->green_byte];
1049               tmp = (fg_g - g) * (gint)grayval;
1050               g = g + ((tmp + (tmp >> 8) + 0x80) >> 8);
1051               dst[gdk_display->green_byte] = g;
1052
1053               b = dst[gdk_display->blue_byte];
1054               tmp = (fg_b - b) * (gint)grayval;
1055               b = b + ((tmp + (tmp >> 8) + 0x80) >> 8);
1056               dst[gdk_display->blue_byte] = b;
1057             }
1058         }
1059     }
1060 }
1061
1062 /*************************************
1063  * gc->fill_rectangle() implementations
1064  *************************************/
1065
1066 void
1067 gdk_fb_fill_rectangle_generic (GdkDrawable    *drawable,
1068                                GdkGC          *gc,
1069                                GdkRectangle   *rect,
1070                                GdkColor       *color)
1071 {
1072   GdkDrawableFBData *private;
1073   GdkSpan *spans;
1074   int i;
1075
1076   if (!_gdk_fb_is_active_vt)
1077     return;
1078
1079   private = GDK_DRAWABLE_FBDATA (drawable);
1080
1081   spans = g_new (GdkSpan, rect->height);
1082   for (i = 0; i < rect->height; i++)
1083     {
1084       spans[i].x = rect->x - private->abs_x;
1085       spans[i].y = rect->y+i - private->abs_y;
1086       spans[i].width = rect->width;
1087     }
1088   gdk_fb_fill_spans (drawable, gc, spans, rect->height, TRUE);
1089   g_free (spans);
1090 }
1091
1092 void
1093 gdk_fb_fill_rectangle_simple_16 (GdkDrawable    *drawable,
1094                                  GdkGC          *gc,
1095                                  GdkRectangle   *rect,
1096                                  GdkColor       *color)
1097 {
1098   GdkGCFBData *gc_private;
1099   GdkDrawableFBData *private;
1100   guchar *ptr;
1101   guint rowstride;
1102   int n;
1103   gboolean extra;
1104   int i;
1105   guint32 pixel;
1106   gint height;
1107   
1108   if (!_gdk_fb_is_active_vt)
1109     return;
1110
1111   private = GDK_DRAWABLE_FBDATA (drawable);
1112   gc_private = GDK_GC_FBDATA (gc);
1113
1114   rowstride = private->rowstride - rect->width*2;
1115   ptr = (guchar *)private->mem + rect->y * private->rowstride + rect->x*2;
1116
1117   extra = rect->width&1;
1118   n = rect->width>>1;
1119     
1120   pixel = (color->pixel << 16) | color->pixel;
1121
1122   height = rect->height;
1123   while (height>0)
1124     {
1125       i = n;
1126       while (i>0)
1127         {
1128           *(guint32 *)ptr = pixel;
1129           ptr += 4;
1130           i--;
1131         }
1132       if (extra)
1133         {
1134           *(guint16 *)ptr = color->pixel;
1135           ptr += 2;
1136         }
1137       ptr += rowstride;
1138       height--; 
1139     }
1140 }
1141
1142 void
1143 gdk_fb_fill_rectangle_simple_32 (GdkDrawable    *drawable,
1144                                  GdkGC          *gc,
1145                                  GdkRectangle   *rect,
1146                                  GdkColor       *color)
1147 {
1148   GdkGCFBData *gc_private;
1149   GdkDrawableFBData *private;
1150   guchar *ptr;
1151   guint rowstride;
1152   int n;
1153   int i;
1154   guint32 pixel;
1155   gint height;
1156   
1157   if (!_gdk_fb_is_active_vt)
1158     return;
1159
1160   private = GDK_DRAWABLE_FBDATA (drawable);
1161   gc_private = GDK_GC_FBDATA (gc);
1162
1163   rowstride = private->rowstride - rect->width*4;
1164   ptr = (guchar *)private->mem + rect->y * private->rowstride + rect->x*4;
1165
1166   n = rect->width;
1167     
1168   pixel = color->pixel;
1169
1170   height = rect->height;
1171   while (height>0)
1172     {
1173       i = n;
1174       while (i>0)
1175         {
1176           *(guint32 *)ptr = pixel;
1177           ptr += 4;
1178           i--;
1179         }
1180       ptr += rowstride;
1181       height--; 
1182     }
1183 }
1184
1185
1186 /*************************************
1187  * GC state calculation
1188  *************************************/
1189
1190 void
1191 _gdk_fb_gc_calc_state (GdkGC           *gc,
1192                        GdkGCValuesMask  changed)
1193 {
1194   GdkGCFBData *gc_private;
1195   int i;
1196
1197   gc_private = GDK_GC_FBDATA (gc);
1198
1199   gc_private->fill_span = gdk_fb_fill_span_generic;
1200   gc_private->fill_rectangle = gdk_fb_fill_rectangle_generic;
1201
1202   for (i = 0; i < GDK_NUM_FB_SRCBPP; i++)
1203     gc_private->draw_drawable[i] = gdk_fb_draw_drawable_generic;
1204   
1205   if (changed & _GDK_FB_GC_DEPTH)
1206     switch (gc_private->depth)
1207       {
1208       case 1:
1209         gc_private->set_pixel = gdk_fb_set_pixel_1;
1210         gc_private->get_color = gdk_fb_get_color_1;
1211         break;
1212       case 8:
1213         gc_private->set_pixel = gdk_fb_set_pixel_8;
1214         gc_private->get_color = gdk_fb_get_color_8;
1215         break;
1216       case 16:
1217         gc_private->set_pixel = gdk_fb_set_pixel_16;
1218         gc_private->get_color = gdk_fb_get_color_16;
1219         break;
1220       case 24:
1221         gc_private->set_pixel = gdk_fb_set_pixel_24;
1222         gc_private->get_color = gdk_fb_get_color_24;
1223         break;
1224       case 32:
1225         gc_private->set_pixel = gdk_fb_set_pixel_32;
1226         gc_private->get_color = gdk_fb_get_color_32;
1227         break;
1228       default:
1229         g_assert_not_reached ();
1230         break;
1231       }
1232
1233   if (!gc_private->values.clip_mask)
1234     {
1235     switch (gc_private->depth)
1236       {
1237       case 8:
1238         gc_private->draw_drawable[GDK_FB_SRC_BPP_8] = gdk_fb_draw_drawable_memmove;
1239         break;
1240       case 16:
1241         gc_private->draw_drawable[GDK_FB_SRC_BPP_16] = gdk_fb_draw_drawable_memmove;
1242         break;
1243       case 24:
1244         gc_private->draw_drawable[GDK_FB_SRC_BPP_8_AA_GRAYVAL] = gdk_fb_draw_drawable_aa_24;
1245         gc_private->draw_drawable[GDK_FB_SRC_BPP_24] = gdk_fb_draw_drawable_memmove;
1246         break;
1247       case 32:
1248         gc_private->draw_drawable[GDK_FB_SRC_BPP_32] = gdk_fb_draw_drawable_memmove;
1249         break;
1250       }
1251     }
1252   
1253   if (!gc_private->values.clip_mask &&
1254       !gc_private->values.tile &&
1255       !gc_private->values.stipple &&
1256        gc_private->values.function == GDK_COPY)
1257     {
1258       switch (gc_private->depth)
1259         {
1260         case 1:
1261           gc_private->fill_span = gdk_fb_fill_span_simple_1;
1262           break;
1263         case 8:
1264           gc_private->fill_span = gdk_fb_fill_span_simple_8;
1265           break;
1266         case 16:
1267           gc_private->fill_span = gdk_fb_fill_span_simple_16;
1268           gc_private->fill_rectangle = gdk_fb_fill_rectangle_simple_16;
1269           break;
1270         case 24:
1271           gc_private->fill_span = gdk_fb_fill_span_simple_24;
1272           break;
1273         case 32:
1274           gc_private->fill_span = gdk_fb_fill_span_simple_32;
1275           gc_private->fill_rectangle = gdk_fb_fill_rectangle_simple_32;
1276           break;
1277         default:
1278           g_assert_not_reached ();
1279           break;
1280         }
1281     }
1282 }
1283
1284 #ifdef ENABLE_SHADOW_FB
1285 static void
1286 gdk_shadow_fb_copy_rect_0 (gint x, gint y, gint width, gint height)
1287 {
1288   guchar *dst, *src;
1289   gint depth;
1290
1291   if (!_gdk_fb_is_active_vt)
1292     return;
1293
1294   depth = gdk_display->modeinfo.bits_per_pixel / 8;
1295
1296   dst = gdk_display->fb_mmap + x * depth + gdk_display->sinfo.line_length * y;
1297   src = gdk_display->fb_mem + x * depth + gdk_display->fb_stride * y;
1298
1299   width = width*depth;
1300   while (height>0)
1301     {
1302       memcpy (dst, src, width);
1303       dst += gdk_display->sinfo.line_length;
1304       src += gdk_display->fb_stride;
1305       height--;
1306     }
1307 }
1308
1309 static void
1310 gdk_shadow_fb_copy_rect_90 (gint x, gint y, gint width, gint height)
1311 {
1312   guchar *dst, *src, *pdst;
1313   gint depth;
1314   gint w;
1315   gint i;
1316
1317   if (!_gdk_fb_is_active_vt)
1318     return;
1319
1320   depth = gdk_display->modeinfo.bits_per_pixel / 8;
1321
1322   src = gdk_display->fb_mem + x * depth + gdk_display->fb_stride * y;
1323   dst = gdk_display->fb_mmap + y * depth + gdk_display->sinfo.line_length * (gdk_display->fb_width - x - 1);
1324
1325   while (height>0)
1326     {
1327       w = width;
1328       pdst = dst;
1329       while (w>0) {
1330         for (i = 0; i < depth; i++)
1331           *pdst++ = *src++;
1332         pdst -= gdk_display->sinfo.line_length + depth;
1333         w--;
1334       }
1335       dst += depth;
1336       src += gdk_display->fb_stride - width * depth;
1337       height--;
1338     }
1339 }
1340
1341 static void
1342 gdk_shadow_fb_copy_rect_180 (gint x, gint y, gint width, gint height)
1343 {
1344   guchar *dst, *src, *pdst;
1345   gint depth;
1346   gint w;
1347   gint i;
1348
1349   if (!_gdk_fb_is_active_vt)
1350     return;
1351
1352   depth = gdk_display->modeinfo.bits_per_pixel / 8;
1353
1354   src = gdk_display->fb_mem + x * depth + gdk_display->fb_stride * y;
1355   dst = gdk_display->fb_mmap + (gdk_display->fb_width - x - 1) * depth + gdk_display->sinfo.line_length * (gdk_display->fb_height - y - 1) ;
1356
1357   while (height>0)
1358     {
1359       w = width;
1360       pdst = dst;
1361       while (w>0) {
1362         for (i = 0; i < depth; i++)
1363           *pdst++ = *src++;
1364         pdst -= 2 * depth;
1365         w--;
1366       }
1367       dst -= gdk_display->sinfo.line_length;
1368       src += gdk_display->fb_stride - width * depth;
1369       height--;
1370     }
1371 }
1372
1373 static void
1374 gdk_shadow_fb_copy_rect_270 (gint x, gint y, gint width, gint height)
1375 {
1376   guchar *dst, *src, *pdst;
1377   gint depth;
1378   gint w;
1379   gint i;
1380
1381   if (!_gdk_fb_is_active_vt)
1382     return;
1383
1384   depth = gdk_display->modeinfo.bits_per_pixel / 8;
1385
1386   src = gdk_display->fb_mem + x * depth + gdk_display->fb_stride * y;
1387   dst = gdk_display->fb_mmap + (gdk_display->fb_height - y - 1) * depth + gdk_display->sinfo.line_length * x;
1388
1389   while (height>0)
1390     {
1391       w = width;
1392       pdst = dst;
1393       while (w>0) {
1394         for (i = 0; i < depth; i++)
1395           *pdst++ = *src++;
1396         pdst += gdk_display->sinfo.line_length - depth;
1397         w--;
1398       }
1399       dst -= depth;
1400       src += gdk_display->fb_stride - width * depth;
1401       height--;
1402     }
1403 }
1404
1405 static void (*shadow_copy_rect[4]) (gint x, gint y, gint width, gint height);
1406
1407 volatile gint refresh_queued = 0;
1408 volatile gint refresh_x1, refresh_y1;
1409 volatile gint refresh_x2, refresh_y2;
1410
1411 static void
1412 gdk_shadow_fb_refresh (int signum)
1413 {
1414   gint minx, miny, maxx, maxy;
1415
1416   if (!refresh_queued)
1417     {
1418       struct itimerval timeout;
1419       /* Stop the timer */ 
1420       timeout.it_value.tv_sec = 0;
1421       timeout.it_value.tv_usec = 0;
1422       timeout.it_interval.tv_sec = 0;
1423       timeout.it_interval.tv_usec = 0;
1424       setitimer (ITIMER_REAL, &timeout, NULL);
1425       return;
1426     }
1427  
1428   
1429   minx = refresh_x1;
1430   miny = refresh_y1;
1431   maxx = refresh_x2;
1432   maxy = refresh_y2;
1433   refresh_queued = 0;
1434
1435   /* clip x */
1436   if (minx < 0) {
1437     minx = 0;
1438     maxx = MAX (maxx, 0);
1439   }
1440   if (maxx >= gdk_display->fb_width) {
1441     maxx = gdk_display->fb_width-1;
1442     minx = MIN (minx, maxx);
1443   }
1444   /* clip y */
1445   if (miny < 0) {
1446     miny = 0;
1447     maxy = MAX (maxy, 0);
1448   }
1449   if (maxy >= gdk_display->fb_height) {
1450     maxy = gdk_display->fb_height-1;
1451     miny = MIN (miny, maxy);
1452   }
1453   
1454   (*shadow_copy_rect[_gdk_fb_screen_angle]) (minx, miny, maxx - minx + 1, maxy - miny + 1);
1455 }
1456
1457 void
1458 gdk_shadow_fb_stop_updates (void)
1459 {
1460   struct itimerval timeout;
1461
1462   refresh_queued = 0;
1463
1464   /* Stop the timer */ 
1465   timeout.it_value.tv_sec = 0;
1466   timeout.it_value.tv_usec = 0;
1467   timeout.it_interval.tv_sec = 0;
1468   timeout.it_interval.tv_usec = 0;
1469   setitimer (ITIMER_REAL, &timeout, NULL);
1470
1471   refresh_queued = 0;
1472 }
1473
1474 void
1475 gdk_shadow_fb_init (void)
1476 {
1477   struct sigaction action;
1478
1479   action.sa_handler = gdk_shadow_fb_refresh;
1480   sigemptyset (&action.sa_mask);
1481   action.sa_flags = 0;
1482   
1483   sigaction (SIGALRM, &action, NULL);
1484
1485   shadow_copy_rect[GDK_FB_0_DEGREES] = gdk_shadow_fb_copy_rect_0;
1486   shadow_copy_rect[GDK_FB_90_DEGREES] = gdk_shadow_fb_copy_rect_90;
1487   shadow_copy_rect[GDK_FB_180_DEGREES] = gdk_shadow_fb_copy_rect_180;
1488   shadow_copy_rect[GDK_FB_270_DEGREES] = gdk_shadow_fb_copy_rect_270;
1489 }
1490
1491 /* maxx and maxy are included */
1492 void
1493 gdk_shadow_fb_update (gint minx, gint miny, gint maxx, gint maxy)
1494 {
1495   struct itimerval timeout;
1496
1497   if (gdk_display->manager_blocked)
1498     return;
1499   
1500   g_assert (minx <= maxx);
1501   g_assert (miny <= maxy);
1502
1503   if (refresh_queued)
1504     {
1505       refresh_x1 = MIN (refresh_x1, minx);
1506       refresh_y1 = MIN (refresh_y1, miny);
1507       refresh_x2 = MAX (refresh_x2, maxx);
1508       refresh_y2 = MAX (refresh_y2, maxy);
1509       refresh_queued = 1;
1510     }
1511   else
1512     {
1513       refresh_x1 = minx;
1514       refresh_y1 = miny;
1515       refresh_x2 = maxx;
1516       refresh_y2 = maxy;
1517       refresh_queued = 1;
1518
1519       getitimer (ITIMER_REAL, &timeout);
1520       if (timeout.it_value.tv_usec == 0)
1521         {
1522           timeout.it_value.tv_sec = 0;
1523           timeout.it_value.tv_usec = 20000; /* 20 ms => 50 fps */
1524           timeout.it_interval.tv_sec = 0;
1525           timeout.it_interval.tv_usec = 20000; /* 20 ms => 50 fps */
1526           setitimer (ITIMER_REAL, &timeout, NULL);
1527         }
1528     }
1529   
1530 }
1531 #else
1532
1533 void
1534 gdk_shadow_fb_stop_updates (void)
1535 {
1536 }
1537
1538 void
1539 gdk_shadow_fb_update (gint minx, gint miny, gint maxx, gint maxy)
1540 {
1541 }
1542
1543 void
1544 gdk_shadow_fb_init (void)
1545 {
1546 }
1547
1548 #endif
1549