External/OxyPlot/OxyPlot.WindowsForms/GraphicsRenderContext.cs
author moel.mich
Sat, 08 Jun 2013 16:53:22 +0000
changeset 391 5be8f2773237
permissions -rw-r--r--
Added the source code of OxyPlot as of commit d190d7748a73 (6.5.2013).
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
}