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