xref: /haiku/src/kits/interface/Icon.cpp (revision ed24eb5ff12640d052171c6a7feba37fab8a75d1)
1 /*
2  * Copyright 2006-2013, Haiku, Inc.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Stephan Aßmus, superstippi@gmx.de
7  *		Ingo Weinhold, ingo_weinhold@gmx.de
8  */
9 
10 
11 #include <Icon.h>
12 
13 #include <string.h>
14 
15 #include <new>
16 
17 #include <Bitmap.h>
18 
19 #include <AutoDeleter.h>
20 
21 
22 namespace BPrivate {
23 
24 
25 BIcon::BIcon()
26 	:
27 	fEnabledBitmaps(8, true),
28 	fDisabledBitmaps(8, true)
29 {
30 }
31 
32 
33 BIcon::~BIcon()
34 {
35 }
36 
37 
38 status_t
39 BIcon::SetTo(const BBitmap* bitmap, uint32 flags)
40 {
41 	if (!bitmap->IsValid())
42 		return B_BAD_VALUE;
43 
44 	DeleteBitmaps();
45 
46 	// check the color space
47 	bool hasAlpha = false;
48 	bool canUseForMakeBitmaps = false;
49 
50 	switch (bitmap->ColorSpace()) {
51 		case B_RGBA32:
52 		case B_RGBA32_BIG:
53 			hasAlpha = true;
54 			// fall through
55 		case B_RGB32:
56 		case B_RGB32_BIG:
57 			canUseForMakeBitmaps = true;
58 			break;
59 
60 		case B_UVLA32:
61 		case B_LABA32:
62 		case B_HSIA32:
63 		case B_HSVA32:
64 		case B_HLSA32:
65 		case B_CMYA32:
66 		case B_RGBA15:
67 		case B_RGBA15_BIG:
68 		case B_CMAP8:
69 			hasAlpha = true;
70 			break;
71 
72 		default:
73 			break;
74 	}
75 
76 	BBitmap* trimmedBitmap = NULL;
77 
78 	// trim the bitmap, if requested and the bitmap actually has alpha
79 	status_t error;
80 	if ((flags & (B_TRIM_ICON_BITMAP | B_TRIM_ICON_BITMAP_KEEP_ASPECT)) != 0
81 		&& hasAlpha) {
82 		if (bitmap->ColorSpace() == B_RGBA32) {
83 			error = _TrimBitmap(bitmap,
84 				(flags & B_TRIM_ICON_BITMAP_KEEP_ASPECT) != 0, trimmedBitmap);
85 		} else {
86 			BBitmap* rgb32Bitmap = _ConvertToRGB32(bitmap, true);
87 			if (rgb32Bitmap != NULL) {
88 				error = _TrimBitmap(rgb32Bitmap,
89 					(flags & B_TRIM_ICON_BITMAP_KEEP_ASPECT) != 0,
90 					trimmedBitmap);
91 				delete rgb32Bitmap;
92 			} else
93 				error = B_NO_MEMORY;
94 		}
95 
96 		if (error != B_OK)
97 			return error;
98 
99 		bitmap = trimmedBitmap;
100 		canUseForMakeBitmaps = true;
101 	}
102 
103 	// create the bitmaps
104 	if (canUseForMakeBitmaps) {
105 		error = _MakeBitmaps(bitmap, flags);
106 	} else {
107 		if (BBitmap* rgb32Bitmap = _ConvertToRGB32(bitmap, true)) {
108 			error = _MakeBitmaps(rgb32Bitmap, flags);
109 			delete rgb32Bitmap;
110 		} else
111 			error = B_NO_MEMORY;
112 	}
113 
114 	delete trimmedBitmap;
115 
116 	return error;
117 }
118 
119 
120 bool
121 BIcon::SetBitmap(BBitmap* bitmap, uint32 which)
122 {
123 	BitmapList& list = (which & B_DISABLED_ICON_BITMAP) == 0
124 		? fEnabledBitmaps : fDisabledBitmaps;
125 	which &= ~uint32(B_DISABLED_ICON_BITMAP);
126 
127 	int32 count = list.CountItems();
128 	if ((int32)which < count) {
129 		list.ReplaceItem(which, bitmap);
130 		return true;
131 	}
132 
133 	while (list.CountItems() < (int32)which) {
134 		if (!list.AddItem((BBitmap*)NULL))
135 			return false;
136 	}
137 
138 	return list.AddItem(bitmap);
139 }
140 
141 
142 BBitmap*
143 BIcon::Bitmap(uint32 which) const
144 {
145 	const BitmapList& list = (which & B_DISABLED_ICON_BITMAP) == 0
146 		? fEnabledBitmaps : fDisabledBitmaps;
147 	return list.ItemAt(which & ~uint32(B_DISABLED_ICON_BITMAP));
148 }
149 
150 
151 BBitmap*
152 BIcon::CreateBitmap(const BRect& bounds, color_space colorSpace, uint32 which)
153 {
154 	BBitmap* bitmap = new(std::nothrow) BBitmap(bounds, colorSpace);
155 	if (bitmap == NULL || !bitmap->IsValid() || !SetBitmap(bitmap, which)) {
156 		delete bitmap;
157 		return NULL;
158 	}
159 
160 	return bitmap;
161 }
162 
163 
164 status_t
165 BIcon::SetExternalBitmap(const BBitmap* bitmap, uint32 which, uint32 flags)
166 {
167 	BBitmap* ourBitmap = NULL;
168 	if (bitmap != NULL) {
169 		if (!bitmap->IsValid())
170 			return B_BAD_VALUE;
171 
172 		if ((flags & B_KEEP_ICON_BITMAP) != 0) {
173 			ourBitmap = const_cast<BBitmap*>(bitmap);
174 		} else {
175 			ourBitmap = _ConvertToRGB32(bitmap);
176 			if (ourBitmap == NULL)
177 				return B_NO_MEMORY;
178 		}
179 	}
180 
181 	if (!SetBitmap(ourBitmap, which)) {
182 		if (ourBitmap != bitmap)
183 			delete ourBitmap;
184 		return B_NO_MEMORY;
185 	}
186 
187 	return B_OK;
188 }
189 
190 
191 BBitmap*
192 BIcon::CopyBitmap(const BBitmap& bitmapToClone, uint32 which)
193 {
194 	BBitmap* bitmap = new(std::nothrow) BBitmap(bitmapToClone);
195 	if (bitmap == NULL || !bitmap->IsValid() || !SetBitmap(bitmap, which)) {
196 		delete bitmap;
197 		return NULL;
198 	}
199 
200 	return bitmap;
201 }
202 
203 
204 void
205 BIcon::DeleteBitmaps()
206 {
207 	fEnabledBitmaps.MakeEmpty(true);
208 	fDisabledBitmaps.MakeEmpty(true);
209 }
210 
211 
212 /*static*/ status_t
213 BIcon::UpdateIcon(const BBitmap* bitmap, uint32 flags, BIcon*& _icon)
214 {
215 	if (bitmap == NULL) {
216 		delete _icon;
217 		_icon = NULL;
218 		return B_OK;
219 	}
220 
221 	BIcon* icon = new(std::nothrow) BIcon;
222 	if (icon == NULL)
223 		return B_NO_MEMORY;
224 
225 	status_t error = icon->SetTo(bitmap, flags);
226 	if (error != B_OK) {
227 		delete icon;
228 		return error;
229 	}
230 
231 	_icon = icon;
232 	return B_OK;
233 }
234 
235 
236 /*static*/ status_t
237 BIcon::SetIconBitmap(const BBitmap* bitmap, uint32 which, uint32 flags,
238 	BIcon*& _icon)
239 {
240 	bool newIcon = false;
241 	if (_icon == NULL) {
242 		if (bitmap == NULL)
243 			return B_OK;
244 
245 		_icon = new(std::nothrow) BIcon;
246 		if (_icon == NULL)
247 			return B_NO_MEMORY;
248 		newIcon = true;
249 	}
250 
251 	status_t error = _icon->SetExternalBitmap(bitmap, which, flags);
252 	if (error != B_OK) {
253 		if (newIcon) {
254 			delete _icon;
255 			_icon = NULL;
256 		}
257 		return error;
258 	}
259 
260 	return B_OK;
261 }
262 
263 
264 /*static*/ BBitmap*
265 BIcon::_ConvertToRGB32(const BBitmap* bitmap, bool noAppServerLink)
266 {
267 	BBitmap* rgb32Bitmap = new(std::nothrow) BBitmap(bitmap->Bounds(),
268 		noAppServerLink ? B_BITMAP_NO_SERVER_LINK : 0, B_RGBA32);
269 	if (rgb32Bitmap == NULL)
270 		return NULL;
271 
272 	if (!rgb32Bitmap->IsValid() || rgb32Bitmap->ImportBits(bitmap)!= B_OK) {
273 		delete rgb32Bitmap;
274 		return NULL;
275 	}
276 
277 	return rgb32Bitmap;
278 }
279 
280 
281 /*static*/ status_t
282 BIcon::_TrimBitmap(const BBitmap* bitmap, bool keepAspect,
283 	BBitmap*& _trimmedBitmap)
284 {
285 	if (bitmap == NULL || !bitmap->IsValid()
286 		|| bitmap->ColorSpace() != B_RGBA32) {
287 		return B_BAD_VALUE;
288 	}
289 
290 	uint8* bits = (uint8*)bitmap->Bits();
291 	uint32 bpr = bitmap->BytesPerRow();
292 	uint32 width = bitmap->Bounds().IntegerWidth() + 1;
293 	uint32 height = bitmap->Bounds().IntegerHeight() + 1;
294 	BRect trimmed(INT32_MAX, INT32_MAX, INT32_MIN, INT32_MIN);
295 
296 	for (uint32 y = 0; y < height; y++) {
297 		uint8* b = bits + 3;
298 		bool rowHasAlpha = false;
299 		for (uint32 x = 0; x < width; x++) {
300 			if (*b) {
301 				rowHasAlpha = true;
302 				if (x < trimmed.left)
303 					trimmed.left = x;
304 				if (x > trimmed.right)
305 					trimmed.right = x;
306 			}
307 			b += 4;
308 		}
309 		if (rowHasAlpha) {
310 			if (y < trimmed.top)
311 				trimmed.top = y;
312 			if (y > trimmed.bottom)
313 				trimmed.bottom = y;
314 		}
315 		bits += bpr;
316 	}
317 
318 	if (!trimmed.IsValid())
319 		return B_BAD_VALUE;
320 
321 	if (keepAspect) {
322 		float minInset = trimmed.left;
323 		minInset = min_c(minInset, trimmed.top);
324 		minInset = min_c(minInset, bitmap->Bounds().right - trimmed.right);
325 		minInset = min_c(minInset, bitmap->Bounds().bottom - trimmed.bottom);
326 		trimmed = bitmap->Bounds().InsetByCopy(minInset, minInset);
327 	}
328 	trimmed = trimmed & bitmap->Bounds();
329 
330 	BBitmap* trimmedBitmap = new(std::nothrow) BBitmap(
331 		trimmed.OffsetToCopy(B_ORIGIN), B_BITMAP_NO_SERVER_LINK, B_RGBA32);
332 	if (trimmedBitmap == NULL)
333 		return B_NO_MEMORY;
334 
335 	bits = (uint8*)bitmap->Bits();
336 	bits += 4 * (int32)trimmed.left + bpr * (int32)trimmed.top;
337 	uint8* dst = (uint8*)trimmedBitmap->Bits();
338 	uint32 trimmedWidth = trimmedBitmap->Bounds().IntegerWidth() + 1;
339 	uint32 trimmedHeight = trimmedBitmap->Bounds().IntegerHeight() + 1;
340 	uint32 trimmedBPR = trimmedBitmap->BytesPerRow();
341 	for (uint32 y = 0; y < trimmedHeight; y++) {
342 		memcpy(dst, bits, trimmedWidth * 4);
343 		dst += trimmedBPR;
344 		bits += bpr;
345 	}
346 
347 	_trimmedBitmap = trimmedBitmap;
348 	return B_OK;
349 }
350 
351 
352 status_t
353 BIcon::_MakeBitmaps(const BBitmap* bitmap, uint32 flags)
354 {
355 	// make our own versions of the bitmap
356 	BRect b(bitmap->Bounds());
357 
358 	color_space format = bitmap->ColorSpace();
359 	BBitmap* normalBitmap = CreateBitmap(b, format, B_INACTIVE_ICON_BITMAP);
360 	if (normalBitmap == NULL)
361 		return B_NO_MEMORY;
362 
363 	BBitmap* disabledBitmap = NULL;
364 	if ((flags & B_CREATE_DISABLED_ICON_BITMAPS) != 0) {
365 		disabledBitmap = CreateBitmap(b, format,
366 			B_INACTIVE_ICON_BITMAP | B_DISABLED_ICON_BITMAP);
367 		if (disabledBitmap == NULL)
368 			return B_NO_MEMORY;
369 	}
370 
371 	BBitmap* clickedBitmap = NULL;
372 	if ((flags & (B_CREATE_ACTIVE_ICON_BITMAP
373 			| B_CREATE_PARTIALLY_ACTIVE_ICON_BITMAP)) != 0) {
374 		clickedBitmap = CreateBitmap(b, format, B_ACTIVE_ICON_BITMAP);
375 		if (clickedBitmap == NULL)
376 			return B_NO_MEMORY;
377 	}
378 
379 	BBitmap* disabledClickedBitmap = NULL;
380 	if (disabledBitmap != NULL && clickedBitmap != NULL) {
381 		disabledClickedBitmap = CreateBitmap(b, format,
382 			B_ACTIVE_ICON_BITMAP | B_DISABLED_ICON_BITMAP);
383 		if (disabledClickedBitmap == NULL)
384 			return B_NO_MEMORY;
385 	}
386 
387 	// copy bitmaps from file bitmap
388 	uint8* nBits = normalBitmap != NULL ? (uint8*)normalBitmap->Bits() : NULL;
389 	uint8* dBits = disabledBitmap != NULL
390 		? (uint8*)disabledBitmap->Bits() : NULL;
391 	uint8* cBits = clickedBitmap != NULL ? (uint8*)clickedBitmap->Bits() : NULL;
392 	uint8* dcBits = disabledClickedBitmap != NULL
393 		? (uint8*)disabledClickedBitmap->Bits() : NULL;
394 	uint8* fBits = (uint8*)bitmap->Bits();
395 	int32 nbpr = normalBitmap->BytesPerRow();
396 	int32 fbpr = bitmap->BytesPerRow();
397 	int32 pixels = b.IntegerWidth() + 1;
398 	int32 lines = b.IntegerHeight() + 1;
399 	if (format == B_RGB32) {
400 		// nontransparent version
401 
402 		// iterate over color components
403 		for (int32 y = 0; y < lines; y++) {
404 			for (int32 x = 0; x < pixels; x++) {
405 				int32 nOffset = 4 * x;
406 				int32 fOffset = 4 * x;
407 				nBits[nOffset + 0] = fBits[fOffset + 0];
408 				nBits[nOffset + 1] = fBits[fOffset + 1];
409 				nBits[nOffset + 2] = fBits[fOffset + 2];
410 				nBits[nOffset + 3] = 255;
411 
412 				// clicked bits are darker (lame method...)
413 				if (cBits != NULL) {
414 					cBits[nOffset + 0] = uint8((float)nBits[nOffset + 0] * 0.8);
415 					cBits[nOffset + 1] = uint8((float)nBits[nOffset + 1] * 0.8);
416 					cBits[nOffset + 2] = uint8((float)nBits[nOffset + 2] * 0.8);
417 					cBits[nOffset + 3] = 255;
418 				}
419 
420 				// disabled bits have less contrast (lame method...)
421 				if (dBits != NULL) {
422 					uint8 grey = 216;
423 					float dist = (nBits[nOffset + 0] - grey) * 0.4;
424 					dBits[nOffset + 0] = (uint8)(grey + dist);
425 					dist = (nBits[nOffset + 1] - grey) * 0.4;
426 					dBits[nOffset + 1] = (uint8)(grey + dist);
427 					dist = (nBits[nOffset + 2] - grey) * 0.4;
428 					dBits[nOffset + 2] = (uint8)(grey + dist);
429 					dBits[nOffset + 3] = 255;
430 				}
431 
432 				// disabled bits have less contrast (lame method...)
433 				if (dcBits != NULL) {
434 					uint8 grey = 188;
435 					float dist = (nBits[nOffset + 0] - grey) * 0.4;
436 					dcBits[nOffset + 0] = (uint8)(grey + dist);
437 					dist = (nBits[nOffset + 1] - grey) * 0.4;
438 					dcBits[nOffset + 1] = (uint8)(grey + dist);
439 					dist = (nBits[nOffset + 2] - grey) * 0.4;
440 					dcBits[nOffset + 2] = (uint8)(grey + dist);
441 					dcBits[nOffset + 3] = 255;
442 				}
443 			}
444 			fBits += fbpr;
445 			nBits += nbpr;
446 			if (cBits != NULL)
447 				cBits += nbpr;
448 			if (dBits != NULL)
449 				dBits += nbpr;
450 			if (dcBits != NULL)
451 				dcBits += nbpr;
452 		}
453 	} else if (format == B_RGB32_BIG) {
454 		// nontransparent version
455 
456 		// iterate over color components
457 		for (int32 y = 0; y < lines; y++) {
458 			for (int32 x = 0; x < pixels; x++) {
459 				int32 nOffset = 4 * x;
460 				int32 fOffset = 4 * x;
461 				nBits[nOffset + 3] = fBits[fOffset + 3];
462 				nBits[nOffset + 2] = fBits[fOffset + 2];
463 				nBits[nOffset + 1] = fBits[fOffset + 1];
464 				nBits[nOffset + 0] = 255;
465 
466 				// clicked bits are darker (lame method...)
467 				if (cBits != NULL) {
468 					cBits[nOffset + 3] = uint8((float)nBits[nOffset + 3] * 0.8);
469 					cBits[nOffset + 2] = uint8((float)nBits[nOffset + 2] * 0.8);
470 					cBits[nOffset + 1] = uint8((float)nBits[nOffset + 1] * 0.8);
471 					cBits[nOffset + 0] = 255;
472 				}
473 
474 				// disabled bits have less contrast (lame method...)
475 				if (dBits != NULL) {
476 					uint8 grey = 216;
477 					float dist = (nBits[nOffset + 3] - grey) * 0.4;
478 					dBits[nOffset + 3] = (uint8)(grey + dist);
479 					dist = (nBits[nOffset + 2] - grey) * 0.4;
480 					dBits[nOffset + 2] = (uint8)(grey + dist);
481 					dist = (nBits[nOffset + 1] - grey) * 0.4;
482 					dBits[nOffset + 1] = (uint8)(grey + dist);
483 					dBits[nOffset + 0] = 255;
484 				}
485 
486 				// disabled bits have less contrast (lame method...)
487 				if (dcBits != NULL) {
488 					uint8 grey = 188;
489 					float dist = (nBits[nOffset + 3] - grey) * 0.4;
490 					dcBits[nOffset + 3] = (uint8)(grey + dist);
491 					dist = (nBits[nOffset + 2] - grey) * 0.4;
492 					dcBits[nOffset + 2] = (uint8)(grey + dist);
493 					dist = (nBits[nOffset + 1] - grey) * 0.4;
494 					dcBits[nOffset + 1] = (uint8)(grey + dist);
495 					dcBits[nOffset + 0] = 255;
496 				}
497 			}
498 			fBits += fbpr;
499 			nBits += nbpr;
500 			if (cBits != NULL)
501 				cBits += nbpr;
502 			if (dBits != NULL)
503 				dBits += nbpr;
504 			if (dcBits != NULL)
505 				dcBits += nbpr;
506 		}
507 	} else if (format == B_RGBA32) {
508 		// transparent version
509 
510 		// iterate over color components
511 		for (int32 y = 0; y < lines; y++) {
512 			for (int32 x = 0; x < pixels; x++) {
513 				int32 nOffset = 4 * x;
514 				int32 fOffset = 4 * x;
515 				nBits[nOffset + 0] = fBits[fOffset + 0];
516 				nBits[nOffset + 1] = fBits[fOffset + 1];
517 				nBits[nOffset + 2] = fBits[fOffset + 2];
518 				nBits[nOffset + 3] = fBits[fOffset + 3];
519 
520 				// clicked bits are darker (lame method...)
521 				if (cBits != NULL) {
522 					cBits[nOffset + 0] = (uint8)(nBits[nOffset + 0] * 0.8);
523 					cBits[nOffset + 1] = (uint8)(nBits[nOffset + 1] * 0.8);
524 					cBits[nOffset + 2] = (uint8)(nBits[nOffset + 2] * 0.8);
525 					cBits[nOffset + 3] = fBits[fOffset + 3];
526 				}
527 
528 				// disabled bits have less opacity
529 				if (dBits != NULL) {
530 					uint8 grey = ((uint16)nBits[nOffset + 0] * 10
531 					    + nBits[nOffset + 1] * 60
532 						+ nBits[nOffset + 2] * 30) / 100;
533 					float dist = (nBits[nOffset + 0] - grey) * 0.3;
534 					dBits[nOffset + 0] = (uint8)(grey + dist);
535 					dist = (nBits[nOffset + 1] - grey) * 0.3;
536 					dBits[nOffset + 1] = (uint8)(grey + dist);
537 					dist = (nBits[nOffset + 2] - grey) * 0.3;
538 					dBits[nOffset + 2] = (uint8)(grey + dist);
539 					dBits[nOffset + 3] = (uint8)(fBits[fOffset + 3] * 0.3);
540 				}
541 
542 				// disabled bits have less contrast (lame method...)
543 				if (dcBits != NULL) {
544 					dcBits[nOffset + 0] = (uint8)(dBits[nOffset + 0] * 0.8);
545 					dcBits[nOffset + 1] = (uint8)(dBits[nOffset + 1] * 0.8);
546 					dcBits[nOffset + 2] = (uint8)(dBits[nOffset + 2] * 0.8);
547 					dcBits[nOffset + 3] = (uint8)(fBits[fOffset + 3] * 0.3);
548 				}
549 			}
550 			fBits += fbpr;
551 			nBits += nbpr;
552 			if (cBits != NULL)
553 				cBits += nbpr;
554 			if (dBits != NULL)
555 				dBits += nbpr;
556 			if (dcBits != NULL)
557 				dcBits += nbpr;
558 		}
559 	} else if (format == B_RGBA32_BIG) {
560 		// transparent version
561 
562 		// iterate over color components
563 		for (int32 y = 0; y < lines; y++) {
564 			for (int32 x = 0; x < pixels; x++) {
565 				int32 nOffset = 4 * x;
566 				int32 fOffset = 4 * x;
567 				nBits[nOffset + 3] = fBits[fOffset + 3];
568 				nBits[nOffset + 2] = fBits[fOffset + 2];
569 				nBits[nOffset + 1] = fBits[fOffset + 1];
570 				nBits[nOffset + 0] = fBits[fOffset + 0];
571 
572 				// clicked bits are darker (lame method...)
573 				if (cBits != NULL) {
574 					cBits[nOffset + 3] = (uint8)(nBits[nOffset + 3] * 0.8);
575 					cBits[nOffset + 2] = (uint8)(nBits[nOffset + 2] * 0.8);
576 					cBits[nOffset + 1] = (uint8)(nBits[nOffset + 1] * 0.8);
577 					cBits[nOffset + 0] = fBits[fOffset + 0];
578 				}
579 
580 				// disabled bits have less opacity
581 				if (dBits != NULL) {
582 					uint8 grey = ((uint16)nBits[nOffset + 3] * 10
583 					    + nBits[nOffset + 2] * 60
584 						+ nBits[nOffset + 1] * 30) / 100;
585 					float dist = (nBits[nOffset + 3] - grey) * 0.3;
586 					dBits[nOffset + 3] = (uint8)(grey + dist);
587 					dist = (nBits[nOffset + 2] - grey) * 0.3;
588 					dBits[nOffset + 2] = (uint8)(grey + dist);
589 					dist = (nBits[nOffset + 1] - grey) * 0.3;
590 					dBits[nOffset + 1] = (uint8)(grey + dist);
591 					dBits[nOffset + 0] = (uint8)(fBits[fOffset + 0] * 0.3);
592 				}
593 
594 				// disabled bits have less contrast (lame method...)
595 				if (dcBits != NULL) {
596 					dcBits[nOffset + 3] = (uint8)(dBits[nOffset + 3] * 0.8);
597 					dcBits[nOffset + 2] = (uint8)(dBits[nOffset + 2] * 0.8);
598 					dcBits[nOffset + 1] = (uint8)(dBits[nOffset + 1] * 0.8);
599 					dcBits[nOffset + 0] = (uint8)(fBits[fOffset + 0] * 0.3);
600 				}
601 			}
602 			fBits += fbpr;
603 			nBits += nbpr;
604 			if (cBits != NULL)
605 				cBits += nbpr;
606 			if (dBits != NULL)
607 				dBits += nbpr;
608 			if (dcBits != NULL)
609 				dcBits += nbpr;
610 		}
611 	} else {
612 		// unsupported format
613 		return B_BAD_VALUE;
614 	}
615 
616 	// make the partially-on bitmaps a copy of the on bitmaps
617 	if ((flags & B_CREATE_PARTIALLY_ACTIVE_ICON_BITMAP) != 0) {
618 		if (CopyBitmap(clickedBitmap, B_PARTIALLY_ACTIVATE_ICON_BITMAP) == NULL)
619 			return B_NO_MEMORY;
620 		if ((flags & B_CREATE_DISABLED_ICON_BITMAPS) != 0) {
621 			if (CopyBitmap(disabledClickedBitmap,
622 					B_PARTIALLY_ACTIVATE_ICON_BITMAP | B_DISABLED_ICON_BITMAP)
623 					== NULL) {
624 				return B_NO_MEMORY;
625 			}
626 		}
627 	}
628 
629 	return B_OK;
630 }
631 
632 
633 }	// namespace BPrivate
634