<% const type = locals.type; const layoutProperties = locals.layoutProperties; const paintProperties = locals.paintProperties; const allProperties = paintProperties.concat(layoutProperties); -%> // clang-format off // This file is generated. Edit scripts/generate-style-code.js, then run `make style-code`. #include _layer.hpp> #include _layer_impl.hpp> #include #include #include #include #include #include #include #include #include namespace mbgl { namespace style { <% let layerCapabilities = {}; let defaults = { caps: { 'Source': 'NotRequired', 'Pass3D': 'NotRequired', 'Layout': 'NotRequired', 'FadingTiles': 'NotRequired', 'CrossTileIndex': 'NotRequired', 'TileKind' : 'NotRequired' }, require: function(cap) { let copy = Object.assign({}, this); copy.caps = Object.assign({}, this.caps); copy.caps[cap] = 'Required'; return copy; }, set: function(cap, value) { let copy = Object.assign({}, this); copy.caps = Object.assign({}, this.caps); copy.caps[cap] = value; return copy; }, finalize: function() { return Object.keys(this.caps).reduce((acc, key) => { acc.push(`${key}::${this.caps[key]}`); return acc; }, []); } }; layerCapabilities['background'] = defaults.finalize(); layerCapabilities['fill'] = defaults.require('Source') .require('Layout') .set('TileKind', 'Geometry') .finalize(); layerCapabilities['fill-extrusion'] = defaults.require('Source') .require('Pass3D') .require('Layout') .set('TileKind', 'Geometry') .finalize(); layerCapabilities['hillshade'] = defaults.require('Source') .require('Pass3D') .set('TileKind', 'RasterDEM') .finalize(); layerCapabilities['symbol'] = defaults.require('Source') .require('Layout') .require('FadingTiles') .require('CrossTileIndex') .set('TileKind', 'Geometry') .finalize(); layerCapabilities['circle'] = defaults.require('Source').set('TileKind', 'Geometry').finalize(); layerCapabilities['line'] = layerCapabilities['fill']; layerCapabilities['heatmap'] = defaults.require('Source') .require('Pass3D') .set('TileKind', 'Geometry') .finalize(); layerCapabilities['raster'] = defaults.require('Source').set('TileKind', 'Raster').finalize(); layerCapabilities['location-component'] = defaults.finalize(); // Splits lines that are over 120 characters at the firts occurance of '='. const split120Line = line => { const ident = ' '; if (line.length + ident.length > 120) { return line.replace('=', `=\n${ident}`); } return line; }; %> // static const LayerTypeInfo* <%- camelize(type) %>Layer::Impl::staticTypeInfo() noexcept { const static LayerTypeInfo typeInfo{"<%- type %>", <%-`${layerCapabilities[type].map(cap => `LayerTypeInfo::${cap}`).join(',\n ')}` %>}; return &typeInfo; } <% if (type === 'background' || type === 'location-component') { -%> <%- camelize(type) %>Layer::<%- camelize(type) %>Layer(const std::string& layerID) : Layer(makeMutable(layerID, std::string())) { } <% } else { -%> <%- camelize(type) %>Layer::<%- camelize(type) %>Layer(const std::string& layerID, const std::string& sourceID) : Layer(makeMutable(layerID, sourceID)) { } <% } -%> <%- camelize(type) %>Layer::<%- camelize(type) %>Layer(Immutable impl_) : Layer(std::move(impl_)) { } <%- camelize(type) %>Layer::~<%- camelize(type) %>Layer() = default; const <%- camelize(type) %>Layer::Impl& <%- camelize(type) %>Layer::impl() const { return static_cast(*baseImpl); } Mutable<<%- camelize(type) %>Layer::Impl> <%- camelize(type) %>Layer::mutableImpl() const { return makeMutable(impl()); } std::unique_ptr <%- camelize(type) %>Layer::cloneRef(const std::string& id_) const { auto impl_ = mutableImpl(); impl_->id = id_; impl_->paint = <%- camelize(type) %>PaintProperties::Transitionable(); return std::make_unique<<%- camelize(type) %>Layer>(std::move(impl_)); } <% if (layoutProperties.length) { -%> void <%- camelize(type) %>Layer::Impl::stringifyLayout(rapidjson::Writer& writer) const { layout.stringify(writer); } <% } else { -%> void <%- camelize(type) %>Layer::Impl::stringifyLayout(rapidjson::Writer&) const { } <% } -%> // Layout properties <% for (const property of layoutProperties) { -%> <%- propertyValueType(property) %> <%- camelize(type) %>Layer::getDefault<%- camelize(property.name) %>() { return <%- camelize(property.name) %>::defaultValue(); } const <%- propertyValueType(property) %>& <%- camelize(type) %>Layer::get<%- camelize(property.name) %>() const { return impl().layout.get<<%- camelize(property.name) %>>(); } void <%- camelize(type) %>Layer::set<%- camelize(property.name) %>(const <%- propertyValueType(property) %>& value) { if (value == get<%- camelize(property.name) %>()) return; auto impl_ = mutableImpl(); impl_->layout.get<<%- camelize(property.name) %>>() = value; baseImpl = std::move(impl_); observer->onLayerChanged(*this); } <% } -%> // Paint properties <% for (const property of paintProperties) { %> <%- propertyValueType(property) %> <%- camelize(type) %>Layer::getDefault<%- camelize(property.name) %>() { <% if (property.name === 'heatmap-color') { -%> conversion::Error error; std::string rawValue = R"JSON(<%- JSON.stringify(property.default) %>)JSON"; return *conversion::convertJSON<<%- propertyValueType(property)%>>(rawValue, error); <% } else { -%> return {<%- defaultValue(property) %>}; <% } -%> } const <%- propertyValueType(property) %>& <%- camelize(type) %>Layer::get<%- camelize(property.name) %>() const { return impl().paint.template get<<%- camelize(property.name) %>>().value; } void <%- camelize(type) %>Layer::set<%- camelize(property.name) %>(const <%- propertyValueType(property) %>& value) { if (value == get<%- camelize(property.name) %>()) return; auto impl_ = mutableImpl(); impl_->paint.template get<<%- camelize(property.name) %>>().value = value; <% if (property.name === 'line-width') { -%> impl_->paint.template get().value = value; <% } -%> baseImpl = std::move(impl_); observer->onLayerChanged(*this); } void <%- camelize(type) %>Layer::set<%- camelize(property.name) %>Transition(const TransitionOptions& options) { auto impl_ = mutableImpl(); impl_->paint.template get<<%- camelize(property.name) %>>().options = options; baseImpl = std::move(impl_); } TransitionOptions <%- camelize(type) %>Layer::get<%- camelize(property.name) %>Transition() const { return impl().paint.template get<<%- camelize(property.name) %>>().options; } <% } -%> using namespace conversion; namespace { constexpr uint8_t kPaintPropertyCount = <%- paintProperties.length * 2 -%>u; enum class Property : uint8_t { <% for (const property of paintProperties) { -%> <%- camelize(property.name) %>, <% } -%> <% for (const property of paintProperties) { -%> <%- camelize(property.name) %>Transition, <% } -%> <% for (let i = 0; i < layoutProperties.length; ++i) { -%> <% if (i===0) { -%> <%- camelize(layoutProperties[i].name) %> = kPaintPropertyCount, <% } else { -%> <%- camelize(layoutProperties[i].name) %>, <% } -%> <% } -%> }; template constexpr uint8_t toUint8(T t) noexcept { return uint8_t(mbgl::underlying_type(t)); } MAPBOX_ETERNAL_CONSTEXPR const auto layerProperties = mapbox::eternal::hash_map( {<%- paintProperties.map(p => `{"${p.name}", toUint8(Property::${camelize(p.name)})}`).join(',\n ') %>, <% if (!layoutProperties.length) { -%> <%- paintProperties.map(p => `{"${p.name}-transition", toUint8(Property::${camelize(p.name)}Transition)}`).join(',\n ') %>}); <% } else { -%> <%- paintProperties.map(p => `{"${p.name}-transition", toUint8(Property::${camelize(p.name)}Transition)}`).join(',\n ') %>, <%- layoutProperties.map(p => `{"${p.name}", toUint8(Property::${camelize(p.name)})}`).join(',\n ') %>}); <% } -%> StyleProperty getLayerProperty(const <%- camelize(type) %>Layer& layer, Property property) { switch (property) { <% for (const property of paintProperties) { -%> case Property::<%- camelize(property.name) %>: return makeStyleProperty(layer.get<%- camelize(property.name) %>()); <% } -%> <% for (const property of paintProperties) { -%> case Property::<%- camelize(property.name) %>Transition: return makeStyleProperty(layer.get<%- camelize(property.name) %>Transition()); <% } -%> <% for (const property of layoutProperties) { -%> case Property::<%- camelize(property.name) %>: return makeStyleProperty(layer.get<%- camelize(property.name) %>()); <% } -%> } return {}; } StyleProperty getLayerProperty(const <%- camelize(type) -%>Layer& layer, const std::string& name) { const auto it = layerProperties.find(name.c_str()); if (it == layerProperties.end()) { return {}; } return getLayerProperty(layer, static_cast(it->second)); } } // namespace Value <%- camelize(type) %>Layer::serialize() const { auto result = Layer::serialize(); assert(result.getObject()); for (const auto& property : layerProperties) { auto styleProperty = getLayerProperty(*this, static_cast(property.second)); if (styleProperty.getKind() == StyleProperty::Kind::Undefined) continue; serializeProperty(result, styleProperty, property.first.c_str(), property.second < kPaintPropertyCount); } return result; } optional <%- camelize(type) %>Layer::setPropertyInternal(const std::string& name, const Convertible& value) { const auto it = layerProperties.find(name.c_str()); if (it == layerProperties.end()) return Error{"layer doesn't support this property"}; auto property = static_cast(it->second); <% const conversions = {}; for (const property of allProperties) { const dataDriven = property['property-type'] === 'data-driven' || property['property-type'] === 'cross-faded-data-driven'; const convertTokens = property.name === 'icon-image' || property.name === 'text-field'; const conversion = `const auto& typedValue = convert<${propertyValueType(property)}>(value, error, ${dataDriven}, ${convertTokens})`; conversions[conversion] = conversions[conversion] || []; conversions[conversion].push(property); } const reduceConditions = (total, e) => { const splitter = ' || '; const ident = ' '; let totalLength = total.length + e.length + ident.length + splitter.length + 3 /* ||*/; const lastCR = total.lastIndexOf('\n'); const length = (lastCR == -1) ? totalLength : (totalLength - (ident.length + lastCR)); return total + (length <= 120 ? splitter : ` ||\n${ident}`) + e; } -%> <% for (const key in conversions) { const properties = conversions[key]; -%> if (<%- properties.map(p => `property == Property::${camelize(p.name)}`).reduce(reduceConditions) %>) { Error error; <%- split120Line(key) %>; if (!typedValue) { return error; } <% if (properties.length == 1) { %> set<%- camelize(properties[0].name) %>(*typedValue); return nullopt; <% } else for (const property of properties) { %> if (property == Property::<%- camelize(property.name) %>) { set<%- camelize(property.name) %>(*typedValue); return nullopt; } <% } -%> } <% } %> Error error; optional transition = convert(value, error); if (!transition) { return error; } <% for (const property of paintProperties) { %> if (property == Property::<%- camelize(property.name) %>Transition) { set<%- camelize(property.name) %>Transition(*transition); return nullopt; } <% } %> return Error{"layer doesn't support this property"}; } StyleProperty <%- camelize(type) %>Layer::getProperty(const std::string& name) const { return getLayerProperty(*this, name); } Mutable <%- camelize(type) %>Layer::mutableBaseImpl() const { return staticMutableCast(mutableImpl()); } } // namespace style } // namespace mbgl // clang-format on