1 /* GDK - The GIMP Drawing Kit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
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/.
27 #include "gdkprivate-x11.h"
28 #include "gdkregion-generic.h"
30 #include <pango/pangox.h>
34 #include <pango/pangoxft.h>
39 #if defined (HAVE_IPC_H) && defined (HAVE_SHM_H) && defined (HAVE_XSHM_H)
44 #include <X11/extensions/XShm.h>
47 #include "gdkprivate-x11.h"
48 #include "gdkdrawable-x11.h"
49 #include "gdkpixmap-x11.h"
51 static void gdk_x11_draw_rectangle (GdkDrawable *drawable,
58 static void gdk_x11_draw_arc (GdkDrawable *drawable,
67 static void gdk_x11_draw_polygon (GdkDrawable *drawable,
72 static void gdk_x11_draw_text (GdkDrawable *drawable,
79 static void gdk_x11_draw_text_wc (GdkDrawable *drawable,
86 static void gdk_x11_draw_drawable (GdkDrawable *drawable,
95 static void gdk_x11_draw_points (GdkDrawable *drawable,
99 static void gdk_x11_draw_segments (GdkDrawable *drawable,
103 static void gdk_x11_draw_lines (GdkDrawable *drawable,
107 static void gdk_x11_draw_glyphs (GdkDrawable *drawable,
112 PangoGlyphString *glyphs);
113 static void gdk_x11_draw_image (GdkDrawable *drawable,
123 static void gdk_x11_set_colormap (GdkDrawable *drawable,
124 GdkColormap *colormap);
126 static GdkColormap* gdk_x11_get_colormap (GdkDrawable *drawable);
128 static gint gdk_x11_get_depth (GdkDrawable *drawable);
130 static GdkVisual* gdk_x11_get_visual (GdkDrawable *drawable);
132 static void gdk_drawable_impl_x11_class_init (GdkDrawableImplX11Class *klass);
134 static gpointer parent_class = NULL;
137 gdk_drawable_impl_x11_get_type (void)
139 static GType object_type = 0;
143 static const GTypeInfo object_info =
145 sizeof (GdkDrawableImplX11Class),
146 (GBaseInitFunc) NULL,
147 (GBaseFinalizeFunc) NULL,
148 (GClassInitFunc) gdk_drawable_impl_x11_class_init,
149 NULL, /* class_finalize */
150 NULL, /* class_data */
151 sizeof (GdkDrawableImplX11),
153 (GInstanceInitFunc) NULL,
156 object_type = g_type_register_static (GDK_TYPE_DRAWABLE,
157 "GdkDrawableImplX11",
165 gdk_drawable_impl_x11_class_init (GdkDrawableImplX11Class *klass)
167 GdkDrawableClass *drawable_class = GDK_DRAWABLE_CLASS (klass);
169 parent_class = g_type_class_peek_parent (klass);
171 drawable_class->create_gc = _gdk_x11_gc_new;
172 drawable_class->draw_rectangle = gdk_x11_draw_rectangle;
173 drawable_class->draw_arc = gdk_x11_draw_arc;
174 drawable_class->draw_polygon = gdk_x11_draw_polygon;
175 drawable_class->draw_text = gdk_x11_draw_text;
176 drawable_class->draw_text_wc = gdk_x11_draw_text_wc;
177 drawable_class->draw_drawable = gdk_x11_draw_drawable;
178 drawable_class->draw_points = gdk_x11_draw_points;
179 drawable_class->draw_segments = gdk_x11_draw_segments;
180 drawable_class->draw_lines = gdk_x11_draw_lines;
181 drawable_class->draw_glyphs = gdk_x11_draw_glyphs;
182 drawable_class->draw_image = gdk_x11_draw_image;
184 drawable_class->set_colormap = gdk_x11_set_colormap;
185 drawable_class->get_colormap = gdk_x11_get_colormap;
187 drawable_class->get_depth = gdk_x11_get_depth;
188 drawable_class->get_visual = gdk_x11_get_visual;
190 drawable_class->get_image = _gdk_x11_get_image;
193 /*****************************************************
194 * X11 specific implementations of generic functions *
195 *****************************************************/
198 gdk_x11_get_colormap (GdkDrawable *drawable)
200 GdkDrawableImplX11 *impl;
202 impl = GDK_DRAWABLE_IMPL_X11 (drawable);
204 return impl->colormap;
208 gdk_x11_set_colormap (GdkDrawable *drawable,
209 GdkColormap *colormap)
211 GdkDrawableImplX11 *impl;
213 g_return_if_fail (colormap != NULL);
215 impl = GDK_DRAWABLE_IMPL_X11 (drawable);
217 if (impl->colormap == colormap)
221 gdk_colormap_unref (impl->colormap);
222 impl->colormap = colormap;
224 gdk_colormap_ref (impl->colormap);
231 gdk_x11_draw_rectangle (GdkDrawable *drawable,
239 GdkDrawableImplX11 *impl;
241 impl = GDK_DRAWABLE_IMPL_X11 (drawable);
244 XFillRectangle (impl->xdisplay, impl->xid,
245 GDK_GC_GET_XGC (gc), x, y, width, height);
247 XDrawRectangle (impl->xdisplay, impl->xid,
248 GDK_GC_GET_XGC (gc), x, y, width, height);
252 gdk_x11_draw_arc (GdkDrawable *drawable,
262 GdkDrawableImplX11 *impl;
264 impl = GDK_DRAWABLE_IMPL_X11 (drawable);
268 XFillArc (impl->xdisplay, impl->xid,
269 GDK_GC_GET_XGC (gc), x, y, width, height, angle1, angle2);
271 XDrawArc (impl->xdisplay, impl->xid,
272 GDK_GC_GET_XGC (gc), x, y, width, height, angle1, angle2);
276 gdk_x11_draw_polygon (GdkDrawable *drawable,
284 GdkDrawableImplX11 *impl;
286 impl = GDK_DRAWABLE_IMPL_X11 (drawable);
290 (points[0].x != points[npoints-1].x || points[0].y != points[npoints-1].y))
292 tmp_npoints = npoints + 1;
293 tmp_points = g_new (XPoint, tmp_npoints);
294 tmp_points[npoints].x = points[0].x;
295 tmp_points[npoints].y = points[0].y;
299 tmp_npoints = npoints;
300 tmp_points = g_new (XPoint, tmp_npoints);
303 for (i=0; i<npoints; i++)
305 tmp_points[i].x = points[i].x;
306 tmp_points[i].y = points[i].y;
310 XFillPolygon (impl->xdisplay, impl->xid,
311 GDK_GC_GET_XGC (gc), tmp_points, tmp_npoints, Complex, CoordModeOrigin);
313 XDrawLines (impl->xdisplay, impl->xid,
314 GDK_GC_GET_XGC (gc), tmp_points, tmp_npoints, CoordModeOrigin);
321 * Modified by Li-Da Lho to draw 16 bits and Multibyte strings
323 * Interface changed: add "GdkFont *font" to specify font or fontset explicitely
326 gdk_x11_draw_text (GdkDrawable *drawable,
334 GdkDrawableImplX11 *impl;
336 impl = GDK_DRAWABLE_IMPL_X11 (drawable);
338 if (font->type == GDK_FONT_FONT)
340 XFontStruct *xfont = (XFontStruct *) GDK_FONT_XFONT (font);
341 XSetFont(impl->xdisplay, GDK_GC_GET_XGC (gc), xfont->fid);
342 if ((xfont->min_byte1 == 0) && (xfont->max_byte1 == 0))
344 XDrawString (impl->xdisplay, impl->xid,
345 GDK_GC_GET_XGC (gc), x, y, text, text_length);
349 XDrawString16 (impl->xdisplay, impl->xid,
350 GDK_GC_GET_XGC (gc), x, y, (XChar2b *) text, text_length / 2);
353 else if (font->type == GDK_FONT_FONTSET)
355 XFontSet fontset = (XFontSet) GDK_FONT_XFONT (font);
356 XmbDrawString (impl->xdisplay, impl->xid,
357 fontset, GDK_GC_GET_XGC (gc), x, y, text, text_length);
360 g_error("undefined font type\n");
364 gdk_x11_draw_text_wc (GdkDrawable *drawable,
369 const GdkWChar *text,
372 GdkDrawableImplX11 *impl;
374 impl = GDK_DRAWABLE_IMPL_X11 (drawable);
376 if (font->type == GDK_FONT_FONT)
378 XFontStruct *xfont = (XFontStruct *) GDK_FONT_XFONT (font);
381 XSetFont(impl->xdisplay, GDK_GC_GET_XGC (gc), xfont->fid);
382 text_8bit = g_new (gchar, text_length);
383 for (i=0; i<text_length; i++) text_8bit[i] = text[i];
384 XDrawString (impl->xdisplay, impl->xid,
385 GDK_GC_GET_XGC (gc), x, y, text_8bit, text_length);
388 else if (font->type == GDK_FONT_FONTSET)
390 if (sizeof(GdkWChar) == sizeof(wchar_t))
392 XwcDrawString (impl->xdisplay, impl->xid,
393 (XFontSet) GDK_FONT_XFONT (font),
394 GDK_GC_GET_XGC (gc), x, y, (wchar_t *)text, text_length);
400 text_wchar = g_new (wchar_t, text_length);
401 for (i=0; i<text_length; i++) text_wchar[i] = text[i];
402 XwcDrawString (impl->xdisplay, impl->xid,
403 (XFontSet) GDK_FONT_XFONT (font),
404 GDK_GC_GET_XGC (gc), x, y, text_wchar, text_length);
409 g_error("undefined font type\n");
413 gdk_x11_draw_drawable (GdkDrawable *drawable,
423 int src_depth = gdk_drawable_get_depth (src);
424 int dest_depth = gdk_drawable_get_depth (drawable);
425 GdkDrawableImplX11 *impl;
426 GdkDrawableImplX11 *src_impl;
428 impl = GDK_DRAWABLE_IMPL_X11 (drawable);
430 if (GDK_IS_DRAWABLE_IMPL_X11 (src))
431 src_impl = GDK_DRAWABLE_IMPL_X11 (src);
437 XCopyArea (impl->xdisplay,
438 src_impl ? src_impl->xid : GDK_DRAWABLE_XID (src),
445 else if (dest_depth != 0 && src_depth == dest_depth)
447 XCopyArea (impl->xdisplay,
448 src_impl ? src_impl->xid : GDK_DRAWABLE_XID (src),
456 g_warning ("Attempt to draw a drawable with depth %d to a drawable with depth %d",
457 src_depth, dest_depth);
461 gdk_x11_draw_points (GdkDrawable *drawable,
466 GdkDrawableImplX11 *impl;
468 impl = GDK_DRAWABLE_IMPL_X11 (drawable);
471 /* We special-case npoints == 1, because X will merge multiple
472 * consecutive XDrawPoint requests into a PolyPoint request
476 XDrawPoint (impl->xdisplay,
479 points[0].x, points[0].y);
484 XPoint *tmp_points = g_new (XPoint, npoints);
486 for (i=0; i<npoints; i++)
488 tmp_points[i].x = points[i].x;
489 tmp_points[i].y = points[i].y;
492 XDrawPoints (impl->xdisplay,
504 gdk_x11_draw_segments (GdkDrawable *drawable,
509 GdkDrawableImplX11 *impl;
511 impl = GDK_DRAWABLE_IMPL_X11 (drawable);
514 /* We special-case nsegs == 1, because X will merge multiple
515 * consecutive XDrawLine requests into a PolySegment request
519 XDrawLine (impl->xdisplay, impl->xid,
520 GDK_GC_GET_XGC (gc), segs[0].x1, segs[0].y1,
521 segs[0].x2, segs[0].y2);
526 XSegment *tmp_segs = g_new (XSegment, nsegs);
528 for (i=0; i<nsegs; i++)
530 tmp_segs[i].x1 = segs[i].x1;
531 tmp_segs[i].x2 = segs[i].x2;
532 tmp_segs[i].y1 = segs[i].y1;
533 tmp_segs[i].y2 = segs[i].y2;
536 XDrawSegments (impl->xdisplay,
546 gdk_x11_draw_lines (GdkDrawable *drawable,
552 XPoint *tmp_points = g_new (XPoint, npoints);
553 GdkDrawableImplX11 *impl;
555 impl = GDK_DRAWABLE_IMPL_X11 (drawable);
558 for (i=0; i<npoints; i++)
560 tmp_points[i].x = points[i].x;
561 tmp_points[i].y = points[i].y;
564 XDrawLines (impl->xdisplay,
575 update_xft_draw_clip (GdkGC *gc)
577 GdkGCX11 *private = GDK_GC_X11 (gc);
580 if (private->xft_draw)
582 if (private->clip_region)
584 GdkRegionBox *boxes = private->clip_region->rects;
585 Region region = XCreateRegion ();
587 for (i=0; i<private->clip_region->numRects; i++)
591 rect.x = CLAMP (boxes[i].x1 + gc->clip_x_origin, G_MINSHORT, G_MAXSHORT);
592 rect.y = CLAMP (boxes[i].y1 + gc->clip_y_origin, G_MINSHORT, G_MAXSHORT);
593 rect.width = CLAMP (boxes[i].x2 + gc->clip_x_origin, G_MINSHORT, G_MAXSHORT) - rect.x;
594 rect.height = CLAMP (boxes[i].y2 + gc->clip_y_origin, G_MINSHORT, G_MAXSHORT) - rect.y;
595 XUnionRectWithRegion (&rect, region, region);
598 XftDrawSetClip (private->xft_draw, region);
599 XDestroyRegion (region);
602 XftDrawSetClip (private->xft_draw, NULL);
608 gdk_x11_draw_glyphs (GdkDrawable *drawable,
613 PangoGlyphString *glyphs)
615 GdkDrawableImplX11 *impl;
617 impl = GDK_DRAWABLE_IMPL_X11 (drawable);
620 if (PANGO_XFT_IS_FONT (font))
622 GdkGCX11 *gc_x11 = GDK_GC_X11 (gc);
627 cmap = gdk_gc_get_colormap (gc);
629 _gdk_x11_gc_flush (gc);
631 if (!gc_x11->xft_draw)
633 gc_x11->xft_draw = XftDrawCreate (impl->xdisplay,
635 GDK_VISUAL_XVISUAL (gdk_colormap_get_visual (cmap)),
636 GDK_COLORMAP_XCOLORMAP (cmap));
637 update_xft_draw_clip (gc);
642 XftDrawChange (gc_x11->xft_draw, impl->xid);
643 update_xft_draw_clip (gc);
646 gdk_colormap_query_color (cmap, gc_x11->fg_pixel, &color);
648 xft_color.color.red = color.red;
649 xft_color.color.green = color.green;
650 xft_color.color.blue = color.blue;
651 xft_color.color.alpha = 0xffff;
653 pango_xft_render (gc_x11->xft_draw, &xft_color,
657 #endif /* !HAVE_XFT */
658 pango_x_render (impl->xdisplay,
665 gdk_x11_draw_image (GdkDrawable *drawable,
675 GdkDrawableImplX11 *impl;
677 impl = GDK_DRAWABLE_IMPL_X11 (drawable);
679 if (image->type == GDK_IMAGE_SHARED)
680 XShmPutImage (impl->xdisplay, impl->xid,
681 GDK_GC_GET_XGC (gc), GDK_IMAGE_XIMAGE (image),
682 xsrc, ysrc, xdest, ydest, width, height, False);
684 XPutImage (impl->xdisplay, impl->xid,
685 GDK_GC_GET_XGC (gc), GDK_IMAGE_XIMAGE (image),
686 xsrc, ysrc, xdest, ydest, width, height);
690 gdk_x11_get_depth (GdkDrawable *drawable)
692 /* This is a bit bogus but I'm not sure the other way is better */
694 return gdk_drawable_get_depth (GDK_DRAWABLE_IMPL_X11 (drawable)->wrapper);
698 gdk_x11_get_visual (GdkDrawable *drawable)
700 return gdk_drawable_get_visual (GDK_DRAWABLE_IMPL_X11 (drawable)->wrapper);