gdkgc.c 12.2 KB
Newer Older
Elliot Lee's avatar
Elliot Lee committed
1 2 3 4
/* GDK - The GIMP Drawing Kit
 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
 *
 * This library is free software; you can redistribute it and/or
5
 * modify it under the terms of the GNU Lesser General Public
Elliot Lee's avatar
Elliot Lee committed
6 7 8 9 10
 * 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
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
12
 * Lesser General Public License for more details.
Elliot Lee's avatar
Elliot Lee committed
13
 *
14
 * You should have received a copy of the GNU Lesser General Public
15 16 17
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
Elliot Lee's avatar
Elliot Lee committed
18
 */
19 20

/*
21
 * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
22 23 24 25 26
 * file for a list of people on the GTK+ Team.  See the ChangeLog
 * files for a list of changes.  These files are distributed with
 * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
 */

Elliot Lee's avatar
Elliot Lee committed
27
#include <string.h>
Owen Taylor's avatar
Started  
Owen Taylor committed
28 29

#include "gdkgc.h"
30
#include "gdkrgb.h"
Elliot Lee's avatar
Elliot Lee committed
31 32
#include "gdkprivate.h"

33 34 35
static void gdk_gc_class_init (GObjectClass *class);
static void gdk_gc_finalize   (GObject      *object);

36
static GObjectClass *parent_class;
37

38 39
GType
gdk_gc_get_type (void)
Elliot Lee's avatar
Elliot Lee committed
40
{
41 42 43 44 45 46 47 48 49
  static GType object_type = 0;

  if (!object_type)
    {
      static const GTypeInfo object_info =
      {
        sizeof (GdkGCClass),
        (GBaseInitFunc) NULL,
        (GBaseFinalizeFunc) NULL,
50
        (GClassInitFunc) gdk_gc_class_init,
51 52 53 54 55 56 57 58 59
        NULL,           /* class_finalize */
        NULL,           /* class_data */
        sizeof (GdkGC),
        0,              /* n_preallocs */
        (GInstanceInitFunc) NULL,
      };
      
      object_type = g_type_register_static (G_TYPE_OBJECT,
                                            "GdkGC",
60
                                            &object_info, 0);
61 62 63
    }
  
  return object_type;
Elliot Lee's avatar
Elliot Lee committed
64 65
}

66 67 68 69 70 71 72 73
static void
gdk_gc_class_init (GObjectClass *class)
{
  parent_class = g_type_class_peek_parent (class);
  
  class->finalize = gdk_gc_finalize;
}

Elliot Lee's avatar
Elliot Lee committed
74
GdkGC*
75
gdk_gc_new (GdkDrawable *drawable)
Elliot Lee's avatar
Elliot Lee committed
76
{
77
  g_return_val_if_fail (drawable != NULL, NULL);
78

79
  return gdk_gc_new_with_values (drawable, NULL, 0);
Elliot Lee's avatar
Elliot Lee committed
80 81
}

82 83 84 85
GdkGC*
gdk_gc_new_with_values (GdkDrawable	*drawable,
			GdkGCValues	*values,
			GdkGCValuesMask	 values_mask)
Elliot Lee's avatar
Elliot Lee committed
86
{
87 88
  GdkGC *gc;

89 90
  g_return_val_if_fail (drawable != NULL, NULL);

91 92 93
  gc = GDK_DRAWABLE_GET_CLASS (drawable)->create_gc (drawable,
                                                     values,
                                                     values_mask);
94

95 96
  if (gc == NULL) /* This would mean the drawable was destroyed. */
    return NULL;
97 98
  
  if (values_mask & GDK_GC_CLIP_X_ORIGIN)
99
    gc->clip_x_origin = values->clip_x_origin;
100
  if (values_mask & GDK_GC_CLIP_Y_ORIGIN)
101
    gc->clip_y_origin = values->clip_y_origin;
102
  if (values_mask & GDK_GC_TS_X_ORIGIN)
103
    gc->ts_x_origin = values->ts_x_origin;
104
  if (values_mask & GDK_GC_TS_Y_ORIGIN)
105
    gc->ts_y_origin = values->ts_y_origin;
106

107 108 109 110
  gc->colormap = gdk_drawable_get_colormap (drawable);
  if (gc->colormap)
    g_object_ref (G_OBJECT (gc->colormap));
  
111
  return gc;
112
}
Elliot Lee's avatar
Elliot Lee committed
113

114 115 116 117 118 119 120 121 122 123 124
static void
gdk_gc_finalize (GObject *object)
{
  GdkGC *gc = GDK_GC (object);
  
  if (gc->colormap)
    g_object_unref (G_OBJECT (gc->colormap));

  parent_class->finalize (object);
}

125 126 127
GdkGC *
gdk_gc_ref (GdkGC *gc)
{
128
  return (GdkGC *) g_object_ref (G_OBJECT (gc));
129
}
Elliot Lee's avatar
Elliot Lee committed
130

131 132 133
void
gdk_gc_unref (GdkGC *gc)
{
134
  g_object_unref (G_OBJECT (gc));
Elliot Lee's avatar
Elliot Lee committed
135 136 137 138 139 140
}

void
gdk_gc_get_values (GdkGC       *gc,
		   GdkGCValues *values)
{
141
  g_return_if_fail (GDK_IS_GC (gc));
142
  g_return_if_fail (values != NULL);
Elliot Lee's avatar
Elliot Lee committed
143

144
  GDK_GC_GET_CLASS (gc)->get_values (gc, values);
145 146
}

Havoc Pennington's avatar
Havoc Pennington committed
147 148 149 150 151 152 153 154 155 156 157 158 159
/**
 * gdk_gc_set_values:
 * @gc: a #GdkGC
 * @values: struct containing the new values
 * @values_mask: mask indicating which struct fields are to be used
 *
 * Sets attributes of a graphics context in bulk. For each flag set in
 * @values_mask, the corresponding field will be read from @values and
 * set as the new value for @gc. If you're only setting a few values
 * on @gc, calling individual "setter" functions is likely more
 * convenient.
 * 
 **/
160 161 162 163 164
void
gdk_gc_set_values (GdkGC           *gc,
		   GdkGCValues	   *values,
		   GdkGCValuesMask  values_mask)
{
165
  g_return_if_fail (GDK_IS_GC (gc));
Elliot Lee's avatar
Elliot Lee committed
166 167
  g_return_if_fail (values != NULL);

168
  if (values_mask & GDK_GC_CLIP_X_ORIGIN)
169
    gc->clip_x_origin = values->clip_x_origin;
170
  if (values_mask & GDK_GC_CLIP_Y_ORIGIN)
171
    gc->clip_y_origin = values->clip_y_origin;
172
  if (values_mask & GDK_GC_TS_X_ORIGIN)
173
    gc->ts_x_origin = values->ts_x_origin;
174
  if (values_mask & GDK_GC_TS_Y_ORIGIN)
175
    gc->ts_y_origin = values->ts_y_origin;
176
  
177
  GDK_GC_GET_CLASS (gc)->set_values (gc, values, values_mask);
Elliot Lee's avatar
Elliot Lee committed
178 179 180
}

void
181
gdk_gc_set_foreground (GdkGC	*gc,
Elliot Lee's avatar
Elliot Lee committed
182 183
		       GdkColor *color)
{
184
  GdkGCValues values;
Elliot Lee's avatar
Elliot Lee committed
185

186
  g_return_if_fail (GDK_IS_GC (gc));
Elliot Lee's avatar
Elliot Lee committed
187 188
  g_return_if_fail (color != NULL);

189 190
  values.foreground = *color;
  gdk_gc_set_values (gc, &values, GDK_GC_FOREGROUND);
Elliot Lee's avatar
Elliot Lee committed
191 192 193
}

void
194
gdk_gc_set_background (GdkGC	*gc,
Elliot Lee's avatar
Elliot Lee committed
195 196
		       GdkColor *color)
{
197
  GdkGCValues values;
Elliot Lee's avatar
Elliot Lee committed
198

199
  g_return_if_fail (GDK_IS_GC (gc));
Elliot Lee's avatar
Elliot Lee committed
200 201
  g_return_if_fail (color != NULL);

202 203
  values.background = *color;
  gdk_gc_set_values (gc, &values, GDK_GC_BACKGROUND);
Elliot Lee's avatar
Elliot Lee committed
204 205 206
}

void
207
gdk_gc_set_font (GdkGC	 *gc,
Elliot Lee's avatar
Elliot Lee committed
208 209
		 GdkFont *font)
{
210
  GdkGCValues values;
Elliot Lee's avatar
Elliot Lee committed
211

212
  g_return_if_fail (GDK_IS_GC (gc));
Elliot Lee's avatar
Elliot Lee committed
213 214
  g_return_if_fail (font != NULL);

215 216
  values.font = font;
  gdk_gc_set_values (gc, &values, GDK_GC_FONT);
Elliot Lee's avatar
Elliot Lee committed
217 218 219
}

void
220
gdk_gc_set_function (GdkGC	 *gc,
Elliot Lee's avatar
Elliot Lee committed
221 222
		     GdkFunction  function)
{
223
  GdkGCValues values;
Elliot Lee's avatar
Elliot Lee committed
224

225
  g_return_if_fail (GDK_IS_GC (gc));
Elliot Lee's avatar
Elliot Lee committed
226

227 228
  values.function = function;
  gdk_gc_set_values (gc, &values, GDK_GC_FUNCTION);
Elliot Lee's avatar
Elliot Lee committed
229 230 231
}

void
232
gdk_gc_set_fill (GdkGC	 *gc,
Elliot Lee's avatar
Elliot Lee committed
233 234
		 GdkFill  fill)
{
235
  GdkGCValues values;
Elliot Lee's avatar
Elliot Lee committed
236

237
  g_return_if_fail (GDK_IS_GC (gc));
Elliot Lee's avatar
Elliot Lee committed
238

239 240
  values.fill = fill;
  gdk_gc_set_values (gc, &values, GDK_GC_FILL);
Elliot Lee's avatar
Elliot Lee committed
241 242 243
}

void
244
gdk_gc_set_tile (GdkGC	   *gc,
Elliot Lee's avatar
Elliot Lee committed
245 246
		 GdkPixmap *tile)
{
247
  GdkGCValues values;
Elliot Lee's avatar
Elliot Lee committed
248

249
  g_return_if_fail (GDK_IS_GC (gc));
Elliot Lee's avatar
Elliot Lee committed
250

251 252
  values.tile = tile;
  gdk_gc_set_values (gc, &values, GDK_GC_TILE);
Elliot Lee's avatar
Elliot Lee committed
253 254 255 256 257 258
}

void
gdk_gc_set_stipple (GdkGC     *gc,
		    GdkPixmap *stipple)
{
259
  GdkGCValues values;
Elliot Lee's avatar
Elliot Lee committed
260

261
  g_return_if_fail (GDK_IS_GC (gc));
Elliot Lee's avatar
Elliot Lee committed
262

263 264
  values.stipple = stipple;
  gdk_gc_set_values (gc, &values, GDK_GC_STIPPLE);
Elliot Lee's avatar
Elliot Lee committed
265 266 267 268 269 270 271
}

void
gdk_gc_set_ts_origin (GdkGC *gc,
		      gint   x,
		      gint   y)
{
272
  GdkGCValues values;
Elliot Lee's avatar
Elliot Lee committed
273

274
  g_return_if_fail (GDK_IS_GC (gc));
Elliot Lee's avatar
Elliot Lee committed
275

276
  values.ts_x_origin = x;
Tor Lillqvist's avatar
Tor Lillqvist committed
277
  values.ts_y_origin = y;
278 279 280
  
  gdk_gc_set_values (gc, &values,
		     GDK_GC_TS_X_ORIGIN | GDK_GC_TS_Y_ORIGIN);
Elliot Lee's avatar
Elliot Lee committed
281 282 283 284 285 286 287
}

void
gdk_gc_set_clip_origin (GdkGC *gc,
			gint   x,
			gint   y)
{
288
  GdkGCValues values;
Elliot Lee's avatar
Elliot Lee committed
289

290
  g_return_if_fail (GDK_IS_GC (gc));
Elliot Lee's avatar
Elliot Lee committed
291

292
  values.clip_x_origin = x;
Tor Lillqvist's avatar
Tor Lillqvist committed
293
  values.clip_y_origin = y;
294 295 296
  
  gdk_gc_set_values (gc, &values,
		     GDK_GC_CLIP_X_ORIGIN | GDK_GC_CLIP_Y_ORIGIN);
Elliot Lee's avatar
Elliot Lee committed
297 298 299
}

void
300
gdk_gc_set_clip_mask (GdkGC	*gc,
Elliot Lee's avatar
Elliot Lee committed
301 302
		      GdkBitmap *mask)
{
303
  GdkGCValues values;
304
  
305
  g_return_if_fail (GDK_IS_GC (gc));
306
  
307 308
  values.clip_mask = mask;
  gdk_gc_set_values (gc, &values, GDK_GC_CLIP_MASK);
Elliot Lee's avatar
Elliot Lee committed
309 310 311
}


312 313 314
void
gdk_gc_set_subwindow (GdkGC	       *gc,
		      GdkSubwindowMode	mode)
Elliot Lee's avatar
Elliot Lee committed
315
{
316
  GdkGCValues values;
Elliot Lee's avatar
Elliot Lee committed
317

318
  g_return_if_fail (GDK_IS_GC (gc));
Elliot Lee's avatar
Elliot Lee committed
319

320 321
  values.subwindow_mode = mode;
  gdk_gc_set_values (gc, &values, GDK_GC_SUBWINDOW);
Elliot Lee's avatar
Elliot Lee committed
322 323 324
}

void
325 326
gdk_gc_set_exposures (GdkGC     *gc,
		      gboolean   exposures)
Elliot Lee's avatar
Elliot Lee committed
327
{
328
  GdkGCValues values;
Elliot Lee's avatar
Elliot Lee committed
329

330
  g_return_if_fail (GDK_IS_GC (gc));
Elliot Lee's avatar
Elliot Lee committed
331

332 333
  values.graphics_exposures = exposures;
  gdk_gc_set_values (gc, &values, GDK_GC_EXPOSURES);
Elliot Lee's avatar
Elliot Lee committed
334 335 336
}

void
337 338
gdk_gc_set_line_attributes (GdkGC	*gc,
			    gint	 line_width,
Elliot Lee's avatar
Elliot Lee committed
339
			    GdkLineStyle line_style,
340
			    GdkCapStyle	 cap_style,
Elliot Lee's avatar
Elliot Lee committed
341 342
			    GdkJoinStyle join_style)
{
343 344 345 346 347 348 349 350 351 352 353 354
  GdkGCValues values;

  values.line_width = line_width;
  values.line_style = line_style;
  values.cap_style = cap_style;
  values.join_style = join_style;

  gdk_gc_set_values (gc, &values,
		     GDK_GC_LINE_WIDTH |
		     GDK_GC_LINE_STYLE |
		     GDK_GC_CAP_STYLE |
		     GDK_GC_JOIN_STYLE);
Elliot Lee's avatar
Elliot Lee committed
355
}
356

357 358 359
void
gdk_gc_set_dashes (GdkGC *gc,
		   gint	  dash_offset,
Owen Taylor's avatar
Owen Taylor committed
360
		   gint8  dash_list[],
361 362
		   gint   n)
{
363
  g_return_if_fail (GDK_IS_GC (gc));
364 365
  g_return_if_fail (dash_list != NULL);

366
  GDK_GC_GET_CLASS (gc)->set_dashes (gc, dash_offset, dash_list, n);
367
}
368

369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401
/**
 * gdk_gc_offset:
 * @gc: a #GdkGC
 * @x_offset: amount by which to offset the GC in the X direction
 * @y_offset: amount by which to offset the GC in the Y direction
 * 
 * Offset attributes such as the clip and tile-stipple origins
 * of the GC so that drawing at x - x_offset, y - y_offset with
 * the offset GC  has the same effect as drawing at x, y with the original
 * GC.
 **/
void
gdk_gc_offset (GdkGC *gc,
	       gint   x_offset,
	       gint   y_offset)
{
  if (x_offset != 0 || y_offset != 0)
    {
      GdkGCValues values;

      values.clip_x_origin = gc->clip_x_origin - x_offset;
      values.clip_y_origin = gc->clip_y_origin - y_offset;
      values.ts_x_origin = gc->ts_x_origin - x_offset;
      values.ts_y_origin = gc->ts_y_origin - y_offset;
      
      gdk_gc_set_values (gc, &values,
			 GDK_GC_CLIP_X_ORIGIN |
			 GDK_GC_CLIP_Y_ORIGIN |
			 GDK_GC_TS_X_ORIGIN |
			 GDK_GC_TS_Y_ORIGIN);
    }
}

402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491
/**
 * gdk_gc_set_colormap:
 * @gc: a #GdkGC
 * @colormap: a #GdkColormap
 * 
 * Sets the colormap for the GC to the given colormap. The depth
 * of the colormap's visual must match the depth of the drawable
 * for which the GC was created.
 **/
void
gdk_gc_set_colormap (GdkGC       *gc,
		     GdkColormap *colormap)
{
  g_return_if_fail (GDK_IS_GC (gc));
  g_return_if_fail (GDK_IS_COLORMAP (colormap));

  if (gc->colormap != colormap)
    {
      if (gc->colormap)
	g_object_unref (G_OBJECT (gc->colormap));

      gc->colormap = colormap;
      g_object_ref (G_OBJECT (gc->colormap));
    }
    
}

/**
 * gdk_gc_get_colormap:
 * @gc: a #GdkGC
 * 
 * Retrieves the colormap for a given GC, if it exists.
 * A GC will have a colormap if the drawable for which it was created
 * has a colormap, or if a colormap was set explicitely with
 * gdk_gc_set_colormap.
 * 
 * Return value: 
 **/
GdkColormap *
gdk_gc_get_colormap (GdkGC *gc)
{
  g_return_val_if_fail (GDK_IS_GC (gc), NULL);

  return gc->colormap;
}

static GdkColormap *
gdk_gc_get_colormap_warn (GdkGC *gc)
{
  GdkColormap *colormap = gdk_gc_get_colormap (gc);
  if (!colormap)
    {
      g_warning ("gdk_gc_set_rgb_fg_color() and gdk_gc_set_rgb_bg_color() can\n"
		 "only be used on GC's with a colormap. A GC will have a colormap\n"
		 "if it is created for a drawable with a colormap, or if a\n"
		 "colormap has been set explicitly with gdk_gc_set_colormap.\n");
      return NULL;
    }

  return colormap;
}

/**
 * gdk_gc_set_rgb_fg_color:
 * @gc: a #GdkGC
 * @color: an unallocated #GdkColor.
 * 
 * Set the foreground color of a GC using an unallocated color. The
 * pixel value for the color will be determined using GdkRGB. If the
 * colormap for the GC has not previously been initialized for GdkRGB,
 * then for pseudo-color colormaps (colormaps with a small modifiable
 * number of colors), a colorcube will be allocated in the colormap.
 * 
 * Calling this function for a GC without a colormap is an error.
 **/
void
gdk_gc_set_rgb_fg_color (GdkGC *gc, GdkColor *color)
{
  GdkColormap *cmap;
  GdkColor tmp_color;

  g_return_if_fail (GDK_IS_GC (gc));
  g_return_if_fail (color != NULL);

  cmap = gdk_gc_get_colormap_warn (gc);
  if (!cmap)
    return;

  tmp_color = *color;
  gdk_rgb_find_color (cmap, &tmp_color);
492
  gdk_gc_set_foreground (gc, &tmp_color);
493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522
}

/**
 * gdk_gc_set_rgb_bg_color:
 * @gc: a #GdkGC
 * @color: an unallocated #GdkColor.
 * 
 * Set the background color of a GC using an unallocated color. The
 * pixel value for the color will be determined using GdkRGB. If the
 * colormap for the GC has not previously been initialized for GdkRGB,
 * then for pseudo-color colormaps (colormaps with a small modifiable
 * number of colors), a colorcube will be allocated in the colormap.
 * 
 * Calling this function for a GC without a colormap is an error.
 **/
void
gdk_gc_set_rgb_bg_color (GdkGC *gc, GdkColor *color)
{
  GdkColormap *cmap;
  GdkColor tmp_color;

  g_return_if_fail (GDK_IS_GC (gc));
  g_return_if_fail (color != NULL);

  cmap = gdk_gc_get_colormap_warn (gc);
  if (!cmap)
    return;

  tmp_color = *color;
  gdk_rgb_find_color (cmap, &tmp_color);
523
  gdk_gc_set_background (gc, &tmp_color);
524
}