1 /* 2 * Copyright 2006, Haiku. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Stephan Aßmus <superstippi@gmx.de> 7 */ 8 9 #include "Layer.h" 10 11 #include <stdio.h> 12 13 #include <Bitmap.h> 14 #include <Message.h> 15 16 #include "bitmap_compression.h" 17 #include "blending.h" 18 #include "lab_convert.h" 19 #include "support.h" 20 21 // constructor 22 Layer::Layer() 23 : fBitmap(NULL), 24 fBounds(0.0, 0.0, -1.0, -1.0), 25 fAlpha(1.0), 26 fMode(MODE_NORMAL), 27 fFlags(0) 28 { 29 } 30 31 // destructor 32 Layer::~Layer() 33 { 34 delete fBitmap; 35 } 36 37 // Compose 38 status_t 39 Layer::Compose(const BBitmap* into, BRect area) 40 { 41 if (!fBitmap || !fBitmap->IsValid() 42 || (fBitmap->ColorSpace() != B_RGBA32 && fBitmap->ColorSpace() != B_RGB32)) 43 return B_NO_INIT; 44 45 status_t status = B_BAD_VALUE; 46 if (!into || !area.IsValid() || (status = into->InitCheck()) < B_OK) 47 return status; 48 49 // make sure we don't access memory outside of our bitmap 50 area = area & fBitmap->Bounds(); 51 52 BRect r = ActiveBounds(); 53 if (!r.IsValid() || (fFlags & FLAG_INVISIBLE) || !r.Intersects(area)) 54 return B_OK; 55 56 r = r & area; 57 int32 left, top, right, bottom; 58 rect_to_int(r, left, top, right, bottom); 59 60 uint8* src = (uint8*)fBitmap->Bits(); 61 uint8* dst = (uint8*)into->Bits(); 62 uint32 bpr = into->BytesPerRow(); 63 src += 4 * left + bpr * top; 64 dst += 4 * left + bpr * top; 65 uint8 alphaOverride = (uint8)(fAlpha * 255); 66 67 switch (fMode) { 68 69 case MODE_SOFT_LIGHT: 70 for (; top <= bottom; top++) { 71 uint8* srcHandle = src; 72 uint8* dstHandle = dst; 73 for (int32 x = left; x <= right; x++) { 74 if (srcHandle[3] > 0) { 75 uint8 c1 = dstHandle[0] * srcHandle[0] >> 8; 76 c1 = c1 + dstHandle[0] * (255 - ((255 - dstHandle[0]) * (255 - srcHandle[0]) >> 8) - c1) >> 8; 77 c1 = (c1 * dstHandle[3] + srcHandle[0] * (255 - dstHandle[3])) >> 8; 78 79 uint8 c2 = dstHandle[1] * srcHandle[1] >> 8; 80 c2 = c2 + dstHandle[1] * (255 - ((255 - dstHandle[1]) * (255 - srcHandle[1]) >> 8) - c2) >> 8; 81 c2 = (c2 * dstHandle[3] + srcHandle[1] * (255 - dstHandle[3])) >> 8; 82 83 uint8 c3 = dstHandle[2] * srcHandle[2] >> 8; 84 c3 = c3 + dstHandle[2] * (255 - ((255 - dstHandle[2]) * (255 - srcHandle[2]) >> 8) - c3) >> 8; 85 c3 = (c3 * dstHandle[3] + srcHandle[2] * (255 - dstHandle[3])) >> 8; 86 87 blend_colors(dstHandle, (srcHandle[3] * alphaOverride) >> 8, 88 c1, c2, c3); 89 } 90 srcHandle += 4; 91 dstHandle += 4; 92 } 93 src += bpr; 94 dst += bpr; 95 } 96 break; 97 98 case MODE_LIGHTEN: 99 for (; top <= bottom; top++) { 100 uint8* srcHandle = src; 101 uint8* dstHandle = dst; 102 for (int32 x = left; x <= right; x++) { 103 if (srcHandle[3] > 0) { 104 // compose 105 uint8 c1 = (max_c(srcHandle[0], dstHandle[0]) * dstHandle[3] 106 + srcHandle[0] * (255 - dstHandle[3])) / 255; 107 uint8 c2 = (max_c(srcHandle[1], dstHandle[1]) * dstHandle[3] 108 + srcHandle[1] * (255 - dstHandle[3])) / 255; 109 uint8 c3 = (max_c(srcHandle[2], dstHandle[2]) * dstHandle[3] 110 + srcHandle[2] * (255 - dstHandle[3])) / 255; 111 blend_colors(dstHandle, (srcHandle[3] * alphaOverride) / 255, 112 c1, c2, c3); 113 } 114 srcHandle += 4; 115 dstHandle += 4; 116 } 117 src += bpr; 118 dst += bpr; 119 } 120 break; 121 122 case MODE_DARKEN: 123 for (; top <= bottom; top++) { 124 uint8* srcHandle = src; 125 uint8* dstHandle = dst; 126 for (int32 x = left; x <= right; x++) { 127 if (srcHandle[3] > 0) { 128 // compose 129 uint8 c1 = (min_c(srcHandle[0], dstHandle[0]) * dstHandle[3] 130 + srcHandle[0] * (255 - dstHandle[3])) / 255; 131 uint8 c2 = (min_c(srcHandle[1], dstHandle[1]) * dstHandle[3] 132 + srcHandle[1] * (255 - dstHandle[3])) / 255; 133 uint8 c3 = (min_c(srcHandle[2], dstHandle[2]) * dstHandle[3] 134 + srcHandle[2] * (255 - dstHandle[3])) / 255; 135 blend_colors(dstHandle, (srcHandle[3] * alphaOverride) / 255, 136 c1, c2, c3); 137 } 138 srcHandle += 4; 139 dstHandle += 4; 140 } 141 src += bpr; 142 dst += bpr; 143 } 144 break; 145 146 case MODE_REPLACE_RED: 147 for (; top <= bottom; top++) { 148 uint8* srcHandle = src; 149 uint8* dstHandle = dst; 150 for (int32 x = left; x <= right; x++) { 151 if (srcHandle[3] > 0) { 152 // compose 153 uint32 alpha = srcHandle[3] * alphaOverride; 154 dstHandle[2] = (srcHandle[2] * alpha 155 + dstHandle[2] * (65025 - alpha)) / 65025; 156 } 157 srcHandle += 4; 158 dstHandle += 4; 159 } 160 src += bpr; 161 dst += bpr; 162 } 163 break; 164 165 case MODE_REPLACE_GREEN: 166 for (; top <= bottom; top++) { 167 uint8* srcHandle = src; 168 uint8* dstHandle = dst; 169 for (int32 x = left; x <= right; x++) { 170 if (srcHandle[3] > 0) { 171 // compose 172 uint32 alpha = srcHandle[3] * alphaOverride; 173 dstHandle[1] = (srcHandle[1] * alpha 174 + dstHandle[1] * (65025 - alpha)) / 65025; 175 } 176 srcHandle += 4; 177 dstHandle += 4; 178 } 179 src += bpr; 180 dst += bpr; 181 } 182 break; 183 184 case MODE_REPLACE_BLUE: 185 for (; top <= bottom; top++) { 186 uint8* srcHandle = src; 187 uint8* dstHandle = dst; 188 for (int32 x = left; x <= right; x++) { 189 if (srcHandle[3] > 0) { 190 // compose 191 uint32 alpha = srcHandle[3] * alphaOverride; 192 dstHandle[0] = (srcHandle[0] * alpha 193 + dstHandle[0] * (65025 - alpha)) / 65025; 194 } 195 srcHandle += 4; 196 dstHandle += 4; 197 } 198 src += bpr; 199 dst += bpr; 200 } 201 break; 202 203 case MODE_MULTIPLY_INVERSE_ALPHA: 204 for (; top <= bottom; top++) { 205 uint8* srcHandle = src; 206 uint8* dstHandle = dst; 207 for (int32 x = left; x <= right; x++) { 208 // compose 209 uint8 temp = min_c(dstHandle[3], 255 - srcHandle[3]); 210 dstHandle[3] = (dstHandle[3] * (255 - alphaOverride) + temp * alphaOverride) / 255; 211 srcHandle += 4; 212 dstHandle += 4; 213 } 214 src += bpr; 215 dst += bpr; 216 } 217 break; 218 219 case MODE_MULTIPLY_ALPHA: 220 for (; top <= bottom; top++) { 221 uint8* srcHandle = src; 222 uint8* dstHandle = dst; 223 for (int32 x = left; x <= right; x++) { 224 // compose 225 uint8 temp = min_c(dstHandle[3], srcHandle[3]); 226 dstHandle[3] = (dstHandle[3] * (255 - alphaOverride) + temp * alphaOverride) / 255; 227 srcHandle += 4; 228 dstHandle += 4; 229 } 230 src += bpr; 231 dst += bpr; 232 } 233 break; 234 235 case MODE_LUMINANCE: 236 for (; top <= bottom; top++) { 237 uint8* srcHandle = src; 238 uint8* dstHandle = dst; 239 for (int32 x = left; x <= right; x++) { 240 if (srcHandle[3] > 0) { 241 // compose 242 uint8 r = dstHandle[2]; 243 uint8 g = dstHandle[1]; 244 uint8 b = dstHandle[0]; 245 uint8 alpha = dstHandle[3]; 246 replace_luminance(r, g, b, srcHandle[2], srcHandle[1], srcHandle[0]); 247 blend_colors(dstHandle, (srcHandle[3] * alphaOverride) / 255, 248 b, g, r); 249 dstHandle[3] = alpha; 250 } 251 srcHandle += 4; 252 dstHandle += 4; 253 } 254 src += bpr; 255 dst += bpr; 256 } 257 break; 258 259 case MODE_INVERSE_MULTIPLY: 260 for (; top <= bottom; top++) { 261 uint8* srcHandle = src; 262 uint8* dstHandle = dst; 263 for (int32 x = left; x <= right; x++) { 264 if (srcHandle[3] > 0) { 265 // compose 266 uint8 c1 = 255 - ((((255 - srcHandle[0]) * (255 - dstHandle[0])) / 255) * dstHandle[3] 267 + (255 - srcHandle[0]) * (255 - dstHandle[3])) / 255; 268 uint8 c2 = 255 - ((((255 - srcHandle[1]) * (255 - dstHandle[1])) / 255) * dstHandle[3] 269 + (255 - srcHandle[1]) * (255 - dstHandle[3])) / 255; 270 uint8 c3 = 255 - ((((255 - srcHandle[2]) * (255 - dstHandle[2])) / 255) * dstHandle[3] 271 + (255 - srcHandle[2]) * (255 - dstHandle[3])) / 255; 272 blend_colors(dstHandle, (srcHandle[3] * alphaOverride) / 255, 273 c1, c2, c3); 274 } 275 srcHandle += 4; 276 dstHandle += 4; 277 } 278 src += bpr; 279 dst += bpr; 280 } 281 break; 282 283 case MODE_MULTIPLY: 284 for (; top <= bottom; top++) { 285 uint8* srcHandle = src; 286 uint8* dstHandle = dst; 287 for (int32 x = left; x <= right; x++) { 288 if (srcHandle[3] > 0) { 289 // compose 290 uint8 c1 = (((srcHandle[0] * dstHandle[0]) / 255) * dstHandle[3] 291 + srcHandle[0] * (255 - dstHandle[3])) / 255; 292 uint8 c2 = (((srcHandle[1] * dstHandle[1]) / 255) * dstHandle[3] 293 + srcHandle[1] * (255 - dstHandle[3])) / 255; 294 uint8 c3 = (((srcHandle[2] * dstHandle[2]) / 255) * dstHandle[3] 295 + srcHandle[2] * (255 - dstHandle[3])) / 255; 296 blend_colors(dstHandle, (srcHandle[3] * alphaOverride) / 255, 297 c1, c2, c3); 298 } 299 srcHandle += 4; 300 dstHandle += 4; 301 } 302 src += bpr; 303 dst += bpr; 304 } 305 break; 306 307 case MODE_NORMAL: 308 default: 309 if (alphaOverride == 255) { 310 // use an optimized version that composes the bitmaps directly 311 for (; top <= bottom; top++) { 312 uint8* srcHandle = src; 313 uint8* dstHandle = dst; 314 for (int32 x = left; x <= right; x++) { 315 blend_colors(dstHandle, srcHandle); 316 srcHandle += 4; 317 dstHandle += 4; 318 } 319 src += bpr; 320 dst += bpr; 321 } 322 } else { 323 for (; top <= bottom; top++) { 324 uint8* srcHandle = src; 325 uint8* dstHandle = dst; 326 for (int32 x = left; x <= right; x++) { 327 blend_colors(dstHandle, srcHandle, alphaOverride); 328 srcHandle += 4; 329 dstHandle += 4; 330 } 331 src += bpr; 332 dst += bpr; 333 } 334 } 335 break; 336 } 337 338 return status; 339 } 340 341 // Unarchive 342 status_t 343 Layer::Unarchive(const BMessage* archive) 344 { 345 if (!archive) 346 return B_BAD_VALUE; 347 348 // restore attributes 349 float alpha; 350 if (archive->FindFloat("alpha", &alpha) == B_OK) { 351 constrain(alpha, 0.0, 1.0); 352 fAlpha = alpha; 353 } else 354 fAlpha = 1.0; 355 if (archive->FindInt32("mode", (int32*)&fMode) < B_OK) 356 fMode = MODE_NORMAL; 357 if (archive->FindInt32("flags", (int32*)&fFlags) < B_OK) 358 fFlags = 0; 359 360 // delete current contents 361 delete fBitmap; 362 fBitmap = NULL; 363 364 status_t status = extract_bitmap(&fBitmap, archive, "current bitmap"); 365 if (status < B_OK) 366 return status; 367 368 // "bounds" is where the layer actually has content 369 BRect bounds; 370 if (archive->FindRect("bounds", &bounds) == B_OK) 371 fBounds = bounds; 372 else 373 fBounds.Set(0.0, 0.0, -1.0, -1.0); 374 375 // validate status of fBitmap 376 if (!fBitmap) 377 return B_ERROR; 378 379 status = fBitmap->InitCheck(); 380 if (status < B_OK) { 381 delete fBitmap; 382 fBitmap = NULL; 383 } 384 385 return status; 386 } 387