1 /*
2 * Copyright (C) 19896 Lorens Younes
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to
6 * deal in the Software without restriction, including without limitation the
7 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
8 * sell copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * Lorens Younes BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
18 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 *
21 * Except as contained in this notice, the name of Lorens Younes shall not be
22 * used in advertising or otherwise to promote the sale, use or other dealings
23 * in this Software without prior written authorization from Lorens Younes.
24 */
25
26 /*****************************************************************************\
27 * amigax.c: *
28 * *
29 * XPM library *
30 * Emulates some Xlib functionality for Amiga. *
31 * *
32 * Developed by Lorens Younes (d93-hyo@nada.kth.se) 7/95 *
33 * Revised 4/96 *
34 \*****************************************************************************/
35
36 #ifdef HAVE_CONFIG_H
37 #include <config.h>
38 #endif
39 #include "XpmI.h"
40 #include "amigax.h"
41
42 #include <graphics/gfxbase.h>
43 #include <intuition/screens.h>
44
45 #include <proto/exec.h>
46
47
48 static struct RastPort *
49 AllocRastPort (unsigned int, unsigned int, unsigned int);
50 static void
51 FreeRastPort (struct RastPort *, unsigned int,unsigned int);
52
53
54 static struct RastPort *
AllocRastPort(unsigned int width,unsigned int height,unsigned int depth)55 AllocRastPort (
56 unsigned int width,
57 unsigned int height,
58 unsigned int depth)
59 {
60 struct RastPort *rp;
61
62 rp = XpmMalloc (sizeof (*rp));
63 if (rp != NULL)
64 {
65 InitRastPort (rp);
66 if (GfxBase->LibNode.lib_Version >= 39)
67 {
68 rp->BitMap = AllocBitMap (width, height, depth, BMF_CLEAR, NULL);
69 if (rp->BitMap == NULL)
70 {
71 FreeRastPort (rp, width, height);
72 return NULL;
73 }
74 }
75 else
76 {
77 unsigned int i;
78
79 rp->BitMap = XpmMalloc (sizeof (*rp->BitMap));
80 if (rp->BitMap == NULL)
81 {
82 FreeRastPort (rp, width, height);
83 return NULL;
84 }
85
86 InitBitMap (rp->BitMap, depth, width, height);
87 for (i = 0; i < depth; ++i)
88 rp->BitMap->Planes[i] = NULL;
89 for (i = 0; i < depth; ++i)
90 {
91 rp->BitMap->Planes[i] = (PLANEPTR)AllocRaster (width, height);
92 if (rp->BitMap->Planes[i] == NULL)
93 {
94 FreeRastPort (rp, width, height);
95 return NULL;
96 }
97 }
98 }
99 }
100
101 return rp;
102 }
103
104
105 static void
FreeRastPort(struct RastPort * rp,unsigned int width,unsigned int height)106 FreeRastPort (
107 struct RastPort *rp,
108 unsigned int width,
109 unsigned int height)
110 {
111 if (rp != NULL)
112 {
113 if (rp->BitMap != NULL)
114 {
115 WaitBlit ();
116 if (GfxBase->LibNode.lib_Version >= 39)
117 FreeBitMap (rp->BitMap);
118 else
119 {
120 unsigned int i;
121
122 for (i = 0; i < rp->BitMap->Depth; ++i)
123 {
124 if (rp->BitMap->Planes[i] != NULL)
125 FreeRaster (rp->BitMap->Planes[i], width, height);
126 }
127 XpmFree (rp->BitMap);
128 }
129 }
130 XpmFree (rp);
131 }
132 }
133
134
135 XImage *
AllocXImage(unsigned int width,unsigned int height,unsigned int depth)136 AllocXImage (
137 unsigned int width,
138 unsigned int height,
139 unsigned int depth)
140 {
141 XImage *img;
142
143 img = XpmMalloc (sizeof (*img));
144 if (img != NULL)
145 {
146 img->width = width;
147 img->height = height;
148 img->rp = AllocRastPort (img->width, img->height, depth);
149 if (img->rp == NULL)
150 {
151 FreeXImage (img);
152 return NULL;
153 }
154 }
155
156 return img;
157 }
158
159
160 int
FreeXImage(XImage * ximage)161 FreeXImage (
162 XImage *ximage)
163 {
164 if (ximage != NULL)
165 {
166 FreeRastPort (ximage->rp, ximage->width, ximage->height);
167 XpmFree (ximage);
168 }
169
170 return Success;
171 }
172
173
174 int
XPutPixel(XImage * ximage,int x,int y,unsigned long pixel)175 XPutPixel (
176 XImage *ximage,
177 int x,
178 int y,
179 unsigned long pixel)
180 {
181 SetAPen (ximage->rp, pixel);
182 WritePixel (ximage->rp, x, y);
183
184 return Success;
185 }
186
187
188 Status
AllocBestPen(Colormap colormap,XColor * screen_in_out,unsigned long precision,Bool fail_if_bad)189 AllocBestPen (
190 Colormap colormap,
191 XColor *screen_in_out,
192 unsigned long precision,
193 Bool fail_if_bad)
194 {
195 if (GfxBase->LibNode.lib_Version >= 39)
196 {
197 unsigned long r, g, b;
198
199 r = screen_in_out->red * 0x00010001;
200 g = screen_in_out->green * 0x00010001;
201 b = screen_in_out->blue * 0x00010001;
202 screen_in_out->pixel = ObtainBestPen (colormap, r, g, b,
203 OBP_Precision, precision,
204 OBP_FailIfBad, fail_if_bad,
205 TAG_DONE);
206 if (screen_in_out->pixel == -1)
207 return False;
208
209 QueryColor (colormap, screen_in_out);
210 }
211 else
212 {
213 XColor nearest, trial;
214 long nearest_delta, trial_delta;
215 int num_cells, i;
216
217 num_cells = colormap->Count;
218 nearest.pixel = 0;
219 QueryColor (colormap, &nearest);
220 nearest_delta = ((((screen_in_out->red >> 8) - (nearest.red >> 8))
221 * ((screen_in_out->red >> 8) - (nearest.red >> 8)))
222 +
223 (((screen_in_out->green >> 8) - (nearest.green >> 8))
224 * ((screen_in_out->green >> 8) - (nearest.green >> 8)))
225 +
226 (((screen_in_out->blue >> 8) - (nearest.blue >> 8))
227 * ((screen_in_out->blue >> 8) - (nearest.blue >> 8))));
228 for (i = 1; i < num_cells; i++)
229 {
230 /* precision and fail_if_bad is ignored under pre V39 */
231 trial.pixel = i;
232 QueryColor (colormap, &trial);
233 trial_delta = ((((screen_in_out->red >> 8) - (trial.red >> 8))
234 * ((screen_in_out->red >> 8) - (trial.red >> 8)))
235 +
236 (((screen_in_out->green >> 8) - (trial.green >> 8))
237 * ((screen_in_out->green >> 8) - (trial.green >> 8)))
238 +
239 (((screen_in_out->blue >> 8) - (trial.blue >> 8))
240 * ((screen_in_out->blue >> 8) - (trial.blue >> 8))));
241 if (trial_delta < nearest_delta)
242 {
243 nearest = trial;
244 nearest_delta = trial_delta;
245 }
246 }
247 screen_in_out->pixel = nearest.pixel;
248 screen_in_out->red = nearest.red;
249 screen_in_out->green = nearest.green;
250 screen_in_out->blue = nearest.blue;
251 }
252
253 return True;
254 }
255
256
257 int
FreePens(Colormap colormap,unsigned long * pixels,int npixels)258 FreePens (
259 Colormap colormap,
260 unsigned long *pixels,
261 int npixels)
262 {
263 if (GfxBase->LibNode.lib_Version >= 39)
264 {
265 int i;
266
267 for (i = 0; i < npixels; i++)
268 ReleasePen (colormap, pixels[i]);
269 }
270
271 return Success;
272 }
273
274
275 Status
ParseColor(char * spec,XColor * exact_def_return)276 ParseColor (
277 char *spec,
278 XColor *exact_def_return)
279 {
280 int spec_length;
281
282 if (spec == 0)
283 return False;
284
285 spec_length = strlen(spec);
286 if (spec[0] == '#')
287 {
288 int hexlen;
289 char hexstr[10];
290
291 hexlen = (spec_length - 1) / 3;
292 if (hexlen < 1 || hexlen > 4 || hexlen * 3 != spec_length - 1)
293 return False;
294
295 hexstr[hexlen] = '\0';
296 strncpy (hexstr, spec + 1, hexlen);
297 exact_def_return->red = strtoul (hexstr, NULL, 16) << (16 - 4*hexlen);
298 strncpy (hexstr, spec + 1 + hexlen, hexlen);
299 exact_def_return->green = strtoul (hexstr, NULL, 16) << (16 - 4*hexlen);
300 strncpy (hexstr, spec + 1 + 2 * hexlen, hexlen);
301 exact_def_return->blue = strtoul (hexstr, NULL, 16) << (16 - 4*hexlen);
302
303 return True;
304 }
305 else
306 {
307 FILE *rgbf;
308 int items, red, green, blue;
309 char line[512], name[512];
310 Bool success = False;
311
312 rgbf = fopen ("LIBS:rgb.txt", "r");
313 if (rgbf == NULL)
314 return False;
315
316 while (fgets(line, sizeof (line), rgbf) && !success)
317 {
318 items = sscanf (line, "%d %d %d %[^\n]\n",
319 &red, &green, &blue, name);
320 if (items != 4)
321 continue;
322
323 if (red < 0 || red > 0xFF
324 || green < 0 || green > 0xFF
325 || blue < 0 || blue > 0xFF)
326 {
327 continue;
328 }
329
330 if (0 == xpmstrcasecmp (spec, name))
331 {
332 exact_def_return->red = red * 0x0101;
333 exact_def_return->green = green * 0x0101;
334 exact_def_return->blue = blue * 0x0101;
335 success = True;
336 }
337 }
338 fclose (rgbf);
339
340 return success;
341 }
342 }
343
344
345 int
QueryColor(Colormap colormap,XColor * def_in_out)346 QueryColor (
347 Colormap colormap,
348 XColor *def_in_out)
349 {
350 if (GfxBase->LibNode.lib_Version >= 39)
351 {
352 unsigned long rgb[3];
353
354 GetRGB32 (colormap, def_in_out->pixel, 1, rgb);
355 def_in_out->red = rgb[0] >> 16;
356 def_in_out->green = rgb[1] >> 16;
357 def_in_out->blue = rgb[2] >> 16;
358 }
359 else
360 {
361 unsigned short rgb;
362
363 rgb = GetRGB4 (colormap, def_in_out->pixel);
364 def_in_out->red = ((rgb >> 8) & 0xF) * 0x1111;
365 def_in_out->green = ((rgb >> 4) & 0xF) * 0x1111;
366 def_in_out->blue = (rgb & 0xF) * 0x1111;
367 }
368
369 return Success;
370 }
371
372
373 int
QueryColors(Colormap colormap,XColor * defs_in_out,int ncolors)374 QueryColors (
375 Colormap colormap,
376 XColor *defs_in_out,
377 int ncolors)
378 {
379 int i;
380
381 for (i = 0; i < ncolors; i++)
382 QueryColor (colormap, &defs_in_out[i]);
383
384 return Success;
385 }
386