Skip to content

Commit a3879a8

Browse files
committed
dwins#32, Add support for graphic-margin vendor option, and dwins#20, Support 'labelObstacle' vendor parameter in CSS
1 parent 44714ab commit a3879a8

File tree

6 files changed

+120
-21
lines changed

6 files changed

+120
-21
lines changed

geocss/src/main/scala/org/geoscript/geocss/Translator.scala

Lines changed: 44 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ class Translator(val baseURL: Option[java.net.URL]) {
3434
val styles = org.geotools.factory.CommonFactoryFinder.getStyleFactory()
3535
type OGCExpression = org.opengis.filter.expression.Expression
3636

37-
val gtVendorOpts = Seq(
37+
val gtTextVendorOpts = Seq(
3838
"-gt-label-padding" -> "spaceAround",
3939
"-gt-label-group" -> "group",
4040
"-gt-label-max-displacement" -> "maxDisplacement",
@@ -52,6 +52,19 @@ class Translator(val baseURL: Option[java.net.URL]) {
5252
"-gt-shield-resize" -> "graphic-resize",
5353
"-gt-shield-margin" -> "graphic-margin"
5454
)
55+
56+
val gtPolygonVendorOpts = Seq(
57+
"-gt-graphic-margin" -> "graphic-margin",
58+
"-gt-fill-label-obstacle" -> "labelObstacle"
59+
)
60+
61+
val gtPointVendorOpts = Seq(
62+
"-gt-mark-label-obstacle" -> "labelObstacle"
63+
)
64+
65+
val gtLineVendorOpts = Seq(
66+
"-gt-stroke-label-obstacle" -> "labelObstacle"
67+
)
5568

5669
private val defaultRGB = filters.literal(colors("grey"))
5770

@@ -409,6 +422,22 @@ class Translator(val baseURL: Option[java.net.URL]) {
409422

410423
def orderedMarkRules(symbolizerType: String, order: Int): Seq[Property] =
411424
rule.context(symbolizerType, order)
425+
426+
/**
427+
* Applies the specified vendor options to the symbolizer, taking them from the collected properties values
428+
*/
429+
def applyVendorOptions(sym: Symbolizer, props : Map[String, Seq[Value]], vendorOptions : Seq[(String, String)]) : Unit = {
430+
for (
431+
(cssName, sldName) <- vendorOptions;
432+
value <- props.get(cssName)
433+
) {
434+
sym.getOptions().put(
435+
sldName,
436+
value.collect({ case Literal(x) => x }).mkString(" ")
437+
)
438+
}
439+
440+
}
412441

413442
val lineSyms: Seq[(Double, LineSymbolizer)] =
414443
(expand(properties, "stroke").toStream zip
@@ -452,6 +481,10 @@ class Translator(val baseURL: Option[java.net.URL]) {
452481
null
453482
)
454483
geom.foreach { sym.setGeometry }
484+
485+
// collect the vendor options for line symbolizers
486+
applyVendorOptions(sym, props, gtLineVendorOpts)
487+
455488
(zIndex, sym)
456489
}
457490

@@ -481,6 +514,10 @@ class Translator(val baseURL: Option[java.net.URL]) {
481514
null
482515
)
483516
geom.foreach { sym.setGeometry(_) }
517+
518+
// collect the vendor options for polygon symbolizers
519+
applyVendorOptions(sym, props, gtPolygonVendorOpts)
520+
484521
(zIndex, sym)
485522
}
486523

@@ -498,6 +535,10 @@ class Translator(val baseURL: Option[java.net.URL]) {
498535
for (g <- graphic) yield {
499536
val sym = styles.createPointSymbolizer(g, null)
500537
geom.foreach { sym.setGeometry(_) }
538+
539+
// collect the vendor options for point symbolizers
540+
applyVendorOptions(sym, props, gtPointVendorOpts)
541+
501542
(zIndex, sym)
502543
}
503544
}
@@ -620,15 +661,8 @@ class Translator(val baseURL: Option[java.net.URL]) {
620661
sym.setPriority(priority)
621662
}
622663

623-
for (
624-
(cssName, sldName) <- gtVendorOpts;
625-
value <- props.get(cssName)
626-
) {
627-
sym.getOptions().put(
628-
sldName,
629-
value.collect({ case Literal(x) => x }).mkString(" ")
630-
)
631-
}
664+
// collect the vendor options for text symbolizers
665+
applyVendorOptions(sym, props, gtTextVendorOpts)
632666

633667
(zIndex, sym)
634668
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
/**
2+
* Example usage of GeoTools-specific extension properties
3+
*/
4+
* {
5+
stroke: red;
6+
-gt-stroke-label-obstacle: true;
7+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
/**
2+
* Example usage of GeoTools-specific extension properties
3+
*/
4+
* {
5+
mark: symbol("cicle");
6+
mark-size: 10;
7+
-gt-mark-label-obstacle: true;
8+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
/**
2+
* Example usage of GeoTools-specific extension properties
3+
*/
4+
* {
5+
fill: red;
6+
-gt-fill-label-obstacle: true;
7+
-gt-graphic-margin: 10 20 40 30;
8+
}

geocss/src/test/scala/org/geoscript/geocss/SLDTest.scala

Lines changed: 53 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -151,23 +151,27 @@ class SLDTest extends FunSuite with ShouldMatchers {
151151
haloparams(0).text.trim should equal ("#FFFFFF")
152152
haloparams(1).text.trim.toDouble should be(closeTo(0.7, 0.001))
153153
}
154-
155-
test("GeoTools vendor options should be passed through") {
156-
val vendorOptions = css2sld2dom("/gt-opts.css")
157-
158-
def vendor(name: String): Option[String] = {
159-
(vendorOptions \\ "VendorOption") find {
160-
_.attribute("name") map (_.text == name) getOrElse(false)
161-
} map {
162-
_.child.text
163-
}
154+
155+
/**
156+
* Extracts the specified vendor option from the xml node
157+
*/
158+
def getVendorOption(xml: scala.xml.Elem) (name: String): Option[String] = {
159+
(xml \\ "VendorOption") find {
160+
_.attribute("name") map (_.text == name) getOrElse(false)
161+
} map {
162+
_.child.text
164163
}
164+
}
165+
166+
test("GeoTools text vendor options should be passed through") {
167+
val vendorOptions = css2sld2dom("/gt-text-opts.css")
165168

166169
// all vendor options should be direct children of textsymbolizers now
167170
vendorOptions \\ "VendorOption" should equal (
168171
vendorOptions \\ "TextSymbolizer" \ "VendorOption"
169172
)
170-
173+
174+
val vendor = getVendorOption(vendorOptions)_;
171175
vendor("allGroup") should be(Some("false"))
172176
vendor("maxAngleDelta") should be(Some("22.5"))
173177
vendor("followLine") should be(Some("false"))
@@ -186,6 +190,44 @@ class SLDTest extends FunSuite with ShouldMatchers {
186190

187191
(vendorOptions \\ "Priority" \ "PropertyName").text should equal ("priority")
188192
}
193+
194+
test("GeoTools polygon vendor options should be passed through") {
195+
val vendorOptions = css2sld2dom("/gt-poly-opts.css")
196+
197+
// all vendor options should be direct children of polygon symbolizer now
198+
vendorOptions \\ "VendorOption" should equal (
199+
vendorOptions \\ "PolygonSymbolizer" \ "VendorOption"
200+
)
201+
202+
val vendor = getVendorOption(vendorOptions)_;
203+
vendor("labelObstacle") should be(Some("true"))
204+
vendor("graphic-margin") should be(Some("10 20 40 30"))
205+
}
206+
207+
test("GeoTools point vendor options should be passed through") {
208+
val vendorOptions = css2sld2dom("/gt-point-opts.css")
209+
210+
// all vendor options should be direct children of point symbolizer now
211+
vendorOptions \\ "VendorOption" should equal (
212+
vendorOptions \\ "PointSymbolizer" \ "VendorOption"
213+
)
214+
215+
val vendor = getVendorOption(vendorOptions)_;
216+
vendor("labelObstacle") should be(Some("true"))
217+
}
218+
219+
test("GeoTools line vendor options should be passed through") {
220+
val vendorOptions = css2sld2dom("/gt-line-opts.css")
221+
222+
// all vendor options should be direct children of line symbolizer now
223+
vendorOptions \\ "VendorOption" should equal (
224+
vendorOptions \\ "LineSymbolizer" \ "VendorOption"
225+
)
226+
227+
val vendor = getVendorOption(vendorOptions)_;
228+
vendor("labelObstacle") should be(Some("true"))
229+
}
230+
189231

190232

191233
test("Mixing selector properties doensn't produce empty rules") {

0 commit comments

Comments
 (0)