1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/osx/core/colour.cpp
3 // Purpose: wxColour class
4 // Author: Stefan Csomor
5 // Modified by:
6 // Created: 1998-01-01
7 // Copyright: (c) Stefan Csomor
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
10
11 #include "wx/wxprec.h"
12
13 #include "wx/colour.h"
14
15 #ifndef WX_PRECOMP
16 #include "wx/gdicmn.h"
17 #endif
18
19 #include "wx/osx/private.h"
20 #include "wx/osx/private/available.h"
21
22 CGColorSpaceRef wxMacGetGenericRGBColorSpace();
23
24 class wxCGColorRefData : public wxColourRefData
25 {
26 public:
27 wxCGColorRefData(CGFloat r, CGFloat g, CGFloat b, CGFloat a = 1.0);
28
29 wxCGColorRefData(CGFloat components[4]);
30
31 wxCGColorRefData(CGColorRef);
32
33 wxCGColorRefData(const wxCGColorRefData& other);
34
IsOk() const35 virtual bool IsOk() const wxOVERRIDE{ return m_cgColour != NULL; }
36
Red() const37 virtual CGFloat Red() const wxOVERRIDE { return m_red; }
Green() const38 virtual CGFloat Green() const wxOVERRIDE { return m_green; }
Blue() const39 virtual CGFloat Blue() const wxOVERRIDE { return m_blue; }
Alpha() const40 virtual CGFloat Alpha() const wxOVERRIDE { return m_alpha; }
41
GetCGColor() const42 CGColorRef GetCGColor() const wxOVERRIDE { return m_cgColour; }
43
Clone() const44 virtual wxColourRefData* Clone() const wxOVERRIDE { return new wxCGColorRefData(*this); }
45
46 private:
47 void Init(CGFloat components[4]);
48
49 wxCFRef<CGColorRef> m_cgColour;
50
51 CGFloat m_red;
52 CGFloat m_blue;
53 CGFloat m_green;
54 CGFloat m_alpha;
55
56 wxDECLARE_NO_ASSIGN_CLASS(wxCGColorRefData);
57 };
58
wxCGColorRefData(CGFloat r,CGFloat g,CGFloat b,CGFloat a)59 wxCGColorRefData::wxCGColorRefData(CGFloat r, CGFloat g, CGFloat b, CGFloat a)
60 {
61 CGFloat components[4];
62 components[0] = r;
63 components[1] = g;
64 components[2] = b;
65 components[3] = a;
66
67 Init(components);
68 }
69
wxCGColorRefData(CGFloat components[4])70 wxCGColorRefData::wxCGColorRefData(CGFloat components[4])
71 {
72 Init(components);
73 }
74
wxCGColorRefData(const wxCGColorRefData & other)75 wxCGColorRefData::wxCGColorRefData(const wxCGColorRefData& other)
76 {
77 m_red = other.m_red;
78 m_blue = other.m_blue;
79 m_green = other.m_green;
80 m_alpha = other.m_alpha;
81
82 m_cgColour = other.m_cgColour;
83 }
84
Init(CGFloat components[4])85 void wxCGColorRefData::Init(CGFloat components[4])
86 {
87 m_red = components[0];
88 m_green = components[1];
89 m_blue = components[2];
90 m_alpha = components[3];
91
92 m_cgColour = CGColorCreate(wxMacGetGenericRGBColorSpace(), components);
93 }
94
wxCGColorRefData(CGColorRef col)95 wxCGColorRefData::wxCGColorRefData(CGColorRef col)
96 {
97 wxASSERT_MSG(col != NULL, "Invalid CoreGraphics Color");
98 m_cgColour.reset(col);
99
100 wxCFRef<CGColorRef> rgbacol;
101 size_t noComp = CGColorGetNumberOfComponents(col);
102 const CGFloat* components = CGColorGetComponents(col);
103
104 // set default alpha
105 m_alpha = 1.0;
106 bool isRGB = true;
107
108 CGColorSpaceModel model = CGColorSpaceGetModel(CGColorGetColorSpace(col));
109 if (model == kCGColorSpaceModelMonochrome)
110 {
111 wxASSERT_MSG(1 <= noComp && noComp <= 2, "Monochrome Color unexpected components");
112 m_red = components[0];
113 m_green = components[0];
114 m_blue = components[0];
115 if (noComp > 1)
116 m_alpha = components[1];
117 isRGB = false;
118 }
119 else if (model != kCGColorSpaceModelRGB)
120 {
121 if ( WX_IS_MACOS_OR_IOS_AVAILABLE(10, 11, 9, 0) )
122 {
123 rgbacol = CGColorCreateCopyByMatchingToColorSpace(wxMacGetGenericRGBColorSpace(), kCGRenderingIntentDefault, col, NULL);
124 noComp = CGColorGetNumberOfComponents(rgbacol);
125 components = CGColorGetComponents(rgbacol);
126 }
127 else
128 {
129 isRGB = false;
130 }
131 }
132
133 if (isRGB)
134 {
135 wxASSERT_MSG(3 <= noComp && noComp <= 4, "RGB Color unexpected components");
136 m_red = components[0];
137 m_green = components[1];
138 m_blue = components[2];
139
140 if (noComp == 4)
141 m_alpha = components[3];
142 }
143 }
144
145 #define M_COLDATA static_cast<wxColourRefData*>(m_refData)
146
147 #if wxOSX_USE_COCOA_OR_CARBON
wxColour(const RGBColor & col)148 wxColour::wxColour(const RGBColor& col)
149 {
150 CGFloat components[4] = { (CGFloat)(col.red / 65535.0), (CGFloat)(col.green / 65535.0),
151 (CGFloat)(col.blue / 65535.0), (CGFloat)1.0 };
152 m_refData = new wxCGColorRefData(components);
153 }
154 #endif
155
wxColour(CGColorRef col)156 wxColour::wxColour(CGColorRef col)
157 {
158 wxASSERT_MSG(col != NULL, "Invalid CoreGraphics Color");
159
160 m_refData = new wxCGColorRefData(col);
161 }
162
Red() const163 wxColour::ChannelType wxColour::Red() const
164 {
165 wxCHECK_MSG( IsOk(), 0, "invalid colour" );
166
167 return wxRound(M_COLDATA->Red() * 255.0);
168 }
169
Green() const170 wxColour::ChannelType wxColour::Green() const
171 {
172 wxCHECK_MSG( IsOk(), 0, "invalid colour" );
173
174 return wxRound(M_COLDATA->Green() * 255.0);
175 }
176
Blue() const177 wxColour::ChannelType wxColour::Blue() const
178 {
179 wxCHECK_MSG( IsOk(), 0, "invalid colour" );
180
181 return wxRound(M_COLDATA->Blue() * 255.0);
182 }
183
Alpha() const184 wxColour::ChannelType wxColour::Alpha() const
185 {
186 wxCHECK_MSG( IsOk(), 0, "invalid colour" );
187
188 return wxRound(M_COLDATA->Alpha() * 255.0);
189 }
190
IsSolid() const191 bool wxColour::IsSolid() const
192 {
193 wxCHECK_MSG( IsOk(), false, "invalid colour" );
194
195 return M_COLDATA->IsSolid();
196 }
197
198 #if wxOSX_USE_COCOA_OR_CARBON
GetRGBColor(RGBColor * col) const199 void wxColour::GetRGBColor(RGBColor* col) const
200 {
201 wxCHECK_RET( IsOk(), "invalid colour" );
202
203 col->red = M_COLDATA->Red() * 65535.0;
204 col->blue = M_COLDATA->Blue() * 65535.0;
205 col->green = M_COLDATA->Green() * 65535.0;
206 }
207 #endif
208
GetCGColor() const209 CGColorRef wxColour::GetCGColor() const
210 {
211 wxCHECK_MSG( IsOk(), NULL, "invalid colour" );
212
213 return M_COLDATA->GetCGColor();
214 }
215
216 #if wxOSX_USE_COCOA
OSXGetNSColor() const217 WX_NSColor wxColour::OSXGetNSColor() const
218 {
219 wxCHECK_MSG( IsOk(), NULL, "invalid colour" );
220
221 return M_COLDATA->GetNSColor();
222 }
223
OSXGetNSPatternImage() const224 WX_NSImage wxColour::OSXGetNSPatternImage() const
225 {
226 wxCHECK_MSG( IsOk(), NULL, "invalid colour" );
227
228 return M_COLDATA->GetNSPatternImage();
229 }
230 #endif
231
InitRGBA(ChannelType r,ChannelType g,ChannelType b,ChannelType a)232 void wxColour::InitRGBA(ChannelType r, ChannelType g, ChannelType b, ChannelType a)
233 {
234 CGFloat components[4] = { (CGFloat)(r / 255.0), (CGFloat)(g / 255.0), (CGFloat)(b / 255.0), (CGFloat)(a / 255.0) };
235 m_refData = new wxCGColorRefData(components);
236 }
237
operator ==(const wxColour & other) const238 bool wxColour::operator==(const wxColour& other) const
239 {
240 if (m_refData == other.m_refData)
241 return true;
242
243 if (!m_refData || !other.m_refData)
244 return false;
245
246 return CGColorEqualToColor(GetCGColor(), other.GetCGColor());
247 }
248
CreateGDIRefData() const249 wxGDIRefData* wxColour::CreateGDIRefData() const
250 {
251 // black
252 return new wxCGColorRefData(0.0, 0.0, 0.0);
253 }
254
CloneGDIRefData(const wxGDIRefData * data) const255 wxGDIRefData* wxColour::CloneGDIRefData(const wxGDIRefData* data) const
256 {
257 return static_cast<const wxColourRefData*>(data)->Clone();
258 }
259