xref: /haiku/src/libs/icon/style/Style.cpp (revision 820dca4df6c7bf955c46e8f6521b9408f50b2900)
1 /*
2  * Copyright 2006, Haiku.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Stephan Aßmus <superstippi@gmx.de>
7  */
8 
9 #include "Style.h"
10 
11 #include <new>
12 
13 # include <Message.h>
14 
15 #ifdef ICON_O_MATIC
16 # include "ui_defines.h"
17 #else
18 # define kWhite (rgb_color){ 255, 255, 255, 255 }
19 #endif // ICON_O_MATIC
20 
21 #include "GradientTransformable.h"
22 
23 using std::nothrow;
24 
25 // constructor
26 Style::Style()
27 #ifdef ICON_O_MATIC
28 	: IconObject("<style>"),
29 	  Observer(),
30 #else
31 	:
32 #endif
33 
34 	  fColor(kWhite),
35 	  fGradient(NULL),
36 	  fColors(NULL),
37 
38 	  fGammaCorrectedColors(NULL),
39 	  fGammaCorrectedColorsValid(false)
40 {
41 }
42 
43 // constructor
44 Style::Style(const rgb_color& color)
45 #ifdef ICON_O_MATIC
46 	: IconObject("<style>"),
47 	  Observer(),
48 #else
49 	:
50 #endif
51 
52 	  fColor(color),
53 	  fGradient(NULL),
54 	  fColors(NULL),
55 
56 	  fGammaCorrectedColors(NULL),
57 	  fGammaCorrectedColorsValid(false)
58 {
59 }
60 
61 // constructor
62 Style::Style(const Style& other)
63 #ifdef ICON_O_MATIC
64 	: IconObject(other),
65 	  Observer(),
66 #else
67 	:
68 #endif
69 
70 	  fColor(other.fColor),
71 	  fGradient(NULL),
72 	  fColors(NULL),
73 
74 	  fGammaCorrectedColors(NULL),
75 	  fGammaCorrectedColorsValid(false)
76 {
77 	SetGradient(other.fGradient);
78 }
79 
80 // constructor
81 Style::Style(BMessage* archive)
82 #ifdef ICON_O_MATIC
83 	: IconObject(archive),
84 	  Observer(),
85 #else
86 	:
87 #endif
88 
89 	  fColor(kWhite),
90 	  fGradient(NULL),
91 	  fColors(NULL),
92 
93 	  fGammaCorrectedColors(NULL),
94 	  fGammaCorrectedColorsValid(false)
95 {
96 	if (!archive)
97 		return;
98 
99 	if (archive->FindInt32("color", (int32*)&fColor) < B_OK)
100 		fColor = kWhite;
101 
102 	BMessage gradientArchive;
103 	if (archive->FindMessage("gradient", &gradientArchive) == B_OK) {
104 		::Gradient gradient(&gradientArchive);
105 		SetGradient(&gradient);
106 	}
107 }
108 
109 // destructor
110 Style::~Style()
111 {
112 	SetGradient(NULL);
113 }
114 
115 #ifdef ICON_O_MATIC
116 // ObjectChanged
117 void
118 Style::ObjectChanged(const Observable* object)
119 {
120 	if (object == fGradient && fColors) {
121 		fGradient->MakeGradient((uint32*)fColors, 256);
122 		fGammaCorrectedColorsValid = false;
123 		Notify();
124 	}
125 }
126 
127 // #pragma mark -
128 
129 // Archive
130 status_t
131 Style::Archive(BMessage* into, bool deep) const
132 {
133 	status_t ret = IconObject::Archive(into, deep);
134 
135 	if (ret == B_OK)
136 		ret = into->AddInt32("color", (uint32&)fColor);
137 
138 	if (ret == B_OK && fGradient) {
139 		BMessage gradientArchive;
140 		ret = fGradient->Archive(&gradientArchive, deep);
141 		if (ret == B_OK)
142 			ret = into->AddMessage("gradient", &gradientArchive);
143 	}
144 
145 	return ret;
146 }
147 
148 // operator ==
149 bool
150 Style::operator==(const Style& other) const
151 {
152 	if (fGradient) {
153 		if (other.fGradient)
154 			return *fGradient == *other.fGradient;
155 		else
156 			return false;
157 	} else {
158 		if (!other.fGradient)
159 			return *(uint32*)&fColor == *(uint32*)&other.fColor;
160 		else
161 			return false;
162 	}
163 }
164 
165 #endif // ICON_O_MATIC
166 
167 // HasTransparency
168 bool
169 Style::HasTransparency() const
170 {
171 	if (fGradient) {
172 		int32 count = fGradient->CountColors();
173 		for (int32 i = 0; i < count; i++) {
174 			BGradient::ColorStop* step = fGradient->ColorAtFast(i);
175 			if (step->color.alpha < 255)
176 				return true;
177 		}
178 		return false;
179 	}
180 	return fColor.alpha < 255;
181 }
182 
183 // SetColor
184 void
185 Style::SetColor(const rgb_color& color)
186 {
187 	if (*(uint32*)&fColor == *(uint32*)&color)
188 		return;
189 
190 	fColor = color;
191 	Notify();
192 }
193 
194 // SetGradient
195 void
196 Style::SetGradient(const ::Gradient* gradient)
197 {
198 	if (!fGradient && !gradient)
199 		return;
200 
201 	if (gradient) {
202 		if (!fGradient) {
203 			fGradient = new (nothrow) ::Gradient(*gradient);
204 			if (fGradient) {
205 #ifdef ICON_O_MATIC
206 				fGradient->AddObserver(this);
207 #endif
208 				// generate gradient
209 				fColors = new agg::rgba8[256];
210 				fGradient->MakeGradient((uint32*)fColors, 256);
211 				fGammaCorrectedColorsValid = false;
212 
213 				Notify();
214 			}
215 		} else {
216 			if (*fGradient != *gradient) {
217 				*fGradient = *gradient;
218 			}
219 		}
220 	} else {
221 #ifdef ICON_O_MATIC
222 		fGradient->RemoveObserver(this);
223 #endif
224 		delete[] fColors;
225 		delete[] fGammaCorrectedColors;
226 		fColors = NULL;
227 		fGammaCorrectedColors = NULL;
228 		fGradient = NULL;
229 		Notify();
230 	}
231 }
232 
233 // GammaCorrectedColors
234 const agg::rgba8*
235 Style::GammaCorrectedColors(const GammaTable& table) const
236 {
237 	if (!fColors)
238 		return NULL;
239 
240 	if (!fGammaCorrectedColors)
241 		fGammaCorrectedColors = new agg::rgba8[256];
242 
243 	if (!fGammaCorrectedColorsValid) {
244 		for (int32 i = 0; i < 256; i++) {
245 			fGammaCorrectedColors[i].r = table.dir(fColors[i].r);
246 			fGammaCorrectedColors[i].g = table.dir(fColors[i].g);
247 			fGammaCorrectedColors[i].b = table.dir(fColors[i].b);
248 			fGammaCorrectedColors[i].a = fColors[i].a;
249 			fGammaCorrectedColors[i].premultiply();
250 		}
251 		fGammaCorrectedColorsValid = true;
252 	}
253 
254 	return fGammaCorrectedColors;
255 }
256 
257