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