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