00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
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
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();
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
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
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
00196
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
00248
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
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
00285
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
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
00354
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
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
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);
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
00685
00686
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
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
00725
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
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
00772
00773
00774
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
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
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
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
00934
00935
00936
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 }