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