public static SizeF MeasureText(this Graphics g, string text, Font font, TextHPosition hpos = TextHPosition.Left, TextVPosition vpos = TextVPosition.Top, float lineHeight = 1.2F, float fontRatio = 1.0F) { return(g.BoundsText(text, font, hpos, vpos, lineHeight, fontRatio).Size); }
public static RectangleF BoundsText(this Graphics g, string text, Font font, TextHPosition hpos = TextHPosition.Left, TextVPosition vpos = TextVPosition.Top, float lineHeight = 1.2F, float fontRatio = 1.0F) { return(g.BoundsText(text, font, null, new Rectangle(0, 0, 0, 0), hpos, vpos, lineHeight, fontRatio)); }
/// <summary> /// 属性指定テキストを描画する /// </summary> /// <param name="text">描画文字列の配列</param> /// <param name="attr">表示属性指定</param> /// <param name="rect">描画範囲</param> /// <returns>描画した領域</returns> public static Rectangle DrawText(this Graphics g, string[] text, MPAttribute attr, Rectangle rect, Control control = null) { if ((text == null) || (text.Length == 0) || (rect == null)) { return(new Rectangle(0, 0, 0, 0)); } Rectangle urect = new Rectangle(0, 0, 0, 0); float lineHeight = (float)rect.Height / (float)text.Length; Rectangle lineRect = new Rectangle(); for (int i = 0; i < text.Length; i++) { MPAttribute xattr = attr; string xtext = text[i].Trim(); Match m = pat_class.Match(xtext); if (m.Success) { xattr = (MPAttribute)attr.GetClass(m.Groups[1].Value); xtext = m.Groups[2].Value.Trim(); } lineRect.X = rect.X; lineRect.Width = rect.Width; lineRect.Y = rect.Y + (int)(lineHeight * i); lineRect.Height = rect.Y + (int)(lineHeight * (i + 1)) - lineRect.Y; Color bgcolor = Color.White; Color color = Color.Black; TextHPosition hpos = TextHPosition.LeftShrink; TextVPosition vpos = TextVPosition.Middle; float outlineRatio = 0F; Color outlineColor = ColorUtil.Invalid; float lh = 1F; Color shadowColor = ColorUtil.Invalid; float shadowOffsetX = 0F; float shadowOffsetY = 0F; float fontRatio = 1.0F; Font refFont = Control.DefaultFont; if (control != null) { bgcolor = control.GetRealBackColor(); color = control.ForeColor; refFont = control.Font; if (control is MPText) { MPText cc = control as MPText; hpos = cc.HPosition; vpos = cc.VPosition; outlineRatio = cc.OutlineRatio; outlineColor = cc.OutlineColor; shadowColor = cc.ShadowColor; shadowOffsetX = cc.ShadowOffsetX; shadowOffsetY = cc.ShadowOffsetY; } } // 文字色は"textcolor", "color"の定義の順に探す。 color = xattr.GetColor("textcolor", xattr.GetColor("color", color)); if (color == ColorUtil.Auto) { color = ColorUtil.GetBWColor(bgcolor); } xattr.FetchTextPosition(ref hpos, ref vpos); xattr.FetchTextStyle(ref outlineRatio, ref outlineColor, ref lh, ref shadowColor, ref shadowOffsetX, ref shadowOffsetY); if (outlineColor == ColorUtil.Auto) { outlineColor = ColorUtil.GetBWColor(color); } Font font = xattr.GetFont(refFont); float outlineWidth = font.GetEmSize() * outlineRatio; Brush brush = null; if (color.A > 0) { brush = new SolidBrush(color); } Pen pen = null; if ((outlineColor.A > 0) && (outlineWidth > 0)) { pen = new Pen(outlineColor, outlineWidth); } Brush shadow = null; if (shadowColor.A > 0) { shadow = new SolidBrush(shadowColor); } lineRect = g.DrawText(new string[] { xtext }, font, pen, brush, lineRect, hpos, TextVPosition.Middle, 1F, fontRatio, shadow, shadowOffsetX, shadowOffsetY); if ((urect.Width == 0) || (urect.Height == 0)) { urect = lineRect; } else if ((lineRect.Width != 0) && (lineRect.Height != 0)) { urect = Rectangle.Union(urect, lineRect); } if (brush != null) { brush.Dispose(); } if (pen != null) { pen.Dispose(); } if (shadow != null) { shadow.Dispose(); } } return(urect); }
/// <summary> /// アウトラインテキストを描画するときの外枠を得る /// </summary> /// <param name="text">描画文字列の配列</param> /// <param name="attr">表示属性指定</param> /// <param name="rect">描画範囲</param> /// <returns>サイズ</returns> public static RectangleF BoundsText(this Graphics g, string[] text, MPAttribute attr, Rectangle rect, Control control = null) { if ((text == null) || (text.Length == 0) || (rect == null)) { return(new RectangleF(0, 0, 0, 0)); } RectangleF urect = new RectangleF(0, 0, 0, 0); float lineHeight = (float)rect.Height / (float)text.Length; Rectangle lineRect = new Rectangle(); for (int i = 0; i < text.Length; i++) { MPAttribute xattr = attr; string xtext = text[i].Trim(); Match m = pat_class.Match(xtext); if (m.Success) { xattr = (MPAttribute)attr.GetClass(m.Groups[1].Value); xtext = m.Groups[2].Value.Trim(); } lineRect.X = rect.X; lineRect.Width = rect.Width; lineRect.Y = rect.Y + (int)(lineHeight * i); lineRect.Height = rect.Y + (int)(lineHeight * (i + 1)) - lineRect.Y; TextHPosition hpos = TextHPosition.LeftShrink; TextVPosition vpos = TextVPosition.Middle; float outlineRatio = 0F; Color outlineColor = ColorUtil.Invalid; float lh = 1F; Color shadowColor = ColorUtil.Invalid; float shadowOffsetX = 0F; float shadowOffsetY = 0F; float fontRatio = 1.0F; xattr.FetchTextPosition(ref hpos, ref vpos); xattr.FetchTextStyle(ref outlineRatio, ref outlineColor, ref lh, ref shadowColor, ref shadowOffsetX, ref shadowOffsetY); Font font = xattr.GetFont((control != null)?control.Font:Control.DefaultFont); float outlineWidth = font.GetEmSize() * outlineRatio; Pen pen = null; if ((outlineColor.A > 0) && (outlineWidth > 0)) { pen = new Pen(outlineColor, outlineWidth); } RectangleF xrect = g.BoundsText(new string[] { xtext }, font, pen, lineRect, hpos, TextVPosition.Middle, 1F, fontRatio); if ((urect.Width == 0) || (urect.Height == 0)) { urect = xrect; } else if ((xrect.Width != 0) && (xrect.Height != 0)) { urect = RectangleF.Union(urect, xrect); } font.Dispose(); if (pen != null) { pen.Dispose(); } } return(urect); }
public void FetchTextPosition(ref TextHPosition hpos, ref TextVPosition vpos, string key = "") { bool shrink = this.Get(key + "shrink", true); string val = this.Get(key + "align"); if (!String.IsNullOrEmpty(val)) { switch (val.ToUpper()) { case "LEFTTOP": case "TOPLEFT": case "TOP": hpos = shrink?TextHPosition.LeftShrink:TextHPosition.Left; vpos = TextVPosition.Top; break; case "CENTERTOP": case "TOPCENTER": hpos = shrink?TextHPosition.CenterShrink:TextHPosition.Center; vpos = TextVPosition.Top; break; case "RIGHTTOP": case "TOPRIGHT": hpos = shrink?TextHPosition.RightShrink:TextHPosition.Right; vpos = TextVPosition.Top; break; case "LEFTFIT": case "FITLEFT": case "FIT": hpos = shrink?TextHPosition.LeftShrink:TextHPosition.Left; vpos = TextVPosition.Fit; break; case "CENTERFIT": case "FITCENTER": hpos = shrink?TextHPosition.CenterShrink:TextHPosition.Center; vpos = TextVPosition.Fit; break; case "RIGHTFIT": case "FITRIGHT": hpos = shrink?TextHPosition.RightShrink:TextHPosition.Right; vpos = TextVPosition.Fit; break; case "LEFT": case "LEFTMIDDLE": case "MIDDLELEFT": case "MIDDLE": hpos = shrink?TextHPosition.LeftShrink:TextHPosition.Left; vpos = TextVPosition.Middle; break; case "CENTER": case "CENTERMIDDLE": case "MIDDLECENTER": hpos = shrink?TextHPosition.CenterShrink:TextHPosition.Center; vpos = TextVPosition.Middle; break; case "RIGHT": case "RIGHTMIDDLE": case "MIDDLERIGHT": hpos = shrink?TextHPosition.RightShrink:TextHPosition.Right; vpos = TextVPosition.Middle; break; case "LEFTBOTTOM": case "BOTTOMLEFT": case "BOTTOM": hpos = shrink?TextHPosition.LeftShrink:TextHPosition.Left; vpos = TextVPosition.Bottom; break; case "CENTERBOTTOM": case "BOTTOMCENTER": hpos = shrink?TextHPosition.CenterShrink:TextHPosition.Center; vpos = TextVPosition.Bottom; break; case "RIGHTBOTTOM": case "BOTTOMRIGHT": hpos = shrink?TextHPosition.RightShrink:TextHPosition.Right; vpos = TextVPosition.Bottom; break; } } }
private static GraphicsPath makeTextPath(string[] text, Font font, Rectangle rect, TextHPosition hpos, TextVPosition vpos, float lineHeight, float fontRatio, float emSize) { // 各行のテキストパスを得る GraphicsPath[] pp = new GraphicsPath[text.Length]; using (Matrix m = new Matrix()) { if (fontRatio != 1F) { m.Scale(fontRatio, 1F); } for (int i = 0; i < text.Length; i++) { pp[i] = new GraphicsPath(); pp[i].AddString(text[i], font.FontFamily, (int)font.Style, emSize, new PointF(0F, 0F), StringFormat.GenericDefault); if (fontRatio != 1F) { pp[i].Transform(m); } } } // 全体の描画幅、高さを得る float ww = 0F; for (int i = 0; i < pp.Length; i++) { RectangleF r = pp[i].GetBounds(); if (ww < r.Width) { ww = r.Width; } } if ((hpos == TextHPosition.LeftShrink) || (hpos == TextHPosition.CenterShrink) || (hpos == TextHPosition.RightShrink)) { if (ww > rect.Width) { ww = rect.Width; } } float hh, hhstep; switch (vpos) { case TextVPosition.Fit: hh = rect.Height; if ((text.Length == 1) || (hh < emSize)) { hhstep = 0; } else { hhstep = (hh - emSize) / (float)(text.Length - 1); } break; case TextVPosition.Proportional: hh = rect.Height; hhstep = (float)rect.Height / (float)text.Length; break; default: hh = emSize + (emSize * lineHeight) * (float)(text.Length - 1); hhstep = emSize * lineHeight; break; } // テキストパスを一つにまとめる GraphicsPath p = new GraphicsPath(); for (int i = 0; i < pp.Length; i++) { RectangleF bb = pp[i].GetBounds(); if ((bb.Width > 0) && (bb.Height > 0)) // 空パスをAddPathするとエラーになるらしい { float xoff = -bb.X; float xmag = 1F; switch (hpos) { case TextHPosition.Left: //xoff += 0F; //xmag = 1F; break; case TextHPosition.Center: xoff += ((float)rect.Width - bb.Width) / 2F; //xmag = 1F; break; case TextHPosition.Right: xoff += (float)rect.Width - bb.Width - 1F; //xmag = 1F; break; case TextHPosition.LeftShrink: if (ww < bb.Width) { //xoff += 0F; if (bb.Width == 0) { xmag = 1F; } else { xmag = (float)rect.Width / (bb.Width + 1F); } } else { //xoff += 0F; xmag = 1F; } break; case TextHPosition.CenterShrink: if (ww < bb.Width) { //xoff += 0F; if (bb.Width == 0) { xmag = 1F; } else { xmag = (float)rect.Width / (bb.Width + 1F); } } else { xoff += ((float)rect.Width - bb.Width) / 2F; xmag = 1F; } break; case TextHPosition.RightShrink: if (ww < bb.Width) { //xoff += 0F; if (bb.Width == 0) { xmag = 1F; } else { xmag = (float)rect.Width / (bb.Width + 1F); } } else { xoff += (float)rect.Width - bb.Width - 1F; xmag = 1F; } break; } float yoff = hhstep * (float)i - bb.Y; if (hhstep <= 0) { yoff += ((float)rect.Height - emSize) / 2F; } float ymag = 1F; switch (vpos) { case TextVPosition.Top: // yoff += 0F; break; case TextVPosition.Middle: yoff += ((float)rect.Height - hh) / 2F; break; case TextVPosition.Bottom: yoff += (float)rect.Height - hh; break; case TextVPosition.Fit: // yoff += 0F; break; case TextVPosition.Proportional: yoff = hhstep * (float)i + (hhstep - bb.Height) / 2F - bb.Y; break; } if ((xoff != 0F) || (yoff != 0F)) { using (Matrix m = new Matrix()) { m.Translate(xoff, yoff); pp[i].Transform(m); } } if ((xmag != 1F) || (ymag != 1F)) { using (Matrix m = new Matrix()) { m.Scale(xmag, ymag); pp[i].Transform(m); } } p.AddPath(pp[i], false); } pp[i].Dispose(); } return(p); }
public static RectangleF BoundsText(this Graphics g, string text, Font font, Rectangle rect, TextHPosition hpos = TextHPosition.Left, TextVPosition vpos = TextVPosition.Top, float lineHeight = 1.2F, float fontRatio = 1.0F) { if (String.IsNullOrEmpty(text)) { return(new RectangleF(0, 0, 0, 0)); } return(g.BoundsText(text.Split("\n".ToCharArray()), font, null, rect, hpos, vpos, lineHeight, fontRatio)); }
/// <summary> /// アウトラインテキストを描画するときの外枠を得る /// </summary> /// <param name="text">描画文字列の配列</param> /// <param name="font">使用フォント</param> /// <param name="outline">アウトラインを描画するペン。nullのときはアウトライン描画なし</param> /// <param name="rect">描画範囲</param> /// <param name="hpos">水平描画位置</param> /// <param name="vpos">垂直描画位置</param> /// <param name="lineHeight">行間隔(行上端から次の行の上端までの間隔)フォント高さの倍数で指定する</param> /// <param name="fontRatio">文字の縦横比</param> /// <returns>BoundRectangle</returns> public static RectangleF BoundsText(this Graphics g, string[] text, Font font, Pen outline, Rectangle rect, TextHPosition hpos = TextHPosition.Left, TextVPosition vpos = TextVPosition.Top, float lineHeight = 1.2F, float fontRatio = 1.0F) { if ((text == null) || (text.Length == 0) || (rect == null)) { return(new RectangleF(0, 0, 0, 0)); } float emSize = font.GetEmSize(); using (GraphicsPath p = makeTextPath(text, font, rect, hpos, vpos, lineHeight, fontRatio, emSize)) { if (outline == null) { return(p.GetBounds()); } else { using (Matrix m = new Matrix()) { return(RectangleF.Inflate(p.GetBounds(), outline.Width / 2F, outline.Width / 2F)); } } } }
/// <summary> /// アウトラインテキストを描画する /// </summary> /// <param name="text">描画文字列の配列</param> /// <param name="font">使用フォント</param> /// <param name="outline">アウトラインを描画するペン。nullのときはアウトライン描画なし</param> /// <param name="fill">文字の描画色。nullのときは塗りつぶしなし</param> /// <param name="rect">描画範囲</param> /// <param name="hpos">水平描画位置</param> /// <param name="vpos">垂直描画位置</param> /// <param name="lineHeight">行間隔(行上端から次の行の上端までの間隔)フォント高さの倍数で指定する</param> /// <param name="fontRatio">文字の縦横比</param> /// <param name="shadow">影描画ブラシ。nullのときは影描画なし</param> /// <param name="shadowOffsetX">影描画時のXオフセット。未指定の場合フォント高さの10%</param> /// <param name="shadowOffsetY">影描画時のYオフセット。未指定の場合フォント高さの10%</param> /// <param name="shadowWidth">影描画時の太さ。未指定の場合shadowOffsetXとshadowOffsetYの二乗平均</param> /// <returns>描画した領域</returns> public static Rectangle DrawText(this Graphics g, string[] text, Font font, Pen outline, Brush fill, Rectangle rect, TextHPosition hpos = TextHPosition.Left, TextVPosition vpos = TextVPosition.Top, float lineHeight = 1.2F, float fontRatio = 1.0F, Brush shadow = null, float shadowOffsetX = float.MaxValue, float shadowOffsetY = float.MaxValue, float shadowWidth = float.MaxValue) { if ((text == null) || (text.Length == 0) || (rect == null)) { return(new Rectangle(0, 0, 0, 0)); } float emSize = font.GetEmSize(); GraphicsPath p = makeTextPath(text, font, rect, hpos, vpos, lineHeight, fontRatio, emSize); using (Matrix m = new Matrix()) { m.Translate((float)rect.X, (float)rect.Y); p.Transform(m); } // 影描画 if (shadow != null) { using (GraphicsPath sp = (GraphicsPath)p.Clone()) { if (shadowOffsetX == float.MaxValue) { shadowOffsetX = emSize / 10F; } if (shadowOffsetY == float.MaxValue) { shadowOffsetY = shadowOffsetX; } using (Matrix m = new Matrix()) { m.Translate(shadowOffsetX, shadowOffsetY); sp.Transform(m); } if (shadowWidth == float.MaxValue) { shadowWidth = (float)Math.Sqrt(shadowOffsetX * shadowOffsetX + shadowOffsetY * shadowOffsetY); } using (Pen pen = new Pen(Color.Black, shadowWidth)) { sp.Widen(pen); } g.FillPath(shadow, sp); } } // 文字描画 if (outline != null) { g.DrawPath(outline, p); } if (fill != null) { g.FillPath(fill, p); } // 描画した領域 Rectangle ret; if (outline == null) { ret = Rectangle.Ceiling(p.GetBounds()); } else { ret = Rectangle.Ceiling(RectangleF.Inflate(p.GetBounds(), outline.Width / 2F, outline.Width / 2F)); } p.Dispose(); return(ret); }
public static Rectangle DrawText(this Graphics g, string text, Font font, Brush fill, Point loc, TextHPosition hpos = TextHPosition.Left, TextVPosition vpos = TextVPosition.Top, float lineHeight = 1.2F, float fontRatio = 1.0F, Brush shadow = null, float shadowOffsetX = float.MaxValue, float shadowOffsetY = float.MaxValue, float shadowWidth = float.MaxValue) { if (String.IsNullOrEmpty(text)) { return(new Rectangle(0, 0, 0, 0)); } return(g.DrawText(text.Split("\n".ToCharArray()), font, null, fill, new Rectangle(loc.X, loc.Y, 0, 0), hpos, vpos, lineHeight, fontRatio, shadow, shadowOffsetX, shadowOffsetY, shadowWidth)); }
public static Rectangle DrawText(this Graphics g, string[] text, Font font, Brush fill, Point loc, TextHPosition hpos = TextHPosition.Left, TextVPosition vpos = TextVPosition.Top, float lineHeight = 1.2F, float fontRatio = 1.0F, Brush shadow = null, float shadowOffsetX = float.MaxValue, float shadowOffsetY = float.MaxValue, float shadowWidth = float.MaxValue) { return(g.DrawText(text, font, null, fill, new Rectangle(loc.X, loc.Y, 0, 0), hpos, vpos, lineHeight, fontRatio, shadow, shadowOffsetX, shadowOffsetY, shadowWidth)); }