Improve and extend fl_contrast() (#370)
- Add internal fl_contrast_cielab() as the new default. - Keep old function as internal fl_contrast_legacy(). - Add fl_contrast_mode() to switch between fl_contrast() functions. - Add fl_contrast_level() to fine tune fl_contrast() per mode. - Add option to register and use a custom contrast function. - Add test/contrast.cxx test program. - Move all fl_contrast() related code to a new file src/fl_contrast.cxx. - Add fl_lightness() convenience function for perceived lightness. - Add fl_luminance() convenience function for physical luminance.
This commit is contained in:
parent
31327cd649
commit
78cf29ba29
@ -1118,7 +1118,53 @@ are free for the user to be given any value using Fl::set_color(). */
|
||||
|
||||
FL_EXPORT Fl_Color fl_inactive(Fl_Color c);
|
||||
|
||||
FL_EXPORT Fl_Color fl_contrast(Fl_Color fg, Fl_Color bg);
|
||||
/**
|
||||
Type of a custom fl_contrast() function.
|
||||
|
||||
Use this signature to define your own custom fl_contrast() function together
|
||||
with fl_contrast_mode(FL_CONTRAST_CUSTOM).
|
||||
Example:
|
||||
\code
|
||||
Fl_Color my_contrast(Fl_Color fg, Fl_Color bg, Fl_Fontsize fs, int context) {
|
||||
// calculate contrast and ...
|
||||
return color;
|
||||
}
|
||||
// call this early in your main() program:
|
||||
fl_contrast_function(my_contrast);
|
||||
fl_contrast_mode(FL_CONTRAST_CUSTOM);
|
||||
\endcode
|
||||
|
||||
\see fl_contrast(Fl_Color, Fl_Color, Fl_Fontsize, int)
|
||||
\see fl_contrast_mode(int)
|
||||
*/
|
||||
typedef Fl_Color (Fl_Contrast_Function)(Fl_Color, Fl_Color, Fl_Fontsize, int);
|
||||
|
||||
FL_EXPORT void fl_contrast_function(Fl_Contrast_Function *f);
|
||||
|
||||
/**
|
||||
Define the possible modes to calculate fl_contrast().
|
||||
*/
|
||||
enum Fl_Contrast_Mode {
|
||||
FL_CONTRAST_NONE = 0, ///< always return foreground color
|
||||
FL_CONTRAST_LEGACY, ///< legacy (FLTK 1.3.x) contrast function
|
||||
FL_CONTRAST_CIELAB, ///< new (FLTK 1.4.0) default function
|
||||
FL_CONTRAST_CUSTOM, ///< optional custom contrast function
|
||||
FL_CONTRAST_LAST ///< internal use only (invalid contrast mode)
|
||||
};
|
||||
|
||||
// The following functions are defined and documented in src/fl_contrast.cxx
|
||||
|
||||
FL_EXPORT void fl_contrast_level(int level);
|
||||
FL_EXPORT int fl_contrast_level();
|
||||
FL_EXPORT void fl_contrast_mode(int 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 double fl_lightness(Fl_Color color);
|
||||
FL_EXPORT double fl_luminance(Fl_Color color);
|
||||
|
||||
// Other color functions are defined and documented in src/fl_color.cxx
|
||||
|
||||
FL_EXPORT Fl_Color fl_color_average(Fl_Color c1, Fl_Color c2, float weight);
|
||||
|
||||
|
@ -132,6 +132,7 @@ set (CPPFILES
|
||||
fl_ask.cxx
|
||||
fl_boxtype.cxx
|
||||
fl_color.cxx
|
||||
fl_contrast.cxx
|
||||
fl_cursor.cxx
|
||||
fl_curve.cxx
|
||||
fl_diamond_box.cxx
|
||||
|
@ -135,6 +135,7 @@ CPPFILES = \
|
||||
fl_ask.cxx \
|
||||
fl_boxtype.cxx \
|
||||
fl_color.cxx \
|
||||
fl_contrast.cxx \
|
||||
fl_cursor.cxx \
|
||||
fl_curve.cxx \
|
||||
fl_diamond_box.cxx \
|
||||
|
@ -168,36 +168,6 @@ Fl_Color fl_inactive(Fl_Color c) {
|
||||
return fl_color_average(c, FL_GRAY, .33f);
|
||||
}
|
||||
|
||||
/**
|
||||
Returns a color that contrasts with the background color.
|
||||
|
||||
This will be the foreground color if it contrasts sufficiently with the
|
||||
background color. Otherwise, returns \p FL_WHITE or \p FL_BLACK depending
|
||||
on which color provides the best contrast.
|
||||
\param[in] fg,bg foreground and background colors
|
||||
\return contrasting color
|
||||
*/
|
||||
Fl_Color fl_contrast(Fl_Color fg, Fl_Color bg) {
|
||||
unsigned c1, c2; // RGB colors
|
||||
int l1, l2; // Luminosities
|
||||
|
||||
// Get the RGB values for each color...
|
||||
if (fg & 0xffffff00) c1 = (unsigned)fg;
|
||||
else c1 = fl_cmap[fg];
|
||||
|
||||
if (bg & 0xffffff00) c2 = (unsigned)bg;
|
||||
else c2 = fl_cmap[bg];
|
||||
|
||||
// Compute the luminosity...
|
||||
l1 = ((c1 >> 24) * 30 + ((c1 >> 16) & 255) * 59 + ((c1 >> 8) & 255) * 11) / 100;
|
||||
l2 = ((c2 >> 24) * 30 + ((c2 >> 16) & 255) * 59 + ((c2 >> 8) & 255) * 11) / 100;
|
||||
|
||||
// Compare and return the contrasting color...
|
||||
if ((l1 - l2) > 99) return fg;
|
||||
else if ((l2 - l1) > 99) return fg;
|
||||
else if (l2 > 127) return FL_BLACK;
|
||||
else return FL_WHITE;
|
||||
}
|
||||
/**
|
||||
\}
|
||||
*/
|
||||
|
488
src/fl_contrast.cxx
Normal file
488
src/fl_contrast.cxx
Normal file
@ -0,0 +1,488 @@
|
||||
//
|
||||
// Color contrast functions for the Fast Light Tool Kit (FLTK).
|
||||
//
|
||||
// Copyright 1998-2022 by Bill Spitzak and others.
|
||||
//
|
||||
// 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
|
||||
// file is missing or damaged, see the license at:
|
||||
//
|
||||
// https://www.fltk.org/COPYING.php
|
||||
//
|
||||
// Please see the following page on how to report bugs and issues:
|
||||
//
|
||||
// https://www.fltk.org/bugs.php
|
||||
//
|
||||
|
||||
/**
|
||||
\file fl_contrast.cxx
|
||||
\brief Color contrast handling
|
||||
|
||||
Implementation of fl_contrast() and its variants.
|
||||
*/
|
||||
|
||||
#include <FL/Fl.H>
|
||||
#include <math.h>
|
||||
|
||||
// Initial values of global/static variables defined by fl_contrast_* functions.
|
||||
|
||||
// This defines the default contrast mode since FLTK 1.4.0
|
||||
static int fl_contrast_mode_ = FL_CONTRAST_CIELAB;
|
||||
|
||||
// This defines the default contrast level per contrast mode
|
||||
static int fl_contrast_level_[10] = {
|
||||
0, 50, 55, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
// There is no default custom contrast function
|
||||
static Fl_Contrast_Function *fl_contrast_function_ = 0;
|
||||
|
||||
|
||||
// The following function is (and must be!) the same as Fl::get_color()
|
||||
// but can be inlined. We need this additional implementation because all contrast
|
||||
// related functions have been moved from fl_color.cxx to fl_contrast.cxx
|
||||
// or have been directly implemented in fl_contrast.cxx (new functions).
|
||||
// Inlining will hopefully prevent an extra function call.
|
||||
|
||||
extern unsigned fl_cmap[256]; // defined in fl_color.cxx
|
||||
|
||||
inline unsigned get_color(Fl_Color i) { // see Fl::get_color() !
|
||||
if (i & 0xffffff00) return (i);
|
||||
else return fl_cmap[i];
|
||||
}
|
||||
|
||||
|
||||
/** \addtogroup fl_attributes
|
||||
\{ */
|
||||
|
||||
/**
|
||||
Return the raw / physical luminance of a color.
|
||||
|
||||
This function calculates the physical luminance of Fl_Color \p color.
|
||||
|
||||
The returned luminance value (aka \p Y) is the physical luminance of the
|
||||
Fl_Color \p color.
|
||||
|
||||
The result is in the range 0.0 (black) to 1.0 (white).
|
||||
|
||||
\note This is probably not what you want if you are interested in perceived
|
||||
contrast or lightness calculation because the luminance \p Y is \b not linear
|
||||
with respect to human perception.
|
||||
|
||||
See fl_lightness(Fl_Color) for a function that returns the perceived lightness
|
||||
of a color which can be used directly for contrast calculation.
|
||||
|
||||
\param[in] color Fl_Color value
|
||||
\return Raw (physical) luminance (0.0 .. 1.0)
|
||||
|
||||
\since 1.4.0
|
||||
|
||||
\see fl_lightness(Fl_Color)
|
||||
*/
|
||||
double fl_luminance(Fl_Color color) {
|
||||
|
||||
// Get the sRGB (0xrrggbb) components of the FLTK color
|
||||
unsigned col = get_color(color) >> 8;
|
||||
|
||||
int r = (col & 0xFF0000) >> 16;
|
||||
int g = (col & 0x00FF00) >> 8;
|
||||
int b = (col & 0x0000FF);
|
||||
|
||||
return (0.2126729 * pow(r/255.0, 2.4) +
|
||||
0.7151522 * pow(g/255.0, 2.4) +
|
||||
0.0721750 * pow(b/255.0, 2.4));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Return the perceived lightness of a color.
|
||||
|
||||
This function calculates the perceived lightness of Fl_Color \p color.
|
||||
|
||||
The returned lightness value \p Lstar according to the CIELAB (L*a*b*)
|
||||
color model is almost linear with respect to human perception. It is in
|
||||
the range 0 (black) to 100 (white).
|
||||
|
||||
The result values of two colors can be compared directly and the difference
|
||||
is their perceived contrast.
|
||||
|
||||
\param[in] color Fl_Color value
|
||||
\return perceived lightness (0 .. 100)
|
||||
|
||||
\since 1.4.0
|
||||
*/
|
||||
double fl_lightness(Fl_Color color) {
|
||||
|
||||
// compute the raw luminance Y (0.0 .. 1.0)
|
||||
|
||||
double Y = fl_luminance(color);
|
||||
|
||||
// return the perceived lightness L* (Lstar)
|
||||
|
||||
if (Y <= (216/24389.))
|
||||
return Y * (24389/27.);
|
||||
else
|
||||
return pow(Y, (1/3.)) * 116 - 16;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Set the contrast level (sensitivity) of the fl_contrast() method.
|
||||
|
||||
This can be used to tune the legacy fl_contrast() function to achieve
|
||||
slightly better results. The default value is defined per contrast mode
|
||||
(see below). Values between 50 and 70 are recommended 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()
|
||||
function but also the new CIELAB contrast mode which is the default since
|
||||
FLTK 1.4.0.
|
||||
|
||||
Other contrast modes are currently not affected by the contrast level.
|
||||
|
||||
You may use the contrast level if you define your own custom contrast
|
||||
function in mode FL_CONTRAST_CUSTOM.
|
||||
|
||||
\note All contrast modes store their own contrast level because the
|
||||
behavior is slightly different. You must change the contrast mode
|
||||
fl_contrast_mode() \b before you set or get the contrast level.
|
||||
|
||||
The default contrast level is
|
||||
- 50 in mode FL_CONTRAST_LEGACY (compatible with FLTK 1.3.x)
|
||||
- 55 in mode FL_CONTRAST_CIELAB
|
||||
- 0 (undefined) for all other modes
|
||||
|
||||
See the description of fl_contrast_mode(int mode) for more information about
|
||||
the contrast level per mode.
|
||||
|
||||
Example:
|
||||
\code
|
||||
fl_contrast_mode(FL_CONTRAST_LEGACY);
|
||||
fl_contrast_level(65);
|
||||
\endcode
|
||||
|
||||
A \p level greater than 50 (probably best in the range 50 to 70) may achieve
|
||||
better results of the legacy fl_contrast() function in some border cases of
|
||||
low contrast between foreground and background colors but we recommend to
|
||||
use the new default algorithm \c FL_CONTRAST_CIELAB unless you need strict
|
||||
backwards compatibility or use a CPU constrained embedded system.
|
||||
|
||||
\param[in] level valid range is 0 to 100
|
||||
|
||||
\since 1.4.0
|
||||
*/
|
||||
void fl_contrast_level(int level) {
|
||||
if (level < 0) level = 0;
|
||||
else if (level > 100) level = 100;
|
||||
fl_contrast_level_[fl_contrast_mode_] = level;
|
||||
}
|
||||
|
||||
/**
|
||||
Get the contrast level (sensitivity) of the fl_contrast() method.
|
||||
|
||||
This returns the level of the currently selected contrast mode.
|
||||
|
||||
\return The current contrast level.
|
||||
|
||||
\see fl_contrast_level(int level)
|
||||
\see fl_contrast_mode(int mode)
|
||||
|
||||
\since 1.4.0
|
||||
*/
|
||||
int fl_contrast_level() {
|
||||
return fl_contrast_level_[fl_contrast_mode_];
|
||||
}
|
||||
|
||||
/**
|
||||
Set the contrast algorithm (mode).
|
||||
|
||||
You can use one of
|
||||
|
||||
- FL_CONTRAST_NONE (not recommended: returns the foreground color)
|
||||
- FL_CONTRAST_LEGACY (same as in FLTK 1.3.x)
|
||||
- FL_CONTRAST_CIELAB (default since FLTK 1.4.0)
|
||||
- FL_CONTRAST_CUSTOM (you must define your own contrast algorithm)
|
||||
|
||||
If you set FL_CONTRAST_CUSTOM you must also register your custom
|
||||
contrast function by calling fl_contrast_function().
|
||||
|
||||
You may set the contrast level fl_contrast_level(int) after setting
|
||||
the contrast mode. This affects the contrast algorithm as described
|
||||
below:
|
||||
|
||||
- FL_CONTRAST_LEGACY: default level is 50 which is compatible with
|
||||
FLTK 1.3.x and older. This mode is no longer the default and is
|
||||
not recommended because it doesn't take human contrast perception
|
||||
into account and doesn't properly handle sRGB color values. You
|
||||
may get better contrasts if you set the level higher than 50.
|
||||
Values in the range 50 to 70 may be useful. Higher values result
|
||||
in higher contrast, i.e. the algorithm switches "earlier" to
|
||||
black or white mode.
|
||||
|
||||
- FL_CONTRAST_CIELAB: defaut level is 55 which appears to be a good
|
||||
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
|
||||
55 switch "earlier" to black or white. Values between 45 and 65 may
|
||||
yield usable contrast experience.
|
||||
|
||||
\param[in] mode if invalid, FL_CONTRAST_CIELAB will be selected
|
||||
|
||||
\since 1.4.0
|
||||
|
||||
\see fl_contrast_function(Fl_Contrast_Function *)
|
||||
\see fl_contrast_level(int)
|
||||
*/
|
||||
void fl_contrast_mode(int mode) {
|
||||
if (mode >= 0 && mode < FL_CONTRAST_LAST)
|
||||
fl_contrast_mode_ = mode;
|
||||
else
|
||||
fl_contrast_mode_ = FL_CONTRAST_CIELAB;
|
||||
}
|
||||
|
||||
/**
|
||||
Return the current contrast algorithm (mode).
|
||||
|
||||
\return Contrast algorithm (mode).
|
||||
|
||||
\since 1.4.0
|
||||
|
||||
\see fl_contrast_mode(int)
|
||||
*/
|
||||
int fl_contrast_mode() {
|
||||
return fl_contrast_mode_;
|
||||
}
|
||||
|
||||
/**
|
||||
Register a custom contrast function.
|
||||
|
||||
Your custom contrast function will be called when fl_contrast() is
|
||||
called if and only if you previously registered your function and
|
||||
called fl_contrast_mode(FL_CONTRAST_CUSTOM) .
|
||||
|
||||
Your custom contrast function must provide the signature
|
||||
\code
|
||||
Fl_Color my_contrast_function(Fl_Color fg, Fl_Color bg, Fl_Fontsize fs, int context)
|
||||
\endcode
|
||||
|
||||
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
|
||||
caller the \p fs parameter can be 0 (default) or a valid fontsize.
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
Your function may also use fl_contrast_level() to modify the result accordingly.
|
||||
|
||||
\since 1.4.0
|
||||
|
||||
\see fl_contrast_mode(int)
|
||||
\see fl_contrast_level(int)
|
||||
\see fl_contrast()
|
||||
*/
|
||||
void fl_contrast_function(Fl_Contrast_Function *f) {
|
||||
fl_contrast_function_ = f;
|
||||
}
|
||||
|
||||
/*
|
||||
Returns a color that contrasts with the background color.
|
||||
|
||||
This is functionally identical to the algorithm used in FLTK 1.3.x,
|
||||
modified only to utilize fl_contrast_level() (since 1.4.0).
|
||||
|
||||
*** This function is intentionally not public and not documented.
|
||||
*** Do not change this except for level adjustment (backwards compatibility).
|
||||
|
||||
Note: this is fast but *inaccurate* WRT human contrast perception.
|
||||
The default since FLTK 1.4 is to use fl_contrast_cielab().
|
||||
|
||||
\param[in] fg,bg foreground and background colors
|
||||
\param[in] fs,context fontsize and context (unused)
|
||||
\return contrasting color
|
||||
*/
|
||||
static Fl_Color fl_contrast_legacy(Fl_Color fg, Fl_Color bg, Fl_Fontsize fs, int context) {
|
||||
|
||||
(void) fs; // currently ignored
|
||||
(void) context; // currently ignored
|
||||
|
||||
// internal static variables, recalculated only if fl_contrast_level() is changed
|
||||
|
||||
static int level = 50; // default, compatible with FLTK 1.3.x
|
||||
static int tc = 99; // sufficient contrast threshold (99 <=> 38.82 %)
|
||||
static int tbw = 127; // black/white threshold (127 <=> 49.80 %)
|
||||
|
||||
// new in FLTK 1.4: adjust thresholds if fl_contrast_level() was changed
|
||||
|
||||
if (fl_contrast_level() != level) {
|
||||
level = fl_contrast_level();
|
||||
if (level == 100)
|
||||
tc = 256;
|
||||
else if (level == 0)
|
||||
tc = 0;
|
||||
else if (level > 50)
|
||||
tc = 99 + ((level - 50) * (255 - 99) / 50);
|
||||
else
|
||||
tc = 99 - ((50 - level) * 99 / 50);
|
||||
}
|
||||
|
||||
// Get the real sRGB values for each color...
|
||||
unsigned cfg = get_color(fg);
|
||||
unsigned cbg = get_color(bg);
|
||||
|
||||
// Compute the luminance for each color (0 .. 255)
|
||||
// Note: FLTK 1.3 compatible, don't change this!
|
||||
|
||||
int lfg = ((cfg >> 24) * 30 + ((cfg >> 16) & 255) * 59 + ((cfg >> 8) & 255) * 11) / 100;
|
||||
int lbg = ((cbg >> 24) * 30 + ((cbg >> 16) & 255) * 59 + ((cbg >> 8) & 255) * 11) / 100;
|
||||
|
||||
int lc = lfg - lbg; // calculated contrast (-255 .. 255)
|
||||
|
||||
// Compare and return the contrasting color...
|
||||
|
||||
if (lc > tc || lc < -tc) return fg; // sufficient contrast
|
||||
if (lbg > tbw) return FL_BLACK; // light background
|
||||
return FL_WHITE; // dark background
|
||||
}
|
||||
|
||||
/*
|
||||
Returns a color that contrasts with the background color.
|
||||
|
||||
** This function is intentionally not public and not documented. **
|
||||
|
||||
This is an improved algorithm compared to the one used in FLTK 1.3.x.
|
||||
It is slower (uses floating point and pow()) but is much more
|
||||
accurate WRT human contrast perception.
|
||||
|
||||
\param[in] fg,bg foreground and background colors
|
||||
\param[in] fs,context unused: fontsize and context
|
||||
\return contrasting color
|
||||
*/
|
||||
static Fl_Color fl_contrast_cielab(Fl_Color fg, Fl_Color bg, Fl_Fontsize fs, int context) {
|
||||
|
||||
(void) fs; // currently ignored
|
||||
(void) context; // currently ignored
|
||||
|
||||
double tc = (double)fl_contrast_level(); // sufficient contrast threshold
|
||||
double tbw = 55.; // black/white threshold
|
||||
|
||||
// Compute the perceived lightness L* (Lstar) and the contrast
|
||||
|
||||
double lfg = fl_lightness(fg);
|
||||
double lbg = fl_lightness(bg);
|
||||
double lc = lfg - lbg;
|
||||
|
||||
// Compare and return the contrasting color...
|
||||
if (lc >= tc || lc <= -tc) return fg; // sufficient contrast
|
||||
if (lbg > tbw) return (Fl_Color)FL_BLACK; // black
|
||||
return (Fl_Color)FL_WHITE; // white
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Returns a color that contrasts with the background color.
|
||||
|
||||
This will be the foreground color if it contrasts sufficiently with the
|
||||
background color. Otherwise, returns \p FL_WHITE or \p FL_BLACK depending
|
||||
on which color provides the best contrast.
|
||||
|
||||
FLTK 1.4.0 uses a different default contrast function than earlier releases
|
||||
(1.3.x) but you can use the old "legacy" contrast function by calling
|
||||
\code
|
||||
fl_contrast_mode(FL_CONTRAST_LEGACY);
|
||||
\endcode
|
||||
early in your main program.
|
||||
|
||||
\note It is a known issue that static initialization using fl_contrast() may already
|
||||
have been executed before you call this function in main(). You should be aware of
|
||||
this and, if necessary, write your own (static) contrast initialization function.
|
||||
This should rarely be necessary.
|
||||
|
||||
You can change the behavior of fl_contrast() in several ways:
|
||||
|
||||
- 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
|
||||
above 50 the overall contrast will generally be higher, i.e. the required contrast
|
||||
to return the foreground color is raised and therefore the calculated color will
|
||||
switch "earlier" to either black or white.
|
||||
In other words, using the following values:
|
||||
- 0 will always use the foreground color
|
||||
- 50 will use the default, unmodified algorithm
|
||||
- 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"
|
||||
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).
|
||||
|
||||
\note Different contrast modes (algorithms) can use their own values and
|
||||
defaults of fl_contrast_level().
|
||||
|
||||
- Change the used contrast calculation function. You can either use the old
|
||||
(FLTK 1.3.x) function or use the better but slower function based on the
|
||||
CIELAB (L*a*b*) color model, or you can define your own custom contrast
|
||||
function if you need even better contrast results.
|
||||
|
||||
The following contrast functions are available:
|
||||
|
||||
- FL_CONTRAST_LEGACY, the old FLTK 1.3.x compatible function. This is the
|
||||
fastest function (using integer arithmetic) but it provides worse results
|
||||
in border cases. You may want to use this on embedded or otherwise CPU
|
||||
constrained systems or if you need strict backwards compatibility.
|
||||
For slightly better results you may utilize the new fl_contrast_level(int)
|
||||
function (since 1.4.0) to increase the contrast sensitivity. This will
|
||||
provide slightly better results than FLTK 1.3.x and earlier but we recommend
|
||||
to use the new default 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.
|
||||
<b>This is the default since FLTK 1.4.0.</b>
|
||||
|
||||
- FL_CONTRAST_CUSTOM, your own contrast calculation function.
|
||||
|
||||
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
|
||||
extensions and are currently not used. Default values are 0.
|
||||
|
||||
\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
|
||||
the fontsize to adjust the calculated contrast, and users defining their own
|
||||
contrast functions may use them in their functions.
|
||||
|
||||
\param[in] fg foreground (text) color
|
||||
\param[in] bg background color
|
||||
\param[in] fs font size (optional, default = 0 == undefined)
|
||||
\param[in] context graphical context (optional, default = 0 == text)
|
||||
|
||||
\return contrasting color: \p fg, \p FL_BLACK, or \p FL_WHITE
|
||||
|
||||
\see fl_contrast_level(int)
|
||||
\see fl_contrast_mode(int)
|
||||
\see fl_contrast_function()
|
||||
*/
|
||||
Fl_Color fl_contrast(Fl_Color fg, Fl_Color bg, Fl_Fontsize fs, int context) {
|
||||
|
||||
switch (fl_contrast_mode_) {
|
||||
|
||||
case FL_CONTRAST_LEGACY:
|
||||
return fl_contrast_legacy(fg, bg, fs, context);
|
||||
|
||||
case FL_CONTRAST_CUSTOM:
|
||||
if (fl_contrast_function_)
|
||||
return (fl_contrast_function_)(fg, bg, fs, context);
|
||||
|
||||
// FALLTHROUGH
|
||||
|
||||
case FL_CONTRAST_CIELAB:
|
||||
return fl_contrast_cielab(fg, bg, fs, context);
|
||||
|
||||
default: // unknown (none): return fg
|
||||
break;
|
||||
}
|
||||
return fg;
|
||||
|
||||
} // fl_contrast()
|
||||
|
||||
/**
|
||||
\}
|
||||
*/
|
@ -1371,6 +1371,15 @@ Fl_compose.o: ../FL/Fl_Valuator.H
|
||||
Fl_compose.o: ../FL/Fl_Widget.H
|
||||
Fl_compose.o: ../FL/platform_types.h
|
||||
Fl_compose.o: Fl_Screen_Driver.H
|
||||
fl_contrast.o: ../FL/Enumerations.H
|
||||
fl_contrast.o: ../FL/Fl.H
|
||||
fl_contrast.o: ../FL/Fl_Cairo.H
|
||||
fl_contrast.o: ../FL/fl_casts.H
|
||||
fl_contrast.o: ../FL/fl_config.h
|
||||
fl_contrast.o: ../FL/Fl_Export.H
|
||||
fl_contrast.o: ../FL/fl_types.h
|
||||
fl_contrast.o: ../FL/fl_utf8.h
|
||||
fl_contrast.o: ../FL/platform_types.h
|
||||
Fl_Copy_Surface.o: ../FL/Enumerations.H
|
||||
Fl_Copy_Surface.o: ../FL/Fl.H
|
||||
Fl_Copy_Surface.o: ../FL/Fl_Bitmap.H
|
||||
|
1
test/.gitignore
vendored
1
test/.gitignore
vendored
@ -30,6 +30,7 @@ clipboard
|
||||
clock
|
||||
colbrowser
|
||||
color_chooser
|
||||
contrast
|
||||
coordinates
|
||||
cube
|
||||
CubeView
|
||||
|
@ -72,6 +72,7 @@ CREATE_EXAMPLE (clipboard clipboard.cxx "fltk_images;fltk")
|
||||
CREATE_EXAMPLE (clock clock.cxx fltk)
|
||||
CREATE_EXAMPLE (colbrowser colbrowser.cxx fltk)
|
||||
CREATE_EXAMPLE (color_chooser color_chooser.cxx fltk)
|
||||
CREATE_EXAMPLE (contrast contrast.cxx fltk)
|
||||
CREATE_EXAMPLE (coordinates coordinates.cxx fltk)
|
||||
CREATE_EXAMPLE (cursor cursor.cxx fltk)
|
||||
CREATE_EXAMPLE (curve curve.cxx fltk)
|
||||
|
@ -65,6 +65,7 @@ CPPFILES =\
|
||||
clock.cxx \
|
||||
colbrowser.cxx \
|
||||
color_chooser.cxx \
|
||||
contrast.cxx \
|
||||
cube.cxx \
|
||||
CubeMain.cxx \
|
||||
CubeView.cxx \
|
||||
@ -159,6 +160,7 @@ ALL = \
|
||||
clock$(EXEEXT) \
|
||||
colbrowser$(EXEEXT) \
|
||||
color_chooser$(EXEEXT) \
|
||||
contrast$(EXEEXT) \
|
||||
cursor$(EXEEXT) \
|
||||
curve$(EXEEXT) \
|
||||
demo$(EXEEXT) \
|
||||
@ -394,6 +396,8 @@ colbrowser$(EXEEXT): colbrowser.o
|
||||
|
||||
color_chooser$(EXEEXT): color_chooser.o
|
||||
|
||||
contrast$(EXEEXT): contrast.o
|
||||
|
||||
cursor$(EXEEXT): cursor.o
|
||||
|
||||
curve$(EXEEXT): curve.o
|
||||
|
454
test/contrast.cxx
Normal file
454
test/contrast.cxx
Normal file
@ -0,0 +1,454 @@
|
||||
//
|
||||
// Contrast function test program for the Fast Light Tool Kit (FLTK).
|
||||
//
|
||||
// Copyright 2022 by Bill Spitzak and others.
|
||||
//
|
||||
// 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
|
||||
// file is missing or damaged, see the license at:
|
||||
//
|
||||
// https://www.fltk.org/COPYING.php
|
||||
//
|
||||
// Please see the following page on how to report bugs and issues:
|
||||
//
|
||||
// https://www.fltk.org/bugs.php
|
||||
//
|
||||
|
||||
// Note: this test and demo program is work in progress. It is published
|
||||
// because it is helpful but it needs some more work to be "perfect" ;-)
|
||||
// AlbrechtS
|
||||
|
||||
#include <FL/Fl.H>
|
||||
#include <FL/Fl_Double_Window.H>
|
||||
#include <FL/Fl_Box.H>
|
||||
#include <FL/Fl_Button.H>
|
||||
#include <FL/Fl_Radio_Round_Button.H>
|
||||
#include <FL/Fl_Color_Chooser.H>
|
||||
#include <FL/Fl_Output.H>
|
||||
#include <FL/Fl_Hor_Value_Slider.H>
|
||||
#include <FL/Fl_Simple_Terminal.H>
|
||||
#include <FL/fl_draw.H>
|
||||
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
// program version
|
||||
|
||||
const char *version = "0.9.0";
|
||||
|
||||
// prototypes and forward declarations
|
||||
|
||||
static void button_cb(Fl_Widget *w, void *v);
|
||||
static Fl_Color calc_contrast(Fl_Color fg, Fl_Color bg, Fl_Fontsize fs);
|
||||
|
||||
// class Button
|
||||
|
||||
class Button : public Fl_Button {
|
||||
char lbuf[20]; // private label buffer
|
||||
Fl_Color ocol_; // "original" (label) color
|
||||
int idx_; // button index (0 - 255)
|
||||
public:
|
||||
Button(int X, int Y, int W, int H, int n)
|
||||
: Fl_Button(X, Y, W, H, "") {
|
||||
idx_ = n;
|
||||
box(FL_THIN_DOWN_BOX);
|
||||
label(lbuf);
|
||||
callback(button_cb);
|
||||
color((Fl_Color)n);
|
||||
sprintf(lbuf, "%03d", n);
|
||||
set_labelcolor(n);
|
||||
labelsize(15);
|
||||
labelfont(FL_HELVETICA);
|
||||
}
|
||||
|
||||
void set_labelcolor(Fl_Color col) {
|
||||
ocol_ = col;
|
||||
labelcolor(calc_contrast(col, color(), labelsize()));
|
||||
}
|
||||
|
||||
Fl_Color ocol() {
|
||||
return ocol_;
|
||||
}
|
||||
|
||||
int idx() {
|
||||
return idx_;
|
||||
}
|
||||
|
||||
virtual void draw() {
|
||||
draw_box();
|
||||
// draw small filled rectangle with "original" color
|
||||
fl_color(ocol_);
|
||||
fl_rectf(x() + 5, y() + 5, 10, h() - 10);
|
||||
// measure and draw label
|
||||
int lw = 0, lh = 0;
|
||||
fl_font(labelfont(), labelsize());
|
||||
fl_measure(lbuf, lw, lh);
|
||||
fl_color(labelcolor());
|
||||
fl_draw(lbuf, x() + 15 + (w() - lw - 15) / 2, y() + h() - (h() - lh) / 2 - lh/4);
|
||||
fl_color(FL_BLACK);
|
||||
}
|
||||
|
||||
}; // class Button
|
||||
|
||||
// global variables
|
||||
|
||||
Fl_Simple_Terminal *term = 0;
|
||||
|
||||
double g_lfg; // perceived lightness of foreground color
|
||||
double g_lbg; // perceived lightness of background color
|
||||
double g_lcref; // calculated contrast reference (CIELAB, L*a*b*)
|
||||
int g_selected = -1; // selected button: -1 = none, 0 - 255 = valid button
|
||||
|
||||
Fl_Fontsize g_fs = 15; // fontsize for button labels
|
||||
int g_level = 0; // *init* fl_contrast_level (sensitivity)
|
||||
|
||||
int g_algo = FL_CONTRAST_LEGACY;// contrast algorithm: 0 = none, 1 = legacy (1.3.x), 2 = CIELAB, 3 = custom
|
||||
const char *alch = ""; // algorithm as char: "LEGACY", "CIELAB" , or "CUSTOM"
|
||||
|
||||
Fl_Color lcolor = FL_BLACK; // label color, set by slider callback
|
||||
Button *buttons[256]; // array of color buttons
|
||||
Fl_Value_Slider *sliders[6]; // array of sliders (gray, red, green, blue, level, fontsize)
|
||||
Fl_Output *color_out = 0; // color output (RRGGBB)
|
||||
|
||||
// Custom contrast algorithm: currently a dummy function (returns fg).
|
||||
// This may be used to define a "better" contrast function in user code
|
||||
|
||||
static Fl_Color custom_contrast(Fl_Color fg, Fl_Color bg, Fl_Fontsize fs, int) {
|
||||
return fg;
|
||||
}
|
||||
|
||||
/*
|
||||
Local function to calculate the contrast and store it in some
|
||||
global variables for display purposes and logging.
|
||||
|
||||
This function is a wrapper around fl_contrast() in this demo program.
|
||||
*/
|
||||
static Fl_Color calc_contrast(Fl_Color fg, Fl_Color bg, Fl_Fontsize fs) {
|
||||
|
||||
// Compute and set global *perceived* lightness L* (Lstar) and contrast for display
|
||||
|
||||
g_lfg = fl_lightness(fg);
|
||||
g_lbg = fl_lightness(bg);
|
||||
g_lcref = g_lfg - g_lbg; // perceived contrast (light on dark = positive)
|
||||
|
||||
switch (g_algo) {
|
||||
case FL_CONTRAST_NONE: // 0 = none (return fg)
|
||||
case FL_CONTRAST_LEGACY: // 1 = legacy (FLTK 1.3.x)
|
||||
case FL_CONTRAST_CIELAB: // 2 = CIELAB (L*a*b*)
|
||||
case FL_CONTRAST_CUSTOM: // 3 = Custom
|
||||
return fl_contrast(fg, bg, fs);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return fg;
|
||||
}
|
||||
|
||||
// set all button label colors and adjust fontsize (labelsize)
|
||||
|
||||
static void update_labels() {
|
||||
for (int i = 0; i < 256; i++) {
|
||||
buttons[i]->set_labelcolor(lcolor);
|
||||
buttons[i]->labelsize(g_fs);
|
||||
}
|
||||
}
|
||||
|
||||
static void button_cb(Fl_Widget *w, void *v) {
|
||||
Button *b = (Button *)w;
|
||||
g_selected = b->idx(); // selected button index
|
||||
Fl_Color ocol = Fl::get_color(b->ocol()); // button's "original" label color (RGB0)
|
||||
Fl_Color fg = Fl::get_color(b->labelcolor()); // button's label color (RGB0)
|
||||
Fl_Color bg = Fl::get_color(b->color()); // button's background color (RGB0)
|
||||
calc_contrast(ocol, bg, g_fs); // calculate values to be displayed
|
||||
const char *color = ""; // calculated label color (text)
|
||||
if (fg == ocol) color = "fg";
|
||||
else if (fg == 0xffffff00) color = "WHITE";
|
||||
else if (fg == 0x0) color = "BLACK";
|
||||
term->printf("[%s] fg: %06x, bg: %06x, lfg: %6.2f, lbg: %6.2f, lc: %7.2f, %s => %-5s",
|
||||
b->label(), ocol >> 8, bg >> 8, g_lfg, g_lbg, g_lcref, alch, color);
|
||||
if (g_algo == FL_CONTRAST_LEGACY ||
|
||||
g_algo == FL_CONTRAST_CIELAB)
|
||||
term->printf(" (level = %3d)\n", g_level);
|
||||
else
|
||||
term->printf("\n");
|
||||
}
|
||||
|
||||
void lf_cb(Fl_Widget *w, void *v) {
|
||||
term->printf("\n");
|
||||
}
|
||||
|
||||
// callback for color (gray and R, G, B) sliders
|
||||
|
||||
void color_slider_cb(Fl_Widget *w, void *v) {
|
||||
int n = fl_int(v); // slider type: 0 = gray, 1 = color
|
||||
unsigned int r, g, b;
|
||||
if (n == 0) { // gray slider
|
||||
int val = (int)sliders[0]->value();
|
||||
lcolor = fl_rgb_color(val, val, val); // set gray value
|
||||
sliders[1]->value(val); // set r/g/b values as well
|
||||
sliders[2]->value(val);
|
||||
sliders[3]->value(val);
|
||||
r = g = b = val;
|
||||
} else { // any color slider
|
||||
r = (unsigned int)sliders[1]->value();
|
||||
g = (unsigned int)sliders[2]->value();
|
||||
b = (unsigned int)sliders[3]->value();
|
||||
lcolor = fl_rgb_color(r, g, b); // set color value
|
||||
}
|
||||
// update button label colors
|
||||
update_labels();
|
||||
// output label color
|
||||
char color_buf[10];
|
||||
sprintf(color_buf, "%02X %02X %02X", r, g, b);
|
||||
color_out->value(color_buf);
|
||||
w->window()->redraw();
|
||||
}
|
||||
|
||||
// callback for "level" and "fontsize" sliders
|
||||
|
||||
void slider_cb(Fl_Widget *w, void *v) {
|
||||
int n = fl_int(v); // slider type: 1 = level, 2 = fontsize
|
||||
switch (n) {
|
||||
case 1: // fl_contrast_level()
|
||||
g_level = (int)sliders[n + 3]->value();
|
||||
fl_contrast_level(g_level); // set/store current contrast level
|
||||
break;
|
||||
case 2: // 2nd slider: fontsize (labelsize)
|
||||
g_fs = (int)sliders[n + 3]->value();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
// update button label colors
|
||||
update_labels();
|
||||
w->window()->redraw();
|
||||
}
|
||||
|
||||
// callback for contrast algorithm (radio buttons)
|
||||
|
||||
void algo_cb(Fl_Widget *w, void *v) {
|
||||
int val = fl_int(v);
|
||||
g_algo = val;
|
||||
switch(val) {
|
||||
case FL_CONTRAST_LEGACY: alch = "LEGACY"; fl_contrast_mode(val); break; // legacy 1.3.x
|
||||
case FL_CONTRAST_CIELAB: alch = "CIELAB"; fl_contrast_mode(val); break; // CIELAB L*a*b*
|
||||
case FL_CONTRAST_CUSTOM: alch = "CUSTOM"; fl_contrast_mode(val); break; // custom
|
||||
case FL_CONTRAST_NONE:
|
||||
default:
|
||||
alch = "none ";
|
||||
fl_contrast_mode(FL_CONTRAST_NONE);
|
||||
break;
|
||||
}
|
||||
g_level = fl_contrast_level(); // get current contrast level (per mode)
|
||||
sliders[4]->value(g_level); // set level slider value
|
||||
update_labels(); // update all button labels
|
||||
|
||||
// print selected button's attributes
|
||||
if (g_selected >= 0) {
|
||||
button_cb(buttons[g_selected], (void *)0);
|
||||
}
|
||||
if (w)
|
||||
w->window()->redraw();
|
||||
}
|
||||
|
||||
// color chooser callback
|
||||
void color_cb(Fl_Widget *w, void *v) {
|
||||
Fl_Color_Chooser *cc = (Fl_Color_Chooser *)w;
|
||||
int r = (int)(cc->r() * 255);
|
||||
int g = (int)(cc->g() * 255);
|
||||
int b = (int)(cc->b() * 255);
|
||||
Fl_Color c = fl_rgb_color(r, g, b);
|
||||
Button *bt = buttons[255]; // last button
|
||||
bt->color(c);
|
||||
bt->set_labelcolor(lcolor);
|
||||
bt->redraw();
|
||||
}
|
||||
|
||||
// ===============================================================
|
||||
// ====================== main() program ======================
|
||||
// ===============================================================
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
|
||||
const int bw = 58;
|
||||
const int bh = 30;
|
||||
int cw = 16 * bw + 10;
|
||||
int ch = 16 * bh + 10;
|
||||
int ww = cw + 10;
|
||||
int wh = 16 * bh + 135 + 10 + 150 /* terminal */ + 10;
|
||||
Fl_Double_Window window(ww, wh, "fl_contrast test");
|
||||
|
||||
int n = 0;
|
||||
Button **b = buttons;
|
||||
for (int y = 0; y < 16; y++) {
|
||||
for (int x = 0; x < 16; x++) {
|
||||
*b = new Button(x * bw + 10, y * bh + 10, bw, bh, n);
|
||||
(*b)->set_labelcolor(n);
|
||||
b++;
|
||||
n++;
|
||||
}
|
||||
}
|
||||
|
||||
// sliders for label color (gray, red, green, blue)
|
||||
|
||||
const int sx = 10 + bw;
|
||||
const int sw = 5 * bw;
|
||||
const int sh = 25;
|
||||
int sy = ch + 10;
|
||||
|
||||
Fl_Hor_Value_Slider *gray = new Fl_Hor_Value_Slider(sx, sy, sw, sh, "gray");
|
||||
gray->color(0xdddddd00);
|
||||
gray->textsize(13);
|
||||
gray->align(FL_ALIGN_LEFT);
|
||||
gray->value(0);
|
||||
gray->bounds(0, 255);
|
||||
gray->step(1);
|
||||
gray->callback(color_slider_cb, (void *)0);
|
||||
sy += sh + 10;
|
||||
|
||||
Fl_Hor_Value_Slider *red = new Fl_Hor_Value_Slider(sx, sy, sw, sh, "red");
|
||||
red->color(FL_RED);
|
||||
red->textcolor(FL_WHITE);
|
||||
red->textsize(13);
|
||||
red->align(FL_ALIGN_LEFT);
|
||||
red->value(0);
|
||||
red->bounds(0, 255);
|
||||
red->step(1);
|
||||
red->callback(color_slider_cb, (void *)1);
|
||||
sy += sh + 5;
|
||||
|
||||
Fl_Hor_Value_Slider *green = new Fl_Hor_Value_Slider(sx, sy, sw, sh, "green");
|
||||
green->color(FL_GREEN);
|
||||
green->textsize(13);
|
||||
green->align(FL_ALIGN_LEFT);
|
||||
green->value(0);
|
||||
green->bounds(0, 255);
|
||||
green->step(1);
|
||||
green->callback(color_slider_cb, (void *)1);
|
||||
sy += sh + 5;
|
||||
|
||||
Fl_Hor_Value_Slider *blue = new Fl_Hor_Value_Slider(sx, sy, sw, sh, "blue");
|
||||
blue->color(FL_BLUE);
|
||||
blue->textcolor(FL_WHITE);
|
||||
blue->textsize(13);
|
||||
blue->align(FL_ALIGN_LEFT);
|
||||
blue->value(0);
|
||||
blue->bounds(0, 255);
|
||||
blue->step(1);
|
||||
blue->callback(color_slider_cb, (void *)1);
|
||||
|
||||
sliders[0] = gray;
|
||||
sliders[1] = red;
|
||||
sliders[2] = green;
|
||||
sliders[3] = blue;
|
||||
|
||||
// contrast algorithm selection group
|
||||
|
||||
int cgx = 10 + 6*bw + 10;
|
||||
int cgy = ch + 30;
|
||||
int cgw = 90;
|
||||
int cgh = 100;
|
||||
int abh = 25;
|
||||
|
||||
Fl_Group *cg = new Fl_Group(cgx, cgy, cgw, cgh, "fl_contrast:");
|
||||
cg->align(FL_ALIGN_TOP);
|
||||
cg->box(FL_FRAME);
|
||||
|
||||
Fl_Radio_Round_Button *anon = new Fl_Radio_Round_Button(cgx, cgy, cgw, abh, "none");
|
||||
Fl_Radio_Round_Button *aleg = new Fl_Radio_Round_Button(cgx, cgy + 25, cgw, abh, "LEGACY");
|
||||
Fl_Radio_Round_Button *acie = new Fl_Radio_Round_Button(cgx, cgy + 50, cgw, abh, "CIELAB");
|
||||
Fl_Radio_Round_Button *aapc = new Fl_Radio_Round_Button(cgx, cgy + 75, cgw, abh, "CUSTOM");
|
||||
aleg->value(1);
|
||||
anon->callback(algo_cb, (void *)0);
|
||||
aleg->callback(algo_cb, (void *)1);
|
||||
acie->callback(algo_cb, (void *)2);
|
||||
aapc->callback(algo_cb, (void *)3);
|
||||
|
||||
cg->end();
|
||||
|
||||
color_out = new Fl_Output(10 + 10 * bw, ch + 10, 100, 30, "label color:");
|
||||
color_out->align(FL_ALIGN_LEFT);
|
||||
color_out->textfont(FL_COURIER);
|
||||
color_out->textsize(16);
|
||||
color_out->value("00 00 00");
|
||||
|
||||
// light blue "level" slider
|
||||
|
||||
Fl_Hor_Value_Slider *s_level = new Fl_Hor_Value_Slider(10 + 9 * bw, red->y(), 3 * bw - 15, sh, "level");
|
||||
s_level->color(231);
|
||||
s_level->textcolor(224);
|
||||
s_level->textsize(13);
|
||||
s_level->align(FL_ALIGN_LEFT);
|
||||
s_level->step(1);
|
||||
s_level->bounds(0, 100);
|
||||
s_level->value(g_level);
|
||||
s_level->callback(slider_cb, (void *)1);
|
||||
s_level->tooltip("set contrast sensitivity level (0-100), default: 50");
|
||||
|
||||
// labelsize slider
|
||||
|
||||
Fl_Hor_Value_Slider *s_fs = new Fl_Hor_Value_Slider(10 + 9 * bw, green->y(), 3 * bw - 15, sh, "labelsize");
|
||||
s_fs->color(231);
|
||||
s_fs->textcolor(224);
|
||||
s_fs->textsize(13);
|
||||
s_fs->align(FL_ALIGN_LEFT);
|
||||
s_fs->step(1);
|
||||
s_fs->bounds(8, 24);
|
||||
s_fs->value(15);
|
||||
s_fs->callback(slider_cb, (void *)2);
|
||||
s_fs->tooltip("set label/text fontsize");
|
||||
|
||||
sliders[4] = s_level;
|
||||
sliders[5] = s_fs;
|
||||
|
||||
// line feed (LF) button
|
||||
|
||||
Fl_Button *lf = new Fl_Button(10 + 8 * bw, blue->y(), bw, sh, "LF");
|
||||
lf->tooltip("Click to output a linefeed to the log.");
|
||||
lf->callback(lf_cb);
|
||||
|
||||
// color chooser for field #255
|
||||
|
||||
int ccx = 10 + 12 * bw;
|
||||
int ccy = ch + 10;
|
||||
int ccw = 4 * bw;
|
||||
int cch = 120;
|
||||
|
||||
Fl_Color_Chooser *color_chooser = new Fl_Color_Chooser(ccx, ccy, ccw, cch);
|
||||
color_chooser->callback(color_cb);
|
||||
color_chooser->label("bg color [255] @->");
|
||||
color_chooser->rgb(1, 1, 1);
|
||||
color_chooser->mode(1); // byte mode
|
||||
color_chooser->align(FL_ALIGN_LEFT_BOTTOM);
|
||||
|
||||
// simple terminal for output (FLTK 1.4 only)
|
||||
|
||||
int ttx = 10;
|
||||
int tty = color_chooser->y() + cch + 10;
|
||||
int ttw = window.w() - 20;
|
||||
int tth = window.h() - tty - 10;
|
||||
|
||||
term = new Fl_Simple_Terminal(ttx, tty, ttw, tth);
|
||||
term->color(FL_WHITE);
|
||||
term->textcolor(FL_BLACK);
|
||||
term->textsize(13);
|
||||
|
||||
term->printf("FLTK fl_contrast() test program with different contrast algorithms, version %s\n", version);
|
||||
term->printf("FLTK version %d.%d.%d\n", FL_MAJOR_VERSION, FL_MINOR_VERSION, FL_PATCH_VERSION);
|
||||
term->printf(" - Select a foreground (text) color with the gray or red/green/blue sliders (displayed inside each field).\n");
|
||||
term->printf(" - Select an arbitrary background color for field #255 with the color chooser.\n");
|
||||
term->printf(" - Select a colored field (by clicking on it) to display its attributes.\n");
|
||||
term->printf(" - Select the contrast algorithm by clicking on the radio buttons.\n");
|
||||
term->printf(" - Tune the contrast algorithm with the light blue \"level\" slider (default: 50).\n");
|
||||
|
||||
// set contrast mode and level, update button label colors
|
||||
|
||||
fl_contrast_mode(g_algo);
|
||||
fl_contrast_function(custom_contrast); // dummy function
|
||||
algo_cb(NULL, fl_voidptr(g_algo)); // updates button labels
|
||||
|
||||
window.resizable(window);
|
||||
window.end();
|
||||
window.show(argc, argv);
|
||||
return Fl::run();
|
||||
}
|
@ -61,7 +61,6 @@
|
||||
@main:Fluid\n(UI design tool):fluid valuators.fl
|
||||
|
||||
@main:Cool\nDemos...:@e
|
||||
@e:X Color\nBrowser:colbrowser rgb.txt
|
||||
@e:Mandelbrot:mandelbrot
|
||||
@e:Fractals:fractals
|
||||
@e:Puzzle:glpuzzle
|
||||
@ -72,17 +71,19 @@
|
||||
@e:Clipboard\nViewer:clipboard
|
||||
|
||||
@main:Other\nTests...:@o
|
||||
@o:Color Choosers:color_chooser
|
||||
@o:File Chooser:file_chooser
|
||||
@o:Native File Chooser:native-filechooser
|
||||
@o:Font Tests...:@of
|
||||
@of:Fonts:fonts
|
||||
@of:UTF-8:utf8
|
||||
@o:HelpDialog:help_dialog help_dialog.html
|
||||
@o:Input Choice:input_choice
|
||||
@o:Preferences:preferences
|
||||
@o:Threading:threads
|
||||
@o:XForms Emulation:forms
|
||||
@o:Colors and Fonts...:@of
|
||||
@of:X Color\nBrowser:colbrowser rgb.txt
|
||||
@of:Color Chooser:color_chooser
|
||||
@of:Color Contrast:contrast
|
||||
@of:Fonts:fonts
|
||||
@of:UTF-8 Fonts:utf8
|
||||
|
||||
@main:Tutorial\nfrom\nManual...:@j
|
||||
@j:ask\n(modified):ask
|
||||
|
@ -459,6 +459,51 @@ color_chooser.o: ../FL/platform.H
|
||||
color_chooser.o: ../FL/platform_types.h
|
||||
color_chooser.o: ../FL/x11.H
|
||||
color_chooser.o: list_visuals.cxx
|
||||
contrast.o: ../FL/Enumerations.H
|
||||
contrast.o: ../FL/Fl.H
|
||||
contrast.o: ../FL/Fl_Bitmap.H
|
||||
contrast.o: ../FL/Fl_Box.H
|
||||
contrast.o: ../FL/Fl_Button.H
|
||||
contrast.o: ../FL/Fl_Cairo.H
|
||||
contrast.o: ../FL/fl_casts.H
|
||||
contrast.o: ../FL/Fl_Choice.H
|
||||
contrast.o: ../FL/Fl_Color_Chooser.H
|
||||
contrast.o: ../FL/fl_config.h
|
||||
contrast.o: ../FL/Fl_Device.H
|
||||
contrast.o: ../FL/Fl_Double_Window.H
|
||||
contrast.o: ../FL/fl_draw.H
|
||||
contrast.o: ../FL/Fl_Export.H
|
||||
contrast.o: ../FL/Fl_Graphics_Driver.H
|
||||
contrast.o: ../FL/Fl_Group.H
|
||||
contrast.o: ../FL/Fl_Hor_Value_Slider.H
|
||||
contrast.o: ../FL/Fl_Image.H
|
||||
contrast.o: ../FL/Fl_Input.H
|
||||
contrast.o: ../FL/Fl_Input_.H
|
||||
contrast.o: ../FL/Fl_Light_Button.H
|
||||
contrast.o: ../FL/Fl_Menu_.H
|
||||
contrast.o: ../FL/Fl_Menu_Item.H
|
||||
contrast.o: ../FL/Fl_Output.H
|
||||
contrast.o: ../FL/Fl_Pixmap.H
|
||||
contrast.o: ../FL/Fl_Plugin.H
|
||||
contrast.o: ../FL/Fl_Preferences.H
|
||||
contrast.o: ../FL/Fl_Radio_Round_Button.H
|
||||
contrast.o: ../FL/Fl_Rect.H
|
||||
contrast.o: ../FL/Fl_Return_Button.H
|
||||
contrast.o: ../FL/Fl_RGB_Image.H
|
||||
contrast.o: ../FL/Fl_Round_Button.H
|
||||
contrast.o: ../FL/Fl_Scrollbar.H
|
||||
contrast.o: ../FL/Fl_Simple_Terminal.H
|
||||
contrast.o: ../FL/Fl_Slider.H
|
||||
contrast.o: ../FL/Fl_Text_Buffer.H
|
||||
contrast.o: ../FL/Fl_Text_Display.H
|
||||
contrast.o: ../FL/fl_types.h
|
||||
contrast.o: ../FL/fl_utf8.h
|
||||
contrast.o: ../FL/Fl_Valuator.H
|
||||
contrast.o: ../FL/Fl_Value_Input.H
|
||||
contrast.o: ../FL/Fl_Value_Slider.H
|
||||
contrast.o: ../FL/Fl_Widget.H
|
||||
contrast.o: ../FL/Fl_Window.H
|
||||
contrast.o: ../FL/platform_types.h
|
||||
cube.o: ../config.h
|
||||
cube.o: ../FL/Enumerations.H
|
||||
cube.o: ../FL/Fl.H
|
||||
|
Loading…
Reference in New Issue
Block a user