moel@391
|
1 |
// --------------------------------------------------------------------------------------------------------------------
|
moel@391
|
2 |
// <copyright file="GraphicsRenderContext.cs" company="OxyPlot">
|
moel@391
|
3 |
// The MIT License (MIT)
|
moel@391
|
4 |
//
|
moel@391
|
5 |
// Copyright (c) 2012 Oystein Bjorke
|
moel@391
|
6 |
//
|
moel@391
|
7 |
// Permission is hereby granted, free of charge, to any person obtaining a
|
moel@391
|
8 |
// copy of this software and associated documentation files (the
|
moel@391
|
9 |
// "Software"), to deal in the Software without restriction, including
|
moel@391
|
10 |
// without limitation the rights to use, copy, modify, merge, publish,
|
moel@391
|
11 |
// distribute, sublicense, and/or sell copies of the Software, and to
|
moel@391
|
12 |
// permit persons to whom the Software is furnished to do so, subject to
|
moel@391
|
13 |
// the following conditions:
|
moel@391
|
14 |
//
|
moel@391
|
15 |
// The above copyright notice and this permission notice shall be included
|
moel@391
|
16 |
// in all copies or substantial portions of the Software.
|
moel@391
|
17 |
//
|
moel@391
|
18 |
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
moel@391
|
19 |
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
moel@391
|
20 |
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
moel@391
|
21 |
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
moel@391
|
22 |
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
moel@391
|
23 |
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
moel@391
|
24 |
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
moel@391
|
25 |
// </copyright>
|
moel@391
|
26 |
// <summary>
|
moel@391
|
27 |
// The graphics render context.
|
moel@391
|
28 |
// </summary>
|
moel@391
|
29 |
// --------------------------------------------------------------------------------------------------------------------
|
moel@391
|
30 |
namespace OxyPlot.WindowsForms
|
moel@391
|
31 |
{
|
moel@391
|
32 |
using System;
|
moel@391
|
33 |
using System.Collections.Generic;
|
moel@391
|
34 |
using System.Drawing;
|
moel@391
|
35 |
using System.Drawing.Drawing2D;
|
moel@391
|
36 |
using System.Drawing.Imaging;
|
moel@391
|
37 |
using System.IO;
|
moel@391
|
38 |
using System.Linq;
|
moel@391
|
39 |
|
moel@391
|
40 |
using OxyPlot;
|
moel@391
|
41 |
|
moel@391
|
42 |
/// <summary>
|
moel@391
|
43 |
/// The graphics render context.
|
moel@391
|
44 |
/// </summary>
|
moel@391
|
45 |
internal class GraphicsRenderContext : RenderContextBase
|
moel@391
|
46 |
{
|
moel@391
|
47 |
/// <summary>
|
moel@391
|
48 |
/// The font size factor.
|
moel@391
|
49 |
/// </summary>
|
moel@391
|
50 |
private const float FontsizeFactor = 0.8f;
|
moel@391
|
51 |
|
moel@391
|
52 |
/// <summary>
|
moel@391
|
53 |
/// The GDI+ drawing surface.
|
moel@391
|
54 |
/// </summary>
|
moel@391
|
55 |
private Graphics g;
|
moel@391
|
56 |
|
moel@391
|
57 |
/// <summary>
|
moel@391
|
58 |
/// Initializes a new instance of the <see cref="GraphicsRenderContext"/> class.
|
moel@391
|
59 |
/// </summary>
|
moel@391
|
60 |
public GraphicsRenderContext()
|
moel@391
|
61 |
{
|
moel@391
|
62 |
}
|
moel@391
|
63 |
|
moel@391
|
64 |
/// <summary>
|
moel@391
|
65 |
/// Sets the graphics target.
|
moel@391
|
66 |
/// </summary>
|
moel@391
|
67 |
/// <param name="graphics">The graphics surface.</param>
|
moel@391
|
68 |
public void SetGraphicsTarget(Graphics graphics)
|
moel@391
|
69 |
{
|
moel@391
|
70 |
this.g = graphics;
|
moel@391
|
71 |
}
|
moel@391
|
72 |
|
moel@391
|
73 |
/// <summary>
|
moel@391
|
74 |
/// Draws the ellipse.
|
moel@391
|
75 |
/// </summary>
|
moel@391
|
76 |
/// <param name="rect">The rect.</param>
|
moel@391
|
77 |
/// <param name="fill">The fill.</param>
|
moel@391
|
78 |
/// <param name="stroke">The stroke.</param>
|
moel@391
|
79 |
/// <param name="thickness">The thickness.</param>
|
moel@391
|
80 |
public override void DrawEllipse(OxyRect rect, OxyColor fill, OxyColor stroke, double thickness)
|
moel@391
|
81 |
{
|
moel@391
|
82 |
if (fill != null)
|
moel@391
|
83 |
{
|
moel@391
|
84 |
this.g.FillEllipse(
|
moel@391
|
85 |
this.ToBrush(fill), (float)rect.Left, (float)rect.Top, (float)rect.Width, (float)rect.Height);
|
moel@391
|
86 |
}
|
moel@391
|
87 |
|
moel@391
|
88 |
if (stroke == null || thickness <= 0)
|
moel@391
|
89 |
{
|
moel@391
|
90 |
return;
|
moel@391
|
91 |
}
|
moel@391
|
92 |
|
moel@391
|
93 |
using (var pen = new Pen(this.ToColor(stroke), (float)thickness))
|
moel@391
|
94 |
{
|
moel@391
|
95 |
this.g.SmoothingMode = SmoothingMode.HighQuality;
|
moel@391
|
96 |
this.g.DrawEllipse(pen, (float)rect.Left, (float)rect.Top, (float)rect.Width, (float)rect.Height);
|
moel@391
|
97 |
}
|
moel@391
|
98 |
}
|
moel@391
|
99 |
|
moel@391
|
100 |
/// <summary>
|
moel@391
|
101 |
/// Draws the line.
|
moel@391
|
102 |
/// </summary>
|
moel@391
|
103 |
/// <param name="points">The points.</param>
|
moel@391
|
104 |
/// <param name="stroke">The stroke.</param>
|
moel@391
|
105 |
/// <param name="thickness">The thickness.</param>
|
moel@391
|
106 |
/// <param name="dashArray">The dash array.</param>
|
moel@391
|
107 |
/// <param name="lineJoin">The line join.</param>
|
moel@391
|
108 |
/// <param name="aliased">if set to <c>true</c> [aliased].</param>
|
moel@391
|
109 |
public override void DrawLine(
|
moel@391
|
110 |
IList<ScreenPoint> points,
|
moel@391
|
111 |
OxyColor stroke,
|
moel@391
|
112 |
double thickness,
|
moel@391
|
113 |
double[] dashArray,
|
moel@391
|
114 |
OxyPenLineJoin lineJoin,
|
moel@391
|
115 |
bool aliased)
|
moel@391
|
116 |
{
|
moel@391
|
117 |
if (stroke == null || thickness <= 0 || points.Count < 2)
|
moel@391
|
118 |
{
|
moel@391
|
119 |
return;
|
moel@391
|
120 |
}
|
moel@391
|
121 |
|
moel@391
|
122 |
this.g.SmoothingMode = aliased ? SmoothingMode.None : SmoothingMode.HighQuality;
|
moel@391
|
123 |
using (var pen = new Pen(this.ToColor(stroke), (float)thickness))
|
moel@391
|
124 |
{
|
moel@391
|
125 |
|
moel@391
|
126 |
if (dashArray != null)
|
moel@391
|
127 |
{
|
moel@391
|
128 |
pen.DashPattern = this.ToFloatArray(dashArray);
|
moel@391
|
129 |
}
|
moel@391
|
130 |
|
moel@391
|
131 |
switch (lineJoin)
|
moel@391
|
132 |
{
|
moel@391
|
133 |
case OxyPenLineJoin.Round:
|
moel@391
|
134 |
pen.LineJoin = LineJoin.Round;
|
moel@391
|
135 |
break;
|
moel@391
|
136 |
case OxyPenLineJoin.Bevel:
|
moel@391
|
137 |
pen.LineJoin = LineJoin.Bevel;
|
moel@391
|
138 |
break;
|
moel@391
|
139 |
|
moel@391
|
140 |
// The default LineJoin is Miter
|
moel@391
|
141 |
}
|
moel@391
|
142 |
|
moel@391
|
143 |
this.g.DrawLines(pen, this.ToPoints(points));
|
moel@391
|
144 |
}
|
moel@391
|
145 |
}
|
moel@391
|
146 |
|
moel@391
|
147 |
/// <summary>
|
moel@391
|
148 |
/// Draws the polygon.
|
moel@391
|
149 |
/// </summary>
|
moel@391
|
150 |
/// <param name="points">The points.</param>
|
moel@391
|
151 |
/// <param name="fill">The fill.</param>
|
moel@391
|
152 |
/// <param name="stroke">The stroke.</param>
|
moel@391
|
153 |
/// <param name="thickness">The thickness.</param>
|
moel@391
|
154 |
/// <param name="dashArray">The dash array.</param>
|
moel@391
|
155 |
/// <param name="lineJoin">The line join.</param>
|
moel@391
|
156 |
/// <param name="aliased">if set to <c>true</c> [aliased].</param>
|
moel@391
|
157 |
public override void DrawPolygon(
|
moel@391
|
158 |
IList<ScreenPoint> points,
|
moel@391
|
159 |
OxyColor fill,
|
moel@391
|
160 |
OxyColor stroke,
|
moel@391
|
161 |
double thickness,
|
moel@391
|
162 |
double[] dashArray,
|
moel@391
|
163 |
OxyPenLineJoin lineJoin,
|
moel@391
|
164 |
bool aliased)
|
moel@391
|
165 |
{
|
moel@391
|
166 |
if (points.Count < 2)
|
moel@391
|
167 |
{
|
moel@391
|
168 |
return;
|
moel@391
|
169 |
}
|
moel@391
|
170 |
|
moel@391
|
171 |
this.g.SmoothingMode = aliased ? SmoothingMode.None : SmoothingMode.HighQuality;
|
moel@391
|
172 |
|
moel@391
|
173 |
PointF[] pts = this.ToPoints(points);
|
moel@391
|
174 |
if (fill != null)
|
moel@391
|
175 |
{
|
moel@391
|
176 |
this.g.FillPolygon(this.ToBrush(fill), pts);
|
moel@391
|
177 |
}
|
moel@391
|
178 |
|
moel@391
|
179 |
if (stroke != null && thickness > 0)
|
moel@391
|
180 |
{
|
moel@391
|
181 |
using (var pen = new Pen(this.ToColor(stroke), (float)thickness))
|
moel@391
|
182 |
{
|
moel@391
|
183 |
|
moel@391
|
184 |
if (dashArray != null)
|
moel@391
|
185 |
{
|
moel@391
|
186 |
pen.DashPattern = this.ToFloatArray(dashArray);
|
moel@391
|
187 |
}
|
moel@391
|
188 |
|
moel@391
|
189 |
switch (lineJoin)
|
moel@391
|
190 |
{
|
moel@391
|
191 |
case OxyPenLineJoin.Round:
|
moel@391
|
192 |
pen.LineJoin = LineJoin.Round;
|
moel@391
|
193 |
break;
|
moel@391
|
194 |
case OxyPenLineJoin.Bevel:
|
moel@391
|
195 |
pen.LineJoin = LineJoin.Bevel;
|
moel@391
|
196 |
break;
|
moel@391
|
197 |
|
moel@391
|
198 |
// The default LineJoin is Miter
|
moel@391
|
199 |
}
|
moel@391
|
200 |
|
moel@391
|
201 |
this.g.DrawPolygon(pen, pts);
|
moel@391
|
202 |
}
|
moel@391
|
203 |
}
|
moel@391
|
204 |
}
|
moel@391
|
205 |
|
moel@391
|
206 |
/// <summary>
|
moel@391
|
207 |
/// The draw rectangle.
|
moel@391
|
208 |
/// </summary>
|
moel@391
|
209 |
/// <param name="rect">
|
moel@391
|
210 |
/// The rect.
|
moel@391
|
211 |
/// </param>
|
moel@391
|
212 |
/// <param name="fill">
|
moel@391
|
213 |
/// The fill.
|
moel@391
|
214 |
/// </param>
|
moel@391
|
215 |
/// <param name="stroke">
|
moel@391
|
216 |
/// The stroke.
|
moel@391
|
217 |
/// </param>
|
moel@391
|
218 |
/// <param name="thickness">
|
moel@391
|
219 |
/// The thickness.
|
moel@391
|
220 |
/// </param>
|
moel@391
|
221 |
public override void DrawRectangle(OxyRect rect, OxyColor fill, OxyColor stroke, double thickness)
|
moel@391
|
222 |
{
|
moel@391
|
223 |
if (fill != null)
|
moel@391
|
224 |
{
|
moel@391
|
225 |
this.g.FillRectangle(
|
moel@391
|
226 |
this.ToBrush(fill), (float)rect.Left, (float)rect.Top, (float)rect.Width, (float)rect.Height);
|
moel@391
|
227 |
}
|
moel@391
|
228 |
|
moel@391
|
229 |
if (stroke == null || thickness <= 0)
|
moel@391
|
230 |
{
|
moel@391
|
231 |
return;
|
moel@391
|
232 |
}
|
moel@391
|
233 |
|
moel@391
|
234 |
using (var pen = new Pen(this.ToColor(stroke), (float)thickness))
|
moel@391
|
235 |
{
|
moel@391
|
236 |
this.g.DrawRectangle(pen, (float)rect.Left, (float)rect.Top, (float)rect.Width, (float)rect.Height);
|
moel@391
|
237 |
}
|
moel@391
|
238 |
}
|
moel@391
|
239 |
|
moel@391
|
240 |
/// <summary>
|
moel@391
|
241 |
/// The draw text.
|
moel@391
|
242 |
/// </summary>
|
moel@391
|
243 |
/// <param name="p">
|
moel@391
|
244 |
/// The p.
|
moel@391
|
245 |
/// </param>
|
moel@391
|
246 |
/// <param name="text">
|
moel@391
|
247 |
/// The text.
|
moel@391
|
248 |
/// </param>
|
moel@391
|
249 |
/// <param name="fill">
|
moel@391
|
250 |
/// The fill.
|
moel@391
|
251 |
/// </param>
|
moel@391
|
252 |
/// <param name="fontFamily">
|
moel@391
|
253 |
/// The font family.
|
moel@391
|
254 |
/// </param>
|
moel@391
|
255 |
/// <param name="fontSize">
|
moel@391
|
256 |
/// The font size.
|
moel@391
|
257 |
/// </param>
|
moel@391
|
258 |
/// <param name="fontWeight">
|
moel@391
|
259 |
/// The font weight.
|
moel@391
|
260 |
/// </param>
|
moel@391
|
261 |
/// <param name="rotate">
|
moel@391
|
262 |
/// The rotate.
|
moel@391
|
263 |
/// </param>
|
moel@391
|
264 |
/// <param name="halign">
|
moel@391
|
265 |
/// The halign.
|
moel@391
|
266 |
/// </param>
|
moel@391
|
267 |
/// <param name="valign">
|
moel@391
|
268 |
/// The valign.
|
moel@391
|
269 |
/// </param>
|
moel@391
|
270 |
/// <param name="maxSize">
|
moel@391
|
271 |
/// The maximum size of the text.
|
moel@391
|
272 |
/// </param>
|
moel@391
|
273 |
public override void DrawText(
|
moel@391
|
274 |
ScreenPoint p,
|
moel@391
|
275 |
string text,
|
moel@391
|
276 |
OxyColor fill,
|
moel@391
|
277 |
string fontFamily,
|
moel@391
|
278 |
double fontSize,
|
moel@391
|
279 |
double fontWeight,
|
moel@391
|
280 |
double rotate,
|
moel@391
|
281 |
HorizontalAlignment halign,
|
moel@391
|
282 |
VerticalAlignment valign,
|
moel@391
|
283 |
OxySize? maxSize)
|
moel@391
|
284 |
{
|
moel@391
|
285 |
var fs = FontStyle.Regular;
|
moel@391
|
286 |
if (fontWeight >= 700)
|
moel@391
|
287 |
{
|
moel@391
|
288 |
fs = FontStyle.Bold;
|
moel@391
|
289 |
}
|
moel@391
|
290 |
|
moel@391
|
291 |
using (var font = new Font(fontFamily, (float)fontSize * FontsizeFactor, fs))
|
moel@391
|
292 |
{
|
moel@391
|
293 |
using (var sf = new StringFormat { Alignment = StringAlignment.Near })
|
moel@391
|
294 |
{
|
moel@391
|
295 |
var size = this.g.MeasureString(text, font);
|
moel@391
|
296 |
if (maxSize != null)
|
moel@391
|
297 |
{
|
moel@391
|
298 |
if (size.Width > maxSize.Value.Width)
|
moel@391
|
299 |
{
|
moel@391
|
300 |
size.Width = (float)maxSize.Value.Width;
|
moel@391
|
301 |
}
|
moel@391
|
302 |
|
moel@391
|
303 |
if (size.Height > maxSize.Value.Height)
|
moel@391
|
304 |
{
|
moel@391
|
305 |
size.Height = (float)maxSize.Value.Height;
|
moel@391
|
306 |
}
|
moel@391
|
307 |
}
|
moel@391
|
308 |
|
moel@391
|
309 |
float dx = 0;
|
moel@391
|
310 |
if (halign == HorizontalAlignment.Center)
|
moel@391
|
311 |
{
|
moel@391
|
312 |
dx = -size.Width / 2;
|
moel@391
|
313 |
}
|
moel@391
|
314 |
|
moel@391
|
315 |
if (halign == HorizontalAlignment.Right)
|
moel@391
|
316 |
{
|
moel@391
|
317 |
dx = -size.Width;
|
moel@391
|
318 |
}
|
moel@391
|
319 |
|
moel@391
|
320 |
float dy = 0;
|
moel@391
|
321 |
sf.LineAlignment = StringAlignment.Near;
|
moel@391
|
322 |
if (valign == VerticalAlignment.Middle)
|
moel@391
|
323 |
{
|
moel@391
|
324 |
dy = -size.Height / 2;
|
moel@391
|
325 |
}
|
moel@391
|
326 |
|
moel@391
|
327 |
if (valign == VerticalAlignment.Bottom)
|
moel@391
|
328 |
{
|
moel@391
|
329 |
dy = -size.Height;
|
moel@391
|
330 |
}
|
moel@391
|
331 |
|
moel@391
|
332 |
this.g.TranslateTransform((float)p.X, (float)p.Y);
|
moel@391
|
333 |
if (Math.Abs(rotate) > double.Epsilon)
|
moel@391
|
334 |
{
|
moel@391
|
335 |
this.g.RotateTransform((float)rotate);
|
moel@391
|
336 |
}
|
moel@391
|
337 |
|
moel@391
|
338 |
this.g.TranslateTransform(dx, dy);
|
moel@391
|
339 |
|
moel@391
|
340 |
var layoutRectangle = new RectangleF(0, 0, size.Width, size.Height);
|
moel@391
|
341 |
this.g.DrawString(text, font, this.ToBrush(fill), layoutRectangle, sf);
|
moel@391
|
342 |
|
moel@391
|
343 |
this.g.ResetTransform();
|
moel@391
|
344 |
}
|
moel@391
|
345 |
}
|
moel@391
|
346 |
}
|
moel@391
|
347 |
|
moel@391
|
348 |
/// <summary>
|
moel@391
|
349 |
/// The measure text.
|
moel@391
|
350 |
/// </summary>
|
moel@391
|
351 |
/// <param name="text">The text.</param>
|
moel@391
|
352 |
/// <param name="fontFamily">The font family.</param>
|
moel@391
|
353 |
/// <param name="fontSize">The font size.</param>
|
moel@391
|
354 |
/// <param name="fontWeight">The font weight.</param>
|
moel@391
|
355 |
/// <returns>The size of the text.</returns>
|
moel@391
|
356 |
public override OxySize MeasureText(string text, string fontFamily, double fontSize, double fontWeight)
|
moel@391
|
357 |
{
|
moel@391
|
358 |
if (text == null)
|
moel@391
|
359 |
{
|
moel@391
|
360 |
return OxySize.Empty;
|
moel@391
|
361 |
}
|
moel@391
|
362 |
|
moel@391
|
363 |
var fs = FontStyle.Regular;
|
moel@391
|
364 |
if (fontWeight >= 700)
|
moel@391
|
365 |
{
|
moel@391
|
366 |
fs = FontStyle.Bold;
|
moel@391
|
367 |
}
|
moel@391
|
368 |
|
moel@391
|
369 |
using (var font = new Font(fontFamily, (float)fontSize * FontsizeFactor, fs))
|
moel@391
|
370 |
{
|
moel@391
|
371 |
var size = this.g.MeasureString(text, font);
|
moel@391
|
372 |
return new OxySize(size.Width, size.Height);
|
moel@391
|
373 |
}
|
moel@391
|
374 |
}
|
moel@391
|
375 |
|
moel@391
|
376 |
/// <summary>
|
moel@391
|
377 |
/// Converts a fill color to a System.Drawing.Brush.
|
moel@391
|
378 |
/// </summary>
|
moel@391
|
379 |
/// <param name="fill">
|
moel@391
|
380 |
/// The fill color.
|
moel@391
|
381 |
/// </param>
|
moel@391
|
382 |
/// <returns>
|
moel@391
|
383 |
/// The brush.
|
moel@391
|
384 |
/// </returns>
|
moel@391
|
385 |
private Brush ToBrush(OxyColor fill)
|
moel@391
|
386 |
{
|
moel@391
|
387 |
if (fill != null)
|
moel@391
|
388 |
{
|
moel@391
|
389 |
return new SolidBrush(this.ToColor(fill));
|
moel@391
|
390 |
}
|
moel@391
|
391 |
|
moel@391
|
392 |
return null;
|
moel@391
|
393 |
}
|
moel@391
|
394 |
|
moel@391
|
395 |
/// <summary>
|
moel@391
|
396 |
/// Converts a color to a System.Drawing.Color.
|
moel@391
|
397 |
/// </summary>
|
moel@391
|
398 |
/// <param name="c">
|
moel@391
|
399 |
/// The color.
|
moel@391
|
400 |
/// </param>
|
moel@391
|
401 |
/// <returns>
|
moel@391
|
402 |
/// The System.Drawing.Color.
|
moel@391
|
403 |
/// </returns>
|
moel@391
|
404 |
private Color ToColor(OxyColor c)
|
moel@391
|
405 |
{
|
moel@391
|
406 |
return Color.FromArgb(c.A, c.R, c.G, c.B);
|
moel@391
|
407 |
}
|
moel@391
|
408 |
|
moel@391
|
409 |
/// <summary>
|
moel@391
|
410 |
/// Converts a double array to a float array.
|
moel@391
|
411 |
/// </summary>
|
moel@391
|
412 |
/// <param name="a">
|
moel@391
|
413 |
/// The a.
|
moel@391
|
414 |
/// </param>
|
moel@391
|
415 |
/// <returns>
|
moel@391
|
416 |
/// The float array.
|
moel@391
|
417 |
/// </returns>
|
moel@391
|
418 |
private float[] ToFloatArray(double[] a)
|
moel@391
|
419 |
{
|
moel@391
|
420 |
if (a == null)
|
moel@391
|
421 |
{
|
moel@391
|
422 |
return null;
|
moel@391
|
423 |
}
|
moel@391
|
424 |
|
moel@391
|
425 |
var r = new float[a.Length];
|
moel@391
|
426 |
for (int i = 0; i < a.Length; i++)
|
moel@391
|
427 |
{
|
moel@391
|
428 |
r[i] = (float)a[i];
|
moel@391
|
429 |
}
|
moel@391
|
430 |
|
moel@391
|
431 |
return r;
|
moel@391
|
432 |
}
|
moel@391
|
433 |
|
moel@391
|
434 |
/// <summary>
|
moel@391
|
435 |
/// Converts a list of point to an array of PointF.
|
moel@391
|
436 |
/// </summary>
|
moel@391
|
437 |
/// <param name="points">
|
moel@391
|
438 |
/// The points.
|
moel@391
|
439 |
/// </param>
|
moel@391
|
440 |
/// <returns>
|
moel@391
|
441 |
/// An array of points.
|
moel@391
|
442 |
/// </returns>
|
moel@391
|
443 |
private PointF[] ToPoints(IList<ScreenPoint> points)
|
moel@391
|
444 |
{
|
moel@391
|
445 |
if (points == null)
|
moel@391
|
446 |
{
|
moel@391
|
447 |
return null;
|
moel@391
|
448 |
}
|
moel@391
|
449 |
|
moel@391
|
450 |
var r = new PointF[points.Count()];
|
moel@391
|
451 |
int i = 0;
|
moel@391
|
452 |
foreach (ScreenPoint p in points)
|
moel@391
|
453 |
{
|
moel@391
|
454 |
r[i++] = new PointF((float)p.X, (float)p.Y);
|
moel@391
|
455 |
}
|
moel@391
|
456 |
|
moel@391
|
457 |
return r;
|
moel@391
|
458 |
}
|
moel@391
|
459 |
|
moel@391
|
460 |
public override void CleanUp()
|
moel@391
|
461 |
{
|
moel@391
|
462 |
var imagesToRelease = imageCache.Keys.Where(i => !imagesInUse.Contains(i));
|
moel@391
|
463 |
foreach (var i in imagesToRelease)
|
moel@391
|
464 |
{
|
moel@391
|
465 |
var image = this.GetImage(i);
|
moel@391
|
466 |
image.Dispose();
|
moel@391
|
467 |
imageCache.Remove(i);
|
moel@391
|
468 |
}
|
moel@391
|
469 |
|
moel@391
|
470 |
imagesInUse.Clear();
|
moel@391
|
471 |
}
|
moel@391
|
472 |
|
moel@391
|
473 |
public override OxyImageInfo GetImageInfo(OxyImage source)
|
moel@391
|
474 |
{
|
moel@391
|
475 |
var image = this.GetImage(source);
|
moel@391
|
476 |
return image == null ? null : new OxyImageInfo { Width = (uint)image.Width, Height = (uint)image.Height, DpiX = image.HorizontalResolution, DpiY = image.VerticalResolution };
|
moel@391
|
477 |
}
|
moel@391
|
478 |
|
moel@391
|
479 |
public override void DrawImage(OxyImage source, uint srcX, uint srcY, uint srcWidth, uint srcHeight, double x, double y, double w, double h, double opacity, bool interpolate)
|
moel@391
|
480 |
{
|
moel@391
|
481 |
var image = this.GetImage(source);
|
moel@391
|
482 |
if (image != null)
|
moel@391
|
483 |
{
|
moel@391
|
484 |
ImageAttributes ia = null;
|
moel@391
|
485 |
if (opacity < 1)
|
moel@391
|
486 |
{
|
moel@391
|
487 |
var cm = new ColorMatrix
|
moel@391
|
488 |
{
|
moel@391
|
489 |
Matrix00 = 1f,
|
moel@391
|
490 |
Matrix11 = 1f,
|
moel@391
|
491 |
Matrix22 = 1f,
|
moel@391
|
492 |
Matrix33 = 1f,
|
moel@391
|
493 |
Matrix44 = (float)opacity
|
moel@391
|
494 |
};
|
moel@391
|
495 |
|
moel@391
|
496 |
ia = new ImageAttributes();
|
moel@391
|
497 |
ia.SetColorMatrix(cm, ColorMatrixFlag.Default, ColorAdjustType.Bitmap);
|
moel@391
|
498 |
}
|
moel@391
|
499 |
|
moel@391
|
500 |
g.InterpolationMode = interpolate ? InterpolationMode.HighQualityBicubic : InterpolationMode.NearestNeighbor;
|
moel@391
|
501 |
int sx = (int)Math.Round(x);
|
moel@391
|
502 |
int sy = (int)Math.Round(y);
|
moel@391
|
503 |
int sw = (int)Math.Round(x + w) - sx;
|
moel@391
|
504 |
int sh = (int)Math.Round(y + h) - sy;
|
moel@391
|
505 |
g.DrawImage(image, new Rectangle(sx, sy, sw, sh), srcX, srcY, srcWidth, srcHeight, GraphicsUnit.Pixel, ia);
|
moel@391
|
506 |
}
|
moel@391
|
507 |
}
|
moel@391
|
508 |
|
moel@391
|
509 |
private HashSet<OxyImage> imagesInUse = new HashSet<OxyImage>();
|
moel@391
|
510 |
|
moel@391
|
511 |
private Dictionary<OxyImage, Image> imageCache = new Dictionary<OxyImage, Image>();
|
moel@391
|
512 |
|
moel@391
|
513 |
|
moel@391
|
514 |
private Image GetImage(OxyImage source)
|
moel@391
|
515 |
{
|
moel@391
|
516 |
if (source == null)
|
moel@391
|
517 |
{
|
moel@391
|
518 |
return null;
|
moel@391
|
519 |
}
|
moel@391
|
520 |
|
moel@391
|
521 |
if (!this.imagesInUse.Contains(source))
|
moel@391
|
522 |
{
|
moel@391
|
523 |
this.imagesInUse.Add(source);
|
moel@391
|
524 |
}
|
moel@391
|
525 |
|
moel@391
|
526 |
Image src;
|
moel@391
|
527 |
if (this.imageCache.TryGetValue(source, out src))
|
moel@391
|
528 |
{
|
moel@391
|
529 |
return src;
|
moel@391
|
530 |
}
|
moel@391
|
531 |
|
moel@391
|
532 |
if (source != null)
|
moel@391
|
533 |
{
|
moel@391
|
534 |
Image btm;
|
moel@391
|
535 |
using (var ms = new MemoryStream(source.GetData()))
|
moel@391
|
536 |
{
|
moel@391
|
537 |
btm = Image.FromStream(ms);
|
moel@391
|
538 |
}
|
moel@391
|
539 |
|
moel@391
|
540 |
this.imageCache.Add(source, btm);
|
moel@391
|
541 |
return btm;
|
moel@391
|
542 |
}
|
moel@391
|
543 |
|
moel@391
|
544 |
return null;
|
moel@391
|
545 |
}
|
moel@391
|
546 |
|
moel@391
|
547 |
public override bool SetClip(OxyRect rect)
|
moel@391
|
548 |
{
|
moel@391
|
549 |
this.g.SetClip(rect.ToRect(false));
|
moel@391
|
550 |
return true;
|
moel@391
|
551 |
}
|
moel@391
|
552 |
|
moel@391
|
553 |
public override void ResetClip()
|
moel@391
|
554 |
{
|
moel@391
|
555 |
this.g.ResetClip();
|
moel@391
|
556 |
}
|
moel@391
|
557 |
}
|
moel@391
|
558 |
} |