2 * Copyright 2006-2009, Haiku.
3 * Distributed under the terms of the MIT License.
6 * Stephan Aßmus <superstippi@gmx.de>
7 * Artur Wyszynski <harakash@gmail.com>
20 BGradient::ColorStop::ColorStop(const rgb_color c
, float o
)
23 color
.green
= c
.green
;
25 color
.alpha
= c
.alpha
;
31 BGradient::ColorStop::ColorStop(uint8 r
, uint8 g
, uint8 b
, uint8 a
, float o
)
42 BGradient::ColorStop::ColorStop(const ColorStop
& other
)
44 color
.red
= other
.color
.red
;
45 color
.green
= other
.color
.green
;
46 color
.blue
= other
.color
.blue
;
47 color
.alpha
= other
.color
.alpha
;
48 offset
= other
.offset
;
53 BGradient::ColorStop::ColorStop()
65 BGradient::ColorStop::operator!=(const ColorStop
& other
) const
67 return color
.red
!= other
.color
.red
||
68 color
.green
!= other
.color
.green
||
69 color
.blue
!= other
.color
.blue
||
70 color
.alpha
!= other
.color
.alpha
||
71 offset
!= other
.offset
;
76 sort_color_stops_by_offset(const BGradient::ColorStop
* left
,
77 const BGradient::ColorStop
* right
)
79 return left
->offset
< right
->offset
;
87 BGradient::BGradient()
96 BGradient::BGradient(BMessage
* archive
)
97 : BArchivable(archive
),
106 for (int32 i
= 0; archive
->FindFloat("offset", i
, &stop
.offset
) >= B_OK
; i
++) {
107 if (archive
->FindInt32("color", i
, (int32
*)&stop
.color
) >= B_OK
)
108 AddColorStop(stop
, i
);
112 if (archive
->FindInt32("type", (int32
*)&fType
) < B_OK
)
116 if (archive
->FindFloat("linear_x1", (float*)&fData
.linear
.x1
) < B_OK
)
117 fData
.linear
.x1
= 0.0f
;
118 if (archive
->FindFloat("linear_y1", (float*)&fData
.linear
.y1
) < B_OK
)
119 fData
.linear
.y1
= 0.0f
;
120 if (archive
->FindFloat("linear_x2", (float*)&fData
.linear
.x2
) < B_OK
)
121 fData
.linear
.x2
= 0.0f
;
122 if (archive
->FindFloat("linear_y2", (float*)&fData
.linear
.y2
) < B_OK
)
123 fData
.linear
.y2
= 0.0f
;
126 if (archive
->FindFloat("radial_cx", (float*)&fData
.radial
.cx
) < B_OK
)
127 fData
.radial
.cx
= 0.0f
;
128 if (archive
->FindFloat("radial_cy", (float*)&fData
.radial
.cy
) < B_OK
)
129 fData
.radial
.cy
= 0.0f
;
130 if (archive
->FindFloat("radial_radius", (float*)&fData
.radial
.radius
) < B_OK
)
131 fData
.radial
.radius
= 0.0f
;
134 if (archive
->FindFloat("radial_f_cx", (float*)&fData
.radial_focus
.cx
) < B_OK
)
135 fData
.radial_focus
.cx
= 0.0f
;
136 if (archive
->FindFloat("radial_f_cy", (float*)&fData
.radial_focus
.cy
) < B_OK
)
137 fData
.radial_focus
.cy
= 0.0f
;
138 if (archive
->FindFloat("radial_f_fx", (float*)&fData
.radial_focus
.fx
) < B_OK
)
139 fData
.radial_focus
.fx
= 0.0f
;
140 if (archive
->FindFloat("radial_f_fy", (float*)&fData
.radial_focus
.fy
) < B_OK
)
141 fData
.radial_focus
.fy
= 0.0f
;
142 if (archive
->FindFloat("radial_f_radius", (float*)&fData
.radial_focus
.radius
) < B_OK
)
143 fData
.radial_focus
.radius
= 0.0f
;
146 if (archive
->FindFloat("diamond_cx", (float*)&fData
.diamond
.cx
) < B_OK
)
147 fData
.diamond
.cx
= 0.0f
;
148 if (archive
->FindFloat("diamond_cy", (float*)&fData
.diamond
.cy
) < B_OK
)
149 fData
.diamond
.cy
= 0.0f
;
152 if (archive
->FindFloat("conic_cx", (float*)&fData
.conic
.cx
) < B_OK
)
153 fData
.conic
.cx
= 0.0f
;
154 if (archive
->FindFloat("conic_cy", (float*)&fData
.conic
.cy
) < B_OK
)
155 fData
.conic
.cy
= 0.0f
;
156 if (archive
->FindFloat("conic_angle", (float*)&fData
.conic
.angle
) < B_OK
)
157 fData
.conic
.angle
= 0.0f
;
162 BGradient::~BGradient()
170 BGradient::Archive(BMessage
* into
, bool deep
) const
172 status_t ret
= BArchivable::Archive(into
, deep
);
176 for (int32 i
= 0; ColorStop
* stop
= ColorStopAt(i
); i
++) {
177 ret
= into
->AddInt32("color", (const uint32
&)stop
->color
);
180 ret
= into
->AddFloat("offset", stop
->offset
);
187 ret
= into
->AddInt32("type", (int32
)fType
);
191 ret
= into
->AddFloat("linear_x1", (float)fData
.linear
.x1
);
193 ret
= into
->AddFloat("linear_y1", (float)fData
.linear
.y1
);
195 ret
= into
->AddFloat("linear_x2", (float)fData
.linear
.x2
);
197 ret
= into
->AddFloat("linear_y2", (float)fData
.linear
.y2
);
201 ret
= into
->AddFloat("radial_cx", (float)fData
.radial
.cx
);
203 ret
= into
->AddFloat("radial_cy", (float)fData
.radial
.cy
);
205 ret
= into
->AddFloat("radial_radius", (float)fData
.radial
.radius
);
209 ret
= into
->AddFloat("radial_f_cx", (float)fData
.radial_focus
.cx
);
211 ret
= into
->AddFloat("radial_f_cy", (float)fData
.radial_focus
.cy
);
213 ret
= into
->AddFloat("radial_f_fx", (float)fData
.radial_focus
.fx
);
215 ret
= into
->AddFloat("radial_f_fy", (float)fData
.radial_focus
.fy
);
217 ret
= into
->AddFloat("radial_f_radius", (float)fData
.radial_focus
.radius
);
221 ret
= into
->AddFloat("diamond_cx", (float)fData
.diamond
.cx
);
223 ret
= into
->AddFloat("diamond_cy", (float)fData
.diamond
.cy
);
227 ret
= into
->AddFloat("conic_cx", (float)fData
.conic
.cx
);
229 ret
= into
->AddFloat("conic_cy", (float)fData
.conic
.cy
);
231 ret
= into
->AddFloat("conic_angle", (float)fData
.conic
.angle
);
235 ret
= into
->AddString("class", "BGradient");
243 BGradient::operator=(const BGradient
& other
)
245 SetColorStops(other
);
253 BGradient::operator==(const BGradient
& other
) const
255 return ((other
.GetType() == GetType()) && ColorStopsAreEqual(other
));
261 BGradient::operator!=(const BGradient
& other
) const
263 return !(*this == other
);
267 // ColorStopsAreEqual
269 BGradient::ColorStopsAreEqual(const BGradient
& other
) const
271 int32 count
= CountColorStops();
272 if (count
== other
.CountColorStops() &&
273 fType
== other
.fType
) {
276 for (int32 i
= 0; i
< count
; i
++) {
277 ColorStop
* ourStop
= ColorStopAtFast(i
);
278 ColorStop
* otherStop
= other
.ColorStopAtFast(i
);
279 if (*ourStop
!= *otherStop
) {
292 BGradient::SetColorStops(const BGradient
& other
)
295 for (int32 i
= 0; ColorStop
* stop
= other
.ColorStopAt(i
); i
++)
296 AddColorStop(*stop
, i
);
302 BGradient::AddColor(const rgb_color
& color
, float offset
)
304 // Out of bounds stops would crash the app_server
305 if (offset
< 0.f
|| offset
> 255.f
)
308 // find the correct index (sorted by offset)
309 ColorStop
* stop
= new ColorStop(color
, offset
);
311 int32 count
= CountColorStops();
312 for (; index
< count
; index
++) {
313 ColorStop
* s
= ColorStopAtFast(index
);
314 if (s
->offset
> stop
->offset
)
317 if (!fColorStops
.AddItem((void*)stop
, index
)) {
327 BGradient::AddColorStop(const ColorStop
& colorStop
, int32 index
)
329 ColorStop
* stop
= new ColorStop(colorStop
);
330 if (!fColorStops
.AddItem((void*)stop
, index
)) {
340 BGradient::RemoveColor(int32 index
)
342 ColorStop
* stop
= (ColorStop
*)fColorStops
.RemoveItem(index
);
353 BGradient::SetColorStop(int32 index
, const ColorStop
& color
)
355 if (ColorStop
* stop
= ColorStopAt(index
)) {
356 if (*stop
!= color
) {
357 stop
->color
= color
.color
;
358 stop
->offset
= color
.offset
;
368 BGradient::SetColor(int32 index
, const rgb_color
& color
)
370 ColorStop
* stop
= ColorStopAt(index
);
371 if (stop
&& stop
->color
!= color
) {
381 BGradient::SetOffset(int32 index
, float offset
)
383 ColorStop
* stop
= ColorStopAt(index
);
384 if (stop
&& stop
->offset
!= offset
) {
385 stop
->offset
= offset
;
394 BGradient::CountColorStops() const
396 return fColorStops
.CountItems();
401 BGradient::ColorStop
*
402 BGradient::ColorStopAt(int32 index
) const
404 return (ColorStop
*)fColorStops
.ItemAt(index
);
409 BGradient::ColorStop
*
410 BGradient::ColorStopAtFast(int32 index
) const
412 return (ColorStop
*)fColorStops
.ItemAtFast(index
);
417 BGradient::ColorStop
*
418 BGradient::ColorStops() const
420 if (CountColorStops() > 0) {
421 return (ColorStop
*) fColorStops
.Items();
427 // SortColorStopsByOffset
429 BGradient::SortColorStopsByOffset()
431 // Use stable sort: stops with the same offset will retain their original
432 // order. This can be used to have sharp color changes in the gradient.
433 // BList.SortItems() uses qsort(), which isn't stable, and sometimes swaps
435 const BGradient::ColorStop
** first
= (const BGradient::ColorStop
**)fColorStops
.Items();
436 const BGradient::ColorStop
** last
= first
+ fColorStops
.CountItems();
437 std::stable_sort(first
, last
, sort_color_stops_by_offset
);
443 BGradient::MakeEmpty()
445 int32 count
= CountColorStops();
446 for (int32 i
= 0; i
< count
; i
++)
447 delete ColorStopAtFast(i
);
448 fColorStops
.MakeEmpty();