The Birdfont Source Code


All Repositories / birdfont.git / blob – RSS feed

SelectorTag.vala in libsvgbird

This file is a part of the Birdfont project.

Contributing

Send patches or pull requests to johan.mattsson.m@gmail.com.
Clone this repository: git clone https://github.com/johanmattssonm/birdfont.git

Revisions

View the latest version of libsvgbird/SelectorTag.vala.
Bounding box for SVG rectangles
1 /* 2 Copyright (C) 2016 Johan Mattsson 3 4 This library is free software; you can redistribute it and/or modify 5 it under the terms of the GNU Lesser General Public License as 6 published by the Free Software Foundation; either version 3 of the 7 License, or (at your option) any later version. 8 9 This library is distributed in the hope that it will be useful, but 10 WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 Lesser General Public License for more details. 13 */ 14 15 using B; 16 using Math; 17 18 namespace SvgBird { 19 20 /** A part of a CSS selector pattern. */ 21 public class SelectorTag : GLib.Object { 22 public string name; 23 string? id = null; 24 string? css_class = null; 25 Gee.ArrayList<AttributePattern>? attribute_patterns = null; 26 27 public SelectorTag.empty () { 28 } 29 30 public SelectorTag (string pattern) { 31 string tag_pattern = pattern.strip (); 32 int id_separator = tag_pattern.index_of ("#"); 33 int class_separator = tag_pattern.index_of ("."); 34 int attribute_separator = tag_pattern.index_of ("["); 35 36 if (attribute_separator != -1) { 37 parse_attributes (tag_pattern.substring (attribute_separator)); 38 } 39 40 if (id_separator != -1) { 41 name = tag_pattern.substring (0, id_separator); 42 43 id_separator += "#".length; 44 if (attribute_separator == -1) { 45 id = tag_pattern.substring (id_separator); 46 } else { 47 id = tag_pattern.substring (id_separator, attribute_separator - id_separator); 48 } 49 } else if (class_separator != -1) { 50 name = tag_pattern.substring (0, class_separator); 51 52 class_separator += ".".length; 53 if (attribute_separator == -1) { 54 css_class = tag_pattern.substring (class_separator); 55 } else { 56 css_class = tag_pattern.substring (class_separator, attribute_separator - class_separator); 57 } 58 } else { 59 if (attribute_separator == -1) { 60 name = tag_pattern; 61 } else { 62 css_class = tag_pattern.substring (0, attribute_separator); 63 } 64 } 65 } 66 67 public SelectorTag copy () { 68 SelectorTag tag = new SelectorTag.empty(); 69 70 tag.name = name; 71 tag.id = id; 72 tag.css_class = css_class; 73 74 if (attribute_patterns != null) { 75 foreach (AttributePattern p in (!) attribute_patterns) { 76 ((!) attribute_patterns).add (p.copy ()); 77 } 78 } 79 80 return tag; 81 } 82 83 void parse_attributes (string attributes) { 84 int index = 0; 85 Gee.ArrayList<AttributePattern> patterns = new Gee.ArrayList<AttributePattern> (); 86 87 while (index != -1) { 88 int start = attributes.index_of ("[", index); 89 90 if (start == -1) { 91 return; 92 } 93 94 int stop = attributes.index_of ("]", start); 95 96 if (stop == -1) { 97 return; 98 } 99 100 AttributePattern pattern; 101 pattern = parse_attribute (attributes.substring (start, stop)); 102 patterns.add (pattern); 103 104 index = stop + "]".length; 105 } 106 107 attribute_patterns = patterns; 108 } 109 110 AttributePattern parse_attribute (string attribute) { 111 int starts_with = attribute.index_of ("|="); 112 int in_list = attribute.index_of ("~="); 113 int equals = attribute.index_of ("="); 114 AttributePattern pattern = new AttributePattern (); 115 116 if (starts_with != -1) { 117 pattern.name = attribute.substring (0, starts_with); 118 pattern.type = AttributePatternType.STARTS_WITH; 119 pattern.content = attribute.substring (0, equals + "~=".length); 120 } else if (in_list != -1) { 121 pattern.name = attribute.substring (0, in_list); 122 pattern.type = AttributePatternType.LIST; 123 pattern.content = attribute.substring (0, equals + "~=".length); 124 } else if (equals != -1) { 125 pattern.name = attribute.substring (0, equals); 126 pattern.type = AttributePatternType.EQUALS; 127 pattern.content = attribute.substring (0, equals + "=".length); 128 } else { 129 pattern.name = attribute; 130 pattern.type = AttributePatternType.ANYTHING; 131 } 132 133 return pattern; 134 } 135 136 public bool match (XmlElement tag, string? id, string? css_class) { 137 string tag_name = tag.get_name (); 138 139 if (this.name != "*" && this.name != "" && tag_name != "") { 140 if (this.name != tag_name) { 141 return false; 142 } 143 } 144 145 if (this.id != null) { 146 if (id == null) { 147 return false; 148 } 149 150 if (((!) this.id) != ((!) id)) { 151 return false; 152 } 153 } 154 155 if (this.css_class != null) { 156 if (css_class == null) { 157 return false; 158 } 159 160 if (((!) this.css_class) != ((!) css_class)) { 161 return false; 162 } 163 } 164 165 if (attribute_patterns != null) { 166 foreach (AttributePattern pattern in (!) attribute_patterns) { 167 if (!pattern.match (tag.get_attributes ())) { 168 return false; 169 } 170 } 171 } 172 173 return true; 174 } 175 176 public string to_string () { 177 StringBuilder s = new StringBuilder (); 178 s.append ((!) name); 179 180 if (id != null) { 181 s.append ("#"); 182 s.append ((!) id); 183 } 184 185 if (css_class != null) { 186 s.append ("."); 187 s.append ((!) css_class); 188 } 189 190 if (attribute_patterns != null) { 191 foreach (AttributePattern a in (!) attribute_patterns) { 192 s.append (a.to_string ()); 193 } 194 } 195 196 return s.str; 197 } 198 } 199 200 } 201