@Override
 public int hashCode() {
   int result = characters.hashCode();
   result = 31 * result + color.hashCode();
   result = 31 * result + style.hashCode();
   return result;
 }
 @Override
 public String toString() {
   if (ignoreRendering) return characters;
   return ANSI.getStart()
       + style.toString()
       + ';'
       + this.color.toString()
       + 'm'
       + getCharacters()
       + ANSI.reset();
 }
 public void write(PrintStream out) {
   if (ignoreRendering) {
     out.print(characters);
   } else {
     out.print(ANSI.getStart());
     out.print(style.toString());
     out.print(';');
     this.color.write(out);
     out.print('m');
     out.print(getCharacters());
   }
 }
 public int getANSILength() {
   if (ignoreRendering) return 0;
   else {
     if (ansiLength == 0)
       ansiLength =
           ANSI.getStart().length()
               + color.getLength()
               + style.getLength()
               + ANSI.reset().length()
               + 2; // ; + m
     return ansiLength;
   }
 }
  /** style, text color, background color */
  public String toString(TerminalString prev) {
    if (ignoreRendering) return characters;
    if (equalsIgnoreCharacter(prev)) return characters;
    else {
      StringBuilder builder = new StringBuilder();
      builder.append(ANSI.getStart()).append(style.getValueComparedToPrev(prev.getStyle()));

      if (!this.color.equals(prev.color)) {
        if (prev.getStyle().isInvert()) builder.append(';').append(this.color.toString());
        else builder.append(';').append(this.color.toString(prev.color));
      }

      builder.append('m').append(getCharacters());
      return builder.toString();
    }
  }