EmbossBorder.cs 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. // Licensed to the .NET Foundation under one or more agreements.
  2. // The .NET Foundation licenses this file to you under the MIT license.
  3. // See the LICENSE file in the project root for more information.
  4. //
  5. // Purpose: Class that implements Emboss 3D border style.
  6. //
  7. using System;
  8. using System.Drawing;
  9. using System.Drawing.Drawing2D;
  10. namespace FastReport.DataVisualization.Charting.Borders3D
  11. {
  12. /// <summary>
  13. /// Implements emboss 3D border.
  14. /// </summary>
  15. internal class EmbossBorder : IBorderType
  16. {
  17. #region Border properties and methods
  18. /// <summary>
  19. /// Default border radius size (relative)
  20. /// </summary>
  21. public float defaultRadiusSize = 15f;
  22. public float resolution = 96f;
  23. /// <summary>
  24. /// Array of corner radius
  25. /// </summary>
  26. internal float[] cornerRadius = { 15f, 15f, 15f, 15f, 15f, 15f, 15f, 15f };
  27. /// <summary>
  28. /// Public constructor
  29. /// </summary>
  30. public EmbossBorder()
  31. {
  32. }
  33. /// <summary>
  34. /// Chart type name
  35. /// </summary>
  36. public virtual string Name { get{ return "Emboss";}}
  37. public virtual float Resolution
  38. {
  39. set
  40. {
  41. resolution = value;
  42. float radius = 15f * value / 96.0f;
  43. defaultRadiusSize = radius;
  44. cornerRadius = new float[] { radius, radius, radius, radius, radius, radius, radius, radius };
  45. }
  46. }
  47. /// <summary>
  48. /// Returns the position of the rectangular area in the border where
  49. /// title should be displayed. Returns empty rect if title can't be shown in the border.
  50. /// </summary>
  51. /// <returns>Title position in border.</returns>
  52. public virtual RectangleF GetTitlePositionInBorder()
  53. {
  54. return RectangleF.Empty;
  55. }
  56. /// <summary>
  57. /// Adjust areas rectangle coordinate to fit the 3D border.
  58. /// </summary>
  59. /// <param name="graph">Graphics to draw the border on.</param>
  60. /// <param name="areasRect">Position to adjust.</param>
  61. public virtual void AdjustAreasPosition(ChartGraphics graph, ref RectangleF areasRect)
  62. {
  63. SizeF borderSize = new SizeF(defaultRadiusSize/2f, defaultRadiusSize/2f);
  64. borderSize = graph.GetRelativeSize(borderSize);
  65. // Do not do anything if rectangle is too small
  66. if(borderSize.Width < 30f)
  67. {
  68. areasRect.X += borderSize.Width;
  69. areasRect.Width -= (float)Math.Min(areasRect.Width, borderSize.Width * 2.5f);
  70. }
  71. if(borderSize.Height < 30f)
  72. {
  73. areasRect.Y += borderSize.Height;
  74. areasRect.Height -= (float)Math.Min(areasRect.Height, borderSize.Height * 2.5f);
  75. }
  76. if(areasRect.X + areasRect.Width > 100f)
  77. {
  78. areasRect.X -= 100f - areasRect.Width;
  79. }
  80. if(areasRect.Y + areasRect.Height > 100f)
  81. {
  82. areasRect.Y -= 100f - areasRect.Height;
  83. }
  84. }
  85. /// <summary>
  86. /// Draws 3D border.
  87. /// </summary>
  88. /// <param name="graph">Graphics to draw the border on.</param>
  89. /// <param name="borderSkin">Border skin object.</param>
  90. /// <param name="rect">Rectangle of the border.</param>
  91. /// <param name="backColor">Color of rectangle</param>
  92. /// <param name="backHatchStyle">Hatch style</param>
  93. /// <param name="backImage">Back Image</param>
  94. /// <param name="backImageWrapMode">Image mode</param>
  95. /// <param name="backImageTransparentColor">Image transparent color.</param>
  96. /// <param name="backImageAlign">Image alignment</param>
  97. /// <param name="backGradientStyle">Gradient type</param>
  98. /// <param name="backSecondaryColor">Gradient End Color</param>
  99. /// <param name="borderColor">Border Color</param>
  100. /// <param name="borderWidth">Border Width</param>
  101. /// <param name="borderDashStyle">Border Style</param>
  102. public virtual void DrawBorder(
  103. ChartGraphics graph,
  104. BorderSkin borderSkin,
  105. RectangleF rect,
  106. Color backColor,
  107. ChartHatchStyle backHatchStyle,
  108. string backImage,
  109. ChartImageWrapMode backImageWrapMode,
  110. Color backImageTransparentColor,
  111. ChartImageAlignmentStyle backImageAlign,
  112. GradientStyle backGradientStyle,
  113. Color backSecondaryColor,
  114. Color borderColor,
  115. int borderWidth,
  116. ChartDashStyle borderDashStyle)
  117. {
  118. RectangleF absolute = graph.Round( rect );
  119. RectangleF shadowRect = absolute;
  120. // Calculate shadow colors (0.2 - 0.6)
  121. float colorDarkeningIndex = 0.2f + (0.4f * (borderSkin.PageColor.R + borderSkin.PageColor.G + borderSkin.PageColor.B) / 765f);
  122. Color shadowColor = Color.FromArgb(
  123. (int)(borderSkin.PageColor.R*colorDarkeningIndex),
  124. (int)(borderSkin.PageColor.G*colorDarkeningIndex),
  125. (int)(borderSkin.PageColor.B*colorDarkeningIndex));
  126. if(borderSkin.PageColor == Color.Transparent)
  127. {
  128. shadowColor = Color.FromArgb(60, 0, 0, 0);
  129. }
  130. colorDarkeningIndex += 0.2f;
  131. Color shadowLightColor = Color.FromArgb(
  132. (int)(borderSkin.PageColor.R*colorDarkeningIndex),
  133. (int)(borderSkin.PageColor.G*colorDarkeningIndex),
  134. (int)(borderSkin.PageColor.B*colorDarkeningIndex));
  135. // Calculate rounded rect radius
  136. float radius = defaultRadiusSize;
  137. radius = (float)Math.Max(radius, 2f * resolution / 96.0f);
  138. radius = (float)Math.Min(radius, rect.Width/2f);
  139. radius = (float)Math.Min(radius, rect.Height/2f);
  140. radius = (float)Math.Ceiling(radius);
  141. // Fill page background color
  142. using (Brush brush = new SolidBrush(borderSkin.PageColor))
  143. {
  144. graph.FillRectangle(brush, rect);
  145. }
  146. // Top/Left shadow
  147. shadowRect = absolute;
  148. shadowRect.Width -= radius * .3f;
  149. shadowRect.Height -= radius * .3f;
  150. graph.DrawRoundedRectShadowAbs(shadowRect, cornerRadius, radius + 1 * resolution / 96.0f, shadowLightColor, borderSkin.PageColor, 1.4f);
  151. // Bottom/Right shadow
  152. shadowRect = absolute;
  153. shadowRect.X = absolute.X + radius / 3f;
  154. shadowRect.Y = absolute.Y + radius / 3f;
  155. shadowRect.Width -= radius / 3.5f;
  156. shadowRect.Height -= radius / 3.5f;
  157. graph.DrawRoundedRectShadowAbs(shadowRect, cornerRadius, radius, shadowColor, borderSkin.PageColor, 1.3f);
  158. // Draw Background
  159. shadowRect = absolute;
  160. shadowRect.X = absolute.X + 3f * resolution / 96.0f;
  161. shadowRect.Y = absolute.Y + 3f * resolution / 96.0f;
  162. shadowRect.Width -= radius * .75f;
  163. shadowRect.Height -= radius * .75f;
  164. GraphicsPath path = graph.CreateRoundedRectPath(shadowRect, cornerRadius);
  165. graph.DrawPathAbs(
  166. path,
  167. backColor,
  168. backHatchStyle,
  169. backImage,
  170. backImageWrapMode,
  171. backImageTransparentColor,
  172. backImageAlign,
  173. backGradientStyle,
  174. backSecondaryColor,
  175. borderColor,
  176. borderWidth,
  177. borderDashStyle,
  178. PenAlignment.Inset );
  179. // Dispose Graphic path
  180. if( path != null )
  181. path.Dispose();
  182. // Bottom/Right inner shadow
  183. Region innerShadowRegion = new Region(
  184. graph.CreateRoundedRectPath(
  185. new RectangleF(
  186. shadowRect.X - radius,
  187. shadowRect.Y - radius,
  188. shadowRect.Width + radius - radius*0.25f,
  189. shadowRect.Height + radius - radius*0.25f),
  190. cornerRadius));
  191. innerShadowRegion.Complement(graph.CreateRoundedRectPath(shadowRect, cornerRadius));
  192. graph.Clip = innerShadowRegion;
  193. graph.DrawRoundedRectShadowAbs(
  194. shadowRect,
  195. cornerRadius,
  196. radius,
  197. Color.Transparent,
  198. Color.FromArgb(128, Color.Gray),
  199. .5f);
  200. graph.Clip = new Region();
  201. }
  202. #endregion
  203. }
  204. }