#pragma once #include #include #include #include #include #include #include namespace mbgl { class PatternDependency { public: std::string min; std::string mid; std::string max; }; using PatternLayerMap = std::map; class PatternFeature { public: PatternFeature(std::size_t i_, std::unique_ptr feature_, PatternLayerMap patterns_, float sortKey_ = 0.0f) : i(i_), feature(std::move(feature_)), patterns(std::move(patterns_)), sortKey(sortKey_) {} friend bool operator<(const PatternFeature& lhs, const PatternFeature& rhs) { return lhs.sortKey < rhs.sortKey; } std::size_t i; std::unique_ptr feature; PatternLayerMap patterns; float sortKey; }; template struct PatternFeatureInserter; template <> struct PatternFeatureInserter { template static void insert(std::vector& features, std::size_t index, std::unique_ptr feature, PatternLayerMap patternDependencyMap, float /*zoom*/, const PropertiesType&, const CanonicalTileID&) { features.emplace_back(index, std::move(feature), std::move(patternDependencyMap)); } }; template struct PatternFeatureInserter { template static void insert(std::vector& features, std::size_t index, std::unique_ptr feature, PatternLayerMap patternDependencyMap, float zoom, const PropertiesType& properties, const CanonicalTileID& canonical) { const auto& sortKeyProperty = properties.template get(); float sortKey = sortKeyProperty.evaluate(*feature, zoom, canonical, SortKeyPropertyType::defaultValue()); PatternFeature patternFeature{index, std::move(feature), std::move(patternDependencyMap), sortKey}; const auto lowerBound = std::lower_bound(features.cbegin(), features.cend(), patternFeature); features.insert(lowerBound, std::move(patternFeature)); } }; template , class SortKeyPropertyType = void> class PatternLayout : public Layout { public: PatternLayout(const BucketParameters& parameters, const std::vector>& group, std::unique_ptr sourceLayer_, const LayoutParameters& layoutParameters) : sourceLayer(std::move(sourceLayer_)), zoom(parameters.tileID.overscaledZ), overscaling(parameters.tileID.overscaleFactor()), hasPattern(false) { assert(!group.empty()); auto leaderLayerProperties = staticImmutableCast(group.front()); layout = leaderLayerProperties->layerImpl().layout.evaluate(PropertyEvaluationParameters(zoom)); sourceLayerID = leaderLayerProperties->layerImpl().sourceLayer; bucketLeaderID = leaderLayerProperties->layerImpl().id; for (const auto& layerProperties : group) { const std::string& layerId = layerProperties->baseImpl->id; const auto& evaluated = style::getEvaluated(layerProperties); const auto& patternProperty = evaluated.template get(); const auto constantPattern = patternProperty.constantOr(Faded{"", ""}); // determine if layer group has any layers that use *-pattern property and add // constant pattern dependencies. if (!patternProperty.isConstant()) { hasPattern = true; } else if (!constantPattern.to.id().empty()) { hasPattern = true; layoutParameters.imageDependencies.emplace(constantPattern.to.id(), ImageType::Pattern); layoutParameters.imageDependencies.emplace(constantPattern.from.id(), ImageType::Pattern); } layerPropertiesMap.emplace(layerId, layerProperties); } const size_t featureCount = sourceLayer->featureCount(); for (size_t i = 0; i < featureCount; ++i) { auto feature = sourceLayer->getFeature(i); if (!leaderLayerProperties->layerImpl().filter( style::expression::EvaluationContext(this->zoom, feature.get()) .withCanonicalTileID(¶meters.tileID.canonical))) continue; PatternLayerMap patternDependencyMap; if (hasPattern) { for (const auto& layerProperties : group) { const std::string& layerId = layerProperties->baseImpl->id; const auto it = layerPropertiesMap.find(layerId); if (it != layerPropertiesMap.end()) { const auto paint = static_cast(*it->second).evaluated; const auto& patternProperty = paint.template get(); if (!patternProperty.isConstant()) { // For layers with non-data-constant pattern properties, evaluate their expression and add // the patterns to the dependency vector const auto min = patternProperty.evaluate(*feature, zoom - 1, layoutParameters.availableImages, parameters.tileID.canonical, PatternPropertyType::defaultValue()); const auto mid = patternProperty.evaluate(*feature, zoom, layoutParameters.availableImages, parameters.tileID.canonical, PatternPropertyType::defaultValue()); const auto max = patternProperty.evaluate(*feature, zoom + 1, layoutParameters.availableImages, parameters.tileID.canonical, PatternPropertyType::defaultValue()); layoutParameters.imageDependencies.emplace(min.to.id(), ImageType::Pattern); layoutParameters.imageDependencies.emplace(mid.to.id(), ImageType::Pattern); layoutParameters.imageDependencies.emplace(max.to.id(), ImageType::Pattern); patternDependencyMap.emplace(layerId, PatternDependency{min.to.id(), mid.to.id(), max.to.id()}); } } } } PatternFeatureInserter::insert(features, i, std::move(feature), std::move(patternDependencyMap), zoom, layout, parameters.tileID.canonical); } }; bool hasDependencies() const override { return hasPattern; } void createBucket(const ImagePositions& patternPositions, std::unique_ptr& featureIndex, std::unordered_map& renderData, const bool /*firstLoad*/, const bool /*showCollisionBoxes*/, const CanonicalTileID& canonical) override { auto bucket = std::make_shared(layout, layerPropertiesMap, zoom, overscaling); for (auto & patternFeature : features) { const auto i = patternFeature.i; std::unique_ptr feature = std::move(patternFeature.feature); const PatternLayerMap& patterns = patternFeature.patterns; const GeometryCollection& geometries = feature->getGeometries(); bucket->addFeature(*feature, geometries, patternPositions, patterns, i, canonical); featureIndex->insert(geometries, i, sourceLayerID, bucketLeaderID); } if (bucket->hasData()) { for (const auto& pair : layerPropertiesMap) { renderData.emplace(pair.first, LayerRenderData {bucket, pair.second}); } } }; protected: std::map> layerPropertiesMap; std::string bucketLeaderID; const std::unique_ptr sourceLayer; std::vector features; typename LayoutPropertiesType::PossiblyEvaluated layout; const float zoom; const uint32_t overscaling; std::string sourceLayerID; bool hasPattern; }; } // namespace mbgl