[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
This commit is contained in:
@@ -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();
|
||||
|
||||
Submodule mapbox-gl-js updated: fd73395ef7...7804faf897
@@ -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
|
||||
|
||||
@@ -1597,6 +1597,112 @@ public class SymbolLayerTest extends BaseStyleTest {
|
||||
assertEquals(1, ((ExponentialStops) layer.getIconOpacity().getFunction().getStops()).size());
|
||||
}
|
||||
|
||||
@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);
|
||||
@@ -1634,6 +1740,77 @@ public class SymbolLayerTest extends BaseStyleTest {
|
||||
assertEquals(1, ((ExponentialStops) layer.getIconColor().getFunction().getStops()).size());
|
||||
}
|
||||
|
||||
@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);
|
||||
@@ -1682,6 +1859,77 @@ public class SymbolLayerTest extends BaseStyleTest {
|
||||
assertEquals(1, ((ExponentialStops) layer.getIconHaloColor().getFunction().getStops()).size());
|
||||
}
|
||||
|
||||
@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);
|
||||
@@ -1730,6 +1978,112 @@ public class SymbolLayerTest extends BaseStyleTest {
|
||||
assertEquals(1, ((ExponentialStops) layer.getIconHaloWidth().getFunction().getStops()).size());
|
||||
}
|
||||
|
||||
@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);
|
||||
@@ -1767,6 +2121,112 @@ public class SymbolLayerTest extends BaseStyleTest {
|
||||
assertEquals(1, ((ExponentialStops) layer.getIconHaloBlur().getFunction().getStops()).size());
|
||||
}
|
||||
|
||||
@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);
|
||||
@@ -1877,6 +2337,112 @@ public class SymbolLayerTest extends BaseStyleTest {
|
||||
assertEquals(1, ((ExponentialStops) layer.getTextOpacity().getFunction().getStops()).size());
|
||||
}
|
||||
|
||||
@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);
|
||||
@@ -1914,6 +2480,77 @@ public class SymbolLayerTest extends BaseStyleTest {
|
||||
assertEquals(1, ((ExponentialStops) layer.getTextColor().getFunction().getStops()).size());
|
||||
}
|
||||
|
||||
@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);
|
||||
@@ -1962,6 +2599,77 @@ public class SymbolLayerTest extends BaseStyleTest {
|
||||
assertEquals(1, ((ExponentialStops) layer.getTextHaloColor().getFunction().getStops()).size());
|
||||
}
|
||||
|
||||
@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);
|
||||
@@ -2010,6 +2718,112 @@ public class SymbolLayerTest extends BaseStyleTest {
|
||||
assertEquals(1, ((ExponentialStops) layer.getTextHaloWidth().getFunction().getStops()).size());
|
||||
}
|
||||
|
||||
@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);
|
||||
@@ -2047,6 +2861,112 @@ public class SymbolLayerTest extends BaseStyleTest {
|
||||
assertEquals(1, ((ExponentialStops) layer.getTextHaloBlur().getFunction().getStops()).size());
|
||||
}
|
||||
|
||||
@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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>' : ''}`;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -40,8 +40,8 @@ public:
|
||||
LinePatternProgram linePattern;
|
||||
RasterProgram raster;
|
||||
SymbolIconProgram symbolIcon;
|
||||
SymbolSDFProgram symbolIconSDF;
|
||||
SymbolSDFProgram symbolGlyph;
|
||||
SymbolSDFIconProgram symbolIconSDF;
|
||||
SymbolSDFTextProgram symbolGlyph;
|
||||
|
||||
DebugProgram debug;
|
||||
CollisionBoxProgram collisionBox;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
using BaseProgram::BaseProgram;
|
||||
|
||||
static UniformValues foregroundUniformValues(const style::SymbolPropertyValues&,
|
||||
const Size& texsize,
|
||||
const std::array<float, 2>& pixelsToGLUnits,
|
||||
const RenderTile&,
|
||||
const TransformState&,
|
||||
float pixelRatio);
|
||||
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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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; }
|
||||
};
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
{{
|
||||
|
||||
@@ -8,95 +8,131 @@ const std::u16string bbb = u"b";
|
||||
|
||||
using namespace mbgl;
|
||||
|
||||
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_;
|
||||
}
|
||||
};
|
||||
|
||||
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 }
|
||||
};
|
||||
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<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 }
|
||||
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 }
|
||||
};
|
||||
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<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 }
|
||||
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 }
|
||||
};
|
||||
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<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 }
|
||||
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());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user