-
Notifications
You must be signed in to change notification settings - Fork 473
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Very initial support of CSS stylesheets in the SVG via including the ExCss and Fizzler libraries - Bug fixes with path rendering - Improvements to the API for loading an SVG file
- Loading branch information
Showing
96 changed files
with
15,061 additions
and
122 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Text; | ||
using Fizzler; | ||
using ExCSS; | ||
|
||
namespace Svg.Css | ||
{ | ||
internal static class CssQuery | ||
{ | ||
public static IEnumerable<SvgElement> QuerySelectorAll(this SvgElement elem, string selector) | ||
{ | ||
var generator = new SelectorGenerator<SvgElement>(new SvgElementOps()); | ||
Fizzler.Parser.Parse(selector, generator); | ||
return generator.Selector(Enumerable.Repeat(elem, 1)); | ||
} | ||
|
||
public static int GetSpecificity(this BaseSelector selector) | ||
{ | ||
if (selector is SimpleSelector) | ||
{ | ||
var simpleCode = selector.ToString(); | ||
if (simpleCode.StartsWith("#")) | ||
{ | ||
return 1 << 12; | ||
} | ||
else if (simpleCode.StartsWith(".")) | ||
{ | ||
return 1 << 8; | ||
} | ||
else | ||
{ | ||
return 1 << 4; | ||
} | ||
} | ||
return 0; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,186 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Text; | ||
using Fizzler; | ||
|
||
namespace Svg.Css | ||
{ | ||
internal class SvgElementOps : IElementOps<SvgElement> | ||
{ | ||
public Selector<SvgElement> Type(NamespacePrefix prefix, string name) | ||
{ | ||
var type = SvgElementFactory.AvailableElements.SingleOrDefault(e => e.ElementName == name); | ||
return nodes => nodes.Where(n => n.GetType() == type.ElementType); | ||
} | ||
|
||
public Selector<SvgElement> Universal(NamespacePrefix prefix) | ||
{ | ||
return nodes => nodes; | ||
} | ||
|
||
public Selector<SvgElement> Id(string id) | ||
{ | ||
return nodes => nodes.Where(n => n.ID == id); | ||
} | ||
|
||
public Selector<SvgElement> Class(string clazz) | ||
{ | ||
return AttributeIncludes(NamespacePrefix.None, "class", clazz); | ||
} | ||
|
||
public Selector<SvgElement> AttributeExists(NamespacePrefix prefix, string name) | ||
{ | ||
return nodes => nodes.Where(n => n.Attributes.ContainsKey(name) || n.CustomAttributes.ContainsKey(name)); | ||
} | ||
|
||
public Selector<SvgElement> AttributeExact(NamespacePrefix prefix, string name, string value) | ||
{ | ||
return nodes => nodes.Where(n => | ||
{ | ||
string val = null; | ||
object oval = null; | ||
return (n.CustomAttributes.TryGetValue(name, out val) && val == value) || | ||
(n.Attributes.TryGetValue(name, out oval) && oval.ToString() == value); | ||
}); | ||
} | ||
|
||
public Selector<SvgElement> AttributeIncludes(NamespacePrefix prefix, string name, string value) | ||
{ | ||
return nodes => nodes.Where(n => | ||
{ | ||
string val = null; | ||
object oval = null; | ||
return (n.CustomAttributes.TryGetValue(name, out val) && val.Split(' ').Contains(value)) || | ||
(n.Attributes.TryGetValue(name, out oval) && oval.ToString().Split(' ').Contains(value)); | ||
}); | ||
} | ||
|
||
public Selector<SvgElement> AttributeDashMatch(NamespacePrefix prefix, string name, string value) | ||
{ | ||
return string.IsNullOrEmpty(value) | ||
? (Selector<SvgElement>)(nodes => Enumerable.Empty<SvgElement>()) | ||
: (nodes => nodes.Where(n => | ||
{ | ||
string val = null; | ||
object oval = null; | ||
return (n.CustomAttributes.TryGetValue(name, out val) && val.Split('-').Contains(value)) || | ||
(n.Attributes.TryGetValue(name, out oval) && oval.ToString().Split('-').Contains(value)); | ||
})); | ||
} | ||
|
||
public Selector<SvgElement> AttributePrefixMatch(NamespacePrefix prefix, string name, string value) | ||
{ | ||
return string.IsNullOrEmpty(value) | ||
? (Selector<SvgElement>)(nodes => Enumerable.Empty<SvgElement>()) | ||
: (nodes => nodes.Where(n => | ||
{ | ||
string val = null; | ||
object oval = null; | ||
return (n.CustomAttributes.TryGetValue(name, out val) && val.StartsWith(value)) || | ||
(n.Attributes.TryGetValue(name, out oval) && oval.ToString().StartsWith(value)); | ||
})); | ||
} | ||
|
||
public Selector<SvgElement> AttributeSuffixMatch(NamespacePrefix prefix, string name, string value) | ||
{ | ||
return string.IsNullOrEmpty(value) | ||
? (Selector<SvgElement>)(nodes => Enumerable.Empty<SvgElement>()) | ||
: (nodes => nodes.Where(n => | ||
{ | ||
string val = null; | ||
object oval = null; | ||
return (n.CustomAttributes.TryGetValue(name, out val) && val.EndsWith(value)) || | ||
(n.Attributes.TryGetValue(name, out oval) && oval.ToString().EndsWith(value)); | ||
})); | ||
} | ||
|
||
public Selector<SvgElement> AttributeSubstring(NamespacePrefix prefix, string name, string value) | ||
{ | ||
return string.IsNullOrEmpty(value) | ||
? (Selector<SvgElement>)(nodes => Enumerable.Empty<SvgElement>()) | ||
: (nodes => nodes.Where(n => | ||
{ | ||
string val = null; | ||
object oval = null; | ||
return (n.CustomAttributes.TryGetValue(name, out val) && val.Contains(value)) || | ||
(n.Attributes.TryGetValue(name, out oval) && oval.ToString().Contains(value)); | ||
})); | ||
} | ||
|
||
public Selector<SvgElement> FirstChild() | ||
{ | ||
return nodes => nodes.Where(n => n.Parent == null || n.Parent.Children.First() == n); | ||
} | ||
|
||
public Selector<SvgElement> LastChild() | ||
{ | ||
return nodes => nodes.Where(n => n.Parent == null || n.Parent.Children.Last() == n); | ||
} | ||
|
||
private IEnumerable<T> GetByIds<T>(IList<T> items, IEnumerable<int> indices) | ||
{ | ||
foreach (var i in indices) | ||
{ | ||
if (i >= 0 && i < items.Count) yield return items[i]; | ||
} | ||
} | ||
|
||
public Selector<SvgElement> NthChild(int a, int b) | ||
{ | ||
return nodes => nodes.Where(n => n.Parent != null && GetByIds(n.Parent.Children, (from i in Enumerable.Range(0, n.Parent.Children.Count / a) select a * i + b)).Contains(n)); | ||
} | ||
|
||
public Selector<SvgElement> OnlyChild() | ||
{ | ||
return nodes => nodes.Where(n => n.Parent == null || n.Parent.Children.Count == 1); | ||
} | ||
|
||
public Selector<SvgElement> Empty() | ||
{ | ||
return nodes => nodes.Where(n => n.Children.Count == 0); | ||
} | ||
|
||
public Selector<SvgElement> Child() | ||
{ | ||
return nodes => nodes.SelectMany(n => n.Children); | ||
} | ||
|
||
public Selector<SvgElement> Descendant() | ||
{ | ||
return nodes => nodes.SelectMany(n => Descendants(n)); | ||
} | ||
|
||
private IEnumerable<SvgElement> Descendants(SvgElement elem) | ||
{ | ||
foreach (var child in elem.Children) | ||
{ | ||
yield return child; | ||
foreach (var descendant in child.Descendants()) | ||
{ | ||
yield return descendant; | ||
} | ||
} | ||
} | ||
|
||
public Selector<SvgElement> Adjacent() | ||
{ | ||
return nodes => nodes.SelectMany(n => ElementsAfterSelf(n).Take(1)); | ||
} | ||
|
||
public Selector<SvgElement> GeneralSibling() | ||
{ | ||
return nodes => nodes.SelectMany(n => ElementsAfterSelf(n)); | ||
} | ||
|
||
private IEnumerable<SvgElement> ElementsAfterSelf(SvgElement self) | ||
{ | ||
return (self.Parent == null ? Enumerable.Empty<SvgElement>() : self.Parent.Children.Skip(self.Parent.Children.IndexOf(self) + 1)); | ||
} | ||
|
||
public Selector<SvgElement> NthLastChild(int a, int b) | ||
{ | ||
throw new NotImplementedException(); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
namespace ExCSS | ||
{ | ||
public interface IToString | ||
{ | ||
string ToString(bool friendlyFormat, int indentation = 0); | ||
} | ||
} |
Oops, something went wrong.