Use color-values-from-color-spec instead of color-name-to-rgb

Replace `color-name-to-rgb' with a new internal helper
`modus-themes--hex-to-rgb' that uses `color-values-from-color-spec'
(a C built-in since Emacs 28.1) to parse hex RGB strings without
any display dependency.

This fixes a crash when loading a Modus theme during early-init.el
on GUI Emacs (e.g. macOS Homebrew emacs-plus), where
`color-name-to-rgb' fails because `color-values' returns nil before
the display is ready.

The fix applies to all three direct call sites:
- `modus-themes-wcag-formula' (the critical one, called during
  theme loading)
- `modus-themes-generate-color-blend'
- `modus-themes-color-warm-p'

Fixes #198.
This commit is contained in:
Mike Olson 2026-02-16 15:04:35 -05:00
parent 0ace30e471
commit c475454d87

View file

@ -3748,6 +3748,16 @@ Info node `(modus-themes) Option for palette overrides'.")
;;;; Helper functions for theme setup
(defun modus-themes--hex-to-rgb (hex-color)
"Convert HEX-COLOR to a list of normalized RGB values.
Use `color-values-from-color-spec' (a C built-in since Emacs 28.1)
instead of `color-name-to-rgb' to avoid dependence on a display
connection. This matters when loading a theme during early init on
GUI Emacs, where `color-values' returns nil before the display is
ready (per issue #198)."
(mapcar (lambda (x) (/ x 65535.0))
(color-values-from-color-spec hex-color)))
;; This is the WCAG formula: https://www.w3.org/TR/WCAG20-TECHS/G18.html
(defun modus-themes--wcag-contribution (channel weight)
"Return the CHANNEL contribution to overall luminance given WEIGHT."
@ -3759,7 +3769,7 @@ Info node `(modus-themes) Option for palette overrides'.")
(defun modus-themes-wcag-formula (hex-color)
"Get WCAG value of color value HEX-COLOR.
The value is defined in hexadecimal RGB notation, such #123456."
(let ((channels (color-name-to-rgb hex-color))
(let ((channels (modus-themes--hex-to-rgb hex-color))
(weights '(0.2126 0.7152 0.0722))
(contribution nil))
(while channels
@ -7619,8 +7629,8 @@ For instance:
BLENDED-WITH-HEX is commensurate with COLOR. ALPHA is between 0.0 and 1.0,
inclusive."
(let* ((blend-rgb (modus-themes-blend
(color-name-to-rgb hex-color)
(color-name-to-rgb blended-with-hex)
(modus-themes--hex-to-rgb hex-color)
(modus-themes--hex-to-rgb blended-with-hex)
alpha))
(blend-hex (apply #'color-rgb-to-hex blend-rgb)))
(modus-themes--color-six-digits blend-hex)))
@ -7649,7 +7659,7 @@ inclusive."
"Return non-nil if COLOR is warm.
A warm color has more contribution from the red channel of light than
the blue one."
(pcase-let ((`(,r ,_ ,b) (color-name-to-rgb color)))
(pcase-let ((`(,r ,_ ,b) (modus-themes--hex-to-rgb color)))
(> r b)))
(defun modus-themes-color-is-warm-or-cool-p (color)