OSDN Git Service

画像系クラスを復元。
authorくまかみ工房 <kumakamikoubou@gmail.com>
Wed, 31 May 2017 06:15:45 +0000 (15:15 +0900)
committerくまかみ工房 <kumakamikoubou@gmail.com>
Wed, 31 May 2017 06:15:45 +0000 (15:15 +0900)
FDK/FDK.csproj
FDK/メディア/描画可能画像.cs [new file with mode: 0644]
FDK/メディア/文字列画像.cs [new file with mode: 0644]
FDK/メディア/画像.cs
FDK/メディア/画像フォント.cs [new file with mode: 0644]

index 516cfdb..c5e0538 100644 (file)
     <Compile Include="メディア\サウンド\WASAPI\Device.cs" />
     <Compile Include="メディア\サウンド\WASAPI\Mixer.cs" />
     <Compile Include="メディア\サウンド\WASAPI\Sound.cs" />
+    <Compile Include="メディア\描画可能画像.cs" />
+    <Compile Include="メディア\文字列画像.cs" />
     <Compile Include="メディア\画像.cs" />
+    <Compile Include="メディア\画像フォント.cs" />
     <Compile Include="メディア\矩形リスト.cs" />
     <Compile Include="入力\IInputDevice.cs" />
     <Compile Include="入力\InputDeviceType.cs" />
diff --git a/FDK/メディア/描画可能画像.cs b/FDK/メディア/描画可能画像.cs
new file mode 100644 (file)
index 0000000..0420ab5
--- /dev/null
@@ -0,0 +1,75 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using SharpDX.Direct2D1;
+
+namespace FDK.メディア
+{
+       /// <summary>
+       ///             レンダーターゲットとしても描画可能なビットマップを扱うクラス。
+       /// </summary>
+       public class 描画可能画像 : 画像
+       {
+               public 描画可能画像( string 画像ファイルパス )
+                       : base( 画像ファイルパス )
+               {
+               }
+
+               public 描画可能画像( SharpDX.Size2 サイズ )
+                       : base( null )
+               {
+                       this._サイズ = サイズ;
+               }
+
+               protected override void On活性化( グラフィックデバイス gd )
+               {
+                       if( this._画像ファイルパス.Nullでも空でもない() )
+                       {
+                               // (A) ファイルから生成する。
+                               this._画像を生成する( gd, new BitmapProperties1() { BitmapOptions = BitmapOptions.Target } );
+                       }
+                       else
+                       {
+                               // (B) 空のビットマップを生成する。
+                               this._Bitmap?.Dispose();
+                               this._Bitmap = new Bitmap1( gd.D2DDeviceContext, this._サイズ, new BitmapProperties1() {
+                                       PixelFormat = new PixelFormat( gd.D2DDeviceContext.PixelFormat.Format, AlphaMode.Premultiplied ),
+                                       BitmapOptions = BitmapOptions.Target,
+                               } );
+                       }
+               }
+
+               /// <summary>
+               ///             生成済み画像(ビットマップ)に対するユーザアクションによる描画を行う。
+               /// </summary>
+               /// <remarks>
+               ///             活性化状態であれば、進行描画() 中でなくても、任意のタイミングで呼び出して良い。
+               ///             ユーザアクション内では BeginDraw(), EndDraw() の呼び出しは(呼び出しもとでやるので)不要。
+               /// </remarks>
+               /// <param name="gd">グラフィックデバイス。</param>
+               /// <param name="描画アクション">Bitmap に対して行いたい操作。</param>
+               public void 画像へ描画する( グラフィックデバイス gd, Action<DeviceContext1> 描画アクション )
+               {
+                       using( var 旧ターゲット = gd.D2DDeviceContext.Target )
+                       {
+                               try
+                               {
+                                       gd.D2DDeviceContext.Target = this._Bitmap;
+                                       gd.D2DBatchDraw( ( dc ) => {
+                                               描画アクション( dc );
+                                       } );
+                               }
+                               finally
+                               {
+                                       gd.D2DDeviceContext.Target = 旧ターゲット;
+                               }
+                       }
+               }
+
+
+               private SharpDX.Size2 _サイズ;
+       }
+}
diff --git a/FDK/メディア/文字列画像.cs b/FDK/メディア/文字列画像.cs
new file mode 100644 (file)
index 0000000..6a90a14
--- /dev/null
@@ -0,0 +1,260 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using SharpDX;
+using SharpDX.Direct2D1;
+using SharpDX.DirectWrite;
+using FDK;
+
+namespace FDK.メディア
+{
+       /// <summary>
+       ///             DirectWrite を使った Direct2D1ビットマップ。
+       /// </summary>
+       /// <remarks>
+       ///             「表示文字列」メンバを設定/更新すれば、次回の描画時にビットマップが生成される。
+       /// </remarks>
+       public class 文字列画像 : Activity
+       {
+               /// <summary>
+               ///             このメンバを set すれば、次回の進行描画時に画像が更新される。
+               /// </summary>
+               public string 表示文字列
+               {
+                       get;
+                       set;
+               } = null;
+
+               public string フォント名
+               {
+                       get;
+                       set;
+               } = "メイリオ";
+
+               public float フォントサイズpt
+               {
+                       get;
+                       set;
+               } = 20.0f;
+
+               public FontWeight フォント幅
+               {
+                       get;
+                       set;
+               } = FontWeight.Normal;
+
+               public FontStyle フォントスタイル
+               {
+                       get;
+                       set;
+               } = FontStyle.Normal;
+
+               public InterpolationMode 補正モード
+               {
+                       get;
+                       set;
+               } = InterpolationMode.Linear;
+
+               public RectangleF? 転送元矩形
+               {
+                       get;
+                       set;
+               } = null;
+
+               public bool 加算合成
+               {
+                       get;
+                       set;
+               } = false;
+
+               public Size2F レイアウトサイズ
+               {
+                       get;
+                       set;
+               } = new Size2F( -1f, -1f );
+
+               public bool 下詰め
+               {
+                       get;
+                       set;
+               } = false;
+
+
+               public 文字列画像()
+               {
+               }
+
+               public 文字列画像( string 文字列, float フォントサイズpt = 20.0f, string フォント名 = "メイリオ", FontWeight フォント幅 = FontWeight.Normal, FontStyle フォントスタイル = FontStyle.Normal )
+                       : this()
+               {
+                       this.表示文字列 = 文字列;
+                       this.フォント名 = フォント名;
+                       this.フォントサイズpt = フォントサイズpt;
+                       this.フォント幅 = フォント幅;
+                       this.フォントスタイル = フォントスタイル;
+               }
+
+               protected override void On活性化( グラフィックデバイス gd )
+               {
+                       this._前回の表示文字列 = null;
+
+                       if( this.表示文字列.Nullでも空でもない() )
+                       {
+                               this.ビットマップレンダーターゲットを生成する( gd );
+                               this._前回の表示文字列 = this.表示文字列; // 最初の構築完了。
+                       }
+               }
+
+               protected override void On非活性化( グラフィックデバイス gd )
+               {
+                       FDKUtilities.解放する( ref this._黒ブラシ );
+                       FDKUtilities.解放する( ref this._白ブラシ );
+                       FDKUtilities.解放する( ref this.ビットマップレンダーターゲット );
+                       FDKUtilities.解放する( ref this._テキストレイアウト );
+                       FDKUtilities.解放する( ref this._テキストフォーマット );
+               }
+
+               public void 描画する( グラフィックデバイス gd, float 左位置, float 上位置, float 不透明度0to1 = 1.0f, float X方向拡大率 = 1.0f, float Y方向拡大率 = 1.0f, Matrix? 変換行列3D = null )
+               {
+                       var 変換行列2D =
+                               Matrix3x2.Scaling( X方向拡大率, Y方向拡大率 )     // スケーリング
+                               * Matrix3x2.Translation( 左位置, 上位置 );        // 平行移動
+
+                       this.描画する( gd, 変換行列2D, 変換行列3D, 不透明度0to1 );
+               }
+
+               public void 描画する( グラフィックデバイス gd, Matrix3x2? 変換行列2D = null, Matrix? 変換行列3D = null, float 不透明度0to1 = 1.0f )
+               {
+                       Debug.Assert( this.活性化している );
+
+                       if( this.表示文字列.Nullまたは空である() )
+                               return;
+
+                       // 表示文字列が変更されているなら、ここで表示ビットマップレンダーターゲットの再構築を行う。
+                       if( false == string.Equals( this.表示文字列, this._前回の表示文字列 ) )
+                       {
+                               this.ビットマップレンダーターゲットを生成する( gd );
+                       }
+
+                       if( null == this.ビットマップレンダーターゲット )
+                               return;
+
+                       gd.D2DBatchDraw( ( dc ) => {
+
+                               // 変換行列とブレンドモードをD2Dレンダーターゲットに設定する。
+                               dc.Transform = ( 変換行列2D ?? Matrix3x2.Identity ) * dc.Transform;
+                               dc.PrimitiveBlend = ( 加算合成 ) ? PrimitiveBlend.Add : PrimitiveBlend.SourceOver;
+
+                               // D2Dレンダーターゲットに this.Bitmap を描画する。
+                               using( var bmp = this.ビットマップレンダーターゲット.Bitmap )
+                               {
+                                       dc.DrawBitmap(
+                                               bitmap: bmp,
+                                               destinationRectangle: null,
+                                               opacity: 不透明度0to1,
+                                               interpolationMode: this.補正モード,
+                                               sourceRectangle: this.転送元矩形,
+                                               erspectiveTransformRef: 変換行列3D );
+                               }
+                       } );
+               }
+
+
+               protected SharpDX.Direct2D1.BitmapRenderTarget ビットマップレンダーターゲット = null;
+
+               protected void ビットマップレンダーターゲットを生成する( グラフィックデバイス gd )
+               {
+                       this._前回の表示文字列 = this.表示文字列;
+
+                       // テキストフォーマット/レイアウトを作成し、表示ビットマップのサイズを計算する。
+                       if( null == this._テキストフォーマット )
+                       {
+                               this._テキストフォーマット = new TextFormat( gd.DWriteFactory, this.フォント名, this.フォント幅, this.フォントスタイル, this.フォントサイズpt ) {
+                                       TextAlignment = TextAlignment.Leading,
+                               };
+                       }
+
+                       this.レイアウトサイズ = new Size2F( gd.設計画面サイズ.Width, gd.設計画面サイズ.Height );
+
+                       this._テキストレイアウト?.Dispose();
+                       this._テキストレイアウト = new TextLayout(
+                               gd.DWriteFactory,
+                               this.表示文字列,
+                               this._テキストフォーマット,
+                               this.レイアウトサイズ.Width,
+                               this.レイアウトサイズ.Height );
+
+                       var 表示ビットマップのサイズ = new Size2F();
+                       var 上マージン = 0.0f;
+
+                       if( this.下詰め )
+                       {
+                               表示ビットマップのサイズ = new Size2F(
+                                       this._テキストレイアウト.Metrics.WidthIncludingTrailingWhitespace,
+                                       this.レイアウトサイズ.Height );       // レイアウトの最大高
+
+                               上マージン = this.レイアウトサイズ.Height - this._テキストレイアウト.Metrics.Height;
+                       }
+                       else
+                       {
+                               表示ビットマップのサイズ = new Size2F(
+                                       this._テキストレイアウト.Metrics.WidthIncludingTrailingWhitespace,
+                                       this._テキストレイアウト.Metrics.Height );
+                       }
+
+                       // 実際のビットマップサイズに更新。
+                       this.レイアウトサイズ = 表示ビットマップのサイズ;
+
+                       // ビットマップレンダーターゲットを生成する。
+                       using( var target = gd.D2DDeviceContext.Target )        // Target を get すると COM参照カウンタが増えるので注意。
+                       {
+                               // D2DContext1.Target が設定済みであること。さもなきゃ例外も出さずに落ちる。
+                               Debug.Assert( null != target );
+                       }
+                       this.ビットマップレンダーターゲット?.Dispose();
+                       this.ビットマップレンダーターゲット = new SharpDX.Direct2D1.BitmapRenderTarget(
+                               gd.D2DDeviceContext,
+                               CompatibleRenderTargetOptions.None,
+                               表示ビットマップのサイズ );
+
+                       // ブラシの作成がまだなら行う。
+                       if( null == this._白ブラシ )
+                       {
+                               this._白ブラシ = new SolidColorBrush( this.ビットマップレンダーターゲット, Color.LightGray );
+                       }
+                       if( null == this._黒ブラシ )
+                       {
+                               this._黒ブラシ = new SolidColorBrush( this.ビットマップレンダーターゲット, Color.Black );
+                       }
+
+                       // ビットマップレンダーターゲットにテキストを描画する。
+                       gd.D2DBatchDraw( this.ビットマップレンダーターゲット, ( rt ) => {
+
+                               rt.Clear( Color.Transparent );
+
+                               rt.DrawTextLayout(    // ドロップシャドウ
+                                       new Vector2( 1.0f, 上マージン + 1.0f ),
+                                       this._テキストレイアウト,
+                                       this._黒ブラシ,
+                                       DrawTextOptions.Clip );
+
+                               rt.DrawTextLayout(    // 本体
+                                       new Vector2( 0.0f, 上マージン ),
+                                       this._テキストレイアウト,
+                                       this._白ブラシ,
+                                       DrawTextOptions.Clip );
+                       } );
+               }
+
+
+               private string _前回の表示文字列 = null;
+
+               private TextFormat _テキストフォーマット = null;
+
+               private TextLayout _テキストレイアウト = null;
+
+               private SolidColorBrush _白ブラシ = null;
+
+               private SolidColorBrush _黒ブラシ = null;
+       }
+}
index b2ef8aa..e2bae05 100644 (file)
@@ -98,16 +98,7 @@ namespace FDK.メディア
                ///             それが困る場合には、<paramref name="描画先矩形を整数境界に合わせる"/> に true を指定すること。
                ///             ただし、これを true にした場合、タイルのように並べて描画した場合に1pxずれる場合がある。この場合は false にすること。
                /// </remarks>
-               public virtual void 描画する(
-                       グラフィックデバイス gd,
-                       float 左位置,
-                       float 上位置,
-                       float 不透明度0to1 = 1.0f,
-                       float X方向拡大率 = 1.0f,
-                       float Y方向拡大率 = 1.0f,
-                       RectangleF? 転送元矩形 = null,
-                       bool 描画先矩形を整数境界に合わせる = false,
-                       Matrix? 変換行列3D = null )
+               public virtual void 描画する( グラフィックデバイス gd, float 左位置, float 上位置, float 不透明度0to1 = 1.0f, float X方向拡大率 = 1.0f, float Y方向拡大率 = 1.0f, RectangleF? 転送元矩形 = null, bool 描画先矩形を整数境界に合わせる = false, Matrix? 変換行列3D = null )
                {
                        Debug.Assert( this.活性化している );
 
@@ -159,12 +150,7 @@ namespace FDK.メディア
                /// <param name="変換行列3D">射影行列。</param>
                /// <param name="不透明度0to1">不透明度。(0:透明~1:不透明)</param>
                /// <param name="転送元矩形">描画する画像範囲。</param>
-               public virtual void 描画する(
-                       グラフィックデバイス gd,
-                       Matrix3x2? 変換行列2D = null,
-                       Matrix? 変換行列3D = null,
-                       float 不透明度0to1 = 1.0f,
-                       RectangleF? 転送元矩形 = null )
+               public virtual void 描画する( グラフィックデバイス gd, Matrix3x2? 変換行列2D = null, Matrix? 変換行列3D = null, float 不透明度0to1 = 1.0f, RectangleF? 転送元矩形 = null )
                {
                        Debug.Assert( this.活性化している );
 
diff --git a/FDK/メディア/画像フォント.cs b/FDK/メディア/画像フォント.cs
new file mode 100644 (file)
index 0000000..b269278
--- /dev/null
@@ -0,0 +1,64 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+
+namespace FDK.メディア
+{
+       /// <summary>
+       ///             任意個の文字を格納した一枚の画像と、それぞれの文字領域の矩形リストから、文字列を連続するD2D画像で表示する。
+       /// </summary>
+       public class 画像フォント : Activity
+       {
+               public 画像フォント( string 文字盤の画像ファイルパス, string 文字矩形リストファイルパス )
+                       : this( 文字盤の画像ファイルパス, new 矩形リスト( 文字矩形リストファイルパス ) )
+               {
+               }
+
+               public 画像フォント( string 文字盤の画像ファイルパス, 矩形リスト 文字矩形リスト )
+               {
+                       this.子リスト.Add( this._文字盤 = new 画像( 文字盤の画像ファイルパス ) );
+                       this._文字矩形リスト = 文字矩形リスト;
+               }
+
+               public void 描画する( グラフィックデバイス gd, float 左位置, float 上位置, string 表示文字列 )
+               {
+                       if( 表示文字列.Nullまたは空である() )
+                               return;
+
+                       // 有効文字(矩形リストに登録されている文字)の矩形、文字数を抽出し、文字列全体のサイズを計算する。
+                       var 有効文字矩形リスト =
+                               from 文字 in 表示文字列
+                               where ( this._文字矩形リスト.文字列to矩形.ContainsKey( new string( new char[] { 文字 } ) ) )
+                               select this._文字矩形リスト.文字列to矩形[ new string( new char[] { 文字 } ) ];
+
+                       int 有効文字数 = 有効文字矩形リスト.Count();
+                       if( 0 == 有効文字数 )
+                               return;
+
+                       var 文字列全体のサイズ = SharpDX.Size2F.Empty;
+                       foreach( var 文字矩形 in 有効文字矩形リスト )
+                       {
+                               文字列全体のサイズ.Width += 文字矩形.Width;
+
+                               if( 文字列全体のサイズ.Height < 文字矩形.Height )
+                                       文字列全体のサイズ.Height = 文字矩形.Height;  // 文字列全体の高さは、最大の文字高に一致。
+                       }
+
+                       // 描画する。
+                       for( int i = 0; i < 有効文字数; i++ )
+                       {
+                               var 文字矩形 = 有効文字矩形リスト.ElementAt( i );
+
+                               this._文字盤.描画する( gd, 左位置, 上位置, 転送元矩形: 文字矩形 );
+
+                               左位置 += 文字矩形.Width;
+                       }
+               }
+
+
+               private 画像 _文字盤 = null;
+
+               private 矩形リスト _文字矩形リスト = null;
+       }
+}