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