?? gdkdrawable-win32.c
字號:
gint tile_x_origin, gint tile_y_origin, gint width, gint height){ const GdkGCValuesMask mask = GDK_GC_FOREGROUND; gint tile_width, tile_height; GdkGC *gc_copy; HDC dest_hdc, tile_hdc; gc_copy = gdk_gc_new (tile); gdk_gc_copy (gc_copy, gc); dest_hdc = gdk_win32_hdc_get (drawable, gc, mask); tile_hdc = gdk_win32_hdc_get (tile, gc_copy, mask); gdk_drawable_get_size (tile, &tile_width, &tile_height); draw_tiles_lowlevel (dest_hdc, tile_hdc, rop3, dest_x, dest_y, tile_x_origin, tile_y_origin, width, height, tile_width, tile_height); gdk_win32_hdc_release (drawable, gc, mask); gdk_win32_hdc_release (tile, gc_copy, mask); gdk_gc_unref (gc_copy);}static voidgeneric_draw (GdkDrawable *drawable, GdkGC *gc, GdkGCValuesMask mask, void (*function) (GdkGCWin32 *, HDC, gint, gint, va_list), const GdkRegion *region, ...){ GdkDrawableImplWin32 *impl = GDK_DRAWABLE_IMPL_WIN32 (drawable); GdkGCWin32 *gcwin32 = GDK_GC_WIN32 (gc); HDC hdc; va_list args; va_start (args, region); /* If tiled or stippled, draw to a temp pixmap and do blitting magic. */ if (gcwin32->values_mask & GDK_GC_FILL && ((gcwin32->fill_style == GDK_TILED && gcwin32->values_mask & GDK_GC_TILE && gcwin32->tile != NULL) || ((gcwin32->fill_style == GDK_OPAQUE_STIPPLED || gcwin32->fill_style == GDK_STIPPLED) && 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; gint height = region->extents.y2 - region->extents.y1; GdkPixmap *mask_pixmap = gdk_pixmap_new (drawable, width, height, 1); GdkPixmap *tile_pixmap = gdk_pixmap_new (drawable, width, height, -1); GdkPixmap *stipple_bitmap = NULL; GdkColor fg; GdkGC *mask_gc = gdk_gc_new (mask_pixmap); GdkGC *tile_gc = gdk_gc_new (tile_pixmap); HDC mask_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) ts_y_origin = gc->ts_y_origin; ts_x_origin -= region->extents.x1; ts_y_origin -= region->extents.y1; /* Fill mask bitmap with zeros */ gdk_gc_set_function (mask_gc, GDK_CLEAR); gdk_draw_rectangle (mask_pixmap, mask_gc, TRUE, 0, 0, width, height); /* Paint into mask bitmap, drawing ones */ gdk_gc_set_function (mask_gc, GDK_COPY); fg.pixel = 1; gdk_gc_set_foreground (mask_gc, &fg); /* 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, drawing_mask); if (gcwin32->fill_style == GDK_TILED) { /* Tile pixmap with tile */ draw_tiles (tile_pixmap, tile_gc, SRCCOPY, gcwin32->tile, 0, 0, ts_x_origin, ts_y_origin, width, height); } else { /* Tile with stipple */ GdkGC *stipple_gc; stipple_bitmap = gdk_pixmap_new (NULL, width, height, 1); stipple_gc = gdk_gc_new (stipple_bitmap); /* Tile stipple bitmap */ draw_tiles (stipple_bitmap, stipple_gc, SRCCOPY, gcwin32->stipple, 0, 0, ts_x_origin, ts_y_origin, width, height); if (gcwin32->fill_style == GDK_OPAQUE_STIPPLED) { /* Fill tile pixmap with background */ fg.pixel = gcwin32->background; gdk_gc_set_foreground (tile_gc, &fg); gdk_draw_rectangle (tile_pixmap, tile_gc, TRUE, 0, 0, width, height); } gdk_gc_unref (stipple_gc); } gdk_gc_unref (mask_gc); gdk_gc_unref (tile_gc); mask_hdc = CreateCompatibleDC (hdc); if ((old_mask_hbm = SelectObject (mask_hdc, GDK_PIXMAP_HBITMAP (mask_pixmap))) == NULL) WIN32_GDI_FAILED ("SelectObject"); if ((old_tile_hbm = SelectObject (tile_hdc, GDK_PIXMAP_HBITMAP (tile_pixmap))) == NULL) WIN32_GDI_FAILED ("SelectObject"); if (gcwin32->fill_style == GDK_STIPPLED || gcwin32->fill_style == GDK_OPAQUE_STIPPLED) { HDC stipple_hdc; HGDIOBJ old_stipple_hbm; HBRUSH fg_brush; HGDIOBJ old_tile_brush; if ((stipple_hdc = CreateCompatibleDC (hdc)) == NULL) WIN32_GDI_FAILED ("CreateCompatibleDC"); if ((old_stipple_hbm = SelectObject (stipple_hdc, GDK_PIXMAP_HBITMAP (stipple_bitmap))) == NULL) WIN32_GDI_FAILED ("SelectObject"); if ((fg_brush = CreateSolidBrush (_gdk_win32_colormap_color (impl->colormap, gcwin32->foreground))) == NULL) WIN32_GDI_FAILED ("CreateSolidBrush"); if ((old_tile_brush = SelectObject (tile_hdc, fg_brush)) == NULL) WIN32_GDI_FAILED ("SelectObject"); /* Paint tile with foreround where stipple is one * * Desired ternary ROP: (P=foreground, S=stipple, D=destination) * P S D ? * 0 0 0 0 * 0 0 1 1 * 0 1 0 0 * 0 1 1 0 * 1 0 0 0 * 1 0 1 1 * 1 1 0 1 * 1 1 1 1 * * Reading bottom-up: 11100010 = 0xE2. PSDK docs say this is * known as DSPDxax, with hex value 0x00E20746. */ GDI_CALL (BitBlt, (tile_hdc, 0, 0, width, height, stipple_hdc, 0, 0, ROP3_DSPDxax)); if (gcwin32->fill_style == GDK_STIPPLED) { /* Punch holes in mask where stipple is zero */ GDI_CALL (BitBlt, (mask_hdc, 0, 0, width, height, stipple_hdc, 0, 0, SRCAND)); } GDI_CALL (SelectObject, (tile_hdc, old_tile_brush)); GDI_CALL (DeleteObject, (fg_brush)); GDI_CALL (SelectObject, (stipple_hdc, old_stipple_hbm)); GDI_CALL (DeleteDC, (stipple_hdc)); g_object_unref (stipple_bitmap); } /* Tile pixmap now contains the pattern that we should paint in * the areas where mask is one. (It is filled with said pattern.) */ if (G_WIN32_IS_NT_BASED ()) { GDI_CALL (MaskBlt, (hdc, region->extents.x1, region->extents.y1, width, height, tile_hdc, 0, 0, GDK_PIXMAP_HBITMAP (mask_pixmap), 0, 0, MAKEROP4 (rop2_to_rop3 (gcwin32->rop2), ROP3_D))); } else { GdkPixmap *temp1_pixmap = gdk_pixmap_new (drawable, width, height, -1); GdkPixmap *temp2_pixmap = gdk_pixmap_new (drawable, width, height, -1); HDC temp1_hdc = CreateCompatibleDC (hdc); HDC temp2_hdc = CreateCompatibleDC (hdc); HGDIOBJ old_temp1_hbm = SelectObject (temp1_hdc, GDK_PIXMAP_HBITMAP (temp1_pixmap)); HGDIOBJ old_temp2_hbm = SelectObject (temp2_hdc, GDK_PIXMAP_HBITMAP (temp2_pixmap)); /* Grab copy of dest region to temp1 */ GDI_CALL (BitBlt,(temp1_hdc, 0, 0, width, height, hdc, region->extents.x1, region->extents.y1, SRCCOPY)); /* Paint tile to temp1 using correct function */ GDI_CALL (BitBlt, (temp1_hdc, 0, 0, width, height, tile_hdc, 0, 0, rop2_to_rop3 (gcwin32->rop2))); /* Mask out temp1 where function didn't paint */ GDI_CALL (BitBlt, (temp1_hdc, 0, 0, width, height, mask_hdc, 0, 0, SRCAND)); /* Grab another copy of dest region to temp2 */ GDI_CALL (BitBlt, (temp2_hdc, 0, 0, width, height, hdc, region->extents.x1, region->extents.y1, SRCCOPY)); /* Mask out temp2 where function did paint */ GDI_CALL (BitBlt, (temp2_hdc, 0, 0, width, height, mask_hdc, 0, 0, ROP3_DSna)); /* Combine temp1 with temp2 */ GDI_CALL (BitBlt, (temp2_hdc, 0, 0, width, height, temp1_hdc, 0, 0, SRCPAINT)); /* Blit back */ GDI_CALL (BitBlt, (hdc, region->extents.x1, region->extents.y1, width, height, temp2_hdc, 0, 0, SRCCOPY)); /* Cleanup */ GDI_CALL (SelectObject, (temp1_hdc, old_temp1_hbm)); GDI_CALL (SelectObject, (temp2_hdc, old_temp2_hbm)); GDI_CALL (DeleteDC, (temp1_hdc)); GDI_CALL (DeleteDC, (temp2_hdc)); g_object_unref (temp1_pixmap); g_object_unref (temp2_pixmap); } /* Cleanup */ GDI_CALL (SelectObject, (mask_hdc, old_mask_hbm)); GDI_CALL (SelectObject, (tile_hdc, old_tile_hbm)); GDI_CALL (DeleteDC, (mask_hdc)); GDI_CALL (DeleteDC, (tile_hdc)); g_object_unref (mask_pixmap); g_object_unref (tile_pixmap); gdk_win32_hdc_release (drawable, gc, blitting_mask); } else { hdc = gdk_win32_hdc_get (drawable, gc, mask); (*function) (gcwin32, hdc, 0, 0, args); gdk_win32_hdc_release (drawable, gc, mask); } va_end (args);}static GdkRegion *widen_bounds (GdkRectangle *bounds, gint pen_width){ if (pen_width == 0) pen_width = 1; bounds->x -= pen_width; bounds->y -= pen_width; bounds->width += 2 * pen_width; bounds->height += 2 * pen_width; return gdk_region_rectangle (bounds);}static voiddraw_rectangle (GdkGCWin32 *gcwin32, HDC hdc, gint x_offset, gint y_offset, va_list args){ HGDIOBJ old_pen_or_brush; gboolean filled; gint x; gint y; gint width; gint height; filled = va_arg (args, gboolean); x = va_arg (args, gint); y = va_arg (args, gint); width = va_arg (args, gint); height = va_arg (args, gint); x -= x_offset; y -= y_offset; if (!filled && MUST_RENDER_DASHES_MANUALLY (gcwin32)) { render_line_vertical (gcwin32, x, y, y+height+1) && render_line_horizontal (gcwin32, x, x+width+1, y) && render_line_vertical (gcwin32, x+width+1, y, y+height+1) && render_line_horizontal (gcwin32, x, x+width+1, y+height+1); } 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"); else GDI_CALL (Rectangle, (hdc, x, y, x+width+1, y+height+1)); if (old_pen_or_brush != NULL) GDI_CALL (SelectObject, (hdc, old_pen_or_brush)); }}static voidgdk_win32_draw_rectangle (GdkDrawable *drawable, GdkGC *gc, gboolean filled, gint x, gint y, gint width, gint height){ GdkRectangle bounds; GdkRegion *region; GDK_NOTE (MISC, g_print ("gdk_win32_draw_rectangle: %s (%p) %s%dx%d@+%d+%d\n", _gdk_win32_drawable_description (drawable), gc, (filled ? "fill " : ""), width, height, x, y)); bounds.x = x; bounds.y = y; bounds.width = width; bounds.height = height; region = widen_bounds (&bounds, GDK_GC_WIN32 (gc)->pen_width); generic_draw (drawable, gc, GDK_GC_FOREGROUND | GDK_GC_BACKGROUND | (filled ? 0 : LINE_ATTRIBUTES), draw_rectangle, region, filled, x, y, width, height); gdk_region_destroy (region);}static voiddraw_arc (GdkGCWin32 *gcwin32, HDC hdc, gint x_offset, gint y_offset, va_list args){ HGDIOBJ old_pen; gboolean filled; gint x, y; gint width, height; gint angle1, angle2; int nXStartArc, nYStartArc, nXEndArc, nYEndArc; filled = va_arg (args, gboolean); x = va_arg (args, gint); y = va_arg (args, gint); width = va_arg (args, gint); height = va_arg (args, gint); angle1 = va_arg (args, gint); angle2 = va_arg (args, gint); x -= x_offset; y -= y_offset; if (angle2 >= 360*64) { nXStartArc = nYStartArc = nXEndArc = nYEndArc = 0; } else if (angle2 > 0) { nXStartArc = x + width/2 + width * cos(angle1/64.*2.*G_PI/360.); nYStartArc = y + height/2 + -height * sin(angle1/64.*2.*G_PI/360.); nXEndArc = x + width/2 + width * cos((angle1+angle2)/64.*2.*G_PI/360.); nYEndArc = y + height/2 + -height * sin((angle1+angle2)/64.*2.*G_PI/360.); } else { nXEndArc = x + width/2 + width * cos(angle1/64.*2.*G_PI/360.); nYEndArc = y + height/2 + -height * sin(angle1/64.*2.*G_PI/360.); nXStartArc = x + width/2 + width * cos((angle1+angle2)/64.*2.*G_PI/360.); nYStartArc = y + height/2 + -height * sin((angle1+angle2)/64.*2.*G_PI/360.); } 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)); }}static voidgdk_win32_draw_arc (GdkDrawable *drawable, GdkGC *gc, gboolean filled, gint x, gint y, gint width, gint height, gint angle1, gint angle2){ GdkRectangle bounds; GdkRegion *region; GDK_NOTE (MISC, g_print ("gdk_win32_draw_arc: %s %d,%d,%d,%d %d %d\n", _gdk_win32_drawable_description (drawable), x, y, width, height, angle1, angle2)); if (width <= 2 || height <= 2 || angle2 == 0) return; bounds.x = x; bounds.y = y; bounds.width = width; bounds.height = height; region = widen_bounds (&bounds, GDK_GC_WIN32 (gc)->pen_width);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -