Commit df5ae9c
CSS pseudo classes in SVG files
Changed files (7)
modifiedlibbirdfont/SvgParser.valamodifiedlibsvgbird/Selector.valamodifiedlibsvgbird/SelectorPattern.valamodifiedlibsvgbird/SelectorTag.valamodifiedlibsvgbird/StyleSheet.valamodifiedlibsvgbird/SvgFile.valamodifiedlibsvgbird/SvgStyle.vala
Diff
@@ -557,7 +557,7 @@ public class SvgParser { } } - style = SvgStyle.parse (null, style, tag);+ style = SvgStyle.parse (null, style, tag, null); if (hidden) { return;@@ -625,7 +625,7 @@ public class SvgParser { } } - style = SvgStyle.parse (null, style, tag);+ style = SvgStyle.parse (null, style, tag, null); if (hidden) { return;@@ -691,7 +691,7 @@ public class SvgParser { } } - style = SvgStyle.parse (null, style, tag);+ style = SvgStyle.parse (null, style, tag, null); if (hidden) { return;@@ -769,7 +769,7 @@ public class SvgParser { } } - style = SvgStyle.parse (null, style, tag);+ style = SvgStyle.parse (null, style, tag, null); if (hidden) { return;@@ -867,7 +867,7 @@ public class SvgParser { } } - style = SvgStyle.parse (null, style, tag);+ style = SvgStyle.parse (null, style, tag, null); if (hidden) { return path_list;@@ -907,7 +907,7 @@ public class SvgParser { } } - style = SvgStyle.parse (null, style, tag);+ style = SvgStyle.parse (null, style, tag, null); if (hidden) { return;@@ -21,6 +21,7 @@ public class Selector : GLib.Object { Gee.ArrayList<SelectorPattern> tag_patterns = new Gee.ArrayList<SelectorPattern> (); Gee.ArrayList<SelectorPattern> class_patterns = new Gee.ArrayList<SelectorPattern> ();+ Gee.ArrayList<SelectorPattern> pseudo_class_patterns = new Gee.ArrayList<SelectorPattern> (); Gee.ArrayList<SelectorPattern> id_patterns = new Gee.ArrayList<SelectorPattern> (); public SvgStyle style { get; set; }@@ -32,13 +33,20 @@ public class Selector : GLib.Object { SelectorPattern p = new SelectorPattern (selector_patterns[i]); if (p.has_id ()) {- id_patterns.add (p);+ SelectorPattern id = p.get_id_patterns ();+ id_patterns.add (id); } if (p.has_class ()) {- class_patterns.add (p);+ SelectorPattern css_class = p.get_class_patterns ();+ class_patterns.add (css_class); } + if (p.has_pseudo_class ()) {+ SelectorPattern pseudo_class = p.get_pseudo_class_patterns ();+ pseudo_class_patterns.add (pseudo_class);+ }+ tag_patterns.add (p); } @@ -59,6 +67,10 @@ public class Selector : GLib.Object { foreach (SelectorPattern pattern in selector.id_patterns) { id_patterns.add (pattern.copy ()); }+ + foreach (SelectorPattern pattern in selector.pseudo_class_patterns) {+ pseudo_class_patterns.add (pattern.copy ());+ } } public string to_string () {@@ -79,9 +91,9 @@ public class Selector : GLib.Object { return new Selector.copy_constructor (this); } - public bool match_tag (XmlElement tag, string? id, string? css_class) {+ public bool match_tag (XmlElement tag, string? id, string? css_class, string? psedo_class) { foreach (SelectorPattern pattern in tag_patterns) {- if (pattern.match (tag, id, css_class)) {+ if (pattern.match (tag, id, css_class, psedo_class)) { return true; } }@@ -89,9 +101,9 @@ public class Selector : GLib.Object { return false; } - public bool match_id (XmlElement tag, string? id, string? css_class) {+ public bool match_id (XmlElement tag, string? id, string? css_class, string? psedo_class) { foreach (SelectorPattern pattern in id_patterns) {- if (pattern.match (tag, id, css_class)) {+ if (pattern.match (tag, id, css_class, psedo_class)) { return true; } }@@ -99,9 +111,19 @@ public class Selector : GLib.Object { return false; } - public bool match_class (XmlElement tag, string? id, string? css_class) {+ public bool match_class (XmlElement tag, string? id, string? css_class, string? psedo_class) { foreach (SelectorPattern pattern in class_patterns) {- if (pattern.match (tag, id, css_class)) {+ if (pattern.match (tag, id, css_class, psedo_class)) {+ return true;+ }+ }+ + return false;+ }+ + public bool match_pseudo_class (XmlElement tag, string? id, string? css_class, string? psedo_class) {+ foreach (SelectorPattern pattern in pseudo_class_patterns) {+ if (pattern.match (tag, id, css_class, psedo_class)) { return true; } }@@ -23,7 +23,7 @@ public class SelectorPattern : GLib.Object { public SelectorPattern.empty () { }-+ public SelectorPattern (string pattern) { string p = pattern.strip (); string[] elements = p.split (" ");@@ -35,6 +35,36 @@ public class SelectorPattern : GLib.Object { } } + public SelectorPattern get_id_patterns () {+ SelectorPattern pattern = new SelectorPattern.empty ();+ foreach (SelectorTag tag in tags) {+ if (tag.id != null) {+ pattern.tags.add (tag);+ }+ }+ return pattern;+ }++ public SelectorPattern get_class_patterns () {+ SelectorPattern pattern = new SelectorPattern.empty ();+ foreach (SelectorTag tag in tags) {+ if (tag.css_class != null) {+ pattern.tags.add (tag);+ }+ }+ return pattern;+ }++ public SelectorPattern get_pseudo_class_patterns () {+ SelectorPattern pattern = new SelectorPattern.empty ();+ foreach (SelectorTag tag in tags) {+ if (tag.pseudo_class != null) {+ pattern.tags.add (tag);+ }+ }+ return pattern;+ }+ public bool has_id () { foreach (SelectorTag tag in tags) { if (tag.id != null) {@@ -55,6 +85,16 @@ public class SelectorPattern : GLib.Object { return false; } + public bool has_pseudo_class () {+ foreach (SelectorTag tag in tags) {+ if (tag.pseudo_class != null) {+ return true;+ }+ }+ + return false;+ }+ public string to_string () { StringBuilder s = new StringBuilder (); @@ -78,7 +118,11 @@ public class SelectorPattern : GLib.Object { return pattern; } - public bool match (XmlElement tag, string? id, string? css_class) {+ public bool match (XmlElement tag, string? id, string? css_class, string? pseudo_class) {+ if (tag.get_name () == "") {+ return false;+ }+ for (int i = tags.size - 1; i >= 0; i--) { SelectorTag pattern = tags.get (i); @@ -104,7 +148,7 @@ public class SelectorPattern : GLib.Object { } } - if (!pattern.match (tag, id, css_class)) {+ if (!pattern.match (tag, id, css_class, pseudo_class)) { return false; } }@@ -22,6 +22,7 @@ public class SelectorTag : GLib.Object { public string name; public string? id = null; public string? css_class = null;+ public string? pseudo_class = null; Gee.ArrayList<AttributePattern>? attribute_patterns = null; public SelectorTag.empty () {@@ -29,39 +30,38 @@ public class SelectorTag : GLib.Object { public SelectorTag (string pattern) { string tag_pattern = pattern.strip ();- int id_separator = tag_pattern.index_of ("#");- int class_separator = tag_pattern.index_of ("."); int attribute_separator = tag_pattern.index_of ("["); if (attribute_separator != -1) { parse_attributes (tag_pattern.substring (attribute_separator));+ tag_pattern = tag_pattern.substring (0, attribute_separator - "[".length); }- - if (id_separator != -1) {- name = tag_pattern.substring (0, id_separator);- - id_separator += "#".length;- if (attribute_separator == -1) {- id = tag_pattern.substring (id_separator);- } else {- id = tag_pattern.substring (id_separator, attribute_separator - id_separator);- }- } else if (class_separator != -1) {- name = tag_pattern.substring (0, class_separator);- - class_separator += ".".length;- if (attribute_separator == -1) {- css_class = tag_pattern.substring (class_separator);- } else {- css_class = tag_pattern.substring (class_separator, attribute_separator - class_separator);- }- } else {- if (attribute_separator == -1) {- name = tag_pattern;- } else {- css_class = tag_pattern.substring (0, attribute_separator);- }++ tag_pattern = create_part (tag_pattern, ":", out pseudo_class);+ tag_pattern = create_part (tag_pattern, ".", out css_class);+ tag_pattern = create_part (tag_pattern, "#", out id);+ name = tag_pattern;+ }+ + string create_part (string tag_pattern, string separator, out string? part) {+ int separator_index = tag_pattern.index_of (separator);+ int separator_length = separator.length;+ + part = null;+ + if (separator_index == -1) {+ return tag_pattern;+ }+ + if (separator_index > -1 && separator_index + separator_length < tag_pattern.length) {+ part = tag_pattern.substring (separator_index + separator_length); }+ + if (separator_index > separator_length) {+ return tag_pattern.substring (0, separator_index);+ } + + return ""; } public SelectorTag copy () {@@ -70,6 +70,7 @@ public class SelectorTag : GLib.Object { tag.name = name; tag.id = id; tag.css_class = css_class;+ tag.pseudo_class = pseudo_class; if (attribute_patterns != null) { foreach (AttributePattern p in (!) attribute_patterns) {@@ -133,7 +134,7 @@ public class SelectorTag : GLib.Object { return pattern; } - public bool match (XmlElement tag, string? id, string? css_class) {+ public bool match (XmlElement tag, string? id, string? css_class, string? pseudo_class) { string tag_name = tag.get_name (); if (this.name != "*" && this.name != "" && tag_name != "") {@@ -162,6 +163,16 @@ public class SelectorTag : GLib.Object { } } + if (this.pseudo_class != null) {+ if (pseudo_class == null) {+ return false;+ } + + if (((!) this.pseudo_class) != ((!) pseudo_class)) {+ return false;+ }+ }+ if (attribute_patterns != null) { foreach (AttributePattern pattern in (!) attribute_patterns) { if (!pattern.match (tag.get_attributes ())) {@@ -186,6 +197,11 @@ public class SelectorTag : GLib.Object { s.append ("."); s.append ((!) css_class); }++ if (pseudo_class != null) {+ s.append (":");+ s.append ((!) pseudo_class);+ } if (attribute_patterns != null) { foreach (AttributePattern a in (!) attribute_patterns) {@@ -47,7 +47,7 @@ public class StyleSheet : GLib.Object { return style_sheet; } - public void apply_style (XmlElement tag, SvgStyle style) {+ public void apply_style (XmlElement tag, SvgStyle style, string? pseudo_class) { string? id = null; string? css_class = null; @@ -62,20 +62,32 @@ public class StyleSheet : GLib.Object { } foreach (Selector selector in styles) {- if (selector.match_tag (tag, id, css_class)) {+ if (selector.match_tag (tag, id, css_class, pseudo_class)) { style.apply (selector.style); } }+ + if (css_class != null) {+ foreach (Selector selector in styles) {+ if (selector.match_class (tag, id, css_class, pseudo_class)) {+ style.apply (selector.style);+ }+ }+ } - foreach (Selector selector in styles) {- if (selector.match_class (tag, id, css_class)) {- style.apply (selector.style);+ if (id != null) {+ foreach (Selector selector in styles) {+ if (selector.match_id (tag, id, css_class, pseudo_class)) {+ style.apply (selector.style);+ } } }- - foreach (Selector selector in styles) {- if (selector.match_id (tag, id, css_class)) {- style.apply (selector.style);++ if (pseudo_class != null) {+ foreach (Selector selector in styles) {+ if (selector.match_pseudo_class (tag, id, css_class, pseudo_class)) {+ style.apply (selector.style);+ } } } @@ -34,7 +34,7 @@ public class SvgFile : GLib.Object { drawing = new SvgDrawing (); SvgStyle style = new SvgStyle ();- SvgStyle.parse (drawing.defs, style, svg_tag);+ SvgStyle.parse (drawing.defs, style, svg_tag, null); foreach (Attribute attr in svg_tag.get_attributes ()) { if (attr.get_name () == "width") {@@ -315,7 +315,7 @@ public class SvgFile : GLib.Object { void parse_stop (Gradient gradient, XmlElement tag) { SvgStyle parent_style = new SvgStyle (); // not inherited- SvgStyle style = SvgStyle.parse (drawing.defs, parent_style, tag);+ SvgStyle style = SvgStyle.parse (drawing.defs, parent_style, tag, null); Stop stop = new Stop (); gradient.stops.add (stop);@@ -428,7 +428,7 @@ public class SvgFile : GLib.Object { object.clip_path = get_clip_path (attributes); object.transforms = get_transform (attributes);- object.style = SvgStyle.parse (drawing.defs, parent_style, tag);+ object.style = SvgStyle.parse (drawing.defs, parent_style, tag, null); object.visible = is_visible (tag); // FIXME: add style fill none } @@ -236,7 +236,7 @@ public class SvgStyle : GLib.Object { } } - public static SvgStyle parse (Defs? d, SvgStyle inherited, XmlElement tag) {+ public static SvgStyle parse (Defs? d, SvgStyle inherited, XmlElement tag, string? psedo_class) { SvgStyle s = new SvgStyle (); Attributes attributes = tag.get_attributes (); @@ -245,7 +245,7 @@ public class SvgStyle : GLib.Object { if (d != null) { StyleSheet style_sheet = ((!) d).style_sheet;- style_sheet.apply_style (tag, s);+ style_sheet.apply_style (tag, s, psedo_class); } foreach (Attribute a in attributes) {