add option for classic magicmenu "mixed" menu style (pull donw on screen title, pop...
[AROS.git] / rom / graphics / obtainbestpena.c
blobbbd8a948399f6b1dff79158bc2403ba1bc0cdd15
1 /*
2 Copyright © 1995-2007, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Obtain the best pen available for a given color
6 Lang: english
7 */
8 #include "graphics_intern.h"
9 #include <proto/utility.h>
10 #include <utility/tagitem.h>
11 #include <graphics/view.h>
13 /*****************************************************************************
15 NAME */
16 #include <proto/graphics.h>
18 AROS_LH5(LONG, ObtainBestPenA,
20 /* SYNOPSIS */
21 AROS_LHA(struct ColorMap *, cm , A0),
22 AROS_LHA(ULONG , r , D1),
23 AROS_LHA(ULONG , g , D2),
24 AROS_LHA(ULONG , b , D3),
25 AROS_LHA(struct TagItem * , tags, A1),
27 /* LOCATION */
28 struct GfxBase *, GfxBase, 140, Graphics)
30 /* FUNCTION
31 Try to find a pen which matches the given parameters.
33 INPUTS
34 cm - colormap
35 r - red value (32 bit left justified fraction)
36 g - green value (32 bit left justified fraction)
37 b - blue value (32 bit left justified fraction)
38 tags - tagarray
39 OBP_Precision - PRECISION_GUI, PRECISION_ICON, PRECISION_IMAGE or PRECISION_EXACT.
40 Defaults to PRECISION_IMAGE.
42 OBP_FailIfBad - if TRUE ObtainBestPen returns an error when there
43 is no color in the given tolerance.
45 RESULT
46 A pen value or -1 if no pen could be found.
48 NOTES
49 You must call ReleasePen() when you're done with the pen.
51 EXAMPLE
53 BUGS
55 SEE ALSO
57 INTERNALS
59 HISTORY
61 *****************************************************************************/
63 AROS_LIBFUNC_INIT
65 struct PaletteExtra *pe = cm->PalExtra;
66 LONG retval = -1;
67 PalExtra_AllocList_Type index;
69 if (NULL != pe)
71 struct TagItem defaults[] =
73 {OBP_Precision, PRECISION_IMAGE },
74 {OBP_FailIfBad, FALSE }
76 ULONG best_distance = (ULONG)-1;
79 /*
80 ** override the defaults if necessary
82 defaults[0].ti_Data = GetTagData(OBP_Precision,
83 defaults[0].ti_Data,
84 tags);
86 defaults[1].ti_Data = GetTagData(OBP_FailIfBad,
87 defaults[1].ti_Data,
88 tags);
90 /*
91 ** let nobody else play with the PalExtra structure
93 ObtainSemaphore(&pe->pe_Semaphore);
95 /*
96 ** Walk through the list of shared pens and search
97 ** for the closest color.
99 index = (PalExtra_AllocList_Type)pe->pe_FirstShared;
100 while ((PalExtra_AllocList_Type)-1 != index)
102 ULONG distance = color_distance(cm,r,g,b,index);
104 if (distance < best_distance)
106 best_distance = distance;
107 retval = index;
110 index = PALEXTRA_ALLOCLIST(pe, index);
113 /* FIXME: The color distance calc might be different than in AmigaOS. */
116 ** If the best distance to an available color is greater than
117 ** the square of the tolerance, try to allocate a better
118 ** color, otherwise increase the shared counter for that color.
119 ** If only a little amount of colors is free for allocation in the
120 ** colormap the restrictions towards color matching should be
121 ** much looser than if the amount of free colors is close to 0.
122 ** The autodocs say that.
124 if (
125 (retval == -1) ||
126 (PRECISION_EXACT == defaults[0].ti_Data && 0 != best_distance ) ||
127 (best_distance * pe->pe_NFree >
128 (defaults[0].ti_Data * defaults[0].ti_Data) * pe->pe_SharableColors
133 ** The given tolerance could not be accomplished.
134 ** Try to allocate a pen. If that fails we
135 ** return -1 if the user specified OBP_FailIfBad = TRUE.
137 LONG tmp = ObtainPen(cm,-1,r,g,b,0);
139 if (-1 == tmp)
142 ** Return -1 if the user is strict with color matching.
143 ** In the other case retval is not changed.
145 if (defaults[1].ti_Data)
147 retval = -1;
149 else if (retval != -1)
152 ** One more application is using this color
155 PALEXTRA_REFCNT(pe, retval)++;
158 else
159 retval = tmp;
161 else
164 ** One more application is using this color
166 PALEXTRA_REFCNT(pe, retval)++;
169 ReleaseSemaphore(&pe->pe_Semaphore);
171 } /* if (NULL != pe) */
173 return retval;
175 AROS_LIBFUNC_EXIT
177 } /* ObtainBestPenA */