?? gdkdrawable-win32.c
字號:
/* GDK - The GIMP Drawing Kit * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald * Copyright (C) 1998-2004 Tor Lillqvist * Copyright (C) 2001-2005 Hans Breuer * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. *//* * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS * 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 <math.h>#include <stdio.h>#include <glib.h>#include <pango/pangowin32.h>#include "gdkscreen.h" /* gdk_screen_get_default() */#include "gdkregion-generic.h"#include "gdkprivate-win32.h"#define ROP3_D 0x00AA0029#define ROP3_DSna 0x00220326#define ROP3_DSPDxax 0x00E20746#define LINE_ATTRIBUTES (GDK_GC_LINE_WIDTH|GDK_GC_LINE_STYLE| \ GDK_GC_CAP_STYLE|GDK_GC_JOIN_STYLE)#define MUST_RENDER_DASHES_MANUALLY(gcwin32) \ (gcwin32->line_style == GDK_LINE_DOUBLE_DASH || \ (gcwin32->line_style == GDK_LINE_ON_OFF_DASH && \ (gcwin32->pen_dash_offset || \ (!G_WIN32_IS_NT_BASED () && (gcwin32->pen_style & PS_STYLE_MASK) == PS_SOLID))))static void gdk_win32_draw_rectangle (GdkDrawable *drawable, GdkGC *gc, gboolean filled, gint x, gint y, gint width, gint height);static void gdk_win32_draw_arc (GdkDrawable *drawable, GdkGC *gc, gboolean filled, gint x, gint y, gint width, gint height, gint angle1, gint angle2);static void gdk_win32_draw_polygon (GdkDrawable *drawable, GdkGC *gc, gboolean filled, GdkPoint *points, gint npoints);static void gdk_win32_draw_text (GdkDrawable *drawable, GdkFont *font, GdkGC *gc, gint x, gint y, const gchar *text, gint text_length);static void gdk_win32_draw_text_wc (GdkDrawable *drawable, GdkFont *font, GdkGC *gc, gint x, gint y, const GdkWChar *text, gint text_length);static void gdk_win32_draw_drawable (GdkDrawable *drawable, GdkGC *gc, GdkPixmap *src, gint xsrc, gint ysrc, gint xdest, gint ydest, gint width, gint height);static void gdk_win32_draw_points (GdkDrawable *drawable, GdkGC *gc, GdkPoint *points, gint npoints);static void gdk_win32_draw_segments (GdkDrawable *drawable, GdkGC *gc, GdkSegment *segs, gint nsegs);static void gdk_win32_draw_lines (GdkDrawable *drawable, GdkGC *gc, GdkPoint *points, gint npoints);static void gdk_win32_draw_glyphs (GdkDrawable *drawable, GdkGC *gc, PangoFont *font, gint x, gint y, PangoGlyphString *glyphs);static void gdk_win32_draw_glyphs_transformed (GdkDrawable *drawable, GdkGC *gc, PangoMatrix *matrix, PangoFont *font, gint x, gint y, PangoGlyphString *glyphs);static void gdk_win32_draw_image (GdkDrawable *drawable, GdkGC *gc, GdkImage *image, gint xsrc, gint ysrc, gint xdest, gint ydest, gint width, gint height);static void gdk_win32_set_colormap (GdkDrawable *drawable, GdkColormap *colormap);static GdkColormap* gdk_win32_get_colormap (GdkDrawable *drawable);static gint gdk_win32_get_depth (GdkDrawable *drawable);static GdkScreen * gdk_win32_get_screen (GdkDrawable *drawable);static GdkVisual* gdk_win32_get_visual (GdkDrawable *drawable);static void gdk_drawable_impl_win32_class_init (GdkDrawableImplWin32Class *klass);static void gdk_drawable_impl_win32_finalize (GObject *object);static gpointer parent_class = NULL;GTypegdk_drawable_impl_win32_get_type (void){ static GType object_type = 0; if (!object_type) { static const GTypeInfo object_info = { sizeof (GdkDrawableImplWin32Class), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) gdk_drawable_impl_win32_class_init, NULL, /* class_finalize */ NULL, /* class_data */ sizeof (GdkDrawableImplWin32), 0, /* n_preallocs */ (GInstanceInitFunc) NULL, }; object_type = g_type_register_static (GDK_TYPE_DRAWABLE, "GdkDrawableImplWin32", &object_info, 0); } return object_type;}static voidgdk_drawable_impl_win32_class_init (GdkDrawableImplWin32Class *klass){ GdkDrawableClass *drawable_class = GDK_DRAWABLE_CLASS (klass); GObjectClass *object_class = G_OBJECT_CLASS (klass); parent_class = g_type_class_peek_parent (klass); object_class->finalize = gdk_drawable_impl_win32_finalize; drawable_class->create_gc = _gdk_win32_gc_new; drawable_class->draw_rectangle = gdk_win32_draw_rectangle; drawable_class->draw_arc = gdk_win32_draw_arc; drawable_class->draw_polygon = gdk_win32_draw_polygon; drawable_class->draw_text = gdk_win32_draw_text; drawable_class->draw_text_wc = gdk_win32_draw_text_wc; drawable_class->draw_drawable = gdk_win32_draw_drawable; drawable_class->draw_points = gdk_win32_draw_points; drawable_class->draw_segments = gdk_win32_draw_segments; drawable_class->draw_lines = gdk_win32_draw_lines; drawable_class->draw_glyphs = gdk_win32_draw_glyphs; drawable_class->draw_glyphs_transformed = gdk_win32_draw_glyphs_transformed; drawable_class->draw_image = gdk_win32_draw_image; drawable_class->set_colormap = gdk_win32_set_colormap; drawable_class->get_colormap = gdk_win32_get_colormap; drawable_class->get_depth = gdk_win32_get_depth; drawable_class->get_screen = gdk_win32_get_screen; drawable_class->get_visual = gdk_win32_get_visual; drawable_class->_copy_to_image = _gdk_win32_copy_to_image;}static voidgdk_drawable_impl_win32_finalize (GObject *object){ gdk_drawable_set_colormap (GDK_DRAWABLE (object), NULL); G_OBJECT_CLASS (parent_class)->finalize (object);}/***************************************************** * Win32 specific implementations of generic functions * *****************************************************/static GdkColormap*gdk_win32_get_colormap (GdkDrawable *drawable){ return GDK_DRAWABLE_IMPL_WIN32 (drawable)->colormap;}static voidgdk_win32_set_colormap (GdkDrawable *drawable, GdkColormap *colormap){ GdkDrawableImplWin32 *impl = GDK_DRAWABLE_IMPL_WIN32 (drawable); if (impl->colormap == colormap) return; if (impl->colormap) gdk_colormap_unref (impl->colormap); impl->colormap = colormap; if (impl->colormap) gdk_colormap_ref (impl->colormap);}/* Drawing */static introp2_to_rop3 (int rop2){ switch (rop2) { /* Oh, Microsoft's silly names for binary and ternary rops. */#define CASE(rop2,rop3) case R2_##rop2: return rop3 CASE (BLACK, BLACKNESS); CASE (NOTMERGEPEN, NOTSRCERASE); CASE (MASKNOTPEN, 0x00220326); CASE (NOTCOPYPEN, NOTSRCCOPY); CASE (MASKPENNOT, SRCERASE); CASE (NOT, DSTINVERT); CASE (XORPEN, SRCINVERT); CASE (NOTMASKPEN, 0x007700E6); CASE (MASKPEN, SRCAND); CASE (NOTXORPEN, 0x00990066); CASE (NOP, 0x00AA0029); CASE (MERGENOTPEN, MERGEPAINT); CASE (COPYPEN, SRCCOPY); CASE (MERGEPENNOT, 0x00DD0228); CASE (MERGEPEN, SRCPAINT); CASE (WHITE, WHITENESS);#undef CASE default: return SRCCOPY; }}static introp2_to_patblt_rop (int rop2){ switch (rop2) {#define CASE(rop2,patblt_rop) case R2_##rop2: return patblt_rop CASE (COPYPEN, PATCOPY); CASE (XORPEN, PATINVERT); CASE (NOT, DSTINVERT); CASE (BLACK, BLACKNESS); CASE (WHITE, WHITENESS);#undef CASE default: g_warning ("Unhandled rop2 in GC to be used in PatBlt: %#x", rop2); return PATCOPY; }}static inline intalign_with_dash_offset (int a, DWORD *dashes, int num_dashes, GdkGCWin32 *gcwin32){ int n = 0; int len_sum = 0; /* * We can't simply add the dashoffset, it can be an arbitrary larger * or smaller value not even between x1 and x2. It just says use the * dash pattern aligned to the offset. So ensure x1 is smaller _x1 * and we start with the appropriate dash. */ for (n = 0; n < num_dashes; n++) len_sum += dashes[n]; if ( len_sum > 0 /* pathological api usage? */ && gcwin32->pen_dash_offset > a) a -= (((gcwin32->pen_dash_offset/len_sum - a/len_sum) + 1) * len_sum); else a = gcwin32->pen_dash_offset; return a;} /* Render a dashed line 'by hand'. Used for all dashes on Win9x (where * GDI is way too limited), and for double dashes on all Windowses. */static inline gbooleanrender_line_horizontal (GdkGCWin32 *gcwin32, int x1, int x2, int y){ int n = 0; const int pen_width = MAX (gcwin32->pen_width, 1); const int _x1 = x1; g_assert (gcwin32->pen_dashes); x1 = align_with_dash_offset (x1, gcwin32->pen_dashes, gcwin32->pen_num_dashes, gcwin32); for (n = 0; x1 < x2; n++) { int len = gcwin32->pen_dashes[n % gcwin32->pen_num_dashes]; if (x1 + len > x2) len = x2 - x1; if (n % 2 == 0 && x1 + len > _x1) if (!GDI_CALL (PatBlt, (gcwin32->hdc, x1 < _x1 ? _x1 : x1, y - pen_width / 2, len, pen_width, rop2_to_patblt_rop (gcwin32->rop2)))) return FALSE; x1 += gcwin32->pen_dashes[n % gcwin32->pen_num_dashes]; } if (gcwin32->line_style == GDK_LINE_DOUBLE_DASH) { HBRUSH hbr; if ((hbr = SelectObject (gcwin32->hdc, gcwin32->pen_hbrbg)) == HGDI_ERROR) return FALSE; x1 = _x1; x1 += gcwin32->pen_dash_offset; for (n = 0; x1 < x2; n++) { int len = gcwin32->pen_dashes[n % gcwin32->pen_num_dashes]; if (x1 + len > x2) len = x2 - x1; if (n % 2) if (!GDI_CALL (PatBlt, (gcwin32->hdc, x1, y - pen_width / 2, len, pen_width, rop2_to_patblt_rop (gcwin32->rop2)))) return FALSE; x1 += gcwin32->pen_dashes[n % gcwin32->pen_num_dashes]; } if (SelectObject (gcwin32->hdc, hbr) == HGDI_ERROR) return FALSE; } return TRUE;}static inline gbooleanrender_line_vertical (GdkGCWin32 *gcwin32, int x, int y1, int y2){ int n; const int pen_width = MAX (gcwin32->pen_width, 1); const int _y1 = y1; g_assert (gcwin32->pen_dashes); y1 = align_with_dash_offset (y1, gcwin32->pen_dashes, gcwin32->pen_num_dashes, gcwin32); for (n = 0; y1 < y2; n++) { int len = gcwin32->pen_dashes[n % gcwin32->pen_num_dashes]; if (y1 + len > y2) len = y2 - y1; if (n % 2 == 0 && y1 + len > _y1) if (!GDI_CALL (PatBlt, (gcwin32->hdc, x - pen_width / 2, y1 < _y1 ? _y1 : y1, pen_width, len, rop2_to_patblt_rop (gcwin32->rop2)))) return FALSE; y1 += gcwin32->pen_dashes[n % gcwin32->pen_num_dashes]; } if (gcwin32->line_style == GDK_LINE_DOUBLE_DASH) { HBRUSH hbr; if ((hbr = SelectObject (gcwin32->hdc, gcwin32->pen_hbrbg)) == HGDI_ERROR) return FALSE; y1 = _y1; y1 += gcwin32->pen_dash_offset; for (n = 0; y1 < y2; n++) { int len = gcwin32->pen_dashes[n % gcwin32->pen_num_dashes]; if (y1 + len > y2) len = y2 - y1; if (n % 2) if (!GDI_CALL (PatBlt, (gcwin32->hdc, x - pen_width / 2, y1, pen_width, len, rop2_to_patblt_rop (gcwin32->rop2)))) return FALSE; y1 += gcwin32->pen_dashes[n % gcwin32->pen_num_dashes]; } if (SelectObject (gcwin32->hdc, hbr) == HGDI_ERROR) return FALSE; } return TRUE;}static voiddraw_tiles_lowlevel (HDC dest, HDC tile, int rop3, gint dest_x, gint dest_y, gint tile_x_origin, gint tile_y_origin, gint width, gint height, gint tile_width, gint tile_height){ gint x, y; GDK_NOTE (MISC, g_print ("draw_tiles_lowlevel: %p +%d+%d tile=%p:%dx%d@+%d+%d %dx%d\n", dest, dest_x, dest_y, tile, tile_width, tile_height, tile_x_origin, tile_y_origin, width, height)); y = tile_y_origin % tile_height; if (y > 0) y -= tile_height; while (y < dest_y + height) { if (y + tile_height >= dest_y) { x = tile_x_origin % tile_width; if (x > 0) x -= tile_width; while (x < dest_x + width) { if (x + tile_width >= dest_x) { gint src_x = MAX (0, dest_x - x); gint src_y = MAX (0, dest_y - y); if (!GDI_CALL (BitBlt, (dest, x + src_x, y + src_y, MIN (tile_width, dest_x + width - (x + src_x)), MIN (tile_height, dest_y + height - (y + src_y)), tile, src_x, src_y, rop3))) return; } x += tile_width; } } y += tile_height; }}static voiddraw_tiles (GdkDrawable *drawable, GdkGC *gc, int rop3, GdkPixmap *tile, gint dest_x, gint dest_y,
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -