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