summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnand Thakker <anandthakker@users.noreply.github.com>2017-02-28 19:54:24 -0800
committerGitHub <noreply@github.com>2017-02-28 19:54:24 -0800
commitf901e776b3e63aaaa6bc0cc4476624bf84127fe6 (patch)
tree3e311971d57109c64e5ace45c111fb5909e7fb7b
parentc3ed1f51ca677c8c2045320fe13ec881cbd94772 (diff)
downloadqtlocation-mapboxgl-f901e776b3e63aaaa6bc0cc4476624bf84127fe6.tar.gz
[core] Implement data-driven styling for {text,icon}-{color,opacity,halo-color,halo-blur,halo-width} (#7939)
* Add symbol dds attributes and adapt style code generation * Update to mapbox-gl-js/master * Refactor SymbolFeature as a subclass of GeometryTileFeature Prepares for enabling DDS on symbol paint properties by allowing the SymbolFeatures, which we keep around after constructing SymbolLayout, to be used in evaluating data-driven paint properties later in the layout process. * Draft approach for splitting icon/text paint properties The `Program` types are set up to bind GL attributes to each of the data-driven paint properties specified in the `PaintProperties` type provided. Since `SymbolPaintProperties` specifies both `Text*` and `Icon*` properties, the symbolIcon, symbolIconSDF, and symbolGlyph programs each attempt to bind roughly double the number of attributes that they actually need. This change addresses this by: - Adding the more specific `IconPaintProperties` and `TextPaintProperties` types, which are subsets of the full `SymbolPaintProperties`. - The symbol layer continues to use its `SymbolPaintProperties paint` member to track layer property state, but it provides helpers that construct objects of each the specific `{Icon,Text}PaintProperties::Evaluated` type, for use by the painter. - The three symbol programs instantiate `Program<>` using the appropriate `{Icon,Text}PaintProperties` type. * check in generated style code * Populate paint buffers for symbol DDS properties * Address first round of review comments * Refactor VectorTile{Layer,Feature} to explicitly share data * Update submodule
-rw-r--r--include/mbgl/style/layers/symbol_layer.hpp60
m---------mapbox-gl-js0
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/PropertyFactory.java64
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/SymbolLayerTest.java920
-rw-r--r--platform/darwin/src/MGLSymbolStyleLayer.h126
-rw-r--r--platform/darwin/src/MGLSymbolStyleLayer.mm60
-rw-r--r--platform/darwin/test/MGLSymbolStyleLayerTests.mm300
-rw-r--r--scripts/generate-style-code.js15
-rw-r--r--src/mbgl/layout/symbol_feature.hpp17
-rw-r--r--src/mbgl/layout/symbol_instance.cpp5
-rw-r--r--src/mbgl/layout/symbol_instance.hpp3
-rw-r--r--src/mbgl/layout/symbol_layout.cpp51
-rw-r--r--src/mbgl/layout/symbol_layout.hpp7
-rw-r--r--src/mbgl/programs/attributes.hpp46
-rw-r--r--src/mbgl/programs/programs.hpp4
-rw-r--r--src/mbgl/programs/symbol_program.cpp88
-rw-r--r--src/mbgl/programs/symbol_program.hpp77
-rw-r--r--src/mbgl/renderer/painter_symbol.cpp46
-rw-r--r--src/mbgl/renderer/symbol_bucket.cpp12
-rw-r--r--src/mbgl/renderer/symbol_bucket.hpp10
-rw-r--r--src/mbgl/shaders/symbol_icon.cpp13
-rw-r--r--src/mbgl/shaders/symbol_sdf.cpp63
-rw-r--r--src/mbgl/style/layers/symbol_layer.cpp132
-rw-r--r--src/mbgl/style/layers/symbol_layer_impl.cpp56
-rw-r--r--src/mbgl/style/layers/symbol_layer_impl.hpp44
-rw-r--r--src/mbgl/style/layers/symbol_layer_properties.hpp20
-rw-r--r--src/mbgl/text/shaping.cpp9
-rw-r--r--src/mbgl/text/shaping.hpp3
-rw-r--r--src/mbgl/tile/vector_tile.cpp70
-rw-r--r--test/tile/vector_tile.test.cpp6
-rw-r--r--test/util/merge_lines.test.cpp136
31 files changed, 1985 insertions, 478 deletions
diff --git a/include/mbgl/style/layers/symbol_layer.hpp b/include/mbgl/style/layers/symbol_layer.hpp
index 8f655d6f77..aeccabb97e 100644
--- a/include/mbgl/style/layers/symbol_layer.hpp
+++ b/include/mbgl/style/layers/symbol_layer.hpp
@@ -169,29 +169,29 @@ public:
// Paint properties
- static PropertyValue<float> getDefaultIconOpacity();
- PropertyValue<float> getIconOpacity(const optional<std::string>& klass = {}) const;
- void setIconOpacity(PropertyValue<float>, const optional<std::string>& klass = {});
+ static DataDrivenPropertyValue<float> getDefaultIconOpacity();
+ DataDrivenPropertyValue<float> getIconOpacity(const optional<std::string>& klass = {}) const;
+ void setIconOpacity(DataDrivenPropertyValue<float>, const optional<std::string>& klass = {});
void setIconOpacityTransition(const TransitionOptions&, const optional<std::string>& klass = {});
- static PropertyValue<Color> getDefaultIconColor();
- PropertyValue<Color> getIconColor(const optional<std::string>& klass = {}) const;
- void setIconColor(PropertyValue<Color>, const optional<std::string>& klass = {});
+ static DataDrivenPropertyValue<Color> getDefaultIconColor();
+ DataDrivenPropertyValue<Color> getIconColor(const optional<std::string>& klass = {}) const;
+ void setIconColor(DataDrivenPropertyValue<Color>, const optional<std::string>& klass = {});
void setIconColorTransition(const TransitionOptions&, const optional<std::string>& klass = {});
- static PropertyValue<Color> getDefaultIconHaloColor();
- PropertyValue<Color> getIconHaloColor(const optional<std::string>& klass = {}) const;
- void setIconHaloColor(PropertyValue<Color>, const optional<std::string>& klass = {});
+ static DataDrivenPropertyValue<Color> getDefaultIconHaloColor();
+ DataDrivenPropertyValue<Color> getIconHaloColor(const optional<std::string>& klass = {}) const;
+ void setIconHaloColor(DataDrivenPropertyValue<Color>, const optional<std::string>& klass = {});
void setIconHaloColorTransition(const TransitionOptions&, const optional<std::string>& klass = {});
- static PropertyValue<float> getDefaultIconHaloWidth();
- PropertyValue<float> getIconHaloWidth(const optional<std::string>& klass = {}) const;
- void setIconHaloWidth(PropertyValue<float>, const optional<std::string>& klass = {});
+ static DataDrivenPropertyValue<float> getDefaultIconHaloWidth();
+ DataDrivenPropertyValue<float> getIconHaloWidth(const optional<std::string>& klass = {}) const;
+ void setIconHaloWidth(DataDrivenPropertyValue<float>, const optional<std::string>& klass = {});
void setIconHaloWidthTransition(const TransitionOptions&, const optional<std::string>& klass = {});
- static PropertyValue<float> getDefaultIconHaloBlur();
- PropertyValue<float> getIconHaloBlur(const optional<std::string>& klass = {}) const;
- void setIconHaloBlur(PropertyValue<float>, const optional<std::string>& klass = {});
+ static DataDrivenPropertyValue<float> getDefaultIconHaloBlur();
+ DataDrivenPropertyValue<float> getIconHaloBlur(const optional<std::string>& klass = {}) const;
+ void setIconHaloBlur(DataDrivenPropertyValue<float>, const optional<std::string>& klass = {});
void setIconHaloBlurTransition(const TransitionOptions&, const optional<std::string>& klass = {});
static PropertyValue<std::array<float, 2>> getDefaultIconTranslate();
@@ -204,29 +204,29 @@ public:
void setIconTranslateAnchor(PropertyValue<TranslateAnchorType>, const optional<std::string>& klass = {});
void setIconTranslateAnchorTransition(const TransitionOptions&, const optional<std::string>& klass = {});
- static PropertyValue<float> getDefaultTextOpacity();
- PropertyValue<float> getTextOpacity(const optional<std::string>& klass = {}) const;
- void setTextOpacity(PropertyValue<float>, const optional<std::string>& klass = {});
+ static DataDrivenPropertyValue<float> getDefaultTextOpacity();
+ DataDrivenPropertyValue<float> getTextOpacity(const optional<std::string>& klass = {}) const;
+ void setTextOpacity(DataDrivenPropertyValue<float>, const optional<std::string>& klass = {});
void setTextOpacityTransition(const TransitionOptions&, const optional<std::string>& klass = {});
- static PropertyValue<Color> getDefaultTextColor();
- PropertyValue<Color> getTextColor(const optional<std::string>& klass = {}) const;
- void setTextColor(PropertyValue<Color>, const optional<std::string>& klass = {});
+ static DataDrivenPropertyValue<Color> getDefaultTextColor();
+ DataDrivenPropertyValue<Color> getTextColor(const optional<std::string>& klass = {}) const;
+ void setTextColor(DataDrivenPropertyValue<Color>, const optional<std::string>& klass = {});
void setTextColorTransition(const TransitionOptions&, const optional<std::string>& klass = {});
- static PropertyValue<Color> getDefaultTextHaloColor();
- PropertyValue<Color> getTextHaloColor(const optional<std::string>& klass = {}) const;
- void setTextHaloColor(PropertyValue<Color>, const optional<std::string>& klass = {});
+ static DataDrivenPropertyValue<Color> getDefaultTextHaloColor();
+ DataDrivenPropertyValue<Color> getTextHaloColor(const optional<std::string>& klass = {}) const;
+ void setTextHaloColor(DataDrivenPropertyValue<Color>, const optional<std::string>& klass = {});
void setTextHaloColorTransition(const TransitionOptions&, const optional<std::string>& klass = {});
- static PropertyValue<float> getDefaultTextHaloWidth();
- PropertyValue<float> getTextHaloWidth(const optional<std::string>& klass = {}) const;
- void setTextHaloWidth(PropertyValue<float>, const optional<std::string>& klass = {});
+ static DataDrivenPropertyValue<float> getDefaultTextHaloWidth();
+ DataDrivenPropertyValue<float> getTextHaloWidth(const optional<std::string>& klass = {}) const;
+ void setTextHaloWidth(DataDrivenPropertyValue<float>, const optional<std::string>& klass = {});
void setTextHaloWidthTransition(const TransitionOptions&, const optional<std::string>& klass = {});
- static PropertyValue<float> getDefaultTextHaloBlur();
- PropertyValue<float> getTextHaloBlur(const optional<std::string>& klass = {}) const;
- void setTextHaloBlur(PropertyValue<float>, const optional<std::string>& klass = {});
+ static DataDrivenPropertyValue<float> getDefaultTextHaloBlur();
+ DataDrivenPropertyValue<float> getTextHaloBlur(const optional<std::string>& klass = {}) const;
+ void setTextHaloBlur(DataDrivenPropertyValue<float>, const optional<std::string>& klass = {});
void setTextHaloBlurTransition(const TransitionOptions&, const optional<std::string>& klass = {});
static PropertyValue<std::array<float, 2>> getDefaultTextTranslate();
diff --git a/mapbox-gl-js b/mapbox-gl-js
-Subproject fd73395ef71cf77993d717b2e23c5dab5e372b6
+Subproject 7804faf89741cf7db90582d9e0881253cb9d4cd
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 03980e6a8b..5cd0d99270 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
@@ -454,11 +454,11 @@ public class PropertyFactory {
/**
* The opacity at which the icon will be drawn.
*
- * @param <Z> the zoom parameter type
- * @param function a wrapper {@link CameraFunction} for Float
+ * @param <T> the function input type
+ * @param function a wrapper function for Float
* @return property wrapper around a Float function
*/
- public static <Z extends Number> PropertyValue<CameraFunction<Z, Float>> iconOpacity(CameraFunction<Z, Float> function) {
+ public static <T> PropertyValue<Function<T, Float>> iconOpacity(Function<T, Float> function) {
return new PaintPropertyValue<>("icon-opacity", function);
}
@@ -486,11 +486,11 @@ public class PropertyFactory {
/**
* The color of the icon. This can only be used with sdf icons.
*
- * @param <Z> the zoom parameter type
- * @param function a wrapper {@link CameraFunction} for String
+ * @param <T> the function input type
+ * @param function a wrapper function for String
* @return property wrapper around a String function
*/
- public static <Z extends Number> PropertyValue<CameraFunction<Z, String>> iconColor(CameraFunction<Z, String> function) {
+ public static <T> PropertyValue<Function<T, String>> iconColor(Function<T, String> function) {
return new PaintPropertyValue<>("icon-color", function);
}
@@ -518,11 +518,11 @@ public class PropertyFactory {
/**
* The color of the icon's halo. Icon halos can only be used with SDF icons.
*
- * @param <Z> the zoom parameter type
- * @param function a wrapper {@link CameraFunction} for String
+ * @param <T> the function input type
+ * @param function a wrapper function for String
* @return property wrapper around a String function
*/
- public static <Z extends Number> PropertyValue<CameraFunction<Z, String>> iconHaloColor(CameraFunction<Z, String> function) {
+ public static <T> PropertyValue<Function<T, String>> iconHaloColor(Function<T, String> function) {
return new PaintPropertyValue<>("icon-halo-color", function);
}
@@ -540,11 +540,11 @@ public class PropertyFactory {
/**
* Distance of halo to the icon outline.
*
- * @param <Z> the zoom parameter type
- * @param function a wrapper {@link CameraFunction} for Float
+ * @param <T> the function input type
+ * @param function a wrapper function for Float
* @return property wrapper around a Float function
*/
- public static <Z extends Number> PropertyValue<CameraFunction<Z, Float>> iconHaloWidth(CameraFunction<Z, Float> function) {
+ public static <T> PropertyValue<Function<T, Float>> iconHaloWidth(Function<T, Float> function) {
return new PaintPropertyValue<>("icon-halo-width", function);
}
@@ -562,11 +562,11 @@ public class PropertyFactory {
/**
* Fade out the halo towards the outside.
*
- * @param <Z> the zoom parameter type
- * @param function a wrapper {@link CameraFunction} for Float
+ * @param <T> the function input type
+ * @param function a wrapper function for Float
* @return property wrapper around a Float function
*/
- public static <Z extends Number> PropertyValue<CameraFunction<Z, Float>> iconHaloBlur(CameraFunction<Z, Float> function) {
+ public static <T> PropertyValue<Function<T, Float>> iconHaloBlur(Function<T, Float> function) {
return new PaintPropertyValue<>("icon-halo-blur", function);
}
@@ -628,11 +628,11 @@ public class PropertyFactory {
/**
* The opacity at which the text will be drawn.
*
- * @param <Z> the zoom parameter type
- * @param function a wrapper {@link CameraFunction} for Float
+ * @param <T> the function input type
+ * @param function a wrapper function for Float
* @return property wrapper around a Float function
*/
- public static <Z extends Number> PropertyValue<CameraFunction<Z, Float>> textOpacity(CameraFunction<Z, Float> function) {
+ public static <T> PropertyValue<Function<T, Float>> textOpacity(Function<T, Float> function) {
return new PaintPropertyValue<>("text-opacity", function);
}
@@ -660,11 +660,11 @@ public class PropertyFactory {
/**
* The color with which the text will be drawn.
*
- * @param <Z> the zoom parameter type
- * @param function a wrapper {@link CameraFunction} for String
+ * @param <T> the function input type
+ * @param function a wrapper function for String
* @return property wrapper around a String function
*/
- public static <Z extends Number> PropertyValue<CameraFunction<Z, String>> textColor(CameraFunction<Z, String> function) {
+ public static <T> PropertyValue<Function<T, String>> textColor(Function<T, String> function) {
return new PaintPropertyValue<>("text-color", function);
}
@@ -692,11 +692,11 @@ public class PropertyFactory {
/**
* The color of the text's halo, which helps it stand out from backgrounds.
*
- * @param <Z> the zoom parameter type
- * @param function a wrapper {@link CameraFunction} for String
+ * @param <T> the function input type
+ * @param function a wrapper function for String
* @return property wrapper around a String function
*/
- public static <Z extends Number> PropertyValue<CameraFunction<Z, String>> textHaloColor(CameraFunction<Z, String> function) {
+ public static <T> PropertyValue<Function<T, String>> textHaloColor(Function<T, String> function) {
return new PaintPropertyValue<>("text-halo-color", function);
}
@@ -714,11 +714,11 @@ public class PropertyFactory {
/**
* Distance of halo to the font outline. Max text halo width is 1/4 of the font-size.
*
- * @param <Z> the zoom parameter type
- * @param function a wrapper {@link CameraFunction} for Float
+ * @param <T> the function input type
+ * @param function a wrapper function for Float
* @return property wrapper around a Float function
*/
- public static <Z extends Number> PropertyValue<CameraFunction<Z, Float>> textHaloWidth(CameraFunction<Z, Float> function) {
+ public static <T> PropertyValue<Function<T, Float>> textHaloWidth(Function<T, Float> function) {
return new PaintPropertyValue<>("text-halo-width", function);
}
@@ -736,11 +736,11 @@ public class PropertyFactory {
/**
* The halo's fadeout distance towards the outside.
*
- * @param <Z> the zoom parameter type
- * @param function a wrapper {@link CameraFunction} for Float
+ * @param <T> the function input type
+ * @param function a wrapper function for Float
* @return property wrapper around a Float function
*/
- public static <Z extends Number> PropertyValue<CameraFunction<Z, Float>> textHaloBlur(CameraFunction<Z, Float> function) {
+ public static <T> PropertyValue<Function<T, Float>> textHaloBlur(Function<T, Float> function) {
return new PaintPropertyValue<>("text-halo-blur", function);
}
@@ -1742,7 +1742,7 @@ public class PropertyFactory {
}
/**
- * Value to use for a text label. Feature properties are specified using tokens like {field_name}. (Token replacement is only supported for literal `textField` values--not for property functions.)
+ * Value to use for a text label. Feature properties are specified using tokens like {field_name}. (Token replacement is only supported for literal {@link PropertyFactory#textField} values--not for property functions.)
*
* @param value a String value
* @return property wrapper around String
@@ -1754,7 +1754,7 @@ public class PropertyFactory {
/**
- * Value to use for a text label. Feature properties are specified using tokens like {field_name}. (Token replacement is only supported for literal `textField` values--not for property functions.)
+ * Value to use for a text label. Feature properties are specified using tokens like {field_name}. (Token replacement is only supported for literal {@link PropertyFactory#textField} values--not for property functions.)
*
* @param <T> the function input type
* @param function a wrapper function for String
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/SymbolLayerTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/SymbolLayerTest.java
index 74b9555183..3b3bc9c8b5 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/SymbolLayerTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/SymbolLayerTest.java
@@ -1598,6 +1598,112 @@ public class SymbolLayerTest extends BaseStyleTest {
}
@Test
+ public void testIconOpacityAsIdentitySourceFunction() {
+ checkViewIsDisplayed(R.id.mapView);
+ Timber.i("icon-opacity");
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ iconOpacity(property("FeaturePropertyA", Stops.<Float>identity()))
+ );
+
+ // Verify
+ assertNotNull(layer.getIconOpacity());
+ assertNotNull(layer.getIconOpacity().getFunction());
+ assertEquals(SourceFunction.class, layer.getIconOpacity().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconOpacity().getFunction()).getProperty());
+ assertEquals(IdentityStops.class, layer.getIconOpacity().getFunction().getStops().getClass());
+ }
+
+ @Test
+ public void testIconOpacityAsExponentialSourceFunction() {
+ checkViewIsDisplayed(R.id.mapView);
+ Timber.i("icon-opacity");
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ iconOpacity(
+ property(
+ "FeaturePropertyA",
+ exponential(
+ stop(0.3f, iconOpacity(0.3f))
+ ).withBase(0.5f)
+ )
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getIconOpacity());
+ assertNotNull(layer.getIconOpacity().getFunction());
+ assertEquals(SourceFunction.class, layer.getIconOpacity().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconOpacity().getFunction()).getProperty());
+ assertEquals(ExponentialStops.class, layer.getIconOpacity().getFunction().getStops().getClass());
+ }
+
+ @Test
+ public void testIconOpacityAsCategoricalSourceFunction() {
+ checkViewIsDisplayed(R.id.mapView);
+ Timber.i("icon-opacity");
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ iconOpacity(
+ property(
+ "FeaturePropertyA",
+ categorical(
+ stop(1.0f, iconOpacity(0.3f))
+ )
+ ).withDefaultValue(0.3f)
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getIconOpacity());
+ assertNotNull(layer.getIconOpacity().getFunction());
+ assertEquals(SourceFunction.class, layer.getIconOpacity().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconOpacity().getFunction()).getProperty());
+ assertEquals(CategoricalStops.class, layer.getIconOpacity().getFunction().getStops().getClass());
+ assertEquals(0.3f, ((SourceFunction) layer.getIconOpacity().getFunction()).getDefaultValue());
+ }
+
+ @Test
+ public void testIconOpacityAsCompositeFunction() {
+ checkViewIsDisplayed(R.id.mapView);
+ Timber.i("icon-opacity");
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ iconOpacity(
+ composite(
+ "FeaturePropertyA",
+ exponential(
+ stop(0, 0.3f, iconOpacity(0.9f))
+ ).withBase(0.5f)
+ ).withDefaultValue(0.3f)
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getIconOpacity());
+ assertNotNull(layer.getIconOpacity().getFunction());
+ assertEquals(CompositeFunction.class, layer.getIconOpacity().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((CompositeFunction) layer.getIconOpacity().getFunction()).getProperty());
+ assertEquals(ExponentialStops.class, layer.getIconOpacity().getFunction().getStops().getClass());
+ assertEquals(1, ((ExponentialStops) layer.getIconOpacity().getFunction().getStops()).size());
+
+ ExponentialStops<Stop.CompositeValue<Float, Float>, Float> stops =
+ (ExponentialStops<Stop.CompositeValue<Float, Float>, Float>) layer.getIconOpacity().getFunction().getStops();
+ Stop<Stop.CompositeValue<Float, Float>, Float> stop = stops.iterator().next();
+ assertEquals(0f, stop.in.zoom, 0.001);
+ assertEquals(0.3f, stop.in.value, 0.001f);
+ assertEquals(0.9f, stop.out, 0.001f);
+ }
+
+ @Test
public void testIconColorAsConstant() {
checkViewIsDisplayed(R.id.mapView);
Timber.i("icon-color");
@@ -1635,6 +1741,77 @@ public class SymbolLayerTest extends BaseStyleTest {
}
@Test
+ public void testIconColorAsIdentitySourceFunction() {
+ checkViewIsDisplayed(R.id.mapView);
+ Timber.i("icon-color");
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ iconColor(property("FeaturePropertyA", Stops.<String>identity()))
+ );
+
+ // Verify
+ assertNotNull(layer.getIconColor());
+ assertNotNull(layer.getIconColor().getFunction());
+ assertEquals(SourceFunction.class, layer.getIconColor().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconColor().getFunction()).getProperty());
+ assertEquals(IdentityStops.class, layer.getIconColor().getFunction().getStops().getClass());
+ }
+
+ @Test
+ public void testIconColorAsExponentialSourceFunction() {
+ checkViewIsDisplayed(R.id.mapView);
+ Timber.i("icon-color");
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ iconColor(
+ property(
+ "FeaturePropertyA",
+ exponential(
+ stop(Color.RED, iconColor(Color.RED))
+ ).withBase(0.5f)
+ )
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getIconColor());
+ assertNotNull(layer.getIconColor().getFunction());
+ assertEquals(SourceFunction.class, layer.getIconColor().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconColor().getFunction()).getProperty());
+ assertEquals(ExponentialStops.class, layer.getIconColor().getFunction().getStops().getClass());
+ }
+
+ @Test
+ public void testIconColorAsCategoricalSourceFunction() {
+ checkViewIsDisplayed(R.id.mapView);
+ Timber.i("icon-color");
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ iconColor(
+ property(
+ "FeaturePropertyA",
+ categorical(
+ stop("valueA", iconColor(Color.RED))
+ )
+ )
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getIconColor());
+ assertNotNull(layer.getIconColor().getFunction());
+ assertEquals(SourceFunction.class, layer.getIconColor().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconColor().getFunction()).getProperty());
+ assertEquals(CategoricalStops.class, layer.getIconColor().getFunction().getStops().getClass());
+ }
+
+ @Test
public void testIconColorAsIntConstant() {
checkViewIsDisplayed(R.id.mapView);
Timber.i("icon-color");
@@ -1683,6 +1860,77 @@ public class SymbolLayerTest extends BaseStyleTest {
}
@Test
+ public void testIconHaloColorAsIdentitySourceFunction() {
+ checkViewIsDisplayed(R.id.mapView);
+ Timber.i("icon-halo-color");
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ iconHaloColor(property("FeaturePropertyA", Stops.<String>identity()))
+ );
+
+ // Verify
+ assertNotNull(layer.getIconHaloColor());
+ assertNotNull(layer.getIconHaloColor().getFunction());
+ assertEquals(SourceFunction.class, layer.getIconHaloColor().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconHaloColor().getFunction()).getProperty());
+ assertEquals(IdentityStops.class, layer.getIconHaloColor().getFunction().getStops().getClass());
+ }
+
+ @Test
+ public void testIconHaloColorAsExponentialSourceFunction() {
+ checkViewIsDisplayed(R.id.mapView);
+ Timber.i("icon-halo-color");
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ iconHaloColor(
+ property(
+ "FeaturePropertyA",
+ exponential(
+ stop(Color.RED, iconHaloColor(Color.RED))
+ ).withBase(0.5f)
+ )
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getIconHaloColor());
+ assertNotNull(layer.getIconHaloColor().getFunction());
+ assertEquals(SourceFunction.class, layer.getIconHaloColor().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconHaloColor().getFunction()).getProperty());
+ assertEquals(ExponentialStops.class, layer.getIconHaloColor().getFunction().getStops().getClass());
+ }
+
+ @Test
+ public void testIconHaloColorAsCategoricalSourceFunction() {
+ checkViewIsDisplayed(R.id.mapView);
+ Timber.i("icon-halo-color");
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ iconHaloColor(
+ property(
+ "FeaturePropertyA",
+ categorical(
+ stop("valueA", iconHaloColor(Color.RED))
+ )
+ )
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getIconHaloColor());
+ assertNotNull(layer.getIconHaloColor().getFunction());
+ assertEquals(SourceFunction.class, layer.getIconHaloColor().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconHaloColor().getFunction()).getProperty());
+ assertEquals(CategoricalStops.class, layer.getIconHaloColor().getFunction().getStops().getClass());
+ }
+
+ @Test
public void testIconHaloColorAsIntConstant() {
checkViewIsDisplayed(R.id.mapView);
Timber.i("icon-halo-color");
@@ -1731,6 +1979,112 @@ public class SymbolLayerTest extends BaseStyleTest {
}
@Test
+ public void testIconHaloWidthAsIdentitySourceFunction() {
+ checkViewIsDisplayed(R.id.mapView);
+ Timber.i("icon-halo-width");
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ iconHaloWidth(property("FeaturePropertyA", Stops.<Float>identity()))
+ );
+
+ // Verify
+ assertNotNull(layer.getIconHaloWidth());
+ assertNotNull(layer.getIconHaloWidth().getFunction());
+ assertEquals(SourceFunction.class, layer.getIconHaloWidth().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconHaloWidth().getFunction()).getProperty());
+ assertEquals(IdentityStops.class, layer.getIconHaloWidth().getFunction().getStops().getClass());
+ }
+
+ @Test
+ public void testIconHaloWidthAsExponentialSourceFunction() {
+ checkViewIsDisplayed(R.id.mapView);
+ Timber.i("icon-halo-width");
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ iconHaloWidth(
+ property(
+ "FeaturePropertyA",
+ exponential(
+ stop(0.3f, iconHaloWidth(0.3f))
+ ).withBase(0.5f)
+ )
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getIconHaloWidth());
+ assertNotNull(layer.getIconHaloWidth().getFunction());
+ assertEquals(SourceFunction.class, layer.getIconHaloWidth().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconHaloWidth().getFunction()).getProperty());
+ assertEquals(ExponentialStops.class, layer.getIconHaloWidth().getFunction().getStops().getClass());
+ }
+
+ @Test
+ public void testIconHaloWidthAsCategoricalSourceFunction() {
+ checkViewIsDisplayed(R.id.mapView);
+ Timber.i("icon-halo-width");
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ iconHaloWidth(
+ property(
+ "FeaturePropertyA",
+ categorical(
+ stop(1.0f, iconHaloWidth(0.3f))
+ )
+ ).withDefaultValue(0.3f)
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getIconHaloWidth());
+ assertNotNull(layer.getIconHaloWidth().getFunction());
+ assertEquals(SourceFunction.class, layer.getIconHaloWidth().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconHaloWidth().getFunction()).getProperty());
+ assertEquals(CategoricalStops.class, layer.getIconHaloWidth().getFunction().getStops().getClass());
+ assertEquals(0.3f, ((SourceFunction) layer.getIconHaloWidth().getFunction()).getDefaultValue());
+ }
+
+ @Test
+ public void testIconHaloWidthAsCompositeFunction() {
+ checkViewIsDisplayed(R.id.mapView);
+ Timber.i("icon-halo-width");
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ iconHaloWidth(
+ composite(
+ "FeaturePropertyA",
+ exponential(
+ stop(0, 0.3f, iconHaloWidth(0.9f))
+ ).withBase(0.5f)
+ ).withDefaultValue(0.3f)
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getIconHaloWidth());
+ assertNotNull(layer.getIconHaloWidth().getFunction());
+ assertEquals(CompositeFunction.class, layer.getIconHaloWidth().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((CompositeFunction) layer.getIconHaloWidth().getFunction()).getProperty());
+ assertEquals(ExponentialStops.class, layer.getIconHaloWidth().getFunction().getStops().getClass());
+ assertEquals(1, ((ExponentialStops) layer.getIconHaloWidth().getFunction().getStops()).size());
+
+ ExponentialStops<Stop.CompositeValue<Float, Float>, Float> stops =
+ (ExponentialStops<Stop.CompositeValue<Float, Float>, Float>) layer.getIconHaloWidth().getFunction().getStops();
+ Stop<Stop.CompositeValue<Float, Float>, Float> stop = stops.iterator().next();
+ assertEquals(0f, stop.in.zoom, 0.001);
+ assertEquals(0.3f, stop.in.value, 0.001f);
+ assertEquals(0.9f, stop.out, 0.001f);
+ }
+
+ @Test
public void testIconHaloBlurAsConstant() {
checkViewIsDisplayed(R.id.mapView);
Timber.i("icon-halo-blur");
@@ -1768,6 +2122,112 @@ public class SymbolLayerTest extends BaseStyleTest {
}
@Test
+ public void testIconHaloBlurAsIdentitySourceFunction() {
+ checkViewIsDisplayed(R.id.mapView);
+ Timber.i("icon-halo-blur");
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ iconHaloBlur(property("FeaturePropertyA", Stops.<Float>identity()))
+ );
+
+ // Verify
+ assertNotNull(layer.getIconHaloBlur());
+ assertNotNull(layer.getIconHaloBlur().getFunction());
+ assertEquals(SourceFunction.class, layer.getIconHaloBlur().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconHaloBlur().getFunction()).getProperty());
+ assertEquals(IdentityStops.class, layer.getIconHaloBlur().getFunction().getStops().getClass());
+ }
+
+ @Test
+ public void testIconHaloBlurAsExponentialSourceFunction() {
+ checkViewIsDisplayed(R.id.mapView);
+ Timber.i("icon-halo-blur");
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ iconHaloBlur(
+ property(
+ "FeaturePropertyA",
+ exponential(
+ stop(0.3f, iconHaloBlur(0.3f))
+ ).withBase(0.5f)
+ )
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getIconHaloBlur());
+ assertNotNull(layer.getIconHaloBlur().getFunction());
+ assertEquals(SourceFunction.class, layer.getIconHaloBlur().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconHaloBlur().getFunction()).getProperty());
+ assertEquals(ExponentialStops.class, layer.getIconHaloBlur().getFunction().getStops().getClass());
+ }
+
+ @Test
+ public void testIconHaloBlurAsCategoricalSourceFunction() {
+ checkViewIsDisplayed(R.id.mapView);
+ Timber.i("icon-halo-blur");
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ iconHaloBlur(
+ property(
+ "FeaturePropertyA",
+ categorical(
+ stop(1.0f, iconHaloBlur(0.3f))
+ )
+ ).withDefaultValue(0.3f)
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getIconHaloBlur());
+ assertNotNull(layer.getIconHaloBlur().getFunction());
+ assertEquals(SourceFunction.class, layer.getIconHaloBlur().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconHaloBlur().getFunction()).getProperty());
+ assertEquals(CategoricalStops.class, layer.getIconHaloBlur().getFunction().getStops().getClass());
+ assertEquals(0.3f, ((SourceFunction) layer.getIconHaloBlur().getFunction()).getDefaultValue());
+ }
+
+ @Test
+ public void testIconHaloBlurAsCompositeFunction() {
+ checkViewIsDisplayed(R.id.mapView);
+ Timber.i("icon-halo-blur");
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ iconHaloBlur(
+ composite(
+ "FeaturePropertyA",
+ exponential(
+ stop(0, 0.3f, iconHaloBlur(0.9f))
+ ).withBase(0.5f)
+ ).withDefaultValue(0.3f)
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getIconHaloBlur());
+ assertNotNull(layer.getIconHaloBlur().getFunction());
+ assertEquals(CompositeFunction.class, layer.getIconHaloBlur().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((CompositeFunction) layer.getIconHaloBlur().getFunction()).getProperty());
+ assertEquals(ExponentialStops.class, layer.getIconHaloBlur().getFunction().getStops().getClass());
+ assertEquals(1, ((ExponentialStops) layer.getIconHaloBlur().getFunction().getStops()).size());
+
+ ExponentialStops<Stop.CompositeValue<Float, Float>, Float> stops =
+ (ExponentialStops<Stop.CompositeValue<Float, Float>, Float>) layer.getIconHaloBlur().getFunction().getStops();
+ Stop<Stop.CompositeValue<Float, Float>, Float> stop = stops.iterator().next();
+ assertEquals(0f, stop.in.zoom, 0.001);
+ assertEquals(0.3f, stop.in.value, 0.001f);
+ assertEquals(0.9f, stop.out, 0.001f);
+ }
+
+ @Test
public void testIconTranslateAsConstant() {
checkViewIsDisplayed(R.id.mapView);
Timber.i("icon-translate");
@@ -1878,6 +2338,112 @@ public class SymbolLayerTest extends BaseStyleTest {
}
@Test
+ public void testTextOpacityAsIdentitySourceFunction() {
+ checkViewIsDisplayed(R.id.mapView);
+ Timber.i("text-opacity");
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ textOpacity(property("FeaturePropertyA", Stops.<Float>identity()))
+ );
+
+ // Verify
+ assertNotNull(layer.getTextOpacity());
+ assertNotNull(layer.getTextOpacity().getFunction());
+ assertEquals(SourceFunction.class, layer.getTextOpacity().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextOpacity().getFunction()).getProperty());
+ assertEquals(IdentityStops.class, layer.getTextOpacity().getFunction().getStops().getClass());
+ }
+
+ @Test
+ public void testTextOpacityAsExponentialSourceFunction() {
+ checkViewIsDisplayed(R.id.mapView);
+ Timber.i("text-opacity");
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ textOpacity(
+ property(
+ "FeaturePropertyA",
+ exponential(
+ stop(0.3f, textOpacity(0.3f))
+ ).withBase(0.5f)
+ )
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getTextOpacity());
+ assertNotNull(layer.getTextOpacity().getFunction());
+ assertEquals(SourceFunction.class, layer.getTextOpacity().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextOpacity().getFunction()).getProperty());
+ assertEquals(ExponentialStops.class, layer.getTextOpacity().getFunction().getStops().getClass());
+ }
+
+ @Test
+ public void testTextOpacityAsCategoricalSourceFunction() {
+ checkViewIsDisplayed(R.id.mapView);
+ Timber.i("text-opacity");
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ textOpacity(
+ property(
+ "FeaturePropertyA",
+ categorical(
+ stop(1.0f, textOpacity(0.3f))
+ )
+ ).withDefaultValue(0.3f)
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getTextOpacity());
+ assertNotNull(layer.getTextOpacity().getFunction());
+ assertEquals(SourceFunction.class, layer.getTextOpacity().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextOpacity().getFunction()).getProperty());
+ assertEquals(CategoricalStops.class, layer.getTextOpacity().getFunction().getStops().getClass());
+ assertEquals(0.3f, ((SourceFunction) layer.getTextOpacity().getFunction()).getDefaultValue());
+ }
+
+ @Test
+ public void testTextOpacityAsCompositeFunction() {
+ checkViewIsDisplayed(R.id.mapView);
+ Timber.i("text-opacity");
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ textOpacity(
+ composite(
+ "FeaturePropertyA",
+ exponential(
+ stop(0, 0.3f, textOpacity(0.9f))
+ ).withBase(0.5f)
+ ).withDefaultValue(0.3f)
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getTextOpacity());
+ assertNotNull(layer.getTextOpacity().getFunction());
+ assertEquals(CompositeFunction.class, layer.getTextOpacity().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((CompositeFunction) layer.getTextOpacity().getFunction()).getProperty());
+ assertEquals(ExponentialStops.class, layer.getTextOpacity().getFunction().getStops().getClass());
+ assertEquals(1, ((ExponentialStops) layer.getTextOpacity().getFunction().getStops()).size());
+
+ ExponentialStops<Stop.CompositeValue<Float, Float>, Float> stops =
+ (ExponentialStops<Stop.CompositeValue<Float, Float>, Float>) layer.getTextOpacity().getFunction().getStops();
+ Stop<Stop.CompositeValue<Float, Float>, Float> stop = stops.iterator().next();
+ assertEquals(0f, stop.in.zoom, 0.001);
+ assertEquals(0.3f, stop.in.value, 0.001f);
+ assertEquals(0.9f, stop.out, 0.001f);
+ }
+
+ @Test
public void testTextColorAsConstant() {
checkViewIsDisplayed(R.id.mapView);
Timber.i("text-color");
@@ -1915,6 +2481,77 @@ public class SymbolLayerTest extends BaseStyleTest {
}
@Test
+ public void testTextColorAsIdentitySourceFunction() {
+ checkViewIsDisplayed(R.id.mapView);
+ Timber.i("text-color");
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ textColor(property("FeaturePropertyA", Stops.<String>identity()))
+ );
+
+ // Verify
+ assertNotNull(layer.getTextColor());
+ assertNotNull(layer.getTextColor().getFunction());
+ assertEquals(SourceFunction.class, layer.getTextColor().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextColor().getFunction()).getProperty());
+ assertEquals(IdentityStops.class, layer.getTextColor().getFunction().getStops().getClass());
+ }
+
+ @Test
+ public void testTextColorAsExponentialSourceFunction() {
+ checkViewIsDisplayed(R.id.mapView);
+ Timber.i("text-color");
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ textColor(
+ property(
+ "FeaturePropertyA",
+ exponential(
+ stop(Color.RED, textColor(Color.RED))
+ ).withBase(0.5f)
+ )
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getTextColor());
+ assertNotNull(layer.getTextColor().getFunction());
+ assertEquals(SourceFunction.class, layer.getTextColor().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextColor().getFunction()).getProperty());
+ assertEquals(ExponentialStops.class, layer.getTextColor().getFunction().getStops().getClass());
+ }
+
+ @Test
+ public void testTextColorAsCategoricalSourceFunction() {
+ checkViewIsDisplayed(R.id.mapView);
+ Timber.i("text-color");
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ textColor(
+ property(
+ "FeaturePropertyA",
+ categorical(
+ stop("valueA", textColor(Color.RED))
+ )
+ )
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getTextColor());
+ assertNotNull(layer.getTextColor().getFunction());
+ assertEquals(SourceFunction.class, layer.getTextColor().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextColor().getFunction()).getProperty());
+ assertEquals(CategoricalStops.class, layer.getTextColor().getFunction().getStops().getClass());
+ }
+
+ @Test
public void testTextColorAsIntConstant() {
checkViewIsDisplayed(R.id.mapView);
Timber.i("text-color");
@@ -1963,6 +2600,77 @@ public class SymbolLayerTest extends BaseStyleTest {
}
@Test
+ public void testTextHaloColorAsIdentitySourceFunction() {
+ checkViewIsDisplayed(R.id.mapView);
+ Timber.i("text-halo-color");
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ textHaloColor(property("FeaturePropertyA", Stops.<String>identity()))
+ );
+
+ // Verify
+ assertNotNull(layer.getTextHaloColor());
+ assertNotNull(layer.getTextHaloColor().getFunction());
+ assertEquals(SourceFunction.class, layer.getTextHaloColor().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextHaloColor().getFunction()).getProperty());
+ assertEquals(IdentityStops.class, layer.getTextHaloColor().getFunction().getStops().getClass());
+ }
+
+ @Test
+ public void testTextHaloColorAsExponentialSourceFunction() {
+ checkViewIsDisplayed(R.id.mapView);
+ Timber.i("text-halo-color");
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ textHaloColor(
+ property(
+ "FeaturePropertyA",
+ exponential(
+ stop(Color.RED, textHaloColor(Color.RED))
+ ).withBase(0.5f)
+ )
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getTextHaloColor());
+ assertNotNull(layer.getTextHaloColor().getFunction());
+ assertEquals(SourceFunction.class, layer.getTextHaloColor().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextHaloColor().getFunction()).getProperty());
+ assertEquals(ExponentialStops.class, layer.getTextHaloColor().getFunction().getStops().getClass());
+ }
+
+ @Test
+ public void testTextHaloColorAsCategoricalSourceFunction() {
+ checkViewIsDisplayed(R.id.mapView);
+ Timber.i("text-halo-color");
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ textHaloColor(
+ property(
+ "FeaturePropertyA",
+ categorical(
+ stop("valueA", textHaloColor(Color.RED))
+ )
+ )
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getTextHaloColor());
+ assertNotNull(layer.getTextHaloColor().getFunction());
+ assertEquals(SourceFunction.class, layer.getTextHaloColor().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextHaloColor().getFunction()).getProperty());
+ assertEquals(CategoricalStops.class, layer.getTextHaloColor().getFunction().getStops().getClass());
+ }
+
+ @Test
public void testTextHaloColorAsIntConstant() {
checkViewIsDisplayed(R.id.mapView);
Timber.i("text-halo-color");
@@ -2011,6 +2719,112 @@ public class SymbolLayerTest extends BaseStyleTest {
}
@Test
+ public void testTextHaloWidthAsIdentitySourceFunction() {
+ checkViewIsDisplayed(R.id.mapView);
+ Timber.i("text-halo-width");
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ textHaloWidth(property("FeaturePropertyA", Stops.<Float>identity()))
+ );
+
+ // Verify
+ assertNotNull(layer.getTextHaloWidth());
+ assertNotNull(layer.getTextHaloWidth().getFunction());
+ assertEquals(SourceFunction.class, layer.getTextHaloWidth().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextHaloWidth().getFunction()).getProperty());
+ assertEquals(IdentityStops.class, layer.getTextHaloWidth().getFunction().getStops().getClass());
+ }
+
+ @Test
+ public void testTextHaloWidthAsExponentialSourceFunction() {
+ checkViewIsDisplayed(R.id.mapView);
+ Timber.i("text-halo-width");
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ textHaloWidth(
+ property(
+ "FeaturePropertyA",
+ exponential(
+ stop(0.3f, textHaloWidth(0.3f))
+ ).withBase(0.5f)
+ )
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getTextHaloWidth());
+ assertNotNull(layer.getTextHaloWidth().getFunction());
+ assertEquals(SourceFunction.class, layer.getTextHaloWidth().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextHaloWidth().getFunction()).getProperty());
+ assertEquals(ExponentialStops.class, layer.getTextHaloWidth().getFunction().getStops().getClass());
+ }
+
+ @Test
+ public void testTextHaloWidthAsCategoricalSourceFunction() {
+ checkViewIsDisplayed(R.id.mapView);
+ Timber.i("text-halo-width");
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ textHaloWidth(
+ property(
+ "FeaturePropertyA",
+ categorical(
+ stop(1.0f, textHaloWidth(0.3f))
+ )
+ ).withDefaultValue(0.3f)
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getTextHaloWidth());
+ assertNotNull(layer.getTextHaloWidth().getFunction());
+ assertEquals(SourceFunction.class, layer.getTextHaloWidth().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextHaloWidth().getFunction()).getProperty());
+ assertEquals(CategoricalStops.class, layer.getTextHaloWidth().getFunction().getStops().getClass());
+ assertEquals(0.3f, ((SourceFunction) layer.getTextHaloWidth().getFunction()).getDefaultValue());
+ }
+
+ @Test
+ public void testTextHaloWidthAsCompositeFunction() {
+ checkViewIsDisplayed(R.id.mapView);
+ Timber.i("text-halo-width");
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ textHaloWidth(
+ composite(
+ "FeaturePropertyA",
+ exponential(
+ stop(0, 0.3f, textHaloWidth(0.9f))
+ ).withBase(0.5f)
+ ).withDefaultValue(0.3f)
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getTextHaloWidth());
+ assertNotNull(layer.getTextHaloWidth().getFunction());
+ assertEquals(CompositeFunction.class, layer.getTextHaloWidth().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((CompositeFunction) layer.getTextHaloWidth().getFunction()).getProperty());
+ assertEquals(ExponentialStops.class, layer.getTextHaloWidth().getFunction().getStops().getClass());
+ assertEquals(1, ((ExponentialStops) layer.getTextHaloWidth().getFunction().getStops()).size());
+
+ ExponentialStops<Stop.CompositeValue<Float, Float>, Float> stops =
+ (ExponentialStops<Stop.CompositeValue<Float, Float>, Float>) layer.getTextHaloWidth().getFunction().getStops();
+ Stop<Stop.CompositeValue<Float, Float>, Float> stop = stops.iterator().next();
+ assertEquals(0f, stop.in.zoom, 0.001);
+ assertEquals(0.3f, stop.in.value, 0.001f);
+ assertEquals(0.9f, stop.out, 0.001f);
+ }
+
+ @Test
public void testTextHaloBlurAsConstant() {
checkViewIsDisplayed(R.id.mapView);
Timber.i("text-halo-blur");
@@ -2048,6 +2862,112 @@ public class SymbolLayerTest extends BaseStyleTest {
}
@Test
+ public void testTextHaloBlurAsIdentitySourceFunction() {
+ checkViewIsDisplayed(R.id.mapView);
+ Timber.i("text-halo-blur");
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ textHaloBlur(property("FeaturePropertyA", Stops.<Float>identity()))
+ );
+
+ // Verify
+ assertNotNull(layer.getTextHaloBlur());
+ assertNotNull(layer.getTextHaloBlur().getFunction());
+ assertEquals(SourceFunction.class, layer.getTextHaloBlur().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextHaloBlur().getFunction()).getProperty());
+ assertEquals(IdentityStops.class, layer.getTextHaloBlur().getFunction().getStops().getClass());
+ }
+
+ @Test
+ public void testTextHaloBlurAsExponentialSourceFunction() {
+ checkViewIsDisplayed(R.id.mapView);
+ Timber.i("text-halo-blur");
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ textHaloBlur(
+ property(
+ "FeaturePropertyA",
+ exponential(
+ stop(0.3f, textHaloBlur(0.3f))
+ ).withBase(0.5f)
+ )
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getTextHaloBlur());
+ assertNotNull(layer.getTextHaloBlur().getFunction());
+ assertEquals(SourceFunction.class, layer.getTextHaloBlur().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextHaloBlur().getFunction()).getProperty());
+ assertEquals(ExponentialStops.class, layer.getTextHaloBlur().getFunction().getStops().getClass());
+ }
+
+ @Test
+ public void testTextHaloBlurAsCategoricalSourceFunction() {
+ checkViewIsDisplayed(R.id.mapView);
+ Timber.i("text-halo-blur");
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ textHaloBlur(
+ property(
+ "FeaturePropertyA",
+ categorical(
+ stop(1.0f, textHaloBlur(0.3f))
+ )
+ ).withDefaultValue(0.3f)
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getTextHaloBlur());
+ assertNotNull(layer.getTextHaloBlur().getFunction());
+ assertEquals(SourceFunction.class, layer.getTextHaloBlur().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextHaloBlur().getFunction()).getProperty());
+ assertEquals(CategoricalStops.class, layer.getTextHaloBlur().getFunction().getStops().getClass());
+ assertEquals(0.3f, ((SourceFunction) layer.getTextHaloBlur().getFunction()).getDefaultValue());
+ }
+
+ @Test
+ public void testTextHaloBlurAsCompositeFunction() {
+ checkViewIsDisplayed(R.id.mapView);
+ Timber.i("text-halo-blur");
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ textHaloBlur(
+ composite(
+ "FeaturePropertyA",
+ exponential(
+ stop(0, 0.3f, textHaloBlur(0.9f))
+ ).withBase(0.5f)
+ ).withDefaultValue(0.3f)
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getTextHaloBlur());
+ assertNotNull(layer.getTextHaloBlur().getFunction());
+ assertEquals(CompositeFunction.class, layer.getTextHaloBlur().getFunction().getClass());
+ assertEquals("FeaturePropertyA", ((CompositeFunction) layer.getTextHaloBlur().getFunction()).getProperty());
+ assertEquals(ExponentialStops.class, layer.getTextHaloBlur().getFunction().getStops().getClass());
+ assertEquals(1, ((ExponentialStops) layer.getTextHaloBlur().getFunction().getStops()).size());
+
+ ExponentialStops<Stop.CompositeValue<Float, Float>, Float> stops =
+ (ExponentialStops<Stop.CompositeValue<Float, Float>, Float>) layer.getTextHaloBlur().getFunction().getStops();
+ Stop<Stop.CompositeValue<Float, Float>, Float> stop = stops.iterator().next();
+ assertEquals(0f, stop.in.zoom, 0.001);
+ assertEquals(0.3f, stop.in.value, 0.001f);
+ assertEquals(0.9f, stop.out, 0.001f);
+ }
+
+ @Test
public void testTextTranslateAsConstant() {
checkViewIsDisplayed(R.id.mapView);
Timber.i("text-translate");
diff --git a/platform/darwin/src/MGLSymbolStyleLayer.h b/platform/darwin/src/MGLSymbolStyleLayer.h
index d2892f9627..a4850a4e18 100644
--- a/platform/darwin/src/MGLSymbolStyleLayer.h
+++ b/platform/darwin/src/MGLSymbolStyleLayer.h
@@ -1204,6 +1204,15 @@ MGL_EXPORT
* `MGLCameraStyleFunction` with an interpolation mode of:
* `MGLInterpolationModeExponential`
* `MGLInterpolationModeInterval`
+ * `MGLSourceStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLInterpolationModeCategorical`
+ * `MGLInterpolationModeIdentity`
+ * `MGLCompositeStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLInterpolationModeCategorical`
*/
@property (nonatomic, null_resettable) MGLStyleValue<UIColor *> *iconColor;
#else
@@ -1224,6 +1233,15 @@ MGL_EXPORT
* `MGLCameraStyleFunction` with an interpolation mode of:
* `MGLInterpolationModeExponential`
* `MGLInterpolationModeInterval`
+ * `MGLSourceStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLInterpolationModeCategorical`
+ * `MGLInterpolationModeIdentity`
+ * `MGLCompositeStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLInterpolationModeCategorical`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSColor *> *iconColor;
#endif
@@ -1246,6 +1264,15 @@ MGL_EXPORT
* `MGLCameraStyleFunction` with an interpolation mode of:
* `MGLInterpolationModeExponential`
* `MGLInterpolationModeInterval`
+ * `MGLSourceStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLInterpolationModeCategorical`
+ * `MGLInterpolationModeIdentity`
+ * `MGLCompositeStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLInterpolationModeCategorical`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *iconHaloBlur;
@@ -1267,6 +1294,15 @@ MGL_EXPORT
* `MGLCameraStyleFunction` with an interpolation mode of:
* `MGLInterpolationModeExponential`
* `MGLInterpolationModeInterval`
+ * `MGLSourceStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLInterpolationModeCategorical`
+ * `MGLInterpolationModeIdentity`
+ * `MGLCompositeStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLInterpolationModeCategorical`
*/
@property (nonatomic, null_resettable) MGLStyleValue<UIColor *> *iconHaloColor;
#else
@@ -1287,6 +1323,15 @@ MGL_EXPORT
* `MGLCameraStyleFunction` with an interpolation mode of:
* `MGLInterpolationModeExponential`
* `MGLInterpolationModeInterval`
+ * `MGLSourceStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLInterpolationModeCategorical`
+ * `MGLInterpolationModeIdentity`
+ * `MGLCompositeStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLInterpolationModeCategorical`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSColor *> *iconHaloColor;
#endif
@@ -1309,6 +1354,15 @@ MGL_EXPORT
* `MGLCameraStyleFunction` with an interpolation mode of:
* `MGLInterpolationModeExponential`
* `MGLInterpolationModeInterval`
+ * `MGLSourceStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLInterpolationModeCategorical`
+ * `MGLInterpolationModeIdentity`
+ * `MGLCompositeStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLInterpolationModeCategorical`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *iconHaloWidth;
@@ -1328,6 +1382,15 @@ MGL_EXPORT
* `MGLCameraStyleFunction` with an interpolation mode of:
* `MGLInterpolationModeExponential`
* `MGLInterpolationModeInterval`
+ * `MGLSourceStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLInterpolationModeCategorical`
+ * `MGLInterpolationModeIdentity`
+ * `MGLCompositeStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLInterpolationModeCategorical`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *iconOpacity;
@@ -1426,6 +1489,15 @@ MGL_EXPORT
* `MGLCameraStyleFunction` with an interpolation mode of:
* `MGLInterpolationModeExponential`
* `MGLInterpolationModeInterval`
+ * `MGLSourceStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLInterpolationModeCategorical`
+ * `MGLInterpolationModeIdentity`
+ * `MGLCompositeStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLInterpolationModeCategorical`
*/
@property (nonatomic, null_resettable) MGLStyleValue<UIColor *> *textColor;
#else
@@ -1445,6 +1517,15 @@ MGL_EXPORT
* `MGLCameraStyleFunction` with an interpolation mode of:
* `MGLInterpolationModeExponential`
* `MGLInterpolationModeInterval`
+ * `MGLSourceStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLInterpolationModeCategorical`
+ * `MGLInterpolationModeIdentity`
+ * `MGLCompositeStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLInterpolationModeCategorical`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSColor *> *textColor;
#endif
@@ -1467,6 +1548,15 @@ MGL_EXPORT
* `MGLCameraStyleFunction` with an interpolation mode of:
* `MGLInterpolationModeExponential`
* `MGLInterpolationModeInterval`
+ * `MGLSourceStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLInterpolationModeCategorical`
+ * `MGLInterpolationModeIdentity`
+ * `MGLCompositeStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLInterpolationModeCategorical`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *textHaloBlur;
@@ -1487,6 +1577,15 @@ MGL_EXPORT
* `MGLCameraStyleFunction` with an interpolation mode of:
* `MGLInterpolationModeExponential`
* `MGLInterpolationModeInterval`
+ * `MGLSourceStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLInterpolationModeCategorical`
+ * `MGLInterpolationModeIdentity`
+ * `MGLCompositeStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLInterpolationModeCategorical`
*/
@property (nonatomic, null_resettable) MGLStyleValue<UIColor *> *textHaloColor;
#else
@@ -1506,6 +1605,15 @@ MGL_EXPORT
* `MGLCameraStyleFunction` with an interpolation mode of:
* `MGLInterpolationModeExponential`
* `MGLInterpolationModeInterval`
+ * `MGLSourceStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLInterpolationModeCategorical`
+ * `MGLInterpolationModeIdentity`
+ * `MGLCompositeStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLInterpolationModeCategorical`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSColor *> *textHaloColor;
#endif
@@ -1529,6 +1637,15 @@ MGL_EXPORT
* `MGLCameraStyleFunction` with an interpolation mode of:
* `MGLInterpolationModeExponential`
* `MGLInterpolationModeInterval`
+ * `MGLSourceStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLInterpolationModeCategorical`
+ * `MGLInterpolationModeIdentity`
+ * `MGLCompositeStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLInterpolationModeCategorical`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *textHaloWidth;
@@ -1548,6 +1665,15 @@ MGL_EXPORT
* `MGLCameraStyleFunction` with an interpolation mode of:
* `MGLInterpolationModeExponential`
* `MGLInterpolationModeInterval`
+ * `MGLSourceStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLInterpolationModeCategorical`
+ * `MGLInterpolationModeIdentity`
+ * `MGLCompositeStyleFunction` with an interpolation mode of:
+ * `MGLInterpolationModeExponential`
+ * `MGLInterpolationModeInterval`
+ * `MGLInterpolationModeCategorical`
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *textOpacity;
diff --git a/platform/darwin/src/MGLSymbolStyleLayer.mm b/platform/darwin/src/MGLSymbolStyleLayer.mm
index 0b065cd7b9..52648e7a05 100644
--- a/platform/darwin/src/MGLSymbolStyleLayer.mm
+++ b/platform/darwin/src/MGLSymbolStyleLayer.mm
@@ -890,7 +890,7 @@ namespace mbgl {
- (void)setIconColor:(MGLStyleValue<MGLColor *> *)iconColor {
MGLAssertStyleLayerIsValid();
- auto mbglValue = MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toInterpolatablePropertyValue(iconColor);
+ auto mbglValue = MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toDataDrivenPropertyValue(iconColor);
self.rawLayer->setIconColor(mbglValue);
}
@@ -899,15 +899,15 @@ namespace mbgl {
auto propertyValue = self.rawLayer->getIconColor();
if (propertyValue.isUndefined()) {
- return MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toStyleValue(self.rawLayer->getDefaultIconColor());
+ return MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toDataDrivenStyleValue(self.rawLayer->getDefaultIconColor());
}
- return MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toStyleValue(propertyValue);
+ return MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toDataDrivenStyleValue(propertyValue);
}
- (void)setIconHaloBlur:(MGLStyleValue<NSNumber *> *)iconHaloBlur {
MGLAssertStyleLayerIsValid();
- auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toInterpolatablePropertyValue(iconHaloBlur);
+ auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toDataDrivenPropertyValue(iconHaloBlur);
self.rawLayer->setIconHaloBlur(mbglValue);
}
@@ -916,15 +916,15 @@ namespace mbgl {
auto propertyValue = self.rawLayer->getIconHaloBlur();
if (propertyValue.isUndefined()) {
- return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(self.rawLayer->getDefaultIconHaloBlur());
+ return MGLStyleValueTransformer<float, NSNumber *>().toDataDrivenStyleValue(self.rawLayer->getDefaultIconHaloBlur());
}
- return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
+ return MGLStyleValueTransformer<float, NSNumber *>().toDataDrivenStyleValue(propertyValue);
}
- (void)setIconHaloColor:(MGLStyleValue<MGLColor *> *)iconHaloColor {
MGLAssertStyleLayerIsValid();
- auto mbglValue = MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toInterpolatablePropertyValue(iconHaloColor);
+ auto mbglValue = MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toDataDrivenPropertyValue(iconHaloColor);
self.rawLayer->setIconHaloColor(mbglValue);
}
@@ -933,15 +933,15 @@ namespace mbgl {
auto propertyValue = self.rawLayer->getIconHaloColor();
if (propertyValue.isUndefined()) {
- return MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toStyleValue(self.rawLayer->getDefaultIconHaloColor());
+ return MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toDataDrivenStyleValue(self.rawLayer->getDefaultIconHaloColor());
}
- return MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toStyleValue(propertyValue);
+ return MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toDataDrivenStyleValue(propertyValue);
}
- (void)setIconHaloWidth:(MGLStyleValue<NSNumber *> *)iconHaloWidth {
MGLAssertStyleLayerIsValid();
- auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toInterpolatablePropertyValue(iconHaloWidth);
+ auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toDataDrivenPropertyValue(iconHaloWidth);
self.rawLayer->setIconHaloWidth(mbglValue);
}
@@ -950,15 +950,15 @@ namespace mbgl {
auto propertyValue = self.rawLayer->getIconHaloWidth();
if (propertyValue.isUndefined()) {
- return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(self.rawLayer->getDefaultIconHaloWidth());
+ return MGLStyleValueTransformer<float, NSNumber *>().toDataDrivenStyleValue(self.rawLayer->getDefaultIconHaloWidth());
}
- return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
+ return MGLStyleValueTransformer<float, NSNumber *>().toDataDrivenStyleValue(propertyValue);
}
- (void)setIconOpacity:(MGLStyleValue<NSNumber *> *)iconOpacity {
MGLAssertStyleLayerIsValid();
- auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toInterpolatablePropertyValue(iconOpacity);
+ auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toDataDrivenPropertyValue(iconOpacity);
self.rawLayer->setIconOpacity(mbglValue);
}
@@ -967,9 +967,9 @@ namespace mbgl {
auto propertyValue = self.rawLayer->getIconOpacity();
if (propertyValue.isUndefined()) {
- return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(self.rawLayer->getDefaultIconOpacity());
+ return MGLStyleValueTransformer<float, NSNumber *>().toDataDrivenStyleValue(self.rawLayer->getDefaultIconOpacity());
}
- return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
+ return MGLStyleValueTransformer<float, NSNumber *>().toDataDrivenStyleValue(propertyValue);
}
- (void)setIconTranslation:(MGLStyleValue<NSValue *> *)iconTranslation {
@@ -1023,7 +1023,7 @@ namespace mbgl {
- (void)setTextColor:(MGLStyleValue<MGLColor *> *)textColor {
MGLAssertStyleLayerIsValid();
- auto mbglValue = MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toInterpolatablePropertyValue(textColor);
+ auto mbglValue = MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toDataDrivenPropertyValue(textColor);
self.rawLayer->setTextColor(mbglValue);
}
@@ -1032,15 +1032,15 @@ namespace mbgl {
auto propertyValue = self.rawLayer->getTextColor();
if (propertyValue.isUndefined()) {
- return MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toStyleValue(self.rawLayer->getDefaultTextColor());
+ return MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toDataDrivenStyleValue(self.rawLayer->getDefaultTextColor());
}
- return MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toStyleValue(propertyValue);
+ return MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toDataDrivenStyleValue(propertyValue);
}
- (void)setTextHaloBlur:(MGLStyleValue<NSNumber *> *)textHaloBlur {
MGLAssertStyleLayerIsValid();
- auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toInterpolatablePropertyValue(textHaloBlur);
+ auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toDataDrivenPropertyValue(textHaloBlur);
self.rawLayer->setTextHaloBlur(mbglValue);
}
@@ -1049,15 +1049,15 @@ namespace mbgl {
auto propertyValue = self.rawLayer->getTextHaloBlur();
if (propertyValue.isUndefined()) {
- return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(self.rawLayer->getDefaultTextHaloBlur());
+ return MGLStyleValueTransformer<float, NSNumber *>().toDataDrivenStyleValue(self.rawLayer->getDefaultTextHaloBlur());
}
- return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
+ return MGLStyleValueTransformer<float, NSNumber *>().toDataDrivenStyleValue(propertyValue);
}
- (void)setTextHaloColor:(MGLStyleValue<MGLColor *> *)textHaloColor {
MGLAssertStyleLayerIsValid();
- auto mbglValue = MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toInterpolatablePropertyValue(textHaloColor);
+ auto mbglValue = MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toDataDrivenPropertyValue(textHaloColor);
self.rawLayer->setTextHaloColor(mbglValue);
}
@@ -1066,15 +1066,15 @@ namespace mbgl {
auto propertyValue = self.rawLayer->getTextHaloColor();
if (propertyValue.isUndefined()) {
- return MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toStyleValue(self.rawLayer->getDefaultTextHaloColor());
+ return MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toDataDrivenStyleValue(self.rawLayer->getDefaultTextHaloColor());
}
- return MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toStyleValue(propertyValue);
+ return MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toDataDrivenStyleValue(propertyValue);
}
- (void)setTextHaloWidth:(MGLStyleValue<NSNumber *> *)textHaloWidth {
MGLAssertStyleLayerIsValid();
- auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toInterpolatablePropertyValue(textHaloWidth);
+ auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toDataDrivenPropertyValue(textHaloWidth);
self.rawLayer->setTextHaloWidth(mbglValue);
}
@@ -1083,15 +1083,15 @@ namespace mbgl {
auto propertyValue = self.rawLayer->getTextHaloWidth();
if (propertyValue.isUndefined()) {
- return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(self.rawLayer->getDefaultTextHaloWidth());
+ return MGLStyleValueTransformer<float, NSNumber *>().toDataDrivenStyleValue(self.rawLayer->getDefaultTextHaloWidth());
}
- return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
+ return MGLStyleValueTransformer<float, NSNumber *>().toDataDrivenStyleValue(propertyValue);
}
- (void)setTextOpacity:(MGLStyleValue<NSNumber *> *)textOpacity {
MGLAssertStyleLayerIsValid();
- auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toInterpolatablePropertyValue(textOpacity);
+ auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toDataDrivenPropertyValue(textOpacity);
self.rawLayer->setTextOpacity(mbglValue);
}
@@ -1100,9 +1100,9 @@ namespace mbgl {
auto propertyValue = self.rawLayer->getTextOpacity();
if (propertyValue.isUndefined()) {
- return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(self.rawLayer->getDefaultTextOpacity());
+ return MGLStyleValueTransformer<float, NSNumber *>().toDataDrivenStyleValue(self.rawLayer->getDefaultTextOpacity());
}
- return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
+ return MGLStyleValueTransformer<float, NSNumber *>().toDataDrivenStyleValue(propertyValue);
}
- (void)setTextTranslation:(MGLStyleValue<NSValue *> *)textTranslation {
diff --git a/platform/darwin/test/MGLSymbolStyleLayerTests.mm b/platform/darwin/test/MGLSymbolStyleLayerTests.mm
index ce4aa11cee..1d599f5aca 100644
--- a/platform/darwin/test/MGLSymbolStyleLayerTests.mm
+++ b/platform/darwin/test/MGLSymbolStyleLayerTests.mm
@@ -1421,7 +1421,7 @@
MGLStyleValue<MGLColor *> *constantStyleValue = [MGLStyleValue<MGLColor *> valueWithRawValue:[MGLColor redColor]];
layer.iconColor = constantStyleValue;
- mbgl::style::PropertyValue<mbgl::Color> propertyValue = { { 1, 0, 0, 1 } };
+ mbgl::style::DataDrivenPropertyValue<mbgl::Color> propertyValue = { { 1, 0, 0, 1 } };
XCTAssertEqual(rawLayer->getIconColor(), propertyValue,
@"Setting iconColor to a constant value should update icon-color.");
XCTAssertEqualObjects(layer.iconColor, constantStyleValue,
@@ -1438,6 +1438,29 @@
XCTAssertEqualObjects(layer.iconColor, functionStyleValue,
@"iconColor should round-trip camera functions.");
+ functionStyleValue = [MGLStyleValue<MGLColor *> valueWithInterpolationMode:MGLInterpolationModeExponential sourceStops:@{@18: constantStyleValue} attributeName:@"keyName" options:nil];
+ layer.iconColor = functionStyleValue;
+
+ mbgl::style::ExponentialStops<mbgl::Color> exponentialStops = { {{18, { 1, 0, 0, 1 }}}, 1.0 };
+ propertyValue = mbgl::style::SourceFunction<mbgl::Color> { "keyName", exponentialStops };
+
+ XCTAssertEqual(rawLayer->getIconColor(), propertyValue,
+ @"Setting iconColor to a source function should update icon-color.");
+ XCTAssertEqualObjects(layer.iconColor, functionStyleValue,
+ @"iconColor should round-trip source functions.");
+
+ functionStyleValue = [MGLStyleValue<MGLColor *> valueWithInterpolationMode:MGLInterpolationModeExponential compositeStops:@{@10: @{@18: constantStyleValue}} attributeName:@"keyName" options:nil];
+ layer.iconColor = functionStyleValue;
+
+ std::map<float, mbgl::Color> innerStops { {18, { 1, 0, 0, 1 }} };
+ mbgl::style::CompositeExponentialStops<mbgl::Color> compositeStops { { {10.0, innerStops} }, 1.0 };
+
+ propertyValue = mbgl::style::CompositeFunction<mbgl::Color> { "keyName", compositeStops };
+
+ XCTAssertEqual(rawLayer->getIconColor(), propertyValue,
+ @"Setting iconColor to a composite function should update icon-color.");
+ XCTAssertEqualObjects(layer.iconColor, functionStyleValue,
+ @"iconColor should round-trip composite functions.");
layer.iconColor = nil;
@@ -1445,11 +1468,6 @@
@"Unsetting iconColor should return icon-color to the default value.");
XCTAssertEqualObjects(layer.iconColor, defaultStyleValue,
@"iconColor should return the default value after being unset.");
-
- functionStyleValue = [MGLStyleValue<MGLColor *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.iconColor = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
- functionStyleValue = [MGLStyleValue<MGLColor *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.iconColor = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
}
// icon-halo-blur
@@ -1460,7 +1478,7 @@
MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
layer.iconHaloBlur = constantStyleValue;
- mbgl::style::PropertyValue<float> propertyValue = { 0xff };
+ mbgl::style::DataDrivenPropertyValue<float> propertyValue = { 0xff };
XCTAssertEqual(rawLayer->getIconHaloBlur(), propertyValue,
@"Setting iconHaloBlur to a constant value should update icon-halo-blur.");
XCTAssertEqualObjects(layer.iconHaloBlur, constantStyleValue,
@@ -1477,6 +1495,29 @@
XCTAssertEqualObjects(layer.iconHaloBlur, functionStyleValue,
@"iconHaloBlur should round-trip camera functions.");
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential sourceStops:@{@18: constantStyleValue} attributeName:@"keyName" options:nil];
+ layer.iconHaloBlur = functionStyleValue;
+
+ mbgl::style::ExponentialStops<float> exponentialStops = { {{18, 0xff}}, 1.0 };
+ propertyValue = mbgl::style::SourceFunction<float> { "keyName", exponentialStops };
+
+ XCTAssertEqual(rawLayer->getIconHaloBlur(), propertyValue,
+ @"Setting iconHaloBlur to a source function should update icon-halo-blur.");
+ XCTAssertEqualObjects(layer.iconHaloBlur, functionStyleValue,
+ @"iconHaloBlur should round-trip source functions.");
+
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential compositeStops:@{@10: @{@18: constantStyleValue}} attributeName:@"keyName" options:nil];
+ layer.iconHaloBlur = functionStyleValue;
+
+ std::map<float, float> innerStops { {18, 0xff} };
+ mbgl::style::CompositeExponentialStops<float> compositeStops { { {10.0, innerStops} }, 1.0 };
+
+ propertyValue = mbgl::style::CompositeFunction<float> { "keyName", compositeStops };
+
+ XCTAssertEqual(rawLayer->getIconHaloBlur(), propertyValue,
+ @"Setting iconHaloBlur to a composite function should update icon-halo-blur.");
+ XCTAssertEqualObjects(layer.iconHaloBlur, functionStyleValue,
+ @"iconHaloBlur should round-trip composite functions.");
layer.iconHaloBlur = nil;
@@ -1484,11 +1525,6 @@
@"Unsetting iconHaloBlur should return icon-halo-blur to the default value.");
XCTAssertEqualObjects(layer.iconHaloBlur, defaultStyleValue,
@"iconHaloBlur should return the default value after being unset.");
-
- functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.iconHaloBlur = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
- functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.iconHaloBlur = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
}
// icon-halo-color
@@ -1499,7 +1535,7 @@
MGLStyleValue<MGLColor *> *constantStyleValue = [MGLStyleValue<MGLColor *> valueWithRawValue:[MGLColor redColor]];
layer.iconHaloColor = constantStyleValue;
- mbgl::style::PropertyValue<mbgl::Color> propertyValue = { { 1, 0, 0, 1 } };
+ mbgl::style::DataDrivenPropertyValue<mbgl::Color> propertyValue = { { 1, 0, 0, 1 } };
XCTAssertEqual(rawLayer->getIconHaloColor(), propertyValue,
@"Setting iconHaloColor to a constant value should update icon-halo-color.");
XCTAssertEqualObjects(layer.iconHaloColor, constantStyleValue,
@@ -1516,6 +1552,29 @@
XCTAssertEqualObjects(layer.iconHaloColor, functionStyleValue,
@"iconHaloColor should round-trip camera functions.");
+ functionStyleValue = [MGLStyleValue<MGLColor *> valueWithInterpolationMode:MGLInterpolationModeExponential sourceStops:@{@18: constantStyleValue} attributeName:@"keyName" options:nil];
+ layer.iconHaloColor = functionStyleValue;
+
+ mbgl::style::ExponentialStops<mbgl::Color> exponentialStops = { {{18, { 1, 0, 0, 1 }}}, 1.0 };
+ propertyValue = mbgl::style::SourceFunction<mbgl::Color> { "keyName", exponentialStops };
+
+ XCTAssertEqual(rawLayer->getIconHaloColor(), propertyValue,
+ @"Setting iconHaloColor to a source function should update icon-halo-color.");
+ XCTAssertEqualObjects(layer.iconHaloColor, functionStyleValue,
+ @"iconHaloColor should round-trip source functions.");
+
+ functionStyleValue = [MGLStyleValue<MGLColor *> valueWithInterpolationMode:MGLInterpolationModeExponential compositeStops:@{@10: @{@18: constantStyleValue}} attributeName:@"keyName" options:nil];
+ layer.iconHaloColor = functionStyleValue;
+
+ std::map<float, mbgl::Color> innerStops { {18, { 1, 0, 0, 1 }} };
+ mbgl::style::CompositeExponentialStops<mbgl::Color> compositeStops { { {10.0, innerStops} }, 1.0 };
+
+ propertyValue = mbgl::style::CompositeFunction<mbgl::Color> { "keyName", compositeStops };
+
+ XCTAssertEqual(rawLayer->getIconHaloColor(), propertyValue,
+ @"Setting iconHaloColor to a composite function should update icon-halo-color.");
+ XCTAssertEqualObjects(layer.iconHaloColor, functionStyleValue,
+ @"iconHaloColor should round-trip composite functions.");
layer.iconHaloColor = nil;
@@ -1523,11 +1582,6 @@
@"Unsetting iconHaloColor should return icon-halo-color to the default value.");
XCTAssertEqualObjects(layer.iconHaloColor, defaultStyleValue,
@"iconHaloColor should return the default value after being unset.");
-
- functionStyleValue = [MGLStyleValue<MGLColor *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.iconHaloColor = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
- functionStyleValue = [MGLStyleValue<MGLColor *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.iconHaloColor = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
}
// icon-halo-width
@@ -1538,7 +1592,7 @@
MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
layer.iconHaloWidth = constantStyleValue;
- mbgl::style::PropertyValue<float> propertyValue = { 0xff };
+ mbgl::style::DataDrivenPropertyValue<float> propertyValue = { 0xff };
XCTAssertEqual(rawLayer->getIconHaloWidth(), propertyValue,
@"Setting iconHaloWidth to a constant value should update icon-halo-width.");
XCTAssertEqualObjects(layer.iconHaloWidth, constantStyleValue,
@@ -1555,6 +1609,29 @@
XCTAssertEqualObjects(layer.iconHaloWidth, functionStyleValue,
@"iconHaloWidth should round-trip camera functions.");
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential sourceStops:@{@18: constantStyleValue} attributeName:@"keyName" options:nil];
+ layer.iconHaloWidth = functionStyleValue;
+
+ mbgl::style::ExponentialStops<float> exponentialStops = { {{18, 0xff}}, 1.0 };
+ propertyValue = mbgl::style::SourceFunction<float> { "keyName", exponentialStops };
+
+ XCTAssertEqual(rawLayer->getIconHaloWidth(), propertyValue,
+ @"Setting iconHaloWidth to a source function should update icon-halo-width.");
+ XCTAssertEqualObjects(layer.iconHaloWidth, functionStyleValue,
+ @"iconHaloWidth should round-trip source functions.");
+
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential compositeStops:@{@10: @{@18: constantStyleValue}} attributeName:@"keyName" options:nil];
+ layer.iconHaloWidth = functionStyleValue;
+
+ std::map<float, float> innerStops { {18, 0xff} };
+ mbgl::style::CompositeExponentialStops<float> compositeStops { { {10.0, innerStops} }, 1.0 };
+
+ propertyValue = mbgl::style::CompositeFunction<float> { "keyName", compositeStops };
+
+ XCTAssertEqual(rawLayer->getIconHaloWidth(), propertyValue,
+ @"Setting iconHaloWidth to a composite function should update icon-halo-width.");
+ XCTAssertEqualObjects(layer.iconHaloWidth, functionStyleValue,
+ @"iconHaloWidth should round-trip composite functions.");
layer.iconHaloWidth = nil;
@@ -1562,11 +1639,6 @@
@"Unsetting iconHaloWidth should return icon-halo-width to the default value.");
XCTAssertEqualObjects(layer.iconHaloWidth, defaultStyleValue,
@"iconHaloWidth should return the default value after being unset.");
-
- functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.iconHaloWidth = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
- functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.iconHaloWidth = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
}
// icon-opacity
@@ -1577,7 +1649,7 @@
MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
layer.iconOpacity = constantStyleValue;
- mbgl::style::PropertyValue<float> propertyValue = { 0xff };
+ mbgl::style::DataDrivenPropertyValue<float> propertyValue = { 0xff };
XCTAssertEqual(rawLayer->getIconOpacity(), propertyValue,
@"Setting iconOpacity to a constant value should update icon-opacity.");
XCTAssertEqualObjects(layer.iconOpacity, constantStyleValue,
@@ -1594,6 +1666,29 @@
XCTAssertEqualObjects(layer.iconOpacity, functionStyleValue,
@"iconOpacity should round-trip camera functions.");
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential sourceStops:@{@18: constantStyleValue} attributeName:@"keyName" options:nil];
+ layer.iconOpacity = functionStyleValue;
+
+ mbgl::style::ExponentialStops<float> exponentialStops = { {{18, 0xff}}, 1.0 };
+ propertyValue = mbgl::style::SourceFunction<float> { "keyName", exponentialStops };
+
+ XCTAssertEqual(rawLayer->getIconOpacity(), propertyValue,
+ @"Setting iconOpacity to a source function should update icon-opacity.");
+ XCTAssertEqualObjects(layer.iconOpacity, functionStyleValue,
+ @"iconOpacity should round-trip source functions.");
+
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential compositeStops:@{@10: @{@18: constantStyleValue}} attributeName:@"keyName" options:nil];
+ layer.iconOpacity = functionStyleValue;
+
+ std::map<float, float> innerStops { {18, 0xff} };
+ mbgl::style::CompositeExponentialStops<float> compositeStops { { {10.0, innerStops} }, 1.0 };
+
+ propertyValue = mbgl::style::CompositeFunction<float> { "keyName", compositeStops };
+
+ XCTAssertEqual(rawLayer->getIconOpacity(), propertyValue,
+ @"Setting iconOpacity to a composite function should update icon-opacity.");
+ XCTAssertEqualObjects(layer.iconOpacity, functionStyleValue,
+ @"iconOpacity should round-trip composite functions.");
layer.iconOpacity = nil;
@@ -1601,11 +1696,6 @@
@"Unsetting iconOpacity should return icon-opacity to the default value.");
XCTAssertEqualObjects(layer.iconOpacity, defaultStyleValue,
@"iconOpacity should return the default value after being unset.");
-
- functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.iconOpacity = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
- functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.iconOpacity = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
}
// icon-translate
@@ -1700,7 +1790,7 @@
MGLStyleValue<MGLColor *> *constantStyleValue = [MGLStyleValue<MGLColor *> valueWithRawValue:[MGLColor redColor]];
layer.textColor = constantStyleValue;
- mbgl::style::PropertyValue<mbgl::Color> propertyValue = { { 1, 0, 0, 1 } };
+ mbgl::style::DataDrivenPropertyValue<mbgl::Color> propertyValue = { { 1, 0, 0, 1 } };
XCTAssertEqual(rawLayer->getTextColor(), propertyValue,
@"Setting textColor to a constant value should update text-color.");
XCTAssertEqualObjects(layer.textColor, constantStyleValue,
@@ -1717,6 +1807,29 @@
XCTAssertEqualObjects(layer.textColor, functionStyleValue,
@"textColor should round-trip camera functions.");
+ functionStyleValue = [MGLStyleValue<MGLColor *> valueWithInterpolationMode:MGLInterpolationModeExponential sourceStops:@{@18: constantStyleValue} attributeName:@"keyName" options:nil];
+ layer.textColor = functionStyleValue;
+
+ mbgl::style::ExponentialStops<mbgl::Color> exponentialStops = { {{18, { 1, 0, 0, 1 }}}, 1.0 };
+ propertyValue = mbgl::style::SourceFunction<mbgl::Color> { "keyName", exponentialStops };
+
+ XCTAssertEqual(rawLayer->getTextColor(), propertyValue,
+ @"Setting textColor to a source function should update text-color.");
+ XCTAssertEqualObjects(layer.textColor, functionStyleValue,
+ @"textColor should round-trip source functions.");
+
+ functionStyleValue = [MGLStyleValue<MGLColor *> valueWithInterpolationMode:MGLInterpolationModeExponential compositeStops:@{@10: @{@18: constantStyleValue}} attributeName:@"keyName" options:nil];
+ layer.textColor = functionStyleValue;
+
+ std::map<float, mbgl::Color> innerStops { {18, { 1, 0, 0, 1 }} };
+ mbgl::style::CompositeExponentialStops<mbgl::Color> compositeStops { { {10.0, innerStops} }, 1.0 };
+
+ propertyValue = mbgl::style::CompositeFunction<mbgl::Color> { "keyName", compositeStops };
+
+ XCTAssertEqual(rawLayer->getTextColor(), propertyValue,
+ @"Setting textColor to a composite function should update text-color.");
+ XCTAssertEqualObjects(layer.textColor, functionStyleValue,
+ @"textColor should round-trip composite functions.");
layer.textColor = nil;
@@ -1724,11 +1837,6 @@
@"Unsetting textColor should return text-color to the default value.");
XCTAssertEqualObjects(layer.textColor, defaultStyleValue,
@"textColor should return the default value after being unset.");
-
- functionStyleValue = [MGLStyleValue<MGLColor *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.textColor = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
- functionStyleValue = [MGLStyleValue<MGLColor *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.textColor = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
}
// text-halo-blur
@@ -1739,7 +1847,7 @@
MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
layer.textHaloBlur = constantStyleValue;
- mbgl::style::PropertyValue<float> propertyValue = { 0xff };
+ mbgl::style::DataDrivenPropertyValue<float> propertyValue = { 0xff };
XCTAssertEqual(rawLayer->getTextHaloBlur(), propertyValue,
@"Setting textHaloBlur to a constant value should update text-halo-blur.");
XCTAssertEqualObjects(layer.textHaloBlur, constantStyleValue,
@@ -1756,6 +1864,29 @@
XCTAssertEqualObjects(layer.textHaloBlur, functionStyleValue,
@"textHaloBlur should round-trip camera functions.");
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential sourceStops:@{@18: constantStyleValue} attributeName:@"keyName" options:nil];
+ layer.textHaloBlur = functionStyleValue;
+
+ mbgl::style::ExponentialStops<float> exponentialStops = { {{18, 0xff}}, 1.0 };
+ propertyValue = mbgl::style::SourceFunction<float> { "keyName", exponentialStops };
+
+ XCTAssertEqual(rawLayer->getTextHaloBlur(), propertyValue,
+ @"Setting textHaloBlur to a source function should update text-halo-blur.");
+ XCTAssertEqualObjects(layer.textHaloBlur, functionStyleValue,
+ @"textHaloBlur should round-trip source functions.");
+
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential compositeStops:@{@10: @{@18: constantStyleValue}} attributeName:@"keyName" options:nil];
+ layer.textHaloBlur = functionStyleValue;
+
+ std::map<float, float> innerStops { {18, 0xff} };
+ mbgl::style::CompositeExponentialStops<float> compositeStops { { {10.0, innerStops} }, 1.0 };
+
+ propertyValue = mbgl::style::CompositeFunction<float> { "keyName", compositeStops };
+
+ XCTAssertEqual(rawLayer->getTextHaloBlur(), propertyValue,
+ @"Setting textHaloBlur to a composite function should update text-halo-blur.");
+ XCTAssertEqualObjects(layer.textHaloBlur, functionStyleValue,
+ @"textHaloBlur should round-trip composite functions.");
layer.textHaloBlur = nil;
@@ -1763,11 +1894,6 @@
@"Unsetting textHaloBlur should return text-halo-blur to the default value.");
XCTAssertEqualObjects(layer.textHaloBlur, defaultStyleValue,
@"textHaloBlur should return the default value after being unset.");
-
- functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.textHaloBlur = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
- functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.textHaloBlur = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
}
// text-halo-color
@@ -1778,7 +1904,7 @@
MGLStyleValue<MGLColor *> *constantStyleValue = [MGLStyleValue<MGLColor *> valueWithRawValue:[MGLColor redColor]];
layer.textHaloColor = constantStyleValue;
- mbgl::style::PropertyValue<mbgl::Color> propertyValue = { { 1, 0, 0, 1 } };
+ mbgl::style::DataDrivenPropertyValue<mbgl::Color> propertyValue = { { 1, 0, 0, 1 } };
XCTAssertEqual(rawLayer->getTextHaloColor(), propertyValue,
@"Setting textHaloColor to a constant value should update text-halo-color.");
XCTAssertEqualObjects(layer.textHaloColor, constantStyleValue,
@@ -1795,6 +1921,29 @@
XCTAssertEqualObjects(layer.textHaloColor, functionStyleValue,
@"textHaloColor should round-trip camera functions.");
+ functionStyleValue = [MGLStyleValue<MGLColor *> valueWithInterpolationMode:MGLInterpolationModeExponential sourceStops:@{@18: constantStyleValue} attributeName:@"keyName" options:nil];
+ layer.textHaloColor = functionStyleValue;
+
+ mbgl::style::ExponentialStops<mbgl::Color> exponentialStops = { {{18, { 1, 0, 0, 1 }}}, 1.0 };
+ propertyValue = mbgl::style::SourceFunction<mbgl::Color> { "keyName", exponentialStops };
+
+ XCTAssertEqual(rawLayer->getTextHaloColor(), propertyValue,
+ @"Setting textHaloColor to a source function should update text-halo-color.");
+ XCTAssertEqualObjects(layer.textHaloColor, functionStyleValue,
+ @"textHaloColor should round-trip source functions.");
+
+ functionStyleValue = [MGLStyleValue<MGLColor *> valueWithInterpolationMode:MGLInterpolationModeExponential compositeStops:@{@10: @{@18: constantStyleValue}} attributeName:@"keyName" options:nil];
+ layer.textHaloColor = functionStyleValue;
+
+ std::map<float, mbgl::Color> innerStops { {18, { 1, 0, 0, 1 }} };
+ mbgl::style::CompositeExponentialStops<mbgl::Color> compositeStops { { {10.0, innerStops} }, 1.0 };
+
+ propertyValue = mbgl::style::CompositeFunction<mbgl::Color> { "keyName", compositeStops };
+
+ XCTAssertEqual(rawLayer->getTextHaloColor(), propertyValue,
+ @"Setting textHaloColor to a composite function should update text-halo-color.");
+ XCTAssertEqualObjects(layer.textHaloColor, functionStyleValue,
+ @"textHaloColor should round-trip composite functions.");
layer.textHaloColor = nil;
@@ -1802,11 +1951,6 @@
@"Unsetting textHaloColor should return text-halo-color to the default value.");
XCTAssertEqualObjects(layer.textHaloColor, defaultStyleValue,
@"textHaloColor should return the default value after being unset.");
-
- functionStyleValue = [MGLStyleValue<MGLColor *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.textHaloColor = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
- functionStyleValue = [MGLStyleValue<MGLColor *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.textHaloColor = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
}
// text-halo-width
@@ -1817,7 +1961,7 @@
MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
layer.textHaloWidth = constantStyleValue;
- mbgl::style::PropertyValue<float> propertyValue = { 0xff };
+ mbgl::style::DataDrivenPropertyValue<float> propertyValue = { 0xff };
XCTAssertEqual(rawLayer->getTextHaloWidth(), propertyValue,
@"Setting textHaloWidth to a constant value should update text-halo-width.");
XCTAssertEqualObjects(layer.textHaloWidth, constantStyleValue,
@@ -1834,6 +1978,29 @@
XCTAssertEqualObjects(layer.textHaloWidth, functionStyleValue,
@"textHaloWidth should round-trip camera functions.");
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential sourceStops:@{@18: constantStyleValue} attributeName:@"keyName" options:nil];
+ layer.textHaloWidth = functionStyleValue;
+
+ mbgl::style::ExponentialStops<float> exponentialStops = { {{18, 0xff}}, 1.0 };
+ propertyValue = mbgl::style::SourceFunction<float> { "keyName", exponentialStops };
+
+ XCTAssertEqual(rawLayer->getTextHaloWidth(), propertyValue,
+ @"Setting textHaloWidth to a source function should update text-halo-width.");
+ XCTAssertEqualObjects(layer.textHaloWidth, functionStyleValue,
+ @"textHaloWidth should round-trip source functions.");
+
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential compositeStops:@{@10: @{@18: constantStyleValue}} attributeName:@"keyName" options:nil];
+ layer.textHaloWidth = functionStyleValue;
+
+ std::map<float, float> innerStops { {18, 0xff} };
+ mbgl::style::CompositeExponentialStops<float> compositeStops { { {10.0, innerStops} }, 1.0 };
+
+ propertyValue = mbgl::style::CompositeFunction<float> { "keyName", compositeStops };
+
+ XCTAssertEqual(rawLayer->getTextHaloWidth(), propertyValue,
+ @"Setting textHaloWidth to a composite function should update text-halo-width.");
+ XCTAssertEqualObjects(layer.textHaloWidth, functionStyleValue,
+ @"textHaloWidth should round-trip composite functions.");
layer.textHaloWidth = nil;
@@ -1841,11 +2008,6 @@
@"Unsetting textHaloWidth should return text-halo-width to the default value.");
XCTAssertEqualObjects(layer.textHaloWidth, defaultStyleValue,
@"textHaloWidth should return the default value after being unset.");
-
- functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.textHaloWidth = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
- functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.textHaloWidth = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
}
// text-opacity
@@ -1856,7 +2018,7 @@
MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
layer.textOpacity = constantStyleValue;
- mbgl::style::PropertyValue<float> propertyValue = { 0xff };
+ mbgl::style::DataDrivenPropertyValue<float> propertyValue = { 0xff };
XCTAssertEqual(rawLayer->getTextOpacity(), propertyValue,
@"Setting textOpacity to a constant value should update text-opacity.");
XCTAssertEqualObjects(layer.textOpacity, constantStyleValue,
@@ -1873,6 +2035,29 @@
XCTAssertEqualObjects(layer.textOpacity, functionStyleValue,
@"textOpacity should round-trip camera functions.");
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential sourceStops:@{@18: constantStyleValue} attributeName:@"keyName" options:nil];
+ layer.textOpacity = functionStyleValue;
+
+ mbgl::style::ExponentialStops<float> exponentialStops = { {{18, 0xff}}, 1.0 };
+ propertyValue = mbgl::style::SourceFunction<float> { "keyName", exponentialStops };
+
+ XCTAssertEqual(rawLayer->getTextOpacity(), propertyValue,
+ @"Setting textOpacity to a source function should update text-opacity.");
+ XCTAssertEqualObjects(layer.textOpacity, functionStyleValue,
+ @"textOpacity should round-trip source functions.");
+
+ functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeExponential compositeStops:@{@10: @{@18: constantStyleValue}} attributeName:@"keyName" options:nil];
+ layer.textOpacity = functionStyleValue;
+
+ std::map<float, float> innerStops { {18, 0xff} };
+ mbgl::style::CompositeExponentialStops<float> compositeStops { { {10.0, innerStops} }, 1.0 };
+
+ propertyValue = mbgl::style::CompositeFunction<float> { "keyName", compositeStops };
+
+ XCTAssertEqual(rawLayer->getTextOpacity(), propertyValue,
+ @"Setting textOpacity to a composite function should update text-opacity.");
+ XCTAssertEqualObjects(layer.textOpacity, functionStyleValue,
+ @"textOpacity should round-trip composite functions.");
layer.textOpacity = nil;
@@ -1880,11 +2065,6 @@
@"Unsetting textOpacity should return text-opacity to the default value.");
XCTAssertEqualObjects(layer.textOpacity, defaultStyleValue,
@"textOpacity should return the default value after being unset.");
-
- functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.textOpacity = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
- functionStyleValue = [MGLStyleValue<NSNumber *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
- XCTAssertThrowsSpecificNamed(layer.textOpacity = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
}
// text-translate
diff --git a/scripts/generate-style-code.js b/scripts/generate-style-code.js
index bf9bef837a..9629c8fe45 100644
--- a/scripts/generate-style-code.js
+++ b/scripts/generate-style-code.js
@@ -47,7 +47,20 @@ global.evaluatedType = function (property) {
};
function attributeType(property, type) {
- const name = property.name.replace(type + '-', '').replace('-', '_');
+ const attributeNameExceptions = {
+ 'text-opacity': 'opacity',
+ 'icon-opacity': 'opacity',
+ 'text-color': 'fill_color',
+ 'icon-color': 'fill_color',
+ 'text-halo-color': 'halo_color',
+ 'icon-halo-color': 'halo_color',
+ 'text-halo-blur': 'halo_blur',
+ 'icon-halo-blur': 'halo_blur',
+ 'text-halo-width': 'halo_width',
+ 'icon-halo-width': 'halo_width'
+ }
+ const name = attributeNameExceptions[property.name] ||
+ property.name.replace(type + '-', '').replace(/-/g, '_');
return `attributes::a_${name}${name === 'offset' ? '<1>' : ''}`;
}
diff --git a/src/mbgl/layout/symbol_feature.hpp b/src/mbgl/layout/symbol_feature.hpp
index e55995f952..f4dc1680bc 100644
--- a/src/mbgl/layout/symbol_feature.hpp
+++ b/src/mbgl/layout/symbol_feature.hpp
@@ -8,14 +8,23 @@
namespace mbgl {
-class SymbolFeature {
+class SymbolFeature : public GeometryTileFeature {
public:
- FeatureType type;
+ SymbolFeature(std::unique_ptr<GeometryTileFeature> feature_) :
+ feature(std::move(feature_)),
+ geometry(feature->getGeometries()) // we need a mutable copy of the geometry for mergeLines()
+ {}
+
+ FeatureType getType() const override { return feature->getType(); }
+ optional<Value> getValue(const std::string& key) const override { return feature->getValue(key); };
+ std::unordered_map<std::string,Value> getProperties() const override { return feature->getProperties(); };
+ optional<FeatureIdentifier> getID() const override { return feature->getID(); };
+ GeometryCollection getGeometries() const override { return geometry; };
+
+ std::unique_ptr<GeometryTileFeature> feature;
GeometryCollection geometry;
optional<std::u16string> text;
optional<std::string> icon;
- std::array<float, 2> iconOffset;
- float iconRotation;
std::size_t index;
};
diff --git a/src/mbgl/layout/symbol_instance.cpp b/src/mbgl/layout/symbol_instance.cpp
index 4f425641e7..d81783b2f6 100644
--- a/src/mbgl/layout/symbol_instance.cpp
+++ b/src/mbgl/layout/symbol_instance.cpp
@@ -10,7 +10,7 @@ SymbolInstance::SymbolInstance(Anchor& anchor, const GeometryCoordinates& line,
const SymbolLayoutProperties::Evaluated& layout, const bool addToBuffers, const uint32_t index_,
const float textBoxScale, const float textPadding, const SymbolPlacementType textPlacement,
const float iconBoxScale, const float iconPadding, const SymbolPlacementType iconPlacement,
- const GlyphPositions& face, const IndexedSubfeature& indexedFeature) :
+ const GlyphPositions& face, const IndexedSubfeature& indexedFeature, const std::size_t featureIndex_) :
point(anchor.point),
index(index_),
hasText(shapedTextOrientations.first || shapedTextOrientations.second),
@@ -18,7 +18,8 @@ SymbolInstance::SymbolInstance(Anchor& anchor, const GeometryCoordinates& line,
// Create the collision features that will be used to check whether this symbol instance can be placed
textCollisionFeature(line, anchor, shapedTextOrientations.second ?: shapedTextOrientations.first, textBoxScale, textPadding, textPlacement, indexedFeature),
- iconCollisionFeature(line, anchor, shapedIcon, iconBoxScale, iconPadding, iconPlacement, indexedFeature) {
+ iconCollisionFeature(line, anchor, shapedIcon, iconBoxScale, iconPadding, iconPlacement, indexedFeature),
+ featureIndex(featureIndex_) {
// Create the quads used for rendering the icon and glyphs.
if (addToBuffers) {
diff --git a/src/mbgl/layout/symbol_instance.hpp b/src/mbgl/layout/symbol_instance.hpp
index 2dbb3bac23..532a4d30d8 100644
--- a/src/mbgl/layout/symbol_instance.hpp
+++ b/src/mbgl/layout/symbol_instance.hpp
@@ -17,7 +17,7 @@ public:
const style::SymbolLayoutProperties::Evaluated&, const bool inside, const uint32_t index,
const float textBoxScale, const float textPadding, style::SymbolPlacementType textPlacement,
const float iconBoxScale, const float iconPadding, style::SymbolPlacementType iconPlacement,
- const GlyphPositions& face, const IndexedSubfeature& indexedfeature);
+ const GlyphPositions& face, const IndexedSubfeature& indexedfeature, const std::size_t featureIndex);
Point<float> point;
uint32_t index;
@@ -28,6 +28,7 @@ public:
CollisionFeature textCollisionFeature;
CollisionFeature iconCollisionFeature;
WritingModeType writingModes;
+ std::size_t featureIndex;
};
} // namespace mbgl
diff --git a/src/mbgl/layout/symbol_layout.cpp b/src/mbgl/layout/symbol_layout.cpp
index cf9e784c26..3a2c082ad8 100644
--- a/src/mbgl/layout/symbol_layout.cpp
+++ b/src/mbgl/layout/symbol_layout.cpp
@@ -87,7 +87,10 @@ SymbolLayout::SymbolLayout(const BucketParameters& parameters,
}
for (const auto& layer : layers) {
- layerPaintProperties.emplace(layer->getID(), layer->as<SymbolLayer>()->impl->paint.evaluated);
+ layerPaintProperties.emplace(layer->getID(), std::make_pair(
+ layer->as<SymbolLayer>()->impl->iconPaintProperties(),
+ layer->as<SymbolLayer>()->impl->textPaintProperties()
+ ));
}
// Determine and load glyph ranges
@@ -96,12 +99,13 @@ SymbolLayout::SymbolLayout(const BucketParameters& parameters,
auto feature = sourceLayer.getFeature(i);
if (!leader.filter(feature->getType(), feature->getID(), [&] (const auto& key) { return feature->getValue(key); }))
continue;
+
+ SymbolFeature ft(std::move(feature));
- SymbolFeature ft;
ft.index = i;
- auto getValue = [&feature](const std::string& key) -> std::string {
- auto value = feature->getValue(key);
+ auto getValue = [&ft](const std::string& key) -> std::string {
+ auto value = ft.getValue(key);
if (!value)
return std::string();
if (value->is<std::string>())
@@ -118,12 +122,12 @@ SymbolLayout::SymbolLayout(const BucketParameters& parameters,
};
if (hasText) {
- std::string u8string = layout.evaluate<TextField>(zoom, *feature);
+ std::string u8string = layout.evaluate<TextField>(zoom, ft);
if (layout.get<TextField>().isConstant()) {
u8string = util::replaceTokens(u8string, getValue);
}
- auto textTransform = layout.evaluate<TextTransform>(zoom, *feature);
+ auto textTransform = layout.evaluate<TextTransform>(zoom, ft);
if (textTransform == TextTransformType::Uppercase) {
u8string = platform::uppercase(u8string);
@@ -144,13 +148,9 @@ SymbolLayout::SymbolLayout(const BucketParameters& parameters,
if (hasIcon) {
ft.icon = util::replaceTokens(layout.get<IconImage>(), getValue);
- ft.iconOffset = layout.evaluate<IconOffset>(zoom, *feature);
- ft.iconRotation = layout.evaluate<IconRotate>(zoom, *feature) * util::DEG2RAD;
}
if (ft.text || ft.icon) {
- ft.type = feature->getType();
- ft.geometry = feature->getGeometries();
features.push_back(std::move(ft));
}
}
@@ -229,7 +229,8 @@ void SymbolLayout::prepare(uintptr_t tileUID,
const bool textAlongLine = layout.get<TextRotationAlignment>() == AlignmentType::Map &&
layout.get<SymbolPlacement>() == SymbolPlacementType::Line;
- for (const auto& feature : features) {
+ for (auto it = features.begin(); it != features.end(); ++it) {
+ auto& feature = *it;
if (feature.geometry.empty()) continue;
std::pair<Shaping, Shaping> shapedTextOrientations;
@@ -273,7 +274,9 @@ void SymbolLayout::prepare(uintptr_t tileUID,
if (feature.icon) {
auto image = spriteAtlas.getIcon(*feature.icon);
if (image) {
- shapedIcon = shapeIcon(*image, feature);
+ shapedIcon = shapeIcon(*image,
+ layout.evaluate<IconOffset>(zoom, feature),
+ layout.evaluate<IconRotate>(zoom, feature) * util::DEG2RAD);
assert((*image).spriteImage);
if ((*image).spriteImage->sdf) {
sdfIcons = true;
@@ -288,15 +291,17 @@ void SymbolLayout::prepare(uintptr_t tileUID,
// if either shapedText or icon position is present, add the feature
if (shapedTextOrientations.first || shapedIcon) {
- addFeature(feature, shapedTextOrientations, shapedIcon, face);
+ addFeature(std::distance(features.begin(), it), feature, shapedTextOrientations, shapedIcon, face);
}
+
+ feature.geometry.clear();
}
- features.clear();
compareText.clear();
}
-void SymbolLayout::addFeature(const SymbolFeature& feature,
+void SymbolLayout::addFeature(const std::size_t index,
+ const SymbolFeature& feature,
const std::pair<Shaping, Shaping>& shapedTextOrientations,
const PositionedIcon& shapedIcon,
const GlyphPositions& face) {
@@ -345,8 +350,10 @@ void SymbolLayout::addFeature(const SymbolFeature& feature,
symbolInstances.emplace_back(anchor, line, shapedTextOrientations, shapedIcon, layout, addToBuffers, symbolInstances.size(),
textBoxScale, textPadding, textPlacement,
iconBoxScale, iconPadding, iconPlacement,
- face, indexedFeature);
+ face, indexedFeature, index);
};
+
+ const auto& type = feature.getType();
if (layout.get<SymbolPlacement>() == SymbolPlacementType::Line) {
auto clippedLines = util::clipLines(feature.geometry, 0, 0, util::EXTENT, util::EXTENT);
@@ -368,7 +375,7 @@ void SymbolLayout::addFeature(const SymbolFeature& feature,
}
}
}
- } else if (feature.type == FeatureType::Polygon) {
+ } else if (type == FeatureType::Polygon) {
for (const auto& polygon : classifyRings(feature.geometry)) {
Polygon<double> poly;
for (const auto& ring : polygon) {
@@ -384,12 +391,12 @@ void SymbolLayout::addFeature(const SymbolFeature& feature,
Anchor anchor(poi.x, poi.y, 0, minScale);
addSymbolInstance(polygon[0], anchor);
}
- } else if (feature.type == FeatureType::LineString) {
+ } else if (type == FeatureType::LineString) {
for (const auto& line : feature.geometry) {
Anchor anchor(line[0].x, line[0].y, 0, minScale);
addSymbolInstance(line, anchor);
}
- } else if (feature.type == FeatureType::Point) {
+ } else if (type == FeatureType::Point) {
for (const auto& points : feature.geometry) {
for (const auto& point : points) {
Anchor anchor(point.x, point.y, 0, minScale);
@@ -503,6 +510,12 @@ std::unique_ptr<SymbolBucket> SymbolLayout::place(CollisionTile& collisionTile)
keepUpright, iconPlacement, collisionTile.config.angle, symbolInstance.writingModes);
}
}
+
+ const auto& feature = features.at(symbolInstance.featureIndex);
+ for (auto& pair : bucket->paintPropertyBinders) {
+ pair.second.first.populateVertexVectors(feature, bucket->icon.vertices.vertexSize());
+ pair.second.second.populateVertexVectors(feature, bucket->text.vertices.vertexSize());
+ }
}
if (collisionTile.config.debug) {
diff --git a/src/mbgl/layout/symbol_layout.hpp b/src/mbgl/layout/symbol_layout.hpp
index dbfdad22d9..491d0078da 100644
--- a/src/mbgl/layout/symbol_layout.hpp
+++ b/src/mbgl/layout/symbol_layout.hpp
@@ -5,6 +5,7 @@
#include <mbgl/layout/symbol_feature.hpp>
#include <mbgl/layout/symbol_instance.hpp>
#include <mbgl/text/bidi.hpp>
+#include <mbgl/style/layers/symbol_layer_impl.hpp>
#include <memory>
#include <map>
@@ -51,10 +52,12 @@ public:
State state = Pending;
- std::unordered_map<std::string, style::SymbolPaintProperties::Evaluated> layerPaintProperties;
+ std::unordered_map<std::string,
+ std::pair<style::IconPaintProperties::Evaluated, style::TextPaintProperties::Evaluated>> layerPaintProperties;
private:
- void addFeature(const SymbolFeature&,
+ void addFeature(const size_t,
+ const SymbolFeature&,
const std::pair<Shaping, Shaping>& shapedTextOrientations,
const PositionedIcon& shapedIcon,
const GlyphPositions& face);
diff --git a/src/mbgl/programs/attributes.hpp b/src/mbgl/programs/attributes.hpp
index c4cc5dea8b..bb90f2c13c 100644
--- a/src/mbgl/programs/attributes.hpp
+++ b/src/mbgl/programs/attributes.hpp
@@ -64,6 +64,34 @@ struct a_color : gl::Attribute<gl::Normalized<uint8_t>, 4> {
}
};
+// used in the symbol sdf shader
+struct a_fill_color : gl::Attribute<gl::Normalized<uint8_t>, 4> {
+ static auto name() { return "a_fill_color"; }
+
+ static Value value(const Color& color) {
+ return {{
+ gl::Normalized<uint8_t>(color.r),
+ gl::Normalized<uint8_t>(color.g),
+ gl::Normalized<uint8_t>(color.b),
+ gl::Normalized<uint8_t>(color.a)
+ }};
+ }
+};
+
+// used in the symbol sdf shader
+struct a_halo_color : gl::Attribute<gl::Normalized<uint8_t>, 4> {
+ static auto name() { return "a_halo_color"; }
+
+ static Value value(const Color& color) {
+ return {{
+ gl::Normalized<uint8_t>(color.r),
+ gl::Normalized<uint8_t>(color.g),
+ gl::Normalized<uint8_t>(color.b),
+ gl::Normalized<uint8_t>(color.a)
+ }};
+ }
+};
+
struct a_stroke_color : gl::Attribute<gl::Normalized<uint8_t>, 4> {
static auto name() { return "a_stroke_color"; }
@@ -171,5 +199,23 @@ struct a_offset<1> : gl::Attribute<float, 1> {
}
};
+struct a_halo_width : gl::Attribute<float, 1> {
+ static auto name() { return "a_halo_width"; }
+
+ static Value value(float width) {
+ return {{ width }};
+ }
+};
+
+struct a_halo_blur : gl::Attribute<float, 1> {
+ static auto name() { return "a_halo_blur"; }
+
+ static Value value(float blur) {
+ return {{ blur }};
+ }
+};
+
+
+
} // namespace attributes
} // namespace mbgl
diff --git a/src/mbgl/programs/programs.hpp b/src/mbgl/programs/programs.hpp
index dd71c2ce97..742c5a221b 100644
--- a/src/mbgl/programs/programs.hpp
+++ b/src/mbgl/programs/programs.hpp
@@ -40,8 +40,8 @@ public:
LinePatternProgram linePattern;
RasterProgram raster;
SymbolIconProgram symbolIcon;
- SymbolSDFProgram symbolIconSDF;
- SymbolSDFProgram symbolGlyph;
+ SymbolSDFIconProgram symbolIconSDF;
+ SymbolSDFTextProgram symbolGlyph;
DebugProgram debug;
CollisionBoxProgram collisionBox;
diff --git a/src/mbgl/programs/symbol_program.cpp b/src/mbgl/programs/symbol_program.cpp
index 3f59000b94..19fe2bc2f6 100644
--- a/src/mbgl/programs/symbol_program.cpp
+++ b/src/mbgl/programs/symbol_program.cpp
@@ -2,6 +2,7 @@
#include <mbgl/renderer/render_tile.hpp>
#include <mbgl/map/transform_state.hpp>
#include <mbgl/style/layers/symbol_layer_impl.hpp>
+#include <mbgl/util/enum.hpp>
namespace mbgl {
@@ -19,6 +20,7 @@ Values makeValues(const style::SymbolPropertyValues& values,
std::array<float, 2> extrudeScale;
const float scale = values.paintSize / values.sdfScale;
+
if (values.pitchAlignment == AlignmentType::Map) {
extrudeScale.fill(tile.id.pixelsToTileUnits(1, state.getZoom()) * scale);
} else {
@@ -27,7 +29,7 @@ Values makeValues(const style::SymbolPropertyValues& values,
pixelsToGLUnits[1] * scale * state.getCameraToCenterDistance()
}};
}
-
+
// adjust min/max zooms for variable font sies
float zoomAdjust = std::log(values.paintSize / values.layoutSize) / std::log(2);
@@ -35,7 +37,6 @@ Values makeValues(const style::SymbolPropertyValues& values,
uniforms::u_matrix::Value{ tile.translatedMatrix(values.translate,
values.translateAnchor,
state) },
- uniforms::u_opacity::Value{ values.opacity },
uniforms::u_extrude_scale::Value{ extrudeScale },
uniforms::u_texsize::Value{ std::array<float, 2> {{ float(texsize.width) / 4, float(texsize.height) / 4 }} },
uniforms::u_zoom::Value{ float((state.getZoom() - zoomAdjust) * 10) },
@@ -62,84 +63,37 @@ SymbolIconProgram::uniformValues(const style::SymbolPropertyValues& values,
);
}
-static SymbolSDFProgram::UniformValues makeSDFValues(const style::SymbolPropertyValues& values,
- const Size& texsize,
- const std::array<float, 2>& pixelsToGLUnits,
- const RenderTile& tile,
- const TransformState& state,
- float pixelRatio,
- Color color,
- float buffer,
- float gammaAdjust)
-{
- // The default gamma value has to be adjust for the current pixelratio so that we're not
- // drawing blurry font on retina screens.
- const float gammaBase = 0.105 * values.sdfScale / values.paintSize / pixelRatio;
- const float gammaScale = (values.pitchAlignment == AlignmentType::Map
- ? 1.0 / std::cos(state.getPitch())
- : 1.0) / state.getCameraToCenterDistance();
-
- return makeValues<SymbolSDFProgram::UniformValues>(
- values,
- texsize,
- pixelsToGLUnits,
- tile,
- state,
- uniforms::u_color::Value{ color },
- uniforms::u_buffer::Value{ buffer },
- uniforms::u_gamma::Value{ (gammaBase + gammaAdjust) * gammaScale },
- uniforms::u_pitch::Value{ state.getPitch() },
- uniforms::u_bearing::Value{ -1.0f * state.getAngle() },
- uniforms::u_aspect_ratio::Value{ (state.getSize().width * 1.0f) / (state.getSize().height * 1.0f) },
- uniforms::u_pitch_with_map::Value{ values.pitchAlignment == AlignmentType::Map }
- );
-}
-
-SymbolSDFProgram::UniformValues
-SymbolSDFProgram::haloUniformValues(const style::SymbolPropertyValues& values,
+template <class PaintProperties>
+typename SymbolSDFProgram<PaintProperties>::UniformValues SymbolSDFProgram<PaintProperties>::uniformValues(const style::SymbolPropertyValues& values,
const Size& texsize,
const std::array<float, 2>& pixelsToGLUnits,
const RenderTile& tile,
const TransformState& state,
- float pixelRatio)
+ const SymbolSDFPart part)
{
const float scale = values.paintSize / values.sdfScale;
- const float sdfPx = 8.0f;
- const float blurOffset = 1.19f;
- const float haloOffset = 6.0f;
-
- return makeSDFValues(
+
+ const float gammaScale = scale * (values.pitchAlignment == AlignmentType::Map
+ ? std::cos(state.getPitch())
+ : 1.0) * state.getCameraToCenterDistance();
+
+ return makeValues<SymbolSDFProgram<PaintProperties>::UniformValues>(
values,
texsize,
pixelsToGLUnits,
tile,
state,
- pixelRatio,
- values.haloColor,
- (haloOffset - values.haloWidth / scale) / sdfPx,
- values.haloBlur * blurOffset / scale / sdfPx
+ uniforms::u_font_scale::Value{ scale },
+ uniforms::u_gamma_scale::Value{ gammaScale },
+ uniforms::u_pitch::Value{ state.getPitch() },
+ uniforms::u_bearing::Value{ -1.0f * state.getAngle() },
+ uniforms::u_aspect_ratio::Value{ (state.getSize().width * 1.0f) / (state.getSize().height * 1.0f) },
+ uniforms::u_pitch_with_map::Value{ values.pitchAlignment == AlignmentType::Map },
+ uniforms::u_is_halo::Value{ part == SymbolSDFPart::Halo }
);
}
-SymbolSDFProgram::UniformValues
-SymbolSDFProgram::foregroundUniformValues(const style::SymbolPropertyValues& values,
- const Size& texsize,
- const std::array<float, 2>& pixelsToGLUnits,
- const RenderTile& tile,
- const TransformState& state,
- float pixelRatio)
-{
- return makeSDFValues(
- values,
- texsize,
- pixelsToGLUnits,
- tile,
- state,
- pixelRatio,
- values.color,
- (256.0f - 64.0f) / 256.0f,
- 0
- );
-}
+template class SymbolSDFProgram<style::IconPaintProperties>;
+template class SymbolSDFProgram<style::TextPaintProperties>;
} // namespace mbgl
diff --git a/src/mbgl/programs/symbol_program.hpp b/src/mbgl/programs/symbol_program.hpp
index e0e90f0fa4..0537c25a2c 100644
--- a/src/mbgl/programs/symbol_program.hpp
+++ b/src/mbgl/programs/symbol_program.hpp
@@ -8,6 +8,7 @@
#include <mbgl/util/geometry.hpp>
#include <mbgl/util/size.hpp>
#include <mbgl/style/layers/symbol_layer_properties.hpp>
+#include <mbgl/style/layers/symbol_layer_impl.hpp>
#include <cmath>
#include <array>
@@ -27,9 +28,10 @@ MBGL_DEFINE_UNIFORM_SCALAR(bool, u_rotate_with_map);
MBGL_DEFINE_UNIFORM_SCALAR(bool, u_pitch_with_map);
MBGL_DEFINE_UNIFORM_SCALAR(gl::TextureUnit, u_texture);
MBGL_DEFINE_UNIFORM_SCALAR(gl::TextureUnit, u_fadetexture);
-MBGL_DEFINE_UNIFORM_SCALAR(float, u_buffer);
-MBGL_DEFINE_UNIFORM_SCALAR(float, u_gamma);
MBGL_DEFINE_UNIFORM_SCALAR(float, u_aspect_ratio);
+MBGL_DEFINE_UNIFORM_SCALAR(bool, u_is_halo);
+MBGL_DEFINE_UNIFORM_SCALAR(float, u_font_scale);
+MBGL_DEFINE_UNIFORM_SCALAR(float, u_gamma_scale);
} // namespace uniforms
struct SymbolLayoutAttributes : gl::Attributes<
@@ -75,14 +77,13 @@ class SymbolIconProgram : public Program<
SymbolLayoutAttributes,
gl::Uniforms<
uniforms::u_matrix,
- uniforms::u_opacity,
uniforms::u_extrude_scale,
uniforms::u_texsize,
uniforms::u_zoom,
uniforms::u_rotate_with_map,
uniforms::u_texture,
uniforms::u_fadetexture>,
- style::SymbolPaintProperties>
+ style::IconPaintProperties>
{
public:
using Program::Program;
@@ -94,47 +95,73 @@ public:
const TransformState&);
};
+enum class SymbolSDFPart {
+ Fill = 1,
+ Halo = 0
+};
+
+template <class PaintProperties>
class SymbolSDFProgram : public Program<
shaders::symbol_sdf,
gl::Triangle,
SymbolLayoutAttributes,
gl::Uniforms<
uniforms::u_matrix,
- uniforms::u_opacity,
uniforms::u_extrude_scale,
uniforms::u_texsize,
uniforms::u_zoom,
uniforms::u_rotate_with_map,
uniforms::u_texture,
uniforms::u_fadetexture,
- uniforms::u_color,
- uniforms::u_buffer,
- uniforms::u_gamma,
+ uniforms::u_font_scale,
+ uniforms::u_gamma_scale,
uniforms::u_pitch,
uniforms::u_bearing,
uniforms::u_aspect_ratio,
- uniforms::u_pitch_with_map>,
- style::SymbolPaintProperties>
+ uniforms::u_pitch_with_map,
+ uniforms::u_is_halo>,
+ PaintProperties>
{
public:
- using Program::Program;
+ using BaseProgram = Program<shaders::symbol_sdf,
+ gl::Triangle,
+ SymbolLayoutAttributes,
+ gl::Uniforms<
+ uniforms::u_matrix,
+ uniforms::u_extrude_scale,
+ uniforms::u_texsize,
+ uniforms::u_zoom,
+ uniforms::u_rotate_with_map,
+ uniforms::u_texture,
+ uniforms::u_fadetexture,
+ uniforms::u_font_scale,
+ uniforms::u_gamma_scale,
+ uniforms::u_pitch,
+ uniforms::u_bearing,
+ uniforms::u_aspect_ratio,
+ uniforms::u_pitch_with_map,
+ uniforms::u_is_halo>,
+ PaintProperties>;
+
+ using UniformValues = typename BaseProgram::UniformValues;
+
- static UniformValues haloUniformValues(const style::SymbolPropertyValues&,
- const Size& texsize,
- const std::array<float, 2>& pixelsToGLUnits,
- const RenderTile&,
- const TransformState&,
- float pixelRatio);
-
- static UniformValues foregroundUniformValues(const style::SymbolPropertyValues&,
- const Size& texsize,
- const std::array<float, 2>& pixelsToGLUnits,
- const RenderTile&,
- const TransformState&,
- float pixelRatio);
+
+ using BaseProgram::BaseProgram;
+
+ static UniformValues uniformValues(const style::SymbolPropertyValues&,
+ const Size& texsize,
+ const std::array<float, 2>& pixelsToGLUnits,
+ const RenderTile&,
+ const TransformState&,
+ const SymbolSDFPart);
};
+using SymbolSDFIconProgram = SymbolSDFProgram<style::IconPaintProperties>;
+using SymbolSDFTextProgram = SymbolSDFProgram<style::TextPaintProperties>;
+
using SymbolLayoutVertex = SymbolLayoutAttributes::Vertex;
-using SymbolAttributes = SymbolIconProgram::Attributes;
+using SymbolIconAttributes = SymbolIconProgram::Attributes;
+using SymbolTextAttributes = SymbolSDFTextProgram::Attributes;
} // namespace mbgl
diff --git a/src/mbgl/renderer/painter_symbol.cpp b/src/mbgl/renderer/painter_symbol.cpp
index 0113c15a08..48c2e7ff66 100644
--- a/src/mbgl/renderer/painter_symbol.cpp
+++ b/src/mbgl/renderer/painter_symbol.cpp
@@ -33,7 +33,9 @@ void Painter::renderSymbol(PaintParameters& parameters,
auto draw = [&] (auto& program,
auto&& uniformValues,
const auto& buffers,
- const SymbolPropertyValues& values_)
+ const SymbolPropertyValues& values_,
+ const auto& binders,
+ const auto& paintProperties)
{
// We clip symbols to their tile extent in still mode.
const bool needsClipping = frame.mapMode == MapMode::Still;
@@ -52,14 +54,15 @@ void Painter::renderSymbol(PaintParameters& parameters,
*buffers.vertexBuffer,
*buffers.indexBuffer,
buffers.segments,
- bucket.paintPropertyBinders.at(layer.getID()),
- layer.impl->paint.evaluated,
+ binders,
+ paintProperties,
state.getZoom()
);
};
if (bucket.hasIconData()) {
auto values = layer.impl->iconPropertyValues(layout);
+ auto paintPropertyValues = layer.impl->iconPaintProperties();
SpriteAtlas& atlas = *layer.impl->spriteAtlas;
const bool iconScaled = values.paintSize != 1.0f || frame.pixelRatio != atlas.getPixelRatio() || bucket.iconsNeedLinear;
@@ -69,24 +72,30 @@ void Painter::renderSymbol(PaintParameters& parameters,
const Size texsize = atlas.getSize();
if (bucket.sdfIcons) {
- if (values.hasHalo()) {
+ if (values.hasHalo) {
draw(parameters.programs.symbolIconSDF,
- SymbolSDFProgram::haloUniformValues(values, texsize, pixelsToGLUnits, tile, state, frame.pixelRatio),
+ SymbolSDFIconProgram::uniformValues(values, texsize, pixelsToGLUnits, tile, state, SymbolSDFPart::Halo),
bucket.icon,
- values);
+ values,
+ bucket.paintPropertyBinders.at(layer.getID()).first,
+ paintPropertyValues);
}
- if (values.hasForeground()) {
+ if (values.hasFill) {
draw(parameters.programs.symbolIconSDF,
- SymbolSDFProgram::foregroundUniformValues(values, texsize, pixelsToGLUnits, tile, state, frame.pixelRatio),
+ SymbolSDFIconProgram::uniformValues(values, texsize, pixelsToGLUnits, tile, state, SymbolSDFPart::Fill),
bucket.icon,
- values);
+ values,
+ bucket.paintPropertyBinders.at(layer.getID()).first,
+ paintPropertyValues);
}
} else {
draw(parameters.programs.symbolIcon,
SymbolIconProgram::uniformValues(values, texsize, pixelsToGLUnits, tile, state),
bucket.icon,
- values);
+ values,
+ bucket.paintPropertyBinders.at(layer.getID()).first,
+ paintPropertyValues);
}
}
@@ -94,21 +103,26 @@ void Painter::renderSymbol(PaintParameters& parameters,
glyphAtlas->bind(context, 0);
auto values = layer.impl->textPropertyValues(layout);
+ auto paintPropertyValues = layer.impl->textPaintProperties();
const Size texsize = glyphAtlas->getSize();
- if (values.hasHalo()) {
+ if (values.hasHalo) {
draw(parameters.programs.symbolGlyph,
- SymbolSDFProgram::haloUniformValues(values, texsize, pixelsToGLUnits, tile, state, frame.pixelRatio),
+ SymbolSDFTextProgram::uniformValues(values, texsize, pixelsToGLUnits, tile, state, SymbolSDFPart::Halo),
bucket.text,
- values);
+ values,
+ bucket.paintPropertyBinders.at(layer.getID()).second,
+ paintPropertyValues);
}
- if (values.hasForeground()) {
+ if (values.hasFill) {
draw(parameters.programs.symbolGlyph,
- SymbolSDFProgram::foregroundUniformValues(values, texsize, pixelsToGLUnits, tile, state, frame.pixelRatio),
+ SymbolSDFTextProgram::uniformValues(values, texsize, pixelsToGLUnits, tile, state, SymbolSDFPart::Fill),
bucket.text,
- values);
+ values,
+ bucket.paintPropertyBinders.at(layer.getID()).second,
+ paintPropertyValues);
}
}
diff --git a/src/mbgl/renderer/symbol_bucket.cpp b/src/mbgl/renderer/symbol_bucket.cpp
index 9d4bde9d07..fa4178dda1 100644
--- a/src/mbgl/renderer/symbol_bucket.cpp
+++ b/src/mbgl/renderer/symbol_bucket.cpp
@@ -9,7 +9,8 @@ namespace mbgl {
using namespace style;
SymbolBucket::SymbolBucket(style::SymbolLayoutProperties::Evaluated layout_,
- const std::unordered_map<std::string, style::SymbolPaintProperties::Evaluated>& layerPaintProperties,
+ const std::unordered_map<std::string, std::pair<
+ style::IconPaintProperties::Evaluated, style::TextPaintProperties::Evaluated>>& layerPaintProperties,
float zoom,
bool sdfIcons_,
bool iconsNeedLinear_)
@@ -17,8 +18,10 @@ SymbolBucket::SymbolBucket(style::SymbolLayoutProperties::Evaluated layout_,
sdfIcons(sdfIcons_),
iconsNeedLinear(iconsNeedLinear_) {
for (const auto& pair : layerPaintProperties) {
- paintPropertyBinders.emplace(pair.first,
- SymbolIconProgram::PaintPropertyBinders(pair.second, zoom));
+ paintPropertyBinders.emplace(pair.first, std::make_pair(
+ SymbolIconProgram::PaintPropertyBinders(pair.second.first, zoom),
+ SymbolSDFTextProgram::PaintPropertyBinders(pair.second.second, zoom)
+ ));
}
}
@@ -39,7 +42,8 @@ void SymbolBucket::upload(gl::Context& context) {
}
for (auto& pair : paintPropertyBinders) {
- pair.second.upload(context);
+ pair.second.first.upload(context);
+ pair.second.second.upload(context);
}
uploaded = true;
diff --git a/src/mbgl/renderer/symbol_bucket.hpp b/src/mbgl/renderer/symbol_bucket.hpp
index 0b40bb34ae..dcf3f5f495 100644
--- a/src/mbgl/renderer/symbol_bucket.hpp
+++ b/src/mbgl/renderer/symbol_bucket.hpp
@@ -17,7 +17,7 @@ namespace mbgl {
class SymbolBucket : public Bucket {
public:
SymbolBucket(style::SymbolLayoutProperties::Evaluated,
- const std::unordered_map<std::string, style::SymbolPaintProperties::Evaluated>&,
+ const std::unordered_map<std::string, std::pair<style::IconPaintProperties::Evaluated, style::TextPaintProperties::Evaluated>>&,
float zoom,
bool sdfIcons,
bool iconsNeedLinear);
@@ -33,12 +33,14 @@ public:
const bool sdfIcons;
const bool iconsNeedLinear;
- std::unordered_map<std::string, SymbolIconProgram::PaintPropertyBinders> paintPropertyBinders;
+ std::unordered_map<std::string, std::pair<
+ SymbolIconProgram::PaintPropertyBinders,
+ SymbolSDFTextProgram::PaintPropertyBinders>> paintPropertyBinders;
struct TextBuffer {
gl::VertexVector<SymbolLayoutVertex> vertices;
gl::IndexVector<gl::Triangles> triangles;
- gl::SegmentVector<SymbolAttributes> segments;
+ gl::SegmentVector<SymbolTextAttributes> segments;
optional<gl::VertexBuffer<SymbolLayoutVertex>> vertexBuffer;
optional<gl::IndexBuffer<gl::Triangles>> indexBuffer;
@@ -47,7 +49,7 @@ public:
struct IconBuffer {
gl::VertexVector<SymbolLayoutVertex> vertices;
gl::IndexVector<gl::Triangles> triangles;
- gl::SegmentVector<SymbolAttributes> segments;
+ gl::SegmentVector<SymbolIconAttributes> segments;
optional<gl::VertexBuffer<SymbolLayoutVertex>> vertexBuffer;
optional<gl::IndexBuffer<gl::Triangles>> indexBuffer;
diff --git a/src/mbgl/shaders/symbol_icon.cpp b/src/mbgl/shaders/symbol_icon.cpp
index eca9342d54..e6728e15de 100644
--- a/src/mbgl/shaders/symbol_icon.cpp
+++ b/src/mbgl/shaders/symbol_icon.cpp
@@ -66,6 +66,10 @@ attribute vec2 a_offset;
attribute vec2 a_texture_pos;
attribute vec4 a_data;
+uniform lowp float a_opacity_t;
+attribute lowp float a_opacity_min;
+attribute lowp float a_opacity_max;
+varying lowp float opacity;
// matrix is for the vertex position.
uniform mat4 u_matrix;
@@ -80,6 +84,8 @@ varying vec2 v_tex;
varying vec2 v_fade_tex;
void main() {
+ opacity = mix(a_opacity_min, a_opacity_max, a_opacity_t);
+
vec2 a_tex = a_texture_pos.xy;
mediump float a_labelminzoom = a_data[0];
mediump vec2 a_zoom = a_data.pq;
@@ -122,13 +128,16 @@ precision mediump float;
#endif
uniform sampler2D u_texture;
uniform sampler2D u_fadetexture;
-uniform lowp float u_opacity;
+
+varying lowp float opacity;
varying vec2 v_tex;
varying vec2 v_fade_tex;
void main() {
- lowp float alpha = texture2D(u_fadetexture, v_fade_tex).a * u_opacity;
+
+
+ lowp float alpha = texture2D(u_fadetexture, v_fade_tex).a * opacity;
gl_FragColor = texture2D(u_texture, v_tex) * alpha;
#ifdef OVERDRAW_INSPECTOR
diff --git a/src/mbgl/shaders/symbol_sdf.cpp b/src/mbgl/shaders/symbol_sdf.cpp
index 7554597893..e087242bf8 100644
--- a/src/mbgl/shaders/symbol_sdf.cpp
+++ b/src/mbgl/shaders/symbol_sdf.cpp
@@ -68,6 +68,26 @@ attribute vec2 a_offset;
attribute vec2 a_texture_pos;
attribute vec4 a_data;
+uniform lowp float a_fill_color_t;
+attribute lowp vec4 a_fill_color_min;
+attribute lowp vec4 a_fill_color_max;
+varying lowp vec4 fill_color;
+uniform lowp float a_halo_color_t;
+attribute lowp vec4 a_halo_color_min;
+attribute lowp vec4 a_halo_color_max;
+varying lowp vec4 halo_color;
+uniform lowp float a_opacity_t;
+attribute lowp float a_opacity_min;
+attribute lowp float a_opacity_max;
+varying lowp float opacity;
+uniform lowp float a_halo_width_t;
+attribute lowp float a_halo_width_min;
+attribute lowp float a_halo_width_max;
+varying lowp float halo_width;
+uniform lowp float a_halo_blur_t;
+attribute lowp float a_halo_blur_min;
+attribute lowp float a_halo_blur_max;
+varying lowp float halo_blur;
// matrix is for the vertex position.
uniform mat4 u_matrix;
@@ -87,6 +107,12 @@ varying vec2 v_fade_tex;
varying float v_gamma_scale;
void main() {
+ fill_color = mix(a_fill_color_min, a_fill_color_max, a_fill_color_t);
+ halo_color = mix(a_halo_color_min, a_halo_color_max, a_halo_color_t);
+ opacity = mix(a_opacity_min, a_opacity_max, a_opacity_t);
+ halo_width = mix(a_halo_width_min, a_halo_width_max, a_halo_width_t);
+ halo_blur = mix(a_halo_blur_min, a_halo_blur_max, a_halo_blur_t);
+
vec2 a_tex = a_texture_pos.xy;
mediump float a_labelminzoom = a_data[0];
mediump vec2 a_zoom = a_data.pq;
@@ -163,24 +189,47 @@ precision mediump float;
#endif
#endif
+#define SDF_PX 8.0
+#define EDGE_GAMMA 0.105/DEVICE_PIXEL_RATIO
+
+uniform bool u_is_halo;
+varying lowp vec4 fill_color;
+varying lowp vec4 halo_color;
+varying lowp float opacity;
+varying lowp float halo_width;
+varying lowp float halo_blur;
+
uniform sampler2D u_texture;
uniform sampler2D u_fadetexture;
-uniform lowp vec4 u_color;
-uniform lowp float u_opacity;
-uniform lowp float u_buffer;
-uniform highp float u_gamma;
+uniform lowp float u_font_scale;
+uniform highp float u_gamma_scale;
varying vec2 v_tex;
varying vec2 v_fade_tex;
varying float v_gamma_scale;
void main() {
+
+
+
+
+
+
+ lowp vec4 color = fill_color;
+ lowp float gamma = EDGE_GAMMA / u_gamma_scale;
+ lowp float buff = (256.0 - 64.0) / 256.0;
+ if (u_is_halo) {
+ color = halo_color;
+ gamma = (halo_blur * 1.19 / SDF_PX + EDGE_GAMMA) / u_gamma_scale;
+ buff = (6.0 - halo_width / u_font_scale) / SDF_PX;
+ }
+
lowp float dist = texture2D(u_texture, v_tex).a;
lowp float fade_alpha = texture2D(u_fadetexture, v_fade_tex).a;
- highp float gamma = u_gamma * v_gamma_scale;
- highp float alpha = smoothstep(u_buffer - gamma, u_buffer + gamma, dist) * fade_alpha;
+ highp float gamma_scaled = gamma * v_gamma_scale;
+ highp float alpha = smoothstep(buff - gamma_scaled, buff + gamma_scaled, dist) * fade_alpha;
- gl_FragColor = u_color * (alpha * u_opacity);
+ gl_FragColor = color * (alpha * opacity);
#ifdef OVERDRAW_INSPECTOR
gl_FragColor = vec4(1.0);
diff --git a/src/mbgl/style/layers/symbol_layer.cpp b/src/mbgl/style/layers/symbol_layer.cpp
index 6364091207..d85b8c00e6 100644
--- a/src/mbgl/style/layers/symbol_layer.cpp
+++ b/src/mbgl/style/layers/symbol_layer.cpp
@@ -542,95 +542,115 @@ void SymbolLayer::setTextOptional(PropertyValue<bool> value) {
// Paint properties
-PropertyValue<float> SymbolLayer::getDefaultIconOpacity() {
+DataDrivenPropertyValue<float> SymbolLayer::getDefaultIconOpacity() {
return { 1 };
}
-PropertyValue<float> SymbolLayer::getIconOpacity(const optional<std::string>& klass) const {
+DataDrivenPropertyValue<float> SymbolLayer::getIconOpacity(const optional<std::string>& klass) const {
return impl->paint.get<IconOpacity>(klass);
}
-void SymbolLayer::setIconOpacity(PropertyValue<float> value, const optional<std::string>& klass) {
+void SymbolLayer::setIconOpacity(DataDrivenPropertyValue<float> value, const optional<std::string>& klass) {
if (value == getIconOpacity(klass))
return;
impl->paint.set<IconOpacity>(value, klass);
- impl->observer->onLayerPaintPropertyChanged(*this);
+ if (value.isDataDriven()) {
+ impl->observer->onLayerDataDrivenPaintPropertyChanged(*this);
+ } else {
+ impl->observer->onLayerPaintPropertyChanged(*this);
+ }
}
void SymbolLayer::setIconOpacityTransition(const TransitionOptions& value, const optional<std::string>& klass) {
impl->paint.setTransition<IconOpacity>(value, klass);
}
-PropertyValue<Color> SymbolLayer::getDefaultIconColor() {
+DataDrivenPropertyValue<Color> SymbolLayer::getDefaultIconColor() {
return { Color::black() };
}
-PropertyValue<Color> SymbolLayer::getIconColor(const optional<std::string>& klass) const {
+DataDrivenPropertyValue<Color> SymbolLayer::getIconColor(const optional<std::string>& klass) const {
return impl->paint.get<IconColor>(klass);
}
-void SymbolLayer::setIconColor(PropertyValue<Color> value, const optional<std::string>& klass) {
+void SymbolLayer::setIconColor(DataDrivenPropertyValue<Color> value, const optional<std::string>& klass) {
if (value == getIconColor(klass))
return;
impl->paint.set<IconColor>(value, klass);
- impl->observer->onLayerPaintPropertyChanged(*this);
+ if (value.isDataDriven()) {
+ impl->observer->onLayerDataDrivenPaintPropertyChanged(*this);
+ } else {
+ impl->observer->onLayerPaintPropertyChanged(*this);
+ }
}
void SymbolLayer::setIconColorTransition(const TransitionOptions& value, const optional<std::string>& klass) {
impl->paint.setTransition<IconColor>(value, klass);
}
-PropertyValue<Color> SymbolLayer::getDefaultIconHaloColor() {
+DataDrivenPropertyValue<Color> SymbolLayer::getDefaultIconHaloColor() {
return { {} };
}
-PropertyValue<Color> SymbolLayer::getIconHaloColor(const optional<std::string>& klass) const {
+DataDrivenPropertyValue<Color> SymbolLayer::getIconHaloColor(const optional<std::string>& klass) const {
return impl->paint.get<IconHaloColor>(klass);
}
-void SymbolLayer::setIconHaloColor(PropertyValue<Color> value, const optional<std::string>& klass) {
+void SymbolLayer::setIconHaloColor(DataDrivenPropertyValue<Color> value, const optional<std::string>& klass) {
if (value == getIconHaloColor(klass))
return;
impl->paint.set<IconHaloColor>(value, klass);
- impl->observer->onLayerPaintPropertyChanged(*this);
+ if (value.isDataDriven()) {
+ impl->observer->onLayerDataDrivenPaintPropertyChanged(*this);
+ } else {
+ impl->observer->onLayerPaintPropertyChanged(*this);
+ }
}
void SymbolLayer::setIconHaloColorTransition(const TransitionOptions& value, const optional<std::string>& klass) {
impl->paint.setTransition<IconHaloColor>(value, klass);
}
-PropertyValue<float> SymbolLayer::getDefaultIconHaloWidth() {
+DataDrivenPropertyValue<float> SymbolLayer::getDefaultIconHaloWidth() {
return { 0 };
}
-PropertyValue<float> SymbolLayer::getIconHaloWidth(const optional<std::string>& klass) const {
+DataDrivenPropertyValue<float> SymbolLayer::getIconHaloWidth(const optional<std::string>& klass) const {
return impl->paint.get<IconHaloWidth>(klass);
}
-void SymbolLayer::setIconHaloWidth(PropertyValue<float> value, const optional<std::string>& klass) {
+void SymbolLayer::setIconHaloWidth(DataDrivenPropertyValue<float> value, const optional<std::string>& klass) {
if (value == getIconHaloWidth(klass))
return;
impl->paint.set<IconHaloWidth>(value, klass);
- impl->observer->onLayerPaintPropertyChanged(*this);
+ if (value.isDataDriven()) {
+ impl->observer->onLayerDataDrivenPaintPropertyChanged(*this);
+ } else {
+ impl->observer->onLayerPaintPropertyChanged(*this);
+ }
}
void SymbolLayer::setIconHaloWidthTransition(const TransitionOptions& value, const optional<std::string>& klass) {
impl->paint.setTransition<IconHaloWidth>(value, klass);
}
-PropertyValue<float> SymbolLayer::getDefaultIconHaloBlur() {
+DataDrivenPropertyValue<float> SymbolLayer::getDefaultIconHaloBlur() {
return { 0 };
}
-PropertyValue<float> SymbolLayer::getIconHaloBlur(const optional<std::string>& klass) const {
+DataDrivenPropertyValue<float> SymbolLayer::getIconHaloBlur(const optional<std::string>& klass) const {
return impl->paint.get<IconHaloBlur>(klass);
}
-void SymbolLayer::setIconHaloBlur(PropertyValue<float> value, const optional<std::string>& klass) {
+void SymbolLayer::setIconHaloBlur(DataDrivenPropertyValue<float> value, const optional<std::string>& klass) {
if (value == getIconHaloBlur(klass))
return;
impl->paint.set<IconHaloBlur>(value, klass);
- impl->observer->onLayerPaintPropertyChanged(*this);
+ if (value.isDataDriven()) {
+ impl->observer->onLayerDataDrivenPaintPropertyChanged(*this);
+ } else {
+ impl->observer->onLayerPaintPropertyChanged(*this);
+ }
}
void SymbolLayer::setIconHaloBlurTransition(const TransitionOptions& value, const optional<std::string>& klass) {
@@ -671,99 +691,119 @@ void SymbolLayer::setIconTranslateAnchor(PropertyValue<TranslateAnchorType> valu
impl->observer->onLayerPaintPropertyChanged(*this);
}
-PropertyValue<float> SymbolLayer::getDefaultTextOpacity() {
- return { 1 };
-}
-
void SymbolLayer::setIconTranslateAnchorTransition(const TransitionOptions& value, const optional<std::string>& klass) {
impl->paint.setTransition<IconTranslateAnchor>(value, klass);
}
-PropertyValue<float> SymbolLayer::getTextOpacity(const optional<std::string>& klass) const {
+DataDrivenPropertyValue<float> SymbolLayer::getDefaultTextOpacity() {
+ return { 1 };
+}
+
+DataDrivenPropertyValue<float> SymbolLayer::getTextOpacity(const optional<std::string>& klass) const {
return impl->paint.get<TextOpacity>(klass);
}
-void SymbolLayer::setTextOpacity(PropertyValue<float> value, const optional<std::string>& klass) {
+void SymbolLayer::setTextOpacity(DataDrivenPropertyValue<float> value, const optional<std::string>& klass) {
if (value == getTextOpacity(klass))
return;
impl->paint.set<TextOpacity>(value, klass);
- impl->observer->onLayerPaintPropertyChanged(*this);
-}
-
-PropertyValue<Color> SymbolLayer::getDefaultTextColor() {
- return { Color::black() };
+ if (value.isDataDriven()) {
+ impl->observer->onLayerDataDrivenPaintPropertyChanged(*this);
+ } else {
+ impl->observer->onLayerPaintPropertyChanged(*this);
+ }
}
void SymbolLayer::setTextOpacityTransition(const TransitionOptions& value, const optional<std::string>& klass) {
impl->paint.setTransition<TextOpacity>(value, klass);
}
-PropertyValue<Color> SymbolLayer::getTextColor(const optional<std::string>& klass) const {
+DataDrivenPropertyValue<Color> SymbolLayer::getDefaultTextColor() {
+ return { Color::black() };
+}
+
+DataDrivenPropertyValue<Color> SymbolLayer::getTextColor(const optional<std::string>& klass) const {
return impl->paint.get<TextColor>(klass);
}
-void SymbolLayer::setTextColor(PropertyValue<Color> value, const optional<std::string>& klass) {
+void SymbolLayer::setTextColor(DataDrivenPropertyValue<Color> value, const optional<std::string>& klass) {
if (value == getTextColor(klass))
return;
impl->paint.set<TextColor>(value, klass);
- impl->observer->onLayerPaintPropertyChanged(*this);
+ if (value.isDataDriven()) {
+ impl->observer->onLayerDataDrivenPaintPropertyChanged(*this);
+ } else {
+ impl->observer->onLayerPaintPropertyChanged(*this);
+ }
}
void SymbolLayer::setTextColorTransition(const TransitionOptions& value, const optional<std::string>& klass) {
impl->paint.setTransition<TextColor>(value, klass);
}
-PropertyValue<Color> SymbolLayer::getDefaultTextHaloColor() {
+DataDrivenPropertyValue<Color> SymbolLayer::getDefaultTextHaloColor() {
return { {} };
}
-PropertyValue<Color> SymbolLayer::getTextHaloColor(const optional<std::string>& klass) const {
+DataDrivenPropertyValue<Color> SymbolLayer::getTextHaloColor(const optional<std::string>& klass) const {
return impl->paint.get<TextHaloColor>(klass);
}
-void SymbolLayer::setTextHaloColor(PropertyValue<Color> value, const optional<std::string>& klass) {
+void SymbolLayer::setTextHaloColor(DataDrivenPropertyValue<Color> value, const optional<std::string>& klass) {
if (value == getTextHaloColor(klass))
return;
impl->paint.set<TextHaloColor>(value, klass);
- impl->observer->onLayerPaintPropertyChanged(*this);
+ if (value.isDataDriven()) {
+ impl->observer->onLayerDataDrivenPaintPropertyChanged(*this);
+ } else {
+ impl->observer->onLayerPaintPropertyChanged(*this);
+ }
}
void SymbolLayer::setTextHaloColorTransition(const TransitionOptions& value, const optional<std::string>& klass) {
impl->paint.setTransition<TextHaloColor>(value, klass);
}
-PropertyValue<float> SymbolLayer::getDefaultTextHaloWidth() {
+DataDrivenPropertyValue<float> SymbolLayer::getDefaultTextHaloWidth() {
return { 0 };
}
-PropertyValue<float> SymbolLayer::getTextHaloWidth(const optional<std::string>& klass) const {
+DataDrivenPropertyValue<float> SymbolLayer::getTextHaloWidth(const optional<std::string>& klass) const {
return impl->paint.get<TextHaloWidth>(klass);
}
-void SymbolLayer::setTextHaloWidth(PropertyValue<float> value, const optional<std::string>& klass) {
+void SymbolLayer::setTextHaloWidth(DataDrivenPropertyValue<float> value, const optional<std::string>& klass) {
if (value == getTextHaloWidth(klass))
return;
impl->paint.set<TextHaloWidth>(value, klass);
- impl->observer->onLayerPaintPropertyChanged(*this);
+ if (value.isDataDriven()) {
+ impl->observer->onLayerDataDrivenPaintPropertyChanged(*this);
+ } else {
+ impl->observer->onLayerPaintPropertyChanged(*this);
+ }
}
void SymbolLayer::setTextHaloWidthTransition(const TransitionOptions& value, const optional<std::string>& klass) {
impl->paint.setTransition<TextHaloWidth>(value, klass);
}
-PropertyValue<float> SymbolLayer::getDefaultTextHaloBlur() {
+DataDrivenPropertyValue<float> SymbolLayer::getDefaultTextHaloBlur() {
return { 0 };
}
-PropertyValue<float> SymbolLayer::getTextHaloBlur(const optional<std::string>& klass) const {
+DataDrivenPropertyValue<float> SymbolLayer::getTextHaloBlur(const optional<std::string>& klass) const {
return impl->paint.get<TextHaloBlur>(klass);
}
-void SymbolLayer::setTextHaloBlur(PropertyValue<float> value, const optional<std::string>& klass) {
+void SymbolLayer::setTextHaloBlur(DataDrivenPropertyValue<float> value, const optional<std::string>& klass) {
if (value == getTextHaloBlur(klass))
return;
impl->paint.set<TextHaloBlur>(value, klass);
- impl->observer->onLayerPaintPropertyChanged(*this);
+ if (value.isDataDriven()) {
+ impl->observer->onLayerDataDrivenPaintPropertyChanged(*this);
+ } else {
+ impl->observer->onLayerPaintPropertyChanged(*this);
+ }
}
void SymbolLayer::setTextHaloBlurTransition(const TransitionOptions& value, const optional<std::string>& klass) {
diff --git a/src/mbgl/style/layers/symbol_layer_impl.cpp b/src/mbgl/style/layers/symbol_layer_impl.cpp
index 32547e465a..ff59b14d65 100644
--- a/src/mbgl/style/layers/symbol_layer_impl.cpp
+++ b/src/mbgl/style/layers/symbol_layer_impl.cpp
@@ -16,9 +16,14 @@ bool SymbolLayer::Impl::evaluate(const PropertyEvaluationParameters& parameters)
// text-size and icon-size are layout properties but they also need to be evaluated as paint properties:
iconSize = layout.evaluate<IconSize>(parameters);
textSize = layout.evaluate<TextSize>(parameters);
-
- passes = ((paint.evaluated.get<IconOpacity>() > 0 && (paint.evaluated.get<IconColor>().a > 0 || paint.evaluated.get<IconHaloColor>().a > 0) && iconSize > 0)
- || (paint.evaluated.get<TextOpacity>() > 0 && (paint.evaluated.get<TextColor>().a > 0 || paint.evaluated.get<TextHaloColor>().a > 0) && textSize > 0))
+
+ auto hasIconOpacity = paint.evaluated.get<IconColor>().constantOr(Color::black()).a > 0 ||
+ paint.evaluated.get<IconHaloColor>().constantOr(Color::black()).a > 0;
+ auto hasTextOpacity = paint.evaluated.get<TextColor>().constantOr(Color::black()).a > 0 ||
+ paint.evaluated.get<TextHaloColor>().constantOr(Color::black()).a > 0;
+
+ passes = ((paint.evaluated.get<IconOpacity>().constantOr(1) > 0 && hasIconOpacity && iconSize > 0)
+ || (paint.evaluated.get<TextOpacity>().constantOr(1) > 0 && hasTextOpacity && textSize > 0))
? RenderPass::Translucent : RenderPass::None;
return paint.hasTransition();
@@ -38,20 +43,43 @@ std::unique_ptr<SymbolLayout> SymbolLayer::Impl::createLayout(const BucketParame
*spriteAtlas);
}
-SymbolPropertyValues SymbolLayer::Impl::iconPropertyValues(const SymbolLayoutProperties::Evaluated& layout_) const {
- return SymbolPropertyValues {
- layout_.get<IconRotationAlignment>(), // icon-pitch-alignment is not yet implemented; inherit the rotation alignment
- layout_.get<IconRotationAlignment>(),
- layout_.get<IconSize>(),
+IconPaintProperties::Evaluated SymbolLayer::Impl::iconPaintProperties() const {
+ return IconPaintProperties::Evaluated {
paint.evaluated.get<IconOpacity>(),
paint.evaluated.get<IconColor>(),
paint.evaluated.get<IconHaloColor>(),
paint.evaluated.get<IconHaloWidth>(),
paint.evaluated.get<IconHaloBlur>(),
paint.evaluated.get<IconTranslate>(),
+ paint.evaluated.get<IconTranslateAnchor>()
+ };
+}
+
+TextPaintProperties::Evaluated SymbolLayer::Impl::textPaintProperties() const {
+ return TextPaintProperties::Evaluated {
+ paint.evaluated.get<TextOpacity>(),
+ paint.evaluated.get<TextColor>(),
+ paint.evaluated.get<TextHaloColor>(),
+ paint.evaluated.get<TextHaloWidth>(),
+ paint.evaluated.get<TextHaloBlur>(),
+ paint.evaluated.get<TextTranslate>(),
+ paint.evaluated.get<TextTranslateAnchor>()
+ };
+}
+
+
+SymbolPropertyValues SymbolLayer::Impl::iconPropertyValues(const SymbolLayoutProperties::Evaluated& layout_) const {
+ return SymbolPropertyValues {
+ layout_.get<IconRotationAlignment>(), // icon-pitch-alignment is not yet implemented; inherit the rotation alignment
+ layout_.get<IconRotationAlignment>(),
+ layout_.get<IconSize>(),
+ paint.evaluated.get<IconTranslate>(),
paint.evaluated.get<IconTranslateAnchor>(),
iconSize,
- 1.0f
+ 1.0f,
+ paint.evaluated.get<IconHaloColor>().constantOr(Color::black()).a > 0 &&
+ paint.evaluated.get<IconHaloWidth>().constantOr(1),
+ paint.evaluated.get<IconColor>().constantOr(Color::black()).a > 0
};
}
@@ -60,15 +88,13 @@ SymbolPropertyValues SymbolLayer::Impl::textPropertyValues(const SymbolLayoutPro
layout_.get<TextPitchAlignment>(),
layout_.get<TextRotationAlignment>(),
layout_.get<TextSize>(),
- paint.evaluated.get<TextOpacity>(),
- paint.evaluated.get<TextColor>(),
- paint.evaluated.get<TextHaloColor>(),
- paint.evaluated.get<TextHaloWidth>(),
- paint.evaluated.get<TextHaloBlur>(),
paint.evaluated.get<TextTranslate>(),
paint.evaluated.get<TextTranslateAnchor>(),
textSize,
- 24.0f
+ 24.0f,
+ paint.evaluated.get<TextHaloColor>().constantOr(Color::black()).a > 0 &&
+ paint.evaluated.get<TextHaloWidth>().constantOr(1),
+ paint.evaluated.get<TextColor>().constantOr(Color::black()).a > 0
};
}
diff --git a/src/mbgl/style/layers/symbol_layer_impl.hpp b/src/mbgl/style/layers/symbol_layer_impl.hpp
index c00c2b0bba..1e9f05e4c7 100644
--- a/src/mbgl/style/layers/symbol_layer_impl.hpp
+++ b/src/mbgl/style/layers/symbol_layer_impl.hpp
@@ -1,5 +1,6 @@
#pragma once
+#include <mbgl/util/variant.hpp>
#include <mbgl/style/layer_impl.hpp>
#include <mbgl/style/layers/symbol_layer.hpp>
#include <mbgl/style/layers/symbol_layer_properties.hpp>
@@ -10,6 +11,30 @@ class SpriteAtlas;
class SymbolLayout;
namespace style {
+
+
+// {icon,text}-specific paint-property packs for use in the symbol Programs.
+// Since each program deals either with icons or text, using a smaller property set
+// lets us avoid unnecessarily binding attributes for properties the program wouldn't use.
+class IconPaintProperties : public PaintProperties<
+ IconOpacity,
+ IconColor,
+ IconHaloColor,
+ IconHaloWidth,
+ IconHaloBlur,
+ IconTranslate,
+ IconTranslateAnchor
+> {};
+
+class TextPaintProperties : public PaintProperties<
+ TextOpacity,
+ TextColor,
+ TextHaloColor,
+ TextHaloWidth,
+ TextHaloBlur,
+ TextTranslate,
+ TextTranslateAnchor
+> {};
// Repackaging evaluated values from SymbolLayoutProperties + SymbolPaintProperties
// for genericity over icons vs. text.
@@ -21,24 +46,14 @@ public:
float layoutSize;
// Paint
- float opacity;
- Color color;
- Color haloColor;
- float haloWidth;
- float haloBlur;
std::array<float, 2> translate;
TranslateAnchorType translateAnchor;
float paintSize;
float sdfScale; // Constant (1.0 or 24.0)
-
- bool hasHalo() const {
- return haloColor.a > 0.0f && haloWidth > 0.0f;
- }
-
- bool hasForeground() const {
- return color.a > 0.0f;
- }
+
+ bool hasHalo;
+ bool hasFill;
};
class SymbolLayer::Impl : public Layer::Impl {
@@ -54,6 +69,9 @@ public:
std::unique_ptr<SymbolLayout> createLayout(const BucketParameters&, const std::vector<const Layer*>&,
const GeometryTileLayer&) const;
+ IconPaintProperties::Evaluated iconPaintProperties() const;
+ TextPaintProperties::Evaluated textPaintProperties() const;
+
SymbolPropertyValues iconPropertyValues(const SymbolLayoutProperties::Evaluated&) const;
SymbolPropertyValues textPropertyValues(const SymbolLayoutProperties::Evaluated&) const;
diff --git a/src/mbgl/style/layers/symbol_layer_properties.hpp b/src/mbgl/style/layers/symbol_layer_properties.hpp
index 3bdae377ea..f2b7bfa00f 100644
--- a/src/mbgl/style/layers/symbol_layer_properties.hpp
+++ b/src/mbgl/style/layers/symbol_layer_properties.hpp
@@ -180,23 +180,23 @@ struct TextOptional : LayoutProperty<bool> {
static bool defaultValue() { return false; }
};
-struct IconOpacity : PaintProperty<float> {
+struct IconOpacity : DataDrivenPaintProperty<float, attributes::a_opacity> {
static float defaultValue() { return 1; }
};
-struct IconColor : PaintProperty<Color> {
+struct IconColor : DataDrivenPaintProperty<Color, attributes::a_fill_color> {
static Color defaultValue() { return Color::black(); }
};
-struct IconHaloColor : PaintProperty<Color> {
+struct IconHaloColor : DataDrivenPaintProperty<Color, attributes::a_halo_color> {
static Color defaultValue() { return {}; }
};
-struct IconHaloWidth : PaintProperty<float> {
+struct IconHaloWidth : DataDrivenPaintProperty<float, attributes::a_halo_width> {
static float defaultValue() { return 0; }
};
-struct IconHaloBlur : PaintProperty<float> {
+struct IconHaloBlur : DataDrivenPaintProperty<float, attributes::a_halo_blur> {
static float defaultValue() { return 0; }
};
@@ -208,23 +208,23 @@ struct IconTranslateAnchor : PaintProperty<TranslateAnchorType> {
static TranslateAnchorType defaultValue() { return TranslateAnchorType::Map; }
};
-struct TextOpacity : PaintProperty<float> {
+struct TextOpacity : DataDrivenPaintProperty<float, attributes::a_opacity> {
static float defaultValue() { return 1; }
};
-struct TextColor : PaintProperty<Color> {
+struct TextColor : DataDrivenPaintProperty<Color, attributes::a_fill_color> {
static Color defaultValue() { return Color::black(); }
};
-struct TextHaloColor : PaintProperty<Color> {
+struct TextHaloColor : DataDrivenPaintProperty<Color, attributes::a_halo_color> {
static Color defaultValue() { return {}; }
};
-struct TextHaloWidth : PaintProperty<float> {
+struct TextHaloWidth : DataDrivenPaintProperty<float, attributes::a_halo_width> {
static float defaultValue() { return 0; }
};
-struct TextHaloBlur : PaintProperty<float> {
+struct TextHaloBlur : DataDrivenPaintProperty<float, attributes::a_halo_blur> {
static float defaultValue() { return 0; }
};
diff --git a/src/mbgl/text/shaping.cpp b/src/mbgl/text/shaping.cpp
index b43ba0220c..e68566d419 100644
--- a/src/mbgl/text/shaping.cpp
+++ b/src/mbgl/text/shaping.cpp
@@ -3,16 +3,15 @@
namespace mbgl {
-PositionedIcon shapeIcon(const SpriteAtlasElement& image,
- const SymbolFeature& feature) {
- float dx = feature.iconOffset[0];
- float dy = feature.iconOffset[1];
+PositionedIcon shapeIcon(const SpriteAtlasElement& image, const std::array<float, 2>& iconOffset, const float iconRotation) {
+ float dx = iconOffset[0];
+ float dy = iconOffset[1];
float x1 = dx - image.spriteImage->getWidth() / 2.0f;
float x2 = x1 + image.spriteImage->getWidth();
float y1 = dy - image.spriteImage->getHeight() / 2.0f;
float y2 = y1 + image.spriteImage->getHeight();
- return PositionedIcon(image, y1, y2, x1, x2, feature.iconRotation);
+ return PositionedIcon(image, y1, y2, x1, x2, iconRotation);
}
} // namespace mbgl
diff --git a/src/mbgl/text/shaping.hpp b/src/mbgl/text/shaping.hpp
index b0e6ae3b1d..1b7b8b2733 100644
--- a/src/mbgl/text/shaping.hpp
+++ b/src/mbgl/text/shaping.hpp
@@ -36,7 +36,6 @@ public:
explicit operator bool() const { return image && (*image).pos.hasArea(); }
};
-PositionedIcon shapeIcon(const SpriteAtlasElement&,
- const SymbolFeature&);
+PositionedIcon shapeIcon(const SpriteAtlasElement&, const std::array<float, 2>& iconOffset, const float iconRotation);
} // namespace mbgl
diff --git a/src/mbgl/tile/vector_tile.cpp b/src/mbgl/tile/vector_tile.cpp
index a195885415..68f48e81fd 100644
--- a/src/mbgl/tile/vector_tile.cpp
+++ b/src/mbgl/tile/vector_tile.cpp
@@ -15,9 +15,23 @@ class VectorTileLayer;
using packed_iter_type = protozero::iterator_range<protozero::pbf_reader::const_uint32_iterator>;
+struct VectorTileLayerData {
+ VectorTileLayerData(std::shared_ptr<const std::string>);
+
+ // Hold a reference to the underlying pbf data that backs the lazily-built
+ // components of the owning VectorTileLayer and VectorTileFeature objects
+ std::shared_ptr<const std::string> data;
+
+ uint32_t version = 1;
+ uint32_t extent = 4096;
+ std::unordered_map<std::string, uint32_t> keysMap;
+ std::vector<std::reference_wrapper<const std::string>> keys;
+ std::vector<Value> values;
+};
+
class VectorTileFeature : public GeometryTileFeature {
public:
- VectorTileFeature(protozero::pbf_reader, const VectorTileLayer&);
+ VectorTileFeature(protozero::pbf_reader, std::shared_ptr<VectorTileLayerData> layerData);
FeatureType getType() const override { return type; }
optional<Value> getValue(const std::string&) const override;
@@ -26,16 +40,16 @@ public:
GeometryCollection getGeometries() const override;
private:
- const VectorTileLayer& layer;
+ std::shared_ptr<VectorTileLayerData> layerData;
optional<FeatureIdentifier> id;
FeatureType type = FeatureType::Unknown;
packed_iter_type tags_iter;
packed_iter_type geometry_iter;
};
-
+
class VectorTileLayer : public GeometryTileLayer {
public:
- VectorTileLayer(protozero::pbf_reader);
+ VectorTileLayer(protozero::pbf_reader, std::shared_ptr<const std::string>);
std::size_t featureCount() const override { return features.size(); }
std::unique_ptr<GeometryTileFeature> getFeature(std::size_t) const override;
@@ -46,12 +60,8 @@ private:
friend class VectorTileFeature;
std::string name;
- uint32_t version = 1;
- uint32_t extent = 4096;
- std::unordered_map<std::string, uint32_t> keysMap;
- std::vector<std::reference_wrapper<const std::string>> keys;
- std::vector<Value> values;
std::vector<protozero::pbf_reader> features;
+ std::shared_ptr<VectorTileLayerData> data;
};
class VectorTileData : public GeometryTileData {
@@ -117,8 +127,8 @@ Value parseValue(protozero::pbf_reader data) {
return false;
}
-VectorTileFeature::VectorTileFeature(protozero::pbf_reader feature_pbf, const VectorTileLayer& layer_)
- : layer(layer_) {
+VectorTileFeature::VectorTileFeature(protozero::pbf_reader feature_pbf, std::shared_ptr<VectorTileLayerData> layerData_)
+ : layerData(std::move(layerData_)) {
while (feature_pbf.next()) {
switch (feature_pbf.tag()) {
case 1: // id
@@ -141,8 +151,8 @@ VectorTileFeature::VectorTileFeature(protozero::pbf_reader feature_pbf, const Ve
}
optional<Value> VectorTileFeature::getValue(const std::string& key) const {
- auto keyIter = layer.keysMap.find(key);
- if (keyIter == layer.keysMap.end()) {
+ auto keyIter = layerData->keysMap.find(key);
+ if (keyIter == layerData->keysMap.end()) {
return optional<Value>();
}
@@ -151,7 +161,7 @@ optional<Value> VectorTileFeature::getValue(const std::string& key) const {
while (start_itr != end_itr) {
uint32_t tag_key = static_cast<uint32_t>(*start_itr++);
- if (layer.keysMap.size() <= tag_key) {
+ if (layerData->keysMap.size() <= tag_key) {
throw std::runtime_error("feature referenced out of range key");
}
@@ -160,12 +170,12 @@ optional<Value> VectorTileFeature::getValue(const std::string& key) const {
}
uint32_t tag_val = static_cast<uint32_t>(*start_itr++);;
- if (layer.values.size() <= tag_val) {
+ if (layerData->values.size() <= tag_val) {
throw std::runtime_error("feature referenced out of range value");
}
if (tag_key == keyIter->second) {
- return layer.values[tag_val];
+ return layerData->values[tag_val];
}
}
@@ -182,7 +192,7 @@ std::unordered_map<std::string,Value> VectorTileFeature::getProperties() const {
throw std::runtime_error("uneven number of feature tag ids");
}
uint32_t tag_val = static_cast<uint32_t>(*start_itr++);
- properties[layer.keys.at(tag_key)] = layer.values.at(tag_val);
+ properties[layerData->keys.at(tag_key)] = layerData->values.at(tag_val);
}
return properties;
}
@@ -196,7 +206,7 @@ GeometryCollection VectorTileFeature::getGeometries() const {
uint32_t length = 0;
int32_t x = 0;
int32_t y = 0;
- const float scale = float(util::EXTENT) / layer.extent;
+ const float scale = float(util::EXTENT) / layerData->extent;
GeometryCollection lines;
@@ -234,7 +244,7 @@ GeometryCollection VectorTileFeature::getGeometries() const {
}
}
- if (layer.version >= 2 || type != FeatureType::Polygon) {
+ if (layerData->version >= 2 || type != FeatureType::Polygon) {
return lines;
}
@@ -250,7 +260,7 @@ const GeometryTileLayer* VectorTileData::getLayer(const std::string& name) const
parsed = true;
protozero::pbf_reader tile_pbf(*data);
while (tile_pbf.next(3)) {
- VectorTileLayer layer(tile_pbf.get_message());
+ VectorTileLayer layer(tile_pbf.get_message(), data);
layers.emplace(layer.name, std::move(layer));
}
}
@@ -262,7 +272,13 @@ const GeometryTileLayer* VectorTileData::getLayer(const std::string& name) const
return nullptr;
}
-VectorTileLayer::VectorTileLayer(protozero::pbf_reader layer_pbf) {
+VectorTileLayerData::VectorTileLayerData(std::shared_ptr<const std::string> pbfData) :
+ data(std::move(pbfData))
+{}
+
+VectorTileLayer::VectorTileLayer(protozero::pbf_reader layer_pbf, std::shared_ptr<const std::string> pbfData)
+ : data(std::make_shared<VectorTileLayerData>(std::move(pbfData)))
+{
while (layer_pbf.next()) {
switch (layer_pbf.tag()) {
case 1: // name
@@ -273,18 +289,18 @@ VectorTileLayer::VectorTileLayer(protozero::pbf_reader layer_pbf) {
break;
case 3: // keys
{
- auto iter = keysMap.emplace(layer_pbf.get_string(), keysMap.size());
- keys.emplace_back(std::reference_wrapper<const std::string>(iter.first->first));
+ auto iter = data->keysMap.emplace(layer_pbf.get_string(), data->keysMap.size());
+ data->keys.emplace_back(std::reference_wrapper<const std::string>(iter.first->first));
}
break;
case 4: // values
- values.emplace_back(parseValue(layer_pbf.get_message()));
+ data->values.emplace_back(parseValue(layer_pbf.get_message()));
break;
case 5: // extent
- extent = layer_pbf.get_uint32();
+ data->extent = layer_pbf.get_uint32();
break;
case 15: // version
- version = layer_pbf.get_uint32();
+ data->version = layer_pbf.get_uint32();
break;
default:
layer_pbf.skip();
@@ -294,7 +310,7 @@ VectorTileLayer::VectorTileLayer(protozero::pbf_reader layer_pbf) {
}
std::unique_ptr<GeometryTileFeature> VectorTileLayer::getFeature(std::size_t i) const {
- return std::make_unique<VectorTileFeature>(features.at(i), *this);
+ return std::make_unique<VectorTileFeature>(features.at(i), data);
}
std::string VectorTileLayer::getName() const {
diff --git a/test/tile/vector_tile.test.cpp b/test/tile/vector_tile.test.cpp
index 2fe2586ec2..49fdcbd9f8 100644
--- a/test/tile/vector_tile.test.cpp
+++ b/test/tile/vector_tile.test.cpp
@@ -61,9 +61,11 @@ TEST(VectorTile, Issue7615) {
style::SymbolLayer symbolLayer("symbol", "source");
auto symbolBucket = std::make_shared<SymbolBucket>(
style::SymbolLayoutProperties::Evaluated(),
- std::unordered_map<std::string, style::SymbolPaintProperties::Evaluated>(),
+ std::unordered_map<
+ std::string,
+ std::pair<style::IconPaintProperties::Evaluated, style::TextPaintProperties::Evaluated>>(),
0.0f, false, false);
-
+
// Simulate placement of a symbol layer.
tile.onPlacement(GeometryTile::PlacementResult {
{{
diff --git a/test/util/merge_lines.test.cpp b/test/util/merge_lines.test.cpp
index 0a39419b70..8a3a400887 100644
--- a/test/util/merge_lines.test.cpp
+++ b/test/util/merge_lines.test.cpp
@@ -8,95 +8,131 @@ const std::u16string bbb = u"b";
using namespace mbgl;
-TEST(MergeLines, SameText) {
- // merges lines with the same text
- std::vector<mbgl::SymbolFeature> input1 = {
- { FeatureType::LineString, {{{0, 0}, {1, 0}, {2, 0}}}, aaa, {}, {{0, 0}}, 0, 0 },
- { FeatureType::LineString, {{{4, 0}, {5, 0}, {6, 0}}}, bbb, {}, {{0, 0}}, 0, 0 },
- { FeatureType::LineString, {{{8, 0}, {9, 0}}}, aaa, {}, {{0, 0}}, 0, 0 },
- { FeatureType::LineString, {{{2, 0}, {3, 0}, {4, 0}}}, aaa, {}, {{0, 0}}, 0, 0 },
- { FeatureType::LineString, {{{6, 0}, {7, 0}, {8, 0}}}, aaa, {}, {{0, 0}}, 0, 0 },
- { FeatureType::LineString, {{{5, 0}, {6, 0}}}, aaa, {}, {{0, 0}}, 0, 0 }
+class GeometryTileFeatureStub : public GeometryTileFeature {
+public:
+ GeometryTileFeatureStub(optional<FeatureIdentifier> id_, FeatureType type_, GeometryCollection geometry_,
+ std::unordered_map<std::string, Value> properties_) :
+ id(id_),
+ type(type_),
+ geometry(geometry_),
+ properties(properties_)
+ {}
+
+ FeatureType getType() const override { return type; }
+ optional<Value> getValue(const std::string& key) const override {
+ auto it = properties.find(key);
+ if (it != properties.end()) {
+ return it->second;
+ }
+ return {};
};
+ std::unordered_map<std::string,Value> getProperties() const override { return properties; };
+ optional<FeatureIdentifier> getID() const override { return id; };
+ GeometryCollection getGeometries() const override { return geometry; };
+
+ optional<FeatureIdentifier> id;
+ FeatureType type;
+ GeometryCollection geometry;
+ std::unordered_map<std::string,Value> properties;
+};
+
+class SymbolFeatureStub : public SymbolFeature {
+public:
+ SymbolFeatureStub(optional<FeatureIdentifier> id_, FeatureType type_, GeometryCollection geometry_,
+ std::unordered_map<std::string, Value> properties_, optional<std::u16string> text_,
+ optional<std::string> icon_, std::size_t index_) :
+ SymbolFeature(std::make_unique<GeometryTileFeatureStub>(id_, type_, geometry_, properties_))
+ {
+ text = text_;
+ icon = icon_;
+ index = index_;
+ }
+};
- const std::vector<mbgl::SymbolFeature> expected1 = {
- { FeatureType::LineString, {{{0, 0}, {1, 0}, {2, 0}, {3, 0}, {4, 0}}}, aaa, {}, {{0, 0}}, 0, 0 },
- { FeatureType::LineString, {{{4, 0}, {5, 0}, {6, 0}}}, bbb, {}, {{0, 0}}, 0, 0 },
- { FeatureType::LineString, {{{5, 0}, {6, 0}, {7, 0}, {8, 0}, {9, 0}}}, aaa, {}, {{0, 0}}, 0, 0 },
- { FeatureType::LineString, {{}}, aaa, {}, {{0, 0}}, 0, 0 },
- { FeatureType::LineString, {{}}, aaa, {}, {{0, 0}}, 0, 0 },
- { FeatureType::LineString, {{}}, aaa, {}, {{0, 0}}, 0, 0 }
+TEST(MergeLines, SameText) {
+ // merges lines with the same text
+ std::vector<mbgl::SymbolFeature> input1;
+ input1.push_back(SymbolFeatureStub({}, FeatureType::LineString, {{{0, 0}, {1, 0}, {2, 0}}}, {}, aaa, {}, 0));
+ input1.push_back(SymbolFeatureStub({}, FeatureType::LineString, {{{4, 0}, {5, 0}, {6, 0}}}, {}, bbb, {}, 0));
+ input1.push_back(SymbolFeatureStub({}, FeatureType::LineString, {{{8, 0}, {9, 0}}}, {}, aaa, {}, 0));
+ input1.push_back(SymbolFeatureStub({}, FeatureType::LineString, {{{2, 0}, {3, 0}, {4, 0}}}, {}, aaa, {}, 0));
+ input1.push_back(SymbolFeatureStub({}, FeatureType::LineString, {{{6, 0}, {7, 0}, {8, 0}}}, {}, aaa, {}, 0));
+ input1.push_back(SymbolFeatureStub({}, FeatureType::LineString, {{{5, 0}, {6, 0}}}, {}, aaa, {}, 0));
+
+ const std::vector<GeometryTileFeatureStub> expected1 = {
+ { {}, FeatureType::LineString, {{{0, 0}, {1, 0}, {2, 0}, {3, 0}, {4, 0}}}, {} },
+ { {}, FeatureType::LineString, {{{4, 0}, {5, 0}, {6, 0}}}, {} },
+ { {}, FeatureType::LineString, {{{5, 0}, {6, 0}, {7, 0}, {8, 0}, {9, 0}}}, {} },
+ { {}, FeatureType::LineString, {{}}, {} },
+ { {}, FeatureType::LineString, {{}}, {} },
+ { {}, FeatureType::LineString, {{}}, {} }
};
-
+
mbgl::util::mergeLines(input1);
for (int i = 0; i < 6; i++) {
- EXPECT_TRUE(input1[i].geometry == expected1[i].geometry);
+ EXPECT_TRUE(input1[i].geometry == expected1[i].getGeometries());
}
}
TEST(MergeLines, BothEnds) {
// mergeLines handles merge from both ends
- std::vector<mbgl::SymbolFeature> input2 = {
- { FeatureType::LineString, {{{0, 0}, {1, 0}, {2, 0}}}, aaa, {}, {{0, 0}}, 0, 0 },
- { FeatureType::LineString, {{{4, 0}, {5, 0}, {6, 0}}}, aaa, {}, {{0, 0}}, 0, 0 },
- { FeatureType::LineString, {{{2, 0}, {3, 0}, {4, 0}}}, aaa, {}, {{0, 0}}, 0, 0 }
- };
-
- const std::vector<mbgl::SymbolFeature> expected2 = {
- { FeatureType::LineString, {{{0, 0}, {1, 0}, {2, 0}, {3, 0}, {4, 0}, {5, 0}, {6, 0}}}, aaa, {}, {{0, 0}}, 0, 0 },
- { FeatureType::LineString, {{}}, aaa, {}, {{0, 0}}, 0, 0 },
- { FeatureType::LineString, {{}}, aaa, {}, {{0, 0}}, 0, 0 }
+ std::vector<mbgl::SymbolFeature> input2;
+ input2.push_back(SymbolFeatureStub { {}, FeatureType::LineString, {{{0, 0}, {1, 0}, {2, 0}}}, {}, aaa, {}, 0 });
+ input2.push_back(SymbolFeatureStub { {}, FeatureType::LineString, {{{4, 0}, {5, 0}, {6, 0}}}, {}, aaa, {}, 0 });
+ input2.push_back(SymbolFeatureStub { {}, FeatureType::LineString, {{{2, 0}, {3, 0}, {4, 0}}}, {}, aaa, {}, 0 });
+
+ const std::vector<GeometryTileFeatureStub> expected2 = {
+ { {}, FeatureType::LineString, {{{0, 0}, {1, 0}, {2, 0}, {3, 0}, {4, 0}, {5, 0}, {6, 0}}}, {} },
+ { {}, FeatureType::LineString, {{}}, {} },
+ { {}, FeatureType::LineString, {{}}, {} }
};
mbgl::util::mergeLines(input2);
for (int i = 0; i < 3; i++) {
- EXPECT_TRUE(input2[i].geometry == expected2[i].geometry);
+ EXPECT_TRUE(input2[i].geometry == expected2[i].getGeometries());
}
}
TEST(MergeLines, CircularLines) {
// mergeLines handles circular lines
- std::vector<mbgl::SymbolFeature> input3 = {
- { FeatureType::LineString, {{{0, 0}, {1, 0}, {2, 0}}}, aaa, {}, {{0, 0}}, 0, 0 },
- { FeatureType::LineString, {{{2, 0}, {3, 0}, {4, 0}}}, aaa, {}, {{0, 0}}, 0, 0 },
- { FeatureType::LineString, {{{4, 0}, {0, 0}}}, aaa, {}, {{0, 0}}, 0, 0 }
- };
-
- const std::vector<mbgl::SymbolFeature> expected3 = {
- { FeatureType::LineString, {{{0, 0}, {1, 0}, {2, 0}, {3, 0}, {4, 0}, {0, 0}}}, aaa, {}, {{0, 0}}, 0, 0 },
- { FeatureType::LineString, {{}}, aaa, {}, {{0, 0}}, 0, 0 },
- { FeatureType::LineString, {{}}, aaa, {}, {{0, 0}}, 0, 0 }
+ std::vector<mbgl::SymbolFeature> input3;
+ input3.push_back(SymbolFeatureStub { {}, FeatureType::LineString, {{{0, 0}, {1, 0}, {2, 0}}}, {}, aaa, {}, 0 });
+ input3.push_back(SymbolFeatureStub { {}, FeatureType::LineString, {{{2, 0}, {3, 0}, {4, 0}}}, {}, aaa, {}, 0 });
+ input3.push_back(SymbolFeatureStub { {}, FeatureType::LineString, {{{4, 0}, {0, 0}}}, {}, aaa, {}, 0 });
+
+ const std::vector<GeometryTileFeatureStub> expected3 = {
+ { {}, FeatureType::LineString, {{{0, 0}, {1, 0}, {2, 0}, {3, 0}, {4, 0}, {0, 0}}}, {} },
+ { {}, FeatureType::LineString, {{}}, {} },
+ { {}, FeatureType::LineString, {{}}, {} }
};
mbgl::util::mergeLines(input3);
for (int i = 0; i < 3; i++) {
- EXPECT_TRUE(input3[i].geometry == expected3[i].geometry);
+ EXPECT_TRUE(input3[i].geometry == expected3[i].getGeometries());
}
}
TEST(MergeLines, EmptyOuterGeometry) {
- std::vector<mbgl::SymbolFeature> input = {
- { FeatureType::LineString, {}, aaa, {}, {{0, 0}}, 0, 0 },
- };
+ std::vector<mbgl::SymbolFeature> input;
+ input.push_back(SymbolFeatureStub { {}, FeatureType::LineString, {}, {}, aaa, {}, 0 });
- const std::vector<mbgl::SymbolFeature> expected = input;
+ const std::vector<GeometryTileFeatureStub> expected = { { {}, FeatureType::LineString, {}, {} } };
mbgl::util::mergeLines(input);
- EXPECT_EQ(expected[0].geometry, input[0].geometry);
+ EXPECT_EQ(input[0].geometry, expected[0].getGeometries());
}
TEST(MergeLines, EmptyInnerGeometry) {
- std::vector<mbgl::SymbolFeature> input = {
- { FeatureType::LineString, {{}}, aaa, {}, {{0, 0}}, 0, 0 },
- };
+ std::vector<mbgl::SymbolFeature> input;
+ input.push_back(SymbolFeatureStub { {}, FeatureType::LineString, {{}}, {}, aaa, {}, 0 });
- const std::vector<mbgl::SymbolFeature> expected = input;
+ const std::vector<GeometryTileFeatureStub> expected = { { {}, FeatureType::LineString, {{}}, {} } };
mbgl::util::mergeLines(input);
- EXPECT_EQ(expected[0].geometry, input[0].geometry);
+ EXPECT_EQ(input[0].geometry, expected[0].getGeometries());
}