gdkdrawable-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 <math.h>
00030 #include <glib.h>
00031 
00032 #ifndef G_PI
00033 #define G_PI 3.14159265358979323846
00034 #endif
00035 
00036 #define GDKBIT(n)       (1 << (n))
00037 #define GDKSETBIT(n,i)  ((n) |= GDKBIT(i))
00038 #define GDKCLRBIT(n,i)  ((n) &= ~GDKBIT(i))
00039 #define GDKTESTBIT(n,i) ((gboolean)(((n) & GDKBIT(i)) != 0))
00040 
00041 #include "gdkdrawable.h"
00042 #include "gdkprivate.h"
00043 #include "gdkwindow.h"
00044 #include "gdkwin32.h"
00045 
00046 static void gdk_win32_drawable_destroy(GdkDrawable * drawable);
00047 
00048  void gdk_win32_draw_rectangle(GdkDrawable * drawable,
00049                                      GdkGC * gc,
00050                                      gint filled,
00051                                      gint x,
00052                                      gint y, gint width, gint height);
00053  void gdk_win32_draw_arc(GdkDrawable * drawable,
00054                                GdkGC * gc,
00055                                gint filled,
00056                                gint x,
00057                                gint y,
00058                                gint width,
00059                                gint height, gint angle1, gint angle2);
00060  void gdk_win32_draw_polygon(GdkDrawable * drawable,
00061                                    GdkGC * gc,
00062                                    gint filled,
00063                                    GdkPoint * points, gint npoints);
00064  void gdk_win32_draw_text(GdkDrawable * drawable,
00065                                 GdkFont * font,
00066                                 GdkGC * gc,
00067                                 gint x,
00068                                 gint y,
00069                                 const gchar * text, gint text_length);
00070 static void gdk_win32_draw_text_wc(GdkDrawable * drawable,
00071                                    GdkFont * font,
00072                                    GdkGC * gc,
00073                                    gint x,
00074                                    gint y,
00075                                    const GdkWChar * text,
00076                                    gint text_length);
00077 static void gdk_win32_draw_drawable(GdkDrawable * drawable,
00078                                     GdkGC * gc,
00079                                     GdkPixmap * src,
00080                                     gint xsrc,
00081                                     gint ysrc,
00082                                     gint xdest,
00083                                     gint ydest, gint width, gint height);
00084  void gdk_win32_draw_points(GdkDrawable * drawable,
00085                                   GdkGC * gc,
00086                                   GdkPoint * points, gint npoints);
00087  void gdk_win32_draw_segments(GdkDrawable * drawable,
00088                                     GdkGC * gc,
00089                                     GdkSegment * segs, gint nsegs);
00090  void gdk_win32_draw_lines(GdkDrawable * drawable,
00091                                  GdkGC * gc,
00092                                  GdkPoint * points, gint npoints);
00093 
00094 GdkDrawableClass _gdk_win32_drawable_class = {
00095    gdk_win32_drawable_destroy,
00096    _gdk_win32_gc_new,
00097    gdk_win32_draw_rectangle,
00098    gdk_win32_draw_arc,
00099    gdk_win32_draw_polygon,
00100    gdk_win32_draw_text,
00101    gdk_win32_draw_text_wc,
00102    gdk_win32_draw_drawable,
00103    gdk_win32_draw_points,
00104    gdk_win32_draw_segments,
00105    gdk_win32_draw_lines
00106 };
00107 
00108 /*****************************************************
00109  * Win32 specific implementations of generic functions *
00110  *****************************************************/
00111 
00112 GdkColormap *gdk_drawable_get_colormap(GdkDrawable * drawable)
00113 {
00114    GdkDrawablePrivate *drawable_private;
00115 
00116    g_return_val_if_fail(drawable != NULL, NULL);
00117    drawable_private = (GdkDrawablePrivate *) drawable;
00118 
00119    if (!GDK_DRAWABLE_DESTROYED(drawable)) {
00120       if (drawable_private->colormap == NULL)
00121          return gdk_colormap_get_system();      /* XXX ??? */
00122       else
00123          return drawable_private->colormap;
00124    }
00125 
00126    return NULL;
00127 }
00128 
00129 void
00130 gdk_drawable_set_colormap(GdkDrawable * drawable, GdkColormap * colormap)
00131 {
00132    GdkDrawablePrivate *drawable_private;
00133    GdkColormapPrivateWin32 *colormap_private;
00134 
00135    g_return_if_fail(drawable != NULL);
00136    g_return_if_fail(colormap != NULL);
00137 
00138    drawable_private = (GdkDrawablePrivate *) drawable;
00139    colormap_private = (GdkColormapPrivateWin32 *) colormap;
00140 
00141    if (!GDK_DRAWABLE_DESTROYED(drawable)) {
00142       if (GDK_IS_WINDOW(drawable)) {
00143          g_return_if_fail(colormap_private->base.visual !=
00144                           ((GdkColormapPrivate *) (drawable_private->
00145                                                    colormap))->visual);
00146          /* XXX ??? */
00147          GDK_NOTE(MISC, g_print("gdk_drawable_set_colormap: %#x %#x\n",
00148                                 GDK_DRAWABLE_XID(drawable),
00149                                 colormap_private->xcolormap));
00150       }
00151       if (drawable_private->colormap)
00152          gdk_colormap_unref(drawable_private->colormap);
00153       drawable_private->colormap = colormap;
00154       gdk_colormap_ref(drawable_private->colormap);
00155 
00156       if (GDK_IS_WINDOW(drawable)
00157           && drawable_private->window_type != GDK_WINDOW_TOPLEVEL)
00158          gdk_window_add_colormap_windows(drawable);
00159    }
00160 }
00161 
00162 /* Drawing
00163  */
00164 static void gdk_win32_drawable_destroy(GdkDrawable * drawable)
00165 {
00166    g_assert_not_reached();
00167 }
00168 
00169  void
00170 gdk_win32_draw_rectangle(GdkDrawable * drawable,
00171                          GdkGC * gc,
00172                          gint filled,
00173                          gint x, gint y, gint width, gint height)
00174 {
00175    GdkGCPrivate *gc_private = (GdkGCPrivate *) gc;
00176    GdkGCWin32Data *gc_data = GDK_GC_WIN32DATA(gc_private);
00177    HDC hdc;
00178    HGDIOBJ oldpen_or_brush;
00179    POINT pts[4];
00180    HBRUSH stipple;
00181    gboolean ok = TRUE;
00182 
00183    GDK_NOTE(MISC,
00184             g_print("gdk_win32_draw_rectangle: %#x (%d) %s%dx%d@+%d+%d\n",
00185                     GDK_DRAWABLE_XID(drawable), gc_private,
00186                     (filled ? "fill " : ""), width, height, x, y));
00187 
00188    hdc = gdk_gc_predraw(drawable, gc_private,
00189                         GDK_GC_FOREGROUND | GDK_GC_BACKGROUND);
00190 
00191    if (gc_data->fill_style == GDK_OPAQUE_STIPPLED) {
00192       if (!BeginPath(hdc))
00193          WIN32_GDI_FAILED("BeginPath"), ok = FALSE;
00194 
00195       /* Win9x doesn't support Rectangle calls in a path,
00196        * thus use Polyline.
00197        */
00198 
00199       pts[0].x = x;
00200       pts[0].y = y;
00201       pts[1].x = x + width + 1;
00202       pts[1].y = y;
00203       pts[2].x = x + width + 1;
00204       pts[2].y = y + height + 1;
00205       pts[3].x = x;
00206       pts[3].y = y + height + 1;
00207 
00208       if (ok)
00209          MoveToEx(hdc, x, y, NULL);
00210 
00211       if (ok && !Polyline(hdc, pts, 4))
00212          WIN32_GDI_FAILED("Polyline"), ok = FALSE;
00213 
00214       if (ok && !CloseFigure(hdc))
00215          WIN32_GDI_FAILED("CloseFigure"), ok = FALSE;
00216 
00217       if (ok && !EndPath(hdc))
00218          WIN32_GDI_FAILED("EndPath"), ok = FALSE;
00219 
00220       if (ok && !filled)
00221          if (!WidenPath(hdc))
00222             WIN32_GDI_FAILED("WidenPath"), ok = FALSE;
00223 
00224       if (ok && !FillPath(hdc))
00225          WIN32_GDI_FAILED("FillPath"), ok = FALSE;
00226    }
00227 #if 0
00228    else if (gc_data->fill_style == GDK_STIPPLED) {
00229       HDC memdc = CreateCompatibleDC(hdc);
00230       HBITMAP hbm = CreateCompatibleBitmap(hdc, width, height);
00231       HBRUSH hbr = CreateSolidBrush(gc_data->
00232                                     stipple =
00233                                     CreatePatternBrush(GDK_DRAWABLE_XID
00234                                                        (gc_data->stipple));
00235                                     SetBrushOrgEx(hdc,
00236                                                   gc_data->ts_x_origin,
00237                                                   gc_data->ts_y_origin);
00238                                     oldpen_or_brush =
00239                                     Select SelectObject(memdc, hbm);
00240                                     rect.left = rect.top = 0;
00241                                     rect.right = width;
00242                                     rect.bottom = height;
00243                                     FillRect(memdc, &rect, hbr);
00244                                     if (!BeginPath(hdc))
00245                                     WIN32_GDI_FAILED("BeginPath"), ok =
00246                                     FALSE;
00247                                     /* Win9x doesn't support Rectangle calls in a path,
00248                                      * thus use Polyline.
00249                                      */
00250                                     pts[0].x = x;
00251                                     pts[0].y = y;
00252                                     pts[1].x = x + width + 1;
00253                                     pts[1].y = y;
00254                                     pts[2].x = x + width + 1;
00255                                     pts[2].y = y + height + 1;
00256                                     pts[3].x = x;
00257                                     pts[3].y = y + height + 1; if (ok)
00258                                     MoveToEx(hdc, x, y, NULL);
00259                                     if (ok && !Polyline(hdc, pts, 4))
00260                                     WIN32_GDI_FAILED("Polyline"), ok =
00261                                     FALSE; if (ok && !CloseFigure(hdc))
00262                                     WIN32_GDI_FAILED("CloseFigure"), ok =
00263                                     FALSE; if (ok && !EndPath(hdc))
00264                                     WIN32_GDI_FAILED("EndPath"), ok =
00265                                     FALSE; if (ok && !filled)
00266                                     if (!WidenPath(hdc))
00267                                     WIN32_GDI_FAILED("WidenPath"), ok =
00268                                     FALSE; if (ok && !FillPath(hdc))
00269                                     WIN32_GDI_FAILED("FillPath"), ok =
00270                                     FALSE;}
00271 #else                           // bb add
00272    else if (gc_data->fill_style == GDK_STIPPLED) {
00273       RECT rect;
00274       HBRUSH hbr = CreatePatternBrush(GDK_DRAWABLE_XID(gc_data->stipple));
00275       SetBkMode(hdc, TRANSPARENT);
00276       SetROP2(hdc, R2_MASKPEN);
00277 //        SetROP2(hdc,R2_MERGEPEN);
00278       oldpen_or_brush = SelectObject(hdc, hbr);
00279       rect.left = rect.top = 0;
00280       rect.right = width;
00281       rect.bottom = height;
00282       if (!BeginPath(hdc))
00283          WIN32_GDI_FAILED("BeginPath"), ok = FALSE;
00284       // Win9x doesn't support Rectangle calls in a path,
00285       // thus use Polyline.
00286 
00287       pts[0].x = x;
00288       pts[0].y = y;
00289       pts[1].x = x + width + 1;
00290       pts[1].y = y;
00291       pts[2].x = x + width + 1;
00292       pts[2].y = y + height + 1;
00293       pts[3].x = x;
00294       pts[3].y = y + height + 1;
00295 
00296       if (ok)
00297          MoveToEx(hdc, x, y, NULL);
00298 
00299       if (ok && !Polyline(hdc, pts, 4))
00300          WIN32_GDI_FAILED("Polyline"), ok = FALSE;
00301 
00302       if (ok && !CloseFigure(hdc))
00303          WIN32_GDI_FAILED("CloseFigure"), ok = FALSE;
00304 
00305       if (ok && !EndPath(hdc))
00306          WIN32_GDI_FAILED("EndPath"), ok = FALSE;
00307 
00308       if (ok && !filled)
00309          if (!WidenPath(hdc))
00310             WIN32_GDI_FAILED("WidenPath"), ok = FALSE;
00311 
00312       if (ok && !FillPath(hdc))
00313          WIN32_GDI_FAILED("FillPath"), ok = FALSE;
00314       SelectObject(hdc, oldpen_or_brush);
00315       DeleteObject(hbr);
00316    }
00317 // end bb add
00318 #endif
00319    else {
00320       if (filled)
00321          oldpen_or_brush = SelectObject(hdc, GetStockObject(NULL_PEN));
00322       else
00323          oldpen_or_brush = SelectObject(hdc, GetStockObject(HOLLOW_BRUSH));
00324 
00325       if (!Rectangle(hdc, x, y, x + width + 1, y + height + 1))
00326          WIN32_GDI_FAILED("Rectangle");
00327 
00328       SelectObject(hdc, oldpen_or_brush);
00329    }
00330 
00331    gdk_gc_postdraw(drawable, gc_private,
00332                    GDK_GC_FOREGROUND | GDK_GC_BACKGROUND);
00333 }
00334 
00335  void
00336 gdk_win32_draw_arc(GdkDrawable * drawable,
00337                    GdkGC * gc,
00338                    gint filled,
00339                    gint x,
00340                    gint y,
00341                    gint width, gint height, gint angle1, gint angle2)
00342 {
00343    GdkGCPrivate *gc_private;
00344    HDC hdc;
00345    int nXStartArc, nYStartArc, nXEndArc, nYEndArc;
00346 
00347    gc_private = (GdkGCPrivate *) gc;
00348 
00349    GDK_NOTE(MISC, g_print("gdk_draw_arc: %#x  %d,%d,%d,%d  %d %d\n",
00350                           GDK_DRAWABLE_XID(drawable),
00351                           x, y, width, height, angle1, angle2));
00352 
00353    /* Seems that drawing arcs with width or height <= 2 fails, at least
00354     * with my TNT card.
00355     */
00356    if (width > 2 && height > 2 && angle2 != 0) {
00357       hdc = gdk_gc_predraw(drawable, gc_private,
00358                            GDK_GC_FOREGROUND | GDK_GC_BACKGROUND);
00359 
00360       if (angle2 >= 360 * 64) {
00361          nXStartArc = nYStartArc = nXEndArc = nYEndArc = 0;
00362       } else if (angle2 > 0) {
00363          /* The 100. is just an arbitrary value */
00364          nXStartArc =
00365              x + width / 2 + 100. * cos(angle1 / 64. * 2. * G_PI / 360.);
00366          nYStartArc =
00367              y + height / 2 + -100. * sin(angle1 / 64. * 2. * G_PI / 360.);
00368          nXEndArc =
00369              x + width / 2 +
00370              100. * cos((angle1 + angle2) / 64. * 2. * G_PI / 360.);
00371          nYEndArc =
00372              y + height / 2 +
00373              -100. * sin((angle1 + angle2) / 64. * 2. * G_PI / 360.);
00374       } else {
00375          nXEndArc =
00376              x + width / 2 + 100. * cos(angle1 / 64. * 2. * G_PI / 360.);
00377          nYEndArc =
00378              y + height / 2 + -100. * sin(angle1 / 64. * 2. * G_PI / 360.);
00379          nXStartArc =
00380              x + width / 2 +
00381              100. * cos((angle1 + angle2) / 64. * 2. * G_PI / 360.);
00382          nYStartArc =
00383              y + height / 2 +
00384              -100. * sin((angle1 + angle2) / 64. * 2. * G_PI / 360.);
00385       }
00386 
00387       /* GDK_OPAQUE_STIPPLED arcs not implemented. */
00388 
00389       if (filled) {
00390          GDK_NOTE(MISC, g_print("...Pie(hdc,%d,%d,%d,%d,%d,%d,%d,%d)\n",
00391                                 x, y, x + width, y + height,
00392                                 nXStartArc, nYStartArc,
00393                                 nXEndArc, nYEndArc));
00394          if (!Pie(hdc, x, y, x + width, y + height,
00395                   nXStartArc, nYStartArc, nXEndArc, nYEndArc))
00396             WIN32_GDI_FAILED("Pie");
00397       } else {
00398          GDK_NOTE(MISC, g_print("...Arc(hdc,%d,%d,%d,%d,%d,%d,%d,%d)\n",
00399                                 x, y, x + width, y + height,
00400                                 nXStartArc, nYStartArc,
00401                                 nXEndArc, nYEndArc));
00402          if (!Arc(hdc, x, y, x + width, y + height,
00403                   nXStartArc, nYStartArc, nXEndArc, nYEndArc))
00404             WIN32_GDI_FAILED("Arc");
00405       }
00406       gdk_gc_postdraw(drawable, gc_private,
00407                       GDK_GC_FOREGROUND | GDK_GC_BACKGROUND);
00408    }
00409 }
00410 
00411  void
00412 gdk_win32_draw_polygon(GdkDrawable * drawable,
00413                        GdkGC * gc,
00414                        gint filled, GdkPoint * points, gint npoints)
00415 {
00416    GdkGCPrivate *gc_private = (GdkGCPrivate *) gc;
00417    GdkGCWin32Data *gc_data = GDK_GC_WIN32DATA(gc_private);
00418    HGDIOBJ oldpen_or_brush;
00419    HDC hdc;
00420    POINT *pts;
00421    gboolean ok = TRUE;
00422    int i;
00423 
00424    GDK_NOTE(MISC, g_print("gdk_win32_draw_polygon: %#x (%d) %d\n",
00425                           GDK_DRAWABLE_XID(drawable), gc_private,
00426                           npoints));
00427 
00428    if (npoints < 2)
00429       return;
00430 
00431    hdc = gdk_gc_predraw(drawable, gc_private,
00432                         GDK_GC_FOREGROUND | GDK_GC_BACKGROUND);
00433    pts = g_new(POINT, npoints + 1);
00434 
00435    for (i = 0; i < npoints; i++) {
00436       pts[i].x = points[i].x;
00437       pts[i].y = points[i].y;
00438    }
00439 
00440    if (gc_data->fill_style == GDK_OPAQUE_STIPPLED) {
00441       if (!BeginPath(hdc))
00442          WIN32_GDI_FAILED("BeginPath"), ok = FALSE;
00443 
00444       MoveToEx(hdc, points[0].x, points[0].y, NULL);
00445 
00446       if (pts[0].x == pts[npoints - 1].x && pts[0].y == pts[npoints - 1].y)
00447          npoints--;
00448 
00449       if (ok && !Polyline(hdc, pts, npoints))
00450          WIN32_GDI_FAILED("Polyline"), ok = FALSE;
00451 
00452       if (ok && !CloseFigure(hdc))
00453          WIN32_GDI_FAILED("CloseFigure"), ok = FALSE;
00454 
00455       if (ok && !EndPath(hdc))
00456          WIN32_GDI_FAILED("EndPath"), ok = FALSE;
00457 
00458       if (ok && !filled)
00459          if (!WidenPath(hdc))
00460             WIN32_GDI_FAILED("WidenPath"), ok = FALSE;
00461 
00462       if (ok && !FillPath(hdc))
00463          WIN32_GDI_FAILED("FillPath"), ok = FALSE;
00464    }
00465    else if (gc_data->fill_style == GDK_STIPPLED) {
00466       HBRUSH hbr = CreatePatternBrush(GDK_DRAWABLE_XID(gc_data->stipple));
00467       SetBkMode(hdc, TRANSPARENT);
00468       SetROP2(hdc, R2_MASKPEN);
00469       oldpen_or_brush = SelectObject(hdc, hbr);
00470 
00471       if (!BeginPath(hdc))
00472          WIN32_GDI_FAILED("BeginPath"), ok = FALSE;
00473 
00474       MoveToEx(hdc, points[0].x, points[0].y, NULL);
00475 
00476       if (pts[0].x == pts[npoints - 1].x && pts[0].y == pts[npoints - 1].y)
00477          npoints--;
00478 
00479       if (ok && !Polyline(hdc, pts, npoints))
00480          WIN32_GDI_FAILED("Polyline"), ok = FALSE;
00481 
00482       if (ok && !CloseFigure(hdc))
00483          WIN32_GDI_FAILED("CloseFigure"), ok = FALSE;
00484 
00485       if (ok && !EndPath(hdc))
00486          WIN32_GDI_FAILED("EndPath"), ok = FALSE;
00487 
00488       if (ok && !filled)
00489          if (!WidenPath(hdc))
00490             WIN32_GDI_FAILED("WidenPath"), ok = FALSE;
00491 
00492       if (ok && !FillPath(hdc))
00493          WIN32_GDI_FAILED("FillPath"), ok = FALSE;
00494       SelectObject(hdc, oldpen_or_brush);
00495       DeleteObject(hbr);
00496    } else {
00497       if (points[0].x != points[npoints - 1].x
00498           || points[0].y != points[npoints - 1].y) {
00499          pts[npoints].x = points[0].x;
00500          pts[npoints].y = points[0].y;
00501          npoints++;
00502       }
00503 
00504       if (filled) {
00505          if (!Polygon(hdc, pts, npoints))
00506             WIN32_GDI_FAILED("Polygon");
00507       } else {
00508          if (!Polyline(hdc, pts, npoints))
00509             WIN32_GDI_FAILED("Polyline");
00510       }
00511    }
00512    g_free(pts);
00513    gdk_gc_postdraw(drawable, gc_private,
00514                    GDK_GC_FOREGROUND | GDK_GC_BACKGROUND);
00515 }
00516 
00517 typedef struct {
00518    gint x, y;
00519    HDC hdc;
00520 } gdk_draw_text_arg;
00521 
00522 static void
00523 gdk_draw_text_handler(GdkWin32SingleFont * singlefont,
00524                       const wchar_t * wcstr, int wclen, void *arg)
00525 {
00526    HGDIOBJ oldfont;
00527    SIZE size;
00528    gdk_draw_text_arg *argp = (gdk_draw_text_arg *) arg;
00529 
00530    if (!singlefont)
00531       return;
00532 
00533    if ((oldfont = SelectObject(argp->hdc, singlefont->xfont)) == NULL) {
00534       WIN32_GDI_FAILED("SelectObject");
00535       return;
00536    }
00537 
00538    if (!TextOutW(argp->hdc, argp->x, argp->y, wcstr, wclen))
00539       WIN32_GDI_FAILED("TextOutW");
00540    GetTextExtentPoint32W(argp->hdc, wcstr, wclen, &size);
00541    argp->x += size.cx;
00542 
00543    SelectObject(argp->hdc, oldfont);
00544 }
00545 
00546  void
00547 gdk_win32_draw_text(GdkDrawable * drawable,
00548                     GdkFont * font,
00549                     GdkGC * gc,
00550                     gint x, gint y, const gchar * text, gint text_length)
00551 {
00552    GdkGCPrivate *gc_private;
00553    wchar_t *wcstr;
00554    gint wlen;
00555    gdk_draw_text_arg arg;
00556 
00557 
00558    if (GDK_DRAWABLE_DESTROYED(drawable))
00559       return;
00560 
00561    if (text_length == 0)
00562       return;
00563 
00564    g_assert(font->type == GDK_FONT_FONT || font->type == GDK_FONT_FONTSET);
00565 
00566    gc_private = (GdkGCPrivate *) gc;
00567 
00568    arg.x = x;
00569    arg.y = y;
00570    arg.hdc = gdk_gc_predraw(drawable, gc_private,
00571                             GDK_GC_FOREGROUND | GDK_GC_FONT);
00572 
00573    GDK_NOTE(MISC, g_print("gdk_draw_text: %#x (%d,%d) \"%.*s\" (len %d)\n",
00574                           GDK_DRAWABLE_XID(drawable),
00575                           x, y,
00576                           (text_length > 10 ? 10 : text_length),
00577                           text, text_length));
00578 
00579    wcstr = g_new(wchar_t, text_length);
00580    if ((wlen =
00581         gdk_nmbstowchar_ts(wcstr, text, text_length, text_length)) == -1)
00582       g_warning("gdk_draw_text: gdk_nmbstowchar_ts failed");
00583    else
00584       gdk_wchar_text_handle(font, wcstr, wlen,
00585                             gdk_draw_text_handler, &arg);
00586 
00587    g_free(wcstr);
00588 
00589    gdk_gc_postdraw(drawable, gc_private, GDK_GC_FOREGROUND | GDK_GC_FONT);
00590 }
00591 
00592 static void
00593 gdk_win32_draw_text_wc(GdkDrawable * drawable,
00594                        GdkFont * font,
00595                        GdkGC * gc,
00596                        gint x,
00597                        gint y, const GdkWChar * text, gint text_length)
00598 {
00599    GdkGCPrivate *gc_private;
00600    gint i, wlen;
00601    wchar_t *wcstr;
00602    gdk_draw_text_arg arg;
00603 
00604 
00605    if (GDK_DRAWABLE_DESTROYED(drawable))
00606       return;
00607 
00608    if (text_length == 0)
00609       return;
00610 
00611    g_assert(font->type == GDK_FONT_FONT || font->type == GDK_FONT_FONTSET);
00612 
00613    gc_private = (GdkGCPrivate *) gc;
00614 
00615    arg.x = x;
00616    arg.y = y;
00617    arg.hdc = gdk_gc_predraw(drawable, gc_private,
00618                             GDK_GC_FOREGROUND | GDK_GC_FONT);
00619 
00620    GDK_NOTE(MISC, g_print("gdk_draw_text_wc: %#x (%d,%d) len: %d\n",
00621                           GDK_DRAWABLE_XID(drawable), x, y, text_length));
00622 
00623    if (sizeof(wchar_t) != sizeof(GdkWChar)) {
00624       wcstr = g_new(wchar_t, text_length);
00625       for (i = 0; i < text_length; i++)
00626          wcstr[i] = text[i];
00627    } else
00628       wcstr = (wchar_t *) text;
00629 
00630    gdk_wchar_text_handle(font, wcstr, text_length,
00631                          gdk_draw_text_handler, &arg);
00632 
00633    if (sizeof(wchar_t) != sizeof(GdkWChar))
00634       g_free(wcstr);
00635 
00636    gdk_gc_postdraw(drawable, gc_private, GDK_GC_FOREGROUND | GDK_GC_FONT);
00637 }
00638 
00639 static void
00640 gdk_win32_draw_drawable(GdkDrawable * drawable,
00641                         GdkGC * gc,
00642                         GdkPixmap * src,
00643                         gint xsrc,
00644                         gint ysrc,
00645                         gint xdest, gint ydest, gint width, gint height)
00646 {
00647    GdkDrawablePrivate *src_private;
00648    GdkGCPrivate *gc_private;
00649    HDC hdc;
00650    HDC srcdc;
00651    HGDIOBJ hgdiobj;
00652    HRGN src_rgn, draw_rgn, outside_rgn;
00653    RECT r;
00654    gboolean transp = FALSE;
00655 
00656    if (GDKTESTBIT(width,31) && GDKTESTBIT(height,31)) {
00657       transp = TRUE;
00658       GDKCLRBIT(width,31);
00659       GDKCLRBIT(height,31);
00660    }
00661 
00662    src_private = (GdkDrawablePrivate *) src;
00663    gc_private = (GdkGCPrivate *) gc;
00664 
00665    GDK_NOTE(MISC, g_print("gdk_draw_pixmap: dest: %#x "
00666                           "src: %#x %dx%d@+%d+%d"
00667                           " dest: %#x @+%d+%d\n",
00668                           GDK_DRAWABLE_XID(drawable),
00669                           GDK_DRAWABLE_XID(src),
00670                           width, height, xsrc, ysrc,
00671                           GDK_DRAWABLE_XID(drawable), xdest, ydest));
00672 
00673    hdc = gdk_gc_predraw(drawable, gc_private, 0);
00674 
00675    SetBkMode(hdc, TRANSPARENT); // bb add
00676 
00677    src_rgn = CreateRectRgn(0, 0, src_private->width + 1,
00678                            src_private->height + 1);
00679    draw_rgn = CreateRectRgn(xsrc, ysrc, xsrc + width + 1, ysrc + height + 1);
00680    SetRectEmpty(&r);
00681    outside_rgn = CreateRectRgnIndirect(&r);
00682 
00683    if (GDK_DRAWABLE_TYPE(drawable) != GDK_DRAWABLE_PIXMAP) {
00684       /* If we are drawing on a window, calculate the region that is
00685        * outside the source pixmap, and invalidate that, causing it to
00686        * be cleared. XXX
00687        */
00688       if (CombineRgn(outside_rgn, draw_rgn, src_rgn, RGN_DIFF) !=
00689           NULLREGION) {
00690          OffsetRgn(outside_rgn, xdest, ydest);
00691          GDK_NOTE(MISC, (GetRgnBox(outside_rgn, &r),
00692                          g_print("...calling InvalidateRgn, "
00693                                  "bbox: %dx%d@+%d+%d\n",
00694                                  r.right - r.left - 1,
00695                                  r.bottom - r.top - 1, r.left, r.top)));
00696          InvalidateRgn(GDK_DRAWABLE_XID(drawable), outside_rgn, TRUE);
00697       }
00698    }
00699 #if 1                           /* Don't know if this is necessary  */
00700    if (CombineRgn(draw_rgn, draw_rgn, src_rgn, RGN_AND) == COMPLEXREGION)
00701       g_warning("gdk_draw_pixmap: CombineRgn returned a COMPLEXREGION");
00702 
00703    GetRgnBox(draw_rgn, &r);
00704    if (r.left != xsrc
00705        || r.top != ysrc
00706        || r.right != xsrc + width + 1 || r.bottom != ysrc + height + 1) {
00707       xdest += r.left - xsrc;
00708       xsrc = r.left;
00709       ydest += r.top - ysrc;
00710       ysrc = r.top;
00711       width = r.right - xsrc - 1;
00712       height = r.bottom - ysrc - 1;
00713 
00714       GDK_NOTE(MISC, g_print("... restricted to src: %dx%d@+%d+%d, "
00715                              "dest: @+%d+%d\n",
00716                              width, height, xsrc, ysrc, xdest, ydest));
00717    }
00718 #endif
00719 
00720    DeleteObject(src_rgn);
00721    DeleteObject(draw_rgn);
00722    DeleteObject(outside_rgn);
00723 
00724    /* Strangely enough, this function is called also to bitblt
00725     * from a window.
00726     */
00727    if (src_private->window_type == GDK_DRAWABLE_PIXMAP) {
00728       BLENDFUNCTION fnc;
00729       fnc.BlendOp = AC_SRC_OVER;
00730       fnc.BlendFlags = 0;
00731       fnc.SourceConstantAlpha = 0xff;
00732       fnc.AlphaFormat = AC_SRC_ALPHA;
00733 
00734       if ((srcdc = CreateCompatibleDC(hdc)) == NULL)
00735          WIN32_GDI_FAILED("CreateCompatibleDC");
00736 
00737       if ((hgdiobj = SelectObject(srcdc, GDK_DRAWABLE_XID(src))) == NULL)
00738          WIN32_GDI_FAILED("SelectObject");
00739 
00740       if (transp && (GetDeviceCaps(hdc, BITSPIXEL) < 32))
00741          transp = FALSE;
00742 
00743       if (transp) {
00744          if (!AlphaBlend(hdc, xdest, ydest, width, height,
00745                          srcdc, xsrc, ysrc, width, height, fnc))
00746             WIN32_GDI_FAILED("AlphaBlend");
00747       } else {
00748          if (!BitBlt(hdc, xdest, ydest, width, height,
00749                      srcdc, xsrc, ysrc, SRCCOPY))
00750             WIN32_GDI_FAILED("BitBlt");
00751       }
00752 
00753       if ((SelectObject(srcdc, hgdiobj) == NULL))
00754          WIN32_GDI_FAILED("SelectObject");
00755 
00756       if (!DeleteDC(srcdc))
00757          WIN32_GDI_FAILED("DeleteDC");
00758 
00759    } else {
00760       if (GDK_DRAWABLE_XID(drawable) == GDK_DRAWABLE_XID(src)) {
00761 #if 1
00762          /* Blitting inside a window, use ScrollDC */
00763          RECT scrollRect, clipRect, emptyRect;
00764          HRGN updateRgn;
00765 
00766          scrollRect.left = MIN(xsrc, xdest);
00767          scrollRect.top = MIN(ysrc, ydest);
00768          scrollRect.right = MAX(xsrc + width + 1, xdest + width + 1);
00769          scrollRect.bottom = MAX(ysrc + height + 1, ydest + height + 1);
00770 
00771          //clipRect.left = xdest;
00772          //clipRect.top = ydest;
00773          //clipRect.right = xdest + width + 1;
00774          //clipRect.bottom = ydest + height + 1;
00775          GetClipBox(hdc, &clipRect);
00776 
00777          SetRectEmpty(&emptyRect);
00778          updateRgn = CreateRectRgnIndirect(&emptyRect);
00779 
00780          if (!ScrollDC(hdc, xdest - xsrc, ydest - ysrc,
00781                        &scrollRect, &clipRect, updateRgn, NULL))
00782             WIN32_GDI_FAILED("ScrollDC");
00783 
00784          if (!InvalidateRgn(GDK_DRAWABLE_XID(drawable), updateRgn, FALSE))
00785             WIN32_GDI_FAILED("InvalidateRgn");
00786 
00787          if (!UpdateWindow(GDK_DRAWABLE_XID(drawable)))
00788             WIN32_GDI_FAILED("UpdateWindow");
00789 
00790          DeleteObject(updateRgn);
00791 #else
00792          if (!BitBlt(hdc, xdest, ydest, width, height,
00793                      hdc, xsrc, ysrc, SRCCOPY))
00794             WIN32_GDI_FAILED("BitBlt");
00795 #endif
00796       } else {
00797          if ((srcdc = GetDC(GDK_DRAWABLE_XID(src))) == NULL)
00798             WIN32_GDI_FAILED("GetDC");
00799 
00800          if (!BitBlt(hdc, xdest, ydest, width, height,
00801                      srcdc, xsrc, ysrc, SRCCOPY))
00802             WIN32_GDI_FAILED("BitBlt");
00803 
00804          ReleaseDC(GDK_DRAWABLE_XID(src), srcdc);
00805       }
00806    }
00807    gdk_gc_postdraw(drawable, gc_private, 0);
00808 }
00809 
00810  void
00811 gdk_win32_draw_points(GdkDrawable * drawable,
00812                       GdkGC * gc, GdkPoint * points, gint npoints)
00813 {
00814    HDC hdc;
00815    COLORREF fg;
00816    GdkGCPrivate *gc_private = (GdkGCPrivate *) gc;
00817    GdkGCWin32Data *gc_data = GDK_GC_WIN32DATA(gc_private);
00818    GdkDrawablePrivate *drawable_private = (GdkDrawablePrivate *) drawable;
00819    GdkColormapPrivateWin32 *colormap_private =
00820        (GdkColormapPrivateWin32 *) drawable_private->colormap;
00821    int i;
00822 
00823    hdc = gdk_gc_predraw(drawable, gc_private, 0);
00824 
00825    fg = gdk_colormap_color(colormap_private, gc_data->foreground);
00826 
00827    GDK_NOTE(MISC, g_print("gdk_draw_points: %#x %dx%.06x\n",
00828                           GDK_DRAWABLE_XID(drawable), npoints, fg));
00829 
00830    for (i = 0; i < npoints; i++)
00831       SetPixel(hdc, points[i].x, points[i].y, fg);
00832 
00833    gdk_gc_postdraw(drawable, gc_private, 0);
00834 }
00835 
00836  void
00837 gdk_win32_draw_segments(GdkDrawable * drawable,
00838                         GdkGC * gc, GdkSegment * segs, gint nsegs)
00839 {
00840    GdkGCPrivate *gc_private = (GdkGCPrivate *) gc;
00841    GdkGCWin32Data *gc_data = GDK_GC_WIN32DATA(gc_private);
00842    HDC hdc;
00843    gboolean ok = TRUE;
00844    int i;
00845 
00846    GDK_NOTE(MISC, g_print("gdk_win32_draw_segments: %#x nsegs: %d\n",
00847                           GDK_DRAWABLE_XID(drawable), nsegs));
00848 
00849    hdc = gdk_gc_predraw(drawable, gc_private,
00850                         GDK_GC_FOREGROUND | GDK_GC_BACKGROUND);
00851 
00852    if (gc_data->fill_style == GDK_OPAQUE_STIPPLED) {
00853       if (!BeginPath(hdc))
00854          WIN32_GDI_FAILED("BeginPath"), ok = FALSE;
00855 
00856       for (i = 0; i < nsegs; i++) {
00857          if (ok && !MoveToEx(hdc, segs[i].x1, segs[i].y1, NULL))
00858             WIN32_GDI_FAILED("MoveToEx"), ok = FALSE;
00859          if (ok && !LineTo(hdc, segs[i].x2, segs[i].y2))
00860             WIN32_GDI_FAILED("LineTo"), ok = FALSE;
00861 
00862          /* Draw end pixel */
00863          if (ok && gc_data->pen_width <= 1)
00864             if (!LineTo(hdc, segs[i].x2 + 1, segs[i].y2))
00865                WIN32_GDI_FAILED("LineTo"), ok = FALSE;
00866       }
00867 
00868       if (ok && !EndPath(hdc))
00869          WIN32_GDI_FAILED("EndPath"), ok = FALSE;
00870 
00871       if (ok && !WidenPath(hdc))
00872          WIN32_GDI_FAILED("WidenPath"), ok = FALSE;
00873 
00874       if (ok && !FillPath(hdc))
00875          WIN32_GDI_FAILED("FillPath"), ok = FALSE;
00876    } else {
00877       for (i = 0; i < nsegs; i++) {
00878          if (!MoveToEx(hdc, segs[i].x1, segs[i].y1, NULL))
00879             WIN32_GDI_FAILED("MoveToEx");
00880          if (!LineTo(hdc, segs[i].x2, segs[i].y2))
00881             WIN32_GDI_FAILED("LineTo");
00882 
00883          /* Draw end pixel */
00884          if (gc_data->pen_width <= 1)
00885             if (!LineTo(hdc, segs[i].x2 + 1, segs[i].y2))
00886                WIN32_GDI_FAILED("LineTo");
00887       }
00888    }
00889    gdk_gc_postdraw(drawable, gc_private,
00890                    GDK_GC_FOREGROUND | GDK_GC_BACKGROUND);
00891 }
00892 
00893  void
00894 gdk_win32_draw_lines(GdkDrawable * drawable,
00895                      GdkGC * gc, GdkPoint * points, gint npoints)
00896 {
00897    GdkGCPrivate *gc_private = (GdkGCPrivate *) gc;
00898    GdkGCWin32Data *gc_data = GDK_GC_WIN32DATA(gc_private);
00899    HDC hdc;
00900    POINT *pts;
00901    int i;
00902 
00903    if (npoints < 2)
00904       return;
00905 
00906    hdc = gdk_gc_predraw(drawable, gc_private,
00907                         GDK_GC_FOREGROUND | GDK_GC_BACKGROUND);
00908 #if 1
00909    pts = g_new(POINT, npoints);
00910 
00911    for (i = 0; i < npoints; i++) {
00912       pts[i].x = points[i].x;
00913       pts[i].y = points[i].y;
00914    }
00915 
00916    if (!Polyline(hdc, pts, npoints))
00917       WIN32_GDI_FAILED("Polyline");
00918 
00919    g_free(pts);
00920 
00921    /* Draw end pixel */
00922    if (gc_data->pen_width <= 1) {
00923       MoveToEx(hdc, points[npoints - 1].x, points[npoints - 1].y, NULL);
00924       if (!LineTo(hdc, points[npoints - 1].x + 1, points[npoints - 1].y))
00925          WIN32_GDI_FAILED("LineTo");
00926    }
00927 #else
00928    MoveToEx(hdc, points[0].x, points[0].y, NULL);
00929    for (i = 1; i < npoints; i++)
00930       if (!LineTo(hdc, points[i].x, points[i].y))
00931          WIN32_GDI_FAILED("LineTo");
00932 
00933    /* Draw end pixel */
00934    /* LineTo doesn't draw the last point, so if we have a pen width of 1,
00935     * we draw the end pixel separately... With wider pens we don't care.
00936     * //HB: But the NT developers don't read their API documentation ...
00937     */
00938    if (gc_data->pen_width <= 1 && windows_version > 0x80000000)
00939       if (!LineTo(hdc, points[npoints - 1].x + 1, points[npoints - 1].y))
00940          WIN32_GDI_FAILED("LineTo");
00941 #endif
00942    gdk_gc_postdraw(drawable, gc_private,
00943                    GDK_GC_FOREGROUND | GDK_GC_BACKGROUND);
00944 }
00945 
00946 void gdk_win32_print_dc_attributes(HDC hdc)
00947 {
00948    HBRUSH hbr = GetCurrentObject(hdc, OBJ_BRUSH);
00949    HPEN hpen = GetCurrentObject(hdc, OBJ_PEN);
00950    LOGBRUSH lbr;
00951    LOGPEN lpen;
00952 
00953    GetObject(hbr, sizeof(lbr), &lbr);
00954    GetObject(hpen, sizeof(lpen), &lpen);
00955 
00956    g_print("current brush: style = %s, color = 0x%.08x\n",
00957            (lbr.lbStyle == BS_SOLID ? "SOLID" : "???"), lbr.lbColor);
00958    g_print("current pen: style = %s, width = %d, color = 0x%.08x\n",
00959            (lpen.lopnStyle == PS_SOLID ? "SOLID" : "???"),
00960            lpen.lopnWidth, lpen.lopnColor);
00961 }

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