Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 324 lines (282 sloc) 7.667 kb
9f1c6f0 @mbert Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
1 /* gwimage.c -- Copyright 2003 by Steve Kirkendall */
2
3 #define CHAR Char
4 #include "elvis.h"
5 #undef CHAR
6 #undef ELVBOOL
7 #ifdef FEATURE_IMAGE
8 # include <windows.h>
9
10 /* read the next string from an XPM file */
11 static char *getstring(fp)
12 FILE *fp;
13 {
14 int ch;
15 int i;
16 static char *buf;
17 static int bufsize = 0;
18
19 /* skip to start of string */
20 while ((ch = getc(fp)) != EOF && ch != '"')
21 {
22 }
23 if (ch == EOF)
24 return NULL;
25
26 /* if first time, then allocate a buffer */
27 if (!buf)
28 {
29 bufsize = 100;
30 buf = (char *)malloc(100);
31 }
32
33 /* collect characters of the string */
34 for (i = 0; (ch = getc(fp)) != '"'; )
35 {
36 /* allow backslash-quoted chars (but not octal or ctrl chars) */
37 if (ch == '\\')
38 ch = getc(fp);
39
40 /* if EOF then return nothing */
41 if (ch == EOF)
42 return NULL;
43
44 /* increase the buffer size if necessary */
45 if (i + 1 >= bufsize)
46 {
47 bufsize *= 2;
48 buf = realloc(buf, bufsize);
49 }
50
51 /* store the character */
52 buf[i++] = ch;
53 }
54
55 /* mark the end of the string, and return it */
56 buf[i] = '\0';
57 return buf;
58 }
59
60 /* Load an image from an XPM file into a HBITMAP. Optionally tint it. Returns
61 * the bitmap's handle if successful, or 0 if failure (without an error msg)
62 */
63 HBITMAP gw_load_xpm(filename, tint, average, mask)
64 char *filename; /* name of *.xpm file to load */
65 long tint; /* -1 for pure image, or a COLORREF to tint */
66 long *average; /* average color return (may be NULL) */
67 HBITMAP *mask; /* mask return (may be NULL) */
68 {
69 FILE *fp;
70 char *line;
71 char *name;
72 int width, height, colors, pixelchars;
73 int ch, ch2;
74 int ci, row, col;
75 long palette[95*95];
76 char transparent[95*95];
77 unsigned char rgb[3];
78 HDC hdc = NULL;
79 HBITMAP bitmap = NULL;
80 long avg, avg1, avg2, avg3;
81
82 /* open the file */
83 fp = fopen(filename, "r");
84 if (!fp)
85 {
86 name = (char *)malloc(strlen(filename) + 8);
87 strcpy(name, "themes/");
88 strcat(name, filename);
89 line = iopath(tochar8(o_elvispath), name, ElvFalse);
90 free(name);
91 if (!line) goto Fail;
92 fp = fopen(line, "r");
93 }
94 if (!fp) goto Fail;
95
96 /* read & parse the header */
97 line = getstring(fp);
98 if (!line || 4 != sscanf(line, "%d %d %d %d",
99 &width, &height, &colors, &pixelchars))
100 goto Fail;
101
102 /* for each color table entry... */
103 for (ci = 0; ci < colors; ci++)
104 {
105 /* read the color table entry */
106 line = getstring(fp);
107 if (!line) goto Fail;
108
109 /* parse the color code */
110 ch = *line++;
111 if (!ch) goto Fail;
112 ch -= 32;
113 if (pixelchars == 2)
114 {
115 ch2 = *line++;
116 if (!ch2) goto Fail;
117 ch2 -= 32;
118 ch += 95 * ch2;
119 }
120
121 /* parse the color tag and name */
122 while (elvspace(*line))
123 line++;
124 if (!*line) goto Fail;
125 if (*line == 'c')
126 {
127 /* skip to the start of the color name */
128 line++;
129 while (elvspace(*line))
130 line++;
131 if (!*line) goto Fail;
132
133 /* convert the color name to a code */
134 if (!(guiwin32.color)(0,line, ElvFalse, &palette[ch], rgb))
135 goto Fail;
136
137 /* tint the code, if necessary */
138 if (tint >= 0)
139 palette[ch] = ((palette[ch] & 0xfefefe)
140 + (tint & 0xfefefe)) >> 1;
141
142 /* it isn't transparent */
143 transparent[ch] = 0;
144 }
145 else /* it must be transparent */
146 {
147 if (tint >= 0)
148 palette[ch] = tint;
149 else
150 palette[ch] = 0x0;
151 transparent[ch] = 1;
152 }
153 }
154
155 /* create a device context for the display */
156 hdc = CreateCompatibleDC(NULL);
157 if (!hdc) goto Fail;
158 SetMapMode(hdc, MM_TEXT);
159
160 /* allocate the bitmap */
161 bitmap = CreateBitmap(width, height, 1, GetDeviceCaps(hdc, BITSPIXEL),
162 malloc((height * (GetDeviceCaps(hdc, BITSPIXEL) * width / 8) + 1 & ~0x1)));
163 if (!bitmap) goto Fail;
164
165 /* if a mask is desired, then allocate it too */
166 if (mask)
167 {
168 *mask = CreateBitmap(width, height, 1, GetDeviceCaps(hdc, BITSPIXEL),
169 malloc((height * (GetDeviceCaps(hdc, BITSPIXEL) * width / 8) + 1 & ~0x1)));
170 if (!*mask) goto Fail;
171 }
172
173 /* use the bitmap in this context */
174 if (SelectObject(hdc, bitmap) == NULL)
175 goto Fail;
176
177 /* for each row of the image... */
178 for (row = 0; row < height; row++)
179 {
180 /* fetch the row */
181 line = getstring(fp);
182 if (!line) goto Fail;
183
184 /* for each column in the row */
185 for (col = 0; col < width; col++)
186 {
187 /* parse the color code */
188 ch = *line++;
189 if (!ch) goto Fail;
190 ch -= 32;
191 if (pixelchars == 2)
192 {
193 ch2 = *line++;
194 if (!ch2) goto Fail;
195 ch2 -= 32;
196 ch += 95 * ch2;
197 }
198
199 /* draw the mask, if necessary */
200 if (mask)
201 {
202 SelectObject(hdc, *mask);
203 if (transparent[ch])
204 SetPixel(hdc, col, row, (COLORREF)0xffffff);
205 else
206 SetPixel(hdc, col, row, (COLORREF)0x000000);
207 SelectObject(hdc, bitmap);
208 }
209
210 /* draw this pixel in the correct color */
211 SetPixel(hdc, col, row, (COLORREF)(palette[ch]));
212 }
213 }
214
215 /* find the average color from the image */
216 if (average)
217 {
218 avg1 = avg2 = avg3 = 0;
219 for (row = height / 8; row < height; row += height / 4)
220 {
221 for (col = width / 8; col < width; col += width / 4)
222 {
223 avg = GetPixel(hdc, col, row);
224 avg1 += avg & 0x0000ff;
225 avg2 += avg & 0x00ff00;
226 avg3 += avg & 0xff0000;
227 }
228 }
229 avg = ((avg1&0x0000ff0) + (avg2&0x00ff000) + (avg3&0xff00000)) >> 4;
230 *average = avg;
231 }
232
233 /* clean up */
234 DeleteDC(hdc);
235 fclose(fp);
236 return bitmap;
237
238 Fail:
239 if (hdc)
240 DeleteDC(hdc);
241 if (bitmap)
242 DeleteObject(bitmap);
243 if (fp != NULL)
244 fclose(fp);
245 return NULL;
246 }
247
248 /* Free a bitmap that was created by gw_load_xpm(). If you also created
249 * a mask bitmap at the same time, then you must call this function separately
250 * for both bitmaps.
251 */
252 void gw_unload_xpm(bitmap)
253 HBITMAP bitmap; /* the bitmap to be freed */
254 {
255 BITMAP bm;
256
257 /* get info about the bitmap */
258 GetObject(bitmap, sizeof(BITMAP), &bm);
259
260 /* free the image memory */
261 free(bm.bmBits);
262
263 /* free the bitmap itself */
264 DeleteObject(bitmap);
265 }
266
267 /* Erase part of a drawing context by copying sections of a bitmap image
268 * into it.
269 */
270 void gw_erase_rect(hdc, rect, bitmap, scrolled)
271 HDC hdc; /* the destination context; what to clear */
272 RECT *rect; /* area to erase within the destination */
273 HBITMAP bitmap; /* the image to use for clearing */
274 long scrolled;/* number of pixels scrolled vertically */
275 {
276 HBITMAP old;
277 BITMAP bm;
278 HDC bmphdc;
279 int x, y, h, w, ret;
280 int base;
281
282 /* get the bitmap's size */
283 GetObject(bitmap, sizeof(BITMAP), &bm);
284
285 /* create a drawing context for the source bitmap */
286 bmphdc = CreateCompatibleDC(hdc);
287 SetMapMode(bmphdc, MM_TEXT);
288 old = SelectObject(bmphdc, bitmap);
289
290 /* choose a height and base for the first row */
291 scrolled += rect->top;
292 if (scrolled < 0)
293 h = (int)(-scrolled % bm.bmHeight);
294 else
295 h = bm.bmHeight - (int)(scrolled % bm.bmHeight);
296 base = bm.bmHeight - h;
297
298 /* for each row or partial row... */
299 for (y = rect->top; y < rect->bottom; y += h, h = bm.bmHeight, base = 0)
300 {
301 /* we may need to reduce the height of the bottom row */
302 if (y + h > rect->bottom)
303 h = rect->bottom - y;
304
305 /* for each column or partial column... */
306 for (x = rect->left; x < rect->right; x += w)
307 {
308 w = bm.bmWidth - x % bm.bmWidth;
309 if (x + w > rect->right)
310 w = rect->right - x;
311
312 /* copy the source image into this row&column of the destination */
313 ret = BitBlt(hdc, x, y, w, h, bmphdc,
314 x % bm.bmWidth, base, SRCCOPY);
315 }
316 }
317
318 /* free the drawing context */
319 SelectObject(bmphdc, old);
320 DeleteDC(bmphdc);
321 }
322 #endif /* FEATURE_IMAGE */
323 /* ex:set sw=4: */
Something went wrong with that request. Please try again.