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