From 4862228f31ab20f00aacdce91c1839447b6ee697 Mon Sep 17 00:00:00 2001 From: Sargun Vohra Date: Thu, 19 Dec 2024 19:02:30 -0600 Subject: [PATCH] feat: support for textVariableAnchorOffset --- .../maplibrecompose/core/layer/SymbolLayer.kt | 5 ++- .../compose/layer/SymbolLayer.kt | 3 +- .../core/expression/ExpressionValue.kt | 19 +++++++++-- .../core/expression/ExpressionsDsl.kt | 32 ++++++++++++++++--- .../maplibrecompose/core/layer/SymbolLayer.kt | 3 +- .../maplibrecompose/core/layer/SymbolLayer.kt | 5 ++- 6 files changed, 57 insertions(+), 10 deletions(-) diff --git a/lib/maplibre-compose/src/androidMain/kotlin/dev/sargunv/maplibrecompose/core/layer/SymbolLayer.kt b/lib/maplibre-compose/src/androidMain/kotlin/dev/sargunv/maplibrecompose/core/layer/SymbolLayer.kt index 3e9929e8..93e32d71 100644 --- a/lib/maplibre-compose/src/androidMain/kotlin/dev/sargunv/maplibrecompose/core/layer/SymbolLayer.kt +++ b/lib/maplibre-compose/src/androidMain/kotlin/dev/sargunv/maplibrecompose/core/layer/SymbolLayer.kt @@ -23,6 +23,7 @@ import dev.sargunv.maplibrecompose.core.expression.TextJustify import dev.sargunv.maplibrecompose.core.expression.TextPitchAlignment import dev.sargunv.maplibrecompose.core.expression.TextRotationAlignment import dev.sargunv.maplibrecompose.core.expression.TextTransform +import dev.sargunv.maplibrecompose.core.expression.TextVariableAnchorOffsetValue import dev.sargunv.maplibrecompose.core.expression.TextWritingMode import dev.sargunv.maplibrecompose.core.expression.TranslateAnchor import dev.sargunv.maplibrecompose.core.source.Source @@ -198,7 +199,9 @@ internal actual class SymbolLayer actual constructor(id: String, source: Source) impl.setProperties(PropertyFactory.textVariableAnchor(variableAnchor.toMLNExpression())) } - actual fun setTextVariableAnchorOffset(variableAnchorOffset: Expression>) { + actual fun setTextVariableAnchorOffset( + variableAnchorOffset: Expression + ) { impl.setProperties( PropertyFactory.textVariableAnchorOffset(variableAnchorOffset.toMLNExpression()) ) diff --git a/lib/maplibre-compose/src/commonMain/kotlin/dev/sargunv/maplibrecompose/compose/layer/SymbolLayer.kt b/lib/maplibre-compose/src/commonMain/kotlin/dev/sargunv/maplibrecompose/compose/layer/SymbolLayer.kt index 5027ed26..3de4053a 100644 --- a/lib/maplibre-compose/src/commonMain/kotlin/dev/sargunv/maplibrecompose/compose/layer/SymbolLayer.kt +++ b/lib/maplibre-compose/src/commonMain/kotlin/dev/sargunv/maplibrecompose/compose/layer/SymbolLayer.kt @@ -41,6 +41,7 @@ import dev.sargunv.maplibrecompose.core.expression.TextPitchAlignment import dev.sargunv.maplibrecompose.core.expression.TextRotationAlignment import dev.sargunv.maplibrecompose.core.expression.TextTransform import dev.sargunv.maplibrecompose.core.expression.TextUnitValue +import dev.sargunv.maplibrecompose.core.expression.TextVariableAnchorOffsetValue import dev.sargunv.maplibrecompose.core.expression.TextWritingMode import dev.sargunv.maplibrecompose.core.expression.TranslateAnchor import dev.sargunv.maplibrecompose.core.expression.ZeroPadding @@ -452,7 +453,7 @@ public fun SymbolLayer( textOffset: Expression = textOffset(0f.em, 0f.em), textVariableAnchor: Expression>> = nil(), textRadialOffset: Expression = const(0f.em), - textVariableAnchorOffset: Expression> = nil(), // TODO proper type + textVariableAnchorOffset: Expression = nil(), // text collision textPadding: Expression = const(2.dp), diff --git a/lib/maplibre-compose/src/commonMain/kotlin/dev/sargunv/maplibrecompose/core/expression/ExpressionValue.kt b/lib/maplibre-compose/src/commonMain/kotlin/dev/sargunv/maplibrecompose/core/expression/ExpressionValue.kt index 8401c4f5..30b491d9 100644 --- a/lib/maplibre-compose/src/commonMain/kotlin/dev/sargunv/maplibrecompose/core/expression/ExpressionValue.kt +++ b/lib/maplibre-compose/src/commonMain/kotlin/dev/sargunv/maplibrecompose/core/expression/ExpressionValue.kt @@ -83,16 +83,31 @@ public sealed interface ColorValue : ExpressionValue, InterpolateableValue : ExpressionValue /** * Represents an [Expression] that resolves to a list value (corresponds to a JSON array). See - * [ExpressionsDsl.literal]. + * [ExpressionsDsl.const]. */ public sealed interface ListValue : ExpressionValue +/** + * Represents an [Expression] that resolves to a list value (corresponds to a JSON array) of + * alternating types. + */ +public sealed interface TupleListValue : + ListValue + +/** + * Represents an [Expression] that resolves to an alternating list of [SymbolAnchor] and + * [OffsetValue]. + * + * See [SymbolLayer][dev.sargunv.maplibrecompose.compose.layer.SymbolLayer]. + */ +public typealias TextVariableAnchorOffsetValue = TupleListValue + /** * Represents an [Expression] that resolves to a list of numbers. * diff --git a/lib/maplibre-compose/src/commonMain/kotlin/dev/sargunv/maplibrecompose/core/expression/ExpressionsDsl.kt b/lib/maplibre-compose/src/commonMain/kotlin/dev/sargunv/maplibrecompose/core/expression/ExpressionsDsl.kt index 5e8d0212..6f222df3 100644 --- a/lib/maplibre-compose/src/commonMain/kotlin/dev/sargunv/maplibrecompose/core/expression/ExpressionsDsl.kt +++ b/lib/maplibre-compose/src/commonMain/kotlin/dev/sargunv/maplibrecompose/core/expression/ExpressionsDsl.kt @@ -70,16 +70,40 @@ public object ExpressionsDsl { public fun const(padding: PaddingValues.Absolute): Expression = Expression.ofPadding(padding) + internal fun literal(list: List): Expression> = + Expression.ofList(listOf("literal", list)).cast() + /** Creates a literal expression for a list of strings. */ @JvmName("constStringList") - public fun const(list: List): Expression> = - Expression.ofList(listOf("literal", list)).cast() + public fun const(list: List): Expression> = literal(list).cast() /** Creates a literal expression for a list of numbers. */ @JvmName("constNumberList") - public fun const(list: List): Expression> = - Expression.ofList(listOf("literal", list)).cast() + public fun const(list: List): Expression> = literal(list).cast() + + /** + * Creates a literal expression for [TextVariableAnchorOffsetValue], used by + * [SymbolLayer][dev.sargunv.maplibrecompose.compose.layer.SymbolLayer]'s + * `textVariableAnchorOffset` parameter. + * + * The offset is measured in a multipler of the text size (EM). It's in [Offset] instead of + * [textOffset] because of technical limitations in MapLibre. + */ + public fun textVariableAnchorOffset( + vararg pairs: Pair + ): Expression { + return literal( + buildList { + pairs.forEach { (anchor, offset) -> + add(anchor.stringConst) + add(offset) + } + } + ) + .cast() + } + /** Creates a literal expression for 2D [TextUnit] offset. */ public fun textOffset(x: TextUnit, y: TextUnit): Expression { require(x.type == y.type) { "x and y must have the same TextUnitType" } diff --git a/lib/maplibre-compose/src/commonMain/kotlin/dev/sargunv/maplibrecompose/core/layer/SymbolLayer.kt b/lib/maplibre-compose/src/commonMain/kotlin/dev/sargunv/maplibrecompose/core/layer/SymbolLayer.kt index b2ccc7d7..664d73e6 100644 --- a/lib/maplibre-compose/src/commonMain/kotlin/dev/sargunv/maplibrecompose/core/layer/SymbolLayer.kt +++ b/lib/maplibre-compose/src/commonMain/kotlin/dev/sargunv/maplibrecompose/core/layer/SymbolLayer.kt @@ -23,6 +23,7 @@ import dev.sargunv.maplibrecompose.core.expression.TextJustify import dev.sargunv.maplibrecompose.core.expression.TextPitchAlignment import dev.sargunv.maplibrecompose.core.expression.TextRotationAlignment import dev.sargunv.maplibrecompose.core.expression.TextTransform +import dev.sargunv.maplibrecompose.core.expression.TextVariableAnchorOffsetValue import dev.sargunv.maplibrecompose.core.expression.TextWritingMode import dev.sargunv.maplibrecompose.core.expression.TranslateAnchor import dev.sargunv.maplibrecompose.core.source.Source @@ -109,7 +110,7 @@ internal expect class SymbolLayer(id: String, source: Source) : FeatureLayer { fun setTextVariableAnchor(variableAnchor: Expression>>) - @JsOnlyApi fun setTextVariableAnchorOffset(variableAnchorOffset: Expression>) + fun setTextVariableAnchorOffset(variableAnchorOffset: Expression) fun setTextAnchor(anchor: Expression>) diff --git a/lib/maplibre-compose/src/iosMain/kotlin/dev/sargunv/maplibrecompose/core/layer/SymbolLayer.kt b/lib/maplibre-compose/src/iosMain/kotlin/dev/sargunv/maplibrecompose/core/layer/SymbolLayer.kt index a0b20392..0ad4880b 100644 --- a/lib/maplibre-compose/src/iosMain/kotlin/dev/sargunv/maplibrecompose/core/layer/SymbolLayer.kt +++ b/lib/maplibre-compose/src/iosMain/kotlin/dev/sargunv/maplibrecompose/core/layer/SymbolLayer.kt @@ -24,6 +24,7 @@ import dev.sargunv.maplibrecompose.core.expression.TextJustify import dev.sargunv.maplibrecompose.core.expression.TextPitchAlignment import dev.sargunv.maplibrecompose.core.expression.TextRotationAlignment import dev.sargunv.maplibrecompose.core.expression.TextTransform +import dev.sargunv.maplibrecompose.core.expression.TextVariableAnchorOffsetValue import dev.sargunv.maplibrecompose.core.expression.TextWritingMode import dev.sargunv.maplibrecompose.core.expression.TranslateAnchor import dev.sargunv.maplibrecompose.core.source.Source @@ -203,7 +204,9 @@ internal actual class SymbolLayer actual constructor(id: String, source: Source) impl.textVariableAnchor = variableAnchor.toNSExpression() } - actual fun setTextVariableAnchorOffset(variableAnchorOffset: Expression>) { + actual fun setTextVariableAnchorOffset( + variableAnchorOffset: Expression + ) { impl.textVariableAnchorOffset = variableAnchorOffset.toNSExpression() }