/** Draws the given text. */
  public void plainText(
      double x,
      double y,
      double w,
      double h,
      String str,
      String align,
      String valign,
      boolean wrap,
      String format,
      String overflow,
      boolean clip,
      double rotation) {
    if (state.fontColor == null) {
      state.fontColor = parseColor(state.fontColorValue);
    }

    if (state.fontColor != null) {
      x = (state.dx + x) * state.scale;
      y = (state.dy + y) * state.scale;
      w *= state.scale;
      h *= state.scale;

      // Font-metrics needed below this line
      Graphics2D g2 = createTextGraphics(x, y, w, h, rotation, clip, align, valign);
      FontMetrics fm = g2.getFontMetrics();
      String[] lines = str.split("\n");

      int[] stringWidths = new int[lines.length];
      int textWidth = 0;

      for (int i = 0; i < lines.length; i++) {
        stringWidths[i] = fm.stringWidth(lines[i]);
        textWidth = Math.max(textWidth, stringWidths[i]);
      }

      int textHeight =
          (int) Math.round(lines.length * (fm.getFont().getSize() * mxConstants.LINE_HEIGHT));

      if (clip && textHeight > h && h > 0) {
        textHeight = (int) h;
      }

      Point2D margin = getMargin(align, valign);
      x += margin.getX() * textWidth;
      y += margin.getY() * textHeight;

      if (state.fontBackgroundColorValue != null) {
        if (state.fontBackgroundColor == null) {
          state.fontBackgroundColor = parseColor(state.fontBackgroundColorValue);
        }

        if (state.fontBackgroundColor != null) {
          g2.setColor(state.fontBackgroundColor);
          g2.fillRect((int) Math.round(x), (int) Math.round(y - 1), textWidth + 1, textHeight + 2);
        }
      }

      if (state.fontBorderColorValue != null) {
        if (state.fontBorderColor == null) {
          state.fontBorderColor = parseColor(state.fontBorderColorValue);
        }

        if (state.fontBorderColor != null) {
          g2.setColor(state.fontBorderColor);
          g2.drawRect((int) Math.round(x), (int) Math.round(y - 1), textWidth + 1, textHeight + 2);
        }
      }

      g2.setColor(state.fontColor);
      y += fm.getHeight() - fm.getDescent() - (margin.getY() + 0.5);

      for (int i = 0; i < lines.length; i++) {
        double dx = 0;

        if (align != null) {
          if (align.equals(mxConstants.ALIGN_CENTER)) {
            dx = (textWidth - stringWidths[i]) / 2;
          } else if (align.equals(mxConstants.ALIGN_RIGHT)) {
            dx = textWidth - stringWidths[i];
          }
        }

        // Adds support for underlined text via attributed character iterator
        if (!lines[i].isEmpty()) {
          if ((state.fontStyle & mxConstants.FONT_UNDERLINE) == mxConstants.FONT_UNDERLINE) {
            AttributedString as = new AttributedString(lines[i]);
            as.addAttribute(TextAttribute.FONT, g2.getFont());
            as.addAttribute(TextAttribute.UNDERLINE, TextAttribute.UNDERLINE_ON);

            g2.drawString(as.getIterator(), (int) Math.round(x + dx), (int) Math.round(y));
          } else {
            g2.drawString(lines[i], (int) Math.round(x + dx), (int) Math.round(y));
          }
        }

        y += (int) Math.round(fm.getFont().getSize() * mxConstants.LINE_HEIGHT);
      }
    }
  }
 public void setFontBackgroundColor(String value) {
   if (state.fontBackgroundColorValue == null || !state.fontBackgroundColorValue.equals(value)) {
     state.fontBackgroundColorValue = value;
     state.fontBackgroundColor = null;
   }
 }