-
Notifications
You must be signed in to change notification settings - Fork 16
/
Helpers.cs
367 lines (314 loc) · 11.7 KB
/
Helpers.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
using System;
using System.Reflection;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;
namespace Patagames.Pdf.Net.Controls.Wpf
{
internal class Helpers
{
static Helpers()
{
var flags = BindingFlags.NonPublic | BindingFlags.Static;
var dpiProperty = typeof(SystemParameters).GetProperty("Dpi", flags);
Dpi = (int)dpiProperty.GetValue(null, null);
}
#region DPIhandling
/// <summary>
/// The Pixels Per Density Independent Pixel value, which is the equivalent of the scale factor.
/// For example, if the DPI of a screen is 120 (or 1.25 because 120/96 = 1.25) ,
/// 1.25 pixel per density independent pixel is drawn.
/// DIP is the unit of measurement used by WPF to be independent of device resolution and DPIs.
/// </summary>
public static double PixelSize { get { return (double)Dpi / 96; } }
/// <summary>
/// Gets current logical DPI
/// </summary>
/// <remarks>
/// This will require restart the app if DPI is changed
/// but it is too much overhead to check it on each conversion
/// </remarks>
public static int Dpi { get; private set; }
/// <summary>
/// Convert WPF units (DIPs - device independent pixels) to physical pixels.
/// </summary>
/// <param name="units">Device independent pixels</param>
/// <returns>Physical pixels</returns>
/// <remarks>1 DIP = 1/96 DPI</remarks>
public static int UnitsToPixels(double units)
{
return (int)(units * PixelSize);
}
/// <summary>
/// Convert physical pixels to WPF units (DIPs - device independent pixels)
/// </summary>
/// <param name="pixels">Physical pixels</param>
/// <returns>Device independent pixels</returns>
/// <remarks>1 DIP = 1/96 DPI</remarks>
public static double PixelsToUnits(int pixels)
{
return (double)pixels / PixelSize;
}
#endregion DPIhandling
#region Colors, pens, brushes, Rects and Sizes, etc
private static Color _emptyColor = Color.FromArgb(0, 0, 0, 0);
public static Color ColorEmpty { get { return _emptyColor; } }
internal static Pen CreatePen(Brush brush, double thick = 1.0)
{
return new Pen(brush, thick);
}
internal static Pen CreatePen(Color color, double thick=1.0)
{
return CreatePen(CreateBrush(color), thick);
}
internal static Brush CreateBrush(Color color)
{
return new SolidColorBrush(color);
}
internal static int ToArgb(Color color)
{
return (color.A << 24) | (color.R << 16) | (color.G << 8) | color.B;
}
internal static Size CreateSize(double nw, double nh)
{
if (nw < 0)
nw = 0;
if (nh < 0)
nh = 0;
return new Size(nw, nh);
}
internal static RenderRect CreateRenderRect(double x, double y, double w, double h, bool isChecked)
{
if (w < 0)
w = 0;
if (h < 0)
h = 0;
return new RenderRect(x, y, w, h, isChecked);
}
internal static Rect CreateRect(double x, double y, double w, double h)
{
if (w < 0)
w = 0;
if (h < 0)
h = 0;
return new Rect(x, y, w, h);
}
internal static Rect CreateRect(Point location, Size size)
{
if (size.Width < 0)
size.Width = 0;
if (size.Height < 0)
size.Height = 0;
return new Rect(location, size);
}
internal static double ThicknessHorizontal(Thickness pageMargin)
{
return pageMargin.Left + pageMargin.Right;
}
internal static double ThicknessVertical(Thickness pageMargin)
{
return pageMargin.Top + pageMargin.Bottom;
}
#endregion
#region Render
public static void DrawImageUnscaled(DrawingContext drawingContext, WriteableBitmap wpfBmp, double x, double y)
{
drawingContext.DrawImage(wpfBmp, new Rect(x, y, PixelsToUnits(wpfBmp.PixelWidth), PixelsToUnits(wpfBmp.PixelHeight)));
}
public static void FillRectangle(DrawingContext drawingContext, Brush brush, Rect rect)
{
drawingContext.DrawRectangle(brush, null, rect);
}
public static void DrawRectangle(DrawingContext drawingContext, Pen pen, Rect rect)
{
drawingContext.DrawRectangle(null, pen, rect);
}
/// <summary>
/// Calculate pixel offset to prevent image blur.
/// </summary>
/// <param name="UI">UIElement in which the offset is calculated.</param>
/// <returns>The offset point</returns>
public static Point GetPixelOffset(UIElement UI)
{
Point pixelOffset = new Point();
PresentationSource ps = PresentationSource.FromVisual(UI);
if (ps != null)
{
Visual rootVisual = ps.RootVisual;
// Transform (0,0) from this element up to pixels.
pixelOffset = UI.TransformToAncestor(rootVisual).Transform(pixelOffset);
pixelOffset = ApplyVisualTransform(pixelOffset, rootVisual, false);
pixelOffset = ps.CompositionTarget.TransformToDevice.Transform(pixelOffset);
// Round the origin to the nearest whole pixel.
pixelOffset.X = Math.Round(pixelOffset.X);
pixelOffset.Y = Math.Round(pixelOffset.Y);
// Transform the whole-pixel back to this element.
pixelOffset = ps.CompositionTarget.TransformFromDevice.Transform(pixelOffset);
pixelOffset = ApplyVisualTransform(pixelOffset, rootVisual, true);
var ttd = rootVisual.TransformToDescendant(UI);
if(ttd!= null)
pixelOffset = ttd.Transform(pixelOffset);
}
return pixelOffset;
}
private static Point ApplyVisualTransform(Point point, Visual v, bool inverse)
{
bool success = true;
return TryApplyVisualTransform(point, v, inverse, true, out success);
}
private static Point TryApplyVisualTransform(Point point, Visual v, bool inverse, bool throwOnError, out bool success)
{
success = true;
if (v != null)
{
Matrix visualTransform = GetVisualTransform(v);
if (inverse)
{
if (!throwOnError && !visualTransform.HasInverse)
{
success = false;
return new Point(0, 0);
}
visualTransform.Invert();
}
point = visualTransform.Transform(point);
}
return point;
}
/// <summary>
/// Gets the matrix that will convert a point from "above" the
/// coordinate space of a visual into the the coordinate space
/// "below" the visual.
/// </summary>
/// <param name="v">Visual</param>
/// <returns>Matrix</returns>
private static Matrix GetVisualTransform(Visual v)
{
if (v != null)
{
Matrix m = Matrix.Identity;
Transform transform = VisualTreeHelper.GetTransform(v);
if (transform != null)
{
Matrix cm = transform.Value;
m = Matrix.Multiply(m, cm);
}
Vector offset = VisualTreeHelper.GetOffset(v);
m.Translate(offset.X, offset.Y);
return m;
}
return Matrix.Identity;
}
#endregion
#region Int32 structures which are missing in WPF
/// <summary>
/// Represents Int32 size
/// </summary>
public struct Int32Size
{
public int Width;
public int Height;
public Int32Size(int width, int height)
{
Width = width;
Height = height;
}
public override bool Equals(object obj)
{
if (!(obj is Int32Size))
return false;
var pt = (Int32Size)obj;
return Equals(pt);
}
public bool Equals(Int32Size obj)
{
if (!obj.Width.Equals(this.Width))
return false;
if (!obj.Height.Equals(this.Height))
return false;
return true;
}
public static bool operator ==(Int32Size left, Int32Size right)
{
return left.Equals(right);
}
public static bool operator !=(Int32Size left, Int32Size right)
{
return !(left == right);
}
public override int GetHashCode()
{
unchecked // Overflow is fine, just wrap
{
int hash = 17;
// Suitable nullity checks etc, of course :)
hash = hash * 23 + Width.GetHashCode();
hash = hash * 23 + Height.GetHashCode();
return hash;
}
}
}
/// <summary>
/// Represents Int32 point
/// </summary>
public struct Int32Point
{
public int X;
public int Y;
public Int32Point(int x, int y)
{
X = x;
Y = y;
}
public override bool Equals(object obj)
{
if (!(obj is Int32Point))
return false;
var pt = (Int32Point)obj;
return Equals(pt);
}
public bool Equals(Int32Point obj)
{
if (!obj.X.Equals(this.X))
return false;
if (!obj.Y.Equals(this.Y))
return false;
return true;
}
public static bool operator ==(Int32Point left, Int32Point right)
{
return left.Equals(right);
}
public static bool operator !=(Int32Point left, Int32Point right)
{
return !(left == right);
}
public override int GetHashCode()
{
unchecked // Overflow is fine, just wrap
{
int hash = 17;
// Suitable nullity checks etc, of course :)
hash = hash * 23 + X.GetHashCode();
hash = hash * 23 + Y.GetHashCode();
return hash;
}
}
}
#endregion
#region Code Security
public static void SecurityAssert()
{
#if DOTNET30 || DOTNET35 || DOTNET40 || DOTNET45 || DOTNET451 || DOTNET452 || DOTNET46 || DOTNET461 || DOTNET462 || DOTNET47 || DOTNET471 || DOTNET472 || DOTNET48 || DOTNET481
new System.Drawing.Printing.PrintingPermission(System.Drawing.Printing.PrintingPermissionLevel.DefaultPrinting).Assert();
#endif
}
internal static void SecurityRevert()
{
#if DOTNET30 || DOTNET35 || DOTNET40 || DOTNET45 || DOTNET451 || DOTNET452 || DOTNET46 || DOTNET461 || DOTNET462 || DOTNET47 || DOTNET471 || DOTNET472 || DOTNET48 || DOTNET481
System.Security.CodeAccessPermission.RevertAssert();
#endif
}
#endregion
}
}