00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "config.h"
00029
00030 #include <stdlib.h>
00031 #include <stdio.h>
00032 #include <string.h>
00033
00034 #include "gdkpixmap.h"
00035 #include "gdkprivate.h"
00036 #include "gdkwin32.h"
00037
00038 typedef struct {
00039 gchar *color_string;
00040 GdkColor color;
00041 gint transparent;
00042 } _GdkPixmapColor;
00043
00044 typedef struct {
00045 guint ncolors;
00046 GdkColormap *colormap;
00047 gulong pixels[1];
00048 } _GdkPixmapInfo;
00049
00050 static void gdk_win32_pixmap_destroy(GdkPixmap * pixmap)
00051 {
00052 GdkDrawablePrivate *private = (GdkDrawablePrivate *) pixmap;
00053
00054 GDK_NOTE(MISC, g_print("gdk_win32_pixmap_destroy: %#x\n",
00055 GDK_DRAWABLE_XID(pixmap)));
00056
00057 if (!DeleteObject(GDK_DRAWABLE_XID(pixmap)))
00058 WIN32_GDI_FAILED("DeleteObject");
00059
00060 gdk_xid_table_remove(GDK_DRAWABLE_XID(pixmap));
00061
00062 g_free(GDK_DRAWABLE_WIN32DATA(pixmap));
00063 }
00064
00065 static GdkDrawable *gdk_win32_pixmap_alloc(void)
00066 {
00067 GdkDrawable *drawable;
00068 GdkDrawablePrivate *private;
00069
00070 static GdkDrawableClass klass;
00071 static gboolean initialized = FALSE;
00072
00073 if (!initialized) {
00074 initialized = TRUE;
00075
00076 klass = _gdk_win32_drawable_class;
00077 klass.destroy = gdk_win32_pixmap_destroy;
00078 }
00079
00080 drawable = gdk_drawable_alloc();
00081 private = (GdkDrawablePrivate *) drawable;
00082
00083 private->klass = &klass;
00084 private->klass_data = g_new(GdkDrawableWin32Data, 1);
00085 private->window_type = GDK_DRAWABLE_PIXMAP;
00086
00087 return drawable;
00088 }
00089
00090 GdkPixmap *gdk_pixmap_new(GdkWindow * window,
00091 gint width, gint height, gint depth)
00092 {
00093 GdkPixmap *pixmap;
00094 GdkDrawablePrivate *private;
00095 struct {
00096 BITMAPINFOHEADER bmiHeader;
00097 union {
00098 WORD bmiIndices[256];
00099 DWORD bmiMasks[3];
00100 RGBQUAD bmiColors[256];
00101 } u;
00102 } bmi;
00103 UINT iUsage;
00104 HDC hdc;
00105 GdkVisual *visual;
00106 guchar *bits;
00107 gint i;
00108
00109 g_return_val_if_fail(window == NULL || GDK_IS_WINDOW(window), NULL);
00110 g_return_val_if_fail((window != NULL) || (depth != -1), NULL);
00111 g_return_val_if_fail((width != 0) && (height != 0), NULL);
00112
00113 if (!window)
00114 window = gdk_parent_root;
00115
00116 if (GDK_DRAWABLE_DESTROYED(window))
00117 return NULL;
00118
00119 if (depth == -1)
00120 depth = gdk_drawable_get_visual(window)->depth;
00121
00122 GDK_NOTE(MISC, g_print("gdk_pixmap_new: %dx%dx%d\n",
00123 width, height, depth));
00124
00125 pixmap = gdk_win32_pixmap_alloc();
00126 private = (GdkDrawablePrivate *) pixmap;
00127
00128 visual = gdk_drawable_get_visual(window);
00129
00130 if ((hdc = GetDC(GDK_DRAWABLE_XID(window))) == NULL) {
00131 WIN32_GDI_FAILED("GetDC");
00132 g_free(private);
00133 return NULL;
00134 }
00135
00136 bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
00137 bmi.bmiHeader.biWidth = width;
00138 bmi.bmiHeader.biHeight = -height;
00139 bmi.bmiHeader.biPlanes = 1;
00140 if (depth == 15)
00141 bmi.bmiHeader.biBitCount = 16;
00142 else
00143 bmi.bmiHeader.biBitCount = depth;
00144 #if 1
00145 if (depth == 16)
00146 bmi.bmiHeader.biCompression = BI_BITFIELDS;
00147 else
00148 #endif
00149 bmi.bmiHeader.biCompression = BI_RGB;
00150 bmi.bmiHeader.biSizeImage = 0;
00151 bmi.bmiHeader.biXPelsPerMeter = bmi.bmiHeader.biYPelsPerMeter = 0;
00152 bmi.bmiHeader.biClrUsed = 0;
00153 bmi.bmiHeader.biClrImportant = 0;
00154
00155 iUsage = DIB_RGB_COLORS;
00156 if (depth == 1) {
00157 bmi.u.bmiColors[0].rgbBlue =
00158 bmi.u.bmiColors[0].rgbGreen = bmi.u.bmiColors[0].rgbRed = 0x00;
00159 bmi.u.bmiColors[0].rgbReserved = 0x00;
00160
00161 bmi.u.bmiColors[1].rgbBlue =
00162 bmi.u.bmiColors[1].rgbGreen = bmi.u.bmiColors[1].rgbRed = 0xFF;
00163 bmi.u.bmiColors[1].rgbReserved = 0x00;
00164 private->colormap = NULL;
00165 } else {
00166 private->colormap = ((GdkWindowPrivate *) window)->drawable.colormap;
00167 if (private->colormap == NULL)
00168 private->colormap = gdk_colormap_get_system();
00169
00170 if (depth == 8) {
00171 iUsage = DIB_PAL_COLORS;
00172 for (i = 0; i < 256; i++)
00173 bmi.u.bmiIndices[i] = i;
00174 } else {
00175 if (depth != visual->depth)
00176 g_warning
00177 ("gdk_pixmap_new: depth %d doesn't match display depth %d",
00178 depth, visual->depth);
00179 #if 1
00180 if (depth == 16) {
00181 bmi.u.bmiMasks[0] = visual->red_mask;
00182 bmi.u.bmiMasks[1] = visual->green_mask;
00183 bmi.u.bmiMasks[2] = visual->blue_mask;
00184 }
00185 #endif
00186 }
00187 }
00188 if ((GDK_DRAWABLE_WIN32DATA(pixmap)->xid =
00189 CreateDIBSection(hdc, (BITMAPINFO *) & bmi,
00190 iUsage, (PVOID *) & bits, NULL, 0)) == NULL) {
00191 WIN32_GDI_FAILED("CreateDIBSection");
00192 ReleaseDC(GDK_DRAWABLE_XID(window), hdc);
00193 g_free(pixmap);
00194 return NULL;
00195 }
00196 ReleaseDC(GDK_DRAWABLE_XID(window), hdc);
00197
00198 GDK_NOTE(MISC, g_print("... = %#x\n", GDK_DRAWABLE_XID(pixmap)));
00199
00200 private->width = width;
00201 private->height = height;
00202
00203 gdk_xid_table_insert(&GDK_DRAWABLE_XID(pixmap), pixmap);
00204
00205 return pixmap;
00206 }
00207
00208 GdkPixmap *gdk_pixmap_create_on_shared_image(GdkImage ** image_return,
00209 GdkWindow * window,
00210 GdkVisual * visual,
00211 gint width,
00212 gint height, gint depth)
00213 {
00214 GdkPixmap *pixmap;
00215 GdkDrawablePrivate *private;
00216
00217 g_return_val_if_fail(window != NULL, NULL);
00218
00219
00220 if (depth == 1)
00221 *image_return =
00222 gdk_image_bitmap_new(GDK_IMAGE_SHARED_PIXMAP, visual, width,
00223 height);
00224 else {
00225 g_return_val_if_fail(depth == visual->depth, NULL);
00226 *image_return =
00227 gdk_image_new(GDK_IMAGE_SHARED_PIXMAP, visual, width, height);
00228 }
00229
00230 g_return_val_if_fail(*image_return != NULL, NULL);
00231
00232 pixmap = gdk_win32_pixmap_alloc();
00233 private = (GdkDrawablePrivate *) pixmap;
00234
00235 GDK_DRAWABLE_WIN32DATA(pixmap)->xid =
00236 ((GdkImagePrivateWin32 *) * image_return)->ximage;
00237 private->colormap = ((GdkWindowPrivate *) window)->drawable.colormap;
00238 private->width = width;
00239 private->height = height;
00240
00241 gdk_xid_table_insert(&GDK_DRAWABLE_XID(pixmap), pixmap);
00242
00243 GDK_NOTE(MISC,
00244 g_print("gdk_pixmap_create_on_shared_image: %dx%dx%d = %#x\n",
00245 width, height, depth, GDK_DRAWABLE_XID(pixmap)));
00246
00247 return pixmap;
00248 }
00249
00250 static unsigned char mirror[256] = {
00251 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
00252 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
00253 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
00254 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
00255 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
00256 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
00257 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
00258 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
00259 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
00260 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
00261 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
00262 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
00263 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
00264 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
00265 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
00266 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
00267 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
00268 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
00269 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
00270 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
00271 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
00272 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
00273 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
00274 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
00275 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
00276 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
00277 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
00278 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
00279 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
00280 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
00281 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
00282 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
00283 };
00284
00285 GdkPixmap *gdk_bitmap_create_from_data(GdkWindow * window,
00286 const gchar * data,
00287 gint width, gint height)
00288 {
00289 GdkPixmap *pixmap;
00290 GdkDrawablePrivate *private;
00291 gint i, j, bpl, aligned_bpl;
00292 guchar *bits;
00293
00294 g_return_val_if_fail(data != NULL, NULL);
00295 g_return_val_if_fail((width != 0) && (height != 0), NULL);
00296 g_return_val_if_fail(window == NULL || GDK_IS_WINDOW(window), NULL);
00297
00298 if (!window)
00299 window = gdk_parent_root;
00300
00301 if (GDK_DRAWABLE_DESTROYED(window))
00302 return NULL;
00303
00304 pixmap = gdk_win32_pixmap_alloc();
00305 private = (GdkDrawablePrivate *) pixmap;
00306
00307 private->width = width;
00308 private->height = height;
00309
00310 bpl = ((width - 1) / 8 + 1);
00311 aligned_bpl = ((bpl - 1) / 2 + 1) * 2;
00312 bits = g_malloc(aligned_bpl * height);
00313 for (i = 0; i < height; i++)
00314 for (j = 0; j < bpl; j++)
00315 bits[i * aligned_bpl + j] = mirror[(guchar) data[i * bpl + j]];
00316
00317 GDK_DRAWABLE_WIN32DATA(pixmap)->xid =
00318 CreateBitmap(width, height, 1, 1, bits);
00319
00320 GDK_NOTE(MISC, g_print("gdk_bitmap_create_from_data: %dx%d = %#x\n",
00321 width, height, GDK_DRAWABLE_XID(pixmap)));
00322
00323 g_free(bits);
00324
00325 private->colormap = NULL;
00326 gdk_xid_table_insert(&GDK_DRAWABLE_XID(pixmap), pixmap);
00327
00328 return pixmap;
00329 }
00330
00331 GdkPixmap *gdk_pixmap_create_from_data(GdkWindow * window,
00332 const gchar * data,
00333 gint width,
00334 gint height,
00335 gint depth,
00336 GdkColor * fg, GdkColor * bg)
00337 {
00338
00339
00340
00341
00342
00343
00344
00345 GdkPixmap *result = gdk_pixmap_new(window, width, height, depth);
00346 GdkPixmap *source =
00347 gdk_bitmap_create_from_data(window, data, width, height);
00348 GdkGC *gc = gdk_gc_new(result);
00349 gdk_gc_set_foreground(gc, fg);
00350 gdk_gc_set_background(gc, bg);
00351 gdk_draw_drawable(result, gc, source, 0, 0, 0, 0, width, height);
00352 gdk_drawable_unref(source);
00353 gdk_gc_unref(gc);
00354
00355 GDK_NOTE(MISC, g_print("gdk_pixmap_create_from_data: %dx%dx%d = %#x\n",
00356 width, height, depth, GDK_DRAWABLE_XID(result)));
00357 return result;
00358 }
00359
00360 static gint
00361 gdk_pixmap_seek_string(FILE * infile,
00362 const gchar * str, gint skip_comments)
00363 {
00364 char instr[1024];
00365
00366 while (!feof(infile)) {
00367 fscanf(infile, "%1023s", instr);
00368 if (skip_comments == TRUE && strcmp(instr, "/*") == 0) {
00369 fscanf(infile, "%1023s", instr);
00370 while (!feof(infile) && strcmp(instr, "*/") != 0)
00371 fscanf(infile, "%1023s", instr);
00372 fscanf(infile, "%1023s", instr);
00373 }
00374 if (strcmp(instr, str) == 0)
00375 return TRUE;
00376 }
00377
00378 return FALSE;
00379 }
00380
00381 static gint gdk_pixmap_seek_char(FILE * infile, gchar c)
00382 {
00383 gint b, oldb;
00384
00385 while ((b = getc(infile)) != EOF) {
00386 if (c != b && b == '/') {
00387 b = getc(infile);
00388 if (b == EOF)
00389 return FALSE;
00390 else if (b == '*') {
00391 b = -1;
00392 do {
00393 oldb = b;
00394 b = getc(infile);
00395 if (b == EOF)
00396 return FALSE;
00397 }
00398 while (!(oldb == '*' && b == '/'));
00399 }
00400 } else if (c == b)
00401 return TRUE;
00402 }
00403 return FALSE;
00404 }
00405
00406 static gint
00407 gdk_pixmap_read_string(FILE * infile, gchar ** buffer, guint * buffer_size)
00408 {
00409 gint c;
00410 guint cnt = 0, bufsiz, ret = FALSE;
00411 gchar *buf;
00412
00413 buf = *buffer;
00414 bufsiz = *buffer_size;
00415 if (buf == NULL) {
00416 bufsiz = 10 * sizeof(gchar);
00417 buf = g_new(gchar, bufsiz);
00418 }
00419
00420 do
00421 c = getc(infile);
00422 while (c != EOF && c != '"');
00423
00424 if (c != '"')
00425 goto out;
00426
00427 while ((c = getc(infile)) != EOF) {
00428 if (cnt == bufsiz) {
00429 guint new_size = bufsiz * 2;
00430 if (new_size > bufsiz)
00431 bufsiz = new_size;
00432 else
00433 goto out;
00434
00435 buf = (gchar *) g_realloc(buf, bufsiz);
00436 buf[bufsiz - 1] = '\0';
00437 }
00438
00439 if (c != '"')
00440 buf[cnt++] = c;
00441 else {
00442 buf[cnt] = 0;
00443 ret = TRUE;
00444 break;
00445 }
00446 }
00447
00448 out:
00449 buf[bufsiz - 1] = '\0';
00450 *buffer = buf;
00451 *buffer_size = bufsiz;
00452 return ret;
00453 }
00454
00455 static gchar *gdk_pixmap_skip_whitespaces(gchar * buffer)
00456 {
00457 gint32 index = 0;
00458
00459 while (buffer[index] != 0
00460 && (buffer[index] == 0x20 || buffer[index] == 0x09))
00461 index++;
00462
00463 return &buffer[index];
00464 }
00465
00466 static gchar *gdk_pixmap_skip_string(gchar * buffer)
00467 {
00468 gint32 index = 0;
00469
00470 while (buffer[index] != 0 && buffer[index] != 0x20
00471 && buffer[index] != 0x09)
00472 index++;
00473
00474 return &buffer[index];
00475 }
00476
00477 #define MAX_COLOR_LEN 120
00478
00479 static gchar *gdk_pixmap_extract_color(gchar * buffer)
00480 {
00481 gint counter, numnames;
00482 gchar *ptr = NULL, ch, temp[128];
00483 gchar color[MAX_COLOR_LEN], *retcol;
00484 gint space;
00485
00486 counter = 0;
00487 while (ptr == NULL) {
00488 if (buffer[counter] == 'c') {
00489 ch = buffer[counter + 1];
00490 if (ch == 0x20 || ch == 0x09)
00491 ptr = &buffer[counter + 1];
00492 } else if (buffer[counter] == 0)
00493 return NULL;
00494
00495 counter++;
00496 }
00497
00498 ptr = gdk_pixmap_skip_whitespaces(ptr);
00499
00500 if (ptr[0] == 0)
00501 return NULL;
00502 else if (ptr[0] == '#') {
00503 counter = 1;
00504 while (ptr[counter] != 0 &&
00505 ((ptr[counter] >= '0' && ptr[counter] <= '9') ||
00506 (ptr[counter] >= 'a' && ptr[counter] <= 'f') ||
00507 (ptr[counter] >= 'A' && ptr[counter] <= 'F')))
00508 counter++;
00509
00510 retcol = g_new(gchar, counter + 1);
00511 strncpy(retcol, ptr, counter);
00512
00513 retcol[counter] = 0;
00514
00515 return retcol;
00516 }
00517
00518 color[0] = 0;
00519 numnames = 0;
00520
00521 space = MAX_COLOR_LEN - 1;
00522 while (space > 0) {
00523 sscanf(ptr, "%127s", temp);
00524
00525 if (((gint) ptr[0] == 0) ||
00526 (strcmp("s", temp) == 0) || (strcmp("m", temp) == 0) ||
00527 (strcmp("g", temp) == 0) || (strcmp("g4", temp) == 0)) {
00528 break;
00529 } else {
00530 if (numnames > 0) {
00531 space -= 1;
00532 strcat(color, " ");
00533 }
00534 strncat(color, temp, space);
00535 space -= MIN(space, (gint)strlen(temp));
00536 ptr = gdk_pixmap_skip_string(ptr);
00537 ptr = gdk_pixmap_skip_whitespaces(ptr);
00538 numnames++;
00539 }
00540 }
00541
00542 retcol = g_strdup(color);
00543 return retcol;
00544 }
00545
00546
00547 enum buffer_op {
00548 op_header,
00549 op_cmap,
00550 op_body
00551 };
00552
00553
00554 static void gdk_xpm_destroy_notify(gpointer data)
00555 {
00556 _GdkPixmapInfo *info = (_GdkPixmapInfo *) data;
00557 GdkColor color;
00558 guint i;
00559
00560 for (i = 0; i < info->ncolors; i++) {
00561 color.pixel = info->pixels[i];
00562 gdk_colormap_free_colors(info->colormap, &color, 1);
00563 }
00564
00565 gdk_colormap_unref(info->colormap);
00566 g_free(info);
00567 }
00568
00569 static GdkPixmap *_gdk_pixmap_create_from_xpm(GdkWindow * window,
00570 GdkColormap * colormap,
00571 GdkBitmap ** mask,
00572 GdkColor * transparent_color,
00573 gchar *
00574 (*get_buf) (enum buffer_op
00575 op,
00576 gpointer handle),
00577 gpointer handle)
00578 {
00579 GdkPixmap *pixmap = NULL;
00580 GdkImage *image = NULL;
00581 GdkVisual *visual;
00582 GdkGC *gc = NULL;
00583 GdkColor tmp_color;
00584 gint width, height, num_cols, cpp, n, ns, cnt, xcnt, ycnt, wbytes;
00585 gchar *buffer, pixel_str[32];
00586 gchar *name_buf;
00587 _GdkPixmapColor *color = NULL, *fallbackcolor = NULL;
00588 _GdkPixmapColor *colors = NULL;
00589 gulong index;
00590 GHashTable *color_hash = NULL;
00591 _GdkPixmapInfo *color_info = NULL;
00592
00593 if ((window == NULL) && (colormap == NULL))
00594 g_warning("Creating pixmap from xpm with NULL window and colormap");
00595
00596 if (window == NULL)
00597 window = gdk_parent_root;
00598
00599 if (colormap == NULL) {
00600 colormap = gdk_drawable_get_colormap(window);
00601 visual = gdk_drawable_get_visual(window);
00602 } else
00603 visual = ((GdkColormapPrivate *) colormap)->visual;
00604
00605 buffer = (*get_buf) (op_header, handle);
00606 if (buffer == NULL)
00607 return NULL;
00608
00609 sscanf(buffer, "%d %d %d %d", &width, &height, &num_cols, &cpp);
00610 if (cpp >= 32) {
00611 g_warning("Pixmap has more than 31 characters per color");
00612 return NULL;
00613 }
00614
00615 color_hash = g_hash_table_new(g_str_hash, g_str_equal);
00616
00617 if (transparent_color == NULL) {
00618 gdk_color_white(colormap, &tmp_color);
00619 transparent_color = &tmp_color;
00620 }
00621
00622
00623
00624
00625 if ((visual->type == GDK_VISUAL_PSEUDO_COLOR) ||
00626 (visual->type == GDK_VISUAL_GRAYSCALE)) {
00627 color_info = g_malloc(sizeof(_GdkPixmapInfo) +
00628 sizeof(gulong) * (num_cols - 1));
00629 color_info->ncolors = num_cols;
00630 color_info->colormap = colormap;
00631 gdk_colormap_ref(colormap);
00632 }
00633
00634 name_buf = g_new(gchar, num_cols * (cpp + 1));
00635 colors = g_new(_GdkPixmapColor, num_cols);
00636
00637 for (cnt = 0; cnt < num_cols; cnt++) {
00638 gchar *color_name;
00639
00640 buffer = (*get_buf) (op_cmap, handle);
00641 if (buffer == NULL)
00642 goto error;
00643
00644 color = &colors[cnt];
00645 color->color_string = &name_buf[cnt * (cpp + 1)];
00646 strncpy(color->color_string, buffer, cpp);
00647 color->color_string[cpp] = 0;
00648 buffer += strlen(color->color_string);
00649 color->transparent = FALSE;
00650
00651 color_name = gdk_pixmap_extract_color(buffer);
00652
00653 if (color_name == NULL ||
00654 gdk_color_parse(color_name, &color->color) == FALSE) {
00655 color->color = *transparent_color;
00656 color->transparent = TRUE;
00657 }
00658
00659 g_free(color_name);
00660
00661
00662
00663 gdk_color_alloc(colormap, &color->color);
00664
00665 if (color_info)
00666 color_info->pixels[cnt] = color->color.pixel;
00667
00668 g_hash_table_insert(color_hash, color->color_string, color);
00669 if (cnt == 0)
00670 fallbackcolor = color;
00671 }
00672
00673 index = 0;
00674 image = gdk_image_new(GDK_IMAGE_FASTEST, visual, width, height);
00675
00676 if (mask) {
00677
00678
00679
00680
00681 GdkColor mask_pattern;
00682
00683 *mask = gdk_pixmap_new(window, width, height, 1);
00684 gc = gdk_gc_new(*mask);
00685
00686 mask_pattern.pixel = 0;
00687 gdk_gc_set_foreground(gc, &mask_pattern);
00688 gdk_draw_rectangle(*mask, gc, TRUE, 0, 0, -1, -1);
00689
00690 mask_pattern.pixel = 1;
00691 gdk_gc_set_foreground(gc, &mask_pattern);
00692 }
00693
00694 wbytes = width * cpp;
00695 for (ycnt = 0; ycnt < height; ycnt++) {
00696 buffer = (*get_buf) (op_body, handle);
00697
00698
00699
00700
00701
00702 if ((buffer == NULL) || (gint)strlen(buffer) < wbytes)
00703 continue;
00704
00705 for (n = 0, cnt = 0, xcnt = 0; n < wbytes; n += cpp, xcnt++) {
00706 strncpy(pixel_str, &buffer[n], cpp);
00707 pixel_str[cpp] = 0;
00708 ns = 0;
00709
00710 color = g_hash_table_lookup(color_hash, pixel_str);
00711
00712 if (!color)
00713 color = fallbackcolor;
00714
00715 gdk_image_put_pixel(image, xcnt, ycnt, color->color.pixel);
00716
00717 if (mask && color->transparent) {
00718 if (cnt < xcnt)
00719 gdk_draw_line(*mask, gc, cnt, ycnt, xcnt - 1, ycnt);
00720 cnt = xcnt + 1;
00721 }
00722 }
00723
00724 if (mask && (cnt < xcnt))
00725 gdk_draw_line(*mask, gc, cnt, ycnt, xcnt - 1, ycnt);
00726 }
00727
00728 error:
00729
00730 if (mask)
00731 gdk_gc_unref(gc);
00732
00733 if (image != NULL) {
00734 pixmap = gdk_pixmap_new(window, width, height, visual->depth);
00735
00736 if (color_info)
00737 gdk_drawable_set_data(pixmap, "gdk-xpm", color_info,
00738 gdk_xpm_destroy_notify);
00739
00740 gc = gdk_gc_new(pixmap);
00741 gdk_gc_set_foreground(gc, transparent_color);
00742 gdk_draw_image(pixmap, gc, image, 0, 0, 0, 0, image->width,
00743 image->height);
00744 gdk_gc_unref(gc);
00745 gdk_image_unref(image);
00746 } else if (color_info)
00747 gdk_xpm_destroy_notify(color_info);
00748
00749 if (color_hash != NULL)
00750 g_hash_table_destroy(color_hash);
00751
00752 if (colors != NULL)
00753 g_free(colors);
00754
00755 if (name_buf != NULL)
00756 g_free(name_buf);
00757
00758 return pixmap;
00759 }
00760
00761
00762 struct file_handle {
00763 FILE *infile;
00764 gchar *buffer;
00765 guint buffer_size;
00766 };
00767
00768
00769 static gchar *file_buffer(enum buffer_op op, gpointer handle)
00770 {
00771 struct file_handle *h = handle;
00772
00773 switch (op) {
00774 case op_header:
00775 if (gdk_pixmap_seek_string(h->infile, "XPM", FALSE) != TRUE)
00776 break;
00777
00778 if (gdk_pixmap_seek_char(h->infile, '{') != TRUE)
00779 break;
00780
00781
00782 case op_cmap:
00783 gdk_pixmap_seek_char(h->infile, '"');
00784 fseek(h->infile, -1, SEEK_CUR);
00785
00786
00787 case op_body:
00788 gdk_pixmap_read_string(h->infile, &h->buffer, &h->buffer_size);
00789 return h->buffer;
00790 }
00791 return 0;
00792 }
00793
00794 GdkPixmap *gdk_pixmap_colormap_create_from_xpm(GdkWindow * window,
00795 GdkColormap * colormap,
00796 GdkBitmap ** mask,
00797 GdkColor *
00798 transparent_color,
00799 const gchar * filename)
00800 {
00801 struct file_handle h;
00802 GdkPixmap *pixmap = NULL;
00803
00804 memset(&h, 0, sizeof(h));
00805 h.infile = fopen(filename, "rb");
00806 if (h.infile != NULL) {
00807 pixmap = _gdk_pixmap_create_from_xpm(window, colormap, mask,
00808 transparent_color,
00809 file_buffer, &h);
00810 fclose(h.infile);
00811 g_free(h.buffer);
00812 }
00813
00814 return pixmap;
00815 }
00816
00817 GdkPixmap *gdk_pixmap_create_from_xpm(GdkWindow * window,
00818 GdkBitmap ** mask,
00819 GdkColor * transparent_color,
00820 const gchar * filename)
00821 {
00822 return gdk_pixmap_colormap_create_from_xpm(window, NULL, mask,
00823 transparent_color, filename);
00824 }
00825
00826 struct mem_handle {
00827 gchar **data;
00828 int offset;
00829 };
00830
00831
00832 static gchar *mem_buffer(enum buffer_op op, gpointer handle)
00833 {
00834 struct mem_handle *h = handle;
00835 switch (op) {
00836 case op_header:
00837 case op_cmap:
00838 case op_body:
00839 if (h->data[h->offset])
00840 return h->data[h->offset++];
00841 }
00842 return 0;
00843 }
00844
00845 GdkPixmap *gdk_pixmap_colormap_create_from_xpm_d(GdkWindow * window,
00846 GdkColormap * colormap,
00847 GdkBitmap ** mask,
00848 GdkColor *
00849 transparent_color,
00850 gchar ** data)
00851 {
00852 struct mem_handle h;
00853 GdkPixmap *pixmap = NULL;
00854
00855 memset(&h, 0, sizeof(h));
00856 h.data = data;
00857 pixmap = _gdk_pixmap_create_from_xpm(window, colormap, mask,
00858 transparent_color, mem_buffer, &h);
00859 return pixmap;
00860 }
00861
00862 GdkPixmap *gdk_pixmap_create_from_xpm_d(GdkWindow * window,
00863 GdkBitmap ** mask,
00864 GdkColor * transparent_color,
00865 gchar ** data)
00866 {
00867 return gdk_pixmap_colormap_create_from_xpm_d(window, NULL, mask,
00868 transparent_color, data);
00869 }
00870
00871 GdkPixmap *gdk_pixmap_foreign_new(guint32 anid)
00872 {
00873 GdkPixmap *pixmap;
00874 GdkDrawablePrivate *private;
00875 HBITMAP xpixmap;
00876 SIZE size;
00877 unsigned int x_ret, y_ret, w_ret, h_ret, bw_ret, depth_ret;
00878
00879
00880
00881 g_return_val_if_fail((anid != 0), NULL);
00882
00883
00884 xpixmap = (HBITMAP) anid;
00885
00886
00887
00888 GetBitmapDimensionEx(xpixmap, &size);
00889 w_ret = size.cx;
00890 h_ret = size.cy;
00891
00892
00893 pixmap = gdk_win32_pixmap_alloc();
00894 private = (GdkDrawablePrivate *) pixmap;
00895
00896 GDK_DRAWABLE_WIN32DATA(pixmap)->xid = xpixmap;
00897 private->colormap = NULL;
00898 private->width = w_ret;
00899 private->height = h_ret;
00900
00901 gdk_xid_table_insert(&GDK_DRAWABLE_XID(pixmap), pixmap);
00902
00903 return pixmap;
00904 }