OSDN Git Service

※ まだ正常な表示にはなっておりません。あしからずご承知おきください。
[dtxmania/dtxmania.git] / DTXManiaプロジェクト / コード / 全体 / CPrivateFont.cs
1 using System;\r
2 using System.Collections.Generic;\r
3 using System.Text;\r
4 using System.IO;\r
5 using System.Runtime.InteropServices;\r
6 using System.Drawing;\r
7 using System.Drawing.Drawing2D;\r
8 using System.Diagnostics;\r
9 using SlimDX;\r
10 using FDK;\r
11 \r
12 namespace DTXMania\r
13 {\r
14         /// <summary>\r
15         /// プライベートフォントでの描画を扱うクラス。\r
16         /// </summary>\r
17         /// <exception cref="FileNotFoundException">フォントファイルが見つからない時に例外発生</exception>\r
18         /// <exception cref="ArgumentException">スタイル指定不正時に例外発生</exception>\r
19         /// <remarks>\r
20         /// 簡単な使い方\r
21         /// CPrivateFont prvFont = new CPrivateFont( CSkin.Path( @"Graphics\fonts\mplus-1p-bold.ttf" ), 36 );   // プライベートフォント\r
22         /// とか\r
23         /// CPrivateFont prvFont = new CPrivateFont( new FontFamily("MS UI Gothic"), 36, FontStyle.Bold );              // システムフォント\r
24         /// とかした上で、\r
25         /// Bitmap bmp = prvFont.DrawPrivateFont( "ABCDE", Color.White, Color.Black );                                                  // フォント色=白、縁の色=黒の例。縁の色は省略可能\r
26         /// とか\r
27         /// Bitmap bmp = prvFont.DrawPrivateFont( "ABCDE", Color.White, Color.Black, Color.Yellow, Color.OrangeRed ); // 上下グラデーション(Yellow→OrangeRed)\r
28         /// とかして、\r
29         /// CTexture ctBmp = CDTXMania.tテクスチャの生成( bmp, false );\r
30         /// ctBMP.t2D描画( ~~~ );\r
31         /// で表示してください。\r
32         /// \r
33         /// 注意点\r
34         /// 任意のフォントでのレンダリングは結構負荷が大きいので、なるべkなら描画フレーム毎にフォントを再レンダリングするようなことはせず、\r
35         /// 一旦レンダリングしたものを描画に使い回すようにしてください。\r
36         /// また、長い文字列を与えると、返されるBitmapも横長になります。この横長画像をそのままテクスチャとして使うと、\r
37         /// 古いPCで問題を発生させやすいです。これを回避するには、一旦Bitmapとして取得したのち、256pixや512pixで分割して\r
38         /// テクスチャに定義するようにしてください。\r
39         /// </remarks>\r
40         public class CPrivateFont : IDisposable\r
41         {\r
42                 #region [ コンストラクタ ]\r
43                 public CPrivateFont( FontFamily fontfamily, int pt, FontStyle style )\r
44                 {\r
45                         Initialize( null, fontfamily, pt, style );\r
46                 }\r
47                 public CPrivateFont( FontFamily fontfamily, int pt )\r
48                 {\r
49                         Initialize( null, fontfamily, pt, FontStyle.Regular );\r
50                 }\r
51                 public CPrivateFont( string fontpath, int pt, FontStyle style )\r
52                 {\r
53                         Initialize( fontpath, null, pt, style );\r
54                 }\r
55                 public CPrivateFont( string fontpath, int pt )\r
56                 {\r
57                         Initialize( fontpath, null, pt, FontStyle.Regular );\r
58                 }\r
59                 public CPrivateFont()\r
60                 {\r
61                         //throw new ArgumentException("CPrivateFont: 引数があるコンストラクタを使用してください。");\r
62                 }\r
63                 #endregion\r
64 \r
65                 protected void Initialize( string fontpath, FontFamily fontfamily, int pt, FontStyle style )\r
66                 {\r
67                         this._pfc = null;\r
68                         this._fontfamily = null;\r
69                         this._font = null;\r
70                         this._pt = pt;\r
71                         this._rectStrings = new Rectangle( 0, 0, 0, 0 );\r
72                         this._ptOrigin = new Point( 0, 0 );\r
73                         this.bDispose完了済み = false;\r
74 \r
75                         if ( fontfamily != null )\r
76                         {\r
77                                 this._fontfamily = fontfamily;\r
78                         }\r
79                         else\r
80                         {\r
81                                 try\r
82                                 {\r
83                                         this._pfc = new System.Drawing.Text.PrivateFontCollection();    //PrivateFontCollectionオブジェクトを作成する\r
84                                         this._pfc.AddFontFile( fontpath );                                                              //PrivateFontCollectionにフォントを追加する\r
85                                 }\r
86                                 catch ( System.IO.FileNotFoundException )\r
87                                 {\r
88                                         Trace.TraceError( "プライベートフォントの追加に失敗しました。({0})", fontpath );\r
89                                         throw new FileNotFoundException( "プライベートフォントの追加に失敗しました。({0})", Path.GetFileName( fontpath ) );\r
90                                         //return;\r
91                                 }\r
92 \r
93                                 //foreach ( FontFamily ff in pfc.Families )\r
94                                 //{\r
95                                 //    Debug.WriteLine( "fontname=" + ff.Name );\r
96                                 //    if ( ff.Name == Path.GetFileNameWithoutExtension( fontpath ) )\r
97                                 //    {\r
98                                 //        _fontfamily = ff;\r
99                                 //        break;\r
100                                 //    }\r
101                                 //}\r
102                                 //if ( _fontfamily == null )\r
103                                 //{\r
104                                 //    Trace.TraceError( "プライベートフォントの追加後、検索に失敗しました。({0})", fontpath );\r
105                                 //    return;\r
106                                 //}\r
107                                 _fontfamily = _pfc.Families[ 0 ];\r
108                         }\r
109 \r
110                         // 指定されたフォントスタイルが適用できない場合は、フォント内で定義されているスタイルから候補を選んで使用する\r
111                         // 何もスタイルが使えないようなフォントなら、例外を出す。\r
112                         if ( !_fontfamily.IsStyleAvailable( style ) )\r
113                         {\r
114                                 FontStyle[] FS = { FontStyle.Regular, FontStyle.Bold, FontStyle.Italic, FontStyle.Underline, FontStyle.Strikeout };\r
115                                 style = FontStyle.Regular | FontStyle.Bold | FontStyle.Italic | FontStyle.Underline | FontStyle.Strikeout;      // null非許容型なので、代わりに全盛をNGワードに設定\r
116                                 foreach ( FontStyle ff in FS )\r
117                                 {\r
118                                         if ( this._fontfamily.IsStyleAvailable( ff ) )\r
119                                         {\r
120                                                 style = ff;\r
121                                                 Trace.TraceWarning( "フォント{0}へのスタイル指定を、{1}に変更しました。", Path.GetFileName( fontpath ), style.ToString() );\r
122                                                 break;\r
123                                         }\r
124                                 }\r
125                                 if ( style == ( FontStyle.Regular | FontStyle.Bold | FontStyle.Italic | FontStyle.Underline | FontStyle.Strikeout ) )\r
126                                 {\r
127                                         throw new ArgumentException( "フォント{0}は適切なスタイルを選択できず、使用できません。", Path.GetFileName( fontpath ) );\r
128                                 }\r
129                         }\r
130                         this._font = new Font( this._fontfamily, pt, style );                   //PrivateFontCollectionの先頭のフォントのFontオブジェクトを作成する\r
131                 }\r
132 \r
133                 [Flags]\r
134                 protected enum DrawMode\r
135                 {\r
136                         Normal,\r
137                         Edge,\r
138                         Gradation\r
139                 }\r
140 \r
141                 #region [ DrawPrivateFontのオーバーロード群 ]\r
142                 /// <summary>\r
143                 /// 文字列を描画したテクスチャを返す\r
144                 /// </summary>\r
145                 /// <param name="drawstr">描画文字列</param>\r
146                 /// <param name="fontColor">描画色</param>\r
147                 /// <returns>描画済テクスチャ</returns>\r
148                 public Bitmap DrawPrivateFont( string drawstr, Color fontColor )\r
149                 {\r
150                         return DrawPrivateFont( drawstr, DrawMode.Normal, fontColor, Color.White, Color.White, Color.White );\r
151                 }\r
152 \r
153                 /// <summary>\r
154                 /// 文字列を描画したテクスチャを返す\r
155                 /// </summary>\r
156                 /// <param name="drawstr">描画文字列</param>\r
157                 /// <param name="fontColor">描画色</param>\r
158                 /// <param name="edgeColor">縁取色</param>\r
159                 /// <returns>描画済テクスチャ</returns>\r
160                 public Bitmap DrawPrivateFont( string drawstr, Color fontColor, Color edgeColor )\r
161                 {\r
162                         return DrawPrivateFont( drawstr, DrawMode.Edge, fontColor, edgeColor, Color.White, Color.White );\r
163                 }\r
164 \r
165                 /// <summary>\r
166                 /// 文字列を描画したテクスチャを返す\r
167                 /// </summary>\r
168                 /// <param name="drawstr">描画文字列</param>\r
169                 /// <param name="fontColor">描画色</param>\r
170                 /// <param name="gradationTopColor">グラデーション 上側の色</param>\r
171                 /// <param name="gradationBottomColor">グラデーション 下側の色</param>\r
172                 /// <returns>描画済テクスチャ</returns>\r
173                 //public Bitmap DrawPrivateFont( string drawstr, Color fontColor, Color gradationTopColor, Color gradataionBottomColor )\r
174                 //{\r
175                 //    return DrawPrivateFont( drawstr, DrawMode.Gradation, fontColor, Color.White, gradationTopColor, gradataionBottomColor );\r
176                 //}\r
177 \r
178                 /// <summary>\r
179                 /// 文字列を描画したテクスチャを返す\r
180                 /// </summary>\r
181                 /// <param name="drawstr">描画文字列</param>\r
182                 /// <param name="fontColor">描画色</param>\r
183                 /// <param name="edgeColor">縁取色</param>\r
184                 /// <param name="gradationTopColor">グラデーション 上側の色</param>\r
185                 /// <param name="gradationBottomColor">グラデーション 下側の色</param>\r
186                 /// <returns>描画済テクスチャ</returns>\r
187                 public Bitmap DrawPrivateFont( string drawstr, Color fontColor, Color edgeColor, Color gradationTopColor, Color gradataionBottomColor )\r
188                 {\r
189                         return DrawPrivateFont( drawstr, DrawMode.Edge | DrawMode.Gradation, fontColor, edgeColor, gradationTopColor, gradataionBottomColor );\r
190                 }\r
191 \r
192 #if こちらは使わない // (Bitmapではなく、CTextureを返す版)\r
193                 /// <summary>\r
194                 /// 文字列を描画したテクスチャを返す\r
195                 /// </summary>\r
196                 /// <param name="drawstr">描画文字列</param>\r
197                 /// <param name="fontColor">描画色</param>\r
198                 /// <returns>描画済テクスチャ</returns>\r
199                 public CTexture DrawPrivateFont( string drawstr, Color fontColor )\r
200                 {\r
201                         Bitmap bmp = DrawPrivateFont( drawstr, DrawMode.Normal, fontColor, Color.White, Color.White, Color.White );\r
202                         return CDTXMania.tテクスチャの生成( bmp, false );\r
203                 }\r
204 \r
205                 /// <summary>\r
206                 /// 文字列を描画したテクスチャを返す\r
207                 /// </summary>\r
208                 /// <param name="drawstr">描画文字列</param>\r
209                 /// <param name="fontColor">描画色</param>\r
210                 /// <param name="edgeColor">縁取色</param>\r
211                 /// <returns>描画済テクスチャ</returns>\r
212                 public CTexture DrawPrivateFont( string drawstr, Color fontColor, Color edgeColor )\r
213                 {\r
214                         Bitmap bmp = DrawPrivateFont( drawstr, DrawMode.Edge, fontColor, edgeColor, Color.White, Color.White );\r
215                         return CDTXMania.tテクスチャの生成( bmp, false );\r
216                 }\r
217 \r
218                 /// <summary>\r
219                 /// 文字列を描画したテクスチャを返す\r
220                 /// </summary>\r
221                 /// <param name="drawstr">描画文字列</param>\r
222                 /// <param name="fontColor">描画色</param>\r
223                 /// <param name="gradationTopColor">グラデーション 上側の色</param>\r
224                 /// <param name="gradationBottomColor">グラデーション 下側の色</param>\r
225                 /// <returns>描画済テクスチャ</returns>\r
226                 //public CTexture DrawPrivateFont( string drawstr, Color fontColor, Color gradationTopColor, Color gradataionBottomColor )\r
227                 //{\r
228                 //    Bitmap bmp = DrawPrivateFont( drawstr, DrawMode.Gradation, fontColor, Color.White, gradationTopColor, gradataionBottomColor );\r
229                 //        return CDTXMania.tテクスチャの生成( bmp, false );\r
230                 //}\r
231 \r
232                 /// <summary>\r
233                 /// 文字列を描画したテクスチャを返す\r
234                 /// </summary>\r
235                 /// <param name="drawstr">描画文字列</param>\r
236                 /// <param name="fontColor">描画色</param>\r
237                 /// <param name="edgeColor">縁取色</param>\r
238                 /// <param name="gradationTopColor">グラデーション 上側の色</param>\r
239                 /// <param name="gradationBottomColor">グラデーション 下側の色</param>\r
240                 /// <returns>描画済テクスチャ</returns>\r
241                 public CTexture DrawPrivateFont( string drawstr, Color fontColor, Color edgeColor,  Color gradationTopColor, Color gradataionBottomColor )\r
242                 {\r
243                         Bitmap bmp = DrawPrivateFont( drawstr, DrawMode.Edge | DrawMode.Gradation, fontColor, edgeColor, gradationTopColor, gradataionBottomColor );\r
244                         return CDTXMania.tテクスチャの生成( bmp, false );\r
245                 }\r
246 #endif\r
247                 #endregion\r
248 \r
249 \r
250                 /// <summary>\r
251                 /// 文字列を描画したテクスチャを返す(メイン処理)\r
252                 /// </summary>\r
253                 /// <param name="rectDrawn">描画された領域</param>\r
254                 /// <param name="ptOrigin">描画文字列</param>\r
255                 /// <param name="drawstr">描画文字列</param>\r
256                 /// <param name="drawmode">描画モード</param>\r
257                 /// <param name="fontColor">描画色</param>\r
258                 /// <param name="edgeColor">縁取色</param>\r
259                 /// <param name="gradationTopColor">グラデーション 上側の色</param>\r
260                 /// <param name="gradationBottomColor">グラデーション 下側の色</param>\r
261                 /// <returns>描画済テクスチャ</returns>\r
262                 protected Bitmap DrawPrivateFont( string drawstr, DrawMode drawmode, Color fontColor, Color edgeColor, Color gradationTopColor, Color gradationBottomColor )\r
263                 {\r
264                         if ( this._fontfamily == null || drawstr == null || drawstr == "" )\r
265                         {\r
266                                 // nullを返すと、その後bmp→texture処理や、textureのサイズを見て・・の処理で全部例外が発生することになる。\r
267                                 // それは非常に面倒なので、最小限のbitmapを返してしまう。\r
268                                 // まずはこの仕様で進めますが、問題有れば(上位側からエラー検出が必要であれば)例外を出したりエラー状態であるプロパティを定義するなり検討します。\r
269                                 if ( drawstr != "" )\r
270                                 {\r
271                                         Trace.TraceWarning( "DrawPrivateFont()の入力不正。最小値のbitmapを返します。" );\r
272                                 }\r
273                                 _rectStrings = new Rectangle( 0, 0, 0, 0 );\r
274                                 _ptOrigin = new Point( 0, 0 );\r
275                                 return new Bitmap(1, 1);\r
276                         }\r
277                         bool bEdge =      ( ( drawmode & DrawMode.Edge      ) == DrawMode.Edge );\r
278                         bool bGradation = ( ( drawmode & DrawMode.Gradation ) == DrawMode.Gradation );\r
279 \r
280                         // 縁取りの縁のサイズは、とりあえずフォントの大きさの1/4とする\r
281                         int nEdgePt = (bEdge)? _pt / 4 : 0;\r
282 \r
283                         // 描画サイズを測定する\r
284                         Size stringSize = System.Windows.Forms.TextRenderer.MeasureText( drawstr, this._font );\r
285 \r
286                         //取得した描画サイズを基に、描画先のbitmapを作成する\r
287                         Bitmap bmp = new Bitmap( stringSize.Width + nEdgePt * 2, stringSize.Height + nEdgePt * 2 );\r
288                         bmp.MakeTransparent();\r
289                         Graphics g = Graphics.FromImage( bmp );\r
290                         g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;\r
291 \r
292                         StringFormat sf = new StringFormat();\r
293                         sf.LineAlignment = StringAlignment.Far; // 画面下部(垂直方向位置)\r
294                         sf.Alignment = StringAlignment.Center;  // 画面中央(水平方向位置)\r
295 \r
296                         // レイアウト枠\r
297                         Rectangle r = new Rectangle( 0, 0, stringSize.Width + nEdgePt * 2, stringSize.Height + nEdgePt * 2 );\r
298 \r
299                         if ( bEdge )    // 縁取り有りの描画\r
300                         {\r
301                                 // DrawPathで、ポイントサイズを使って描画するために、DPIを使って単位変換する\r
302                                 // (これをしないと、単位が違うために、小さめに描画されてしまう)\r
303                                 float sizeInPixels = _font.SizeInPoints * g.DpiY / 72;  // 1 inch = 72 points\r
304 \r
305                                 System.Drawing.Drawing2D.GraphicsPath gp = new System.Drawing.Drawing2D.GraphicsPath();\r
306                                 gp.AddString( drawstr, this._fontfamily, (int) this._font.Style, sizeInPixels, r, sf );\r
307 \r
308                                 // 縁取りを描画する\r
309                                 Pen p = new Pen( edgeColor, nEdgePt );\r
310                                 p.LineJoin = System.Drawing.Drawing2D.LineJoin.Round;\r
311                                 g.DrawPath( p, gp );\r
312 \r
313                                 // 塗りつぶす\r
314                                 Brush br;\r
315                                 if ( bGradation )\r
316                                 {\r
317                                         br = new LinearGradientBrush( r, gradationTopColor, gradationBottomColor, LinearGradientMode.Vertical );\r
318                                 }\r
319                                 else\r
320                                 {\r
321                                         br = new SolidBrush( fontColor );\r
322                                 }\r
323                                 g.FillPath( br, gp );\r
324 \r
325                                 if ( br != null ) br.Dispose(); br = null;\r
326                                 if ( p != null ) p.Dispose(); p = null;\r
327                                 if ( gp != null ) gp.Dispose(); gp = null;\r
328                         }\r
329                         else\r
330                         {\r
331                                 // 縁取りなしの描画\r
332                                 System.Windows.Forms.TextRenderer.DrawText( g, drawstr, _font, new Point( 0, 0 ), fontColor );\r
333                         }\r
334 #if debug表示\r
335                         g.DrawRectangle( new Pen( Color.White, 1 ), new Rectangle( 1, 1, stringSize.Width-1, stringSize.Height-1 ) );\r
336                         g.DrawRectangle( new Pen( Color.Green, 1 ), new Rectangle( 0, 0, bmp.Width - 1, bmp.Height - 1 ) );\r
337 #endif\r
338                         _rectStrings = new Rectangle( 0, 0, stringSize.Width, stringSize.Height );\r
339                         _ptOrigin = new Point( nEdgePt * 2, nEdgePt * 2 );\r
340                         \r
341 \r
342                         #region [ リソースを解放する ]\r
343                         if ( sf != null )       sf.Dispose();   sf = null;\r
344                         if ( g != null )        g.Dispose();    g = null;\r
345                         #endregion\r
346 \r
347                         return bmp;\r
348                 }\r
349 \r
350                 /// <summary>\r
351                 /// 最後にDrawPrivateFont()した文字列の描画領域を取得します。\r
352                 /// </summary>\r
353                 public Rectangle RectStrings\r
354                 {\r
355                         get\r
356                         {\r
357                                 return _rectStrings;\r
358                         }\r
359                         protected set\r
360                         {\r
361                                 _rectStrings = value;\r
362                         }\r
363                 }\r
364                 public Point PtOrigin\r
365                 {\r
366                         get\r
367                         {\r
368                                 return _ptOrigin;\r
369                         }\r
370                         protected set\r
371                         {\r
372                                 _ptOrigin = value;\r
373                         }\r
374                 }\r
375 \r
376                 #region [ IDisposable 実装 ]\r
377                 //-----------------\r
378                 public void Dispose()\r
379                 {\r
380                         if ( !this.bDispose完了済み )\r
381                         {\r
382                                 if ( this._font != null )\r
383                                 {\r
384                                         this._font.Dispose();\r
385                                         this._font = null;\r
386                                 }\r
387                                 if ( this._pfc != null )\r
388                                 {\r
389                                         this._pfc.Dispose();\r
390                                         this._pfc = null;\r
391                                 }\r
392 \r
393                                 this.bDispose完了済み = true;\r
394                         }\r
395                 }\r
396                 //-----------------\r
397                 #endregion\r
398 \r
399                 #region [ private ]\r
400                 //-----------------\r
401                 protected bool bDispose完了済み;\r
402                 protected Font _font;\r
403 \r
404                 private System.Drawing.Text.PrivateFontCollection _pfc;\r
405                 private FontFamily _fontfamily;\r
406                 private int _pt;\r
407                 private Rectangle _rectStrings;\r
408                 private Point _ptOrigin;\r
409                 //-----------------\r
410                 #endregion\r
411         }\r
412 }\r