File indexing completed on 2025-01-05 04:01:19

0001 /*
0002  * SPDX-FileCopyrightText: 2019-2023 Mattia Basaglia <dev@dragon.best>
0003  *
0004  * SPDX-License-Identifier: GPL-3.0-or-later
0005  */
0006 
0007 #pragma once
0008 
0009 #include <map>
0010 #include <unordered_set>
0011 
0012 #include <QColor>
0013 #include <QDomNodeList>
0014 
0015 #include "app/utils/qstring_hash.hpp"
0016 
0017 namespace glaxnimate::io::svg::detail {
0018 
0019 extern const std::map<QString, QString> xmlns;
0020 
0021 struct Style
0022 {
0023 public:
0024     using Map = std::map<QString, QString>;
0025 
0026     Style(Map&& map) : map(std::move(map)) {}
0027     Style() = default;
0028 
0029     QString& operator[](const QString& s) { return map[s]; }
0030     const QString& operator[](const QString& s) const { return map.at(s); }
0031     const QString& get(const QString& k, const QString& def = {}) const
0032     {
0033         auto it = map.find(k);
0034         if ( it == map.end() )
0035             return def;
0036         return it->second;
0037     }
0038     void set(const QString& k, const QString& v)
0039     {
0040         map[k] = v;
0041     }
0042 
0043     bool contains(const QString& k) const { return map.count(k); }
0044 
0045     Map map;
0046     QColor color = Qt::black;
0047 };
0048 
0049 extern const std::unordered_set<QString> css_atrrs;
0050 
0051 
0052 template<class T>
0053 struct ItemCountRange
0054 {
0055 //         using value_type = decltype(std::declval<T>().item(0));
0056     struct iterator
0057     {
0058         auto operator*() const { return range->dom_list.item(index); }
0059         iterator& operator++() { index++; return *this; }
0060         bool operator != (const iterator& it) const
0061         {
0062             return range != it.range || index != it.index;
0063         }
0064 
0065         const ItemCountRange* range;
0066         int index;
0067     };
0068 
0069     ItemCountRange(const T& dom_list) : dom_list(dom_list) {}
0070     iterator begin() const { return {this, 0}; }
0071     iterator end() const { return {this, dom_list.count()}; }
0072     int size() const { return dom_list.count(); }
0073 
0074     T dom_list;
0075 };
0076 
0077 struct ElementRange
0078 {
0079     struct iterator
0080     {
0081         auto operator*() const { return range->dom_list.item(index).toElement(); }
0082 
0083         iterator& operator++()
0084         {
0085             index++;
0086             while ( index < range->dom_list.count() && !acceptable() )
0087                 index++;
0088             return *this;
0089 
0090         }
0091 
0092         bool operator != (const iterator& it) const
0093         {
0094             return range != it.range || index != it.index;
0095         }
0096 
0097         bool acceptable() const
0098         {
0099             if ( !range->dom_list.item(index).isElement() )
0100                 return false;
0101 
0102             if ( range->tag_name.isEmpty() )
0103                 return true;
0104 
0105             return range->dom_list.item(index).toElement().tagName() == range->tag_name;
0106         }
0107 
0108         const ElementRange* range;
0109         int index;
0110     };
0111 
0112     ElementRange(const QDomNodeList& dom_list, QString tag_name = {})
0113         : dom_list(dom_list), tag_name(std::move(tag_name)) {}
0114     ElementRange(const QDomElement& el, QString tag_name = {})
0115         : dom_list(el.childNodes()), tag_name(std::move(tag_name)) {}
0116     iterator begin() const { return {this, 0}; }
0117     iterator end() const { return {this, dom_list.count()}; }
0118     int size() const { return dom_list.count(); }
0119 
0120     QDomNodeList dom_list;
0121     QString tag_name;
0122 };
0123 
0124 } // io::svg::detail