+/*
+ * Print the color to stdout.
+ */
+INLINE_MAYBE
+void color_print(color_t c)
+{
+#if (SCALAR_SIZE == 8)
+ const char* fmt = "[ %9.5lf %9.5lf %9.5lf %9.5lf ]";
+#else
+ const char* fmt = "[ %9.5f %9.5f %9.5f %9.5f ]";
+#endif
+ printf(fmt, c.r, c.g, c.b, c.a);
+}
+
+
+/*
+ * Add two colors together. Color may need to be clamped afterward.
+ */
+INLINE_MAYBE
+color_t color_add(color_t c1, color_t c2)
+{
+ return color_new(c1.r + c2.r, c1.g + c2.g, c1.b + c2.b, c1.a + c2.a);
+}
+
+/*
+ * Add three colors together. Color may need to be clamped afterward.
+ */
+INLINE_MAYBE
+color_t color_add2(color_t c1, color_t c2, color_t c3)
+{
+ return color_add(color_add(c1, c2), c3);
+}
+
+/*
+ * Clamp a color's channels to the normal range of 0.0 to 1.0.
+ */
+INLINE_MAYBE
+color_t color_clamp(color_t c)
+{
+ c.r = scal_clamp(c.r, S(0.0), S(1.0));
+ c.g = scal_clamp(c.g, S(0.0), S(1.0));
+ c.b = scal_clamp(c.b, S(0.0), S(1.0));
+ c.a = scal_clamp(c.a, S(0.0), S(1.0));
+ return c;
+}
+
+
+/*
+ * Interpolate smoothly between two colors with an alpha value.
+ */
+INLINE_MAYBE
+color_t color_interp(color_t c1, color_t c2, scal_t a)
+{
+ return color_new(c1.r * (S(1.0) - a) + c2.r * a,
+ c1.g * (S(1.0) - a) + c2.g * a,
+ c1.b * (S(1.0) - a) + c2.b * a,
+ c1.a * (S(1.0) - a) + c2.a * a);
+}
+
+/*
+ * Interpolate smoothly between three colors with barycentric coordinates.
+ */
+INLINE_MAYBE
+color_t color_interp2(color_t c1, color_t c2, color_t c3, scal_t b[3])
+{
+ return color_new(c1.r * b[0] + c2.r * b[1] + c3.r * b[2],
+ c1.g * b[0] + c2.g * b[1] + c3.g * b[2],
+ c1.b * b[0] + c2.b * b[1] + c3.b * b[2],
+ S(1.0));
+}
+
+