xref: /haiku/src/add-ons/translators/wonderbrush/Layer.cpp (revision 25a7b01d15612846f332751841da3579db313082)
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>
156537cf97SJérôme Duval #include <Catalog.h>
1673a2ffbaSStephan Aßmus #include <Message.h>
1773a2ffbaSStephan Aßmus 
1873a2ffbaSStephan Aßmus #include "bitmap_compression.h"
1973a2ffbaSStephan Aßmus #include "blending.h"
2073a2ffbaSStephan Aßmus #include "lab_convert.h"
2173a2ffbaSStephan Aßmus #include "support.h"
2273a2ffbaSStephan Aßmus 
2336947c7bSOliver Tappe 
24*546208a5SOliver Tappe #undef B_TRANSLATION_CONTEXT
25*546208a5SOliver Tappe #define B_TRANSLATION_CONTEXT "Layer"
266537cf97SJérôme Duval 
276537cf97SJérôme Duval 
2873a2ffbaSStephan Aßmus // constructor
Layer()2973a2ffbaSStephan Aßmus Layer::Layer()
3073a2ffbaSStephan Aßmus 	: fBitmap(NULL),
3173a2ffbaSStephan Aßmus 	  fBounds(0.0, 0.0, -1.0, -1.0),
3273a2ffbaSStephan Aßmus 	  fAlpha(1.0),
3373a2ffbaSStephan Aßmus 	  fMode(MODE_NORMAL),
3473a2ffbaSStephan Aßmus 	  fFlags(0)
3573a2ffbaSStephan Aßmus {
3673a2ffbaSStephan Aßmus }
3773a2ffbaSStephan Aßmus 
3836947c7bSOliver Tappe 
3973a2ffbaSStephan Aßmus // destructor
~Layer()4073a2ffbaSStephan Aßmus Layer::~Layer()
4173a2ffbaSStephan Aßmus {
4273a2ffbaSStephan Aßmus 	delete fBitmap;
4373a2ffbaSStephan Aßmus }
4473a2ffbaSStephan Aßmus 
4536947c7bSOliver Tappe 
4673a2ffbaSStephan Aßmus // Compose
4773a2ffbaSStephan Aßmus status_t
Compose(const BBitmap * into,BRect area)4873a2ffbaSStephan Aßmus Layer::Compose(const BBitmap* into, BRect area)
4973a2ffbaSStephan Aßmus {
5073a2ffbaSStephan Aßmus 	if (!fBitmap || !fBitmap->IsValid()
5136947c7bSOliver Tappe 		|| (fBitmap->ColorSpace() != B_RGBA32
5236947c7bSOliver Tappe 			&& fBitmap->ColorSpace() != B_RGB32))
5373a2ffbaSStephan Aßmus 		return B_NO_INIT;
5473a2ffbaSStephan Aßmus 
5573a2ffbaSStephan Aßmus 	status_t status = B_BAD_VALUE;
5673a2ffbaSStephan Aßmus 	if (!into || !area.IsValid() || (status = into->InitCheck()) < B_OK)
5773a2ffbaSStephan Aßmus 		return status;
5873a2ffbaSStephan Aßmus 
5973a2ffbaSStephan Aßmus 	// make sure we don't access memory outside of our bitmap
6073a2ffbaSStephan Aßmus 	area = area & fBitmap->Bounds();
6173a2ffbaSStephan Aßmus 
6273a2ffbaSStephan Aßmus 	BRect r = ActiveBounds();
6373a2ffbaSStephan Aßmus 	if (!r.IsValid() || (fFlags & FLAG_INVISIBLE) || !r.Intersects(area))
6473a2ffbaSStephan Aßmus 		return B_OK;
6573a2ffbaSStephan Aßmus 
6673a2ffbaSStephan Aßmus 	r = r & area;
6773a2ffbaSStephan Aßmus 	int32 left, top, right, bottom;
6873a2ffbaSStephan Aßmus 	rect_to_int(r, left, top, right, bottom);
6973a2ffbaSStephan Aßmus 
7073a2ffbaSStephan Aßmus 	uint8* src = (uint8*)fBitmap->Bits();
7173a2ffbaSStephan Aßmus 	uint8* dst = (uint8*)into->Bits();
7273a2ffbaSStephan Aßmus 	uint32 bpr = into->BytesPerRow();
7373a2ffbaSStephan Aßmus 	src += 4 * left + bpr * top;
7473a2ffbaSStephan Aßmus 	dst += 4 * left + bpr * top;
7573a2ffbaSStephan Aßmus 	uint8 alphaOverride = (uint8)(fAlpha * 255);
7673a2ffbaSStephan Aßmus 
7773a2ffbaSStephan Aßmus 	switch (fMode) {
7873a2ffbaSStephan Aßmus 
7973a2ffbaSStephan Aßmus 		case MODE_SOFT_LIGHT:
8073a2ffbaSStephan Aßmus 			for (; top <= bottom; top++) {
8173a2ffbaSStephan Aßmus 				uint8* srcHandle = src;
8273a2ffbaSStephan Aßmus 				uint8* dstHandle = dst;
8373a2ffbaSStephan Aßmus 				for (int32 x = left; x <= right; x++) {
8473a2ffbaSStephan Aßmus 					if (srcHandle[3] > 0) {
8573a2ffbaSStephan Aßmus 						uint8 c1 = dstHandle[0] * srcHandle[0] >> 8;
86258b762aSOliver Tappe 						c1 += dstHandle[0] * (
8736947c7bSOliver Tappe 								255 - (
8836947c7bSOliver Tappe 									(255 - dstHandle[0])
8936947c7bSOliver Tappe 									* (255 - srcHandle[0])
9036947c7bSOliver Tappe 									>> 8
9136947c7bSOliver Tappe 								) - c1
9236947c7bSOliver Tappe 							) >> 8;
9336947c7bSOliver Tappe 						c1 = (c1 * dstHandle[3]
9436947c7bSOliver Tappe 								+ srcHandle[0] * (255 - dstHandle[3])
9536947c7bSOliver Tappe 							) >> 8;
9673a2ffbaSStephan Aßmus 
9773a2ffbaSStephan Aßmus 						uint8 c2 = dstHandle[1] * srcHandle[1] >> 8;
98258b762aSOliver Tappe 						c2 += dstHandle[1] * (
9936947c7bSOliver Tappe 								255 - (
10036947c7bSOliver Tappe 									(255 - dstHandle[1])
10136947c7bSOliver Tappe 									* (255 - srcHandle[1])
10236947c7bSOliver Tappe 									>> 8
10336947c7bSOliver Tappe 								) - c2
10436947c7bSOliver Tappe 							) >> 8;
10536947c7bSOliver Tappe 						c2 = (c2 * dstHandle[3]
10636947c7bSOliver Tappe 								+ srcHandle[1] * (255 - dstHandle[3])
10736947c7bSOliver Tappe 							) >> 8;
10873a2ffbaSStephan Aßmus 
10973a2ffbaSStephan Aßmus 						uint8 c3 = dstHandle[2] * srcHandle[2] >> 8;
110258b762aSOliver Tappe 						c3 += dstHandle[2] * (
11136947c7bSOliver Tappe 								255 - (
11236947c7bSOliver Tappe 									(255 - dstHandle[2])
11336947c7bSOliver Tappe 									* (255 - srcHandle[2])
11436947c7bSOliver Tappe 									>> 8
11536947c7bSOliver Tappe 								) - c3
11636947c7bSOliver Tappe 							) >> 8;
11736947c7bSOliver Tappe 						c3 = (c3 * dstHandle[3]
11836947c7bSOliver Tappe 								+ srcHandle[2] * (255 - dstHandle[3])
11936947c7bSOliver Tappe 							) >> 8;
12073a2ffbaSStephan Aßmus 
12136947c7bSOliver Tappe 						blend_colors(dstHandle,
12236947c7bSOliver Tappe 							(srcHandle[3] * alphaOverride) >> 8, c1, c2, c3);
12373a2ffbaSStephan Aßmus 					}
12473a2ffbaSStephan Aßmus 					srcHandle += 4;
12573a2ffbaSStephan Aßmus 					dstHandle += 4;
12673a2ffbaSStephan Aßmus 				}
12773a2ffbaSStephan Aßmus 				src += bpr;
12873a2ffbaSStephan Aßmus 				dst += bpr;
12973a2ffbaSStephan Aßmus 			}
13073a2ffbaSStephan Aßmus 			break;
13173a2ffbaSStephan Aßmus 
13273a2ffbaSStephan Aßmus 		case MODE_LIGHTEN:
13373a2ffbaSStephan Aßmus 			for (; top <= bottom; top++) {
13473a2ffbaSStephan Aßmus 				uint8* srcHandle = src;
13573a2ffbaSStephan Aßmus 				uint8* dstHandle = dst;
13673a2ffbaSStephan Aßmus 				for (int32 x = left; x <= right; x++) {
13773a2ffbaSStephan Aßmus 					if (srcHandle[3] > 0) {
13873a2ffbaSStephan Aßmus 						// compose
13936947c7bSOliver Tappe 						uint8 c1
14036947c7bSOliver Tappe 							= (max_c(srcHandle[0], dstHandle[0]) * dstHandle[3]
14173a2ffbaSStephan Aßmus 								+ srcHandle[0] * (255 - dstHandle[3])) / 255;
14236947c7bSOliver Tappe 						uint8 c2
14336947c7bSOliver Tappe 							= (max_c(srcHandle[1], dstHandle[1]) * dstHandle[3]
14473a2ffbaSStephan Aßmus 								+ srcHandle[1] * (255 - dstHandle[3])) / 255;
14536947c7bSOliver Tappe 						uint8 c3
14636947c7bSOliver Tappe 							= (max_c(srcHandle[2], dstHandle[2]) * dstHandle[3]
14773a2ffbaSStephan Aßmus 								+ srcHandle[2] * (255 - dstHandle[3])) / 255;
14836947c7bSOliver Tappe 						blend_colors(dstHandle,
14936947c7bSOliver Tappe 							(srcHandle[3] * alphaOverride) / 255, c1, c2, c3);
15073a2ffbaSStephan Aßmus 					}
15173a2ffbaSStephan Aßmus 					srcHandle += 4;
15273a2ffbaSStephan Aßmus 					dstHandle += 4;
15373a2ffbaSStephan Aßmus 				}
15473a2ffbaSStephan Aßmus 				src += bpr;
15573a2ffbaSStephan Aßmus 				dst += bpr;
15673a2ffbaSStephan Aßmus 			}
15773a2ffbaSStephan Aßmus 			break;
15873a2ffbaSStephan Aßmus 
15973a2ffbaSStephan Aßmus 		case MODE_DARKEN:
16073a2ffbaSStephan Aßmus 			for (; top <= bottom; top++) {
16173a2ffbaSStephan Aßmus 				uint8* srcHandle = src;
16273a2ffbaSStephan Aßmus 				uint8* dstHandle = dst;
16373a2ffbaSStephan Aßmus 				for (int32 x = left; x <= right; x++) {
16473a2ffbaSStephan Aßmus 					if (srcHandle[3] > 0) {
16573a2ffbaSStephan Aßmus 						// compose
16636947c7bSOliver Tappe 						uint8 c1
16736947c7bSOliver Tappe 							= (min_c(srcHandle[0], dstHandle[0]) * dstHandle[3]
16873a2ffbaSStephan Aßmus 								+ srcHandle[0] * (255 - dstHandle[3])) / 255;
16936947c7bSOliver Tappe 						uint8 c2
17036947c7bSOliver Tappe 							= (min_c(srcHandle[1], dstHandle[1]) * dstHandle[3]
17173a2ffbaSStephan Aßmus 								+ srcHandle[1] * (255 - dstHandle[3])) / 255;
17236947c7bSOliver Tappe 						uint8 c3
17336947c7bSOliver Tappe 							= (min_c(srcHandle[2], dstHandle[2]) * dstHandle[3]
17473a2ffbaSStephan Aßmus 								+ srcHandle[2] * (255 - dstHandle[3])) / 255;
17536947c7bSOliver Tappe 						blend_colors(dstHandle,
17636947c7bSOliver Tappe 							(srcHandle[3] * alphaOverride) / 255, c1, c2, c3);
17773a2ffbaSStephan Aßmus 					}
17873a2ffbaSStephan Aßmus 					srcHandle += 4;
17973a2ffbaSStephan Aßmus 					dstHandle += 4;
18073a2ffbaSStephan Aßmus 				}
18173a2ffbaSStephan Aßmus 				src += bpr;
18273a2ffbaSStephan Aßmus 				dst += bpr;
18373a2ffbaSStephan Aßmus 			}
18473a2ffbaSStephan Aßmus 			break;
18573a2ffbaSStephan Aßmus 
18673a2ffbaSStephan Aßmus 		case MODE_REPLACE_RED:
18773a2ffbaSStephan Aßmus 			for (; top <= bottom; top++) {
18873a2ffbaSStephan Aßmus 				uint8* srcHandle = src;
18973a2ffbaSStephan Aßmus 				uint8* dstHandle = dst;
19073a2ffbaSStephan Aßmus 				for (int32 x = left; x <= right; x++) {
19173a2ffbaSStephan Aßmus 					if (srcHandle[3] > 0) {
19273a2ffbaSStephan Aßmus 						// compose
19373a2ffbaSStephan Aßmus 						uint32 alpha = srcHandle[3] * alphaOverride;
19473a2ffbaSStephan Aßmus 						dstHandle[2] = (srcHandle[2] * alpha
19573a2ffbaSStephan Aßmus 								+ dstHandle[2] * (65025 - alpha)) / 65025;
19673a2ffbaSStephan Aßmus 					}
19773a2ffbaSStephan Aßmus 					srcHandle += 4;
19873a2ffbaSStephan Aßmus 					dstHandle += 4;
19973a2ffbaSStephan Aßmus 				}
20073a2ffbaSStephan Aßmus 				src += bpr;
20173a2ffbaSStephan Aßmus 				dst += bpr;
20273a2ffbaSStephan Aßmus 			}
20373a2ffbaSStephan Aßmus 			break;
20473a2ffbaSStephan Aßmus 
20573a2ffbaSStephan Aßmus 		case MODE_REPLACE_GREEN:
20673a2ffbaSStephan Aßmus 			for (; top <= bottom; top++) {
20773a2ffbaSStephan Aßmus 				uint8* srcHandle = src;
20873a2ffbaSStephan Aßmus 				uint8* dstHandle = dst;
20973a2ffbaSStephan Aßmus 				for (int32 x = left; x <= right; x++) {
21073a2ffbaSStephan Aßmus 					if (srcHandle[3] > 0) {
21173a2ffbaSStephan Aßmus 						// compose
21273a2ffbaSStephan Aßmus 						uint32 alpha = srcHandle[3] * alphaOverride;
21373a2ffbaSStephan Aßmus 						dstHandle[1] = (srcHandle[1] * alpha
21473a2ffbaSStephan Aßmus 								+ dstHandle[1] * (65025 - alpha)) / 65025;
21573a2ffbaSStephan Aßmus 					}
21673a2ffbaSStephan Aßmus 					srcHandle += 4;
21773a2ffbaSStephan Aßmus 					dstHandle += 4;
21873a2ffbaSStephan Aßmus 				}
21973a2ffbaSStephan Aßmus 				src += bpr;
22073a2ffbaSStephan Aßmus 				dst += bpr;
22173a2ffbaSStephan Aßmus 			}
22273a2ffbaSStephan Aßmus 			break;
22373a2ffbaSStephan Aßmus 
22473a2ffbaSStephan Aßmus 		case MODE_REPLACE_BLUE:
22573a2ffbaSStephan Aßmus 			for (; top <= bottom; top++) {
22673a2ffbaSStephan Aßmus 				uint8* srcHandle = src;
22773a2ffbaSStephan Aßmus 				uint8* dstHandle = dst;
22873a2ffbaSStephan Aßmus 				for (int32 x = left; x <= right; x++) {
22973a2ffbaSStephan Aßmus 					if (srcHandle[3] > 0) {
23073a2ffbaSStephan Aßmus 						// compose
23173a2ffbaSStephan Aßmus 						uint32 alpha = srcHandle[3] * alphaOverride;
23273a2ffbaSStephan Aßmus 						dstHandle[0] = (srcHandle[0] * alpha
23373a2ffbaSStephan Aßmus 								+ dstHandle[0] * (65025 - alpha)) / 65025;
23473a2ffbaSStephan Aßmus 					}
23573a2ffbaSStephan Aßmus 					srcHandle += 4;
23673a2ffbaSStephan Aßmus 					dstHandle += 4;
23773a2ffbaSStephan Aßmus 				}
23873a2ffbaSStephan Aßmus 				src += bpr;
23973a2ffbaSStephan Aßmus 				dst += bpr;
24073a2ffbaSStephan Aßmus 			}
24173a2ffbaSStephan Aßmus 			break;
24273a2ffbaSStephan Aßmus 
24373a2ffbaSStephan Aßmus 		case MODE_MULTIPLY_INVERSE_ALPHA:
24473a2ffbaSStephan Aßmus 			for (; top <= bottom; top++) {
24573a2ffbaSStephan Aßmus 				uint8* srcHandle = src;
24673a2ffbaSStephan Aßmus 				uint8* dstHandle = dst;
24773a2ffbaSStephan Aßmus 				for (int32 x = left; x <= right; x++) {
24873a2ffbaSStephan Aßmus 					// compose
24973a2ffbaSStephan Aßmus 					uint8 temp = min_c(dstHandle[3], 255 - srcHandle[3]);
25036947c7bSOliver Tappe 					dstHandle[3] = (
25136947c7bSOliver Tappe 							dstHandle[3] * (255 - alphaOverride)
25236947c7bSOliver Tappe 							+ temp * alphaOverride
25336947c7bSOliver Tappe 						) / 255;
25473a2ffbaSStephan Aßmus 					srcHandle += 4;
25573a2ffbaSStephan Aßmus 					dstHandle += 4;
25673a2ffbaSStephan Aßmus 				}
25773a2ffbaSStephan Aßmus 				src += bpr;
25873a2ffbaSStephan Aßmus 				dst += bpr;
25973a2ffbaSStephan Aßmus 			}
26073a2ffbaSStephan Aßmus 			break;
26173a2ffbaSStephan Aßmus 
26273a2ffbaSStephan Aßmus 		case MODE_MULTIPLY_ALPHA:
26373a2ffbaSStephan Aßmus 			for (; top <= bottom; top++) {
26473a2ffbaSStephan Aßmus 				uint8* srcHandle = src;
26573a2ffbaSStephan Aßmus 				uint8* dstHandle = dst;
26673a2ffbaSStephan Aßmus 				for (int32 x = left; x <= right; x++) {
26773a2ffbaSStephan Aßmus 					// compose
26873a2ffbaSStephan Aßmus 					uint8 temp = min_c(dstHandle[3], srcHandle[3]);
26936947c7bSOliver Tappe 					dstHandle[3] = (
27036947c7bSOliver Tappe 							dstHandle[3] * (255 - alphaOverride)
27136947c7bSOliver Tappe 							+ temp * alphaOverride
27236947c7bSOliver Tappe 						) / 255;
27373a2ffbaSStephan Aßmus 					srcHandle += 4;
27473a2ffbaSStephan Aßmus 					dstHandle += 4;
27573a2ffbaSStephan Aßmus 				}
27673a2ffbaSStephan Aßmus 				src += bpr;
27773a2ffbaSStephan Aßmus 				dst += bpr;
27873a2ffbaSStephan Aßmus 			}
27973a2ffbaSStephan Aßmus 			break;
28073a2ffbaSStephan Aßmus 
28173a2ffbaSStephan Aßmus 		case MODE_LUMINANCE:
28273a2ffbaSStephan Aßmus 			for (; top <= bottom; top++) {
28373a2ffbaSStephan Aßmus 				uint8* srcHandle = src;
28473a2ffbaSStephan Aßmus 				uint8* dstHandle = dst;
28573a2ffbaSStephan Aßmus 				for (int32 x = left; x <= right; x++) {
28673a2ffbaSStephan Aßmus 					if (srcHandle[3] > 0) {
28773a2ffbaSStephan Aßmus 						// compose
28873a2ffbaSStephan Aßmus 						uint8 r = dstHandle[2];
28973a2ffbaSStephan Aßmus 						uint8 g = dstHandle[1];
29073a2ffbaSStephan Aßmus 						uint8 b = dstHandle[0];
29173a2ffbaSStephan Aßmus 						uint8 alpha = dstHandle[3];
29236947c7bSOliver Tappe 						replace_luminance(r, g, b, srcHandle[2], srcHandle[1],
29336947c7bSOliver Tappe 							srcHandle[0]);
29436947c7bSOliver Tappe 						blend_colors(dstHandle,
29536947c7bSOliver Tappe 							(srcHandle[3] * alphaOverride) / 255, b, g, r);
29673a2ffbaSStephan Aßmus 						dstHandle[3] = alpha;
29773a2ffbaSStephan Aßmus 					}
29873a2ffbaSStephan Aßmus 					srcHandle += 4;
29973a2ffbaSStephan Aßmus 					dstHandle += 4;
30073a2ffbaSStephan Aßmus 				}
30173a2ffbaSStephan Aßmus 				src += bpr;
30273a2ffbaSStephan Aßmus 				dst += bpr;
30373a2ffbaSStephan Aßmus 			}
30473a2ffbaSStephan Aßmus 			break;
30573a2ffbaSStephan Aßmus 
30673a2ffbaSStephan Aßmus 		case MODE_INVERSE_MULTIPLY:
30773a2ffbaSStephan Aßmus 			for (; top <= bottom; top++) {
30873a2ffbaSStephan Aßmus 				uint8* srcHandle = src;
30973a2ffbaSStephan Aßmus 				uint8* dstHandle = dst;
31073a2ffbaSStephan Aßmus 				for (int32 x = left; x <= right; x++) {
31173a2ffbaSStephan Aßmus 					if (srcHandle[3] > 0) {
31273a2ffbaSStephan Aßmus 						// compose
31336947c7bSOliver Tappe 						uint8 c1 = 255 - (
31436947c7bSOliver Tappe 								(((255 - srcHandle[0]) * (255 - dstHandle[0]))
31536947c7bSOliver Tappe 									/ 255) * dstHandle[3]
31636947c7bSOliver Tappe 								+ (255 - srcHandle[0]) * (255 - dstHandle[3])
31736947c7bSOliver Tappe 							) / 255;
31836947c7bSOliver Tappe 						uint8 c2 = 255 - (
31936947c7bSOliver Tappe 								(((255 - srcHandle[1]) * (255 - dstHandle[1]))
32036947c7bSOliver Tappe 									/ 255) * dstHandle[3]
32136947c7bSOliver Tappe 								+ (255 - srcHandle[1]) * (255 - dstHandle[3])
32236947c7bSOliver Tappe 							) / 255;
32336947c7bSOliver Tappe 						uint8 c3 = 255 - (
32436947c7bSOliver Tappe 								(((255 - srcHandle[2]) * (255 - dstHandle[2]))
32536947c7bSOliver Tappe 									/ 255) * dstHandle[3]
32636947c7bSOliver Tappe 								+ (255 - srcHandle[2]) * (255 - dstHandle[3])
32736947c7bSOliver Tappe 							) / 255;
32836947c7bSOliver Tappe 						blend_colors(dstHandle,
32936947c7bSOliver Tappe 							(srcHandle[3] * alphaOverride) / 255, c1, c2, c3);
33073a2ffbaSStephan Aßmus 					}
33173a2ffbaSStephan Aßmus 					srcHandle += 4;
33273a2ffbaSStephan Aßmus 					dstHandle += 4;
33373a2ffbaSStephan Aßmus 				}
33473a2ffbaSStephan Aßmus 				src += bpr;
33573a2ffbaSStephan Aßmus 				dst += bpr;
33673a2ffbaSStephan Aßmus 			}
33773a2ffbaSStephan Aßmus 			break;
33873a2ffbaSStephan Aßmus 
33973a2ffbaSStephan Aßmus 		case MODE_MULTIPLY:
34073a2ffbaSStephan Aßmus 			for (; top <= bottom; top++) {
34173a2ffbaSStephan Aßmus 				uint8* srcHandle = src;
34273a2ffbaSStephan Aßmus 				uint8* dstHandle = dst;
34373a2ffbaSStephan Aßmus 				for (int32 x = left; x <= right; x++) {
34473a2ffbaSStephan Aßmus 					if (srcHandle[3] > 0) {
34573a2ffbaSStephan Aßmus 						// compose
34636947c7bSOliver Tappe 						uint8 c1 = (
34736947c7bSOliver Tappe 								((srcHandle[0] * dstHandle[0]) / 255)
34836947c7bSOliver Tappe 									* dstHandle[3]
34936947c7bSOliver Tappe 								+ srcHandle[0] * (255 - dstHandle[3])
35036947c7bSOliver Tappe 							) / 255;
35136947c7bSOliver Tappe 						uint8 c2 = (
35236947c7bSOliver Tappe 								((srcHandle[1] * dstHandle[1]) / 255)
35336947c7bSOliver Tappe 									* dstHandle[3]
35436947c7bSOliver Tappe 								+ srcHandle[1] * (255 - dstHandle[3])
35536947c7bSOliver Tappe 							) / 255;
35636947c7bSOliver Tappe 						uint8 c3 = (
35736947c7bSOliver Tappe 								((srcHandle[2] * dstHandle[2]) / 255)
35836947c7bSOliver Tappe 									* dstHandle[3]
35936947c7bSOliver Tappe 								+ srcHandle[2] * (255 - dstHandle[3])
36036947c7bSOliver Tappe 							) / 255;
36136947c7bSOliver Tappe 						blend_colors(dstHandle,
36236947c7bSOliver Tappe 							(srcHandle[3] * alphaOverride) / 255, c1, c2, c3);
36373a2ffbaSStephan Aßmus 					}
36473a2ffbaSStephan Aßmus 					srcHandle += 4;
36573a2ffbaSStephan Aßmus 					dstHandle += 4;
36673a2ffbaSStephan Aßmus 				}
36773a2ffbaSStephan Aßmus 				src += bpr;
36873a2ffbaSStephan Aßmus 				dst += bpr;
36973a2ffbaSStephan Aßmus 			}
37073a2ffbaSStephan Aßmus 			break;
37173a2ffbaSStephan Aßmus 
37273a2ffbaSStephan Aßmus 		case MODE_NORMAL:
37373a2ffbaSStephan Aßmus 		default:
37473a2ffbaSStephan Aßmus 			if (alphaOverride == 255) {
37573a2ffbaSStephan Aßmus 				// use an optimized version that composes the bitmaps directly
37673a2ffbaSStephan Aßmus 				for (; top <= bottom; top++) {
37773a2ffbaSStephan Aßmus 					uint8* srcHandle = src;
37873a2ffbaSStephan Aßmus 					uint8* dstHandle = dst;
37973a2ffbaSStephan Aßmus 					for (int32 x = left; x <= right; x++) {
38073a2ffbaSStephan Aßmus 						blend_colors(dstHandle, srcHandle);
38173a2ffbaSStephan Aßmus 						srcHandle += 4;
38273a2ffbaSStephan Aßmus 						dstHandle += 4;
38373a2ffbaSStephan Aßmus 					}
38473a2ffbaSStephan Aßmus 					src += bpr;
38573a2ffbaSStephan Aßmus 					dst += bpr;
38673a2ffbaSStephan Aßmus 				}
38773a2ffbaSStephan Aßmus 			} else {
38873a2ffbaSStephan Aßmus 				for (; top <= bottom; top++) {
38973a2ffbaSStephan Aßmus 					uint8* srcHandle = src;
39073a2ffbaSStephan Aßmus 					uint8* dstHandle = dst;
39173a2ffbaSStephan Aßmus 					for (int32 x = left; x <= right; x++) {
39273a2ffbaSStephan Aßmus 						blend_colors(dstHandle, srcHandle, alphaOverride);
39373a2ffbaSStephan Aßmus 						srcHandle += 4;
39473a2ffbaSStephan Aßmus 						dstHandle += 4;
39573a2ffbaSStephan Aßmus 					}
39673a2ffbaSStephan Aßmus 					src += bpr;
39773a2ffbaSStephan Aßmus 					dst += bpr;
39873a2ffbaSStephan Aßmus 				}
39973a2ffbaSStephan Aßmus 			}
40073a2ffbaSStephan Aßmus 			break;
40173a2ffbaSStephan Aßmus 	}
40273a2ffbaSStephan Aßmus 
40373a2ffbaSStephan Aßmus 	return status;
40473a2ffbaSStephan Aßmus }
40573a2ffbaSStephan Aßmus 
40636947c7bSOliver Tappe 
40773a2ffbaSStephan Aßmus // Unarchive
40873a2ffbaSStephan Aßmus status_t
Unarchive(const BMessage * archive)40973a2ffbaSStephan Aßmus Layer::Unarchive(const BMessage* archive)
41073a2ffbaSStephan Aßmus {
41173a2ffbaSStephan Aßmus 	if (!archive)
41273a2ffbaSStephan Aßmus 		return B_BAD_VALUE;
41373a2ffbaSStephan Aßmus 
41473a2ffbaSStephan Aßmus 	// restore attributes
41573a2ffbaSStephan Aßmus 	float alpha;
41673a2ffbaSStephan Aßmus 	if (archive->FindFloat("alpha", &alpha) == B_OK) {
41773a2ffbaSStephan Aßmus 		constrain(alpha, 0.0, 1.0);
41873a2ffbaSStephan Aßmus 		fAlpha = alpha;
41973a2ffbaSStephan Aßmus 	} else
42073a2ffbaSStephan Aßmus 		fAlpha = 1.0;
42173a2ffbaSStephan Aßmus 	if (archive->FindInt32("mode", (int32*)&fMode) < B_OK)
42273a2ffbaSStephan Aßmus 		fMode = MODE_NORMAL;
42373a2ffbaSStephan Aßmus 	if (archive->FindInt32("flags", (int32*)&fFlags) < B_OK)
42473a2ffbaSStephan Aßmus 		fFlags = 0;
42573a2ffbaSStephan Aßmus 
42673a2ffbaSStephan Aßmus 	// delete current contents
42773a2ffbaSStephan Aßmus 	delete fBitmap;
42873a2ffbaSStephan Aßmus 	fBitmap = NULL;
42973a2ffbaSStephan Aßmus 
43073a2ffbaSStephan Aßmus 	status_t status = extract_bitmap(&fBitmap, archive, "current bitmap");
43173a2ffbaSStephan Aßmus 	if (status < B_OK)
43273a2ffbaSStephan Aßmus 		return status;
43373a2ffbaSStephan Aßmus 
43473a2ffbaSStephan Aßmus 	// "bounds" is where the layer actually has content
43573a2ffbaSStephan Aßmus 	BRect bounds;
43673a2ffbaSStephan Aßmus 	if (archive->FindRect("bounds", &bounds) == B_OK)
43773a2ffbaSStephan Aßmus 		fBounds = bounds;
43873a2ffbaSStephan Aßmus 	else
43973a2ffbaSStephan Aßmus 		fBounds.Set(0.0, 0.0, -1.0, -1.0);
44073a2ffbaSStephan Aßmus 
44173a2ffbaSStephan Aßmus 	// validate status of fBitmap
44273a2ffbaSStephan Aßmus 	if (!fBitmap)
44373a2ffbaSStephan Aßmus 		return B_ERROR;
44473a2ffbaSStephan Aßmus 
44573a2ffbaSStephan Aßmus 	status = fBitmap->InitCheck();
44673a2ffbaSStephan Aßmus 	if (status < B_OK) {
44773a2ffbaSStephan Aßmus 		delete fBitmap;
44873a2ffbaSStephan Aßmus 		fBitmap = NULL;
44973a2ffbaSStephan Aßmus 	}
45073a2ffbaSStephan Aßmus 
45173a2ffbaSStephan Aßmus 	return status;
45273a2ffbaSStephan Aßmus }
453