DrawUtils.cs 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. using System;
  2. using System.Drawing;
  3. using System.Linq;
  4. namespace FastReport.Utils
  5. {
  6. internal enum MonoRendering
  7. {
  8. Undefined,
  9. Pango,
  10. Cairo
  11. }
  12. public static partial class DrawUtils
  13. {
  14. private static Font FDefaultFont;
  15. private static Font FDefaultReportFont;
  16. private static Font FDefaultTextObjectFont;
  17. private static Font FFixedFont;
  18. private static int FScreenDpi;
  19. private static float FDpiFX;
  20. private static MonoRendering FMonoRendering = MonoRendering.Undefined;
  21. public static int ScreenDpi
  22. {
  23. get
  24. {
  25. if (FScreenDpi == 0)
  26. FScreenDpi = GetDpi();
  27. return FScreenDpi;
  28. }
  29. }
  30. public static float ScreenDpiFX
  31. {
  32. get
  33. {
  34. if (FDpiFX == 0f)
  35. FDpiFX = 96f / DrawUtils.ScreenDpi;
  36. return FDpiFX;
  37. }
  38. }
  39. private static int GetDpi()
  40. {
  41. using (Bitmap bmp = new Bitmap(1, 1))
  42. using (Graphics g = Graphics.FromImage(bmp))
  43. {
  44. return (int)g.DpiX;
  45. }
  46. }
  47. public static Font DefaultFont
  48. {
  49. get
  50. {
  51. if (FDefaultFont == null)
  52. {
  53. #if AVALONIA
  54. if (OperatingSystem.IsWindows())
  55. {
  56. FDefaultFont = new Font("Segoe UI", 8.5f);
  57. }
  58. else if (OperatingSystem.IsMacOS())
  59. {
  60. FDefaultFont = new Font("Helvetica Neue", 8.5f);
  61. }
  62. else if (OperatingSystem.IsLinux())
  63. {
  64. FDefaultFont = new Font("Liberation Sans", 8.5f);
  65. }
  66. #else
  67. switch (System.Globalization.CultureInfo.CurrentCulture.TwoLetterISOLanguageName)
  68. {
  69. case "ja":
  70. FDefaultFont = CreateFont("MS UI Gothic", 9);
  71. break;
  72. case "zh":
  73. FDefaultFont = CreateFont("SimSun", 9);
  74. break;
  75. default:
  76. #if WPF
  77. FDefaultFont = CreateFont("Segoe UI", 8.5f);
  78. #else
  79. FDefaultFont = CreateFont("Tahoma", 8);
  80. #endif
  81. break;
  82. }
  83. #endif
  84. }
  85. return FDefaultFont;
  86. }
  87. set
  88. {
  89. FDefaultFont = value;
  90. }
  91. }
  92. public static Font DefaultReportFont
  93. {
  94. get
  95. {
  96. if (FDefaultReportFont == null)
  97. {
  98. switch (System.Globalization.CultureInfo.CurrentCulture.TwoLetterISOLanguageName)
  99. {
  100. case "ja":
  101. FDefaultReportFont = CreateFont("MS UI Gothic", 9);
  102. break;
  103. case "zh":
  104. FDefaultReportFont = CreateFont("SimSun", 9);
  105. break;
  106. default:
  107. FDefaultReportFont = CreateFont("Arial", 10);
  108. break;
  109. }
  110. }
  111. return FDefaultReportFont;
  112. }
  113. }
  114. public static Font DefaultTextObjectFont
  115. {
  116. get
  117. {
  118. if (FDefaultTextObjectFont == null)
  119. FDefaultTextObjectFont = CreateFont("Arial", 10);
  120. return FDefaultTextObjectFont;
  121. }
  122. }
  123. public static Font FixedFont
  124. {
  125. get
  126. {
  127. if (FFixedFont == null)
  128. #if WPF
  129. FFixedFont = CreateFont("Consolas", 9);
  130. #elif AVALONIA
  131. if (OperatingSystem.IsWindows())
  132. {
  133. FFixedFont = CreateFont("Lucida Console", 9);
  134. }
  135. else if (OperatingSystem.IsMacOS())
  136. {
  137. FFixedFont = CreateFont("PT Mono", 9);
  138. }
  139. else if (OperatingSystem.IsLinux())
  140. {
  141. FFixedFont = CreateFont("Liberation Mono", 9);
  142. }
  143. #else
  144. FFixedFont = CreateFont("Courier New", 10);
  145. #endif
  146. return FFixedFont;
  147. }
  148. }
  149. internal static Font CreateFont(string familyName, float emSize,
  150. FontStyle style = FontStyle.Regular,
  151. GraphicsUnit unit = GraphicsUnit.Point,
  152. byte gdiCharSet = 1,
  153. bool gdiVerticalFont = false)
  154. {
  155. Font font = new Font(familyName, emSize, style, unit, gdiCharSet, gdiVerticalFont);
  156. // skia now handles Font instantiation correctly
  157. /*#if SKIA
  158. if (font.Name != familyName)
  159. {
  160. // font family not found in installed fonts, search in the user fonts
  161. font = new Font(familyName, emSize, style, unit, gdiCharSet, gdiVerticalFont, Config.PrivateFontCollection.Collection);
  162. }
  163. #endif*/
  164. return font;
  165. }
  166. public static SizeF MeasureString(string text)
  167. {
  168. return MeasureString(text, DefaultFont);
  169. }
  170. public static SizeF MeasureString(string text, Font font)
  171. {
  172. using (Bitmap bmp = new Bitmap(1, 1))
  173. using (StringFormat sf = new StringFormat())
  174. {
  175. Graphics g = Graphics.FromImage(bmp);
  176. return MeasureString(g, text, font, sf);
  177. }
  178. }
  179. public static SizeF MeasureString(Graphics g, string text, Font font, StringFormat format)
  180. {
  181. return MeasureString(g, text, font, new RectangleF(0, 0, 10000, 10000), format);
  182. }
  183. public static SizeF MeasureString(Graphics g, string text, Font font, RectangleF layoutRect, StringFormat format)
  184. {
  185. if (String.IsNullOrEmpty(text))
  186. return new SizeF(0, 0);
  187. CharacterRange[] characterRanges = { new CharacterRange(0, text.Length) };
  188. StringFormatFlags saveFlags = format.FormatFlags;
  189. format.FormatFlags |= StringFormatFlags.MeasureTrailingSpaces;
  190. format.SetMeasurableCharacterRanges(characterRanges);
  191. Region[] regions = g.MeasureCharacterRanges(text, font, layoutRect, format);
  192. format.FormatFlags = saveFlags;
  193. RectangleF rect = regions[0].GetBounds(g);
  194. regions[0].Dispose();
  195. return rect.Size;
  196. }
  197. internal static MonoRendering GetMonoRendering(IGraphics printerGraphics)
  198. {
  199. if (FMonoRendering == MonoRendering.Undefined)
  200. {
  201. GraphicsUnit savedUnit = printerGraphics.PageUnit;
  202. printerGraphics.PageUnit = GraphicsUnit.Point;
  203. const string s = "test string test string test string test string";
  204. float f1 = printerGraphics.MeasureString(s, DefaultReportFont).Width;
  205. FMonoRendering = f1 > 200 ? MonoRendering.Pango : MonoRendering.Cairo;
  206. printerGraphics.PageUnit = savedUnit;
  207. }
  208. return FMonoRendering;
  209. }
  210. /// <summary>
  211. /// The method adjusts the dotted line style for the <see cref="Pen"/> in a graphical context.
  212. /// </summary>
  213. /// <param name="dashPattern">Collection of values for custom dash pattern.</param>
  214. /// <param name="pen">Pen for lines.</param>
  215. /// <param name="border">Border around the report object.</param>
  216. /// <remarks>
  217. /// If a <c>DashPattern</c> pattern is specified and contains elements, the method checks each element.
  218. /// If the element is less than or equal to 0, it is replaced by 1.<br/>
  219. /// Then the resulting array of patterns is converted to the <see cref="float"/> type and set as a dotted line pattern for the <see cref="Pen"/>.<br/>
  220. /// If the pattern is empty or not specified,
  221. /// the method sets the style of the dotted line of the <see cref="Pen"/> equal to the style of the dotted line of the <see cref="Border"/> object.
  222. ///</remarks>
  223. internal static void SetPenDashPatternOrStyle(FloatCollection dashPattern, Pen pen, Border border)
  224. {
  225. if (dashPattern?.Count > 0)
  226. {
  227. for (int i = 0; i < dashPattern.Count; i++)
  228. {
  229. if (dashPattern[i] <= 0)
  230. dashPattern[i] = 1;
  231. }
  232. pen.DashPattern = dashPattern.Cast<float>().ToArray();
  233. }
  234. else
  235. {
  236. pen.DashStyle = border.DashStyle;
  237. }
  238. }
  239. }
  240. }