c# - 翻转绘制文本/字符串的 GraphicsPath

标签 c# .net winforms gdi+ graphicspath

我的文本类中有这个方法,但我似乎无法翻转整个文本。
我正在使用矩阵来转换用于绘制字符串的 GraphicsPath

这是我使用@Jimi 的回答后的代码:

    public LayerClass DrawString(LayerClass.Type _text, string text, RectangleF rect, Font _fontStyle, Brush brush, float angle, PaintEventArgs e)
    {
        using (StringFormat string_format = new StringFormat())
        {
            SizeF stringSize = e.Graphics.MeasureString(text, _fontStyle);
            rect.Location = new PointF(Shape.center.X - (rect.Width / 2), Shape.center.Y - (rect.Height / 2));
            GraphicsContainer gc = e.Graphics.BeginContainer();
            e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
            e.Graphics.CompositingQuality = CompositingQuality.HighQuality;
            //e.Graphics.DrawRectangle(Pens.Red, Rectangle.Round(rect));

            RectangleF r = new RectangleF(rect.Location, rect.Size);
            GraphicsPath path = new GraphicsPath();
            if (text == "" || text == " ")
                path.Dispose(); //Disposes the path to prevent OutOfMemoryExcetption
            else
            {
                path.AddString(text, _fontStyle.FontFamily, Convert.ToInt32(_fontStyle.Style), _fontStyle.Height, new Point(0,0), string_format);
                RectangleF text_rectf = path.GetBounds();
                PointF[] target_pts = {
                            new PointF(r.Left, r.Top),
                            new PointF(r.Right, r.Top),
                            new PointF(r.Left, r.Bottom)};
                //e.Graphics.DrawRectangle(Pens.Red, Rectangle.Round(r));
                using (Matrix m = new Matrix(text_rectf, target_pts)) 
                using (Matrix rotate = new Matrix())
                using (Matrix FlipXMatrix = new Matrix(-1, 0, 0, 1, 0, 0)) 
                using (Matrix FlipYMatrix = new Matrix(1, 0, 0, -1, 0, 0))
                using (Matrix TransformMatrix = new Matrix())
                {
                    TransformMatrix.Multiply(m);
                    m.RotateAt(angle, new PointF(0 + (stringSize.Width / 2), +(r.Height * 2)));
                    rotate.RotateAt(angle, new PointF(r.X, r.Y));
                    TransformMatrix.Multiply(rotate);
                    if (flipped)
                    {
                        TransformMatrix.Multiply(FlipXMatrix);
                    }
                    path.Transform(TransformMatrix);

                    if (flipY)
                    {
                        TransformMatrix.Multiply(FlipYMatrix);
                        path.Transform(TransformMatrix);
                    }

                    //Checks if the user wants the text filled or outlined
                    if (!isOutlined)
                        e.Graphics.FillPath(Brushes.Red, path);
                    else
                        e.Graphics.DrawPath(Pens.Red, path);
                } 
            }
        e.Graphics.EndContainer(gc);
        }
        this._Text = text;
        this._TextRect = rect;
        this.brush = brush;
        this._Angle = angle;
        return new LayerClass(_text, this, text, rect);
    }

Now the problem is, it goes out the center of the picturebox.

最佳答案

翻转 Graphics 对象有一种更简单的方法。
创建 Matrix这是 Matrix multiplication 的结果需要应用于指定对象的所有转换。

矩阵转换可以应用于 GraphicsPath对象或 Graphics 对象。或两者,当需要顺序执行多个转换时。

.Net System.Drawing.Drawing2D Matrix 类没有预先构建的Flip(镜像)转换,但是这个 Matrix 结构已经众所周知(我我不确定这就是 Matrix 类中没有特定方法的原因):

| 1 | 0 | 0 |       |-1 | 0 | 0 |       | 1 | 0 | 0 |
| 0 | 1 | 0 |       | 0 | 1 | 0 |       | 0 |-1 | 0 |
| 0 | 0 | 1 |       | 0 | 0 | 1 |       | 0 | 0 | 1 |

   Identity         Mirror X-Axis       Mirror Y-Axis
    Matrix              Matrix             Matrix

您会注意到(文档中也有报道)第 3 列始终相同,因此,在构建新 Matrix 时,第 3 列值是隐含的,由 Matrix 类初始化提供,因此我们仅指定前两列中的元素。

重要说明,直接来自 Matrix 类文档:

Caution:
The order of a composite transformation is important. In general, rotate, then scale, then translate is not the same as scale, then rotate, then translate. Similarly, the order of matrix multiplication is important. In general, ABC is not the same as BAC

使用 GraphicsPath.AddString()面板 上绘制的字符串示例方法
GraphicsPath 对象中添加了两个 Matrix 转换:
Flip-XFlip-Y,使用 Matrix.Multiply() 方法组合:

构建Flip-XFlip-Y 矩阵,包括XY 转换,应用到每个 Matrix 的第 3 行。 翻译值由 Canvas 尺寸决定。
例如,Flip-X 矩阵:

使用 [Canvas].Width = 100 =>:
旋转元素:在原点 Point(0, 0) 上将 X 轴旋转 180°(-1 弧度)。
平移元素:将X位置100个图形单元向右平移(正值)。

| -1  |  0  |  0  |
|  0  |  1  |  0  |
| 100 |  0  |  1  |

   Mirror X-Axis
  Translate X +100
      Matrix 

效果的可视化表示。
代码中引用的控件与您在此处看到的相同(如果您需要重现它)。

Matrix Flip

using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Text;

bool flipX = false;
bool flipY = false;
bool outlined = false;
float sampleFontEmSize = 28f;
string sampleText = "Sample Text to Flip";
FontFamily sampleFont = new FontFamily("Segoe UI");

private void panel1_Paint(object sender, PaintEventArgs e)
{
    Panel panel = sender as Panel;
    e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;

    using (var path = new GraphicsPath())
    using (var format = new StringFormat(StringFormatFlags.NoClip | StringFormatFlags.NoWrap))
    {
        format.Alignment = StringAlignment.Center;
        format.LineAlignment = StringAlignment.Center;
        path.AddString(sampleText, sampleFont, (int)FontStyle.Regular, sampleFontEmSize, panel.ClientRectangle, format);

        using (var flipXMatrix = new Matrix(-1, 0, 0, 1, panel.Width, 0))
        using (var flipYMatrix = new Matrix(1, 0, 0, -1, 0, panel.Height))
        using (var transformMatrix = new Matrix())
        {
            if (flipX) {
                transformMatrix.Multiply(flipXMatrix);
            }
            if (flipY) {
                transformMatrix.Multiply(flipYMatrix);
            }
            path.Transform(transformMatrix);
            //Or e.Graphics.Transform = TransformMatrix;

            if (outlined) {
                e.Graphics.DrawPath(Pens.LawnGreen, path);
            }
            else {
                e.Graphics.FillPath(Brushes.Orange, path);
            }
        }
    }
}

private void btnFlipX_Click(object sender, EventArgs e)
{
    flipX = !flipX;
    panel1.Invalidate();
}

private void btnFlipY_Click(object sender, EventArgs e)
{
    flipY = !flipY;
    panel1.Invalidate();
}

private void chkOutlined_CheckedChanged(object sender, EventArgs e)
{
    outlined = chkOutlined.Checked;
    panel1.Invalidate();
}

关于c# - 翻转绘制文本/字符串的 GraphicsPath,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53181887/

相关文章:

c# - Linq 到文本文件

c# - 读取 Stream 对象而不使用它

c# - 从枚举中获取值

c# - 在第一列中显示第二列的值(如果第一列为空,则作为后备)

c# - 在 C# 中绑定(bind)到 DataGridView 时使用的一个很好的集合

c# - 动态更改 GroupBox 的内容

c# - 聚合值直到达到限制

.net - 为什么 .NET 区分字符串和字符?

c# - 在 C# 中显示只读文本的最佳方式

c# - 如何处理 System.OverflowException