]>
git.saurik.com Git - wxWidgets.git/blob - src/common/colourcmn.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/colourcmn.cpp
3 // Purpose: wxColourBase implementation
4 // Author: Francesco Montorsi
7 // Copyright: (c) Francesco Montorsi
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
12 // For compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
19 #include "wx/colour.h"
24 #include "wx/gdicmn.h"
25 #include "wx/wxcrtvararg.h"
29 IMPLEMENT_VARIANT_OBJECT_EXPORTED(wxColour
,WXDLLEXPORT
)
33 // ----------------------------------------------------------------------------
35 // ----------------------------------------------------------------------------
37 #if wxUSE_EXTENDED_RTTI
41 template<> void wxStringReadValue(const wxString
&s
, wxColour
&data
)
45 wxLogError(_("String To Colour : Incorrect colour specification : %s"),
51 template<> void wxStringWriteValue(wxString
&s
, const wxColour
&data
)
53 s
= data
.GetAsString(wxC2S_HTML_SYNTAX
);
56 wxTO_STRING_IMP( wxColour
)
57 wxFROM_STRING_IMP( wxColour
)
59 wxIMPLEMENT_DYNAMIC_CLASS_WITH_COPY_AND_STREAMERS_XTI( wxColour
, wxObject
, \
60 "wx/colour.h", &wxTO_STRING( wxColour
), &wxFROM_STRING( wxColour
))
61 //WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl<wxColour>)
62 wxBEGIN_PROPERTIES_TABLE(wxColour
)
63 wxREADONLY_PROPERTY( Red
, unsigned char, Red
, wxEMPTY_PARAMETER_VALUE
, \
64 0 /*flags*/, wxT("Helpstring"), wxT("group"))
65 wxREADONLY_PROPERTY( Green
, unsigned char, Green
, wxEMPTY_PARAMETER_VALUE
, \
66 0 /*flags*/, wxT("Helpstring"), wxT("group"))
67 wxREADONLY_PROPERTY( Blue
, unsigned char, Blue
, wxEMPTY_PARAMETER_VALUE
, \
68 0 /*flags*/, wxT("Helpstring"), wxT("group"))
69 wxEND_PROPERTIES_TABLE()
71 wxDIRECT_CONSTRUCTOR_3( wxColour
, unsigned char, Red
, \
72 unsigned char, Green
, unsigned char, Blue
)
74 wxEMPTY_HANDLERS_TABLE(wxColour
)
77 #if wxCOLOUR_IS_GDIOBJECT
78 wxIMPLEMENT_DYNAMIC_CLASS(wxColour
, wxGDIObject
)
80 wxIMPLEMENT_DYNAMIC_CLASS(wxColour
, wxObject
)
85 // ============================================================================
86 // wxString <-> wxColour conversions
87 // ============================================================================
89 bool wxColourBase::FromString(const wxString
& str
)
92 return false; // invalid or empty string
94 if ( wxStrnicmp(str
, wxT("RGB"), 3) == 0 )
96 // CSS-like RGB specification
97 // according to http://www.w3.org/TR/css3-color/#colorunits
98 // values outside 0-255 range are allowed but should be clipped
100 alpha
= wxALPHA_OPAQUE
;
101 if ( str
.length() > 3 && (str
[3] == wxT('a') || str
[3] == wxT('A')) )
103 // We can't use sscanf() for the alpha value as sscanf() uses the
104 // current locale while the floating point numbers in CSS always
105 // use point as decimal separator, regardless of locale. So parse
106 // the tail of the string manually by putting it in a buffer and
107 // using wxString::ToCDouble() below. Notice that we can't use "%s"
108 // for this as it stops at white space and we need "%c" to avoid
109 // this and really get all the rest of the string into the buffer.
111 const unsigned len
= str
.length(); // always big enough
112 wxCharBuffer
alphaBuf(len
);
113 char * const alphaPtr
= alphaBuf
.data();
115 for ( unsigned n
= 0; n
< len
; n
++ )
118 // Construct the format string which ensures that the last argument
119 // receives all the rest of the string.
121 formatStr
<< wxS("( %d , %d , %d , %") << len
<< 'c';
123 // Notice that we use sscanf() here because if the string is not
124 // ASCII it can't represent a valid RGB colour specification anyhow
125 // and like this we can be sure that %c corresponds to "char *"
126 // while with wxSscanf() it depends on the type of the string
127 // passed as first argument: if it is a wide string, then %c
128 // expects "wchar_t *" matching parameter under MSW for example.
129 if ( sscanf(str
.c_str() + 4,
131 &red
, &green
, &blue
, alphaPtr
) != 4 )
134 // Notice that we must explicitly specify the length to get rid of
136 wxString
alphaStr(alphaPtr
, wxStrlen(alphaPtr
));
137 if ( alphaStr
.empty() || alphaStr
.Last() != ')' )
140 alphaStr
.RemoveLast();
144 if ( !alphaStr
.ToCDouble(&a
) )
147 alpha
= wxRound(a
* 255);
149 else // no 'a' following "rgb"
151 if ( wxSscanf(str
.wx_str() + 3, wxT("( %d , %d , %d )"),
152 &red
, &green
, &blue
) != 3 )
156 Set((unsigned char)wxClip(red
, 0, 255),
157 (unsigned char)wxClip(green
, 0, 255),
158 (unsigned char)wxClip(blue
, 0, 255),
159 (unsigned char)wxClip(alpha
, 0, 255));
161 else if ( str
[0] == wxT('#') && wxStrlen(str
) == 7 )
163 // hexadecimal prefixed with # (HTML syntax)
165 if (wxSscanf(str
.wx_str() + 1, wxT("%lx"), &tmp
) != 1)
168 Set((unsigned char)(tmp
>> 16),
169 (unsigned char)(tmp
>> 8),
172 else if (wxTheColourDatabase
) // a colour name ?
175 // *this = wxTheColourDatabase->Find(str)
176 // because this place can be called from constructor
177 // and 'this' could not be available yet
178 wxColour clr
= wxTheColourDatabase
->Find(str
);
180 Set((unsigned char)clr
.Red(),
181 (unsigned char)clr
.Green(),
182 (unsigned char)clr
.Blue());
188 wxLogDebug(wxT("wxColour::Set - couldn't set to colour string '%s'"), str
);
192 wxString
wxColourBase::GetAsString(long flags
) const
196 const bool isOpaque
= Alpha() == wxALPHA_OPAQUE
;
198 // we can't use the name format if the colour is not opaque as the alpha
199 // information would be lost
200 if ( (flags
& wxC2S_NAME
) && isOpaque
)
202 colName
= wxTheColourDatabase
->FindName(
203 static_cast<const wxColour
&>(*this)).MakeLower();
206 if ( colName
.empty() )
208 const int red
= Red(),
212 if ( flags
& wxC2S_CSS_SYNTAX
)
214 // no name for this colour; return it in CSS syntax
217 colName
.Printf(wxT("rgb(%d, %d, %d)"), red
, green
, blue
);
219 else // use rgba() form
221 colName
.Printf(wxT("rgba(%d, %d, %d, %s)"),
223 wxString::FromCDouble(Alpha() / 255., 3));
226 else if ( flags
& wxC2S_HTML_SYNTAX
)
228 wxASSERT_MSG( isOpaque
, "alpha is lost in HTML syntax" );
230 // no name for this colour; return it in HTML syntax
231 colName
.Printf(wxT("#%02X%02X%02X"), red
, green
, blue
);
235 // this function should alway returns a non-empty string
236 wxASSERT_MSG(!colName
.empty(),
237 wxT("Invalid wxColour -> wxString conversion flags"));
243 void wxColourBase::MakeMono(unsigned char* r
, unsigned char* g
, unsigned char* b
,
246 *r
= *g
= *b
= on
? 255 : 0;
250 void wxColourBase::MakeGrey(unsigned char* r
, unsigned char* g
, unsigned char* b
251 /*, unsigned char brightness */
254 *r
= *g
= *b
= (wxByte
)(((*b
)*117UL + (*g
)*601UL + (*r
)*306UL) >> 10);
258 void wxColourBase::MakeGrey(unsigned char* r
, unsigned char* g
, unsigned char* b
,
259 double weight_r
, double weight_g
, double weight_b
)
261 double luma
= (*r
) * weight_r
+ (*g
) * weight_g
+ (*b
) * weight_b
;
262 *r
= *g
= *b
= (wxByte
)wxRound(luma
);
266 void wxColourBase::MakeDisabled(unsigned char* r
, unsigned char* g
, unsigned char* b
,
267 unsigned char brightness
)
269 //MakeGrey(r, g, b, brightness); // grey no-blend version
270 *r
= AlphaBlend(*r
, brightness
, 0.4);
271 *g
= AlphaBlend(*g
, brightness
, 0.4);
272 *b
= AlphaBlend(*b
, brightness
, 0.4);
275 wxColour
& wxColourBase::MakeDisabled(unsigned char brightness
)
277 unsigned char r
= Red(),
280 MakeDisabled(&r
, &g
, &b
, brightness
);
281 Set(r
, g
, b
, Alpha());
282 return static_cast<wxColour
&>(*this);
285 // AlphaBlend is used by ChangeLightness and MakeDisabled
288 unsigned char wxColourBase::AlphaBlend(unsigned char fg
, unsigned char bg
,
291 double result
= bg
+ (alpha
* (fg
- bg
));
292 result
= wxMax(result
, 0.0);
293 result
= wxMin(result
, 255.0);
294 return (unsigned char)result
;
297 // ChangeLightness() is a utility function that simply darkens
298 // or lightens a color, based on the specified percentage
299 // ialpha of 0 would be completely black, 100 completely white
300 // an ialpha of 100 returns the same colour
303 void wxColourBase::ChangeLightness(unsigned char* r
, unsigned char* g
, unsigned char* b
,
306 if (ialpha
== 100) return;
308 // ialpha is 0..200 where 0 is completely black
309 // and 200 is completely white and 100 is the same
310 // convert that to normal alpha 0.0 - 1.0
311 ialpha
= wxMax(ialpha
, 0);
312 ialpha
= wxMin(ialpha
, 200);
313 double alpha
= ((double)(ialpha
- 100.0))/100.0;
320 alpha
= 1.0 - alpha
; // 0 = transparent fg; 1 = opaque fg
326 alpha
= 1.0 + alpha
; // 0 = transparent fg; 1 = opaque fg
329 *r
= AlphaBlend(*r
, bg
, alpha
);
330 *g
= AlphaBlend(*g
, bg
, alpha
);
331 *b
= AlphaBlend(*b
, bg
, alpha
);
334 wxColour
wxColourBase::ChangeLightness(int ialpha
) const
339 ChangeLightness(&r
, &g
, &b
, ialpha
);
340 return wxColour(r
,g
,b
);
343 #if WXWIN_COMPATIBILITY_2_6
346 wxColour
wxColourBase::CreateByName(const wxString
& name
)
348 return wxColour(name
);
351 void wxColourBase::InitFromName(const wxString
& col
)
356 #endif // WXWIN_COMPATIBILITY_2_6
358 // wxColour <-> wxString utilities, used by wxConfig
359 wxString
wxToString(const wxColourBase
& col
)
361 return col
.IsOk() ? col
.GetAsString(wxC2S_CSS_SYNTAX
)
365 bool wxFromString(const wxString
& str
, wxColourBase
*col
)
367 wxCHECK_MSG( col
, false, wxT("NULL output parameter") );
375 return col
->Set(str
);