Add support for text-variable-anchor-offset property (#2921)
Co-authored-by: Yingfang Wang <junew@microsoft.com> Co-authored-by: Alexey Kon <48697757+random3940@users.noreply.github.com>
This commit is contained in:
@@ -44,6 +44,25 @@ Result<jni::Local<jni::Object<>>> Converter<jni::Local<jni::Object<>>, Padding>:
|
||||
return result;
|
||||
}
|
||||
|
||||
Result<jni::Local<jni::Object<>>> Converter<jni::Local<jni::Object<>>, VariableAnchorOffsetCollection>::operator()(
|
||||
jni::JNIEnv& env, const VariableAnchorOffsetCollection& value) const {
|
||||
auto variableAnchorOffsets = jni::Array<jni::Object<>>::New(env, value.size() * 2);
|
||||
for (std::size_t i = 0; i < value.size(); i++) {
|
||||
auto anchorOffsetPair = value[i];
|
||||
auto anchorType = jni::Make<jni::String>(env,
|
||||
Enum<style::SymbolAnchorType>::toString(anchorOffsetPair.anchorType));
|
||||
auto offset = jni::Array<jni::Float>::New(env, anchorOffsetPair.offset.size());
|
||||
for (size_t j = 0; j < anchorOffsetPair.offset.size(); j++) {
|
||||
offset.Set(env, j, jni::Box(env, anchorOffsetPair.offset[j]));
|
||||
}
|
||||
|
||||
variableAnchorOffsets.Set(env, i, anchorType);
|
||||
variableAnchorOffsets.Set(env, i + 1, offset);
|
||||
}
|
||||
|
||||
return variableAnchorOffsets;
|
||||
}
|
||||
|
||||
Result<jni::Local<jni::Object<>>> Converter<jni::Local<jni::Object<>>, style::expression::Formatted>::operator()(
|
||||
jni::JNIEnv& env, const style::expression::Formatted& value) const {
|
||||
return Formatted::New(env, value);
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
#include <mbgl/style/expression/formatted.hpp>
|
||||
#include <mbgl/style/expression/image.hpp>
|
||||
#include <mbgl/style/variable_anchor_offset_collection.hpp>
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
@@ -63,6 +64,11 @@ struct Converter<jni::Local<jni::Object<>>, Padding> {
|
||||
Result<jni::Local<jni::Object<>>> operator()(jni::JNIEnv& env, const Padding& value) const;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<jni::Local<jni::Object<>>, VariableAnchorOffsetCollection> {
|
||||
Result<jni::Local<jni::Object<>>> operator()(jni::JNIEnv& env, const VariableAnchorOffsetCollection& value) const;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<jni::Local<jni::Object<>>, style::expression::Formatted> {
|
||||
Result<jni::Local<jni::Object<>>> operator()(jni::JNIEnv& env, const style::expression::Formatted& value) const;
|
||||
|
||||
@@ -189,6 +189,11 @@ jni::Local<jni::Object<>> SymbolLayer::getTextVariableAnchor(jni::JNIEnv& env) {
|
||||
return std::move(*convert<jni::Local<jni::Object<>>>(env, toSymbolLayer(layer).getTextVariableAnchor()));
|
||||
}
|
||||
|
||||
jni::Local<jni::Object<>> SymbolLayer::getTextVariableAnchorOffset(jni::JNIEnv& env) {
|
||||
using namespace mbgl::android::conversion;
|
||||
return std::move(*convert<jni::Local<jni::Object<>>>(env, toSymbolLayer(layer).getTextVariableAnchorOffset()));
|
||||
}
|
||||
|
||||
jni::Local<jni::Object<>> SymbolLayer::getTextAnchor(jni::JNIEnv& env) {
|
||||
using namespace mbgl::android::conversion;
|
||||
return std::move(*convert<jni::Local<jni::Object<>>>(env, toSymbolLayer(layer).getTextAnchor()));
|
||||
@@ -540,6 +545,7 @@ void SymbolJavaLayerPeerFactory::registerNative(jni::JNIEnv& env) {
|
||||
METHOD(&SymbolLayer::getTextJustify, "nativeGetTextJustify"),
|
||||
METHOD(&SymbolLayer::getTextRadialOffset, "nativeGetTextRadialOffset"),
|
||||
METHOD(&SymbolLayer::getTextVariableAnchor, "nativeGetTextVariableAnchor"),
|
||||
METHOD(&SymbolLayer::getTextVariableAnchorOffset, "nativeGetTextVariableAnchorOffset"),
|
||||
METHOD(&SymbolLayer::getTextAnchor, "nativeGetTextAnchor"),
|
||||
METHOD(&SymbolLayer::getTextMaxAngle, "nativeGetTextMaxAngle"),
|
||||
METHOD(&SymbolLayer::getTextWritingMode, "nativeGetTextWritingMode"),
|
||||
|
||||
@@ -86,6 +86,8 @@ public:
|
||||
|
||||
jni::Local<jni::Object<jni::ObjectTag>> getTextVariableAnchor(jni::JNIEnv&);
|
||||
|
||||
jni::Local<jni::Object<jni::ObjectTag>> getTextVariableAnchorOffset(jni::JNIEnv&);
|
||||
|
||||
jni::Local<jni::Object<jni::ObjectTag>> getTextAnchor(jni::JNIEnv&);
|
||||
|
||||
jni::Local<jni::Object<jni::ObjectTag>> getTextMaxAngle(jni::JNIEnv&);
|
||||
|
||||
@@ -2387,6 +2387,50 @@ The unit is in density-independent pixels only for SDF sprites that were created
|
||||
return new LayoutPropertyValue<>("text-variable-anchor", value);
|
||||
}
|
||||
|
||||
/**
|
||||
* To increase the chance of placing high-priority labels on the map, you can provide an array of {@link Property.TEXT_ANCHOR} locations, each paired with an offset value. The renderer will attempt to place the label at each location, in order, before moving on to the next location+offset. Use `text-justify: auto` to choose justification based on anchor position.
|
||||
|
||||
The length of the array must be even, and must alternate between enum and point entries. i.e., each anchor location must be accompanied by a point, and that point defines the offset when the corresponding anchor location is used. Positive offset values indicate right and down, while negative values indicate left and up. Anchor locations may repeat, allowing the renderer to try multiple offsets to try and place a label using the same anchor.
|
||||
|
||||
When present, this property takes precedence over {@link Property.TEXT_ANCHOR}, {@link PropertyFactory#textVariableAnchor}, {@link PropertyFactory#textOffset}, and {@link PropertyFactory#textRadialOffset}.
|
||||
|
||||
```json
|
||||
{ "text-variable-anchor-offset": ["top", [0, 4], "left", [3,0], "bottom", [1, 1]] }
|
||||
```
|
||||
|
||||
When the renderer chooses the `top` anchor, `[0, 4]` will be used for {@link PropertyFactory#textOffset}; the text will be shifted down by 4 ems.
|
||||
|
||||
When the renderer chooses the `left` anchor, `[3, 0]` will be used for {@link PropertyFactory#textOffset}; the text will be shifted right by 3 ems.
|
||||
*
|
||||
* @param value a Object[] value
|
||||
* @return property wrapper around Object[]
|
||||
*/
|
||||
public static PropertyValue<Object[]> textVariableAnchorOffset(Object[] value) {
|
||||
return new LayoutPropertyValue<>("text-variable-anchor-offset", value);
|
||||
}
|
||||
|
||||
/**
|
||||
* To increase the chance of placing high-priority labels on the map, you can provide an array of {@link Property.TEXT_ANCHOR} locations, each paired with an offset value. The renderer will attempt to place the label at each location, in order, before moving on to the next location+offset. Use `text-justify: auto` to choose justification based on anchor position.
|
||||
|
||||
The length of the array must be even, and must alternate between enum and point entries. i.e., each anchor location must be accompanied by a point, and that point defines the offset when the corresponding anchor location is used. Positive offset values indicate right and down, while negative values indicate left and up. Anchor locations may repeat, allowing the renderer to try multiple offsets to try and place a label using the same anchor.
|
||||
|
||||
When present, this property takes precedence over {@link Property.TEXT_ANCHOR}, {@link PropertyFactory#textVariableAnchor}, {@link PropertyFactory#textOffset}, and {@link PropertyFactory#textRadialOffset}.
|
||||
|
||||
```json
|
||||
{ "text-variable-anchor-offset": ["top", [0, 4], "left", [3,0], "bottom", [1, 1]] }
|
||||
```
|
||||
|
||||
When the renderer chooses the `top` anchor, `[0, 4]` will be used for {@link PropertyFactory#textOffset}; the text will be shifted down by 4 ems.
|
||||
|
||||
When the renderer chooses the `left` anchor, `[3, 0]` will be used for {@link PropertyFactory#textOffset}; the text will be shifted right by 3 ems.
|
||||
*
|
||||
* @param value a Object[] value
|
||||
* @return property wrapper around Object[]
|
||||
*/
|
||||
public static PropertyValue<Expression> textVariableAnchorOffset(Expression value) {
|
||||
return new LayoutPropertyValue<>("text-variable-anchor-offset", value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Part of the text placed closest to the anchor.
|
||||
*
|
||||
|
||||
@@ -505,6 +505,18 @@ public class SymbolLayer extends Layer {
|
||||
return (PropertyValue<String[]>) new PropertyValue("text-variable-anchor", nativeGetTextVariableAnchor());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the TextVariableAnchorOffset property
|
||||
*
|
||||
* @return property wrapper value around Object[]
|
||||
*/
|
||||
@NonNull
|
||||
@SuppressWarnings("unchecked")
|
||||
public PropertyValue<Object[]> getTextVariableAnchorOffset() {
|
||||
checkThread();
|
||||
return (PropertyValue<Object[]>) new PropertyValue("text-variable-anchor-offset", nativeGetTextVariableAnchorOffset());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the TextAnchor property
|
||||
*
|
||||
@@ -1245,6 +1257,10 @@ public class SymbolLayer extends Layer {
|
||||
@Keep
|
||||
private native Object nativeGetTextVariableAnchor();
|
||||
|
||||
@NonNull
|
||||
@Keep
|
||||
private native Object nativeGetTextVariableAnchorOffset();
|
||||
|
||||
@NonNull
|
||||
@Keep
|
||||
private native Object nativeGetTextAnchor();
|
||||
|
||||
@@ -722,6 +722,19 @@ public class SymbolLayerTest extends BaseLayerTest {
|
||||
assertEquals(layer.getTextVariableAnchor().getValue(), propertyValue);
|
||||
}
|
||||
|
||||
@Test
|
||||
@UiThreadTest
|
||||
public void testTextVariableAnchorOffsetAsConstant() {
|
||||
Timber.i("text-variable-anchor-offset");
|
||||
assertNotNull(layer);
|
||||
assertNull(layer.getTextVariableAnchorOffset().getValue());
|
||||
|
||||
// Set and Get
|
||||
Object[] propertyValue = new Object[] {"top", new Float[]{1f, 2f}};
|
||||
layer.setProperties(textVariableAnchorOffset(propertyValue));
|
||||
assertEquals(layer.getTextVariableAnchorOffset().getValue(), propertyValue);
|
||||
}
|
||||
|
||||
@Test
|
||||
@UiThreadTest
|
||||
public void testTextAnchorAsConstant() {
|
||||
|
||||
@@ -120,7 +120,9 @@ global.propertyType = function propertyType(property) {
|
||||
case 'color':
|
||||
return 'String';
|
||||
case 'padding':
|
||||
return 'Float[]'
|
||||
return 'Float[]';
|
||||
case 'variableAnchorOffsetCollection':
|
||||
return 'Object[]';
|
||||
case 'array':
|
||||
return `${propertyType({type:property.value, name: property.name})}[]`;
|
||||
default:
|
||||
@@ -197,6 +199,8 @@ global.propertyNativeType = function (property) {
|
||||
return `Color`;
|
||||
case 'padding':
|
||||
return 'Padding';
|
||||
case 'variableAnchorOffsetCollection':
|
||||
return 'VariableAnchorOffsetCollection';
|
||||
case 'array':
|
||||
if (property.length) {
|
||||
return `std::array<${propertyType({type: property.value})}, ${property.length}>`;
|
||||
@@ -269,6 +273,8 @@ global.defaultValueJava = function(property) {
|
||||
return '"rgba(255,128,0,0.7)"';
|
||||
case 'padding':
|
||||
return '{2.0f, 2.0f, 2.0f, 2.0f}';
|
||||
case 'variableAnchorOffsetCollection':
|
||||
return 'new Object[] {"top", new Float[]{1f, 2f}}';
|
||||
case 'array':
|
||||
switch (property.value) {
|
||||
case 'string':
|
||||
|
||||
Reference in New Issue
Block a user