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