code: protected List<TermFunction.Gradient.ColorStop> decodeColorStops(List<List<Term<?>>> args, int firstStop) {
          boolean valid = true;
          List<TermFunction.Gradient.ColorStop> colorStops = null;
          if (args.size() > firstStop) {
              colorStops = new ArrayList<>();
              for (int i = firstStop; valid && i < args.size(); i++) {
                  List<Term<?>> sarg = args.get(i);
                  if (sarg.size() == 1 || sarg.size() == 2) {
                      Term<?> tclr = sarg.get(0);
                      Term<?> tlen = (sarg.size() == 2) ? sarg.get(1) : null;
                      if (tclr instanceof TermColor
                              && (tlen == null || tlen instanceof TermLengthOrPercent)) {
                          TermFunction.Gradient.ColorStop newStop = new ColorStopImpl((TermColor) tclr, (TermLengthOrPercent) tlen);
                          colorStops.add(newStop);
                      } else {
                          valid = false;
                      }
                  } else {
                      valid = false;
                  }
              }
          }
          if (valid && colorStops != null && !colorStops.isEmpty())
              return colorStops;
          else
              return null;
      }
docs: Loads the color stops from the gunction arguments.
  @param args the comma-separated function arguments
  @param firstStop the first argument to start with
  @return the list of color stops or {@code null} when the arguments are invalid or missing