]> Pileus Git - ~andy/gtk/blob - gdk/linux-fb/gdkrender-fb.c
Huge GtkFB patch with lots of small bugfixes and initial selections implementation.
[~andy/gtk] / gdk / linux-fb / gdkrender-fb.c
1 #include "gdkprivate-fb.h"
2 #include <string.h>
3
4 /*
5  * Reading pixel values from a generic drawable.
6  */
7
8 static GetPixelRet
9 gdk_fb_drawable_get_color (GdkDrawable *drawable,
10                            GdkGC *gc,
11                            int x,
12                            int y,
13                            GdkColor *spot)
14 {
15   GetPixelRet retval = GPR_NONE;
16   GdkDrawableFBData *private = GDK_DRAWABLE_FBDATA (drawable);
17   guchar *mem = private->mem;
18   guint rowstride = private->rowstride;
19
20   switch (private->depth)
21     {
22     case 1:
23       {
24         guchar foo = mem[(x >> 3) + y * rowstride];
25         if (foo & (1 << (x % 8)))
26           *spot = GDK_GC_FBDATA (gc)->values.foreground;
27         else
28           {
29             retval = GPR_USED_BG;
30             *spot = GDK_GC_FBDATA (gc)->values.background;
31           }
32       }
33       break;
34     case 71:
35       if (mem[x + y * rowstride])
36         *spot = GDK_GC_FBDATA (gc)->values.foreground;
37       else
38         *spot = GDK_GC_FBDATA (gc)->values.background;
39       break;
40     case 77:
41       retval = GPR_AA_GRAYVAL;
42       spot->pixel = mem[x + y * rowstride] << 1;
43       spot->red = spot->green = spot->blue = spot->pixel << 8;
44       break;
45     case 78: /* AA mode */
46       retval = GPR_AA_GRAYVAL;
47       spot->pixel = mem[x + y * rowstride];
48       spot->red = spot->green = spot->blue = spot->pixel << 8;
49       break;
50     case 8:
51       spot->pixel = mem[x + y * rowstride];
52       *spot = private->colormap->colors[spot->pixel];
53       break;
54     case 16:
55       {
56         guint16 val16 = *((guint16 *)&mem[x*2 + y*rowstride]);
57
58         spot->red = (((1<<gdk_display->modeinfo.red.length) - 1) & (val16 >> gdk_display->modeinfo.red.offset)) << (16 - gdk_display->modeinfo.red.length);
59         spot->green = (((1<<gdk_display->modeinfo.green.length) - 1) & (val16 >> gdk_display->modeinfo.green.offset)) << (16 - gdk_display->modeinfo.green.length);
60         spot->blue = (((1<<gdk_display->modeinfo.blue.length) - 1) & (val16 >> gdk_display->modeinfo.blue.offset)) << (16 - gdk_display->modeinfo.blue.length);
61
62         spot->pixel = val16;
63       }
64       break;
65     case 24:
66       {
67         guchar *smem = &mem[x*3 + y*rowstride];
68         spot->red = smem[gdk_display->red_byte] << 8;
69         spot->green = smem[gdk_display->green_byte] << 8;
70         spot->blue = smem[gdk_display->blue_byte] << 8;
71 #if (G_BYTE_ORDER == G_BIG_ENDIAN)
72         spot->pixel = (smem[0]<<16)|(smem[1]<<8)|smem[2];
73 #else
74         spot->pixel = smem[0]|(smem[1]<<8)|(smem[2]<<16);
75 #endif
76       }
77       break;
78     case 32:
79       {
80         guchar *smem = &mem[x*4 + y*rowstride];
81         spot->red = smem[gdk_display->red_byte] << 8;
82         spot->green = smem[gdk_display->green_byte] << 8;
83         spot->blue = smem[gdk_display->blue_byte] << 8;
84         spot->pixel = *(guint32 *)smem;
85       }
86       break;
87     }
88
89   return retval;
90 }
91
92 /*************************************
93  * gc->get_color() implementations
94  *************************************/
95
96 static GetPixelRet
97 gdk_fb_get_color_1 (GdkDrawable *drawable,
98                     GdkGC *gc,
99                     int x,
100                     int y,
101                     GdkColor *color)
102 {
103   GetPixelRet retval = GPR_NONE;
104   GdkDrawableFBData *private = GDK_DRAWABLE_FBDATA (drawable);
105   guchar *mem = private->mem;
106   guint rowstride = private->rowstride;
107   guchar foo;
108
109   g_assert (private->depth == GDK_GC_FBDATA (gc)->depth);
110   
111   foo = mem[(x >> 3) + y * rowstride];
112   if (foo & (1 << (x % 8)))
113     *color = GDK_GC_FBDATA (gc)->values.foreground;
114   else
115     {
116       retval = GPR_USED_BG;
117
118       *color = GDK_GC_FBDATA (gc)->values.background;
119     }
120   
121   return retval;
122 }
123
124 static GetPixelRet
125 gdk_fb_get_color_8 (GdkDrawable *drawable,
126                     GdkGC *gc,
127                     int x,
128                     int y,
129                     GdkColor *color)
130 {
131   GdkDrawableFBData *private = GDK_DRAWABLE_FBDATA (drawable);
132   guchar *mem = private->mem;
133   guint rowstride = private->rowstride;
134   gint pixel;
135
136   g_assert (private->depth == GDK_GC_FBDATA (gc)->depth);
137   
138   pixel = mem[x + y * rowstride];
139   *color = private->colormap->colors[pixel];
140
141   return GPR_NONE;
142 }
143
144 static GetPixelRet
145 gdk_fb_get_color_16 (GdkDrawable *drawable,
146                      GdkGC *gc,
147                      int x,
148                      int y,
149                      GdkColor *color)
150 {
151   GdkDrawableFBData *private = GDK_DRAWABLE_FBDATA (drawable);
152   guchar *mem = private->mem;
153   guint rowstride = private->rowstride;
154   guint16 val16;
155
156   g_assert (private->depth == GDK_GC_FBDATA (gc)->depth);
157
158   val16 = *((guint16 *)&mem[x*2 + y*rowstride]);
159
160   color->red = (((1<<gdk_display->modeinfo.red.length) - 1) & (val16 >> gdk_display->modeinfo.red.offset)) << (16 - gdk_display->modeinfo.red.length);
161   color->green = (((1<<gdk_display->modeinfo.green.length) - 1) & (val16 >> gdk_display->modeinfo.green.offset)) << (16 - gdk_display->modeinfo.green.length);
162   color->blue = (((1<<gdk_display->modeinfo.blue.length) - 1) & (val16 >> gdk_display->modeinfo.blue.offset)) << (16 - gdk_display->modeinfo.blue.length);
163
164   color->pixel = val16;
165
166   return GPR_NONE;
167 }
168
169 static GetPixelRet
170 gdk_fb_get_color_24 (GdkDrawable *drawable,
171                      GdkGC *gc,
172                      int x,
173                      int y,
174                      GdkColor *color)
175 {
176   GdkDrawableFBData *private = GDK_DRAWABLE_FBDATA (drawable);
177   guchar *mem = private->mem;
178   guint rowstride = private->rowstride;
179   guchar *smem;
180
181   g_assert (private->depth == GDK_GC_FBDATA (gc)->depth);
182
183   smem = &mem[x*3 + y*rowstride];
184   color->red = smem[gdk_display->red_byte] << 8;
185   color->green = smem[gdk_display->green_byte] << 8;
186   color->blue = smem[gdk_display->blue_byte] << 8;
187 #if (G_BYTE_ORDER == G_BIG_ENDIAN)
188   color->pixel = (smem[0]<<16)|(smem[1]<<8)|smem[2];
189 #else
190   color->pixel = smem[0]|(smem[1]<<8)|(smem[2]<<16);
191 #endif
192
193   return GPR_NONE;
194 }
195
196 static GetPixelRet
197 gdk_fb_get_color_32 (GdkDrawable *drawable,
198                      GdkGC *gc,
199                      int x,
200                      int y,
201                      GdkColor *color)
202 {
203   GdkDrawableFBData *private = GDK_DRAWABLE_FBDATA (drawable);
204   guchar *mem = private->mem;
205   guint rowstride = private->rowstride;
206   guchar *smem;
207
208   g_assert (private->depth == GDK_GC_FBDATA (gc)->depth);
209   
210   smem = &mem[x*4 + y*rowstride];
211   color->red = smem[gdk_display->red_byte] << 8;
212   color->green = smem[gdk_display->green_byte] << 8;
213   color->blue = smem[gdk_display->blue_byte] << 8;
214   color->pixel = *(guint32 *)smem;
215
216   return GPR_NONE;
217 }
218
219 /*************************************
220  * gc->set_pixel() implementations
221  *************************************/
222
223 static void
224 gdk_fb_set_pixel_1(GdkDrawable *drawable,
225                    GdkGC *gc,
226                    int x,
227                    int y,
228                    gulong pixel)
229 {
230   GdkDrawableFBData *private = GDK_DRAWABLE_FBDATA (drawable);
231   guchar *mem = private->mem;
232   guint rowstride = private->rowstride;
233   guchar *ptr;
234
235   g_assert (private->depth == GDK_GC_FBDATA (gc)->depth);
236   
237   ptr = mem + (y*rowstride) + (x >> 3);
238
239   if (pixel)
240     *ptr |= (1 << (x % 8));
241   else
242     *ptr &= ~(1 << (x % 8));
243 }
244
245 static void
246 gdk_fb_set_pixel_8(GdkDrawable *drawable,
247                    GdkGC *gc,
248                    int x,
249                    int y,
250                    gulong pixel)
251 {
252   GdkDrawableFBData *private = GDK_DRAWABLE_FBDATA (drawable);
253   guchar *mem = private->mem;
254   guint rowstride = private->rowstride;
255
256   g_assert (private->depth == GDK_GC_FBDATA (gc)->depth);
257
258   mem[x + y*rowstride] = pixel;
259 }
260
261 static void
262 gdk_fb_set_pixel_16(GdkDrawable *drawable,
263                     GdkGC *gc,
264                     int x,
265                     int y,
266                     gulong pixel)
267 {
268   GdkDrawableFBData *private = GDK_DRAWABLE_FBDATA (drawable);
269   guchar *mem = private->mem;
270   guint rowstride = private->rowstride;
271   guint16 *ptr;
272
273   g_assert (private->depth == GDK_GC_FBDATA (gc)->depth);
274   
275   ptr = (guint16 *)&mem[x*2 + y*rowstride];
276   *ptr = pixel;
277 }
278
279 static void
280 gdk_fb_set_pixel_24(GdkDrawable *drawable,
281                     GdkGC *gc,
282                     int x,
283                     int y,
284                     gulong pixel)
285 {
286   GdkDrawableFBData *private = GDK_DRAWABLE_FBDATA (drawable);
287   guchar *mem = private->mem;
288   guint rowstride = private->rowstride;
289   guchar *smem;
290   
291   g_assert (private->depth == GDK_GC_FBDATA (gc)->depth);
292   
293   smem = &mem[x*3 + y*rowstride];
294   smem[0] = pixel & 0xff;
295   smem[1] = (pixel >> 8) & 0xff;
296   smem[2] = (pixel >> 16) & 0xff;
297 }
298
299 static void
300 gdk_fb_set_pixel_32(GdkDrawable *drawable,
301                     GdkGC *gc,
302                     int x,
303                     int y,
304                     gulong pixel)
305 {
306   GdkDrawableFBData *private = GDK_DRAWABLE_FBDATA (drawable);
307   guchar *mem = private->mem;
308   guint rowstride = private->rowstride;
309   guint32 *smem;
310
311   g_assert (private->depth == GDK_GC_FBDATA (gc)->depth);
312   
313   smem = (guint32 *)&mem[x*4 + y*rowstride];
314   *smem = pixel;
315 }
316
317
318 /*************************************
319  * gc->fill_span() implementations
320  *************************************/
321
322 static void
323 gdk_fb_fill_span_generic (GdkDrawable *drawable,
324                           GdkGC       *gc,
325                           GdkSpan     *span,
326                           GdkColor    *color)
327 {
328   int curx;
329   GdkColor spot = *color;
330   GdkGCFBData *gc_private;
331   GdkDrawableFBData *private;
332   gint left, right, y;
333   int clipxoff, clipyoff; /* Amounts to add to curx & cury to get x & y in clip mask */
334   int tsxoff, tsyoff;
335   GdkDrawable *cmask;
336   guchar *clipmem;
337   guint mask_rowstride;
338   GdkPixmap *ts = NULL;
339   GdkDrawableFBData *ts_private;
340   gboolean solid_stipple;
341   GdkFunction func;
342
343   private = GDK_DRAWABLE_FBDATA (drawable);
344   gc_private = GDK_GC_FBDATA (gc);
345
346   g_assert (gc);
347
348   y = span->y;
349   left = span->x;
350   right = span->x + span->width;
351   
352   func = gc_private->values.function;
353     
354   cmask = gc_private->values.clip_mask;
355   clipxoff = clipyoff = tsxoff = tsyoff = 0;
356   mask_rowstride = 0;
357   solid_stipple = FALSE;
358   clipmem = NULL;
359   
360   if (cmask)
361     {
362       GdkDrawableFBData *cmask_private;
363       
364       cmask_private = GDK_DRAWABLE_IMPL_FBDATA (cmask);
365       
366       clipmem = cmask_private->mem;
367       clipxoff = cmask_private->abs_x - gc_private->values.clip_x_origin - private->abs_x;
368       clipyoff = cmask_private->abs_y - gc_private->values.clip_y_origin - private->abs_y;
369       mask_rowstride = cmask_private->rowstride;
370     }
371   
372   if (gc_private->values.fill == GDK_TILED &&
373       gc_private->values.tile)
374     {
375       gint xstep;
376       gint relx, rely;
377       int drawh;
378       GdkFBDrawingContext *dc, dc_data;
379       
380       dc = &dc_data;
381       
382       gdk_fb_drawing_context_init (dc, drawable, gc, FALSE, TRUE);
383       
384       ts = gc_private->values.tile;
385       ts_private = GDK_DRAWABLE_IMPL_FBDATA (ts);
386       
387       rely = y - private->abs_y;
388       drawh = (rely + gc_private->values.ts_y_origin) % ts_private->height;
389       if (drawh < 0)
390         drawh += GDK_DRAWABLE_FBDATA (ts)->height;
391       
392       for (curx = left; curx < right; curx += xstep)
393         {
394           int draww;
395           
396           relx = curx - private->abs_x;
397           
398           draww = (relx + gc_private->values.ts_x_origin) % ts_private->width;
399           if (draww < 0)
400             draww += ts_private->width;
401           
402           xstep = MIN (ts_private->width - draww, right - relx);
403           
404           gdk_fb_draw_drawable_3 (drawable, gc, GDK_DRAWABLE_IMPL (ts),
405                                   dc,
406                                   draww, drawh,
407                                   relx, rely,
408                                   xstep, 1);
409         }
410       
411       gdk_fb_drawing_context_finalize (dc);
412       
413       return;
414     }
415   else if ((gc_private->values.fill == GDK_STIPPLED ||
416             gc_private->values.fill == GDK_OPAQUE_STIPPLED) &&
417            gc_private->values.stipple)
418     {
419       ts = gc_private->values.stipple;
420       tsxoff = GDK_DRAWABLE_FBDATA (ts)->abs_x - gc_private->values.ts_x_origin - private->abs_x;
421       tsyoff = GDK_DRAWABLE_FBDATA (ts)->abs_y - gc_private->values.ts_y_origin - private->abs_y;
422       solid_stipple = (gc_private->values.fill == GDK_OPAQUE_STIPPLED);
423     }
424   
425   for (curx = left; curx < right; curx++)
426     {
427       int maskx = curx+clipxoff, masky = y + clipyoff;
428       guchar foo;
429       
430       if (cmask)
431         {
432           foo = clipmem[masky*mask_rowstride + (maskx >> 3)];
433           
434           if (!(foo & (1 << (maskx % 8))))
435             continue;
436         }
437       
438       if (func == GDK_INVERT)
439         {
440           (gc_private->get_color) (drawable, gc, curx, y, &spot);
441           spot.pixel = ~spot.pixel;
442           spot.red = ~spot.red;
443           spot.green = ~spot.green;
444           spot.blue = ~spot.blue;
445         }
446       else if (ts)
447         {
448           int wid, hih;
449           
450           ts_private = GDK_DRAWABLE_IMPL_FBDATA (ts);
451           
452           wid = ts_private->width;
453           hih = ts_private->height;
454           
455           maskx = (curx+tsxoff)%wid;
456           masky = (y+tsyoff)%hih;
457           if (maskx < 0)
458             maskx += wid;
459           if (masky < 0)
460             masky += hih;
461           
462           foo = ts_private->mem[(maskx >> 3) + ts_private->rowstride*masky];
463           if (foo & (1 << (maskx % 8)))
464             {
465               spot = gc_private->values.foreground;
466             }
467           else if (solid_stipple)
468             {
469               spot = gc_private->values.background;
470             }
471           else
472             continue;
473         }
474       
475       (gc_private->set_pixel) (drawable, gc, curx, y, spot.pixel);
476     }
477 }
478
479 static void
480 gdk_fb_fill_span_simple_1 (GdkDrawable *drawable,
481                            GdkGC       *gc,
482                            GdkSpan     *span,
483                            GdkColor    *color)
484 {
485   int curx;
486   GdkGCFBData *gc_private;
487   GdkDrawableFBData *private;
488   guchar *mem, *ptr;
489   guint rowstride;
490   gint left, right, y;
491
492   private = GDK_DRAWABLE_FBDATA (drawable);
493   gc_private = GDK_GC_FBDATA (gc);
494
495   g_assert (gc);
496
497   g_assert (!gc_private->values.clip_mask &&
498             !gc_private->values.tile &&
499             !gc_private->values.stipple &&
500             gc_private->values.function != GDK_INVERT);
501
502   y = span->y;
503   left = span->x;
504   right = span->x + span->width;
505   
506   mem = private->mem;
507   rowstride = private->rowstride;
508
509   {
510     int fromx = MIN ((left+7)&(~7), right);
511     int begn = fromx - left, begoff = left % 8, endn;
512     guchar begmask, endmask;
513     int body_end = right & ~7;
514     int body_len = (body_end - fromx)/8;
515     
516     begmask = ((1 << (begn + begoff)) - 1)
517       & ~((1 << (begoff)) - 1);
518     endn = right - body_end;
519     endmask = (1 << endn) - 1;
520     
521     ptr = mem + y*rowstride + (left >> 3);
522         
523     if (color->pixel)
524       *ptr |= begmask;
525     else
526       *ptr &= ~begmask;
527     
528     curx = fromx;
529     
530     if (curx < right)
531       {
532         ptr = mem + y*rowstride + (curx >> 3);
533         memset (ptr, color->pixel?0xFF:0, body_len);
534         
535         if (endn)
536           {
537             ptr = mem + y*rowstride + (body_end >> 3);
538             if (color->pixel)
539               *ptr |= endmask;
540             else
541               *ptr &= ~endmask;
542           }
543       }
544   }
545 }
546
547 static void
548 gdk_fb_fill_span_simple_8 (GdkDrawable *drawable,
549                            GdkGC       *gc,
550                            GdkSpan     *span,
551                            GdkColor    *color)
552 {
553   GdkGCFBData *gc_private;
554   GdkDrawableFBData *private;
555   guchar *mem, *ptr;
556   guint rowstride;
557
558   private = GDK_DRAWABLE_FBDATA (drawable);
559   gc_private = GDK_GC_FBDATA (gc);
560
561   g_assert (gc);
562
563   g_assert (!gc_private->values.clip_mask &&
564             !gc_private->values.tile &&
565             !gc_private->values.stipple &&
566             gc_private->values.function != GDK_INVERT);
567
568   mem = private->mem;
569   rowstride = private->rowstride;
570
571   ptr = mem + span->y*rowstride + span->x;
572   memset (ptr, color->pixel, span->width);
573 }
574 static void
575 gdk_fb_fill_span_simple_16 (GdkDrawable *drawable,
576                             GdkGC       *gc,
577                             GdkSpan     *span,
578                             GdkColor    *color)
579 {
580   GdkGCFBData *gc_private;
581   GdkDrawableFBData *private;
582   guchar *mem;
583   guint rowstride;
584   guint16 *p16;
585   int n;
586   int i;
587
588   private = GDK_DRAWABLE_FBDATA (drawable);
589   gc_private = GDK_GC_FBDATA (gc);
590
591   g_assert (gc);
592
593   g_assert (!gc_private->values.clip_mask &&
594             !gc_private->values.tile &&
595             !gc_private->values.stipple &&
596             gc_private->values.function != GDK_INVERT);
597
598   mem = private->mem;
599   rowstride = private->rowstride;
600
601   n = span->width;
602   p16 = (guint16 *)(mem + span->y * rowstride + span->x*2);
603   for (i = 0; i < n; i++)
604     *(p16++) = color->pixel;
605 }
606
607 static void
608 gdk_fb_fill_span_simple_24 (GdkDrawable *drawable,
609                             GdkGC       *gc,
610                             GdkSpan     *span,
611                             GdkColor    *color)
612 {
613   GdkGCFBData *gc_private;
614   GdkDrawableFBData *private;
615   guchar *mem, *ptr;
616   guint rowstride;
617   int n;
618   guchar redval, greenval, blueval;
619   guchar *firstline, *ptr_end;
620
621   private = GDK_DRAWABLE_FBDATA (drawable);
622   gc_private = GDK_GC_FBDATA (gc);
623
624   g_assert (gc);
625
626   g_assert (!gc_private->values.clip_mask &&
627             !gc_private->values.tile &&
628             !gc_private->values.stipple &&
629             gc_private->values.function != GDK_INVERT);
630
631   mem = private->mem;
632   rowstride = private->rowstride;
633
634   redval = color->red>>8;
635   greenval = color->green>>8;
636   blueval = color->blue>>8;
637     
638   n = span->width*3;
639     
640   firstline = ptr = mem + span->y * rowstride + span->x*3;
641   ptr_end = ptr+n;
642   while (ptr < ptr_end)
643     {
644       ptr[gdk_display->red_byte] = redval;
645       ptr[gdk_display->green_byte] = greenval;
646       ptr[gdk_display->blue_byte] = blueval;
647       ptr += 3;
648     }
649 }
650 static void
651 gdk_fb_fill_span_simple_32 (GdkDrawable *drawable,
652                             GdkGC       *gc,
653                             GdkSpan     *span,
654                             GdkColor    *color)
655 {
656   GdkGCFBData *gc_private;
657   GdkDrawableFBData *private;
658   guchar *mem;
659   guint rowstride;
660   guint32 *p32;
661   int n;
662   int i;
663
664   private = GDK_DRAWABLE_FBDATA (drawable);
665   gc_private = GDK_GC_FBDATA (gc);
666
667   g_assert (gc);
668
669   g_assert (!gc_private->values.clip_mask &&
670             !gc_private->values.tile &&
671             !gc_private->values.stipple &&
672             gc_private->values.function != GDK_INVERT);
673
674   mem = private->mem;
675   rowstride = private->rowstride;
676
677   n = span->width;
678   p32 = (guint32 *)(mem + span->y * rowstride + span->x*4);
679   for (i = 0; i < n; i++)
680     *(p32++) = color->pixel;
681 }
682
683
684 /*************************************
685  * gc->draw_drawable() implementations
686  *************************************/
687
688 static void
689 gdk_fb_draw_drawable_generic (GdkDrawable *drawable,
690                               GdkGC       *gc,
691                               GdkPixmap   *src,
692                               GdkFBDrawingContext *dc,
693                               gint         start_y,
694                               gint         end_y,
695                               gint         start_x,
696                               gint         end_x,
697                               gint         src_x_off,
698                               gint         src_y_off,
699                               gint         draw_direction)
700 {
701   GdkDrawableFBData *private = GDK_DRAWABLE_FBDATA (drawable);
702   int cur_x, cur_y;
703
704   if (draw_direction < 0)
705     {
706       int tmp;
707       tmp = start_y;
708       start_y = end_y;
709       end_y = tmp;
710       start_y--;
711       end_y--;
712       
713       tmp = start_x;
714       start_x = end_x;
715       end_x = tmp;
716       start_x--;
717       end_x--;
718     }
719
720   for (cur_y = start_y; cur_y != end_y; cur_y+=draw_direction)
721     {
722       for (cur_x = start_x; cur_x != end_x; cur_x+=draw_direction)
723         {
724           GdkColor spot;
725           
726           if (GDK_GC_FBDATA(gc)->values.clip_mask)
727             {
728               int maskx = cur_x + dc->clipxoff, masky = cur_y + dc->clipyoff;
729               guchar foo;
730               
731               foo = dc->clipmem[masky*dc->clip_rowstride + (maskx >> 3)];
732               
733               if (!(foo & (1 << (maskx % 8))))
734                 continue;
735             }
736           
737           switch (gdk_fb_drawable_get_color (src, gc, cur_x + src_x_off, cur_y + src_y_off, &spot))
738             {
739             case GPR_AA_GRAYVAL:
740               {
741                 GdkColor realspot, fg;
742                 guint graylevel = spot.pixel;
743                 gint tmp;
744                 
745                 if (private->depth == 1)
746                   {
747                     if (spot.pixel > 192)
748                       spot = GDK_GC_FBDATA (gc)->values.foreground;
749                     else
750                       spot = GDK_GC_FBDATA (gc)->values.background;
751                     break;
752                   }
753                 else
754                   {
755                     if (graylevel >= 254)
756                       {
757                         spot = GDK_GC_FBDATA (gc)->values.foreground;
758                       }
759                     else if (graylevel <= 2)
760                       {
761                         if (!dc->draw_bg)
762                           continue;
763                         
764                         spot = GDK_GC_FBDATA (gc)->values.background;
765                       }
766                     else
767                       {
768                         switch ((GDK_GC_FBDATA (gc)->get_color) (drawable, gc, cur_x, cur_y, &realspot))
769                           {
770                           case GPR_USED_BG:
771                             {
772                               int bgx, bgy;
773                               
774                               bgx = (cur_x - GDK_DRAWABLE_IMPL_FBDATA (dc->bg_relto)->abs_x) % GDK_DRAWABLE_IMPL_FBDATA (dc->bgpm)->width + private->abs_x;
775                               bgy = (cur_y - GDK_DRAWABLE_IMPL_FBDATA (dc->bg_relto)->abs_y) % GDK_DRAWABLE_IMPL_FBDATA (dc->bgpm)->height + private->abs_y;
776                               gdk_fb_drawable_get_color (dc->bgpm, gc, bgx, bgy, &realspot);
777                             }
778                             break;
779                           case GPR_NONE:
780                             break;
781                           default:
782                             g_assert_not_reached ();
783                             break;
784                           }
785                         
786                         fg = GDK_GC_FBDATA (gc)->values.foreground;
787
788                         /* Now figure out what 'spot' should actually look like */
789                         fg.red >>= 8;
790                         fg.green >>= 8;
791                         fg.blue >>= 8;
792                         realspot.red >>= 8;
793                         realspot.green >>= 8;
794                         realspot.blue >>= 8;
795
796                                 
797                         tmp = (fg.red - realspot.red) * graylevel;
798                         spot.red = realspot.red + ((tmp + (tmp >> 8) + 0x80) >> 8);
799                         spot.red <<= 8;
800                         
801                         tmp = (fg.green - realspot.green) * graylevel;
802                         spot.green = realspot.green + ((tmp + (tmp >> 8) + 0x80) >> 8);
803                         spot.green <<= 8;
804                         
805                         tmp = (fg.blue - realspot.blue) * graylevel;
806                         spot.blue = realspot.blue + ((tmp + (tmp >> 8) + 0x80) >> 8);
807                         spot.blue <<= 8;
808                         
809                         /* Now find the pixel for this thingie */
810                         switch (private->depth)
811                           {
812                           case 8:
813                             if (!gdk_colormap_alloc_color (private->colormap, &spot, FALSE, TRUE))
814                               {
815                                 g_error ("Can't allocate AA color!");
816                               }
817                             break;
818                           case 16:
819                             spot.pixel = (spot.red >> (16 - gdk_display->modeinfo.red.length)) << gdk_display->modeinfo.red.offset;
820                             spot.pixel |= (spot.green >> (16 - gdk_display->modeinfo.green.length)) << gdk_display->modeinfo.green.offset;
821                             spot.pixel |= (spot.blue >> (16 - gdk_display->modeinfo.blue.length)) << gdk_display->modeinfo.blue.offset;
822                             break;
823                           case 24:
824                           case 32:
825                             spot.pixel = ((spot.red & 0xFF00) >> 8  << (gdk_display->modeinfo.red.offset))
826                               | ((spot.green & 0xFF00) >> 8 << (gdk_display->modeinfo.green.offset))
827                               | ((spot.blue & 0xFF00) >> 8 << (gdk_display->modeinfo.blue.offset));
828                             break;
829                           }
830                       }
831                   }
832               }
833               break;
834             case GPR_USED_BG:
835               if (!dc->draw_bg)
836                 continue;
837               break;
838             case GPR_NONE:
839               break;
840             default:
841               g_assert_not_reached ();
842               break;
843             }
844           
845           (GDK_GC_FBDATA (gc)->set_pixel) (drawable, gc, cur_x, cur_y, spot.pixel);
846         }
847     }
848
849 }
850
851 void
852 gdk_fb_draw_drawable_memmove (GdkDrawable *drawable,
853                               GdkGC       *gc,
854                               GdkPixmap   *src,
855                               GdkFBDrawingContext *dc,
856                               gint         start_y,
857                               gint         end_y,
858                               gint         start_x,
859                               gint         end_x,
860                               gint         src_x_off,
861                               gint         src_y_off,
862                               gint         draw_direction)
863 {
864   GdkDrawableFBData *src_private = GDK_DRAWABLE_FBDATA (src);
865   guint depth = src_private->depth;
866   guint src_rowstride = src_private->rowstride;
867   guchar *srcmem = src_private->mem;
868   int linelen = (end_x - start_x)*(depth>>3);
869   gint cur_y;
870
871   if (draw_direction < 0)
872     {
873       int tmp;
874       tmp = start_y;
875       start_y = end_y;
876       end_y = tmp;
877       start_y--;
878       end_y--;
879     }
880
881   for(cur_y = start_y; cur_y != end_y; cur_y += draw_direction)
882     {
883       memmove (dc->mem + (cur_y * dc->rowstride) + start_x*(depth>>3),
884                srcmem + ((cur_y + src_y_off)*src_rowstride) + (start_x + src_x_off)*(depth>>3),
885                linelen);
886     }
887
888 }
889
890 static void
891 gdk_fb_draw_drawable_aa_24 (GdkDrawable *drawable,
892                             GdkGC       *gc,
893                             GdkPixmap   *src,
894                             GdkFBDrawingContext *dc,
895                             gint         start_y,
896                             gint         end_y,
897                             gint         start_x,
898                             gint         end_x,
899                             gint         src_x_off,
900                             gint         src_y_off,
901                             gint         draw_direction)
902 {
903   GdkDrawableFBData *private = GDK_DRAWABLE_FBDATA (drawable);
904   int x, y;
905   GdkGCFBData *gc_private;
906   guchar *dmem = private->mem;
907   guint dst_rowstride = private->rowstride;
908   guchar *smem = GDK_DRAWABLE_FBDATA (src)->mem;
909   guint src_rowstride = GDK_DRAWABLE_FBDATA (src)->rowstride;
910   guchar *dst;
911   guint grayval;
912   gint r, g, b, tmp;
913   GdkColor fg;
914   gint fg_r, fg_g, fg_b;
915   
916   gc_private = GDK_GC_FBDATA (gc);
917
918   fg = GDK_GC_FBDATA (gc)->values.foreground;
919   fg_r = fg.red >> 8;
920   fg_g = fg.green >> 8;
921   fg_b = fg.blue >> 8;
922
923   if (draw_direction < 0)
924     {
925       int tmp;
926       tmp = start_y;
927       start_y = end_y;
928       end_y = tmp;
929       start_y--;
930       end_y--;
931       
932       tmp = start_x;
933       start_x = end_x;
934       end_x = tmp;
935       start_x--;
936       end_x--;
937     }
938
939   for (y = start_y; y != end_y; y+=draw_direction)
940     {
941       for (x = start_x; x != end_x; x+=draw_direction)
942         {
943           grayval = smem[x + src_x_off + (y + src_y_off) * src_rowstride];
944
945           if ((grayval <= 2) && (!dc->draw_bg))
946             continue;
947
948           dst = &dmem[x*3 + y*dst_rowstride];
949           
950           if (grayval >= 254)
951             {
952               dst[gdk_display->red_byte] = fg_r;
953               dst[gdk_display->green_byte] = fg_g;
954               dst[gdk_display->blue_byte] = fg_b;
955             }
956           else if (grayval <= 2)
957             {
958               dst[gdk_display->red_byte] = GDK_GC_FBDATA (gc)->values.background.red >> 8;
959               dst[gdk_display->green_byte] = GDK_GC_FBDATA (gc)->values.background.green >> 8;
960               dst[gdk_display->blue_byte] = GDK_GC_FBDATA (gc)->values.background.blue >> 8;
961             }
962           else
963             {
964               r = dst[gdk_display->red_byte];
965               tmp = (fg_r - r) * (gint)grayval;
966               r = r + ((tmp + (tmp >> 8) + 0x80) >> 8);
967               dst[gdk_display->red_byte] = r;
968
969               g = dst[gdk_display->green_byte];
970               tmp = (fg_g - g) * (gint)grayval;
971               g = g + ((tmp + (tmp >> 8) + 0x80) >> 8);
972               dst[gdk_display->green_byte] = g;
973
974               b = dst[gdk_display->blue_byte];
975               tmp = (fg_b - b) * (gint)grayval;
976               b = b + ((tmp + (tmp >> 8) + 0x80) >> 8);
977               dst[gdk_display->blue_byte] = b;
978             }
979         }
980     }
981 }
982
983 /*************************************
984  * gc->fill_rectangle() implementations
985  *************************************/
986
987 void
988 gdk_fb_fill_rectangle_generic (GdkDrawable    *drawable,
989                                GdkGC          *gc,
990                                GdkRectangle   *rect,
991                                GdkColor       *color)
992 {
993   GdkDrawableFBData *private;
994   GdkSpan *spans;
995   int i;
996
997   private = GDK_DRAWABLE_FBDATA (drawable);
998
999   spans = g_new (GdkSpan, rect->height);
1000   for (i=0;i<rect->height;i++)
1001     {
1002       spans[i].x = rect->x - private->abs_x;
1003       spans[i].y = rect->y+i - private->abs_y;
1004       spans[i].width = rect->width;
1005     }
1006   gdk_fb_fill_spans (drawable, gc, spans, rect->height, TRUE);
1007   g_free (spans);
1008 }
1009
1010 void
1011 gdk_fb_fill_rectangle_simple_16 (GdkDrawable    *drawable,
1012                                  GdkGC          *gc,
1013                                  GdkRectangle   *rect,
1014                                  GdkColor       *color)
1015 {
1016   GdkGCFBData *gc_private;
1017   GdkDrawableFBData *private;
1018   guchar *ptr;
1019   guint rowstride;
1020   int n;
1021   gboolean extra;
1022   int i;
1023   guint32 pixel;
1024   gint height;
1025   
1026   private = GDK_DRAWABLE_FBDATA (drawable);
1027   gc_private = GDK_GC_FBDATA (gc);
1028
1029   rowstride = private->rowstride - rect->width*2;
1030   ptr = (guchar *)private->mem + rect->y * private->rowstride + rect->x*2;
1031
1032   extra = rect->width&1;
1033   n = rect->width>>1;
1034     
1035   pixel = (color->pixel << 16) | color->pixel;
1036
1037   height = rect->height;
1038   while (height>0)
1039     {
1040       i = n;
1041       while (i>0)
1042         {
1043           *(guint32 *)ptr = pixel;
1044           ptr += 4;
1045           i--;
1046         }
1047       if (extra)
1048         {
1049           *(guint16 *)ptr = color->pixel;
1050           ptr += 2;
1051         }
1052       ptr += rowstride;
1053       height--; 
1054     }
1055 }
1056
1057 void
1058 gdk_fb_fill_rectangle_simple_32 (GdkDrawable    *drawable,
1059                                  GdkGC          *gc,
1060                                  GdkRectangle   *rect,
1061                                  GdkColor       *color)
1062 {
1063   GdkGCFBData *gc_private;
1064   GdkDrawableFBData *private;
1065   guchar *ptr;
1066   guint rowstride;
1067   int n;
1068   int i;
1069   guint32 pixel;
1070   gint height;
1071   
1072   private = GDK_DRAWABLE_FBDATA (drawable);
1073   gc_private = GDK_GC_FBDATA (gc);
1074
1075   rowstride = private->rowstride - rect->width*4;
1076   ptr = (guchar *)private->mem + rect->y * private->rowstride + rect->x*4;
1077
1078   n = rect->width;
1079     
1080   pixel = color->pixel;
1081
1082   height = rect->height;
1083   while (height>0)
1084     {
1085       i = n;
1086       while (i>0)
1087         {
1088           *(guint32 *)ptr = pixel;
1089           ptr += 4;
1090           i--;
1091         }
1092       ptr += rowstride;
1093       height--; 
1094     }
1095 }
1096
1097
1098 /*************************************
1099  * GC state calculation
1100  *************************************/
1101
1102 void
1103 _gdk_fb_gc_calc_state (GdkGC           *gc,
1104                        GdkGCValuesMask  changed)
1105 {
1106   GdkGCFBData *gc_private;
1107   int i;
1108
1109   gc_private = GDK_GC_FBDATA (gc);
1110
1111   gc_private->fill_span = gdk_fb_fill_span_generic;
1112   gc_private->fill_rectangle = gdk_fb_fill_rectangle_generic;
1113
1114   for (i=0;i<GDK_NUM_FB_SRCBPP;i++)
1115     gc_private->draw_drawable[i] = gdk_fb_draw_drawable_generic;
1116   
1117   if (changed & _GDK_FB_GC_DEPTH)
1118     switch (gc_private->depth)
1119       {
1120       case 1:
1121         gc_private->set_pixel = gdk_fb_set_pixel_1;
1122         gc_private->get_color = gdk_fb_get_color_1;
1123         break;
1124       case 8:
1125         gc_private->set_pixel = gdk_fb_set_pixel_8;
1126         gc_private->get_color = gdk_fb_get_color_8;
1127         break;
1128       case 16:
1129         gc_private->set_pixel = gdk_fb_set_pixel_16;
1130         gc_private->get_color = gdk_fb_get_color_16;
1131         break;
1132       case 24:
1133         gc_private->set_pixel = gdk_fb_set_pixel_24;
1134         gc_private->get_color = gdk_fb_get_color_24;
1135         break;
1136       case 32:
1137         gc_private->set_pixel = gdk_fb_set_pixel_32;
1138         gc_private->get_color = gdk_fb_get_color_32;
1139         break;
1140       default:
1141         g_assert_not_reached ();
1142         break;
1143       }
1144
1145   if (!gc_private->values.clip_mask)
1146     {
1147     switch (gc_private->depth)
1148       {
1149       case 8:
1150         gc_private->draw_drawable[GDK_FB_SRC_BPP_8] = gdk_fb_draw_drawable_memmove;
1151         break;
1152       case 16:
1153         gc_private->draw_drawable[GDK_FB_SRC_BPP_16] = gdk_fb_draw_drawable_memmove;
1154         break;
1155       case 24:
1156         gc_private->draw_drawable[GDK_FB_SRC_BPP_8_AA_GRAYVAL] = gdk_fb_draw_drawable_aa_24;
1157         gc_private->draw_drawable[GDK_FB_SRC_BPP_24] = gdk_fb_draw_drawable_memmove;
1158         break;
1159       case 32:
1160         gc_private->draw_drawable[GDK_FB_SRC_BPP_32] = gdk_fb_draw_drawable_memmove;
1161         break;
1162       }
1163     }
1164   
1165   if (!gc_private->values.clip_mask &&
1166       !gc_private->values.tile &&
1167       !gc_private->values.stipple &&
1168        gc_private->values.function != GDK_INVERT)
1169     {
1170       switch (gc_private->depth)
1171         {
1172         case 1:
1173           gc_private->fill_span = gdk_fb_fill_span_simple_1;
1174           break;
1175         case 8:
1176           gc_private->fill_span = gdk_fb_fill_span_simple_8;
1177           break;
1178         case 16:
1179           gc_private->fill_span = gdk_fb_fill_span_simple_16;
1180           gc_private->fill_rectangle = gdk_fb_fill_rectangle_simple_16;
1181           break;
1182         case 24:
1183           gc_private->fill_span = gdk_fb_fill_span_simple_24;
1184           break;
1185         case 32:
1186           gc_private->fill_span = gdk_fb_fill_span_simple_32;
1187           gc_private->fill_rectangle = gdk_fb_fill_rectangle_simple_32;
1188           break;
1189         default:
1190           g_assert_not_reached ();
1191           break;
1192         }
1193     }
1194
1195 }
1196