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