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