Add array support for icon-padding (#2845)
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
#include "collection.hpp"
|
||||
#include "../style/formatted.hpp"
|
||||
|
||||
#include <mbgl/style/conversion/stringify.hpp>
|
||||
#include <mbgl/util/string.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
@@ -33,6 +34,16 @@ Result<jni::Local<jni::Object<>>> Converter<jni::Local<jni::Object<>>, Color>::o
|
||||
return jni::Make<jni::String>(env, value.stringify());
|
||||
}
|
||||
|
||||
Result<jni::Local<jni::Object<>>> Converter<jni::Local<jni::Object<>>, Padding>::operator()(
|
||||
jni::JNIEnv& env, const Padding& value) const {
|
||||
const auto values = value.toArray();
|
||||
auto result = jni::Array<jni::Float>::New(env, values.size());
|
||||
for (size_t i = 0; i < values.size(); i++) {
|
||||
result.Set(env, i, jni::Box(env, values[i]));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
Result<jni::Local<jni::Object<>>> Converter<jni::Local<jni::Object<>>, style::expression::Formatted>::operator()(
|
||||
jni::JNIEnv& env, const style::expression::Formatted& value) const {
|
||||
return Formatted::New(env, value);
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "conversion.hpp"
|
||||
|
||||
#include <mbgl/util/color.hpp>
|
||||
#include <mbgl/util/padding.hpp>
|
||||
#include <mbgl/util/enum.hpp>
|
||||
|
||||
#include <mbgl/style/expression/formatted.hpp>
|
||||
@@ -57,6 +58,11 @@ struct Converter<jni::Local<jni::Object<>>, Color> {
|
||||
Result<jni::Local<jni::Object<>>> operator()(jni::JNIEnv& env, const Color& value) const;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<jni::Local<jni::Object<>>, Padding> {
|
||||
Result<jni::Local<jni::Object<>>> operator()(jni::JNIEnv& env, const Padding& value) const;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<jni::Local<jni::Object<>>, style::expression::Formatted> {
|
||||
Result<jni::Local<jni::Object<>>> operator()(jni::JNIEnv& env, const style::expression::Formatted& value) const;
|
||||
|
||||
@@ -3688,6 +3688,20 @@ public class Expression {
|
||||
return new Expression("to-color", input);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts input value to a padding.
|
||||
*
|
||||
* If the input is a number or an array of numbers padding is created following
|
||||
* the same pattern as CSS padding. See <a href="https://maplibre.org/maplibre-style-spec/types/#padding">Style specification</a>.
|
||||
* Otherwise, the expression is an error.
|
||||
*
|
||||
* @param input expression input
|
||||
* @return expression
|
||||
*/
|
||||
public static Expression toPadding(@NonNull Expression input) {
|
||||
return new Expression("to-padding", input);
|
||||
}
|
||||
|
||||
/**
|
||||
* Binds input to named variables,
|
||||
* which can then be referenced in the result expression using {@link #var(String)} or {@link #var(Expression)}.
|
||||
|
||||
@@ -2050,18 +2050,18 @@ The unit is in density-independent pixels only for SDF sprites that were created
|
||||
/**
|
||||
* Size of additional area round the icon bounding box used for detecting symbol collisions.
|
||||
*
|
||||
* @param value a Float value
|
||||
* @return property wrapper around Float
|
||||
* @param value a Float[] value
|
||||
* @return property wrapper around Float[]
|
||||
*/
|
||||
public static PropertyValue<Float> iconPadding(Float value) {
|
||||
public static PropertyValue<Float[]> iconPadding(Float[] value) {
|
||||
return new LayoutPropertyValue<>("icon-padding", value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Size of additional area round the icon bounding box used for detecting symbol collisions.
|
||||
*
|
||||
* @param value a Float value
|
||||
* @return property wrapper around Float
|
||||
* @param value a Float[] value
|
||||
* @return property wrapper around Float[]
|
||||
*/
|
||||
public static PropertyValue<Expression> iconPadding(Expression value) {
|
||||
return new LayoutPropertyValue<>("icon-padding", value);
|
||||
|
||||
@@ -316,13 +316,13 @@ public class SymbolLayer extends Layer {
|
||||
/**
|
||||
* Get the IconPadding property
|
||||
*
|
||||
* @return property wrapper value around Float
|
||||
* @return property wrapper value around Float[]
|
||||
*/
|
||||
@NonNull
|
||||
@SuppressWarnings("unchecked")
|
||||
public PropertyValue<Float> getIconPadding() {
|
||||
public PropertyValue<Float[]> getIconPadding() {
|
||||
checkThread();
|
||||
return (PropertyValue<Float>) new PropertyValue("icon-padding", nativeGetIconPadding());
|
||||
return (PropertyValue<Float[]>) new PropertyValue("icon-padding", nativeGetIconPadding());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1124,6 +1124,14 @@ class ExpressionTest {
|
||||
Assert.assertTrue("expression should match", Arrays.deepEquals(expected, actual))
|
||||
}
|
||||
|
||||
@Test
|
||||
@Throws(Exception::class)
|
||||
fun testToPadding() {
|
||||
val expected = arrayOf<Any>("to-padding", "value")
|
||||
val actual = Expression.toPadding(Expression.literal("value")).toArray()
|
||||
Assert.assertTrue("expression should match", Arrays.deepEquals(expected, actual))
|
||||
}
|
||||
|
||||
@Test
|
||||
@Throws(Exception::class)
|
||||
fun testLet() {
|
||||
|
||||
@@ -55,11 +55,13 @@ import static org.maplibre.android.style.expressions.Expression.stop;
|
||||
import static org.maplibre.android.style.expressions.Expression.string;
|
||||
import static org.maplibre.android.style.expressions.Expression.switchCase;
|
||||
import static org.maplibre.android.style.expressions.Expression.toColor;
|
||||
import static org.maplibre.android.style.expressions.Expression.toPadding;
|
||||
import static org.maplibre.android.style.expressions.Expression.zoom;
|
||||
import static org.maplibre.android.style.layers.PropertyFactory.circleColor;
|
||||
import static org.maplibre.android.style.layers.PropertyFactory.fillAntialias;
|
||||
import static org.maplibre.android.style.layers.PropertyFactory.fillColor;
|
||||
import static org.maplibre.android.style.layers.PropertyFactory.fillOutlineColor;
|
||||
import static org.maplibre.android.style.layers.PropertyFactory.iconPadding;
|
||||
import static org.maplibre.android.style.layers.PropertyFactory.textColor;
|
||||
import static org.maplibre.android.style.layers.PropertyFactory.textField;
|
||||
import static org.maplibre.android.testapp.action.MapLibreMapAction.invoke;
|
||||
@@ -779,6 +781,93 @@ public class ExpressionTest extends EspressoTest {
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToPaddingExpression() {
|
||||
validateTestSetup();
|
||||
invoke(maplibreMap, (uiController, maplibreMap) -> {
|
||||
LatLng latLng = new LatLng(51, 17);
|
||||
maplibreMap.getStyle().addSource(
|
||||
new GeoJsonSource("source", Point.fromLngLat(latLng.getLongitude(), latLng.getLatitude()))
|
||||
);
|
||||
|
||||
SymbolLayer layer = new SymbolLayer("layer", "source");
|
||||
maplibreMap.getStyle().addLayer(layer);
|
||||
|
||||
// Automatic usage with iconPadding property, analogous to testGetExpressionWrapping()
|
||||
{
|
||||
Expression input = get("value");
|
||||
layer.setProperties(iconPadding(input));
|
||||
|
||||
Expression expectedOuput = toPadding(input);
|
||||
Expression output = layer.getIconPadding().getExpression();
|
||||
assertNotNull(output);
|
||||
assertArrayEquals("Expression should match", expectedOuput.toArray(), output.toArray());
|
||||
}
|
||||
|
||||
// Same within interpolate expression
|
||||
{
|
||||
Expression input = interpolate(
|
||||
exponential(0.5f), zoom(),
|
||||
stop(-0.1, get("value")),
|
||||
stop(0, get("value"))
|
||||
);
|
||||
layer.setProperties(iconPadding(input));
|
||||
|
||||
Expression expectedOutput = interpolate(
|
||||
exponential(0.5f), zoom(),
|
||||
stop(-0.1, toPadding(get("value"))),
|
||||
stop(0, toPadding(get("value")))
|
||||
);
|
||||
Expression output = layer.getIconPadding().getExpression();
|
||||
assertNotNull(output);
|
||||
assertArrayEquals("Expression should match", expectedOutput.toArray(), output.toArray());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToPaddingResult() {
|
||||
validateTestSetup();
|
||||
invoke(maplibreMap, (uiController, maplibreMap) -> {
|
||||
LatLng latLng = new LatLng(51, 17);
|
||||
maplibreMap.getStyle().addSource(
|
||||
new GeoJsonSource("source", Point.fromLngLat(latLng.getLongitude(), latLng.getLatitude()))
|
||||
);
|
||||
|
||||
SymbolLayer layer = new SymbolLayer("layer", "source");
|
||||
maplibreMap.getStyle().addLayer(layer);
|
||||
|
||||
Expression input = Expression.toPadding(Expression.literal(new Float[] { 7.5f, 10.0f, 1.0f}));
|
||||
layer.setProperties(iconPadding(input));
|
||||
|
||||
assertNull("Expression should be null", layer.getIconPadding().getExpression());
|
||||
assertArrayEquals(
|
||||
"Padding value should match",
|
||||
new Float[] { 7.5f, 10.0f, 1.0f, 10.0f },
|
||||
layer.getIconPadding().getValue());
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToPaddingError() {
|
||||
validateTestSetup();
|
||||
invoke(maplibreMap, (uiController, maplibreMap) -> {
|
||||
LatLng latLng = new LatLng(51, 17);
|
||||
maplibreMap.getStyle().addSource(
|
||||
new GeoJsonSource("source", Point.fromLngLat(latLng.getLongitude(), latLng.getLatitude()))
|
||||
);
|
||||
|
||||
SymbolLayer layer = new SymbolLayer("layer", "source");
|
||||
maplibreMap.getStyle().addLayer(layer);
|
||||
|
||||
Expression input = toPadding(literal("invalid"));
|
||||
layer.setProperties(iconPadding(input));
|
||||
|
||||
assertNull("Expression should be null", layer.getIconPadding().getExpression());
|
||||
assertNull("Padding value should be null", layer.getIconPadding().getValue());
|
||||
});
|
||||
}
|
||||
|
||||
private void setupStyle() {
|
||||
invoke(maplibreMap, (uiController, maplibreMap) -> {
|
||||
// Add a source
|
||||
|
||||
@@ -422,11 +422,24 @@ public class SymbolLayerTest extends BaseLayerTest {
|
||||
assertNull(layer.getIconPadding().getValue());
|
||||
|
||||
// Set and Get
|
||||
Float propertyValue = 0.3f;
|
||||
Float[] propertyValue = {2.0f, 2.0f, 2.0f, 2.0f};
|
||||
layer.setProperties(iconPadding(propertyValue));
|
||||
assertEquals(layer.getIconPadding().getValue(), propertyValue);
|
||||
}
|
||||
|
||||
@Test
|
||||
@UiThreadTest
|
||||
public void testIconPaddingAsExpression() {
|
||||
Timber.i("icon-padding-expression");
|
||||
assertNotNull(layer);
|
||||
assertNull(layer.getIconPadding().getExpression());
|
||||
|
||||
// Set and Get
|
||||
Expression expression = toPadding(Expression.get("undefined"));
|
||||
layer.setProperties(iconPadding(expression));
|
||||
assertEquals(layer.getIconPadding().getExpression(), expression);
|
||||
}
|
||||
|
||||
@Test
|
||||
@UiThreadTest
|
||||
public void testIconKeepUprightAsConstant() {
|
||||
|
||||
@@ -119,6 +119,8 @@ global.propertyType = function propertyType(property) {
|
||||
return 'String';
|
||||
case 'color':
|
||||
return 'String';
|
||||
case 'padding':
|
||||
return 'Float[]'
|
||||
case 'array':
|
||||
return `${propertyType({type:property.value, name: property.name})}[]`;
|
||||
default:
|
||||
@@ -193,6 +195,8 @@ global.propertyNativeType = function (property) {
|
||||
return `${camelize(property.name)}Type`;
|
||||
case 'color':
|
||||
return `Color`;
|
||||
case 'padding':
|
||||
return 'Padding';
|
||||
case 'array':
|
||||
if (property.length) {
|
||||
return `std::array<${propertyType({type: property.value})}, ${property.length}>`;
|
||||
@@ -229,6 +233,8 @@ global.defaultExpressionJava = function(property) {
|
||||
return "string";
|
||||
case 'color':
|
||||
return 'toColor';
|
||||
case 'padding':
|
||||
return 'toPadding';
|
||||
case 'array':
|
||||
return "array";
|
||||
default: return "string";
|
||||
@@ -261,6 +267,8 @@ global.defaultValueJava = function(property) {
|
||||
return snakeCaseUpper(property.name) + "_" + snakeCaseUpper(Object.keys(property.values)[0]);
|
||||
case 'color':
|
||||
return '"rgba(255,128,0,0.7)"';
|
||||
case 'padding':
|
||||
return '{2.0f, 2.0f, 2.0f, 2.0f}';
|
||||
case 'array':
|
||||
switch (property.value) {
|
||||
case 'string':
|
||||
|
||||
Reference in New Issue
Block a user