package org.osmdroid.bonuspack.kml; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.PorterDuff.Mode; import android.graphics.drawable.BitmapDrawable; import android.os.Parcel; import android.os.Parcelable; import android.util.Log; import org.apache.commons.lang3.StringEscapeUtils; import org.osmdroid.bonuspack.utils.BonusPackHelper; import org.osmdroid.bonuspack.utils.WebImageCache; import org.osmdroid.views.overlay.Marker; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.Writer; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; /** Handling of KML IconStyle */ public class IconStyle extends ColorStyle implements Parcelable { public float mScale; public float mHeading; public String mHref; public Bitmap mIcon; public HotSpot mHotSpot; private static WebImageCache mIconCache; static { //one common memory cache for all icons: mIconCache = new WebImageCache(100); } public IconStyle(){ super(); mScale = 1.0f; mHeading = 0.0f; mHotSpot = new HotSpot(); } /** Load and set the icon bitmap, from a url or from a local file. * @param href either the full url, or a relative path to a local file. Set null for none. * @param containerFile the KML container file - or null if irrelevant. * @param kmzContainer current KMZ file (as a ZipFile) - or null if irrelevant. */ public void setIcon(String href, File containerFile, ZipFile kmzContainer){ mHref = href; if (mHref == null) { mIcon = null; } else if (mHref.startsWith("http://") || mHref.startsWith("https://")) { mIcon = mIconCache.get(mHref); } else if (kmzContainer == null){ if (containerFile != null){ String actualFullPath = containerFile.getParent()+'/'+mHref; mIcon = BitmapFactory.decodeFile(actualFullPath); } else mIcon = null; } else { try { final ZipEntry fileEntry = kmzContainer.getEntry(href); InputStream stream = kmzContainer.getInputStream(fileEntry); mIcon = BitmapFactory.decodeStream(stream); } catch (Exception e) { mIcon = null; } } } /** @return the icon, scaled and blended with the icon color, as specified in the IconStyle. * Assumes the icon is already loaded. */ public BitmapDrawable getFinalIcon(Context context){ if (mIcon == null) return null; int sizeX = Math.round(mIcon.getWidth() * mScale); int sizeY = Math.round(mIcon.getHeight() * mScale); if (sizeX == 0 || sizeY == 0) { Log.w(BonusPackHelper.LOG_TAG, "KML icon has size=0"); return null; } Bitmap scaledBitmap = Bitmap.createScaledBitmap(mIcon, sizeX, sizeY, true); BitmapDrawable marker = new BitmapDrawable(context.getResources(), scaledBitmap); int color = getFinalColor(); if (color != 0) //there is a real color to blend with: marker.setColorFilter(color, Mode.MULTIPLY); return marker; } /** apply all IconStyle attributes to the Marker */ public void styleMarker(Marker marker, Context context){ BitmapDrawable icon = getFinalIcon(context); if (icon != null) { marker.setIcon(icon); marker.setAnchor(mHotSpot.getX(icon.getIntrinsicWidth() / mScale), 1.0f - mHotSpot.getY(icon.getIntrinsicHeight() / mScale)); } //else, default Marker icon will be used. //Y coords are top->bottom for Marker Anchor, and bottom->up for KML hotSpot marker.setRotation(mHeading); } public void writeAsKML(Writer writer){ try { writer.write("<IconStyle>\n"); super.writeAsKML(writer); //write the specifics: if (mScale != 1.0f) writer.write("<scale>"+mScale+"</scale>\n"); if (mHeading != 0.0f) writer.write("<heading>"+mHeading+"</heading>\n"); if (mHref != null) writer.write("<Icon><href>"+StringEscapeUtils.escapeXml10(mHref)+"</href></Icon>\n"); mHotSpot.writeAsKML(writer); writer.write("</IconStyle>\n"); } catch (IOException e) { e.printStackTrace(); } } //Parcelable implementation ------------ @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel out, int flags) { super.writeToParcel(out, flags); out.writeFloat(mScale); out.writeFloat(mHeading); out.writeString(mHref); out.writeParcelable(mIcon, flags); out.writeParcelable(mHotSpot, flags); } public static final Creator<IconStyle> CREATOR = new Creator<IconStyle>() { @Override public IconStyle createFromParcel(Parcel source) { return new IconStyle(source); } @Override public IconStyle[] newArray(int size) { return new IconStyle[size]; } }; public IconStyle(Parcel in){ super(in); mScale = in.readFloat(); mHeading = in.readFloat(); mHref = in.readString(); mIcon = in.readParcelable(Bitmap.class.getClassLoader()); mHotSpot = in.readParcelable(HotSpot.class.getClassLoader()); } }