source: trunk/kitgen/8.x/blt/generic/bltBitmap.c@ 191

Last change on this file since 191 was 175, checked in by demin, 12 years ago

initial commit

File size: 42.2 KB
Line 
1
2/*
3 * bltBitmap.c --
4 *
5 * This module implements Tcl bitmaps for the Tk toolkit.
6 *
7 * Much of the code is taken from XRdBitF.c and XWrBitF.c
8 * from the MIT X11R5 distribution.
9 *
10 * Copyright, 1987, Massachusetts Institute of Technology Permission
11 * to use, copy, modify, distribute, and sell this software and its
12 * documentation for any purpose is hereby granted without fee,
13 * provided that the above copyright notice appear in all copies and
14 * that both that copyright notice and this permission notice appear
15 * in supporting documentation, and that the name of M.I.T. not be
16 * used in advertising or publicity pertaining to distribution of the
17 * software without specific, written prior permission. M.I.T. makes
18 * no representations about the suitability of this software for any
19 * purpose. It is provided "as is" without express or implied
20 * warranty.
21 *
22 * Copyright 1993-1998 Lucent Technologies, Inc.
23 *
24 * Permission to use, copy, modify, and distribute this software and
25 * its documentation for any purpose and without fee is hereby
26 * granted, provided that the above copyright notice appear in all
27 * copies and that both that the copyright notice and warranty
28 * disclaimer appear in supporting documentation, and that the names
29 * of Lucent Technologies any of their entities not be used in
30 * advertising or publicity pertaining to distribution of the software
31 * without specific, written prior permission.
32 *
33 * Lucent Technologies disclaims all warranties with regard to this
34 * software, including all implied warranties of merchantability and
35 * fitness. In no event shall Lucent Technologies be liable for any
36 * special, indirect or consequential damages or any damages
37 * whatsoever resulting from loss of use, data or profits, whether in
38 * an action of contract, negligence or other tortuous action, arising
39 * out of or in connection with the use or performance of this
40 * software.
41 *
42 * The "bitmap" command created by George Howlett. */
43
44/*
45 Predefined table holds bitmap info (source width, height)
46 Name table holds bitmap names
47 Id table hold bitmap ids
48 Both id and name tables get you the actual bitmap.
49 */
50#include "bltInt.h"
51
52#ifndef NO_BITMAP
53#include "bltHash.h"
54#include <X11/Xutil.h>
55
56#define BITMAP_THREAD_KEY "BLT Bitmap Data"
57
58/*
59 * BitmapInterpData --
60 *
61 * Tk's routine to create a bitmap, Tk_DefineBitmap, assumes that
62 * the source (bit array) is always statically allocated. This
63 * isn't true here (we dynamically allocate the arrays), so we have
64 * to save them in a hashtable and cleanup after the interpreter
65 * is deleted.
66 */
67typedef struct {
68 Blt_HashTable bitmapTable; /* Hash table of bitmap data keyed by
69 * the name of the bitmap. */
70 Tcl_Interp *interp;
71 Display *display; /* Display of interpreter. */
72 Tk_Window tkwin; /* Main window of interpreter. */
73} BitmapInterpData;
74
75#define MAX_SIZE 255
76
77/*
78 * BitmapInfo --
79 */
80typedef struct {
81 double rotate; /* Rotation of text string */
82 double scale; /* Scaling factor */
83 Tk_Font font; /* Font pointer */
84 Tk_Justify justify; /* Justify text */
85 Blt_Pad padX, padY; /* Padding around the text */
86} BitmapInfo;
87
88/*
89 * BitmapData --
90 */
91typedef struct {
92 int width, height; /* Dimension of image */
93 unsigned char *bits; /* Data array for bitmap image */
94 int arraySize; /* Number of bytes in data array */
95} BitmapData;
96
97#define DEF_BITMAP_FONT STD_FONT
98#define DEF_BITMAP_PAD "4"
99#define DEF_BITMAP_ROTATE "0.0"
100#define DEF_BITMAP_SCALE "1.0"
101#define DEF_BITMAP_JUSTIFY "center"
102
103#define ROTATE_0 0
104#define ROTATE_90 1
105#define ROTATE_180 2
106#define ROTATE_270 3
107
108
109extern Tk_CustomOption bltPadOption;
110
111static Tk_ConfigSpec composeConfigSpecs[] =
112{
113 {TK_CONFIG_FONT, "-font", (char *)NULL, (char *)NULL,
114 DEF_BITMAP_FONT, Tk_Offset(BitmapInfo, font), 0},
115 {TK_CONFIG_JUSTIFY, "-justify", (char *)NULL, (char *)NULL,
116 DEF_BITMAP_JUSTIFY, Tk_Offset(BitmapInfo, justify),
117 TK_CONFIG_DONT_SET_DEFAULT},
118 {TK_CONFIG_CUSTOM, "-padx", (char *)NULL, (char *)NULL,
119 DEF_BITMAP_PAD, Tk_Offset(BitmapInfo, padX),
120 TK_CONFIG_DONT_SET_DEFAULT, &bltPadOption},
121 {TK_CONFIG_CUSTOM, "-pady", (char *)NULL, (char *)NULL,
122 DEF_BITMAP_PAD, Tk_Offset(BitmapInfo, padY),
123 TK_CONFIG_DONT_SET_DEFAULT, &bltPadOption},
124 {TK_CONFIG_DOUBLE, "-rotate", (char *)NULL, (char *)NULL,
125 DEF_BITMAP_ROTATE, Tk_Offset(BitmapInfo, rotate),
126 TK_CONFIG_DONT_SET_DEFAULT},
127 {TK_CONFIG_DOUBLE, "-scale", (char *)NULL, (char *)NULL,
128 DEF_BITMAP_SCALE, Tk_Offset(BitmapInfo, scale),
129 TK_CONFIG_DONT_SET_DEFAULT},
130 {TK_CONFIG_END, (char *)NULL, (char *)NULL, (char *)NULL,
131 (char *)NULL, 0, 0}
132};
133
134static Tk_ConfigSpec defineConfigSpecs[] =
135{
136 {TK_CONFIG_DOUBLE, "-rotate", (char *)NULL, (char *)NULL,
137 DEF_BITMAP_ROTATE, Tk_Offset(BitmapInfo, rotate),
138 TK_CONFIG_DONT_SET_DEFAULT},
139 {TK_CONFIG_DOUBLE, "-scale", (char *)NULL, (char *)NULL,
140 DEF_BITMAP_SCALE, Tk_Offset(BitmapInfo, scale),
141 TK_CONFIG_DONT_SET_DEFAULT},
142 {TK_CONFIG_END, (char *)NULL, (char *)NULL, (char *)NULL,
143 (char *)NULL, 0, 0}
144};
145
146/* Shared data for the image read/parse logic */
147static char hexTable[256]; /* conversion value */
148static int initialized = 0; /* easier to fill in at run time */
149
150#define blt_width 40
151#define blt_height 40
152static unsigned char blt_bits[] =
153{
154 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0x03, 0x00, 0x04,
155 0x00, 0x00, 0x02, 0x00, 0x04, 0x00, 0x00, 0x02, 0x00, 0xe4, 0x33, 0x3f,
156 0x01, 0x00, 0x64, 0x36, 0x0c, 0x01, 0x00, 0x64, 0x36, 0x8c, 0x00, 0x00,
157 0xe4, 0x33, 0x8c, 0x00, 0x00, 0x64, 0x36, 0x8c, 0x00, 0x00, 0x64, 0x36,
158 0x0c, 0x01, 0x00, 0xe4, 0xf3, 0x0d, 0x01, 0x00, 0x04, 0x00, 0x00, 0x02,
159 0x00, 0x04, 0x00, 0x00, 0x02, 0x00, 0xfc, 0xff, 0xff, 0x03, 0x00, 0x0c,
160 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x0c, 0xf8, 0xff,
161 0x03, 0x80, 0xed, 0x07, 0x00, 0x04, 0xe0, 0x0c, 0x00, 0x20, 0x09, 0x10,
162 0x0c, 0x00, 0x00, 0x12, 0x10, 0x0c, 0x00, 0x00, 0x10, 0x30, 0x00, 0x00,
163 0x00, 0x19, 0xd0, 0x03, 0x00, 0x00, 0x14, 0xb0, 0xfe, 0xff, 0xff, 0x1b,
164 0x50, 0x55, 0x55, 0x55, 0x0d, 0xe8, 0xaa, 0xaa, 0xaa, 0x16, 0xe4, 0xff,
165 0xff, 0xff, 0x2f, 0xf4, 0xff, 0xff, 0xff, 0x27, 0xd8, 0xae, 0xaa, 0xbd,
166 0x2d, 0x6c, 0x5f, 0xd5, 0x67, 0x1b, 0xbc, 0xf3, 0x7f, 0xd0, 0x36, 0xf8,
167 0x01, 0x10, 0xcc, 0x1f, 0xe0, 0x45, 0x8e, 0x92, 0x0f, 0xb0, 0x32, 0x41,
168 0x43, 0x0b, 0xd0, 0xcf, 0x3c, 0x7c, 0x0d, 0xb0, 0xaa, 0xc2, 0xab, 0x0a,
169 0x60, 0x55, 0x55, 0x55, 0x05, 0xc0, 0xff, 0xab, 0xaa, 0x03, 0x00, 0x00,
170 0xfe, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
171};
172
173#define bigblt_width 64
174#define bigblt_height 64
175static unsigned char bigblt_bits[] =
176{
177 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
178 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0x3f, 0x00,
179 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x02, 0x00,
180 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10, 0x00,
181 0x00, 0x00, 0xe2, 0x0f, 0xc7, 0xff, 0x10, 0x00, 0x00, 0x00, 0xe2, 0x1f,
182 0xc7, 0xff, 0x10, 0x00, 0x00, 0x00, 0xe2, 0x38, 0x07, 0x1c, 0x08, 0x00,
183 0x00, 0x00, 0xe2, 0x38, 0x07, 0x1c, 0x08, 0x00, 0x00, 0x00, 0xe2, 0x38,
184 0x07, 0x1c, 0x08, 0x00, 0x00, 0x00, 0xe2, 0x1f, 0x07, 0x1c, 0x04, 0x00,
185 0x00, 0x00, 0xe2, 0x1f, 0x07, 0x1c, 0x04, 0x00, 0x00, 0x00, 0xe2, 0x38,
186 0x07, 0x1c, 0x08, 0x00, 0x00, 0x00, 0xe2, 0x38, 0x07, 0x1c, 0x08, 0x00,
187 0x00, 0x00, 0xe2, 0x38, 0x07, 0x1c, 0x08, 0x00, 0x00, 0x00, 0xe2, 0x1f,
188 0xff, 0x1c, 0x10, 0x00, 0x00, 0x00, 0xe2, 0x0f, 0xff, 0x1c, 0x10, 0x00,
189 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00,
190 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x20, 0x00,
191 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x06, 0x00,
192 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
193 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00,
194 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0xc0, 0xff, 0xff, 0x07, 0x00,
195 0x00, 0xe0, 0xf6, 0x3f, 0x00, 0x00, 0x38, 0x00, 0x00, 0x1c, 0x06, 0x00,
196 0x00, 0x00, 0xc0, 0x00, 0x80, 0x03, 0x06, 0x00, 0x00, 0xc0, 0x08, 0x03,
197 0x40, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x04, 0x40, 0x00, 0x06, 0x00,
198 0x00, 0x00, 0x40, 0x04, 0x40, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x04,
199 0x40, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x04, 0xc0, 0x00, 0x00, 0x00,
200 0x00, 0x00, 0x0c, 0x06, 0x40, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
201 0xc0, 0xfe, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x06, 0x40, 0x55, 0xff, 0xff,
202 0xff, 0xff, 0x7f, 0x05, 0x80, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x06,
203 0x80, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x03, 0x40, 0xab, 0xaa, 0xaa,
204 0xaa, 0xaa, 0xaa, 0x01, 0x70, 0x57, 0x55, 0x55, 0x55, 0x55, 0xd5, 0x04,
205 0x28, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0b, 0xd8, 0xff, 0xff, 0xff,
206 0xff, 0xff, 0xff, 0x14, 0xd0, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0x13,
207 0xf0, 0xda, 0xbf, 0xaa, 0xba, 0xfd, 0xd6, 0x0b, 0x70, 0xed, 0x77, 0x55,
208 0x57, 0xe5, 0xad, 0x07, 0xb8, 0xf7, 0xab, 0xaa, 0xaa, 0xd2, 0x5b, 0x0f,
209 0xf8, 0xfb, 0x54, 0x55, 0x75, 0x94, 0xf7, 0x1e, 0xf0, 0x7b, 0xfa, 0xff,
210 0x9f, 0xa9, 0xef, 0x1f, 0xc0, 0xbf, 0x00, 0x20, 0x40, 0x54, 0xfe, 0x0f,
211 0x00, 0x1f, 0x92, 0x00, 0x04, 0xa9, 0xfc, 0x01, 0xc0, 0x5f, 0x41, 0xf9,
212 0x04, 0x21, 0xfd, 0x00, 0xc0, 0x9b, 0x28, 0x04, 0xd8, 0x0a, 0x9a, 0x03,
213 0x40, 0x5d, 0x08, 0x40, 0x44, 0x44, 0x62, 0x03, 0xc0, 0xaa, 0x67, 0xe2,
214 0x03, 0x64, 0xba, 0x02, 0x40, 0x55, 0xd5, 0x55, 0xfd, 0xdb, 0x55, 0x03,
215 0x80, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x01, 0x00, 0x57, 0x55, 0x55,
216 0x55, 0x55, 0xd5, 0x00, 0x00, 0xac, 0xaa, 0xaa, 0xaa, 0xaa, 0x2a, 0x00,
217 0x00, 0xf0, 0xff, 0x57, 0x55, 0x55, 0x1d, 0x00, 0x00, 0x00, 0x00, 0xf8,
218 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
219 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
220};
221
222static Tcl_CmdProc BitmapCmd;
223static Tcl_InterpDeleteProc BitmapInterpDeleteProc;
224
225/*
226 * -----------------------------------------------------------------------
227 *
228 * GetHexValue --
229 *
230 * Converts the hexadecimal string into an unsigned integer
231 * value. The hexadecimal string need not have a leading "0x".
232 *
233 * Results:
234 * Returns a standard TCL result. If the conversion was
235 * successful, TCL_OK is returned, otherwise TCL_ERROR.
236 *
237 * Side Effects:
238 * If the conversion fails, interp->result is filled with an
239 * error message.
240 *
241 * -----------------------------------------------------------------------
242 */
243static int
244GetHexValue(interp, string, valuePtr)
245 Tcl_Interp *interp;
246 char *string;
247 int *valuePtr;
248{
249 register int c;
250 register char *s;
251 register int value;
252
253 s = string;
254 if ((s[0] == '0') && ((s[1] == 'x') || (s[1] == 'X'))) {
255 s += 2;
256 }
257 if (s[0] == '\0') {
258 Tcl_AppendResult(interp, "expecting hex value: got \"", string, "\"",
259 (char *)NULL);
260 return TCL_ERROR; /* Only found "0x" */
261 }
262 value = 0;
263 for ( /*empty*/ ; *s != '\0'; s++) {
264 /* Trim high bits, check type and accumulate */
265 c = *s & 0xff;
266 if (!isxdigit(c)) {
267 Tcl_AppendResult(interp, "expecting hex value: got \"", string,
268 "\"", (char *)NULL);
269 return TCL_ERROR; /* Not a hexadecimal number */
270 }
271 value = (value << 4) + hexTable[c];
272 }
273 *valuePtr = value;
274 return TCL_OK;
275}
276
277#ifdef WIN32
278/*
279 * -----------------------------------------------------------------------
280 *
281 * BitmapToData --
282 *
283 * Converts a bitmap into an data array.
284 *
285 * Results:
286 * Returns the number of bytes in an data array representing the bitmap.
287 *
288 * Side Effects:
289 * Memory is allocated for the data array. Caller must free
290 * array later.
291 *
292 * -----------------------------------------------------------------------
293 */
294static int
295BitmapToData(
296 Tk_Window tkwin, /* Main window of interpreter */
297 Pixmap bitmap, /* Bitmap to be queried */
298 int width, int height, /* Dimensions of the bitmap */
299 unsigned char **bitsPtr) /* Pointer to converted array of data */
300{
301 int value, bitMask;
302 unsigned long pixel;
303 register int x, y;
304 int count;
305 int arraySize, bytes_per_line;
306 unsigned char *bits;
307 unsigned char *srcPtr, *srcBits;
308 int bytesPerRow;
309
310 *bitsPtr = NULL;
311 srcBits = Blt_GetBitmapData(Tk_Display(tkwin), bitmap, width, height,
312 &bytesPerRow);
313 if (srcBits == NULL) {
314 OutputDebugString("BitmapToData: Can't get bitmap data");
315 return 0;
316 }
317 bytes_per_line = (width + 7) / 8;
318 arraySize = height * bytes_per_line;
319 bits = Blt_Malloc(sizeof(unsigned char) * arraySize);
320 assert(bits);
321 count = 0;
322 for (y = height - 1; y >= 0; y--) {
323 srcPtr = srcBits + (bytesPerRow * y);
324 value = 0, bitMask = 1;
325 for (x = 0; x < width; /* empty */ ) {
326 pixel = (*srcPtr & (0x80 >> (x % 8)));
327 if (pixel) {
328 value |= bitMask;
329 }
330 bitMask <<= 1;
331 x++;
332 if (!(x & 7)) {
333 bits[count++] = (unsigned char)value;
334 value = 0, bitMask = 1;
335 srcPtr++;
336 }
337 }
338 if (x & 7) {
339 bits[count++] = (unsigned char)value;
340 }
341 }
342 *bitsPtr = bits;
343 return count;
344}
345
346#else
347
348/*
349 * -----------------------------------------------------------------------
350 *
351 * BitmapToData --
352 *
353 * Converts a bitmap into an data array.
354 *
355 * Results:
356 * Returns the number of bytes in an data array representing the bitmap.
357 *
358 * Side Effects:
359 * Memory is allocated for the data array. Caller must free
360 * array later.
361 *
362 * -----------------------------------------------------------------------
363 */
364static int
365BitmapToData(tkwin, bitmap, width, height, bitsPtr)
366 Tk_Window tkwin; /* Main window of interpreter */
367 Pixmap bitmap; /* Bitmap to be queried */
368 int width, height; /* Dimensions of the bitmap */
369 unsigned char **bitsPtr; /* Pointer to converted array of data */
370{
371 int value, bitMask;
372 unsigned long pixel;
373 register int x, y;
374 int count;
375 int arraySize, bytes_per_line;
376 Display *display;
377 XImage *imagePtr;
378 unsigned char *bits;
379
380 display = Tk_Display(tkwin);
381 /* Convert the bitmap to an image */
382 imagePtr = XGetImage(display, bitmap, 0, 0, width, height, 1L, XYPixmap);
383 /*
384 * The slow but robust brute force method of converting an image:
385 */
386 bytes_per_line = (width + 7) / 8;
387 arraySize = height * bytes_per_line;
388 bits = Blt_Malloc(sizeof(unsigned char) * arraySize);
389 assert(bits);
390 count = 0;
391 for (y = 0; y < height; y++) {
392 value = 0, bitMask = 1;
393 for (x = 0; x < width; /*empty*/ ) {
394 pixel = XGetPixel(imagePtr, x, y);
395 if (pixel) {
396 value |= bitMask;
397 }
398 bitMask <<= 1;
399 x++;
400 if (!(x & 7)) {
401 bits[count++] = (unsigned char)value;
402 value = 0, bitMask = 1;
403 }
404 }
405 if (x & 7) {
406 bits[count++] = (unsigned char)value;
407 }
408 }
409 XDestroyImage(imagePtr);
410 *bitsPtr = bits;
411 return count;
412}
413
414#endif
415
416/*
417 * -----------------------------------------------------------------------
418 *
419 * AsciiToData --
420 *
421 * Converts a Tcl list of ASCII values into a data array.
422 *
423 * Results:
424 * A standard TCL result.
425 *
426 * Side Effects:
427 * If an error occurs while processing the data, interp->result
428 * is filled with a corresponding error message.
429 *
430 * -----------------------------------------------------------------------
431 */
432static int
433AsciiToData(interp, elemList, width, height, bitsPtr)
434 Tcl_Interp *interp; /* Interpreter to report results to */
435 char *elemList; /* List of of hex numbers representing
436 * bitmap data */
437 int width, height; /* Height and width */
438 unsigned char **bitsPtr; /* data array (output) */
439{
440 int arraySize; /* Number of bytes of data */
441 int value; /* from an input line */
442 int padding; /* to handle alignment */
443 int bytesPerLine; /* per scanline of data */
444 unsigned char *bits;
445 register int count;
446 enum Formats {
447 V10, V11
448 } format;
449 register int i; /* */
450 char **valueArr;
451 int nValues;
452
453 /* First time through initialize the ascii->hex translation table */
454 if (!initialized) {
455 Blt_InitHexTable(hexTable);
456 initialized = 1;
457 }
458 if (Tcl_SplitList(interp, elemList, &nValues, &valueArr) != TCL_OK) {
459 return -1;
460 }
461 bytesPerLine = (width + 7) / 8;
462 arraySize = bytesPerLine * height;
463 if (nValues == arraySize) {
464 format = V11;
465 } else if (nValues == (arraySize / 2)) {
466 format = V10;
467 } else {
468 Tcl_AppendResult(interp, "bitmap has wrong # of data values",
469 (char *)NULL);
470 goto error;
471 }
472 padding = 0;
473 if (format == V10) {
474 padding = ((width % 16) && ((width % 16) < 9));
475 if (padding) {
476 bytesPerLine = (width + 7) / 8 + padding;
477 arraySize = bytesPerLine * height;
478 }
479 }
480 bits = Blt_Calloc(sizeof(unsigned char), arraySize);
481 if (bits == NULL) {
482 Tcl_AppendResult(interp, "can't allocate memory for bitmap",
483 (char *)NULL);
484 goto error;
485 }
486 count = 0;
487 for (i = 0; i < nValues; i++) {
488 if (GetHexValue(interp, valueArr[i], &value) != TCL_OK) {
489 Blt_Free(bits);
490 goto error;
491 }
492 bits[count++] = (unsigned char)value;
493 if (format == V10) {
494 if ((!padding) || (((i * 2) + 2) % bytesPerLine)) {
495 bits[count++] = value >> 8;
496 }
497 }
498 }
499 Blt_Free(valueArr);
500 *bitsPtr = bits;
501 return count;
502 error:
503 Blt_Free(valueArr);
504 return -1;
505}
506
507
508static int
509ParseListData(interp, string, widthPtr, heightPtr, bitsPtr)
510 Tcl_Interp *interp;
511 char *string;
512 int *widthPtr;
513 int *heightPtr;
514 unsigned char **bitsPtr;
515{
516 register char *p;
517 char **elemArr;
518 int nElem;
519 int width, height;
520 int result;
521 int arraySize;
522
523 arraySize = -1;
524 if (Tcl_SplitList(interp, string, &nElem, &elemArr) != TCL_OK) {
525 return -1;
526 }
527 if (nElem == 2) {
528 char **dimArr;
529 int nDim;
530
531 if (Tcl_SplitList(interp, elemArr[0], &nDim, &dimArr) != TCL_OK) {
532 goto error;
533 }
534 if (nDim != 2) {
535 Tcl_AppendResult(interp, "wrong # of bitmap dimensions: ",
536 "should be \"width height\"", (char *)NULL);
537 result = TCL_ERROR;
538 } else {
539 result = ((Tcl_GetInt(interp, dimArr[0], &width) == TCL_OK) &&
540 (Tcl_GetInt(interp, dimArr[1], &height) == TCL_OK));
541 }
542 Blt_Free(dimArr);
543 if (!result) {
544 goto error;
545 }
546 string = elemArr[1];
547 } else if (nElem == 3) {
548 if ((Tcl_GetInt(interp, elemArr[0], &width) != TCL_OK) ||
549 (Tcl_GetInt(interp, elemArr[1], &height) != TCL_OK)) {
550 goto error;
551 }
552 string = elemArr[2];
553 } else {
554 Tcl_AppendResult(interp, "wrong # of bitmap data components: ",
555 "should be \"dimensions sourceData\"", (char *)NULL);
556 goto error;
557 }
558 if ((width < 1) || (height < 1)) {
559 Tcl_AppendResult(interp, "bad bitmap dimensions", (char *)NULL);
560 goto error;
561 }
562 /* Convert commas to blank spaces */
563
564 for (p = string; *p != '\0'; p++) {
565 if (*p == ',') {
566 *p = ' ';
567 }
568 }
569 arraySize = AsciiToData(interp, string, width, height, bitsPtr);
570 *widthPtr = width;
571 *heightPtr = height;
572 error:
573 Blt_Free(elemArr);
574 return arraySize;
575}
576
577/*
578 * Parse the lines that define the dimensions of the bitmap,
579 * plus the first line that defines the bitmap data (it declares
580 * the name of a data variable but doesn't include any actual
581 * data). These lines look something like the following:
582 *
583 * #define foo_width 16
584 * #define foo_height 16
585 * #define foo_x_hot 3
586 * #define foo_y_hot 3
587 * static char foo_bits[] = {
588 *
589 * The x_hot and y_hot lines may or may not be present. It's
590 * important to check for "char" in the last line, in order to
591 * reject old X10-style bitmaps that used shorts.
592 */
593
594static int
595ParseStructData(interp, string, widthPtr, heightPtr, bitsPtr)
596 Tcl_Interp *interp;
597 char *string;
598 int *widthPtr;
599 int *heightPtr;
600 unsigned char **bitsPtr;
601{
602 int width, height;
603 int hotX, hotY;
604 char *line, *nextline;
605 register char *p;
606 Tcl_RegExp re;
607 char *name, *value, *data;
608 int len;
609 int arraySize;
610
611 width = height = 0;
612 hotX = hotY = -1;
613 data = NULL;
614 nextline = string;
615 for (line = string; nextline != NULL; line = nextline + 1) {
616 nextline = strchr(line, '\n');
617 if ((nextline == NULL) || (line == nextline)) {
618 continue; /* Empty line */
619 }
620 *nextline = '\0';
621 re = Tcl_RegExpCompile(interp, " *# *define +");
622 if (Tcl_RegExpExec(interp, re, line, line)) {
623 char *start, *end;
624
625 Tcl_RegExpRange(re, 0, &start, &end);
626 name = strtok(end, " \t");
627 value = strtok(NULL, " \t");
628 if ((name == NULL) || (value == NULL)) {
629 return TCL_ERROR;
630 }
631 len = strlen(name);
632 if ((len >= 6) && (name[len-6] == '_') &&
633 (strcmp(name+len-6, "_width") == 0)) {
634 if (Tcl_GetInt(interp, value, &width) != TCL_OK) {
635 return -1;
636 }
637 } else if ((len >= 7) && (name[len-7] == '_') &&
638 (strcmp(name+len-7, "_height") == 0)) {
639 if (Tcl_GetInt(interp, value, &height) != TCL_OK) {
640 return -1;
641 }
642 } else if ((len >= 6) && (name[len-6] == '_') &&
643 (strcmp(name+len-6, "_x_hot") == 0)) {
644 if (Tcl_GetInt(interp, value, &hotX) != TCL_OK) {
645 return -1;
646 }
647 } else if ((len >= 6) && (name[len-6] == '_') &&
648 (strcmp(name+len-6, "_y_hot") == 0)) {
649 if (Tcl_GetInt(interp, value, &hotY) != TCL_OK) {
650 return -1;
651 }
652 }
653 } else {
654 re = Tcl_RegExpCompile(interp, " *static +.*char +");
655 if (Tcl_RegExpExec(interp, re, line, line)) {
656 /* Find the { */
657 /* Repair the string so we can search the entire string. */
658 *nextline = ' ';
659 p = strchr(line, '{');
660 if (p == NULL) {
661 return -1;
662 }
663 data = p + 1;
664 break;
665 } else {
666 Tcl_AppendResult(interp, "unknown bitmap format: ",
667 "obsolete X10 bitmap file?", (char *) NULL);
668 return -1;
669 }
670 }
671 }
672 /*
673 * Now we've read everything but the data. Allocate an array
674 * and read in the data.
675 */
676 if ((width <= 0) || (height <= 0)) {
677 Tcl_AppendResult(interp, "invalid bitmap dimensions \"", (char *)NULL);
678 Tcl_AppendResult(interp, Blt_Itoa(width), " x ", (char *)NULL);
679 Tcl_AppendResult(interp, Blt_Itoa(height), "\"", (char *)NULL);
680 return -1;
681 }
682 *widthPtr = width;
683 *heightPtr = height;
684 for (p = data; *p != '\0'; p++) {
685 if ((*p == ',') || (*p == ';') || (*p == '}')) {
686 *p = ' ';
687 }
688 }
689 arraySize = AsciiToData(interp, data, width, height, bitsPtr);
690 return arraySize;
691}
692
693/*
694 * -----------------------------------------------------------------------
695 *
696 * ScaleRotateData --
697 *
698 * Creates a new data array of the rotated and scaled bitmap.
699 *
700 * Results:
701 * A standard Tcl result. If the bitmap data is rotated
702 * successfully, TCL_OK is returned. But if memory could not be
703 * allocated for the new data array, TCL_ERROR is returned and an
704 * error message is left in interp->result.
705 *
706 * Side Effects:
707 * Memory is allocated for rotated, scaled data array. Caller
708 * must free array later.
709 *
710 * -----------------------------------------------------------------------
711 */
712static int
713ScaleRotateData(
714 Tcl_Interp *interp, /* Interpreter to report results to */
715 BitmapData *srcPtr, /* Source bitmap to transform. */
716 double theta, /* Number of degrees to rotate the bitmap. */
717 double scale, /* Factor to scale the bitmap. */
718 BitmapData *destPtr) /* Destination bitmap. */
719{
720 register int x, y, sx, sy;
721 double srcX, srcY, destX, destY; /* Origins of source and destination
722 * bitmaps */
723 double dx, dy;
724 double sinTheta, cosTheta;
725 double rotWidth, rotHeight;
726 double radians;
727 unsigned char *bits;
728 int arraySize;
729 int pixel, ipixel;
730 int srcBytesPerLine, destBytesPerLine;
731
732 srcBytesPerLine = (srcPtr->width + 7) / 8;
733 Blt_GetBoundingBox(srcPtr->width, srcPtr->height, theta, &rotWidth,
734 &rotHeight, (Point2D *)NULL);
735 destPtr->width = (int)(rotWidth * scale + 0.5) ;
736 destPtr->height = (int)(rotHeight * scale + 0.5);
737
738 destBytesPerLine = (destPtr->width + 7) / 8;
739 arraySize = destPtr->height * destBytesPerLine;
740 bits = Blt_Calloc(arraySize, sizeof(unsigned char));
741 if (bits == NULL) {
742 Tcl_AppendResult(interp, "can't allocate bitmap data array",
743 (char *)NULL);
744 return TCL_ERROR;
745 }
746 scale = 1.0 / scale;
747 destPtr->bits = bits;
748 destPtr->arraySize = arraySize;
749
750 radians = (theta / 180.0) * M_PI;
751 sinTheta = sin(radians);
752 cosTheta = cos(radians);
753
754 /*
755 * Coordinates of the centers of the source and destination rectangles
756 */
757 srcX = srcPtr->width * 0.5;
758 srcY = srcPtr->height * 0.5;
759 destX = rotWidth * 0.5;
760 destY = rotHeight * 0.5;
761
762 /*
763 * Rotate each pixel of dest image, placing results in source image
764 */
765 for (y = 0; y < destPtr->height; y++) {
766 for (x = 0; x < destPtr->width; x++) {
767 dx = scale * (double)x;
768 dy = scale * (double)y;
769 if (theta == 270.0) {
770 sx = (int)dy, sy = (int)(rotWidth - dx) - 1;
771 } else if (theta == 180.0) {
772 sx = (int)(rotWidth - dx) - 1, sy = (int)(rotHeight - dy) - 1;
773 } else if (theta == 90.0) {
774 sx = (int)(rotHeight - dy) - 1, sy = (int)dx;
775 } else if (theta == 0.0) {
776 sx = (int)dx, sy = (int)dy;
777 } else {
778 double transX, transY, rotX, rotY;
779 /* Translate origin to center of destination image */
780
781 transX = dx - destX;
782 transY = dy - destY;
783
784 /* Rotate the coordinates about the origin */
785
786 rotX = (transX * cosTheta) - (transY * sinTheta);
787 rotY = (transX * sinTheta) + (transY * cosTheta);
788
789 /* Translate back to the center of the source image */
790 rotX += srcX;
791 rotY += srcY;
792
793 sx = ROUND(rotX);
794 sy = ROUND(rotY);
795
796 /*
797 * Verify the coordinates, since the destination image
798 * can be bigger than the source.
799 */
800
801 if ((sx >= srcPtr->width) || (sx < 0) ||
802 (sy >= srcPtr->height) || (sy < 0)) {
803 continue;
804 }
805 }
806 ipixel = (srcBytesPerLine * sy) + (sx / 8);
807 pixel = srcPtr->bits[ipixel] & (1 << (sx % 8));
808 if (pixel) {
809 ipixel = (destBytesPerLine * y) + (x / 8);
810 bits[ipixel] |= (1 << (x % 8));
811 }
812 }
813 }
814 return TCL_OK;
815}
816
817/*
818 * -----------------------------------------------------------------------
819 *
820 * BitmapDataToString --
821 *
822 * Returns a list of hex values corresponding to the data
823 * bits of the bitmap given.
824 *
825 * Converts the unsigned character value into a two character
826 * hexadecimal string. A separator is also added, which may
827 * either a newline or space according the the number of bytes
828 * already output.
829 *
830 * Results:
831 * Returns TCL_ERROR if a data array can't be generated
832 * from the bitmap (memory allocation failure), otherwise TCL_OK.
833 *
834 * -----------------------------------------------------------------------
835 */
836static void
837BitmapDataToString(tkwin, bitmap, resultPtr)
838 Tk_Window tkwin; /* Main window of interpreter */
839 Pixmap bitmap; /* Bitmap to be queried */
840 Tcl_DString *resultPtr; /* Dynamic string to output results to */
841{
842 unsigned char *bits;
843 char *separator;
844 int arraySize;
845 register int i;
846 char string[200];
847 int width, height;
848
849 /* Get the dimensions of the bitmap */
850 Tk_SizeOfBitmap(Tk_Display(tkwin), bitmap, &width, &height);
851 arraySize = BitmapToData(tkwin, bitmap, width, height, &bits);
852#define BYTES_PER_OUTPUT_LINE 24
853 for (i = 0; i < arraySize; i++) {
854 separator = (i % BYTES_PER_OUTPUT_LINE) ? " " : "\n ";
855 sprintf(string, "%s%02x", separator, bits[i]);
856 Tcl_DStringAppend(resultPtr, string, -1);
857 }
858 if (bits != NULL) {
859 Blt_Free(bits);
860 }
861}
862
863/*
864 *--------------------------------------------------------------
865 *
866 * ComposeOp --
867 *
868 * Converts the text string into an internal bitmap.
869 *
870 * There's a lot of extra (read unnecessary) work going on here,
871 * but I don't (right now) think that it matters much. The
872 * rotated bitmap (formerly an image) is converted back to an
873 * image just so we can convert it to a data array for
874 * Tk_DefineBitmap.
875 *
876 * Results:
877 * A standard TCL result.
878 *
879 * Side Effects:
880 * If an error occurs while processing the data, interp->result
881 * is filled with a corresponding error message.
882 *
883 *--------------------------------------------------------------
884 */
885static int
886ComposeOp(clientData, interp, argc, argv)
887 ClientData clientData; /* Thread-specific data for bitmaps. */
888 Tcl_Interp *interp; /* Interpreter to report results to */
889 int argc; /* Number of arguments */
890 char **argv; /* Argument list */
891{
892 BitmapInterpData *dataPtr = clientData;
893 int width, height; /* Dimensions of bitmap */
894 Pixmap bitmap; /* Text bitmap */
895 unsigned char *bits; /* Data array derived from text bitmap */
896 int arraySize;
897 BitmapInfo info; /* Text rotation and font information */
898 int result;
899 double theta;
900 TextStyle ts;
901 TextLayout *textPtr;
902 Tk_Window tkwin; /* Main window of interpreter */
903 Blt_HashEntry *hPtr;
904 int isNew;
905
906 tkwin = dataPtr->tkwin;
907 bitmap = Tk_GetBitmap(interp, tkwin, Tk_GetUid(argv[2]));
908 Tcl_ResetResult(interp);
909 if (bitmap != None) {
910 Tk_FreeBitmap(dataPtr->display, bitmap);
911 return TCL_OK;
912 }
913 /* Initialize info and process flags */
914 info.justify = TK_JUSTIFY_CENTER;
915 info.rotate = 0.0; /* No rotation or scaling by default */
916 info.scale = 1.0;
917 info.padLeft = info.padRight = 0;
918 info.padTop = info.padBottom = 0;
919 info.font = (Tk_Font)NULL; /* Initialized by Tk_ConfigureWidget */
920 if (Tk_ConfigureWidget(interp, tkwin, composeConfigSpecs,
921 argc - 4, argv + 4, (char *)&info, 0) != TCL_OK) {
922 return TCL_ERROR;
923 }
924 theta = FMOD(info.rotate, (double)360.0);
925 if (theta < 0.0) {
926 theta += 360.0;
927 }
928 Blt_InitTextStyle(&ts);
929 ts.font = info.font;
930 ts.theta = 0.0;
931 ts.justify = info.justify;
932 ts.padX = info.padX;
933 ts.padY = info.padY;
934 ts.leader = 0;
935 ts.anchor = TK_ANCHOR_CENTER;
936
937 textPtr = Blt_GetTextLayout(argv[3], &ts);
938 bitmap = Blt_CreateTextBitmap(tkwin, textPtr, &ts, &width, &height);
939 Blt_Free(textPtr);
940 if (bitmap == None) {
941 Tcl_AppendResult(interp, "can't create bitmap", (char *)NULL);
942 return TCL_ERROR;
943 }
944 /* Free the font structure, since we don't need it anymore */
945 Tk_FreeOptions(composeConfigSpecs, (char *)&info, dataPtr->display, 0);
946
947 /* Convert bitmap back to a data array */
948 arraySize = BitmapToData(tkwin, bitmap, width, height, &bits);
949 Tk_FreePixmap(dataPtr->display, bitmap);
950 if (arraySize == 0) {
951 Tcl_AppendResult(interp, "can't get bitmap data", (char *)NULL);
952 return TCL_ERROR;
953 }
954 /* If bitmap is to be rotated or scale, do it here */
955 if ((theta != 0.0) || (info.scale != 1.0)) {
956 BitmapData srcData, destData;
957
958 srcData.bits = bits;
959 srcData.width = width;
960 srcData.height = height;
961 srcData.arraySize = arraySize;
962
963 result = ScaleRotateData(interp, &srcData, theta, info.scale,
964 &destData);
965 Blt_Free(bits); /* Free the un-transformed data array. */
966 if (result != TCL_OK) {
967 return TCL_ERROR;
968 }
969 bits = destData.bits;
970 width = destData.width;
971 height = destData.height;
972 }
973 /* Create the bitmap again, this time using Tk's bitmap facilities */
974 result = Tk_DefineBitmap(interp, Tk_GetUid(argv[2]), (char *)bits,
975 width, height);
976 if (result != TCL_OK) {
977 Blt_Free(bits);
978 }
979 hPtr = Blt_CreateHashEntry(&(dataPtr->bitmapTable), argv[2], &isNew);
980 Blt_SetHashValue(hPtr, bits);
981 return result;
982}
983
984/*
985 *--------------------------------------------------------------
986 *
987 * DefineOp --
988 *
989 * Converts the dataList into an internal bitmap.
990 *
991 * Results:
992 * A standard TCL result.
993 *
994 * Side Effects:
995 * If an error occurs while processing the data, interp->result
996 * is filled with a corresponding error message.
997 *
998 *--------------------------------------------------------------
999 */
1000/* ARGSUSED */
1001static int
1002DefineOp(clientData, interp, argc, argv)
1003 ClientData clientData; /* Thread-specific data for bitmaps. */
1004 Tcl_Interp *interp; /* Interpreter to report results to */
1005 int argc; /* Number of arguments */
1006 char **argv; /* Argument list */
1007{
1008 BitmapInterpData *dataPtr = clientData;
1009 int width, height; /* Dimensions of bitmap */
1010 unsigned char *bits; /* working variable */
1011 register char *p;
1012 char *defn; /* Definition of bitmap. */
1013 BitmapInfo info; /* Not used. */
1014 int arraySize;
1015 int result;
1016 double theta;
1017 Pixmap bitmap;
1018 Blt_HashEntry *hPtr;
1019 int isNew;
1020
1021 bitmap = Tk_GetBitmap(interp, dataPtr->tkwin, Tk_GetUid(argv[2]));
1022 Tcl_ResetResult(interp);
1023 if (bitmap != None) {
1024 Tk_FreeBitmap(dataPtr->display, bitmap);
1025 return TCL_OK;
1026 }
1027 /* Initialize info and then process flags */
1028 info.rotate = 0.0; /* No rotation by default */
1029 info.scale = 1.0; /* No scaling by default */
1030 if (Tk_ConfigureWidget(interp, dataPtr->tkwin, defineConfigSpecs,
1031 argc - 4, argv + 4, (char *)&info, 0) != TCL_OK) {
1032 return TCL_ERROR;
1033 }
1034 /* Skip leading spaces. */
1035 for (p = argv[3]; isspace(UCHAR(*p)); p++) {
1036 /*empty*/
1037 }
1038 defn = Blt_Strdup(p);
1039 bits = NULL;
1040 if (*p == '#') {
1041 arraySize = ParseStructData(interp, defn, &width, &height, &bits);
1042 } else {
1043 arraySize = ParseListData(interp, defn, &width, &height, &bits);
1044 }
1045 Blt_Free(defn);
1046 if (arraySize <= 0) {
1047 return TCL_ERROR;
1048 }
1049 theta = FMOD(info.rotate, 360.0);
1050 if (theta < 0.0) {
1051 theta += 360.0;
1052 }
1053 /* If bitmap is to be rotated or scale, do it here */
1054 if ((theta != 0.0) || (info.scale != 1.0)) {
1055 BitmapData srcData, destData;
1056
1057 srcData.bits = bits;
1058 srcData.width = width;
1059 srcData.height = height;
1060 srcData.arraySize = arraySize;
1061
1062 result = ScaleRotateData(interp, &srcData, theta, info.scale,
1063 &destData);
1064 Blt_Free(bits); /* Free the array of un-transformed data. */
1065 if (result != TCL_OK) {
1066 return TCL_ERROR;
1067 }
1068 bits = destData.bits;
1069 width = destData.width;
1070 height = destData.height;
1071 }
1072 result = Tk_DefineBitmap(interp, Tk_GetUid(argv[2]), (char *)bits,
1073 width, height);
1074 if (result != TCL_OK) {
1075 Blt_Free(bits);
1076 }
1077 hPtr = Blt_CreateHashEntry(&(dataPtr->bitmapTable), argv[2], &isNew);
1078 Blt_SetHashValue(hPtr, bits);
1079 return result;
1080}
1081
1082/*
1083 *--------------------------------------------------------------
1084 *
1085 * ExistOp --
1086 *
1087 * Indicates if the named bitmap exists.
1088 *
1089 *--------------------------------------------------------------
1090 */
1091/*ARGSUSED*/
1092static int
1093ExistsOp(clientData, interp, argc, argv)
1094 ClientData clientData; /* Thread-specific data for bitmaps. */
1095 Tcl_Interp *interp; /* Interpreter to report results to */
1096 int argc; /* Not used. */
1097 char **argv; /* Argument list */
1098{
1099 BitmapInterpData *dataPtr = clientData;
1100 Pixmap bitmap;
1101
1102 bitmap = Tk_GetBitmap(interp, dataPtr->tkwin, Tk_GetUid(argv[2]));
1103 Tcl_ResetResult(interp);
1104 if (bitmap != None) {
1105 Tk_FreeBitmap(dataPtr->display, bitmap);
1106 }
1107 Blt_SetBooleanResult(interp, (bitmap != None));
1108 return TCL_OK;
1109}
1110
1111/*
1112 *--------------------------------------------------------------
1113 *
1114 * HeightOp --
1115 *
1116 * Returns the height of the named bitmap.
1117 *
1118 *--------------------------------------------------------------
1119 */
1120/*ARGSUSED*/
1121static int
1122HeightOp(clientData, interp, argc, argv)
1123 ClientData clientData; /* Thread-specific data for bitmaps. */
1124 Tcl_Interp *interp; /* Interpreter to report results to */
1125 int argc; /* Not used. */
1126 char **argv; /* Argument list */
1127{
1128 BitmapInterpData *dataPtr = clientData;
1129 int width, height;
1130 Pixmap bitmap;
1131
1132 bitmap = Tk_GetBitmap(interp, dataPtr->tkwin, Tk_GetUid(argv[2]));
1133 if (bitmap == None) {
1134 return TCL_ERROR;
1135 }
1136 Tk_SizeOfBitmap(dataPtr->display, bitmap, &width, &height);
1137 Tcl_SetResult(interp, Blt_Itoa(height), TCL_VOLATILE);
1138 Tk_FreeBitmap(dataPtr->display, bitmap);
1139 return TCL_OK;
1140}
1141
1142/*
1143 *--------------------------------------------------------------
1144 *
1145 * WidthOp --
1146 *
1147 * Returns the width of the named bitmap.
1148 *
1149 *--------------------------------------------------------------
1150 */
1151/*ARGSUSED*/
1152static int
1153WidthOp(clientData, interp, argc, argv)
1154 ClientData clientData; /* Thread-specific data for bitmaps. */
1155 Tcl_Interp *interp; /* Interpreter to report results to */
1156 int argc; /* Not used. */
1157 char **argv; /* Argument list */
1158{
1159 BitmapInterpData *dataPtr = clientData;
1160 int width, height;
1161 Pixmap bitmap;
1162
1163 bitmap = Tk_GetBitmap(interp, dataPtr->tkwin, Tk_GetUid(argv[2]));
1164 if (bitmap == None) {
1165 return TCL_ERROR;
1166 }
1167 Tk_SizeOfBitmap(dataPtr->display, bitmap, &width, &height);
1168 Tcl_SetResult(interp, Blt_Itoa(width), TCL_VOLATILE);
1169 Tk_FreeBitmap(dataPtr->display, bitmap);
1170 return TCL_OK;
1171}
1172
1173/*
1174 *--------------------------------------------------------------
1175 *
1176 * SourceOp --
1177 *
1178 * Returns the data array (excluding width and height)
1179 * of the named bitmap.
1180 *
1181 *--------------------------------------------------------------
1182 */
1183/*ARGSUSED*/
1184static int
1185SourceOp(clientData, interp, argc, argv)
1186 ClientData clientData; /* Thread-specific data for bitmaps. */
1187 Tcl_Interp *interp; /* Interpreter to report results to */
1188 int argc; /* Not used. */
1189 char **argv; /* Argument list */
1190{
1191 BitmapInterpData *dataPtr = clientData;
1192 Pixmap bitmap;
1193 Tcl_DString dString;
1194
1195 bitmap = Tk_GetBitmap(interp, dataPtr->tkwin, Tk_GetUid(argv[2]));
1196 if (bitmap == None) {
1197 return TCL_ERROR;
1198 }
1199 Tcl_DStringInit(&dString);
1200 BitmapDataToString(dataPtr->tkwin, bitmap, &dString);
1201 Tk_FreeBitmap(dataPtr->display, bitmap);
1202 Tcl_DStringResult(interp, &dString);
1203 return TCL_OK;
1204}
1205
1206/*
1207 *--------------------------------------------------------------
1208 *
1209 * DataOp --
1210 *
1211 * Returns the data array, including width and height,
1212 * of the named bitmap.
1213 *
1214 *--------------------------------------------------------------
1215 */
1216/*ARGSUSED*/
1217static int
1218DataOp(clientData, interp, argc, argv)
1219 ClientData clientData; /* Thread-specific data for bitmaps. */
1220 Tcl_Interp *interp; /* Interpreter to report results to */
1221 int argc; /* Not used. */
1222 char **argv; /* Argument list */
1223{
1224 BitmapInterpData *dataPtr = clientData;
1225 Pixmap bitmap;
1226 int width, height;
1227 Tcl_DString dString;
1228
1229 bitmap = Tk_GetBitmap(interp, dataPtr->tkwin, Tk_GetUid(argv[2]));
1230 if (bitmap == None) {
1231 return TCL_ERROR;
1232 }
1233 Tk_SizeOfBitmap(dataPtr->display, bitmap, &width, &height);
1234 Tcl_DStringInit(&dString);
1235 Tcl_DStringAppendElement(&dString, Blt_Itoa(width));
1236 Tcl_DStringAppendElement(&dString, Blt_Itoa(height));
1237 Tcl_DStringStartSublist(&dString);
1238 BitmapDataToString(dataPtr->tkwin, bitmap, &dString);
1239 Tcl_DStringEndSublist(&dString);
1240 Tk_FreeBitmap(dataPtr->display, bitmap);
1241 Tcl_DStringResult(interp, &dString);
1242 return TCL_OK;
1243}
1244
1245/*
1246 *--------------------------------------------------------------
1247 *
1248 * BLT Sub-command specification:
1249 *
1250 * - Name of the sub-command.
1251 * - Minimum number of characters needed to unambiguously
1252 * recognize the sub-command.
1253 * - Pointer to the function to be called for the sub-command.
1254 * - Minimum number of arguments accepted.
1255 * - Maximum number of arguments accepted.
1256 * - String to be displayed for usage.
1257 *
1258 *--------------------------------------------------------------
1259 */
1260static Blt_OpSpec bitmapOps[] =
1261{
1262 {"compose", 1, (Blt_Op)ComposeOp, 4, 0, "bitmapName text ?flags?",},
1263 {"data", 2, (Blt_Op)DataOp, 3, 3, "bitmapName",},
1264 {"define", 2, (Blt_Op)DefineOp, 4, 0, "bitmapName data ?flags?",},
1265 {"exists", 1, (Blt_Op)ExistsOp, 3, 3, "bitmapName",},
1266 {"height", 1, (Blt_Op)HeightOp, 3, 3, "bitmapName",},
1267 {"source", 1, (Blt_Op)SourceOp, 3, 3, "bitmapName",},
1268 {"width", 1, (Blt_Op)WidthOp, 3, 3, "bitmapName",},
1269};
1270static int nBitmapOps = sizeof(bitmapOps) / sizeof(Blt_OpSpec);
1271
1272/*
1273 *--------------------------------------------------------------
1274 *
1275 * BitmapCmd --
1276 *
1277 * This procedure is invoked to process the Tcl command
1278 * that corresponds to bitmaps managed by this module.
1279 * See the user documentation for details on what it does.
1280 *
1281 * Results:
1282 * A standard Tcl result.
1283 *
1284 * Side effects:
1285 * See the user documentation.
1286 *
1287 *--------------------------------------------------------------
1288 */
1289/*ARGSUSED*/
1290static int
1291BitmapCmd(clientData, interp, argc, argv)
1292 ClientData clientData; /* Thread-specific data for bitmaps. */
1293 Tcl_Interp *interp; /* Interpreter to report results to */
1294 int argc;
1295 char **argv;
1296{
1297 Blt_Op proc;
1298 int result;
1299
1300 proc = Blt_GetOp(interp, nBitmapOps, bitmapOps, BLT_OP_ARG1, argc, argv,0);
1301 if (proc == NULL) {
1302 return TCL_ERROR;
1303 }
1304 result = (*proc) (clientData, interp, argc, argv);
1305 return result;
1306}
1307
1308/*
1309 * -----------------------------------------------------------------------
1310 *
1311 * BitmapInterpDeleteProc --
1312 *
1313 * This is called when the interpreter is deleted. All the tiles
1314 * are specific to that interpreter are destroyed.
1315 *
1316 * Results:
1317 * None.
1318 *
1319 * Side effects:
1320 * Destroys the tile table.
1321 *
1322 * ------------------------------------------------------------------------
1323 */
1324/* ARGSUSED */
1325static void
1326BitmapInterpDeleteProc(clientData, interp)
1327 ClientData clientData; /* Thread-specific data. */
1328 Tcl_Interp *interp;
1329{
1330 BitmapInterpData *dataPtr = clientData;
1331 Blt_HashEntry *hPtr;
1332 unsigned char *bits;
1333 Blt_HashSearch cursor;
1334
1335 for (hPtr = Blt_FirstHashEntry(&(dataPtr->bitmapTable), &cursor);
1336 hPtr != NULL; hPtr = Blt_NextHashEntry(&cursor)) {
1337 bits = (unsigned char *)Blt_GetHashValue(hPtr);
1338 Blt_Free(bits);
1339 }
1340 Blt_DeleteHashTable(&(dataPtr->bitmapTable));
1341 Tcl_DeleteAssocData(interp, BITMAP_THREAD_KEY);
1342 Blt_Free(dataPtr);
1343}
1344
1345static BitmapInterpData *
1346GetBitmapInterpData(interp)
1347 Tcl_Interp *interp;
1348{
1349 BitmapInterpData *dataPtr;
1350 Tcl_InterpDeleteProc *proc;
1351
1352 dataPtr = (BitmapInterpData *)
1353 Tcl_GetAssocData(interp, BITMAP_THREAD_KEY, &proc);
1354 if (dataPtr == NULL) {
1355 dataPtr = Blt_Malloc(sizeof(BitmapInterpData));
1356 assert(dataPtr);
1357 dataPtr->interp = interp;
1358 dataPtr->tkwin = Tk_MainWindow(interp);
1359 dataPtr->display = Tk_Display(dataPtr->tkwin);
1360 Tcl_SetAssocData(interp, BITMAP_THREAD_KEY, BitmapInterpDeleteProc,
1361 dataPtr);
1362 Blt_InitHashTable(&(dataPtr->bitmapTable), BLT_STRING_KEYS);
1363 }
1364 return dataPtr;
1365}
1366
1367/*
1368 *--------------------------------------------------------------
1369 *
1370 * Blt_BitmapInit --
1371 *
1372 * This procedure is invoked to initialize the bitmap command.
1373 *
1374 * Results:
1375 * None.
1376 *
1377 * Side effects:
1378 * Adds the command to the interpreter and sets an array variable
1379 * which its version number.
1380 *
1381 *--------------------------------------------------------------
1382 */
1383int
1384Blt_BitmapInit(interp)
1385 Tcl_Interp *interp;
1386{
1387 BitmapInterpData *dataPtr;
1388 static Blt_CmdSpec cmdSpec =
1389 {"bitmap", BitmapCmd};
1390
1391 /* Define the BLT logo bitmaps */
1392
1393 dataPtr = GetBitmapInterpData(interp);
1394 cmdSpec.clientData = dataPtr;
1395 if (Blt_InitCmd(interp, "blt", &cmdSpec) == NULL) {
1396 return TCL_ERROR;
1397 }
1398 Tk_DefineBitmap(interp, Tk_GetUid("bigBLT"), (char *)bigblt_bits,
1399 bigblt_width, bigblt_height);
1400 Tk_DefineBitmap(interp, Tk_GetUid("BLT"), (char *)blt_bits,
1401 blt_width, blt_height);
1402 Tcl_ResetResult(interp);
1403 return TCL_OK;
1404}
1405
1406#endif /* NO_BITMAP */
Note: See TracBrowser for help on using the repository browser.