1/* 2 * tkWinPixmap.c -- 3 * 4 * This file contains the Xlib emulation functions pertaining to 5 * creating and destroying pixmaps. 6 * 7 * Copyright (c) 1995 Sun Microsystems, Inc. 8 * 9 * See the file "license.terms" for information on usage and redistribution 10 * of this file, and for a DISCLAIMER OF ALL WARRANTIES. 11 * 12 * RCS: @(#) $Id: tkWinPixmap.c,v 1.3 2000/02/01 11:41:44 hobbs Exp $ 13 */ 14 15#include "tkWinInt.h" 16 17 18/* 19 *---------------------------------------------------------------------- 20 * 21 * Tk_GetPixmap -- 22 * 23 * Creates an in memory drawing surface. 24 * 25 * Results: 26 * Returns a handle to a new pixmap. 27 * 28 * Side effects: 29 * Allocates a new Win32 bitmap. 30 * 31 *---------------------------------------------------------------------- 32 */ 33 34Pixmap 35Tk_GetPixmap(display, d, width, height, depth) 36 Display* display; 37 Drawable d; 38 int width; 39 int height; 40 int depth; 41{ 42 TkWinDrawable *newTwdPtr, *twdPtr; 43 int planes; 44 Screen *screen; 45 46 display->request++; 47 48 newTwdPtr = (TkWinDrawable*) ckalloc(sizeof(TkWinDrawable)); 49 newTwdPtr->type = TWD_BITMAP; 50 newTwdPtr->bitmap.depth = depth; 51 twdPtr = (TkWinDrawable *)d; 52 if (twdPtr->type != TWD_BITMAP) { 53 if (twdPtr->window.winPtr == NULL) { 54 newTwdPtr->bitmap.colormap = DefaultColormap(display, 55 DefaultScreen(display)); 56 } else { 57 newTwdPtr->bitmap.colormap = twdPtr->window.winPtr->atts.colormap; 58 } 59 } else { 60 newTwdPtr->bitmap.colormap = twdPtr->bitmap.colormap; 61 } 62 screen = &display->screens[0]; 63 planes = 1; 64 if (depth == screen->root_depth) { 65 planes = (int) screen->ext_data; 66 depth /= planes; 67 } 68 newTwdPtr->bitmap.handle = 69 CreateBitmap(width, height, (DWORD) planes, (DWORD) depth, NULL); 70 71 /* 72 * CreateBitmap tries to use memory on the graphics card. If it fails, 73 * call CreateDIBSection which uses real memory; slower, but at least 74 * still works. [Bug 2080533] 75 */ 76 77 if (newTwdPtr->bitmap.handle == NULL) { 78 static int repeatError = 0; 79 unsigned char *bits = NULL; 80 BITMAPINFO bitmapInfo; 81 HDC dc; 82 83 memset(&bitmapInfo, 0, sizeof(bitmapInfo)); 84 bitmapInfo.bmiHeader.biSize = sizeof(bitmapInfo.bmiHeader); 85 bitmapInfo.bmiHeader.biWidth = width; 86 bitmapInfo.bmiHeader.biHeight = height; 87 bitmapInfo.bmiHeader.biPlanes = planes; 88 bitmapInfo.bmiHeader.biBitCount = depth; 89 bitmapInfo.bmiHeader.biCompression = BI_RGB; 90 bitmapInfo.bmiHeader.biSizeImage = 0; 91 dc = GetDC(NULL); 92 newTwdPtr->bitmap.handle = CreateDIBSection(dc, &bitmapInfo, 93 DIB_RGB_COLORS, (void **) &bits, 0, 0); 94 ReleaseDC(NULL, dc); 95 96 /* 97 * Oh no! Things are still going wrong. Pop up a warning message here 98 * (because things will probably crash soon) which will encourage 99 * people to report this as a bug... 100 */ 101 102 if (newTwdPtr->bitmap.handle == NULL && !repeatError) { 103 LPVOID lpMsgBuf; 104 105 repeatError = 1; 106 if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | 107 FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, 108 NULL, GetLastError(), 109 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 110 (LPTSTR) &lpMsgBuf, 0, NULL)) { 111 MessageBox(NULL, (LPCTSTR) lpMsgBuf, 112 "Tk_GetPixmap: Error from CreateDIBSection", 113 MB_OK | MB_ICONINFORMATION); 114 LocalFree(lpMsgBuf); 115 } 116 } 117 } 118 119 if (newTwdPtr->bitmap.handle == NULL) { 120 ckfree((char *) newTwdPtr); 121 return None; 122 } 123 124 return (Pixmap)newTwdPtr; 125} 126 127/* 128 *---------------------------------------------------------------------- 129 * 130 * Tk_FreePixmap -- 131 * 132 * Release the resources associated with a pixmap. 133 * 134 * Results: 135 * None. 136 * 137 * Side effects: 138 * Deletes the bitmap created by Tk_GetPixmap. 139 * 140 *---------------------------------------------------------------------- 141 */ 142 143void 144Tk_FreePixmap(display, pixmap) 145 Display* display; 146 Pixmap pixmap; 147{ 148 TkWinDrawable *twdPtr = (TkWinDrawable *) pixmap; 149 150 display->request++; 151 if (twdPtr != NULL) { 152 DeleteObject(twdPtr->bitmap.handle); 153 ckfree((char *)twdPtr); 154 } 155} 156 157/* 158 *---------------------------------------------------------------------- 159 * 160 * TkSetPixmapColormap -- 161 * 162 * The following function is a hack used by the photo widget to 163 * explicitly set the colormap slot of a Pixmap. 164 * 165 * Results: 166 * None. 167 * 168 * Side effects: 169 * None. 170 * 171 *---------------------------------------------------------------------- 172 */ 173 174void 175TkSetPixmapColormap(pixmap, colormap) 176 Pixmap pixmap; 177 Colormap colormap; 178{ 179 TkWinDrawable *twdPtr = (TkWinDrawable *)pixmap; 180 twdPtr->bitmap.colormap = colormap; 181} 182 183/* 184 *---------------------------------------------------------------------- 185 * 186 * XGetGeometry -- 187 * 188 * Retrieve the geometry of the given drawable. Note that 189 * this is a degenerate implementation that only returns the 190 * size of a pixmap or window. 191 * 192 * Results: 193 * Returns 0. 194 * 195 * Side effects: 196 * None. 197 * 198 *---------------------------------------------------------------------- 199 */ 200 201int 202XGetGeometry(display, d, root_return, x_return, y_return, width_return, 203 height_return, border_width_return, depth_return) 204 Display* display; 205 Drawable d; 206 Window* root_return; 207 int* x_return; 208 int* y_return; 209 unsigned int* width_return; 210 unsigned int* height_return; 211 unsigned int* border_width_return; 212 unsigned int* depth_return; 213{ 214 TkWinDrawable *twdPtr = (TkWinDrawable *)d; 215 216 if (twdPtr->type == TWD_BITMAP) { 217 HDC dc; 218 BITMAPINFO info; 219 220 if (twdPtr->bitmap.handle == NULL) { 221 panic("XGetGeometry: invalid pixmap"); 222 } 223 dc = GetDC(NULL); 224 info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); 225 info.bmiHeader.biBitCount = 0; 226 if (!GetDIBits(dc, twdPtr->bitmap.handle, 0, 0, NULL, &info, 227 DIB_RGB_COLORS)) { 228 panic("XGetGeometry: unable to get bitmap size"); 229 } 230 ReleaseDC(NULL, dc); 231 232 *width_return = info.bmiHeader.biWidth; 233 *height_return = info.bmiHeader.biHeight; 234 } else if (twdPtr->type == TWD_WINDOW) { 235 RECT rect; 236 237 if (twdPtr->window.handle == NULL) { 238 panic("XGetGeometry: invalid window"); 239 } 240 GetClientRect(twdPtr->window.handle, &rect); 241 *width_return = rect.right - rect.left; 242 *height_return = rect.bottom - rect.top; 243 } else { 244 panic("XGetGeometry: invalid window"); 245 } 246 return 1; 247} 248