SVGLinearGradientBrush.cs 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. using System;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. public class SVGLinearGradientBrush {
  5. private SVGLinearGradientElement _linearGradElement;
  6. private float _x1, _y1, _x2, _y2;
  7. private List<Color> _stopColorList;
  8. private List<float> _stopOffsetList;
  9. private SVGSpreadMethod _spreadMethod;
  10. public SVGLinearGradientBrush(SVGLinearGradientElement linearGradElement) {
  11. _linearGradElement = linearGradElement;
  12. Initialize();
  13. }
  14. public SVGLinearGradientBrush(SVGLinearGradientElement linearGradElement, SVGGraphicsPath graphicsPath) {
  15. _linearGradElement = linearGradElement;
  16. Initialize();
  17. SetGradientVector(graphicsPath);
  18. PreLocationProcess();
  19. }
  20. private void Initialize() {
  21. _x1 = _linearGradElement.x1.value;
  22. _y1 = _linearGradElement.y1.value;
  23. _x2 = _linearGradElement.x2.value;
  24. _y2 = _linearGradElement.y2.value;
  25. _stopColorList = new List<Color>();
  26. _stopOffsetList = new List<float>();
  27. _spreadMethod = _linearGradElement.spreadMethod;
  28. GetStopList();
  29. _vitriOffset = 0;
  30. PreColorProcess(_vitriOffset);
  31. }
  32. private void GetStopList() {
  33. List<SVGStopElement> _stopList = _linearGradElement.stopList;
  34. int _length = _stopList.Count;
  35. if(_length == 0)
  36. return;
  37. _stopColorList.Add(_stopList[0].stopColor.color);
  38. _stopOffsetList.Add(0f);
  39. int i = 0;
  40. for(i = 0; i < _length; i++) {
  41. float t_offset = _stopList[i].offset;
  42. if((t_offset > _stopOffsetList[_stopOffsetList.Count - 1]) && (t_offset <= 100f)) {
  43. _stopColorList.Add(_stopList[i].stopColor.color);
  44. _stopOffsetList.Add(t_offset);
  45. } else if(t_offset == _stopOffsetList[_stopOffsetList.Count - 1])
  46. _stopColorList[_stopOffsetList.Count - 1] = _stopList[i].stopColor.color;
  47. }
  48. if(_stopOffsetList[_stopOffsetList.Count - 1] != 100f) {
  49. _stopColorList.Add(_stopColorList[_stopOffsetList.Count - 1]);
  50. _stopOffsetList.Add(100f);
  51. }
  52. }
  53. private float _deltaR, _deltaG, _deltaB;
  54. private int _vitriOffset = 0;
  55. private void PreColorProcess(int index) {
  56. float dp = _stopOffsetList[index + 1] - _stopOffsetList[index];
  57. _deltaR = (_stopColorList[index + 1].r - _stopColorList[index].r) / dp;
  58. _deltaG = (_stopColorList[index + 1].g - _stopColorList[index].g) / dp;
  59. _deltaB = (_stopColorList[index + 1].b - _stopColorList[index].b) / dp;
  60. }
  61. private float _a, _b, _aP, _bP, _cP;
  62. private void PreLocationProcess() {
  63. if((_x1 - _x2 == 0f) || (_y1 - _y2 == 0f))
  64. return;
  65. float dx, dy;
  66. dx = _x2 - _x1;
  67. dy = _y2 - _y1;
  68. _a = dy / dx;
  69. _b = _y1 - _a * _x1;
  70. _aP = (dx) / (dx + _a * dy);
  71. _bP = (dy) / (dx + _a * dy);
  72. _cP = -(_b * dy) / (dx + _a * dy);
  73. }
  74. //-----
  75. private float Percent(float x, float y) {
  76. float cx, cy;
  77. if(_x1 - _x2 == 0) {
  78. cx = _x1;
  79. cy = y;
  80. } else if(_y1 - _y2 == 0) {
  81. cx = x;
  82. cy = _y1;
  83. } else {
  84. cx = _aP * x + _bP * y + _cP;
  85. cy = _a * cx + _b;
  86. }
  87. float d1 = (float)Math.Sqrt((_x1 - cx) * (_x1 - cx) + (_y1 - cy) * (_y1 - cy));
  88. float d2 = (float)Math.Sqrt((_x2 - cx) * (_x2 - cx) + (_y2 - cy) * (_y2 - cy));
  89. float dd = (float)Math.Sqrt((_x2 - _x1) * (_x2 - _x1) + (_y2 - _y1) * (_y2 - _y1));
  90. //-1 trai, 0 giua, 1 phai
  91. int vt = 0;
  92. if((d1 >= dd) || (d2 >= dd))
  93. vt = (d1 < d2) ? -1 : 1;
  94. int _reflectTimes;
  95. float _remainder;
  96. switch(_spreadMethod) {
  97. case SVGSpreadMethod.Pad:
  98. if(vt == -1)
  99. return 0f;
  100. if(vt == 1)
  101. return 100f;
  102. return (d1 / dd * 100f);
  103. case SVGSpreadMethod.Reflect:
  104. _reflectTimes = (int)(d1 / dd);
  105. _remainder = d1 - (dd * (float)_reflectTimes);
  106. int _od = (int)(_reflectTimes) % 2;
  107. return ((100f * _od) + (1 - 2 * _od) * (_remainder / dd * 100f));
  108. case SVGSpreadMethod.Repeat:
  109. _reflectTimes = (int)(d1 / dd);
  110. _remainder = d1 - (dd * (float)_reflectTimes);
  111. return (_remainder / dd * 100f);
  112. }
  113. return 100f;
  114. }
  115. private void SetGradientVector(SVGGraphicsPath graphicsPath) {
  116. Rect bound = graphicsPath.GetBound();
  117. if(_linearGradElement.x1.unitType == SVGLengthType.Percentage)
  118. _x1 = bound.x + (bound.width * _x1 / 100f);
  119. if(_linearGradElement.y1.unitType == SVGLengthType.Percentage)
  120. _y1 = bound.y + (bound.height * _y1 / 100f);
  121. if(_linearGradElement.x2.unitType == SVGLengthType.Percentage)
  122. _x2 = bound.x + (bound.width * _x2 / 100f);
  123. if(_linearGradElement.y2.unitType == SVGLengthType.Percentage)
  124. _y2 = bound.y + (bound.height * _y2 / 100f);
  125. if(_linearGradElement.gradientUnits == SVGGradientUnit.ObjectBoundingBox) {
  126. Vector2 _point = graphicsPath.matrixTransform.Transform(new Vector2(_x1, _y1));
  127. _x1 = _point.x;
  128. _y1 = _point.y;
  129. _point = graphicsPath.matrixTransform.Transform(new Vector2(_x2, _y2));
  130. _x2 = _point.x;
  131. _y2 = _point.y;
  132. }
  133. }
  134. /*private float _ox = 0;
  135. private int _dem = 0;
  136. private bool _show = false;*/
  137. public Color GetColor(float x, float y) {
  138. Color _color = Color.black;
  139. /*if(_ox != x) {
  140. _ox = x;
  141. _dem ++ ;
  142. if(_dem < 300) {
  143. _show = true;
  144. }
  145. }*/
  146. float _percent = Percent(x, y);
  147. /*if(_show == true) {
  148. UnityEngine.Debug.Log("x " + x + " y " + y + " percent " + _percent);
  149. }*/
  150. if((_stopOffsetList[_vitriOffset] <= _percent) && (_percent <= _stopOffsetList[_vitriOffset + 1])) {
  151. _color.r = ((_percent - _stopOffsetList[_vitriOffset]) * _deltaR) + _stopColorList[_vitriOffset].r;
  152. _color.g = ((_percent - _stopOffsetList[_vitriOffset]) * _deltaG) + _stopColorList[_vitriOffset].g;
  153. _color.b = ((_percent - _stopOffsetList[_vitriOffset]) * _deltaB) + _stopColorList[_vitriOffset].b;
  154. } else {
  155. for(int i = 0; i < _stopOffsetList.Count - 1; i++)
  156. if((_stopOffsetList[i] <= _percent) && (_percent <= _stopOffsetList[i + 1])) {
  157. _vitriOffset = i;
  158. PreColorProcess(_vitriOffset);
  159. _color.r = ((_percent - _stopOffsetList[i]) * _deltaR) + _stopColorList[i].r;
  160. _color.g = ((_percent - _stopOffsetList[i]) * _deltaG) + _stopColorList[i].g;
  161. _color.b = ((_percent - _stopOffsetList[i]) * _deltaB) + _stopColorList[i].b;
  162. break;
  163. }
  164. }
  165. //_show = false;
  166. return _color;
  167. }
  168. }