The Birdfont Source Code


All Repositories / birdfont.git / blob – RSS feed

SelectorPattern.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/SelectorPattern.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 CSS selector pattern. */ 21 public class SelectorPattern : GLib.Object { 22 Gee.ArrayList<SelectorTag> tags = new Gee.ArrayList<SelectorTag> (); 23 24 public SelectorPattern.empty () { 25 } 26 27 public SelectorPattern (string pattern) { 28 string p = pattern.strip (); 29 string[] elements = p.split (" "); 30 31 foreach (string element in elements) { 32 if (element != "") { 33 tags.add (new SelectorTag (element)); 34 } 35 } 36 } 37 38 public string to_string () { 39 StringBuilder s = new StringBuilder (); 40 41 foreach (SelectorTag tag in tags) { 42 if (s.str != "") { 43 s.append (" "); 44 } 45 46 s.append (tag.to_string ()); 47 } 48 49 return s.str; 50 } 51 public SelectorPattern copy () { 52 SelectorPattern pattern = new SelectorPattern.empty (); 53 54 foreach (SelectorTag tag in tags) { 55 pattern.tags.add (tag.copy ()); 56 } 57 58 return pattern; 59 } 60 61 public bool match (XmlElement tag, string? id, string? css_class) { 62 for (int i = tags.size - 1; i >= 0; i--) { 63 SelectorTag pattern = tags.get (i); 64 65 if (pattern.name == ">") { 66 if (i - 1 < 0) { 67 return false; 68 } 69 70 string parent = tags.get (i - 1).name; 71 72 if (!has_parent (tag, parent)) { 73 return false; 74 } 75 } else if (pattern.name == "+") { 76 if (i - 1 < 0) { 77 return false; 78 } 79 80 string previous = tags.get (i - 1).name; 81 82 if (!is_immediately_following (tag, previous)) { 83 return false; 84 } 85 } else if (!pattern.match (tag, id, css_class)) { 86 return false; 87 } 88 } 89 90 return true; 91 } 92 93 public bool is_immediately_following (XmlElement tag, string previous) { 94 return get_previous (tag) == tag; 95 } 96 97 XmlElement? get_previous (XmlElement? xml_parent) { 98 if (xml_parent == null) { 99 return null; 100 } 101 102 XmlElement element = (!) xml_parent; 103 XmlElement? parent = element.get_parent (); 104 105 if (parent != null) { 106 XmlElement? previous = null; 107 108 foreach (XmlElement e in (!) parent) { 109 if (e == xml_parent) { 110 return previous; 111 } 112 113 previous = e; 114 } 115 } 116 117 return null; 118 } 119 120 public bool has_parent (XmlElement tag, string parent) { 121 XmlElement? xml_parent = tag.get_parent (); 122 123 while (xml_parent != null) { 124 if (((!) xml_parent).get_name () == parent) { 125 return true; 126 } 127 128 xml_parent = tag.get_parent (); 129 } 130 131 return false; 132 } 133 } 134 135 } 136