adopt previous changes. (NicJA)
[AROS.git] / rom / graphics / obtainbestpena.c
blob0bcf467015af9516473bc7c2a7be7e2b86a992ad
1 /*
2 Copyright © 1995-2018, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Obtain the best pen available for a given color
6 Lang: english
7 */
9 #include "graphics_intern.h"
10 #include <proto/utility.h>
11 #include <utility/tagitem.h>
12 #include <graphics/view.h>
14 /*****************************************************************************
16 NAME */
17 #include <proto/graphics.h>
19 AROS_LH5(LONG, ObtainBestPenA,
21 /* SYNOPSIS */
22 AROS_LHA(struct ColorMap *, cm , A0),
23 AROS_LHA(ULONG , r , D1),
24 AROS_LHA(ULONG , g , D2),
25 AROS_LHA(ULONG , b , D3),
26 AROS_LHA(struct TagItem * , tags, A1),
28 /* LOCATION */
29 struct GfxBase *, GfxBase, 140, Graphics)
31 /* FUNCTION
32 Try to find a pen which matches the given parameters.
34 INPUTS
35 cm - colormap
36 r - red value (32 bit left justified fraction)
37 g - green value (32 bit left justified fraction)
38 b - blue value (32 bit left justified fraction)
39 tags - tagarray
40 OBP_Precision - PRECISION_GUI, PRECISION_ICON, PRECISION_IMAGE or PRECISION_EXACT.
41 Defaults to PRECISION_IMAGE.
43 OBP_FailIfBad - if TRUE ObtainBestPen returns an error when there
44 is no color in the given tolerance.
46 RESULT
47 A pen value or -1 if no pen could be found.
49 NOTES
50 You must call ReleasePen() when you're done with the pen.
52 EXAMPLE
54 BUGS
56 SEE ALSO
58 INTERNALS
60 HISTORY
62 *****************************************************************************/
64 AROS_LIBFUNC_INIT
66 struct PaletteExtra *pe = cm->PalExtra;
67 LONG retval = -1;
68 PalExtra_AllocList_Type index;
70 if (NULL != pe)
72 struct TagItem defaults[] =
74 {OBP_Precision, PRECISION_IMAGE },
75 {OBP_FailIfBad, FALSE }
77 ULONG best_distance = (ULONG)-1;
80 /*
81 ** override the defaults if necessary
83 defaults[0].ti_Data = GetTagData(OBP_Precision,
84 defaults[0].ti_Data,
85 tags);
87 defaults[1].ti_Data = GetTagData(OBP_FailIfBad,
88 defaults[1].ti_Data,
89 tags);
91 /*
92 ** let nobody else play with the PalExtra structure
94 ObtainSemaphore(&pe->pe_Semaphore);
96 /*
97 ** Walk through the list of shared pens and search
98 ** for the closest color.
100 index = (PalExtra_AllocList_Type)pe->pe_FirstShared;
101 while ((PalExtra_AllocList_Type)-1 != index)
103 ULONG distance = color_distance(cm,r,g,b,index);
105 if (distance < best_distance)
107 best_distance = distance;
108 retval = index;
111 index = PALEXTRA_ALLOCLIST(pe, index);
114 /* FIXME: The color distance calc might be different than in AmigaOS. */
117 ** If the best distance to an available color is greater than
118 ** the square of the tolerance, try to allocate a better
119 ** color, otherwise increase the shared counter for that color.
120 ** If only a little amount of colors is free for allocation in the
121 ** colormap the restrictions towards color matching should be
122 ** much looser than if the amount of allocated colors is close to 0.
123 ** The autodocs say that.
125 if (
126 (retval == -1) ||
127 (PRECISION_EXACT == defaults[0].ti_Data && 0 != best_distance ) ||
128 (best_distance * pe->pe_NFree >
129 (defaults[0].ti_Data * defaults[0].ti_Data) * pe->pe_SharableColors
134 ** The given tolerance could not be accomplished.
135 ** Try to allocate a pen. If that fails we
136 ** return -1 if the user specified OBP_FailIfBad = TRUE.
138 LONG tmp = ObtainPen(cm,-1,r,g,b,0);
140 if (-1 == tmp)
143 ** Return -1 if the user is strict with color matching.
144 ** In the other case retval is not changed.
146 if (defaults[1].ti_Data)
148 retval = -1;
150 else if (retval != -1)
153 ** One more application is using this color
156 PALEXTRA_REFCNT(pe, retval)++;
159 else
160 retval = tmp;
162 else
165 ** One more application is using this color
167 PALEXTRA_REFCNT(pe, retval)++;
170 ReleaseSemaphore(&pe->pe_Semaphore);
172 } /* if (NULL != pe) */
174 return retval;
176 AROS_LIBFUNC_EXIT
178 } /* ObtainBestPenA */