std::vector<Resource> OfflineDownload::glyphResources(const StyleParser& parser) const { std::vector<Resource> result; if (!parser.glyphURL.empty()) { for (const auto& fontStack : parser.fontStacks()) { for (uint32_t i = 0; i < 256; i++) { result.push_back(Resource::glyphs(parser.glyphURL, fontStack, getGlyphRange(i * 256))); } } } return result; }
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; }
void SymbolBucket::parseFeatures(const GeometryTileLayer& layer, const Filter& filter) { const bool has_text = !layout.textField.value.empty() && !layout.textFont.value.empty(); const bool has_icon = !layout.iconImage.value.empty(); if (!has_text && !has_icon) { return; } auto layerName = layer.getName(); // Determine and load glyph ranges const GLsizei featureCount = static_cast<GLsizei>(layer.featureCount()); for (GLsizei i = 0; i < featureCount; i++) { auto feature = layer.getFeature(i); FilterEvaluator evaluator(*feature); if (!Filter::visit(filter, evaluator)) continue; SymbolFeature ft; ft.index = i; auto getValue = [&feature](const std::string& key) -> std::string { auto value = feature->getValue(key); if (!value) return std::string(); if (value->is<std::string>()) return value->get<std::string>(); if (value->is<bool>()) return value->get<bool>() ? "true" : "false"; if (value->is<int64_t>()) return util::toString(value->get<int64_t>()); if (value->is<uint64_t>()) return util::toString(value->get<uint64_t>()); if (value->is<double>()) return util::toString(value->get<double>()); return "null"; }; if (has_text) { std::string u8string = util::replaceTokens(layout.textField, getValue); if (layout.textTransform == TextTransformType::Uppercase) { u8string = platform::uppercase(u8string); } else if (layout.textTransform == TextTransformType::Lowercase) { u8string = platform::lowercase(u8string); } ft.label = util::utf8_to_utf32::convert(u8string); if (!ft.label.empty()) { // 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.iconImage, getValue); } if (ft.label.length() || ft.sprite.length()) { auto &multiline = ft.geometry; GeometryCollection geometryCollection = getGeometries(*feature); 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.symbolPlacement == SymbolPlacementType::Line) { util::mergeLines(features); } }