File indexing completed on 2024-11-17 04:17:27
0001 /* 0002 SPDX-FileCopyrightText: 2020 Volker Krause <vkrause@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "mapcssstyle.h" 0008 #include "mapcssstyle_p.h" 0009 #include "mapcssparser.h" 0010 #include "mapcssresult.h" 0011 #include "mapcssrule_p.h" 0012 #include "mapcssstate_p.h" 0013 #include "mapcsstypes.h" 0014 0015 #include <QDebug> 0016 #include <QIODevice> 0017 0018 using namespace KOSMIndoorMap; 0019 0020 MapCSSStyle::MapCSSStyle() 0021 : d(new MapCSSStylePrivate) 0022 {} 0023 0024 MapCSSStyle::MapCSSStyle(MapCSSStyle&&) noexcept = default; 0025 MapCSSStyle::~MapCSSStyle() = default; 0026 MapCSSStyle& MapCSSStyle::operator=(MapCSSStyle&&) noexcept = default; 0027 0028 bool MapCSSStyle::isEmpty() const 0029 { 0030 return d->m_rules.empty(); 0031 } 0032 0033 void MapCSSStyle::compile(const OSM::DataSet &dataSet) 0034 { 0035 d->m_areaKey = dataSet.tagKey("area"); 0036 d->m_typeKey = dataSet.tagKey("type"); 0037 for (const auto &rule : d->m_rules) { 0038 rule->compile(dataSet); 0039 } 0040 } 0041 0042 void MapCSSStyle::evaluate(MapCSSState &&state, MapCSSResult &result) const 0043 { 0044 result.clear(); 0045 0046 // determine object type of the input element 0047 // This involves tag lookups (and thus cost), but as long as there is at least 0048 // one area and one line selector for each zoom level this is break-even. In practice 0049 // there are actually many more than that, which means this is a useful optimization 0050 // over doing this in MapCSSBasicSelector after checking for the zoom level 0051 switch (state.element.type()) { 0052 case OSM::Type::Null: 0053 Q_UNREACHABLE(); 0054 case OSM::Type::Node: 0055 state.objectType = MapCSSObjectType::Node; 0056 break; 0057 case OSM::Type::Way: 0058 { 0059 if (!state.element.way()->isClosed()) { 0060 state.objectType = MapCSSObjectType::Line; 0061 break; 0062 } 0063 const auto area = state.element.tagValue(d->m_areaKey); 0064 if (area == "yes") { 0065 state.objectType = MapCSSObjectType::Area; 0066 } else { 0067 state.objectType = MapCSSObjectType::LineOrArea; 0068 } 0069 break; 0070 } 0071 case OSM::Type::Relation: 0072 state.objectType = state.element.tagValue(d->m_typeKey) == "multipolygon" ? MapCSSObjectType::Area : MapCSSObjectType::Relation; 0073 break; 0074 } 0075 0076 for (const auto &rule : d->m_rules) { 0077 rule->evaluate(state, result); 0078 } 0079 } 0080 0081 void MapCSSStyle::evaluateCanvas(const MapCSSState &state, MapCSSResult &result) const 0082 { 0083 result.clear(); 0084 for (const auto &rule : d->m_rules) { 0085 rule->evaluateCanvas(state, result); 0086 } 0087 } 0088 0089 void MapCSSStyle::write(QIODevice *out) const 0090 { 0091 for (const auto &rule : d->m_rules) { 0092 rule->write(out); 0093 } 0094 } 0095 0096 ClassSelectorKey MapCSSStyle::classKey(const char *className) const 0097 { 0098 return d->m_classSelectorRegistry.key(className); 0099 } 0100 0101 LayerSelectorKey MapCSSStyle::layerKey(const char *layerName) const 0102 { 0103 return d->m_layerSelectorRegistry.key(layerName); 0104 }