Skip to content

Mapbox Style JSON

Nimbus parses and evaluates Mapbox Style Spec JSON for data-driven rendering. The style system lives across three modules:

  • src/style.rs — JSON deserialization (sources, layers, metadata)
  • src/style_eval/ — filter compilation, paint/layout resolution
  • src/styler/ — Google Maps styler JSON transforms

Supported Layer Types

Type Paint properties Layout properties
background background-color
fill fill-color, fill-opacity visibility
line line-color, line-width, line-opacity visibility, line-cap
symbol icon-color, icon-opacity, text-color, text-opacity, text-halo-color, text-halo-width icon-image, text-field, text-font, text-size, text-anchor, text-offset, text-variable-anchor, text-radial-offset, symbol-placement, visibility

Style Resolution Pipeline

graph LR
    A[style.json] -->|deserialize| B[Style struct]
    B -->|resolve_style| C[Vec of ResolvedLayer]
    C -->|compile filters| D[CompiledFilter per layer]
    C -->|resolve paint| E[StyleValue per property]

ResolvedLayer

resolve_style() compiles the raw JSON into a Vec<ResolvedLayer>, each containing:

  • A CompiledFilter for feature matching
  • StyleValue<T> for each paint/layout property (constant, zoom function, or expression)
  • Optional feature_type and element_types for Google Maps styler matching
  • visible flag (layers with visibility: "none" are kept but marked invisible)

Filters

Two filter syntaxes are supported:

["==", "class", "motorway"]
["==", ["get", "class"], "motorway"]

Filters are compiled into CompiledFilter at style load time and evaluated per-feature during extraction.

Paint Values

Paint properties resolve to StyleValue<T>, which can be:

  • Constant — a single value (e.g., "#ff0000")
  • Zoom function — legacy stops array or modern interpolate/step expression
  • Data expression — depends on feature properties (e.g., ["get", "height"])

Color Parsing

src/color.rs provides parse_color() supporting:

  • Hex: #rgb, #rrggbb, #rrggbbaa
  • Functions: rgb(), rgba(), hsla()
  • Named colors: red, blue, transparent, etc.

Colors are stored as [f32; 4] (linear RGBA). sRGB correction (pow(c, 2.2)) is applied in the shader via a branchless approximation.

Google Maps Styler

src/styler/ applies Google Maps-style JSON rules to modify layer colors after the Mapbox style is loaded.

map_renderer.apply_styler(r#"[
    {"featureType": "water", "elementType": "geometry.fill",
     "stylers": [{"color": "#529acc"}]}
]"#)?;

How It Works

  1. Builds a Tree<T> from dot-separated featureType paths (e.g., poi.medical)
  2. Matches rules to resolved layers by feature type and element type
  3. Applies HSL delta transforms: color, hue, saturation, lightness, invert_lightness, gamma, visibility
  4. Only transforms StyleValue::Constant (zoom functions are left as-is)

POI Expansion

Enabled POI classes are expanded into individual ResolvedLayer entries (one per class) rather than using case expressions. This gives each POI class its own filter, icon, and color:

poi.medical → medical.pharmacy, medical.hospital, ...

Prefix matching: rule "poi.medical" enables both "medical.pharmacy" and "medical.hospital".