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