/**
   * Determine and set the {@link Path} highlight attributes from the KML <i>Feature</i> fields.
   *
   * @param attrType the type of attributes, either {@link KMLConstants#NORMAL} or {@link
   *     KMLConstants#HIGHLIGHT}.
   * @return the new attributes.
   */
  protected ShapeAttributes makeAttributesCurrent(String attrType) {
    ShapeAttributes attrs =
        this.getInitialAttributes(
            this.isHighlighted() ? KMLConstants.HIGHLIGHT : KMLConstants.NORMAL);

    // Get the KML sub-style for Line attributes. Map them to Shape attributes.

    KMLAbstractSubStyle lineSubStyle = this.parent.getSubStyle(new KMLLineStyle(null), attrType);
    if (!this.isHighlighted() || KMLUtil.isHighlightStyleState(lineSubStyle)) {
      KMLUtil.assembleLineAttributes(attrs, (KMLLineStyle) lineSubStyle);
      if (lineSubStyle.hasField(AVKey.UNRESOLVED)) attrs.setUnresolved(true);
    }

    // Get the KML sub-style for interior attributes. Map them to Shape attributes.

    KMLAbstractSubStyle fillSubStyle = this.parent.getSubStyle(new KMLPolyStyle(null), attrType);
    if (!this.isHighlighted() || KMLUtil.isHighlightStyleState(lineSubStyle)) {
      KMLUtil.assembleInteriorAttributes(attrs, (KMLPolyStyle) fillSubStyle);
      if (fillSubStyle.hasField(AVKey.UNRESOLVED)) attrs.setUnresolved(true);
    }

    attrs.setDrawInterior(((KMLPolyStyle) fillSubStyle).isFill());
    attrs.setDrawOutline(((KMLPolyStyle) fillSubStyle).isOutline());

    return attrs;
  }
  /**
   * Create an screen image.
   *
   * @param tc the current {@link KMLTraversalContext}.
   * @param overlay the <i>Overlay</i> element containing.
   * @throws NullPointerException if the traversal context is null.
   * @throws IllegalArgumentException if the parent overlay or the traversal context is null.
   */
  public KMLSurfaceImageImpl(KMLTraversalContext tc, KMLGroundOverlay overlay) {
    this.parent = overlay;

    if (tc == null) {
      String msg = Logging.getMessage("nullValue.TraversalContextIsNull");
      Logging.logger().severe(msg);
      throw new IllegalArgumentException(msg);
    }

    if (overlay == null) {
      String msg = Logging.getMessage("nullValue.ParentIsNull");
      Logging.logger().severe(msg);
      throw new IllegalArgumentException(msg);
    }

    // Positions are specified either as a kml:LatLonBox or a gx:LatLonQuad
    KMLLatLonBox box = overlay.getLatLonBox();
    if (box != null) {
      Sector sector = KMLUtil.createSectorFromLatLonBox(box);
      this.initializeGeometry(sector);

      // TODO: rotation
    } else {
      GXLatLongQuad latLonQuad = overlay.getLatLonQuad();
      if (latLonQuad != null && latLonQuad.getCoordinates() != null) {
        this.initializeGeometry(latLonQuad.getCoordinates().list);
      }
    }

    this.setPickEnabled(false);
  }
  /**
   * Create an screen image.
   *
   * @param tc the current {@link KMLTraversalContext}.
   * @param overlay the <i>Overlay</i> element containing.
   * @throws NullPointerException if the traversal context is null.
   * @throws IllegalArgumentException if the parent overlay or the traversal context is null.
   */
  public KMLScreenImageImpl(KMLTraversalContext tc, KMLScreenOverlay overlay) {
    this.parent = overlay;

    if (tc == null) {
      String msg = Logging.getMessage("nullValue.TraversalContextIsNull");
      Logging.logger().severe(msg);
      throw new IllegalArgumentException(msg);
    }

    if (overlay == null) {
      String msg = Logging.getMessage("nullValue.ParentIsNull");
      Logging.logger().severe(msg);
      throw new IllegalArgumentException(msg);
    }

    KMLVec2 xy = this.parent.getScreenXY();
    if (xy != null) {
      this.screenOffset =
          new Offset(
              xy.getX(),
              xy.getY(),
              KMLUtil.kmlUnitsToWWUnits(xy.getXunits()),
              KMLUtil.kmlUnitsToWWUnits(xy.getYunits()));
    }

    xy = this.parent.getOverlayXY();
    if (xy != null) {
      this.imageOffset =
          new Offset(
              xy.getX(),
              xy.getY(),
              KMLUtil.kmlUnitsToWWUnits(xy.getXunits()),
              KMLUtil.kmlUnitsToWWUnits(xy.getYunits()));
    }

    this.setRotation(overlay.getRotation());

    xy = this.parent.getRotationXY();
    if (xy != null) {
      setRotationOffset(
          new Offset(
              xy.getX(),
              xy.getY(),
              KMLUtil.kmlUnitsToWWUnits(xy.getXunits()),
              KMLUtil.kmlUnitsToWWUnits(xy.getYunits())));
    }

    String colorStr = overlay.getColor();
    if (colorStr != null) {
      Color color = WWUtil.decodeColorABGR(colorStr);
      this.setColor(color);
    }

    // Compute desired image size, and the scale factor that will make it that size
    KMLVec2 kmlSize = this.parent.getSize();
    if (kmlSize != null) {
      Size size = new Size();
      size.setWidth(
          getSizeMode(kmlSize.getX()),
          kmlSize.getX(),
          KMLUtil.kmlUnitsToWWUnits(kmlSize.getXunits()));
      size.setHeight(
          getSizeMode(kmlSize.getY()),
          kmlSize.getY(),
          KMLUtil.kmlUnitsToWWUnits(kmlSize.getYunits()));
      this.setSize(size);
    }
  }