Ejemplo n.º 1
0
std::vector<SymbolFeature> SymbolBucket::processFeatures(const GeometryTileLayer& layer,
                                                         const FilterExpression& filter,
                                                         GlyphStore &glyphStore) {
    const bool has_text = !layout.text.field.empty() && !layout.text.font.empty();
    const bool has_icon = !layout.icon.image.empty();

    std::vector<SymbolFeature> features;

    if (!has_text && !has_icon) {
        return features;
    }

    // Determine and load glyph ranges
    std::set<GlyphRange> ranges;

    for (std::size_t i = 0; i < layer.featureCount(); i++) {
        auto feature = layer.getFeature(i);

        GeometryTileFeatureExtractor extractor(*feature);
        if (!evaluate(filter, extractor))
            continue;

        SymbolFeature ft;

        auto getValue = [&feature](const std::string& key) -> std::string {
            auto value = feature->getValue(key);
            return value ? toString(*value) : std::string();
        };

        if (has_text) {
            std::string u8string = util::replaceTokens(layout.text.field, getValue);

            if (layout.text.transform == TextTransformType::Uppercase) {
                u8string = platform::uppercase(u8string);
            } else if (layout.text.transform == TextTransformType::Lowercase) {
                u8string = platform::lowercase(u8string);
            }

            ft.label = util::utf8_to_utf32::convert(u8string);

            if (ft.label.size()) {
                // Loop through all characters of this text and collect unique codepoints.
                for (char32_t chr : ft.label) {
                    ranges.insert(getGlyphRange(chr));
                }
            }
        }

        if (has_icon) {
            ft.sprite = util::replaceTokens(layout.icon.image, getValue);
        }

        if (ft.label.length() || ft.sprite.length()) {

            auto &multiline = ft.geometry;

            GeometryCollection geometryCollection = feature->getGeometries();
            for (auto& line : geometryCollection) {
                multiline.emplace_back();
                for (auto& point : line) {
                    multiline.back().emplace_back(point.x, point.y);
                }
            }

            features.push_back(std::move(ft));
        }
    }

    if (layout.placement == PlacementType::Line) {
        util::mergeLines(features);
    }

    if (glyphStore.requestGlyphRangesIfNeeded(layout.text.font, ranges)) {
        needsGlyphs_ = true;
        return {};
    }

    return features;
}