The Birdfont Source Code


All Repositories / birdfont.git / blob – RSS feed

StyleSheet.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/StyleSheet.vala.
Apply css styles
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 21 public class StyleSheet : GLib.Object { 22 23 public string css_data { get; set; default = ""; } 24 public Gee.ArrayList<Selector> styles = new Gee.ArrayList<Selector> (); 25 26 public StyleSheet () { 27 } 28 29 /** Copy references to all selectors in this style sheet. */ 30 public StyleSheet shallow_copy () { 31 StyleSheet style_sheet = new StyleSheet (); 32 33 foreach (Selector selector in styles) { 34 style_sheet.styles.add (selector); 35 } 36 37 return style_sheet; 38 } 39 40 public StyleSheet copy () { 41 StyleSheet style_sheet = new StyleSheet (); 42 43 foreach (Selector selector in styles) { 44 style_sheet.styles.add (selector.copy ()); 45 } 46 47 return style_sheet; 48 } 49 50 public void apply_style (XmlElement tag, SvgStyle style) { 51 string? id = null; 52 string? css_class = null; 53 54 foreach (Attribute attribute in tag.get_attributes ()) { 55 string name = attribute.get_name (); 56 57 if (name == "id") { 58 id = attribute.get_content (); 59 } else if (name == "class") { 60 css_class = attribute.get_content (); 61 } 62 } 63 64 foreach (Selector selector in styles) { 65 if (selector.match_tag (tag, id, css_class)) { 66 style.apply (selector.style); 67 } 68 } 69 70 foreach (Selector selector in styles) { 71 if (selector.match_class (tag, id, css_class)) { 72 style.apply (selector.style); 73 } 74 } 75 76 foreach (Selector selector in styles) { 77 if (selector.match_id (tag, id, css_class)) { 78 style.apply (selector.style); 79 } 80 } 81 82 SvgStyle.set_style_properties (null, style); 83 } 84 85 public void merge (StyleSheet style_sheet) { 86 foreach (Selector selector in style_sheet.styles) { 87 styles.add (selector.copy ()); 88 } 89 } 90 91 public static StyleSheet parse (Defs defs, XmlElement style_tag) { 92 return parse_css_data (defs, style_tag.get_content ()); 93 } 94 95 public static StyleSheet parse_css_data (Defs defs, string css_data) { 96 StyleSheet style_sheet = new StyleSheet (); 97 string css = get_cdata (css_data); 98 style_sheet.css_data = css; 99 css = add_separators (css); 100 css = replace_whitespace (css); 101 102 int index = 0; 103 int start_bracket_length = "{".length; 104 int end_bracket_length = "}".length; 105 int css_length = css.length; 106 107 while (index < css_length) { 108 int style_rules_start = css.index_of ("{", index); 109 int style_rules_end = css.index_of ("}", style_rules_start); 110 111 if (style_rules_start == -1 || style_rules_end == -1) { 112 break; 113 } 114 115 int selector_end = style_rules_start - start_bracket_length; 116 string selectors = css.substring (index, selector_end - index); 117 118 int style_start = style_rules_start + start_bracket_length; 119 int style_end = style_rules_end; 120 string style_rules = css.substring (style_start, style_end - style_start); 121 122 index = style_rules_end + end_bracket_length; 123 SvgStyle style = new SvgStyle.for_properties (defs, style_rules); 124 125 Selector selector = new Selector (selectors, style); 126 style_sheet.styles.add (selector); 127 } 128 129 return style_sheet; 130 } 131 132 public static string get_cdata (string tag_content) { 133 StringBuilder data = new StringBuilder (); 134 135 int index = 0; 136 int cdata_tag_length = "<![CDATA[".length; 137 int cdata_end_tag_length = "]]>".length; 138 int content_length = tag_content.length; 139 140 while (index < content_length) { 141 int cdata_start = tag_content.index_of ("<![CDATA[", index); 142 int cdata_end = tag_content.index_of ("]]>", cdata_start); 143 144 if (cdata_start == -1 || cdata_end == -1) { 145 break; 146 } 147 148 cdata_start += cdata_tag_length; 149 data.append (tag_content.substring (cdata_start, cdata_end - cdata_start)); 150 index = cdata_end + cdata_end_tag_length; 151 } 152 153 if (index < tag_content.length) { 154 data.append (tag_content.substring (index)); 155 } 156 157 return data.str; 158 } 159 160 public static string add_separators (string data) { 161 string style_data = data.replace (">", " > "); 162 style_data = data.replace ("+", " + "); 163 return style_data; 164 } 165 166 public static string replace_whitespace (string data) { 167 string style_data = data.replace ("\n", " "); 168 style_data = style_data.replace ("\r", " "); 169 style_data = style_data.replace ("\t", " "); 170 171 while (style_data.index_of (" ") != -1) { 172 style_data = style_data.replace (" ", " "); 173 } 174 175 return style_data; 176 } 177 } 178 179 } 180