Improve fl_contrast() functionality and documentation
- swap 3rd and 4th parameter of fl_contrast() - change 'Fl_Fontsize fs' to a neutral 'int size' parameter - clarify documentation of fl_contrast_level() and that different contrast algorithms use different level values - clarify that level 39 for the CIELAB mode results in "sufficient" contrast, i.e. /readable/ text which is the only intention of fl_contrast(). Reasoning: swapping the arguments looks more natural, i.e. the context before another argument (size) is what one would usually expect. Since the 'size' argument doesn't have be a font size, making it a simple 'int size' is more flexible and correct for future extensions.
This commit is contained in:
parent
7410498a7f
commit
d0922792ae
@ -1161,19 +1161,22 @@ FL_EXPORT Fl_Color fl_inactive(Fl_Color c);
|
|||||||
with fl_contrast_mode(FL_CONTRAST_CUSTOM).
|
with fl_contrast_mode(FL_CONTRAST_CUSTOM).
|
||||||
Example:
|
Example:
|
||||||
\code
|
\code
|
||||||
Fl_Color my_contrast(Fl_Color fg, Fl_Color bg, Fl_Fontsize fs, int context) {
|
Fl_Color my_contrast(Fl_Color fg, Fl_Color bg, int context, int size) {
|
||||||
// calculate contrast and ...
|
// calculate contrast and ...
|
||||||
return color;
|
return color;
|
||||||
}
|
}
|
||||||
// call this early in your main() program:
|
// call this early in your main() program:
|
||||||
fl_contrast_function(my_contrast);
|
fl_contrast_function(my_contrast);
|
||||||
fl_contrast_mode(FL_CONTRAST_CUSTOM);
|
fl_contrast_mode(FL_CONTRAST_CUSTOM);
|
||||||
|
fl_contrast_level(50); // optional, must be called after fl_contrast_mode()
|
||||||
\endcode
|
\endcode
|
||||||
|
|
||||||
\see fl_contrast(Fl_Color, Fl_Color, Fl_Fontsize, int)
|
For parameters and types see fl_contrast(Fl_Color, Fl_Color, int, int).
|
||||||
|
|
||||||
|
\see fl_contrast(Fl_Color, Fl_Color, int, int)
|
||||||
\see fl_contrast_mode(int)
|
\see fl_contrast_mode(int)
|
||||||
*/
|
*/
|
||||||
typedef Fl_Color (Fl_Contrast_Function)(Fl_Color, Fl_Color, Fl_Fontsize, int);
|
typedef Fl_Color (Fl_Contrast_Function)(Fl_Color, Fl_Color, int, int);
|
||||||
|
|
||||||
FL_EXPORT void fl_contrast_function(Fl_Contrast_Function *f);
|
FL_EXPORT void fl_contrast_function(Fl_Contrast_Function *f);
|
||||||
|
|
||||||
@ -1195,7 +1198,7 @@ FL_EXPORT int fl_contrast_level();
|
|||||||
FL_EXPORT void fl_contrast_mode(int mode);
|
FL_EXPORT void fl_contrast_mode(int mode);
|
||||||
FL_EXPORT int fl_contrast_mode();
|
FL_EXPORT int fl_contrast_mode();
|
||||||
|
|
||||||
FL_EXPORT Fl_Color fl_contrast(Fl_Color fg, Fl_Color bg, Fl_Fontsize fs = 0, int context = 0);
|
FL_EXPORT Fl_Color fl_contrast(Fl_Color fg, Fl_Color bg, int context = 0, int size = 0);
|
||||||
|
|
||||||
FL_EXPORT double fl_lightness(Fl_Color color);
|
FL_EXPORT double fl_lightness(Fl_Color color);
|
||||||
FL_EXPORT double fl_luminance(Fl_Color color);
|
FL_EXPORT double fl_luminance(Fl_Color color);
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
//
|
//
|
||||||
// Color contrast functions for the Fast Light Tool Kit (FLTK).
|
// Color contrast functions for the Fast Light Tool Kit (FLTK).
|
||||||
//
|
//
|
||||||
// Copyright 1998-2022 by Bill Spitzak and others.
|
// Copyright 1998-2024 by Bill Spitzak and others.
|
||||||
//
|
//
|
||||||
// This library is free software. Distribution and use rights are outlined in
|
// This library is free software. Distribution and use rights are outlined in
|
||||||
// the file "COPYING" which should have been included with this file. If this
|
// the file "COPYING" which should have been included with this file. If this
|
||||||
@ -46,8 +46,8 @@ static int fl_contrast_level_[10] = {
|
|||||||
static Fl_Contrast_Function *fl_contrast_function_ = 0;
|
static Fl_Contrast_Function *fl_contrast_function_ = 0;
|
||||||
|
|
||||||
|
|
||||||
// The following function is (and must be!) the same as Fl::get_color()
|
// The following function is (and must be!) the same as Fl::get_color() but
|
||||||
// but can be inlined. We need this additional implementation because all contrast
|
// can be inlined. We need this additional implementation because all contrast
|
||||||
// related functions have been moved from fl_color.cxx to fl_contrast.cxx
|
// related functions have been moved from fl_color.cxx to fl_contrast.cxx
|
||||||
// or have been directly implemented in fl_contrast.cxx (new functions).
|
// or have been directly implemented in fl_contrast.cxx (new functions).
|
||||||
// Inlining will hopefully prevent an extra function call.
|
// Inlining will hopefully prevent an extra function call.
|
||||||
@ -139,12 +139,13 @@ double fl_lightness(Fl_Color color) {
|
|||||||
|
|
||||||
This can be used to tune the legacy fl_contrast() function to achieve
|
This can be used to tune the legacy fl_contrast() function to achieve
|
||||||
slightly better results. The default value is defined per contrast mode
|
slightly better results. The default value is defined per contrast mode
|
||||||
(see below). Values between 50 and 70 are recommended but you can raise
|
(see below). Values between 50 and 70 may be useful for the legacy contrast
|
||||||
it up to 100. Lower values than 50 are probably not useful.
|
mode but you can raise it up to 100. Lower values than 50 are probably not
|
||||||
|
useful.
|
||||||
|
|
||||||
The contrast \p level affects not only the legacy (1.3.x) fl_contrast()
|
The contrast \p level affects not only the legacy (1.3.x) fl_contrast()
|
||||||
function but also the new CIELAB contrast mode which is the default since
|
function but also the new CIELAB contrast mode which is the default since
|
||||||
FLTK 1.4.0.
|
FLTK 1.4.0. See default value below.
|
||||||
|
|
||||||
Other contrast modes are currently not affected by the contrast level.
|
Other contrast modes are currently not affected by the contrast level.
|
||||||
|
|
||||||
@ -157,7 +158,7 @@ double fl_lightness(Fl_Color color) {
|
|||||||
|
|
||||||
The default contrast level is
|
The default contrast level is
|
||||||
- 50 in mode FL_CONTRAST_LEGACY (compatible with FLTK 1.3.x)
|
- 50 in mode FL_CONTRAST_LEGACY (compatible with FLTK 1.3.x)
|
||||||
- 55 in mode FL_CONTRAST_CIELAB
|
- 39 in mode FL_CONTRAST_CIELAB (similar threshold as in FLTK 1.3.x)
|
||||||
- 0 (undefined) for all other modes
|
- 0 (undefined) for all other modes
|
||||||
|
|
||||||
See the description of fl_contrast_mode(int mode) for more information about
|
See the description of fl_contrast_mode(int mode) for more information about
|
||||||
@ -166,7 +167,7 @@ double fl_lightness(Fl_Color color) {
|
|||||||
Example:
|
Example:
|
||||||
\code
|
\code
|
||||||
fl_contrast_mode(FL_CONTRAST_LEGACY);
|
fl_contrast_mode(FL_CONTRAST_LEGACY);
|
||||||
fl_contrast_level(65);
|
fl_contrast_level(60);
|
||||||
\endcode
|
\endcode
|
||||||
|
|
||||||
A \p level greater than 50 (probably best in the range 50 to 70) may achieve
|
A \p level greater than 50 (probably best in the range 50 to 70) may achieve
|
||||||
@ -208,7 +209,7 @@ int fl_contrast_level() {
|
|||||||
|
|
||||||
- FL_CONTRAST_NONE (not recommended: returns the foreground color)
|
- FL_CONTRAST_NONE (not recommended: returns the foreground color)
|
||||||
- FL_CONTRAST_LEGACY (same as in FLTK 1.3.x)
|
- FL_CONTRAST_LEGACY (same as in FLTK 1.3.x)
|
||||||
- FL_CONTRAST_CIELAB (default since FLTK 1.4.0)
|
- FL_CONTRAST_CIELAB (better, this is the default since FLTK 1.4.0)
|
||||||
- FL_CONTRAST_CUSTOM (you must define your own contrast algorithm)
|
- FL_CONTRAST_CUSTOM (you must define your own contrast algorithm)
|
||||||
|
|
||||||
If you set FL_CONTRAST_CUSTOM you must also register your custom
|
If you set FL_CONTRAST_CUSTOM you must also register your custom
|
||||||
@ -227,12 +228,24 @@ int fl_contrast_level() {
|
|||||||
in higher contrast, i.e. the algorithm switches "earlier" to
|
in higher contrast, i.e. the algorithm switches "earlier" to
|
||||||
black or white mode.
|
black or white mode.
|
||||||
|
|
||||||
- FL_CONTRAST_CIELAB: defaut level is 55 which appears to be a good
|
- FL_CONTRAST_CIELAB: defaut level is 39 which appears to be a good
|
||||||
value. The higher the level is, the more contrast is to be expected.
|
value. The higher the level is, the more contrast is to be expected.
|
||||||
Values in the range below 55 accept lower contrast and values above
|
Values in the range below 39 accept lower contrast and values above
|
||||||
55 switch "earlier" to black or white. Values between 45 and 65 may
|
39 switch "earlier" to black or white. Values between 36 and 46 may
|
||||||
yield usable contrast experience.
|
yield usable contrast experience.
|
||||||
|
|
||||||
|
\note The goal of fl_contrast() is to achieve a "sufficient" contrast
|
||||||
|
between text and background. Level 39 in CIELAB mode means that the
|
||||||
|
accepted contrast is about 39% of the lightness difference between
|
||||||
|
both colors. This can be perceived as very low contrast in some cases,
|
||||||
|
but the text should at least be readable. Note that the highest possible
|
||||||
|
contrast value on a medium gray background is 50% (either black or white).
|
||||||
|
Bill Spitzak wrote on May 16, 2024 in fltk.general in thread "FLTK 1.4
|
||||||
|
Menu Bar Style": <i>"I would certainly aim for a function that does not
|
||||||
|
alter color combinations where it is physically possible to read the
|
||||||
|
text, even if squinting is needed."</i>\n
|
||||||
|
See https://groups.google.com/g/fltkgeneral/c/EkWI4HTHSLA/m/rsZunZ1vAwAJ
|
||||||
|
|
||||||
\param[in] mode if invalid, FL_CONTRAST_CIELAB will be selected
|
\param[in] mode if invalid, FL_CONTRAST_CIELAB will be selected
|
||||||
|
|
||||||
\since 1.4.0
|
\since 1.4.0
|
||||||
@ -269,15 +282,16 @@ int fl_contrast_mode() {
|
|||||||
|
|
||||||
Your custom contrast function must provide the signature
|
Your custom contrast function must provide the signature
|
||||||
\code
|
\code
|
||||||
Fl_Color my_contrast_function(Fl_Color fg, Fl_Color bg, Fl_Fontsize fs, int context)
|
Fl_Color my_contrast_function(Fl_Color fg, Fl_Color bg, int context, int size)
|
||||||
\endcode
|
\endcode
|
||||||
|
|
||||||
The arguments are the same as for the full fl_contrast() function since FLTK 1.4.
|
The arguments are the same as for the full fl_contrast() function since FLTK 1.4.
|
||||||
You can use the supplied fontsize \p fs to modify the result. Depending on the
|
You can use the supplied \p size to modify the result. Depending on the
|
||||||
caller the \p fs parameter can be 0 (default) or a valid fontsize.
|
caller the \p size parameter can be 0 (default) or a valid size. In the context
|
||||||
|
of text, i.e. \p context == 0, the \p size parameter is the fontsize.
|
||||||
|
|
||||||
The \p context parameter is not yet used and will always be 0 unless included in
|
The \p context parameter is not yet used and will always be 0 unless included in
|
||||||
a call to fl_contrast(). The value 0 should be interpreted as text.
|
a call to fl_contrast(). The value 0 must be interpreted as text.
|
||||||
In the future the \p context argument will be used to supply a different context
|
In the future the \p context argument will be used to supply a different context
|
||||||
than text (small icons, large icons, etc.). The exact usage is not yet specified.
|
than text (small icons, large icons, etc.). The exact usage is not yet specified.
|
||||||
|
|
||||||
@ -309,10 +323,10 @@ void fl_contrast_function(Fl_Contrast_Function *f) {
|
|||||||
\param[in] fs,context fontsize and context (unused)
|
\param[in] fs,context fontsize and context (unused)
|
||||||
\return contrasting color
|
\return contrasting color
|
||||||
*/
|
*/
|
||||||
static Fl_Color fl_contrast_legacy(Fl_Color fg, Fl_Color bg, Fl_Fontsize fs, int context) {
|
static Fl_Color fl_contrast_legacy(Fl_Color fg, Fl_Color bg, int context, int size) {
|
||||||
|
|
||||||
(void) fs; // currently ignored
|
|
||||||
(void) context; // currently ignored
|
(void) context; // currently ignored
|
||||||
|
(void) size; // currently ignored
|
||||||
|
|
||||||
// internal static variables, recalculated only if fl_contrast_level() is changed
|
// internal static variables, recalculated only if fl_contrast_level() is changed
|
||||||
|
|
||||||
@ -378,10 +392,10 @@ static Fl_Color fl_contrast_legacy(Fl_Color fg, Fl_Color bg, Fl_Fontsize fs, int
|
|||||||
\param[in] fs,context unused: fontsize and context
|
\param[in] fs,context unused: fontsize and context
|
||||||
\return contrasting color
|
\return contrasting color
|
||||||
*/
|
*/
|
||||||
static Fl_Color fl_contrast_cielab(Fl_Color fg, Fl_Color bg, Fl_Fontsize fs, int context) {
|
static Fl_Color fl_contrast_cielab(Fl_Color fg, Fl_Color bg, int context, int size) {
|
||||||
|
|
||||||
(void) fs; // currently ignored
|
|
||||||
(void) context; // currently ignored
|
(void) context; // currently ignored
|
||||||
|
(void) size; // currently ignored
|
||||||
|
|
||||||
double tc = (double)fl_contrast_level(); // sufficient contrast threshold
|
double tc = (double)fl_contrast_level(); // sufficient contrast threshold
|
||||||
double tbw = 50.; // black/white threshold
|
double tbw = 50.; // black/white threshold
|
||||||
@ -421,15 +435,16 @@ static Fl_Color fl_contrast_cielab(Fl_Color fg, Fl_Color bg, Fl_Fontsize fs, int
|
|||||||
You can change the behavior of fl_contrast() in several ways:
|
You can change the behavior of fl_contrast() in several ways:
|
||||||
|
|
||||||
- Change the "level" (sensitivity) for contrast calculation, see fl_contrast_level().
|
- Change the "level" (sensitivity) for contrast calculation, see fl_contrast_level().
|
||||||
Valid levels are 0 - 100, the default "medium" value is 50. If you raise the level
|
Valid levels are 0 - 100, the default "medium" value depends on the contrast mode.
|
||||||
above 50 the overall contrast will generally be higher, i.e. the required contrast
|
If you raise the level above the default value the overall contrast will generally
|
||||||
to return the foreground color is raised and therefore the calculated color will
|
be higher, i.e. the required contrast to return the foreground color is raised and
|
||||||
switch "earlier" to either black or white.
|
therefore the calculated color switches "earlier" to either black or white.
|
||||||
In other words, using the following values:
|
In other words, using the following values:
|
||||||
- 0 will always use the foreground color
|
- 0 always uses the foreground color
|
||||||
- 50 will use the default, unmodified algorithm
|
- the default, unmodified algorithm allows a sufficient contrast such that the text
|
||||||
|
is readable
|
||||||
- 100 will always use black or white
|
- 100 will always use black or white
|
||||||
- values larger than 50 may yield slightly better results.
|
|
||||||
Changing the \p level is particularly useful and intended for the "legacy mode"
|
Changing the \p level is particularly useful and intended for the "legacy mode"
|
||||||
to improve the results partially. Values slightly above 50 (50 - 70) will likely
|
to improve the results partially. Values slightly above 50 (50 - 70) will likely
|
||||||
return the best results (50 is the default, as used in FLTK 1.3.x).
|
return the best results (50 is the default, as used in FLTK 1.3.x).
|
||||||
@ -454,25 +469,33 @@ static Fl_Color fl_contrast_cielab(Fl_Color fg, Fl_Color bg, Fl_Fontsize fs, int
|
|||||||
to use the new default function:
|
to use the new default function:
|
||||||
|
|
||||||
- FL_CONTRAST_CIELAB, based on the CIELAB (L*a*b*) color model. This function
|
- FL_CONTRAST_CIELAB, based on the CIELAB (L*a*b*) color model. This function
|
||||||
is superior regarding the visual contrast perception but may be slower.
|
is superior regarding the human contrast perception but may be slightly
|
||||||
|
slower - which should not matter on a modern CPU. The default contrast
|
||||||
|
level in this mode is 39 which results in a very similar experience as the
|
||||||
|
old contrast function but avoids unreadable border cases.
|
||||||
<b>This is the default since FLTK 1.4.0.</b>
|
<b>This is the default since FLTK 1.4.0.</b>
|
||||||
|
|
||||||
- FL_CONTRAST_CUSTOM, your own contrast calculation function.
|
- FL_CONTRAST_CUSTOM, your own contrast calculation function.
|
||||||
|
|
||||||
In the future we \b may provide even more (and superior) contrast algorithms.
|
In the future we \b may provide even more (and superior) contrast algorithms.
|
||||||
|
|
||||||
The new parameters \p fs and \p context (since 1.4.0) are defined for future
|
The new parameters \p context and \p size (since 1.4.0) are defined for
|
||||||
extensions and are currently not used. Default values are 0.
|
future extensions and are currently not used. Default values are 0.
|
||||||
|
- The \p context is intended to differentiate text and other kinds
|
||||||
|
of objects, e.g. radio buttons, check marks, or icon types.
|
||||||
|
- The \p size parameter is an unspecified (object) size that may be used to
|
||||||
|
calculate the required contrast. In text mode this must be the font size.
|
||||||
|
Rule: the larger the object (font), the lower the required contrast.
|
||||||
|
|
||||||
\note These new optional parameters must be provided in the custom contrast
|
\note These new optional parameters must be provided in the custom contrast
|
||||||
function which is the reason why they are added now. In the future we may use
|
function which is the reason why they are added now. In the future we may use
|
||||||
the fontsize to adjust the calculated contrast, and users defining their own
|
the (font) size to adjust the calculated contrast, and users defining their
|
||||||
contrast functions may use them in their functions.
|
own contrast functions may use them in their functions.
|
||||||
|
|
||||||
\param[in] fg foreground (text) color
|
\param[in] fg foreground (text) color
|
||||||
\param[in] bg background color
|
\param[in] bg background color
|
||||||
\param[in] fs font size (optional, default = 0 == undefined)
|
|
||||||
\param[in] context graphical context (optional, default = 0 == text)
|
\param[in] context graphical context (optional, default = 0 == text)
|
||||||
|
\param[in] size unspecified size (optional, default = 0 == undefined)
|
||||||
|
|
||||||
\return contrasting color: \p fg, \p FL_BLACK, or \p FL_WHITE
|
\return contrasting color: \p fg, \p FL_BLACK, or \p FL_WHITE
|
||||||
|
|
||||||
@ -480,21 +503,21 @@ static Fl_Color fl_contrast_cielab(Fl_Color fg, Fl_Color bg, Fl_Fontsize fs, int
|
|||||||
\see fl_contrast_mode(int)
|
\see fl_contrast_mode(int)
|
||||||
\see fl_contrast_function()
|
\see fl_contrast_function()
|
||||||
*/
|
*/
|
||||||
Fl_Color fl_contrast(Fl_Color fg, Fl_Color bg, Fl_Fontsize fs, int context) {
|
Fl_Color fl_contrast(Fl_Color fg, Fl_Color bg, int context, int size) {
|
||||||
|
|
||||||
switch (fl_contrast_mode_) {
|
switch (fl_contrast_mode_) {
|
||||||
|
|
||||||
case FL_CONTRAST_LEGACY:
|
case FL_CONTRAST_LEGACY:
|
||||||
return fl_contrast_legacy(fg, bg, fs, context);
|
return fl_contrast_legacy(fg, bg, context, size);
|
||||||
|
|
||||||
case FL_CONTRAST_CUSTOM:
|
case FL_CONTRAST_CUSTOM:
|
||||||
if (fl_contrast_function_)
|
if (fl_contrast_function_)
|
||||||
return (fl_contrast_function_)(fg, bg, fs, context);
|
return (fl_contrast_function_)(fg, bg, context, size);
|
||||||
|
|
||||||
// FALLTHROUGH
|
// FALLTHROUGH
|
||||||
|
|
||||||
case FL_CONTRAST_CIELAB:
|
case FL_CONTRAST_CIELAB:
|
||||||
return fl_contrast_cielab(fg, bg, fs, context);
|
return fl_contrast_cielab(fg, bg, context, size);
|
||||||
|
|
||||||
default: // unknown (none): return fg
|
default: // unknown (none): return fg
|
||||||
break;
|
break;
|
||||||
|
Loading…
Reference in New Issue
Block a user