diff options
Diffstat (limited to 'tk/win/tkWinDraw.c')
-rw-r--r-- | tk/win/tkWinDraw.c | 253 |
1 files changed, 163 insertions, 90 deletions
diff --git a/tk/win/tkWinDraw.c b/tk/win/tkWinDraw.c index 445166705d8..eafe1effd78 100644 --- a/tk/win/tkWinDraw.c +++ b/tk/win/tkWinDraw.c @@ -106,6 +106,12 @@ static int bltModes[] = { typedef BOOL (CALLBACK *WinDrawFunc) _ANSI_ARGS_((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 procedures defined in this file: */ @@ -119,6 +125,7 @@ static void DrawOrFillArc _ANSI_ARGS_((Display *display, static void RenderObject _ANSI_ARGS_((HDC dc, GC gc, XPoint* points, int npoints, int mode, HPEN pen, WinDrawFunc func)); +static HPEN SetUpGraphicsPort _ANSI_ARGS_((GC gc)); /* *---------------------------------------------------------------------- @@ -166,6 +173,7 @@ TkWinGetDrawableDC(display, d, state) cmap = twdPtr->bitmap.colormap; } state->palette = TkWinSelectPalette(dc, cmap); + state->bkmode = GetBkMode(dc); return dc; } @@ -192,6 +200,7 @@ TkWinReleaseDrawableDC(d, dc, state) TkWinDCState *state; { TkWinDrawable *twdPtr = (TkWinDrawable *)d; + SetBkMode(dc, state->bkmode); SelectPalette(dc, state->palette, TRUE); RealizePalette(dc); if (twdPtr->type == TWD_WINDOW) { @@ -212,7 +221,8 @@ TkWinReleaseDrawableDC(d, dc, state) * Returns the converted array of POINTs. * * Side effects: - * Allocates a block of memory that should not be freed. + * Allocates a block of memory in thread local storage that + * should not be freed. * *---------------------------------------------------------------------- */ @@ -224,8 +234,8 @@ ConvertPoints(points, npoints, mode, bbox) int mode; /* CoordModeOrigin or CoordModePrevious. */ RECT *bbox; /* Bounding box of points. */ { - static POINT *winPoints = NULL; /* Array of points that is reused. */ - static int nWinPoints = -1; /* Current size of point array. */ + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); int i; /* @@ -233,16 +243,16 @@ ConvertPoints(points, npoints, mode, bbox) * we reuse the last array if it is large enough. */ - if (npoints > nWinPoints) { - if (winPoints != NULL) { - ckfree((char *) winPoints); + if (npoints > tsdPtr->nWinPoints) { + if (tsdPtr->winPoints != NULL) { + ckfree((char *) tsdPtr->winPoints); } - winPoints = (POINT *) ckalloc(sizeof(POINT) * npoints); - if (winPoints == NULL) { - nWinPoints = -1; + tsdPtr->winPoints = (POINT *) ckalloc(sizeof(POINT) * npoints); + if (tsdPtr->winPoints == NULL) { + tsdPtr->nWinPoints = -1; return NULL; } - nWinPoints = npoints; + tsdPtr->nWinPoints = npoints; } bbox->left = bbox->right = points[0].x; @@ -250,26 +260,26 @@ ConvertPoints(points, npoints, mode, bbox) if (mode == CoordModeOrigin) { for (i = 0; i < npoints; i++) { - winPoints[i].x = points[i].x; - winPoints[i].y = points[i].y; - bbox->left = MIN(bbox->left, winPoints[i].x); - bbox->right = MAX(bbox->right, winPoints[i].x); - bbox->top = MIN(bbox->top, winPoints[i].y); - bbox->bottom = MAX(bbox->bottom, winPoints[i].y); + 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 { - winPoints[0].x = points[0].x; - winPoints[0].y = points[0].y; + tsdPtr->winPoints[0].x = points[0].x; + tsdPtr->winPoints[0].y = points[0].y; for (i = 1; i < npoints; i++) { - winPoints[i].x = winPoints[i-1].x + points[i].x; - winPoints[i].y = winPoints[i-1].y + points[i].y; - bbox->left = MIN(bbox->left, winPoints[i].x); - bbox->right = MAX(bbox->right, winPoints[i].x); - bbox->top = MIN(bbox->top, winPoints[i].y); - bbox->bottom = MAX(bbox->bottom, winPoints[i].y); + 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 winPoints; + return tsdPtr->winPoints; } /* @@ -555,33 +565,7 @@ TkPutImage(colors, ncolors, display, d, gc, image, src_x, src_y, dest_x, infoPtr->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); infoPtr->bmiHeader.biWidth = image->width; - - /* - * The following code works around a bug in Win32s. CreateDIBitmap - * fails under Win32s for top-down images. So we have to reverse the - * order of the scanlines. If we are not running under Win32s, we can - * just declare the image to be top-down. - */ - - if (tkpIsWin32s) { - int y; - char *srcPtr, *dstPtr, *temp; - - temp = ckalloc((unsigned) image->bytes_per_line); - srcPtr = image->data; - dstPtr = image->data+(image->bytes_per_line * (image->height - 1)); - for (y = 0; y < (image->height/2); y++) { - memcpy(temp, srcPtr, image->bytes_per_line); - memcpy(srcPtr, dstPtr, image->bytes_per_line); - memcpy(dstPtr, temp, image->bytes_per_line); - srcPtr += image->bytes_per_line; - dstPtr -= image->bytes_per_line; - } - ckfree(temp); - infoPtr->bmiHeader.biHeight = image->height; /* Bottom-up order */ - } else { - infoPtr->bmiHeader.biHeight = -image->height; /* Top-down order */ - } + infoPtr->bmiHeader.biHeight = -image->height; /* Top-down order */ infoPtr->bmiHeader.biPlanes = 1; infoPtr->bmiHeader.biBitCount = image->bits_per_pixel; infoPtr->bmiHeader.biCompression = BI_RGB; @@ -881,42 +865,8 @@ XDrawLines(display, d, gc, points, npoints, mode) dc = TkWinGetDrawableDC(display, d, &state); - if (!tkpIsWin32s && (gc->line_width > 1)) { - LOGBRUSH lb; - DWORD style; - - lb.lbStyle = BS_SOLID; - lb.lbColor = gc->foreground; - lb.lbHatch = 0; - - style = PS_GEOMETRIC|PS_COSMETIC; - 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; - } - pen = ExtCreatePen(style, gc->line_width, &lb, 0, NULL); - } else { - pen = CreatePen(PS_SOLID, gc->line_width, gc->foreground); - } + pen = SetUpGraphicsPort(gc); + SetBkMode(dc, TRANSPARENT); RenderObject(dc, gc, points, npoints, mode, pen, Polyline); DeleteObject(pen); @@ -1002,7 +952,8 @@ XDrawRectangle(display, d, gc, x, y, width, height) dc = TkWinGetDrawableDC(display, d, &state); - pen = CreatePen(PS_SOLID, gc->line_width, gc->foreground); + pen = SetUpGraphicsPort(gc); + SetBkMode(dc, TRANSPARENT); oldPen = SelectObject(dc, pen); oldBrush = SelectObject(dc, GetStockObject(NULL_BRUSH)); SetROP2(dc, tkpWinRopModes[gc->function]); @@ -1164,7 +1115,7 @@ DrawOrFillArc(display, d, gc, x, y, width, height, start, extent, fill) * difference in pixel definitions between X and Windows. */ - pen = CreatePen(PS_SOLID, gc->line_width, gc->foreground); + pen = SetUpGraphicsPort(gc); oldPen = SelectObject(dc, pen); if (!fill) { /* @@ -1173,6 +1124,7 @@ DrawOrFillArc(display, d, gc, x, y, width, height, start, extent, fill) * it's only supported under Windows NT. */ + SetBkMode(dc, TRANSPARENT); Arc(dc, x, y, x+width+1, y+height+1, xstart, ystart, xend, yend); } else { brush = CreateSolidBrush(gc->foreground); @@ -1191,6 +1143,92 @@ DrawOrFillArc(display, d, gc, x, y, width, height, start, extent, fill) /* *---------------------------------------------------------------------- * + * SetUpGraphicsPort -- + * + * Set up the graphics port from the given GC. + * + * Results: + * None. + * + * Side effects: + * The current port is adjusted. + * + *---------------------------------------------------------------------- + */ + +static HPEN +SetUpGraphicsPort(gc) + 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(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, gc->line_width, &lb, 0, NULL); + } +} + +/* + *---------------------------------------------------------------------- + * * TkScrollWindow -- * * Scroll a rectangle of the specified window and accumulate @@ -1262,3 +1300,38 @@ TkWinFillRect(dc, x, y, width, height, pixel) ExtTextOut(dc, 0, 0, ETO_OPAQUE, &rect, NULL, 0, NULL); SetBkColor(dc, oldColor); } + +/* + *---------------------------------------------------------------------- + * + * TkpDrawHighlightBorder -- + * + * This procedure 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(tkwin, fgGC, bgGC, highlightWidth, drawable) + Tk_Window tkwin; + GC fgGC; + GC bgGC; + int highlightWidth; + Drawable drawable; +{ + TkDrawInsetFocusHighlight(tkwin, fgGC, highlightWidth, drawable, 0); +} + + |