SvgElement.cs 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. using System.Text;
  2. using System.Xml;
  3. using System.Xml.Linq;
  4. using PixiEditor.SVG.Exceptions;
  5. using PixiEditor.SVG.Features;
  6. using PixiEditor.SVG.Units;
  7. namespace PixiEditor.SVG;
  8. public class SvgElement(string tagName)
  9. {
  10. public SvgProperty<SvgStringUnit> Id { get; } = new("id");
  11. public Dictionary<string, string> RequiredNamespaces { get; } = new();
  12. public string TagName { get; } = tagName;
  13. public XElement ToXml(XNamespace nameSpace)
  14. {
  15. XElement element = new XElement(nameSpace + TagName);
  16. foreach (var property in GetType().GetProperties())
  17. {
  18. if (property.PropertyType.IsAssignableTo(typeof(SvgProperty)))
  19. {
  20. SvgProperty prop = (SvgProperty)property.GetValue(this);
  21. if (prop?.Unit != null)
  22. {
  23. if (string.IsNullOrEmpty(prop.SvgName))
  24. {
  25. element.Value = prop.Unit.ToXml();
  26. }
  27. else
  28. {
  29. if (!string.IsNullOrEmpty(prop.NamespaceName))
  30. {
  31. XName name = XNamespace.Get(RequiredNamespaces[prop.NamespaceName]) + prop.SvgName;
  32. element.Add(new XAttribute(name, prop.Unit.ToXml()));
  33. }
  34. else
  35. {
  36. element.Add(new XAttribute(prop.SvgName, prop.Unit.ToXml()));
  37. }
  38. }
  39. }
  40. }
  41. }
  42. if (this is IElementContainer container)
  43. {
  44. foreach (SvgElement child in container.Children)
  45. {
  46. element.Add(child.ToXml(nameSpace));
  47. }
  48. }
  49. return element;
  50. }
  51. public virtual void ParseData(XmlReader reader)
  52. {
  53. // This is supposed to be overriden by child classes
  54. throw new SvgParsingException($"Element {TagName} does not support parsing");
  55. }
  56. protected void ParseAttributes(List<SvgProperty> properties, XmlReader reader)
  57. {
  58. do
  59. {
  60. SvgProperty matchingProperty = properties.FirstOrDefault(x =>
  61. string.Equals(x.SvgName, reader.Name, StringComparison.OrdinalIgnoreCase));
  62. if (matchingProperty != null)
  63. {
  64. ParseAttribute(matchingProperty, reader);
  65. }
  66. } while (reader.MoveToNextAttribute());
  67. }
  68. private void ParseAttribute(SvgProperty property, XmlReader reader)
  69. {
  70. if (property is SvgList list)
  71. {
  72. ParseListProperty(list, reader);
  73. }
  74. else
  75. {
  76. property.Unit ??= CreateDefaultUnit(property);
  77. property.Unit.ValuesFromXml(reader.Value);
  78. }
  79. }
  80. private void ParseListProperty(SvgList list, XmlReader reader)
  81. {
  82. list.Unit ??= CreateDefaultUnit(list);
  83. list.Unit.ValuesFromXml(reader.Value);
  84. }
  85. private ISvgUnit CreateDefaultUnit(SvgProperty property)
  86. {
  87. var genericType = property.GetType().GetGenericArguments();
  88. if (genericType.Length == 0)
  89. {
  90. throw new InvalidOperationException("Property does not have a generic type");
  91. }
  92. ISvgUnit unit = Activator.CreateInstance(genericType[0]) as ISvgUnit;
  93. if (unit == null)
  94. {
  95. throw new InvalidOperationException("Could not create unit");
  96. }
  97. return unit;
  98. }
  99. }