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