summaryrefslogtreecommitdiff
path: root/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk
diff options
context:
space:
mode:
Diffstat (limited to 'platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk')
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLngBounds.java227
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/HTTPRequest.java1
-rwxr-xr-xplatform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java5
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/storage/FileSource.java5
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/PropertyFactory.java20
5 files changed, 194 insertions, 64 deletions
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLngBounds.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLngBounds.java
index 2b56f5b326..c639e49013 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLngBounds.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLngBounds.java
@@ -238,6 +238,7 @@ public class LatLngBounds implements Parcelable {
westLon = temp;
}
} else {
+ lonSpan = GeometryConstants.LONGITUDE_SPAN - lonSpan;
if (westLon < eastLon) {
double temp = eastLon;
eastLon = westLon;
@@ -293,6 +294,20 @@ public class LatLngBounds implements Parcelable {
@FloatRange(from = GeometryConstants.MIN_LATITUDE, to = GeometryConstants.MAX_LATITUDE) double latSouth,
double lonWest) {
+ checkParams(latNorth, lonEast, latSouth, lonWest);
+
+ lonEast = LatLng.wrap(lonEast, GeometryConstants.MIN_LONGITUDE, GeometryConstants.MAX_LONGITUDE);
+ lonWest = LatLng.wrap(lonWest, GeometryConstants.MIN_LONGITUDE, GeometryConstants.MAX_LONGITUDE);
+
+ return new LatLngBounds(latNorth, lonEast, latSouth, lonWest);
+ }
+
+ private static void checkParams(
+ @FloatRange(from = GeometryConstants.MIN_LATITUDE, to = GeometryConstants.MAX_LATITUDE) double latNorth,
+ double lonEast,
+ @FloatRange(from = GeometryConstants.MIN_LATITUDE, to = GeometryConstants.MAX_LATITUDE) double latSouth,
+ double lonWest) {
+
if (Double.isNaN(latNorth) || Double.isNaN(latSouth)) {
throw new IllegalArgumentException("latitude must not be NaN");
}
@@ -313,11 +328,6 @@ public class LatLngBounds implements Parcelable {
if (latNorth < latSouth) {
throw new IllegalArgumentException("LatSouth cannot be less than latNorth");
}
-
- lonEast = LatLng.wrap(lonEast, GeometryConstants.MIN_LONGITUDE, GeometryConstants.MAX_LONGITUDE);
- lonWest = LatLng.wrap(lonWest, GeometryConstants.MIN_LONGITUDE, GeometryConstants.MAX_LONGITUDE);
-
- return new LatLngBounds(latNorth, lonEast, latSouth, lonWest);
}
private static double lat_(int z, int y) {
@@ -394,7 +404,7 @@ public class LatLngBounds implements Parcelable {
return (longitude <= eastLon)
&& (longitude >= westLon);
}
- return (longitude < eastLon) || (longitude > westLon);
+ return (longitude <= eastLon) || (longitude >= westLon);
}
/**
@@ -425,36 +435,94 @@ public class LatLngBounds implements Parcelable {
* @param bounds LatLngBounds to add
* @return LatLngBounds
*/
- public LatLngBounds union(LatLngBounds bounds) {
- return union(bounds.getLatNorth(), bounds.getLonEast(), bounds.getLatSouth(), bounds.getLonWest());
+ public @NonNull LatLngBounds union(@NonNull LatLngBounds bounds) {
+ return unionNoParamCheck(bounds.getLatNorth(), bounds.getLonEast(), bounds.getLatSouth(), bounds.getLonWest());
}
/**
* Returns a new LatLngBounds that stretches to include another LatLngBounds,
* given by corner points.
+ * <p>
+ * This values of northLat and southLat should be in the range of [-90, 90],
+ * see {@link GeometryConstants#MIN_LATITUDE} and {@link GeometryConstants#MAX_LATITUDE},
+ * otherwise IllegalArgumentException will be thrown.
+ * northLat should be greater or equal southLat, otherwise IllegalArgumentException will be thrown.
+ * <p>
+ * This method doesn't recalculate most east or most west boundaries.
+ * Note that eastLon and westLon will be wrapped to be in the range of [-180, 180],
+ * see {@link GeometryConstants#MIN_LONGITUDE} and {@link GeometryConstants#MAX_LONGITUDE}
*
- * @param latNorth Northern Latitude
- * @param lonEast Eastern Longitude
- * @param latSouth Southern Latitude
- * @param lonWest Western Longitude
- * @return BoundingBox
- */
- public LatLngBounds union(final double latNorth, final double lonEast, final double latSouth, final double lonWest) {
- double north = (this.latitudeNorth < latNorth) ? latNorth : this.latitudeNorth;
- double south = (this.latitudeSouth > latSouth) ? latSouth : this.latitudeSouth;
-
- if (LatLngSpan.getLongitudeSpan(lonEast, this.longitudeWest)
- < LatLngSpan.getLongitudeSpan(this.longitudeEast, lonWest)) {
- return new LatLngBounds(north,
- lonEast,
- south,
+ * @param northLat Northern Latitude corner point
+ * @param eastLon Eastern Longitude corner point
+ * @param southLat Southern Latitude corner point
+ * @param westLon Western Longitude corner point
+ * @return LatLngBounds
+ */
+ public @NonNull LatLngBounds union(
+ @FloatRange(from = GeometryConstants.MIN_LATITUDE, to = GeometryConstants.MAX_LATITUDE)double northLat,
+ double eastLon,
+ @FloatRange(from = GeometryConstants.MIN_LATITUDE, to = GeometryConstants.MAX_LATITUDE) double southLat,
+ double westLon) {
+
+ checkParams(northLat, eastLon, southLat, westLon);
+
+ return unionNoParamCheck(northLat, eastLon, southLat, westLon);
+ }
+
+ private @NonNull LatLngBounds unionNoParamCheck(
+ @FloatRange(from = GeometryConstants.MIN_LATITUDE, to = GeometryConstants.MAX_LATITUDE)double northLat,
+ double eastLon,
+ @FloatRange(from = GeometryConstants.MIN_LATITUDE, to = GeometryConstants.MAX_LATITUDE) double southLat,
+ double westLon) {
+
+ northLat = (this.latitudeNorth < northLat) ? northLat : this.latitudeNorth;
+ southLat = (this.latitudeSouth > southLat) ? southLat : this.latitudeSouth;
+
+ eastLon = LatLng.wrap(eastLon, GeometryConstants.MIN_LONGITUDE, GeometryConstants.MAX_LONGITUDE);
+ westLon = LatLng.wrap(westLon, GeometryConstants.MIN_LONGITUDE, GeometryConstants.MAX_LONGITUDE);
+
+ // longitudes match
+ if (this.longitudeEast == eastLon && this.longitudeWest == westLon) {
+ return new LatLngBounds(northLat, eastLon, southLat, westLon);
+ }
+
+ boolean eastInThis = containsLongitude(this.longitudeEast, this.longitudeWest, eastLon);
+ boolean westInThis = containsLongitude(this.longitudeEast, this.longitudeWest, westLon);
+ boolean thisEastInside = containsLongitude(eastLon, westLon, this.longitudeEast);
+ boolean thisWestInside = containsLongitude(eastLon, westLon, this.longitudeWest);
+
+ // two intersections on each end - covers entire longitude
+ if (eastInThis && westInThis && thisEastInside && thisWestInside) {
+ return new LatLngBounds(northLat, GeometryConstants.MAX_LONGITUDE, southLat, GeometryConstants.MIN_LONGITUDE);
+ }
+
+ if (eastInThis) {
+ if (westInThis) {
+ return new LatLngBounds(northLat, this.longitudeEast, southLat, this.longitudeWest);
+ }
+ return new LatLngBounds(northLat, this.longitudeEast, southLat, westLon);
+ }
+
+ if (thisEastInside) {
+ if (thisWestInside) {
+ return new LatLngBounds(northLat, eastLon, southLat, westLon);
+ }
+ return new LatLngBounds(northLat, eastLon, southLat, this.longitudeWest);
+ }
+
+ // bounds do not intersect, find where they will form shortest union
+ if (LatLngSpan.getLongitudeSpan(eastLon, this.longitudeWest)
+ < LatLngSpan.getLongitudeSpan(this.longitudeEast, westLon)) {
+ return new LatLngBounds(northLat,
+ eastLon,
+ southLat,
this.longitudeWest);
}
- return new LatLngBounds(north,
+ return new LatLngBounds(northLat,
this.longitudeEast,
- south,
- lonWest);
+ southLat,
+ westLon);
}
/**
@@ -463,32 +531,89 @@ public class LatLngBounds implements Parcelable {
* @param box LatLngBounds to intersect with
* @return LatLngBounds
*/
- @Nullable
- public LatLngBounds intersect(LatLngBounds box) {
- double minLonWest = Math.max(getLonWest(), box.getLonWest());
- double maxLonEast = Math.min(getLonEast(), box.getLonEast());
- if (maxLonEast > minLonWest) {
- double minLatSouth = Math.max(getLatSouth(), box.getLatSouth());
- double maxLatNorth = Math.min(getLatNorth(), box.getLatNorth());
- if (maxLatNorth > minLatSouth) {
- return new LatLngBounds(maxLatNorth, maxLonEast, minLatSouth, minLonWest);
- }
- }
- return null;
+ public @Nullable LatLngBounds intersect(@NonNull LatLngBounds box) {
+ return intersectNoParamCheck(box.getLatNorth(), box.getLonEast(), box.getLatSouth(), box.getLonWest());
}
/**
* Returns a new LatLngBounds that is the intersection of this with another LatLngBounds
+ * <p>
+ * This values of northLat and southLat should be in the range of [-90, 90],
+ * see {@link GeometryConstants#MIN_LATITUDE} and {@link GeometryConstants#MAX_LATITUDE},
+ * otherwise IllegalArgumentException will be thrown.
+ * northLat should be greater or equal southLat, otherwise IllegalArgumentException will be thrown.
+ * <p>
+ * This method doesn't recalculate most east or most west boundaries.
+ * Note that eastLon and westLon will be wrapped to be in the range of [-180, 180],
+ * see {@link GeometryConstants#MIN_LONGITUDE} and {@link GeometryConstants#MAX_LONGITUDE}
*
- * @param northLatitude Northern Longitude
- * @param eastLongitude Eastern Latitude
- * @param southLatitude Southern Longitude
- * @param westLongitude Western Latitude
+ * @param northLat Northern Latitude corner point
+ * @param eastLon Eastern Longitude corner point
+ * @param southLat Southern Latitude corner point
+ * @param westLon Western Longitude corner point
* @return LatLngBounds
*/
- public LatLngBounds intersect(double northLatitude, double eastLongitude, double southLatitude,
- double westLongitude) {
- return intersect(new LatLngBounds(northLatitude, eastLongitude, southLatitude, westLongitude));
+ public @Nullable LatLngBounds intersect(
+ @FloatRange(from = GeometryConstants.MIN_LATITUDE, to = GeometryConstants.MAX_LATITUDE)double northLat,
+ double eastLon,
+ @FloatRange(from = GeometryConstants.MIN_LATITUDE, to = GeometryConstants.MAX_LATITUDE) double southLat,
+ double westLon) {
+
+ checkParams(northLat, eastLon, southLat, westLon);
+
+ return intersectNoParamCheck(northLat, eastLon, southLat, westLon);
+ }
+
+ private @Nullable LatLngBounds intersectNoParamCheck(
+ @FloatRange(from = GeometryConstants.MIN_LATITUDE, to = GeometryConstants.MAX_LATITUDE)double northLat,
+ double eastLon,
+ @FloatRange(from = GeometryConstants.MIN_LATITUDE, to = GeometryConstants.MAX_LATITUDE) double southLat,
+ double westLon) {
+
+ double maxsouthLat = Math.max(getLatSouth(), Math.min(GeometryConstants.MAX_LATITUDE, southLat));
+ double minnorthLat = Math.min(getLatNorth(), Math.max(GeometryConstants.MIN_LATITUDE, northLat));
+ if (minnorthLat < maxsouthLat) {
+ return null;
+ }
+
+ eastLon = LatLng.wrap(eastLon, GeometryConstants.MIN_LONGITUDE, GeometryConstants.MAX_LONGITUDE);
+ westLon = LatLng.wrap(westLon, GeometryConstants.MIN_LONGITUDE, GeometryConstants.MAX_LONGITUDE);
+
+ // longitudes match
+ if (this.longitudeEast == eastLon && this.longitudeWest == westLon) {
+ return new LatLngBounds(minnorthLat, eastLon, maxsouthLat, westLon);
+ }
+
+ boolean eastInThis = containsLongitude(this.longitudeEast, this.longitudeWest, eastLon);
+ boolean westInThis = containsLongitude(this.longitudeEast, this.longitudeWest, westLon);
+ boolean thisEastInside = containsLongitude(eastLon, westLon, this.longitudeEast);
+ boolean thisWestInside = containsLongitude(eastLon, westLon, this.longitudeWest);
+
+ // two intersections : find the one that has longest span
+ if (eastInThis && westInThis && thisEastInside && thisWestInside) {
+
+ if (getLongitudeSpan(eastLon, this.longitudeWest) > getLongitudeSpan(this.longitudeEast, westLon)) {
+ return new LatLngBounds(minnorthLat, eastLon, maxsouthLat, this.longitudeWest);
+ }
+
+ return new LatLngBounds(minnorthLat, this.longitudeEast, maxsouthLat, westLon);
+ }
+
+ if (eastInThis) {
+ if (westInThis) {
+ return new LatLngBounds(minnorthLat, eastLon, maxsouthLat, westLon);
+ }
+ return new LatLngBounds(minnorthLat, eastLon, maxsouthLat, this.longitudeWest);
+ }
+
+ if (thisEastInside) {
+ if (thisWestInside) {
+ return new LatLngBounds(minnorthLat, this.longitudeEast, maxsouthLat, this.longitudeWest);
+ }
+ return new LatLngBounds(minnorthLat, this.longitudeEast, maxsouthLat, westLon);
+ }
+
+ return null;
}
/**
@@ -517,7 +642,7 @@ public class LatLngBounds implements Parcelable {
return (int) ((latitudeNorth + 90)
+ ((latitudeSouth + 90) * 1000)
+ ((longitudeEast + 180) * 1000000)
- + ((longitudeEast + 180) * 1000000000));
+ + ((longitudeWest + 180) * 1000000000));
}
/**
@@ -545,11 +670,11 @@ public class LatLngBounds implements Parcelable {
}
private static LatLngBounds readFromParcel(final Parcel in) {
- final double lonNorth = in.readDouble();
- final double latEast = in.readDouble();
- final double lonSouth = in.readDouble();
- final double latWest = in.readDouble();
- return new LatLngBounds(lonNorth, latEast, lonSouth, latWest);
+ final double northLat = in.readDouble();
+ final double eastLon = in.readDouble();
+ final double southLat = in.readDouble();
+ final double westLon = in.readDouble();
+ return new LatLngBounds(northLat, eastLon, southLat, westLon);
}
/**
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/HTTPRequest.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/HTTPRequest.java
index ab1191c0cc..d0e51f941f 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/HTTPRequest.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/HTTPRequest.java
@@ -1,6 +1,5 @@
package com.mapbox.mapboxsdk.http;
-
import android.content.Context;
import android.content.pm.PackageInfo;
import android.os.Build;
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java
index c84651da24..d258064908 100755
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java
@@ -779,8 +779,9 @@ final class NativeMapView {
return;
}
- // Determine pixel ratio
- nativeAddImage(name, image, image.getDensity() / DisplayMetrics.DENSITY_DEFAULT);
+ // Determine pixel ratio, cast to float to avoid rounding, see mapbox-gl-native/issues/11809
+ float pixelRatio = (float) image.getDensity() / DisplayMetrics.DENSITY_DEFAULT;
+ nativeAddImage(name, image, pixelRatio);
}
public void addImages(@NonNull HashMap<String, Bitmap> bitmapHashMap) {
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/storage/FileSource.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/storage/FileSource.java
index f0cb8d973a..929e4b4279 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/storage/FileSource.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/storage/FileSource.java
@@ -6,6 +6,8 @@ import android.content.pm.PackageManager;
import android.content.res.AssetManager;
import android.os.Environment;
import android.support.annotation.NonNull;
+import android.support.annotation.UiThread;
+
import com.mapbox.mapboxsdk.Mapbox;
import com.mapbox.mapboxsdk.constants.MapboxConstants;
import timber.log.Timber;
@@ -43,6 +45,7 @@ public class FileSource {
* @param context the context to derive the cache path from
* @return the single instance of FileSource
*/
+ @UiThread
public static synchronized FileSource getInstance(Context context) {
if (INSTANCE == null) {
String cachePath = getCachePath(context);
@@ -122,6 +125,8 @@ public class FileSource {
initialize(Mapbox.getAccessToken(), cachePath, assetManager);
}
+ public native boolean isActivated();
+
public native void activate();
public native void deactivate();
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/PropertyFactory.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/PropertyFactory.java
index 4289deeda3..1dd8eddab9 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/PropertyFactory.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/PropertyFactory.java
@@ -166,7 +166,7 @@ public class PropertyFactory {
}
/**
- * Name of image in sprite to use for drawing image fills. For seamless patterns, image width and height must be a factor of two (2, 4, 8, ..., 512).
+ * Name of image in sprite to use for drawing image fills. For seamless patterns, image width and height must be a factor of two (2, 4, 8, ..., 512). Note that zoom-dependent expressions will be evaluated only at integer zoom levels.
*
* @param value a String value
* @return property wrapper around String
@@ -176,7 +176,7 @@ public class PropertyFactory {
}
/**
- * Name of image in sprite to use for drawing image fills. For seamless patterns, image width and height must be a factor of two (2, 4, 8, ..., 512).
+ * Name of image in sprite to use for drawing image fills. For seamless patterns, image width and height must be a factor of two (2, 4, 8, ..., 512). Note that zoom-dependent expressions will be evaluated only at integer zoom levels.
*
* @param expression an expression statement
* @return property wrapper around an expression statement
@@ -356,7 +356,7 @@ public class PropertyFactory {
}
/**
- * Specifies the lengths of the alternating dashes and gaps that form the dash pattern. The lengths are later scaled by the line width. To convert a dash length to density-independent pixels, multiply the length by the current line width.
+ * Specifies the lengths of the alternating dashes and gaps that form the dash pattern. The lengths are later scaled by the line width. To convert a dash length to density-independent pixels, multiply the length by the current line width. Note that GeoJSON sources with `lineMetrics: true` specified won't render dashed lines to the expected scale. Also note that zoom-dependent expressions will be evaluated only at integer zoom levels.
*
* @param value a Float[] value
* @return property wrapper around Float[]
@@ -366,7 +366,7 @@ public class PropertyFactory {
}
/**
- * Specifies the lengths of the alternating dashes and gaps that form the dash pattern. The lengths are later scaled by the line width. To convert a dash length to density-independent pixels, multiply the length by the current line width.
+ * Specifies the lengths of the alternating dashes and gaps that form the dash pattern. The lengths are later scaled by the line width. To convert a dash length to density-independent pixels, multiply the length by the current line width. Note that GeoJSON sources with `lineMetrics: true` specified won't render dashed lines to the expected scale. Also note that zoom-dependent expressions will be evaluated only at integer zoom levels.
*
* @param expression an expression statement
* @return property wrapper around an expression statement
@@ -376,7 +376,7 @@ public class PropertyFactory {
}
/**
- * Name of image in sprite to use for drawing image lines. For seamless patterns, image width must be a factor of two (2, 4, 8, ..., 512).
+ * Name of image in sprite to use for drawing image lines. For seamless patterns, image width must be a factor of two (2, 4, 8, ..., 512). Note that zoom-dependent expressions will be evaluated only at integer zoom levels.
*
* @param value a String value
* @return property wrapper around String
@@ -386,7 +386,7 @@ public class PropertyFactory {
}
/**
- * Name of image in sprite to use for drawing image lines. For seamless patterns, image width must be a factor of two (2, 4, 8, ..., 512).
+ * Name of image in sprite to use for drawing image lines. For seamless patterns, image width must be a factor of two (2, 4, 8, ..., 512). Note that zoom-dependent expressions will be evaluated only at integer zoom levels.
*
* @param expression an expression statement
* @return property wrapper around an expression statement
@@ -1156,7 +1156,7 @@ public class PropertyFactory {
}
/**
- * Name of image in sprite to use for drawing images on extruded fills. For seamless patterns, image width and height must be a factor of two (2, 4, 8, ..., 512).
+ * Name of image in sprite to use for drawing images on extruded fills. For seamless patterns, image width and height must be a factor of two (2, 4, 8, ..., 512). Note that zoom-dependent expressions will be evaluated only at integer zoom levels.
*
* @param value a String value
* @return property wrapper around String
@@ -1166,7 +1166,7 @@ public class PropertyFactory {
}
/**
- * Name of image in sprite to use for drawing images on extruded fills. For seamless patterns, image width and height must be a factor of two (2, 4, 8, ..., 512).
+ * Name of image in sprite to use for drawing images on extruded fills. For seamless patterns, image width and height must be a factor of two (2, 4, 8, ..., 512). Note that zoom-dependent expressions will be evaluated only at integer zoom levels.
*
* @param expression an expression statement
* @return property wrapper around an expression statement
@@ -1536,7 +1536,7 @@ public class PropertyFactory {
}
/**
- * Name of image in sprite to use for drawing an image background. For seamless patterns, image width and height must be a factor of two (2, 4, 8, ..., 512).
+ * Name of image in sprite to use for drawing an image background. For seamless patterns, image width and height must be a factor of two (2, 4, 8, ..., 512). Note that zoom-dependent expressions will be evaluated only at integer zoom levels.
*
* @param value a String value
* @return property wrapper around String
@@ -1546,7 +1546,7 @@ public class PropertyFactory {
}
/**
- * Name of image in sprite to use for drawing an image background. For seamless patterns, image width and height must be a factor of two (2, 4, 8, ..., 512).
+ * Name of image in sprite to use for drawing an image background. For seamless patterns, image width and height must be a factor of two (2, 4, 8, ..., 512). Note that zoom-dependent expressions will be evaluated only at integer zoom levels.
*
* @param expression an expression statement
* @return property wrapper around an expression statement