2013-10-27T22:49:12の更新内容

programming/netfx/tips/pathgradientbrush_outofmemoryexception/index.wiki.txt

current previous
1,151 0,0
+
${smdncms:title,PathGradientBrushがOutOfMemoryExceptionをスローする条件}
+
${smdncms:keywords,C#,PathGradientBrush,OutOfMemoryException}
+
${smdncms:tags,lang/c#,api/.net}
+

          
+
&msdn(netfx,type,System.Drawing.dll,System.Drawing.Drawing2D.GraphicsPath){GraphicsPath};を指定して&msdn(netfx,type,System.Drawing.dll,System.Drawing.Drawing2D.PathGradientBrush){PathGradientBrush};のインスタンスを作成する際、GraphicsPathに設定されているパスの内容次第ではPathGradientBrushのコンストラクタが例外&msdn(netfx,type,System.OutOfMemoryException){OutOfMemoryException};をスローする。
+

          
+
#googleadunit
+

          
+
*扇型のパス (GraphicsPath.AddPie)
+
&msdn(netfx,member,System.Drawing.dll,System.Drawing.Drawing2D.GraphicsPath.AddPie){GraphicsPath.AddPie};で&var{sweepAngle};に``0``などの微小な角度を指定したパスを追加すると、OutOfMemoryExceptionとなる。
+

          
+
#code(cs,sweepAngleが0の扇型パスからPathGradientBrushを作成する){{
+
using System;
+
using System.Drawing;
+
using System.Drawing.Drawing2D;
+

          
+
class Sample {
+
  public static void Main(string[] args)
+
  {
+
    var bounds = new RectangleF(0.0f, 0.0f, 64.0f, 64.0f);
+
    const float startAngle = 0.0f;
+
    const float sweepAngle = 0.0f;
+

          
+
    using (var gp = new GraphicsPath()) {
+
      // GraphicsPathにsweepAngleが0の扇型パスを追加する
+
      gp.AddPie(bounds.X, bounds.Y, bounds.Width, bounds.Height, startAngle, sweepAngle);
+

          
+
      // PathGradientBrushのコンストラクタがOutOfMemoryExceptionをスローする
+
      using (var pgb = new PathGradientBrush(gp)) {
+
        Console.WriteLine(pgb);
+
      }
+
    }
+
  }
+
}
+
}}
+

          
+
扇形が正円(外接するRectangleが正方形)の場合は、&var{sweepAngle};に指定する値が``1.611493E-43``以上(後述の検証結果参照)であればOutOfMemoryExceptionとならない模様。 この値は扇形(外接するRectangle)の大きさによらず一定。 扇型が楕円(外接するRectangleが長方形)の場合は、その縦横比に応じてOutOfMemoryExceptionとなる&var{sweepAngle};の値も変わる。
+

          
+
以下は、GraphicsPath.AddPieに指定する&var{sweepAngle};の値を変えて正円の扇型パスを追加し、PathGradientBrushがOutOfMemoryExceptionをスローするかどうかを検証した結果。
+

          
+
#prompt(sweepAngleが1.0E-45から1.0E-1まで、10倍刻み){{
+
1.401298E-45: OutOfMemoryException
+
9.809089E-45: OutOfMemoryException
+
9.949219E-44: OutOfMemoryException
+
1.000527E-42: OK
+
9.999666E-42: OK
+
9.999946E-41: OK
+
1E-39: OK
+
9.999999E-39: OK
+
1E-37: OK
+
1E-36: OK
+
1E-35: OK
+
1E-34: OK
+
1E-33: OK
+
1E-32: OK
+
1E-31: OK
+
1E-30: OK
+
1E-29: OK
+
1E-28: OK
+
1E-27: OK
+
1E-26: OK
+
1E-25: OK
+
1E-24: OK
+
1E-23: OK
+
1E-22: OK
+
1E-21: OK
+
1E-20: OK
+
1E-19: OK
+
1E-18: OK
+
1E-17: OK
+
1E-16: OK
+
1E-15: OK
+
1E-14: OK
+
1E-13: OK
+
1E-12: OK
+
1E-11: OK
+
1E-10: OK
+
1E-09: OK
+
1E-08: OK
+
1E-07: OK
+
1E-06: OK
+
1E-05: OK
+
0.0001: OK
+
0.001: OK
+
0.01: OK
+
0.1: OK
+
}}
+

          
+
#prompt(sweepAngleが0.0以上、float.Epsilon刻み){{
+
0: OutOfMemoryException
+
1.401298E-45: OutOfMemoryException
+
2.802597E-45: OutOfMemoryException
+
4.203895E-45: OutOfMemoryException
+
  :
+
(中略)
+
  :
+
1.569454E-43: OutOfMemoryException
+
1.583467E-43: OutOfMemoryException
+
1.59748E-43: OutOfMemoryException
+
1.611493E-43: OK
+
1.625506E-43: OK
+
1.639519E-43: OK
+
  :
+
(後略)
+
  :
+
}}
+

          
+
#code(cs,検証に使ったコード){{
+
using System;
+
using System.Drawing;
+
using System.Drawing.Drawing2D;
+

          
+
class Sample {
+
  public static void Main(string[] args)
+
  {
+
    var bounds = new RectangleF(0.0f, 0.0f, 64.0f, 64.0f);
+
    const float startAngle = 0.0f;
+

          
+
    //for (var sweepAngle = 0.0f; sweepAngle <= 1.0f; sweepAngle += float.Epsilon) {
+
    for (var exp = -45; exp < 0; exp++) {
+
      var sweepAngle = (float)Math.Pow(10.0, exp);
+

          
+
      Console.Write("{0}: ", sweepAngle);
+

          
+
      using (var gp = new GraphicsPath()) {
+
        gp.AddPie(bounds.X, bounds.Y, bounds.Width, bounds.Height, startAngle, sweepAngle);
+

          
+
        try {
+
          using (var pgb = new PathGradientBrush(gp)) {
+
            Console.WriteLine("OK");
+
          }
+
        }
+
        catch (OutOfMemoryException) {
+
          Console.WriteLine("OutOfMemoryException");
+
        }
+
      }
+
    }
+
  }
+
}
+
}}
+

          
+
**Graphics.FillPie/DrawPie
+
&msdn(netfx,member,System.Drawing.dll,System.Drawing.Graphics.FillPie){Graphics.FillPie};メソッドや&msdn(netfx,member,System.Drawing.dll,System.Drawing.Graphics.DrawPie){Graphics.DrawPie};メソッドでは、&var{sweepAngle};が``0``や微小な値であってもOutOfMemoryExceptionや&msdn(netfx,type,System.ArgumentOutOfRangeException){ArgumentOutOfRangeException};はスローされない。
+

          
+
**libgdiplus(Mono)の場合
+
libgdiplusでは、AddPieメソッドに指定する&var{sweepAngle};が``0``や微小な値であってもOutOfMemoryExceptionや&msdn(netfx,type,System.ArgumentOutOfRangeException){ArgumentOutOfRangeException};はスローされない。
+

          
+
*それ以外のパス
+
未検証。
+

          
+