1 /* GDK - The GIMP Drawing Kit
2 * Copyright (C) 2000 Elliot Lee
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.
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.
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.
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/.
28 #include "gdkprivate-fb.h"
31 #include <gdkregion-generic.h>
33 #include <pango/pangoft2.h>
34 #include <freetype/ftglyph.h>
37 #define g_alloca alloca
40 void gdk_fb_draw_rectangle (GdkDrawable *drawable,
47 static void gdk_fb_draw_arc (GdkDrawable *drawable,
56 static void gdk_fb_draw_polygon (GdkDrawable *drawable,
61 static void gdk_fb_draw_text (GdkDrawable *drawable,
68 static void gdk_fb_draw_text_wc (GdkDrawable *drawable,
75 static void gdk_fb_draw_glyphs (GdkDrawable *drawable,
80 PangoGlyphString *glyphs);
81 void gdk_fb_draw_drawable (GdkDrawable *drawable,
90 static void gdk_fb_draw_image (GdkDrawable *drawable,
99 static void gdk_fb_draw_points (GdkDrawable *drawable,
103 static void gdk_fb_draw_segments (GdkDrawable *drawable,
107 static void gdk_fb_draw_lines (GdkDrawable *drawable,
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);
119 #ifdef ENABLE_SHADOW_FB
120 static void gdk_shadow_fb_draw_rectangle (GdkDrawable *drawable,
127 static void gdk_shadow_fb_draw_arc (GdkDrawable *drawable,
136 static void gdk_shadow_fb_draw_polygon (GdkDrawable *drawable,
141 static void gdk_shadow_fb_draw_text (GdkDrawable *drawable,
148 static void gdk_shadow_fb_draw_text_wc (GdkDrawable *drawable,
153 const GdkWChar *text,
155 static void gdk_shadow_fb_draw_glyphs (GdkDrawable *drawable,
160 PangoGlyphString *glyphs);
161 static void gdk_shadow_fb_draw_drawable (GdkDrawable *drawable,
170 static void gdk_shadow_fb_draw_image (GdkDrawable *drawable,
179 static void gdk_shadow_fb_draw_points (GdkDrawable *drawable,
183 static void gdk_shadow_fb_draw_segments (GdkDrawable *drawable,
187 static void gdk_shadow_fb_draw_lines (GdkDrawable *drawable,
194 static gpointer parent_class = NULL;
197 gdk_fb_get_size (GdkDrawable *d, gint *width, gint *height)
200 *width = GDK_DRAWABLE_FBDATA (d)->width;
202 *height = GDK_DRAWABLE_FBDATA (d)->height;
206 gdk_drawable_impl_fb_class_init (GdkDrawableFBClass *klass)
208 GdkDrawableClass *drawable_class = GDK_DRAWABLE_CLASS (klass);
209 GObjectClass *object_class = G_OBJECT_CLASS (klass);
211 parent_class = g_type_class_peek_parent (klass);
213 object_class->finalize = gdk_fb_drawable_finalize;
215 drawable_class->create_gc = _gdk_fb_gc_new;
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;
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;
243 drawable_class->set_colormap = gdk_fb_set_colormap;
244 drawable_class->get_colormap = gdk_fb_get_colormap;
246 drawable_class->get_size = gdk_fb_get_size;
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;
252 drawable_class->_copy_to_image = _gdk_fb_copy_to_image;
256 gdk_fb_drawable_finalize (GObject *object)
258 gdk_drawable_set_colormap (GDK_DRAWABLE (object), NULL);
260 G_OBJECT_CLASS (parent_class)->finalize (object);
265 gdk_drawable_impl_fb_get_type (void)
267 static GType object_type = 0;
271 static const GTypeInfo object_info =
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),
281 (GInstanceInitFunc) NULL,
284 object_type = g_type_register_static (GDK_TYPE_DRAWABLE,
293 /*****************************************************
294 * FB specific implementations of generic functions *
295 *****************************************************/
298 gdk_fb_get_colormap (GdkDrawable *drawable)
300 GdkColormap *retval = GDK_DRAWABLE_FBDATA (drawable)->colormap;
303 retval = gdk_colormap_get_system ();
309 gdk_fb_set_colormap (GdkDrawable *drawable,
310 GdkColormap *colormap)
312 GdkDrawableFBData *private;
314 private = GDK_DRAWABLE_FBDATA (drawable);
316 if (private->colormap == colormap)
319 if (private->colormap)
320 gdk_colormap_unref (private->colormap);
321 private->colormap = colormap;
322 if (private->colormap)
323 gdk_colormap_ref (private->colormap);
326 /* Calculates the real clipping region for a drawable, taking into account
327 * other windows, gc clip region and gc clip mask.
330 gdk_fb_clip_region (GdkDrawable *drawable,
332 gboolean do_clipping,
333 gboolean do_children,
334 gboolean full_shapes)
336 GdkRectangle draw_rect;
337 GdkRegion *real_clip_region, *tmpreg, *shape;
338 gboolean skipit = FALSE;
339 GdkDrawableFBData *private;
340 GdkWindowObject *parent;
342 GDK_CHECK_IMPL (drawable);
344 private = GDK_DRAWABLE_FBDATA (drawable);
346 g_assert(!GDK_IS_WINDOW (private->wrapper) ||
347 !GDK_WINDOW_P (private->wrapper)->input_only);
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))
354 draw_rect.width = private->lim_x - draw_rect.x;
355 draw_rect.height = private->lim_y - draw_rect.y;
359 draw_rect.width = draw_rect.height = 0;
362 real_clip_region = gdk_region_rectangle (&draw_rect);
364 return real_clip_region;
366 if (GDK_IS_WINDOW (private->wrapper))
368 parent = GDK_WINDOW_P (private->wrapper);
369 while (parent != (GdkWindowObject *)_gdk_parent_root)
373 shape = gdk_fb_window_get_abs_shape (GDK_DRAWABLE (parent));
376 gdk_region_intersect (real_clip_region, shape);
377 gdk_region_destroy (shape);
383 shape = gdk_fb_window_peek_shape (GDK_DRAWABLE (parent), &dx, &dy);
389 gdk_region_get_clipbox (shape, &rect);
391 rect.x += GDK_DRAWABLE_IMPL_FBDATA (parent)->abs_x + dx;
392 rect.y += GDK_DRAWABLE_IMPL_FBDATA (parent)->abs_y + dy;
394 reg = gdk_region_rectangle(&rect);
395 gdk_region_intersect (real_clip_region, reg);
396 gdk_region_destroy (reg);
400 parent = parent->parent;
404 if (gc && GDK_GC_FBDATA(gc)->values.subwindow_mode == GDK_INCLUDE_INFERIORS)
408 GDK_IS_WINDOW (private->wrapper) &&
409 GDK_WINDOW_IS_MAPPED (private->wrapper) &&
410 !GDK_WINDOW_P (private->wrapper)->input_only)
412 GdkWindow *parentwin, *lastwin;
413 GdkDrawableFBData *impl_private;
415 lastwin = private->wrapper;
419 parentwin = (GdkWindow *)GDK_WINDOW_P (lastwin)->parent;
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)
426 for (cur = GDK_WINDOW_P (parentwin)->children; cur && cur->data != lastwin; cur = cur->next)
428 if (!GDK_WINDOW_IS_MAPPED (cur->data) || GDK_WINDOW_P (cur->data)->input_only)
431 impl_private = GDK_DRAWABLE_IMPL_FBDATA(cur->data);
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)
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;
445 tmpreg = gdk_region_rectangle (&draw_rect);
447 shape = gdk_fb_window_get_abs_shape (impl_private->wrapper);
450 gdk_region_intersect (tmpreg, shape);
451 gdk_region_destroy (shape);
454 gdk_region_subtract (real_clip_region, tmpreg);
455 gdk_region_destroy (tmpreg);
462 GdkRegion *gc = _gdk_gc_get_clip_region (gc);
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);
473 if (GDK_GC_FBDATA (gc)->values.clip_mask)
475 GdkDrawable *cmask = GDK_GC_FBDATA (gc)->values.clip_mask;
476 GdkDrawableFBData *cmask_private;
478 cmask_private = GDK_DRAWABLE_IMPL_FBDATA (cmask);
480 g_assert (cmask_private->depth == 1);
481 g_assert (cmask_private->abs_x == 0 &&
482 cmask_private->abs_y == 0);
484 draw_rect.x = private->abs_x +
485 cmask_private->llim_x +
486 GDK_GC_FBDATA (gc)->values.clip_x_origin;
488 draw_rect.y = private->abs_y +
489 cmask_private->llim_y +
490 GDK_GC_FBDATA (gc)->values.clip_y_origin;
492 draw_rect.width = cmask_private->width;
493 draw_rect.height = cmask_private->height;
495 tmpreg = gdk_region_rectangle (&draw_rect);
496 gdk_region_intersect (real_clip_region, tmpreg);
497 gdk_region_destroy (tmpreg);
499 if (!real_clip_region->numRects)
500 g_warning ("Empty clip region");
505 return real_clip_region;
511 GdkDrawable *drawable;
517 gdk_fb_fill_span_helper(GdkSpan *span,
520 struct GdkSpanHelper *info = (struct GdkSpanHelper *)data;
521 GdkGC * gc = info->gc;
523 (GDK_GC_FBDATA (gc)->fill_span) (info->drawable, gc, span, &info->color);
527 gdk_fb_fill_spans (GdkDrawable *real_drawable,
534 struct GdkSpanHelper info;
535 GdkRegion *real_clip_region;
536 gboolean handle_cursor = FALSE;
537 GdkDrawable *drawable;
538 GdkDrawableFBData *private;
540 drawable = real_drawable;
541 private = GDK_DRAWABLE_FBDATA (drawable);
545 if (GDK_IS_WINDOW (private->wrapper) && !GDK_WINDOW_IS_MAPPED (private->wrapper))
547 if (GDK_IS_WINDOW (private->wrapper) && GDK_WINDOW_P (private->wrapper)->input_only)
548 g_error ("Drawing on the evil input-only!");
550 info.drawable = drawable;
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;
558 gdk_color_black (private->colormap, &info.color);
560 real_clip_region = gdk_fb_clip_region (drawable, gc, TRUE, GDK_GC_FBDATA (gc)->values.function != GDK_INVERT, TRUE);
562 if (private->mem == GDK_DRAWABLE_IMPL_FBDATA (_gdk_parent_root)->mem &&
563 gdk_fb_cursor_region_need_hide (real_clip_region))
565 handle_cursor = TRUE;
566 gdk_fb_cursor_hide ();
569 for (i = 0; i < nspans; i++)
575 cur->x += private->abs_x;
576 cur->y += private->abs_y;
578 if ( (cur->y < private->llim_y) || (cur->y >= private->lim_y))
581 if (cur->x < private->llim_x)
583 cur->width -= private->llim_x - cur->x;
584 cur->x = private->llim_x;
587 if (cur->x + cur->width > private->lim_x)
589 cur->width = private->lim_x - cur->x;
596 gdk_region_spans_intersect_foreach (real_clip_region,
600 gdk_fb_fill_span_helper,
603 gdk_region_destroy (real_clip_region);
605 gdk_fb_cursor_unhide ();
609 gdk_fb_drawing_context_init (GdkFBDrawingContext *dc,
610 GdkDrawable *drawable,
613 gboolean do_clipping)
615 GdkDrawableFBData *private = GDK_DRAWABLE_FBDATA (drawable);
616 dc->mem = private->mem;
617 dc->rowstride = private->rowstride;
618 dc->handle_cursor = FALSE;
620 dc->bg_relto = private->wrapper;
621 dc->draw_bg = draw_bg;
623 GDK_CHECK_IMPL (drawable);
625 if (GDK_IS_WINDOW (private->wrapper))
627 dc->bgpm = GDK_WINDOW_P (private->wrapper)->bg_pixmap;
628 if (dc->bgpm == GDK_PARENT_RELATIVE_BG)
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;
634 if (dc->bgpm == GDK_NO_BG)
637 dc->clipxoff = - private->abs_x;
638 dc->clipyoff = - private->abs_y;
640 dc->real_clip_region = gdk_fb_clip_region (drawable, gc, do_clipping, TRUE, TRUE);
644 dc->clipxoff -= GDK_GC_FBDATA (gc)->values.clip_x_origin;
645 dc->clipyoff -= GDK_GC_FBDATA (gc)->values.clip_y_origin;
647 if (GDK_GC_FBDATA (gc)->values.clip_mask)
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;
655 private->mem == GDK_DRAWABLE_IMPL_FBDATA (_gdk_parent_root)->mem &&
656 gdk_fb_cursor_region_need_hide (dc->real_clip_region))
658 dc->handle_cursor = TRUE;
659 gdk_fb_cursor_hide ();
664 gdk_fb_drawing_context_finalize (GdkFBDrawingContext *dc)
666 gdk_region_destroy (dc->real_clip_region);
668 if (dc->handle_cursor)
669 gdk_fb_cursor_unhide ();
673 gdk_fb_draw_drawable_2 (GdkDrawable *drawable,
683 gboolean do_clipping)
685 GdkFBDrawingContext *dc, dc_data;
688 GDK_CHECK_IMPL (src);
689 GDK_CHECK_IMPL (drawable);
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);
697 gdk_fb_draw_drawable_3 (GdkDrawable *drawable,
700 GdkFBDrawingContext *dc,
708 GdkDrawableFBData *private = GDK_DRAWABLE_FBDATA (drawable);
709 GdkDrawableFBData *src_private = GDK_DRAWABLE_FBDATA (src);
711 int src_x_off, src_y_off;
712 GdkRegion *tmpreg, *real_clip_region;
714 int draw_direction = 1;
715 gdk_fb_draw_drawable_func *draw_func = NULL;
716 GdkGCFBData *gc_private;
720 GDK_CHECK_IMPL (src);
721 GDK_CHECK_IMPL (drawable);
723 if (GDK_IS_WINDOW (private->wrapper))
725 if (!GDK_WINDOW_IS_MAPPED (private->wrapper))
727 if (GDK_WINDOW_P (private->wrapper)->input_only)
728 g_error ("Drawing on the evil input-only!");
731 gc_private = GDK_GC_FBDATA (gc);
735 GdkRegionBox srcb, destb;
738 srcb.x2 = xsrc + width;
739 srcb.y2 = ysrc + height;
742 destb.x2 = xdest + width;
743 destb.y2 = ydest + height;
745 if (EXTENTCHECK (&srcb, &destb) && ((ydest > ysrc) || ((ydest == ysrc) && (xdest > xsrc))))
749 switch (src_private->depth)
752 draw_func = gc_private->draw_drawable[GDK_FB_SRC_BPP_1];
755 draw_func = gc_private->draw_drawable[GDK_FB_SRC_BPP_8];
758 draw_func = gc_private->draw_drawable[GDK_FB_SRC_BPP_16];
761 draw_func = gc_private->draw_drawable[GDK_FB_SRC_BPP_24];
764 draw_func = gc_private->draw_drawable[GDK_FB_SRC_BPP_32];
767 draw_func = gc_private->draw_drawable[GDK_FB_SRC_BPP_7_AA_GRAYVAL];
770 draw_func = gc_private->draw_drawable[GDK_FB_SRC_BPP_8_AA_GRAYVAL];
773 g_assert_not_reached ();
777 /* Do some magic to avoid creating extra regions unnecessarily */
778 tmpreg = dc->real_clip_region;
780 rect.x = xdest + private->abs_x;
781 rect.y = ydest + private->abs_y;
783 rect.height = height;
784 real_clip_region = gdk_region_rectangle (&rect);
785 gdk_region_intersect (real_clip_region, tmpreg);
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)
793 tmpreg = gdk_region_rectangle (&rect);
794 gdk_region_intersect (real_clip_region, tmpreg);
795 gdk_region_destroy (tmpreg);
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);
800 for (i = (draw_direction>0)?0:real_clip_region->numRects-1; i >= 0 && i < real_clip_region->numRects; i+=draw_direction)
802 GdkRegionBox *cur = &real_clip_region->rects[i];
804 (*draw_func) (drawable,
818 gdk_region_destroy (real_clip_region);
823 gdk_fb_draw_drawable (GdkDrawable *drawable,
835 if (GDK_IS_DRAWABLE_IMPL_FBDATA (src))
838 src_impl = GDK_DRAWABLE_IMPL (src);
840 GDK_CHECK_IMPL (drawable);
842 gdk_fb_draw_drawable_2 (drawable, gc, src_impl , xsrc, ysrc, xdest, ydest, width, height, TRUE, TRUE);
845 #ifdef EMULATE_GDKFONT
847 gdk_fb_draw_text(GdkDrawable *drawable,
855 GdkFontPrivateFB *private;
856 guchar *utf8, *utf8_end;
857 PangoGlyphString *glyphs = pango_glyph_string_new ();
858 PangoEngineShape *shaper, *last_shaper;
859 PangoAnalysis analysis;
864 g_return_if_fail (font != NULL);
865 g_return_if_fail (text != NULL);
867 private = (GdkFontPrivateFB*) font;
869 utf8 = alloca (text_length*2);
871 /* Convert latin-1 to utf8 */
873 for (i = 0; i < text_length; i++)
876 *p++ = 1; /* Hack to handle embedded nulls */
879 if(((guchar)text[i])<128)
883 *p++ = ((((guchar)text[i])>>6) & 0x3f) | 0xC0;
884 *p++ = (((guchar)text[i]) & 0x3f) | 0x80;
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)
902 analysis.shape_engine = shaper;
903 analysis.lang_engine = NULL;
904 analysis.font = private->pango_font;
907 pango_shape (start, p - start, &analysis, glyphs);
909 gdk_fb_draw_glyphs (drawable, gc, private->pango_font,
910 x + PANGO_PIXELS (x_offset), y,
913 for (i = 0; i < glyphs->num_glyphs; i++)
914 x_offset += glyphs->glyphs[i].geometry.width;
919 last_shaper = shaper;
924 analysis.shape_engine = shaper;
925 analysis.lang_engine = NULL;
926 analysis.font = private->pango_font;
929 pango_shape (start, p - start, &analysis, glyphs);
931 gdk_fb_draw_glyphs (drawable, gc, private->pango_font,
932 x + PANGO_PIXELS (x_offset), y,
936 pango_glyph_string_free (glyphs);
943 gdk_fb_draw_text(GdkDrawable *drawable,
951 g_warning ("gdk_fb_draw_text NYI");
956 gdk_fb_draw_text_wc (GdkDrawable *drawable,
961 const GdkWChar *text,
964 g_warning ("gdk_fb_draw_text_wc NYI");
968 gdk_fb_draw_rectangle (GdkDrawable *drawable,
976 GdkDrawableFBData *private;
978 private = GDK_DRAWABLE_FBDATA (drawable);
982 gboolean handle_cursor = FALSE;
983 GdkRectangle tmprect;
985 GdkRegion *real_clip_region;
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;
994 gdk_color_black (private->colormap, &color);
996 real_clip_region = gdk_fb_clip_region (drawable, gc, TRUE, GDK_GC_FBDATA (gc)->values.function != GDK_INVERT, TRUE);
998 if (private->mem == GDK_DRAWABLE_IMPL_FBDATA (_gdk_parent_root)->mem &&
999 gdk_fb_cursor_region_need_hide (real_clip_region))
1001 handle_cursor = TRUE;
1002 gdk_fb_cursor_hide ();
1005 x += private->abs_x;
1006 y += private->abs_y;
1008 if (x < private->llim_x)
1010 width -= private->llim_x - x;
1011 x = private->llim_x;
1013 if (x + width > private->lim_x)
1014 width = private->lim_x - x;
1016 if (y < private->llim_y)
1018 height -= private->llim_y - y;
1019 y = private->llim_y;
1021 if (y + height > private->lim_y)
1022 height = private->lim_y - y;
1026 tmprect.width = width;
1027 tmprect.height = height;
1028 tmpreg = gdk_region_rectangle (&tmprect);
1030 gdk_region_intersect (tmpreg, real_clip_region);
1032 for (i = 0; i < tmpreg->numRects; i++)
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;
1040 if ((r.width > 0) && (r.height > 0))
1041 (GDK_GC_FBDATA (gc)->fill_rectangle) (drawable, gc, &r, &color);
1044 gdk_region_destroy (tmpreg);
1046 gdk_region_destroy (real_clip_region);
1048 gdk_fb_cursor_unhide ();
1054 pts[0].x = pts[4].x = x;
1055 pts[0].y = pts[4].y = y;
1056 pts[1].x = x + width;
1058 pts[2].x = x + width;
1059 pts[2].y = y + height;
1061 pts[3].y = y + height;
1062 gdk_fb_draw_lines (drawable, gc, pts, 5);
1068 gdk_fb_draw_points (GdkDrawable *drawable,
1073 GdkSpan *spans = g_alloca (npoints * sizeof(GdkSpan));
1076 for (i = 0; i < npoints; i++)
1078 spans[i].x = points[i].x;
1079 spans[i].y = points[i].y;
1083 gdk_fb_fill_spans (drawable, gc, spans, npoints, FALSE);
1087 gdk_fb_draw_arc (GdkDrawable *drawable,
1102 arc.height = height;
1103 arc.angle1 = angle1;
1104 arc.angle2 = angle2;
1107 miPolyFillArc (drawable, gc, 1, &arc);
1109 miPolyArc (drawable, gc, 1, &arc);
1113 gdk_fb_draw_polygon (GdkDrawable *drawable,
1120 miFillPolygon (drawable, gc, 0, 0, npoints, points);
1124 gboolean free_points = FALSE;
1125 GdkPoint *tmp_points;
1127 if (points[0].x != points[npoints-1].x || points[0].y != points[npoints-1].y)
1129 tmp_npoints = npoints + 1;
1130 tmp_points = g_new (GdkPoint, tmp_npoints);
1132 memcpy (tmp_points, points, sizeof(GdkPoint) * npoints);
1133 tmp_points[npoints].x = points[0].x;
1134 tmp_points[npoints].y = points[0].y;
1138 tmp_npoints = npoints;
1139 tmp_points = points;
1142 gdk_fb_draw_lines (drawable, gc, tmp_points, tmp_npoints);
1145 g_free (tmp_points);
1150 gdk_fb_draw_lines (GdkDrawable *drawable,
1155 GdkGCFBData *private;
1157 private = GDK_GC_FBDATA (gc);
1158 if (private->values.line_width > 0)
1160 if ((private->values.line_style != GDK_LINE_SOLID) && private->dash_list)
1161 miWideDash (drawable, gc, 0, npoints, points);
1163 miWideLine (drawable, gc, 0, npoints, points);
1167 if ((private->values.line_style != GDK_LINE_SOLID) && private->dash_list)
1168 miZeroDashLine (drawable, gc, 0, npoints, points);
1170 miZeroLine (drawable, gc, 0, npoints, points);
1175 gdk_fb_draw_segments (GdkDrawable *drawable,
1183 for(i = 0; i < nsegs; i++)
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;
1190 gdk_fb_draw_lines (drawable, gc, pts, 2);
1195 gdk_fb_drawable_clear (GdkDrawable *d)
1198 _gdk_windowing_window_clear_area (GdkWindow *window,
1204 _gdk_windowing_window_clear_area (d, 0, 0, GDK_DRAWABLE_IMPL_FBDATA (d)->width, GDK_DRAWABLE_IMPL_FBDATA (d)->height);
1208 _gdk_fb_draw_glyphs (GdkDrawable *drawable,
1213 PangoGlyphString *glyphs,
1216 GdkFBDrawingContext fbdc;
1217 GdkPixmapFBData pixmap;
1220 FT_UInt glyph_index;
1225 g_return_if_fail (font);
1227 gdk_fb_drawing_context_init (&fbdc, drawable, gc, FALSE, TRUE);
1229 /* Fake its existence as a pixmap */
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;
1238 gi = glyphs->glyphs;
1239 for (i = 0, xpos = 0; i < glyphs->num_glyphs; i++, gi++)
1243 glyph_index = gi->glyph;
1244 face = pango_ft2_font_get_face (font);
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);
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;
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,
1264 x + PANGO_PIXELS (xpos) + face->glyph->bitmap_left,
1266 face->glyph->bitmap.width, face->glyph->bitmap.rows);
1269 xpos += glyphs->glyphs[i].geometry.width;
1272 gdk_fb_drawing_context_finalize (&fbdc);
1279 bbox->height = maxy - miny;
1284 gdk_fb_draw_glyphs (GdkDrawable *drawable,
1289 PangoGlyphString *glyphs)
1291 _gdk_fb_draw_glyphs (drawable, gc, font, x, y, glyphs, NULL);
1295 gdk_fb_draw_image (GdkDrawable *drawable,
1305 GdkImagePrivateFB *image_private;
1306 GdkPixmapFBData fbd;
1308 g_return_if_fail (drawable != NULL);
1309 g_return_if_fail (image != NULL);
1310 g_return_if_fail (gc != NULL);
1312 image_private = (GdkImagePrivateFB*) image;
1314 g_return_if_fail (image->type == GDK_IMAGE_NORMAL);
1316 /* Fake its existence as a pixmap */
1317 memset (&fbd, 0, sizeof(fbd));
1319 ((GTypeInstance *)&fbd)->g_class = g_type_class_peek (_gdk_pixmap_impl_get_type ());
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 ();
1329 gdk_fb_draw_drawable_2 (drawable, gc, (GdkPixmap *)&fbd, xsrc, ysrc, xdest, ydest, width, height, TRUE, TRUE);
1333 gdk_fb_get_depth (GdkDrawable *drawable)
1335 return GDK_DRAWABLE_FBDATA (drawable)->depth;
1339 gdk_fb_get_screen (GdkDrawable *drawable)
1341 return gdk_screen_get_default();
1345 gdk_fb_get_visual (GdkDrawable *drawable)
1347 return gdk_visual_get_system();
1350 #ifdef ENABLE_SHADOW_FB
1352 gdk_shadow_fb_draw_rectangle (GdkDrawable *drawable,
1360 GdkDrawableFBData *private;
1362 gdk_fb_draw_rectangle (drawable, gc, filled, x, y, width, height);
1364 private = GDK_DRAWABLE_FBDATA (drawable);
1365 if (GDK_IS_WINDOW (private->wrapper))
1367 gint minx, miny, maxx, maxy;
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;
1377 extra_width = (GDK_GC_FBDATA (gc)->values.line_width + 1) / 2;
1379 minx -= extra_width;
1380 miny -= extra_width;
1381 maxx += extra_width;
1382 maxy += extra_width;
1384 gdk_shadow_fb_update (minx, miny, maxx, maxy);
1389 gdk_shadow_fb_draw_arc (GdkDrawable *drawable,
1399 GdkDrawableFBData *private;
1401 gdk_fb_draw_arc (drawable, gc, filled, x, y, width, height, angle1, angle2);
1403 private = GDK_DRAWABLE_FBDATA (drawable);
1404 if (GDK_IS_WINDOW (private->wrapper))
1406 gint minx, miny, maxx, maxy;
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;
1416 extra_width = (GDK_GC_FBDATA (gc)->values.line_width + 1) / 2;
1418 minx -= extra_width;
1419 miny -= extra_width;
1420 maxx += extra_width;
1421 maxy += extra_width;
1423 gdk_shadow_fb_update (minx, miny, maxx, maxy);
1428 gdk_shadow_fb_draw_polygon (GdkDrawable *drawable,
1434 GdkDrawableFBData *private;
1436 gdk_fb_draw_polygon (drawable, gc, filled, points, npoints);
1438 private = GDK_DRAWABLE_FBDATA (drawable);
1439 if (GDK_IS_WINDOW (private->wrapper))
1441 gint minx, miny, maxx, maxy;
1445 minx = maxx = points[0].x;
1446 miny = maxy = points[0].y;
1448 for (i = 1; i < npoints; i++)
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);
1458 extra_width = (GDK_GC_FBDATA (gc)->values.line_width + 1) / 2;
1460 minx -= extra_width;
1461 miny -= extra_width;
1462 maxx += extra_width;
1463 maxy += extra_width;
1465 gdk_shadow_fb_update (minx + private->abs_x, miny + private->abs_y,
1466 maxx + private->abs_x, maxy + private->abs_y);
1471 gdk_shadow_fb_draw_text (GdkDrawable *drawable,
1479 gdk_fb_draw_text (drawable, font, gc, x, y, text, text_length);
1483 gdk_shadow_fb_draw_text_wc (GdkDrawable *drawable,
1488 const GdkWChar *text,
1491 gdk_fb_draw_text_wc (drawable, font, gc, x, y, text, text_length);
1495 gdk_shadow_fb_draw_glyphs (GdkDrawable *drawable,
1500 PangoGlyphString *glyphs)
1502 GdkDrawableFBData *private;
1505 _gdk_fb_draw_glyphs (drawable, gc, font, x, y, glyphs, &bbox);
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);
1514 gdk_shadow_fb_draw_drawable (GdkDrawable *drawable,
1524 GdkDrawableFBData *private;
1526 gdk_fb_draw_drawable (drawable, gc, src, xsrc, ysrc, xdest, ydest, width, height);
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);
1535 gdk_shadow_fb_draw_image (GdkDrawable *drawable,
1545 GdkDrawableFBData *private;
1547 gdk_fb_draw_image (drawable, gc, image, xsrc, ysrc, xdest, ydest, width, height);
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);
1556 gdk_shadow_fb_draw_points (GdkDrawable *drawable,
1561 GdkDrawableFBData *private;
1563 gdk_fb_draw_points (drawable, gc, points, npoints);
1565 private = GDK_DRAWABLE_FBDATA (drawable);
1566 if (GDK_IS_WINDOW (private->wrapper))
1568 gint minx, miny, maxx, maxy;
1571 minx = maxx = points[0].x;
1572 miny = maxy = points[0].y;
1574 for (i = 1; i < npoints; i++)
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);
1582 gdk_shadow_fb_update (minx + private->abs_x, miny + private->abs_y,
1583 maxx + private->abs_x, maxy + private->abs_y);
1588 gdk_shadow_fb_draw_segments (GdkDrawable *drawable,
1593 GdkDrawableFBData *private;
1595 gdk_fb_draw_segments (drawable, gc, segs, nsegs);
1597 private = GDK_DRAWABLE_FBDATA (drawable);
1598 if (GDK_IS_WINDOW (private->wrapper))
1600 gint minx, miny, maxx, maxy;
1604 minx = maxx = segs[0].x1;
1605 miny = maxy = segs[0].y1;
1607 for (i = 0; i < nsegs; i++)
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);
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);
1621 extra_width = (GDK_GC_FBDATA (gc)->values.line_width + 1) / 2;
1623 minx -= extra_width;
1624 miny -= extra_width;
1625 maxx += extra_width;
1626 maxy += extra_width;
1628 gdk_shadow_fb_update (minx + private->abs_x, miny + private->abs_y,
1629 maxx + private->abs_x, maxy + private->abs_y);
1634 gdk_shadow_fb_draw_lines (GdkDrawable *drawable,
1639 GdkDrawableFBData *private;
1641 gdk_fb_draw_lines (drawable, gc, points, npoints);
1643 private = GDK_DRAWABLE_FBDATA (drawable);
1644 if (GDK_IS_WINDOW (private->wrapper))
1646 gint minx, miny, maxx, maxy;
1650 minx = maxx = points[0].x;
1651 miny = maxy = points[0].y;
1653 for (i = 1; i < npoints; i++)
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);
1661 extra_width = (GDK_GC_FBDATA (gc)->values.line_width + 1) / 2;
1663 minx -= extra_width;
1664 miny -= extra_width;
1665 maxx += extra_width;
1666 maxy += extra_width;
1668 gdk_shadow_fb_update (minx + private->abs_x, miny + private->abs_y,
1669 maxx + private->abs_x, maxy + private->abs_y);
1676 gdk_draw_rectangle_alpha_libgtk_only (GdkDrawable *drawable,