📄 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));#define F_POLYGON 0#define F_POLYLINE 1#define POLYFUNC(functype,hdc,lp,count) \ functype==F_POLYGON?CkPolygon(hdc,lp,count):CkPolyline(hdc,lp,count)/* * 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, int functype));static double mycos(double val){ return cos(val);}static double mysin(double val){ return sin(val);}#ifdef USE_CKGRAPH_IMP int tkWinHashBrushs=1; int tkWinHashPens=1;#endif#ifdef USE_CKGRAPH_IMPHDC TkWinGetNULLDC(void){ return CkGraph_GetHashedDC();}void TkWinReleaseNULLDC(HDC hdc){ CkGraph_ReleaseHashedDC(hdc);}#else /*USE_CKGRAPH_IMP*/HDC TkWinGetNULLDC(void){ return GetDC(NULL);}void TkWinReleaseNULLDC(HDC hdc){ ReleaseDC(NULL,hdc);}#endif /*USE_CKGRAPH_IMP*/HBRUSH TkWinCreateSolidBrush(GC gc,COLORREF color){#ifdef USE_CKGRAPH_IMP if (tkpIsWin32s || tkWinHashBrushs==0 ) #endif return CkCreateSolidBrush(color);#ifdef USE_CKGRAPH_IMP if(color==gc->foreground){ return (HBRUSH)((gc->fgBrush==None)? gc->fgBrush=(unsigned int)CkCreateSolidBrush(gc->foreground): gc->fgBrush); } else if(color==gc->background) { return (HBRUSH)((gc->bgBrush==None)? gc->bgBrush=(unsigned int)CkCreateSolidBrush(gc->background): gc->bgBrush); } else { return CkCreateSolidBrush(color); }#endif}BOOL TkWinDeleteBrush(GC gc,HBRUSH hBrush){#ifdef USE_CKGRAPH_IMP if (tkpIsWin32s || tkWinHashBrushs==0 ) #endif return CkDeleteBrush(hBrush);#ifdef USE_CKGRAPH_IMP/* * let the brushs allocated until GC is destroyed * except this is a temporary allocated brush */ if(hBrush!=(HBRUSH)gc->bgBrush && hBrush!=(HBRUSH)gc->fgBrush){ return CkDeleteBrush(hBrush); } return TRUE;#endif}static HPEN TkWinExtCreatePen(GC gc,DWORD style,DWORD width,CONST LOGBRUSH* lb, DWORD count,CONST DWORD* lp){#ifdef USE_CKGRAPH_IMP if (tkpIsWin32s || tkWinHashPens==0 ) #endif return CkExtCreatePen(style, width, lb, count, lp);#ifdef USE_CKGRAPH_IMP if(gc->fgExtPen==None){ goto done; } else if (style!=gc->extpenstyle){ CkDeletePen((HPEN)gc->fgExtPen); goto done; } else { return (HPEN)gc->fgExtPen; }done: gc->extpenstyle=style; return (HPEN) (gc->fgExtPen=(unsigned int)CkExtCreatePen(style, width, lb, count, lp));#endif}static HPEN TkWinCreatePen(GC gc,int style,int width,COLORREF color){#ifdef USE_CKGRAPH_IMP if (tkpIsWin32s || tkWinHashPens==0 ) #endif return CkCreatePen(style,width,color);#ifdef USE_CKGRAPH_IMP return (HPEN)((gc->fgPen==None)? gc->fgPen=(unsigned int)CkCreatePen(style,width,color): gc->fgPen);#endif}static BOOL TkWinDeletePen(GC gc,HPEN hPen){#ifdef USE_CKGRAPH_IMP if (tkpIsWin32s || tkWinHashPens==0 ) #endif return CkDeletePen(hPen);#ifdef USE_CKGRAPH_IMP/* * let the pens allocated until GC is destroyed * except this is a temporary allocated brush */ return TRUE;#endif}/* *---------------------------------------------------------------------- * * 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; GTRACE(("begin TkWinGetDrawableDC\n");) if (twdPtr->type == TWD_WINDOW) { TkWindow *winPtr = twdPtr->window.winPtr; dc = CkGetDC(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 {#ifdef USE_CKGRAPH_IMP dc = CkGraph_GetHashedDC();#else dc = CkCreateCompatibleDC(NULL);#endif#ifdef USE_CKGRAPH_IMP#ifdef CKGRAPH_DEBUG CkGraph_CheckSelectedBitmap(dc, twdPtr->bitmap.handle);#endif#endif CkSelectBitmap(dc, twdPtr->bitmap.handle); cmap = twdPtr->bitmap.colormap; } state->palette = TkWinSelectPalette(dc, cmap); GTRACE(("end TkWinGetDrawableDC\n");) 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; GTRACE(("begin TkWinReleaseDrawableDC\n");)#ifndef USE_CKGRAPH_IMP CkSelectPalette(dc, state->palette, TRUE); CkRealizePalette(dc);#endif if (twdPtr->type == TWD_WINDOW) { CkReleaseDC(TkWinGetHWND(d), dc); } else if (twdPtr->type == TWD_BITMAP) {#ifdef USE_CKGRAPH_IMP CkGraph_ReleaseHashedDC(dc);#else CkDeleteDC(dc);#endif } GTRACE(("end TkWinReleaseDrawableDC\n");)}/* *---------------------------------------------------------------------- * * 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; GTRACE(("begin XCopyArea\n");) srcDC = TkWinGetDrawableDC(display, src, &srcState); if (src != dest) { destDC = TkWinGetDrawableDC(display, dest, &destState); } else { destDC = srcDC; } if (clipPtr && clipPtr->type == TKP_CLIP_REGION) { CkSelectClipRgn(destDC, (HRGN) clipPtr->value.region); CkOffsetClipRgn(destDC, gc->clip_x_origin, gc->clip_y_origin); } CkBitBlt(destDC, dest_x, dest_y, width, height, srcDC, src_x, src_y, bltModes[gc->function]); CkSelectClipRgn(destDC, NULL); if (src != dest) { TkWinReleaseDrawableDC(dest, destDC, &destState); } TkWinReleaseDrawableDC(src, srcDC, &srcState); GTRACE(("end XCopyArea\n");)}/* *---------------------------------------------------------------------- * * 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; #ifndef USE_CKGRAPH_IMP HBRUSH oldBrush;#endif TkpClipMask *clipPtr = (TkpClipMask*)gc->clip_mask; GTRACE(("begin XCopyPlane\n");) 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) { //this sometimes fail in BLT-Graph, dunno why CkSelectClipRgn(destDC, (HRGN) clipPtr->value.region); CkOffsetClipRgn(destDC, gc->clip_x_origin, gc->clip_y_origin); } CkSetBkMode(destDC, OPAQUE); CkSetBkColor(destDC, gc->foreground); CkSetTextColor(destDC, gc->background); CkBitBlt(destDC, dest_x, dest_y, width, height, srcDC, src_x, src_y, SRCCOPY); CkSelectClipRgn(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. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -