summaryrefslogtreecommitdiffstats
path: root/tk8.6/win/tkWinDraw.c
diff options
context:
space:
mode:
Diffstat (limited to 'tk8.6/win/tkWinDraw.c')
-rw-r--r--tk8.6/win/tkWinDraw.c1391
1 files changed, 0 insertions, 1391 deletions
diff --git a/tk8.6/win/tkWinDraw.c b/tk8.6/win/tkWinDraw.c
deleted file mode 100644
index ba4176c..0000000
--- a/tk8.6/win/tkWinDraw.c
+++ /dev/null
@@ -1,1391 +0,0 @@
-/*
- * tkWinDraw.c --
- *
- * This file contains the Xlib emulation functions pertaining to actually
- * drawing objects on a window.
- *
- * Copyright (c) 1995 Sun Microsystems, Inc.
- * Copyright (c) 1994 Software Research Associates, Inc.
- *
- * See the file "license.terms" for information on usage and redistribution of
- * this file, and for a DISCLAIMER OF ALL WARRANTIES.
- */
-
-#include "tkWinInt.h"
-
-/*
- * These macros convert between X's bizarre angle units to radians.
- */
-
-#define XAngleToRadians(a) ((double)(a) / 64 * PI / 180);
-
-/*
- * Translation table between X gc functions and Win32 raster op modes.
- */
-
-const int tkpWinRopModes[] = {
- R2_BLACK, /* GXclear */
- R2_MASKPEN, /* GXand */
- R2_MASKPENNOT, /* GXandReverse */
- R2_COPYPEN, /* GXcopy */
- R2_MASKNOTPEN, /* GXandInverted */
- R2_NOT, /* GXnoop */
- R2_XORPEN, /* GXxor */
- R2_MERGEPEN, /* GXor */
- R2_NOTMERGEPEN, /* GXnor */
- R2_NOTXORPEN, /* GXequiv */
- R2_NOT, /* GXinvert */
- R2_MERGEPENNOT, /* GXorReverse */
- R2_NOTCOPYPEN, /* GXcopyInverted */
- R2_MERGENOTPEN, /* GXorInverted */
- R2_NOTMASKPEN, /* GXnand */
- R2_WHITE /* GXset */
-};
-
-/*
- * Translation table between X gc functions and Win32 BitBlt op modes. Some of
- * the operations defined in X don't have names, so we have to construct new
- * opcodes for those functions. This is arcane and probably not all that
- * useful, but at least it's accurate.
- */
-
-#define NOTSRCAND (DWORD)0x00220326 /* dest = (NOT source) AND dest */
-#define NOTSRCINVERT (DWORD)0x00990066 /* dest = (NOT source) XOR dest */
-#define SRCORREVERSE (DWORD)0x00DD0228 /* dest = source OR (NOT dest) */
-#define SRCNAND (DWORD)0x007700E6 /* dest = NOT (source AND dest) */
-
-const int tkpWinBltModes[] = {
- BLACKNESS, /* GXclear */
- SRCAND, /* GXand */
- SRCERASE, /* GXandReverse */
- SRCCOPY, /* GXcopy */
- NOTSRCAND, /* GXandInverted */
- PATCOPY, /* GXnoop */
- SRCINVERT, /* GXxor */
- SRCPAINT, /* GXor */
- NOTSRCERASE, /* GXnor */
- NOTSRCINVERT, /* GXequiv */
- DSTINVERT, /* GXinvert */
- SRCORREVERSE, /* GXorReverse */
- NOTSRCCOPY, /* GXcopyInverted */
- MERGEPAINT, /* GXorInverted */
- SRCNAND, /* GXnand */
- WHITENESS /* GXset */
-};
-
-/*
- * The following raster op uses the source bitmap as a mask for the pattern.
- * This is used to draw in a foreground color but leave the background color
- * transparent.
- */
-
-#define MASKPAT 0x00E20746 /* dest = (src & pat) | (!src & dst) */
-
-/*
- * The following two raster ops are used to copy the foreground and background
- * bits of a source pattern as defined by a stipple used as the pattern.
- */
-
-#define COPYFG 0x00CA0749 /* dest = (pat & src) | (!pat & dst) */
-#define COPYBG 0x00AC0744 /* dest = (!pat & src) | (pat & dst) */
-
-/*
- * Macros used later in the file.
- */
-#ifndef MIN
-# define MIN(a,b) ((a>b) ? b : a)
-# define MAX(a,b) ((a<b) ? b : a)
-#endif
-
-/*
- * The followng typedef is used to pass Windows GDI drawing functions.
- */
-
-typedef BOOL (CALLBACK *WinDrawFunc)(HDC dc, const POINT *points, int npoints);
-
-typedef struct ThreadSpecificData {
- POINT *winPoints; /* Array of points that is reused. */
- int nWinPoints; /* Current size of point array. */
-} ThreadSpecificData;
-static Tcl_ThreadDataKey dataKey;
-
-/*
- * Forward declarations for functions defined in this file:
- */
-
-static POINT * ConvertPoints(XPoint *points, int npoints, int mode,
- RECT *bbox);
-static int DrawOrFillArc(Display *display, Drawable d, GC gc,
- int x, int y, unsigned int width,
- unsigned int height, int start, int extent,
- int fill);
-static void RenderObject(HDC dc, GC gc, XPoint* points,
- int npoints, int mode, HPEN pen, WinDrawFunc func);
-static HPEN SetUpGraphicsPort(GC gc);
-
-/*
- *----------------------------------------------------------------------
- *
- * TkWinGetDrawableDC --
- *
- * Retrieve the DC from a drawable.
- *
- * Results:
- * Returns the window DC for windows. Returns a new memory DC for
- * pixmaps.
- *
- * Side effects:
- * Sets up the palette for the device context, and saves the old device
- * context state in the passed in TkWinDCState structure.
- *
- *----------------------------------------------------------------------
- */
-
-HDC
-TkWinGetDrawableDC(
- Display *display,
- Drawable d,
- TkWinDCState *state)
-{
- HDC dc;
- TkWinDrawable *twdPtr = (TkWinDrawable *)d;
- Colormap cmap;
-
- if (twdPtr->type == TWD_WINDOW) {
- TkWindow *winPtr = twdPtr->window.winPtr;
-
- dc = GetDC(twdPtr->window.handle);
- if (winPtr == NULL) {
- cmap = DefaultColormap(display, DefaultScreen(display));
- } else {
- cmap = winPtr->atts.colormap;
- }
- } else if (twdPtr->type == TWD_WINDC) {
- dc = twdPtr->winDC.hdc;
- cmap = DefaultColormap(display, DefaultScreen(display));
- } else {
- dc = CreateCompatibleDC(NULL);
- SelectObject(dc, twdPtr->bitmap.handle);
- cmap = twdPtr->bitmap.colormap;
- }
- state->palette = TkWinSelectPalette(dc, cmap);
- state->bkmode = GetBkMode(dc);
- return dc;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * TkWinReleaseDrawableDC --
- *
- * Frees the resources associated with a drawable's DC.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Restores the old bitmap handle to the memory DC for pixmaps.
- *
- *----------------------------------------------------------------------
- */
-
-void
-TkWinReleaseDrawableDC(
- Drawable d,
- HDC dc,
- TkWinDCState *state)
-{
- TkWinDrawable *twdPtr = (TkWinDrawable *)d;
-
- SetBkMode(dc, state->bkmode);
- SelectPalette(dc, state->palette, TRUE);
- RealizePalette(dc);
- if (twdPtr->type == TWD_WINDOW) {
- ReleaseDC(TkWinGetHWND(d), dc);
- } else if (twdPtr->type == TWD_BITMAP) {
- DeleteDC(dc);
- }
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * ConvertPoints --
- *
- * Convert an array of X points to an array of Win32 points.
- *
- * Results:
- * Returns the converted array of POINTs.
- *
- * Side effects:
- * Allocates a block of memory in thread local storage that should not be
- * freed.
- *
- *----------------------------------------------------------------------
- */
-
-static POINT *
-ConvertPoints(
- XPoint *points,
- int npoints,
- int mode, /* CoordModeOrigin or CoordModePrevious. */
- RECT *bbox) /* Bounding box of points. */
-{
- ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
- Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
- int i;
-
- /*
- * To avoid paying the cost of a malloc on every drawing routine, we reuse
- * the last array if it is large enough.
- */
-
- if (npoints > tsdPtr->nWinPoints) {
- if (tsdPtr->winPoints != NULL) {
- ckfree(tsdPtr->winPoints);
- }
- tsdPtr->winPoints = ckalloc(sizeof(POINT) * npoints);
- if (tsdPtr->winPoints == NULL) {
- tsdPtr->nWinPoints = -1;
- return NULL;
- }
- tsdPtr->nWinPoints = npoints;
- }
-
- bbox->left = bbox->right = points[0].x;
- bbox->top = bbox->bottom = points[0].y;
-
- if (mode == CoordModeOrigin) {
- for (i = 0; i < npoints; i++) {
- tsdPtr->winPoints[i].x = points[i].x;
- tsdPtr->winPoints[i].y = points[i].y;
- bbox->left = MIN(bbox->left, tsdPtr->winPoints[i].x);
- bbox->right = MAX(bbox->right, tsdPtr->winPoints[i].x);
- bbox->top = MIN(bbox->top, tsdPtr->winPoints[i].y);
- bbox->bottom = MAX(bbox->bottom, tsdPtr->winPoints[i].y);
- }
- } else {
- tsdPtr->winPoints[0].x = points[0].x;
- tsdPtr->winPoints[0].y = points[0].y;
- for (i = 1; i < npoints; i++) {
- tsdPtr->winPoints[i].x = tsdPtr->winPoints[i-1].x + points[i].x;
- tsdPtr->winPoints[i].y = tsdPtr->winPoints[i-1].y + points[i].y;
- bbox->left = MIN(bbox->left, tsdPtr->winPoints[i].x);
- bbox->right = MAX(bbox->right, tsdPtr->winPoints[i].x);
- bbox->top = MIN(bbox->top, tsdPtr->winPoints[i].y);
- bbox->bottom = MAX(bbox->bottom, tsdPtr->winPoints[i].y);
- }
- }
- return tsdPtr->winPoints;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * XCopyArea --
- *
- * Copies data from one drawable to another using block transfer
- * routines.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Data is moved from a window or bitmap to a second window or bitmap.
- *
- *----------------------------------------------------------------------
- */
-
-int
-XCopyArea(
- Display *display,
- Drawable src,
- Drawable dest,
- GC gc,
- int src_x, int src_y,
- unsigned int width, unsigned int height,
- int dest_x, int dest_y)
-{
- HDC srcDC, destDC;
- TkWinDCState srcState, destState;
- TkpClipMask *clipPtr = (TkpClipMask*)gc->clip_mask;
-
- srcDC = TkWinGetDrawableDC(display, src, &srcState);
-
- if (src != dest) {
- destDC = TkWinGetDrawableDC(display, dest, &destState);
- } else {
- destDC = srcDC;
- }
-
- if (clipPtr && clipPtr->type == TKP_CLIP_REGION) {
- SelectClipRgn(destDC, (HRGN) clipPtr->value.region);
- OffsetClipRgn(destDC, gc->clip_x_origin, gc->clip_y_origin);
- }
-
- BitBlt(destDC, dest_x, dest_y, (int) width, (int) height, srcDC,
- src_x, src_y, (DWORD) tkpWinBltModes[gc->function]);
-
- SelectClipRgn(destDC, NULL);
-
- if (src != dest) {
- TkWinReleaseDrawableDC(dest, destDC, &destState);
- }
- TkWinReleaseDrawableDC(src, srcDC, &srcState);
- return Success;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * XCopyPlane --
- *
- * Copies a bitmap from a source drawable to a destination drawable. The
- * plane argument specifies which bit plane of the source contains the
- * bitmap. Note that this implementation ignores the gc->function.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Changes the destination drawable.
- *
- *----------------------------------------------------------------------
- */
-
-int
-XCopyPlane(
- Display *display,
- Drawable src,
- Drawable dest,
- GC gc,
- int src_x, int src_y,
- unsigned int width, unsigned int height,
- int dest_x, int dest_y,
- unsigned long plane)
-{
- HDC srcDC, destDC;
- TkWinDCState srcState, destState;
- HBRUSH bgBrush, fgBrush, oldBrush;
- TkpClipMask *clipPtr = (TkpClipMask*)gc->clip_mask;
-
- display->request++;
-
- if (plane != 1) {
- Tcl_Panic("Unexpected plane specified for XCopyPlane");
- }
-
- srcDC = TkWinGetDrawableDC(display, src, &srcState);
-
- if (src != dest) {
- destDC = TkWinGetDrawableDC(display, dest, &destState);
- } else {
- destDC = srcDC;
- }
-
- if (clipPtr == NULL || clipPtr->type == TKP_CLIP_REGION) {
- /*
- * Case 1: opaque bitmaps. Windows handles the conversion from one bit
- * to multiple bits by setting 0 to the foreground color, and 1 to the
- * background color (seems backwards, but there you are).
- */
-
- if (clipPtr && clipPtr->type == TKP_CLIP_REGION) {
- SelectClipRgn(destDC, (HRGN) clipPtr->value.region);
- OffsetClipRgn(destDC, gc->clip_x_origin, gc->clip_y_origin);
- }
-
- SetBkMode(destDC, OPAQUE);
- SetBkColor(destDC, gc->foreground);
- SetTextColor(destDC, gc->background);
- BitBlt(destDC, dest_x, dest_y, (int) width, (int) height, srcDC,
- src_x, src_y, SRCCOPY);
-
- SelectClipRgn(destDC, NULL);
- } else if (clipPtr->type == TKP_CLIP_PIXMAP) {
- if (clipPtr->value.pixmap == src) {
-
- /*
- * Case 2: transparent bitmaps are handled by setting the
- * destination to the foreground color whenever the source pixel
- * is set.
- */
-
- fgBrush = CreateSolidBrush(gc->foreground);
- oldBrush = SelectObject(destDC, fgBrush);
- SetBkColor(destDC, RGB(255,255,255));
- SetTextColor(destDC, RGB(0,0,0));
- BitBlt(destDC, dest_x, dest_y, (int) width, (int) height, srcDC,
- src_x, src_y, MASKPAT);
- SelectObject(destDC, oldBrush);
- DeleteObject(fgBrush);
- } else {
-
- /*
- * Case 3: two arbitrary bitmaps. Copy the source rectangle into a
- * color pixmap. Use the result as a brush when copying the clip
- * mask into the destination.
- */
-
- HDC memDC, maskDC;
- HBITMAP bitmap;
- TkWinDCState maskState;
-
- fgBrush = CreateSolidBrush(gc->foreground);
- bgBrush = CreateSolidBrush(gc->background);
- maskDC = TkWinGetDrawableDC(display, clipPtr->value.pixmap,
- &maskState);
- memDC = CreateCompatibleDC(destDC);
- bitmap = CreateBitmap((int) width, (int) height, 1, 1, NULL);
- SelectObject(memDC, bitmap);
-
- /*
- * Set foreground bits. We create a new bitmap containing (source
- * AND mask), then use it to set the foreground color into the
- * destination.
- */
-
- BitBlt(memDC, 0, 0, (int) width, (int) height, srcDC, src_x, src_y,
- SRCCOPY);
- BitBlt(memDC, 0, 0, (int) width, (int) height, maskDC,
- dest_x - gc->clip_x_origin, dest_y - gc->clip_y_origin,
- SRCAND);
- oldBrush = SelectObject(destDC, fgBrush);
- BitBlt(destDC, dest_x, dest_y, (int) width, (int) height, memDC,
- 0, 0, MASKPAT);
-
- /*
- * Set background bits. Same as foreground, except we use ((NOT
- * source) AND mask) and the background brush.
- */
-
- BitBlt(memDC, 0, 0, (int) width, (int) height, srcDC, src_x, src_y,
- NOTSRCCOPY);
- BitBlt(memDC, 0, 0, (int) width, (int) height, maskDC,
- dest_x - gc->clip_x_origin, dest_y - gc->clip_y_origin,
- SRCAND);
- SelectObject(destDC, bgBrush);
- BitBlt(destDC, dest_x, dest_y, (int) width, (int) height, memDC,
- 0, 0, MASKPAT);
-
- TkWinReleaseDrawableDC(clipPtr->value.pixmap, maskDC, &maskState);
- SelectObject(destDC, oldBrush);
- DeleteDC(memDC);
- DeleteObject(bitmap);
- DeleteObject(fgBrush);
- DeleteObject(bgBrush);
- }
- }
- if (src != dest) {
- TkWinReleaseDrawableDC(dest, destDC, &destState);
- }
- TkWinReleaseDrawableDC(src, srcDC, &srcState);
- return Success;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * TkPutImage --
- *
- * Copies a subimage from an in-memory image to a rectangle of of the
- * specified drawable.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Draws the image on the specified drawable.
- *
- *----------------------------------------------------------------------
- */
-
-int
-TkPutImage(
- unsigned long *colors, /* Array of pixel values used by this image.
- * May be NULL. */
- int ncolors, /* Number of colors used, or 0. */
- Display *display,
- Drawable d, /* Destination drawable. */
- GC gc,
- XImage *image, /* Source image. */
- int src_x, int src_y, /* Offset of subimage. */
- int dest_x, int dest_y, /* Position of subimage origin in drawable. */
- unsigned int width, unsigned int height)
- /* Dimensions of subimage. */
-{
- HDC dc, dcMem;
- TkWinDCState state;
- BITMAPINFO *infoPtr;
- HBITMAP bitmap;
- char *data;
-
- display->request++;
-
- dc = TkWinGetDrawableDC(display, d, &state);
- SetROP2(dc, tkpWinRopModes[gc->function]);
- dcMem = CreateCompatibleDC(dc);
-
- if (image->bits_per_pixel == 1) {
- /*
- * If the image isn't in the right format, we have to copy it into a
- * new buffer in MSBFirst and word-aligned format.
- */
-
- if ((image->bitmap_bit_order != MSBFirst)
- || (image->bitmap_pad != sizeof(WORD))) {
- data = TkAlignImageData(image, sizeof(WORD), MSBFirst);
- bitmap = CreateBitmap(image->width, image->height, 1, 1, data);
- ckfree(data);
- } else {
- bitmap = CreateBitmap(image->width, image->height, 1, 1,
- image->data);
- }
- SetTextColor(dc, gc->foreground);
- SetBkColor(dc, gc->background);
- } else {
- int i, usePalette;
-
- /*
- * Do not use a palette for TrueColor images.
- */
-
- usePalette = (image->bits_per_pixel < 16);
-
- if (usePalette) {
- infoPtr = ckalloc(sizeof(BITMAPINFOHEADER)
- + sizeof(RGBQUAD)*ncolors);
- } else {
- infoPtr = ckalloc(sizeof(BITMAPINFOHEADER));
- }
-
- infoPtr->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
- infoPtr->bmiHeader.biWidth = image->width;
- infoPtr->bmiHeader.biHeight = -image->height; /* Top-down order */
- infoPtr->bmiHeader.biPlanes = 1;
- infoPtr->bmiHeader.biBitCount = image->bits_per_pixel;
- infoPtr->bmiHeader.biCompression = BI_RGB;
- infoPtr->bmiHeader.biSizeImage = 0;
- infoPtr->bmiHeader.biXPelsPerMeter = 0;
- infoPtr->bmiHeader.biYPelsPerMeter = 0;
- infoPtr->bmiHeader.biClrImportant = 0;
-
- if (usePalette) {
- infoPtr->bmiHeader.biClrUsed = ncolors;
- for (i = 0; i < ncolors; i++) {
- infoPtr->bmiColors[i].rgbBlue = GetBValue(colors[i]);
- infoPtr->bmiColors[i].rgbGreen = GetGValue(colors[i]);
- infoPtr->bmiColors[i].rgbRed = GetRValue(colors[i]);
- infoPtr->bmiColors[i].rgbReserved = 0;
- }
- } else {
- infoPtr->bmiHeader.biClrUsed = 0;
- }
- bitmap = CreateDIBitmap(dc, &infoPtr->bmiHeader, CBM_INIT,
- image->data, infoPtr, DIB_RGB_COLORS);
- ckfree(infoPtr);
- }
- if (!bitmap) {
- Tcl_Panic("Fail to allocate bitmap");
- DeleteDC(dcMem);
- TkWinReleaseDrawableDC(d, dc, &state);
- return BadValue;
- }
- bitmap = SelectObject(dcMem, bitmap);
- BitBlt(dc, dest_x, dest_y, (int) width, (int) height, dcMem, src_x, src_y,
- SRCCOPY);
- DeleteObject(SelectObject(dcMem, bitmap));
- DeleteDC(dcMem);
- TkWinReleaseDrawableDC(d, dc, &state);
- return Success;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * XFillRectangles --
- *
- * Fill multiple rectangular areas in the given drawable.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Draws onto the specified drawable.
- *
- *----------------------------------------------------------------------
- */
-
-int
-XFillRectangles(
- Display *display,
- Drawable d,
- GC gc,
- XRectangle *rectangles,
- int nrectangles)
-{
- HDC dc;
- int i;
- RECT rect;
- TkWinDCState state;
- HBRUSH brush, oldBrush;
-
- if (d == None) {
- return BadDrawable;
- }
-
- dc = TkWinGetDrawableDC(display, d, &state);
- SetROP2(dc, tkpWinRopModes[gc->function]);
- brush = CreateSolidBrush(gc->foreground);
-
- if ((gc->fill_style == FillStippled
- || gc->fill_style == FillOpaqueStippled)
- && gc->stipple != None) {
- TkWinDrawable *twdPtr = (TkWinDrawable *)gc->stipple;
- HBRUSH stipple;
- HBITMAP oldBitmap, bitmap;
- HDC dcMem;
- HBRUSH bgBrush = CreateSolidBrush(gc->background);
-
- if (twdPtr->type != TWD_BITMAP) {
- Tcl_Panic("unexpected drawable type in stipple");
- }
-
- /*
- * Select stipple pattern into destination dc.
- */
-
- stipple = CreatePatternBrush(twdPtr->bitmap.handle);
- SetBrushOrgEx(dc, gc->ts_x_origin, gc->ts_y_origin, NULL);
- oldBrush = SelectObject(dc, stipple);
- dcMem = CreateCompatibleDC(dc);
-
- /*
- * For each rectangle, create a drawing surface which is the size of
- * the rectangle and fill it with the background color. Then merge the
- * result with the stipple pattern.
- */
-
- for (i = 0; i < nrectangles; i++) {
- bitmap = CreateCompatibleBitmap(dc, rectangles[i].width,
- rectangles[i].height);
- oldBitmap = SelectObject(dcMem, bitmap);
- rect.left = 0;
- rect.top = 0;
- rect.right = rectangles[i].width;
- rect.bottom = rectangles[i].height;
- FillRect(dcMem, &rect, brush);
- BitBlt(dc, rectangles[i].x, rectangles[i].y, rectangles[i].width,
- rectangles[i].height, dcMem, 0, 0, COPYFG);
- if (gc->fill_style == FillOpaqueStippled) {
- FillRect(dcMem, &rect, bgBrush);
- BitBlt(dc, rectangles[i].x, rectangles[i].y,
- rectangles[i].width, rectangles[i].height, dcMem,
- 0, 0, COPYBG);
- }
- SelectObject(dcMem, oldBitmap);
- DeleteObject(bitmap);
- }
-
- DeleteDC(dcMem);
- SelectObject(dc, oldBrush);
- DeleteObject(stipple);
- DeleteObject(bgBrush);
- } else {
- if (gc->function == GXcopy) {
- for (i = 0; i < nrectangles; i++) {
- rect.left = rectangles[i].x;
- rect.right = rect.left + rectangles[i].width;
- rect.top = rectangles[i].y;
- rect.bottom = rect.top + rectangles[i].height;
- FillRect(dc, &rect, brush);
- }
- } else {
- HPEN newPen = CreatePen(PS_NULL, 0, gc->foreground);
- HPEN oldPen = SelectObject(dc, newPen);
- oldBrush = SelectObject(dc, brush);
-
- for (i = 0; i < nrectangles; i++) {
- Rectangle(dc, rectangles[i].x, rectangles[i].y,
- rectangles[i].x + rectangles[i].width + 1,
- rectangles[i].y + rectangles[i].height + 1);
- }
-
- SelectObject(dc, oldBrush);
- SelectObject(dc, oldPen);
- DeleteObject(newPen);
- }
- }
- DeleteObject(brush);
- TkWinReleaseDrawableDC(d, dc, &state);
- return Success;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * RenderObject --
- *
- * This function draws a shape using a list of points, a stipple pattern,
- * and the specified drawing function.
- *
- * Results:
- * None.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-static void
-RenderObject(
- HDC dc,
- GC gc,
- XPoint *points,
- int npoints,
- int mode,
- HPEN pen,
- WinDrawFunc func)
-{
- RECT rect = {0,0,0,0};
- HPEN oldPen;
- HBRUSH oldBrush;
- POINT *winPoints = ConvertPoints(points, npoints, mode, &rect);
-
- if ((gc->fill_style == FillStippled
- || gc->fill_style == FillOpaqueStippled)
- && gc->stipple != None) {
-
- TkWinDrawable *twdPtr = (TkWinDrawable *)gc->stipple;
- HDC dcMem;
- LONG width, height;
- HBITMAP oldBitmap;
- int i;
- HBRUSH oldMemBrush;
-
- if (twdPtr->type != TWD_BITMAP) {
- Tcl_Panic("unexpected drawable type in stipple");
- }
-
- /*
- * Grow the bounding box enough to account for line width.
- */
-
- rect.left -= gc->line_width;
- rect.top -= gc->line_width;
- rect.right += gc->line_width;
- rect.bottom += gc->line_width;
-
- width = rect.right - rect.left;
- height = rect.bottom - rect.top;
-
- /*
- * Select stipple pattern into destination dc.
- */
-
- SetBrushOrgEx(dc, gc->ts_x_origin, gc->ts_y_origin, NULL);
- oldBrush = SelectObject(dc, CreatePatternBrush(twdPtr->bitmap.handle));
-
- /*
- * Create temporary drawing surface containing a copy of the
- * destination equal in size to the bounding box of the object.
- */
-
- dcMem = CreateCompatibleDC(dc);
- oldBitmap = SelectObject(dcMem, CreateCompatibleBitmap(dc, width,
- height));
- oldPen = SelectObject(dcMem, pen);
- BitBlt(dcMem, 0, 0, width, height, dc, rect.left, rect.top, SRCCOPY);
-
- /*
- * Translate the object for rendering in the temporary drawing
- * surface.
- */
-
- for (i = 0; i < npoints; i++) {
- winPoints[i].x -= rect.left;
- winPoints[i].y -= rect.top;
- }
-
- /*
- * Draw the object in the foreground color and copy it to the
- * destination wherever the pattern is set.
- */
-
- SetPolyFillMode(dcMem, (gc->fill_rule == EvenOddRule) ? ALTERNATE
- : WINDING);
- oldMemBrush = SelectObject(dcMem, CreateSolidBrush(gc->foreground));
- func(dcMem, winPoints, npoints);
- BitBlt(dc, rect.left, rect.top, width, height, dcMem, 0, 0, COPYFG);
-
- /*
- * If we are rendering an opaque stipple, then draw the polygon in the
- * background color and copy it to the destination wherever the
- * pattern is clear.
- */
-
- if (gc->fill_style == FillOpaqueStippled) {
- DeleteObject(SelectObject(dcMem,
- CreateSolidBrush(gc->background)));
- func(dcMem, winPoints, npoints);
- BitBlt(dc, rect.left, rect.top, width, height, dcMem, 0, 0,
- COPYBG);
- }
-
- SelectObject(dcMem, oldPen);
- DeleteObject(SelectObject(dcMem, oldMemBrush));
- DeleteObject(SelectObject(dcMem, oldBitmap));
- DeleteDC(dcMem);
- } else {
- oldPen = SelectObject(dc, pen);
- oldBrush = SelectObject(dc, CreateSolidBrush(gc->foreground));
- SetROP2(dc, tkpWinRopModes[gc->function]);
-
- SetPolyFillMode(dc, (gc->fill_rule == EvenOddRule) ? ALTERNATE
- : WINDING);
- func(dc, winPoints, npoints);
- SelectObject(dc, oldPen);
- }
- DeleteObject(SelectObject(dc, oldBrush));
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * XDrawLines --
- *
- * Draw connected lines.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Renders a series of connected lines.
- *
- *----------------------------------------------------------------------
- */
-
-int
-XDrawLines(
- Display *display,
- Drawable d,
- GC gc,
- XPoint *points,
- int npoints,
- int mode)
-{
- HPEN pen;
- TkWinDCState state;
- HDC dc;
-
- if (d == None) {
- return BadDrawable;
- }
-
- dc = TkWinGetDrawableDC(display, d, &state);
-
- pen = SetUpGraphicsPort(gc);
- SetBkMode(dc, TRANSPARENT);
- RenderObject(dc, gc, points, npoints, mode, pen, Polyline);
- DeleteObject(pen);
-
- TkWinReleaseDrawableDC(d, dc, &state);
- return Success;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * XFillPolygon --
- *
- * Draws a filled polygon.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Draws a filled polygon on the specified drawable.
- *
- *----------------------------------------------------------------------
- */
-
-int
-XFillPolygon(
- Display *display,
- Drawable d,
- GC gc,
- XPoint *points,
- int npoints,
- int shape,
- int mode)
-{
- HPEN pen;
- TkWinDCState state;
- HDC dc;
-
- if (d == None) {
- return BadDrawable;
- }
-
- dc = TkWinGetDrawableDC(display, d, &state);
-
- pen = GetStockObject(NULL_PEN);
- RenderObject(dc, gc, points, npoints, mode, pen, Polygon);
-
- TkWinReleaseDrawableDC(d, dc, &state);
- return Success;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * XDrawRectangle --
- *
- * Draws a rectangle.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Draws a rectangle on the specified drawable.
- *
- *----------------------------------------------------------------------
- */
-
-int
-XDrawRectangle(
- Display *display,
- Drawable d,
- GC gc,
- int x, int y,
- unsigned int width, unsigned int height)
-{
- HPEN pen, oldPen;
- TkWinDCState state;
- HBRUSH oldBrush;
- HDC dc;
-
- if (d == None) {
- return BadDrawable;
- }
-
- dc = TkWinGetDrawableDC(display, d, &state);
-
- pen = SetUpGraphicsPort(gc);
- SetBkMode(dc, TRANSPARENT);
- oldPen = SelectObject(dc, pen);
- oldBrush = SelectObject(dc, GetStockObject(NULL_BRUSH));
- SetROP2(dc, tkpWinRopModes[gc->function]);
-
- Rectangle(dc, x, y, (int) x+width+1, (int) y+height+1);
-
- DeleteObject(SelectObject(dc, oldPen));
- SelectObject(dc, oldBrush);
- TkWinReleaseDrawableDC(d, dc, &state);
- return Success;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * XDrawArc --
- *
- * Draw an arc.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Draws an arc on the specified drawable.
- *
- *----------------------------------------------------------------------
- */
-
-int
-XDrawArc(
- Display *display,
- Drawable d,
- GC gc,
- int x, int y,
- unsigned int width, unsigned int height,
- int start, int extent)
-{
- display->request++;
-
- return DrawOrFillArc(display, d, gc, x, y, width, height, start, extent, 0);
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * XFillArc --
- *
- * Draw a filled arc.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Draws a filled arc on the specified drawable.
- *
- *----------------------------------------------------------------------
- */
-
-int
-XFillArc(
- Display *display,
- Drawable d,
- GC gc,
- int x, int y,
- unsigned int width, unsigned int height,
- int start, int extent)
-{
- display->request++;
-
- return DrawOrFillArc(display, d, gc, x, y, width, height, start, extent, 1);
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * DrawOrFillArc --
- *
- * This function handles the rendering of drawn or filled arcs and
- * chords.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Renders the requested arc.
- *
- *----------------------------------------------------------------------
- */
-
-static int
-DrawOrFillArc(
- Display *display,
- Drawable d,
- GC gc,
- int x, int y, /* left top */
- unsigned int width, unsigned int height,
- int start, /* start: three-o'clock (deg*64) */
- int extent, /* extent: relative (deg*64) */
- int fill) /* ==0 draw, !=0 fill */
-{
- HDC dc;
- HBRUSH brush, oldBrush;
- HPEN pen, oldPen;
- TkWinDCState state;
- int clockwise = (extent < 0); /* non-zero if clockwise */
- int xstart, ystart, xend, yend;
- double radian_start, radian_end, xr, yr;
-
- if (d == None) {
- return BadDrawable;
- }
-
- dc = TkWinGetDrawableDC(display, d, &state);
-
- SetROP2(dc, tkpWinRopModes[gc->function]);
-
- /*
- * Compute the absolute starting and ending angles in normalized radians.
- * Swap the start and end if drawing clockwise.
- */
-
- start = start % (64*360);
- if (start < 0) {
- start += (64*360);
- }
- extent = (start+extent) % (64*360);
- if (extent < 0) {
- extent += (64*360);
- }
- if (clockwise) {
- int tmp = start;
- start = extent;
- extent = tmp;
- }
- radian_start = XAngleToRadians(start);
- radian_end = XAngleToRadians(extent);
-
- /*
- * Now compute points on the radial lines that define the starting and
- * ending angles. Be sure to take into account that the y-coordinate
- * system is inverted.
- */
-
- xr = x + width / 2.0;
- yr = y + height / 2.0;
- xstart = (int)((xr + cos(radian_start)*width/2.0) + 0.5);
- ystart = (int)((yr + sin(-radian_start)*height/2.0) + 0.5);
- xend = (int)((xr + cos(radian_end)*width/2.0) + 0.5);
- yend = (int)((yr + sin(-radian_end)*height/2.0) + 0.5);
-
- /*
- * Now draw a filled or open figure. Note that we have to increase the
- * size of the bounding box by one to account for the difference in pixel
- * definitions between X and Windows.
- */
-
- pen = SetUpGraphicsPort(gc);
- oldPen = SelectObject(dc, pen);
- if (!fill) {
- /*
- * Note that this call will leave a gap of one pixel at the end of the
- * arc for thin arcs. We can't use ArcTo because it's only supported
- * under Windows NT.
- */
-
- SetBkMode(dc, TRANSPARENT);
- Arc(dc, x, y, (int) (x+width+1), (int) (y+height+1), xstart, ystart,
- xend, yend);
- } else {
- brush = CreateSolidBrush(gc->foreground);
- oldBrush = SelectObject(dc, brush);
- if (gc->arc_mode == ArcChord) {
- Chord(dc, x, y, (int) (x+width+1), (int) (y+height+1),
- xstart, ystart, xend, yend);
- } else if (gc->arc_mode == ArcPieSlice) {
- Pie(dc, x, y, (int) (x+width+1), (int) (y+height+1),
- xstart, ystart, xend, yend);
- }
- DeleteObject(SelectObject(dc, oldBrush));
- }
- DeleteObject(SelectObject(dc, oldPen));
- TkWinReleaseDrawableDC(d, dc, &state);
- return Success;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * SetUpGraphicsPort --
- *
- * Set up the graphics port from the given GC.
- *
- * Results:
- * None.
- *
- * Side effects:
- * The current port is adjusted.
- *
- *----------------------------------------------------------------------
- */
-
-static HPEN
-SetUpGraphicsPort(
- GC gc)
-{
- DWORD style;
-
- if (gc->line_style == LineOnOffDash) {
- unsigned char *p = (unsigned char *) &(gc->dashes);
- /* pointer to the dash-list */
-
- /*
- * Below is a simple translation of serveral dash patterns to valid
- * windows pen types. Far from complete, but I don't know how to do it
- * better. Any ideas: <mailto:j.nijtmans@chello.nl>
- */
-
- if (p[1] && p[2]) {
- if (!p[3] || p[4]) {
- style = PS_DASHDOTDOT; /* -.. */
- } else {
- style = PS_DASHDOT; /* -. */
- }
- } else {
- if (p[0] > (4 * gc->line_width)) {
- style = PS_DASH; /* - */
- } else {
- style = PS_DOT; /* . */
- }
- }
- } else {
- style = PS_SOLID;
- }
- if (gc->line_width < 2) {
- return CreatePen((int) style, gc->line_width, gc->foreground);
- } else {
- LOGBRUSH lb;
-
- lb.lbStyle = BS_SOLID;
- lb.lbColor = gc->foreground;
- lb.lbHatch = 0;
-
- style |= PS_GEOMETRIC;
- switch (gc->cap_style) {
- case CapNotLast:
- case CapButt:
- style |= PS_ENDCAP_FLAT;
- break;
- case CapRound:
- style |= PS_ENDCAP_ROUND;
- break;
- default:
- style |= PS_ENDCAP_SQUARE;
- break;
- }
- switch (gc->join_style) {
- case JoinMiter:
- style |= PS_JOIN_MITER;
- break;
- case JoinRound:
- style |= PS_JOIN_ROUND;
- break;
- default:
- style |= PS_JOIN_BEVEL;
- break;
- }
- return ExtCreatePen(style, (DWORD) gc->line_width, &lb, 0, NULL);
- }
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * TkScrollWindow --
- *
- * Scroll a rectangle of the specified window and accumulate a damage
- * region.
- *
- * Results:
- * Returns 0 if the scroll genereated no additional damage. Otherwise,
- * sets the region that needs to be repainted after scrolling and returns
- * 1.
- *
- * Side effects:
- * Scrolls the bits in the window.
- *
- *----------------------------------------------------------------------
- */
-
-int
-TkScrollWindow(
- Tk_Window tkwin, /* The window to be scrolled. */
- GC gc, /* GC for window to be scrolled. */
- int x, int y, int width, int height,
- /* Position rectangle to be scrolled. */
- int dx, int dy, /* Distance rectangle should be moved. */
- TkRegion damageRgn) /* Region to accumulate damage in. */
-{
- HWND hwnd = TkWinGetHWND(Tk_WindowId(tkwin));
- RECT scrollRect;
-
- scrollRect.left = x;
- scrollRect.top = y;
- scrollRect.right = x + width;
- scrollRect.bottom = y + height;
- return (ScrollWindowEx(hwnd, dx, dy, &scrollRect, NULL, (HRGN) damageRgn,
- NULL, 0) == NULLREGION) ? 0 : 1;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * TkWinFillRect --
- *
- * This routine fills a rectangle with the foreground color from the
- * specified GC ignoring all other GC values. This is the fastest way to
- * fill a drawable with a solid color.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Modifies the contents of the DC drawing surface.
- *
- *----------------------------------------------------------------------
- */
-
-void
-TkWinFillRect(
- HDC dc,
- int x, int y, int width, int height,
- int pixel)
-{
- RECT rect;
- COLORREF oldColor;
-
- rect.left = x;
- rect.top = y;
- rect.right = x + width;
- rect.bottom = y + height;
- oldColor = SetBkColor(dc, (COLORREF)pixel);
- SetBkMode(dc, OPAQUE);
- ExtTextOut(dc, 0, 0, ETO_OPAQUE, &rect, NULL, 0, NULL);
- SetBkColor(dc, oldColor);
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * TkpDrawHighlightBorder --
- *
- * This function draws a rectangular ring around the outside of a widget
- * to indicate that it has received the input focus.
- *
- * On Windows, we just draw the simple inset ring. On other sytems, e.g.
- * the Mac, the focus ring is a little more complicated, so we need this
- * abstraction.
- *
- * Results:
- * None.
- *
- * Side effects:
- * A rectangle "width" pixels wide is drawn in "drawable", corresponding
- * to the outer area of "tkwin".
- *
- *----------------------------------------------------------------------
- */
-
-void
-TkpDrawHighlightBorder(
- Tk_Window tkwin,
- GC fgGC,
- GC bgGC,
- int highlightWidth,
- Drawable drawable)
-{
- TkDrawInsetFocusHighlight(tkwin, fgGC, highlightWidth, drawable, 0);
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * TkpDrawFrame --
- *
- * This function draws the rectangular frame area.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Draws inside the tkwin area.
- *
- *----------------------------------------------------------------------
- */
-
-void
-TkpDrawFrame(
- Tk_Window tkwin,
- Tk_3DBorder border,
- int highlightWidth,
- int borderWidth,
- int relief)
-{
- Tk_Fill3DRectangle(tkwin, Tk_WindowId(tkwin), border, highlightWidth,
- highlightWidth, Tk_Width(tkwin) - 2 * highlightWidth,
- Tk_Height(tkwin) - 2 * highlightWidth, borderWidth, relief);
-}
-
-/*
- * Local Variables:
- * mode: c
- * c-basic-offset: 4
- * fill-column: 78
- * End:
- */