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

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

Tor Lillqvist's avatar
Tor Lillqvist committed
28 29 30
#define LINE_ATTRIBUTES (GDK_GC_LINE_WIDTH|GDK_GC_LINE_STYLE| \
			 GDK_GC_CAP_STYLE|GDK_GC_JOIN_STYLE)

31 32 33 34 35
#include <string.h>

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

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,
46
				     gint8            dash_list[],
Tor Lillqvist's avatar
Tor Lillqvist committed
47 48
				     gint             n);

49 50 51 52 53 54
static void gdk_gc_win32_class_init (GdkGCWin32Class *klass);
static void gdk_gc_win32_finalize   (GObject         *object);

static gpointer parent_class = NULL;

GType
55
_gdk_gc_win32_get_type (void)
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
{
  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
76
                                            &object_info, 0);
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
    }
  
  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);
  
102 103
  if (win32_gc->hcliprgn != NULL)
    DeleteObject (win32_gc->hcliprgn);
104 105 106 107 108 109 110 111 112
  
  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);
113 114 115

  if (win32_gc->pen_dashes)
    g_free (win32_gc->pen_dashes);
116 117 118
  
  G_OBJECT_CLASS (parent_class)->finalize (object);
}
119

120 121 122
static void
gdk_win32_gc_values_to_win32values (GdkGCValues    *values,
				    GdkGCValuesMask mask,
123
				    GdkGCWin32     *win32_gc)
124 125
{				    
  char *s = "";
126
  gint sw, sh;
127

128
  GDK_NOTE (GC, g_print ("{"));
129

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

146 147
  if ((mask & GDK_GC_FONT) && (values->font->type == GDK_FONT_FONT
			       || values->font->type == GDK_FONT_FONTSET))
148
    {
149 150 151 152
      if (win32_gc->font != NULL)
	gdk_font_unref (win32_gc->font);
      win32_gc->font = values->font;
      if (win32_gc->font != NULL)
153
	{
154 155
	  gdk_font_ref (win32_gc->font);
	  win32_gc->values_mask |= GDK_GC_FONT;
156 157
	  GDK_NOTE (GC, (g_print ("%sfont=%p", s, win32_gc->font),
			 s = ","));
158 159 160
	}
      else
	{
161
	  win32_gc->values_mask &= ~GDK_GC_FONT;
162 163
	  GDK_NOTE (GC, (g_print ("%sfont=NULL", s),
			 s = ","));
164
	}
165 166
    }

167
  if (mask & GDK_GC_FUNCTION)
168
    {
169 170
      GDK_NOTE (GC, (g_print ("%srop2=", s),
		     s = ","));
171 172
      switch (values->function)
	{
173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190
#define CASE(x,y) case GDK_##x: win32_gc->rop2 = R2_##y; GDK_NOTE (GC, g_print (#y)); break
	CASE (COPY, COPYPEN);
	CASE (INVERT, NOT);
	CASE (XOR, XORPEN);
	CASE (CLEAR, BLACK);
	CASE (AND, MASKPEN);
	CASE (AND_REVERSE, MASKPENNOT);
	CASE (AND_INVERT, MASKNOTPEN);
	CASE (NOOP, NOP);
	CASE (OR, MERGEPEN);
	CASE (EQUIV, NOTXORPEN);
	CASE (OR_REVERSE, MERGEPENNOT);
	CASE (COPY_INVERT, NOTCOPYPEN);
	CASE (OR_INVERT, MERGENOTPEN);
	CASE (NAND, NOTMASKPEN);
	CASE (NOR, NOTMERGEPEN);
	CASE (SET, WHITE);
#undef CASE
191
	}
192
      win32_gc->values_mask |= GDK_GC_FUNCTION;
193 194
    }

195
  if (mask & GDK_GC_FILL)
196
    {
197 198
      win32_gc->fill_style = values->fill;
      win32_gc->values_mask |= GDK_GC_FILL;
199 200
      GDK_NOTE (GC, (g_print ("%sfill=%s", s,
			      _gdk_win32_fill_style_to_string (win32_gc->fill_style)),
201
		     s = ","));
202 203
    }

204
  if (mask & GDK_GC_TILE)
205
    {
206 207 208 209
      if (win32_gc->tile != NULL)
	gdk_drawable_unref (win32_gc->tile);
      win32_gc->tile = values->tile;
      if (win32_gc->tile != NULL)
210
	{
211 212
	  gdk_drawable_ref (win32_gc->tile);
	  win32_gc->values_mask |= GDK_GC_TILE;
213 214 215
	  GDK_NOTE (GC,
		    (g_print ("%stile=%p", s,
			      GDK_PIXMAP_HBITMAP (win32_gc->tile)),
216
		     s = ","));
217 218 219
	}
      else
	{
220
	  win32_gc->values_mask &= ~GDK_GC_TILE;
221 222
	  GDK_NOTE (GC, (g_print ("%stile=NULL", s),
			 s = ","));
223
	}
224 225
    }

226
  if (mask & GDK_GC_STIPPLE)
227
    {
228 229 230 231
      if (win32_gc->stipple != NULL)
	gdk_drawable_unref (win32_gc->stipple);
      win32_gc->stipple = values->stipple;
      if (win32_gc->stipple != NULL)
232
	{
233
	  gdk_drawable_get_size (win32_gc->stipple, &sw, &sh);
234

235 236 237 238 239 240
#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 */
241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257
	    {
	      /* 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)
		    {
258
		      gdk_draw_drawable (bm, gc, win32_gc->stipple, 0, 0, i, j, sw, sh);
259 260 261 262
		      j += sh;
		    }
		  i += sw;
		}
263
	      win32_gc->stipple = bm;
264 265 266
	      gdk_gc_unref (gc);
	    }
	  else
267
#endif
268 269
	    gdk_drawable_ref (win32_gc->stipple);
	  win32_gc->values_mask |= GDK_GC_STIPPLE;
270 271 272
	  GDK_NOTE (GC,
		    (g_print ("%sstipple=%p", s,
			      GDK_PIXMAP_HBITMAP (win32_gc->stipple)),
273
		     s = ","));
274 275 276
	}
      else
	{
277
	  win32_gc->values_mask &= ~GDK_GC_STIPPLE;
278 279
	  GDK_NOTE (GC, (g_print ("%sstipple=NULL", s),
			 s = ","));
280
	}
281 282
    }

283
  if (mask & GDK_GC_CLIP_MASK)
284
    {
285
      if (win32_gc->hcliprgn != NULL)
286
	DeleteObject (win32_gc->hcliprgn);
287

288 289
      if (values->clip_mask != NULL)
	{
290
	  win32_gc->hcliprgn = _gdk_win32_bitmap_to_hrgn (values->clip_mask);
291
	  win32_gc->values_mask |= GDK_GC_CLIP_MASK;
292 293 294
	}
      else
	{
295 296
	  win32_gc->hcliprgn = NULL;
	  win32_gc->values_mask &= ~GDK_GC_CLIP_MASK;
297
	}
298 299
      GDK_NOTE (GC, (g_print ("%sclip=%p", s, win32_gc->hcliprgn),
		     s = ","));
300 301
    }

302
  if (mask & GDK_GC_SUBWINDOW)
303
    {
304 305
      win32_gc->subwindow_mode = values->subwindow_mode;
      win32_gc->values_mask |= GDK_GC_SUBWINDOW;
306 307
      GDK_NOTE (GC, (g_print ("%ssubw=%d", s, win32_gc->subwindow_mode),
		     s = ","));
308 309
    }

310
  if (mask & GDK_GC_TS_X_ORIGIN)
311
    {
312
      win32_gc->values_mask |= GDK_GC_TS_X_ORIGIN;
313 314
      GDK_NOTE (GC, (g_print ("%sts_x=%d", s, values->ts_x_origin),
		     s = ","));
315 316
    }

317
  if (mask & GDK_GC_TS_Y_ORIGIN)
318
    {
319
      win32_gc->values_mask |= GDK_GC_TS_Y_ORIGIN;
320 321
      GDK_NOTE (GC, (g_print ("%sts_y=%d", s, values->ts_y_origin),
		     s = ","));
322 323
    }

324
  if (mask & GDK_GC_CLIP_X_ORIGIN)
325
    {
326
      win32_gc->values_mask |= GDK_GC_CLIP_X_ORIGIN;
327 328
      GDK_NOTE (GC, (g_print ("%sclip_x=%d", s, values->clip_x_origin),
		     s = ","));
329 330
    }

331
  if (mask & GDK_GC_CLIP_Y_ORIGIN)
332
    {
333
      win32_gc->values_mask |= GDK_GC_CLIP_Y_ORIGIN;
334 335
      GDK_NOTE (GC, (g_print ("%sclip_y=%d", s, values->clip_y_origin),
		     s = ","));
Hans Breuer's avatar
updated  
Hans Breuer committed
336 337
    }

338
  if (mask & GDK_GC_EXPOSURES)
339
    {
340 341
      win32_gc->graphics_exposures = values->graphics_exposures;
      win32_gc->values_mask |= GDK_GC_EXPOSURES;
342 343
      GDK_NOTE (GC, (g_print ("%sexp=%d", s, win32_gc->graphics_exposures),
		     s = ","));
344 345
    }

346 347
  if (mask & GDK_GC_LINE_WIDTH)
    {
348 349
      win32_gc->pen_width = values->line_width;
      win32_gc->values_mask |= GDK_GC_LINE_WIDTH;
350 351
      GDK_NOTE (GC, (g_print ("%spw=%d", s, win32_gc->pen_width),
		     s = ","));
352
    }
353

354
  if (mask & GDK_GC_LINE_STYLE)
355
    {
356
      switch (values->line_style)
357
	{
358
	case GDK_LINE_SOLID:
359 360 361 362 363 364 365
	  if (win32_gc->pen_dashes)
	    {
	      g_free (win32_gc->pen_dashes);
	      win32_gc->pen_dashes = NULL;
            win32_gc->pen_num_dashes = 0;
	    }
          win32_gc->pen_style &= ~(PS_STYLE_MASK);
366
	  win32_gc->pen_style |= PS_SOLID;
367 368
	  break;
	case GDK_LINE_ON_OFF_DASH:
369 370
	case GDK_LINE_DOUBLE_DASH: 
	  if (!win32_gc->pen_dashes)
371
	    {
372 373 374 375
            /* setting to PS_DASH probably isn't correct. If I understand the
             * xlib docs correctly it should influence the handling of
             * line endings ? --hb
             */
376
            win32_gc->pen_style &= ~(PS_STYLE_MASK);
377
	    win32_gc->pen_style |= PS_DASH;
378
          }
379
	  break;
380
	}
381 382
      GDK_NOTE (GC, (g_print ("%sps|=PS_STYLE_%s", s, _gdk_win32_psstyle_to_string (win32_gc->pen_style)),
		     s = ","));
383
      win32_gc->values_mask |= GDK_GC_LINE_STYLE;
384 385
    }

386
  if (mask & GDK_GC_CAP_STYLE)
387
    {
388
      win32_gc->pen_style &= ~(PS_ENDCAP_MASK);
389 390 391 392
      switch (values->cap_style)
	{
	case GDK_CAP_NOT_LAST:	/* ??? */
	case GDK_CAP_BUTT:
393
	  win32_gc->pen_style |= PS_ENDCAP_FLAT;
394
	  break;
395
	case GDK_CAP_ROUND:
396
	  win32_gc->pen_style |= PS_ENDCAP_ROUND;
397
	  break;
398
	case GDK_CAP_PROJECTING:
399
	  win32_gc->pen_style |= PS_ENDCAP_SQUARE;
400
	  break;
401
	}
402 403
      GDK_NOTE (GC, (g_print ("%sps|=PS_ENDCAP_%s", s, _gdk_win32_psendcap_to_string (win32_gc->pen_style)),
		     s = ","));
404
      win32_gc->values_mask |= GDK_GC_CAP_STYLE;
405 406
    }

407
  if (mask & GDK_GC_JOIN_STYLE)
408
    {
409
      win32_gc->pen_style &= ~(PS_JOIN_MASK);
410 411 412
      switch (values->join_style)
	{
	case GDK_JOIN_MITER:
413
	  win32_gc->pen_style |= PS_JOIN_MITER;
414 415
	  break;
	case GDK_JOIN_ROUND:
416
	  win32_gc->pen_style |= PS_JOIN_ROUND;
417 418
	  break;
	case GDK_JOIN_BEVEL:
419
	  win32_gc->pen_style |= PS_JOIN_BEVEL;
420 421
	  break;
	}
422 423
      GDK_NOTE (GC, (g_print ("%sps|=PS_JOIN_%s", s, _gdk_win32_psjoin_to_string (win32_gc->pen_style)),
		     s = ","));
424
      win32_gc->values_mask |= GDK_GC_JOIN_STYLE;
425
    }
426
  GDK_NOTE (GC, g_print ("} mask=(%s)", _gdk_win32_gcvalues_mask_to_string (win32_gc->values_mask)));
427 428 429 430 431 432 433 434
}

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

437 438 439 440
  /* 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);
441

442
  gc = g_object_new (_gdk_gc_win32_get_type (), NULL);
443 444 445
  win32_gc = GDK_GC_WIN32 (gc);

  win32_gc->hcliprgn = NULL;
446

447 448 449
  /* 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.
   */
450 451 452 453 454 455 456
  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;
457 458
  win32_gc->subwindow_mode = GDK_CLIP_BY_CHILDREN;
  win32_gc->graphics_exposures = TRUE;
459
  win32_gc->pen_width = 0;
460
  win32_gc->pen_style = PS_GEOMETRIC|PS_ENDCAP_FLAT|PS_JOIN_MITER;
461 462
  win32_gc->pen_dashes = NULL;
  win32_gc->pen_num_dashes = 0;
463 464

  win32_gc->values_mask = GDK_GC_FUNCTION | GDK_GC_FILL;
465

466
  GDK_NOTE (GC, g_print ("_gdk_win32_gc_new: %p: ", win32_gc));
467
  gdk_win32_gc_values_to_win32values (values, mask, win32_gc);
468
  GDK_NOTE (GC, g_print ("\n"));
469

470
  win32_gc->hdc = NULL;
471
  win32_gc->hwnd = NULL;
472 473 474 475

  return gc;
}

Tor Lillqvist's avatar
Tor Lillqvist committed
476 477 478
static void
gdk_win32_gc_get_values (GdkGC       *gc,
			 GdkGCValues *values)
479
{
480
  GdkGCWin32 *win32_gc = GDK_GC_WIN32 (gc);
481

482 483 484
  values->foreground.pixel = win32_gc->foreground;
  values->background.pixel = win32_gc->background;
  values->font = win32_gc->font;
485

486
  switch (win32_gc->rop2)
487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515
    {
    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;
516 517
    case R2_NOTMERGEPEN:
      values->function = GDK_NOR; break;
518 519 520 521
    case R2_WHITE:
      values->function = GDK_SET; break;
    }

522
  values->fill = win32_gc->fill_style;
523

524 525
  values->tile = win32_gc->tile;
  values->stipple = win32_gc->stipple;
526

527 528 529
  /* Also the X11 backend always returns a NULL clip_mask */
  values->clip_mask = NULL;

530 531 532 533 534 535 536
  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;
537
  
538
  if (win32_gc->pen_style & PS_SOLID)
539
    values->line_style = GDK_LINE_SOLID;
540
  else if (win32_gc->pen_style & PS_DASH)
541 542 543 544 545
    values->line_style = GDK_LINE_ON_OFF_DASH;
  else
    values->line_style = GDK_LINE_SOLID;

  /* PS_ENDCAP_ROUND is zero */
546
  if (win32_gc->pen_style & PS_ENDCAP_FLAT)
547
    values->cap_style = GDK_CAP_BUTT;
548
  else if (win32_gc->pen_style & PS_ENDCAP_SQUARE)
549 550 551 552 553
    values->cap_style = GDK_CAP_PROJECTING;
  else
    values->cap_style = GDK_CAP_ROUND;
    
  /* PS_JOIN_ROUND is zero */
554
  if (win32_gc->pen_style & PS_JOIN_MITER)
555
    values->join_style = GDK_JOIN_MITER;
556
  else if (win32_gc->pen_style & PS_JOIN_BEVEL)
557 558 559 560 561
    values->join_style = GDK_JOIN_BEVEL;
  else
    values->join_style = GDK_JOIN_ROUND;
}

Tor Lillqvist's avatar
Tor Lillqvist committed
562 563 564
static void
gdk_win32_gc_set_values (GdkGC           *gc,
			 GdkGCValues     *values,
565
			 GdkGCValuesMask  mask)
566
{
567 568
  g_return_if_fail (GDK_IS_GC (gc));

569
  GDK_NOTE (GC, g_print ("gdk_win32_gc_set_values: %p: ", GDK_GC_WIN32 (gc)));
570
  gdk_win32_gc_values_to_win32values (values, mask, GDK_GC_WIN32 (gc));
571
  GDK_NOTE (GC, g_print ("\n"));
Tor Lillqvist's avatar
Tor Lillqvist committed
572 573 574 575
}

static void
gdk_win32_gc_set_dashes (GdkGC *gc,
576 577
			 gint	dash_offset,
			 gint8  dash_list[],
Tor Lillqvist's avatar
Tor Lillqvist committed
578 579
			 gint   n)
{
580
  GdkGCWin32 *win32_gc;
581
  int i;
582 583 584

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

586 587
  win32_gc = GDK_GC_WIN32 (gc);

588 589 590
  /* mark as set, see gdk_win32_gc_values_to_win32values () for the reason */
  win32_gc->values_mask |= GDK_GC_LINE_STYLE;

591
  win32_gc->pen_style &= ~(PS_STYLE_MASK);
592

593 594 595 596 597
  win32_gc->pen_style |= (PS_GEOMETRIC | PS_USERSTYLE);
  win32_gc->pen_num_dashes = n;
  win32_gc->pen_dashes = g_new (DWORD, n);
  for (i = 0; i < n; i++)
    win32_gc->pen_dashes[i] = dash_list[i];
598 599 600 601 602 603
}

void
gdk_gc_set_clip_rectangle (GdkGC	*gc,
			   GdkRectangle *rectangle)
{
604 605 606
  GdkGCWin32 *win32_gc;

  g_return_if_fail (GDK_IS_GC (gc));
607

608
  win32_gc = GDK_GC_WIN32 (gc);
609

610
  if (win32_gc->hcliprgn)
611
    DeleteObject (win32_gc->hcliprgn);
612

613 614
  if (rectangle)
    {
615 616
      GDK_NOTE (GC, g_print ("gdk_gc_set_clip_rectangle: %p: %s\n",
			     win32_gc,
617 618 619 620
			     _gdk_win32_gdkrectangle_to_string (rectangle)));
      win32_gc->hcliprgn = CreateRectRgn (rectangle->x, rectangle->y,
					  rectangle->x + rectangle->width,
					  rectangle->y + rectangle->height);
621
      win32_gc->values_mask |= GDK_GC_CLIP_MASK;
622 623 624
    }
  else
    {
625
      GDK_NOTE (GC, g_print ("gdk_gc_set_clip_rectangle: NULL\n"));
626

627
      win32_gc->hcliprgn = NULL;
628
      win32_gc->values_mask &= ~GDK_GC_CLIP_MASK;
629
    }
630 631 632 633 634

  gc->clip_x_origin = 0;
  gc->clip_y_origin = 0;
  
  win32_gc->values_mask &= ~(GDK_GC_CLIP_X_ORIGIN | GDK_GC_CLIP_Y_ORIGIN);
635 636 637
} 

void
638 639
gdk_gc_set_clip_region (GdkGC	  *gc,
			GdkRegion *region)
640
{
641
  GdkGCWin32 *win32_gc;
642

643
  g_return_if_fail (GDK_IS_GC (gc));
644

645
  win32_gc = GDK_GC_WIN32 (gc);
646

647 648
  if (win32_gc->hcliprgn)
    DeleteObject (win32_gc->hcliprgn);
649 650 651

  if (region)
    {
652 653
      GDK_NOTE (GC, g_print ("gdk_gc_set_clip_region: %p: %s\n",
			     win32_gc,
654
			     _gdk_win32_gdkregion_to_string (region)));
655

656
      win32_gc->hcliprgn = _gdk_win32_gdkregion_to_hrgn (region, 0, 0);
657
      win32_gc->values_mask |= GDK_GC_CLIP_MASK;
658 659 660
    }
  else
    {
661
      GDK_NOTE (GC, g_print ("gdk_gc_set_clip_region: NULL\n"));
662

663
      win32_gc->hcliprgn = NULL;
664
      win32_gc->values_mask &= ~GDK_GC_CLIP_MASK;
665
    }
666

667 668
  gc->clip_x_origin = 0;
  gc->clip_y_origin = 0;
669
  
670
  win32_gc->values_mask &= ~(GDK_GC_CLIP_X_ORIGIN | GDK_GC_CLIP_Y_ORIGIN);
671 672 673
}

void
674 675
gdk_gc_copy (GdkGC *dst_gc,
	     GdkGC *src_gc)
676
{
Tor Lillqvist's avatar
Tor Lillqvist committed
677 678
  GdkGCWin32 *dst_win32_gc;
  GdkGCWin32 *src_win32_gc;
Tor Lillqvist's avatar
Tor Lillqvist committed
679

680 681 682 683 684 685
  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);

686 687
  GDK_NOTE (GC, g_print ("gdk_gc_copy: %p := %p\n", dst_win32_gc, src_win32_gc));

688 689 690 691 692 693
  if (dst_gc->colormap)
    g_object_unref (G_OBJECT (dst_gc->colormap));

  if (dst_win32_gc->hcliprgn != NULL)
    DeleteObject (dst_win32_gc->hcliprgn);

694 695
  if (dst_win32_gc->font != NULL)
    gdk_font_unref (dst_win32_gc->font);
696

697 698
  if (dst_win32_gc->tile != NULL)
    gdk_drawable_unref (dst_win32_gc->tile);
699

700 701
  if (dst_win32_gc->stipple != NULL)
    gdk_drawable_unref (dst_win32_gc->stipple);
702

703 704
  if (dst_win32_gc->pen_dashes)
    g_free (dst_win32_gc->pen_dashes);
Tor Lillqvist's avatar
Tor Lillqvist committed
705
  
706
  *dst_win32_gc = *src_win32_gc;
707
  dst_win32_gc->hdc = NULL;
708

709 710 711
  if (dst_gc->colormap)
    g_object_ref (G_OBJECT (dst_gc->colormap));

712 713 714
  if (dst_win32_gc->hcliprgn)
    {
      /* create a new region, to copy to */
715
      dst_win32_gc->hcliprgn = CreateRectRgn (0,0,1,1);
716 717 718 719
      /* overwrite from source */
      CombineRgn (dst_win32_gc->hcliprgn, src_win32_gc->hcliprgn,
		  NULL, RGN_COPY);
    }
720

721 722
  if (dst_win32_gc->font != NULL)
    gdk_font_ref (dst_win32_gc->font);
723

724 725
  if (dst_win32_gc->tile != NULL)
    gdk_drawable_ref (dst_win32_gc->tile);
726

727 728
  if (dst_win32_gc->stipple != NULL)
    gdk_drawable_ref (dst_win32_gc->stipple);
729 730 731 732

  if (dst_win32_gc->pen_dashes)
    dst_win32_gc->pen_dashes = g_memdup (src_win32_gc->pen_dashes, 
                                         sizeof (DWORD) * src_win32_gc->pen_num_dashes);
733 734
}

Tor Lillqvist's avatar
Tor Lillqvist committed
735 736 737 738 739 740 741 742
GdkScreen *  
gdk_gc_get_screen (GdkGC *gc)
{
  g_return_val_if_fail (GDK_IS_GC_WIN32 (gc), NULL);
  
  return _gdk_screen;
}

743 744 745
static guint bitmask[9] = { 0, 1, 3, 7, 15, 31, 63, 127, 255 };

COLORREF
746 747
_gdk_win32_colormap_color (GdkColormap *colormap,
                           gulong       pixel)
748
{
Tor Lillqvist's avatar
Tor Lillqvist committed
749 750
  const GdkVisual *visual;
  GdkColormapPrivateWin32 *colormap_private;
751 752
  guchar r, g, b;

Tor Lillqvist's avatar
Tor Lillqvist committed
753
  if (colormap == NULL)
754
    return DIBINDEX (pixel & 1);
Tor Lillqvist's avatar
Tor Lillqvist committed
755

756
  colormap_private = GDK_WIN32_COLORMAP_DATA (colormap);
Tor Lillqvist's avatar
Tor Lillqvist committed
757

758
  g_assert (colormap_private != NULL);
Tor Lillqvist's avatar
Tor Lillqvist committed
759 760

  visual = colormap->visual;
761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780
  switch (visual->type)
    {
    case GDK_VISUAL_GRAYSCALE:
    case GDK_VISUAL_PSEUDO_COLOR:
    case GDK_VISUAL_STATIC_COLOR:
      return PALETTEINDEX (pixel);

    case GDK_VISUAL_TRUE_COLOR:
      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);

    default:
      g_assert_not_reached ();
      return 0;
    }
781
}
782

Tor Lillqvist's avatar
Tor Lillqvist committed
783
static COLORREF
Tor Lillqvist's avatar
Tor Lillqvist committed
784 785 786
predraw_set_foreground (GdkGC       *gc,
			GdkColormap *colormap,
			gboolean    *ok)
787 788
{
  COLORREF fg;
789 790 791
  GdkGCWin32 *win32_gc = (GdkGCWin32 *) gc;
  GdkColormapPrivateWin32 *colormap_private;
  gint k;
792

793 794 795
  if (colormap &&
      (colormap->visual->type == GDK_VISUAL_PSEUDO_COLOR ||
       colormap->visual->type == GDK_VISUAL_STATIC_COLOR))
796
    {
797
      colormap_private = GDK_WIN32_COLORMAP_DATA (colormap);
798

799 800 801 802 803 804 805 806 807
      g_assert (colormap_private != NULL);

      if (!(win32_gc->holdpal = SelectPalette (win32_gc->hdc, colormap_private->hpal, FALSE)))
	WIN32_GDI_FAILED ("SelectPalette"), *ok = FALSE;
      else if ((k = RealizePalette (win32_gc->hdc)) == GDI_ERROR)
	WIN32_GDI_FAILED ("RealizePalette"), *ok = FALSE;
      else if (k > 0)
	GDK_NOTE (COLORMAP, g_print ("predraw_set_foreground: realized %p: %d colors\n",
				     colormap_private->hpal, k));
808
    }
809

810
  fg = _gdk_win32_colormap_color (colormap, win32_gc->foreground);
811

812
  GDK_NOTE (GC, g_print ("predraw_set_foreground: fg=%06lx\n", fg));
Tor Lillqvist's avatar
Tor Lillqvist committed
813
  return fg;
814 815
}

Tor Lillqvist's avatar
Tor Lillqvist committed
816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865
/**
 * gdk_win32_hdc_get:
 * @drawable: destination #GdkDrawable
 * @gc: #GdkGC to use for drawing on @drawable
 * @usage: mask indicating what properties needs to be set up
 *
 * Allocates a Windows device context handle (HDC) for drawing into
 * @drawable, and sets it up appropriately according to @usage.
 *
 * Each #GdkGC can at one time have only one HDC associated with it.
 *
 * The following flags in @mask are handled:
 *
 * If %GDK_GC_FOREGROUND is set in @mask, a solid brush of the
 * foreground color in @gc is selected into the HDC. The text color of
 * the HDC is also set. If the @drawable has a palette (256-color
 * mode), the palette is selected and realized.
 *
 * If any of the line attribute flags (%GDK_GC_LINE_WIDTH,
 * %GDK_GC_LINE_STYLE, %GDK_GC_CAP_STYLE and %GDK_GC_JOIN_STYLE) is
 * set in @mask, a solid pen of the foreground color and appropriate
 * width and stule is created and selected into the HDC. Note that the
 * dash properties are not completely implemented.
 *
 * If the %GDK_GC_FONT flag is set, the background mix mode is set to
 * %TRANSPARENT. and the text alignment is set to
 * %TA_BASELINE|%TA_LEFT. Note that no font gets selected into the HDC
 * by this function.
 *
 * Some things are done regardless of @mask: If the function in @gc is
 * any other than %GDK_COPY, the raster operation of the HDC is
 * set. If @gc has a clip mask, the clip region of the HDC is set.
 *
 * Note that the fill style, tile, stipple, and tile and stipple
 * origins in the @gc are ignored by this function. (In general, tiles
 * and stipples can't be implemented directly on Win32; you need to do
 * multiple pass drawing and blitting to implement tiles or
 * stipples. GDK does just that when you call the GDK drawing
 * functions with a GC that asks for tiles or stipples.)
 *
 * When the HDC is no longer used, it should be released by calling
 * <function>gdk_win32_hdc_release()</function> with the same
 * parameters.
 *
 * If you modify the HDC by calling <function>SelectObject</function>
 * you should undo those modifications before calling
 * <function>gdk_win32_hdc_release()</function>.
 *
 * Return value: The HDC.
 **/
866
HDC
Tor Lillqvist's avatar
Tor Lillqvist committed
867 868 869
gdk_win32_hdc_get (GdkDrawable    *drawable,
		   GdkGC          *gc,
		   GdkGCValuesMask usage)
870
{
Tor Lillqvist's avatar
Tor Lillqvist committed
871
  GdkGCWin32 *win32_gc = (GdkGCWin32 *) gc;
872
  GdkDrawableImplWin32 *impl = NULL;
873
  gboolean ok = TRUE;
Tor Lillqvist's avatar
Tor Lillqvist committed
874 875 876 877
  COLORREF fg = RGB (0, 0, 0);
  LOGBRUSH logbrush;
  HPEN hpen;
  HBRUSH hbr;
878

879
  g_assert (win32_gc->hdc == NULL);</