mirror of
https://github.com/omniscale/magnacarto.git
synced 2025-09-28 21:03:34 +02:00
278 lines
6.8 KiB
Go
278 lines
6.8 KiB
Go
package mss
|
|
|
|
import "github.com/omniscale/magnacarto/color"
|
|
|
|
var attributeTypes map[string]isValid
|
|
|
|
type isValid func(interface{}) bool
|
|
|
|
func isNumber(val interface{}) bool {
|
|
_, ok := val.(float64)
|
|
return ok
|
|
}
|
|
|
|
func isNumbers(val interface{}) bool {
|
|
vals, ok := val.([]Value)
|
|
if !ok {
|
|
return false
|
|
}
|
|
for _, v := range vals {
|
|
if !isNumber(v) {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
|
|
func isString(val interface{}) bool {
|
|
_, ok := val.(string)
|
|
return ok
|
|
}
|
|
|
|
func isStrings(val interface{}) bool {
|
|
vals, ok := val.([]Value)
|
|
if !ok {
|
|
return false
|
|
}
|
|
for _, v := range vals {
|
|
if !isString(v) {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
|
|
func isStringOrStrings(val interface{}) bool {
|
|
return isString(val) || isStrings(val)
|
|
}
|
|
|
|
func isFieldOr(other isValid) isValid {
|
|
return func(val interface{}) bool {
|
|
if s, ok := val.(string); ok {
|
|
if len(s) > 2 && s[0] == '[' && s[len(s)-1] == ']' {
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
return other(val)
|
|
}
|
|
}
|
|
|
|
func isColor(val interface{}) bool {
|
|
_, ok := val.(color.Color)
|
|
return ok
|
|
}
|
|
|
|
func isBool(val interface{}) bool {
|
|
_, ok := val.(bool)
|
|
return ok
|
|
}
|
|
|
|
func isKeyword(keywords ...string) isValid {
|
|
return func(val interface{}) bool {
|
|
k, ok := val.(string)
|
|
if !ok {
|
|
return false
|
|
}
|
|
for _, expected := range keywords {
|
|
if k == expected {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
}
|
|
|
|
func isStops(val interface{}) bool {
|
|
vals, ok := val.([]Value)
|
|
if !ok {
|
|
return false
|
|
}
|
|
for _, v := range vals {
|
|
if _, ok := v.(Stop); !ok {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
|
|
func isCompOp(val interface{}) bool {
|
|
return isKeyword(
|
|
"src",
|
|
"dst",
|
|
"src-over",
|
|
"dst-over",
|
|
"src-in",
|
|
"dst-in",
|
|
"src-out",
|
|
"dst-out",
|
|
"src-atop",
|
|
"dst-atop",
|
|
"xor",
|
|
"plus",
|
|
"minus",
|
|
"multiply",
|
|
"screen",
|
|
"overlay",
|
|
"darken",
|
|
"lighten",
|
|
"color-dodge",
|
|
"color-burn",
|
|
"hard-light",
|
|
"soft-light",
|
|
"difference",
|
|
"exclusion",
|
|
"contrast",
|
|
"invert",
|
|
"invert-rgb",
|
|
"grain-merge",
|
|
"grain-extract",
|
|
"hue",
|
|
"saturation",
|
|
"color",
|
|
"value",
|
|
)(val)
|
|
}
|
|
|
|
func isScaling(val interface{}) bool {
|
|
return isKeyword(
|
|
"near",
|
|
"fast",
|
|
"bilinear",
|
|
"bicubic",
|
|
"spline16",
|
|
"spline36",
|
|
"hanning",
|
|
"hamming",
|
|
"hermite",
|
|
"kaiser",
|
|
"quadric",
|
|
"catrom",
|
|
"gaussian",
|
|
"bessel",
|
|
"mitchell",
|
|
"sinc",
|
|
"lanczos",
|
|
"blackman",
|
|
)(val)
|
|
}
|
|
func init() {
|
|
attributeTypes = map[string]isValid{
|
|
"background-color": isColor,
|
|
|
|
"building-fill": isColor,
|
|
"building-height": isNumber,
|
|
|
|
"line-cap": isKeyword("round", "butt", "square"),
|
|
"line-clip": isBool,
|
|
"line-color": isColor,
|
|
"line-dasharray": isNumbers,
|
|
"line-gamma-method": isKeyword("power", "linear", "none", "threshold", "multiply"),
|
|
"line-join": isKeyword("miter", "round", "bevel"),
|
|
"line-offset": isNumber,
|
|
"line-opacity": isNumber,
|
|
"line-rastersizer": isKeyword("full", "fast"),
|
|
"line-simplify": isNumber,
|
|
"line-smooth": isNumber,
|
|
"line-width": isNumber,
|
|
|
|
"marker-allow-overlap": isBool,
|
|
"marker-file": isString,
|
|
"marker-fill": isColor,
|
|
"marker-height": isNumber,
|
|
"marker-line-color": isColor,
|
|
"marker-line-width": isNumber,
|
|
"marker-opacity": isNumber,
|
|
"marker-placement": isKeyword("point", "interior", "line"),
|
|
"marker-spacing": isNumber,
|
|
"marker-transform": isString,
|
|
"marker-type": isKeyword("arrow", "ellipse"),
|
|
"marker-width": isNumber,
|
|
|
|
"point-file": isString,
|
|
"point-allow-overlap": isBool,
|
|
"point-opacity": isNumber,
|
|
"point-transform": isString,
|
|
"point-ignore-placement": isBool,
|
|
|
|
"polygon-fill": isColor,
|
|
"polygon-gamma": isNumber,
|
|
"polygon-gamma-method": isKeyword("power", "linear", "none", "threshold", "multiply"),
|
|
"polygon-opacity": isNumber,
|
|
"polygon-pattern-alignment": isKeyword("global", "local"),
|
|
"polygon-pattern-file": isString,
|
|
|
|
"shield-allow-overlap": isBool,
|
|
"shield-avoid-edges": isBool,
|
|
"shield-character-spacing": isNumber,
|
|
"shield-clip": isBool,
|
|
"shield-dx": isNumber,
|
|
"shield-dy": isNumber,
|
|
"shield-face-name": isStringOrStrings,
|
|
"shield-file": isString,
|
|
"shield-fill": isColor,
|
|
"shield-halo-fill": isColor,
|
|
"shield-halo-radius": isNumber,
|
|
"shield-line-spacing": isNumber,
|
|
"shield-min-distance": isNumber,
|
|
"shield-min-padding": isNumber,
|
|
"shield-name": isString,
|
|
"shield-opacity": isNumber,
|
|
"shield-placement": isKeyword("line", "point", "vertex", "interior"),
|
|
"shield-placement-type": isKeyword("dummy", "simple", "list"),
|
|
"shield-placements": isString,
|
|
"shield-size": isNumber,
|
|
"shield-spacing": isNumber,
|
|
"shield-text-dx": isNumber,
|
|
"shield-text-dy": isNumber,
|
|
"shield-transform": isKeyword("none", "uppercase", "lowercase", "capitalize"),
|
|
"shield-wrap-before": isBool,
|
|
"shield-wrap-character": isString,
|
|
"shield-wrap-width": isNumber,
|
|
"shield-unlock-image": isBool,
|
|
|
|
"text-allow-overlap": isBool,
|
|
"text-avoid-edges": isBool,
|
|
"text-character-spacing": isNumber,
|
|
"text-clip": isBool,
|
|
"text-dx": isNumber,
|
|
"text-dy": isNumber,
|
|
"text-face-name": isStringOrStrings,
|
|
"text-fill": isColor,
|
|
"text-halo-fill": isColor,
|
|
"text-halo-radius": isNumber,
|
|
"text-line-spacing": isNumber,
|
|
"text-min-distance": isNumber,
|
|
"text-min-padding": isNumber,
|
|
"text-name": isString,
|
|
"text-opacity": isNumber,
|
|
"text-orientation": isFieldOr(isNumber),
|
|
"text-placement": isKeyword("line", "point", "vertex", "interior"),
|
|
"text-placement-type": isKeyword("dummy", "simple", "list"),
|
|
"text-placements": isString,
|
|
"text-size": isNumber,
|
|
"text-spacing": isNumber,
|
|
"text-transform": isKeyword("none", "uppercase", "lowercase", "capitalize"),
|
|
"text-wrap-before": isBool,
|
|
"text-wrap-character": isString,
|
|
"text-wrap-width": isNumber,
|
|
|
|
"raster-opacity": isNumber,
|
|
"raster-scaling": isScaling,
|
|
"raster-colorizer-default-mode": isKeyword("discrete", "linear", "exact"),
|
|
"raster-colorizer-default-color": isColor,
|
|
"raster-colorizer-stops": isStops,
|
|
"raster-comp-op": isCompOp,
|
|
"raster-filter-factor": isNumber,
|
|
"raster-mesh-size": isNumber,
|
|
"raster-epsilon": isNumber,
|
|
}
|
|
}
|
|
|
|
func validProperty(property string, value interface{}) bool {
|
|
checkFunc, ok := attributeTypes[property]
|
|
if !ok {
|
|
return false
|
|
}
|
|
return checkFunc(value)
|
|
}
|