2 using System.Collections.Generic;
\r
5 using System.Runtime.InteropServices;
\r
6 using System.Drawing;
\r
7 using System.Drawing.Drawing2D;
\r
8 using System.Diagnostics;
\r
15 /// プライベートフォントでの描画を扱うクラス。
\r
17 /// <exception cref="FileNotFoundException">フォントファイルが見つからない時に例外発生</exception>
\r
18 /// <exception cref="ArgumentException">スタイル指定不正時に例外発生</exception>
\r
21 /// CPrivateFont prvFont = new CPrivateFont( CSkin.Path( @"Graphics\fonts\mplus-1p-bold.ttf" ), 36 ); // プライベートフォント
\r
23 /// CPrivateFont prvFont = new CPrivateFont( new FontFamily("MS UI Gothic"), 36, FontStyle.Bold ); // システムフォント
\r
25 /// Bitmap bmp = prvFont.DrawPrivateFont( "ABCDE", Color.White, Color.Black ); // フォント色=白、縁の色=黒の例。縁の色は省略可能
\r
27 /// Bitmap bmp = prvFont.DrawPrivateFont( "ABCDE", Color.White, Color.Black, Color.Yellow, Color.OrangeRed ); // 上下グラデーション(Yellow→OrangeRed)
\r
29 /// CTexture ctBmp = TextureFactory.tテクスチャの生成( bmp, false );
\r
30 /// ctBMP.t2D描画( ~~~ );
\r
34 /// 任意のフォントでのレンダリングは結構負荷が大きいので、なるべkなら描画フレーム毎にフォントを再レンダリングするようなことはせず、
\r
35 /// 一旦レンダリングしたものを描画に使い回すようにしてください。
\r
36 /// また、長い文字列を与えると、返されるBitmapも横長になります。この横長画像をそのままテクスチャとして使うと、
\r
37 /// 古いPCで問題を発生させやすいです。これを回避するには、一旦Bitmapとして取得したのち、256pixや512pixで分割して
\r
38 /// テクスチャに定義するようにしてください。
\r
40 public class CPrivateFont : IDisposable
\r
43 public CPrivateFont(FontFamily fontfamily, int pt, FontStyle style)
\r
45 Initialize(null, fontfamily, pt, style);
\r
47 public CPrivateFont(FontFamily fontfamily, int pt)
\r
49 Initialize(null, fontfamily, pt, FontStyle.Regular);
\r
51 public CPrivateFont(string fontpath, int pt, FontStyle style)
\r
53 Initialize(fontpath, null, pt, style);
\r
55 public CPrivateFont(string fontpath, int pt)
\r
57 Initialize(fontpath, null, pt, FontStyle.Regular);
\r
59 public CPrivateFont()
\r
61 //throw new ArgumentException("CPrivateFont: 引数があるコンストラクタを使用してください。");
\r
65 protected void Initialize(string fontpath, FontFamily fontfamily, int pt, FontStyle style)
\r
68 this._fontfamily = null;
\r
71 this._rectStrings = new Rectangle(0, 0, 0, 0);
\r
72 this._ptOrigin = new Point(0, 0);
\r
73 this.bDispose完了済み = false;
\r
75 if (fontfamily != null)
\r
77 this._fontfamily = fontfamily;
\r
83 this._pfc = new System.Drawing.Text.PrivateFontCollection(); //PrivateFontCollectionオブジェクトを作成する
\r
84 this._pfc.AddFontFile(fontpath); //PrivateFontCollectionにフォントを追加する
\r
85 _fontfamily = _pfc.Families[0];
\r
87 catch (System.IO.FileNotFoundException)
\r
89 Trace.TraceWarning("プライベートフォントの追加に失敗しました({0})。代わりにMS PGothicの使用を試みます。", fontpath);
\r
90 //throw new FileNotFoundException( "プライベートフォントの追加に失敗しました。({0})", Path.GetFileName( fontpath ) );
\r
95 //foreach ( FontFamily ff in _pfc.Families )
\r
97 // Debug.WriteLine( "fontname=" + ff.Name );
\r
98 // if ( ff.Name == Path.GetFileNameWithoutExtension( fontpath ) )
\r
100 // _fontfamily = ff;
\r
104 //if ( _fontfamily == null )
\r
106 // Trace.TraceError( "プライベートフォントの追加後、検索に失敗しました。({0})", fontpath );
\r
111 // 指定されたフォントスタイルが適用できない場合は、フォント内で定義されているスタイルから候補を選んで使用する
\r
112 // 何もスタイルが使えないようなフォントなら、例外を出す。
\r
113 if (_fontfamily != null)
\r
115 if (!_fontfamily.IsStyleAvailable(style))
\r
117 FontStyle[] FS = { FontStyle.Regular, FontStyle.Bold, FontStyle.Italic, FontStyle.Underline, FontStyle.Strikeout };
\r
118 style = FontStyle.Regular | FontStyle.Bold | FontStyle.Italic | FontStyle.Underline | FontStyle.Strikeout; // null非許容型なので、代わりに全盛をNGワードに設定
\r
119 foreach (FontStyle ff in FS)
\r
121 if (this._fontfamily.IsStyleAvailable(ff))
\r
124 Trace.TraceWarning("フォント{0}へのスタイル指定を、{1}に変更しました。", Path.GetFileName(fontpath), style.ToString());
\r
128 if (style == (FontStyle.Regular | FontStyle.Bold | FontStyle.Italic | FontStyle.Underline | FontStyle.Strikeout))
\r
130 Trace.TraceWarning("フォント{0}は適切なスタイル{1}を選択できませんでした。", Path.GetFileName(fontpath), style.ToString());
\r
133 //this._font = new Font(this._fontfamily, pt, style); //PrivateFontCollectionの先頭のフォントのFontオブジェクトを作成する
\r
134 float emSize = pt * 96.0f / 72.0f;
\r
135 this._font = new Font(this._fontfamily, emSize, style, GraphicsUnit.Pixel); //PrivateFontCollectionの先頭のフォントのFontオブジェクトを作成する
\r
136 //HighDPI対応のため、pxサイズで指定
\r
139 // フォントファイルが見つからなかった場合 (MS PGothicを代わりに指定する)
\r
141 float emSize = pt * 96.0f / 72.0f;
\r
142 this._font = new Font("MS PGothic", emSize, style, GraphicsUnit.Pixel); //MS PGothicのFontオブジェクトを作成する
\r
143 FontFamily[] ffs = new System.Drawing.Text.InstalledFontCollection().Families;
\r
144 int lcid = System.Globalization.CultureInfo.GetCultureInfo("en-us").LCID;
\r
145 foreach (FontFamily ff in ffs)
\r
147 // Trace.WriteLine( lcid ) );
\r
148 if (ff.GetName(lcid) == "MS PGothic")
\r
150 this._fontfamily = ff;
\r
151 Trace.TraceInformation("MS PGothicを代わりに指定しました。");
\r
155 throw new FileNotFoundException("プライベートフォントの追加に失敗し、MS PGothicでの代替処理にも失敗しました。({0})", Path.GetFileName(fontpath));
\r
160 protected enum DrawMode
\r
167 #region [ DrawPrivateFontのオーバーロード群 ]
\r
169 /// 文字列を描画したテクスチャを返す
\r
171 /// <param name="drawstr">描画文字列</param>
\r
172 /// <param name="fontColor">描画色</param>
\r
173 /// <returns>描画済テクスチャ</returns>
\r
174 public Bitmap DrawPrivateFont(string drawstr, Color fontColor)
\r
176 return DrawPrivateFont(drawstr, DrawMode.Normal, fontColor, Color.White, Color.White, Color.White);
\r
180 /// 文字列を描画したテクスチャを返す
\r
182 /// <param name="drawstr">描画文字列</param>
\r
183 /// <param name="fontColor">描画色</param>
\r
184 /// <param name="edgeColor">縁取色</param>
\r
185 /// <returns>描画済テクスチャ</returns>
\r
186 public Bitmap DrawPrivateFont(string drawstr, Color fontColor, Color edgeColor)
\r
188 return DrawPrivateFont(drawstr, DrawMode.Edge, fontColor, edgeColor, Color.White, Color.White);
\r
192 /// 文字列を描画したテクスチャを返す
\r
194 /// <param name="drawstr">描画文字列</param>
\r
195 /// <param name="fontColor">描画色</param>
\r
196 /// <param name="gradationTopColor">グラデーション 上側の色</param>
\r
197 /// <param name="gradationBottomColor">グラデーション 下側の色</param>
\r
198 /// <returns>描画済テクスチャ</returns>
\r
199 //public Bitmap DrawPrivateFont( string drawstr, Color fontColor, Color gradationTopColor, Color gradataionBottomColor )
\r
201 // return DrawPrivateFont( drawstr, DrawMode.Gradation, fontColor, Color.White, gradationTopColor, gradataionBottomColor );
\r
205 /// 文字列を描画したテクスチャを返す
\r
207 /// <param name="drawstr">描画文字列</param>
\r
208 /// <param name="fontColor">描画色</param>
\r
209 /// <param name="edgeColor">縁取色</param>
\r
210 /// <param name="gradationTopColor">グラデーション 上側の色</param>
\r
211 /// <param name="gradationBottomColor">グラデーション 下側の色</param>
\r
212 /// <returns>描画済テクスチャ</returns>
\r
213 public Bitmap DrawPrivateFont(string drawstr, Color fontColor, Color edgeColor, Color gradationTopColor, Color gradataionBottomColor)
\r
215 return DrawPrivateFont(drawstr, DrawMode.Edge | DrawMode.Gradation, fontColor, edgeColor, gradationTopColor, gradataionBottomColor);
\r
218 #if こちらは使わない // (Bitmapではなく、CTextureを返す版)
\r
220 /// 文字列を描画したテクスチャを返す
\r
222 /// <param name="drawstr">描画文字列</param>
\r
223 /// <param name="fontColor">描画色</param>
\r
224 /// <returns>描画済テクスチャ</returns>
\r
225 public CTexture DrawPrivateFont( string drawstr, Color fontColor )
\r
227 Bitmap bmp = DrawPrivateFont( drawstr, DrawMode.Normal, fontColor, Color.White, Color.White, Color.White );
\r
228 return TextureFactory.tテクスチャの生成( bmp, false );
\r
232 /// 文字列を描画したテクスチャを返す
\r
234 /// <param name="drawstr">描画文字列</param>
\r
235 /// <param name="fontColor">描画色</param>
\r
236 /// <param name="edgeColor">縁取色</param>
\r
237 /// <returns>描画済テクスチャ</returns>
\r
238 public CTexture DrawPrivateFont( string drawstr, Color fontColor, Color edgeColor )
\r
240 Bitmap bmp = DrawPrivateFont( drawstr, DrawMode.Edge, fontColor, edgeColor, Color.White, Color.White );
\r
241 return TextureFactory.tテクスチャの生成( bmp, false );
\r
245 /// 文字列を描画したテクスチャを返す
\r
247 /// <param name="drawstr">描画文字列</param>
\r
248 /// <param name="fontColor">描画色</param>
\r
249 /// <param name="gradationTopColor">グラデーション 上側の色</param>
\r
250 /// <param name="gradationBottomColor">グラデーション 下側の色</param>
\r
251 /// <returns>描画済テクスチャ</returns>
\r
252 //public CTexture DrawPrivateFont( string drawstr, Color fontColor, Color gradationTopColor, Color gradataionBottomColor )
\r
254 // Bitmap bmp = DrawPrivateFont( drawstr, DrawMode.Gradation, fontColor, Color.White, gradationTopColor, gradataionBottomColor );
\r
255 // return TextureFactory.tテクスチャの生成( bmp, false );
\r
259 /// 文字列を描画したテクスチャを返す
\r
261 /// <param name="drawstr">描画文字列</param>
\r
262 /// <param name="fontColor">描画色</param>
\r
263 /// <param name="edgeColor">縁取色</param>
\r
264 /// <param name="gradationTopColor">グラデーション 上側の色</param>
\r
265 /// <param name="gradationBottomColor">グラデーション 下側の色</param>
\r
266 /// <returns>描画済テクスチャ</returns>
\r
267 public CTexture DrawPrivateFont( string drawstr, Color fontColor, Color edgeColor, Color gradationTopColor, Color gradataionBottomColor )
\r
269 Bitmap bmp = DrawPrivateFont( drawstr, DrawMode.Edge | DrawMode.Gradation, fontColor, edgeColor, gradationTopColor, gradataionBottomColor );
\r
270 return TextureFactory.tテクスチャの生成( bmp, false );
\r
276 /// 文字列を描画したテクスチャを返す(メイン処理)
\r
278 /// <param name="rectDrawn">描画された領域</param>
\r
279 /// <param name="ptOrigin">描画文字列</param>
\r
280 /// <param name="drawstr">描画文字列</param>
\r
281 /// <param name="drawmode">描画モード</param>
\r
282 /// <param name="fontColor">描画色</param>
\r
283 /// <param name="edgeColor">縁取色</param>
\r
284 /// <param name="gradationTopColor">グラデーション 上側の色</param>
\r
285 /// <param name="gradationBottomColor">グラデーション 下側の色</param>
\r
286 /// <returns>描画済テクスチャ</returns>
\r
287 protected Bitmap DrawPrivateFont(string drawstr, DrawMode drawmode, Color fontColor, Color edgeColor, Color gradationTopColor, Color gradationBottomColor)
\r
289 if (this._fontfamily == null || drawstr == null || drawstr == "")
\r
291 // nullを返すと、その後bmp→texture処理や、textureのサイズを見て・・の処理で全部例外が発生することになる。
\r
292 // それは非常に面倒なので、最小限のbitmapを返してしまう。
\r
293 // まずはこの仕様で進めますが、問題有れば(上位側からエラー検出が必要であれば)例外を出したりエラー状態であるプロパティを定義するなり検討します。
\r
296 Trace.TraceWarning("DrawPrivateFont()の入力不正。最小値のbitmapを返します。");
\r
298 _rectStrings = new Rectangle(0, 0, 0, 0);
\r
299 _ptOrigin = new Point(0, 0);
\r
300 return new Bitmap(1, 1);
\r
302 bool bEdge = ((drawmode & DrawMode.Edge) == DrawMode.Edge);
\r
303 bool bGradation = ((drawmode & DrawMode.Gradation) == DrawMode.Gradation);
\r
305 // 縁取りの縁のサイズは、とりあえずフォントの大きさの1/4とする
\r
306 int nEdgePt = (bEdge) ? _pt / 4 : 0;
\r
309 Size stringSize = System.Windows.Forms.TextRenderer.MeasureText(drawstr, this._font, new Size(int.MaxValue, int.MaxValue),
\r
310 System.Windows.Forms.TextFormatFlags.NoPrefix |
\r
311 System.Windows.Forms.TextFormatFlags.NoPadding
\r
314 //取得した描画サイズを基に、描画先のbitmapを作成する
\r
315 Bitmap bmp = new Bitmap(stringSize.Width + nEdgePt * 2, stringSize.Height + nEdgePt * 2);
\r
316 bmp.MakeTransparent();
\r
318 using (Graphics g = Graphics.FromImage(bmp))
\r
320 g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
\r
322 using (StringFormat sf = new StringFormat())
\r
325 sf.LineAlignment = StringAlignment.Far;
\r
327 sf.Alignment = StringAlignment.Center;
\r
330 Rectangle r = new Rectangle(0, 0, stringSize.Width + nEdgePt * 2, stringSize.Height + nEdgePt * 2);
\r
335 // DrawPathで、ポイントサイズを使って描画するために、DPIを使って単位変換する
\r
336 // (これをしないと、単位が違うために、小さめに描画されてしまう)
\r
337 float sizeInPixels = _font.SizeInPoints * g.DpiY / 72; // 1 inch = 72 points
\r
339 using (System.Drawing.Drawing2D.GraphicsPath gp = new System.Drawing.Drawing2D.GraphicsPath())
\r
341 gp.AddString(drawstr, this._fontfamily, (int)this._font.Style, sizeInPixels, r, sf);
\r
344 using (Pen p = new Pen(edgeColor, nEdgePt))
\r
346 p.LineJoin = System.Drawing.Drawing2D.LineJoin.Round;
\r
350 using (Brush br = bGradation ?
\r
351 new LinearGradientBrush(r, gradationTopColor, gradationBottomColor, LinearGradientMode.Vertical) as Brush :
\r
352 new SolidBrush(fontColor) as Brush)
\r
354 g.FillPath(br, gp);
\r
362 using (Brush br = new SolidBrush(fontColor))
\r
364 g.DrawString(drawstr, _font, br, 0f, 0f);
\r
366 // System.Windows.Forms.TextRenderer.DrawText(g, drawstr, _font, new Point(0, 0), fontColor);
\r
369 g.DrawRectangle( new Pen( Color.White, 1 ), new Rectangle( 1, 1, stringSize.Width-1, stringSize.Height-1 ) );
\r
370 g.DrawRectangle( new Pen( Color.Green, 1 ), new Rectangle( 0, 0, bmp.Width - 1, bmp.Height - 1 ) );
\r
372 _rectStrings = new Rectangle(0, 0, stringSize.Width, stringSize.Height);
\r
373 _ptOrigin = new Point(nEdgePt * 2, nEdgePt * 2);
\r
381 /// 最後にDrawPrivateFont()した文字列の描画領域を取得します。
\r
383 public Rectangle RectStrings
\r
387 return _rectStrings;
\r
391 _rectStrings = value;
\r
394 public Point PtOrigin
\r
406 #region [ IDisposable 実装 ]
\r
407 //-----------------
\r
408 public void Dispose()
\r
410 if (!this.bDispose完了済み)
\r
412 if (this._font != null)
\r
414 this._font.Dispose();
\r
417 if (this._pfc != null)
\r
419 this._pfc.Dispose();
\r
423 this.bDispose完了済み = true;
\r
426 //-----------------
\r
429 #region [ private ]
\r
430 //-----------------
\r
431 protected bool bDispose完了済み;
\r
432 protected Font _font;
\r
434 private System.Drawing.Text.PrivateFontCollection _pfc;
\r
435 private FontFamily _fontfamily;
\r
437 private Rectangle _rectStrings;
\r
438 private Point _ptOrigin;
\r
439 //-----------------
\r