From 250739a41c0a0d57890b4067a7049e941857dc44 Mon Sep 17 00:00:00 2001 From: Caio Freitas de Oliveira Date: Wed, 5 Oct 2022 00:51:19 -0300 Subject: [PATCH] restore hsv_gradient --- src/CMakeLists.txt | 3 + src/conky.cc | 11 ++- src/hsv_gradient.cc | 221 ++++++++++++++++++++++++++++++++++++++++++++ src/hsv_gradient.h | 47 ++++++++++ src/main.cc | 3 + 5 files changed, 283 insertions(+), 2 deletions(-) create mode 100644 src/hsv_gradient.cc create mode 100644 src/hsv_gradient.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4f87eb5a..1c764353 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -302,6 +302,9 @@ endif(BUILD_INTEL_BACKLIGHT) if(BUILD_HCL_GRADIENT) set(hcl_gradient hcl_gradient.cc hcl_gradient.h) set(optional_sources ${optional_sources} ${hcl_gradient}) +elseif(BUILD_HSV_GRADIENT) + set(hsv_gradient hsv_gradient.cc hsv_gradient.h) + set(optional_sources ${optional_sources} ${hsv_gradient}) endif(BUILD_HCL_GRADIENT) if(BUILD_TESTS) diff --git a/src/conky.cc b/src/conky.cc index 4898e2fb..558d8369 100644 --- a/src/conky.cc +++ b/src/conky.cc @@ -133,6 +133,9 @@ #ifdef BUILD_HCL_GRADIENT #include "hcl_gradient.h" #endif /* BUILD_HCL_GRADIENT */ +#ifdef BUILD_HSV_GRADIENT +#include "hsv_gradient.h" +#endif /* BUILD_HSV_GRADIENT */ #ifdef BUILD_OLD_CONFIG #include "convertconf.h" @@ -1294,10 +1297,14 @@ int draw_each_line_inner(char *s, int special_index, int last_special_applied) { #ifdef BUILD_HCL_GRADIENT tmpcolour = do_hcl_gradient(w - 1, current->last_colour, current->first_colour); -#else /* BUILD_HCL_GRADIENT */ +#endif /* BUILD_HCL_GRADIENT */ +#ifdef BUILD_HSV_GRADIENT + tmpcolour = do_hsv_gradient(w - 1, current->last_colour, + current->first_colour); +#else /* BUILD_HSV_GRADIENT */ tmpcolour = do_gradient(w - 1, current->last_colour, current->first_colour); -#endif /* BUILD_HCL_GRADIENT */ +#endif /* BUILD_HSV_GRADIENT */ } colour_idx = 0; for (i = w - 2; i > -1; i--) { diff --git a/src/hsv_gradient.cc b/src/hsv_gradient.cc new file mode 100644 index 00000000..0962e0c3 --- /dev/null +++ b/src/hsv_gradient.cc @@ -0,0 +1,221 @@ +/* + * + * Conky, a system monitor, based on torsmo + * + * Any original torsmo code is licensed under the BSD license + * + * All code written since the fork of torsmo is licensed under the GPL + * + * Please see COPYING for details + * + * Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen + * Copyright (c) 2005-2021 Brenden Matthews, Philip Kovacs, et. al. + * (see AUTHORS) + * All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ +#include "hsv_gradient.h" +#include "colours.h" +#include "conky.h" +#include "logging.h" + +#ifdef BUILD_X11 +#include "x11.h" +#endif /* BUILD_X11 */ + +#define CONST_SCALE 512L +#define CONST_SCALE_HALF (CONST_SCALE / 2) +#define CONST_SCALE2 (CONST_SCALE * 2L) +#define CONST_SCALE4 (CONST_SCALE * 4L) +#define CONST_SCALE6 (CONST_SCALE * 6L) +#define CONST_SCALE60 (CONST_SCALE * 60L) +#define CONST_SCALE120 (CONST_SCALE * 120L) +#define CONST_SCALE180 (CONST_SCALE * 180L) +#define CONST_SCALE240 (CONST_SCALE * 240L) +#define CONST_SCALE300 (CONST_SCALE * 300L) +#define CONST_SCALE360 (CONST_SCALE * 360L) + +long to_decimal_scale(long value, long max_value) { + if (value == 0) { + return 0; + } else if (value > 0) { + return (value * CONST_SCALE + max_value - 1) / max_value; + } + return -((std::abs(value) * CONST_SCALE + max_value - 1) / max_value); +} + +long from_decimal_scale(long value, long max_value) { + if (value == 0) { + return 0; + } else if (value > 0) { + return (value * max_value + CONST_SCALE_HALF) / CONST_SCALE; + } + return -((std::abs(value) * max_value + CONST_SCALE_HALF) / CONST_SCALE); +} + +void scaled_rgb_to_scaled_hsv(long *const rgb, long *hsv) { + long val = + rgb[0] > rgb[1] ? std::max(rgb[0], rgb[2]) : std::max(rgb[1], rgb[2]); + long cmin = + rgb[0] < rgb[1] ? std::min(rgb[0], rgb[2]) : std::min(rgb[1], rgb[2]); + long delta = val - cmin; + + long hue; + + if (delta == 0) { + hue = 0; + } else { + long d; + long offset; + + if (rgb[0] == val) { + d = rgb[1] - rgb[2]; + offset = 0; + } else if (rgb[1] == val) { + d = rgb[2] - rgb[0]; + offset = CONST_SCALE2; + } else { + d = rgb[0] - rgb[1]; + offset = CONST_SCALE4; + } + long h = (CONST_SCALE * d + delta / 2) / delta + offset; + hue = 60L * ((CONST_SCALE6 + h) % CONST_SCALE6); + } + + long sat; + if (val == 0) { + sat = 0; + } else { + sat = (CONST_SCALE * delta + val / 2) / val; + } + + hsv[0] = hue; + hsv[1] = sat; + hsv[2] = val; +} + +void scaled_hsv_to_scaled_rgb(long *const hsv, long *rgb) { + long c = (hsv[2] * hsv[1] + CONST_SCALE_HALF) / CONST_SCALE; + + long hue = hsv[0] % CONST_SCALE360; + long x = (c * (CONST_SCALE - + std::abs(((hue + 30L) / 60L) % CONST_SCALE2 - CONST_SCALE)) + + CONST_SCALE_HALF) / + CONST_SCALE; + long m = hsv[2] - c; + + rgb[0] = m; + rgb[1] = m; + rgb[2] = m; + + if (hue < CONST_SCALE60) { + rgb[0] += c; + rgb[1] += x; + } else if (hue < CONST_SCALE120) { + rgb[0] += x; + rgb[1] += c; + } else if (hue < CONST_SCALE180) { + rgb[1] += c; + rgb[2] += x; + } else if (hue < CONST_SCALE240) { + rgb[1] += x; + rgb[2] += c; + } else if (hue < CONST_SCALE300) { + rgb[2] += c; + rgb[0] += x; + } else { + rgb[2] += x; + rgb[0] += c; + } +} + +/* this function returns the next colour between two colours in hsv space for a + * gradient */ +std::unique_ptr do_hsv_gradient(int width, + unsigned long first_colour, + unsigned long last_colour) { + long rgb1[3], rgb2[3], rgb3[3]; + long hsv1[3], hsv2[3]; + long hueDiff, satDiff, valDiff; + + int redshift = (2 * colour_depth / 3 + colour_depth % 3); + int greenshift = (colour_depth / 3); + + // Make sure the width is always at least 2 + width = std::max(2, width); + + std::unique_ptr colours(new unsigned long[width]); + + if (colour_depth == 0) { set_up_gradient(); } + + rgb1[0] = to_decimal_scale((first_colour & redmask) >> redshift, + redmask >> redshift); + rgb1[1] = to_decimal_scale((first_colour & greenmask) >> greenshift, + greenmask >> greenshift); + rgb1[2] = to_decimal_scale(first_colour & bluemask, bluemask); + rgb2[0] = to_decimal_scale((last_colour & redmask) >> redshift, + redmask >> redshift); + rgb2[1] = to_decimal_scale((last_colour & greenmask) >> greenshift, + greenmask >> greenshift); + rgb2[2] = to_decimal_scale(last_colour & bluemask, bluemask); + + scaled_rgb_to_scaled_hsv(rgb1, hsv1); + scaled_rgb_to_scaled_hsv(rgb2, hsv2); + + hueDiff = hsv2[0] - hsv1[0]; + // use shortest hue path + if (hueDiff > CONST_SCALE180) { + hueDiff = hueDiff - CONST_SCALE360; + } else if (hueDiff < -CONST_SCALE180) { + hueDiff = hueDiff + CONST_SCALE360; + } + satDiff = hsv2[1] - hsv1[1]; + valDiff = hsv2[2] - hsv1[2]; + + colours[0] = first_colour; + colours[width - 1] = last_colour; + + for (int i = 1; i < (width - 1); i++) { + long k; + + long divisor = width - i; + k = (hueDiff + divisor / 2) / divisor; + hueDiff -= k; + long h = hsv1[0] + k; + if (h < 0) { + hsv1[0] = CONST_SCALE360 + h; + } else { + hsv1[0] = h; + } + + k = (satDiff + divisor / 2) / divisor; + satDiff -= k; + hsv1[1] += k; + + k = (valDiff + divisor / 2) / divisor; + valDiff -= k; + hsv1[2] += k; + + scaled_hsv_to_scaled_rgb(hsv1, rgb3); + + long red3 = from_decimal_scale(rgb3[0], bluemask); + long green3 = from_decimal_scale(rgb3[1], bluemask); + long blue3 = from_decimal_scale(rgb3[2], bluemask); + + colours[i] = (red3 << redshift) | (green3 << greenshift) | blue3; + } + + return colours; +} diff --git a/src/hsv_gradient.h b/src/hsv_gradient.h new file mode 100644 index 00000000..8beba631 --- /dev/null +++ b/src/hsv_gradient.h @@ -0,0 +1,47 @@ +/* + * + * Conky, a system monitor, based on torsmo + * + * Any original torsmo code is licensed under the BSD license + * + * All code written since the fork of torsmo is licensed under the GPL + * + * Please see COPYING for details + * + * Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen + * Copyright (c) 2005-2021 Brenden Matthews, Philip Kovacs, et. al. + * (see AUTHORS) + * All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ +#ifndef _HSV_GRADIENT_H +#define _HSV_GRADIENT_H + +#include + +// needed by hsv_gradient +extern short colour_depth; +extern long redmask, greenmask, bluemask; +extern void set_up_gradient(); + +std::unique_ptr do_hsv_gradient(int, unsigned long, + unsigned long); + +long to_decimal_scale(long value, long max_value); +long from_decimal_scale(long value, long max_value); +void scaled_rgb_to_scaled_hsv(long *const rgb, long *hsv); +void scaled_hsv_to_scaled_rgb(long *const hsv, long *rgb); + +#endif /* _HSV_GRADIENT_H */ diff --git a/src/main.cc b/src/main.cc index 61763868..38342cef 100644 --- a/src/main.cc +++ b/src/main.cc @@ -182,6 +182,9 @@ static void print_version() { #ifdef BUILD_HCL_GRADIENT << _(" * HCL Gradient\n") #endif /* BUILD_HCL_GRADIENT */ +#ifdef BUILD_HSV_GRADIENT + << _(" * HSV Gradient\n") +#endif /* BUILD_HSV_GRADIENT */ #if defined BUILD_AUDACIOUS || defined BUILD_CMUS || defined BUILD_MPD || \ defined BUILD_MOC || defined BUILD_XMMS2 << _("\n Music detection:\n")