Переверните 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);
    }

Теперь проблема в том, что он выходит из центра картинки.

1 ответ

Решение

Существует более простой способ перевернуть Graphics объект.
Создайте матрицу, которая является результатом умножения матрицы всех преобразований, которые необходимо применить к указанному объекту.

Матричное преобразование может быть применено к объекту GraphicsPath или к Graphics объект. Или оба, когда многократное преобразование должно быть выполнено последовательно.

Сеть 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-й столбец всегда одинаков, поэтому при построении новой матрицы значения 3-го столбца подразумеваются и предоставляются инициализацией класса Matrix, поэтому мы указываем только элементы в первые 2 столбца.

Важное примечание, прямо из документов класса Matrix:

Осторожно:
Порядок составного преобразования важен. В общем, поверните, затем масштабируйте, затем переведите не то же самое, что масштаб, затем поверните, затем переведите. Точно так же важен порядок умножения матриц. В общем, ABC - это не то же самое, что BAC

Пример строки, нарисованной на Panel используя метод GraphicsPath.AddString().
Два преобразования матрицы добавляются к GraphicsPath объект:
Flip-X и Flip-Y, которые объединяются с использованием Matrix.Multiply() метод:

Flip-X а также Flip-Y Матрицы построены в том числе X а также Y переводы, примененные к 3-й строке каждого Matrix, Значения перевода определяются размерами Canvas.
Например, Flip-X Матрица:

С [Canvas].Width = 100 =>:
Элемент вращения: повернуть ось X на 180° (-1 радиан) в начале координат Point(0, 0),
Перевести элемент: перевести 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;

string SampleText = "Sample Text to Flip";
bool FlipX = false;
bool FlipY = false;
bool Outlined = false;

private void panel1_Paint(object sender, PaintEventArgs e)
{
    e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
    e.Graphics.CompositingMode = CompositingMode.SourceOver;
    e.Graphics.CompositingQuality = CompositingQuality.HighQuality;
    e.Graphics.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;

    using (GraphicsPath path = new GraphicsPath())
    using (StringFormat format = new StringFormat(StringFormatFlags.NoClip | StringFormatFlags.NoWrap))
    {
        format.Alignment = StringAlignment.Center;
        format.LineAlignment = StringAlignment.Center;
        path.AddString(SampleText, new FontFamily("Segoe UI"), (int)FontStyle.Regular, 28, panel1.ClientRectangle, format);

        using (Matrix FlipXMatrix = new Matrix(-1, 0, 0, 1, panel1.Width, 0))
        using (Matrix FlipYMatrix = new Matrix(1, 0, 0, -1, 0, panel1.Height))
        using (Matrix 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();
}
Другие вопросы по тегам