gdkgc.c 12.4 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
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);
}

Matthias Clasen's avatar
Matthias Clasen committed
125 126 127 128 129 130 131 132
/**
 * gdk_gc_ref:
 * @gc: a #GdkGC
 *
 * Deprecated function; use g_object_ref() instead.
 *
 * Return value: the gc.
 **/
133 134 135
GdkGC *
gdk_gc_ref (GdkGC *gc)
{
136
  return (GdkGC *) g_object_ref (G_OBJECT (gc));
137
}
Elliot Lee's avatar
Elliot Lee committed
138

Matthias Clasen's avatar
Matthias Clasen committed
139 140 141 142 143 144
/**
 * gdk_gc_unref:
 * @gc: a #GdkGC
 *
 * Deprecated function; use g_object_unref() instead.
 **/
145 146 147
void
gdk_gc_unref (GdkGC *gc)
{
148
  g_object_unref (G_OBJECT (gc));
Elliot Lee's avatar
Elliot Lee committed
149 150 151 152 153 154
}

void
gdk_gc_get_values (GdkGC       *gc,
		   GdkGCValues *values)
{
155
  g_return_if_fail (GDK_IS_GC (gc));
156
  g_return_if_fail (values != NULL);
Elliot Lee's avatar
Elliot Lee committed
157

158
  GDK_GC_GET_CLASS (gc)->get_values (gc, values);
159 160
}

161 162 163 164 165 166 167 168 169 170 171 172 173
/**
 * 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.
 * 
 **/
174 175 176 177 178
void
gdk_gc_set_values (GdkGC           *gc,
		   GdkGCValues	   *values,
		   GdkGCValuesMask  values_mask)
{
179
  g_return_if_fail (GDK_IS_GC (gc));
Elliot Lee's avatar
Elliot Lee committed
180 181
  g_return_if_fail (values != NULL);

182
  if (values_mask & GDK_GC_CLIP_X_ORIGIN)
183
    gc->clip_x_origin = values->clip_x_origin;
184
  if (values_mask & GDK_GC_CLIP_Y_ORIGIN)
185
    gc->clip_y_origin = values->clip_y_origin;
186
  if (values_mask & GDK_GC_TS_X_ORIGIN)
187
    gc->ts_x_origin = values->ts_x_origin;
188
  if (values_mask & GDK_GC_TS_Y_ORIGIN)
189
    gc->ts_y_origin = values->ts_y_origin;
190
  
191
  GDK_GC_GET_CLASS (gc)->set_values (gc, values, values_mask);
Elliot Lee's avatar
Elliot Lee committed
192 193 194
}

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

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

203 204
  values.foreground = *color;
  gdk_gc_set_values (gc, &values, GDK_GC_FOREGROUND);
Elliot Lee's avatar
Elliot Lee committed
205 206 207
}

void
208
gdk_gc_set_background (GdkGC	*gc,
Elliot Lee's avatar
Elliot Lee committed
209 210
		       GdkColor *color)
{
211
  GdkGCValues values;
Elliot Lee's avatar
Elliot Lee committed
212

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

216 217
  values.background = *color;
  gdk_gc_set_values (gc, &values, GDK_GC_BACKGROUND);
Elliot Lee's avatar
Elliot Lee committed
218 219 220
}

void
221
gdk_gc_set_font (GdkGC	 *gc,
Elliot Lee's avatar
Elliot Lee committed
222 223
		 GdkFont *font)
{
224
  GdkGCValues values;
Elliot Lee's avatar
Elliot Lee committed
225

226
  g_return_if_fail (GDK_IS_GC (gc));
Elliot Lee's avatar
Elliot Lee committed
227 228
  g_return_if_fail (font != NULL);

229 230
  values.font = font;
  gdk_gc_set_values (gc, &values, GDK_GC_FONT);
Elliot Lee's avatar
Elliot Lee committed
231 232 233
}

void
234
gdk_gc_set_function (GdkGC	 *gc,
Elliot Lee's avatar
Elliot Lee committed
235 236
		     GdkFunction  function)
{
237
  GdkGCValues values;
Elliot Lee's avatar
Elliot Lee committed
238

239
  g_return_if_fail (GDK_IS_GC (gc));
Elliot Lee's avatar
Elliot Lee committed
240

241 242
  values.function = function;
  gdk_gc_set_values (gc, &values, GDK_GC_FUNCTION);
Elliot Lee's avatar
Elliot Lee committed
243 244 245
}

void
246
gdk_gc_set_fill (GdkGC	 *gc,
Elliot Lee's avatar
Elliot Lee committed
247 248
		 GdkFill  fill)
{
249
  GdkGCValues values;
Elliot Lee's avatar
Elliot Lee committed
250

251
  g_return_if_fail (GDK_IS_GC (gc));
Elliot Lee's avatar
Elliot Lee committed
252

253 254
  values.fill = fill;
  gdk_gc_set_values (gc, &values, GDK_GC_FILL);
Elliot Lee's avatar
Elliot Lee committed
255 256 257
}

void
258
gdk_gc_set_tile (GdkGC	   *gc,
Elliot Lee's avatar
Elliot Lee committed
259 260
		 GdkPixmap *tile)
{
261
  GdkGCValues values;
Elliot Lee's avatar
Elliot Lee committed
262

263
  g_return_if_fail (GDK_IS_GC (gc));
Elliot Lee's avatar
Elliot Lee committed
264

265 266
  values.tile = tile;
  gdk_gc_set_values (gc, &values, GDK_GC_TILE);
Elliot Lee's avatar
Elliot Lee committed
267 268 269 270 271 272
}

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

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

277 278
  values.stipple = stipple;
  gdk_gc_set_values (gc, &values, GDK_GC_STIPPLE);
Elliot Lee's avatar
Elliot Lee committed
279 280 281 282 283 284 285
}

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

288
  g_return_if_fail (GDK_IS_GC (gc));
Elliot Lee's avatar
Elliot Lee committed
289

290
  values.ts_x_origin = x;
291
  values.ts_y_origin = y;
292 293 294
  
  gdk_gc_set_values (gc, &values,
		     GDK_GC_TS_X_ORIGIN | GDK_GC_TS_Y_ORIGIN);
Elliot Lee's avatar
Elliot Lee committed
295 296 297 298 299 300 301
}

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

304
  g_return_if_fail (GDK_IS_GC (gc));
Elliot Lee's avatar
Elliot Lee committed
305

306
  values.clip_x_origin = x;
307
  values.clip_y_origin = y;
308 309 310
  
  gdk_gc_set_values (gc, &values,
		     GDK_GC_CLIP_X_ORIGIN | GDK_GC_CLIP_Y_ORIGIN);
Elliot Lee's avatar
Elliot Lee committed
311 312 313
}

void
314
gdk_gc_set_clip_mask (GdkGC	*gc,
Elliot Lee's avatar
Elliot Lee committed
315 316
		      GdkBitmap *mask)
{
317
  GdkGCValues values;
318
  
319
  g_return_if_fail (GDK_IS_GC (gc));
320
  
321 322
  values.clip_mask = mask;
  gdk_gc_set_values (gc, &values, GDK_GC_CLIP_MASK);
Elliot Lee's avatar
Elliot Lee committed
323 324 325
}


326 327 328
void
gdk_gc_set_subwindow (GdkGC	       *gc,
		      GdkSubwindowMode	mode)
Elliot Lee's avatar
Elliot Lee committed
329
{
330
  GdkGCValues values;
Elliot Lee's avatar
Elliot Lee committed
331

332
  g_return_if_fail (GDK_IS_GC (gc));
Elliot Lee's avatar
Elliot Lee committed
333

334 335
  values.subwindow_mode = mode;
  gdk_gc_set_values (gc, &values, GDK_GC_SUBWINDOW);
Elliot Lee's avatar
Elliot Lee committed
336 337 338
}

void
339 340
gdk_gc_set_exposures (GdkGC     *gc,
		      gboolean   exposures)
Elliot Lee's avatar
Elliot Lee committed
341
{
342
  GdkGCValues values;
Elliot Lee's avatar
Elliot Lee committed
343

344
  g_return_if_fail (GDK_IS_GC (gc));
Elliot Lee's avatar
Elliot Lee committed
345

346 347
  values.graphics_exposures = exposures;
  gdk_gc_set_values (gc, &values, GDK_GC_EXPOSURES);
Elliot Lee's avatar
Elliot Lee committed
348 349 350
}

void
351 352
gdk_gc_set_line_attributes (GdkGC	*gc,
			    gint	 line_width,
Elliot Lee's avatar
Elliot Lee committed
353
			    GdkLineStyle line_style,
354
			    GdkCapStyle	 cap_style,
Elliot Lee's avatar
Elliot Lee committed
355 356
			    GdkJoinStyle join_style)
{
357 358 359 360 361 362 363 364 365 366 367 368
  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
369
}
370

371 372 373
void
gdk_gc_set_dashes (GdkGC *gc,
		   gint	  dash_offset,
Owen Taylor's avatar
Owen Taylor committed
374
		   gint8  dash_list[],
375 376
		   gint   n)
{
377
  g_return_if_fail (GDK_IS_GC (gc));
378 379
  g_return_if_fail (dash_list != NULL);

380
  GDK_GC_GET_CLASS (gc)->set_dashes (gc, dash_offset, dash_list, n);
381
}
382

383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415
/**
 * 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);
    }
}

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 492 493 494 495 496 497 498 499 500 501 502 503 504 505
/**
 * 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);
506
  gdk_gc_set_foreground (gc, &tmp_color);
507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536
}

/**
 * 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);
537
  gdk_gc_set_background (gc, &tmp_color);
538
}