1/*
2 * Copyright 2001-2008, Haiku Inc.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 *		Ingo Weinhold (bonefish@users.sf.net)
7 *		DarkWyrm <bpmagic@columbus.rr.com>
8 *		Stephan A��mus <superstippi@gmx.de>
9 */
10
11/*!	BBitmap objects represent off-screen windows that contain bitmap data. */
12
13#include <algorithm>
14#include <limits.h>
15#include <new>
16#include <stdio.h>
17#include <stdlib.h>
18
19#include <Bitmap.h>
20#include <GraphicsDefs.h>
21#include <Locker.h>
22#include <Message.h>
23
24
25// structures defining the pixel layout
26
27struct rgb32_pixel {
28	uint8 blue;
29	uint8 green;
30	uint8 red;
31	uint8 alpha;
32};
33
34struct rgb32_big_pixel {
35	uint8 red;
36	uint8 green;
37	uint8 blue;
38	uint8 alpha;
39};
40
41struct rgb24_pixel {
42	uint8 blue;
43	uint8 green;
44	uint8 red;
45};
46
47struct rgb24_big_pixel {
48	uint8 red;
49	uint8 green;
50	uint8 blue;
51};
52
53struct rgb16_pixel {
54	uint8 gb;	// G[2:0],B[4:0]
55	uint8 rg;	// 16: R[4:0],G[5:3]
56				// 15: -[0],R[4:0],G[4:3]
57};
58
59struct rgb16_big_pixel {
60	uint8 rg;	// 16: R[4:0],G[5:3]
61				// 15: -[0],R[4:0],G[4:3]
62	uint8 gb;	// G[2:0],B[4:0]
63};
64
65// types defining what is needed to store a color value
66
67struct rgb_color_value {
68	uint8 red;
69	uint8 green;
70	uint8 blue;
71	uint8 alpha;
72};
73
74typedef uint8 gray_color_value;
75
76// TODO: system palette -- hard-coded for now, when the app server is ready
77// we should use system_colors() or BScreen::ColorMap().
78const rgb_color kSystemPalette[] = {
79	{   0,   0,   0, 255 }, {   8,   8,   8, 255 }, {  16,  16,  16, 255 },
80	{  24,  24,  24, 255 }, {  32,  32,  32, 255 }, {  40,  40,  40, 255 },
81	{  48,  48,  48, 255 }, {  56,  56,  56, 255 }, {  64,  64,  64, 255 },
82	{  72,  72,  72, 255 }, {  80,  80,  80, 255 }, {  88,  88,  88, 255 },
83	{  96,  96,  96, 255 }, { 104, 104, 104, 255 }, { 112, 112, 112, 255 },
84	{ 120, 120, 120, 255 }, { 128, 128, 128, 255 }, { 136, 136, 136, 255 },
85	{ 144, 144, 144, 255 }, { 152, 152, 152, 255 }, { 160, 160, 160, 255 },
86	{ 168, 168, 168, 255 }, { 176, 176, 176, 255 }, { 184, 184, 184, 255 },
87	{ 192, 192, 192, 255 }, { 200, 200, 200, 255 }, { 208, 208, 208, 255 },
88	{ 216, 216, 216, 255 }, { 224, 224, 224, 255 }, { 232, 232, 232, 255 },
89	{ 240, 240, 240, 255 }, { 248, 248, 248, 255 }, {   0,   0, 255, 255 },
90	{   0,   0, 229, 255 }, {   0,   0, 204, 255 }, {   0,   0, 179, 255 },
91	{   0,   0, 154, 255 }, {   0,   0, 129, 255 }, {   0,   0, 105, 255 },
92	{   0,   0,  80, 255 }, {   0,   0,  55, 255 }, {   0,   0,  30, 255 },
93	{ 255,   0,   0, 255 }, { 228,   0,   0, 255 }, { 203,   0,   0, 255 },
94	{ 178,   0,   0, 255 }, { 153,   0,   0, 255 }, { 128,   0,   0, 255 },
95	{ 105,   0,   0, 255 }, {  80,   0,   0, 255 }, {  55,   0,   0, 255 },
96	{  30,   0,   0, 255 }, {   0, 255,   0, 255 }, {   0, 228,   0, 255 },
97	{   0, 203,   0, 255 }, {   0, 178,   0, 255 }, {   0, 153,   0, 255 },
98	{   0, 128,   0, 255 }, {   0, 105,   0, 255 }, {   0,  80,   0, 255 },
99	{   0,  55,   0, 255 }, {   0,  30,   0, 255 }, {   0, 152,  51, 255 },
100	{ 255, 255, 255, 255 }, { 203, 255, 255, 255 }, { 203, 255, 203, 255 },
101	{ 203, 255, 152, 255 }, { 203, 255, 102, 255 }, { 203, 255,  51, 255 },
102	{ 203, 255,   0, 255 }, { 152, 255, 255, 255 }, { 152, 255, 203, 255 },
103	{ 152, 255, 152, 255 }, { 152, 255, 102, 255 }, { 152, 255,  51, 255 },
104	{ 152, 255,   0, 255 }, { 102, 255, 255, 255 }, { 102, 255, 203, 255 },
105	{ 102, 255, 152, 255 }, { 102, 255, 102, 255 }, { 102, 255,  51, 255 },
106	{ 102, 255,   0, 255 }, {  51, 255, 255, 255 }, {  51, 255, 203, 255 },
107	{  51, 255, 152, 255 }, {  51, 255, 102, 255 }, {  51, 255,  51, 255 },
108	{  51, 255,   0, 255 }, { 255, 152, 255, 255 }, { 255, 152, 203, 255 },
109	{ 255, 152, 152, 255 }, { 255, 152, 102, 255 }, { 255, 152,  51, 255 },
110	{ 255, 152,   0, 255 }, {   0, 102, 255, 255 }, {   0, 102, 203, 255 },
111	{ 203, 203, 255, 255 }, { 203, 203, 203, 255 }, { 203, 203, 152, 255 },
112	{ 203, 203, 102, 255 }, { 203, 203,  51, 255 }, { 203, 203,   0, 255 },
113	{ 152, 203, 255, 255 }, { 152, 203, 203, 255 }, { 152, 203, 152, 255 },
114	{ 152, 203, 102, 255 }, { 152, 203,  51, 255 }, { 152, 203,   0, 255 },
115	{ 102, 203, 255, 255 }, { 102, 203, 203, 255 }, { 102, 203, 152, 255 },
116	{ 102, 203, 102, 255 }, { 102, 203,  51, 255 }, { 102, 203,   0, 255 },
117	{  51, 203, 255, 255 }, {  51, 203, 203, 255 }, {  51, 203, 152, 255 },
118	{  51, 203, 102, 255 }, {  51, 203,  51, 255 }, {  51, 203,   0, 255 },
119	{ 255, 102, 255, 255 }, { 255, 102, 203, 255 }, { 255, 102, 152, 255 },
120	{ 255, 102, 102, 255 }, { 255, 102,  51, 255 }, { 255, 102,   0, 255 },
121	{   0, 102, 152, 255 }, {   0, 102, 102, 255 }, { 203, 152, 255, 255 },
122	{ 203, 152, 203, 255 }, { 203, 152, 152, 255 }, { 203, 152, 102, 255 },
123	{ 203, 152,  51, 255 }, { 203, 152,   0, 255 }, { 152, 152, 255, 255 },
124	{ 152, 152, 203, 255 }, { 152, 152, 152, 255 }, { 152, 152, 102, 255 },
125	{ 152, 152,  51, 255 }, { 152, 152,   0, 255 }, { 102, 152, 255, 255 },
126	{ 102, 152, 203, 255 }, { 102, 152, 152, 255 }, { 102, 152, 102, 255 },
127	{ 102, 152,  51, 255 }, { 102, 152,   0, 255 }, {  51, 152, 255, 255 },
128	{  51, 152, 203, 255 }, {  51, 152, 152, 255 }, {  51, 152, 102, 255 },
129	{  51, 152,  51, 255 }, {  51, 152,   0, 255 }, { 230, 134,   0, 255 },
130	{ 255,  51, 203, 255 }, { 255,  51, 152, 255 }, { 255,  51, 102, 255 },
131	{ 255,  51,  51, 255 }, { 255,  51,   0, 255 }, {   0, 102,  51, 255 },
132	{   0, 102,   0, 255 }, { 203, 102, 255, 255 }, { 203, 102, 203, 255 },
133	{ 203, 102, 152, 255 }, { 203, 102, 102, 255 }, { 203, 102,  51, 255 },
134	{ 203, 102,   0, 255 }, { 152, 102, 255, 255 }, { 152, 102, 203, 255 },
135	{ 152, 102, 152, 255 }, { 152, 102, 102, 255 }, { 152, 102,  51, 255 },
136	{ 152, 102,   0, 255 }, { 102, 102, 255, 255 }, { 102, 102, 203, 255 },
137	{ 102, 102, 152, 255 }, { 102, 102, 102, 255 }, { 102, 102,  51, 255 },
138	{ 102, 102,   0, 255 }, {  51, 102, 255, 255 }, {  51, 102, 203, 255 },
139	{  51, 102, 152, 255 }, {  51, 102, 102, 255 }, {  51, 102,  51, 255 },
140	{  51, 102,   0, 255 }, { 255,   0, 255, 255 }, { 255,   0, 203, 255 },
141	{ 255,   0, 152, 255 }, { 255,   0, 102, 255 }, { 255,   0,  51, 255 },
142	{ 255, 175,  19, 255 }, {   0,  51, 255, 255 }, {   0,  51, 203, 255 },
143	{ 203,  51, 255, 255 }, { 203,  51, 203, 255 }, { 203,  51, 152, 255 },
144	{ 203,  51, 102, 255 }, { 203,  51,  51, 255 }, { 203,  51,   0, 255 },
145	{ 152,  51, 255, 255 }, { 152,  51, 203, 255 }, { 152,  51, 152, 255 },
146	{ 152,  51, 102, 255 }, { 152,  51,  51, 255 }, { 152,  51,   0, 255 },
147	{ 102,  51, 255, 255 }, { 102,  51, 203, 255 }, { 102,  51, 152, 255 },
148	{ 102,  51, 102, 255 }, { 102,  51,  51, 255 }, { 102,  51,   0, 255 },
149	{  51,  51, 255, 255 }, {  51,  51, 203, 255 }, {  51,  51, 152, 255 },
150	{  51,  51, 102, 255 }, {  51,  51,  51, 255 }, {  51,  51,   0, 255 },
151	{ 255, 203, 102, 255 }, { 255, 203, 152, 255 }, { 255, 203, 203, 255 },
152	{ 255, 203, 255, 255 }, {   0,  51, 152, 255 }, {   0,  51, 102, 255 },
153	{   0,  51,  51, 255 }, {   0,  51,   0, 255 }, { 203,   0, 255, 255 },
154	{ 203,   0, 203, 255 }, { 203,   0, 152, 255 }, { 203,   0, 102, 255 },
155	{ 203,   0,  51, 255 }, { 255, 227,  70, 255 }, { 152,   0, 255, 255 },
156	{ 152,   0, 203, 255 }, { 152,   0, 152, 255 }, { 152,   0, 102, 255 },
157	{ 152,   0,  51, 255 }, { 152,   0,   0, 255 }, { 102,   0, 255, 255 },
158	{ 102,   0, 203, 255 }, { 102,   0, 152, 255 }, { 102,   0, 102, 255 },
159	{ 102,   0,  51, 255 }, { 102,   0,   0, 255 }, {  51,   0, 255, 255 },
160	{  51,   0, 203, 255 }, {  51,   0, 152, 255 }, {  51,   0, 102, 255 },
161	{  51,   0,  51, 255 }, {  51,   0,   0, 255 }, { 255, 203,  51, 255 },
162	{ 255, 203,   0, 255 }, { 255, 255,   0, 255 }, { 255, 255,  51, 255 },
163	{ 255, 255, 102, 255 }, { 255, 255, 152, 255 }, { 255, 255, 203, 255 },
164	{ 255, 255, 255, 0 } // B_TRANSPARENT_MAGIC_CMAP8
165};
166
167
168/*!	\brief Returns the number of bytes per row needed to store the actual
169		   bitmap data (not including any padding) given a color space and a
170		   row width.
171	\param colorSpace The color space.
172	\param width The width.
173	\return The number of bytes per row needed to store data for a row, or
174			0, if the color space is not supported.
175*/
176static inline int32
177get_raw_bytes_per_row(color_space colorSpace, int32 width)
178{
179	int32 bpr = 0;
180	switch (colorSpace) {
181		// supported
182		case B_RGBA64: case B_RGBA64_BIG:
183			bpr = 8 * width;
184			break;
185		case B_RGB48: case B_RGB48_BIG:
186			bpr = 6 * width;
187			break;
188		case B_RGB32: case B_RGBA32:
189		case B_RGB32_BIG: case B_RGBA32_BIG:
190		case B_UVL32: case B_UVLA32:
191		case B_LAB32: case B_LABA32:
192		case B_HSI32: case B_HSIA32:
193		case B_HSV32: case B_HSVA32:
194		case B_HLS32: case B_HLSA32:
195		case B_CMY32: case B_CMYA32: case B_CMYK32:
196			bpr = 4 * width;
197			break;
198		case B_RGB24: case B_RGB24_BIG:
199		case B_UVL24: case B_LAB24: case B_HSI24:
200		case B_HSV24: case B_HLS24: case B_CMY24:
201			bpr = 3 * width;
202			break;
203		case B_RGB16:		case B_RGB15:		case B_RGBA15:
204		case B_RGB16_BIG:	case B_RGB15_BIG:	case B_RGBA15_BIG:
205			bpr = 2 * width;
206			break;
207		case B_CMAP8: case B_GRAY8:
208			bpr = width;
209			break;
210		case B_GRAY1:
211			bpr = (width + 7) / 8;
212			break;
213		case B_YCbCr422: case B_YUV422:
214			bpr = (width + 3) / 4 * 8;
215			break;
216		case B_YCbCr411: case B_YUV411:
217			bpr = (width + 3) / 4 * 6;
218			break;
219		case B_YCbCr444: case B_YUV444:
220			bpr = (width + 3) / 4 * 12;
221			break;
222		case B_YCbCr420: case B_YUV420:
223			bpr = (width + 3) / 4 * 6;
224			break;
225		case B_YUV9:
226			bpr = (width + 15) / 16 * 18;
227		// unsupported
228		case B_NO_COLOR_SPACE:
229		case B_YUV12:
230			break;
231	}
232	return bpr;
233}
234
235
236/*!	\brief Returns the number of bytes per row needed to store the bitmap
237		   data (including any padding) given a color space and a row width.
238	\param colorSpace The color space.
239	\param width The width.
240	\return The number of bytes per row needed to store data for a row, or
241			0, if the color space is not supported.
242*/
243static inline int32
244get_bytes_per_row(color_space colorSpace, int32 width)
245{
246	int32 bpr = get_raw_bytes_per_row(colorSpace, width);
247	// align to int32
248	bpr = (bpr + 3) & 0x7ffffffc;
249	return bpr;
250}
251
252
253/*!	\brief Returns the brightness of an RGB 24 color.
254	\param red Value of the red component.
255	\param green Value of the green component.
256	\param blue Value of the blue component.
257	\return The brightness for the supplied RGB color as a value between 0
258			and 255.
259*/
260static inline uint8
261brightness_for(uint8 red, uint8 green, uint8 blue)
262{
263	// brightness = 0.301 * red + 0.586 * green + 0.113 * blue
264	// we use for performance reasons:
265	// brightness = (308 * red + 600 * green + 116 * blue) / 1024
266	return uint8((308 * red + 600 * green + 116 * blue) / 1024);
267}
268
269
270/*!	\brief Returns the "distance" between two RGB colors.
271
272	This functions defines an metric on the RGB color space. The distance
273	between two colors is 0, if and only if the colors are equal.
274
275	\param red1 Red component of the first color.
276	\param green1 Green component of the first color.
277	\param blue1 Blue component of the first color.
278	\param red2 Red component of the second color.
279	\param green2 Green component of the second color.
280	\param blue2 Blue component of the second color.
281	\return The distance between the given colors.
282*/
283static inline unsigned
284color_distance(uint8 red1, uint8 green1, uint8 blue1, uint8 red2, uint8 green2,
285	uint8 blue2)
286{
287	// euklidian distance (its square actually)
288	int rd = (int)red1 - (int)red2;
289	int gd = (int)green1 - (int)green2;
290	int bd = (int)blue1 - (int)blue2;
291//	return rd * rd + gd * gd + bd * bd;
292
293	// distance according to psycho-visual tests
294	int rmean = ((int)red1 + (int)red2) / 2;
295	return (((512 + rmean) * rd * rd) >> 8) + 4 * gd * gd
296		+ (((767 - rmean) * bd * bd) >> 8);
297}
298
299
300static inline int32
301bit_mask(int32 bit)
302{
303	return 1 << bit;
304}
305
306
307static inline int32
308inverse_bit_mask(int32 bit)
309{
310	return ~bit_mask(bit);
311}
312
313
314//	#pragma mark - PaletteConverter
315
316
317namespace BPrivate {
318
319/*!	\brief Helper class for conversion between RGB and palette colors.
320*/
321class PaletteConverter {
322public:
323	PaletteConverter();
324	PaletteConverter(const rgb_color *palette);
325	PaletteConverter(const color_map *colorMap);
326	~PaletteConverter();
327
328	status_t SetTo(const rgb_color *palette);
329	status_t SetTo(const color_map *colorMap);
330	status_t InitCheck() const;
331
332	inline uint8 IndexForRGB15(uint16 rgb) const;
333	inline uint8 IndexForRGB15(uint8 red, uint8 green, uint8 blue) const;
334	inline uint8 IndexForRGB16(uint16 rgb) const;
335	inline uint8 IndexForRGB16(uint8 red, uint8 green, uint8 blue) const;
336	inline uint8 IndexForRGB24(uint32 rgb) const;
337	inline uint8 IndexForRGB24(uint8 red, uint8 green, uint8 blue) const;
338	inline uint8 IndexForGray(uint8 gray) const;
339
340	inline const rgb_color &RGBColorForIndex(uint8 index) const;
341	inline uint16 RGB15ColorForIndex(uint8 index) const;
342	inline uint16 RGB16ColorForIndex(uint8 index) const;
343	inline uint32 RGB24ColorForIndex(uint8 index) const;
344	inline void RGB24ColorForIndex(uint8 index, uint8 &red, uint8 &green,
345		uint8 &blue, uint8 &alpha) const;
346	inline uint8 GrayColorForIndex(uint8 index) const;
347
348private:
349	const color_map	*fColorMap;
350	color_map		*fOwnColorMap;
351	status_t		fCStatus;
352};
353
354}	// namespace BPrivate
355
356using BPrivate::PaletteConverter;
357using namespace std;
358
359
360/*!	\brief Creates an uninitialized PaletteConverter.
361*/
362PaletteConverter::PaletteConverter()
363	: fColorMap(NULL),
364	  fOwnColorMap(NULL),
365	  fCStatus(B_NO_INIT)
366{
367}
368
369
370/*!	\brief Creates a PaletteConverter and initializes it to the supplied
371		   palette.
372	\param palette The palette being a 256 entry rgb_color array.
373*/
374PaletteConverter::PaletteConverter(const rgb_color *palette)
375	: fColorMap(NULL),
376	  fOwnColorMap(NULL),
377	  fCStatus(B_NO_INIT)
378{
379	SetTo(palette);
380}
381
382
383/*!	\brief Creates a PaletteConverter and initializes it to the supplied
384		   color map.
385	\param colorMap The completely initialized color map.
386*/
387PaletteConverter::PaletteConverter(const color_map *colorMap)
388	: fColorMap(NULL),
389	  fOwnColorMap(NULL),
390	  fCStatus(B_NO_INIT)
391{
392	SetTo(colorMap);
393}
394
395
396/*!	\brief Frees all resources associated with this object.
397*/
398PaletteConverter::~PaletteConverter()
399{
400	delete fOwnColorMap;
401}
402
403
404/*!	\brief Initializes the converter to the supplied palette.
405	\param palette The palette being a 256 entry rgb_color array.
406	\return \c B_OK, if everything went fine, an error code otherwise.
407*/
408status_t
409PaletteConverter::SetTo(const rgb_color *palette)
410{
411	// cleanup
412	SetTo((const color_map*)NULL);
413	status_t error = (palette ? B_OK : B_BAD_VALUE);
414	// alloc color map
415	if (error == B_OK) {
416		fOwnColorMap = new(nothrow) color_map;
417		if (fOwnColorMap == NULL)
418			error = B_NO_MEMORY;
419	}
420	// init color map
421	if (error == B_OK) {
422		fColorMap = fOwnColorMap;
423		// init color list
424		memcpy(fOwnColorMap->color_list, palette, sizeof(rgb_color) * 256);
425		// init index map
426		for (int32 color = 0; color < 32768; color++) {
427			// get components
428			uint8 red = (color & 0x7c00) >> 7;
429			uint8 green = (color & 0x3e0) >> 2;
430			uint8 blue = (color & 0x1f) << 3;
431			red |= red >> 5;
432			green |= green >> 5;
433			blue |= blue >> 5;
434			// find closest color
435			uint8 closestIndex = 0;
436			unsigned closestDistance = UINT_MAX;
437			for (int32 i = 0; i < 256; i++) {
438				const rgb_color &c = fOwnColorMap->color_list[i];
439				unsigned distance = color_distance(red, green, blue,
440												   c.red, c.green, c.blue);
441				if (distance < closestDistance) {
442					closestIndex = i;
443					closestDistance = distance;
444				}
445			}
446			fOwnColorMap->index_map[color] = closestIndex;
447		}
448		// no need to init inversion map
449	}
450	fCStatus = error;
451	return error;
452}
453
454
455/*!	\brief Initializes the converter to the supplied color map.
456	\param colorMap The completely initialized color map.
457	\return \c B_OK, if everything went fine, an error code otherwise.
458*/
459status_t
460PaletteConverter::SetTo(const color_map *colorMap)
461{
462	// cleanup
463	if (fOwnColorMap) {
464		delete fOwnColorMap;
465		fOwnColorMap = NULL;
466	}
467	// set
468	fColorMap = colorMap;
469	fCStatus = fColorMap ? B_OK : B_BAD_VALUE;
470	return fCStatus;
471}
472
473
474/*!	\brief Returns the result of the last initialization via constructor or
475		   SetTo().
476	\return \c B_OK, if the converter is properly initialized, an error code
477			otherwise.
478*/
479status_t
480PaletteConverter::InitCheck() const
481{
482	return fCStatus;
483}
484
485
486/*!	\brief Returns the palette color index closest to a given RGB 15 color.
487
488	The object must be properly initialized.
489
490	\param rgb The RGB 15 color value (R[14:10]G[9:5]B[4:0]).
491	\return The palette color index for the supplied color.
492*/
493inline uint8
494PaletteConverter::IndexForRGB15(uint16 rgb) const
495{
496	return fColorMap->index_map[rgb];
497}
498
499
500/*!	\brief Returns the palette color index closest to a given RGB 15 color.
501
502	The object must be properly initialized.
503
504	\param red Red component of the color (R[4:0]).
505	\param green Green component of the color (G[4:0]).
506	\param blue Blue component of the color (B[4:0]).
507	\return The palette color index for the supplied color.
508*/
509inline uint8
510PaletteConverter::IndexForRGB15(uint8 red, uint8 green, uint8 blue) const
511{
512	// the 5 least significant bits are used
513	return fColorMap->index_map[(red << 10) | (green << 5) | blue];
514}
515
516
517/*!	\brief Returns the palette color index closest to a given RGB 16 color.
518
519	The object must be properly initialized.
520
521	\param rgb The RGB 16 color value (R[15:11]G[10:5]B[4:0]).
522	\return The palette color index for the supplied color.
523*/
524inline uint8
525PaletteConverter::IndexForRGB16(uint16 rgb) const
526{
527	return fColorMap->index_map[((rgb >> 1) & 0x7fe0) | (rgb & 0x1f)];
528}
529
530
531/*!	\brief Returns the palette color index closest to a given RGB 16 color.
532
533	The object must be properly initialized.
534
535	\param red Red component of the color (R[4:0]).
536	\param green Green component of the color (G[5:0]).
537	\param blue Blue component of the color (B[4:0]).
538	\return The palette color index for the supplied color.
539*/
540inline uint8
541PaletteConverter::IndexForRGB16(uint8 red, uint8 green, uint8 blue) const
542{
543	// the 5 (for red, blue) / 6 (for green) least significant bits are used
544	return fColorMap->index_map[(red << 10) | ((green & 0x3e) << 4) | blue];
545}
546
547
548/*!	\brief Returns the palette color index closest to a given RGB 32 color.
549
550	The object must be properly initialized.
551
552	\param rgb The RGB 32 color value (R[31:24]G[23:16]B[15:8]).
553	\return The palette color index for the supplied color.
554*/
555inline uint8
556PaletteConverter::IndexForRGB24(uint32 rgb) const
557{
558	return fColorMap->index_map[((rgb & 0xf8000000) >> 17)
559		| ((rgb & 0xf80000) >> 14) | ((rgb & 0xf800) >> 11)];
560}
561
562
563/*!	\brief Returns the palette color index closest to a given RGB 24 color.
564
565	The object must be properly initialized.
566
567	\param red Red component of the color.
568	\param green Green component of the color.
569	\param blue Blue component of the color.
570	\return The palette color index for the supplied color.
571*/
572inline uint8
573PaletteConverter::IndexForRGB24(uint8 red, uint8 green, uint8 blue) const
574{
575	return fColorMap->index_map[((red & 0xf8) << 7) | ((green & 0xf8) << 2)
576		| (blue >> 3)];
577}
578
579
580/*!	\brief Returns the palette color index closest to a given Gray 8 color.
581
582	The object must be properly initialized.
583
584	\param gray The Gray 8 color value.
585	\return The palette color index for the supplied color.
586*/
587inline uint8
588PaletteConverter::IndexForGray(uint8 gray) const
589{
590	return IndexForRGB24(gray, gray, gray);
591}
592
593
594/*!	\brief Returns the RGB color for a given palette color index.
595
596	The object must be properly initialized.
597
598	\param index The palette color index.
599	\return The color for the supplied palette color index.
600*/
601inline const rgb_color &
602PaletteConverter::RGBColorForIndex(uint8 index) const
603{
604	return fColorMap->color_list[index];
605}
606
607
608/*!	\brief Returns the RGB 15 color for a given palette color index.
609
610	The object must be properly initialized.
611
612	\param index The palette color index.
613	\return The color for the supplied palette color index
614			(R[14:10]G[9:5]B[4:0]).
615*/
616inline uint16
617PaletteConverter::RGB15ColorForIndex(uint8 index) const
618{
619	const rgb_color &color = fColorMap->color_list[index];
620	return ((color.red & 0xf8) << 7) | ((color.green & 0xf8) << 2)
621		| (color.blue >> 3);
622}
623
624
625/*!	\brief Returns the RGB 16 color for a given palette color index.
626
627	The object must be properly initialized.
628
629	\param index The palette color index.
630	\return The color for the supplied palette color index
631			(R[15:11]G[10:5]B[4:0]).
632*/
633inline uint16
634PaletteConverter::RGB16ColorForIndex(uint8 index) const
635{
636	const rgb_color &color = fColorMap->color_list[index];
637	return ((color.red & 0xf8) << 8) | ((color.green & 0xfc) << 3)
638		| (color.blue >> 3);
639}
640
641
642/*!	\brief Returns the RGB 24 color for a given palette color index.
643
644	The object must be properly initialized.
645
646	\param index The palette color index.
647	\return The color for the supplied palette color index
648			(R[31:24]G[23:16]B[15:8]).
649*/
650inline uint32
651PaletteConverter::RGB24ColorForIndex(uint8 index) const
652{
653	const rgb_color &color = fColorMap->color_list[index];
654	return (color.blue << 24) | (color.red << 8) | (color.green << 16)
655		| color.alpha;
656}
657
658
659/*!	\brief Returns the RGB 24 color for a given palette color index.
660
661	The object must be properly initialized.
662
663	\param index The palette color index.
664	\param red Reference to the variable the red component shall be stored
665		   into.
666	\param green Reference to the variable the green component shall be stored
667		   into.
668	\param blue Reference to the variable the blue component shall be stored
669		   into.
670*/
671inline void
672PaletteConverter::RGB24ColorForIndex(uint8 index, uint8 &red, uint8 &green,
673	uint8 &blue, uint8 &alpha) const
674{
675	const rgb_color &color = fColorMap->color_list[index];
676	red = color.red;
677	green = color.green;
678	blue = color.blue;
679	alpha = color.alpha;
680}
681
682
683/*!	\brief Returns the Gray 8 color for a given palette color index.
684
685	The object must be properly initialized.
686
687	\param index The palette color index.
688	\return The color for the supplied palette color index.
689*/
690inline uint8
691PaletteConverter::GrayColorForIndex(uint8 index) const
692{
693	const rgb_color &color = fColorMap->color_list[index];
694	return brightness_for(color.red, color.green, color.blue);
695}
696
697// TODO: Remove these and palette_converter() when BScreen is available.
698static BLocker gPaletteConverterLock;
699static PaletteConverter	gPaletteConverter;
700
701
702/*!	\brief Returns a PaletteConverter using the system color palette.
703	\return A PaletteConverter.
704*/
705static const PaletteConverter*
706palette_converter()
707{
708	if (gPaletteConverterLock.Lock()) {
709		if (gPaletteConverter.InitCheck() != B_OK)
710			gPaletteConverter.SetTo(kSystemPalette);
711		gPaletteConverterLock.Unlock();
712	}
713	return &gPaletteConverter;
714}
715
716
717//	#pragma mark - Reader classes
718
719
720// BaseReader
721template<typename _PixelType>
722struct BaseReader {
723	typedef _PixelType		pixel_t;
724
725	BaseReader(const void *data) : pixels((const pixel_t*)data) {}
726
727	inline void SetTo(const void *data) { pixels = (const pixel_t*)data; }
728
729	inline void NextRow(int32 skip)
730	{
731		pixels = (const pixel_t*)((const char*)pixels + skip);
732	}
733
734	const pixel_t *pixels;
735};
736
737// RGB24Reader
738template<typename _PixelType>
739struct RGB24Reader : public BaseReader<_PixelType> {
740	typedef rgb_color_value	preferred_color_value_t;
741	typedef _PixelType		pixel_t;
742
743	RGB24Reader(const void *data) : BaseReader<_PixelType>(data) {}
744
745	inline void Read(rgb_color_value &color)
746	{
747		const pixel_t &pixel = *BaseReader<_PixelType>::pixels;
748		color.red = pixel.red;
749		color.green = pixel.green;
750		color.blue = pixel.blue;
751		color.alpha = 255;
752		BaseReader<_PixelType>::pixels++;
753	}
754
755	inline void Read(gray_color_value &gray)
756	{
757		rgb_color_value color;
758		Read(color);
759		gray = brightness_for(color.red, color.green, color.blue);
760	}
761};
762
763// RGB16Reader
764template<typename _PixelType>
765struct RGB16Reader : public BaseReader<_PixelType> {
766	typedef rgb_color_value	preferred_color_value_t;
767	typedef _PixelType		pixel_t;
768
769	RGB16Reader(const void *data) : BaseReader<_PixelType>(data) {}
770
771	inline void Read(rgb_color_value &color)
772	{
773		// rg: R[4:0],G[5:3]
774		// gb: G[2:0],B[4:0]
775		const pixel_t &pixel = *BaseReader<_PixelType>::pixels;
776		color.red = pixel.rg & 0xf8;
777		color.green = ((pixel.rg & 0x07) << 5) & ((pixel.gb & 0xe0) >> 3);
778		color.blue = (pixel.gb & 0x1f) << 3;
779		color.red |= color.red >> 5;
780		color.green |= color.green >> 6;
781		color.blue |= color.blue >> 5;
782		color.alpha = 255;
783		BaseReader<_PixelType>::pixels++;
784	}
785
786	inline void Read(gray_color_value &gray)
787	{
788		rgb_color_value color;
789		Read(color);
790		gray = brightness_for(color.red, color.green, color.blue);
791	}
792};
793
794// RGB15Reader
795template<typename _PixelType>
796struct RGB15Reader : public BaseReader<_PixelType> {
797	typedef rgb_color_value	preferred_color_value_t;
798	typedef _PixelType		pixel_t;
799
800	RGB15Reader(const void *data) : BaseReader<_PixelType>(data) {}
801
802	inline void Read(rgb_color_value &color)
803	{
804		// rg: -[0],R[4:0],G[4:3]
805		// gb: G[2:0],B[4:0]
806		const pixel_t &pixel = *BaseReader<_PixelType>::pixels;
807		color.red = (pixel.rg & 0x7c) << 1;
808		color.green = ((pixel.rg & 0x03) << 6) & ((pixel.gb & 0xe0) >> 2);
809		color.blue = (pixel.gb & 0x1f) << 3;
810		color.red |= color.red >> 5;
811		color.green |= color.green >> 5;
812		color.blue |= color.blue >> 5;
813		color.alpha = 255;
814		BaseReader<_PixelType>::pixels++;
815	}
816
817	inline void Read(gray_color_value &gray)
818	{
819		rgb_color_value color;
820		Read(color);
821		gray = brightness_for(color.red, color.green, color.blue);
822	}
823};
824
825// CMAP8Reader
826struct CMAP8Reader : public BaseReader<uint8> {
827	typedef rgb_color_value	preferred_color_value_t;
828
829	CMAP8Reader(const void *data, const PaletteConverter &converter)
830		: BaseReader<uint8>(data), converter(converter) {}
831
832	inline void Read(rgb_color_value &color)
833	{
834		converter.RGB24ColorForIndex(*BaseReader<uint8>::pixels, color.red, color.green,
835									 color.blue, color.alpha);
836		BaseReader<uint8>::pixels++;
837	}
838
839	inline void Read(gray_color_value &gray)
840	{
841		gray = converter.GrayColorForIndex(*BaseReader<uint8>::pixels);
842		BaseReader<uint8>::pixels++;
843	}
844
845	const PaletteConverter &converter;
846};
847
848// Gray8Reader
849struct Gray8Reader : public BaseReader<uint8> {
850	typedef gray_color_value	preferred_color_value_t;
851
852	Gray8Reader(const void *data) : BaseReader<uint8>(data) {}
853
854	inline void Read(rgb_color_value &color)
855	{
856		color.red = color.green = color.blue = *BaseReader<uint8>::pixels;
857		color.alpha = 255;
858		BaseReader<uint8>::pixels++;
859	}
860
861	inline void Read(gray_color_value &gray)
862	{
863		gray = *BaseReader<uint8>::pixels;
864		BaseReader<uint8>::pixels++;
865	}
866};
867
868// Gray1Reader
869struct Gray1Reader : public BaseReader<uint8> {
870	typedef gray_color_value	preferred_color_value_t;
871
872	Gray1Reader(const void *data) : BaseReader<uint8>(data), bit(7) {}
873
874	inline void SetTo(const void *data)
875	{
876		pixels = (const pixel_t*)data;
877		bit = 7;
878	}
879
880	inline void NextRow(int32 skip)
881	{
882		if (bit == 7)
883			pixels = (const pixel_t*)((const char*)pixels + skip);
884		else {
885			pixels = (const pixel_t*)((const char*)pixels + skip + 1);
886			bit = 7;
887		}
888	}
889
890	inline void Read(rgb_color_value &color)
891	{
892		if (*pixels & bit_mask(bit))
893			color.red = color.green = color.blue = 255;
894		else
895			color.red = color.green = color.blue = 0;
896		color.alpha = 255;
897		bit--;
898		if (bit == -1) {
899			pixels++;
900			bit = 7;
901		}
902	}
903
904	inline void Read(gray_color_value &gray)
905	{
906		if (*pixels & bit_mask(bit))
907			gray = 255;
908		else
909			gray = 0;
910		bit--;
911		if (bit == -1) {
912			pixels++;
913			bit = 7;
914		}
915	}
916
917	int32 bit;
918};
919
920
921//	#pragma mark - Writer classes
922
923
924// BaseWriter
925template<typename _PixelType>
926struct BaseWriter {
927	typedef _PixelType		pixel_t;
928
929	BaseWriter(void *data) : pixels((pixel_t*)data) {}
930
931	inline void SetTo(void *data) { pixels = (pixel_t*)data; }
932
933	pixel_t *pixels;
934};
935
936
937// RGB32Writer
938template<typename _PixelType>
939struct RGB32Writer : public BaseWriter<_PixelType> {
940	typedef rgb_color_value	preferred_color_value_t;
941	typedef _PixelType		pixel_t;
942
943	RGB32Writer(void *data) : BaseWriter<_PixelType>(data) {}
944
945	inline void Write(const rgb_color_value &color)
946	{
947		pixel_t &pixel = *BaseWriter<_PixelType>::pixels;
948		pixel.red = color.red;
949		pixel.green = color.green;
950		pixel.blue = color.blue;
951		pixel.alpha = color.alpha;
952		BaseWriter<_PixelType>::pixels++;
953	}
954
955	inline void Write(const gray_color_value &gray)
956	{
957		pixel_t &pixel = *BaseWriter<_PixelType>::pixels;
958		pixel.red = gray;
959		pixel.green = gray;
960		pixel.blue = gray;
961		pixel.alpha = 255;
962		BaseWriter<_PixelType>::pixels++;
963	}
964};
965
966// RGB24Writer
967template<typename _PixelType>
968struct RGB24Writer : public BaseWriter<_PixelType> {
969	typedef rgb_color_value	preferred_color_value_t;
970	typedef _PixelType		pixel_t;
971
972	RGB24Writer(void *data) : BaseWriter<_PixelType>(data) {}
973
974	inline void Write(const rgb_color_value &color)
975	{
976		pixel_t &pixel = *BaseWriter<_PixelType>::pixels;
977		pixel.red = color.red;
978		pixel.green = color.green;
979		pixel.blue = color.blue;
980		BaseWriter<_PixelType>::pixels++;
981	}
982
983	inline void Write(const gray_color_value &gray)
984	{
985		pixel_t &pixel = *BaseWriter<_PixelType>::pixels;
986		pixel.red = gray;
987		pixel.green = gray;
988		pixel.blue = gray;
989		BaseWriter<_PixelType>::pixels++;
990	}
991};
992
993// RGB16Writer
994template<typename _PixelType>
995struct RGB16Writer : public BaseWriter<_PixelType> {
996	typedef rgb_color_value	preferred_color_value_t;
997	typedef _PixelType		pixel_t;
998
999	RGB16Writer(void *data) : BaseWriter<_PixelType>(data) {}
1000
1001	inline void Write(const rgb_color_value &color)
1002	{
1003		// rg: R[4:0],G[5:3]
1004		// gb: G[2:0],B[4:0]
1005		pixel_t &pixel = *BaseWriter<_PixelType>::pixels;
1006		pixel.rg = (color.red & 0xf8) | (color.green >> 5);
1007		pixel.gb = ((color.green & 0x1c) << 3) | (color.blue >> 3);
1008		BaseWriter<_PixelType>::pixels++;
1009	}
1010
1011	inline void Write(const gray_color_value &gray)
1012	{
1013		pixel_t &pixel = *BaseWriter<_PixelType>::pixels;
1014		pixel.rg = (gray & 0xf8) | (gray >> 5);
1015		pixel.gb = ((gray & 0x1c) << 3) | (gray >> 3);
1016		BaseWriter<_PixelType>::pixels++;
1017	}
1018};
1019
1020// RGB15Writer
1021template<typename _PixelType>
1022struct RGB15Writer : public BaseWriter<_PixelType> {
1023	typedef rgb_color_value	preferred_color_value_t;
1024	typedef _PixelType		pixel_t;
1025
1026	RGB15Writer(void *data) : BaseWriter<_PixelType>(data) {}
1027
1028	inline void Write(const rgb_color_value &color)
1029	{
1030		// rg: -[0],R[4:0],G[4:3]
1031		// gb: G[2:0],B[4:0]
1032		pixel_t &pixel = *BaseWriter<_PixelType>::pixels;
1033		pixel.rg = ((color.red & 0xf8) >> 1) | (color.green >> 6);
1034		pixel.gb = ((color.green & 0x38) << 2) | (color.blue >> 3);
1035		BaseWriter<_PixelType>::pixels++;
1036	}
1037
1038	inline void Write(const gray_color_value &gray)
1039	{
1040		pixel_t &pixel = *BaseWriter<_PixelType>::pixels;
1041		pixel.rg = ((gray & 0xf8) >> 1) | (gray >> 6);
1042		pixel.gb = ((gray & 0x38) << 2) | (gray >> 3);
1043		BaseWriter<_PixelType>::pixels++;
1044	}
1045};
1046
1047// CMAP8Writer
1048struct CMAP8Writer : public BaseWriter<uint8> {
1049	typedef rgb_color_value	preferred_color_value_t;
1050
1051	CMAP8Writer(void *data, const PaletteConverter &converter)
1052		: BaseWriter<uint8>(data), converter(converter) {}
1053
1054	inline void Write(const rgb_color_value &color)
1055	{
1056		*pixels = converter.IndexForRGB24(color.red, color.green, color.blue);
1057		pixels++;
1058	}
1059
1060	inline void Write(const gray_color_value &gray)
1061	{
1062		*pixels = converter.IndexForGray(gray);
1063		pixels++;
1064	}
1065
1066	const PaletteConverter &converter;
1067};
1068
1069// Gray8Writer
1070struct Gray8Writer : public BaseWriter<uint8> {
1071	typedef gray_color_value	preferred_color_value_t;
1072
1073	Gray8Writer(void *data) : BaseWriter<uint8>(data) {}
1074
1075	inline void Write(const rgb_color_value &color)
1076	{
1077		*pixels = brightness_for(color.red, color.green, color.blue);
1078		pixels++;
1079	}
1080
1081	inline void Write(const gray_color_value &gray)
1082	{
1083		*pixels = gray;
1084		pixels++;
1085	}
1086};
1087
1088// Gray1Writer
1089struct Gray1Writer : public BaseWriter<uint8> {
1090	typedef gray_color_value	preferred_color_value_t;
1091
1092	Gray1Writer(void *data) : BaseWriter<uint8>(data), bit(7) {}
1093
1094	inline void SetTo(void *data) { pixels = (pixel_t*)data; bit = 7; }
1095
1096	inline void Write(const gray_color_value &gray)
1097	{
1098		*pixels = (*pixels & inverse_bit_mask(bit))
1099				  | (gray & 0x80) >> (7 - bit);
1100		bit--;
1101		if (bit == -1) {
1102			pixels++;
1103			bit = 7;
1104		}
1105	}
1106
1107	inline void Write(const rgb_color_value &color)
1108	{
1109		Write(brightness_for(color.red, color.green, color.blue));
1110	}
1111
1112	int32 bit;
1113};
1114
1115
1116// set_bits_worker
1117/*!	\brief Worker function that reads bitmap data from one buffer and writes
1118		   it (converted) to another one.
1119	\param Reader The pixel reader class.
1120	\param Writer The pixel writer class.
1121	\param color_value_t The color value type used to transport a pixel from
1122		   the reader to the writer.
1123	\param inData A pointer to the buffer to be read.
1124	\param inLength The length (in bytes) of the "in" buffer.
1125	\param inBPR The number of bytes per row in the "in" buffer.
1126	\param inRowSkip The number of bytes per row in the "in" buffer serving as
1127		   padding.
1128	\param outData A pointer to the buffer to be written to.
1129	\param outLength The length (in bytes) of the "out" buffer.
1130	\param outOffset The offset (in bytes) relative to \a outData from which
1131		   the function shall start writing.
1132	\param outBPR The number of bytes per row in the "out" buffer.
1133	\param rawOutBPR The number of bytes per row in the "out" buffer actually
1134		   containing bitmap data (i.e. not including the padding).
1135	\param _reader A reader object. The pointer to the data doesn't need to
1136		   be initialized.
1137	\param _writer A writer object. The pointer to the data doesn't need to
1138		   be initialized.
1139	\return \c B_OK, if everything went fine, an error code otherwise.
1140*/
1141template<typename Reader, typename Writer, typename color_value_t>
1142static
1143status_t
1144set_bits_worker(const void *inData, int32 inLength, int32 inBPR,
1145				int32 inRowSkip, void *outData, int32 outLength,
1146				int32 outOffset, int32 outBPR, int32 rawOutBPR,
1147				Reader _reader, Writer _writer)
1148{
1149	status_t error = B_OK;
1150	Reader reader(_reader);
1151	Writer writer(_writer);
1152	reader.SetTo(inData);
1153	writer.SetTo((char*)outData + outOffset);
1154	const char *inEnd = (const char*)inData + inLength
1155						- sizeof(typename Reader::pixel_t);
1156	const char *inLastRow = (const char*)inData + inLength
1157							- (inBPR - inRowSkip);
1158	const char *outEnd = (const char*)outData + outLength
1159						 - sizeof(typename Writer::pixel_t);
1160	char *outRow = (char*)outData + outOffset - outOffset % outBPR;
1161	const char *outRowEnd = outRow + rawOutBPR - sizeof(typename Writer::pixel_t);
1162	while ((const char*)reader.pixels <= inEnd
1163		   && (const char*)writer.pixels <= outEnd) {
1164		// process one row
1165		if ((const char*)reader.pixels <= inLastRow) {
1166			// at least a complete row left
1167			while ((const char*)writer.pixels <= outRowEnd) {
1168				color_value_t color;
1169				reader.Read(color);
1170				writer.Write(color);
1171			}
1172		} else {
1173			// no complete row left
1174			// but maybe the complete end of the first row
1175			while ((const char*)reader.pixels <= inEnd
1176				   && (const char*)writer.pixels <= outRowEnd) {
1177				color_value_t color;
1178				reader.Read(color);
1179				writer.Write(color);
1180			}
1181		}
1182		// must be here, not in the if-branch (end of first row)
1183		outRow += outBPR;
1184		outRowEnd += outBPR;
1185		reader.NextRow(inRowSkip);
1186		writer.SetTo(outRow);
1187	}
1188	return error;
1189}
1190
1191// set_bits_worker_gray1
1192/*!	\brief Worker function that reads bitmap data from one buffer and writes
1193		   it (converted) to another one, which uses color space \c B_GRAY1.
1194	\param Reader The pixel reader class.
1195	\param Writer The pixel writer class.
1196	\param color_value_t The color value type used to transport a pixel from
1197		   the reader to the writer.
1198	\param inData A pointer to the buffer to be read.
1199	\param inLength The length (in bytes) of the "in" buffer.
1200	\param inBPR The number of bytes per row in the "in" buffer.
1201	\param inRowSkip The number of bytes per row in the "in" buffer serving as
1202		   padding.
1203	\param outData A pointer to the buffer to be written to.
1204	\param outLength The length (in bytes) of the "out" buffer.
1205	\param outOffset The offset (in bytes) relative to \a outData from which
1206		   the function shall start writing.
1207	\param outBPR The number of bytes per row in the "out" buffer.
1208	\param width The number of pixels per row in "in" and "out" data.
1209	\param _reader A reader object. The pointer to the data doesn't need to
1210		   be initialized.
1211	\param _writer A writer object. The pointer to the data doesn't need to
1212		   be initialized.
1213	\return \c B_OK, if everything went fine, an error code otherwise.
1214*/
1215template<typename Reader, typename Writer, typename color_value_t>
1216static
1217status_t
1218set_bits_worker_gray1(const void *inData, int32 inLength, int32 inBPR,
1219					  int32 inRowSkip, void *outData, int32 outLength,
1220					  int32 outOffset, int32 outBPR, int32 width,
1221					  Reader _reader, Writer _writer)
1222{
1223	status_t error = B_OK;
1224	Reader reader(_reader);
1225	Writer writer(_writer);
1226	reader.SetTo(inData);
1227	writer.SetTo((char*)outData + outOffset);
1228	const char *inEnd = (const char*)inData + inLength
1229						- sizeof(typename Reader::pixel_t);
1230	const char *inLastRow = (const char*)inData + inLength
1231							- (inBPR - inRowSkip);
1232	const char *outEnd = (const char*)outData + outLength - outBPR;
1233	char *outRow = (char*)outData + outOffset - outOffset % outBPR;
1234	int32 x = max((int32)0,
1235		width - (int32)((char*)outData + outOffset - outRow) * 8) - 1;
1236	while ((const char*)reader.pixels <= inEnd
1237		   && (const char*)writer.pixels <= outEnd) {
1238		// process one row
1239		if ((const char*)reader.pixels <= inLastRow) {
1240			// at least a complete row left
1241			while (x >= 0) {
1242				color_value_t color;
1243				reader.Read(color);
1244				writer.Write(color);
1245				x--;
1246			}
1247		} else {
1248			// no complete row left
1249			// but maybe the complete end of the first row
1250			while ((const char*)reader.pixels <= inEnd && x >= 0) {
1251				color_value_t color;
1252				reader.Read(color);
1253				writer.Write(color);
1254				x--;
1255			}
1256		}
1257		// must be here, not in the if-branch (end of first row)
1258		x = width - 1;
1259		outRow += outBPR;
1260		reader.NextRow(inRowSkip);
1261		writer.SetTo(outRow);
1262	}
1263	return error;
1264}
1265
1266// set_bits
1267/*!	\brief Helper function that reads bitmap data from one buffer and writes
1268		   it (converted) to another one.
1269	\param Reader The pixel reader class.
1270	\param inData A pointer to the buffer to be read.
1271	\param inLength The length (in bytes) of the "in" buffer.
1272	\param inBPR The number of bytes per row in the "in" buffer.
1273	\param inRowSkip The number of bytes per row in the "in" buffer serving as
1274		   padding.
1275	\param outData A pointer to the buffer to be written to.
1276	\param outLength The length (in bytes) of the "out" buffer.
1277	\param outOffset The offset (in bytes) relative to \a outData from which
1278		   the function shall start writing.
1279	\param outBPR The number of bytes per row in the "out" buffer.
1280	\param rawOutBPR The number of bytes per row in the "out" buffer actually
1281		   containing bitmap data (i.e. not including the padding).
1282	\param outColorSpace Color space of the target buffer.
1283	\param width The number of pixels per row in "in" and "out" data.
1284	\param reader A reader object. The pointer to the data doesn't need to
1285		   be initialized.
1286	\param paletteConverter Reference to a PaletteConverter to be used, if
1287		   a conversion from or to \c B_CMAP8 has to be done.
1288	\return \c B_OK, if everything went fine, an error code otherwise.
1289*/
1290template<typename Reader>
1291static
1292status_t
1293set_bits(const void *inData, int32 inLength, int32 inBPR, int32 inRowSkip,
1294		 void *outData, int32 outLength, int32 outOffset, int32 outBPR,
1295		 int32 rawOutBPR, color_space outColorSpace, int32 width,
1296		 Reader reader, const PaletteConverter &paletteConverter)
1297{
1298	status_t error = B_OK;
1299	switch (outColorSpace) {
1300		// supported
1301		case B_RGB32: case B_RGBA32:
1302		{
1303			typedef RGB32Writer<rgb32_pixel> Writer;
1304			typedef typename Reader::preferred_color_value_t color_value_t;
1305			error = set_bits_worker<Reader, Writer, color_value_t>(
1306				inData, inLength, inBPR, inRowSkip, outData, outLength,
1307				outOffset, outBPR, rawOutBPR, reader, Writer(outData));
1308			break;
1309		}
1310		case B_RGB32_BIG: case B_RGBA32_BIG:
1311		{
1312			typedef RGB32Writer<rgb32_big_pixel> Writer;
1313			typedef typename Reader::preferred_color_value_t color_value_t;
1314			error = set_bits_worker<Reader, Writer, color_value_t>(
1315				inData, inLength, inBPR, inRowSkip, outData, outLength,
1316				outOffset, outBPR, rawOutBPR, reader, Writer(outData));
1317			break;
1318		}
1319		case B_RGB24:
1320		{
1321			typedef RGB24Writer<rgb24_pixel> Writer;
1322			typedef typename Reader::preferred_color_value_t color_value_t;
1323			error = set_bits_worker<Reader, Writer, color_value_t>(
1324				inData, inLength, inBPR, inRowSkip, outData, outLength,
1325				outOffset, outBPR, rawOutBPR, reader, Writer(outData));
1326			break;
1327		}
1328		case B_RGB24_BIG:
1329		{
1330			typedef RGB24Writer<rgb24_big_pixel> Writer;
1331			typedef typename Reader::preferred_color_value_t color_value_t;
1332			error = set_bits_worker<Reader, Writer, color_value_t>(
1333				inData, inLength, inBPR, inRowSkip, outData, outLength,
1334				outOffset, outBPR, rawOutBPR, reader, Writer(outData));
1335			break;
1336		}
1337		case B_RGB16:
1338		{
1339			typedef RGB16Writer<rgb16_pixel> Writer;
1340			typedef typename Reader::preferred_color_value_t color_value_t;
1341			error = set_bits_worker<Reader, Writer, color_value_t>(
1342				inData, inLength, inBPR, inRowSkip, outData, outLength,
1343				outOffset, outBPR, rawOutBPR, reader, Writer(outData));
1344			break;
1345		}
1346		case B_RGB16_BIG:
1347		{
1348			typedef RGB16Writer<rgb16_big_pixel> Writer;
1349			typedef typename Reader::preferred_color_value_t color_value_t;
1350			error = set_bits_worker<Reader, Writer, color_value_t>(
1351				inData, inLength, inBPR, inRowSkip, outData, outLength,
1352				outOffset, outBPR, rawOutBPR, reader, Writer(outData));
1353			break;
1354		}
1355		case B_RGB15: case B_RGBA15:
1356		{
1357			typedef RGB15Writer<rgb16_pixel> Writer;
1358			typedef typename Reader::preferred_color_value_t color_value_t;
1359			error = set_bits_worker<Reader, Writer, color_value_t>(
1360				inData, inLength, inBPR, inRowSkip, outData, outLength,
1361				outOffset, outBPR, rawOutBPR, reader, Writer(outData));
1362			break;
1363		}
1364		case B_RGB15_BIG: case B_RGBA15_BIG:
1365		{
1366			typedef RGB15Writer<rgb16_big_pixel> Writer;
1367			typedef typename Reader::preferred_color_value_t color_value_t;
1368			error = set_bits_worker<Reader, Writer, color_value_t>(
1369				inData, inLength, inBPR, inRowSkip, outData, outLength,
1370				outOffset, outBPR, rawOutBPR, reader, Writer(outData));
1371			break;
1372		}
1373		case B_CMAP8:
1374		{
1375			typedef CMAP8Writer Writer;
1376			typedef typename Reader::preferred_color_value_t color_value_t;
1377			error = set_bits_worker<Reader, Writer, color_value_t>(
1378				inData, inLength, inBPR, inRowSkip, outData, outLength,
1379				outOffset, outBPR, rawOutBPR, reader,
1380				Writer(outData, paletteConverter));
1381			break;
1382		}
1383		case B_GRAY8:
1384		{
1385			typedef Gray8Writer Writer;
1386			typedef gray_color_value color_value_t;
1387			error = set_bits_worker<Reader, Writer, color_value_t>(
1388				inData, inLength, inBPR, inRowSkip, outData, outLength,
1389				outOffset, outBPR, rawOutBPR, reader, Writer(outData));
1390			break;
1391		}
1392		case B_GRAY1:
1393		{
1394			typedef Gray1Writer Writer;
1395			typedef gray_color_value color_value_t;
1396			error = set_bits_worker_gray1<Reader, Writer, color_value_t>(
1397				inData, inLength, inBPR, inRowSkip, outData, outLength,
1398				outOffset, outBPR, width, reader, Writer(outData));
1399			break;
1400		}
1401		// unsupported
1402		case B_NO_COLOR_SPACE:
1403		case B_YUV9: case B_YUV12:
1404		case B_UVL32: case B_UVLA32:
1405		case B_LAB32: case B_LABA32:
1406		case B_HSI32: case B_HSIA32:
1407		case B_HSV32: case B_HSVA32:
1408		case B_HLS32: case B_HLSA32:
1409		case B_CMY32: case B_CMYA32: case B_CMYK32:
1410		case B_UVL24: case B_LAB24: case B_HSI24:
1411		case B_HSV24: case B_HLS24: case B_CMY24:
1412		case B_YCbCr422: case B_YUV422:
1413		case B_YCbCr411: case B_YUV411:
1414		case B_YCbCr444: case B_YUV444:
1415		case B_YCbCr420: case B_YUV420:
1416		default:
1417			error = B_BAD_VALUE;
1418			break;
1419	}
1420	return error;
1421}
1422
1423
1424//	#pragma mark - Bitmap
1425
1426
1427/*!	\brief Creates and initializes a BBitmap.
1428	\param bounds The bitmap dimensions.
1429	\param flags Creation flags.
1430	\param colorSpace The bitmap's color space.
1431	\param bytesPerRow The number of bytes per row the bitmap should use.
1432		   \c B_ANY_BYTES_PER_ROW to let the constructor choose an appropriate
1433		   value.
1434	\param screenID ???
1435*/
1436BBitmap::BBitmap(BRect bounds, uint32 flags, color_space colorSpace,
1437		int32 bytesPerRow, screen_id screenID)
1438	: fBasePtr(NULL),
1439	  fSize(0),
1440	  fColorSpace(B_NO_COLOR_SPACE),
1441	  fBounds(0, 0, -1, -1),
1442	  fBytesPerRow(0),
1443	  fServerToken(-1),
1444	  fToken(-1),
1445	  fArea(-1),
1446	  fOrigArea(-1),
1447	  fFlags(0),
1448	  fInitError(B_NO_INIT)
1449{
1450	InitObject(bounds, colorSpace, flags, bytesPerRow, screenID);
1451}
1452
1453
1454/*!	\brief Creates and initializes a BBitmap.
1455	\param bounds The bitmap dimensions.
1456	\param colorSpace The bitmap's color space.
1457	\param acceptsViews \c true, if the bitmap shall accept BViews, i.e. if
1458		   it shall be possible to attach BView to the bitmap and draw into
1459		   it.
1460	\param needsContiguous If \c true a physically contiguous chunk of memory
1461		   will be allocated.
1462*/
1463BBitmap::BBitmap(BRect bounds, color_space colorSpace, bool acceptsViews,
1464		bool needsContiguous)
1465	: fBasePtr(NULL),
1466	  fSize(0),
1467	  fColorSpace(B_NO_COLOR_SPACE),
1468	  fBounds(0, 0, -1, -1),
1469	  fBytesPerRow(0),
1470	  fServerToken(-1),
1471	  fToken(-1),
1472	  fArea(-1),
1473	  fOrigArea(-1),
1474	  fFlags(0),
1475	  fInitError(B_NO_INIT)
1476{
1477	int32 flags = (acceptsViews ? B_BITMAP_ACCEPTS_VIEWS : 0)
1478				| (needsContiguous ? B_BITMAP_IS_CONTIGUOUS : 0);
1479	InitObject(bounds, colorSpace, flags, B_ANY_BYTES_PER_ROW,
1480			   B_MAIN_SCREEN_ID);
1481
1482}
1483
1484
1485/*!	\brief Creates a BBitmap as a clone of another bitmap.
1486	\param source The source bitmap.
1487	\param acceptsViews \c true, if the bitmap shall accept BViews, i.e. if
1488		   it shall be possible to attach BView to the bitmap and draw into
1489		   it.
1490	\param needsContiguous If \c true a physically contiguous chunk of memory
1491		   will be allocated.
1492*/
1493BBitmap::BBitmap(const BBitmap *source, bool acceptsViews,
1494		bool needsContiguous)
1495	: fBasePtr(NULL),
1496	  fSize(0),
1497	  fColorSpace(B_NO_COLOR_SPACE),
1498	  fBounds(0, 0, -1, -1),
1499	  fBytesPerRow(0),
1500	  fServerToken(-1),
1501	  fToken(-1),
1502	  fArea(-1),
1503	  fOrigArea(-1),
1504	  fFlags(0),
1505	  fInitError(B_NO_INIT)
1506{
1507	if (source && source->IsValid()) {
1508		int32 flags = (acceptsViews ? B_BITMAP_ACCEPTS_VIEWS : 0)
1509			| (needsContiguous ? B_BITMAP_IS_CONTIGUOUS : 0);
1510		InitObject(source->Bounds(), source->ColorSpace(), flags,
1511			source->BytesPerRow(), B_MAIN_SCREEN_ID);
1512		if (InitCheck() == B_OK)
1513			memcpy(Bits(), source->Bits(), BytesPerRow());
1514	}
1515}
1516
1517
1518/*!	\brief Frees all resources associated with this object. */
1519BBitmap::~BBitmap()
1520{
1521	CleanUp();
1522}
1523
1524
1525/*!	\brief Unarchives a bitmap from a BMessage.
1526	\param data The archive.
1527*/
1528BBitmap::BBitmap(BMessage *data)
1529	: BArchivable(data),
1530	  fBasePtr(NULL),
1531	  fSize(0),
1532	  fColorSpace(B_NO_COLOR_SPACE),
1533	  fBounds(0, 0, -1, -1),
1534	  fBytesPerRow(0),
1535	  fServerToken(-1),
1536	  fToken(-1),
1537	  fArea(-1),
1538	  fOrigArea(-1),
1539	  fFlags(0),
1540	  fInitError(B_NO_INIT)
1541{
1542	BRect bounds;
1543	data->FindRect("_frame", &bounds);
1544
1545	color_space cspace;
1546	data->FindInt32("_cspace", (int32 *)&cspace);
1547
1548	int32 flags = 0;
1549	data->FindInt32("_bmflags", &flags);
1550
1551	int32 rowbytes = 0;
1552	data->FindInt32("_rowbytes", &rowbytes);
1553
1554flags |= B_BITMAP_NO_SERVER_LINK;
1555flags &= ~B_BITMAP_ACCEPTS_VIEWS;
1556	InitObject(bounds, cspace, flags, rowbytes, B_MAIN_SCREEN_ID);
1557
1558	if (data->HasData("_data", B_RAW_TYPE) && InitCheck() == B_OK) {
1559			ssize_t size = 0;
1560			const void *buffer;
1561			if (data->FindData("_data", B_RAW_TYPE, &buffer, &size) == B_OK)
1562				memcpy(fBasePtr, buffer, size);
1563	}
1564
1565	if (fFlags & B_BITMAP_ACCEPTS_VIEWS) {
1566// 		BArchivable *obj;
1567// 		BMessage message;
1568// 		int i = 0;
1569//
1570// 		while (data->FindMessage("_view", i++, &message) == B_OK) {
1571// 			obj = instantiate_object(&message);
1572// 			BView *view = dynamic_cast<BView *>(obj);
1573//
1574// 			if (view)
1575// 				AddChild(view);
1576// 		}
1577	}
1578}
1579
1580
1581/*!	\brief Instantiates a BBitmap from an archive.
1582	\param data The archive.
1583	\return A bitmap reconstructed from the archive or \c NULL, if an error
1584			occured.
1585*/
1586BArchivable *
1587BBitmap::Instantiate(BMessage *data)
1588{
1589	if (validate_instantiation(data, "BBitmap"))
1590		return new BBitmap(data);
1591
1592	return NULL;
1593}
1594
1595
1596/*!	\brief Archives the BBitmap object.
1597	\param data The archive.
1598	\param deep \c true, if child object shall be archived as well, \c false
1599		   otherwise.
1600	\return \c B_OK, if everything went fine, an error code otherwise.
1601*/
1602status_t
1603BBitmap::Archive(BMessage *data, bool deep) const
1604{
1605	BArchivable::Archive(data, deep);
1606
1607	data->AddRect("_frame", fBounds);
1608	data->AddInt32("_cspace", (int32)fColorSpace);
1609	data->AddInt32("_bmflags", fFlags);
1610	data->AddInt32("_rowbytes", fBytesPerRow);
1611
1612	if (deep) {
1613		if (fFlags & B_BITMAP_ACCEPTS_VIEWS) {
1614//			BMessage views;
1615// 			for (int32 i = 0; i < CountChildren(); i++) {
1616// 				if (ChildAt(i)->Archive(&views, deep))
1617// 					data->AddMessage("_views", &views);
1618// 			}
1619		}
1620		// Note: R5 does not archive the data if B_BITMAP_IS_CONTIGNUOUS is
1621		// true and it does save all formats as B_RAW_TYPE and it does save
1622		// the data even if B_BITMAP_ACCEPTS_VIEWS is set (as opposed to
1623		// the BeBook)
1624
1625		data->AddData("_data", B_RAW_TYPE, fBasePtr, fSize);
1626	}
1627
1628	return B_OK;
1629}
1630
1631
1632/*!	\brief Returns the result from the construction.
1633	\return \c B_OK, if the object is properly initialized, an error code
1634			otherwise.
1635*/
1636status_t
1637BBitmap::InitCheck() const
1638{
1639	return fInitError;
1640}
1641
1642
1643/*!	\brief Returns whether or not the BBitmap object is valid.
1644	\return \c true, if the object is properly initialized, \c false otherwise.
1645*/
1646bool
1647BBitmap::IsValid() const
1648{
1649	return (InitCheck() == B_OK);
1650}
1651
1652
1653status_t
1654BBitmap::LockBits(uint32 *state)
1655{
1656	return B_ERROR;
1657}
1658
1659
1660void
1661BBitmap::UnlockBits()
1662{
1663}
1664
1665
1666/*! \brief Returns the ID of the area the bitmap data reside in.
1667	\return The ID of the area the bitmap data reside in.
1668*/
1669area_id
1670BBitmap::Area() const
1671{
1672	return fArea;
1673}
1674
1675
1676/*!	\brief Returns the pointer to the bitmap data.
1677	\return The pointer to the bitmap data.
1678*/
1679void *
1680BBitmap::Bits() const
1681{
1682	return fBasePtr;
1683}
1684
1685
1686/*!	\brief Returns the size of the bitmap data.
1687	\return The size of the bitmap data.
1688*/
1689int32
1690BBitmap::BitsLength() const
1691{
1692	return fSize;
1693}
1694
1695
1696/*!	\brief Returns the number of bytes used to store a row of bitmap data.
1697	\return The number of bytes used to store a row of bitmap data.
1698*/
1699int32
1700BBitmap::BytesPerRow() const
1701{
1702	return fBytesPerRow;
1703}
1704
1705
1706/*!	\brief Returns the bitmap's color space.
1707	\return The bitmap's color space.
1708*/
1709color_space
1710BBitmap::ColorSpace() const
1711{
1712	return fColorSpace;
1713}
1714
1715
1716/*!	\brief Returns the bitmap's dimensions.
1717	\return The bitmap's dimensions.
1718*/
1719BRect
1720BBitmap::Bounds() const
1721{
1722	return fBounds;
1723}
1724
1725
1726/*!	\brief Assigns data to the bitmap.
1727
1728	Data are directly written into the bitmap's data buffer, being converted
1729	beforehand, if necessary. Some conversions work rather unintuitively:
1730	- \c B_RGB32: The source buffer is supposed to contain \c B_RGB24_BIG
1731	  data without padding at the end of the rows.
1732	- \c B_RGB32: The source buffer is supposed to contain \c B_CMAP8
1733	  data without padding at the end of the rows.
1734	- other color spaces: The source buffer is supposed to contain data
1735	  according to the specified color space being rowwise padded to int32.
1736
1737	The currently supported source/target color spaces are
1738	\c B_RGB{32,24,16,15}[_BIG], \c B_CMAP8 and \c B_GRAY{8,1}.
1739
1740	\note As this methods is apparently a bit strange to use, Haiku introduces
1741		  ImportBits() methods, which are recommended to be used instead.
1742
1743	\param data The data to be copied.
1744	\param length The length in bytes of the data to be copied.
1745	\param offset The offset (in bytes) relative to beginning of the bitmap
1746		   data specifying the position at which the source data shall be
1747		   written.
1748	\param colorSpace Color space of the source data.
1749*/
1750void
1751BBitmap::SetBits(const void *data, int32 length, int32 offset,
1752	color_space colorSpace)
1753{
1754	status_t error = (InitCheck() == B_OK ? B_OK : B_NO_INIT);
1755	// check params
1756	if (error == B_OK && (data == NULL || offset > fSize || length < 0))
1757		error = B_BAD_VALUE;
1758	int32 width = 0;
1759	if (error == B_OK)
1760		width = fBounds.IntegerWidth() + 1;
1761	int32 inBPR = -1;
1762	// tweaks to mimic R5 behavior
1763	if (error == B_OK) {
1764		// B_RGB32 means actually unpadded B_RGB24_BIG
1765		if (colorSpace == B_RGB32) {
1766			colorSpace = B_RGB24_BIG;
1767			inBPR = width * 3;
1768		// If in color space is B_CMAP8, but the bitmap's is another one,
1769		// ignore source data row padding.
1770		} else if (colorSpace == B_CMAP8 && fColorSpace != B_CMAP8)
1771			inBPR = width;
1772
1773		// call the sane method, which does the actual work
1774		error = ImportBits(data, length, inBPR, offset, colorSpace);
1775	}
1776}
1777
1778
1779/*!	\brief Assigns data to the bitmap.
1780
1781	Data are directly written into the bitmap's data buffer, being converted
1782	beforehand, if necessary. Unlike for SetBits(), the meaning of
1783	\a colorSpace is exactly the expected one here, i.e. the source buffer
1784	is supposed to contain data of that color space. \a bpr specifies how
1785	many bytes the source contains per row. \c B_ANY_BYTES_PER_ROW can be
1786	supplied, if standard padding to int32 is used.
1787
1788	The currently supported source/target color spaces are
1789	\c B_RGB{32,24,16,15}[_BIG], \c B_CMAP8 and \c B_GRAY{8,1}.
1790
1791	\param data The data to be copied.
1792	\param length The length in bytes of the data to be copied.
1793	\param bpr The number of bytes per row in the source data.
1794	\param offset The offset (in bytes) relative to beginning of the bitmap
1795		   data specifying the position at which the source data shall be
1796		   written.
1797	\param colorSpace Color space of the source data.
1798	\return
1799	- \c B_OK: Everything went fine.
1800	- \c B_BAD_VALUE: \c NULL \a data, invalid \a bpr or \a offset, or
1801	  unsupported \a colorSpace.
1802*/
1803status_t
1804BBitmap::ImportBits(const void *data, int32 length, int32 bpr, int32 offset,
1805	color_space colorSpace)
1806{
1807	status_t error = (InitCheck() == B_OK ? B_OK : B_NO_INIT);
1808	// check params
1809	if (error == B_OK && (data == NULL || offset > fSize || length < 0))
1810		error = B_BAD_VALUE;
1811	// get BPR
1812	int32 width = 0;
1813	int32 inRowSkip = 0;
1814	if (error == B_OK) {
1815		width = fBounds.IntegerWidth() + 1;
1816		if (bpr < 0)
1817			bpr = get_bytes_per_row(colorSpace, width);
1818		inRowSkip = bpr - get_raw_bytes_per_row(colorSpace, width);
1819		if (inRowSkip < 0)
1820			error = B_BAD_VALUE;
1821	}
1822	if (error != B_OK) {
1823		// catch error case
1824	} else if (colorSpace == fColorSpace && bpr == fBytesPerRow) {
1825		length = min(length, fSize - offset);
1826		memcpy((char*)fBasePtr + offset, data, length);
1827	} else {
1828		// TODO: Retrieve color map from BScreen, when available:
1829		// PaletteConverter paletteConverter(BScreen().ColorMap());
1830		const PaletteConverter &paletteConverter = *palette_converter();
1831		int32 rawOutBPR = get_raw_bytes_per_row(fColorSpace, width);
1832		switch (colorSpace) {
1833			// supported
1834			case B_RGB32: case B_RGBA32:
1835			{
1836				typedef RGB24Reader<rgb32_pixel> Reader;
1837				error = set_bits<Reader>(data, length, bpr, inRowSkip,
1838					fBasePtr, fSize, offset, fBytesPerRow, rawOutBPR,
1839					fColorSpace, width, Reader(data), paletteConverter);
1840				break;
1841			}
1842			case B_RGB32_BIG: case B_RGBA32_BIG:
1843			{
1844				typedef RGB24Reader<rgb32_big_pixel> Reader;
1845				error = set_bits<Reader>(data, length, bpr, inRowSkip,
1846					fBasePtr, fSize, offset, fBytesPerRow, rawOutBPR,
1847					fColorSpace, width, Reader(data), paletteConverter);
1848				break;
1849			}
1850			case B_RGB24:
1851			{
1852				typedef RGB24Reader<rgb24_pixel> Reader;
1853				error = set_bits<Reader>(data, length, bpr, inRowSkip,
1854					fBasePtr, fSize, offset, fBytesPerRow, rawOutBPR,
1855					fColorSpace, width, Reader(data), paletteConverter);
1856				break;
1857			}
1858			case B_RGB24_BIG:
1859			{
1860				typedef RGB24Reader<rgb24_big_pixel> Reader;
1861				error = set_bits<Reader>(data, length, bpr, inRowSkip,
1862					fBasePtr, fSize, offset, fBytesPerRow, rawOutBPR,
1863					fColorSpace, width, Reader(data), paletteConverter);
1864				break;
1865			}
1866			case B_RGB16:
1867			{
1868				typedef RGB16Reader<rgb16_pixel> Reader;
1869				error = set_bits<Reader>(data, length, bpr, inRowSkip,
1870					fBasePtr, fSize, offset, fBytesPerRow, rawOutBPR,
1871					fColorSpace, width, Reader(data), paletteConverter);
1872				break;
1873			}
1874			case B_RGB16_BIG:
1875			{
1876				typedef RGB16Reader<rgb16_big_pixel> Reader;
1877				error = set_bits<Reader>(data, length, bpr, inRowSkip,
1878					fBasePtr, fSize, offset, fBytesPerRow, rawOutBPR,
1879					fColorSpace, width, Reader(data), paletteConverter);
1880				break;
1881			}
1882			case B_RGB15: case B_RGBA15:
1883			{
1884				typedef RGB15Reader<rgb16_pixel> Reader;
1885				error = set_bits<Reader>(data, length, bpr, inRowSkip,
1886					fBasePtr, fSize, offset, fBytesPerRow, rawOutBPR,
1887					fColorSpace, width, Reader(data), paletteConverter);
1888				break;
1889			}
1890			case B_RGB15_BIG: case B_RGBA15_BIG:
1891			{
1892				typedef RGB15Reader<rgb16_big_pixel> Reader;
1893				error = set_bits<Reader>(data, length, bpr, inRowSkip,
1894					fBasePtr, fSize, offset, fBytesPerRow, rawOutBPR,
1895					fColorSpace, width, Reader(data), paletteConverter);
1896				break;
1897			}
1898			case B_CMAP8:
1899			{
1900				typedef CMAP8Reader Reader;
1901				error = set_bits<Reader>(data, length, bpr, inRowSkip,
1902					fBasePtr, fSize, offset, fBytesPerRow, rawOutBPR,
1903					fColorSpace, width, Reader(data, paletteConverter),
1904					paletteConverter);
1905				break;
1906			}
1907			case B_GRAY8:
1908			{
1909				typedef Gray8Reader Reader;
1910				error = set_bits<Reader>(data, length, bpr, inRowSkip,
1911					fBasePtr, fSize, offset, fBytesPerRow, rawOutBPR,
1912					fColorSpace, width, Reader(data), paletteConverter);
1913				break;
1914			}
1915			case B_GRAY1:
1916			{
1917				typedef Gray1Reader Reader;
1918				error = set_bits<Reader>(data, length, bpr, inRowSkip,
1919					fBasePtr, fSize, offset, fBytesPerRow, rawOutBPR,
1920					fColorSpace, width, Reader(data), paletteConverter);
1921				break;
1922			}
1923			// unsupported
1924			case B_NO_COLOR_SPACE:
1925			case B_YUV9: case B_YUV12:
1926			case B_UVL32: case B_UVLA32:
1927			case B_LAB32: case B_LABA32:
1928			case B_HSI32: case B_HSIA32:
1929			case B_HSV32: case B_HSVA32:
1930			case B_HLS32: case B_HLSA32:
1931			case B_CMY32: case B_CMYA32: case B_CMYK32:
1932			case B_UVL24: case B_LAB24: case B_HSI24:
1933			case B_HSV24: case B_HLS24: case B_CMY24:
1934			case B_YCbCr422: case B_YUV422:
1935			case B_YCbCr411: case B_YUV411:
1936			case B_YCbCr444: case B_YUV444:
1937			case B_YCbCr420: case B_YUV420:
1938			default:
1939				error = B_BAD_VALUE;
1940				break;
1941		}
1942	}
1943	return error;
1944}
1945
1946
1947/*!	\briefly Assigns another bitmap's data to this bitmap.
1948
1949	The supplied bitmap must have the exactly same dimensions as this bitmap.
1950	Its data are converted to the color space of this bitmap.
1951
1952	The currently supported source/target color spaces are
1953	\c B_RGB{32,24,16,15}[_BIG], \c B_CMAP8 and \c B_GRAY{8,1}.
1954
1955	\param bitmap The source bitmap.
1956	\return
1957	- \c B_OK: Everything went fine.
1958	- \c B_BAD_VALUE: \c NULL \a bitmap, or \a bitmap has other dimensions,
1959	  or the conversion from or to one of the color spaces is not supported.
1960*/
1961status_t
1962BBitmap::ImportBits(const BBitmap *bitmap)
1963{
1964	status_t error = (InitCheck() == B_OK ? B_OK : B_NO_INIT);
1965	// check param
1966	if (error == B_OK && bitmap == NULL)
1967		error = B_BAD_VALUE;
1968	if (error == B_OK && bitmap->InitCheck() != B_OK)
1969		error = B_BAD_VALUE;
1970	if (error == B_OK && bitmap->Bounds() != fBounds)
1971		error = B_BAD_VALUE;
1972	// set bits
1973	if (error == B_OK) {
1974		error = ImportBits(bitmap->Bits(), bitmap->BitsLength(),
1975			bitmap->BytesPerRow(), 0, bitmap->ColorSpace());
1976	}
1977	return error;
1978}
1979
1980
1981status_t
1982BBitmap::GetOverlayRestrictions(overlay_restrictions *restrictions) const
1983{
1984	// TODO: Implement
1985	return B_ERROR;
1986}
1987
1988
1989status_t
1990BBitmap::Perform(perform_code d, void *arg)
1991{
1992	return BArchivable::Perform(d, arg);
1993}
1994
1995
1996// FBC
1997void BBitmap::_ReservedBitmap1() {}
1998void BBitmap::_ReservedBitmap2() {}
1999void BBitmap::_ReservedBitmap3() {}
2000
2001
2002/*!	\brief Privatized copy constructor to prevent usage.
2003*/
2004BBitmap::BBitmap(const BBitmap &)
2005{
2006}
2007
2008
2009/*!	\brief Privatized assignment operator to prevent usage.
2010*/
2011BBitmap &
2012BBitmap::operator=(const BBitmap &)
2013{
2014	return *this;
2015}
2016
2017
2018char *
2019BBitmap::get_shared_pointer() const
2020{
2021	return NULL;	// not implemented
2022}
2023
2024
2025int32
2026BBitmap::get_server_token() const
2027{
2028	return fServerToken;
2029}
2030
2031
2032/*!	\brief Initializes the bitmap.
2033	\param bounds The bitmap dimensions.
2034	\param colorSpace The bitmap's color space.
2035	\param flags Creation flags.
2036	\param bytesPerRow The number of bytes per row the bitmap should use.
2037		   \c B_ANY_BYTES_PER_ROW to let the constructor choose an appropriate
2038		   value.
2039	\param screenID ???
2040*/
2041void
2042BBitmap::InitObject(BRect bounds, color_space colorSpace, uint32 flags,
2043	int32 bytesPerRow, screen_id screenID)
2044{
2045//printf("BBitmap::InitObject(bounds: BRect(%.1f, %.1f, %.1f, %.1f), format: %ld, flags: %ld, bpr: %ld\n",
2046//	   bounds.left, bounds.top, bounds.right, bounds.bottom, colorSpace, flags, bytesPerRow);
2047
2048	// TODO: Hanlde setting up the offscreen window if we're such a bitmap!
2049
2050	// TODO: Should we handle rounding of the "bounds" here? How does R5 behave?
2051
2052	status_t error = B_OK;
2053
2054//#ifdef RUN_WITHOUT_APP_SERVER
2055	flags |= B_BITMAP_NO_SERVER_LINK;
2056//#endif	// RUN_WITHOUT_APP_SERVER
2057flags &= ~B_BITMAP_ACCEPTS_VIEWS;
2058
2059	CleanUp();
2060
2061	// check params
2062	if (!bounds.IsValid() || !bitmaps_support_space(colorSpace, NULL))
2063		error = B_BAD_VALUE;
2064	if (error == B_OK) {
2065		int32 bpr = get_bytes_per_row(colorSpace, bounds.IntegerWidth() + 1);
2066		if (bytesPerRow < 0)
2067			bytesPerRow = bpr;
2068		else if (bytesPerRow < bpr)
2069// NOTE: How does R5 behave?
2070			error = B_BAD_VALUE;
2071	}
2072	// allocate the bitmap buffer
2073	if (error == B_OK) {
2074		// NOTE: Maybe the code would look more robust if the
2075		// "size" was not calculated here when we ask the server
2076		// to allocate the bitmap. -Stephan
2077		int32 size = bytesPerRow * (bounds.IntegerHeight() + 1);
2078
2079		if (flags & B_BITMAP_NO_SERVER_LINK) {
2080			fBasePtr = malloc(size);
2081			if (fBasePtr) {
2082				fSize = size;
2083				fColorSpace = colorSpace;
2084				fBounds = bounds;
2085				fBytesPerRow = bytesPerRow;
2086				fFlags = flags;
2087			} else
2088				error = B_NO_MEMORY;
2089		} else {
2090// 			// Ask the server (via our owning application) to create a bitmap.
2091// 			BPrivate::AppServerLink link;
2092//
2093// 			// Attach Data:
2094// 			// 1) BRect bounds
2095// 			// 2) color_space space
2096// 			// 3) int32 bitmap_flags
2097// 			// 4) int32 bytes_per_row
2098// 			// 5) int32 screen_id::id
2099// 			link.StartMessage(AS_CREATE_BITMAP);
2100// 			link.Attach<BRect>(bounds);
2101// 			link.Attach<color_space>(colorSpace);
2102// 			link.Attach<int32>((int32)flags);
2103// 			link.Attach<int32>(bytesPerRow);
2104// 			link.Attach<int32>(screenID.id);
2105//
2106// 			// Reply Code: SERVER_TRUE
2107// 			// Reply Data:
2108// 			//	1) int32 server token
2109// 			//	2) area_id id of the area in which the bitmap data resides
2110// 			//	3) int32 area pointer offset used to calculate fBasePtr
2111//
2112// 			// alternatively, if something went wrong
2113// 			// Reply Code: SERVER_FALSE
2114// 			// Reply Data:
2115// 			//		None
2116// 			int32 code = SERVER_FALSE;
2117// 			error = link.FlushWithReply(code);
2118//
2119// 			if (error >= B_OK) {
2120// 				// *communication* with server successful
2121// 				if (code == SERVER_TRUE) {
2122// 					// server side success
2123// 					// Get token
2124// 					area_id bmparea;
2125// 					int32 areaoffset;
2126//
2127// 					link.Read<int32>(&fServerToken);
2128// 					link.Read<area_id>(&bmparea);
2129// 					link.Read<int32>(&areaoffset);
2130//
2131// 					// Get the area in which the data resides
2132// 					fArea = clone_area("shared bitmap area",
2133// 									   (void**)&fBasePtr,
2134// 									   B_ANY_ADDRESS,
2135// 									   B_READ_AREA | B_WRITE_AREA,
2136// 									   bmparea);
2137//
2138// 					// Jump to the location in the area
2139// 					fBasePtr = (int8*)fBasePtr + areaoffset;
2140//
2141// 					fSize = size;
2142// 					fColorSpace = colorSpace;
2143// 					fBounds = bounds;
2144// 					fBytesPerRow = bytesPerRow;
2145// 					fFlags = flags;
2146// 				} else {
2147// 					// server side error, we assume:
2148// 					error = B_NO_MEMORY;
2149// 				}
2150// 			}
2151// 			// NOTE: not "else" to handle B_NO_MEMORY on server side!
2152// 			if (error < B_OK) {
2153// 				fBasePtr = NULL;
2154// 				fServerToken = -1;
2155// 				fArea = -1;
2156// 				// NOTE: why not "0" in case of error?
2157// 				fFlags = flags;
2158// 			}
2159		}
2160//		fWindow = NULL;
2161		fToken = -1;
2162		fOrigArea = -1;
2163	}
2164
2165	fInitError = error;
2166	// TODO: on success, handle clearing to white if the flags say so. Needs to be
2167	// dependent on color space.
2168
2169	if (fInitError == B_OK) {
2170		if (flags & B_BITMAP_ACCEPTS_VIEWS) {
2171// 			fWindow = new BWindow(Bounds(), fServerToken);
2172// 			// A BWindow starts life locked and is unlocked
2173// 			// in Show(), but this window is never shown and
2174// 			// it's message loop is never started.
2175// 			fWindow->Unlock();
2176		}
2177	}
2178}
2179
2180
2181/*!	\brief Cleans up any memory allocated by the bitmap or
2182		   informs the server to do so.
2183*/
2184void
2185BBitmap::CleanUp()
2186{
2187	if (fBasePtr) {
2188		if (fFlags & B_BITMAP_NO_SERVER_LINK) {
2189			free(fBasePtr);
2190		} else {
2191// 			BPrivate::AppServerLink link;
2192// 			// AS_DELETE_BITMAP:
2193// 			// Attached Data:
2194// 			//	1) int32 server token
2195//
2196// 			// Reply Code: SERVER_TRUE if successful,
2197// 			//			   SERVER_FALSE if the buffer was already deleted
2198// 			// Reply Data: none
2199// //			status_t freestat;
2200// 			int32 code = SERVER_FALSE;
2201// 			link.StartMessage(AS_DELETE_BITMAP);
2202// 			link.Attach<int32>(fServerToken);
2203// 			link.FlushWithReply(code);
2204// 			if (code == SERVER_FALSE) {
2205// 				// TODO: Find out if "SERVER_FALSE if the buffer
2206// 				// was already deleted" is true. If not, maybe we
2207// 				// need to take additional action.
2208// 			}
2209// 			fArea = -1;
2210// 			fServerToken = -1;
2211		}
2212		fBasePtr = NULL;
2213	}
2214}
2215
2216
2217void
2218BBitmap::AssertPtr()
2219{
2220}
2221
2222