xref: /haiku/src/add-ons/translators/wonderbrush/Layer.cpp (revision 258b762aefaa9a9e92f87e664ff29c2b13c72fb8)
173a2ffbaSStephan Aßmus /*
273a2ffbaSStephan Aßmus  * Copyright 2006, Haiku. All rights reserved.
373a2ffbaSStephan Aßmus  * Distributed under the terms of the MIT License.
473a2ffbaSStephan Aßmus  *
573a2ffbaSStephan Aßmus  * Authors:
673a2ffbaSStephan Aßmus  *		Stephan Aßmus <superstippi@gmx.de>
773a2ffbaSStephan Aßmus  */
873a2ffbaSStephan Aßmus 
936947c7bSOliver Tappe 
1073a2ffbaSStephan Aßmus #include "Layer.h"
1173a2ffbaSStephan Aßmus 
1273a2ffbaSStephan Aßmus #include <stdio.h>
1373a2ffbaSStephan Aßmus 
1473a2ffbaSStephan Aßmus #include <Bitmap.h>
1573a2ffbaSStephan Aßmus #include <Message.h>
1673a2ffbaSStephan Aßmus 
1773a2ffbaSStephan Aßmus #include "bitmap_compression.h"
1873a2ffbaSStephan Aßmus #include "blending.h"
1973a2ffbaSStephan Aßmus #include "lab_convert.h"
2073a2ffbaSStephan Aßmus #include "support.h"
2173a2ffbaSStephan Aßmus 
2236947c7bSOliver Tappe 
2373a2ffbaSStephan Aßmus // constructor
2473a2ffbaSStephan Aßmus Layer::Layer()
2573a2ffbaSStephan Aßmus 	: fBitmap(NULL),
2673a2ffbaSStephan Aßmus 	  fBounds(0.0, 0.0, -1.0, -1.0),
2773a2ffbaSStephan Aßmus 	  fAlpha(1.0),
2873a2ffbaSStephan Aßmus 	  fMode(MODE_NORMAL),
2973a2ffbaSStephan Aßmus 	  fFlags(0)
3073a2ffbaSStephan Aßmus {
3173a2ffbaSStephan Aßmus }
3273a2ffbaSStephan Aßmus 
3336947c7bSOliver Tappe 
3473a2ffbaSStephan Aßmus // destructor
3573a2ffbaSStephan Aßmus Layer::~Layer()
3673a2ffbaSStephan Aßmus {
3773a2ffbaSStephan Aßmus 	delete fBitmap;
3873a2ffbaSStephan Aßmus }
3973a2ffbaSStephan Aßmus 
4036947c7bSOliver Tappe 
4173a2ffbaSStephan Aßmus // Compose
4273a2ffbaSStephan Aßmus status_t
4373a2ffbaSStephan Aßmus Layer::Compose(const BBitmap* into, BRect area)
4473a2ffbaSStephan Aßmus {
4573a2ffbaSStephan Aßmus 	if (!fBitmap || !fBitmap->IsValid()
4636947c7bSOliver Tappe 		|| (fBitmap->ColorSpace() != B_RGBA32
4736947c7bSOliver Tappe 			&& fBitmap->ColorSpace() != B_RGB32))
4873a2ffbaSStephan Aßmus 		return B_NO_INIT;
4973a2ffbaSStephan Aßmus 
5073a2ffbaSStephan Aßmus 	status_t status = B_BAD_VALUE;
5173a2ffbaSStephan Aßmus 	if (!into || !area.IsValid() || (status = into->InitCheck()) < B_OK)
5273a2ffbaSStephan Aßmus 		return status;
5373a2ffbaSStephan Aßmus 
5473a2ffbaSStephan Aßmus 	// make sure we don't access memory outside of our bitmap
5573a2ffbaSStephan Aßmus 	area = area & fBitmap->Bounds();
5673a2ffbaSStephan Aßmus 
5773a2ffbaSStephan Aßmus 	BRect r = ActiveBounds();
5873a2ffbaSStephan Aßmus 	if (!r.IsValid() || (fFlags & FLAG_INVISIBLE) || !r.Intersects(area))
5973a2ffbaSStephan Aßmus 		return B_OK;
6073a2ffbaSStephan Aßmus 
6173a2ffbaSStephan Aßmus 	r = r & area;
6273a2ffbaSStephan Aßmus 	int32 left, top, right, bottom;
6373a2ffbaSStephan Aßmus 	rect_to_int(r, left, top, right, bottom);
6473a2ffbaSStephan Aßmus 
6573a2ffbaSStephan Aßmus 	uint8* src = (uint8*)fBitmap->Bits();
6673a2ffbaSStephan Aßmus 	uint8* dst = (uint8*)into->Bits();
6773a2ffbaSStephan Aßmus 	uint32 bpr = into->BytesPerRow();
6873a2ffbaSStephan Aßmus 	src += 4 * left + bpr * top;
6973a2ffbaSStephan Aßmus 	dst += 4 * left + bpr * top;
7073a2ffbaSStephan Aßmus 	uint8 alphaOverride = (uint8)(fAlpha * 255);
7173a2ffbaSStephan Aßmus 
7273a2ffbaSStephan Aßmus 	switch (fMode) {
7373a2ffbaSStephan Aßmus 
7473a2ffbaSStephan Aßmus 		case MODE_SOFT_LIGHT:
7573a2ffbaSStephan Aßmus 			for (; top <= bottom; top++) {
7673a2ffbaSStephan Aßmus 				uint8* srcHandle = src;
7773a2ffbaSStephan Aßmus 				uint8* dstHandle = dst;
7873a2ffbaSStephan Aßmus 				for (int32 x = left; x <= right; x++) {
7973a2ffbaSStephan Aßmus 					if (srcHandle[3] > 0) {
8073a2ffbaSStephan Aßmus 						uint8 c1 = dstHandle[0] * srcHandle[0] >> 8;
81*258b762aSOliver Tappe 						c1 += dstHandle[0] * (
8236947c7bSOliver Tappe 								255 - (
8336947c7bSOliver Tappe 									(255 - dstHandle[0])
8436947c7bSOliver Tappe 									* (255 - srcHandle[0])
8536947c7bSOliver Tappe 									>> 8
8636947c7bSOliver Tappe 								) - c1
8736947c7bSOliver Tappe 							) >> 8;
8836947c7bSOliver Tappe 						c1 = (c1 * dstHandle[3]
8936947c7bSOliver Tappe 								+ srcHandle[0] * (255 - dstHandle[3])
9036947c7bSOliver Tappe 							) >> 8;
9173a2ffbaSStephan Aßmus 
9273a2ffbaSStephan Aßmus 						uint8 c2 = dstHandle[1] * srcHandle[1] >> 8;
93*258b762aSOliver Tappe 						c2 += dstHandle[1] * (
9436947c7bSOliver Tappe 								255 - (
9536947c7bSOliver Tappe 									(255 - dstHandle[1])
9636947c7bSOliver Tappe 									* (255 - srcHandle[1])
9736947c7bSOliver Tappe 									>> 8
9836947c7bSOliver Tappe 								) - c2
9936947c7bSOliver Tappe 							) >> 8;
10036947c7bSOliver Tappe 						c2 = (c2 * dstHandle[3]
10136947c7bSOliver Tappe 								+ srcHandle[1] * (255 - dstHandle[3])
10236947c7bSOliver Tappe 							) >> 8;
10373a2ffbaSStephan Aßmus 
10473a2ffbaSStephan Aßmus 						uint8 c3 = dstHandle[2] * srcHandle[2] >> 8;
105*258b762aSOliver Tappe 						c3 += dstHandle[2] * (
10636947c7bSOliver Tappe 								255 - (
10736947c7bSOliver Tappe 									(255 - dstHandle[2])
10836947c7bSOliver Tappe 									* (255 - srcHandle[2])
10936947c7bSOliver Tappe 									>> 8
11036947c7bSOliver Tappe 								) - c3
11136947c7bSOliver Tappe 							) >> 8;
11236947c7bSOliver Tappe 						c3 = (c3 * dstHandle[3]
11336947c7bSOliver Tappe 								+ srcHandle[2] * (255 - dstHandle[3])
11436947c7bSOliver Tappe 							) >> 8;
11573a2ffbaSStephan Aßmus 
11636947c7bSOliver Tappe 						blend_colors(dstHandle,
11736947c7bSOliver Tappe 							(srcHandle[3] * alphaOverride) >> 8, c1, c2, c3);
11873a2ffbaSStephan Aßmus 					}
11973a2ffbaSStephan Aßmus 					srcHandle += 4;
12073a2ffbaSStephan Aßmus 					dstHandle += 4;
12173a2ffbaSStephan Aßmus 				}
12273a2ffbaSStephan Aßmus 				src += bpr;
12373a2ffbaSStephan Aßmus 				dst += bpr;
12473a2ffbaSStephan Aßmus 			}
12573a2ffbaSStephan Aßmus 			break;
12673a2ffbaSStephan Aßmus 
12773a2ffbaSStephan Aßmus 		case MODE_LIGHTEN:
12873a2ffbaSStephan Aßmus 			for (; top <= bottom; top++) {
12973a2ffbaSStephan Aßmus 				uint8* srcHandle = src;
13073a2ffbaSStephan Aßmus 				uint8* dstHandle = dst;
13173a2ffbaSStephan Aßmus 				for (int32 x = left; x <= right; x++) {
13273a2ffbaSStephan Aßmus 					if (srcHandle[3] > 0) {
13373a2ffbaSStephan Aßmus 						// compose
13436947c7bSOliver Tappe 						uint8 c1
13536947c7bSOliver Tappe 							= (max_c(srcHandle[0], dstHandle[0]) * dstHandle[3]
13673a2ffbaSStephan Aßmus 								+ srcHandle[0] * (255 - dstHandle[3])) / 255;
13736947c7bSOliver Tappe 						uint8 c2
13836947c7bSOliver Tappe 							= (max_c(srcHandle[1], dstHandle[1]) * dstHandle[3]
13973a2ffbaSStephan Aßmus 								+ srcHandle[1] * (255 - dstHandle[3])) / 255;
14036947c7bSOliver Tappe 						uint8 c3
14136947c7bSOliver Tappe 							= (max_c(srcHandle[2], dstHandle[2]) * dstHandle[3]
14273a2ffbaSStephan Aßmus 								+ srcHandle[2] * (255 - dstHandle[3])) / 255;
14336947c7bSOliver Tappe 						blend_colors(dstHandle,
14436947c7bSOliver Tappe 							(srcHandle[3] * alphaOverride) / 255, c1, c2, c3);
14573a2ffbaSStephan Aßmus 					}
14673a2ffbaSStephan Aßmus 					srcHandle += 4;
14773a2ffbaSStephan Aßmus 					dstHandle += 4;
14873a2ffbaSStephan Aßmus 				}
14973a2ffbaSStephan Aßmus 				src += bpr;
15073a2ffbaSStephan Aßmus 				dst += bpr;
15173a2ffbaSStephan Aßmus 			}
15273a2ffbaSStephan Aßmus 			break;
15373a2ffbaSStephan Aßmus 
15473a2ffbaSStephan Aßmus 		case MODE_DARKEN:
15573a2ffbaSStephan Aßmus 			for (; top <= bottom; top++) {
15673a2ffbaSStephan Aßmus 				uint8* srcHandle = src;
15773a2ffbaSStephan Aßmus 				uint8* dstHandle = dst;
15873a2ffbaSStephan Aßmus 				for (int32 x = left; x <= right; x++) {
15973a2ffbaSStephan Aßmus 					if (srcHandle[3] > 0) {
16073a2ffbaSStephan Aßmus 						// compose
16136947c7bSOliver Tappe 						uint8 c1
16236947c7bSOliver Tappe 							= (min_c(srcHandle[0], dstHandle[0]) * dstHandle[3]
16373a2ffbaSStephan Aßmus 								+ srcHandle[0] * (255 - dstHandle[3])) / 255;
16436947c7bSOliver Tappe 						uint8 c2
16536947c7bSOliver Tappe 							= (min_c(srcHandle[1], dstHandle[1]) * dstHandle[3]
16673a2ffbaSStephan Aßmus 								+ srcHandle[1] * (255 - dstHandle[3])) / 255;
16736947c7bSOliver Tappe 						uint8 c3
16836947c7bSOliver Tappe 							= (min_c(srcHandle[2], dstHandle[2]) * dstHandle[3]
16973a2ffbaSStephan Aßmus 								+ srcHandle[2] * (255 - dstHandle[3])) / 255;
17036947c7bSOliver Tappe 						blend_colors(dstHandle,
17136947c7bSOliver Tappe 							(srcHandle[3] * alphaOverride) / 255, c1, c2, c3);
17273a2ffbaSStephan Aßmus 					}
17373a2ffbaSStephan Aßmus 					srcHandle += 4;
17473a2ffbaSStephan Aßmus 					dstHandle += 4;
17573a2ffbaSStephan Aßmus 				}
17673a2ffbaSStephan Aßmus 				src += bpr;
17773a2ffbaSStephan Aßmus 				dst += bpr;
17873a2ffbaSStephan Aßmus 			}
17973a2ffbaSStephan Aßmus 			break;
18073a2ffbaSStephan Aßmus 
18173a2ffbaSStephan Aßmus 		case MODE_REPLACE_RED:
18273a2ffbaSStephan Aßmus 			for (; top <= bottom; top++) {
18373a2ffbaSStephan Aßmus 				uint8* srcHandle = src;
18473a2ffbaSStephan Aßmus 				uint8* dstHandle = dst;
18573a2ffbaSStephan Aßmus 				for (int32 x = left; x <= right; x++) {
18673a2ffbaSStephan Aßmus 					if (srcHandle[3] > 0) {
18773a2ffbaSStephan Aßmus 						// compose
18873a2ffbaSStephan Aßmus 						uint32 alpha = srcHandle[3] * alphaOverride;
18973a2ffbaSStephan Aßmus 						dstHandle[2] = (srcHandle[2] * alpha
19073a2ffbaSStephan Aßmus 								+ dstHandle[2] * (65025 - alpha)) / 65025;
19173a2ffbaSStephan Aßmus 					}
19273a2ffbaSStephan Aßmus 					srcHandle += 4;
19373a2ffbaSStephan Aßmus 					dstHandle += 4;
19473a2ffbaSStephan Aßmus 				}
19573a2ffbaSStephan Aßmus 				src += bpr;
19673a2ffbaSStephan Aßmus 				dst += bpr;
19773a2ffbaSStephan Aßmus 			}
19873a2ffbaSStephan Aßmus 			break;
19973a2ffbaSStephan Aßmus 
20073a2ffbaSStephan Aßmus 		case MODE_REPLACE_GREEN:
20173a2ffbaSStephan Aßmus 			for (; top <= bottom; top++) {
20273a2ffbaSStephan Aßmus 				uint8* srcHandle = src;
20373a2ffbaSStephan Aßmus 				uint8* dstHandle = dst;
20473a2ffbaSStephan Aßmus 				for (int32 x = left; x <= right; x++) {
20573a2ffbaSStephan Aßmus 					if (srcHandle[3] > 0) {
20673a2ffbaSStephan Aßmus 						// compose
20773a2ffbaSStephan Aßmus 						uint32 alpha = srcHandle[3] * alphaOverride;
20873a2ffbaSStephan Aßmus 						dstHandle[1] = (srcHandle[1] * alpha
20973a2ffbaSStephan Aßmus 								+ dstHandle[1] * (65025 - alpha)) / 65025;
21073a2ffbaSStephan Aßmus 					}
21173a2ffbaSStephan Aßmus 					srcHandle += 4;
21273a2ffbaSStephan Aßmus 					dstHandle += 4;
21373a2ffbaSStephan Aßmus 				}
21473a2ffbaSStephan Aßmus 				src += bpr;
21573a2ffbaSStephan Aßmus 				dst += bpr;
21673a2ffbaSStephan Aßmus 			}
21773a2ffbaSStephan Aßmus 			break;
21873a2ffbaSStephan Aßmus 
21973a2ffbaSStephan Aßmus 		case MODE_REPLACE_BLUE:
22073a2ffbaSStephan Aßmus 			for (; top <= bottom; top++) {
22173a2ffbaSStephan Aßmus 				uint8* srcHandle = src;
22273a2ffbaSStephan Aßmus 				uint8* dstHandle = dst;
22373a2ffbaSStephan Aßmus 				for (int32 x = left; x <= right; x++) {
22473a2ffbaSStephan Aßmus 					if (srcHandle[3] > 0) {
22573a2ffbaSStephan Aßmus 						// compose
22673a2ffbaSStephan Aßmus 						uint32 alpha = srcHandle[3] * alphaOverride;
22773a2ffbaSStephan Aßmus 						dstHandle[0] = (srcHandle[0] * alpha
22873a2ffbaSStephan Aßmus 								+ dstHandle[0] * (65025 - alpha)) / 65025;
22973a2ffbaSStephan Aßmus 					}
23073a2ffbaSStephan Aßmus 					srcHandle += 4;
23173a2ffbaSStephan Aßmus 					dstHandle += 4;
23273a2ffbaSStephan Aßmus 				}
23373a2ffbaSStephan Aßmus 				src += bpr;
23473a2ffbaSStephan Aßmus 				dst += bpr;
23573a2ffbaSStephan Aßmus 			}
23673a2ffbaSStephan Aßmus 			break;
23773a2ffbaSStephan Aßmus 
23873a2ffbaSStephan Aßmus 		case MODE_MULTIPLY_INVERSE_ALPHA:
23973a2ffbaSStephan Aßmus 			for (; top <= bottom; top++) {
24073a2ffbaSStephan Aßmus 				uint8* srcHandle = src;
24173a2ffbaSStephan Aßmus 				uint8* dstHandle = dst;
24273a2ffbaSStephan Aßmus 				for (int32 x = left; x <= right; x++) {
24373a2ffbaSStephan Aßmus 					// compose
24473a2ffbaSStephan Aßmus 					uint8 temp = min_c(dstHandle[3], 255 - srcHandle[3]);
24536947c7bSOliver Tappe 					dstHandle[3] = (
24636947c7bSOliver Tappe 							dstHandle[3] * (255 - alphaOverride)
24736947c7bSOliver Tappe 							+ temp * alphaOverride
24836947c7bSOliver Tappe 						) / 255;
24973a2ffbaSStephan Aßmus 					srcHandle += 4;
25073a2ffbaSStephan Aßmus 					dstHandle += 4;
25173a2ffbaSStephan Aßmus 				}
25273a2ffbaSStephan Aßmus 				src += bpr;
25373a2ffbaSStephan Aßmus 				dst += bpr;
25473a2ffbaSStephan Aßmus 			}
25573a2ffbaSStephan Aßmus 			break;
25673a2ffbaSStephan Aßmus 
25773a2ffbaSStephan Aßmus 		case MODE_MULTIPLY_ALPHA:
25873a2ffbaSStephan Aßmus 			for (; top <= bottom; top++) {
25973a2ffbaSStephan Aßmus 				uint8* srcHandle = src;
26073a2ffbaSStephan Aßmus 				uint8* dstHandle = dst;
26173a2ffbaSStephan Aßmus 				for (int32 x = left; x <= right; x++) {
26273a2ffbaSStephan Aßmus 					// compose
26373a2ffbaSStephan Aßmus 					uint8 temp = min_c(dstHandle[3], srcHandle[3]);
26436947c7bSOliver Tappe 					dstHandle[3] = (
26536947c7bSOliver Tappe 							dstHandle[3] * (255 - alphaOverride)
26636947c7bSOliver Tappe 							+ temp * alphaOverride
26736947c7bSOliver Tappe 						) / 255;
26873a2ffbaSStephan Aßmus 					srcHandle += 4;
26973a2ffbaSStephan Aßmus 					dstHandle += 4;
27073a2ffbaSStephan Aßmus 				}
27173a2ffbaSStephan Aßmus 				src += bpr;
27273a2ffbaSStephan Aßmus 				dst += bpr;
27373a2ffbaSStephan Aßmus 			}
27473a2ffbaSStephan Aßmus 			break;
27573a2ffbaSStephan Aßmus 
27673a2ffbaSStephan Aßmus 		case MODE_LUMINANCE:
27773a2ffbaSStephan Aßmus 			for (; top <= bottom; top++) {
27873a2ffbaSStephan Aßmus 				uint8* srcHandle = src;
27973a2ffbaSStephan Aßmus 				uint8* dstHandle = dst;
28073a2ffbaSStephan Aßmus 				for (int32 x = left; x <= right; x++) {
28173a2ffbaSStephan Aßmus 					if (srcHandle[3] > 0) {
28273a2ffbaSStephan Aßmus 						// compose
28373a2ffbaSStephan Aßmus 						uint8 r = dstHandle[2];
28473a2ffbaSStephan Aßmus 						uint8 g = dstHandle[1];
28573a2ffbaSStephan Aßmus 						uint8 b = dstHandle[0];
28673a2ffbaSStephan Aßmus 						uint8 alpha = dstHandle[3];
28736947c7bSOliver Tappe 						replace_luminance(r, g, b, srcHandle[2], srcHandle[1],
28836947c7bSOliver Tappe 							srcHandle[0]);
28936947c7bSOliver Tappe 						blend_colors(dstHandle,
29036947c7bSOliver Tappe 							(srcHandle[3] * alphaOverride) / 255, b, g, r);
29173a2ffbaSStephan Aßmus 						dstHandle[3] = alpha;
29273a2ffbaSStephan Aßmus 					}
29373a2ffbaSStephan Aßmus 					srcHandle += 4;
29473a2ffbaSStephan Aßmus 					dstHandle += 4;
29573a2ffbaSStephan Aßmus 				}
29673a2ffbaSStephan Aßmus 				src += bpr;
29773a2ffbaSStephan Aßmus 				dst += bpr;
29873a2ffbaSStephan Aßmus 			}
29973a2ffbaSStephan Aßmus 			break;
30073a2ffbaSStephan Aßmus 
30173a2ffbaSStephan Aßmus 		case MODE_INVERSE_MULTIPLY:
30273a2ffbaSStephan Aßmus 			for (; top <= bottom; top++) {
30373a2ffbaSStephan Aßmus 				uint8* srcHandle = src;
30473a2ffbaSStephan Aßmus 				uint8* dstHandle = dst;
30573a2ffbaSStephan Aßmus 				for (int32 x = left; x <= right; x++) {
30673a2ffbaSStephan Aßmus 					if (srcHandle[3] > 0) {
30773a2ffbaSStephan Aßmus 						// compose
30836947c7bSOliver Tappe 						uint8 c1 = 255 - (
30936947c7bSOliver Tappe 								(((255 - srcHandle[0]) * (255 - dstHandle[0]))
31036947c7bSOliver Tappe 									/ 255) * dstHandle[3]
31136947c7bSOliver Tappe 								+ (255 - srcHandle[0]) * (255 - dstHandle[3])
31236947c7bSOliver Tappe 							) / 255;
31336947c7bSOliver Tappe 						uint8 c2 = 255 - (
31436947c7bSOliver Tappe 								(((255 - srcHandle[1]) * (255 - dstHandle[1]))
31536947c7bSOliver Tappe 									/ 255) * dstHandle[3]
31636947c7bSOliver Tappe 								+ (255 - srcHandle[1]) * (255 - dstHandle[3])
31736947c7bSOliver Tappe 							) / 255;
31836947c7bSOliver Tappe 						uint8 c3 = 255 - (
31936947c7bSOliver Tappe 								(((255 - srcHandle[2]) * (255 - dstHandle[2]))
32036947c7bSOliver Tappe 									/ 255) * dstHandle[3]
32136947c7bSOliver Tappe 								+ (255 - srcHandle[2]) * (255 - dstHandle[3])
32236947c7bSOliver Tappe 							) / 255;
32336947c7bSOliver Tappe 						blend_colors(dstHandle,
32436947c7bSOliver Tappe 							(srcHandle[3] * alphaOverride) / 255, c1, c2, c3);
32573a2ffbaSStephan Aßmus 					}
32673a2ffbaSStephan Aßmus 					srcHandle += 4;
32773a2ffbaSStephan Aßmus 					dstHandle += 4;
32873a2ffbaSStephan Aßmus 				}
32973a2ffbaSStephan Aßmus 				src += bpr;
33073a2ffbaSStephan Aßmus 				dst += bpr;
33173a2ffbaSStephan Aßmus 			}
33273a2ffbaSStephan Aßmus 			break;
33373a2ffbaSStephan Aßmus 
33473a2ffbaSStephan Aßmus 		case MODE_MULTIPLY:
33573a2ffbaSStephan Aßmus 			for (; top <= bottom; top++) {
33673a2ffbaSStephan Aßmus 				uint8* srcHandle = src;
33773a2ffbaSStephan Aßmus 				uint8* dstHandle = dst;
33873a2ffbaSStephan Aßmus 				for (int32 x = left; x <= right; x++) {
33973a2ffbaSStephan Aßmus 					if (srcHandle[3] > 0) {
34073a2ffbaSStephan Aßmus 						// compose
34136947c7bSOliver Tappe 						uint8 c1 = (
34236947c7bSOliver Tappe 								((srcHandle[0] * dstHandle[0]) / 255)
34336947c7bSOliver Tappe 									* dstHandle[3]
34436947c7bSOliver Tappe 								+ srcHandle[0] * (255 - dstHandle[3])
34536947c7bSOliver Tappe 							) / 255;
34636947c7bSOliver Tappe 						uint8 c2 = (
34736947c7bSOliver Tappe 								((srcHandle[1] * dstHandle[1]) / 255)
34836947c7bSOliver Tappe 									* dstHandle[3]
34936947c7bSOliver Tappe 								+ srcHandle[1] * (255 - dstHandle[3])
35036947c7bSOliver Tappe 							) / 255;
35136947c7bSOliver Tappe 						uint8 c3 = (
35236947c7bSOliver Tappe 								((srcHandle[2] * dstHandle[2]) / 255)
35336947c7bSOliver Tappe 									* dstHandle[3]
35436947c7bSOliver Tappe 								+ srcHandle[2] * (255 - dstHandle[3])
35536947c7bSOliver Tappe 							) / 255;
35636947c7bSOliver Tappe 						blend_colors(dstHandle,
35736947c7bSOliver Tappe 							(srcHandle[3] * alphaOverride) / 255, c1, c2, c3);
35873a2ffbaSStephan Aßmus 					}
35973a2ffbaSStephan Aßmus 					srcHandle += 4;
36073a2ffbaSStephan Aßmus 					dstHandle += 4;
36173a2ffbaSStephan Aßmus 				}
36273a2ffbaSStephan Aßmus 				src += bpr;
36373a2ffbaSStephan Aßmus 				dst += bpr;
36473a2ffbaSStephan Aßmus 			}
36573a2ffbaSStephan Aßmus 			break;
36673a2ffbaSStephan Aßmus 
36773a2ffbaSStephan Aßmus 		case MODE_NORMAL:
36873a2ffbaSStephan Aßmus 		default:
36973a2ffbaSStephan Aßmus 			if (alphaOverride == 255) {
37073a2ffbaSStephan Aßmus 				// use an optimized version that composes the bitmaps directly
37173a2ffbaSStephan Aßmus 				for (; top <= bottom; top++) {
37273a2ffbaSStephan Aßmus 					uint8* srcHandle = src;
37373a2ffbaSStephan Aßmus 					uint8* dstHandle = dst;
37473a2ffbaSStephan Aßmus 					for (int32 x = left; x <= right; x++) {
37573a2ffbaSStephan Aßmus 						blend_colors(dstHandle, srcHandle);
37673a2ffbaSStephan Aßmus 						srcHandle += 4;
37773a2ffbaSStephan Aßmus 						dstHandle += 4;
37873a2ffbaSStephan Aßmus 					}
37973a2ffbaSStephan Aßmus 					src += bpr;
38073a2ffbaSStephan Aßmus 					dst += bpr;
38173a2ffbaSStephan Aßmus 				}
38273a2ffbaSStephan Aßmus 			} else {
38373a2ffbaSStephan Aßmus 				for (; top <= bottom; top++) {
38473a2ffbaSStephan Aßmus 					uint8* srcHandle = src;
38573a2ffbaSStephan Aßmus 					uint8* dstHandle = dst;
38673a2ffbaSStephan Aßmus 					for (int32 x = left; x <= right; x++) {
38773a2ffbaSStephan Aßmus 						blend_colors(dstHandle, srcHandle, alphaOverride);
38873a2ffbaSStephan Aßmus 						srcHandle += 4;
38973a2ffbaSStephan Aßmus 						dstHandle += 4;
39073a2ffbaSStephan Aßmus 					}
39173a2ffbaSStephan Aßmus 					src += bpr;
39273a2ffbaSStephan Aßmus 					dst += bpr;
39373a2ffbaSStephan Aßmus 				}
39473a2ffbaSStephan Aßmus 			}
39573a2ffbaSStephan Aßmus 			break;
39673a2ffbaSStephan Aßmus 	}
39773a2ffbaSStephan Aßmus 
39873a2ffbaSStephan Aßmus 	return status;
39973a2ffbaSStephan Aßmus }
40073a2ffbaSStephan Aßmus 
40136947c7bSOliver Tappe 
40273a2ffbaSStephan Aßmus // Unarchive
40373a2ffbaSStephan Aßmus status_t
40473a2ffbaSStephan Aßmus Layer::Unarchive(const BMessage* archive)
40573a2ffbaSStephan Aßmus {
40673a2ffbaSStephan Aßmus 	if (!archive)
40773a2ffbaSStephan Aßmus 		return B_BAD_VALUE;
40873a2ffbaSStephan Aßmus 
40973a2ffbaSStephan Aßmus 	// restore attributes
41073a2ffbaSStephan Aßmus 	float alpha;
41173a2ffbaSStephan Aßmus 	if (archive->FindFloat("alpha", &alpha) == B_OK) {
41273a2ffbaSStephan Aßmus 		constrain(alpha, 0.0, 1.0);
41373a2ffbaSStephan Aßmus 		fAlpha = alpha;
41473a2ffbaSStephan Aßmus 	} else
41573a2ffbaSStephan Aßmus 		fAlpha = 1.0;
41673a2ffbaSStephan Aßmus 	if (archive->FindInt32("mode", (int32*)&fMode) < B_OK)
41773a2ffbaSStephan Aßmus 		fMode = MODE_NORMAL;
41873a2ffbaSStephan Aßmus 	if (archive->FindInt32("flags", (int32*)&fFlags) < B_OK)
41973a2ffbaSStephan Aßmus 		fFlags = 0;
42073a2ffbaSStephan Aßmus 
42173a2ffbaSStephan Aßmus 	// delete current contents
42273a2ffbaSStephan Aßmus 	delete fBitmap;
42373a2ffbaSStephan Aßmus 	fBitmap = NULL;
42473a2ffbaSStephan Aßmus 
42573a2ffbaSStephan Aßmus 	status_t status = extract_bitmap(&fBitmap, archive, "current bitmap");
42673a2ffbaSStephan Aßmus 	if (status < B_OK)
42773a2ffbaSStephan Aßmus 		return status;
42873a2ffbaSStephan Aßmus 
42973a2ffbaSStephan Aßmus 	// "bounds" is where the layer actually has content
43073a2ffbaSStephan Aßmus 	BRect bounds;
43173a2ffbaSStephan Aßmus 	if (archive->FindRect("bounds", &bounds) == B_OK)
43273a2ffbaSStephan Aßmus 		fBounds = bounds;
43373a2ffbaSStephan Aßmus 	else
43473a2ffbaSStephan Aßmus 		fBounds.Set(0.0, 0.0, -1.0, -1.0);
43573a2ffbaSStephan Aßmus 
43673a2ffbaSStephan Aßmus 	// validate status of fBitmap
43773a2ffbaSStephan Aßmus 	if (!fBitmap)
43873a2ffbaSStephan Aßmus 		return B_ERROR;
43973a2ffbaSStephan Aßmus 
44073a2ffbaSStephan Aßmus 	status = fBitmap->InitCheck();
44173a2ffbaSStephan Aßmus 	if (status < B_OK) {
44273a2ffbaSStephan Aßmus 		delete fBitmap;
44373a2ffbaSStephan Aßmus 		fBitmap = NULL;
44473a2ffbaSStephan Aßmus 	}
44573a2ffbaSStephan Aßmus 
44673a2ffbaSStephan Aßmus 	return status;
44773a2ffbaSStephan Aßmus }
448