Re: [gtk-list] Re: clip origin, and **clip mask origion** ??



>I'm amazed with what I've created so far using GTK considering my lack of
>fundamental understanding. I don't know what a GC actually is although
>I've used them quite a bit. I don't know how to create a GC with a depth
>of 2.

Get and read Adrian Nye's book "the Xlib Programming Manual". Its
vital for anyone wanting to do "unusual" things with X, although from
what I've learned on this list, its a little outdated in some areas,
particularly where hardware capabilities are relevant. It has a very
good explanation of GC's and drawing operation that I found
invaluable. 

I've only been doing this for a couple of months :)

>And if I don't have the mask yet doesn't it make sense that when I draw
>the mask that it will copy a square because in order to copy we need to
>already have the mask?

Nope. If your original pixmap had the color "None" for its transparent
areas, then when it is drawn into a bitmap, those areas will remain
undrawn (i.e. they will retain their background pixel value). So the
final bitmap will be exactly what you want from a mask: pixels set to
1 where the mask should "include" any pixmap pixels, and 0 everywhere
else. Note that the one/zero thing is H/W dependent; see the code
below for how I dealt with this.

>I'm trying to implement your suggesting and getting this error:
>
>Gdk-ERROR **: BadMatch (invalid parameter attributes)
>  serial 2192 error_code 8 request_code 62 minor_code 0
>
>I don't know how to make a GC of 2, that might be the problem.

Once again, rapid typing/weak thinking has led me to be
misleading. lets just go with the source ...

Here's part of the code that implements my GtkTransparency
widget. I've added few more comments than were in the original.

This widget comes with a set of replacements for the
gtk_draw_*() functions that result in the window being opaque *only
where a drawing operation has taken place*. 

Its realize() function contains code that creates a GC of depth 1,
creates a bitmap that will function as the mask for the window in
shape_combine_mask() operations, and more. 

Each drawing operation draws first into the bitmap (mask), and then
into the actual pixmap. These two draws are done with different
GC's. 

When we finally call gtk_transparency_project() (not shown), we do a
shape_combine_mask() using the current state of the mask, and this
gives us the desired result.

The function gtk_transparency_wipe() clears the mask to all zeroes,
causing the window to become completely transparent whenever it is redrawn.

This should hopefully offer a few more clues :)

Note that from what Havoc said, we could really use gtk_bitmap_new()
for the mask; I used gtk_pixmap_new() because under the hood, there is
no difference between the two for my purposes. I think. Heh, heh.

--p

/* This file is intended to be part of GTK - The GIMP Toolkit
 * Copyright (C) 1999 Paul Barton-Davis
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */

.
.
.
.

static void
gtk_transparency_realize (GtkWidget *w)
{
  GtkTransparency *tarea;
  GdkWindowAttr attributes;
  gchar *clear_data;
  GdkColor zero;
  GdkColor one;

  gint attributes_mask;

  g_return_if_fail (w != NULL);
  g_return_if_fail (GTK_IS_TRANSPARENCY (w));

  tarea = GTK_TRANSPARENCY (w);
  GTK_WIDGET_SET_FLAGS (w, GTK_REALIZED);

  attributes.window_type = GDK_WINDOW_CHILD;
  attributes.x = w->allocation.x;
  attributes.y = w->allocation.y;
  attributes.width = w->allocation.width;
  attributes.height = w->allocation.height;
  attributes.wclass = GDK_INPUT_OUTPUT;
  attributes.visual = gtk_widget_get_visual (w);
  attributes.colormap = gtk_widget_get_colormap (w);
  attributes.event_mask = gtk_widget_get_events (w) | GDK_EXPOSURE_MASK;

  attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;

  /* This is the window where everything will happen */

  w->window = gdk_window_new (gtk_widget_get_parent_window (w),
				   &attributes, attributes_mask);

  /* this is the pixmap where we do all real drawing operations,
     and it functions as a buffer until we call gtk_transparency_project().
  */

  tarea->buffer = gdk_pixmap_new (w->window,
				  w->allocation.width,
				  w->allocation.height, -1);
 
  /* this is the mask. we will duplicate everything drawn into the
     buffer pixmap here, but we will use a GC that creates a bitmap
     for use as a mask. this GC will cause the foreground bits to be
     set to one, and background to zero, which is the attribute we
     want for a mask.
  */

  tarea->mask  = gdk_pixmap_new  (w->window,
				  w->allocation.width,
				  w->allocation.height, 1);

  /* create a GC for bitmap (depth=1) operations */

  gdk_color_black (gdk_colormap_get_system (), &zero);

  if (zero.pixel != 0) {
      gdk_color_white (gdk_colormap_get_system(), &zero);
      gdk_color_black (gdk_colormap_get_system(), &one);
  } else {
      gdk_color_white (gdk_colormap_get_system(), &one);
  }

  
  tarea->bitmap_gc = gdk_gc_new (tarea->mask);
  gdk_gc_set_foreground (tarea->bitmap_gc, &one);
  gdk_gc_set_background (tarea->bitmap_gc, &zero);

  /* Create a clear bitmap for use in wiping the mask bitmap 
     
     There are better ways of doing this, but I haven't gotten
     around to implementing them yet. XDrawRectangle is it ....
   */

  clear_data = (gchar *) g_malloc (w->allocation.width * w->allocation.height);
  memset (clear_data, 0, w->allocation.width * w->allocation.height);
  tarea->clearmask = gdk_pixmap_create_from_data (w->window,
						  clear_data,
						  w->allocation.width,
						  w->allocation.height,
						  1, 
						  &one,
						  &zero);

  /* use it to clear the mask */

  gdk_window_copy_area (tarea->mask,
			tarea->bitmap_gc,
			0, 0,
			tarea->clearmask,
			0, 0,
			w->allocation.width,
			w->allocation.height);

  /* do an initial shaping of the window, which is going to 
     make it completely transparent, since we just cleared the
     mask to zero.
  */

  gdk_window_shape_combine_mask (w->window, tarea->mask, 0, 0);
  g_free (clear_data);

  gdk_window_set_user_data (w->window, tarea);

  w->style = gtk_style_attach (w->style, w->window);

  gtk_transparency_send_configure (GTK_TRANSPARENCY (w));
}


void
gtk_transparency_project (GtkTransparency *tarea)

{
    GtkWidget *w = GTK_WIDGET(tarea);

    /* Reshape the window */

    gdk_window_shape_combine_mask (w->window, tarea->mask, 0, 0);

    /* flush the current pixmap into the window */

    gdk_draw_pixmap (w->window, w->style->fg_gc[GTK_STATE_NORMAL],
		     tarea->buffer, 0, 0, 0, 0, 
		     w->allocation.width, w->allocation.height);
}

void
gtk_transparency_wipe (GtkTransparency *tarea)

{
    GtkWidget *w = GTK_WIDGET(tarea);

    /* this just copies the clear bitmap to the mask bitmap,
       thus making the entire window transparent.
    */

    gdk_window_copy_area (tarea->mask,
			  tarea->bitmap_gc,
			  0, 0,
			  tarea->clearmask,
			  0, 0,
			  w->allocation.width,
			  w->allocation.height);
}

.
.
.
.

/* Drawing Functions */

#define CHECK_GC(t,gc) \
    if (gc == NULL) { \
       gc = GTK_WIDGET(t)->style->fg_gc[GTK_WIDGET_STATE(GTK_WIDGET(t))];\
    }

void 
gtk_transparency_draw_rectangle	 (GtkTransparency  *tarea,
				  GdkGC	       *gc,
				  gint		filled,
				  gint		x,
				  gint		y,
				  gint		width,
				  gint		height)

{
    CHECK_GC(tarea,gc);
    gdk_draw_rectangle (tarea->mask, tarea->bitmap_gc, 
			filled, x, y, width, height);
    gdk_draw_rectangle (tarea->buffer, gc, filled, x, y, width, height);
}


void gtk_transparency_draw_point	    (GtkTransparency  *tarea,
				     GdkGC	       *gc,
				     gint		x,
				     gint		y)

{
        CHECK_GC(tarea,gc);
	gdk_draw_point (tarea->mask, tarea->bitmap_gc, x, y);
	gdk_draw_point (tarea->buffer, gc, x, y);
}

void gtk_transparency_draw_line	    (GtkTransparency  *tarea,
				     GdkGC	       *gc,
				     gint		x1,
				     gint		y1,
				     gint		x2,
				     gint		y2)

{
        CHECK_GC(tarea,gc);
	gdk_draw_line (tarea->mask, tarea->bitmap_gc, x1, y1, x2, y2);
	gdk_draw_line (tarea->buffer, gc, x1, y1, x2, y2);
}
.
.
. 
  [ etc for all gtk_draw_* operations ]

.
.
.
.

void       
gtk_transparency_set_mask_gc (GtkTransparency *tarea,
			      GdkGCValues     *values,
			      gint             values_mask)

{
	gdk_gc_change_values (tarea->bitmap_gc,
			      values, 
			      values_mask);
}



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]