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