diff options
| author | Pip Cet | 2019-07-22 02:40:35 +0000 |
|---|---|---|
| committer | Eli Zaretskii | 2019-07-27 14:05:46 +0300 |
| commit | 357399014acacc75bd1825fb2f498f1a4be7b362 (patch) | |
| tree | fbbfbca7fed181b564f5814c6941297e6f5f0372 | |
| parent | e310843d9dc106187d0e45ef7f0b9cd90a881eec (diff) | |
| download | emacs-357399014acacc75bd1825fb2f498f1a4be7b362.tar.gz emacs-357399014acacc75bd1825fb2f498f1a4be7b362.zip | |
Use the CSS convention for #RGB colors (bug#36304)
* src/xterm.c (x_parse_color): Change interpretation of #RGB color
triplets to match CSS rather than X conventions.
* lisp/term/tty-colors.el (tty-color-standard-values): Change
interpretation of #RGB color triplets to match CSS rather than X
conventions. Allow upper-case digits. Fix rgb:R/G/B
interpretation.
* doc/emacs/display.texi (Colors): Specify the convention used for
"#RGB" color triplets.
* test/lisp/tty-colors-tests.el: New file.
* etc/NEWS: Mention the change.
| -rw-r--r-- | doc/emacs/display.texi | 18 | ||||
| -rw-r--r-- | etc/NEWS | 7 | ||||
| -rw-r--r-- | lisp/term/tty-colors.el | 74 | ||||
| -rw-r--r-- | src/xterm.c | 33 |
4 files changed, 88 insertions, 44 deletions
diff --git a/doc/emacs/display.texi b/doc/emacs/display.texi index 0ce291335a9..8e842bea179 100644 --- a/doc/emacs/display.texi +++ b/doc/emacs/display.texi | |||
| @@ -556,14 +556,14 @@ Font Lock mode. | |||
| 556 | 556 | ||
| 557 | @node Colors | 557 | @node Colors |
| 558 | @section Colors for Faces | 558 | @section Colors for Faces |
| 559 | @cindex color name | ||
| 560 | @cindex RGB triplet | ||
| 561 | 559 | ||
| 562 | Faces can have various foreground and background colors. When you | 560 | Faces can have various foreground and background colors. When you |
| 563 | specify a color for a face---for instance, when customizing the face | 561 | specify a color for a face---for instance, when customizing the face |
| 564 | (@pxref{Face Customization})---you can use either a @dfn{color name} | 562 | (@pxref{Face Customization})---you can use either a @dfn{color name} |
| 565 | or an @dfn{RGB triplet}. | 563 | or an @dfn{RGB triplet}. |
| 566 | 564 | ||
| 565 | @subsection Color Names | ||
| 566 | @cindex color name | ||
| 567 | @findex list-colors-display | 567 | @findex list-colors-display |
| 568 | @vindex list-colors-sort | 568 | @vindex list-colors-sort |
| 569 | A color name is a pre-defined name, such as @samp{dark orange} or | 569 | A color name is a pre-defined name, such as @samp{dark orange} or |
| @@ -578,12 +578,16 @@ such terminals. However, Emacs understands X11 color names even on | |||
| 578 | text terminals; if a face is given a color specified by an X11 color | 578 | text terminals; if a face is given a color specified by an X11 color |
| 579 | name, it is displayed using the closest-matching terminal color. | 579 | name, it is displayed using the closest-matching terminal color. |
| 580 | 580 | ||
| 581 | @subsection RGB Triplets | ||
| 582 | @cindex RGB triplet | ||
| 581 | An RGB triplet is a string of the form @samp{#RRGGBB}. Each of the | 583 | An RGB triplet is a string of the form @samp{#RRGGBB}. Each of the |
| 582 | R, G, and B components is a hexadecimal number specifying the | 584 | primary color components is represented by a hexadecimal number |
| 583 | component's relative intensity, one to four digits long (usually two | 585 | between @samp{00} (intensity 0) and @samp{FF} (the maximum intensity). |
| 584 | digits are used). The components must have the same number of digits. | 586 | It is also possible to use one, three, or four hex digits for each |
| 585 | For hexadecimal values A to F, either upper or lower case are | 587 | component, so @samp{red} can be represented as @samp{#F00}, |
| 586 | acceptable. | 588 | @samp{#fff000000}, or @samp{#ffff00000000}. The components must have |
| 589 | the same number of digits. For hexadecimal values A to F, either | ||
| 590 | upper or lower case are acceptable. | ||
| 587 | 591 | ||
| 588 | The @kbd{M-x list-colors-display} command also shows the equivalent | 592 | The @kbd{M-x list-colors-display} command also shows the equivalent |
| 589 | RGB triplet for each named color. For instance, @samp{medium sea | 593 | RGB triplet for each named color. For instance, @samp{medium sea |
| @@ -407,6 +407,12 @@ names in xref buffers. | |||
| 407 | 407 | ||
| 408 | ** New variable `file-size-function' controls how file sizes are displayed. | 408 | ** New variable `file-size-function' controls how file sizes are displayed. |
| 409 | 409 | ||
| 410 | +++ | ||
| 411 | ** Emacs now interprets RGB triplets like HTML, SVG, and CSS do. | ||
| 412 | |||
| 413 | The X convention previously used differed slightly, particularly for | ||
| 414 | RGB triplets with a single hexadecimal digit per component. | ||
| 415 | |||
| 410 | 416 | ||
| 411 | * Editing Changes in Emacs 27.1 | 417 | * Editing Changes in Emacs 27.1 |
| 412 | 418 | ||
| @@ -1509,7 +1515,6 @@ automatically updates. In the buffer, you can use 's q' or 's e' to | |||
| 1509 | signal a thread with quit or error respectively, or get a snapshot | 1515 | signal a thread with quit or error respectively, or get a snapshot |
| 1510 | backtrace with 'b'. | 1516 | backtrace with 'b'. |
| 1511 | 1517 | ||
| 1512 | |||
| 1513 | ** thingatpt.el | 1518 | ** thingatpt.el |
| 1514 | 1519 | ||
| 1515 | --- | 1520 | --- |
diff --git a/lisp/term/tty-colors.el b/lisp/term/tty-colors.el index 5af8170203e..43c1071ceb7 100644 --- a/lisp/term/tty-colors.el +++ b/lisp/term/tty-colors.el | |||
| @@ -919,57 +919,63 @@ FRAME defaults to the selected frame." | |||
| 919 | The result is a list of integer RGB values--(RED GREEN BLUE). | 919 | The result is a list of integer RGB values--(RED GREEN BLUE). |
| 920 | These values range from 0 to 65535; white is (65535 65535 65535). | 920 | These values range from 0 to 65535; white is (65535 65535 65535). |
| 921 | 921 | ||
| 922 | The returned value reflects the standard X definition of COLOR, | 922 | The returned value reflects the standard Emacs definition of |
| 923 | regardless of whether the terminal can display it, so the return value | 923 | COLOR (see the info node `(emacs) Colors'), regardless of whether |
| 924 | should be the same regardless of what display is being used." | 924 | the terminal can display it, so the return value should be the |
| 925 | same regardless of what display is being used." | ||
| 925 | (let ((len (length color))) | 926 | (let ((len (length color))) |
| 926 | (cond ((and (>= len 4) ;; X-style "#XXYYZZ" color spec | 927 | (cond ((and (>= len 4) ;; HTML/CSS/SVG-style "#XXYYZZ" color spec |
| 927 | (eq (aref color 0) ?#) | 928 | (eq (aref color 0) ?#) |
| 928 | (member (aref color 1) | 929 | (member (aref color 1) |
| 929 | '(?0 ?1 ?2 ?3 ?4 ?5 ?6 ?7 ?8 ?9 | 930 | '(?0 ?1 ?2 ?3 ?4 ?5 ?6 ?7 ?8 ?9 |
| 930 | ?a ?b ?c ?d ?e ?f))) | 931 | ?a ?b ?c ?d ?e ?f |
| 931 | ;; Translate the string "#XXYYZZ" into a list | 932 | ?A ?B ?C ?D ?E ?F))) |
| 932 | ;; of numbers (XX YY ZZ). If the primary colors | 933 | ;; Translate the string "#XXYYZZ" into a list of numbers |
| 933 | ;; are specified with less than 4 hex digits, | 934 | ;; (XX YY ZZ), scaling each to the {0..65535} range. This |
| 934 | ;; the used digits represent the most significant | 935 | ;; follows the HTML color convention, where both "#fff" and |
| 935 | ;; bits of the value (e.g. #XYZ = #X000Y000Z000). | 936 | ;; "#ffffff" represent the same color, white. |
| 936 | (let* ((ndig (/ (- len 1) 3)) | 937 | (let* ((ndig (/ (- len 1) 3)) |
| 938 | (maxval (1- (ash 1 (* 4 ndig)))) | ||
| 937 | (i1 1) | 939 | (i1 1) |
| 938 | (i2 (+ i1 ndig)) | 940 | (i2 (+ i1 ndig)) |
| 939 | (i3 (+ i2 ndig))) | 941 | (i3 (+ i2 ndig)) |
| 942 | (i4 (+ i3 ndig))) | ||
| 940 | (list | 943 | (list |
| 941 | (ash | 944 | (/ (* (string-to-number |
| 942 | (string-to-number (substring color i1 i2) 16) | 945 | (substring color i1 i2) 16) |
| 943 | (* 4 (- 4 ndig))) | 946 | 65535) |
| 944 | (ash | 947 | maxval) |
| 945 | (string-to-number (substring color i2 i3) 16) | 948 | (/ (* (string-to-number |
| 946 | (* 4 (- 4 ndig))) | 949 | (substring color i2 i3) 16) |
| 947 | (ash | 950 | 65535) |
| 948 | (string-to-number (substring color i3) 16) | 951 | maxval) |
| 949 | (* 4 (- 4 ndig)))))) | 952 | (/ (* (string-to-number |
| 950 | ((and (>= len 9) ;; X-style RGB:xx/yy/zz color spec | 953 | (substring color i3 i4) 16) |
| 954 | 65535) | ||
| 955 | maxval)))) | ||
| 956 | ((and (>= len 9) ;; X-style rgb:xx/yy/zz color spec | ||
| 951 | (string= (substring color 0 4) "rgb:")) | 957 | (string= (substring color 0 4) "rgb:")) |
| 952 | ;; Translate the string "RGB:XX/YY/ZZ" into a list | 958 | ;; Translate the string "rgb:XX/YY/ZZ" into a list of |
| 953 | ;; of numbers (XX YY ZZ). If fewer than 4 hex | 959 | ;; numbers (XX YY ZZ), scaling each to the {0..65535} |
| 954 | ;; digits are used, they represent the fraction | 960 | ;; range. "rgb:F/F/F" is white. |
| 955 | ;; of the maximum value (RGB:X/Y/Z = #XXXXYYYYZZZZ). | ||
| 956 | (let* ((ndig (/ (- len 3) 3)) | 961 | (let* ((ndig (/ (- len 3) 3)) |
| 957 | (maxval (1- (ash 1 (* 4 (- ndig 1))))) | 962 | (maxval (1- (ash 1 (* 4 (- ndig 1))))) |
| 958 | (i1 4) | 963 | (i1 4) |
| 959 | (i2 (+ i1 ndig)) | 964 | (i2 (+ i1 ndig)) |
| 960 | (i3 (+ i2 ndig))) | 965 | (i3 (+ i2 ndig)) |
| 966 | (i4 (+ i3 ndig))) | ||
| 961 | (list | 967 | (list |
| 962 | (/ (* (string-to-number | 968 | (/ (* (string-to-number |
| 963 | (substring color i1 (- i2 1)) 16) | 969 | (substring color i1 (- i2 1)) 16) |
| 964 | 255) | 970 | 65535) |
| 965 | maxval) | 971 | maxval) |
| 966 | (/ (* (string-to-number | 972 | (/ (* (string-to-number |
| 967 | (substring color i2 (- i3 1)) 16) | 973 | (substring color i2 (- i3 1)) 16) |
| 968 | 255) | 974 | 65535) |
| 969 | maxval) | 975 | maxval) |
| 970 | (/ (* (string-to-number | 976 | (/ (* (string-to-number |
| 971 | (substring color i3) 16) | 977 | (substring color i3 (1- i4)) 16) |
| 972 | 255) | 978 | 65535) |
| 973 | maxval)))) | 979 | maxval)))) |
| 974 | (t | 980 | (t |
| 975 | (cdr (assoc color color-name-rgb-alist)))))) | 981 | (cdr (assoc color color-name-rgb-alist)))))) |
| @@ -977,9 +983,9 @@ should be the same regardless of what display is being used." | |||
| 977 | (defun tty-color-translate (color &optional frame) | 983 | (defun tty-color-translate (color &optional frame) |
| 978 | "Given a color COLOR, return the index of the corresponding TTY color. | 984 | "Given a color COLOR, return the index of the corresponding TTY color. |
| 979 | 985 | ||
| 980 | COLOR must be a string that is either the color's name, or its X-style | 986 | COLOR must be a string that is either the color's name, or its |
| 981 | specification like \"#RRGGBB\" or \"RGB:rr/gg/bb\", where each primary. | 987 | color triplet specification like \"#RRGGBB\" or \"rgb:RR/GG/BB\", |
| 982 | color can be given with 1 to 4 hex digits. | 988 | where each primary color can be given with 1 to 4 hex digits. |
| 983 | 989 | ||
| 984 | If COLOR is a color name that is found among supported colors in | 990 | If COLOR is a color name that is found among supported colors in |
| 985 | `tty-color-alist', the associated index is returned. Otherwise, the | 991 | `tty-color-alist', the associated index is returned. Otherwise, the |
| @@ -987,7 +993,7 @@ RGB values of the color, either as given by the argument or from | |||
| 987 | looking up the name in `color-name-rgb-alist', are used to find the | 993 | looking up the name in `color-name-rgb-alist', are used to find the |
| 988 | supported color that is the best approximation for COLOR in the RGB | 994 | supported color that is the best approximation for COLOR in the RGB |
| 989 | space. | 995 | space. |
| 990 | If COLOR is neither a valid X RGB specification of the color, nor a | 996 | If COLOR is neither a valid RGB specification of the color, nor a |
| 991 | name of a color in `color-name-rgb-alist', the returned value is nil. | 997 | name of a color in `color-name-rgb-alist', the returned value is nil. |
| 992 | 998 | ||
| 993 | If FRAME is unspecified or nil, it defaults to the selected frame." | 999 | If FRAME is unspecified or nil, it defaults to the selected frame." |
diff --git a/src/xterm.c b/src/xterm.c index c96aa74a7a6..75568a82a18 100644 --- a/src/xterm.c +++ b/src/xterm.c | |||
| @@ -2381,6 +2381,8 @@ x_query_frame_background_color (struct frame *f, XColor *bgcolor) | |||
| 2381 | x_query_colors (f, bgcolor, 1); | 2381 | x_query_colors (f, bgcolor, 1); |
| 2382 | } | 2382 | } |
| 2383 | 2383 | ||
| 2384 | #define HEX_COLOR_NAME_LENGTH 32 | ||
| 2385 | |||
| 2384 | /* On frame F, translate the color name to RGB values. Use cached | 2386 | /* On frame F, translate the color name to RGB values. Use cached |
| 2385 | information, if possible. | 2387 | information, if possible. |
| 2386 | 2388 | ||
| @@ -2398,9 +2400,36 @@ Status x_parse_color (struct frame *f, const char *color_name, | |||
| 2398 | 2400 | ||
| 2399 | if (color_name[0] == '#') | 2401 | if (color_name[0] == '#') |
| 2400 | { | 2402 | { |
| 2401 | /* The hex form is parsed directly by XParseColor without | 2403 | /* Don't pass #RGB strings directly to XParseColor, because that |
| 2404 | follows the X convention of zero-extending each channel | ||
| 2405 | value: #f00 means #f00000. We want the convention of scaling | ||
| 2406 | channel values, so #f00 means #ff0000, just as it does for | ||
| 2407 | HTML, SVG, and CSS. | ||
| 2408 | |||
| 2409 | So we translate #f00 to rgb:f/0/0, which X handles | ||
| 2410 | differently. */ | ||
| 2411 | char rgb_color_name[HEX_COLOR_NAME_LENGTH]; | ||
| 2412 | int len = strlen (color_name); | ||
| 2413 | int digits_per_channel; | ||
| 2414 | if (len == 4) | ||
| 2415 | digits_per_channel = 1; | ||
| 2416 | else if (len == 7) | ||
| 2417 | digits_per_channel = 2; | ||
| 2418 | else if (len == 10) | ||
| 2419 | digits_per_channel = 3; | ||
| 2420 | else if (len == 13) | ||
| 2421 | digits_per_channel = 4; | ||
| 2422 | else | ||
| 2423 | return 0; | ||
| 2424 | |||
| 2425 | snprintf (rgb_color_name, sizeof rgb_color_name, "rgb:%.*s/%.*s/%.*s", | ||
| 2426 | digits_per_channel, color_name + 1, | ||
| 2427 | digits_per_channel, color_name + digits_per_channel + 1, | ||
| 2428 | digits_per_channel, color_name + 2 * digits_per_channel + 1); | ||
| 2429 | |||
| 2430 | /* The rgb form is parsed directly by XParseColor without | ||
| 2402 | talking to the X server. No need for caching. */ | 2431 | talking to the X server. No need for caching. */ |
| 2403 | return XParseColor (dpy, cmap, color_name, color); | 2432 | return XParseColor (dpy, cmap, rgb_color_name, color); |
| 2404 | } | 2433 | } |
| 2405 | 2434 | ||
| 2406 | for (cache_entry = FRAME_DISPLAY_INFO (f)->color_names; cache_entry; | 2435 | for (cache_entry = FRAME_DISPLAY_INFO (f)->color_names; cache_entry; |