翻转绘制文本/字符串的 GraphicsPath [英] Flip the GraphicsPath that draws the text/string

查看:22
本文介绍了翻转绘制文本/字符串的 GraphicsPath的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

 public LayerClass DrawString(LayerClass.Type _text, string text, RectangleF rect, Font _fontStyle, Brush Brush, float angle, PaintEventArgs e){使用 (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();如果(文本=="||文本==")path.Dispose();//设置防止OutOfMemoryExcetption的路径别的{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 = {新 PointF(r.Left, r.Top),新 PointF(r.Right, r.Top),新 PointF(r.Left, r.Bottom)};//e.Graphics.DrawRectangle(Pens.Red, Rectangle.Round(r));使用(矩阵 m = 新矩阵(text_rectf,target_pts))使用(矩阵旋转 = 新矩阵())使用 (Matrix FlipXMatrix = new Matrix(-1, 0, 0, 1, 0, 0))使用 (Matrix FlipYMatrix = new Matrix(1, 0, 0, -1, 0, 0))使用 (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);如果(翻转){TransformMatrix.Multiply(FlipXMatrix);}path.Transform(TransformMatrix);如果(翻转){TransformMatrix.Multiply(FlipYMatrix);path.Transform(TransformMatrix);}//检查用户是否想要填充或勾勒文本如果 (!isOutlined)e.Graphics.FillPath(Brushes.Red, path);别的e.Graphics.DrawPath(Pens.Red, path);}}e.Graphics.EndContainer(gc);}this._Text = 文字;this._TextRect = rect;this.brush = 画笔;this._Angle = 角度;返回新的图层类(_text,this,text,rect);}

<块引用>

现在的问题是,它超出了图片框的中心.

解决方案

有一种更简单的方法来翻转Graphics 对象.
创建一个

使用 System.Drawing;使用 System.Drawing.Drawing2D;使用 System.Drawing.Text;布尔翻转X =假;bool flipY = false;布尔概述 = 假;浮动 sampleFontEmSize = 28f;string sampleText = "要翻转的示例文本";FontFamily sampleFont = new FontFamily("Segoe UI");private void panel1_Paint(对象发送者,PaintEventArgs e){面板面板 = 发送方为面板;e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;使用 (var path = new GraphicsPath())使用 (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);使用 (var flipXMatrix = new Matrix(-1, 0, 0, 1, panel.Width, 0))使用 (var flipYMatrix = new Matrix(1, 0, 0, -1, 0, panel.Height))使用 (var transformMatrix = new Matrix()){如果(翻转X){transformMatrix.Multiply(flipXMatrix);}如果(翻转){transformMatrix.Multiply(flipYMatrix);}path.Transform(transformMatrix);//或 e.Graphics.Transform = TransformMatrix;如果(概述){e.Graphics.DrawPath(Pens.LawnGreen, path);}别的 {e.Graphics.FillPath(Brushes.Orange, path);}}}}私有无效 btnFlipX_Click(对象发送者,EventArgs e){翻转X =!翻转X;panel1.Invalidate();}private void btnFlipY_Click(对象发送者,EventArgs e){翻转Y = !翻转Y;panel1.Invalidate();}私人无效 chkOutlined_CheckedChanged(对象发送者,EventArgs e){概述 = chkOutlined.Checked;panel1.Invalidate();}

I have this method in my Text Class and I can't seem to flip the whole text.
I am using a Matrix to transform the GraphicsPath which is used to draw the string.

Here's the code since I used @Jimi's answer:

    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.

解决方案

There is a simpler way to flip a Graphics object.
Create a Matrix which is the result of the Matrix multiplication of all the transformations that need to be applied to the specified object.

A Matrix transformation can be applied to either the GraphicsPath object or the Graphics object. Or both, when multiple transformation need to be performed sequentially.

The .Net System.Drawing.Drawing2D Matrix class does not have a pre-built Flip (mirroring) transformation, but this Matrix structure is already well known (I'm not sure this is the reason why there isn't a specific method in the 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

You can notice (it's also reported in the Docs) that the 3rd column is always the same, therefore, when building a new Matrix, the 3rd column values are implied and are provided by the Matrix class initialization, so we specify just the elements in the first 2 columns.

Important note, straight from the Matrix class Docs:

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

An example of a string drawn on a Panel using the GraphicsPath.AddString() method.
Two Matrix transformations are added to the GraphicsPath object:
a Flip-X and a Flip-Y, which are combined using the Matrix.Multiply() method:

The Flip-X and Flip-Y Matrices are built including the X and Y translations, applied to the 3rd row of each Matrix. The translation values are determined by the Canvas dimensions.
For example, the Flip-X Matrix:

With a [Canvas].Width = 100 =>:
Rotation Element : Rotate the X-Axis 180° (-1 radians) on the origin Point(0, 0).
Translate Element: Translate the X Position 100 Graphics Units to the right (positive value).

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

   Mirror X-Axis
  Translate X +100
      Matrix 


A visual representation of the effect.
The Controls referenced in the code are the same you can see here (if you need to reproduce it).

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

这篇关于翻转绘制文本/字符串的 GraphicsPath的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆