/// <summary> /// 文字列を描画したテクスチャを返す(メイン処理) /// </summary> /// <param name="rectDrawn">描画された領域</param> /// <param name="ptOrigin">描画文字列</param> /// <param name="drawstr">描画文字列</param> /// <param name="drawmode">描画モード</param> /// <param name="fontColor">描画色</param> /// <param name="edgeColor">縁取色</param> /// <param name="gradationTopColor">グラデーション 上側の色</param> /// <param name="gradationBottomColor">グラデーション 下側の色</param> /// <returns>描画済テクスチャ</returns> protected SixLabors.ImageSharp.Image <SixLabors.ImageSharp.PixelFormats.Rgba32> DrawPrivateFont_V(string drawstr, DrawMode drawMode, Color fontColor, Color edgeColor, int edge_Ratio) { if (this._fontfamily == null || drawstr == null || drawstr == "" || drawstr == " " || drawstr == " ") { // nullを返すと、その後bmp→texture処理や、textureのサイズを見て__の処理で全部例外が発生することになる。 // それは非常に面倒なので、最小限のbitmapを返してしまう。 // まずはこの仕様で進めますが、問題有れば(上位側からエラー検出が必要であれば)例外を出したりエラー状態であるプロパティを定義するなり検討します。 if (drawstr != "") { Trace.TraceWarning("DrawPrivateFont()の入力不正。最小値のbitmapを返します。"); } _rectStrings = new Rectangle(0, 0, 0, 0); _ptOrigin = new Point(0, 0); return(new SixLabors.ImageSharp.Image <SixLabors.ImageSharp.PixelFormats.Rgba32>(1, 1)); } drawstr = drawstr.Replace("・", "."); string[] strName = new string[drawstr.Length]; for (int i = 0; i < drawstr.Length; i++) { strName[i] = drawstr.Substring(i, 1); } #region [ キャンバスの大きさ予測 ] //大きさを計算していく。 int nHeight = 0; for (int i = 0; i < strName.Length; i++) { Size strSize; using (Bitmap bmptmp = new Bitmap(1, 1)) { using (Graphics gtmp = Graphics.FromImage(bmptmp)) { using ( StringFormat sf = new StringFormat() { LineAlignment = StringAlignment.Far, // 画面下部(垂直方向位置) Alignment = StringAlignment.Center, // 画面中央(水平方向位置) FormatFlags = StringFormatFlags.NoWrap, // どんなに長くて単語の区切りが良くても改行しない (AioiLight) Trimming = StringTrimming.None, // どんなに長くてもトリミングしない (AioiLight) }) { //float to int SizeF fstringSize = gtmp.MeasureString(strName[i], this._font, new PointF(0, 0), sf); strSize = new Size((int)fstringSize.Width, (int)fstringSize.Height); } } } //stringformatは最初にやっていてもいいだろう。 using (StringFormat sFormat = new StringFormat() { LineAlignment = StringAlignment.Center, // 画面下部(垂直方向位置) Alignment = StringAlignment.Center, // 画面中央(水平方向位置) }) { //できるだけ正確な値を計算しておきたい...! Rectangle rect正確なサイズ = this.MeasureStringPrecisely(strName[i], strSize, sFormat, edge_Ratio); int n余白サイズ = strSize.Height - rect正確なサイズ.Height; if (strName[i] == "ー" || strName[i] == "-" || strName[i] == "~" || strName[i] == "<" || strName[i] == ">" || strName[i] == "(" || strName[i] == ")" || strName[i] == "「" || strName[i] == "」" || strName[i] == "[" || strName[i] == "]") { nHeight += (rect正確なサイズ.Width) + 2; } else if (strName[i] == "_") { nHeight += (rect正確なサイズ.Height) + 2; } else if (strName[i] == " ") { nHeight += (6); } else { nHeight += (rect正確なサイズ.Height) + 2; } } } #endregion Bitmap bmpCambus = new Bitmap(46, nHeight); using (Graphics Gcambus = Graphics.FromImage(bmpCambus)) { //キャンバス作成→1文字ずつ作成してキャンバスに描画という形がよさそうかな? int nNowPos = 0; int nAdded = 0; int nEdge補正X = 0; int nEdge補正Y = 0; if (this._pt < 18) { nAdded -= 2; } for (int i = 0; i < strName.Length; i++) { Size strSize; using (Bitmap bmptmp = new Bitmap(1, 1)) { using (Graphics gtmp = Graphics.FromImage(bmptmp)) { using ( StringFormat sf = new StringFormat() { LineAlignment = StringAlignment.Far, // 画面下部(垂直方向位置) Alignment = StringAlignment.Center, // 画面中央(水平方向位置) FormatFlags = StringFormatFlags.NoWrap, // どんなに長くて単語の区切りが良くても改行しない (AioiLight) Trimming = StringTrimming.None, // どんなに長くてもトリミングしない (AioiLight) }) { //float to int SizeF fstringSize = gtmp.MeasureString(strName[i], this._font, new PointF(0, 0), sf); strSize = new Size((int)fstringSize.Width, (int)fstringSize.Height); } } } //stringformatは最初にやっていてもいいだろう。 StringFormat sFormat = new StringFormat() { LineAlignment = StringAlignment.Center, // 画面下部(垂直方向位置) Alignment = StringAlignment.Near, // 画面中央(水平方向位置) }; //できるだけ正確な値を計算しておきたい...! Rectangle rect正確なサイズ = this.MeasureStringPrecisely(strName[i], strSize, sFormat, edge_Ratio); int n余白サイズ = strSize.Height - rect正確なサイズ.Height; Bitmap bmpV = new Bitmap((rect正確なサイズ.Width + 6) + nAdded, (rect正確なサイズ.Height) + 6); bmpV.MakeTransparent(); Graphics gV = Graphics.FromImage(bmpV); gV.SmoothingMode = SmoothingMode.HighQuality; if (CorrectionX_Chara_List_Vertical != null && CorrectionX_Chara_List_Value_Vertical != null) { int Xindex = Array.IndexOf(CorrectionX_Chara_List_Vertical, strName[i]); if (-1 < Xindex && Xindex < CorrectionX_Chara_List_Value_Vertical.Length && strName[i].In(CorrectionX_Chara_List_Vertical)) { nEdge補正X = CorrectionX_Chara_List_Value_Vertical[Xindex]; } else { if (-1 < Xindex && CorrectionX_Chara_List_Value_Vertical.Length <= Xindex && strName[i].In(CorrectionX_Chara_List_Vertical)) { nEdge補正X = CorrectionX_Chara_List_Value_Vertical[0]; } else { nEdge補正X = 0; } } } if (CorrectionY_Chara_List_Vertical != null && CorrectionY_Chara_List_Value_Vertical != null) { int Yindex = Array.IndexOf(CorrectionY_Chara_List_Vertical, strName[i]); if (-1 < Yindex && Yindex < CorrectionY_Chara_List_Value_Vertical.Length && strName[i].In(CorrectionY_Chara_List_Vertical)) { nEdge補正Y = CorrectionY_Chara_List_Value_Vertical[Yindex]; } else { if (-1 < Yindex && CorrectionY_Chara_List_Value_Vertical.Length <= Yindex && strName[i].In(CorrectionY_Chara_List_Vertical)) { nEdge補正Y = CorrectionY_Chara_List_Value_Vertical[0]; } else { nEdge補正Y = 0; } } } //X座標、Y座標それぞれについて、SkinConfig内でズレを直したい文字を , で区切って列挙して、 //補正値を記入することで、特定のそれらの文字について一括で座標をずらす。 //現時点では補正値をX,Y各座標について1個ずつしか取れない(複数対1)ので、 //文字を列挙して、同じ数だけそれぞれの文字の補正値を記入できるような枠組をつくりたい。(20181205 rhimm)←実装済み //2020.05.04 Mr-Ojii 文字ごとに補正をかけられるように。「,」区切りで書けるように。 Rectangle rect = new Rectangle(-3 - nAdded + (nEdge補正X * _pt / 100), -rect正確なサイズ.Y - 2 + (nEdge補正Y * _pt / 100), (strSize.Width + 12), (strSize.Height + 11)); //Rectangle rect = new Rectangle( 0, -rect正確なサイズ.Y - 2, 36, rect正確なサイズ.Height + 10); // DrawPathで、ポイントサイズを使って描画するために、DPIを使って単位変換する // (これをしないと、単位が違うために、小さめに描画されてしまう) float sizeInPixels = _font.SizeInPoints * gV.DpiY / 72f; // 1 inch = 72 points GraphicsPath gpV = new GraphicsPath(); gpV.AddString(strName[i], this._fontfamily, (int)this._font.Style, sizeInPixels, rect, sFormat); // 縁取りを描画する //int nEdgePt = (_pt / 3); // 縁取りをフォントサイズ基準に変更 float nEdgePt = (10f * _pt / edge_Ratio); // SkinConfigにて設定可能に(rhimm) Pen pV = new Pen(edgeColor, nEdgePt); pV.LineJoin = LineJoin.Round; gV.DrawPath(pV, gpV); // 塗りつぶす Brush brV = new SolidBrush(fontColor); gV.FillPath(brV, gpV); if (brV != null) { brV.Dispose(); } if (pV != null) { pV.Dispose(); } if (gpV != null) { gpV.Dispose(); } if (gV != null) { gV.Dispose(); } int n補正 = 0; int nY補正 = 0; if (strName[i] == "ー" || strName[i] == "-" || strName[i] == "~") { bmpV.RotateFlip(RotateFlipType.Rotate90FlipNone); n補正 = 2; if (this._pt < 20) { n補正 = 0; } //nNowPos = nNowPos - 2; } else if (strName[i] == "<" || strName[i] == ">" || strName[i] == "(" || strName[i] == ")" || strName[i] == "[" || strName[i] == "]" || strName[i] == "」" || strName[i] == ")" || strName[i] == "』") { bmpV.RotateFlip(RotateFlipType.Rotate90FlipNone); n補正 = 2; if (this._pt < 20) { n補正 = 0; //nNowPos = nNowPos - 4; } } else if (strName[i] == "「" || strName[i] == "(" || strName[i] == "『") { bmpV.RotateFlip(RotateFlipType.Rotate90FlipNone); n補正 = 2; if (this._pt < 20) { n補正 = 2; //nNowPos = nNowPos; } } else if (strName[i] == "・") { n補正 = -8; if (this._pt < 20) { n補正 = -8; //nNowPos = nNowPos; } } else if (strName[i] == ".") { n補正 = 8; if (this._pt < 20) { n補正 = 8; //nNowPos = nNowPos; } } else if (strName[i].In(Rotate_Chara_List_Vertical)) { bmpV.RotateFlip(RotateFlipType.Rotate90FlipNone); } //個別の文字に関して、カンマで区切ってSkinConfigに記入したものを回転させる(20181205 rhimm) else if (strName[i] == " ") { nNowPos += 10; } if (i == 0) { nNowPos = 4; } Gcambus.DrawImage(bmpV, (bmpCambus.Width / 2) - (bmpV.Width / 2) + n補正, nNowPos + nY補正); nNowPos += bmpV.Size.Height - 6; if (bmpV != null) { bmpV.Dispose(); } _rectStrings = new Rectangle(0, 0, strSize.Width, strSize.Height); _ptOrigin = new Point(6 * 2, 6 * 2); } } return(C変換.ToImageSharpImage(bmpCambus)); }
/// <summary> /// 文字列を描画したテクスチャを返す(メイン処理) /// </summary> /// <param name="rectDrawn">描画された領域</param> /// <param name="ptOrigin">描画文字列</param> /// <param name="drawstr">描画文字列</param> /// <param name="drawmode">描画モード</param> /// <param name="fontColor">描画色</param> /// <param name="edgeColor">縁取色</param> /// <param name="gradationTopColor">グラデーション 上側の色</param> /// <param name="gradationBottomColor">グラデーション 下側の色</param> /// <returns>描画済テクスチャ</returns> protected SixLabors.ImageSharp.Image <SixLabors.ImageSharp.PixelFormats.Rgba32> DrawPrivateFont(string drawstr, DrawMode drawmode, Color fontColor, Color edgeColor, Color gradationTopColor, Color gradationBottomColor, int edge_Ratio) { if (this._fontfamily == null || drawstr == null || drawstr == "" || drawstr == " " || drawstr == " ") { // nullを返すと、その後bmp→texture処理や、textureのサイズを見て__の処理で全部例外が発生することになる。 // それは非常に面倒なので、最小限のbitmapを返してしまう。 // まずはこの仕様で進めますが、問題有れば(上位側からエラー検出が必要であれば)例外を出したりエラー状態であるプロパティを定義するなり検討します。 if (drawstr != "") { Trace.TraceWarning("DrawPrivateFont()の入力不正。最小値のbitmapを返します。"); } _rectStrings = new Rectangle(0, 0, 0, 0); _ptOrigin = new Point(0, 0); return(new SixLabors.ImageSharp.Image <SixLabors.ImageSharp.PixelFormats.Rgba32>(1, 1)); } // 描画サイズを測定する Size stringSize; using (Bitmap bmptmp = new Bitmap(1, 1)) { using (Graphics gtmp = Graphics.FromImage(bmptmp)) { gtmp.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias; using (StringFormat sf = new StringFormat() { LineAlignment = StringAlignment.Far, // 画面下部(垂直方向位置) Alignment = StringAlignment.Center, // 画面中央(水平方向位置) FormatFlags = StringFormatFlags.NoWrap, // どんなに長くて単語の区切りが良くても改行しない (AioiLight) Trimming = StringTrimming.None, // どんなに長くてもトリミングしない (AioiLight) }) { //float to int SizeF fstringSize = gtmp.MeasureString(drawstr, this._font, new PointF(0, 0), sf); stringSize = new Size((int)fstringSize.Width, this._font.Height); stringSize.Width += 10; //2015.04.01 kairera0467 ROTTERDAM NATIONの描画サイズがうまくいかんので。 } } } bool bEdge = ((drawmode & DrawMode.Edge) == DrawMode.Edge); bool bGradation = ((drawmode & DrawMode.Gradation) == DrawMode.Gradation); // 縁取りの縁のサイズは、とりあえずフォントの大きさの(1/SkinConfig)とする int nEdgePt = (bEdge) ? (10 * _pt / edge_Ratio) : 0; //SkinConfigにて設定可能に(rhimm) //取得した描画サイズを基に、描画先のbitmapを作成する Bitmap bmp = new Bitmap(stringSize.Width + nEdgePt * 2, stringSize.Height + nEdgePt * 2); bmp.MakeTransparent(); using (Graphics g = Graphics.FromImage(bmp)) { g.SmoothingMode = SmoothingMode.HighQuality; g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias; // レイアウト枠 Rectangle r = new Rectangle(0, 0, stringSize.Width + nEdgePt * 2 + (Text_Correction_X * stringSize.Width / 100), stringSize.Height + nEdgePt * 2 + (Text_Correction_Y * stringSize.Height / 100)); if (bEdge) // 縁取り有りの描画 { using (StringFormat sf = new StringFormat() { LineAlignment = StringAlignment.Far, // 画面下部(垂直方向位置) Alignment = StringAlignment.Center, // 画面中央(水平方向位置) FormatFlags = StringFormatFlags.NoWrap, // どんなに長くて単語の区切りが良くても改行しない (AioiLight) Trimming = StringTrimming.None, // どんなに長くてもトリミングしない (AioiLight) }) { // DrawPathで、ポイントサイズを使って描画するために、DPIを使って単位変換する // (これをしないと、単位が違うために、小さめに描画されてしまう) float sizeInPixels = _font.SizeInPoints * g.DpiY / 72; // 1 inch = 72 points GraphicsPath gp = new GraphicsPath(); gp.AddString(drawstr, this._fontfamily, (int)this._font.Style, sizeInPixels, r, sf); // 縁取りを描画する Pen p = new Pen(edgeColor, nEdgePt); p.LineJoin = LineJoin.Round; g.DrawPath(p, gp); // 塗りつぶす Brush br; if (bGradation) { br = new LinearGradientBrush(r, gradationTopColor, gradationBottomColor, LinearGradientMode.Vertical); } else { br = new SolidBrush(fontColor); } g.FillPath(br, gp); if (br != null) { br.Dispose(); } br = null; if (p != null) { p.Dispose(); } p = null; if (gp != null) { gp.Dispose(); } gp = null; } } else { // 縁取りなしの描画 g.DrawString(drawstr, _font, new SolidBrush(fontColor), new PointF(0, 0)); } _rectStrings = new Rectangle(0, 0, stringSize.Width, stringSize.Height); _ptOrigin = new Point(nEdgePt * 2, nEdgePt * 2); } return(C変換.ToImageSharpImage(bmp)); }