@Override
  public void drawString(String string, BoundingBox2d bounds, double padding) {
    FontMetrics metrics = pipe.getFontMetrics(pipe.getFont());

    final double stringWidth = metrics.stringWidth(string);
    final double stringHeight = metrics.getHeight();

    // calculate scale, so that bb fits into bounds - padding
    final double sx = bounds.getWidth() / (stringWidth + padding);
    final double sy = bounds.getHeight() / (stringHeight + padding);

    final double scale = Math.min(sx, sy);

    java.awt.Font oldFont = pipe.getFont();
    java.awt.Font scaledFont = oldFont.deriveFont((float) (oldFont.getSize2D() * scale));

    // position b inside bounds
    final double x = bounds.getLocation().getX() + (bounds.getWidth() - stringWidth * scale) / 2;
    final double y =
        bounds.getLocation().getY()
            + bounds.getHeight()
            - (bounds.getHeight() - scaledFont.getSize2D()) / 2;

    pipe.setFont(scaledFont);
    try {
      pipe.drawString(string, (float) x, (float) y);
    } finally {
      pipe.setFont(oldFont);
    }
  }
 @Override
 public void drawString(String string, double x, double y) {
   pipe.drawString(string, (float) x, (float) y);
 }
 @Override
 public Font getFont() {
   return Convert.convertAwtFontToFont(pipe.getFont());
 }
 @Override
 public void setFont(Font font) {
   pipe.setFont(Convert.convertFontToAwtFont(font));
 }
 @Override
 public Brush getBrush() {
   return Convert.convertToBrush(pipe.getPaint());
 }
 @Override
 public void setBrush(Brush brush) {
   pipe.setPaint(Convert.convertToAwtPaint(brush));
 }
 @Override
 public Pen getPen() {
   // TODO: this sucks
   return Convert.convertStroke((BasicStroke) pipe.getStroke());
 }
 @Override
 public void setPen(Pen pen) {
   pipe.setStroke(convertPen(pen));
 }
 @Override
 public Matrix2d getTransform() {
   return convertAffineTransform(pipe.getTransform());
 }
 @Override
 public void setTransform(Matrix2d xform) {
   pipe.setTransform(convertMatrix(xform));
 }
 @Override
 public void fillPolygon(Polygon2d polygon) {
   pipe.fill(convertPolygon(polygon));
 }
 @Override
 public void drawPolygon(Polygon2d polygon) {
   pipe.draw(convertPolygon(polygon));
 }
 private void fillShape(Shape s) {
   pipe.fill(s);
 }
 private void drawShape(Shape s) {
   pipe.draw(s);
 }
 @Override
 public void drawLine(Point2d start, Point2d end) {
   pipe.drawLine((int) start.getX(), (int) start.getY(), (int) end.getX(), (int) end.getY());
 }