public void writeObject(Object object, GraphicsDocument document, boolean asChild)
      throws RenderException {
    InternalTile tile = (InternalTile) object;
    String style = null;
    for (InternalFeature feature : tile.getFeatures()) {
      FeatureStyleInfo featureStyle = feature.getStyleInfo();
      if (null != featureStyle) {
        String nextStyle = Integer.toString(featureStyle.getIndex());
        if (style == null || !style.equals(nextStyle)) {
          if (style != null) {
            document.closeElement();
            document.writeElement("vml:group", false);
            document.writeAttribute("coordsize", coordWidth + "," + coordHeight);
            document.writeAttribute("style", "WIDTH: " + coordWidth + "; HEIGHT: " + coordHeight);
          } else {
            document.writeElement("vml:group", true);
            document.writeAttribute("coordsize", coordWidth + "," + coordHeight);
            document.writeAttribute("style", "WIDTH: " + coordWidth + "; HEIGHT: " + coordHeight);
          }
          style = nextStyle;

          VectorLayerInfo layerInfo = feature.getLayer().getLayerInfo();
          if (layerInfo.getLayerType() != LayerType.POINT
              && layerInfo.getLayerType() != LayerType.MULTIPOINT) {

            // the shapetype
            document.writeElement("vml:shapetype", true);
            document.writeAttribute("id", featureStyle.getStyleId());
            document.writeAttribute("style", "WIDTH: 100%; HEIGHT: 100%");
            document.writeAttribute("style", "VISIBILITY: hidden");
            document.writeAttribute("coordsize", coordWidth + "," + coordHeight);
            document.writeAttribute("fillcolor", featureStyle.getFillColor());
            document.writeAttribute("strokecolor", featureStyle.getStrokeColor());
            document.writeAttribute("strokeweight", featureStyle.getStrokeWidth() + "px");

            // Tile-fill element:
            document.writeElement("vml:fill", true);
            document.writeAttribute("opacity", Float.toString(featureStyle.getFillOpacity()));
            document.closeElement();

            // Tile-stroke element:
            document.writeElement("vml:stroke", true);
            document.writeAttribute("opacity", Float.toString(featureStyle.getStrokeOpacity()));
            document.closeElement();

            // up to style group
            document.closeElement();
          }
          // now the feature
          document.writeObject(feature, true);
        } else {
          document.writeObject(feature, false);
        }
      }
    }
    if (style != null) {
      document.closeElement();
    }
    document.closeElement();
  }
  /**
   * Writes the body for a <code>MultiPolygon</code> object. MultiPolygons are encoded into SVG path
   * elements. This function writes the different polygons in one d-attribute of an SVG path
   * element, separated by an 'M' character. (in other words, it calls the super.writeBody for each
   * polygon).
   *
   * @param o The <code>MultiPolygon</code> to be encoded.
   */
  public void writeObject(Object o, GraphicsDocument document, boolean asChild)
      throws RenderException {
    document.writeElement("path", asChild);
    document.writeAttribute("fill-rule", "evenodd");
    document.writeAttributeStart("d");
    MultiPolygon mpoly = (MultiPolygon) o;
    for (int i = 0; i < mpoly.getNumGeometries(); i++) {
      Polygon poly = (Polygon) mpoly.getGeometryN(i);
      LineString shell = poly.getExteriorRing();
      int nHoles = poly.getNumInteriorRing();
      document.writeClosedPathContent(shell.getCoordinates());

      for (int j = 0; j < nHoles; j++) {
        document.writeClosedPathContent(poly.getInteriorRingN(j).getCoordinates());
      }
    }
    document.writeAttributeEnd();
  }