1/*
2 * Copyright 2001-2015, Haiku.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 *		DarkWyrm <bpmagic@columbus.rr.com>
7 *		Caz <turok2@currantbun.com>
8 *		Axel Dörfler, axeld@pinc-software.de
9 */
10
11//!	Graphics functions and variables for the Interface Kit
12
13#include <GraphicsDefs.h>
14
15#include <AppServerLink.h>
16#include <ServerProtocol.h>
17
18
19// patterns
20const pattern B_SOLID_HIGH = {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}};
21const pattern B_MIXED_COLORS = {{0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55}};
22const pattern B_SOLID_LOW = {{0, 0, 0, 0, 0, 0, 0, 0}};
23
24// colors
25const rgb_color B_TRANSPARENT_COLOR = {0x77, 0x74, 0x77, 0x00};
26const rgb_color B_TRANSPARENT_32_BIT = {0x77, 0x74, 0x77, 0x00};
27const uint8 B_TRANSPARENT_8_BIT = 0xff;
28
29const uint8 B_TRANSPARENT_MAGIC_CMAP8 = 0xff;
30const uint16 B_TRANSPARENT_MAGIC_RGBA15 = 0x39ce;
31const uint16 B_TRANSPARENT_MAGIC_RGBA15_BIG = 0xce39;
32const uint32 B_TRANSPARENT_MAGIC_RGBA32 = 0x00777477;
33const uint32 B_TRANSPARENT_MAGIC_RGBA32_BIG = 0x77747700;
34
35// misc.
36const struct screen_id B_MAIN_SCREEN_ID = {0};
37
38
39// rgb_color
40int32
41rgb_color::Brightness() const
42{
43	return ((int32)red * 41 + (int32)green * 187 + (int32)blue * 28) >> 8;
44}
45
46
47// Mix two colors without respect for their alpha values
48rgb_color
49mix_color(rgb_color color1, rgb_color color2, uint8 amount)
50{
51	color1.red = (uint8)(((int16(color2.red) - int16(color1.red)) * amount)
52		/ 255 + color1.red);
53	color1.green = (uint8)(((int16(color2.green) - int16(color1.green))
54		* amount) / 255 + color1.green);
55	color1.blue = (uint8)(((int16(color2.blue) - int16(color1.blue)) * amount)
56		/ 255 + color1.blue );
57	color1.alpha = (uint8)(((int16(color2.alpha) - int16(color1.alpha))
58		* amount) / 255 + color1.alpha );
59
60	return color1;
61}
62
63
64// Mix two colors, respecting their alpha values.
65rgb_color
66blend_color(rgb_color color1, rgb_color color2, uint8 amount)
67{
68	const uint8 alphaMix = (uint8)(((int16(color2.alpha) - int16(255
69		- color1.alpha)) * amount) / 255 + (255 - color1.alpha));
70
71	color1.red = (uint8)(((int16(color2.red) - int16(color1.red)) * alphaMix)
72		/ 255 + color1.red );
73	color1.green = (uint8)(((int16(color2.green) - int16(color1.green))
74		* alphaMix) / 255 + color1.green);
75	color1.blue = (uint8)(((int16(color2.blue) - int16(color1.blue))
76		* alphaMix) / 255 + color1.blue);
77	color1.alpha = (uint8)(((int16(color2.alpha) - int16(color1.alpha))
78		* amount) / 255 + color1.alpha);
79
80	return color1;
81}
82
83
84rgb_color
85disable_color(rgb_color color, rgb_color background)
86{
87	return mix_color(color, background, 185);
88}
89
90
91status_t
92get_pixel_size_for(color_space space, size_t *pixelChunk, size_t *rowAlignment,
93	size_t *pixelsPerChunk)
94{
95	status_t status = B_OK;
96	int32 bytesPerPixel = 0;
97	int32 pixPerChunk = 0;
98	switch (space) {
99		// supported
100		case B_RGB32: case B_RGBA32:
101		case B_RGB32_BIG: case B_RGBA32_BIG:
102		case B_UVL32: case B_UVLA32:
103		case B_LAB32: case B_LABA32:
104		case B_HSI32: case B_HSIA32:
105		case B_HSV32: case B_HSVA32:
106		case B_HLS32: case B_HLSA32:
107		case B_CMY32: case B_CMYA32: case B_CMYK32:
108			bytesPerPixel = 4;
109			pixPerChunk = 1;
110			break;
111		case B_RGB24: case B_RGB24_BIG:
112		case B_UVL24: case B_LAB24: case B_HSI24:
113		case B_HSV24: case B_HLS24: case B_CMY24:
114			bytesPerPixel = 3;
115			pixPerChunk = 1;
116			break;
117		case B_RGB16:		case B_RGB15:		case B_RGBA15:
118		case B_RGB16_BIG:	case B_RGB15_BIG:	case B_RGBA15_BIG:
119			bytesPerPixel = 2;
120			pixPerChunk = 1;
121			break;
122		case B_CMAP8: case B_GRAY8:
123			bytesPerPixel = 1;
124			pixPerChunk = 1;
125			break;
126		case B_GRAY1:
127			bytesPerPixel = 1;
128			pixPerChunk = 8;
129			break;
130		case B_YCbCr422: case B_YUV422:
131			bytesPerPixel = 4;
132			pixPerChunk = 2;
133			break;
134		case B_YCbCr411: case B_YUV411:
135			bytesPerPixel = 12;
136			pixPerChunk = 8;
137			break;
138		case B_YCbCr444: case B_YUV444:
139			bytesPerPixel = 3;
140			pixPerChunk = 1;
141			break;
142		// TODO: I don't know if it's correct,
143		// but beos reports B_YUV420 to be
144		// 6 bytes per pixel and 4 pixel per chunk
145		case B_YCbCr420: case B_YUV420:
146			bytesPerPixel = 3;
147			pixPerChunk = 2;
148			break;
149		case B_YUV9:
150			bytesPerPixel = 5;
151			pixPerChunk = 4;
152			break;
153		case B_YUV12:
154			bytesPerPixel = 6;
155			pixPerChunk = 4;
156			break;
157		// unsupported
158		case B_NO_COLOR_SPACE:
159		default:
160			status = B_BAD_VALUE;
161			break;
162	}
163
164	if (pixelChunk != NULL)
165		*pixelChunk = bytesPerPixel;
166
167	size_t alignment = 0;
168	if (bytesPerPixel != 0) {
169		alignment = (sizeof(int) % bytesPerPixel) * sizeof(int);
170		if (alignment < sizeof(int))
171			alignment = sizeof(int);
172	}
173
174	if (rowAlignment!= NULL)
175		*rowAlignment = alignment;
176
177	if (pixelsPerChunk!= NULL)
178		*pixelsPerChunk = pixPerChunk;
179
180	return status;
181}
182
183
184static uint32
185get_overlay_flags(color_space space)
186{
187	BPrivate::AppServerLink link;
188	link.StartMessage(AS_GET_BITMAP_SUPPORT_FLAGS);
189	link.Attach<uint32>((uint32)space);
190
191	uint32 flags = 0;
192	int32 code;
193	if (link.FlushWithReply(code) == B_OK && code == B_OK) {
194		if (link.Read<uint32>(&flags) < B_OK)
195			flags = 0;
196	}
197	return flags;
198}
199
200
201bool
202bitmaps_support_space(color_space space, uint32 *supportFlags)
203{
204	bool result = true;
205	switch (space) {
206		// supported, also for drawing and for attaching BViews
207		case B_RGB32:		case B_RGBA32:		case B_RGB24:
208		case B_RGB32_BIG:	case B_RGBA32_BIG:	case B_RGB24_BIG:
209		case B_RGB16:		case B_RGB15:		case B_RGBA15:
210		case B_RGB16_BIG:	case B_RGB15_BIG:	case B_RGBA15_BIG:
211		case B_CMAP8:		case B_GRAY8:		case B_GRAY1:
212			if (supportFlags != NULL) {
213				*supportFlags = B_VIEWS_SUPPORT_DRAW_BITMAP
214					| B_BITMAPS_SUPPORT_ATTACHED_VIEWS
215					| get_overlay_flags(space);
216			}
217			break;
218
219		// supported, but cannot draw
220		case B_YCbCr422: case B_YCbCr411: case B_YCbCr444: case B_YCbCr420:
221		case B_YUV422: case B_YUV411: case B_YUV444: case B_YUV420:
222		case B_UVL24: case B_UVL32: case B_UVLA32:
223		case B_LAB24: case B_LAB32: case B_LABA32:
224		case B_HSI24: case B_HSI32: case B_HSIA32:
225		case B_HSV24: case B_HSV32: case B_HSVA32:
226		case B_HLS24: case B_HLS32: case B_HLSA32:
227		case B_CMY24: case B_CMY32: case B_CMYA32: case B_CMYK32:
228			if (supportFlags != NULL)
229				*supportFlags = get_overlay_flags(space);
230			break;
231		// unsupported
232		case B_NO_COLOR_SPACE:
233		case B_YUV9: case B_YUV12:
234			result = false;
235			break;
236	}
237	return result;
238}
239