gdkgc-win32.c 43.2 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 286 287 288 289 290 291 292 293 294 295 296 297

	  if (sw != 8 || sh != 8)
	    {
	      /* 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)
		    {
298
		      gdk_draw_drawable (bm, gc, win32_gc->stipple, 0, 0, i, j, sw, sh);
299 300 301 302
		      j += sh;
		    }
		  i += sw;
		}
303
	      win32_gc->stipple = bm;
304 305 306
	      gdk_gc_unref (gc);
	    }
	  else
307 308
	    gdk_drawable_ref (win32_gc->stipple);
	  win32_gc->values_mask |= GDK_GC_STIPPLE;
309 310 311 312
	  GDK_NOTE (MISC,
		    (g_print ("%sstipple=%#x", s,
			      (guint) GDK_PIXMAP_HBITMAP (win32_gc->stipple)),
		     s = ","));
313 314 315
	}
      else
	{
316
	  win32_gc->values_mask &= ~GDK_GC_STIPPLE;
317 318 319
	  GDK_NOTE (MISC, (g_print ("%sstipple=NULL", s),
			   s = ","));
	}
320 321
    }

322
  if (mask & GDK_GC_CLIP_MASK)
323
    {
324
      if (win32_gc->clip_region != NULL)
325
	{
326 327
	  gdk_region_destroy (win32_gc->clip_region);
	  win32_gc->clip_region = NULL;
328
	}
329

330
      if (win32_gc->hcliprgn != NULL)
331 332 333 334
	{
	  DeleteObject (win32_gc->hcliprgn);
	  win32_gc->hcliprgn = NULL;
	}
335

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

351
  if (mask & GDK_GC_SUBWINDOW)
352
    {
353 354 355
      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),
356
		       s = ","));
357 358
    }

359
  if (mask & GDK_GC_TS_X_ORIGIN)
360
    {
361
      win32_gc->values_mask |= GDK_GC_TS_X_ORIGIN;
362
      GDK_NOTE (MISC, (g_print ("%sts_x=%d", s, values->ts_x_origin),
363
		       s = ","));
364 365
    }

366
  if (mask & GDK_GC_TS_Y_ORIGIN)
367
    {
368
      win32_gc->values_mask |= GDK_GC_TS_Y_ORIGIN;
369
      GDK_NOTE (MISC, (g_print ("%sts_y=%d", s, values->ts_y_origin),
370
		       s = ","));
371 372
    }

373
  if (mask & GDK_GC_CLIP_X_ORIGIN)
374
    {
375
      win32_gc->values_mask |= GDK_GC_CLIP_X_ORIGIN;
376
      GDK_NOTE (MISC, (g_print ("%sclip_x=%d", s, values->clip_x_origin),
377
		       s = ","));
378 379
    }

380
  if (mask & GDK_GC_CLIP_Y_ORIGIN)
381
    {
382
      win32_gc->values_mask |= GDK_GC_CLIP_Y_ORIGIN;
383
      GDK_NOTE (MISC, (g_print ("%sclip_y=%d", s, values->clip_y_origin),
384
		       s = ","));
Hans Breuer's avatar
updated  
Hans Breuer committed
385 386
    }

387
  if (mask & GDK_GC_EXPOSURES)
388
    {
389 390 391
      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),
392
		       s = ","));
393 394
    }

395 396
  if (mask & GDK_GC_LINE_WIDTH)
    {
397 398 399
      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),
400 401
		       s = ","));
    }
402

403
  if (mask & GDK_GC_LINE_STYLE)
404
    {
405
      win32_gc->pen_style &= ~(PS_STYLE_MASK);
406 407 408
      GDK_NOTE (MISC, (g_print ("%sps|=", s),
		       s = ","));
      switch (values->line_style)
409
	{
410 411
	case GDK_LINE_SOLID:
	  GDK_NOTE (MISC, g_print ("LINE_SOLID"));
412
	  win32_gc->pen_style |= PS_SOLID;
413 414 415 416
	  break;
	case GDK_LINE_ON_OFF_DASH:
	case GDK_LINE_DOUBLE_DASH: /* ??? */
	  GDK_NOTE (MISC, g_print ("DASH"));
417
	  win32_gc->pen_style |= PS_DASH;
418
	  break;
419
	}
420
      win32_gc->values_mask |= GDK_GC_LINE_STYLE;
421 422
    }

423
  if (mask & GDK_GC_CAP_STYLE)
424
    {
425
      win32_gc->pen_style &= ~(PS_ENDCAP_MASK);
426 427
      GDK_NOTE (MISC, (g_print ("%sps|=", s),
		       s = ","));
428 429 430 431
      switch (values->cap_style)
	{
	case GDK_CAP_NOT_LAST:	/* ??? */
	case GDK_CAP_BUTT:
432
	  GDK_NOTE (MISC, g_print ("ENDCAP_FLAT"));
433
	  win32_gc->pen_style |= PS_ENDCAP_FLAT;
434
	  break;
435
	case GDK_CAP_ROUND:
436
	  GDK_NOTE (MISC, g_print ("ENDCAP_ROUND"));
437
	  win32_gc->pen_style |= PS_ENDCAP_ROUND;
438
	  break;
439
	case GDK_CAP_PROJECTING:
440
	  GDK_NOTE (MISC, g_print ("ENDCAP_SQUARE"));
441
	  win32_gc->pen_style |= PS_ENDCAP_SQUARE;
442
	  break;
443
	}
444
      win32_gc->values_mask |= GDK_GC_CAP_STYLE;
445 446
    }

447
  if (mask & GDK_GC_JOIN_STYLE)
448
    {
449
      win32_gc->pen_style &= ~(PS_JOIN_MASK);
450 451
      GDK_NOTE (MISC, (g_print ("%sps|=", s),
		       s = ","));
452 453 454
      switch (values->join_style)
	{
	case GDK_JOIN_MITER:
455
	  GDK_NOTE (MISC, g_print ("JOIN_MITER"));
456
	  win32_gc->pen_style |= PS_JOIN_MITER;
457 458
	  break;
	case GDK_JOIN_ROUND:
459
	  GDK_NOTE (MISC, g_print ("JOIN_ROUND"));
460
	  win32_gc->pen_style |= PS_JOIN_ROUND;
461 462
	  break;
	case GDK_JOIN_BEVEL:
463
	  GDK_NOTE (MISC, g_print ("JOIN_BEVEL"));
464
	  win32_gc->pen_style |= PS_JOIN_BEVEL;
465 466
	  break;
	}
467
      win32_gc->values_mask |= GDK_GC_JOIN_STYLE;
468 469 470 471 472 473 474 475 476 477
    }
  GDK_NOTE (MISC, g_print ("}\n"));
}

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

480 481 482 483
  /* 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);
484

485 486 487 488 489 490
  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;
491

492 493 494
  /* 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.
   */
495 496 497 498 499 500 501 502 503 504 505
  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;
506 507

  GDK_NOTE (MISC, g_print ("_gdk_win32_gc_new: "));
508
  gdk_win32_gc_values_to_win32values (values, mask, win32_gc);
509

510
  win32_gc->hwnd = NULL;
511

512
  GDK_NOTE (MISC, g_print (" = %p\n", gc));
513 514 515 516

  return gc;
}

Tor Lillqvist's avatar
Tor Lillqvist committed
517 518 519
static void
gdk_win32_gc_get_values (GdkGC       *gc,
			 GdkGCValues *values)
520
{
521
  GdkGCWin32 *win32_gc = GDK_GC_WIN32 (gc);
522

523 524 525
  values->foreground.pixel = win32_gc->foreground;
  values->background.pixel = win32_gc->background;
  values->font = win32_gc->font;
526

527
  switch (win32_gc->rop2)
528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556
    {
    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;
557 558
    case R2_NOTMERGEPEN:
      values->function = GDK_NOR; break;
559 560 561 562
    case R2_WHITE:
      values->function = GDK_SET; break;
    }

563
  values->fill = win32_gc->fill_style;
564

565 566
  values->tile = win32_gc->tile;
  values->stipple = win32_gc->stipple;
567

568 569 570
  /* Also the X11 backend always returns a NULL clip_mask */
  values->clip_mask = NULL;

571 572 573 574 575 576 577
  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;
578
  
579
  if (win32_gc->pen_style & PS_SOLID)
580
    values->line_style = GDK_LINE_SOLID;
581
  else if (win32_gc->pen_style & PS_DASH)
582 583 584 585 586
    values->line_style = GDK_LINE_ON_OFF_DASH;
  else
    values->line_style = GDK_LINE_SOLID;

  /* PS_ENDCAP_ROUND is zero */
587
  if (win32_gc->pen_style & PS_ENDCAP_FLAT)
588
    values->cap_style = GDK_CAP_BUTT;
589
  else if (win32_gc->pen_style & PS_ENDCAP_SQUARE)
590 591 592 593 594
    values->cap_style = GDK_CAP_PROJECTING;
  else
    values->cap_style = GDK_CAP_ROUND;
    
  /* PS_JOIN_ROUND is zero */
595
  if (win32_gc->pen_style & PS_JOIN_MITER)
596
    values->join_style = GDK_JOIN_MITER;
597
  else if (win32_gc->pen_style & PS_JOIN_BEVEL)
598 599 600 601 602
    values->join_style = GDK_JOIN_BEVEL;
  else
    values->join_style = GDK_JOIN_ROUND;
}

Tor Lillqvist's avatar
Tor Lillqvist committed
603 604 605
static void
gdk_win32_gc_set_values (GdkGC           *gc,
			 GdkGCValues     *values,
606
			 GdkGCValuesMask  mask)
607
{
608 609
  g_return_if_fail (GDK_IS_GC (gc));

610
  GDK_NOTE (MISC, g_print ("gdk_win32_gc_set_values: "));
611 612

  gdk_win32_gc_values_to_win32values (values, mask, GDK_GC_WIN32 (gc));
Tor Lillqvist's avatar
Tor Lillqvist committed
613 614 615 616
}

static void
gdk_win32_gc_set_dashes (GdkGC *gc,
617 618
			 gint	dash_offset,
			 gint8  dash_list[],
Tor Lillqvist's avatar
Tor Lillqvist committed
619 620
			 gint   n)
{
621 622 623 624
  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
625

626 627 628 629
  win32_gc = GDK_GC_WIN32 (gc);

  win32_gc->pen_style &= ~(PS_STYLE_MASK);
  win32_gc->pen_style |= PS_DASH;
630 631 632 633 634 635 636 637 638 639 640

  /* 
   * 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
641
  if (!IS_WIN_NT () && win32_gc->pen_width > 1)
642 643
    {
      GDK_NOTE (MISC, g_print ("gdk_win32_gc_set_dashes: not fully supported\n"));
644
      win32_gc->pen_style |= PS_SOLID;
645 646 647
      return;
    }
  
648
  /* win32_gc->pen_style = PS_COSMETIC; ??? */
649 650 651 652
  if (2 == n)
    {
      if ((dash_list[0] == dash_list[1]) && (dash_list[0] > 2))
        {
653
          win32_gc->pen_style |= PS_DASH;
654 655 656 657 658
          GDK_NOTE (MISC, g_print("gdk_win32_gc_set_dashes: PS_DASH (%d,%d)\n", 
                                  dash_list[0], dash_list[1]));
        }
      else
        {
659
          win32_gc->pen_style |= PS_DOT;
660 661 662 663 664 665
          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)
    {
666
      win32_gc->pen_style |= PS_DASHDOT; 
667 668 669 670 671 672
      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)
    {
673
      win32_gc->pen_style |= PS_DASHDOTDOT; 
674 675 676 677 678 679 680
      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
    {
681
      win32_gc->pen_style |= PS_DASH;
682 683
      GDK_NOTE (MISC, g_print("gdk_win32_gc_set_dashes: no guess for %d dashes\n", n));
    }
684 685 686 687 688 689
}

void
gdk_gc_set_clip_rectangle (GdkGC	*gc,
			   GdkRectangle *rectangle)
{
690 691 692
  GdkGCWin32 *win32_gc;

  g_return_if_fail (GDK_IS_GC (gc));
693

694
  win32_gc = GDK_GC_WIN32 (gc);
695

696 697 698 699 700 701
  if (win32_gc->hcliprgn)
    {
      DeleteObject (win32_gc->hcliprgn);
      win32_gc->hcliprgn = NULL;
    }

702 703
  if (win32_gc->clip_region)
    gdk_region_destroy (win32_gc->clip_region);
704

705 706 707
  if (rectangle)
    {
      GDK_NOTE (MISC,
708
		g_print ("gdk_gc_set_clip_rectangle: %dx%d@+%d+%d\n",
709 710
			 rectangle->width, rectangle->height,
			 rectangle->x, rectangle->y));
711 712
      win32_gc->clip_region = gdk_region_rectangle (rectangle);
      win32_gc->values_mask |= GDK_GC_CLIP_MASK;
713 714 715
    }
  else
    {
716 717
      GDK_NOTE (MISC, g_print ("gdk_gc_set_clip_rectangle: NULL\n"));

718 719
      win32_gc->clip_region = NULL;
      win32_gc->values_mask &= ~GDK_GC_CLIP_MASK;
720
    }
721
    win32_gc->values_mask &= ~(GDK_GC_CLIP_X_ORIGIN | GDK_GC_CLIP_Y_ORIGIN);
722 723 724 725 726 727
} 

void
gdk_gc_set_clip_region (GdkGC		 *gc,
			GdkRegion	 *region)
{
728
  GdkGCWin32 *win32_gc;
729

730
  g_return_if_fail (GDK_IS_GC (gc));
731

732
  win32_gc = GDK_GC_WIN32 (gc);
733

734 735
  if (win32_gc->clip_region)
    gdk_region_destroy (win32_gc->clip_region);
736 737 738

  if (region)
    {
739
      GDK_NOTE (MISC, g_print ("gdk_gc_set_clip_region: %dx%d+%d+%d\n",
740 741 742
			       region->extents.x2 - region->extents.x1,
			       region->extents.y2 - region->extents.y1,
			       region->extents.x1, region->extents.y1));
743

744 745
      win32_gc->clip_region = gdk_region_copy (region);
      win32_gc->values_mask |= GDK_GC_CLIP_MASK;
746 747 748
    }
  else
    {
749 750
      GDK_NOTE (MISC, g_print ("gdk_gc_set_clip_region: NULL\n"));

751 752
      win32_gc->clip_region = NULL;
      win32_gc->values_mask &= ~GDK_GC_CLIP_MASK;
753
    }
754

755 756
  gc->clip_x_origin = 0;
  gc->clip_y_origin = 0;
757

758
  win32_gc->values_mask &= ~(GDK_GC_CLIP_X_ORIGIN | GDK_GC_CLIP_Y_ORIGIN);
759 760 761
}

void
762 763
gdk_gc_copy (GdkGC *dst_gc,
	     GdkGC *src_gc)
764
{
Tor Lillqvist's avatar
Tor Lillqvist committed
765 766
  GdkGCWin32 *dst_win32_gc;
  GdkGCWin32 *src_win32_gc;
Tor Lillqvist's avatar
Tor Lillqvist committed
767

768 769 770 771 772 773 774 775 776 777 778 779 780 781
  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);
782 783
  if (dst_win32_gc->hcliprgn != NULL)
    DeleteObject (dst_win32_gc->hcliprgn);
Tor Lillqvist's avatar
Tor Lillqvist committed
784
  
785 786
  *dst_win32_gc = *src_win32_gc;

787 788 789 790 791 792 793 794
  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);
    }
795 796 797 798 799 800 801 802
  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);
803 804
}

805 806 807
static guint bitmask[9] = { 0, 1, 3, 7, 15, 31, 63, 127, 255 };

COLORREF
Tor Lillqvist's avatar
Tor Lillqvist committed
808 809
gdk_colormap_color (GdkColormap *colormap,
		    gulong       pixel)
810
{
Tor Lillqvist's avatar
Tor Lillqvist committed
811 812
  const GdkVisual *visual;
  GdkColormapPrivateWin32 *colormap_private;
813 814
  guchar r, g, b;

Tor Lillqvist's avatar
Tor Lillqvist committed
815
  if (colormap == NULL)
816
    return PALETTEINDEX (pixel);
Tor Lillqvist's avatar
Tor Lillqvist committed
817 818 819

  colormap_private = GDK_COLORMAP_PRIVATE_DATA (colormap);

820 821
  g_return_val_if_fail(colormap_private != NULL, RGB (0,0,0));

Tor Lillqvist's avatar
Tor Lillqvist committed
822 823 824 825 826 827 828 829 830 831 832 833
  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);
834
}
835 836

static void
Tor Lillqvist's avatar
Tor Lillqvist committed
837 838 839
predraw_set_foreground (GdkGC       *gc,
			GdkColormap *colormap,
			gboolean    *ok)
840
{
Tor Lillqvist's avatar
Tor Lillqvist committed
841 842
  GdkGCWin32 *win32_gc = (GdkGCWin32 *) gc;
  GdkColormapPrivateWin32 *colormap_private;
843 844 845 846 847
  COLORREF fg;
  LOGBRUSH logbrush;
  HPEN hpen;
  HBRUSH hbr;

Tor Lillqvist's avatar
Tor Lillqvist committed
848
  if (colormap == NULL)
849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872
    {
      /* A 1 bit deep bitmap */
      struct
      {
	WORD palVersion;
	WORD palNumEntries;
	PALETTEENTRY palPalEntry[2];
      } logpal;
      static HPALETTE hpal = NULL;

      if (hpal == NULL)
	{
	  /* Create a b&w palette */
	  logpal.palVersion = 0x300;
	  logpal.palNumEntries = 2;
	  logpal.palPalEntry[0].peRed = 
	    logpal.palPalEntry[0].peGreen = 
	    logpal.palPalEntry[0].peBlue = 0x00;
	  logpal.palPalEntry[0].peFlags = 0x00;
	  logpal.palPalEntry[1].peRed = 
	    logpal.palPalEntry[