翻转绘制 text/string 的 GraphicsPath

Flip the GraphicsPath that draws the text/string

我的文本中有这个方法Class,但我似乎无法翻转整个文本。
我正在使用矩阵来转换用于绘制字符串的 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 which is the result of the Matrix multiplication

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

.Net System.Drawing.Drawing2D Matrix class 没有预先构建的 Flip (镜像)转换,但是这个 Matrix 结构已经众所周知(我不确定这就是矩阵 class):

中没有特定方法的原因
| 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 列始终相同,因此,在构建新矩阵时,第 3 列值是隐含的,由矩阵提供 class初始化,所以我们只指定前两列中的元素。

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

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() 方法.[=63 在 Panel 上绘制字符串的示例=] 向 GraphicsPath 对象添加了两个矩阵转换:
一个Flip-X和一个Flip-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 

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

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();
}