Mercurial > octave
view scripts/plot/appearance/whitebg.m @ 22709:5c04055aa767
maint: Strip trailing whitespace from source files.
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Tue, 01 Nov 2016 16:38:34 -0400 |
parents | e70551dacef6 |
children | 3a2b891d0b33 |
line wrap: on
line source
## Copyright (C) 2010-2016 David Bateman ## ## This file is part of Octave. ## ## Octave 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. ## ## Octave 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 Octave; see the file COPYING. If not, see ## <http://www.gnu.org/licenses/>. ## -*- texinfo -*- ## @deftypefn {} {} whitebg () ## @deftypefnx {} {} whitebg (@var{color}) ## @deftypefnx {} {} whitebg ("none") ## @deftypefnx {} {} whitebg (@var{hfig}) ## @deftypefnx {} {} whitebg (@var{hfig}, @var{color}) ## @deftypefnx {} {} whitebg (@var{hfig}, "none") ## Invert the colors in the current color scheme. ## ## The root properties are also inverted such that all subsequent plots will ## use the new color scheme. ## ## If the optional argument @var{color} is present then the background color ## is set to @var{color} rather than inverted. @var{color} may be a string ## representing one of the eight known colors or an RGB triplet. The special ## string argument @qcode{"none"} restores the plot to the factory default ## colors. ## ## If the first argument @var{hfig} is a figure handle or list of figure ## handles, then operate on these figures rather than the current figure ## returned by @code{gcf}. The root properties will not be changed unless 0 ## is in the list of figures. ## ## Programming Note: @code{whitebg} operates by changing the color properties ## of the children of the specified figures. Only objects with a single color ## are affected. For example, a patch with a single @qcode{"FaceColor"} will ## be changed, but a patch with shading (@qcode{"interp"}) will not be ## modified. For inversion, the new color is simply the inversion in RGB ## space: @code{@var{cnew} = [1-@var{R} 1-@var{G} 1-@var{B}]}. When a color ## is specified, the axes and figure are set to the new color, and the color ## of child objects are then adjusted to have some contrast (visibility) ## against the new background. ## @seealso{reset, get, set} ## @end deftypefn ## FIXME: It's not clear whether Matlab also changes color properties ## of the figure object itself, or only the children. However, visually, ## it looks better to change the figure along with the axes background. function whitebg (varargin) if (nargin > 2) print_usage (); endif h = 0; color = NaN; have_fig = false; if (nargin > 0) if (all (ishandle (varargin{1}))) h = varargin{1}; have_fig = true; if (nargin == 2) color = varargin{2}; endif elseif (nargin == 1) color = varargin{1}; else print_usage (); endif endif if (! have_fig) fig = gcf (); do_root = true; elseif (all (isfigure (h) | h == 0)) fig = h(h != 0); do_root = any (h == 0); else error ("whitebg: HFIG must be a valid figure handle"); endif if (isnan (color)) if (do_root) ## Set the default axes and figure properties on root ## so that subsequent plots have the new color scheme fac = get (0, "factory"); fields = fieldnames (fac); idx = ! cellfun ("isempty", regexp (fields, '^factory(axes|figure).*color$')); ## Use default value in place of factory value if specified. for field = fields(idx)' defaultfield = strrep (field{1}, "factory", "default"); try defaultvalue = 1 - get (0, defaultfield); catch defaultvalue = 1 - fac.(field{1}); end_try_catch set (0, defaultfield, defaultvalue); endfor endif ## The sort is necessary so that child legend objects are acted on ## before the legend axes object. hlist = sort (findobj (fig)); for h = hlist' props = get (h); fields = fieldnames (props); ## Find all fields with the word color in them and invert. idx = find (! cellfun ("isempty", regexp (fields, 'color$'))); for field = fields(idx)'; c = props.(field{1}); if (! ischar (c) && columns (c) == 3) set (h, field{1}, 1 - c); endif endfor endfor else # 2nd argument such as a color or "none" if (! strcmp (color, "none")) ## Set the specified color on the figure and all axes objects hlist = [fig; findobj(fig, "type", "axes")]; set (hlist, "color", color); if (do_root) defs = get (0, "default"); if (isfield (defs, "defaultaxescolor") && strcmp (defs.defaultaxescolor, "none")) set (0, "defaultaxescolor", color); endif endif ## Adjust colors of remaining objects to have some contrast bg = rgb2hsv (get (fig, "color")); ## List of children without the figure and axes objects already changed hlist = setdiff (findobj (fig), hlist); for h = hlist' props = get (h); fields = fieldnames (props); ## Find all fields with the word color in them and adjust HSV. idx = find (! cellfun ("isempty", regexp (fields, 'color$'))); for field = fields(idx)'; c = props.(field{1}); if (! ischar (c) && columns (c) == 3) set (h, field{1}, calc_contrast_color (bg, c)); endif endfor endfor else ## Reset colors to factory defaults if (do_root) fac = get (0, "factory"); fields = fieldnames (fac); idx = ! cellfun ("isempty", regexp (fields, '^factory(axes|figure).*color$')); for field = fields(idx)' factoryfield = field{1}; factoryvalue = fac.(factoryfield); if (strncmp (factoryfield, "factoryfigure", 13)) ## Strip off "factoryfigure" part of fieldname before applying set (fig, factoryfield(14:end), factoryvalue); endif ## Remove applied default from root defaultfield = strrep (factoryfield, "factory", "default"); set (0, defaultfield, "remove"); endfor endif hlist = sort (findobj (fig)); for h = hlist' props = get (h); fields = fieldnames (props); ## Find all fields with the word color in them and restore to factory. idx = find (! cellfun ("isempty", regexp (fields, 'color$'))); for field = fields(idx)' set (h, field{1}, "factory"); endfor endfor endif endif endfunction ## Calculate a new color which contrasts with the supplied bg color and is ## perceptually related to the original color. ## ## Input color bg must be in HSV space. Input color corig is in RGB space. ## ## FIXME: Calculation is segregated into its own function in case anyone wants ## to try and improve the selection of a "contrasting" color. ## ## This algorithm maintains at least 90 degrees separation between corig and bg ## in Hue rotation space. No modifications are done for saturation or value. function cnew = calc_contrast_color (bg, corig) hsv = rgb2hsv (corig); contrast_hue = mod (bg(1) + 0.5, 1); # Generate a contrasting bg color ## If close to existing contrast color, leave alone delta = abs (hsv(1) - contrast_hue); if (delta < 0.25 || delta > 0.75) cnew(1) = hsv(1); else cnew(1) = mod (hsv(1) + 0.5, 1); endif ## No modifications to saturation or value. cnew(2:3) = hsv(2:3); cnew = hsv2rgb (cnew); endfunction %!test %! dac = get (0, "defaultaxescolor"); %! dfc = get (0, "defaultfigurecolor"); %! hf = figure ("visible", "off"); %! unwind_protect %! hl = line ("Color", "r"); %! assert (get (hf, "color"), dfc); %! assert (get (gca, "color"), dac); %! assert (get (hl, "color"), [1 0 0]); %! whitebg (hf); %! assert (get (hf, "color"), 1 - dfc); %! assert (get (gca, "color"), 1 - dac); %! assert (get (hl, "color"), [0 1 1]); %! c = [0.2 0.2 0.2]; %! whitebg (hf, c); %! assert (get (hf, "color"), c); %! assert (get (gca, "color"), c); %! unwind_protect_cleanup %! close (hf); %! end_unwind_protect ## Test input validation %!error whitebg (1,2,3) %!error whitebg ({1}, 2)