SvgElement.cs 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  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.NamespaceName))
  24. {
  25. XName name = XNamespace.Get(RequiredNamespaces[prop.NamespaceName]) + prop.SvgName;
  26. element.Add(new XAttribute(name, prop.Unit.ToXml()));
  27. }
  28. else
  29. {
  30. element.Add(new XAttribute(prop.SvgName, prop.Unit.ToXml()));
  31. }
  32. }
  33. }
  34. }
  35. if (this is IElementContainer container)
  36. {
  37. foreach (SvgElement child in container.Children)
  38. {
  39. element.Add(child.ToXml(nameSpace));
  40. }
  41. }
  42. return element;
  43. }
  44. public virtual void ParseData(XmlReader reader)
  45. {
  46. // This is supposed to be overriden by child classes
  47. throw new SvgParsingException($"Element {TagName} does not support parsing");
  48. }
  49. protected void ParseAttributes(List<SvgProperty> properties, XmlReader reader)
  50. {
  51. do
  52. {
  53. SvgProperty matchingProperty = properties.FirstOrDefault(x =>
  54. string.Equals(x.SvgName, reader.Name, StringComparison.OrdinalIgnoreCase));
  55. if (matchingProperty != null)
  56. {
  57. ParseAttribute(matchingProperty, reader);
  58. }
  59. } while (reader.MoveToNextAttribute());
  60. }
  61. private void ParseAttribute(SvgProperty property, XmlReader reader)
  62. {
  63. if (property is SvgList list)
  64. {
  65. ParseListProperty(list, reader);
  66. }
  67. else
  68. {
  69. property.Unit ??= CreateDefaultUnit(property);
  70. property.Unit.ValuesFromXml(reader.Value);
  71. }
  72. }
  73. private void ParseListProperty(SvgList list, XmlReader reader)
  74. {
  75. list.Unit ??= CreateDefaultUnit(list);
  76. list.Unit.ValuesFromXml(reader.Value);
  77. }
  78. private ISvgUnit CreateDefaultUnit(SvgProperty property)
  79. {
  80. var genericType = property.GetType().GetGenericArguments();
  81. if (genericType.Length == 0)
  82. {
  83. throw new InvalidOperationException("Property does not have a generic type");
  84. }
  85. ISvgUnit unit = Activator.CreateInstance(genericType[0]) as ISvgUnit;
  86. if (unit == null)
  87. {
  88. throw new InvalidOperationException("Could not create unit");
  89. }
  90. return unit;
  91. }
  92. }