ardour
rgb_macros.h
Go to the documentation of this file.
1 /*
2  Copyright (C) 2000 EMC Capital Management, Inc.
3 
4  Developed by Jon Trowbridge <trow@gnu.org> and
5  Havoc Pennington <hp@pobox.com>.
6 
7  This program is free software; you can redistribute it and/or modify
8  it under the terms of the GNU General Public License as published by
9  the Free Software Foundation; either version 2 of the License, or
10  (at your option) any later version.
11 
12  This program is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with this program; if not, write to the Free Software
19  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 
21 */
22 
23 #ifndef __gtkmm2ext_rgb_macros_h__
24 #define __gtkmm2ext_rgb_macros_h__
25 
26 /*
27  Some convenient macros for drawing into an RGB buffer.
28  Beware of side effects, code-bloat, and all of the other classic
29  cpp-perils...
30 */
31 
32 #define RGB_TO_UINT(r,g,b) ((((guint)(r))<<16)|(((guint)(g))<<8)|((guint)(b)))
33 #define RGB_TO_RGBA(x,a) (((x) << 8) | ((((guint)a) & 0xff)))
34 #define RGBA_TO_UINT(r,g,b,a) RGB_TO_RGBA(RGB_TO_UINT(r,g,b), a)
35 #define RGB_WHITE RGB_TO_UINT(0xff, 0xff, 0xff)
36 #define RGB_BLACK RGB_TO_UINT(0x00, 0x00, 0x00)
37 #define RGB_RED RGB_TO_UINT(0xff, 0x00, 0x00)
38 #define RGB_GREEN RGB_TO_UINT(0x00, 0xff, 0x00)
39 #define RGB_BLUE RGB_TO_UINT(0x00, 0x00, 0xff)
40 #define RGB_YELLOW RGB_TO_UINT(0xff, 0xff, 0x00)
41 #define RGB_VIOLET RGB_TO_UINT(0xff, 0x00, 0xff)
42 #define RGB_CYAN RGB_TO_UINT(0x00, 0xff, 0xff)
43 #define RGBA_WHITE RGB_TO_RGBA(RGB_WHITE, 0xff)
44 #define RGBA_BLACK RGB_TO_RGBA(RGB_BLACK, 0xff)
45 #define RGBA_RED RGB_TO_RGBA(RGB_RED, 0xff)
46 #define RGBA_GREEN RGB_TO_RGBA(RGB_GREEN, 0xff)
47 #define RGBA_BLUE RGB_TO_RGBA(RGB_BLUE, 0xff)
48 #define RGBA_YELLOW RGB_TO_RGBA(RGB_YELLOW, 0xff)
49 #define RGBA_VIOLET RGB_TO_RGBA(RGB_VIOLET, 0xff)
50 #define RGBA_CYAN RGB_TO_RGBA(RGB_CYAN, 0xff)
51 #define RGB_GREY(x) RGB_TO_UINT(x,x,x)
52 #define RGBA_GREY(x) RGB_TO_RGBA(RGB_GREY(x), 0xff)
53 #define UINT_RGBA_R(x) (((guint)(x))>>24)
54 #define UINT_RGBA_G(x) ((((guint)(x))>>16)&0xff)
55 #define UINT_RGBA_B(x) ((((guint)(x))>>8)&0xff)
56 #define UINT_RGBA_A(x) (((guint)(x))&0xff)
57 #define UINT_RGBA_R_FLT(x) ((((guint)(x))>>24)/255.0)
58 #define UINT_RGBA_G_FLT(x) (((((guint)(x))>>16)&0xff)/255.0)
59 #define UINT_RGBA_B_FLT(x) (((((guint)(x))>>8)&0xff)/255.0)
60 #define UINT_RGBA_A_FLT(x) ((((guint)(x))&0xff)/255.0)
61 #define UINT_RGBA_CHANGE_R(x, r) (((x)&(~(0xff<<24)))|(((r)&0xff)<<24))
62 #define UINT_RGBA_CHANGE_G(x, g) (((x)&(~(0xff<<16)))|(((g)&0xff)<<16))
63 #define UINT_RGBA_CHANGE_B(x, b) (((x)&(~(0xff<<8)))|(((b)&0xff)<<8))
64 #define UINT_RGBA_CHANGE_A(x, a) (((x)&(~0xff))|((a)&0xff))
65 #define UINT_TO_RGB(u,r,g,b) \
66 { (*(r)) = ((u)>>16)&0xff; (*(g)) = ((u)>>8)&0xff; (*(b)) = (u)&0xff; }
67 #define UINT_TO_RGBA(u,r,g,b,a) \
68 { UINT_TO_RGB(((u)>>8),r,g,b); (*(a)) = (u)&0xff; }
69 #define MONO_INTERPOLATE(v1, v2, t) ((gint)rint((v2)*(t)+(v1)*(1-(t))))
70 #define UINT_INTERPOLATE(c1, c2, t) \
71  RGBA_TO_UINT( MONO_INTERPOLATE(UINT_RGBA_R(c1), UINT_RGBA_R(c2), t), \
72  MONO_INTERPOLATE(UINT_RGBA_G(c1), UINT_RGBA_G(c2), t), \
73  MONO_INTERPOLATE(UINT_RGBA_B(c1), UINT_RGBA_B(c2), t), \
74  MONO_INTERPOLATE(UINT_RGBA_A(c1), UINT_RGBA_A(c2), t) )
75 #define PIXEL_RGB(p, r, g, b) \
76 {((guchar*)(p))[0]=(r); ((guchar*)(p))[1]=(g); ((guchar*)(p))[2]=(b);}
77 #define PIXEL_RGBA(p, r, g, b, a) \
78 { if ((a)>=0xff) { PIXEL_RGB(p,r,g,b) } \
79  else if ((a)>0) { \
80  guint pixel_tmp; \
81  pixel_tmp = ((guchar*)(p))[0]; \
82  ((guchar*)(p))[0] = pixel_tmp + ((((r)-pixel_tmp)*(a)+0x80) >> 8); \
83  pixel_tmp = ((guchar*)(p))[1]; \
84  ((guchar*)(p))[1] = pixel_tmp + ((((g)-pixel_tmp)*(a)+0x80) >> 8); \
85  pixel_tmp = ((guchar*)(p))[2]; \
86  ((guchar*)(p))[2] = pixel_tmp + ((((b)-pixel_tmp)*(a)+0x80) >> 8); }}
87 #define PIXEL_RGB_UINT(p, i) \
88 UINT_TO_RGB((i), ((guchar*)p), ((guchar*)p)+1, ((guchar*)p)+2)
89 #define PIXEL_RGBA_UINT(p, i) \
90  PIXEL_RGBA((p), ((i)>>24)&0xff, ((i)>>16)&0xff, ((i)>>8)&0xff, (i)&0xff)
91 #define PIXEL_BLACK(p) PIXEL_RGB(p,0,0,0)
92 #define PIXEL_WHITE(p) PIXEL_RGB(p,0xff,0xff,0xff)
93 #define PIXEL_GREY(p,g) PIXEL_RGB(p,g,g,g)
94 #define PIXEL_GREYA(p,g,a) PIXEL_RGBA(p,g,g,g,a)
95 #define BUF_PTR(inbuf, ptx, pty) \
96  ((inbuf)->buf + 3*((ptx)-(inbuf)->rect.x0) + (inbuf)->buf_rowstride*((pty)-(inbuf)->rect.y0))
97 #define BUF_INBOUNDS_X(inbuf, ptx) \
98 ((inbuf)->rect.x0 <= (ptx) && (ptx) < (inbuf)->rect.x1)
99 #define BUF_INBOUNDS_Y(inbuf, pty) \
100 ((inbuf)->rect.y0 <= (pty) && (pty) < (inbuf)->rect.y1)
101 #define PAINT_DOT(inbuf, colr, colg, colb,ptx, pty) \
102 { \
103  guchar* pd_p; \
104  if (BUF_INBOUNDS_X(inbuf, ptx) && BUF_INBOUNDS_Y(inbuf, pty)) { \
105  pd_p = BUF_PTR(inbuf, ptx, pty); \
106  PIXEL_RGB(pd_p, (colr), (colg), (colb)); \
107  } \
108 }
109 #define FAST_PAINT_DOT(inbuf, colr, colg, colb,ptx, pty) \
110 { \
111  guchar* pd_p; \
112  pd_p = BUF_PTR(inbuf, ptx, pty); \
113  PIXEL_RGB(pd_p, (colr), (colg), (colb)); \
114 }
115 #define PAINT_DOTA(inbuf, colr, colg, colb, cola, ptx, pty) \
116 { \
117  guchar* pd_p; \
118  if (BUF_INBOUNDS_X(inbuf, ptx) && BUF_INBOUNDS_Y(inbuf, pty)) { \
119  pd_p = BUF_PTR(inbuf, ptx, pty); \
120  PIXEL_RGBA(pd_p, (colr), (colg), (colb), (cola)); \
121  } \
122 }
123 #define FAST_PAINT_DOTA(inbuf, colr, colg, colb, cola, ptx, pty) \
124 { \
125  guchar* pd_p; \
126  pd_p = BUF_PTR(inbuf, ptx, pty); \
127  PIXEL_RGBA(pd_p, (colr), (colg), (colb), (cola)); \
128 }
129 #define PAINT_HORIZ(inbuf, colr, colg, colb, ptx0, ptx1, pty) \
130 { \
131  GnomeCanvasBuf* ph_buf = (inbuf); \
132  guchar* ph_p; \
133  gint ph_a0, ph_a1; \
134  gint ph_colr=(colr), ph_colg=(colg), ph_colb=(colb); \
135 \
136  ph_a0 = MAX(ph_buf->rect.x0, (gint)(ptx0)); \
137  ph_a1 = MIN(ph_buf->rect.x1, (gint)(ptx1)); \
138 \
139  if (ph_a0 < ph_a1 && BUF_INBOUNDS_Y(ph_buf, (gint)(pty))) { \
140  ph_p = BUF_PTR(ph_buf, ph_a0, pty); \
141  while (ph_a0 < ph_a1) { \
142  PIXEL_RGB(ph_p, ph_colr, ph_colg, ph_colb); \
143  ++ph_a0; \
144  ph_p += 3; \
145  } \
146  } \
147 }
148 #define FAST_PAINT_HORIZ(inbuf, colr, colg, colb, ptx0, ptx1, pty) \
149 { \
150  GnomeCanvasBuf* ph_buf = (inbuf); \
151  guchar* ph_p; \
152  gint ph_a0, ph_a1; \
153  gint ph_colr=(colr), ph_colg=(colg), ph_colb=(colb); \
154 \
155  ph_a0 = MAX(ph_buf->rect.x0, (gint)(ptx0)); \
156  ph_a1 = MIN(ph_buf->rect.x1, (gint)(ptx1)); \
157 \
158  if (ph_a0 < ph_a1 && BUF_INBOUNDS_Y(ph_buf, (gint)(pty))) { \
159  ph_p = BUF_PTR(ph_buf, ph_a0, pty); \
160  while (ph_a0 < ph_a1) { \
161  PIXEL_RGB(ph_p, ph_colr, ph_colg, ph_colb); \
162  ++ph_a0; \
163  ph_p += 3; \
164  } \
165  } \
166 }
167 #define PAINT_HORIZA(inbuf, colr, colg, colb, cola, ptx0, ptx1, pty) \
168 { \
169  GnomeCanvasBuf* ph_buf = (inbuf); \
170  guchar* ph_p; \
171  gint ph_a0, ph_a1; \
172  gint ph_colr=(colr), ph_colg=(colg), ph_colb=(colb), ph_cola=(cola); \
173 \
174  ph_a0 = MAX(ph_buf->rect.x0, (gint)(ptx0)); \
175  ph_a1 = MIN(ph_buf->rect.x1, (gint)(ptx1)); \
176 \
177  if (ph_a0 < ph_a1 && BUF_INBOUNDS_Y(ph_buf, (gint)(pty))) { \
178  ph_p = BUF_PTR(ph_buf, ph_a0, pty); \
179  while (ph_a0 < ph_a1) { \
180  PIXEL_RGBA(ph_p, ph_colr, ph_colg, ph_colb, ph_cola); \
181  ++ph_a0; \
182  ph_p += 3; \
183  } \
184  } \
185 }
186 #define PAINT_VERT(inbuf, colr, colg, colb, ptx, pty0, pty1) \
187 { \
188  GnomeCanvasBuf* pv_buf = (inbuf); \
189  guchar* pv_p; \
190  gint pv_b0, pv_b1; \
191  gint pv_colr=(colr), pv_colg=(colg), pv_colb=(colb);\
192 \
193  pv_b0 = MAX(pv_buf->rect.y0, (gint)(pty0)); \
194  pv_b1 = MIN(pv_buf->rect.y1, (gint)(pty1)); \
195 \
196  if (pv_b0 < pv_b1 && BUF_INBOUNDS_X(pv_buf, (gint)(ptx))) { \
197  pv_p = BUF_PTR(pv_buf, ptx, pv_b0); \
198  while (pv_b0 < pv_b1) { \
199  PIXEL_RGB(pv_p, pv_colr, pv_colg, pv_colb); \
200  ++pv_b0; \
201  pv_p += pv_buf->buf_rowstride; \
202  } \
203  } \
204 }
205 #define FAST_PAINT_VERT(inbuf, colr, colg, colb, ptx, pty0, pty1) \
206 { \
207  GnomeCanvasBuf* fpv_buf = (inbuf); \
208  guchar* fpv_p; \
209  gint fpv_b0, fpv_b1; \
210 \
211  fpv_b0 = MAX(fpv_buf->rect.y0, (gint)(pty0)); \
212  fpv_b1 = MIN(fpv_buf->rect.y1, (gint)(pty1)); \
213 \
214  fpv_p = BUF_PTR(fpv_buf, ptx, fpv_b0); \
215 \
216  while (fpv_b0 < fpv_b1) { \
217  PIXEL_RGB(fpv_p, colr, colg, colb); \
218  ++fpv_b0; \
219  fpv_p += fpv_buf->buf_rowstride; \
220  } \
221 }
222 #define PAINT_VERTA(inbuf, colr, colg, colb, cola, ptx, pty0, pty1) \
223 { \
224  GnomeCanvasBuf* pv_buf = (inbuf); \
225  guchar* pv_p; \
226  gint pv_b0, pv_b1; \
227  gint pv_colr=(colr), pv_colg=(colg), pv_colb=(colb), pv_cola=(cola);\
228 \
229  pv_b0 = MAX(pv_buf->rect.y0, (pty0)); \
230  pv_b1 = MIN(pv_buf->rect.y1, (pty1)); \
231 \
232  if (pv_b0 < pv_b1 && BUF_INBOUNDS_X(pv_buf, ptx)) { \
233  pv_p = BUF_PTR(pv_buf, ptx, pv_b0); \
234  while (pv_b0 < pv_b1) { \
235  PIXEL_RGBA(pv_p, pv_colr, pv_colg, pv_colb, pv_cola); \
236  ++pv_b0; \
237  pv_p += pv_buf->buf_rowstride; \
238  } \
239  } \
240 }
241 
242 #define PAINT_VERTA_GR(inbuf, colr, colg, colb, cola, ptx, pty0, pty1, origin_y, obj_top) \
243 { \
244  GnomeCanvasBuf* pv_buf = (inbuf); \
245  guchar* pv_p; \
246  gint pv_b0, pv_b1; \
247  gint pv_colr=(colr), pv_colg=(colg), pv_colb=(colb), pv_cola=(cola); \
248  gint y_fract; \
249  gint y_span = (origin_y - obj_top); \
250  gint sat; \
251 \
252  pv_b0 = MAX(pv_buf->rect.y0, (pty0)); \
253  pv_b1 = MIN(pv_buf->rect.y1, (pty1)); \
254 \
255  if (pv_b0 < pv_b1 && BUF_INBOUNDS_X(pv_buf, ptx)) { \
256  pv_p = BUF_PTR(pv_buf, ptx, pv_b0); \
257  while (pv_b0 < pv_b1) { \
258  y_fract = (abs(origin_y - pv_b0)) * 0xFF; \
259  y_fract = y_fract / y_span; \
260  sat = 0xFF - (y_fract); \
261  PIXEL_RGBA(pv_p, (((pv_colr << 8) * sat) >> 16), (((pv_colg << 8) * sat) >> 16), (((pv_colb << 8) * sat) >> 16), pv_cola); \
262  ++pv_b0; \
263  pv_p += pv_buf->buf_rowstride; \
264  } \
265  } \
266 }
267 
268 /* Paint a solid-colored box into a GnomeCanvasBuf (clipping as necessary).
269  The box contains (ptx0,pty0), but not (ptx1, pty1).
270  Each macro arg should appear exactly once in the body of the code. */
271 #define PAINT_BOX(inbuf, colr, colg, colb, cola, ptx0, pty0, ptx1, pty1) \
272 { \
273  GnomeCanvasBuf* pb_buf = (inbuf); \
274  guchar* pb_p; \
275  guchar* pb_pp; \
276  gint pb_a0, pb_a1, pb_b0, pb_b1, pb_i, pb_j; \
277  gint pb_colr=(colr), pb_colg=(colg), pb_colb=(colb), pb_cola=(cola); \
278 \
279  pb_a0 = MAX(pb_buf->rect.x0, (ptx0)); \
280  pb_a1 = MIN(pb_buf->rect.x1, (ptx1)); \
281  pb_b0 = MAX(pb_buf->rect.y0, (pty0)); \
282  pb_b1 = MIN(pb_buf->rect.y1, (pty1)); \
283 \
284  if (pb_a0 < pb_a1 && pb_b0 < pb_b1) { \
285  pb_p = BUF_PTR(pb_buf, pb_a0, pb_b0); \
286  for (pb_j=pb_b0; pb_j<pb_b1; ++pb_j) { \
287  pb_pp = pb_p; \
288  for (pb_i=pb_a0; pb_i<pb_a1; ++pb_i) { \
289  PIXEL_RGBA(pb_pp, pb_colr, pb_colg, pb_colb, pb_cola); \
290  pb_pp += 3; \
291  } \
292  pb_p += pb_buf->buf_rowstride; \
293  } \
294  } \
295 }
296 
297 /* Paint a gradient-colored box into a GnomeCanvasBuf (clipping as necessary).
298  The box contains (ptx0,pty0), but not (ptx1, pty1).
299  Each macro arg should appear exactly once in the body of the code. */
300 #define PAINT_BOX_GR(inbuf, colr, colg, colb, cola, ptx0, pty0, ptx1, pty1, v_span) \
301 { \
302  GnomeCanvasBuf* pb_buf = (inbuf); \
303  guchar* pb_p; \
304  guchar* pb_pp; \
305  gint pb_a0, pb_a1, pb_b0, pb_b1, pb_i, pb_j; \
306  gint pb_colr=(colr), pb_colg=(colg), pb_colb=(colb), pb_cola=(cola); \
307  gint sat; \
308  gint y_fract; \
309  gint y_span = MAX(abs(v_span), 1); \
310 \
311  pb_a0 = MAX(pb_buf->rect.x0, (ptx0)); \
312  pb_a1 = MIN(pb_buf->rect.x1, (ptx1)); \
313  pb_b0 = MAX(pb_buf->rect.y0, (pty0)); \
314  pb_b1 = MIN(pb_buf->rect.y1, (pty1)); \
315 \
316  if (pb_a0 < pb_a1 && pb_b0 < pb_b1) { \
317  pb_p = BUF_PTR(pb_buf, pb_a0, pb_b0); \
318  for (pb_j=pb_b0; pb_j<pb_b1; ++pb_j) { \
319  y_fract = 0xFF * (abs(pb_j - pty0)); \
320  y_fract = y_fract / y_span; \
321  sat = 0xFF - (y_fract >> 1); \
322  pb_pp = pb_p; \
323  for (pb_i=pb_a0; pb_i<pb_a1; ++pb_i) { \
324  PIXEL_RGBA(pb_pp, (((pb_colr << 8) * sat) >> 16), (((pb_colg << 8) * sat) >> 16), (((pb_colb << 8) * sat) >> 16), pb_cola); \
325  pb_pp += 3; \
326  } \
327  pb_p += pb_buf->buf_rowstride; \
328  } \
329  } \
330 }
331 
332 
333 /* No bounds checking in this version */
334 
335 #define FAST_PAINT_BOX(inbuf, colr, colg, colb, cola, ptx0, pty0, ptx1, pty1) \
336 { \
337  GnomeCanvasBuf* pb_buf = (inbuf); \
338  guchar* pb_p; \
339  guchar* pb_pp; \
340  gint pb_i, pb_j; \
341 \
342  pb_p = BUF_PTR(pb_buf, ptx0, pty0); \
343  for (pb_j=pty0; pb_j<pty1; ++pb_j) { \
344  pb_pp = pb_p; \
345  for (pb_i=ptx0; pb_i<ptx1; ++pb_i) { \
346  PIXEL_RGBA(pb_pp, colr, colg, colb, cola); \
347  pb_pp += 3; \
348  } \
349  pb_p += pb_buf->buf_rowstride; \
350  } \
351 }
352 
353 #endif /* __gtkmm2ext_rgb_macros_h__ */