5ec80c9f644a19fb93c38e05345038f7bfd253bd
1 #define __SP_CURSOR_C__
3 /*
4 * Some convenience stuff
5 *
6 * Authors:
7 * Lauris Kaplinski <lauris@kaplinski.com>
8 *
9 * Copyright (C) 1999-2002 authors
10 * Copyright (C) 2001-2002 Ximian, Inc.
11 *
12 * Released under GNU GPL, read the file 'COPYING' for more information
13 */
15 #include <cstdio>
16 #include <cstring>
17 #include <string>
18 #include <ctype.h>
19 #include <map>
20 #include "color.h"
21 #include "sp-cursor.h"
23 void
24 sp_cursor_bitmap_and_mask_from_xpm(GdkBitmap **bitmap, GdkBitmap **mask, gchar const *const *xpm)
25 {
26 int height;
27 int width;
28 int colors;
29 int pix;
30 sscanf(xpm[0], "%d %d %d %d", &height, &width, &colors, &pix);
32 g_return_if_fail (height == 32);
33 g_return_if_fail (width == 32);
34 g_return_if_fail (colors >= 3);
36 int transparent_color = ' ';
37 std::string black_colors;
39 char pixmap_buffer[(32 * 32)/8];
40 char mask_buffer[(32 * 32)/8];
42 for (int i = 0; i < colors; i++) {
44 char const *p = xpm[1 + i];
45 char const ccode = *p;
47 p++;
48 while (isspace(*p)) {
49 p++;
50 }
51 p++;
52 while (isspace(*p)) {
53 p++;
54 }
56 if (strcmp(p, "None") == 0) {
57 transparent_color = ccode;
58 }
60 if (strcmp(p, "Stroke") == 0) {
61 black_colors.push_back(ccode);
62 }
64 if (strcmp(p, "#000000") == 0) {
65 black_colors.push_back(ccode);
66 }
67 }
69 for (int y = 0; y < 32; y++) {
70 for (int x = 0; x < 32; ) {
72 char value = 0;
73 char maskv = 0;
75 for (int pix = 0; pix < 8; pix++, x++){
76 if (xpm[1+colors+y][x] != transparent_color) {
77 maskv |= 1 << pix;
79 if (black_colors.find(xpm[1+colors+y][x]) != std::string::npos) {
80 value |= 1 << pix;
81 }
82 }
83 }
85 pixmap_buffer[(y * 4 + x/8)-1] = value;
86 mask_buffer[(y * 4 + x/8)-1] = maskv;
87 }
88 }
90 *bitmap = gdk_bitmap_create_from_data(NULL, pixmap_buffer, 32, 32);
91 *mask = gdk_bitmap_create_from_data(NULL, mask_buffer, 32, 32);
92 }
94 static void free_cursor_data(guchar *pixels, gpointer data) {
95 delete [] reinterpret_cast<guint32*>(pixels);
96 }
98 struct RGBA {
99 guchar v[4];
100 RGBA() { v[0] = 0; v[1] = 0; v[2] = 0; v[3] = 0; }
101 RGBA(guchar r, guchar g, guchar b, guchar a) { v[0] = r; v[1] = g; v[2] = b; v[3] = a; }
102 operator guint32 const () const { return *reinterpret_cast<guint32 const *>(v); }
103 };
105 GdkPixbuf*
106 sp_cursor_pixbuf_from_xpm(gchar const *const *xpm, GdkColor const& black, GdkColor const& white, guint32 fill, guint32 stroke)
107 {
108 int height;
109 int width;
110 int colors;
111 int pix;
112 sscanf(xpm[0], "%d %d %d %d", &height, &width, &colors, &pix);
114 //g_return_if_fail (height == 32);
115 //g_return_if_fail (width == 32);
116 //g_return_if_fail (colors >= 3);
118 std::map<char,RGBA> colorMap;
120 for (int i = 0; i < colors; i++) {
122 char const *p = xpm[1 + i];
123 char const ccode = *p;
125 p++;
126 while (isspace(*p)) {
127 p++;
128 }
129 p++;
130 while (isspace(*p)) {
131 p++;
132 }
134 if (strcmp(p, "None") == 0) {
135 colorMap.insert(std::make_pair(ccode, RGBA()));
136 } else if (strcmp(p, "Fill") == 0) {
137 colorMap.insert(std::make_pair(ccode, RGBA(SP_RGBA32_R_U(fill),SP_RGBA32_G_U(fill),SP_RGBA32_B_U(fill),SP_RGBA32_A_U(fill))));
138 } else if (strcmp(p, "Stroke") == 0) {
139 colorMap.insert(std::make_pair(ccode, RGBA(SP_RGBA32_R_U(stroke),SP_RGBA32_G_U(stroke),SP_RGBA32_B_U(stroke),SP_RGBA32_A_U(stroke))));
140 } else if (strcmp(p, "#000000") == 0) {
141 colorMap.insert(std::make_pair(ccode, RGBA(black.red,black.green,black.blue,255)));
142 } else if (strcmp(p, "#FFFFFF") == 0) {
143 colorMap.insert(std::make_pair(ccode, RGBA(white.red,white.green,white.blue,255)));
144 } else {
145 colorMap.insert(std::make_pair(ccode, RGBA()));
146 }
147 }
149 guint32 *pixmap_buffer = new guint32[width * height];
151 for (int y = 0; y < height; y++) {
152 for (int x = 0; x < width; x++) {
153 std::map<char,RGBA>::const_iterator it = colorMap.find(xpm[1+colors+y][x]);
154 pixmap_buffer[y * width + x] = it==colorMap.end() ? 0u : it->second;
155 }
156 }
158 return gdk_pixbuf_new_from_data(reinterpret_cast<guchar*>(pixmap_buffer), GDK_COLORSPACE_RGB, TRUE, 8, width, height, width*sizeof(guint32), free_cursor_data, NULL);
159 }
161 GdkCursor *
162 sp_cursor_new_from_xpm(gchar const *const *xpm, gint hot_x, gint hot_y)
163 {
164 GdkColor const fg = { 0, 0, 0, 0 };
165 GdkColor const bg = { 0, 65535, 65535, 65535 };
167 GdkBitmap *bitmap = NULL;
168 GdkBitmap *mask = NULL;
170 sp_cursor_bitmap_and_mask_from_xpm (&bitmap, &mask, xpm);
171 if ( bitmap != NULL && mask != NULL ) {
172 GdkCursor *new_cursor = gdk_cursor_new_from_pixmap (bitmap, mask,
173 &fg, &bg,
174 hot_x, hot_y);
175 g_object_unref (bitmap);
176 g_object_unref (mask);
177 return new_cursor;
178 }
180 return NULL;
181 }
183 /*
184 Local Variables:
185 mode:c++
186 c-file-style:"stroustrup"
187 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
188 indent-tabs-mode:nil
189 fill-column:99
190 End:
191 */
192 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :