Commit 8251eaad authored by Volker Krause's avatar Volker Krause
Browse files

Prepare MapCSSResult for carrying results for multiple layer selectors

This is neither properly filled nor consumed yet.
parent f073f240
......@@ -190,7 +190,7 @@ void MapData::processElements()
MapCSSState filterState;
filterState.element = e;
filter.evaluate(filterState, filterResult);
if (auto prop = filterResult.declaration(MapCSSDeclaration::Opacity)) {
if (auto prop = filterResult[{}].declaration(MapCSSDeclaration::Opacity)) {
if (prop->doubleValue() == 0.0) {
qDebug() << "input filter dropped" << e.url();
return;
......
......@@ -192,7 +192,7 @@ void SceneController::updateCanvas(SceneGraph &sg) const
state.zoomLevel = d->m_view->zoomLevel();
state.floorLevel = d->m_view->level();
d->m_styleSheet->evaluateCanvas(state, d->m_styleResult);
for (auto decl : d->m_styleResult.declarations()) {
for (auto decl : d->m_styleResult[{}].declarations()) {
switch (decl->property()) {
case MapCSSDeclaration::FillColor:
sg.setBackgroundColor(decl->colorValue());
......@@ -214,8 +214,14 @@ void SceneController::updateElement(OSM::Element e, int level, SceneGraph &sg) c
state.floorLevel = d->m_view->level();
state.openingHours = &d->m_openingHours;
d->m_styleSheet->evaluate(state, d->m_styleResult);
for (const auto &result : d->m_styleResult.results()) {
updateElement(e, level, sg, result);
}
}
if (d->m_styleResult.hasAreaProperties()) {
void SceneController::updateElement(OSM::Element e, int level, SceneGraph &sg, const MapCSSResultItem &result) const
{
if (result.hasAreaProperties()) {
PolygonBaseItem *item = nullptr;
std::unique_ptr<SceneGraphItemPayload> baseItem;
if (e.type() == OSM::Type::Relation && e.tagValue(d->m_typeTag) == "multipolygon") {
......@@ -223,7 +229,7 @@ void SceneController::updateElement(OSM::Element e, int level, SceneGraph &sg) c
auto i = static_cast<MultiPolygonItem*>(baseItem.get());
if (i->path.isEmpty()) {
i->path = createPath(e, d->m_labelPlacementPath);
} else if (d->m_styleResult.hasLabelProperties()) {
} else if (result.hasLabelProperties()) {
SceneGeometry::outerPolygonFromPath(i->path, d->m_labelPlacementPath);
}
item = i;
......@@ -240,7 +246,7 @@ void SceneController::updateElement(OSM::Element e, int level, SceneGraph &sg) c
double lineOpacity = 1.0;
double fillOpacity = 1.0;
initializePen(item->pen);
for (auto decl : d->m_styleResult.declarations()) {
for (auto decl : result.declarations()) {
applyGenericStyle(decl, item);
applyPenStyle(e, decl, item->pen, lineOpacity, item->penWidthUnit);
switch (decl->property()) {
......@@ -266,7 +272,7 @@ void SceneController::updateElement(OSM::Element e, int level, SceneGraph &sg) c
}
addItem(sg, e, level, std::move(baseItem));
} else if (d->m_styleResult.hasLineProperties()) {
} else if (result.hasLineProperties()) {
auto baseItem = sg.findOrCreatePayload<PolylineItem>(e, level);
auto item = static_cast<PolylineItem*>(baseItem.get());
if (item->path.isEmpty()) {
......@@ -277,7 +283,7 @@ void SceneController::updateElement(OSM::Element e, int level, SceneGraph &sg) c
double casingOpacity = 1.0;
initializePen(item->pen);
initializePen(item->casingPen);
for (auto decl : d->m_styleResult.declarations()) {
for (auto decl : result.declarations()) {
applyGenericStyle(decl, item);
applyPenStyle(e, decl, item->pen, lineOpacity, item->penWidthUnit);
applyCasingPenStyle(e, decl, item->casingPen, casingOpacity, item->casingPenWidthUnit);
......@@ -289,11 +295,11 @@ void SceneController::updateElement(OSM::Element e, int level, SceneGraph &sg) c
addItem(sg, e, level, std::move(baseItem));
}
if (d->m_styleResult.hasLabelProperties()) {
if (result.hasLabelProperties()) {
QString text;
auto textDecl = d->m_styleResult.declaration(MapCSSDeclaration::Text);
auto textDecl = result.declaration(MapCSSDeclaration::Text);
if (!textDecl) {
textDecl = d->m_styleResult.declaration(MapCSSDeclaration::ShieldText);
textDecl = result.declaration(MapCSSDeclaration::ShieldText);
}
if (textDecl) {
......@@ -304,7 +310,7 @@ void SceneController::updateElement(OSM::Element e, int level, SceneGraph &sg) c
}
}
const auto iconDecl = d->m_styleResult.declaration(MapCSSDeclaration::IconImage);
const auto iconDecl = result.declaration(MapCSSDeclaration::IconImage);
if (!text.isEmpty() || iconDecl) {
auto baseItem = sg.findOrCreatePayload<LabelItem>(e, level);
......@@ -314,9 +320,9 @@ void SceneController::updateElement(OSM::Element e, int level, SceneGraph &sg) c
item->color = d->m_defaultTextColor;
if (item->pos.isNull()) {
if (d->m_styleResult.hasAreaProperties()) {
if (result.hasAreaProperties()) {
item->pos = SceneGeometry::polygonCentroid(d->m_labelPlacementPath);
} else if (d->m_styleResult.hasLineProperties()) {
} else if (result.hasLineProperties()) {
item->pos = SceneGeometry::polylineMidPoint(d->m_labelPlacementPath);
}
if (item->pos.isNull()) {
......@@ -327,7 +333,7 @@ void SceneController::updateElement(OSM::Element e, int level, SceneGraph &sg) c
double textOpacity = 1.0;
double shieldOpacity = 1.0;
IconData iconData;
for (auto decl : d->m_styleResult.declarations()) {
for (auto decl : result.declarations()) {
applyGenericStyle(decl, item);
applyFontStyle(decl, item->font);
switch (decl->property()) {
......@@ -435,7 +441,7 @@ void SceneController::updateElement(OSM::Element e, int level, SceneGraph &sg) c
item->text.prepare({}, item->font);
// discard labels that are longer than the line they are aligned with
if (d->m_styleResult.hasLineProperties() && d->m_labelPlacementPath.size() > 1 && item->angle != 0.0) {
if (result.hasLineProperties() && d->m_labelPlacementPath.size() > 1 && item->angle != 0.0) {
const auto sceneLen = SceneGeometry::polylineLength(d->m_labelPlacementPath);
const auto sceneP1 = d->m_view->viewport().topLeft();
const auto sceneP2 = QPointF(sceneP1.x() + sceneLen, sceneP1.y());
......
......@@ -26,6 +26,7 @@ namespace KOSMIndoorMap {
class AbstractOverlaySource;
class MapData;
class MapCSSDeclaration;
class MapCSSResultItem;
class MapCSSStyle;
class SceneControllerPrivate;
class SceneGraph;
......@@ -53,6 +54,7 @@ public:
private:
void updateCanvas(SceneGraph &sg) const;
void updateElement(OSM::Element e, int level, SceneGraph &sg) const;
void updateElement(OSM::Element e, int level, SceneGraph &sg, const MapCSSResultItem &result) const;
QPolygonF createPolygon(OSM::Element e) const;
QPainterPath createPath(OSM::Element e, QPolygonF &outerPath) const;
......
......@@ -10,32 +10,33 @@
using namespace KOSMIndoorMap;
MapCSSResult::MapCSSResult() = default;
MapCSSResult::~MapCSSResult() = default;
MapCSSResultItem::MapCSSResultItem() = default;
MapCSSResultItem::~MapCSSResultItem() = default;
void MapCSSResult::clear()
void MapCSSResultItem::clear()
{
m_declarations.clear();
m_classes.clear();
m_flags = MapCSSDeclaration::NoFlag;
m_layer = {};
}
bool MapCSSResult::hasAreaProperties() const
bool MapCSSResultItem::hasAreaProperties() const
{
return m_flags & MapCSSDeclaration::AreaProperty;
}
bool MapCSSResult::hasLineProperties() const
bool MapCSSResultItem::hasLineProperties() const
{
return m_flags & MapCSSDeclaration::LineProperty;
}
bool MapCSSResult::hasLabelProperties() const
bool MapCSSResultItem::hasLabelProperties() const
{
return m_flags & MapCSSDeclaration::LabelProperty;
}
const MapCSSDeclaration* MapCSSResult::declaration(MapCSSDeclaration::Property prop) const
const MapCSSDeclaration* MapCSSResultItem::declaration(MapCSSDeclaration::Property prop) const
{
const auto it = std::lower_bound(m_declarations.begin(), m_declarations.end(), prop, [](auto lhs, auto rhs) {
return lhs->property() < rhs;
......@@ -46,12 +47,12 @@ const MapCSSDeclaration* MapCSSResult::declaration(MapCSSDeclaration::Property p
return (*it);
}
const std::vector<const MapCSSDeclaration*>& MapCSSResult::declarations() const
const std::vector<const MapCSSDeclaration*>& MapCSSResultItem::declarations() const
{
return m_declarations;
}
void MapCSSResult::addDeclaration(const MapCSSDeclaration *decl)
void MapCSSResultItem::addDeclaration(const MapCSSDeclaration *decl)
{
const auto it = std::lower_bound(m_declarations.begin(), m_declarations.end(), decl, [](auto lhs, auto rhs) {
return lhs->property() < rhs->property();
......@@ -65,7 +66,7 @@ void MapCSSResult::addDeclaration(const MapCSSDeclaration *decl)
m_flags |= decl->propertyFlags();
}
void MapCSSResult::addClass(ClassSelectorKey cls)
void MapCSSResultItem::addClass(ClassSelectorKey cls)
{
const auto it = std::lower_bound(m_classes.begin(), m_classes.end(), cls);
if (it == m_classes.end() || (*it) != cls) {
......@@ -73,7 +74,70 @@ void MapCSSResult::addClass(ClassSelectorKey cls)
}
}
bool MapCSSResult::hasClass(ClassSelectorKey cls) const
bool MapCSSResultItem::hasClass(ClassSelectorKey cls) const
{
return std::binary_search(m_classes.begin(), m_classes.end(), cls);
}
LayerSelectorKey MapCSSResultItem::layerSelector() const
{
return m_layer;
}
void MapCSSResultItem::setLayerSelector(LayerSelectorKey layer)
{
m_layer = layer;
}
MapCSSResult::MapCSSResult() = default;
MapCSSResult::~MapCSSResult() = default;
void MapCSSResult::clear()
{
std::move(m_results.begin(), m_results.end(), std::back_inserter(m_inactivePool));
m_results.clear();
std::for_each(m_inactivePool.begin(), m_inactivePool.end(), std::mem_fn(&MapCSSResultItem::clear));
}
const std::vector<MapCSSResultItem>& MapCSSResult::results() const
{
return m_results;
}
MapCSSResultItem& MapCSSResult::operator[](LayerSelectorKey layer)
{
const auto it = std::find_if(m_results.begin(), m_results.end(), [layer](const auto &res) {
return res.layerSelector() == layer;
});
if (it != m_results.end()) {
return *it;
}
if (!m_inactivePool.empty()) {
auto res = std::move(m_inactivePool.back());
m_inactivePool.pop_back();
res.setLayerSelector(layer);
m_results.push_back(std::move(res));
} else {
MapCSSResultItem res;
res.setLayerSelector(layer);
m_results.push_back(std::move(res));
}
return m_results.back();
}
const MapCSSResultItem& MapCSSResult::operator[](LayerSelectorKey layer) const
{
const auto it = std::find_if(m_results.begin(), m_results.end(), [layer](const auto &res) {
return res.layerSelector() == layer;
});
if (it != m_results.end()) {
return *it;
}
if (m_inactivePool.empty()) {
m_inactivePool.push_back(MapCSSResultItem());
}
return m_inactivePool.back();
}
......@@ -14,12 +14,12 @@
namespace KOSMIndoorMap {
/** Result of MapCSS stylesheet evaluation. */
class MapCSSResult
/** Result of MapCSS stylesheet evaluation for a single layer selector. */
class MapCSSResultItem
{
public:
explicit MapCSSResult();
~MapCSSResult();
explicit MapCSSResultItem();
~MapCSSResultItem();
void clear();
......@@ -35,17 +35,43 @@ public:
/** The active declarations for the queried element. */
const std::vector<const MapCSSDeclaration*>& declarations() const;
/** The layer selector for this result. */
LayerSelectorKey layerSelector() const;
/** @internal */
void addDeclaration(const MapCSSDeclaration *decl);
void addClass(ClassSelectorKey cls);
bool hasClass(ClassSelectorKey cls) const;
void setLayerSelector(LayerSelectorKey layer);
private:
std::vector<const MapCSSDeclaration*> m_declarations;
std::vector<ClassSelectorKey> m_classes;
LayerSelectorKey m_layer;
int m_flags = 0;
};
/** Result of MapCSS stylesheet evaluation for all layer selectors. */
class MapCSSResult
{
public:
explicit MapCSSResult();
~MapCSSResult();
void clear();
/** Results for all layer selectors. */
const std::vector<MapCSSResultItem>& results() const;
/** @internal */
MapCSSResultItem& operator[](LayerSelectorKey layer);
const MapCSSResultItem& operator[](LayerSelectorKey layer) const;
private:
std::vector<MapCSSResultItem> m_results;
mutable std::vector<MapCSSResultItem> m_inactivePool; // for reuse of already allocated result items
};
}
#endif // KOSMINDOORMAP_MAPCSSRESULT_P_H
......@@ -34,10 +34,10 @@ void MapCSSRule::evaluate(const MapCSSState &state, MapCSSResult &result) const
for (const auto &decl : m_declarations) {
switch (decl->type()) {
case MapCSSDeclaration::PropertyDeclaration:
result.addDeclaration(decl.get());
result[{}].addDeclaration(decl.get());
break;
case MapCSSDeclaration::ClassDeclaration:
result.addClass(decl->classSelectorKey());
result[{}].addClass(decl->classSelectorKey());
break;
case MapCSSDeclaration::TagDeclaration:
// TODO
......@@ -55,7 +55,7 @@ void MapCSSRule::evaluateCanvas(const MapCSSState &state, MapCSSResult &result)
for (const auto &decl : m_declarations) {
if (decl->type() == MapCSSDeclaration::PropertyDeclaration) {
result.addDeclaration(decl.get());
result[{}].addDeclaration(decl.get());
}
}
}
......
......@@ -72,7 +72,7 @@ bool MapCSSBasicSelector::matches(const MapCSSState &state, const MapCSSResult &
case Any: break;
}
if (!m_class.isNull() && !result.hasClass(m_class)) {
if (!m_class.isNull() && !result[m_layer].hasClass(m_class)) {
return false;
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment