]>
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
8 // Copyright: (c) Francesco Montorsi
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
13 // For compilers that support precompilation, includes "wx.h".
14 #include "wx/wxprec.h"
20 #include "wx/colour.h"
25 #include "wx/gdicmn.h"
26 #include "wx/wxcrtvararg.h"
30 IMPLEMENT_VARIANT_OBJECT_EXPORTED(wxColour
,WXDLLEXPORT
)
34 // ----------------------------------------------------------------------------
36 // ----------------------------------------------------------------------------
38 #if wxUSE_EXTENDED_RTTI
42 template<> void wxStringReadValue(const wxString
&s
, wxColour
&data
)
46 wxLogError(_("String To Colour : Incorrect colour specification : %s"),
52 template<> void wxStringWriteValue(wxString
&s
, const wxColour
&data
)
54 s
= data
.GetAsString(wxC2S_HTML_SYNTAX
);
57 wxTO_STRING_IMP( wxColour
)
58 wxFROM_STRING_IMP( wxColour
)
60 wxIMPLEMENT_DYNAMIC_CLASS_WITH_COPY_AND_STREAMERS_XTI( wxColour
, wxObject
, \
61 "wx/colour.h", &wxTO_STRING( wxColour
), &wxFROM_STRING( wxColour
))
62 //WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl<wxColour>)
63 wxBEGIN_PROPERTIES_TABLE(wxColour
)
64 wxREADONLY_PROPERTY( Red
, unsigned char, Red
, wxEMPTY_PARAMETER_VALUE
, \
65 0 /*flags*/, wxT("Helpstring"), wxT("group"))
66 wxREADONLY_PROPERTY( Green
, unsigned char, Green
, wxEMPTY_PARAMETER_VALUE
, \
67 0 /*flags*/, wxT("Helpstring"), wxT("group"))
68 wxREADONLY_PROPERTY( Blue
, unsigned char, Blue
, wxEMPTY_PARAMETER_VALUE
, \
69 0 /*flags*/, wxT("Helpstring"), wxT("group"))
70 wxEND_PROPERTIES_TABLE()
72 wxDIRECT_CONSTRUCTOR_3( wxColour
, unsigned char, Red
, \
73 unsigned char, Green
, unsigned char, Blue
)
75 wxEMPTY_HANDLERS_TABLE(wxColour
)
78 #if wxCOLOUR_IS_GDIOBJECT
79 wxIMPLEMENT_DYNAMIC_CLASS(wxColour
, wxGDIObject
)
81 wxIMPLEMENT_DYNAMIC_CLASS(wxColour
, wxObject
)
86 // ============================================================================
87 // wxString <-> wxColour conversions
88 // ============================================================================
90 bool wxColourBase::FromString(const wxString
& str
)
93 return false; // invalid or empty string
95 if ( wxStrnicmp(str
, wxT("RGB"), 3) == 0 )
97 // CSS-like RGB specification
98 // according to http://www.w3.org/TR/css3-color/#colorunits
99 // values outside 0-255 range are allowed but should be clipped
100 int red
, green
, blue
,
101 alpha
= wxALPHA_OPAQUE
;
102 if ( str
.length() > 3 && (str
[3] == wxT('a') || str
[3] == wxT('A')) )
104 // We can't use sscanf() for the alpha value as sscanf() uses the
105 // current locale while the floating point numbers in CSS always
106 // use point as decimal separator, regardless of locale. So parse
107 // the tail of the string manually by putting it in a buffer and
108 // using wxString::ToCDouble() below. Notice that we can't use "%s"
109 // for this as it stops at white space and we need "%c" to avoid
110 // this and really get all the rest of the string into the buffer.
112 const unsigned len
= str
.length(); // always big enough
113 wxCharBuffer
alphaBuf(len
);
114 char * const alphaPtr
= alphaBuf
.data();
116 for ( unsigned n
= 0; n
< len
; n
++ )
119 // Construct the format string which ensures that the last argument
120 // receives all the rest of the string.
122 formatStr
<< wxS("( %d , %d , %d , %") << len
<< 'c';
124 // Notice that we use sscanf() here because if the string is not
125 // ASCII it can't represent a valid RGB colour specification anyhow
126 // and like this we can be sure that %c corresponds to "char *"
127 // while with wxSscanf() it depends on the type of the string
128 // passed as first argument: if it is a wide string, then %c
129 // expects "wchar_t *" matching parameter under MSW for example.
130 if ( sscanf(str
.c_str() + 4,
132 &red
, &green
, &blue
, alphaPtr
) != 4 )
135 // Notice that we must explicitly specify the length to get rid of
137 wxString
alphaStr(alphaPtr
, wxStrlen(alphaPtr
));
138 if ( alphaStr
.empty() || alphaStr
.Last() != ')' )
141 alphaStr
.RemoveLast();
145 if ( !alphaStr
.ToCDouble(&a
) )
148 alpha
= wxRound(a
* 255);
150 else // no 'a' following "rgb"
152 if ( wxSscanf(str
.wx_str() + 3, wxT("( %d , %d , %d )"),
153 &red
, &green
, &blue
) != 3 )
157 Set((unsigned char)wxClip(red
, 0, 255),
158 (unsigned char)wxClip(green
, 0, 255),
159 (unsigned char)wxClip(blue
, 0, 255),
160 (unsigned char)wxClip(alpha
, 0, 255));
162 else if ( str
[0] == wxT('#') && wxStrlen(str
) == 7 )
164 // hexadecimal prefixed with # (HTML syntax)
166 if (wxSscanf(str
.wx_str() + 1, wxT("%lx"), &tmp
) != 1)
169 Set((unsigned char)(tmp
>> 16),
170 (unsigned char)(tmp
>> 8),
173 else if (wxTheColourDatabase
) // a colour name ?
176 // *this = wxTheColourDatabase->Find(str)
177 // because this place can be called from constructor
178 // and 'this' could not be available yet
179 wxColour clr
= wxTheColourDatabase
->Find(str
);
181 Set((unsigned char)clr
.Red(),
182 (unsigned char)clr
.Green(),
183 (unsigned char)clr
.Blue());
189 wxLogDebug(wxT("wxColour::Set - couldn't set to colour string '%s'"), str
);
193 wxString
wxColourBase::GetAsString(long flags
) const
197 const bool isOpaque
= Alpha() == wxALPHA_OPAQUE
;
199 // we can't use the name format if the colour is not opaque as the alpha
200 // information would be lost
201 if ( (flags
& wxC2S_NAME
) && isOpaque
)
203 colName
= wxTheColourDatabase
->FindName(
204 static_cast<const wxColour
&>(*this)).MakeLower();
207 if ( colName
.empty() )
209 const int red
= Red(),
213 if ( flags
& wxC2S_CSS_SYNTAX
)
215 // no name for this colour; return it in CSS syntax
218 colName
.Printf(wxT("rgb(%d, %d, %d)"), red
, green
, blue
);
220 else // use rgba() form
222 colName
.Printf(wxT("rgba(%d, %d, %d, %s)"),
224 wxString::FromCDouble(Alpha() / 255., 3));
227 else if ( flags
& wxC2S_HTML_SYNTAX
)
229 wxASSERT_MSG( isOpaque
, "alpha is lost in HTML syntax" );
231 // no name for this colour; return it in HTML syntax
232 colName
.Printf(wxT("#%02X%02X%02X"), red
, green
, blue
);
236 // this function should alway returns a non-empty string
237 wxASSERT_MSG(!colName
.empty(),
238 wxT("Invalid wxColour -> wxString conversion flags"));
244 void wxColourBase::MakeMono(unsigned char* r
, unsigned char* g
, unsigned char* b
,
247 *r
= *g
= *b
= on
? 255 : 0;
251 void wxColourBase::MakeGrey(unsigned char* r
, unsigned char* g
, unsigned char* b
252 /*, unsigned char brightness */
255 *r
= *g
= *b
= (wxByte
)(((*b
)*117UL + (*g
)*601UL + (*r
)*306UL) >> 10);
259 void wxColourBase::MakeGrey(unsigned char* r
, unsigned char* g
, unsigned char* b
,
260 double weight_r
, double weight_g
, double weight_b
)
262 double luma
= (*r
) * weight_r
+ (*g
) * weight_g
+ (*b
) * weight_b
;
263 *r
= *g
= *b
= (wxByte
)wxRound(luma
);
267 void wxColourBase::MakeDisabled(unsigned char* r
, unsigned char* g
, unsigned char* b
,
268 unsigned char brightness
)
270 //MakeGrey(r, g, b, brightness); // grey no-blend version
271 *r
= AlphaBlend(*r
, brightness
, 0.4);
272 *g
= AlphaBlend(*g
, brightness
, 0.4);
273 *b
= AlphaBlend(*b
, brightness
, 0.4);
276 wxColour
& wxColourBase::MakeDisabled(unsigned char brightness
)
278 unsigned char r
= Red(),
281 MakeDisabled(&r
, &g
, &b
, brightness
);
282 Set(r
, g
, b
, Alpha());
283 return static_cast<wxColour
&>(*this);
286 // AlphaBlend is used by ChangeLightness and MakeDisabled
289 unsigned char wxColourBase::AlphaBlend(unsigned char fg
, unsigned char bg
,
292 double result
= bg
+ (alpha
* (fg
- bg
));
293 result
= wxMax(result
, 0.0);
294 result
= wxMin(result
, 255.0);
295 return (unsigned char)result
;
298 // ChangeLightness() is a utility function that simply darkens
299 // or lightens a color, based on the specified percentage
300 // ialpha of 0 would be completely black, 100 completely white
301 // an ialpha of 100 returns the same colour
304 void wxColourBase::ChangeLightness(unsigned char* r
, unsigned char* g
, unsigned char* b
,
307 if (ialpha
== 100) return;
309 // ialpha is 0..200 where 0 is completely black
310 // and 200 is completely white and 100 is the same
311 // convert that to normal alpha 0.0 - 1.0
312 ialpha
= wxMax(ialpha
, 0);
313 ialpha
= wxMin(ialpha
, 200);
314 double alpha
= ((double)(ialpha
- 100.0))/100.0;
321 alpha
= 1.0 - alpha
; // 0 = transparent fg; 1 = opaque fg
327 alpha
= 1.0 + alpha
; // 0 = transparent fg; 1 = opaque fg
330 *r
= AlphaBlend(*r
, bg
, alpha
);
331 *g
= AlphaBlend(*g
, bg
, alpha
);
332 *b
= AlphaBlend(*b
, bg
, alpha
);
335 wxColour
wxColourBase::ChangeLightness(int ialpha
) const
340 ChangeLightness(&r
, &g
, &b
, ialpha
);
341 return wxColour(r
,g
,b
);
344 #if WXWIN_COMPATIBILITY_2_6
347 wxColour
wxColourBase::CreateByName(const wxString
& name
)
349 return wxColour(name
);
352 void wxColourBase::InitFromName(const wxString
& col
)
357 #endif // WXWIN_COMPATIBILITY_2_6
359 // wxColour <-> wxString utilities, used by wxConfig
360 wxString
wxToString(const wxColourBase
& col
)
362 return col
.IsOk() ? col
.GetAsString(wxC2S_CSS_SYNTAX
)
366 bool wxFromString(const wxString
& str
, wxColourBase
*col
)
368 wxCHECK_MSG( col
, false, wxT("NULL output parameter") );
376 return col
->Set(str
);