diff options
author | Tor Lillqvist <tml@src.gnome.org> | 1999-11-12 21:56:29 +0000 |
---|---|---|
committer | Tor Lillqvist <tml@src.gnome.org> | 1999-11-12 21:56:29 +0000 |
commit | 28bcddaca2688b2051f6af967e272d5ac1729d07 (patch) | |
tree | b7acc308bff9e8cc744d0911c96fca33e5f1c8b1 | |
parent | af73e9d21bc101470aff0d2f40873c106e642019 (diff) | |
download | gtk+-28bcddaca2688b2051f6af967e272d5ac1729d07.tar.gz |
*** empty log message ***
-rw-r--r-- | gdk/win32/gdk.def | 323 | ||||
-rw-r--r-- | gdk/win32/gdkdraw.c | 909 | ||||
-rw-r--r-- | gdk/win32/gdkimage-win32.c | 759 | ||||
-rw-r--r-- | gdk/win32/gdkimage.c | 759 |
4 files changed, 1518 insertions, 1232 deletions
diff --git a/gdk/win32/gdk.def b/gdk/win32/gdk.def deleted file mode 100644 index 564af22e41..0000000000 --- a/gdk/win32/gdk.def +++ /dev/null @@ -1,323 +0,0 @@ -EXPORTS - gdk_atom_intern - gdk_atom_name - gdk_beep - gdk_bitmap_create_from_data - gdk_bitmap_ref - gdk_bitmap_unref - gdk_char_height - gdk_char_measure - gdk_char_width - gdk_char_width_wc - gdk_color_alloc - gdk_color_black - gdk_color_change - gdk_color_copy - gdk_color_equal - gdk_color_free - gdk_color_hash - gdk_color_parse - gdk_color_white - gdk_colormap_alloc_color - gdk_colormap_alloc_colors - gdk_colormap_change - gdk_colormap_free_colors - gdk_colormap_get_system - gdk_colormap_get_system_size - gdk_colormap_get_visual - gdk_colormap_new - gdk_colormap_ref - gdk_colormap_unref - gdk_colors_alloc - gdk_colors_free - gdk_colors_store - gdk_cursor_destroy - gdk_cursor_new - gdk_cursor_new_from_pixmap - gdk_debug_flags - gdk_dnd_init - gdk_drag_abort - gdk_drag_begin - gdk_drag_context_new - gdk_drag_context_ref - gdk_drag_context_unref - gdk_drag_drop - gdk_drag_find_window - gdk_drag_get_protocol - gdk_drag_get_selection - gdk_drag_motion - gdk_drag_status - gdk_drop_finish - gdk_drop_reply - gdk_draw_arc - gdk_draw_gray_image - gdk_draw_image - gdk_draw_indexed_image - gdk_draw_line - gdk_draw_lines - gdk_draw_pixmap - gdk_draw_point - gdk_draw_points - gdk_draw_polygon - gdk_draw_rectangle - gdk_draw_rgb_32_image - gdk_draw_rgb_image - gdk_draw_rgb_image_dithalign - gdk_draw_segments - gdk_draw_string - gdk_draw_text - gdk_draw_text_wc - gdk_drawable_get_colormap - gdk_drawable_get_size - gdk_drawable_get_type - gdk_drawable_get_visual - gdk_drawable_set_colormap - gdk_drawable_set_data - gdk_error_code - gdk_error_trap_pop - gdk_error_trap_push - gdk_error_warnings - gdk_event_copy - gdk_event_free - gdk_event_get - gdk_event_get_graphics_expose - gdk_event_get_time - gdk_event_handler_set - gdk_event_peek - gdk_event_put - gdk_event_send_client_message - gdk_event_send_clientmessage_toall - gdk_events_pending - gdk_exit - gdk_flush - gdk_font_equal - gdk_font_id - gdk_font_list_free - gdk_font_list_new - gdk_font_load - gdk_font_ref - gdk_font_unref - gdk_font_xlfd_create - gdk_font_xlfd_free - gdk_fontset_load - gdk_free_compound_text - gdk_free_text_list - gdk_gc_copy - gdk_gc_destroy - gdk_gc_get_values - gdk_gc_new - gdk_gc_new_with_values - gdk_gc_ref - gdk_gc_set_background - gdk_gc_set_clip_mask - gdk_gc_set_clip_origin - gdk_gc_set_clip_rectangle - gdk_gc_set_clip_region - gdk_gc_set_dashes - gdk_gc_set_exposures - gdk_gc_set_fill - gdk_gc_set_font - gdk_gc_set_foreground - gdk_gc_set_function - gdk_gc_set_line_attributes - gdk_gc_set_stipple - gdk_gc_set_subwindow - gdk_gc_set_tile - gdk_gc_set_ts_origin - gdk_gc_unref - gdk_get_display - gdk_get_show_events - gdk_get_use_xshm - gdk_ic_destroy - gdk_ic_get_attr - gdk_ic_get_events - gdk_ic_get_style - gdk_ic_get_values - gdk_ic_new - gdk_ic_set_attr - gdk_ic_set_values - gdk_im_begin - gdk_im_decide_style - gdk_im_end - gdk_im_ready - gdk_im_set_best_style - gdk_image_bitmap_new - gdk_image_destroy - gdk_image_get - gdk_image_get_pixel - gdk_image_new - gdk_image_new_bitmap - gdk_image_put_pixel - gdk_init - gdk_init_check - gdk_input_add - gdk_input_add_full - gdk_input_exit - gdk_input_init - gdk_input_list_devices - gdk_input_motion_events - gdk_input_remove - gdk_input_set_axes - gdk_input_set_extension_events - gdk_input_set_key - gdk_input_set_mode - gdk_input_set_source - gdk_input_window_get_pointer - gdk_key_repeat_disable - gdk_key_repeat_restore - gdk_keyboard_grab - gdk_keyboard_ungrab - gdk_keyval_from_name - gdk_keyval_is_lower - gdk_keyval_is_upper - gdk_keyval_name - gdk_keyval_to_lower - gdk_keyval_to_upper - gdk_list_visuals - gdk_mbstowcs - gdk_null_window_warnings - gdk_pixmap_colormap_create_from_xpm - gdk_pixmap_colormap_create_from_xpm_d - gdk_pixmap_create_from_data - gdk_pixmap_create_from_xpm - gdk_pixmap_create_from_xpm_d - gdk_pixmap_create_on_shared_image - gdk_pixmap_foreign_new - gdk_pixmap_new - gdk_pixmap_ref - gdk_pixmap_unref - gdk_pointer_grab - gdk_pointer_is_grabbed - gdk_pointer_ungrab - gdk_progclass - gdk_property_change - gdk_property_delete - gdk_property_get - gdk_query_depths - gdk_query_visual_types - gdk_rectangle_intersect - gdk_rectangle_union - gdk_region_destroy - gdk_region_empty - gdk_region_equal - gdk_region_get_clipbox - gdk_region_new - gdk_region_offset - gdk_region_point_in - gdk_region_polygon - gdk_region_rect_in - gdk_region_shrink - gdk_region_union_with_rect - gdk_regions_intersect - gdk_regions_subtract - gdk_regions_union - gdk_regions_xor - gdk_rgb_cmap_free - gdk_rgb_cmap_new - gdk_rgb_ditherable - gdk_rgb_gc_set_background - gdk_rgb_gc_set_foreground - gdk_rgb_get_cmap - gdk_rgb_get_visual - gdk_rgb_init - gdk_rgb_set_install - gdk_rgb_set_min_colors - gdk_rgb_set_verbose - gdk_rgb_xpixel_from_rgb - gdk_root_parent - gdk_screen_height - gdk_screen_height_mm - gdk_screen_width - gdk_screen_width_mm - gdk_selection_convert - gdk_selection_owner_get - gdk_selection_owner_set - gdk_selection_property - gdk_selection_property_get - gdk_selection_send_notify - gdk_set_locale - gdk_set_show_events - gdk_set_use_xshm - gdk_string_extents - gdk_string_height - gdk_string_measure - gdk_string_to_compound_text - gdk_string_width - gdk_text_extents - gdk_text_extents_wc - gdk_text_height - gdk_text_measure - gdk_text_property_to_text_list - gdk_text_width - gdk_text_width_wc - gdk_threads_enter - gdk_threads_leave - gdk_threads_mutex - gdk_visual_get_best - gdk_visual_get_best_depth - gdk_visual_get_best_type - gdk_visual_get_best_with_both - gdk_visual_get_best_with_depth - gdk_visual_get_best_with_type - gdk_visual_get_system - gdk_visual_ref - gdk_visual_unref - gdk_wcstombs - gdk_window_add_filter - gdk_window_at_pointer - gdk_window_clear - gdk_window_clear_area - gdk_window_clear_area_e - gdk_window_destroy - gdk_window_foreign_new - gdk_window_get_deskrelative_origin - gdk_window_get_children - gdk_window_get_events - gdk_window_get_geometry - gdk_window_get_origin - gdk_window_get_parent - gdk_window_get_pointer - gdk_window_get_position - gdk_window_get_root_origin - gdk_window_get_toplevel - gdk_window_get_toplevels - gdk_window_get_user_data - gdk_window_hide - gdk_window_is_visible - gdk_window_is_viewable - gdk_window_lower - gdk_window_merge_child_shapes - gdk_window_move - gdk_window_move_resize - gdk_window_new - gdk_window_raise - gdk_window_ref - gdk_window_register_dnd - gdk_window_remove_filter - gdk_window_reparent - gdk_window_resize - gdk_window_set_back_pixmap - gdk_window_set_background - gdk_window_set_child_shapes - gdk_window_set_cursor - gdk_window_set_decorations - gdk_window_set_events - gdk_window_set_functions - gdk_window_set_geometry_hints - gdk_window_set_group - gdk_window_set_hints - gdk_window_set_icon - gdk_window_set_icon_name - gdk_window_set_override_redirect - gdk_window_set_role - gdk_window_set_static_gravities - gdk_window_set_title - gdk_window_set_transient_for - gdk_window_set_user_data - gdk_window_shape_combine_mask - gdk_window_show - gdk_window_unref - gdk_window_withdraw - gdk_xid_table_insert - gdk_xid_table_lookup - gdk_xid_table_remove
\ No newline at end of file diff --git a/gdk/win32/gdkdraw.c b/gdk/win32/gdkdraw.c deleted file mode 100644 index 73f5e513d9..0000000000 --- a/gdk/win32/gdkdraw.c +++ /dev/null @@ -1,909 +0,0 @@ -/* GDK - The GIMP Drawing Kit - * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library 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-1999. 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 "gdkdrawable.h" -#include "gdkprivate.h" -#include "gdkwindow.h" -#include "gdkx.h" - -#ifndef G_PI -#define G_PI 3.14159265358979323846 -#endif - -/* Manipulation of drawables - */ -void -gdk_drawable_set_data (GdkDrawable *drawable, - const gchar *key, - gpointer data, - GDestroyNotify destroy_func) -{ - g_dataset_set_data_full (drawable, key, data, destroy_func); -} - -void -gdk_drawable_get_data (GdkDrawable *drawable, - const gchar *key) -{ - g_dataset_get_data (drawable, key); -} - -GdkDrawableType -gdk_drawable_get_type (GdkDrawable *drawable) -{ - g_return_val_if_fail (drawable != NULL, (GdkDrawableType) -1); - - return GDK_DRAWABLE_TYPE (drawable); -} - -void -gdk_drawable_get_size (GdkDrawable *drawable, - gint *width, - gint *height) -{ - GdkDrawablePrivate *drawable_private; - - g_return_if_fail (drawable != NULL); - - drawable_private = (GdkDrawablePrivate*) drawable; - - if (width) - *width = drawable_private->width; - if (height) - *height = drawable_private->height; -} - -void -gdk_drawable_set_colormap (GdkDrawable *drawable, - GdkColormap *colormap) -{ - GdkDrawablePrivate *drawable_private; - GdkColormapPrivate *colormap_private; - - g_return_if_fail (drawable != NULL); - g_return_if_fail (colormap != NULL); - - drawable_private = (GdkDrawablePrivate*) drawable; - colormap_private = (GdkColormapPrivate*) colormap; - - if (!GDK_DRAWABLE_DESTROYED (drawable)) - { - if (GDK_IS_WINDOW (drawable)) - { - g_return_if_fail (colormap_private->visual != - ((GdkColormapPrivate*)(drawable_private->colormap))->visual); - /* XXX ??? */ - GDK_NOTE (MISC, g_print ("gdk_drawable_set_colormap: %#x %#x\n", - GDK_DRAWABLE_XID (drawable), - colormap_private->xcolormap)); - } - if (drawable_private->colormap) - gdk_colormap_unref (drawable_private->colormap); - drawable_private->colormap = colormap; - gdk_colormap_ref (drawable_private->colormap); - - if (GDK_IS_WINDOW (drawable) && - drawable_private->window_type != GDK_WINDOW_TOPLEVEL) - gdk_window_add_colormap_windows (drawable); - } -} - -GdkColormap* -gdk_drawable_get_colormap (GdkDrawable *drawable) -{ - GdkDrawablePrivate *drawable_private; - - g_return_val_if_fail (drawable != NULL, NULL); - drawable_private = (GdkDrawablePrivate*) drawable; - - if (!GDK_DRAWABLE_DESTROYED (drawable)) - { - if (drawable_private->colormap == NULL) - return gdk_colormap_get_system (); /* XXX ??? */ - else - return drawable_private->colormap; - } - - return NULL; -} - -GdkVisual* -gdk_drawable_get_visual (GdkDrawable *drawable) -{ - GdkColormap *colormap; - - g_return_val_if_fail (drawable != NULL, NULL); - - colormap = gdk_drawable_get_colormap (drawable); - return colormap ? gdk_colormap_get_visual (colormap) : NULL; -} - -void -gdk_draw_point (GdkDrawable *drawable, - GdkGC *gc, - gint x, - gint y) -{ - GdkDrawablePrivate *drawable_private; - GdkGCPrivate *gc_private; - HDC hdc; - - g_return_if_fail (drawable != NULL); - g_return_if_fail (gc != NULL); - - if (GDK_DRAWABLE_DESTROYED (drawable)) - return; - drawable_private = (GdkDrawablePrivate*) drawable; - gc_private = (GdkGCPrivate*) gc; - - hdc = gdk_gc_predraw (drawable_private, gc_private); - - /* We use LineTo because SetPixel wants the COLORREF directly, - * and doesn't use the current pen, which is what we want. - */ - if (!MoveToEx (hdc, x, y, NULL)) - g_warning ("gdk_draw_point: MoveToEx failed"); - if (!LineTo (hdc, x + 1, y)) - g_warning ("gdk_draw_point: LineTo failed"); - - gdk_gc_postdraw (drawable_private, gc_private); -} - -void -gdk_draw_line (GdkDrawable *drawable, - GdkGC *gc, - gint x1, - gint y1, - gint x2, - gint y2) -{ - GdkDrawablePrivate *drawable_private; - GdkGCPrivate *gc_private; - HDC hdc; - - g_return_if_fail (drawable != NULL); - g_return_if_fail (gc != NULL); - - if (GDK_DRAWABLE_DESTROYED (drawable)) - return; - drawable_private = (GdkDrawablePrivate*) drawable; - gc_private = (GdkGCPrivate*) gc; - - hdc = gdk_gc_predraw (drawable_private, gc_private); - - GDK_NOTE (MISC, g_print ("gdk_draw_line: %#x (%d) +%d+%d..+%d+%d\n", - drawable_private->xwindow, gc_private, - x1, y1, x2, y2)); - - MoveToEx (hdc, x1, y1, NULL); - if (!LineTo (hdc, x2, y2)) - g_warning ("gdk_draw_line: LineTo #1 failed"); - /* LineTo doesn't draw the last point, so if we have a pen width of 1, - * we draw the end pixel separately... With wider pens we don't care. - * //HB: But the NT developers don't read their API documentation ... - */ - if (gc_private->pen_width == 1 && windows_version > 0x80000000) - if (!LineTo (hdc, x2 + 1, y2)) - g_warning ("gdk_draw_line: LineTo #2 failed"); - gdk_gc_postdraw (drawable_private, gc_private); -} - -void -gdk_draw_rectangle (GdkDrawable *drawable, - GdkGC *gc, - gint filled, - gint x, - gint y, - gint width, - gint height) -{ - GdkDrawablePrivate *drawable_private; - GdkGCPrivate *gc_private; - HDC hdc; - HGDIOBJ oldpen, oldbrush; - - g_return_if_fail (drawable != NULL); - g_return_if_fail (gc != NULL); - - if (GDK_DRAWABLE_DESTROYED (drawable)) - return; - drawable_private = (GdkDrawablePrivate*) drawable; - gc_private = (GdkGCPrivate*) gc; - - if (width == -1) - width = drawable_private->width; - if (height == -1) - height = drawable_private->height; - - hdc = gdk_gc_predraw (drawable_private, gc_private); - - GDK_NOTE (MISC, g_print ("gdk_draw_rectangle: %#x (%d) %s%dx%d@+%d+%d\n", - drawable_private->xwindow, - gc_private, - (filled ? "fill " : ""), - width, height, x, y)); - -#if 0 - { - HBRUSH hbr = GetCurrentObject (hdc, OBJ_BRUSH); - HPEN hpen = GetCurrentObject (hdc, OBJ_PEN); - LOGBRUSH lbr; - LOGPEN lpen; - GetObject (hbr, sizeof (lbr), &lbr); - GetObject (hpen, sizeof (lpen), &lpen); - - g_print ("current brush: style = %s, color = 0x%.08x\n", - (lbr.lbStyle == BS_SOLID ? "SOLID" : "???"), - lbr.lbColor); - g_print ("current pen: style = %s, width = %d, color = 0x%.08x\n", - (lpen.lopnStyle == PS_SOLID ? "SOLID" : "???"), - lpen.lopnWidth, - lpen.lopnColor); - } -#endif - - if (filled) - oldpen = SelectObject (hdc, GetStockObject (NULL_PEN)); - else - oldbrush = SelectObject (hdc, GetStockObject (HOLLOW_BRUSH)); - - if (!Rectangle (hdc, x, y, x+width+1, y+height+1)) - g_warning ("gdk_draw_rectangle: Rectangle failed"); - - if (filled) - SelectObject (hdc, oldpen); - else - SelectObject (hdc, oldbrush); - - gdk_gc_postdraw (drawable_private, gc_private); -} - -void -gdk_draw_arc (GdkDrawable *drawable, - GdkGC *gc, - gint filled, - gint x, - gint y, - gint width, - gint height, - gint angle1, - gint angle2) -{ - GdkDrawablePrivate *drawable_private; - GdkGCPrivate *gc_private; - HDC hdc; - int nXStartArc, nYStartArc, nXEndArc, nYEndArc; - - g_return_if_fail (drawable != NULL); - g_return_if_fail (gc != NULL); - - if (GDK_DRAWABLE_DESTROYED (drawable)) - return; - drawable_private = (GdkDrawablePrivate*) drawable; - gc_private = (GdkGCPrivate*) gc; - - if (width == -1) - width = drawable_private->width; - if (height == -1) - height = drawable_private->height; - - GDK_NOTE (MISC, g_print ("gdk_draw_arc: %#x %d,%d,%d,%d %d %d\n", - drawable_private->xwindow, - x, y, width, height, angle1, angle2)); - - if (width != 0 && height != 0 && angle2 != 0) - { - hdc = gdk_gc_predraw (drawable_private, gc_private); - - 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.); - } - - if (filled) - { - 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)); - Pie (hdc, x, y, x+width, y+height, - nXStartArc, nYStartArc, nXEndArc, nYEndArc); - } - 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)); - Arc (hdc, x, y, x+width, y+height, - nXStartArc, nYStartArc, nXEndArc, nYEndArc); - } - gdk_gc_postdraw (drawable_private, gc_private); - } -} - -void -gdk_draw_polygon (GdkDrawable *drawable, - GdkGC *gc, - gint filled, - GdkPoint *points, - gint npoints) -{ - GdkDrawablePrivate *drawable_private; - GdkGCPrivate *gc_private; - HDC hdc; - POINT *pts; - int i; - - g_return_if_fail (drawable != NULL); - g_return_if_fail (gc != NULL); - - if (GDK_DRAWABLE_DESTROYED (drawable)) - return; - drawable_private = (GdkDrawablePrivate*) drawable; - gc_private = (GdkGCPrivate*) gc; - - GDK_NOTE (MISC, g_print ("gdk_draw_polygon: %#x (%d) %d\n", - drawable_private->xwindow, gc_private, - npoints)); - - if (npoints < 2) - return; - - hdc = gdk_gc_predraw (drawable_private, gc_private); - pts = g_malloc ((npoints+1) * sizeof (POINT)); - - for (i = 0; i < npoints; i++) - { - pts[i].x = points[i].x; - pts[i].y = points[i].y; - } - - 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)) - g_warning ("gdk_draw_polygon: Polygon failed"); - } - else - { - if (!Polyline (hdc, pts, npoints)) - g_warning ("gdk_draw_polygon: Polyline failed"); - } - g_free (pts); - gdk_gc_postdraw (drawable_private, gc_private); -} - -typedef struct -{ - gint x, y; - HDC hdc; -} gdk_draw_text_arg; - -/* gdk_draw_string - */ -void -gdk_draw_string (GdkDrawable *drawable, - GdkFont *font, - GdkGC *gc, - gint x, - gint y, - const gchar *string) -{ - gdk_draw_text (drawable, font, gc, x, y, string, strlen (string)); -} - -static void -gdk_draw_text_handler (GdkWin32SingleFont *singlefont, - const wchar_t *wcstr, - int wclen, - void *arg) -{ - HGDIOBJ oldfont; - SIZE size; - gdk_draw_text_arg *argp = (gdk_draw_text_arg *) arg; - - if (!singlefont) - return; - - if ((oldfont = SelectObject (argp->hdc, singlefont->xfont)) == NULL) - { - g_warning ("gdk_draw_text_handler: SelectObject failed"); - return; - } - - if (!TextOutW (argp->hdc, argp->x, argp->y, wcstr, wclen)) - g_warning ("gdk_draw_text_handler: TextOutW failed"); - GetTextExtentPoint32W (argp->hdc, wcstr, wclen, &size); - argp->x += size.cx; - - SelectObject (argp->hdc, oldfont); -} - -/* gdk_draw_text - * - */ -void -gdk_draw_text (GdkDrawable *drawable, - GdkFont *font, - GdkGC *gc, - gint x, - gint y, - const gchar *text, - gint text_length) -{ - GdkDrawablePrivate *drawable_private; - GdkGCPrivate *gc_private; - wchar_t *wcstr; - gint wlen; - gdk_draw_text_arg arg; - - g_return_if_fail (drawable != NULL); - g_return_if_fail (font != NULL); - g_return_if_fail (gc != NULL); - g_return_if_fail (text != NULL); - - if (GDK_DRAWABLE_DESTROYED (drawable)) - return; - - if (text_length == 0) - return; - - g_assert (font->type == GDK_FONT_FONT || font->type == GDK_FONT_FONTSET); - - drawable_private = (GdkDrawablePrivate*) drawable; - gc_private = (GdkGCPrivate*) gc; - - arg.x = x; - arg.y = y; - arg.hdc = gdk_gc_predraw (drawable_private, gc_private); - - GDK_NOTE (MISC, g_print ("gdk_draw_text: %#x (%d,%d) \"%.*s\" (len %d)\n", - drawable_private->xwindow, - x, y, - (text_length > 10 ? 10 : text_length), - text, text_length)); - - wcstr = g_new (wchar_t, text_length); - if ((wlen = gdk_nmbstowchar_ts (wcstr, text, text_length, text_length)) == -1) - g_warning ("gdk_draw_text: gdk_nmbstowchar_ts failed"); - else - gdk_wchar_text_handle (font, wcstr, wlen, - gdk_draw_text_handler, &arg); - - g_free (wcstr); - - gdk_gc_postdraw (drawable_private, gc_private); -} - -void -gdk_draw_text_wc (GdkDrawable *drawable, - GdkFont *font, - GdkGC *gc, - gint x, - gint y, - const GdkWChar *text, - gint text_length) -{ - GdkDrawablePrivate *drawable_private; - GdkGCPrivate *gc_private; - gint i, wlen; - wchar_t *wcstr; - gdk_draw_text_arg arg; - - g_return_if_fail (drawable != NULL); - g_return_if_fail (font != NULL); - g_return_if_fail (gc != NULL); - g_return_if_fail (text != NULL); - - if (GDK_DRAWABLE_DESTROYED (drawable)) - return; - - if (text_length == 0) - return; - - g_assert (font->type == GDK_FONT_FONT || font->type == GDK_FONT_FONTSET); - - drawable_private = (GdkDrawablePrivate*) drawable; - gc_private = (GdkGCPrivate*) gc; - - arg.x = x; - arg.y = y; - arg.hdc = gdk_gc_predraw (drawable_private, gc_private); - - GDK_NOTE (MISC, g_print ("gdk_draw_text_wc: %#x (%d,%d) len: %d\n", - drawable_private->xwindow, - x, y, text_length)); - - if (sizeof (wchar_t) != sizeof (GdkWChar)) - { - wcstr = g_new (wchar_t, text_length); - for (i = 0; i < text_length; i++) - wcstr[i] = text[i]; - } - else - wcstr = (wchar_t *) text; - - gdk_wchar_text_handle (font, wcstr, text_length, - gdk_draw_text_handler, &arg); - - if (sizeof (wchar_t) != sizeof (GdkWChar)) - g_free (wcstr); - - gdk_gc_postdraw (drawable_private, gc_private); -} - -void -gdk_draw_pixmap (GdkDrawable *drawable, - GdkGC *gc, - GdkPixmap *src, - gint xsrc, - gint ysrc, - gint xdest, - gint ydest, - gint width, - gint height) -{ - GdkDrawablePrivate *drawable_private; - GdkDrawablePrivate *src_private; - GdkGCPrivate *gc_private; - HDC hdc; - HDC srcdc; - HGDIOBJ hgdiobj; - HRGN src_rgn, draw_rgn, outside_rgn; - RECT r; - - g_return_if_fail (drawable != NULL); - g_return_if_fail (src != NULL); - g_return_if_fail (gc != NULL); - - if (GDK_DRAWABLE_DESTROYED (drawable) || GDK_DRAWABLE_DESTROYED (src)) - return; - drawable_private = (GdkDrawablePrivate*) drawable; - src_private = (GdkDrawablePrivate*) src; - gc_private = (GdkGCPrivate*) gc; - - if (width == -1) - width = src_private->width; /* Or should we subtract xsrc? */ - if (height == -1) - height = src_private->height; /* Ditto? */ - - GDK_NOTE (MISC, g_print ("gdk_draw_pixmap: dest: %#x " - "src: %#x %dx%d@+%d+%d" - " dest: %#x @+%d+%d\n", - drawable_private->xwindow, - src_private->xwindow, - width, height, xsrc, ysrc, - drawable_private->xwindow, xdest, ydest)); - - hdc = gdk_gc_predraw (drawable_private, gc_private); - - src_rgn = CreateRectRgn (0, 0, src_private->width + 1, src_private->height + 1); - draw_rgn = CreateRectRgn (xsrc, ysrc, xsrc + width + 1, ysrc + height + 1); - SetRectEmpty (&r); - outside_rgn = CreateRectRgnIndirect (&r); - - if (drawable_private->window_type != GDK_DRAWABLE_PIXMAP) - { - /* If we are drawing on a window, calculate the region that is - * outside the source pixmap, and invalidate that, causing it to - * be cleared. XXX - */ - if (CombineRgn (outside_rgn, draw_rgn, src_rgn, RGN_DIFF) != NULLREGION) - { - OffsetRgn (outside_rgn, xdest, ydest); - GDK_NOTE (MISC, (GetRgnBox (outside_rgn, &r), - g_print ("...calling InvalidateRgn, " - "bbox: %dx%d@+%d+%d\n", - r.right - r.left - 1, r.bottom - r.top - 1, - r.left, r.top))); - InvalidateRgn (drawable_private->xwindow, outside_rgn, TRUE); - } - } - -#if 1 /* Don't know if this is necessary */ - if (CombineRgn (draw_rgn, draw_rgn, src_rgn, RGN_AND) == COMPLEXREGION) - g_warning ("gdk_draw_pixmap: CombineRgn returned a COMPLEXREGION"); - - GetRgnBox (draw_rgn, &r); - if (r.left != xsrc - || r.top != ysrc - || r.right != xsrc + width + 1 - || r.bottom != ysrc + height + 1) - { - xdest += r.left - xsrc; - xsrc = r.left; - ydest += r.top - ysrc; - ysrc = r.top; - width = r.right - xsrc - 1; - height = r.bottom - ysrc - 1; - - GDK_NOTE (MISC, g_print ("... restricted to src: %dx%d@+%d+%d, " - "dest: @+%d+%d\n", - width, height, xsrc, ysrc, - xdest, ydest)); - } -#endif - - DeleteObject (src_rgn); - DeleteObject (draw_rgn); - DeleteObject (outside_rgn); - - /* Strangely enough, this function is called also to bitblt - * from a window. - */ - if (src_private->window_type == GDK_DRAWABLE_PIXMAP) - { - if ((srcdc = CreateCompatibleDC (hdc)) == NULL) - g_warning ("gdk_draw_pixmap: CreateCompatibleDC failed"); - - if ((hgdiobj = SelectObject (srcdc, src_private->xwindow)) == NULL) - g_warning ("gdk_draw_pixmap: SelectObject #1 failed"); - - if (!BitBlt (hdc, xdest, ydest, width, height, - srcdc, xsrc, ysrc, SRCCOPY)) - g_warning ("gdk_draw_pixmap: BitBlt failed"); - - if ((SelectObject (srcdc, hgdiobj) == NULL)) - g_warning ("gdk_draw_pixmap: SelectObject #2 failed"); - - if (!DeleteDC (srcdc)) - g_warning ("gdk_draw_pixmap: DeleteDC failed"); - } - else - { - if (drawable_private->xwindow == src_private->xwindow) - { - /* Blitting inside a window, use ScrollDC */ - RECT scrollRect, clipRect, emptyRect; - HRGN updateRgn; - - scrollRect.left = MIN (xsrc, xdest); - scrollRect.top = MIN (ysrc, ydest); - scrollRect.right = MAX (xsrc + width + 1, xdest + width + 1); - scrollRect.bottom = MAX (ysrc + height + 1, ydest + height + 1); - - clipRect.left = xdest; - clipRect.top = ydest; - clipRect.right = xdest + width + 1; - clipRect.bottom = ydest + height + 1; - - SetRectEmpty (&emptyRect); - updateRgn = CreateRectRgnIndirect (&emptyRect); - if (!ScrollDC (hdc, xdest - xsrc, ydest - ysrc, - &scrollRect, &clipRect, - updateRgn, NULL)) - g_warning ("gdk_draw_pixmap: ScrollDC failed"); - if (!InvalidateRgn (drawable_private->xwindow, updateRgn, FALSE)) - g_warning ("gdk_draw_pixmap: InvalidateRgn failed"); - if (!UpdateWindow (drawable_private->xwindow)) - g_warning ("gdk_draw_pixmap: UpdateWindow failed"); - } - else - { - if ((srcdc = GetDC (src_private->xwindow)) == NULL) - g_warning ("gdk_draw_pixmap: GetDC failed"); - - if (!BitBlt (hdc, xdest, ydest, width, height, - srcdc, xsrc, ysrc, SRCCOPY)) - g_warning ("gdk_draw_pixmap: BitBlt failed"); - ReleaseDC (src_private->xwindow, srcdc); - } - } - gdk_gc_postdraw (drawable_private, gc_private); -} - -void -gdk_draw_image (GdkDrawable *drawable, - GdkGC *gc, - GdkImage *image, - gint xsrc, - gint ysrc, - gint xdest, - gint ydest, - gint width, - gint height) -{ - GdkImagePrivate *image_private; - - g_return_if_fail (drawable != NULL); - g_return_if_fail (image != NULL); - g_return_if_fail (gc != NULL); - - image_private = (GdkImagePrivate*) image; - - g_return_if_fail (image_private->image_put != NULL); - - if (width == -1) - width = image->width; - if (height == -1) - height = image->height; - - (* image_private->image_put) (drawable, gc, image, xsrc, ysrc, - xdest, ydest, width, height); -} - -void -gdk_draw_points (GdkDrawable *drawable, - GdkGC *gc, - GdkPoint *points, - gint npoints) -{ - GdkDrawablePrivate *drawable_private; - GdkGCPrivate *gc_private; - HDC hdc; - int i; - - g_return_if_fail (drawable != NULL); - g_return_if_fail ((points != NULL) && (npoints > 0)); - g_return_if_fail (gc != NULL); - - if (GDK_DRAWABLE_DESTROYED (drawable)) - return; - drawable_private = (GdkDrawablePrivate*) drawable; - gc_private = (GdkGCPrivate*) gc; - - hdc = gdk_gc_predraw (drawable_private, gc_private); - - GDK_NOTE (MISC, g_print ("gdk_draw_points: %#x destdc: (%d) %#x " - "npoints: %d\n", - drawable_private->xwindow, gc_private, hdc, - npoints)); - - for (i = 0; i < npoints; i++) - { - if (!MoveToEx (hdc, points[i].x, points[i].y, NULL)) - g_warning ("gdk_draw_points: MoveToEx failed"); - if (!LineTo (hdc, points[i].x + 1, points[i].y)) - g_warning ("gdk_draw_points: LineTo failed"); - } - gdk_gc_postdraw (drawable_private, gc_private); -} - -void -gdk_draw_segments (GdkDrawable *drawable, - GdkGC *gc, - GdkSegment *segs, - gint nsegs) -{ - GdkDrawablePrivate *drawable_private; - GdkGCPrivate *gc_private; - HDC hdc; - int i; - - if (nsegs <= 0) - return; - - g_return_if_fail (drawable != NULL); - g_return_if_fail (segs != NULL); - g_return_if_fail (gc != NULL); - - if (GDK_DRAWABLE_DESTROYED (drawable)) - return; - drawable_private = (GdkDrawablePrivate*) drawable; - gc_private = (GdkGCPrivate*) gc; - - hdc = gdk_gc_predraw (drawable_private, gc_private); - - for (i = 0; i < nsegs; i++) - { - if (!MoveToEx (hdc, segs[i].x1, segs[i].y1, NULL)) - g_warning ("gdk_draw_segments: MoveToEx failed"); - if (!LineTo (hdc, segs[i].x2, segs[i].y2)) - g_warning ("gdk_draw_segments: LineTo #1 failed"); - - /* Draw end pixel */ - if (gc_private->pen_width == 1) - if (!LineTo (hdc, segs[i].x2 + 1, segs[i].y2)) - g_warning ("gdk_draw_segments: LineTo #2 failed"); - } - gdk_gc_postdraw (drawable_private, gc_private); -} - -void -gdk_draw_lines (GdkDrawable *drawable, - GdkGC *gc, - GdkPoint *points, - gint npoints) -{ - GdkDrawablePrivate *drawable_private; - GdkGCPrivate *gc_private; - HDC hdc; - POINT *pts; - int i; - - if (npoints < 2) - return; - - g_return_if_fail (drawable != NULL); - g_return_if_fail (points != NULL); - g_return_if_fail (gc != NULL); - - if (GDK_DRAWABLE_DESTROYED (drawable)) - return; - drawable_private = (GdkDrawablePrivate*) drawable; - gc_private = (GdkGCPrivate*) gc; - - hdc = gdk_gc_predraw (drawable_private, gc_private); -#if 1 - pts = g_malloc (npoints * sizeof (POINT)); - - for (i = 0; i < npoints; i++) - { - pts[i].x = points[i].x; - pts[i].y = points[i].y; - } - - if (!Polyline (hdc, pts, npoints)) - g_warning ("gdk_draw_lines: Polyline(,,%d) failed", npoints); - - g_free (pts); - - /* Draw end pixel */ - if (gc_private->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)) - g_warning ("gdk_draw_lines: LineTo failed"); - } -#else - MoveToEx (hdc, points[0].x, points[0].y, NULL); - for (i = 1; i < npoints; i++) - if (!LineTo (hdc, points[i].x, points[i].y)) - g_warning ("gdk_draw_lines: LineTo #1 failed"); - - /* Draw end pixel */ - if (gc_private->pen_width == 1) - if (!LineTo (hdc, points[npoints-1].x + 1, points[npoints-1].y)) - g_warning ("gdk_draw_lines: LineTo #2 failed"); -#endif - gdk_gc_postdraw (drawable_private, gc_private); -} diff --git a/gdk/win32/gdkimage-win32.c b/gdk/win32/gdkimage-win32.c new file mode 100644 index 0000000000..0f2825e405 --- /dev/null +++ b/gdk/win32/gdkimage-win32.c @@ -0,0 +1,759 @@ +/* GDK - The GIMP Drawing Kit + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library 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-1999. 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 "gdk.h" /* For gdk_error_trap_* / gdk_flush_* */ +#include "gdkimage.h" +#include "gdkprivate.h" +#include "gdkx.h" + +static void gdk_image_put_normal (GdkDrawable *drawable, + GdkGC *gc, + GdkImage *image, + gint xsrc, + gint ysrc, + gint xdest, + gint ydest, + gint width, + gint height); +static GList *image_list = NULL; + +void +gdk_image_exit (void) +{ + GdkImage *image; + + while (image_list) + { + image = image_list->data; + gdk_image_destroy (image); + } +} + +GdkImage * +gdk_image_new_bitmap (GdkVisual *visual, gpointer data, gint w, gint h) +/* + * Desc: create a new bitmap image + */ +{ + Visual *xvisual; + GdkImage *image; + GdkImagePrivate *private; + struct { + BITMAPINFOHEADER bmiHeader; + union { + WORD bmiIndices[2]; + RGBQUAD bmiColors[2]; + } u; + } bmi; + char *bits; + int bpl = (w-1)/8 + 1; + int bpl32 = ((w-1)/32 + 1)*4; + + private = g_new(GdkImagePrivate, 1); + image = (GdkImage *) private; + private->image_put = gdk_image_put_normal; + image->type = GDK_IMAGE_SHARED; + image->visual = visual; + image->width = w; + image->height = h; + image->depth = 1; + xvisual = ((GdkVisualPrivate*) visual)->xvisual; + + GDK_NOTE (MISC, g_print ("gdk_image_new_bitmap: %dx%d\n", w, h)); + + bmi.bmiHeader.biSize = sizeof (BITMAPINFOHEADER); + bmi.bmiHeader.biWidth = w; + bmi.bmiHeader.biHeight = -h; + bmi.bmiHeader.biPlanes = 1; + bmi.bmiHeader.biBitCount = 1; + bmi.bmiHeader.biCompression = BI_RGB; + bmi.bmiHeader.biSizeImage = 0; + bmi.bmiHeader.biXPelsPerMeter = + bmi.bmiHeader.biYPelsPerMeter = 0; + bmi.bmiHeader.biClrUsed = 0; + bmi.bmiHeader.biClrImportant = 0; + + bmi.u.bmiColors[0].rgbBlue = + bmi.u.bmiColors[0].rgbGreen = + bmi.u.bmiColors[0].rgbRed = 0x00; + bmi.u.bmiColors[0].rgbReserved = 0x00; + + bmi.u.bmiColors[1].rgbBlue = + bmi.u.bmiColors[1].rgbGreen = + bmi.u.bmiColors[1].rgbRed = 0xFF; + bmi.u.bmiColors[1].rgbReserved = 0x00; + + private->ximage = CreateDIBSection (gdk_DC, (BITMAPINFO *) &bmi, + DIB_RGB_COLORS, &bits, NULL, 0); + if (bpl != bpl32) + { + /* Win32 expects scanlines in DIBs to be 32 bit aligned */ + int i; + for (i = 0; i < h; i++) + memmove (bits + i*bpl32, ((char *) data) + i*bpl, bpl); + } + else + memmove (bits, data, bpl*h); + image->mem = bits; + image->bpl = bpl32; + image->byte_order = GDK_MSB_FIRST; + + image->bpp = 1; + return(image); +} /* gdk_image_new_bitmap() */ + +void +gdk_image_init (void) +{ +} + +static GdkImage* +gdk_image_new_with_depth (GdkImageType type, + GdkVisual *visual, + gint width, + gint height, + gint depth) +{ + GdkImage *image; + GdkImagePrivate *private; + Visual *xvisual; + struct { + BITMAPINFOHEADER bmiHeader; + union { + WORD bmiIndices[256]; + DWORD bmiMasks[3]; + RGBQUAD bmiColors[256]; + } u; + } bmi; + UINT iUsage; + int i; + + if (type == GDK_IMAGE_FASTEST || type == GDK_IMAGE_NORMAL) + type = GDK_IMAGE_SHARED; + + GDK_NOTE (MISC, g_print ("gdk_image_new_with_depth: %dx%dx%d %s\n", + width, height, depth, + (type == GDK_IMAGE_SHARED ? "shared" : + (type == GDK_IMAGE_SHARED_PIXMAP ? "shared_pixmap" : + "???")))); + + private = g_new (GdkImagePrivate, 1); + image = (GdkImage*) private; + + private->image_put = NULL; + + image->type = type; + image->visual = visual; + image->width = width; + image->height = height; + image->depth = depth; + + xvisual = ((GdkVisualPrivate*) visual)->xvisual; + + private->image_put = gdk_image_put_normal; + + bmi.bmiHeader.biSize = sizeof (BITMAPINFOHEADER); + bmi.bmiHeader.biWidth = width; + bmi.bmiHeader.biHeight = -height; + bmi.bmiHeader.biPlanes = 1; + if (depth == 15) + bmi.bmiHeader.biBitCount = 16; + else + bmi.bmiHeader.biBitCount = depth; +#if 1 + if (depth == 16) + bmi.bmiHeader.biCompression = BI_BITFIELDS; + else +#endif + bmi.bmiHeader.biCompression = BI_RGB; + bmi.bmiHeader.biSizeImage = 0; + bmi.bmiHeader.biXPelsPerMeter = + bmi.bmiHeader.biYPelsPerMeter = 0; + bmi.bmiHeader.biClrUsed = 0; + bmi.bmiHeader.biClrImportant = 0; + + if (image->visual->type == GDK_VISUAL_PSEUDO_COLOR) + { + iUsage = DIB_PAL_COLORS; + for (i = 0; i < 256; i++) + bmi.u.bmiIndices[i] = i; + } + else + { + if (depth == 1) + { + bmi.u.bmiColors[0].rgbBlue = + bmi.u.bmiColors[0].rgbGreen = + bmi.u.bmiColors[0].rgbRed = 0x00; + bmi.u.bmiColors[0].rgbReserved = 0x00; + + bmi.u.bmiColors[1].rgbBlue = + bmi.u.bmiColors[1].rgbGreen = + bmi.u.bmiColors[1].rgbRed = 0xFF; + bmi.u.bmiColors[1].rgbReserved = 0x00; + + } +#if 1 + else if (depth == 16) + { + bmi.u.bmiMasks[0] = visual->red_mask; + bmi.u.bmiMasks[1] = visual->green_mask; + bmi.u.bmiMasks[2] = visual->blue_mask; + } +#endif + iUsage = DIB_RGB_COLORS; + } + + private->ximage = + CreateDIBSection (gdk_DC, (BITMAPINFO *) &bmi, iUsage, + &image->mem, NULL, 0); + + if (private->ximage == NULL) + { + g_warning ("gdk_image_new_with_depth: CreateDIBSection failed"); + g_free (image); + return NULL; + } + + switch (depth) + { + case 1: + case 8: + image->bpp = 1; + break; + case 15: + case 16: + image->bpp = 2; + break; + case 24: + image->bpp = 3; + break; + case 32: + image->bpp = 4; + break; + default: + g_warning ("gdk_image_new_with_depth: depth = %d", depth); + g_assert_not_reached (); + } + image->byte_order = GDK_LSB_FIRST; + if (depth == 1) + image->bpl = ((width-1)/32 + 1)*4; + else + image->bpl = ((width*image->bpp - 1)/4 + 1)*4; + + GDK_NOTE (MISC, g_print ("... = %#x mem = %#x, bpl = %d\n", + private->ximage, image->mem, image->bpl)); + + return image; +} + +GdkImage* +gdk_image_new (GdkImageType type, + GdkVisual *visual, + gint width, + gint height) +{ + GdkVisualPrivate *visual_private = (GdkVisualPrivate *) visual; + return gdk_image_new_with_depth (type, visual, width, height, + visual_private->xvisual->bitspixel); +} + +GdkImage* +gdk_image_bitmap_new (GdkImageType type, + GdkVisual *visual, + gint width, + gint height) +{ + return gdk_image_new_with_depth (type, visual, width, height, 1); +} + +GdkImage* +gdk_image_get (GdkWindow *window, + gint x, + gint y, + gint width, + gint height) +{ + GdkImage *image; + GdkImagePrivate *private; + HDC hdc, memdc; + struct { + BITMAPINFOHEADER bmiHeader; + union { + WORD bmiIndices[256]; + DWORD bmiMasks[3]; + RGBQUAD bmiColors[256]; + } u; + } bmi; + HGDIOBJ oldbitmap1, oldbitmap2; + UINT iUsage; + BITMAP bm; + int i; + + g_return_val_if_fail (window != NULL, NULL); + + if (GDK_DRAWABLE_DESTROYED (window)) + return NULL; + + GDK_NOTE (MISC, g_print ("gdk_image_get: %#x %dx%d@+%d+%d\n", + GDK_DRAWABLE_XID (window), width, height, x, y)); + + private = g_new (GdkImagePrivate, 1); + image = (GdkImage*) private; + + private->image_put = gdk_image_put_normal; + + image->type = GDK_IMAGE_SHARED; + image->visual = gdk_window_get_visual (window); + image->width = width; + image->height = height; + + /* This function is called both to blit from a window and from + * a pixmap. + */ + if (GDK_DRAWABLE_TYPE (window) == GDK_DRAWABLE_PIXMAP) + { + if ((hdc = CreateCompatibleDC (NULL)) == NULL) + { + g_warning ("gdk_image_get: CreateCompatibleDC #1 failed"); + g_free (image); + return NULL; + } + if ((oldbitmap1 = SelectObject (hdc, GDK_DRAWABLE_XID (window))) == NULL) + { + g_warning ("gdk_image_get: SelectObject #1 failed"); + DeleteDC (hdc); + g_free (image); + return NULL; + } + GetObject (GDK_DRAWABLE_XID (window), sizeof (BITMAP), &bm); + GDK_NOTE (MISC, + g_print ("gdk_image_get: bmWidth = %d, bmHeight = %d, bmWidthBytes = %d, bmBitsPixel = %d\n", + bm.bmWidth, bm.bmHeight, bm.bmWidthBytes, bm.bmBitsPixel)); + image->depth = bm.bmBitsPixel; + if (image->depth <= 8) + { + iUsage = DIB_PAL_COLORS; + for (i = 0; i < 256; i++) + bmi.u.bmiIndices[i] = i; + } + else + iUsage = DIB_RGB_COLORS; + } + else + { + if ((hdc = GetDC (GDK_DRAWABLE_XID (window))) == NULL) + { + g_warning ("gdk_image_get: GetDC failed"); + g_free (image); + return NULL; + } + image->depth = gdk_visual_get_system ()->depth; + if (image->visual->type == GDK_VISUAL_PSEUDO_COLOR) + { + iUsage = DIB_PAL_COLORS; + for (i = 0; i < 256; i++) + bmi.u.bmiIndices[i] = i; + } + else + iUsage = DIB_RGB_COLORS; + } + + if ((memdc = CreateCompatibleDC (hdc)) == NULL) + { + g_warning ("gdk_image_get: CreateCompatibleDC #2 failed"); + if (GDK_DRAWABLE_TYPE (window) == GDK_DRAWABLE_PIXMAP) + { + SelectObject (hdc, oldbitmap1); + DeleteDC (hdc); + } + else + { + ReleaseDC (GDK_DRAWABLE_XID (window), hdc); + } + g_free (image); + return NULL; + } + + bmi.bmiHeader.biSize = sizeof (BITMAPINFOHEADER); + bmi.bmiHeader.biWidth = width; + bmi.bmiHeader.biHeight = -height; + bmi.bmiHeader.biPlanes = 1; + bmi.bmiHeader.biBitCount = image->depth; + if (image->depth == 16) + { + bmi.bmiHeader.biCompression = BI_BITFIELDS; + if (image->visual == NULL) + { + /* XXX ??? Is it always this if depth==16 and a pixmap? Guess so. */ + bmi.u.bmiMasks[0] = 0xf800; + bmi.u.bmiMasks[1] = 0x07e0; + bmi.u.bmiMasks[2] = 0x001f; + } + else + { + bmi.u.bmiMasks[0] = image->visual->red_mask; + bmi.u.bmiMasks[1] = image->visual->green_mask; + bmi.u.bmiMasks[2] = image->visual->blue_mask; + } + } + else + bmi.bmiHeader.biCompression = BI_RGB; + bmi.bmiHeader.biSizeImage = 0; + bmi.bmiHeader.biXPelsPerMeter = + bmi.bmiHeader.biYPelsPerMeter = 0; + bmi.bmiHeader.biClrUsed = 0; + bmi.bmiHeader.biClrImportant = 0; + + if ((private->ximage = + CreateDIBSection (hdc, (BITMAPINFO *) &bmi, iUsage, + &image->mem, NULL, 0)) == NULL) + { + g_warning ("gdk_image_get: CreateDIBSection failed"); + DeleteDC (memdc); + if (GDK_DRAWABLE_TYPE (window) == GDK_DRAWABLE_PIXMAP) + { + SelectObject (hdc, oldbitmap1); + DeleteDC (hdc); + } + else + { + ReleaseDC (GDK_DRAWABLE_XID (window), hdc); + } + g_free (image); + return NULL; + } + + if ((oldbitmap2 = SelectObject (memdc, private->ximage)) == NULL) + { + g_warning ("gdk_image_get: SelectObject #2 failed"); + DeleteObject (private->ximage); + DeleteDC (memdc); + if (GDK_DRAWABLE_TYPE (window) == GDK_DRAWABLE_PIXMAP) + { + SelectObject (hdc, oldbitmap1); + DeleteDC (hdc); + } + else + { + ReleaseDC (GDK_DRAWABLE_XID (window), hdc); + } + g_free (image); + return NULL; + } + + if (!BitBlt (memdc, 0, 0, width, height, hdc, x, y, SRCCOPY)) + { + g_warning ("gdk_image_get: BitBlt failed"); + SelectObject (memdc, oldbitmap2); + DeleteObject (private->ximage); + DeleteDC (memdc); + if (GDK_DRAWABLE_TYPE (window) == GDK_DRAWABLE_PIXMAP) + { + SelectObject (hdc, oldbitmap1); + DeleteDC (hdc); + } + else + { + ReleaseDC (GDK_DRAWABLE_XID (window), hdc); + } + g_free (image); + return NULL; + } + + if (SelectObject (memdc, oldbitmap2) == NULL) + g_warning ("gdk_image_get: SelectObject #3 failed"); + + if (!DeleteDC (memdc)) + g_warning ("gdk_image_get: DeleteDC failed"); + + if (GDK_DRAWABLE_TYPE (window) == GDK_DRAWABLE_PIXMAP) + { + SelectObject (hdc, oldbitmap1); + DeleteDC (hdc); + } + else + { + ReleaseDC (GDK_DRAWABLE_XID (window), hdc); + } + + switch (image->depth) + { + case 1: + case 8: + image->bpp = 1; + break; + case 15: + case 16: + image->bpp = 2; + break; + case 24: + image->bpp = 3; + break; + case 32: + image->bpp = 4; + break; + default: + g_warning ("gdk_image_get: image->depth = %d", image->depth); + g_assert_not_reached (); + } + image->byte_order = GDK_LSB_FIRST; + if (image->depth == 1) + image->bpl = ((width - 1)/32 + 1)*4; + else + image->bpl = ((width*image->bpp - 1)/4 + 1)*4; + + GDK_NOTE (MISC, g_print ("... = %#x mem = %#x, bpl = %d\n", + private->ximage, image->mem, image->bpl)); + + return image; +} + +guint32 +gdk_image_get_pixel (GdkImage *image, + gint x, + gint y) +{ + guint32 pixel; + GdkImagePrivate *private; + + g_return_val_if_fail (image != NULL, 0); + + private = (GdkImagePrivate *) image; + + g_return_val_if_fail (x >= 0 && x < image->width + && y >= 0 && y < image->height, 0); + + if (image->depth == 1) + pixel = (((char *) image->mem)[y * image->bpl + (x >> 3)] & (1 << (7 - (x & 0x7)))) != 0; + else + { + guchar *pixelp = (guchar *) image->mem + y * image->bpl + x * image->bpp; + + switch (image->bpp) + { + case 1: + pixel = *pixelp; + break; + + /* Windows is always LSB, no need to check image->byte_order. */ + case 2: + pixel = pixelp[0] | (pixelp[1] << 8); + break; + + case 3: + pixel = pixelp[0] | (pixelp[1] << 8) | (pixelp[2] << 16); + break; + + case 4: + pixel = pixelp[0] | (pixelp[1] << 8) | (pixelp[2] << 16); + break; + } + } + + return pixel; +} + +void +gdk_image_put_pixel (GdkImage *image, + gint x, + gint y, + guint32 pixel) +{ + GdkImagePrivate *private; + + g_return_if_fail (image != NULL); + + private = (GdkImagePrivate *) image; + + g_return_if_fail (x >= 0 && x < image->width && y >= 0 && y < image->height); + + if (image->depth == 1) + if (pixel & 1) + ((guchar *) image->mem)[y * image->bpl + (x >> 3)] |= (1 << (7 - (x & 0x7))); + else + ((guchar *) image->mem)[y * image->bpl + (x >> 3)] &= ~(1 << (7 - (x & 0x7))); + else + { + guchar *pixelp = (guchar *) image->mem + y * image->bpl + x * image->bpp; + + /* Windows is always LSB, no need to check image->byte_order. */ + switch (image->bpp) + { + case 4: + pixelp[3] = 0; + case 3: + pixelp[2] = ((pixel >> 16) & 0xFF); + case 2: + pixelp[1] = ((pixel >> 8) & 0xFF); + case 1: + pixelp[0] = (pixel & 0xFF); + } + } +} + +void +gdk_image_destroy (GdkImage *image) +{ + GdkImagePrivate *private; + + g_return_if_fail (image != NULL); + + private = (GdkImagePrivate*) image; + + GDK_NOTE (MISC, g_print ("gdk_image_destroy: %#x%s\n", + private->ximage, + (image->type == GDK_IMAGE_SHARED_PIXMAP ? + " (shared pixmap)" : ""))); + + switch (image->type) + { + case GDK_IMAGE_SHARED_PIXMAP: + break; /* The Windows bitmap has already been + * (or will be) deleted when freeing + * the corresponding pixmap. + */ + + case GDK_IMAGE_SHARED: + if (!DeleteObject (private->ximage)) + g_warning ("gdk_image_destroy: DeleteObject failed"); + break; + + default: + g_assert_not_reached (); + } + + g_free (image); +} + +static void +gdk_image_put_normal (GdkDrawable *drawable, + GdkGC *gc, + GdkImage *image, + gint xsrc, + gint ysrc, + gint xdest, + gint ydest, + gint width, + gint height) +{ + GdkDrawablePrivate *drawable_private; + GdkImagePrivate *image_private; + GdkGCPrivate *gc_private; + HDC hdc; + GdkColormapPrivate *colormap_private; + + g_return_if_fail (drawable != NULL); + g_return_if_fail (image != NULL); + g_return_if_fail (gc != NULL); + + if (GDK_DRAWABLE_DESTROYED (drawable)) + return; + image_private = (GdkImagePrivate*) image; + drawable_private = (GdkDrawablePrivate*) drawable; + gc_private = (GdkGCPrivate*) gc; + + /* The image can in fact be "shared", so don't test */ + + hdc = gdk_gc_predraw (drawable_private, gc_private); + colormap_private = (GdkColormapPrivate *) drawable_private->colormap; + if (colormap_private && colormap_private->xcolormap->rc_palette) + { + DIBSECTION ds; + static struct { + BITMAPINFOHEADER bmiHeader; + WORD bmiIndices[256]; + } bmi; + static gboolean bmi_inited = FALSE; + int i; + + if (!bmi_inited) + { + for (i = 0; i < 256; i++) + bmi.bmiIndices[i] = i; + bmi_inited = TRUE; + } + + if (GetObject (image_private->ximage, sizeof (DIBSECTION), + &ds) != sizeof (DIBSECTION)) + { + g_warning ("gdk_image_put_normal: GetObject failed"); + } +#if 0 + g_print("xdest = %d, ydest = %d, xsrc = %d, ysrc = %d, width = %d, height = %d\n", + xdest, ydest, xsrc, ysrc, width, height); + g_print("bmWidth = %d, bmHeight = %d, bmBitsPixel = %d, bmBits = %p\n", + ds.dsBm.bmWidth, ds.dsBm.bmHeight, ds.dsBm.bmBitsPixel, ds.dsBm.bmBits); + g_print("biWidth = %d, biHeight = %d, biBitCount = %d, biClrUsed = %d\n", + ds.dsBmih.biWidth, ds.dsBmih.biHeight, ds.dsBmih.biBitCount, ds.dsBmih.biClrUsed); +#endif + bmi.bmiHeader = ds.dsBmih; + /* I have spent hours on getting the parameters to + * SetDIBitsToDevice right. I wonder what drugs the guys in + * Redmond were on when they designed this API. + */ + if (SetDIBitsToDevice (hdc, + xdest, ydest, + width, height, + xsrc, (-ds.dsBmih.biHeight)-height-ysrc, + 0, -ds.dsBmih.biHeight, + ds.dsBm.bmBits, + (CONST BITMAPINFO *) &bmi, + DIB_PAL_COLORS) == 0) + g_warning ("SetDIBitsToDevice failed"); + } + else + { + HDC memdc; + HGDIOBJ oldbitmap; + + if ((memdc = CreateCompatibleDC (hdc)) == NULL) + { + g_warning ("gdk_image_put_normal: CreateCompatibleDC failed"); + gdk_gc_postdraw (drawable_private, gc_private); + return; + } + + if ((oldbitmap = SelectObject (memdc, image_private->ximage)) == NULL) + { + g_warning ("gdk_image_put_normal: SelectObject #1 failed"); + gdk_gc_postdraw (drawable_private, gc_private); + return; + } + if (!BitBlt (hdc, xdest, ydest, width, height, + memdc, xsrc, ysrc, SRCCOPY)) + g_warning ("gdk_image_put_normal: BitBlt failed"); + + if (SelectObject (memdc, oldbitmap) == NULL) + g_warning ("gdk_image_put_normal: SelectObject #2 failed"); + + if (!DeleteDC (memdc)) + g_warning ("gdk_image_put_normal: DeleteDC failed"); + } + gdk_gc_postdraw (drawable_private, gc_private); +} diff --git a/gdk/win32/gdkimage.c b/gdk/win32/gdkimage.c new file mode 100644 index 0000000000..0f2825e405 --- /dev/null +++ b/gdk/win32/gdkimage.c @@ -0,0 +1,759 @@ +/* GDK - The GIMP Drawing Kit + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library 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-1999. 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 "gdk.h" /* For gdk_error_trap_* / gdk_flush_* */ +#include "gdkimage.h" +#include "gdkprivate.h" +#include "gdkx.h" + +static void gdk_image_put_normal (GdkDrawable *drawable, + GdkGC *gc, + GdkImage *image, + gint xsrc, + gint ysrc, + gint xdest, + gint ydest, + gint width, + gint height); +static GList *image_list = NULL; + +void +gdk_image_exit (void) +{ + GdkImage *image; + + while (image_list) + { + image = image_list->data; + gdk_image_destroy (image); + } +} + +GdkImage * +gdk_image_new_bitmap (GdkVisual *visual, gpointer data, gint w, gint h) +/* + * Desc: create a new bitmap image + */ +{ + Visual *xvisual; + GdkImage *image; + GdkImagePrivate *private; + struct { + BITMAPINFOHEADER bmiHeader; + union { + WORD bmiIndices[2]; + RGBQUAD bmiColors[2]; + } u; + } bmi; + char *bits; + int bpl = (w-1)/8 + 1; + int bpl32 = ((w-1)/32 + 1)*4; + + private = g_new(GdkImagePrivate, 1); + image = (GdkImage *) private; + private->image_put = gdk_image_put_normal; + image->type = GDK_IMAGE_SHARED; + image->visual = visual; + image->width = w; + image->height = h; + image->depth = 1; + xvisual = ((GdkVisualPrivate*) visual)->xvisual; + + GDK_NOTE (MISC, g_print ("gdk_image_new_bitmap: %dx%d\n", w, h)); + + bmi.bmiHeader.biSize = sizeof (BITMAPINFOHEADER); + bmi.bmiHeader.biWidth = w; + bmi.bmiHeader.biHeight = -h; + bmi.bmiHeader.biPlanes = 1; + bmi.bmiHeader.biBitCount = 1; + bmi.bmiHeader.biCompression = BI_RGB; + bmi.bmiHeader.biSizeImage = 0; + bmi.bmiHeader.biXPelsPerMeter = + bmi.bmiHeader.biYPelsPerMeter = 0; + bmi.bmiHeader.biClrUsed = 0; + bmi.bmiHeader.biClrImportant = 0; + + bmi.u.bmiColors[0].rgbBlue = + bmi.u.bmiColors[0].rgbGreen = + bmi.u.bmiColors[0].rgbRed = 0x00; + bmi.u.bmiColors[0].rgbReserved = 0x00; + + bmi.u.bmiColors[1].rgbBlue = + bmi.u.bmiColors[1].rgbGreen = + bmi.u.bmiColors[1].rgbRed = 0xFF; + bmi.u.bmiColors[1].rgbReserved = 0x00; + + private->ximage = CreateDIBSection (gdk_DC, (BITMAPINFO *) &bmi, + DIB_RGB_COLORS, &bits, NULL, 0); + if (bpl != bpl32) + { + /* Win32 expects scanlines in DIBs to be 32 bit aligned */ + int i; + for (i = 0; i < h; i++) + memmove (bits + i*bpl32, ((char *) data) + i*bpl, bpl); + } + else + memmove (bits, data, bpl*h); + image->mem = bits; + image->bpl = bpl32; + image->byte_order = GDK_MSB_FIRST; + + image->bpp = 1; + return(image); +} /* gdk_image_new_bitmap() */ + +void +gdk_image_init (void) +{ +} + +static GdkImage* +gdk_image_new_with_depth (GdkImageType type, + GdkVisual *visual, + gint width, + gint height, + gint depth) +{ + GdkImage *image; + GdkImagePrivate *private; + Visual *xvisual; + struct { + BITMAPINFOHEADER bmiHeader; + union { + WORD bmiIndices[256]; + DWORD bmiMasks[3]; + RGBQUAD bmiColors[256]; + } u; + } bmi; + UINT iUsage; + int i; + + if (type == GDK_IMAGE_FASTEST || type == GDK_IMAGE_NORMAL) + type = GDK_IMAGE_SHARED; + + GDK_NOTE (MISC, g_print ("gdk_image_new_with_depth: %dx%dx%d %s\n", + width, height, depth, + (type == GDK_IMAGE_SHARED ? "shared" : + (type == GDK_IMAGE_SHARED_PIXMAP ? "shared_pixmap" : + "???")))); + + private = g_new (GdkImagePrivate, 1); + image = (GdkImage*) private; + + private->image_put = NULL; + + image->type = type; + image->visual = visual; + image->width = width; + image->height = height; + image->depth = depth; + + xvisual = ((GdkVisualPrivate*) visual)->xvisual; + + private->image_put = gdk_image_put_normal; + + bmi.bmiHeader.biSize = sizeof (BITMAPINFOHEADER); + bmi.bmiHeader.biWidth = width; + bmi.bmiHeader.biHeight = -height; + bmi.bmiHeader.biPlanes = 1; + if (depth == 15) + bmi.bmiHeader.biBitCount = 16; + else + bmi.bmiHeader.biBitCount = depth; +#if 1 + if (depth == 16) + bmi.bmiHeader.biCompression = BI_BITFIELDS; + else +#endif + bmi.bmiHeader.biCompression = BI_RGB; + bmi.bmiHeader.biSizeImage = 0; + bmi.bmiHeader.biXPelsPerMeter = + bmi.bmiHeader.biYPelsPerMeter = 0; + bmi.bmiHeader.biClrUsed = 0; + bmi.bmiHeader.biClrImportant = 0; + + if (image->visual->type == GDK_VISUAL_PSEUDO_COLOR) + { + iUsage = DIB_PAL_COLORS; + for (i = 0; i < 256; i++) + bmi.u.bmiIndices[i] = i; + } + else + { + if (depth == 1) + { + bmi.u.bmiColors[0].rgbBlue = + bmi.u.bmiColors[0].rgbGreen = + bmi.u.bmiColors[0].rgbRed = 0x00; + bmi.u.bmiColors[0].rgbReserved = 0x00; + + bmi.u.bmiColors[1].rgbBlue = + bmi.u.bmiColors[1].rgbGreen = + bmi.u.bmiColors[1].rgbRed = 0xFF; + bmi.u.bmiColors[1].rgbReserved = 0x00; + + } +#if 1 + else if (depth == 16) + { + bmi.u.bmiMasks[0] = visual->red_mask; + bmi.u.bmiMasks[1] = visual->green_mask; + bmi.u.bmiMasks[2] = visual->blue_mask; + } +#endif + iUsage = DIB_RGB_COLORS; + } + + private->ximage = + CreateDIBSection (gdk_DC, (BITMAPINFO *) &bmi, iUsage, + &image->mem, NULL, 0); + + if (private->ximage == NULL) + { + g_warning ("gdk_image_new_with_depth: CreateDIBSection failed"); + g_free (image); + return NULL; + } + + switch (depth) + { + case 1: + case 8: + image->bpp = 1; + break; + case 15: + case 16: + image->bpp = 2; + break; + case 24: + image->bpp = 3; + break; + case 32: + image->bpp = 4; + break; + default: + g_warning ("gdk_image_new_with_depth: depth = %d", depth); + g_assert_not_reached (); + } + image->byte_order = GDK_LSB_FIRST; + if (depth == 1) + image->bpl = ((width-1)/32 + 1)*4; + else + image->bpl = ((width*image->bpp - 1)/4 + 1)*4; + + GDK_NOTE (MISC, g_print ("... = %#x mem = %#x, bpl = %d\n", + private->ximage, image->mem, image->bpl)); + + return image; +} + +GdkImage* +gdk_image_new (GdkImageType type, + GdkVisual *visual, + gint width, + gint height) +{ + GdkVisualPrivate *visual_private = (GdkVisualPrivate *) visual; + return gdk_image_new_with_depth (type, visual, width, height, + visual_private->xvisual->bitspixel); +} + +GdkImage* +gdk_image_bitmap_new (GdkImageType type, + GdkVisual *visual, + gint width, + gint height) +{ + return gdk_image_new_with_depth (type, visual, width, height, 1); +} + +GdkImage* +gdk_image_get (GdkWindow *window, + gint x, + gint y, + gint width, + gint height) +{ + GdkImage *image; + GdkImagePrivate *private; + HDC hdc, memdc; + struct { + BITMAPINFOHEADER bmiHeader; + union { + WORD bmiIndices[256]; + DWORD bmiMasks[3]; + RGBQUAD bmiColors[256]; + } u; + } bmi; + HGDIOBJ oldbitmap1, oldbitmap2; + UINT iUsage; + BITMAP bm; + int i; + + g_return_val_if_fail (window != NULL, NULL); + + if (GDK_DRAWABLE_DESTROYED (window)) + return NULL; + + GDK_NOTE (MISC, g_print ("gdk_image_get: %#x %dx%d@+%d+%d\n", + GDK_DRAWABLE_XID (window), width, height, x, y)); + + private = g_new (GdkImagePrivate, 1); + image = (GdkImage*) private; + + private->image_put = gdk_image_put_normal; + + image->type = GDK_IMAGE_SHARED; + image->visual = gdk_window_get_visual (window); + image->width = width; + image->height = height; + + /* This function is called both to blit from a window and from + * a pixmap. + */ + if (GDK_DRAWABLE_TYPE (window) == GDK_DRAWABLE_PIXMAP) + { + if ((hdc = CreateCompatibleDC (NULL)) == NULL) + { + g_warning ("gdk_image_get: CreateCompatibleDC #1 failed"); + g_free (image); + return NULL; + } + if ((oldbitmap1 = SelectObject (hdc, GDK_DRAWABLE_XID (window))) == NULL) + { + g_warning ("gdk_image_get: SelectObject #1 failed"); + DeleteDC (hdc); + g_free (image); + return NULL; + } + GetObject (GDK_DRAWABLE_XID (window), sizeof (BITMAP), &bm); + GDK_NOTE (MISC, + g_print ("gdk_image_get: bmWidth = %d, bmHeight = %d, bmWidthBytes = %d, bmBitsPixel = %d\n", + bm.bmWidth, bm.bmHeight, bm.bmWidthBytes, bm.bmBitsPixel)); + image->depth = bm.bmBitsPixel; + if (image->depth <= 8) + { + iUsage = DIB_PAL_COLORS; + for (i = 0; i < 256; i++) + bmi.u.bmiIndices[i] = i; + } + else + iUsage = DIB_RGB_COLORS; + } + else + { + if ((hdc = GetDC (GDK_DRAWABLE_XID (window))) == NULL) + { + g_warning ("gdk_image_get: GetDC failed"); + g_free (image); + return NULL; + } + image->depth = gdk_visual_get_system ()->depth; + if (image->visual->type == GDK_VISUAL_PSEUDO_COLOR) + { + iUsage = DIB_PAL_COLORS; + for (i = 0; i < 256; i++) + bmi.u.bmiIndices[i] = i; + } + else + iUsage = DIB_RGB_COLORS; + } + + if ((memdc = CreateCompatibleDC (hdc)) == NULL) + { + g_warning ("gdk_image_get: CreateCompatibleDC #2 failed"); + if (GDK_DRAWABLE_TYPE (window) == GDK_DRAWABLE_PIXMAP) + { + SelectObject (hdc, oldbitmap1); + DeleteDC (hdc); + } + else + { + ReleaseDC (GDK_DRAWABLE_XID (window), hdc); + } + g_free (image); + return NULL; + } + + bmi.bmiHeader.biSize = sizeof (BITMAPINFOHEADER); + bmi.bmiHeader.biWidth = width; + bmi.bmiHeader.biHeight = -height; + bmi.bmiHeader.biPlanes = 1; + bmi.bmiHeader.biBitCount = image->depth; + if (image->depth == 16) + { + bmi.bmiHeader.biCompression = BI_BITFIELDS; + if (image->visual == NULL) + { + /* XXX ??? Is it always this if depth==16 and a pixmap? Guess so. */ + bmi.u.bmiMasks[0] = 0xf800; + bmi.u.bmiMasks[1] = 0x07e0; + bmi.u.bmiMasks[2] = 0x001f; + } + else + { + bmi.u.bmiMasks[0] = image->visual->red_mask; + bmi.u.bmiMasks[1] = image->visual->green_mask; + bmi.u.bmiMasks[2] = image->visual->blue_mask; + } + } + else + bmi.bmiHeader.biCompression = BI_RGB; + bmi.bmiHeader.biSizeImage = 0; + bmi.bmiHeader.biXPelsPerMeter = + bmi.bmiHeader.biYPelsPerMeter = 0; + bmi.bmiHeader.biClrUsed = 0; + bmi.bmiHeader.biClrImportant = 0; + + if ((private->ximage = + CreateDIBSection (hdc, (BITMAPINFO *) &bmi, iUsage, + &image->mem, NULL, 0)) == NULL) + { + g_warning ("gdk_image_get: CreateDIBSection failed"); + DeleteDC (memdc); + if (GDK_DRAWABLE_TYPE (window) == GDK_DRAWABLE_PIXMAP) + { + SelectObject (hdc, oldbitmap1); + DeleteDC (hdc); + } + else + { + ReleaseDC (GDK_DRAWABLE_XID (window), hdc); + } + g_free (image); + return NULL; + } + + if ((oldbitmap2 = SelectObject (memdc, private->ximage)) == NULL) + { + g_warning ("gdk_image_get: SelectObject #2 failed"); + DeleteObject (private->ximage); + DeleteDC (memdc); + if (GDK_DRAWABLE_TYPE (window) == GDK_DRAWABLE_PIXMAP) + { + SelectObject (hdc, oldbitmap1); + DeleteDC (hdc); + } + else + { + ReleaseDC (GDK_DRAWABLE_XID (window), hdc); + } + g_free (image); + return NULL; + } + + if (!BitBlt (memdc, 0, 0, width, height, hdc, x, y, SRCCOPY)) + { + g_warning ("gdk_image_get: BitBlt failed"); + SelectObject (memdc, oldbitmap2); + DeleteObject (private->ximage); + DeleteDC (memdc); + if (GDK_DRAWABLE_TYPE (window) == GDK_DRAWABLE_PIXMAP) + { + SelectObject (hdc, oldbitmap1); + DeleteDC (hdc); + } + else + { + ReleaseDC (GDK_DRAWABLE_XID (window), hdc); + } + g_free (image); + return NULL; + } + + if (SelectObject (memdc, oldbitmap2) == NULL) + g_warning ("gdk_image_get: SelectObject #3 failed"); + + if (!DeleteDC (memdc)) + g_warning ("gdk_image_get: DeleteDC failed"); + + if (GDK_DRAWABLE_TYPE (window) == GDK_DRAWABLE_PIXMAP) + { + SelectObject (hdc, oldbitmap1); + DeleteDC (hdc); + } + else + { + ReleaseDC (GDK_DRAWABLE_XID (window), hdc); + } + + switch (image->depth) + { + case 1: + case 8: + image->bpp = 1; + break; + case 15: + case 16: + image->bpp = 2; + break; + case 24: + image->bpp = 3; + break; + case 32: + image->bpp = 4; + break; + default: + g_warning ("gdk_image_get: image->depth = %d", image->depth); + g_assert_not_reached (); + } + image->byte_order = GDK_LSB_FIRST; + if (image->depth == 1) + image->bpl = ((width - 1)/32 + 1)*4; + else + image->bpl = ((width*image->bpp - 1)/4 + 1)*4; + + GDK_NOTE (MISC, g_print ("... = %#x mem = %#x, bpl = %d\n", + private->ximage, image->mem, image->bpl)); + + return image; +} + +guint32 +gdk_image_get_pixel (GdkImage *image, + gint x, + gint y) +{ + guint32 pixel; + GdkImagePrivate *private; + + g_return_val_if_fail (image != NULL, 0); + + private = (GdkImagePrivate *) image; + + g_return_val_if_fail (x >= 0 && x < image->width + && y >= 0 && y < image->height, 0); + + if (image->depth == 1) + pixel = (((char *) image->mem)[y * image->bpl + (x >> 3)] & (1 << (7 - (x & 0x7)))) != 0; + else + { + guchar *pixelp = (guchar *) image->mem + y * image->bpl + x * image->bpp; + + switch (image->bpp) + { + case 1: + pixel = *pixelp; + break; + + /* Windows is always LSB, no need to check image->byte_order. */ + case 2: + pixel = pixelp[0] | (pixelp[1] << 8); + break; + + case 3: + pixel = pixelp[0] | (pixelp[1] << 8) | (pixelp[2] << 16); + break; + + case 4: + pixel = pixelp[0] | (pixelp[1] << 8) | (pixelp[2] << 16); + break; + } + } + + return pixel; +} + +void +gdk_image_put_pixel (GdkImage *image, + gint x, + gint y, + guint32 pixel) +{ + GdkImagePrivate *private; + + g_return_if_fail (image != NULL); + + private = (GdkImagePrivate *) image; + + g_return_if_fail (x >= 0 && x < image->width && y >= 0 && y < image->height); + + if (image->depth == 1) + if (pixel & 1) + ((guchar *) image->mem)[y * image->bpl + (x >> 3)] |= (1 << (7 - (x & 0x7))); + else + ((guchar *) image->mem)[y * image->bpl + (x >> 3)] &= ~(1 << (7 - (x & 0x7))); + else + { + guchar *pixelp = (guchar *) image->mem + y * image->bpl + x * image->bpp; + + /* Windows is always LSB, no need to check image->byte_order. */ + switch (image->bpp) + { + case 4: + pixelp[3] = 0; + case 3: + pixelp[2] = ((pixel >> 16) & 0xFF); + case 2: + pixelp[1] = ((pixel >> 8) & 0xFF); + case 1: + pixelp[0] = (pixel & 0xFF); + } + } +} + +void +gdk_image_destroy (GdkImage *image) +{ + GdkImagePrivate *private; + + g_return_if_fail (image != NULL); + + private = (GdkImagePrivate*) image; + + GDK_NOTE (MISC, g_print ("gdk_image_destroy: %#x%s\n", + private->ximage, + (image->type == GDK_IMAGE_SHARED_PIXMAP ? + " (shared pixmap)" : ""))); + + switch (image->type) + { + case GDK_IMAGE_SHARED_PIXMAP: + break; /* The Windows bitmap has already been + * (or will be) deleted when freeing + * the corresponding pixmap. + */ + + case GDK_IMAGE_SHARED: + if (!DeleteObject (private->ximage)) + g_warning ("gdk_image_destroy: DeleteObject failed"); + break; + + default: + g_assert_not_reached (); + } + + g_free (image); +} + +static void +gdk_image_put_normal (GdkDrawable *drawable, + GdkGC *gc, + GdkImage *image, + gint xsrc, + gint ysrc, + gint xdest, + gint ydest, + gint width, + gint height) +{ + GdkDrawablePrivate *drawable_private; + GdkImagePrivate *image_private; + GdkGCPrivate *gc_private; + HDC hdc; + GdkColormapPrivate *colormap_private; + + g_return_if_fail (drawable != NULL); + g_return_if_fail (image != NULL); + g_return_if_fail (gc != NULL); + + if (GDK_DRAWABLE_DESTROYED (drawable)) + return; + image_private = (GdkImagePrivate*) image; + drawable_private = (GdkDrawablePrivate*) drawable; + gc_private = (GdkGCPrivate*) gc; + + /* The image can in fact be "shared", so don't test */ + + hdc = gdk_gc_predraw (drawable_private, gc_private); + colormap_private = (GdkColormapPrivate *) drawable_private->colormap; + if (colormap_private && colormap_private->xcolormap->rc_palette) + { + DIBSECTION ds; + static struct { + BITMAPINFOHEADER bmiHeader; + WORD bmiIndices[256]; + } bmi; + static gboolean bmi_inited = FALSE; + int i; + + if (!bmi_inited) + { + for (i = 0; i < 256; i++) + bmi.bmiIndices[i] = i; + bmi_inited = TRUE; + } + + if (GetObject (image_private->ximage, sizeof (DIBSECTION), + &ds) != sizeof (DIBSECTION)) + { + g_warning ("gdk_image_put_normal: GetObject failed"); + } +#if 0 + g_print("xdest = %d, ydest = %d, xsrc = %d, ysrc = %d, width = %d, height = %d\n", + xdest, ydest, xsrc, ysrc, width, height); + g_print("bmWidth = %d, bmHeight = %d, bmBitsPixel = %d, bmBits = %p\n", + ds.dsBm.bmWidth, ds.dsBm.bmHeight, ds.dsBm.bmBitsPixel, ds.dsBm.bmBits); + g_print("biWidth = %d, biHeight = %d, biBitCount = %d, biClrUsed = %d\n", + ds.dsBmih.biWidth, ds.dsBmih.biHeight, ds.dsBmih.biBitCount, ds.dsBmih.biClrUsed); +#endif + bmi.bmiHeader = ds.dsBmih; + /* I have spent hours on getting the parameters to + * SetDIBitsToDevice right. I wonder what drugs the guys in + * Redmond were on when they designed this API. + */ + if (SetDIBitsToDevice (hdc, + xdest, ydest, + width, height, + xsrc, (-ds.dsBmih.biHeight)-height-ysrc, + 0, -ds.dsBmih.biHeight, + ds.dsBm.bmBits, + (CONST BITMAPINFO *) &bmi, + DIB_PAL_COLORS) == 0) + g_warning ("SetDIBitsToDevice failed"); + } + else + { + HDC memdc; + HGDIOBJ oldbitmap; + + if ((memdc = CreateCompatibleDC (hdc)) == NULL) + { + g_warning ("gdk_image_put_normal: CreateCompatibleDC failed"); + gdk_gc_postdraw (drawable_private, gc_private); + return; + } + + if ((oldbitmap = SelectObject (memdc, image_private->ximage)) == NULL) + { + g_warning ("gdk_image_put_normal: SelectObject #1 failed"); + gdk_gc_postdraw (drawable_private, gc_private); + return; + } + if (!BitBlt (hdc, xdest, ydest, width, height, + memdc, xsrc, ysrc, SRCCOPY)) + g_warning ("gdk_image_put_normal: BitBlt failed"); + + if (SelectObject (memdc, oldbitmap) == NULL) + g_warning ("gdk_image_put_normal: SelectObject #2 failed"); + + if (!DeleteDC (memdc)) + g_warning ("gdk_image_put_normal: DeleteDC failed"); + } + gdk_gc_postdraw (drawable_private, gc_private); +} |