All Downloads are FREE. Search and download functionalities are using the official Maven repository.

gov.nasa.worldwind.ogc.kml.impl.KMLScreenImageImpl Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (C) 2012 United States Government as represented by the Administrator of the
 * National Aeronautics and Space Administration.
 * All Rights Reserved.
 */
package gov.nasa.worldwind.ogc.kml.impl;

import gov.nasa.worldwind.ogc.kml.*;
import gov.nasa.worldwind.render.*;
import gov.nasa.worldwind.util.*;

import java.awt.*;
import java.io.IOException;

/**
 * Implements at KML ScreenOverlay element.
 *
 * @author pabercrombie
 * @version $Id: KMLScreenImageImpl.java 1171 2013-02-11 21:45:02Z dcollins $
 */
public class KMLScreenImageImpl extends ScreenImage implements KMLRenderable
{
    /** Size value that KML uses to indicate that the native image dimension should be maintained. */
    protected static final int KML_NATIVE_DIMENSION = -1;

    /** Size value that KML uses to indicate that the image aspect ration should be maintained. */
    protected static final int KML_MAINTAIN_ASPECT_RATIO = 0;

    protected final KMLScreenOverlay parent;

    /** Indicates the time at which the image source was specified. */
    protected long iconRetrievalTime;

    /**
     * Create an screen image.
     *
     * @param tc      the current {@link KMLTraversalContext}.
     * @param overlay the Overlay 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);
        }
    }

    /** {@inheritDoc} */
    public void preRender(KMLTraversalContext tc, DrawContext dc)
    {
        // No pre-rendering
    }

    /**
     * Indicates whether or not the image source needs to be resolved. The source needs to be resolved when the KMLIcon
     * is updated.
     *
     * @return True if the image source must be resolved.
     */
    protected boolean mustResolveHref()
    {
        KMLIcon icon = this.parent.getIcon();
        //noinspection SimplifiableIfStatement
        if (icon == null || icon.getHref() == null)
            return false;

        // Resolve the reference if the image hasn't been retrieved, or if the link has expired.
        return this.getImageSource() == null || icon.getUpdateTime() > this.iconRetrievalTime;
    }

    /**
     * Resolve the HREF in this overlay's Icon element against the KML root.
     *
     * @return The resolved path to the image source.
     */
    protected String resolveHref()
    {
        // The icon reference may be to a support file within a KMZ file, so check for that. If it's not, then just
        // let the normal ScreenImage code resolve the reference.
        String href = this.parent.getIcon().getHref();
        String localAddress = null;
        try
        {
            localAddress = this.parent.getRoot().getSupportFilePath(href);
        }
        catch (IOException e)
        {
            String message = Logging.getMessage("generic.UnableToResolveReference", href);
            Logging.logger().warning(message);
        }

        return localAddress != null ? localAddress : href;
    }

    /** {@inheritDoc} */
    public void render(KMLTraversalContext tc, DrawContext dc)
    {
        if (this.mustResolveHref()) // resolve the href to either a local file or a remote URL
        {
            String path = this.resolveHref();

            // Evict the resource from the file store if there is a cached resource older than the icon update time.
            // This prevents fetching a stale resource out of the cache when the Icon is updated.
            this.parent.getRoot().evictIfExpired(path, this.iconRetrievalTime);

            this.setImageSource(path);
        }

        this.render(dc);
    }

    /**
     * {@inheritDoc} Overridden to set the link expiration time based on HTTP headers after the image has been
     * retrieved.
     */
    protected BasicWWTexture initializeTexture()
    {
        BasicWWTexture ret = super.initializeTexture();
        if (this.texture != null)
        {
            this.iconRetrievalTime = System.currentTimeMillis();

            String path = this.resolveHref();

            // Query the KMLRoot for the expiration time.
            long expiration = this.parent.getRoot().getExpiration(path);

            // Set the Icon's expiration. This has no effect if the refreshMode is not onExpire.
            this.parent.getIcon().setExpirationTime(expiration);
        }
        return ret;
    }

    /**
     * Get the size mode for a size parameter. The KML size tag takes a numeric size attribute, but certain values of
     * this attribute change the interpretation of the tag.
     * 

*

  • A value of -1 indicates to use the native dimension
  • .
  • A value of 0 indicates to maintain the * aspect ratio
  • .
  • A value of n sets the value of the dimension
  • .
* * @param size The KML size attribute * * @return One of {@link gov.nasa.worldwind.render.Size#NATIVE_DIMENSION}, {@link gov.nasa.worldwind.render.Size#MAINTAIN_ASPECT_RATIO}, * or {@link gov.nasa.worldwind.render.Size#EXPLICIT_DIMENSION}. */ protected String getSizeMode(Double size) { // KML spec requires a value, but if there isn't one, use the image's native size. if (size == null) return Size.NATIVE_DIMENSION; int s = (int) size.doubleValue(); if (s == KML_NATIVE_DIMENSION) return Size.NATIVE_DIMENSION; else if (size == KML_MAINTAIN_ASPECT_RATIO) return Size.MAINTAIN_ASPECT_RATIO; else return Size.EXPLICIT_DIMENSION; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy