Initial import of gtk2_ardour.
[ardour.git] / gtk2_ardour / rgb_macros.h
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     $Id$
22 */
23
24 #ifndef __gtk_ardour_rgb_macros_h__
25 #define __gtk_ardour_rgb_macros_h__
26
27 /*
28   Some convenient macros for drawing into an RGB buffer.
29   Beware of side effects, code-bloat, and all of the other classic
30   cpp-perils...
31 */
32
33 #define RGB_TO_UINT(r,g,b) ((((guint)(r))<<16)|(((guint)(g))<<8)|((guint)(b)))
34 #define RGB_TO_RGBA(x,a) (((x) << 8) | ((((guint)a) & 0xff)))
35 #define RGBA_TO_UINT(r,g,b,a) RGB_TO_RGBA(RGB_TO_UINT(r,g,b), a)
36 #define RGB_WHITE  RGB_TO_UINT(0xff, 0xff, 0xff)
37 #define RGB_BLACK  RGB_TO_UINT(0x00, 0x00, 0x00)
38 #define RGB_RED    RGB_TO_UINT(0xff, 0x00, 0x00)
39 #define RGB_GREEN  RGB_TO_UINT(0x00, 0xff, 0x00)
40 #define RGB_BLUE   RGB_TO_UINT(0x00, 0x00, 0xff)
41 #define RGB_YELLOW RGB_TO_UINT(0xff, 0xff, 0x00)
42 #define RGB_VIOLET RGB_TO_UINT(0xff, 0x00, 0xff)
43 #define RGB_CYAN   RGB_TO_UINT(0x00, 0xff, 0xff)
44 #define RGBA_WHITE  RGB_TO_RGBA(RGB_WHITE, 0xff)
45 #define RGBA_BLACK  RGB_TO_RGBA(RGB_BLACK, 0xff)
46 #define RGBA_RED    RGB_TO_RGBA(RGB_RED, 0xff)
47 #define RGBA_GREEN  RGB_TO_RGBA(RGB_GREEN, 0xff)
48 #define RGBA_BLUE   RGB_TO_RGBA(RGB_BLUE, 0xff)
49 #define RGBA_YELLOW RGB_TO_RGBA(RGB_YELLOW, 0xff)
50 #define RGBA_VIOLET RGB_TO_RGBA(RGB_VIOLET, 0xff)
51 #define RGBA_CYAN   RGB_TO_RGBA(RGB_CYAN, 0xff)
52 #define RGB_GREY(x) RGB_TO_UINT(x,x,x)
53 #define RGBA_GREY(x) RGB_TO_RGBA(RGB_GREY(x), 0xff)
54 #define UINT_RGBA_R(x) (((guint)(x))>>24)
55 #define UINT_RGBA_G(x) ((((guint)(x))>>16)&0xff)
56 #define UINT_RGBA_B(x) ((((guint)(x))>>8)&0xff)
57 #define UINT_RGBA_A(x) (((guint)(x))&0xff)
58 #define UINT_RGBA_CHANGE_R(x, r) (((x)&(~(0xff<<24)))|(((r)&0xff)<<24))
59 #define UINT_RGBA_CHANGE_G(x, g) (((x)&(~(0xff<<16)))|(((g)&0xff)<<16))
60 #define UINT_RGBA_CHANGE_B(x, b) (((x)&(~(0xff<<8)))|(((b)&0xff)<<8))
61 #define UINT_RGBA_CHANGE_A(x, a) (((x)&(~0xff))|((a)&0xff))
62 #define UINT_TO_RGB(u,r,g,b) \
63 { (*(r)) = ((u)>>16)&0xff; (*(g)) = ((u)>>8)&0xff; (*(b)) = (u)&0xff; }
64 #define UINT_TO_RGBA(u,r,g,b,a) \
65 { UINT_TO_RGB(((u)>>8),r,g,b); (*(a)) = (u)&0xff; }
66 #define MONO_INTERPOLATE(v1, v2, t) ((gint)rint((v2)*(t)+(v1)*(1-(t))))
67 #define UINT_INTERPOLATE(c1, c2, t) \
68   RGBA_TO_UINT( MONO_INTERPOLATE(UINT_RGBA_R(c1), UINT_RGBA_R(c2), t), \
69                 MONO_INTERPOLATE(UINT_RGBA_G(c1), UINT_RGBA_G(c2), t), \
70                 MONO_INTERPOLATE(UINT_RGBA_B(c1), UINT_RGBA_B(c2), t), \
71                 MONO_INTERPOLATE(UINT_RGBA_A(c1), UINT_RGBA_A(c2), t) )
72 #define PIXEL_RGB(p, r, g, b) \
73 {((guchar*)(p))[0]=(r); ((guchar*)(p))[1]=(g); ((guchar*)(p))[2]=(b);}
74 #define PIXEL_RGBA(p, r, g, b, a) \
75 { if ((a)>=0xff) { PIXEL_RGB(p,r,g,b) } \
76   else if ((a)>0) { \
77     guint pixel_tmp; \
78     pixel_tmp = ((guchar*)(p))[0]; \
79     ((guchar*)(p))[0] = pixel_tmp + ((((r)-pixel_tmp)*(a)+0x80) >> 8); \
80     pixel_tmp = ((guchar*)(p))[1]; \
81     ((guchar*)(p))[1] = pixel_tmp + ((((g)-pixel_tmp)*(a)+0x80) >> 8); \
82     pixel_tmp = ((guchar*)(p))[2]; \
83     ((guchar*)(p))[2] = pixel_tmp + ((((b)-pixel_tmp)*(a)+0x80) >> 8); }}
84 #define PIXEL_RGB_UINT(p, i) \
85 UINT_TO_RGB((i), ((guchar*)p), ((guchar*)p)+1, ((guchar*)p)+2)
86 #define PIXEL_RGBA_UINT(p, i) \
87   PIXEL_RGBA((p), ((i)>>24)&0xff, ((i)>>16)&0xff, ((i)>>8)&0xff, (i)&0xff)
88 #define PIXEL_BLACK(p) PIXEL_RGB(p,0,0,0)
89 #define PIXEL_WHITE(p) PIXEL_RGB(p,0xff,0xff,0xff)
90 #define PIXEL_GREY(p,g) PIXEL_RGB(p,g,g,g)
91 #define PIXEL_GREYA(p,g,a) PIXEL_RGBA(p,g,g,g,a)
92 #define BUF_PTR(inbuf, ptx, pty) \
93  ((inbuf)->buf + 3*((ptx)-(inbuf)->rect.x0) + (inbuf)->buf_rowstride*((pty)-(inbuf)->rect.y0))
94 #define BUF_INBOUNDS_X(inbuf, ptx) \
95 ((inbuf)->rect.x0 <= (ptx) && (ptx) < (inbuf)->rect.x1)
96 #define BUF_INBOUNDS_Y(inbuf, pty) \
97 ((inbuf)->rect.y0 <= (pty) && (pty) < (inbuf)->rect.y1)
98 #define PAINT_DOT(inbuf, colr, colg, colb,ptx, pty) \
99 { \
100   guchar* pd_p; \
101   if (BUF_INBOUNDS_X(inbuf, ptx) && BUF_INBOUNDS_Y(inbuf, pty)) { \
102     pd_p = BUF_PTR(inbuf, ptx, pty); \
103     PIXEL_RGB(pd_p, (colr), (colg), (colb)); \
104   } \
105 }
106 #define FAST_PAINT_DOT(inbuf, colr, colg, colb,ptx, pty) \
107 { \
108   guchar* pd_p; \
109   pd_p = BUF_PTR(inbuf, ptx, pty); \
110   PIXEL_RGB(pd_p, (colr), (colg), (colb)); \
111 }
112 #define PAINT_DOTA(inbuf, colr, colg, colb, cola, ptx, pty) \
113 { \
114   guchar* pd_p; \
115   if (BUF_INBOUNDS_X(inbuf, ptx) && BUF_INBOUNDS_Y(inbuf, pty)) { \
116     pd_p = BUF_PTR(inbuf, ptx, pty); \
117     PIXEL_RGBA(pd_p, (colr), (colg), (colb), (cola)); \
118   } \
119 }
120 #define FAST_PAINT_DOTA(inbuf, colr, colg, colb, cola, ptx, pty) \
121 { \
122   guchar* pd_p; \
123   pd_p = BUF_PTR(inbuf, ptx, pty); \
124   PIXEL_RGBA(pd_p, (colr), (colg), (colb), (cola)); \
125 }
126 #define PAINT_HORIZ(inbuf, colr, colg, colb, ptx0, ptx1, pty) \
127 { \
128   GtkCanvasBuf* ph_buf = (inbuf); \
129   guchar* ph_p; \
130   gint ph_a0, ph_a1; \
131   gint ph_colr=(colr), ph_colg=(colg), ph_colb=(colb); \
132 \
133   ph_a0 = MAX(ph_buf->rect.x0, (ptx0)); \
134   ph_a1 = MIN(ph_buf->rect.x1, (ptx1)); \
135 \
136   if (ph_a0 < ph_a1 && BUF_INBOUNDS_Y(ph_buf, pty)) { \
137     ph_p = BUF_PTR(ph_buf, ph_a0, pty); \
138     while (ph_a0 < ph_a1) { \
139       PIXEL_RGB(ph_p, ph_colr, ph_colg, ph_colb); \
140       ++ph_a0; \
141       ph_p += 3; \
142     } \
143   } \
144 }
145 #define FAST_PAINT_HORIZ(inbuf, colr, colg, colb, ptx0, ptx1, pty) \
146 { \
147   GtkCanvasBuf* ph_buf = (inbuf); \
148   guchar* ph_p; \
149   gint ph_a0, ph_a1; \
150   gint ph_colr=(colr), ph_colg=(colg), ph_colb=(colb); \
151 \
152   ph_a0 = MAX(ph_buf->rect.x0, (ptx0)); \
153   ph_a1 = MIN(ph_buf->rect.x1, (ptx1)); \
154 \
155   if (ph_a0 < ph_a1 && BUF_INBOUNDS_Y(ph_buf, pty)) { \
156     ph_p = BUF_PTR(ph_buf, ph_a0, pty); \
157     while (ph_a0 < ph_a1) { \
158       PIXEL_RGB(ph_p, ph_colr, ph_colg, ph_colb); \
159       ++ph_a0; \
160       ph_p += 3; \
161     } \
162   } \
163 }
164 #define PAINT_HORIZA(inbuf, colr, colg, colb, cola, ptx0, ptx1, pty) \
165 { \
166   GtkCanvasBuf* ph_buf = (inbuf); \
167   guchar* ph_p; \
168   gint ph_a0, ph_a1; \
169   gint ph_colr=(colr), ph_colg=(colg), ph_colb=(colb), ph_cola=(cola); \
170 \
171   ph_a0 = MAX(ph_buf->rect.x0, (ptx0)); \
172   ph_a1 = MIN(ph_buf->rect.x1, (ptx1)); \
173 \
174   if (ph_a0 < ph_a1 && BUF_INBOUNDS_Y(ph_buf, pty)) { \
175     ph_p = BUF_PTR(ph_buf, ph_a0, pty); \
176     while (ph_a0 < ph_a1) { \
177       PIXEL_RGBA(ph_p, ph_colr, ph_colg, ph_colb, ph_cola); \
178       ++ph_a0; \
179       ph_p += 3; \
180     } \
181   } \
182 }
183 #define PAINT_VERT(inbuf, colr, colg, colb, ptx, pty0, pty1) \
184 { \
185   GtkCanvasBuf* pv_buf = (inbuf); \
186   guchar* pv_p; \
187   gint pv_b0, pv_b1; \
188   gint pv_colr=(colr), pv_colg=(colg), pv_colb=(colb);\
189 \
190   pv_b0 = MAX(pv_buf->rect.y0, (pty0)); \
191   pv_b1 = MIN(pv_buf->rect.y1, (pty1)); \
192 \
193  if (pv_b0 < pv_b1 && BUF_INBOUNDS_X(pv_buf, ptx)) { \
194     pv_p = BUF_PTR(pv_buf, ptx, pv_b0); \
195     while (pv_b0 < pv_b1) { \
196       PIXEL_RGB(pv_p, pv_colr, pv_colg, pv_colb); \
197       ++pv_b0; \
198       pv_p += pv_buf->buf_rowstride; \
199     } \
200   } \
201 }
202 #define FAST_PAINT_VERT(inbuf, colr, colg, colb, ptx, pty0, pty1) \
203 { \
204   GtkCanvasBuf* fpv_buf = (inbuf); \
205   guchar* fpv_p; \
206   gint fpv_b0, fpv_b1; \
207 \
208   fpv_b0 = MAX(fpv_buf->rect.y0, (pty0)); \
209   fpv_b1 = MIN(fpv_buf->rect.y1, (pty1)); \
210 \
211   fpv_p = BUF_PTR(fpv_buf, ptx, fpv_b0); \
212 \
213   while (fpv_b0 < fpv_b1) { \
214       PIXEL_RGB(fpv_p, colr, colg, colb); \
215       ++fpv_b0; \
216       fpv_p += fpv_buf->buf_rowstride; \
217   } \
218 }
219 #define PAINT_VERTA(inbuf, colr, colg, colb, cola, ptx, pty0, pty1) \
220 { \
221   GtkCanvasBuf* pv_buf = (inbuf); \
222   guchar* pv_p; \
223   gint pv_b0, pv_b1; \
224   gint pv_colr=(colr), pv_colg=(colg), pv_colb=(colb), pv_cola=(cola);\
225 \
226   pv_b0 = MAX(pv_buf->rect.y0, (pty0)); \
227   pv_b1 = MIN(pv_buf->rect.y1, (pty1)); \
228 \
229  if (pv_b0 < pv_b1 && BUF_INBOUNDS_X(pv_buf, ptx)) { \
230     pv_p = BUF_PTR(pv_buf, ptx, pv_b0); \
231     while (pv_b0 < pv_b1) { \
232       PIXEL_RGBA(pv_p, pv_colr, pv_colg, pv_colb, pv_cola); \
233       ++pv_b0; \
234       pv_p += pv_buf->buf_rowstride; \
235     } \
236   } \
237 }
238
239 /* Paint a solid-colored box into a GtkCanvasBuf (clipping as necessary).
240    The box contains (ptx0,pty0), but not (ptx1, pty1).
241    Each macro arg should appear exactly once in the body of the code. */
242 #define PAINT_BOX(inbuf, colr, colg, colb, cola, ptx0, pty0, ptx1, pty1) \
243 { \
244   GtkCanvasBuf* pb_buf = (inbuf); \
245   guchar* pb_p; \
246   guchar* pb_pp; \
247   gint pb_a0, pb_a1, pb_b0, pb_b1, pb_i, pb_j; \
248   gint pb_colr=(colr), pb_colg=(colg), pb_colb=(colb), pb_cola=(cola); \
249 \
250   pb_a0 = MAX(pb_buf->rect.x0, (ptx0)); \
251   pb_a1 = MIN(pb_buf->rect.x1, (ptx1)); \
252   pb_b0 = MAX(pb_buf->rect.y0, (pty0)); \
253   pb_b1 = MIN(pb_buf->rect.y1, (pty1)); \
254 \
255   if (pb_a0 < pb_a1 && pb_b0 < pb_b1) { \
256     pb_p = BUF_PTR(pb_buf, pb_a0, pb_b0); \
257     for (pb_j=pb_b0; pb_j<pb_b1; ++pb_j) { \
258       pb_pp = pb_p; \
259       for (pb_i=pb_a0; pb_i<pb_a1; ++pb_i) { \
260         PIXEL_RGBA(pb_pp, pb_colr, pb_colg, pb_colb, pb_cola); \
261         pb_pp += 3; \
262       } \
263       pb_p += pb_buf->buf_rowstride; \
264     } \
265   } \
266 }
267
268 /* No bounds checking in this version */
269
270 #define FAST_PAINT_BOX(inbuf, colr, colg, colb, cola, ptx0, pty0, ptx1, pty1) \
271 { \
272   GtkCanvasBuf* pb_buf = (inbuf); \
273   guchar* pb_p; \
274   guchar* pb_pp; \
275   gint pb_i, pb_j; \
276 \
277   pb_p = BUF_PTR(pb_buf, ptx0, pty0); \
278   for (pb_j=pty0; pb_j<pty1; ++pb_j) { \
279       pb_pp = pb_p; \
280       for (pb_i=ptx0; pb_i<ptx1; ++pb_i) { \
281         PIXEL_RGBA(pb_pp, colr, colg, colb, cola); \
282         pb_pp += 3; \
283       } \
284       pb_p += pb_buf->buf_rowstride; \
285     } \
286 }
287
288 #endif /* __gtk_ardour_rgb_macros_h__ */