xref: /haiku/src/libs/icon/style/Style.cpp (revision d2e1e872611179c9cfaa43ce11bd58b1e3554e4b)
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 #ifdef ICON_O_MATIC
14 # include <Message.h>
15 
16 # include "ui_defines.h"
17 #else
18 # define kWhite (rgb_color){ 255, 255, 255, 255 }
19 #endif // ICON_O_MATIC
20 
21 #include "Gradient.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 #ifdef ICON_O_MATIC
81 // constructor
82 Style::Style(BMessage* archive)
83 	: IconObject(archive),
84 	  Observer(),
85 
86 	  fColor(kWhite),
87 	  fGradient(NULL),
88 	  fColors(NULL),
89 
90 	  fGammaCorrectedColors(NULL),
91 	  fGammaCorrectedColorsValid(false)
92 {
93 	if (!archive)
94 		return;
95 
96 	if (archive->FindInt32("color", (int32*)&fColor) < B_OK)
97 		fColor = kWhite;
98 
99 	BMessage gradientArchive;
100 	if (archive->FindMessage("gradient", &gradientArchive) == B_OK) {
101 		::Gradient gradient(&gradientArchive);
102 		SetGradient(&gradient);
103 	}
104 }
105 #endif // ICON_O_MATIC
106 
107 // destructor
108 Style::~Style()
109 {
110 	SetGradient(NULL);
111 }
112 
113 #ifdef ICON_O_MATIC
114 // ObjectChanged
115 void
116 Style::ObjectChanged(const Observable* object)
117 {
118 	if (object == fGradient && fColors) {
119 		fGradient->MakeGradient((uint32*)fColors, 256);
120 		fGammaCorrectedColorsValid = false;
121 		Notify();
122 	}
123 }
124 
125 // #pragma mark -
126 
127 // Archive
128 status_t
129 Style::Archive(BMessage* into, bool deep) const
130 {
131 	status_t ret = IconObject::Archive(into, deep);
132 
133 	if (ret == B_OK)
134 		ret = into->AddInt32("color", (uint32&)fColor);
135 
136 	if (ret == B_OK && fGradient) {
137 		BMessage gradientArchive;
138 		ret = fGradient->Archive(&gradientArchive, deep);
139 		if (ret == B_OK)
140 			ret = into->AddMessage("gradient", &gradientArchive);
141 	}
142 
143 	return ret;
144 }
145 
146 // operator ==
147 bool
148 Style::operator==(const Style& other) const
149 {
150 	if (fGradient) {
151 		if (other.fGradient)
152 			return *fGradient == *other.fGradient;
153 		else
154 			return false;
155 	} else {
156 		if (!other.fGradient)
157 			return *(uint32*)&fColor == *(uint32*)&other.fColor;
158 		else
159 			return false;
160 	}
161 }
162 
163 #endif // ICON_O_MATIC
164 
165 // HasTransparency
166 bool
167 Style::HasTransparency() const
168 {
169 	if (fGradient) {
170 		int32 count = fGradient->CountColors();
171 		for (int32 i = 0; i < count; i++) {
172 			color_step* step = fGradient->ColorAtFast(i);
173 			if (step->color.alpha < 255)
174 				return true;
175 		}
176 		return false;
177 	}
178 	return fColor.alpha < 255;
179 }
180 
181 // SetColor
182 void
183 Style::SetColor(const rgb_color& color)
184 {
185 	if (*(uint32*)&fColor == *(uint32*)&color)
186 		return;
187 
188 	fColor = color;
189 	Notify();
190 }
191 
192 // SetGradient
193 void
194 Style::SetGradient(const ::Gradient* gradient)
195 {
196 	if (!fGradient && !gradient)
197 		return;
198 
199 	if (gradient) {
200 		if (!fGradient) {
201 			fGradient = new (nothrow) ::Gradient(*gradient);
202 			if (fGradient) {
203 #ifdef ICON_O_MATIC
204 				fGradient->AddObserver(this);
205 #endif
206 				// generate gradient
207 				fColors = new agg::rgba8[256];
208 				fGradient->MakeGradient((uint32*)fColors, 256);
209 				fGammaCorrectedColorsValid = false;
210 
211 				Notify();
212 			}
213 		} else {
214 			if (*fGradient != *gradient) {
215 				*fGradient = *gradient;
216 			}
217 		}
218 	} else {
219 #ifdef ICON_O_MATIC
220 		fGradient->RemoveObserver(this);
221 #endif
222 		delete[] fColors;
223 		delete[] fGammaCorrectedColors;
224 		fColors = NULL;
225 		fGammaCorrectedColors = NULL;
226 		fGradient = NULL;
227 		Notify();
228 	}
229 }
230 
231 // GammaCorrectedColors
232 const agg::rgba8*
233 Style::GammaCorrectedColors(const GammaTable& table) const
234 {
235 	if (!fColors)
236 		return NULL;
237 
238 	if (!fGammaCorrectedColors)
239 		fGammaCorrectedColors = new agg::rgba8[256];
240 
241 	if (!fGammaCorrectedColorsValid) {
242 		for (int32 i = 0; i < 256; i++) {
243 			fGammaCorrectedColors[i].r = table.dir(fColors[i].r);
244 			fGammaCorrectedColors[i].g = table.dir(fColors[i].g);
245 			fGammaCorrectedColors[i].b = table.dir(fColors[i].b);
246 			fGammaCorrectedColors[i].a = fColors[i].a;
247 			fGammaCorrectedColors[i].premultiply();
248 		}
249 		fGammaCorrectedColorsValid = true;
250 	}
251 
252 	return fGammaCorrectedColors;
253 }
254 
255