gdkgc-win32.c

Go to the documentation of this file.
00001 /* GDK - The GIMP Drawing Kit
00002  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
00003  *
00004  * This library is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU Library General Public
00006  * License as published by the Free Software Foundation; either
00007  * version 2 of the License, or (at your option) any later version.
00008  *
00009  * This library is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * Library General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU Library General Public
00015  * License along with this library; if not, write to the
00016  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00017  * Boston, MA 02111-1307, USA.
00018  */
00019 
00020 /*
00021  * Modified by the GTK+ Team and others 1997-1999.  See the AUTHORS
00022  * file for a list of people on the GTK+ Team.  See the ChangeLog
00023  * files for a list of changes.  These files are distributed with
00024  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
00025  */
00026 
00027 #include "config.h"
00028 
00029 #include <string.h>
00030 
00031 #include "gdkgc.h"
00032 #include "gdkfont.h"
00033 #include "gdkpixmap.h"
00034 #include "gdkprivate.h"
00035 #include "gdkwin32.h"
00036 
00037 static UINT text_align = TA_BASELINE;
00038 
00039 static void gdk_win32_gc_destroy(GdkGC * gc);
00040 static void gdk_win32_gc_get_values(GdkGC * gc, GdkGCValues * values);
00041 static void gdk_win32_gc_set_values(GdkGC * gc,
00042                                     GdkGCValues * values,
00043                                     GdkGCValuesMask values_mask);
00044 static void gdk_win32_gc_set_dashes(GdkGC * gc,
00045                                     gint dash_offset,
00046                                     gchar dash_list[], gint n);
00047 
00048 static GdkGCClass gdk_win32_gc_class = {
00049    gdk_win32_gc_destroy,
00050    gdk_win32_gc_get_values,
00051    gdk_win32_gc_set_values,
00052    gdk_win32_gc_set_dashes
00053 };
00054 
00055 guint gdk_gc_set_text_align(GdkGC * gc, guint tAlign)
00056 {
00057 
00058 //    GdkGCWin32Data *data = GDK_GC_WIN32DATA ((GdkGCPrivate *)gc);
00059 
00060    guint old_val = text_align;
00061    switch (tAlign) {
00062    case 7:
00063       text_align = TA_LEFT | TA_BOTTOM;
00064       break;
00065    case 4:
00066       text_align = TA_LEFT | TA_BASELINE;
00067       break;
00068    case 1:
00069       text_align = TA_LEFT | TA_TOP;
00070       break;
00071    case 8:
00072       text_align = TA_CENTER | TA_BOTTOM;
00073       break;
00074    case 5:
00075       text_align = TA_CENTER | TA_BASELINE;
00076       break;
00077    case 2:
00078       text_align = TA_CENTER | TA_TOP;
00079       break;
00080    case 9:
00081       text_align = TA_RIGHT | TA_BOTTOM;
00082       break;
00083    case 6:
00084       text_align = TA_RIGHT | TA_BASELINE;
00085       break;
00086    case 3:
00087       text_align = TA_RIGHT | TA_TOP;
00088       break;
00089    case 0:
00090       text_align = TA_BASELINE;
00091       break;
00092    }
00093 //    if (SetTextAlign (data->xgc, text_align) == GDI_ERROR)
00094 //                                                                                                                                                                                                                                                             WIN32_GDI_FAILED ("SetTextAlign");
00095    return (old_val);
00096 }
00097 
00098 static void
00099 gdk_win32_gc_values_to_win32values(GdkGCValues * values,
00100                                    GdkGCValuesMask mask,
00101                                    GdkGCWin32Data * data)
00102 {
00103    char *s = "";
00104    gint sw, sh;
00105 
00106    GDK_NOTE(MISC, g_print("{"));
00107 
00108    if (mask & GDK_GC_FOREGROUND) {
00109       data->foreground = values->foreground.pixel;
00110       data->values_mask |= GDK_GC_FOREGROUND;
00111       GDK_NOTE(MISC, (g_print("fg=%.06x", data->foreground), s = ","));
00112    }
00113 
00114    if (mask & GDK_GC_BACKGROUND) {
00115       data->background = values->background.pixel;
00116       data->values_mask |= GDK_GC_BACKGROUND;
00117       GDK_NOTE(MISC, (g_print("%sbg=%.06x", s, data->background),
00118                       s = ","));
00119    }
00120 
00121    if ((mask & GDK_GC_FONT) && (values->font->type == GDK_FONT_FONT
00122                                 || values->font->type == GDK_FONT_FONTSET))
00123    {
00124       if (data->font != NULL)
00125          gdk_font_unref(data->font);
00126       data->font = values->font;
00127       if (data->font != NULL) {
00128          gchar *xlfd;
00129 
00130          gdk_font_ref(data->font);
00131          data->values_mask |= GDK_GC_FONT;
00132          GDK_NOTE(MISC, (xlfd = gdk_font_full_name_get(data->font),
00133                          g_print("%sfont=%s", s, xlfd),
00134                          s = ",", gdk_font_full_name_free(xlfd)));
00135       } else {
00136          data->values_mask &= ~GDK_GC_FONT;
00137          GDK_NOTE(MISC, (g_print("%sfont=NULL"), s = ","));
00138       }
00139    }
00140 
00141    if (mask & GDK_GC_FUNCTION) {
00142       GDK_NOTE(MISC,
00143                (g_print("%srop2=%s ",
00144                         s,
00145                         gdk_win32_function_to_string(values->function)),
00146                 s = ","));
00147       switch (values->function) {
00148       case GDK_COPY:
00149          data->rop2 = R2_COPYPEN;
00150          GDK_NOTE(MISC, g_print("(COPYPEN)"));
00151          break;
00152       case GDK_INVERT:
00153          data->rop2 = R2_NOT;
00154          GDK_NOTE(MISC, g_print("(NOT)"));
00155          break;
00156       case GDK_XOR:
00157          data->rop2 = R2_XORPEN;
00158          GDK_NOTE(MISC, g_print("(XORPEN)"));
00159          break;
00160       case GDK_CLEAR:
00161          data->rop2 = R2_BLACK;
00162          GDK_NOTE(MISC, g_print("(BLACK)"));
00163          break;
00164       case GDK_AND:
00165          data->rop2 = R2_MASKPEN;
00166          GDK_NOTE(MISC, g_print("(MASKPEN)"));
00167          break;
00168       case GDK_AND_REVERSE:
00169          data->rop2 = R2_MASKPENNOT;
00170          GDK_NOTE(MISC, g_print("(MASKPENNOT)"));
00171          break;
00172       case GDK_AND_INVERT:
00173          data->rop2 = R2_MASKNOTPEN;
00174          GDK_NOTE(MISC, g_print("(MASKNOTPEN)"));
00175          break;
00176       case GDK_NOOP:
00177          data->rop2 = R2_NOP;
00178          GDK_NOTE(MISC, g_print("(NOP)"));
00179          break;
00180       case GDK_OR:
00181          data->rop2 = R2_MERGEPEN;
00182          GDK_NOTE(MISC, g_print("(MERGEPEN)"));
00183          break;
00184       case GDK_EQUIV:
00185          data->rop2 = R2_NOTXORPEN;
00186          GDK_NOTE(MISC, g_print("(NOTXORPEN)"));
00187          break;
00188       case GDK_OR_REVERSE:
00189          data->rop2 = R2_MERGEPENNOT;
00190          GDK_NOTE(MISC, g_print("(MERGEPENNOT)"));
00191          break;
00192       case GDK_COPY_INVERT:
00193          data->rop2 = R2_NOTCOPYPEN;
00194          GDK_NOTE(MISC, g_print("(NOTCOPYPEN)"));
00195          break;
00196       case GDK_OR_INVERT:
00197          data->rop2 = R2_MERGENOTPEN;
00198          GDK_NOTE(MISC, g_print("(MERGENOTPEN)"));
00199          break;
00200       case GDK_NAND:
00201          data->rop2 = R2_NOTMASKPEN;
00202          GDK_NOTE(MISC, g_print("(NOTMASKPEN)"));
00203          break;
00204       case GDK_SET:
00205          data->rop2 = R2_WHITE;
00206          GDK_NOTE(MISC, g_print("(WHITE)"));
00207          break;
00208       }
00209       GDK_NOTE(MISC, g_print(" "));
00210       data->values_mask |= GDK_GC_FUNCTION;
00211    }
00212 
00213    if (mask & GDK_GC_FILL) {
00214       data->fill_style = values->fill;
00215       data->values_mask |= GDK_GC_FILL;
00216       GDK_NOTE(MISC,
00217                (g_print("%sfill=%s",
00218                         s,
00219                         gdk_win32_fill_style_to_string(data->fill_style)),
00220                 s = ","));
00221    }
00222 
00223    if (mask & GDK_GC_TILE) {
00224       if (data->tile != NULL)
00225          gdk_drawable_unref(data->tile);
00226       data->tile = values->tile;
00227       if (data->tile != NULL) {
00228          gdk_drawable_ref(data->tile);
00229          data->values_mask |= GDK_GC_TILE;
00230          GDK_NOTE(MISC, (g_print("%stile=%#x", s,
00231                                  GDK_DRAWABLE_XID(data->tile)), s = ","));
00232       } else {
00233          data->values_mask &= ~GDK_GC_TILE;
00234          GDK_NOTE(MISC, (g_print("%stile=NULL", s), s = ","));
00235       }
00236    }
00237 
00238    if (mask & GDK_GC_STIPPLE) {
00239       if (data->stipple != NULL)
00240          gdk_drawable_unref(data->stipple);
00241       data->stipple = values->stipple;
00242       if (data->stipple != NULL) {
00243          gdk_drawable_get_size(data->stipple, &sw, &sh);
00244 
00245          if (sw != 8 || sh != 8) {
00246             /* It seems that it *must* be 8x8, at least on my machine. 
00247              * Thus, tile an 8x8 bitmap with the stipple in case it is
00248              * smaller, or simply use just the top left 8x8 in case it is
00249              * larger.
00250              */
00251             gchar dummy[8];
00252             GdkPixmap *bm = gdk_bitmap_create_from_data(NULL, dummy, 8, 8);
00253             GdkGC *gc = gdk_gc_new(bm);
00254             gint i, j;
00255 
00256             i = 0;
00257             while (i < 8) {
00258                j = 0;
00259                while (j < 8) {
00260                   gdk_draw_drawable(bm, gc, data->stipple, 0, 0, i, j, sw,
00261                                     sh);
00262                   j += sh;
00263                }
00264                i += sw;
00265             }
00266             data->stipple = bm;
00267             gdk_gc_unref(gc);
00268          } else
00269             gdk_drawable_ref(data->stipple);
00270          data->values_mask |= GDK_GC_STIPPLE;
00271          GDK_NOTE(MISC, (g_print("%sstipple=%#x", s,
00272                                  GDK_DRAWABLE_XID(data->stipple)),
00273                          s = ","));
00274       } else {
00275          data->values_mask &= ~GDK_GC_STIPPLE;
00276          GDK_NOTE(MISC, (g_print("%sstipple=NULL", s), s = ","));
00277       }
00278    }
00279 
00280    if (mask & GDK_GC_CLIP_MASK) {
00281       if (data->clip_region != NULL)
00282          if (!DeleteObject(data->clip_region))
00283             WIN32_GDI_FAILED("DeleteObject");
00284       if (values->clip_mask != NULL) {
00285          data->clip_region =
00286              BitmapToRegion((HBITMAP) GDK_DRAWABLE_XID(values->clip_mask));
00287          data->values_mask |= GDK_GC_CLIP_MASK;
00288       } else {
00289          data->clip_region = NULL;
00290          data->values_mask &= ~GDK_GC_CLIP_MASK;
00291       }
00292       GDK_NOTE(MISC, (g_print("%sclip=%#x", s, data->clip_region),
00293                       s = ","));
00294    }
00295 
00296    if (mask & GDK_GC_SUBWINDOW) {
00297       data->subwindow_mode = values->subwindow_mode;
00298       data->values_mask |= GDK_GC_SUBWINDOW;
00299       GDK_NOTE(MISC, (g_print("%ssubw=%d", s, data->subwindow_mode),
00300                       s = ","));
00301    }
00302 
00303    if (mask & GDK_GC_TS_X_ORIGIN) {
00304       data->ts_x_origin = values->ts_x_origin;
00305       data->values_mask |= GDK_GC_TS_X_ORIGIN;
00306       GDK_NOTE(MISC, (g_print("%sts_x=%d", s, data->ts_x_origin),
00307                       s = ","));
00308    }
00309 
00310    if (mask & GDK_GC_TS_Y_ORIGIN) {
00311       data->ts_y_origin = values->ts_y_origin;
00312       data->values_mask |= GDK_GC_TS_Y_ORIGIN;
00313       GDK_NOTE(MISC, (g_print("%sts_y=%d", s, data->ts_y_origin),
00314                       s = ","));
00315    }
00316 
00317    if (mask & GDK_GC_CLIP_X_ORIGIN) {
00318       data->clip_x_origin = values->clip_x_origin;
00319       data->values_mask |= GDK_GC_CLIP_X_ORIGIN;
00320       GDK_NOTE(MISC, (g_print("%sclip_x=%d", s, data->clip_x_origin),
00321                       s = ","));
00322    }
00323 
00324    if (mask & GDK_GC_CLIP_Y_ORIGIN) {
00325       data->clip_y_origin = values->clip_y_origin;
00326       data->values_mask |= GDK_GC_CLIP_Y_ORIGIN;
00327       GDK_NOTE(MISC, (g_print("%sclip_y=%d", s, data->clip_y_origin),
00328                       s = ","));
00329    }
00330 
00331    if (mask & GDK_GC_EXPOSURES) {
00332       data->graphics_exposures = values->graphics_exposures;
00333       data->values_mask |= GDK_GC_EXPOSURES;
00334       GDK_NOTE(MISC, (g_print("%sexp=%d", s, data->graphics_exposures),
00335                       s = ","));
00336    }
00337 
00338    if (mask & GDK_GC_LINE_WIDTH) {
00339       data->pen_width = values->line_width;
00340       data->values_mask |= GDK_GC_LINE_WIDTH;
00341       GDK_NOTE(MISC, (g_print("%spw=%d", s, data->pen_width), s = ","));
00342    }
00343 
00344    if (mask & GDK_GC_LINE_STYLE) {
00345       data->pen_style &= ~(PS_STYLE_MASK);
00346       GDK_NOTE(MISC, (g_print("%sps|=", s), s = ","));
00347       switch (values->line_style) {
00348       case GDK_LINE_SOLID:
00349          GDK_NOTE(MISC, g_print("LINE_SOLID"));
00350          data->pen_style |= PS_SOLID;
00351          break;
00352       case GDK_LINE_ON_OFF_DASH:
00353       case GDK_LINE_DOUBLE_DASH:        /* ??? */
00354          GDK_NOTE(MISC, g_print("DASH"));
00355          data->pen_style |= PS_DASH;
00356          break;
00357       }
00358       data->values_mask |= GDK_GC_LINE_STYLE;
00359    }
00360 
00361    if (mask & GDK_GC_CAP_STYLE) {
00362       data->pen_style &= ~(PS_ENDCAP_MASK);
00363       GDK_NOTE(MISC, (g_print("%sps|=", s), s = ","));
00364       switch (values->cap_style) {
00365       case GDK_CAP_NOT_LAST:   /* ??? */
00366       case GDK_CAP_BUTT:
00367          GDK_NOTE(MISC, g_print("ENDCAP_FLAT"));
00368          data->pen_style |= PS_ENDCAP_FLAT;
00369          break;
00370       case GDK_CAP_ROUND:
00371          GDK_NOTE(MISC, g_print("ENDCAP_ROUND"));
00372          data->pen_style |= PS_ENDCAP_ROUND;
00373          break;
00374       case GDK_CAP_PROJECTING:
00375          GDK_NOTE(MISC, g_print("ENDCAP_SQUARE"));
00376          data->pen_style |= PS_ENDCAP_SQUARE;
00377          break;
00378       }
00379       data->values_mask |= GDK_GC_CAP_STYLE;
00380    }
00381 
00382    if (mask & GDK_GC_JOIN_STYLE) {
00383       data->pen_style &= ~(PS_JOIN_MASK);
00384       GDK_NOTE(MISC, (g_print("%sps|=", s), s = ","));
00385       switch (values->join_style) {
00386       case GDK_JOIN_MITER:
00387          GDK_NOTE(MISC, g_print("JOIN_MITER"));
00388          data->pen_style |= PS_JOIN_MITER;
00389          break;
00390       case GDK_JOIN_ROUND:
00391          GDK_NOTE(MISC, g_print("JOIN_ROUND"));
00392          data->pen_style |= PS_JOIN_ROUND;
00393          break;
00394       case GDK_JOIN_BEVEL:
00395          GDK_NOTE(MISC, g_print("JOIN_BEVEL"));
00396          data->pen_style |= PS_JOIN_BEVEL;
00397          break;
00398       }
00399       data->values_mask |= GDK_GC_JOIN_STYLE;
00400    }
00401    GDK_NOTE(MISC, g_print("}\n"));
00402 }
00403 
00404 GdkGC *_gdk_win32_gc_new(GdkDrawable * drawable,
00405                          GdkGCValues * values, GdkGCValuesMask mask)
00406 {
00407    GdkGC *gc;
00408    GdkGCPrivate *private;
00409    GdkGCWin32Data *data;
00410 #if 0
00411    static GdkColor black;
00412    static GdkColor white;
00413    static gboolean beenhere = FALSE;
00414 
00415    if (!beenhere) {
00416       gdk_color_black(gdk_colormap_get_system(), &black);
00417       gdk_color_white(gdk_colormap_get_system(), &white);
00418       beenhere = TRUE;
00419    }
00420 #endif
00421    gc = gdk_gc_alloc();
00422    private = (GdkGCPrivate *) gc;
00423 
00424    private->klass = &gdk_win32_gc_class;
00425    private->klass_data = data = g_new(GdkGCWin32Data, 1);
00426 
00427 #if 0
00428    data->foreground = black.pixel;
00429    data->background = white.pixel;
00430 #else
00431    data->foreground = 0;
00432    data->background = 1;
00433 #endif
00434    data->font = NULL;
00435    data->rop2 = R2_COPYPEN;
00436    data->fill_style = GDK_SOLID;
00437    data->tile = NULL;
00438    data->stipple = NULL;
00439    data->clip_region = NULL;
00440    data->ts_x_origin = data->ts_y_origin =
00441        data->clip_x_origin = data->clip_y_origin = 0;
00442    data->pen_style = PS_GEOMETRIC | PS_ENDCAP_FLAT | PS_JOIN_MITER;
00443    data->pen_width = 0;
00444 
00445    data->values_mask = GDK_GC_FUNCTION | GDK_GC_FILL;
00446 
00447    GDK_NOTE(MISC, g_print("_gdk_win32_gc_new: "));
00448    gdk_win32_gc_values_to_win32values(values, mask, data);
00449 
00450    data->hwnd = NULL;
00451    data->xgc = NULL;
00452 
00453    GDK_NOTE(MISC, g_print(" = %p\n", gc));
00454 
00455    return gc;
00456 }
00457 
00458 static void gdk_win32_gc_destroy(GdkGC * gc)
00459 {
00460    GdkGCWin32Data *data = GDK_GC_WIN32DATA(gc);
00461 
00462    if (data->values_mask & GDK_GC_FONT)
00463       gdk_font_unref(data->font);
00464 
00465    if (data->values_mask & GDK_GC_TILE)
00466       gdk_drawable_unref(data->tile);
00467 
00468    if (data->values_mask & GDK_GC_STIPPLE)
00469       gdk_drawable_unref(data->stipple);
00470 
00471    if (data->values_mask & GDK_GC_CLIP_MASK)
00472       DeleteObject(data->clip_region);
00473 
00474    g_free(GDK_GC_WIN32DATA(gc));
00475 }
00476 
00477 static void gdk_win32_gc_get_values(GdkGC * gc, GdkGCValues * values)
00478 {
00479    GdkGCWin32Data *data = GDK_GC_WIN32DATA(gc);
00480 
00481    values->foreground.pixel = data->foreground;
00482    values->background.pixel = data->background;
00483    values->font = data->font;
00484 
00485    switch (data->rop2) {
00486    case R2_COPYPEN:
00487       values->function = GDK_COPY;
00488       break;
00489    case R2_NOT:
00490       values->function = GDK_INVERT;
00491       break;
00492    case R2_XORPEN:
00493       values->function = GDK_XOR;
00494       break;
00495    case R2_BLACK:
00496       values->function = GDK_CLEAR;
00497       break;
00498    case R2_MASKPEN:
00499       values->function = GDK_AND;
00500       break;
00501    case R2_MASKPENNOT:
00502       values->function = GDK_AND_REVERSE;
00503       break;
00504    case R2_MASKNOTPEN:
00505       values->function = GDK_AND_INVERT;
00506       break;
00507    case R2_NOP:
00508       values->function = GDK_NOOP;
00509       break;
00510    case R2_MERGEPEN:
00511       values->function = GDK_OR;
00512       break;
00513    case R2_NOTXORPEN:
00514       values->function = GDK_EQUIV;
00515       break;
00516    case R2_MERGEPENNOT:
00517       values->function = GDK_OR_REVERSE;
00518       break;
00519    case R2_NOTCOPYPEN:
00520       values->function = GDK_COPY_INVERT;
00521       break;
00522    case R2_MERGENOTPEN:
00523       values->function = GDK_OR_INVERT;
00524       break;
00525    case R2_NOTMASKPEN:
00526       values->function = GDK_NAND;
00527       break;
00528    case R2_WHITE:
00529       values->function = GDK_SET;
00530       break;
00531    }
00532 
00533    values->fill = data->fill_style;
00534 
00535    values->tile = data->tile;
00536    values->stipple = data->stipple;
00537 
00538    values->clip_mask = NULL;
00539 #if 0 // bb mod 15.02.06
00540    if (data->clip_region != NULL) {
00541       RECT rect;
00542       HBRUSH hbr;
00543       HDC hdc;
00544       HGDIOBJ oldbitmap;
00545       GdkPixmap *pixmap;
00546       gboolean ok = TRUE;
00547 
00548       /* Build pixmap for clip region; if anything fails, do so w/o invoking */
00549       /* more code on failed objects, just in case this is the cause of one */
00550       /* of the rare crashes we're seeing */
00551       GetRgnBox (data->clip_region, &rect);
00552       pixmap = gdk_pixmap_new (NULL, rect.right - rect.left, rect.bottom - rect.top,1);
00553       hbr = GetStockObject (WHITE_BRUSH);
00554       if ((hdc = CreateCompatibleDC (NULL)) == NULL)
00555          WIN32_GDI_FAILED ("CreateCompatibleDC"), ok = FALSE;
00556       if (ok && (oldbitmap =
00557                  SelectObject (hdc, GDK_DRAWABLE_XID (pixmap))) == NULL) 
00558          WIN32_GDI_FAILED ("SelectObject"), ok = FALSE;
00559       if (ok) {
00560          hbr = GetStockObject (BLACK_BRUSH);
00561          if (hbr == NULL || !FillRect (hdc, &rect, hbr)) 
00562             WIN32_GDI_FAILED ("FillRect"), ok = FALSE;
00563       }
00564       if (ok) {
00565          hbr = GetStockObject (WHITE_BRUSH);
00566          if (hbr == NULL || !FillRgn (hdc, data->clip_region, hbr)) 
00567             WIN32_GDI_FAILED ("FillRgn"), ok = FALSE;
00568       }
00569       if (hdc != NULL && oldbitmap != NULL) {
00570          if (SelectObject (hdc, oldbitmap) == NULL) 
00571             WIN32_GDI_FAILED ("SelectObject"), ok = FALSE;
00572       }     
00573       if (hdc != NULL)
00574          DeleteDC (hdc);
00575       if (ok)
00576          values->clip_mask = pixmap;
00577       else if (pixmap != NULL)
00578          gdk_drawable_unref(pixmap);
00579    }
00580 #endif // bb mod 15.02.06
00581 
00582    values->subwindow_mode = data->subwindow_mode;
00583    values->ts_x_origin = data->ts_x_origin;
00584    values->ts_y_origin = data->ts_y_origin;
00585    values->clip_x_origin = data->clip_x_origin;
00586    values->clip_y_origin = data->clip_y_origin;
00587    values->graphics_exposures = data->graphics_exposures;
00588    values->line_width = data->pen_width;
00589 
00590    if (data->pen_style & PS_SOLID)
00591       values->line_style = GDK_LINE_SOLID;
00592    else if (data->pen_style & PS_DASH)
00593       values->line_style = GDK_LINE_ON_OFF_DASH;
00594    else
00595       values->line_style = GDK_LINE_SOLID;
00596 
00597    /* PS_ENDCAP_ROUND is zero */
00598    if (data->pen_style & PS_ENDCAP_FLAT)
00599       values->cap_style = GDK_CAP_BUTT;
00600    else if (data->pen_style & PS_ENDCAP_SQUARE)
00601       values->cap_style = GDK_CAP_PROJECTING;
00602    else
00603       values->cap_style = GDK_CAP_ROUND;
00604 
00605    /* PS_JOIN_ROUND is zero */
00606    if (data->pen_style & PS_JOIN_MITER)
00607       values->join_style = GDK_JOIN_MITER;
00608    else if (data->pen_style & PS_JOIN_BEVEL)
00609       values->join_style = GDK_JOIN_BEVEL;
00610    else
00611       values->join_style = GDK_JOIN_ROUND;
00612 }
00613 
00614 static void
00615 gdk_win32_gc_set_values(GdkGC * gc,
00616                         GdkGCValues * values, GdkGCValuesMask mask)
00617 {
00618    GdkGCWin32Data *data = GDK_GC_WIN32DATA(gc);
00619 
00620    GDK_NOTE(MISC, g_print("gdk_win32_gc_set_values: "));
00621 
00622    gdk_win32_gc_values_to_win32values(values, mask, data);
00623 }
00624 
00625 static void
00626 gdk_win32_gc_set_dashes(GdkGC * gc,
00627                         gint dash_offset, gchar dash_list[], gint n)
00628 {
00629    int i;
00630    GdkGCWin32Data *data = GDK_GC_WIN32DATA(gc);
00631 
00632    data->pen_style &= ~(PS_STYLE_MASK);
00633 //  data->pen_style |= PS_DASH; // bb removed 28.01.2003
00634 
00635    /* 
00636     * Set the extended line style. This could be done by 
00637     * PS_USERSTYLE and ExtCreatePen; but ONLY on WinNT, 
00638     * so let's make a guess (based on the implementation 
00639     * in DIA). On Win9x this does only work for lines
00640     * with width one ...
00641     *
00642     * More workarounds for Win9x descibed at:
00643     * http://www.codeguru.com/gdi/dashed.shtml
00644     */
00645    if (!IS_WIN_NT(windows_version) && data->pen_width > 1) {
00646       GDK_NOTE(MISC,
00647                g_print("gdk_win32_gc_set_dashes: not fully supported\n"));
00648       data->pen_style |= PS_SOLID;
00649       return;
00650    }
00651    // bb changes 29.01.2003
00652    if (!IS_WIN_NT(windows_version)) {
00653       /* data->pen_style = PS_COSMETIC; ??? */
00654       if (2 == n) {
00655          if ((dash_list[0] == dash_list[1]) && (dash_list[0] > 2)) {
00656             data->pen_style |= PS_DASH;
00657             GDK_NOTE(MISC,
00658                      g_print("gdk_win32_gc_set_dashes: PS_DASH (%d,%d)\n",
00659                              dash_list[0], dash_list[1]));
00660          } else {
00661             data->pen_style |= PS_DOT;
00662             GDK_NOTE(MISC,
00663                      g_print("gdk_win32_gc_set_dashes: PS_DOT (%d,%d)\n",
00664                              dash_list[0], dash_list[1]));
00665          }
00666       } else if (4 == n) {
00667          data->pen_style |= PS_DASHDOT;
00668          GDK_NOTE(MISC,
00669                   g_print
00670                   ("gdk_win32_gc_set_dashes: PS_DASHDOT (%d,%d,%d,%d)\n",
00671                    dash_list[0], dash_list[1], dash_list[2],
00672                    dash_list[3]));
00673       } else if (6 == n) {
00674          data->pen_style |= PS_DASHDOTDOT;
00675          GDK_NOTE(MISC,
00676                   g_print
00677                   ("gdk_win32_gc_set_dashes: PS_DASHDOTDOT (%d,%d,%d,%d,%d,%d)\n",
00678                    dash_list[0], dash_list[1], dash_list[2], dash_list[3],
00679                    dash_list[4], dash_list[5]));
00680       } else {
00681          data->pen_style |= PS_DASH;
00682          GDK_NOTE(MISC,
00683                   g_print
00684                   ("gdk_win32_gc_set_dashes: no guess for %d dashes\n",
00685                    n));
00686       }
00687    } else {
00688 
00689 // vo add
00690       if (IS_WIN_NT(windows_version)) {
00691          if ((data->pen_width <= 1) && (n == 0)) {
00692             data->pen_style = PS_COSMETIC;
00693             data->luser_dash = 0;
00694             data->pen_width = 1;
00695             return;
00696          }
00697       }
00698 
00699       data->pen_style |= PS_USERSTYLE;
00700       data->luser_dash = n;     // not for Windows 95
00701       for (i = 0; i < n; i++)
00702          data->user_dash[i] = (int) dash_list[i];
00703    }
00704 }
00705 
00706 void gdk_gc_set_clip_rectangle(GdkGC * gc, GdkRectangle * rectangle)
00707 {
00708    GdkGCWin32Data *data;
00709 
00710    g_return_if_fail(gc != NULL);
00711 
00712    data = GDK_GC_WIN32DATA(gc);
00713 
00714    if (data->clip_region != NULL)
00715       if (!DeleteObject(data->clip_region))
00716          WIN32_GDI_FAILED("DeleteObject");
00717    if (rectangle) {
00718       GDK_NOTE(MISC,
00719                g_print("gdk_gc_set_clip_rectangle: (%d) %dx%d@+%d+%d\n",
00720                        data,
00721                        rectangle->width, rectangle->height,
00722                        rectangle->x, rectangle->y));
00723       if ((data->clip_region =
00724            CreateRectRgn(rectangle->x, rectangle->y,
00725                          rectangle->x + rectangle->width,
00726                          rectangle->y + rectangle->height)) == NULL)
00727          WIN32_GDI_FAILED("CreateRectRgn");
00728 
00729       data->values_mask |= GDK_GC_CLIP_MASK;
00730    } else {
00731       GDK_NOTE(MISC, g_print("gdk_gc_set_clip_rectangle: (%d) NULL\n",
00732                              data));
00733       data->clip_region = NULL;
00734       data->values_mask &= ~GDK_GC_CLIP_MASK;
00735    }
00736    data->values_mask &= ~(GDK_GC_CLIP_X_ORIGIN | GDK_GC_CLIP_Y_ORIGIN);
00737 }
00738 
00739 void gdk_gc_set_clip_region(GdkGC * gc, GdkRegion * region)
00740 {
00741    GdkGCWin32Data *data;
00742 
00743    g_return_if_fail(gc != NULL);
00744 
00745    data = GDK_GC_WIN32DATA(gc);
00746 
00747    GDK_NOTE(MISC, g_print("gdk_gc_set_clip_region: (%d) %s\n",
00748                           data, (region != NULL ? "xxx" : "None")));
00749 
00750    if (data->clip_region != NULL)
00751       if (!DeleteObject(data->clip_region))
00752          WIN32_GDI_FAILED("DeleteObject");
00753    if (region) {
00754       GdkRegionPrivate *region_private;
00755 
00756       region_private = (GdkRegionPrivate *) region;
00757       data->clip_region = CreateRectRgn(1, 1, 0, 0);
00758       CombineRgn(data->clip_region, region_private->xregion, NULL,
00759                  RGN_COPY);
00760       data->values_mask |= GDK_GC_CLIP_MASK;
00761    } else {
00762       data->clip_region = NULL;
00763       data->values_mask &= ~GDK_GC_CLIP_MASK;
00764    }
00765 }
00766 
00767 void gdk_gc_copy(GdkGC * dst_gc, GdkGC * src_gc)
00768 {
00769    GdkGCWin32Data *dst_data = GDK_GC_WIN32DATA(dst_gc);
00770    GdkGCWin32Data *src_data = GDK_GC_WIN32DATA(src_gc);
00771    DWORD nbytes;
00772    LPRGNDATA rgn;
00773 
00774    if (dst_data->font != NULL)
00775       gdk_font_unref(dst_data->font);
00776    if (dst_data->tile != NULL)
00777       gdk_drawable_unref(dst_data->tile);
00778    if (dst_data->stipple != NULL)
00779       gdk_drawable_unref(dst_data->stipple);
00780    if (dst_data->clip_region != NULL)
00781       if (!DeleteObject(dst_data->clip_region))
00782          WIN32_GDI_FAILED("DeleteObject");
00783 
00784    *dst_data = *src_data;
00785 
00786    if (dst_data->clip_region != NULL) {
00787       nbytes = GetRegionData(dst_data->clip_region, 0, NULL);
00788       rgn = g_malloc(nbytes);
00789       GetRegionData(dst_data->clip_region, nbytes, rgn);
00790       if ((dst_data->clip_region =
00791            ExtCreateRegion(NULL, nbytes, rgn)) == NULL)
00792          WIN32_GDI_FAILED("ExtCreateRegion");
00793       g_free(rgn);
00794    }
00795 
00796    if (dst_data->font != NULL)
00797       gdk_font_ref(dst_data->font);
00798    if (dst_data->tile != NULL)
00799       gdk_drawable_ref(dst_data->tile);
00800    if (dst_data->stipple != NULL)
00801       gdk_drawable_ref(dst_data->stipple);
00802 }
00803 
00804 static guint bitmask[9] = { 0, 1, 3, 7, 15, 31, 63, 127, 255 };
00805 
00806 COLORREF
00807 gdk_colormap_color(GdkColormapPrivateWin32 * colormap_private,
00808                    gulong pixel)
00809 {
00810    GdkVisual *visual;
00811    guchar r, g, b;
00812 
00813    if (colormap_private == NULL || colormap_private->xcolormap->rc_palette)
00814       return PALETTEINDEX(pixel);
00815    else {
00816       visual = colormap_private->base.visual;
00817       r = (pixel & visual->red_mask) >> visual->red_shift;
00818       r = (r * 255) / bitmask[visual->red_prec];
00819       g = (pixel & visual->green_mask) >> visual->green_shift;
00820       g = (g * 255) / bitmask[visual->green_prec];
00821       b = (pixel & visual->blue_mask) >> visual->blue_shift;
00822       b = (b * 255) / bitmask[visual->blue_prec];
00823 
00824       return RGB(r, g, b);
00825    }
00826 }
00827 
00828 static void
00829 predraw_set_foreground(GdkGCWin32Data * data,
00830                        GdkColormapPrivateWin32 * colormap_private)
00831 {
00832    COLORREF fg;
00833    LOGBRUSH logbrush;
00834    HPEN hpen;
00835    HBRUSH hbr;
00836 
00837    if (colormap_private == NULL) {
00838       /* A 1 bit deep bitmap */
00839       struct {
00840          WORD palVersion;
00841          WORD palNumEntries;
00842          PALETTEENTRY palPalEntry[2];
00843       } logpal;
00844       static HPALETTE hpal = NULL;
00845 
00846       if (hpal == NULL) {
00847          /* Create a b&w palette */
00848          logpal.palVersion = 0x300;
00849          logpal.palNumEntries = 2;
00850          logpal.palPalEntry[0].peRed =
00851              logpal.palPalEntry[0].peGreen =
00852              logpal.palPalEntry[0].peBlue = 0x00;
00853          logpal.palPalEntry[0].peFlags = 0x00;
00854          logpal.palPalEntry[1].peRed =
00855              logpal.palPalEntry[1].peGreen =
00856              logpal.palPalEntry[1].peBlue = 0xFF;
00857          logpal.palPalEntry[1].peFlags = 0x00;
00858          if ((hpal = CreatePalette((LOGPALETTE *) & logpal)) == NULL)
00859             WIN32_GDI_FAILED("CreatePalette");
00860       }
00861       SelectPalette(data->xgc, hpal, FALSE);
00862       RealizePalette(data->xgc);
00863       fg = PALETTEINDEX(data->foreground);
00864    } else if (colormap_private->xcolormap->rc_palette) {
00865       int k;
00866       if (SelectPalette(data->xgc, colormap_private->xcolormap->palette,
00867                         FALSE) == NULL)
00868          WIN32_GDI_FAILED("SelectPalette");
00869       if (TRUE || colormap_private->xcolormap->stale) {
00870          if ((k = RealizePalette(data->xgc)) == GDI_ERROR)
00871             WIN32_GDI_FAILED("RealizePalette");
00872          colormap_private->xcolormap->stale = FALSE;
00873       }
00874 #if 0
00875       g_print("Selected palette %#x for gc %#x, realized %d colors\n",
00876               colormap_private->xcolormap->palette, data->xgc, k);
00877 #endif
00878    }
00879 
00880    fg = gdk_colormap_color(colormap_private, data->foreground);
00881 
00882    if (SetTextColor(data->xgc, fg) == CLR_INVALID)
00883       WIN32_GDI_FAILED("SetTextColor");
00884 
00885    /* Create and select pen and brush. */
00886 
00887    logbrush.lbStyle = BS_SOLID;
00888    logbrush.lbColor = fg;
00889    logbrush.lbHatch = 0;
00890 
00891 // vo add
00892    if (data->pen_width <= 1) {
00893       data->pen_width = 1;
00894 
00895       if (IS_WIN_NT(windows_version)) {
00896          if ((data->pen_style & PS_STYLE_MASK) == PS_SOLID) {
00897             data->pen_style = PS_COSMETIC;
00898          }
00899       }
00900 
00901    } else {
00902       data->pen_style |= PS_GEOMETRIC;
00903    }
00904 
00905 // bb add
00906    if (IS_WIN_NT(windows_version) && (data->pen_style & PS_USERSTYLE)) {
00907       if ((hpen = ExtCreatePen(data->pen_style, data->pen_width,
00908                                &logbrush, data->luser_dash,
00909                                (CONST DWORD *) data->user_dash)) == NULL)
00910          WIN32_GDI_FAILED("ExtCreatePen");
00911    } else {
00912       if ((hpen = ExtCreatePen(data->pen_style, data->pen_width,
00913                                &logbrush, 0, NULL)) == NULL)
00914          WIN32_GDI_FAILED("ExtCreatePen");
00915       if (SetBkMode(data->xgc, TRANSPARENT) == 0)
00916          WIN32_GDI_FAILED("SetBkMode");
00917    }
00918    if (SelectObject(data->xgc, hpen) == NULL)
00919       WIN32_GDI_FAILED("SelectObject");
00920 
00921    switch (data->fill_style) {
00922    case GDK_OPAQUE_STIPPLED:
00923       if ((hbr =
00924            CreatePatternBrush(GDK_DRAWABLE_XID(data->stipple))) == NULL)
00925          WIN32_GDI_FAILED("CreatePatternBrush");
00926 
00927       SetBrushOrgEx(data->xgc, data->ts_x_origin, data->ts_y_origin, NULL);
00928 
00929       break;
00930 // bb add
00931    case GDK_STIPPLED:
00932       if ((hbr =
00933            CreatePatternBrush(GDK_DRAWABLE_XID(data->stipple))) == NULL)
00934          WIN32_GDI_FAILED("CreatePatternBrush");
00935 
00936       SetBrushOrgEx(data->xgc, data->ts_x_origin, data->ts_y_origin, NULL);
00937 
00938       break;
00939 // end bb add
00940    case GDK_SOLID:
00941    default:
00942       if ((hbr = CreateSolidBrush(fg)) == NULL)
00943          WIN32_GDI_FAILED("CreateSolidBrush");
00944       break;
00945    }
00946    if (SelectObject(data->xgc, hbr) == NULL)
00947       WIN32_GDI_FAILED("SelectObject");
00948 }
00949 
00950 void
00951 predraw_set_background(GdkGCWin32Data * data,
00952                        GdkColormapPrivateWin32 * colormap_private)
00953 {
00954    COLORREF bg = gdk_colormap_color(colormap_private, data->background);
00955 
00956    if (SetBkColor(data->xgc, bg) == CLR_INVALID)
00957       WIN32_GDI_FAILED("SetBkColor");
00958 }
00959 
00960 HDC
00961 gdk_gc_predraw(GdkDrawable * drawable,
00962                GdkGCPrivate * gc_private, GdkGCValuesMask usage)
00963 {
00964    GdkDrawablePrivate *drawable_private = (GdkDrawablePrivate *) drawable;
00965    GdkColormapPrivateWin32 *colormap_private =
00966        (GdkColormapPrivateWin32 *) drawable_private->colormap;
00967    GdkGCWin32Data *data = GDK_GC_WIN32DATA(gc_private);
00968 
00969    g_assert(data->xgc == NULL);
00970 
00971    data->hwnd = GDK_DRAWABLE_XID(drawable);
00972 
00973    if (GDK_DRAWABLE_TYPE(drawable) == GDK_DRAWABLE_PIXMAP) {
00974       if ((data->xgc = CreateCompatibleDC(NULL)) == NULL)
00975          WIN32_GDI_FAILED("CreateCompatibleDC");
00976 
00977       if ((data->saved_dc = SaveDC(data->xgc)) == 0)
00978          WIN32_GDI_FAILED("SaveDC");
00979 
00980       if (SelectObject(data->xgc, data->hwnd) == NULL)
00981          WIN32_GDI_FAILED("SelectObject");
00982    } else {
00983       if ((data->xgc = GetDC(data->hwnd)) == NULL)
00984          WIN32_GDI_FAILED("GetDC");
00985 
00986       if ((data->saved_dc = SaveDC(data->xgc)) == 0)
00987          WIN32_GDI_FAILED("SaveDC");
00988    }
00989 
00990    if (usage & GDK_GC_FOREGROUND)
00991       predraw_set_foreground(data, colormap_private);
00992 
00993    if ((usage & GDK_GC_BACKGROUND)
00994        && (data->values_mask & GDK_GC_BACKGROUND))
00995       predraw_set_background(data, colormap_private);
00996 
00997 // vo add
00998    if (!IS_WIN_NT(windows_version)) {
00999       if (SetBkMode(data->xgc, TRANSPARENT) == 0)
01000          WIN32_GDI_FAILED("SetBkMode");
01001    }
01002 
01003    if (usage & GDK_GC_FONT) {
01004       if (SetBkMode(data->xgc, TRANSPARENT) == 0)
01005          WIN32_GDI_FAILED("SetBkMode");
01006 
01007 //      if (SetTextAlign (data->xgc, TA_BASELINE) == GDI_ERROR)
01008       if (SetTextAlign(data->xgc, text_align) == GDI_ERROR)
01009          WIN32_GDI_FAILED("SetTextAlign");
01010    }
01011 
01012    if (data->rop2 != R2_COPYPEN)
01013       if (SetROP2(data->xgc, data->rop2) == 0)
01014          WIN32_GDI_FAILED("SetROP2");
01015 
01016    if ((data->values_mask & GDK_GC_CLIP_MASK)
01017        && data->clip_region != NULL) {
01018       if (data->
01019           values_mask & (GDK_GC_CLIP_X_ORIGIN | GDK_GC_CLIP_Y_ORIGIN))
01020          OffsetRgn(data->clip_region, data->clip_x_origin,
01021                    data->clip_y_origin);
01022       SelectClipRgn(data->xgc, data->clip_region);
01023    }
01024 
01025    return data->xgc;
01026 }
01027 
01028 void
01029 gdk_gc_postdraw(GdkDrawable * drawable,
01030                 GdkGCPrivate * gc_private, GdkGCValuesMask usage)
01031 {
01032    GdkDrawablePrivate *drawable_private = (GdkDrawablePrivate *) drawable;
01033    GdkColormapPrivateWin32 *colormap_private =
01034        (GdkColormapPrivateWin32 *) drawable_private->colormap;
01035    GdkGCWin32Data *data = GDK_GC_WIN32DATA(gc_private);
01036    HGDIOBJ hpen = NULL;
01037    HGDIOBJ hbr = NULL;
01038 
01039    if (usage & GDK_GC_FOREGROUND) {
01040       if ((hpen = GetCurrentObject(data->xgc, OBJ_PEN)) == NULL)
01041          WIN32_GDI_FAILED("GetCurrentObject");
01042 
01043       if ((hbr = GetCurrentObject(data->xgc, OBJ_BRUSH)) == NULL)
01044          WIN32_GDI_FAILED("GetCurrentObject");
01045    }
01046 
01047    if (!RestoreDC(data->xgc, data->saved_dc))
01048       WIN32_GDI_FAILED("RestoreDC");
01049 #if 0
01050    if (colormap_private != NULL
01051        && colormap_private->xcolormap->rc_palette
01052        && colormap_private->xcolormap->stale) {
01053       SelectPalette(data->xgc, GetStockObject(DEFAULT_PALETTE), FALSE);
01054       if (!UnrealizeObject(colormap_private->xcolormap->palette))
01055          WIN32_GDI_FAILED("UnrealizeObject");
01056    }
01057 #endif
01058    if (GDK_DRAWABLE_TYPE(drawable) == GDK_DRAWABLE_PIXMAP) {
01059       if (!DeleteDC(data->xgc))
01060          WIN32_GDI_FAILED("DeleteDC");
01061    } else {
01062       ReleaseDC(data->hwnd, data->xgc);
01063    }
01064 
01065    if (hpen != NULL)
01066       if (!DeleteObject(hpen))
01067          WIN32_GDI_FAILED("DeleteObject");
01068 
01069    if (hbr != NULL)
01070       if (!DeleteObject(hbr))
01071          WIN32_GDI_FAILED("DeleteObject");
01072 
01073    if ((data->values_mask & GDK_GC_CLIP_MASK)
01074        && data->clip_region != NULL
01075        && (data->
01076            values_mask & (GDK_GC_CLIP_X_ORIGIN | GDK_GC_CLIP_Y_ORIGIN)))
01077       OffsetRgn(data->clip_region, -data->clip_x_origin,
01078                 -data->clip_y_origin);
01079    data->xgc = NULL;
01080 }
01081 
01082 HDC
01083 gdk_win32_hdc_get(GdkDrawable * drawable,
01084                   GdkGC * gc, GdkGCValuesMask usage)
01085 {
01086    return gdk_gc_predraw(drawable, (GdkGCPrivate *) gc, usage);
01087 }
01088 
01089 void
01090 gdk_win32_hdc_release(GdkDrawable * drawable,
01091                       GdkGC * gc, GdkGCValuesMask usage)
01092 {
01093    gdk_gc_postdraw(drawable, (GdkGCPrivate *) gc, usage);
01094 }
01095 
01096 /* This function originally from Jean-Edouard Lachand-Robert, and
01097  * available at www.codeguru.com. Simplified for our needs, now
01098  * handles just one-bit deep bitmaps (in Window parlance, ie those
01099  * that GDK calls bitmaps (and not pixmaps), with zero pixels being
01100  * transparent.
01101  */
01102 
01103 /*
01104  *  BitmapToRegion :  Create a region from the "non-transparent" pixels of
01105  *  a bitmap
01106  *  Author :      Jean-Edouard Lachand-Robert
01107  *  (http://www.geocities.com/Paris/LeftBank/1160/resume.htm), June 1998.
01108  */
01109 
01110 HRGN BitmapToRegion(HBITMAP hBmp)
01111 {
01112    HRGN hRgn = NULL;
01113    HDC hMemDC;
01114    BITMAP bm;
01115 
01116    struct {
01117       BITMAPINFOHEADER bmiHeader;
01118 #if 1
01119       WORD bmiColors[2];
01120 #else
01121       RGBQUAD bmiColors[2];
01122 #endif
01123    } bmi;
01124    VOID *pbits8;
01125    HBITMAP hbm8;
01126    struct {
01127       WORD palVersion;
01128       WORD palNumEntries;
01129       PALETTEENTRY palPalEntry[2];
01130    } logpal;
01131    static HPALETTE bwPalette = NULL;
01132 
01133    HBITMAP holdBmp;
01134    HDC hDC;
01135 
01136    BITMAP bm8;
01137    HBITMAP holdBmp2;
01138    DWORD maxRects;
01139    RGNDATA *pData;
01140    BYTE *p8;
01141    int x, y;
01142    HRGN h;
01143 
01144    /* Create a B&W palette */
01145    if (bwPalette == NULL) {
01146       /* Create a b&w palette */
01147       logpal.palVersion = 0x300;
01148       logpal.palNumEntries = 2;
01149       logpal.palPalEntry[0].peRed =
01150           logpal.palPalEntry[0].peGreen = logpal.palPalEntry[0].peBlue = 0;
01151       logpal.palPalEntry[0].peFlags = 0;
01152       logpal.palPalEntry[1].peRed =
01153           logpal.palPalEntry[1].peGreen =
01154           logpal.palPalEntry[1].peBlue = 0xFF;
01155       logpal.palPalEntry[1].peFlags = 0;
01156       if ((bwPalette = CreatePalette((LOGPALETTE *) & logpal)) == NULL)
01157          WIN32_GDI_FAILED("CreatePalette");
01158    }
01159 
01160    /* Create a memory DC inside which we will scan the bitmap content */
01161    hMemDC = CreateCompatibleDC(NULL);
01162    if (!hMemDC) {
01163       WIN32_GDI_FAILED("CreateCompatibleDC");
01164       return NULL;
01165    }
01166 
01167    SelectPalette(hMemDC, bwPalette, FALSE);
01168    RealizePalette(hMemDC);
01169 
01170    /* Get bitmap size */
01171    GetObject(hBmp, sizeof(bm), &bm);
01172 
01173    /* Create a 8 bits depth bitmap and select it into the memory DC */
01174    bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
01175    bmi.bmiHeader.biWidth = bm.bmWidth;
01176    bmi.bmiHeader.biHeight = bm.bmHeight;
01177    bmi.bmiHeader.biPlanes = 1;
01178    bmi.bmiHeader.biBitCount = 8;
01179    bmi.bmiHeader.biCompression = BI_RGB;
01180    bmi.bmiHeader.biSizeImage = 0;
01181    bmi.bmiHeader.biXPelsPerMeter = 0;
01182    bmi.bmiHeader.biYPelsPerMeter = 0;
01183    bmi.bmiHeader.biClrUsed = 2;
01184    bmi.bmiHeader.biClrImportant = 2;
01185 #if 1
01186    bmi.bmiColors[0] = 0;
01187    bmi.bmiColors[1] = 1;
01188    hbm8 = CreateDIBSection(hMemDC, (BITMAPINFO *) & bmi,
01189                            DIB_PAL_COLORS, &pbits8, NULL, 0);
01190 #else
01191    bmi.bmiColors[0].rgbBlue =
01192        bmi.bmiColors[0].rgbGreen = bmi.bmiColors[0].rgbRed = 0x00;
01193    bmi.bmiColors[0].rgbReserved = 0x00;
01194 
01195    bmi.bmiColors[1].rgbBlue =
01196        bmi.bmiColors[1].rgbGreen = bmi.bmiColors[1].rgbRed = 0xFF;
01197    bmi.bmiColors[0].rgbReserved = 0x00;
01198 
01199    hbm8 = CreateDIBSection(hMemDC, (BITMAPINFO *) & bmi,
01200                            DIB_RGB_COLORS, &pbits8, NULL, 0);
01201 #endif
01202    if (!hbm8) {
01203       WIN32_GDI_FAILED("CreateDIBSection");
01204       DeleteDC(hMemDC);
01205       return NULL;
01206    }
01207 
01208    holdBmp = (HBITMAP) SelectObject(hMemDC, hbm8);
01209 
01210    /* Create a DC just to copy the bitmap into the memory DC */
01211    hDC = CreateCompatibleDC(hMemDC);
01212    if (!hDC) {
01213       WIN32_GDI_FAILED("CreateCompatibleDC #2");
01214       SelectObject(hMemDC, holdBmp);
01215       DeleteObject(hbm8);
01216       DeleteDC(hMemDC);
01217       return NULL;
01218    }
01219 
01220    /* Get how many bytes per row we have for the bitmap bits */
01221    GetObject(hbm8, sizeof(bm8), &bm8);
01222 
01223    /* Hans Breuer found a fix to the long-standing erroneous behaviour
01224     * on NT 4.0: There seems to be a bug in Win NT 4.0 GDI: scanlines
01225     * in bitmaps are dword aligned on both Win95 and NT. In the case of
01226     * a bitmap with 22 bytes worth of width, GetObject above returns
01227     * with bmWidth == 22. On Win95 bmWidthBytes == 24, as it should be,
01228     * but on NT is it 22. We need to correct this here.
01229     */
01230    bm8.bmWidthBytes = (((bm8.bmWidthBytes - 1) / 4) + 1) * 4;   /* dword aligned!! */
01231 
01232    /* Copy the bitmap into the memory DC */
01233    holdBmp2 = (HBITMAP) SelectObject(hDC, hBmp);
01234 
01235    if (!BitBlt(hMemDC, 0, 0, bm.bmWidth, bm.bmHeight, hDC, 0, 0, SRCCOPY)) {
01236       WIN32_GDI_FAILED("BitBlt");
01237       SelectObject(hDC, holdBmp2);
01238       SelectObject(hMemDC, holdBmp);
01239       DeleteObject(hbm8);
01240       DeleteDC(hMemDC);
01241       return NULL;
01242    }
01243    SelectObject(hDC, holdBmp2);
01244    DeleteDC(hDC);
01245 
01246    /* For better performances, we will use the ExtCreateRegion()
01247     * function to create the region. This function take a RGNDATA
01248     * structure on entry. We will add rectangles by amount of
01249     * ALLOC_UNIT number in this structure.
01250     */
01251 #define ALLOC_UNIT  200
01252    maxRects = ALLOC_UNIT;
01253 
01254    pData = g_malloc(sizeof(RGNDATAHEADER) + (sizeof(RECT) * maxRects));
01255    memset(pData, 0, sizeof(RGNDATAHEADER) + (sizeof(RECT) * maxRects));
01256    pData->rdh.dwSize = sizeof(RGNDATAHEADER);
01257    pData->rdh.iType = RDH_RECTANGLES;
01258    pData->rdh.nCount = pData->rdh.nRgnSize = 0;
01259    SetRect(&pData->rdh.rcBound, MAXLONG, MAXLONG, 0, 0);
01260 
01261    /* Scan each bitmap from bottom to top (the bitmap is inverted vertically) */
01262    p8 = (BYTE *) pbits8 + (bm8.bmHeight - 1) * bm8.bmWidthBytes;
01263    for (y = 0; y < bm.bmHeight; y++) {
01264       /* Scan each bitmap row from left to right */
01265       for (x = 0; x < bm.bmWidth; x++) {
01266          /* Search for a continuous range of "non transparent pixels" */
01267          int x0 = x;
01268          BYTE *p = p8 + x;
01269          while (x < bm.bmWidth) {
01270             if (*p == 0)
01271                /* This pixel is "transparent" */
01272                break;
01273             p++;
01274             x++;
01275          }
01276 
01277          if (x > x0) {
01278             RECT *pr;
01279             /* Add the pixels (x0, y) to (x, y+1) as a new rectangle
01280              * in the region
01281              */
01282             if (pData->rdh.nCount >= maxRects) {
01283                maxRects += ALLOC_UNIT;
01284                pData = g_realloc(pData, sizeof(RGNDATAHEADER)
01285                                  + (sizeof(RECT) * maxRects));
01286             }
01287             pr = (RECT *) & pData->Buffer;
01288             SetRect(&pr[pData->rdh.nCount], x0, y, x, y + 1);
01289             if (x0 < pData->rdh.rcBound.left)
01290                pData->rdh.rcBound.left = x0;
01291             if (y < pData->rdh.rcBound.top)
01292                pData->rdh.rcBound.top = y;
01293             if (x > pData->rdh.rcBound.right)
01294                pData->rdh.rcBound.right = x;
01295             if (y + 1 > pData->rdh.rcBound.bottom)
01296                pData->rdh.rcBound.bottom = y + 1;
01297             pData->rdh.nCount++;
01298 
01299             /* On Windows98, ExtCreateRegion() may fail if the
01300              * number of rectangles is too large (ie: >
01301              * 4000). Therefore, we have to create the region by
01302              * multiple steps.
01303              */
01304             if (pData->rdh.nCount == 2000) {
01305                HRGN h = ExtCreateRegion(NULL,
01306                                    sizeof(RGNDATAHEADER) +
01307                                    (sizeof(RECT) * maxRects), pData);
01308                if (hRgn) {
01309                   CombineRgn(hRgn, hRgn, h, RGN_OR);
01310                   DeleteObject(h);
01311                } else
01312                   hRgn = h;
01313                pData->rdh.nCount = 0;
01314                SetRect(&pData->rdh.rcBound, MAXLONG, MAXLONG, 0, 0);
01315             }
01316          }
01317       }
01318 
01319       /* Go to next row (remember, the bitmap is inverted vertically) */
01320       p8 -= bm8.bmWidthBytes;
01321    }
01322 
01323    /* Create or extend the region with the remaining rectangles */
01324    h = ExtCreateRegion(NULL, sizeof(RGNDATAHEADER)
01325                        + (sizeof(RECT) * maxRects), pData);
01326    if (hRgn) {
01327       CombineRgn(hRgn, hRgn, h, RGN_OR);
01328       DeleteObject(h);
01329    } else
01330       hRgn = h;
01331 
01332    /* Clean up */
01333    g_free(pData);
01334    SelectObject(hMemDC, holdBmp);
01335    DeleteObject(hbm8);
01336    DeleteDC(hMemDC);
01337 
01338    return hRgn;
01339 }
01340 
01341 #ifdef G_ENABLE_DEBUG
01342 
01343 gchar *gdk_win32_cap_style_to_string(GdkCapStyle cap_style)
01344 {
01345    switch (cap_style) {
01346 #define CASE(x) case x: return #x + strlen ("GDK_CAP_")
01347       CASE(GDK_CAP_NOT_LAST);
01348       CASE(GDK_CAP_BUTT);
01349       CASE(GDK_CAP_ROUND);
01350       CASE(GDK_CAP_PROJECTING);
01351 #undef CASE
01352    default:
01353       return ("illegal GdkCapStyle value");
01354    }
01355    /* NOTREACHED */
01356    return NULL;
01357 }
01358 
01359 gchar *gdk_win32_fill_style_to_string(GdkFill fill)
01360 {
01361    switch (fill) {
01362 #define CASE(x) case x: return #x + strlen ("GDK_")
01363       CASE(GDK_SOLID);
01364       CASE(GDK_TILED);
01365       CASE(GDK_STIPPLED);
01366       CASE(GDK_OPAQUE_STIPPLED);
01367 #undef CASE
01368    default:
01369       return ("illegal GdkFill value");
01370    }
01371    /* NOTREACHED */
01372    return NULL;
01373 }
01374 
01375 gchar *gdk_win32_function_to_string(GdkFunction function)
01376 {
01377    switch (function) {
01378 #define CASE(x) case x: return #x + strlen ("GDK_")
01379       CASE(GDK_COPY);
01380       CASE(GDK_INVERT);
01381       CASE(GDK_XOR);
01382       CASE(GDK_CLEAR);
01383       CASE(GDK_AND);
01384       CASE(GDK_AND_REVERSE);
01385       CASE(GDK_AND_INVERT);
01386       CASE(GDK_NOOP);
01387       CASE(GDK_OR);
01388       CASE(GDK_EQUIV);
01389       CASE(GDK_OR_REVERSE);
01390       CASE(GDK_COPY_INVERT);
01391       CASE(GDK_OR_INVERT);
01392       CASE(GDK_NAND);
01393       CASE(GDK_SET);
01394 #undef CASE
01395    default:
01396       return ("illegal GdkFunction value");
01397    }
01398    /* NOTREACHED */
01399    return NULL;
01400 }
01401 
01402 gchar *gdk_win32_join_style_to_string(GdkJoinStyle join_style)
01403 {
01404    switch (join_style) {
01405 #define CASE(x) case x: return #x + strlen ("GDK_JOIN_")
01406       CASE(GDK_JOIN_MITER);
01407       CASE(GDK_JOIN_ROUND);
01408       CASE(GDK_JOIN_BEVEL);
01409 #undef CASE
01410    default:
01411       return ("illegal GdkJoinStyle value");
01412    }
01413    /* NOTREACHED */
01414    return NULL;
01415 }
01416 
01417 gchar *gdk_win32_line_style_to_string(GdkLineStyle line_style)
01418 {
01419    switch (line_style) {
01420 #define CASE(x) case x: return #x + strlen ("GDK_LINE_")
01421       CASE(GDK_LINE_SOLID);
01422       CASE(GDK_LINE_ON_OFF_DASH);
01423       CASE(GDK_LINE_DOUBLE_DASH);
01424 #undef CASE
01425    default:
01426       return ("illegal GdkLineStyle value");
01427    }
01428    /* NOTREACHED */
01429    return NULL;
01430 }
01431 #endif

Generated on Tue Jul 5 14:14:40 2011 for ROOT_528-00b_version by  doxygen 1.5.1