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