1 /* 2 * Copyright 2006, 2023, Haiku. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Stephan Aßmus <superstippi@gmx.de> 7 * Zardshard 8 */ 9 10 #include "Style.h" 11 12 #include <new> 13 14 #include <Bitmap.h> 15 #include <Message.h> 16 17 #ifdef ICON_O_MATIC 18 # include "ui_defines.h" 19 #else 20 # define kWhite (rgb_color){ 255, 255, 255, 255 } 21 #endif // ICON_O_MATIC 22 23 #include "GradientTransformable.h" 24 25 using std::nothrow; 26 27 28 Style::Style() 29 #ifdef ICON_O_MATIC 30 : IconObject("<style>"), 31 Observer(), 32 #else 33 : 34 #endif 35 36 fColor(kWhite), 37 fGradient(NULL), 38 fColors(NULL), 39 #ifdef ICON_O_MATIC 40 fImage(NULL), 41 fAlpha(255), 42 #endif 43 44 fGammaCorrectedColors(NULL), 45 fGammaCorrectedColorsValid(false) 46 { 47 } 48 49 50 Style::Style(const rgb_color& color) 51 #ifdef ICON_O_MATIC 52 : IconObject("<style>"), 53 Observer(), 54 #else 55 : 56 #endif 57 58 fColor(color), 59 fGradient(NULL), 60 fColors(NULL), 61 #ifdef ICON_O_MATIC 62 fImage(NULL), 63 fAlpha(255), 64 #endif 65 66 fGammaCorrectedColors(NULL), 67 fGammaCorrectedColorsValid(false) 68 { 69 } 70 71 72 #ifdef ICON_O_MATIC 73 Style::Style(BBitmap* image) 74 : IconObject("<style>"), 75 Observer(), 76 77 fColor(kWhite), 78 fGradient(NULL), 79 fColors(NULL), 80 fImage(image), 81 82 fGammaCorrectedColors(NULL), 83 fGammaCorrectedColorsValid(false) 84 { 85 } 86 #endif 87 88 89 Style::Style(const Style& other) 90 #ifdef ICON_O_MATIC 91 : IconObject(other), 92 Observer(), 93 #else 94 : 95 #endif 96 97 fColor(other.fColor), 98 fGradient(NULL), 99 fColors(NULL), 100 #ifdef ICON_O_MATIC 101 fImage(other.fImage != NULL ? new (nothrow) BBitmap(other.fImage) : NULL), 102 fAlpha(255), 103 #endif 104 105 fGammaCorrectedColors(NULL), 106 fGammaCorrectedColorsValid(false) 107 { 108 SetGradient(other.fGradient); 109 } 110 111 // constructor 112 Style::Style(BMessage* archive) 113 #ifdef ICON_O_MATIC 114 : IconObject(archive), 115 Observer(), 116 #else 117 : 118 #endif 119 120 fColor(kWhite), 121 fGradient(NULL), 122 fColors(NULL), 123 #ifdef ICON_O_MATIC 124 fImage(NULL), 125 fAlpha(255), 126 #endif 127 128 fGammaCorrectedColors(NULL), 129 fGammaCorrectedColorsValid(false) 130 { 131 if (!archive) 132 return; 133 134 if (archive->FindInt32("color", (int32*)&fColor) < B_OK) 135 fColor = kWhite; 136 137 BMessage gradientArchive; 138 if (archive->FindMessage("gradient", &gradientArchive) == B_OK) { 139 ::Gradient gradient(&gradientArchive); 140 SetGradient(&gradient); 141 } 142 } 143 144 145 Style::~Style() 146 { 147 SetGradient(NULL); 148 149 #ifdef ICON_O_MATIC 150 delete fImage; 151 #endif 152 } 153 154 155 #ifdef ICON_O_MATIC 156 void 157 Style::ObjectChanged(const Observable* object) 158 { 159 if (object == fGradient && fColors) { 160 fGradient->MakeGradient((uint32*)fColors, 256); 161 fGammaCorrectedColorsValid = false; 162 Notify(); 163 } 164 } 165 166 167 // #pragma mark - 168 169 170 status_t 171 Style::Archive(BMessage* into, bool deep) const 172 { 173 status_t ret = IconObject::Archive(into, deep); 174 175 if (ret == B_OK) 176 ret = into->AddInt32("color", (uint32&)fColor); 177 178 if (ret == B_OK && fGradient) { 179 BMessage gradientArchive; 180 ret = fGradient->Archive(&gradientArchive, deep); 181 if (ret == B_OK) 182 ret = into->AddMessage("gradient", &gradientArchive); 183 } 184 185 // Archiving the fImage is the responsibility of ReferenceImage 186 187 return ret; 188 } 189 190 191 bool 192 Style::operator==(const Style& other) const 193 { 194 if (fGradient) { 195 if (other.fGradient) 196 return *fGradient == *other.fGradient; 197 else 198 return false; 199 } else { 200 if (!other.fGradient) 201 return *(uint32*)&fColor == *(uint32*)&other.fColor; 202 else 203 return false; 204 } 205 } 206 #endif // ICON_O_MATIC 207 208 209 bool 210 Style::HasTransparency() const 211 { 212 if (fGradient) { 213 int32 count = fGradient->CountColors(); 214 for (int32 i = 0; i < count; i++) { 215 BGradient::ColorStop* step = fGradient->ColorAtFast(i); 216 if (step->color.alpha < 255) 217 return true; 218 } 219 return false; 220 } 221 return fColor.alpha < 255; 222 } 223 224 225 void 226 Style::SetColor(const rgb_color& color) 227 { 228 if (*(uint32*)&fColor == *(uint32*)&color) 229 return; 230 231 fColor = color; 232 Notify(); 233 } 234 235 236 void 237 Style::SetGradient(const ::Gradient* gradient) 238 { 239 if (!fGradient && !gradient) 240 return; 241 242 if (gradient) { 243 if (!fGradient) { 244 fGradient = new (nothrow) ::Gradient(*gradient); 245 if (fGradient) { 246 #ifdef ICON_O_MATIC 247 fGradient->AddObserver(this); 248 #endif 249 // generate gradient 250 fColors = new agg::rgba8[256]; 251 fGradient->MakeGradient((uint32*)fColors, 256); 252 fGammaCorrectedColorsValid = false; 253 254 Notify(); 255 } 256 } else { 257 if (*fGradient != *gradient) { 258 *fGradient = *gradient; 259 } 260 } 261 } else { 262 #ifdef ICON_O_MATIC 263 fGradient->RemoveObserver(this); 264 #endif 265 delete[] fColors; 266 delete[] fGammaCorrectedColors; 267 #ifdef ICON_O_MATIC 268 if (fGradient != NULL) 269 fGradient->ReleaseReference(); 270 271 delete fImage; 272 fImage = NULL; 273 #else 274 delete fGradient; 275 #endif 276 fColors = NULL; 277 fGammaCorrectedColors = NULL; 278 fGradient = NULL; 279 Notify(); 280 } 281 } 282 283 284 #ifdef ICON_O_MATIC 285 void 286 Style::SetBitmap(BBitmap* image) 287 { 288 delete fImage; 289 fImage = image; 290 291 // TODO: This does not reset fGradient or fColors. Currently, this is not 292 // required, since Icon-O-Matic never turns Gradients into Bitmaps. Probably, 293 // this class should be subclassed if this feature is ever required. For more 294 // information, see the todo item in the header file. 295 if (fGradient != NULL) 296 debugger("Not implemented"); 297 298 Notify(); 299 } 300 #endif // ICON_O_MATIC 301 302 303 const agg::rgba8* 304 Style::GammaCorrectedColors(const GammaTable& table) const 305 { 306 if (!fColors) 307 return NULL; 308 309 if (!fGammaCorrectedColors) 310 fGammaCorrectedColors = new agg::rgba8[256]; 311 312 if (!fGammaCorrectedColorsValid) { 313 for (int32 i = 0; i < 256; i++) { 314 fGammaCorrectedColors[i].r = table.dir(fColors[i].r); 315 fGammaCorrectedColors[i].g = table.dir(fColors[i].g); 316 fGammaCorrectedColors[i].b = table.dir(fColors[i].b); 317 fGammaCorrectedColors[i].a = fColors[i].a; 318 fGammaCorrectedColors[i].premultiply(); 319 } 320 fGammaCorrectedColorsValid = true; 321 } 322 323 return fGammaCorrectedColors; 324 } 325 326