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
24546208a5SOliver Tappe#undef B_TRANSLATION_CONTEXT
25546208a5SOliver Tappe#define B_TRANSLATION_CONTEXT "Layer"
266537cf97SJérôme Duval
276537cf97SJérôme Duval
2873a2ffbaSStephan Aßmus// constructor
2973a2ffbaSStephan AßmusLayer::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
4073a2ffbaSStephan AßmusLayer::~Layer()
4173a2ffbaSStephan Aßmus{
4273a2ffbaSStephan Aßmus	delete fBitmap;
4373a2ffbaSStephan Aßmus}
4473a2ffbaSStephan Aßmus
4536947c7bSOliver Tappe
4673a2ffbaSStephan Aßmus// Compose
4773a2ffbaSStephan Aßmusstatus_t
4873a2ffbaSStephan AßmusLayer::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;
12036947c7bSOliver Tappe
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]
14136947c7bSOliver Tappe								+ srcHandle[0] * (255 - dstHandle[3])) / 255;
14236947c7bSOliver Tappe						uint8 c2
14336947c7bSOliver Tappe							= (max_c(srcHandle[1], dstHandle[1]) * dstHandle[3]
14436947c7bSOliver Tappe								+ srcHandle[1] * (255 - dstHandle[3])) / 255;
14536947c7bSOliver Tappe						uint8 c3
14636947c7bSOliver Tappe							= (max_c(srcHandle[2], dstHandle[2]) * dstHandle[3]
14736947c7bSOliver Tappe								+ 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]
16836947c7bSOliver Tappe								+ srcHandle[0] * (255 - dstHandle[3])) / 255;
16936947c7bSOliver Tappe						uint8 c2
17036947c7bSOliver Tappe							= (min_c(srcHandle[1], dstHandle[1]) * dstHandle[3]
17136947c7bSOliver Tappe								+ srcHandle[1] * (255 - dstHandle[3])) / 255;
17236947c7bSOliver Tappe						uint8 c3
17336947c7bSOliver Tappe							= (min_c(srcHandle[2], dstHandle[2]) * dstHandle[3]
17436947c7bSOliver Tappe								+ 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
19536947c7bSOliver Tappe								+ 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
21436947c7bSOliver Tappe								+ 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
23336947c7bSOliver Tappe								+ 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ßmusstatus_t
40973a2ffbaSStephan AßmusLayer::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