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