gdkgc-win32.c 45.3 KB
Newer Older
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
6 7 8 9 10 11
 * 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
12
 * Lesser General Public License for more details.
13
 *
14
 * You should have received a copy of the GNU Lesser General Public
15 16 17 18 19 20
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */

/*
21
 * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
22 23 24 25 26 27 28 29 30 31 32 33
 * 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/. 
 */

#include "config.h"

#include <string.h>

#include "gdkgc.h"
#include "gdkfont.h"
#include "gdkpixmap.h"
34 35 36
#include "gdkregion-generic.h"
#include "gdkinternals.h"
#include "gdkprivate-win32.h"
Tor Lillqvist's avatar
Tor Lillqvist committed
37 38 39 40 41 42 43 44

static void gdk_win32_gc_get_values (GdkGC           *gc,
				     GdkGCValues     *values);
static void gdk_win32_gc_set_values (GdkGC           *gc,
				     GdkGCValues     *values,
				     GdkGCValuesMask  values_mask);
static void gdk_win32_gc_set_dashes (GdkGC           *gc,
				     gint             dash_offset,
45
				     gint8            dash_list[],
Tor Lillqvist's avatar
Tor Lillqvist committed
46 47
				     gint             n);

48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
static void gdk_gc_win32_class_init (GdkGCWin32Class *klass);
static void gdk_gc_win32_finalize   (GObject         *object);

static gpointer parent_class = NULL;

GType
gdk_gc_win32_get_type (void)
{
  static GType object_type = 0;

  if (!object_type)
    {
      static const GTypeInfo object_info =
      {
        sizeof (GdkGCWin32Class),
        (GBaseInitFunc) NULL,
        (GBaseFinalizeFunc) NULL,
        (GClassInitFunc) gdk_gc_win32_class_init,
        NULL,           /* class_finalize */
        NULL,           /* class_data */
        sizeof (GdkGCWin32),
        0,              /* n_preallocs */
        (GInstanceInitFunc) NULL,
      };
      
      object_type = g_type_register_static (GDK_TYPE_GC,
                                            "GdkGCWin32",
Tor Lillqvist's avatar
Tor Lillqvist committed
75
                                            &object_info, 0);
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
    }
  
  return object_type;
}

static void
gdk_gc_win32_class_init (GdkGCWin32Class *klass)
{
  GObjectClass *object_class = G_OBJECT_CLASS (klass);
  GdkGCClass *gc_class = GDK_GC_CLASS (klass);
  
  parent_class = g_type_class_peek_parent (klass);

  object_class->finalize = gdk_gc_win32_finalize;

  gc_class->get_values = gdk_win32_gc_get_values;
  gc_class->set_values = gdk_win32_gc_set_values;
  gc_class->set_dashes = gdk_win32_gc_set_dashes;
}

static void
gdk_gc_win32_finalize (GObject *object)
{
  GdkGCWin32 *win32_gc = GDK_GC_WIN32 (object);
  
  if (win32_gc->clip_region)
    gdk_region_destroy (win32_gc->clip_region);
  
  if (win32_gc->values_mask & GDK_GC_FONT)
    gdk_font_unref (win32_gc->font);
  
  if (win32_gc->values_mask & GDK_GC_TILE)
    gdk_drawable_unref (win32_gc->tile);
  
  if (win32_gc->values_mask & GDK_GC_STIPPLE)
    gdk_drawable_unref (win32_gc->stipple);
  
  G_OBJECT_CLASS (parent_class)->finalize (object);
}
115

116 117 118
static void
gdk_win32_gc_values_to_win32values (GdkGCValues    *values,
				    GdkGCValuesMask mask,
119
				    GdkGCWin32     *win32_gc)
120 121
{				    
  char *s = "";
122
  gint sw, sh;
123

124
  GDK_NOTE (MISC, g_print ("{"));
125

126
  if (mask & GDK_GC_FOREGROUND)
127
    {
128 129
      win32_gc->foreground = values->foreground.pixel;
      win32_gc->values_mask |= GDK_GC_FOREGROUND;
130
      GDK_NOTE (MISC, (g_print ("fg=%.06lx", win32_gc->foreground),
131
		       s = ","));
132 133
    }
  
134
  if (mask & GDK_GC_BACKGROUND)
135
    {
136 137
      win32_gc->background = values->background.pixel;
      win32_gc->values_mask |= GDK_GC_BACKGROUND;
138
      GDK_NOTE (MISC, (g_print ("%sbg=%.06lx", s, win32_gc->background),
139
		       s = ","));
140 141
    }

142 143
  if ((mask & GDK_GC_FONT) && (values->font->type == GDK_FONT_FONT
			       || values->font->type == GDK_FONT_FONTSET))
144
    {
145 146 147 148
      if (win32_gc->font != NULL)
	gdk_font_unref (win32_gc->font);
      win32_gc->font = values->font;
      if (win32_gc->font != NULL)
149 150 151
	{
	  gchar *xlfd;

152 153 154
	  gdk_font_ref (win32_gc->font);
	  win32_gc->values_mask |= GDK_GC_FONT;
	  GDK_NOTE (MISC, (xlfd = gdk_font_full_name_get (win32_gc->font),
155 156 157 158 159 160
			   g_print ("%sfont=%s", s, xlfd),
			   s = ",",
			   gdk_font_full_name_free (xlfd)));
	}
      else
	{
161
	  win32_gc->values_mask &= ~GDK_GC_FONT;
162
	  GDK_NOTE (MISC, (g_print ("%sfont=NULL", s),
163 164
			   s = ","));
	}
165 166
    }

167
  if (mask & GDK_GC_FUNCTION)
168
    {
169 170
      GDK_NOTE (MISC, (g_print ("%srop2=", s),
		       s = ","));
171 172 173
      switch (values->function)
	{
	case GDK_COPY:
174
	  win32_gc->rop2 = R2_COPYPEN;
175 176
	  GDK_NOTE (MISC, g_print ("COPYPEN"));
	  break;
177
	case GDK_INVERT:
178
	  win32_gc->rop2 = R2_NOT;
179 180
	  GDK_NOTE (MISC, g_print ("NOT"));
	  break;
181
	case GDK_XOR:
182
	  win32_gc->rop2 = R2_XORPEN;
183 184
	  GDK_NOTE (MISC, g_print ("XORPEN"));
	  break;
185
	case GDK_CLEAR:
186
	  win32_gc->rop2 = R2_BLACK;
187 188
	  GDK_NOTE (MISC, g_print ("BLACK"));
	  break;
189
	case GDK_AND:
190
	  win32_gc->rop2 = R2_MASKPEN;
191 192
	  GDK_NOTE (MISC, g_print ("MASKPEN"));
	  break;
193
	case GDK_AND_REVERSE:
194
	  win32_gc->rop2 = R2_MASKPENNOT;
195 196
	  GDK_NOTE (MISC, g_print ("MASKPENNOT"));
	  break;
197
	case GDK_AND_INVERT:
198
	  win32_gc->rop2 = R2_MASKNOTPEN;
199 200
	  GDK_NOTE (MISC, g_print ("MASKNOTPEN"));
	  break;
201
	case GDK_NOOP:
202
	  win32_gc->rop2 = R2_NOP;
203 204
	  GDK_NOTE (MISC, g_print ("NOP"));
	  break;
205
	case GDK_OR:
206
	  win32_gc->rop2 = R2_MERGEPEN;
207 208
	  GDK_NOTE (MISC, g_print ("MERGEPEN"));
	  break;
209
	case GDK_EQUIV:
210
	  win32_gc->rop2 = R2_NOTXORPEN;
211 212
	  GDK_NOTE (MISC, g_print ("NOTXORPEN"));
	  break;
213
	case GDK_OR_REVERSE:
214
	  win32_gc->rop2 = R2_MERGEPENNOT;
215 216
	  GDK_NOTE (MISC, g_print ("MERGEPENNOT"));
	  break;
217
	case GDK_COPY_INVERT:
218
	  win32_gc->rop2 = R2_NOTCOPYPEN;
219 220
	  GDK_NOTE (MISC, g_print ("NOTCOPYPEN"));
	  break;
221
	case GDK_OR_INVERT:
222
	  win32_gc->rop2 = R2_MERGENOTPEN;
223 224
	  GDK_NOTE (MISC, g_print ("MERGENOTPEN"));
	  break;
225
	case GDK_NAND:
226
	  win32_gc->rop2 = R2_NOTMASKPEN;
227 228
	  GDK_NOTE (MISC, g_print ("NOTMASKPEN"));
	  break;
229
	case GDK_NOR:
230
	  win32_gc->rop2 = R2_NOTMERGEPEN;
231 232
	  GDK_NOTE (MISC, g_print ("NOTMERGEPEN"));
	  break;
233
	case GDK_SET:
234
	  win32_gc->rop2 = R2_WHITE;
235 236
	  GDK_NOTE (MISC, g_print ("WHITE"));
	  break;
237
	}
238
      win32_gc->values_mask |= GDK_GC_FUNCTION;
239 240
    }

241
  if (mask & GDK_GC_FILL)
242
    {
243 244 245
      win32_gc->fill_style = values->fill;
      win32_gc->values_mask |= GDK_GC_FILL;
      GDK_NOTE (MISC, (g_print ("%sfill=%d", s, win32_gc->fill_style),
246
		       s = ","));
247 248
    }

249
  if (mask & GDK_GC_TILE)
250
    {
251 252 253 254
      if (win32_gc->tile != NULL)
	gdk_drawable_unref (win32_gc->tile);
      win32_gc->tile = values->tile;
      if (win32_gc->tile != NULL)
255
	{
256 257
	  gdk_drawable_ref (win32_gc->tile);
	  win32_gc->values_mask |= GDK_GC_TILE;
258 259 260 261
	  GDK_NOTE (MISC,
		    (g_print ("%stile=%#x", s,
			      (guint) GDK_PIXMAP_HBITMAP (win32_gc->tile)),
		     s = ","));
262 263 264
	}
      else
	{
265
	  win32_gc->values_mask &= ~GDK_GC_TILE;
266 267 268
	  GDK_NOTE (MISC, (g_print ("%stile=NULL", s),
			   s = ","));
	}
269 270
    }

271
  if (mask & GDK_GC_STIPPLE)
272
    {
273 274 275 276
      if (win32_gc->stipple != NULL)
	gdk_drawable_unref (win32_gc->stipple);
      win32_gc->stipple = values->stipple;
      if (win32_gc->stipple != NULL)
277
	{
278
	  gdk_drawable_get_size (win32_gc->stipple, &sw, &sh);
279

280 281 282 283 284 285
#if 0 /* HB: this size limitation is disabled to make radio and check
       * buttons work. I got the impression from the API docs, that
       * it shouldn't be necessary at all, but win9x would do the clipping
       */
	  if (   (sw != 8 || sh != 8)
	      && !IS_WIN_NT ()) /* HB: the MSDN says it's a Win95 limitation */
286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302
	    {
	      /* It seems that it *must* be 8x8, at least on my machine. 
	       * Thus, tile an 8x8 bitmap with the stipple in case it is
	       * smaller, or simply use just the top left 8x8 in case it is
	       * larger.
	       */
	      gchar dummy[8];
	      GdkPixmap *bm = gdk_bitmap_create_from_data (NULL, dummy, 8, 8);
	      GdkGC *gc = gdk_gc_new (bm);
	      gint i, j;

	      i = 0;
	      while (i < 8)
		{
		  j = 0;
		  while (j < 8)
		    {
303
		      gdk_draw_drawable (bm, gc, win32_gc->stipple, 0, 0, i, j, sw, sh);
304 305 306 307
		      j += sh;
		    }
		  i += sw;
		}
308
	      win32_gc->stipple = bm;
309 310 311
	      gdk_gc_unref (gc);
	    }
	  else
312
#endif
313 314
	    gdk_drawable_ref (win32_gc->stipple);
	  win32_gc->values_mask |= GDK_GC_STIPPLE;
315 316 317 318
	  GDK_NOTE (MISC,
		    (g_print ("%sstipple=%#x", s,
			      (guint) GDK_PIXMAP_HBITMAP (win32_gc->stipple)),
		     s = ","));
319 320 321
	}
      else
	{
322
	  win32_gc->values_mask &= ~GDK_GC_STIPPLE;
323 324 325
	  GDK_NOTE (MISC, (g_print ("%sstipple=NULL", s),
			   s = ","));
	}
326 327
    }

328
  if (mask & GDK_GC_CLIP_MASK)
329
    {
330
      if (win32_gc->clip_region != NULL)
331
	{
332 333
	  gdk_region_destroy (win32_gc->clip_region);
	  win32_gc->clip_region = NULL;
334
	}
335

336
      if (win32_gc->hcliprgn != NULL)
337 338 339 340
	{
	  DeleteObject (win32_gc->hcliprgn);
	  win32_gc->hcliprgn = NULL;
	}
341

342 343
      if (values->clip_mask != NULL)
	{
344
	  win32_gc->hcliprgn =
Tor Lillqvist's avatar
Tor Lillqvist committed
345
	    BitmapToRegion ((HBITMAP) GDK_PIXMAP_HBITMAP (values->clip_mask));
346
	  win32_gc->values_mask |= GDK_GC_CLIP_MASK;
347 348 349
	}
      else
	{
350 351
	  win32_gc->hcliprgn = NULL;
	  win32_gc->values_mask &= ~GDK_GC_CLIP_MASK;
352
	}
353
      GDK_NOTE (MISC, (g_print ("%sclip=%#x", s, (guint) win32_gc->hcliprgn),
354
		       s = ","));
355 356
    }

357
  if (mask & GDK_GC_SUBWINDOW)
358
    {
359 360 361
      win32_gc->subwindow_mode = values->subwindow_mode;
      win32_gc->values_mask |= GDK_GC_SUBWINDOW;
      GDK_NOTE (MISC, (g_print ("%ssubw=%d", s, win32_gc->subwindow_mode),
362
		       s = ","));
363 364
    }

365
  if (mask & GDK_GC_TS_X_ORIGIN)
366
    {
367
      win32_gc->values_mask |= GDK_GC_TS_X_ORIGIN;
368
      GDK_NOTE (MISC, (g_print ("%sts_x=%d", s, values->ts_x_origin),
369
		       s = ","));
370 371
    }

372
  if (mask & GDK_GC_TS_Y_ORIGIN)
373
    {
374
      win32_gc->values_mask |= GDK_GC_TS_Y_ORIGIN;
375
      GDK_NOTE (MISC, (g_print ("%sts_y=%d", s, values->ts_y_origin),
376
		       s = ","));
377 378
    }

379
  if (mask & GDK_GC_CLIP_X_ORIGIN)
380
    {
381
      win32_gc->values_mask |= GDK_GC_CLIP_X_ORIGIN;
382
      GDK_NOTE (MISC, (g_print ("%sclip_x=%d", s, values->clip_x_origin),
383
		       s = ","));
384 385
    }

386
  if (mask & GDK_GC_CLIP_Y_ORIGIN)
387
    {
388
      win32_gc->values_mask |= GDK_GC_CLIP_Y_ORIGIN;
389
      GDK_NOTE (MISC, (g_print ("%sclip_y=%d", s, values->clip_y_origin),
390
		       s = ","));
Hans Breuer's avatar
updated  
Hans Breuer committed
391 392
    }

393
  if (mask & GDK_GC_EXPOSURES)
394
    {
395 396 397
      win32_gc->graphics_exposures = values->graphics_exposures;
      win32_gc->values_mask |= GDK_GC_EXPOSURES;
      GDK_NOTE (MISC, (g_print ("%sexp=%d", s, win32_gc->graphics_exposures),
398
		       s = ","));
399 400
    }

401 402
  if (mask & GDK_GC_LINE_WIDTH)
    {
403 404 405
      win32_gc->pen_width = values->line_width;
      win32_gc->values_mask |= GDK_GC_LINE_WIDTH;
      GDK_NOTE (MISC, (g_print ("%spw=%d", s, win32_gc->pen_width),
406 407
		       s = ","));
    }
408

409
  if (mask & GDK_GC_LINE_STYLE)
410
    {
411 412 413
      GDK_NOTE (MISC, (g_print ("%sps|=", s),
		       s = ","));
      switch (values->line_style)
414
	{
415
	case GDK_LINE_SOLID:
416
        win32_gc->pen_style &= ~(PS_STYLE_MASK);
417
	  GDK_NOTE (MISC, g_print ("LINE_SOLID"));
418
	  win32_gc->pen_style |= PS_SOLID;
419 420 421
	  break;
	case GDK_LINE_ON_OFF_DASH:
	case GDK_LINE_DOUBLE_DASH: /* ??? */
422 423 424 425 426 427 428 429 430
	  /* only set the linestyle here, if it isn't already set
	   * gdk_win32_gc_set_dashes () knows better
	   */
	  if (0 == (win32_gc->values_mask & GDK_GC_LINE_STYLE))
	    {
            win32_gc->pen_style &= ~(PS_STYLE_MASK);
	      GDK_NOTE (MISC, g_print ("DASH"));
	      win32_gc->pen_style |= PS_DASH;
	    }
431
	  break;
432
	}
433
      win32_gc->values_mask |= GDK_GC_LINE_STYLE;
434 435
    }

436
  if (mask & GDK_GC_CAP_STYLE)
437
    {
438
      win32_gc->pen_style &= ~(PS_ENDCAP_MASK);
439 440
      GDK_NOTE (MISC, (g_print ("%sps|=", s),
		       s = ","));
441 442 443 444
      switch (values->cap_style)
	{
	case GDK_CAP_NOT_LAST:	/* ??? */
	case GDK_CAP_BUTT:
445
	  GDK_NOTE (MISC, g_print ("ENDCAP_FLAT"));
446
	  win32_gc->pen_style |= PS_ENDCAP_FLAT;
447
	  break;
448
	case GDK_CAP_ROUND:
449
	  GDK_NOTE (MISC, g_print ("ENDCAP_ROUND"));
450
	  win32_gc->pen_style |= PS_ENDCAP_ROUND;
451
	  break;
452
	case GDK_CAP_PROJECTING:
453
	  GDK_NOTE (MISC, g_print ("ENDCAP_SQUARE"));
454
	  win32_gc->pen_style |= PS_ENDCAP_SQUARE;
455
	  break;
456
	}
457
      win32_gc->values_mask |= GDK_GC_CAP_STYLE;
458 459
    }

460
  if (mask & GDK_GC_JOIN_STYLE)
461
    {
462
      win32_gc->pen_style &= ~(PS_JOIN_MASK);
463 464
      GDK_NOTE (MISC, (g_print ("%sps|=", s),
		       s = ","));
465 466 467
      switch (values->join_style)
	{
	case GDK_JOIN_MITER:
468
	  GDK_NOTE (MISC, g_print ("JOIN_MITER"));
469
	  win32_gc->pen_style |= PS_JOIN_MITER;
470 471
	  break;
	case GDK_JOIN_ROUND:
472
	  GDK_NOTE (MISC, g_print ("JOIN_ROUND"));
473
	  win32_gc->pen_style |= PS_JOIN_ROUND;
474 475
	  break;
	case GDK_JOIN_BEVEL:
476
	  GDK_NOTE (MISC, g_print ("JOIN_BEVEL"));
477
	  win32_gc->pen_style |= PS_JOIN_BEVEL;
478 479
	  break;
	}
480
      win32_gc->values_mask |= GDK_GC_JOIN_STYLE;
481 482 483 484 485 486 487 488 489 490
    }
  GDK_NOTE (MISC, g_print ("}\n"));
}

GdkGC*
_gdk_win32_gc_new (GdkDrawable	  *drawable,
		   GdkGCValues	  *values,
		   GdkGCValuesMask mask)
{
  GdkGC *gc;
491
  GdkGCWin32 *win32_gc;
492

493 494 495 496
  /* NOTICE that the drawable here has to be the impl drawable,
   * not the publically-visible drawables.
   */
  g_return_val_if_fail (GDK_IS_DRAWABLE_IMPL_WIN32 (drawable), NULL);
497

498 499 500 501 502 503
  gc = g_object_new (gdk_gc_win32_get_type (), NULL);
  win32_gc = GDK_GC_WIN32 (gc);

  win32_gc->hdc = NULL;
  win32_gc->clip_region = NULL;
  win32_gc->hcliprgn = NULL;
504

505 506 507
  /* Use the same default values as X11 does, even if they don't make
   * sense per se. But apps always set fg and bg anyway.
   */
508 509 510 511 512 513 514 515 516 517 518
  win32_gc->foreground = 0;
  win32_gc->background = 1;
  win32_gc->font = NULL;
  win32_gc->rop2 = R2_COPYPEN;
  win32_gc->fill_style = GDK_SOLID;
  win32_gc->tile = NULL;
  win32_gc->stipple = NULL;
  win32_gc->pen_style = PS_GEOMETRIC|PS_ENDCAP_FLAT|PS_JOIN_MITER;
  win32_gc->pen_width = 0;

  win32_gc->values_mask = GDK_GC_FUNCTION | GDK_GC_FILL;
519 520

  GDK_NOTE (MISC, g_print ("_gdk_win32_gc_new: "));
521
  gdk_win32_gc_values_to_win32values (values, mask, win32_gc);
522

523
  win32_gc->hwnd = NULL;
524

525
  GDK_NOTE (MISC, g_print (" = %p\n", gc));
526 527 528 529

  return gc;
}

Tor Lillqvist's avatar
Tor Lillqvist committed
530 531 532
static void
gdk_win32_gc_get_values (GdkGC       *gc,
			 GdkGCValues *values)
533
{
534
  GdkGCWin32 *win32_gc = GDK_GC_WIN32 (gc);
535

536 537 538
  values->foreground.pixel = win32_gc->foreground;
  values->background.pixel = win32_gc->background;
  values->font = win32_gc->font;
539

540
  switch (win32_gc->rop2)
541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569
    {
    case R2_COPYPEN:
      values->function = GDK_COPY; break;
    case R2_NOT:
      values->function = GDK_INVERT; break;
    case R2_XORPEN:
      values->function = GDK_XOR; break;
    case R2_BLACK:
      values->function = GDK_CLEAR; break;
    case R2_MASKPEN:
      values->function = GDK_AND; break;
    case R2_MASKPENNOT:
      values->function = GDK_AND_REVERSE; break;
    case R2_MASKNOTPEN:
      values->function = GDK_AND_INVERT; break;
    case R2_NOP:
      values->function = GDK_NOOP; break;
    case R2_MERGEPEN:
      values->function = GDK_OR; break;
    case R2_NOTXORPEN:
      values->function = GDK_EQUIV; break;
    case R2_MERGEPENNOT:
      values->function = GDK_OR_REVERSE; break;
    case R2_NOTCOPYPEN:
      values->function = GDK_COPY_INVERT; break;
    case R2_MERGENOTPEN:
      values->function = GDK_OR_INVERT; break;
    case R2_NOTMASKPEN:
      values->function = GDK_NAND; break;
570 571
    case R2_NOTMERGEPEN:
      values->function = GDK_NOR; break;
572 573 574 575
    case R2_WHITE:
      values->function = GDK_SET; break;
    }

576
  values->fill = win32_gc->fill_style;
577

578 579
  values->tile = win32_gc->tile;
  values->stipple = win32_gc->stipple;
580

581 582 583
  /* Also the X11 backend always returns a NULL clip_mask */
  values->clip_mask = NULL;

584 585 586 587 588 589 590
  values->subwindow_mode = win32_gc->subwindow_mode;
  values->ts_x_origin = win32_gc->parent_instance.ts_x_origin;
  values->ts_y_origin = win32_gc->parent_instance.ts_y_origin;
  values->clip_x_origin = win32_gc->parent_instance.clip_x_origin;
  values->clip_y_origin = win32_gc->parent_instance.clip_y_origin;
  values->graphics_exposures = win32_gc->graphics_exposures;
  values->line_width = win32_gc->pen_width;
591
  
592
  if (win32_gc->pen_style & PS_SOLID)
593
    values->line_style = GDK_LINE_SOLID;
594
  else if (win32_gc->pen_style & PS_DASH)
595 596 597 598 599
    values->line_style = GDK_LINE_ON_OFF_DASH;
  else
    values->line_style = GDK_LINE_SOLID;

  /* PS_ENDCAP_ROUND is zero */
600
  if (win32_gc->pen_style & PS_ENDCAP_FLAT)
601
    values->cap_style = GDK_CAP_BUTT;
602
  else if (win32_gc->pen_style & PS_ENDCAP_SQUARE)
603 604 605 606 607
    values->cap_style = GDK_CAP_PROJECTING;
  else
    values->cap_style = GDK_CAP_ROUND;
    
  /* PS_JOIN_ROUND is zero */
608
  if (win32_gc->pen_style & PS_JOIN_MITER)
609
    values->join_style = GDK_JOIN_MITER;
610
  else if (win32_gc->pen_style & PS_JOIN_BEVEL)
611 612 613 614 615
    values->join_style = GDK_JOIN_BEVEL;
  else
    values->join_style = GDK_JOIN_ROUND;
}

Tor Lillqvist's avatar
Tor Lillqvist committed
616 617 618
static void
gdk_win32_gc_set_values (GdkGC           *gc,
			 GdkGCValues     *values,
619
			 GdkGCValuesMask  mask)
620
{
621 622
  g_return_if_fail (GDK_IS_GC (gc));

623
  GDK_NOTE (MISC, g_print ("gdk_win32_gc_set_values: "));
624 625

  gdk_win32_gc_values_to_win32values (values, mask, GDK_GC_WIN32 (gc));
Tor Lillqvist's avatar
Tor Lillqvist committed
626 627 628 629
}

static void
gdk_win32_gc_set_dashes (GdkGC *gc,
630 631
			 gint	dash_offset,
			 gint8  dash_list[],
Tor Lillqvist's avatar
Tor Lillqvist committed
632 633
			 gint   n)
{
634 635 636 637
  GdkGCWin32 *win32_gc;

  g_return_if_fail (GDK_IS_GC (gc));
  g_return_if_fail (dash_list != NULL);
Tor Lillqvist's avatar
Tor Lillqvist committed
638

639 640
  win32_gc = GDK_GC_WIN32 (gc);

641 642 643
  /* mark as set, see gdk_win32_gc_values_to_win32values () for the reason */
  win32_gc->values_mask |= GDK_GC_LINE_STYLE;

644
  win32_gc->pen_style &= ~(PS_STYLE_MASK);
645 646 647 648 649 650 651 652 653 654 655

  /* 
   * Set the extended line style. This could be done by 
   * PS_USERSTYLE and ExtCreatePen; but ONLY on WinNT, 
   * so let's make a guess (based on the implementation 
   * in DIA). On Win9x this does only work for lines
   * with width one ...
   *
   * More workarounds for Win9x descibed at:
   * http://www.codeguru.com/gdi/dashed.shtml
   */
Tor Lillqvist's avatar
Tor Lillqvist committed
656
  if (!IS_WIN_NT () && win32_gc->pen_width > 1)
657 658
    {
      GDK_NOTE (MISC, g_print ("gdk_win32_gc_set_dashes: not fully supported\n"));
659
      win32_gc->pen_style |= PS_SOLID;
660 661 662
      return;
    }
  
Hans Breuer's avatar
Hans Breuer committed
663
  win32_gc->pen_style = PS_COSMETIC; /* ??? */
664 665 666 667
  if (2 == n)
    {
      if ((dash_list[0] == dash_list[1]) && (dash_list[0] > 2))
        {
668
          win32_gc->pen_style |= PS_DASH;
669 670 671 672 673
          GDK_NOTE (MISC, g_print("gdk_win32_gc_set_dashes: PS_DASH (%d,%d)\n", 
                                  dash_list[0], dash_list[1]));
        }
      else
        {
674
          win32_gc->pen_style |= PS_DOT;
675 676 677 678 679 680
          GDK_NOTE (MISC, g_print("gdk_win32_gc_set_dashes: PS_DOT (%d,%d)\n", 
                                  dash_list[0], dash_list[1]));
        }
    }
  else if (4 == n)
    {
681
      win32_gc->pen_style |= PS_DASHDOT; 
682 683 684 685 686 687
      GDK_NOTE (MISC, g_print("gdk_win32_gc_set_dashes: PS_DASHDOT (%d,%d,%d,%d)\n", 
                              dash_list[0], dash_list[1],
                              dash_list[2], dash_list[3]));
    }
  else if (6 == n)
    {
688
      win32_gc->pen_style |= PS_DASHDOTDOT; 
689 690 691 692 693 694 695
      GDK_NOTE (MISC, g_print("gdk_win32_gc_set_dashes: PS_DASHDOTDOT (%d,%d,%d,%d,%d,%d)\n", 
                              dash_list[0], dash_list[1],
                              dash_list[2], dash_list[3],
                              dash_list[4], dash_list[5]));
    }
  else
    {
696
      win32_gc->pen_style |= PS_DASH;
697 698
      GDK_NOTE (MISC, g_print("gdk_win32_gc_set_dashes: no guess for %d dashes\n", n));
    }
699 700 701 702 703 704
}

void
gdk_gc_set_clip_rectangle (GdkGC	*gc,
			   GdkRectangle *rectangle)
{
705 706 707
  GdkGCWin32 *win32_gc;

  g_return_if_fail (GDK_IS_GC (gc));
708

709
  win32_gc = GDK_GC_WIN32 (gc);
710

711 712 713 714 715 716
  if (win32_gc->hcliprgn)
    {
      DeleteObject (win32_gc->hcliprgn);
      win32_gc->hcliprgn = NULL;
    }

717 718
  if (win32_gc->clip_region)
    gdk_region_destroy (win32_gc->clip_region);
719

720 721 722
  if (rectangle)
    {
      GDK_NOTE (MISC,
723
		g_print ("gdk_gc_set_clip_rectangle: %dx%d@+%d+%d\n",
724 725
			 rectangle->width, rectangle->height,
			 rectangle->x, rectangle->y));
726 727
      win32_gc->clip_region = gdk_region_rectangle (rectangle);
      win32_gc->values_mask |= GDK_GC_CLIP_MASK;
728 729 730
    }
  else
    {
731 732
      GDK_NOTE (MISC, g_print ("gdk_gc_set_clip_rectangle: NULL\n"));

733 734
      win32_gc->clip_region = NULL;
      win32_gc->values_mask &= ~GDK_GC_CLIP_MASK;
735
    }
736
    win32_gc->values_mask &= ~(GDK_GC_CLIP_X_ORIGIN | GDK_GC_CLIP_Y_ORIGIN);
737 738 739 740 741 742
} 

void
gdk_gc_set_clip_region (GdkGC		 *gc,
			GdkRegion	 *region)
{
743
  GdkGCWin32 *win32_gc;
744

745
  g_return_if_fail (GDK_IS_GC (gc));
746

747
  win32_gc = GDK_GC_WIN32 (gc);
748

749 750
  if (win32_gc->clip_region)
    gdk_region_destroy (win32_gc->clip_region);
751 752 753

  if (region)
    {
754
      GDK_NOTE (MISC, g_print ("gdk_gc_set_clip_region: %dx%d+%d+%d\n",
755 756 757
			       region->extents.x2 - region->extents.x1,
			       region->extents.y2 - region->extents.y1,
			       region->extents.x1, region->extents.y1));
758

759 760
      win32_gc->clip_region = gdk_region_copy (region);
      win32_gc->values_mask |= GDK_GC_CLIP_MASK;
761 762 763
    }
  else
    {
764 765
      GDK_NOTE (MISC, g_print ("gdk_gc_set_clip_region: NULL\n"));

766 767
      win32_gc->clip_region = NULL;
      win32_gc->values_mask &= ~GDK_GC_CLIP_MASK;
768
    }
769

770 771
  gc->clip_x_origin = 0;
  gc->clip_y_origin = 0;
772

773
  win32_gc->values_mask &= ~(GDK_GC_CLIP_X_ORIGIN | GDK_GC_CLIP_Y_ORIGIN);
774 775 776
}

void
777 778
gdk_gc_copy (GdkGC *dst_gc,
	     GdkGC *src_gc)
779
{
Tor Lillqvist's avatar
Tor Lillqvist committed
780 781
  GdkGCWin32 *dst_win32_gc;
  GdkGCWin32 *src_win32_gc;
Tor Lillqvist's avatar
Tor Lillqvist committed
782

783 784 785 786 787 788 789 790 791 792 793 794 795 796
  g_return_if_fail (GDK_IS_GC_WIN32 (dst_gc));
  g_return_if_fail (GDK_IS_GC_WIN32 (src_gc));
  
  dst_win32_gc = GDK_GC_WIN32 (dst_gc);
  src_win32_gc = GDK_GC_WIN32 (src_gc);

  if (dst_win32_gc->font != NULL)
    gdk_font_unref (dst_win32_gc->font);
  if (dst_win32_gc->tile != NULL)
    gdk_drawable_unref (dst_win32_gc->tile);
  if (dst_win32_gc->stipple != NULL)
    gdk_drawable_unref (dst_win32_gc->stipple);
  if (dst_win32_gc->clip_region != NULL)
    gdk_region_destroy (dst_win32_gc->clip_region);
797 798
  if (dst_win32_gc->hcliprgn != NULL)
    DeleteObject (dst_win32_gc->hcliprgn);
Tor Lillqvist's avatar
Tor Lillqvist committed
799
  
800 801
  *dst_win32_gc = *src_win32_gc;

802 803 804 805 806 807 808 809
  if (dst_win32_gc->hcliprgn)
    {
      /* create a new region, to copy to */
      dst_win32_gc->hcliprgn = CreateRectRgn(0,0,1,1);
      /* overwrite from source */
      CombineRgn (dst_win32_gc->hcliprgn, src_win32_gc->hcliprgn,
		  NULL, RGN_COPY);
    }
810 811 812 813 814 815 816 817
  if (dst_win32_gc->clip_region != NULL)
    dst_win32_gc->clip_region = gdk_region_copy (dst_win32_gc->clip_region);
  if (dst_win32_gc->font != NULL)
    gdk_font_ref (dst_win32_gc->font);
  if (dst_win32_gc->tile != NULL)
    gdk_drawable_ref (dst_win32_gc->tile);
  if (dst_win32_gc->stipple != NULL)
    gdk_drawable_ref (dst_win32_gc->stipple);
818 819
}

820 821 822
static guint bitmask[9] = { 0, 1, 3, 7, 15, 31, 63, 127, 255 };

COLORREF
Tor Lillqvist's avatar
Tor Lillqvist committed
823 824
gdk_colormap_color (GdkColormap *colormap,
		    gulong       pixel)
825
{
Tor Lillqvist's avatar
Tor Lillqvist committed
826 827
  const GdkVisual *visual;
  GdkColormapPrivateWin32 *colormap_private;
828 829
  guchar r, g, b;

Tor Lillqvist's avatar
Tor Lillqvist committed
830
  if (colormap == NULL)
831
    return PALETTEINDEX (pixel);
Tor Lillqvist's avatar
Tor Lillqvist committed
832 833 834

  colormap_private = GDK_COLORMAP_PRIVATE_DATA (colormap);

835 836
  g_return_val_if_fail(colormap_private != NULL, RGB (0,0,0));

Tor Lillqvist's avatar
Tor Lillqvist committed
837 838 839 840 841 842 843 844 845 846 847 848
  if (colormap_private->xcolormap->rc_palette)
    return PALETTEINDEX (pixel);

  visual = colormap->visual;
  r = (pixel & visual->red_mask) >> visual->red_shift;
  r = (r * 255) / bitmask[visual->red_prec];
  g = (pixel & visual->green_mask) >> visual->green_shift;
  g = (g * 255) / bitmask[visual->green_prec];
  b = (pixel & visual->blue_mask) >> visual->blue_shift;
  b = (b * 255) / bitmask[visual->blue_prec];
  
  return RGB (r, g, b);
849
}
850 851

static void
Tor Lillqvist's avatar
Tor Lillqvist committed
852 853 854
predraw_set_foreground (GdkGC       *gc,
			GdkColormap *colormap,
			gboolean    *ok)
855
{
Tor Lillqvist's avatar
Tor Lillqvist committed
856 857
  GdkGCWin32 *win32_gc = (GdkGCWin32 *) gc;
  GdkColormapPrivateWin32 *colormap_private;
858 859 860 861 862
  COLORREF fg;
  LOGBRUSH logbrush;
  HPEN hpen;
  HBRUSH hbr;