i3lock-color

The world's most popular non-default computer lockscreen.
Index Commits Files Refs README LICENSE
commit 1ecd26e59c969f410219e8446612f7da76bff1de
parent 8011b0c9abd96cfb7aa68e428129084cba82502e
Author: Chris Guillott <chris@techfo.xyz>
Date:   Tue,  5 Dec 2017 13:09:27 -0500

merge existing work in (stuff is a bit broken currently)

Diffstat:
MMakefile.am | 15++++++++++++---
Mblur.c | 2+-
Mblur.h | 2+-
Mblur_simd.c | 24+++++++++++++++++-------
Mconfigure.ac | 9++++++---
Munlock_indicator.c | 147++++++++++++++++++++++++++++++++++++++++++-------------------------------------
Munlock_indicator.h | 14+++++++-------
7 files changed, 122 insertions(+), 91 deletions(-)
diff --git a/Makefile.am b/Makefile.am
@@ -21,7 +21,9 @@ i3lock_CFLAGS = \
     $(XCB_UTIL_CFLAGS) \
     $(XKBCOMMON_CFLAGS) \
     $(CAIRO_CFLAGS) \
-    $(CODE_COVERAGE_CFLAGS)
+    $(CODE_COVERAGE_CFLAGS) \
+    $(X11_CFLAGS) \
+    $(SIMD_CFLAGS)
 
 i3lock_CPPFLAGS = \
     $(AM_CPPFLAGS) \
@@ -33,7 +35,8 @@ i3lock_LDADD = \
     $(XCB_UTIL_LIBS) \
     $(XKBCOMMON_LIBS) \
     $(CAIRO_LIBS) \
-    $(CODE_COVERAGE_LDFLAGS)
+    $(CODE_COVERAGE_LDFLAGS) \
+    $(X11_LIBS)
 
 i3lock_SOURCES = \
     cursors.h \
@@ -44,7 +47,13 @@ i3lock_SOURCES = \
     unlock_indicator.c \
     unlock_indicator.h \
     xcb.c \
-    xcb.h
+    xcb.h \
+    tinyexpr.c \
+    tinyexpr.h \
+    blur_simd.c \
+    blur.c \
+    blur.h 
+
 
 EXTRA_DIST = \
     $(pamd_files) \
diff --git a/blur.c b/blur.c
@@ -65,7 +65,7 @@ blur_image_surface (cairo_surface_t *surface, int sigma)
 
     // according to a paper by Peter Kovesi [1], box filter of width w, equals to Gaussian blur of following sigma:
     // σ_av = sqrt((w*w-1)/12)
-    // for our 7x7 filter we have σ_av = 2.0.
+    // for our 8x8 filter we have σ_av = 2.0.
     // applying the same Gaussian filter n times results in σ_n = sqrt(n*σ_av*σ_av) [2]
     // after some trivial math, we arrive at n = ((σ_d)/(σ_av))^2
     // since it's a box blur filter, n >= 3
diff --git a/blur.h b/blur.h
@@ -4,7 +4,7 @@
 #include <stdint.h>
 #include <cairo.h>
 
-#define KERNEL_SIZE 7 
+#define KERNEL_SIZE 8 
 #define SIGMA_AV 2
 #define HALF_KERNEL KERNEL_SIZE / 2
 
diff --git a/blur_simd.c b/blur_simd.c
@@ -10,24 +10,30 @@
 #include "blur.h"
 #include <xmmintrin.h>
 
+#include <stdio.h>
+
 // number of xmm registers needed to store input pixels for given kernel size
 #define REGISTERS_CNT (KERNEL_SIZE + 4/2) / 4
 
 void blur_impl_horizontal_pass_sse2(uint32_t *src, uint32_t *dst, int width, int height) {
+    printf("height %d by width %d\n", height, width);
     for (int row = 0; row < height; row++) {
+        printf("row %d\n", row);
         for (int column = 0; column < width; column++, src++) {
+            printf("\tcol %d\n", column);
             __m128i rgbaIn[REGISTERS_CNT];
 
             // handle borders
             int leftBorder = column < HALF_KERNEL;
-            int rightBorder = column > width - HALF_KERNEL;
+            int rightBorder = column > (width - HALF_KERNEL);
+            // +1 to make memory checkers not complain
             uint32_t _rgbaIn[KERNEL_SIZE] __attribute__((aligned(16)));
             int i = 0;
             if (leftBorder) {
-                // for kernel size 7x7 and column == 0, we have:
-                // x x x P0 P1 P2 P3
-                // first loop mirrors P{0..3} to fill x's,
-                // second one loads P{0..3}
+                // for kernel size 8x8 and column == 0, we have:
+                // x x x x P0 P1 P2 P3
+                // first loop mirrors P{0..4} to fill x's,
+                // second one loads P{0..4}
                 for (; i < HALF_KERNEL - column; i++)
                     _rgbaIn[i] = *(src + (HALF_KERNEL - i));
                 for (; i < KERNEL_SIZE; i++)
@@ -44,8 +50,10 @@ void blur_impl_horizontal_pass_sse2(uint32_t *src, uint32_t *dst, int width, int
                 for (int k = 0; k < REGISTERS_CNT; k++)
                     rgbaIn[k] = _mm_load_si128((__m128i*)(_rgbaIn + 4*k));
             } else {
-                for (int k = 0; k < REGISTERS_CNT; k++)
-                    rgbaIn[k] = _mm_loadu_si128((__m128i*)(src + 4*k - HALF_KERNEL));
+                for (int k = 0; k < REGISTERS_CNT; k++) {
+                    printf("\t\tk: %d\n", k);
+                    rgbaIn[k] = _mm_load_si128((__m128i*)(src + 4*k - HALF_KERNEL));
+                }
             }
 
             __m128i zero = _mm_setzero_si128();
@@ -57,10 +65,12 @@ void blur_impl_horizontal_pass_sse2(uint32_t *src, uint32_t *dst, int width, int
 
             // kernel size equals to 7, but we can only load multiples of 4 pixels
             // we have to set 8th pixel to zero
+/*
             acc = _mm_add_epi16(acc, _mm_andnot_si128(_mm_set_epi32(0xFFFFFFFF, 0xFFFFFFFF, 0, 0), 
                                                       _mm_unpackhi_epi8(rgbaIn[1], zero)));
             acc = _mm_add_epi32(_mm_unpacklo_epi16(acc, zero), 
                                 _mm_unpackhi_epi16(acc, zero));
+*/
 
             // multiplication is significantly faster than division
             acc = _mm_cvtps_epi32(_mm_mul_ps(_mm_cvtepi32_ps(acc),
diff --git a/configure.ac b/configure.ac
@@ -2,7 +2,7 @@
 # Run autoreconf -fi to generate a configure script from this file.
 
 AC_PREREQ([2.69])
-AC_INIT([i3lock], [2.10], [https://github.com/i3/i3lock/issues])
+AC_INIT([i3lock-color], [2.10], [https://github.com/chrjguill/i3lock-color/issues])
 # For AX_EXTEND_SRCDIR
 AX_ENABLE_BUILDDIR
 AM_INIT_AUTOMAKE([foreign subdir-objects -Wall no-dist-gzip dist-bzip2])
@@ -34,7 +34,7 @@ AS_IF([test -d ${srcdir}/.git],
         VERSION="$(git -C ${srcdir} describe --tags --abbrev=0)"
         I3LOCK_VERSION="$(git -C ${srcdir} describe --tags --always) ($(git -C ${srcdir} log --pretty=format:%cd --date=short -n1), branch \\\"$(git -C ${srcdir} describe --tags --always --all | sed s:heads/::)\\\")"
         # Mirrors what libi3/is_debug_build.c does:
-        is_release=$(test $(echo "${I3LOCK_VERSION}" | cut -d '(' -f 1 | wc -m) -lt 10 && echo yes || echo no)
+        is_release=$(test $(echo "${I3LOCK_VERSION}" | cut -d '(' -f 1 | wc -m) -lt 11 && echo yes || echo no)
       ],
       [
         VERSION="$(cut -d '-' -f 1 ${srcdir}/I3LOCK_VERSION | cut -d ' ' -f 1)"
@@ -82,11 +82,14 @@ AC_SEARCH_LIBS([iconv_open], [iconv], , [AC_MSG_FAILURE([cannot find the require
 
 dnl Each prefix corresponds to a source tarball which users might have
 dnl downloaded in a newer version and would like to overwrite.
-PKG_CHECK_MODULES([XCB], [xcb xcb-xkb xcb-xinerama xcb-randr])
+PKG_CHECK_MODULES([XCB], [xcb xcb-xkb xcb-xinerama xcb-randr xcb-composite])
 PKG_CHECK_MODULES([XCB_IMAGE], [xcb-image])
 PKG_CHECK_MODULES([XCB_UTIL], [xcb-event xcb-util xcb-atom])
 PKG_CHECK_MODULES([XKBCOMMON], [xkbcommon xkbcommon-x11])
 PKG_CHECK_MODULES([CAIRO], [cairo])
+PKG_CHECK_MODULES([X11], [x11])
+
+SIMD_CFLAGS=" -funroll-loops -msse2 -std=c99 -pipe -O2"
 
 # Checks for programs.
 AC_PROG_AWK
diff --git a/unlock_indicator.c b/unlock_indicator.c
@@ -145,22 +145,22 @@ unlock_state_t unlock_state;
 auth_state_t auth_state;
 
 // color arrays
-rgba_t insidever16[4];
-rgba_t insidewrong16[4];
-rgba_t inside16[4];
-rgba_t ringver16[4];
-rgba_t ringwrong16[4];
-rgba_t ring16[4];
-rgba_t line16[4];
-rgba_t text16[4];
-rgba_t layout16[4];
-rgba_t time16[4];
-rgba_t date16[4];
-rgba_t keyhl16[4];
-rgba_t bshl16[4];
-rgba_t sep16[4];
+rgba_t insidever16;
+rgba_t insidewrong16;
+rgba_t inside16;
+rgba_t ringver16;
+rgba_t ringwrong16;
+rgba_t ring16;
+rgba_t line16;
+rgba_t text16;
+rgba_t layout16;
+rgba_t time16;
+rgba_t date16;
+rgba_t keyhl16;
+rgba_t bshl16;
+rgba_t sep16;
 // just rgb
-rgb_t  rgb16[3];
+rgb_t  rgb16;
 
 /*
  * Initialize all the color arrays once.
@@ -182,32 +182,32 @@ rgb_t  rgb16[3];
                      (strtol(colorstring_tmparr[3], NULL, 16))};
  */
 
-inline void set_color(char* dest, const char* src, int offset) {
+void set_color(char* dest, const char* src, int offset) {
     dest[0] = src[offset];
     dest[1] = src[offset + 1];
     dest[2] = '\0';
 }
 
-inline void colorgen(rgba_str_t* tmp, const char* src, rgba_t* dest) {
+void colorgen(rgba_str_t* tmp, const char* src, rgba_t* dest) {
     set_color(tmp->red, src, 0);
     set_color(tmp->green, src, 2);
     set_color(tmp->blue, src, 4);
     set_color(tmp->alpha, src, 6);
 
-    dest->red = strtol(tmp->red, NULL, 16);
-    dest->green = strtol(tmp->green, NULL, 16);
-    dest->blue = strtol(tmp->blue, NULL, 16);
-    dest->alpha = strtol(tmp->alpha, NULL, 16);
+    dest->red = strtol(tmp->red, NULL, 16) / 255.0;
+    dest->green = strtol(tmp->green, NULL, 16) / 255.0;
+    dest->blue = strtol(tmp->blue, NULL, 16) / 255.0;
+    dest->alpha = strtol(tmp->alpha, NULL, 16) / 255.0;
 }
 
-inline void colorgen_rgb(rgb_str_t* tmp, const char* src, rgb_t* dest) {
+void colorgen_rgb(rgb_str_t* tmp, const char* src, rgb_t* dest) {
     set_color(tmp->red, src, 0);
     set_color(tmp->green, src, 2);
     set_color(tmp->blue, src, 4);
 
-    dest->red = strtol(tmp->red, NULL, 16);
-    dest->green = strtol(tmp->green, NULL, 16);
-    dest->blue = strtol(tmp->blue, NULL, 16);
+    dest->red = strtol(tmp->red, NULL, 16) / 255.0;
+    dest->green = strtol(tmp->green, NULL, 16) / 255.0;
+    dest->blue = strtol(tmp->blue, NULL, 16) / 255.0;
 }
 
 void init_colors_once(void) {
@@ -215,21 +215,21 @@ void init_colors_once(void) {
     rgb_str_t  tmp_rgb;
 
     /* build indicator color arrays */
-    colorgen(&tmp, insidevercolor, insidever16);
-    colorgen(&tmp, insidewrongcolor, insidewrong16);
-    colorgen(&tmp, insidecolor, inside16);
-    colorgen(&tmp, ringvercolor, ringver16);
-    colorgen(&tmp, ringwrongcolor, ringwrong16);
-    colorgen(&tmp, ringcolor, ring16);
-    colorgen(&tmp, linecolor, line16);
-    colorgen(&tmp, textcolor, text16);
-    colorgen(&tmp, layoutcolor, layout16);
-    colorgen(&tmp, timecolor, time16);
-    colorgen(&tmp, datecolor, date16);
-    colorgen(&tmp, keyhlcolor, keyhl16);
-    colorgen(&tmp, bshlcolor, bshl16);
-    colorgen(&tmp, separatorcolor, sep16);
-    colorgen_rgb(&tmp_rgb, color, rgb16);
+    colorgen(&tmp, insidevercolor, &insidever16);
+    colorgen(&tmp, insidewrongcolor, &insidewrong16);
+    colorgen(&tmp, insidecolor, &inside16);
+    colorgen(&tmp, ringvercolor, &ringver16);
+    colorgen(&tmp, ringwrongcolor, &ringwrong16);
+    colorgen(&tmp, ringcolor, &ring16);
+    colorgen(&tmp, linecolor, &line16);
+    colorgen(&tmp, textcolor, &text16);
+    colorgen(&tmp, layoutcolor, &layout16);
+    colorgen(&tmp, timecolor, &time16);
+    colorgen(&tmp, datecolor, &date16);
+    colorgen(&tmp, keyhlcolor, &keyhl16);
+    colorgen(&tmp, bshlcolor, &bshl16);
+    colorgen(&tmp, separatorcolor, &sep16);
+    colorgen_rgb(&tmp_rgb, color, &rgb16);
 }
 
 /*
@@ -238,8 +238,8 @@ void init_colors_once(void) {
  *
  */
 static double scaling_factor(void) {
-    const int dpi = (double)screen->height_in_pixels * 25.4 /
-                    (double)screen->height_in_millimeters;
+    const int dpi = (double) screen->height_in_pixels * 25.4 /
+                    (double) screen->height_in_millimeters;
     return (dpi / 96.0);
 }
 
@@ -301,7 +301,7 @@ xcb_pixmap_t draw_image(uint32_t *resolution) {
             }
         }
     } else {
-        cairo_set_source_rgb(xcb_ctx, rgb16->red / 255.0, rgb16->green / 255.0, rgb16->blue / 255.0);
+        cairo_set_source_rgb(xcb_ctx, rgb16.red, rgb16.green, rgb16.blue);
         cairo_rectangle(xcb_ctx, 0, 0, resolution[0], resolution[1]);
         cairo_fill(xcb_ctx);
     }
@@ -331,14 +331,14 @@ xcb_pixmap_t draw_image(uint32_t *resolution) {
         switch (auth_state) {
             case STATE_AUTH_VERIFY:
             case STATE_AUTH_LOCK:
-                cairo_set_source_rgba(ctx, (double)insidever16->red/255, (double)insidever16->green/255, (double)insidever16->blue/255, (double)insidever16->alpha/255);
+                cairo_set_source_rgba(ctx, insidever16.red, insidever16.green, insidever16.blue, insidever16.alpha);
                 break;
             case STATE_AUTH_WRONG:
             case STATE_I3LOCK_LOCK_FAILED:
-                cairo_set_source_rgba(ctx, (double)insidewrong16->red/255, (double)insidewrong16->green/255, (double)insidewrong16->blue/255, (double)insidewrong16->alpha/255);
+                cairo_set_source_rgba(ctx, insidewrong16.red, insidewrong16.green, insidewrong16.blue, insidewrong16.alpha);
                 break;
             default:
-                cairo_set_source_rgba(ctx, (double)inside16->red/255, (double)inside16->green/255, (double)inside16->blue/255, (double)inside16->alpha/255);
+                cairo_set_source_rgba(ctx, inside16.red, inside16.green, inside16.blue, inside16.alpha);
                 break;
         }
         cairo_fill_preserve(ctx);
@@ -346,31 +346,31 @@ xcb_pixmap_t draw_image(uint32_t *resolution) {
         switch (auth_state) {
             case STATE_AUTH_VERIFY:
             case STATE_AUTH_LOCK:
-                cairo_set_source_rgba(ctx, (double)ringver16->red/255, (double)ringver16->green/255, (double)ringver16->blue/255, (double)ringver16->alpha/255);
+                cairo_set_source_rgba(ctx, ringver16.red, ringver16.green, ringver16.blue, ringver16.alpha);
                 if (internal_line_source == 1) {
-                  line16->red = ringver16->red;
-                  line16->green = ringver16->green;
-                  line16->blue = ringver16->blue;
-                  line16->alpha = ringver16->alpha;
+                  line16.red = ringver16.red;
+                  line16.green = ringver16.green;
+                  line16.blue = ringver16.blue;
+                  line16.alpha = ringver16.alpha;
                 }
                 break;
             case STATE_AUTH_WRONG:
             case STATE_I3LOCK_LOCK_FAILED:
-                cairo_set_source_rgba(ctx, (double)ringwrong16->red/255, (double)ringwrong16->green/255, (double)ringwrong16->blue/255, (double)ringwrong16->alpha/255);
+                cairo_set_source_rgba(ctx, ringwrong16.red, ringwrong16.green, ringwrong16.blue, ringwrong16.alpha);
                 if (internal_line_source == 1) {
-                  line16->red = ringwrong16->red;
-                  line16->green = ringwrong16->green;
-                  line16->blue = ringwrong16->blue;
-                  line16->alpha = ringwrong16->alpha;
+                  line16.red = ringwrong16.red;
+                  line16.green = ringwrong16.green;
+                  line16.blue = ringwrong16.blue;
+                  line16.alpha = ringwrong16.alpha;
                 }
                 break;
             case STATE_AUTH_IDLE:
-                cairo_set_source_rgba(ctx, (double)ring16->red/255, (double)ring16->green/255, (double)ring16->blue/255, (double)ring16->alpha/255);
+                cairo_set_source_rgba(ctx, ring16.red, ring16.green, ring16.blue, ring16.alpha);
                 if (internal_line_source == 1) {
-                  line16->red = ring16->red;
-                  line16->green = ring16->green;
-                  line16->blue = ring16->blue;
-                  line16->alpha = ring16->alpha;
+                  line16.red = ring16.red;
+                  line16.green = ring16.green;
+                  line16.blue = ring16.blue;
+                  line16.alpha = ring16.alpha;
                 }
                 break;
         }
@@ -378,7 +378,7 @@ xcb_pixmap_t draw_image(uint32_t *resolution) {
 
         /* Draw an inner separator line. */
         if (internal_line_source != 2) { //pretty sure this only needs drawn if it's being drawn over the inside?
-          cairo_set_source_rgba(ctx, (double)line16->red/255, (double)line16->green/255, (double)line16->blue/255, (double)line16->alpha/255);
+          cairo_set_source_rgba(ctx, line16.red, line16.green, line16.blue, line16.alpha);
           cairo_set_line_width(ctx, 2.0);
           cairo_arc(ctx,
                     BUTTON_CENTER /* x */,
@@ -397,7 +397,7 @@ xcb_pixmap_t draw_image(uint32_t *resolution) {
         /* We don't want to show more than a 3-digit number. */
         char buf[4];
 
-        cairo_set_source_rgba(ctx, (double)text16->red/255, (double)text16->green/255, (double)text16->blue/255, (double)text16->alpha/255);
+        cairo_set_source_rgba(ctx, text16.red, text16.green, text16.blue, text16.alpha);
         cairo_select_font_face(ctx, status_font, CAIRO_FONT_SLANT_NORMAL,
                 CAIRO_FONT_WEIGHT_NORMAL);
         cairo_set_font_size(ctx, text_size);
@@ -472,17 +472,17 @@ xcb_pixmap_t draw_image(uint32_t *resolution) {
                       highlight_start + (M_PI / 3.0));
             if (unlock_state == STATE_KEY_ACTIVE) {
                 /* For normal keys, we use a lighter green. */ //lol no
-                cairo_set_source_rgba(ctx, (double)keyhl16->red/255, (double)keyhl16->green/255, (double)keyhl16->blue/255, (double)keyhl16->alpha/255);
+                cairo_set_source_rgba(ctx, keyhl16.red, keyhl16.green, keyhl16.blue, keyhl16.alpha);
             } else {
                 /* For backspace, we use red. */ //lol no
-                cairo_set_source_rgba(ctx, (double)bshl16->red/255, (double)bshl16->green/255, (double)bshl16->blue/255, (double)bshl16->alpha/255);
+                cairo_set_source_rgba(ctx, bshl16.red, bshl16.green, bshl16.blue, bshl16.alpha);
             }
 
             cairo_stroke(ctx);
 
             /* Draw two little separators for the highlighted part of the
              * unlock indicator. */
-            cairo_set_source_rgba(ctx, (double)sep16->red/255, (double)sep16->green/255, (double)sep16->blue/255, (double)sep16->alpha/255);
+            cairo_set_source_rgba(ctx, sep16.red, sep16.green, sep16.blue, sep16.alpha);
             cairo_arc(ctx,
                       BUTTON_CENTER /* x */,
                       BUTTON_CENTER /* y */,
@@ -517,7 +517,7 @@ xcb_pixmap_t draw_image(uint32_t *resolution) {
         if (text) {
             cairo_set_font_size(time_ctx, time_size);
             cairo_select_font_face(time_ctx, time_font, CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
-            cairo_set_source_rgba(time_ctx, (double)time16->red/255, (double)time16->green/255, (double)time16->blue/255, (double)time16->alpha/255);
+            cairo_set_source_rgba(time_ctx, time16.red, time16.green, time16.blue, time16.alpha);
 
             cairo_text_extents(time_ctx, text, &extents);
             switch(time_align) {
@@ -542,7 +542,7 @@ xcb_pixmap_t draw_image(uint32_t *resolution) {
 
         if (date) {
             cairo_select_font_face(date_ctx, date_font, CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
-            cairo_set_source_rgba(date_ctx, (double)date16->red/255, (double)date16->green/255, (double)date16->blue/255, (double)date16->alpha/255);
+            cairo_set_source_rgba(date_ctx, date16.red, date16.green, date16.blue, date16.alpha);
             cairo_set_font_size(date_ctx, date_size);
 
             cairo_text_extents(date_ctx, date, &extents);
@@ -568,7 +568,7 @@ xcb_pixmap_t draw_image(uint32_t *resolution) {
         }
         if (layout_text) {
             cairo_select_font_face(layout_ctx, layout_font, CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
-            cairo_set_source_rgba(layout_ctx, (double)layout16->red/255, (double)layout16->green/255, (double)layout16->blue/255, (double)layout16->alpha/255);
+            cairo_set_source_rgba(layout_ctx, layout16.red, layout16.green, layout16.blue, layout16.alpha);
             cairo_set_font_size(layout_ctx, layout_size);
 
             cairo_text_extents(layout_ctx, layout_text, &extents);
@@ -763,6 +763,15 @@ xcb_pixmap_t draw_image(uint32_t *resolution) {
             cairo_fill(xcb_ctx);
         }
     }
+    
+    te_free(te_ind_x_expr);
+    te_free(te_ind_y_expr);
+    te_free(te_time_x_expr);
+    te_free(te_time_y_expr);
+    te_free(te_date_x_expr);
+    te_free(te_date_y_expr);
+    te_free(te_layout_x_expr);
+    te_free(te_layout_y_expr);
 
     cairo_surface_destroy(xcb_output);
     cairo_surface_destroy(time_output);
diff --git a/unlock_indicator.h b/unlock_indicator.h
@@ -4,9 +4,9 @@
 #include <ev.h>
 
 typedef struct rgb {
-    uint32_t red;
-    uint32_t green;
-    uint32_t blue;
+    double red;
+    double green;
+    double blue;
 } rgb_t;
 
 typedef struct rgb_str {
@@ -16,10 +16,10 @@ typedef struct rgb_str {
 } rgb_str_t;
 
 typedef struct rgba {
-    uint32_t red;
-    uint32_t green;
-    uint32_t blue;
-    uint32_t alpha;
+    double red;
+    double green;
+    double blue;
+    double alpha;
 } rgba_t;
 
 typedef struct rgba_str {