📄 tkwindraw.c
字号:
/* * 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. * * SCCS: @(#) tkWinDraw.c 1.30 97/03/21 11:20:05 */#include "tkWinInt.h"/* * These macros convert between X's bizarre angle units to radians. */#define PI 3.14159265358979#define XAngleToRadians(a) ((double)(a) / 64 * PI / 180);/* * Translation table between X gc functions and Win32 raster op modes. */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) */static int bltModes[] = { 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. */#define MIN(a,b) ((a>b) ? b : a)#define MAX(a,b) ((a<b) ? b : a)/* * The followng typedef is used to pass Windows GDI drawing functions. */typedef BOOL (CALLBACK *WinDrawFunc) _ANSI_ARGS_((HDC dc, CONST POINT* points, int npoints));/* * Forward declarations for procedures defined in this file: */static POINT * ConvertPoints _ANSI_ARGS_((XPoint *points, int npoints, int mode, RECT *bbox));static void DrawOrFillArc _ANSI_ARGS_((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 _ANSI_ARGS_((HDC dc, GC gc, XPoint* points, int npoints, int mode, HPEN pen, WinDrawFunc func));/* *---------------------------------------------------------------------- * * 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. * *---------------------------------------------------------------------- */HDCTkWinGetDrawableDC(display, d, state) 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); 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. * *---------------------------------------------------------------------- */voidTkWinReleaseDrawableDC(d, dc, state) Drawable d; HDC dc; TkWinDCState *state;{ TkWinDrawable *twdPtr = (TkWinDrawable *)d; 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 that should not be freed. * *---------------------------------------------------------------------- */static POINT *ConvertPoints(points, npoints, mode, bbox) XPoint *points; int npoints; 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. */ 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 > nWinPoints) { if (winPoints != NULL) { ckfree((char *) winPoints); } winPoints = (POINT *) ckalloc(sizeof(POINT) * npoints); if (winPoints == NULL) { nWinPoints = -1; return NULL; } 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++) { 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); } } else { winPoints[0].x = points[0].x; 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); } } return 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. * *---------------------------------------------------------------------- */voidXCopyArea(display, src, dest, gc, src_x, src_y, width, height, dest_x, dest_y) Display* display; Drawable src; Drawable dest; GC gc; int src_x, src_y; unsigned int width, height; int dest_x, 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, width, height, srcDC, src_x, src_y, bltModes[gc->function]); SelectClipRgn(destDC, NULL); if (src != dest) { TkWinReleaseDrawableDC(dest, destDC, &destState); } TkWinReleaseDrawableDC(src, srcDC, &srcState);}/* *---------------------------------------------------------------------- * * 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. * *---------------------------------------------------------------------- */voidXCopyPlane(display, src, dest, gc, src_x, src_y, width, height, dest_x, dest_y, plane) Display* display; Drawable src; Drawable dest; GC gc; int src_x, src_y; unsigned int width, height; int dest_x, 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) { 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, width, 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); BitBlt(destDC, dest_x, dest_y, width, 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.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -