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