SvgPaintServerFactory.cs 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Drawing;
  5. using System.Globalization;
  6. using System.Linq;
  7. #pragma warning disable
  8. namespace Svg
  9. {
  10. internal class SvgPaintServerFactory : TypeConverter
  11. {
  12. private static readonly SvgColourConverter _colourConverter;
  13. static SvgPaintServerFactory()
  14. {
  15. _colourConverter = new SvgColourConverter();
  16. }
  17. public static SvgPaintServer Create(string value, SvgDocument document)
  18. {
  19. // If it's pointing to a paint server
  20. if (string.IsNullOrEmpty(value))
  21. {
  22. return SvgColourServer.NotSet;
  23. }
  24. else if (value == "inherit")
  25. {
  26. return SvgColourServer.Inherit;
  27. }
  28. else if (value == "currentColor")
  29. {
  30. return new SvgDeferredPaintServer(document, value);
  31. }
  32. else
  33. {
  34. var servers = new List<SvgPaintServer>();
  35. while (!string.IsNullOrEmpty(value))
  36. {
  37. if (value.StartsWith("url(#"))
  38. {
  39. var leftParen = value.IndexOf(')', 5);
  40. Uri id = new Uri(value.Substring(5, leftParen - 5), UriKind.Relative);
  41. value = value.Substring(leftParen + 1).Trim();
  42. servers.Add((SvgPaintServer)document.IdManager.GetElementById(id));
  43. }
  44. // If referenced to to a different (linear or radial) gradient
  45. else if (document.IdManager.GetElementById(value) != null && document.IdManager.GetElementById(value).GetType().BaseType == typeof(SvgGradientServer))
  46. {
  47. return (SvgPaintServer)document.IdManager.GetElementById(value);
  48. }
  49. else if (value.StartsWith("#")) // Otherwise try and parse as colour
  50. {
  51. switch (CountHexDigits(value, 1))
  52. {
  53. case 3:
  54. servers.Add(new SvgColourServer((Color)_colourConverter.ConvertFrom(value.Substring(0, 4))));
  55. value = value.Substring(4).Trim();
  56. break;
  57. case 6:
  58. servers.Add(new SvgColourServer((Color)_colourConverter.ConvertFrom(value.Substring(0, 7))));
  59. value = value.Substring(7).Trim();
  60. break;
  61. default:
  62. return new SvgDeferredPaintServer(document, value);
  63. }
  64. }
  65. else
  66. {
  67. return new SvgColourServer((Color)_colourConverter.ConvertFrom(value.Trim()));
  68. }
  69. }
  70. if (servers.Count > 1)
  71. {
  72. return new SvgFallbackPaintServer(servers[0], servers.Skip(1));
  73. }
  74. return servers[0];
  75. }
  76. }
  77. private static int CountHexDigits(string value, int start)
  78. {
  79. int i = Math.Max(start, 0);
  80. int count = 0;
  81. while (i < value.Length &&
  82. ((value[i] >= '0' && value[i] <= '9') ||
  83. (value[i] >= 'a' && value[i] <= 'f') ||
  84. (value[i] >= 'A' && value[i] <= 'F')))
  85. {
  86. count++;
  87. i++;
  88. }
  89. return count;
  90. }
  91. public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
  92. {
  93. if (value is string)
  94. {
  95. var s = (string)value;
  96. if (String.Equals(s.Trim(), "none", StringComparison.OrdinalIgnoreCase) || string.IsNullOrEmpty(s) || s.Trim().Length < 1)
  97. return SvgPaintServer.None;
  98. else
  99. return SvgPaintServerFactory.Create(s, (SvgDocument)context);
  100. }
  101. return base.ConvertFrom(context, culture, value);
  102. }
  103. public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
  104. {
  105. if (sourceType == typeof(string))
  106. {
  107. return true;
  108. }
  109. return base.CanConvertFrom(context, sourceType);
  110. }
  111. public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
  112. {
  113. if (destinationType == typeof(string))
  114. {
  115. return true;
  116. }
  117. return base.CanConvertTo(context, destinationType);
  118. }
  119. public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
  120. {
  121. if (destinationType == typeof(string))
  122. {
  123. //check for none
  124. if (value == SvgPaintServer.None || value == SvgColourServer.None) return "none";
  125. if (value == SvgColourServer.Inherit) return "inherit";
  126. if (value == SvgColourServer.NotSet) return "";
  127. var colourServer = value as SvgColourServer;
  128. if (colourServer != null)
  129. {
  130. return new SvgColourConverter().ConvertTo(colourServer.Colour, typeof(string));
  131. }
  132. var deferred = value as SvgDeferredPaintServer;
  133. if (deferred != null)
  134. {
  135. return deferred.ToString();
  136. }
  137. if (value != null)
  138. {
  139. return string.Format(CultureInfo.InvariantCulture, "url(#{0})", ((SvgPaintServer)value).ID);
  140. }
  141. else
  142. {
  143. return "none";
  144. }
  145. }
  146. return base.ConvertTo(context, culture, value, destinationType);
  147. }
  148. }
  149. }
  150. #pragma warning restore