Переверните GraphicsPath, который рисует текст / строку - PullRequest
0 голосов
/ 07 ноября 2018

У меня есть этот метод в моем текстовом классе, и я не могу перевернуть весь текст.
Я использую Матрицу для преобразования 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 Ответ

0 голосов
/ 07 ноября 2018

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

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

. Matrix класс .Net System.Drawing.Drawing2D не имеет предварительно созданного преобразования 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 () метод .
Два объекта Matrix добавлены к объекту 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 

Визуальное представление эффекта.
Элементы управления, указанные в коде, такие же, как вы можете видеть здесь (если вам нужно воспроизвести его).

Matrix Flip

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