Mercurial > octave
diff scripts/plot/draw/private/__patch__.m @ 30634:36d940c58c2e
Improve input validation for patch function (bug #61782)
* patch.m: Avoid call to gca() before executing __patch__ as input validation may
stop patch from being created leaving empty figure and axes objects. Add BIST
tests for input validation.
* __patch__.m: Remove second output of function (failed). Detect 3-input case
with bad color specification and issue and emit an error. Add comments to
clarify code about which input combination is being processed in long if/elseif
tree. Call gca() if patch is validated but no axes has been specified.
* fill.m: Re-write call to __patch__ to match new function with only one output.
author | Rik <rik@octave.org> |
---|---|
date | Tue, 11 Jan 2022 12:17:16 -0800 |
parents | 796f54d4ddbf |
children | 597f3ee61a48 |
line wrap: on
line diff
--- a/scripts/plot/draw/private/__patch__.m Tue Jan 11 20:43:58 2022 +0100 +++ b/scripts/plot/draw/private/__patch__.m Tue Jan 11 12:17:16 2022 -0800 @@ -32,153 +32,154 @@ ## Create patch object from x and y with color c and parent p. ## Return handle to patch object. -function [h, failed] = __patch__ (p, varargin) +function h = __patch__ (p, varargin) h = NaN; - failed = false; + nargin = nargin - 1; is_numeric_arg = cellfun (@isnumeric, varargin); if (isempty (varargin)) - args = varargin; + args = {}; elseif (is_numeric_arg(1)) if (nargin < 3 || ! is_numeric_arg(2)) - failed = true; - else - if (nargin > 4 && all (is_numeric_arg(1:4))) - x = varargin{1}; - y = varargin{2}; + print_usage ("patch"); + endif + + if (nargin >= 4 && all (is_numeric_arg(1:4))) + x = varargin{1}; + y = varargin{2}; + z = varargin{3}; + c = varargin{4}; + iarg = 5; + elseif (nargin >= 3 && all (is_numeric_arg(1:3))) + x = varargin{1}; + y = varargin{2}; + if (nargin > 3 && iscolorspec (varargin{4})) z = varargin{3}; c = varargin{4}; iarg = 5; - elseif (nargin > 3 && all (is_numeric_arg(1:3))) - x = varargin{1}; - y = varargin{2}; - if (nargin > 4 && iscolorspec (varargin{4})) - z = varargin{3}; - c = varargin{4}; - iarg = 5; - else - z = []; - c = varargin{3}; - iarg = 4; - endif - elseif (nargin > 2 && all (is_numeric_arg(1:2))) - x = varargin{1}; - y = varargin{2}; + else z = []; - if (iscolorspec (varargin{3})) - c = varargin{3}; - iarg = 4; - else - c = []; - iarg = 3; - endif + c = varargin{3}; + iarg = 4; endif + elseif (nargin >= 3 && all (is_numeric_arg(1:2))) + x = varargin{1}; + y = varargin{2}; + z = []; + if (iscolorspec (varargin{3})) + c = varargin{3}; + iarg = 4; + elseif (nargin == 3) + error ("patch: invalid color specification C"); + else + c = []; + iarg = 3; + endif + endif - if (isvector (x)) - x = x(:); - y = y(:); - z = z(:); - if (isnumeric (c)) - if (isvector (c)) - if (isequal (size (c), [1, 3])) - ## Do nothing, this is a single RGB color specification - elseif (numel (c) == numel (x)) - c = c(:); - endif - elseif (rows (c) != numel (x) && columns (c) == numel (x)) - c = c.'; + if (isvector (x)) + x = x(:); + y = y(:); + z = z(:); + if (isnumeric (c)) + if (isvector (c)) + if (isequal (size (c), [1, 3])) + ## Do nothing, this is a single RGB color specification + elseif (numel (c) == numel (x)) + c = c(:); endif + elseif (rows (c) != numel (x) && columns (c) == numel (x)) + c = c.'; endif endif - args{1} = "xdata"; - args{2} = x; - args{3} = "ydata"; - args{4} = y; - args{5} = "zdata"; - args{6} = z; + endif + args{1} = "xdata"; + args{2} = x; + args{3} = "ydata"; + args{4} = y; + args{5} = "zdata"; + args{6} = z; - if (isnumeric (c)) + if (isnumeric (c) && ! isempty (c)) - if (ndims (c) == 3 && columns (c) == 1) - c = permute (c, [1, 3, 2]); - endif + if (ndims (c) == 3 && columns (c) == 1) + c = permute (c, [1, 3, 2]); + endif - if (isvector (c) && numel (c) == columns (x)) - if (isnan (c)) - args{7} = "facecolor"; - args{8} = [1, 1, 1]; - args{9} = "cdata"; - args{10} = c; - elseif (isnumeric (c)) - args{7} = "facecolor"; - args{8} = "flat"; - args{9} = "cdata"; - args{10} = c; - else - error ("patch: color data C must be numeric"); - endif - elseif (isrow (c) && numel (c) == 3) + if (isvector (c) && numel (c) == columns (x)) + ## One color per face + if (isnan (c)) + args{7} = "facecolor"; + args{8} = [1, 1, 1]; + else args{7} = "facecolor"; - args{8} = c; + args{8} = "flat"; + endif + args{9} = "cdata"; + args{10} = c; + elseif (isrow (c) && numel (c) == 3) + ## One RGB color + args{7} = "facecolor"; + args{8} = c; + args{9} = "cdata"; + args{10} = []; + elseif (ndims (c) == 3 && size (c, 3) == 3) + ## CDATA is specified as 3-D RGB data + if ((rows (c) == 1 && columns (c) == 1) ... + || (rows (c) == 1 && columns (c) == columns (x))) + ## Single patch color or per-face color + args{7} = "facecolor"; + args{8} = "flat"; + args{9} = "cdata"; + args{10} = c; + elseif (rows (c) == rows (x) && columns (c) == columns (x)) + ## Per-vertex color + args{7} = "facecolor"; + args{8} = "interp"; + args{9} = "cdata"; + args{10} = c; + else + error ("patch: invalid TrueColor data C"); + endif + else + ## Color vectors + if (isempty (c)) + args{7} = "facecolor"; + args{8} = "interp"; args{9} = "cdata"; args{10} = []; - elseif (ndims (c) == 3 && size (c, 3) == 3) - ## CDATA is specified as RGB data - if ((rows (c) == 1 && columns (c) == 1) ... - || (rows (c) == 1 && columns (c) == columns (x))) - ## Single patch color or per-face color - args{7} = "facecolor"; - args{8} = "flat"; - args{9} = "cdata"; - args{10} = c; - elseif (rows (c) == rows (x) && columns (c) == columns (x)) - ## Per-vertex color - args{7} = "facecolor"; - args{8} = "interp"; - args{9} = "cdata"; - args{10} = c; - else - error ("patch: Invalid TrueColor data C"); - endif + elseif (size_equal (c, x) && size_equal (c, y)) + args{7} = "facecolor"; + args{8} = "interp"; + args{9} = "cdata"; + args{10} = c; else - ## Color Vectors - if (isempty (c)) - args{7} = "facecolor"; - args{8} = "interp"; - args{9} = "cdata"; - args{10} = []; - elseif (size_equal (c, x) && size_equal (c, y)) - args{7} = "facecolor"; - args{8} = "interp"; - args{9} = "cdata"; - args{10} = c; - else - error ("patch: size of X, Y, and C must be equal"); - endif + error ("patch: size of X, Y, and C must be equal"); endif - elseif (iscolorspec (c)) - args{7} = "facecolor"; - args{8} = tolower (c); - args{9} = "cdata"; - args{10} = []; - else - args{7} = "facecolor"; - args{8} = [0, 0, 0]; - args{9} = "cdata"; - args{10} = []; endif + elseif (iscolorspec (c)) + ## Color specification is a string + args{7} = "facecolor"; + args{8} = tolower (c); + args{9} = "cdata"; + args{10} = []; + elseif (! isempty (c)) + error ("patch: invalid color specification C"); + endif - args = [args, varargin(iarg:end)]; - endif + args = [args, varargin(iarg:end)]; + else + ## "Property"/Value pair input args = varargin; endif - if (! failed) - h = __go_patch__ (p, args{:}); + if (isempty (p)) + p = gca (); endif + h = __go_patch__ (p, args{:}); endfunction