diff --git a/ChangeLog b/ChangeLog index 535da546f2..891ac6209b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,33 @@ +2002-11-24 Tor Lillqvist + + * gdk/win32/gdkdrawable-win32.c: Remove the already ifdeffed-out + code that didn't use generic_draw. + + (generic_draw): When drawing into the mask (for tiled/stippled + fill styles), copy the line attributes from the actual GC. Also + ask for text drawing setup if needed. Use differently set up HDCs + in the normal and tiled/stippled cases. + + (draw_segments) Slight code reorg. + + (draw_lines, gdk_win32_draw_lines): Use generic_draw() also for + lines. + + * gdk/win32/gdkgc-win32.c: Remove ifdeffed-out code. + + (predraw_set_foreground, gdk_win32_hdc_get): Some code moved + around. Call SetROP2() only if necessary. Call SetTextColor() only + if GDK_GC_FOREGROUND flag present. + + Remove background color handling from here. The background color + of a GdkGC is supposed to affect only GDK_OPAQUE_STIPPLED fill style, + which it is already handled in generic_draw(), and + GDK_LINE_DOUBLE_DASH lines, which aren't implemented properly + anyway. Calling SetBkColor() is unnecessary. + + (gdk_win32_hdc_get, gdk_win32_hdc_release): Add doc comments, as + these are public functions. + 2002-11-23 Tor Lillqvist * gdk/win32/gdkdrawable-win32.c (draw_polygon, diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10 index 535da546f2..891ac6209b 100644 --- a/ChangeLog.pre-2-10 +++ b/ChangeLog.pre-2-10 @@ -1,3 +1,33 @@ +2002-11-24 Tor Lillqvist + + * gdk/win32/gdkdrawable-win32.c: Remove the already ifdeffed-out + code that didn't use generic_draw. + + (generic_draw): When drawing into the mask (for tiled/stippled + fill styles), copy the line attributes from the actual GC. Also + ask for text drawing setup if needed. Use differently set up HDCs + in the normal and tiled/stippled cases. + + (draw_segments) Slight code reorg. + + (draw_lines, gdk_win32_draw_lines): Use generic_draw() also for + lines. + + * gdk/win32/gdkgc-win32.c: Remove ifdeffed-out code. + + (predraw_set_foreground, gdk_win32_hdc_get): Some code moved + around. Call SetROP2() only if necessary. Call SetTextColor() only + if GDK_GC_FOREGROUND flag present. + + Remove background color handling from here. The background color + of a GdkGC is supposed to affect only GDK_OPAQUE_STIPPLED fill style, + which it is already handled in generic_draw(), and + GDK_LINE_DOUBLE_DASH lines, which aren't implemented properly + anyway. Calling SetBkColor() is unnecessary. + + (gdk_win32_hdc_get, gdk_win32_hdc_release): Add doc comments, as + these are public functions. + 2002-11-23 Tor Lillqvist * gdk/win32/gdkdrawable-win32.c (draw_polygon, diff --git a/ChangeLog.pre-2-2 b/ChangeLog.pre-2-2 index 535da546f2..891ac6209b 100644 --- a/ChangeLog.pre-2-2 +++ b/ChangeLog.pre-2-2 @@ -1,3 +1,33 @@ +2002-11-24 Tor Lillqvist + + * gdk/win32/gdkdrawable-win32.c: Remove the already ifdeffed-out + code that didn't use generic_draw. + + (generic_draw): When drawing into the mask (for tiled/stippled + fill styles), copy the line attributes from the actual GC. Also + ask for text drawing setup if needed. Use differently set up HDCs + in the normal and tiled/stippled cases. + + (draw_segments) Slight code reorg. + + (draw_lines, gdk_win32_draw_lines): Use generic_draw() also for + lines. + + * gdk/win32/gdkgc-win32.c: Remove ifdeffed-out code. + + (predraw_set_foreground, gdk_win32_hdc_get): Some code moved + around. Call SetROP2() only if necessary. Call SetTextColor() only + if GDK_GC_FOREGROUND flag present. + + Remove background color handling from here. The background color + of a GdkGC is supposed to affect only GDK_OPAQUE_STIPPLED fill style, + which it is already handled in generic_draw(), and + GDK_LINE_DOUBLE_DASH lines, which aren't implemented properly + anyway. Calling SetBkColor() is unnecessary. + + (gdk_win32_hdc_get, gdk_win32_hdc_release): Add doc comments, as + these are public functions. + 2002-11-23 Tor Lillqvist * gdk/win32/gdkdrawable-win32.c (draw_polygon, diff --git a/ChangeLog.pre-2-4 b/ChangeLog.pre-2-4 index 535da546f2..891ac6209b 100644 --- a/ChangeLog.pre-2-4 +++ b/ChangeLog.pre-2-4 @@ -1,3 +1,33 @@ +2002-11-24 Tor Lillqvist + + * gdk/win32/gdkdrawable-win32.c: Remove the already ifdeffed-out + code that didn't use generic_draw. + + (generic_draw): When drawing into the mask (for tiled/stippled + fill styles), copy the line attributes from the actual GC. Also + ask for text drawing setup if needed. Use differently set up HDCs + in the normal and tiled/stippled cases. + + (draw_segments) Slight code reorg. + + (draw_lines, gdk_win32_draw_lines): Use generic_draw() also for + lines. + + * gdk/win32/gdkgc-win32.c: Remove ifdeffed-out code. + + (predraw_set_foreground, gdk_win32_hdc_get): Some code moved + around. Call SetROP2() only if necessary. Call SetTextColor() only + if GDK_GC_FOREGROUND flag present. + + Remove background color handling from here. The background color + of a GdkGC is supposed to affect only GDK_OPAQUE_STIPPLED fill style, + which it is already handled in generic_draw(), and + GDK_LINE_DOUBLE_DASH lines, which aren't implemented properly + anyway. Calling SetBkColor() is unnecessary. + + (gdk_win32_hdc_get, gdk_win32_hdc_release): Add doc comments, as + these are public functions. + 2002-11-23 Tor Lillqvist * gdk/win32/gdkdrawable-win32.c (draw_polygon, diff --git a/ChangeLog.pre-2-6 b/ChangeLog.pre-2-6 index 535da546f2..891ac6209b 100644 --- a/ChangeLog.pre-2-6 +++ b/ChangeLog.pre-2-6 @@ -1,3 +1,33 @@ +2002-11-24 Tor Lillqvist + + * gdk/win32/gdkdrawable-win32.c: Remove the already ifdeffed-out + code that didn't use generic_draw. + + (generic_draw): When drawing into the mask (for tiled/stippled + fill styles), copy the line attributes from the actual GC. Also + ask for text drawing setup if needed. Use differently set up HDCs + in the normal and tiled/stippled cases. + + (draw_segments) Slight code reorg. + + (draw_lines, gdk_win32_draw_lines): Use generic_draw() also for + lines. + + * gdk/win32/gdkgc-win32.c: Remove ifdeffed-out code. + + (predraw_set_foreground, gdk_win32_hdc_get): Some code moved + around. Call SetROP2() only if necessary. Call SetTextColor() only + if GDK_GC_FOREGROUND flag present. + + Remove background color handling from here. The background color + of a GdkGC is supposed to affect only GDK_OPAQUE_STIPPLED fill style, + which it is already handled in generic_draw(), and + GDK_LINE_DOUBLE_DASH lines, which aren't implemented properly + anyway. Calling SetBkColor() is unnecessary. + + (gdk_win32_hdc_get, gdk_win32_hdc_release): Add doc comments, as + these are public functions. + 2002-11-23 Tor Lillqvist * gdk/win32/gdkdrawable-win32.c (draw_polygon, diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8 index 535da546f2..891ac6209b 100644 --- a/ChangeLog.pre-2-8 +++ b/ChangeLog.pre-2-8 @@ -1,3 +1,33 @@ +2002-11-24 Tor Lillqvist + + * gdk/win32/gdkdrawable-win32.c: Remove the already ifdeffed-out + code that didn't use generic_draw. + + (generic_draw): When drawing into the mask (for tiled/stippled + fill styles), copy the line attributes from the actual GC. Also + ask for text drawing setup if needed. Use differently set up HDCs + in the normal and tiled/stippled cases. + + (draw_segments) Slight code reorg. + + (draw_lines, gdk_win32_draw_lines): Use generic_draw() also for + lines. + + * gdk/win32/gdkgc-win32.c: Remove ifdeffed-out code. + + (predraw_set_foreground, gdk_win32_hdc_get): Some code moved + around. Call SetROP2() only if necessary. Call SetTextColor() only + if GDK_GC_FOREGROUND flag present. + + Remove background color handling from here. The background color + of a GdkGC is supposed to affect only GDK_OPAQUE_STIPPLED fill style, + which it is already handled in generic_draw(), and + GDK_LINE_DOUBLE_DASH lines, which aren't implemented properly + anyway. Calling SetBkColor() is unnecessary. + + (gdk_win32_hdc_get, gdk_win32_hdc_release): Add doc comments, as + these are public functions. + 2002-11-23 Tor Lillqvist * gdk/win32/gdkdrawable-win32.c (draw_polygon, diff --git a/gdk/win32/gdkdrawable-win32.c b/gdk/win32/gdkdrawable-win32.c index 7febc5832a..89eed71a82 100644 --- a/gdk/win32/gdkdrawable-win32.c +++ b/gdk/win32/gdkdrawable-win32.c @@ -25,8 +25,6 @@ * GTK+ at ftp://ftp.gtk.org/pub/gtk/. */ -#define USE_GENERIC_DRAW - #include #include #include @@ -40,6 +38,9 @@ #define ROP3_DPSao 0x00EA02E9 #define ROP3_DSna 0x00220326 +#define LINE_ATTRIBUTES (GDK_GC_LINE_WIDTH|GDK_GC_LINE_STYLE| \ + GDK_GC_CAP_STYLE|GDK_GC_JOIN_STYLE) + static void gdk_win32_draw_rectangle (GdkDrawable *drawable, GdkGC *gc, gint filled, @@ -399,8 +400,6 @@ rop2_to_rop3 (int rop2) } } -#ifdef USE_GENERIC_DRAW - static void generic_draw (GdkDrawable *drawable, GdkGC *gc, @@ -411,7 +410,7 @@ generic_draw (GdkDrawable *drawable, { GdkDrawableImplWin32 *impl = GDK_DRAWABLE_IMPL_WIN32 (drawable); GdkGCWin32 *gcwin32 = GDK_GC_WIN32 (gc); - HDC hdc = gdk_win32_hdc_get (drawable, gc, mask); + HDC hdc; va_list args; va_start (args, region); @@ -429,6 +428,8 @@ generic_draw (GdkDrawable *drawable, gcwin32->values_mask & GDK_GC_STIPPLE && gcwin32->stipple != NULL))) { + const GdkGCValuesMask blitting_mask = 0; + GdkGCValuesMask drawing_mask = GDK_GC_FOREGROUND; gint ts_x_origin = 0, ts_y_origin = 0; gint width = region->extents.x2 - region->extents.x1; @@ -445,11 +446,16 @@ generic_draw (GdkDrawable *drawable, GdkGC *tile_gc = gdk_gc_new (tile_pixmap); HDC mask_hdc; - HDC tile_hdc = CreateCompatibleDC (hdc); + HDC tile_hdc; HGDIOBJ old_mask_hbm; HGDIOBJ old_tile_hbm; + GdkGCValues gcvalues; + + hdc = gdk_win32_hdc_get (drawable, gc, blitting_mask); + tile_hdc = CreateCompatibleDC (hdc); + if (gcwin32->values_mask & GDK_GC_TS_X_ORIGIN) ts_x_origin = gc->ts_x_origin; if (gcwin32->values_mask & GDK_GC_TS_Y_ORIGIN) @@ -468,10 +474,32 @@ generic_draw (GdkDrawable *drawable, fg.pixel = 1; gdk_gc_set_foreground (mask_gc, &fg); - mask_hdc = gdk_win32_hdc_get (mask_pixmap, mask_gc, GDK_GC_FOREGROUND); + /* If the drawing function uses line attributes, set them as in + * the real GC. + */ + if (mask & LINE_ATTRIBUTES) + { + gdk_gc_get_values (gc, &gcvalues); + if (gcvalues.line_width != 0 || + gcvalues.line_style != GDK_LINE_SOLID || + gcvalues.cap_style != GDK_CAP_BUTT || + gcvalues.join_style != GDK_JOIN_MITER) + gdk_gc_set_line_attributes (mask_gc, + gcvalues.line_width, + gcvalues.line_style, + gcvalues.cap_style, + gcvalues.join_style); + drawing_mask |= LINE_ATTRIBUTES; + } + + /* Ditto, if the drawing function draws text, set up for that. */ + if (mask & GDK_GC_FONT) + drawing_mask |= GDK_GC_FONT; + + mask_hdc = gdk_win32_hdc_get (mask_pixmap, mask_gc, drawing_mask); (*function) (GDK_GC_WIN32 (mask_gc), mask_hdc, region->extents.x1, region->extents.y1, args); - gdk_win32_hdc_release (mask_pixmap, mask_gc, GDK_GC_FOREGROUND); + gdk_win32_hdc_release (mask_pixmap, mask_gc, drawing_mask); if (gcwin32->fill_style == GDK_TILED) { @@ -612,12 +640,16 @@ generic_draw (GdkDrawable *drawable, GDI_CALL (DeleteDC, (tile_hdc)); gdk_drawable_unref (mask_pixmap); gdk_drawable_unref (tile_pixmap); + + gdk_win32_hdc_release (drawable, gc, blitting_mask); } else - (*function) (gcwin32, hdc, 0, 0, args); - + { + hdc = gdk_win32_hdc_get (drawable, gc, mask); + (*function) (gcwin32, hdc, 0, 0, args); + gdk_win32_hdc_release (drawable, gc, mask); + } va_end (args); - gdk_win32_hdc_release (drawable, gc, mask); } static GdkRegion * @@ -693,8 +725,6 @@ draw_rectangle (GdkGCWin32 *gcwin32, } } -#endif /* USE_GENERIC_DRAW */ - static void gdk_win32_draw_rectangle (GdkDrawable *drawable, GdkGC *gc, @@ -704,8 +734,6 @@ gdk_win32_draw_rectangle (GdkDrawable *drawable, gint width, gint height) { -#ifdef USE_GENERIC_DRAW - GdkRectangle bounds; GdkRegion *region; @@ -721,123 +749,12 @@ gdk_win32_draw_rectangle (GdkDrawable *drawable, bounds.height = height; region = widen_bounds (&bounds, GDK_GC_WIN32 (gc)->pen_width); - generic_draw (drawable, gc, GDK_GC_FOREGROUND|GDK_GC_BACKGROUND, + generic_draw (drawable, gc, GDK_GC_FOREGROUND|LINE_ATTRIBUTES, draw_rectangle, region, filled, x, y, width, height); gdk_region_destroy (region); - -#else /* !USE_GENERIC_DRAW */ - - GdkGCWin32 *gcwin32 = GDK_GC_WIN32 (gc); - const GdkGCValuesMask mask = GDK_GC_FOREGROUND|GDK_GC_BACKGROUND; - HDC hdc; - HGDIOBJ old_pen_or_brush; - POINT pts[4]; - gboolean ok = TRUE; - - GDK_NOTE (MISC, g_print ("gdk_win32_draw_rectangle: %s (%p) %s%dx%d@+%d+%d\n", - gdk_win32_drawable_description (drawable), - gcwin32, - (filled ? "fill " : ""), - width, height, x, y)); - - if (filled - && (gcwin32->values_mask & GDK_GC_TILE) - && (gcwin32->tile) - && (gcwin32->values_mask & GDK_GC_FILL) - && (gcwin32->fill_style == GDK_TILED)) - { - draw_tiles (drawable, gc, SRCCOPY, - gcwin32->tile, - x, y, - gc->ts_x_origin, - gc->ts_y_origin, - width, height); - return; - } - - hdc = gdk_win32_hdc_get (drawable, gc, mask); - - if (gcwin32->fill_style == GDK_OPAQUE_STIPPLED) - { - if (!BeginPath (hdc)) - WIN32_GDI_FAILED ("BeginPath"), ok = FALSE; - - /* Win9x doesn't support Rectangle calls in a path, - * thus use Polyline. - */ - - pts[0].x = x; - pts[0].y = y; - pts[1].x = x + width + 1; - pts[1].y = y; - pts[2].x = x + width + 1; - pts[2].y = y + height + 1; - pts[3].x = x; - pts[3].y = y + height + 1; - - if (ok) - MoveToEx (hdc, x, y, NULL); - - if (ok && !Polyline (hdc, pts, 4)) - WIN32_GDI_FAILED ("Polyline"), ok = FALSE; - - if (ok && !CloseFigure (hdc)) - WIN32_GDI_FAILED ("CloseFigure"), ok = FALSE; - - if (ok && !EndPath (hdc)) - WIN32_GDI_FAILED ("EndPath"), ok = FALSE; - - if (ok && !filled) - if (!WidenPath (hdc)) - WIN32_GDI_FAILED ("WidenPath"), ok = FALSE; - - if (ok && !FillPath (hdc)) - WIN32_GDI_FAILED ("FillPath"), ok = FALSE; - } - else - { - if (!filled && gcwin32->pen_dashes && !IS_WIN_NT ()) - { - ok = ok && render_line_vertical (hdc, x, y, y+height+1, - gcwin32->pen_width, - gcwin32->pen_dashes, - gcwin32->pen_num_dashes); - ok = ok && render_line_horizontal (hdc, x, x+width+1, y, - gcwin32->pen_width, - gcwin32->pen_dashes, - gcwin32->pen_num_dashes); - ok = ok && render_line_vertical (hdc, x+width+1, y, y+height+1, - gcwin32->pen_width, - gcwin32->pen_dashes, - gcwin32->pen_num_dashes); - ok = ok && render_line_horizontal (hdc, x, x+width+1, y+height+1, - gcwin32->pen_width, - gcwin32->pen_dashes, - gcwin32->pen_num_dashes); - } - else - { - if (filled) - old_pen_or_brush = SelectObject (hdc, GetStockObject (NULL_PEN)); - else - old_pen_or_brush = SelectObject (hdc, GetStockObject (HOLLOW_BRUSH)); - if (old_pen_or_brush == NULL) - WIN32_GDI_FAILED ("SelectObject"); - if (!Rectangle (hdc, x, y, x+width+1, y+height+1)) - WIN32_GDI_FAILED ("Rectangle"); - if (old_pen_or_brush) - SelectObject (hdc, old_pen_or_brush); - } - } - - gdk_win32_hdc_release (drawable, gc, mask); - -#endif /* !USE_GENERIC_DRAW */ } -#ifdef USE_GENERIC_DRAW - static void draw_arc (GdkGCWin32 *gcwin32, HDC hdc, @@ -908,8 +825,6 @@ draw_arc (GdkGCWin32 *gcwin32, } } -#endif /* USE_GENERIC_DRAW */ - static void gdk_win32_draw_arc (GdkDrawable *drawable, GdkGC *gc, @@ -921,8 +836,6 @@ gdk_win32_draw_arc (GdkDrawable *drawable, gint angle1, gint angle2) { -#ifdef USE_GENERIC_DRAW - GdkRectangle bounds; GdkRegion *region; @@ -939,79 +852,12 @@ gdk_win32_draw_arc (GdkDrawable *drawable, bounds.height = height; region = widen_bounds (&bounds, GDK_GC_WIN32 (gc)->pen_width); - generic_draw (drawable, gc, GDK_GC_FOREGROUND|GDK_GC_BACKGROUND, + generic_draw (drawable, gc, GDK_GC_FOREGROUND|LINE_ATTRIBUTES, draw_arc, region, filled, x, y, width, height, angle1, angle2); gdk_region_destroy (region); - -#else /* !USE_GENERIC_DRAW */ - - const GdkGCValuesMask mask = GDK_GC_FOREGROUND|GDK_GC_BACKGROUND; - HGDIOBJ old_pen; - HDC hdc; - int nXStartArc, nYStartArc, nXEndArc, nYEndArc; - - GDK_NOTE (MISC, g_print ("gdk_draw_arc: %s %d,%d,%d,%d %d %d\n", - gdk_win32_drawable_description (drawable), - x, y, width, height, angle1, angle2)); - - /* Seems that drawing arcs with width or height <= 2 fails, at least - * with my TNT card. - */ - if (width <= 2 || height <= 2 || angle2 == 0) - return; - - hdc = gdk_win32_hdc_get (drawable, gc, mask); - - if (angle2 >= 360*64) - { - nXStartArc = nYStartArc = nXEndArc = nYEndArc = 0; - } - else if (angle2 > 0) - { - /* The 100. is just an arbitrary value */ - nXStartArc = x + width/2 + 100. * cos(angle1/64.*2.*G_PI/360.); - nYStartArc = y + height/2 + -100. * sin(angle1/64.*2.*G_PI/360.); - nXEndArc = x + width/2 + 100. * cos((angle1+angle2)/64.*2.*G_PI/360.); - nYEndArc = y + height/2 + -100. * sin((angle1+angle2)/64.*2.*G_PI/360.); - } - else - { - nXEndArc = x + width/2 + 100. * cos(angle1/64.*2.*G_PI/360.); - nYEndArc = y + height/2 + -100. * sin(angle1/64.*2.*G_PI/360.); - nXStartArc = x + width/2 + 100. * cos((angle1+angle2)/64.*2.*G_PI/360.); - nYStartArc = y + height/2 + -100. * sin((angle1+angle2)/64.*2.*G_PI/360.); - } - - /* GDK_OPAQUE_STIPPLED arcs not implemented. */ - - if (filled) - { - old_pen = SelectObject (hdc, GetStockObject (NULL_PEN)); - GDK_NOTE (MISC, g_print ("...Pie(hdc,%d,%d,%d,%d,%d,%d,%d,%d)\n", - x, y, x+width, y+height, - nXStartArc, nYStartArc, - nXEndArc, nYEndArc)); - GDI_CALL (Pie, (hdc, x, y, x+width, y+height, - nXStartArc, nYStartArc, nXEndArc, nYEndArc)); - GDI_CALL (SelectObject, (hdc, old_pen)); - } - else - { - GDK_NOTE (MISC, g_print ("...Arc(hdc,%d,%d,%d,%d,%d,%d,%d,%d)\n", - x, y, x+width, y+height, - nXStartArc, nYStartArc, - nXEndArc, nYEndArc)); - GDI_CALL (Arc, (hdc, x, y, x+width, y+height, - nXStartArc, nYStartArc, nXEndArc, nYEndArc)); - } - gdk_win32_hdc_release (drawable, gc, mask); - -#endif /* !USE_GENERIC_DRAW */ } -#ifdef USE_GENERIC_DRAW - static void draw_polygon (GdkGCWin32 *gcwin32, HDC hdc, @@ -1041,8 +887,6 @@ draw_polygon (GdkGCWin32 *gcwin32, GDI_CALL (Polyline, (hdc, pts, npoints)); } -#endif /* USE_GENERIC_DRAW */ - static void gdk_win32_draw_polygon (GdkDrawable *drawable, GdkGC *gc, @@ -1050,8 +894,6 @@ gdk_win32_draw_polygon (GdkDrawable *drawable, GdkPoint *points, gint npoints) { -#ifdef USE_GENERIC_DRAW - GdkRectangle bounds; GdkRegion *region; POINT *pts; @@ -1091,90 +933,11 @@ gdk_win32_draw_polygon (GdkDrawable *drawable, region = widen_bounds (&bounds, GDK_GC_WIN32 (gc)->pen_width); - generic_draw (drawable, gc, GDK_GC_FOREGROUND|GDK_GC_BACKGROUND, + generic_draw (drawable, gc, GDK_GC_FOREGROUND|LINE_ATTRIBUTES, draw_polygon, region, filled, pts, npoints); gdk_region_destroy (region); g_free (pts); - -#else - - GdkGCWin32 *gcwin32 = GDK_GC_WIN32 (gc); - const GdkGCValuesMask mask = GDK_GC_FOREGROUND|GDK_GC_BACKGROUND; - HDC hdc; - POINT *pts; - gboolean ok = TRUE; - int i; - - GDK_NOTE (MISC, g_print ("gdk_win32_draw_polygon: %s (%p) %d\n", - gdk_win32_drawable_description (drawable), - gcwin32, - npoints)); - - if (npoints < 2) - return; - - hdc = gdk_win32_hdc_get (drawable, gc, mask); - pts = g_new (POINT, npoints+1); - - for (i = 0; i < npoints; i++) - { - pts[i].x = points[i].x; - pts[i].y = points[i].y; - } - - if (gcwin32->fill_style == GDK_OPAQUE_STIPPLED) - { - if (!BeginPath (hdc)) - WIN32_GDI_FAILED ("BeginPath"), ok = FALSE; - - if (ok) - MoveToEx (hdc, points[0].x, points[0].y, NULL); - - if (pts[0].x == pts[npoints-1].x && pts[0].y == pts[npoints-1].y) - npoints--; - - if (ok && !Polyline (hdc, pts, 4)) - WIN32_GDI_FAILED ("Polyline"), ok = FALSE; - - if (ok && !CloseFigure (hdc)) - WIN32_GDI_FAILED ("CloseFigure"), ok = FALSE; - - if (ok && !EndPath (hdc)) - WIN32_GDI_FAILED ("EndPath"), ok = FALSE; - - if (ok && !filled) - if (!WidenPath (hdc)) - WIN32_GDI_FAILED ("WidenPath"), ok = FALSE; - - if (ok && !FillPath (hdc)) - WIN32_GDI_FAILED ("FillPath"), ok = FALSE; - } - else - { - if (points[0].x != points[npoints-1].x - || points[0].y != points[npoints-1].y) - { - pts[npoints].x = points[0].x; - pts[npoints].y = points[0].y; - npoints++; - } - - if (filled) - { - if (!Polygon (hdc, pts, npoints)) - WIN32_GDI_FAILED ("Polygon"); - } - else - { - if (!Polyline (hdc, pts, npoints)) - WIN32_GDI_FAILED ("Polyline"); - } - } - g_free (pts); - gdk_win32_hdc_release (drawable, gc, mask); - -#endif /* USE_GENERIC_DRAW */ } typedef struct @@ -1353,8 +1116,6 @@ gdk_win32_draw_points (GdkDrawable *drawable, gdk_win32_hdc_release (drawable, gc, GDK_GC_FOREGROUND); } -#ifdef USE_GENERIC_DRAW - static void draw_segments (GdkGCWin32 *gcwin32, HDC hdc, @@ -1369,6 +1130,15 @@ draw_segments (GdkGCWin32 *gcwin32, segs = va_arg (args, GdkSegment *); nsegs = va_arg (args, gint); + if (x_offset != 0 || y_offset != 0) + for (i = 0; i < nsegs; i++) + { + segs[i].x1 -= x_offset; + segs[i].y1 -= y_offset; + segs[i].x2 -= x_offset; + segs[i].y2 -= y_offset; + } + if (gcwin32->pen_dashes && !IS_WIN_NT ()) { for (i = 0; i < nsegs; i++) @@ -1383,8 +1153,7 @@ draw_segments (GdkGCWin32 *gcwin32, y1 = segs[i].y2, y2 = segs[i].y1; render_line_vertical (hdc, - segs[i].x1 - x_offset, - y1 - y_offset, y2 - y_offset, + segs[i].x1, y1, y2, gcwin32->pen_width, gcwin32->pen_dashes, gcwin32->pen_num_dashes); @@ -1399,45 +1168,34 @@ draw_segments (GdkGCWin32 *gcwin32, x1 = segs[i].x2, x2 = segs[i].x1; render_line_horizontal (hdc, - x1 - x_offset, x2 - x_offset, - segs[i].y1 - y_offset, + x1, x2, segs[i].y1, gcwin32->pen_width, gcwin32->pen_dashes, gcwin32->pen_num_dashes); } else - GDI_CALL (MoveToEx, (hdc, segs[i].x1 - x_offset, - segs[i].y1 - y_offset, NULL)) && - GDI_CALL (LineTo, (hdc, segs[i].x2 - x_offset, - segs[i].y2 - y_offset)) && + GDI_CALL (MoveToEx, (hdc, segs[i].x1, segs[i].y1, NULL)) && + GDI_CALL (LineTo, (hdc, segs[i].x2, segs[i].y2)) && (gcwin32->pen_width <= 1 && - GDI_CALL (LineTo, (hdc, segs[i].x2 - x_offset + 1, - segs[i].y2 - y_offset + 1))); + GDI_CALL (LineTo, (hdc, segs[i].x2 + 1, segs[i].y2 + 1))); } } else { for (i = 0; i < nsegs; i++) - GDI_CALL (MoveToEx, (hdc, segs[i].x1 - x_offset, - segs[i].y1 - y_offset, NULL)) && - GDI_CALL (LineTo, (hdc, segs[i].x2 - x_offset, - segs[i].y2 - y_offset)) && + GDI_CALL (MoveToEx, (hdc, segs[i].x1, segs[i].y1, NULL)) && + GDI_CALL (LineTo, (hdc, segs[i].x2, segs[i].y2)) && (gcwin32->pen_width <= 1 && - GDI_CALL (LineTo, (hdc, segs[i].x2 - x_offset + 1, - segs[i].y2 - y_offset + 1))); + GDI_CALL (LineTo, (hdc, segs[i].x2 + 1, segs[i].y2 + 1))); } } -#endif /* USE_GENERIC_DRAW */ - static void gdk_win32_draw_segments (GdkDrawable *drawable, GdkGC *gc, GdkSegment *segs, gint nsegs) { -#ifdef USE_GENERIC_DRAW - GdkRectangle bounds; GdkRegion *region; gint i; @@ -1465,163 +1223,70 @@ gdk_win32_draw_segments (GdkDrawable *drawable, region = widen_bounds (&bounds, GDK_GC_WIN32 (gc)->pen_width); - generic_draw (drawable, gc, GDK_GC_FOREGROUND, + generic_draw (drawable, gc, GDK_GC_FOREGROUND|LINE_ATTRIBUTES, draw_segments, region, segs, nsegs); gdk_region_destroy (region); +} -#else +static void +draw_lines (GdkGCWin32 *gcwin32, + HDC hdc, + gint x_offset, + gint y_offset, + va_list args) +{ + POINT *pts; + gint npoints; + gint i; - GdkGCWin32 *gcwin32 = GDK_GC_WIN32 (gc); - const GdkGCValuesMask mask = GDK_GC_FOREGROUND|GDK_GC_BACKGROUND; - HDC hdc; - gboolean ok = TRUE; - int i; + pts = va_arg (args, POINT *); + npoints = va_arg (args, gint); - GDK_NOTE (MISC, g_print ("gdk_win32_draw_segments: %s nsegs: %d\n", - gdk_win32_drawable_description (drawable), nsegs)); - - hdc = gdk_win32_hdc_get (drawable, gc, mask); - - if (gcwin32->fill_style == GDK_OPAQUE_STIPPLED) + if (x_offset != 0 || y_offset != 0) + for (i = 0; i < npoints; i++) + { + pts[i].x -= x_offset; + pts[i].y -= y_offset; + } + + if (gcwin32->pen_dashes && !IS_WIN_NT ()) { - if (!BeginPath (hdc)) - WIN32_GDI_FAILED ("BeginPath"), ok = FALSE; - - for (i = 0; ok && i < nsegs; i++) - { - if (ok && !MoveToEx (hdc, segs[i].x1, segs[i].y1, NULL)) - WIN32_GDI_FAILED ("MoveToEx"), ok = FALSE; - if (ok && !LineTo (hdc, segs[i].x2, segs[i].y2)) - WIN32_GDI_FAILED ("LineTo"), ok = FALSE; - - /* Draw end pixel */ - if (ok && gcwin32->pen_width <= 1) - if (!LineTo (hdc, segs[i].x2 + 1, segs[i].y2)) - WIN32_GDI_FAILED ("LineTo"), ok = FALSE; - } + for (i = 0; i < npoints - 1; i++) + { + if (pts[i].x == pts[i+1].x) + { + int y1, y2; + if (pts[i].y > pts[i+1].y) + y1 = pts[i+1].y, y2 = pts[i].y; + else + y1 = pts[i].y, y2 = pts[i+1].y; + + render_line_vertical (hdc, pts[i].x, y1, y2, + gcwin32->pen_width, + gcwin32->pen_dashes, + gcwin32->pen_num_dashes); + } + else if (pts[i].y == pts[i+1].y) + { + int x1, x2; + if (pts[i].x > pts[i+1].x) + x1 = pts[i+1].x, x2 = pts[i].x; + else + x1 = pts[i].x, x2 = pts[i+1].x; - if (ok && !EndPath (hdc)) - WIN32_GDI_FAILED ("EndPath"), ok = FALSE; - - if (ok && !WidenPath (hdc)) - WIN32_GDI_FAILED ("WidenPath"), ok = FALSE; - - if (ok && !FillPath (hdc)) - WIN32_GDI_FAILED ("FillPath"), ok = FALSE; + render_line_horizontal (hdc, x1, x2, pts[i].y, + gcwin32->pen_width, + gcwin32->pen_dashes, + gcwin32->pen_num_dashes); + } + else + GDI_CALL (MoveToEx, (hdc, pts[i].x, pts[i].y, NULL)) && + GDI_CALL (LineTo, (hdc, pts[i+1].x, pts[i+1].y)); + } } else - { - if (gcwin32->pen_dashes && !IS_WIN_NT ()) - { - /* code very similar to the IMHO questionable optimization - * below. This one draws dashed vertical/horizontal lines - * with the limited Win9x GDI. --hb - */ - for (i = 0; ok && i < nsegs; i++) - { - if (segs[i].x1 == segs[i].x2) - { - int y1, y2; - - if (segs[i].y1 <= segs[i].y2) - y1 = segs[i].y1, y2 = segs[i].y2; - else - y1 = segs[i].y2, y2 = segs[i].y1; - - ok = render_line_vertical (hdc, - segs[i].x1, y1, y2, - gcwin32->pen_width, - gcwin32->pen_dashes, - gcwin32->pen_num_dashes); - } - else if (segs[i].y1 == segs[i].y2) - { - int x1, x2; - - if (segs[i].x1 <= segs[i].x2) - x1 = segs[i].x1, x2 = segs[i].x2; - else - x1 = segs[i].x2, x2 = segs[i].x1; - - ok = render_line_horizontal (hdc, - x1, x2, segs[i].y1, - gcwin32->pen_width, - gcwin32->pen_dashes, - gcwin32->pen_num_dashes); - } - else - { - if (!MoveToEx (hdc, segs[i].x1, segs[i].y1, NULL)) - WIN32_GDI_FAILED ("MoveToEx"), ok = FALSE; - if (ok && !LineTo (hdc, segs[i].x2, segs[i].y2)) - WIN32_GDI_FAILED ("LineTo"), ok = FALSE; - - /* Draw end pixel */ - if (ok && gcwin32->pen_width <= 1) - if (!LineTo (hdc, segs[i].x2 + 1, segs[i].y2)) - WIN32_GDI_FAILED ("LineTo"), ok = FALSE; - } - } - } - else - { - const gboolean maybe_patblt = - gcwin32->rop2 == R2_COPYPEN && - gcwin32->pen_width <= 1 && - (gcwin32->pen_style & PS_STYLE_MASK) == PS_SOLID; - - for (i = 0; ok && i < nsegs; i++) - { - /* PatBlt() is much faster than LineTo(), says - * jpe@archaeopteryx.com. Hmm. Use it if we have a solid - * colour pen, then we know that the brush is also solid and - * of the same colour. - */ - if (maybe_patblt && segs[i].x1 == segs[i].x2) - { - int y1, y2; - - if (segs[i].y1 <= segs[i].y2) - y1 = segs[i].y1, y2 = segs[i].y2; - else - y1 = segs[i].y2, y2 = segs[i].y1; - - if (!PatBlt (hdc, segs[i].x1, y1, - 1, y2 - y1 + 1, PATCOPY)) - WIN32_GDI_FAILED ("PatBlt"), ok = FALSE; - } - else if (maybe_patblt && segs[i].y1 == segs[i].y2) - { - int x1, x2; - - if (segs[i].x1 <= segs[i].x2) - x1 = segs[i].x1, x2 = segs[i].x2; - else - x1 = segs[i].x2, x2 = segs[i].x1; - - if (!PatBlt (hdc, x1, segs[i].y1, - x2 - x1 + 1, 1, PATCOPY)) - WIN32_GDI_FAILED ("PatBlt"), ok = FALSE; - } - else - { - if (!MoveToEx (hdc, segs[i].x1, segs[i].y1, NULL)) - WIN32_GDI_FAILED ("MoveToEx"), ok = FALSE; - if (ok && !LineTo (hdc, segs[i].x2, segs[i].y2)) - WIN32_GDI_FAILED ("LineTo"), ok = FALSE; - - /* Draw end pixel */ - if (ok && gcwin32->pen_width <= 1) - if (!LineTo (hdc, segs[i].x2 + 1, segs[i].y2)) - WIN32_GDI_FAILED ("LineTo"), ok = FALSE; - } - } - } - } - gdk_win32_hdc_release (drawable, gc, mask); - -#endif /* USE_GENERIC_DRAW */ + GDI_CALL (Polyline, (hdc, pts, npoints)); } static void @@ -1630,82 +1295,42 @@ gdk_win32_draw_lines (GdkDrawable *drawable, GdkPoint *points, gint npoints) { - GdkGCWin32 *gcwin32 = GDK_GC_WIN32 (gc); - const GdkGCValuesMask mask = GDK_GC_FOREGROUND|GDK_GC_BACKGROUND; - HDC hdc; + GdkRectangle bounds; + GdkRegion *region; POINT *pts; int i; - gboolean ok = TRUE; + + GDK_NOTE (MISC, g_print ("gdk_win32_draw_lines: %s %d points\n", + gdk_win32_drawable_description (drawable), + npoints)); if (npoints < 2) return; - hdc = gdk_win32_hdc_get (drawable, gc, mask); + bounds.x = G_MAXINT; + bounds.y = G_MAXINT; + bounds.width = 0; + bounds.height = 0; - if (gcwin32->pen_dashes && !IS_WIN_NT ()) + pts = g_new (POINT, npoints); + + for (i = 0; i < npoints; i++) { - for (i = 0; i < npoints - 1; i++) - { - if (points[i].x == points[i+1].x) - { - int y1, y2; - if (points[i].y > points[i+1].y) - y1 = points[i+1].y, y2 = points[i].y; - else - y1 = points[i].y, y2 = points[i+1].y; - - render_line_vertical (hdc, points[i].x, y1, y2, - gcwin32->pen_width, - gcwin32->pen_dashes, - gcwin32->pen_num_dashes); - } - else if (points[i].y == points[i+1].y) - { - int x1, x2; - if (points[i].x > points[i+1].x) - x1 = points[i+1].x, x2 = points[i].x; - else - x1 = points[i].x, x2 = points[i+1].x; - - render_line_horizontal (hdc, x1, x2, points[i].y, - gcwin32->pen_width, - gcwin32->pen_dashes, - gcwin32->pen_num_dashes); - } - else - { - if (!MoveToEx (hdc, points[i].x, points[i].y, NULL)) - WIN32_GDI_FAILED ("MoveToEx"), ok = FALSE; - if (ok && !LineTo (hdc, points[i+1].x, points[i+1].y)) - WIN32_GDI_FAILED ("LineTo"), ok = FALSE; - } - } - } - else - { - pts = g_new (POINT, npoints); - - for (i = 0; i < npoints; i++) - { - pts[i].x = points[i].x; - pts[i].y = points[i].y; - } - - if (!Polyline (hdc, pts, npoints)) - WIN32_GDI_FAILED ("Polyline"), ok = FALSE; - - g_free (pts); - - /* Draw end pixel */ - if (ok && gcwin32->pen_width <= 1) - { - MoveToEx (hdc, points[npoints-1].x, points[npoints-1].y, NULL); - if (!LineTo (hdc, points[npoints-1].x + 1, points[npoints-1].y)) - WIN32_GDI_FAILED ("LineTo"); - } + bounds.x = MIN (bounds.x, points[i].x); + bounds.y = MIN (bounds.y, points[i].y); + bounds.width = MAX (bounds.width, points[i].x - bounds.x); + bounds.height = MAX (bounds.height, points[i].y - bounds.y); + pts[i].x = points[i].x; + pts[i].y = points[i].y; } - gdk_win32_hdc_release (drawable, gc, mask); + region = widen_bounds (&bounds, GDK_GC_WIN32 (gc)->pen_width); + + generic_draw (drawable, gc, GDK_GC_FOREGROUND|LINE_ATTRIBUTES, + draw_lines, region, pts, npoints); + + gdk_region_destroy (region); + g_free (pts); } static void @@ -1728,13 +1353,6 @@ draw_glyphs (GdkGCWin32 *gcwin32, x -= x_offset; y -= y_offset; - /* HB: Maybe there should be a GDK_GC_PANGO flag for hdc_get */ - /* default write mode is transparent (leave background) */ - GDI_CALL (SetBkMode, (hdc, TRANSPARENT)); - - if (GDI_ERROR == SetTextAlign (hdc, TA_LEFT|TA_BASELINE|TA_NOUPDATECP)) - WIN32_GDI_FAILED ("SetTextAlign"); - pango_win32_render (hdc, font, glyphs, x, y); } @@ -1746,8 +1364,6 @@ gdk_win32_draw_glyphs (GdkDrawable *drawable, gint y, PangoGlyphString *glyphs) { -#ifdef USE_GENERIC_DRAW - GdkRectangle bounds; GdkRegion *region; PangoRectangle ink_rect; @@ -1760,30 +1376,10 @@ gdk_win32_draw_glyphs (GdkDrawable *drawable, bounds.height = PANGO_PIXELS (ink_rect.height) + 2; region = gdk_region_rectangle (&bounds); - generic_draw (drawable, gc, GDK_GC_FOREGROUND, + generic_draw (drawable, gc, GDK_GC_FOREGROUND|GDK_GC_FONT, draw_glyphs, region, font, x, y, glyphs); gdk_region_destroy (region); - -#else - - const GdkGCValuesMask mask = GDK_GC_FOREGROUND; - HDC hdc; - - hdc = gdk_win32_hdc_get (drawable, gc, mask); - - /* HB: Maybe there should be a GDK_GC_PANGO flag for hdc_get */ - /* default write mode is transparent (leave background) */ - GDI_CALL (SetBkMode, (hdc, TRANSPARENT)); - - if (GDI_ERROR == SetTextAlign (hdc, TA_LEFT|TA_BASELINE|TA_NOUPDATECP)) - WIN32_GDI_FAILED ("SetTextAlign"); - - pango_win32_render (hdc, font, glyphs, x, y); - - gdk_win32_hdc_release (drawable, gc, mask); - -#endif } static void diff --git a/gdk/win32/gdkgc-win32.c b/gdk/win32/gdkgc-win32.c index ecbe9cba88..d3b9439758 100644 --- a/gdk/win32/gdkgc-win32.c +++ b/gdk/win32/gdkgc-win32.c @@ -25,7 +25,8 @@ * GTK+ at ftp://ftp.gtk.org/pub/gtk/. */ -#define USE_GENERIC_DRAW /* See also gdkdrawable-win32.c */ +#define LINE_ATTRIBUTES (GDK_GC_LINE_WIDTH|GDK_GC_LINE_STYLE| \ + GDK_GC_CAP_STYLE|GDK_GC_JOIN_STYLE) #include @@ -769,15 +770,12 @@ _gdk_win32_colormap_color (GdkColormap *colormap, } } -static void +static COLORREF predraw_set_foreground (GdkGC *gc, GdkColormap *colormap, gboolean *ok) { COLORREF fg; - LOGBRUSH logbrush; - HPEN hpen; - HBRUSH hbr; GdkGCWin32 *win32_gc = (GdkGCWin32 *) gc; GdkColormapPrivateWin32 *colormap_private; gint k; @@ -802,94 +800,59 @@ predraw_set_foreground (GdkGC *gc, fg = _gdk_win32_colormap_color (colormap, win32_gc->foreground); GDK_NOTE (GC, g_print ("predraw_set_foreground: fg=%06lx\n", fg)); - - if (SetTextColor (win32_gc->hdc, fg) == CLR_INVALID) - WIN32_GDI_FAILED ("SetTextColor"), *ok = FALSE; - - /* Create and select pen and brush. */ - - logbrush.lbStyle = BS_SOLID; - logbrush.lbColor = fg; - logbrush.lbHatch = 0; - - if (win32_gc->pen_num_dashes > 0 && !IS_WIN_NT ()) - { - /* The Win9x GDI is rather limited so we either draw dotted - * lines ourselve (only horizontal and vertical) or let them - * be drawn solid to avoid implementing a whole line renderer - */ - if (*ok && (hpen = ExtCreatePen ( - (win32_gc->pen_style & ~(PS_STYLE_MASK)) | PS_SOLID, - (win32_gc->pen_width > 0 ? win32_gc->pen_width : 1), - &logbrush, - 0, NULL)) == NULL) - WIN32_GDI_FAILED ("ExtCreatePen"), *ok = FALSE; - } - else - { - if (*ok && (hpen = ExtCreatePen (win32_gc->pen_style, - (win32_gc->pen_width > 0 ? win32_gc->pen_width : 1), - &logbrush, - win32_gc->pen_num_dashes, - win32_gc->pen_dashes)) == NULL) - WIN32_GDI_FAILED ("ExtCreatePen"), *ok = FALSE; - } - - if (*ok && SelectObject (win32_gc->hdc, hpen) == NULL) - WIN32_GDI_FAILED ("SelectObject"), *ok = FALSE; - - switch (win32_gc->fill_style) - { -#ifndef USE_GENERIC_DRAW - case GDK_OPAQUE_STIPPLED: - if (*ok && (hbr = CreatePatternBrush (GDK_PIXMAP_HBITMAP (win32_gc->stipple))) == NULL) - WIN32_GDI_FAILED ("CreatePatternBrush"), *ok = FALSE; - if (*ok && win32_gc->values_mask & (GDK_GC_TS_X_ORIGIN | GDK_GC_TS_Y_ORIGIN) && - !SetBrushOrgEx(win32_gc->hdc, - win32_gc->values_mask & GDK_GC_TS_X_ORIGIN ? gc->ts_x_origin : 0, - win32_gc->values_mask & GDK_GC_TS_Y_ORIGIN ? gc->ts_y_origin : 0, - NULL)) - WIN32_GDI_FAILED ("SetBrushOrgEx"), *ok = FALSE; - - break; - - case GDK_SOLID: -#endif - default: - if (*ok && (hbr = CreateSolidBrush (fg)) == NULL) - WIN32_GDI_FAILED ("CreateSolidBrush"), *ok = FALSE; - break; - } - - if (*ok) - { - HBRUSH old_hbr = SelectObject (win32_gc->hdc, hbr); - if (old_hbr == NULL) - WIN32_GDI_FAILED ("SelectObject"), *ok = FALSE; - } -} - -static void -predraw_set_background (GdkGC *gc, - GdkColormap *colormap, - gboolean *ok) -{ - GdkGCWin32 *win32_gc = (GdkGCWin32 *) gc; - - if (win32_gc->values_mask & GDK_GC_BACKGROUND) - { - COLORREF bg = _gdk_win32_colormap_color (colormap, win32_gc->background); - - if (SetBkColor (win32_gc->hdc, bg) == CLR_INVALID) - WIN32_GDI_FAILED ("SetBkColor"), *ok = FALSE; - } - else - { - if (!SetBkMode (win32_gc->hdc, TRANSPARENT)) - WIN32_GDI_FAILED ("SetBkMode"), *ok = FALSE; - } + return fg; } +/** + * 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 + * gdk_win32_hdc_release() with the same + * parameters. + * + * If you modify the HDC by calling SelectObject + * you should undo those modifications before calling + * gdk_win32_hdc_release(). + * + * Return value: The HDC. + **/ HDC gdk_win32_hdc_get (GdkDrawable *drawable, GdkGC *gc, @@ -898,6 +861,10 @@ gdk_win32_hdc_get (GdkDrawable *drawable, GdkGCWin32 *win32_gc = (GdkGCWin32 *) gc; GdkDrawableImplWin32 *impl = NULL; gboolean ok = TRUE; + COLORREF fg = RGB (0, 0, 0); + LOGBRUSH logbrush; + HPEN hpen; + HBRUSH hbr; g_assert (win32_gc->hdc == NULL); @@ -933,21 +900,62 @@ gdk_win32_hdc_get (GdkDrawable *drawable, } if (ok && (usage & GDK_GC_FOREGROUND)) - predraw_set_foreground (gc, impl->colormap, &ok); + { + fg = predraw_set_foreground (gc, impl->colormap, &ok); + if (ok && (hbr = CreateSolidBrush (fg)) == NULL) + WIN32_GDI_FAILED ("CreateSolidBrush"), ok = FALSE; + + if (ok && SelectObject (win32_gc->hdc, hbr) == NULL) + WIN32_GDI_FAILED ("SelectObject"), ok = FALSE; + + if (ok && SetTextColor (win32_gc->hdc, fg) == CLR_INVALID) + WIN32_GDI_FAILED ("SetTextColor"), ok = FALSE; + } + + if (ok && (usage & LINE_ATTRIBUTES)) + { + /* Create and select pen */ + logbrush.lbStyle = BS_SOLID; + logbrush.lbColor = fg; + logbrush.lbHatch = 0; + + if (win32_gc->pen_num_dashes > 0 && !IS_WIN_NT ()) + { + /* The Win9x GDI is rather limited so we either draw dashed + * lines ourselves (only horizontal and vertical) or let them be + * drawn solid to avoid implementing a whole line renderer. + */ + if ((hpen = ExtCreatePen ( + (win32_gc->pen_style & ~(PS_STYLE_MASK)) | PS_SOLID, + MAX (win32_gc->pen_width, 1), + &logbrush, + 0, NULL)) == NULL) + WIN32_GDI_FAILED ("ExtCreatePen"), ok = FALSE; + } + else + { + if ((hpen = ExtCreatePen (win32_gc->pen_style, + MAX (win32_gc->pen_width, 1), + &logbrush, + win32_gc->pen_num_dashes, + win32_gc->pen_dashes)) == NULL) + WIN32_GDI_FAILED ("ExtCreatePen"), ok = FALSE; + } + + if (ok && SelectObject (win32_gc->hdc, hpen) == NULL) + WIN32_GDI_FAILED ("SelectObject"), ok = FALSE; + } - if (ok && (usage & GDK_GC_BACKGROUND)) - predraw_set_background (gc, impl->colormap, &ok); - if (ok && (usage & GDK_GC_FONT)) { if (SetBkMode (win32_gc->hdc, TRANSPARENT) == 0) WIN32_GDI_FAILED ("SetBkMode"), ok = FALSE; - if (ok && SetTextAlign (win32_gc->hdc, TA_BASELINE) == GDI_ERROR) + if (ok && SetTextAlign (win32_gc->hdc, TA_BASELINE|TA_LEFT|TA_NOUPDATECP) == GDI_ERROR) WIN32_GDI_FAILED ("SetTextAlign"), ok = FALSE; } - if (ok && (win32_gc->values_mask & GDK_GC_FUNCTION)) + if (ok && win32_gc->rop2 != R2_COPYPEN) if (SetROP2 (win32_gc->hdc, win32_gc->rop2) == 0) WIN32_GDI_FAILED ("SetROP2"), ok = FALSE; @@ -958,33 +966,6 @@ gdk_win32_hdc_get (GdkDrawable *drawable, if (SelectClipRgn (win32_gc->hdc, win32_gc->hcliprgn) == ERROR) WIN32_API_FAILED ("SelectClipRgn"), ok = FALSE; -#if 0 /* No, this is totally bogus. The stipple should replicate in x - * and y directions, not be just one copy of the bitmap. We must - * handle stipples elsewhere. - */ - /* Combine the fillmode-stipple with the clip region */ - if (ok && - (win32_gc->values_mask & GDK_GC_STIPPLE) && - (win32_gc->values_mask & GDK_GC_FILL) && - (win32_gc->fill_style == GDK_STIPPLED)) - { - HRGN hstipplergn; - - if ((hstipplergn = _gdk_win32_bitmap_to_hrgn (win32_gc->stipple)) == NULL) - ; - else if (win32_gc->values_mask & (GDK_GC_TS_X_ORIGIN | GDK_GC_TS_Y_ORIGIN) && - OffsetRgn (hstipplergn, - win32_gc->values_mask & GDK_GC_TS_X_ORIGIN ? gc->ts_x_origin : 0, - win32_gc->values_mask & GDK_GC_TS_Y_ORIGIN ? gc->ts_y_origin : 0) == ERROR) - WIN32_API_FAILED ("OffsetRgn"); - else if (ExtSelectClipRgn (win32_gc->hdc, hstipplergn, RGN_AND) == ERROR) - WIN32_API_FAILED ("ExtSelectClipRgn"); - - if (hstipplergn != NULL && !DeleteObject (hstipplergn)) - WIN32_API_FAILED ("DeleteObject"); - } -#endif - if (ok && win32_gc->values_mask & (GDK_GC_CLIP_X_ORIGIN | GDK_GC_CLIP_Y_ORIGIN) && OffsetClipRgn (win32_gc->hdc, win32_gc->values_mask & GDK_GC_CLIP_X_ORIGIN ? gc->clip_x_origin : 0, @@ -999,6 +980,16 @@ gdk_win32_hdc_get (GdkDrawable *drawable, return win32_gc->hdc; } +/** + * gdk_win32_hdc_release: + * @drawable: destination #GdkDrawable + * @gc: #GdkGC to use for drawing on @drawable + * @usage: mask indicating what properties were set up + * + * This function deallocates the Windows device context allocated by + * gdk_win32_hdc_get(). It should be called with + * the same parameters. + **/ void gdk_win32_hdc_release (GdkDrawable *drawable, GdkGC *gc, @@ -1036,36 +1027,26 @@ gdk_win32_hdc_release (GdkDrawable *drawable, win32_gc->holdpal = NULL; } + if (usage & (LINE_ATTRIBUTES)) + if ((hpen = GetCurrentObject (win32_gc->hdc, OBJ_PEN)) == NULL) + WIN32_GDI_FAILED ("GetCurrentObject"); + if (usage & GDK_GC_FOREGROUND) - { - if ((hpen = GetCurrentObject (win32_gc->hdc, OBJ_PEN)) == NULL) - WIN32_GDI_FAILED ("GetCurrentObject"); + if ((hbr = GetCurrentObject (win32_gc->hdc, OBJ_BRUSH)) == NULL) + WIN32_GDI_FAILED ("GetCurrentObject"); - if ((hbr = GetCurrentObject (win32_gc->hdc, OBJ_BRUSH)) == NULL) - WIN32_GDI_FAILED ("GetCurrentObject"); - } - - if (!RestoreDC (win32_gc->hdc, win32_gc->saved_dc)) - WIN32_GDI_FAILED ("RestoreDC"); + GDI_CALL (RestoreDC, (win32_gc->hdc, win32_gc->saved_dc)); if (GDK_IS_PIXMAP_IMPL_WIN32 (impl)) - { - if (!DeleteDC (win32_gc->hdc)) - WIN32_GDI_FAILED ("DeleteDC"); - } + GDI_CALL (DeleteDC, (win32_gc->hdc)); else - { - if (!ReleaseDC (win32_gc->hwnd, win32_gc->hdc)) - WIN32_GDI_FAILED ("ReleaseDC"); - } + GDI_CALL (ReleaseDC, (win32_gc->hwnd, win32_gc->hdc)); if (hpen != NULL) - if (!DeleteObject (hpen)) - WIN32_GDI_FAILED ("DeleteObject"); + GDI_CALL (DeleteObject, (hpen)); if (hbr != NULL) - if (!DeleteObject (hbr)) - WIN32_GDI_FAILED ("DeleteObject"); + GDI_CALL (DeleteObject, (hbr)); win32_gc->hdc = NULL; }