xref: /haiku/src/kits/interface/GraphicsDefs.cpp (revision dd2a1e350b303b855a50fd64e6cb55618be1ae6a)
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
21 const pattern B_SOLID_HIGH = {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}};
22 const pattern B_MIXED_COLORS = {{0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55}};
23 const pattern B_SOLID_LOW = {{0, 0, 0, 0, 0, 0, 0, 0}};
24 
25 // colors
26 const rgb_color B_TRANSPARENT_COLOR = {0x77, 0x74, 0x77, 0x00};
27 const rgb_color B_TRANSPARENT_32_BIT = {0x77, 0x74, 0x77, 0x00};
28 const uint8 B_TRANSPARENT_8_BIT = 0xff;
29 
30 const uint8 B_TRANSPARENT_MAGIC_CMAP8 = 0xff;
31 const uint16 B_TRANSPARENT_MAGIC_RGBA15 = 0x39ce;
32 const uint16 B_TRANSPARENT_MAGIC_RGBA15_BIG = 0xce39;
33 const uint32 B_TRANSPARENT_MAGIC_RGBA32 = 0x00777477;
34 const uint32 B_TRANSPARENT_MAGIC_RGBA32_BIG = 0x77747700;
35 
36 // misc.
37 const struct screen_id B_MAIN_SCREEN_ID = {0};
38 
39 
40 int32
41 rgb_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
53 rgb_color
54 mix_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.
70 rgb_color
71 blend_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 
89 rgb_color
90 disable_color(rgb_color color, rgb_color background)
91 {
92 	return mix_color(color, background, 185);
93 }
94 
95 
96 status_t
97 get_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 
197 static uint32
198 get_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 
214 bool
215 bitmaps_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