mirror of
https://github.com/SubtitleEdit/subtitleedit.git
synced 2024-11-23 03:33:18 +01:00
194 lines
6.4 KiB
C#
194 lines
6.4 KiB
C#
using System.Diagnostics;
|
|
using System.Drawing;
|
|
using System.Drawing.Drawing2D;
|
|
using System.Linq;
|
|
using System.Text;
|
|
|
|
namespace Nikse.SubtitleEdit.Core
|
|
{
|
|
public static class TextDraw
|
|
{
|
|
|
|
public static double GetFontSize(double fontSize)
|
|
{
|
|
return fontSize * 0.895d; // font rendered in video players like vlc/mpv are a little smaller than .net, so we adjust font size a bit down
|
|
}
|
|
|
|
public static void DrawText(Font font, StringFormat sf, GraphicsPath path, StringBuilder sb, bool isItalic, bool isBold, bool isUnderline, float left, float top, ref bool newLine, float leftMargin, ref int pathPointsStart)
|
|
{
|
|
var next = new PointF(left, top);
|
|
|
|
if (path.PointCount > 0)
|
|
{
|
|
int k = 0;
|
|
var list = (PointF[])path.PathPoints.Clone(); // avoid using very slow path.PathPoints indexer!!!
|
|
for (int i = list.Length - 1; i >= 0; i--)
|
|
{
|
|
if (list[i].X > next.X)
|
|
{
|
|
next.X = list[i].X;
|
|
}
|
|
|
|
k++;
|
|
if (k > 60 || i <= pathPointsStart && pathPointsStart != -1)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (newLine)
|
|
{
|
|
next.X = leftMargin;
|
|
newLine = false;
|
|
pathPointsStart = path.PointCount;
|
|
}
|
|
|
|
var fontStyle = FontStyle.Regular;
|
|
if (isItalic)
|
|
{
|
|
fontStyle |= FontStyle.Italic;
|
|
}
|
|
|
|
if (isBold)
|
|
{
|
|
fontStyle |= FontStyle.Bold;
|
|
}
|
|
|
|
if (isUnderline)
|
|
{
|
|
fontStyle |= FontStyle.Underline;
|
|
}
|
|
|
|
var fontSize = (float)GetFontSize(font.Size);
|
|
try
|
|
{
|
|
path.AddString(sb.ToString(), font.FontFamily, (int)fontStyle, fontSize, next, sf);
|
|
}
|
|
catch
|
|
{
|
|
fontStyle = FontStyle.Regular;
|
|
try
|
|
{
|
|
path.AddString(sb.ToString(), font.FontFamily, (int)fontStyle, fontSize, next, sf);
|
|
}
|
|
catch
|
|
{
|
|
path.AddString(sb.ToString(), new FontFamily("Arial"), (int)fontStyle, fontSize, next, sf);
|
|
}
|
|
}
|
|
sb.Length = 0;
|
|
}
|
|
|
|
public static float MeasureTextWidth(Font font, string text, bool bold)
|
|
{
|
|
using (var sf = new StringFormat { Alignment = StringAlignment.Near, LineAlignment = StringAlignment.Near })
|
|
{
|
|
using (var path = new GraphicsPath())
|
|
{
|
|
var sb = new StringBuilder(text);
|
|
bool newLine = false;
|
|
const int leftMargin = 0;
|
|
int pathPointsStart = -1;
|
|
DrawText(font, sf, path, sb, false, bold, false, 0, 0, ref newLine, leftMargin, ref pathPointsStart);
|
|
if (path.PathData.Points.Length == 0)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
float width = 0;
|
|
var list = (PointF[])path.PathPoints.Clone(); // avoid using very slow path.PathPoints indexer!!!
|
|
int max = list.Length;
|
|
if (max <= 500)
|
|
{
|
|
for (int i = 0; i < max; i++)
|
|
{
|
|
if (list[i].X > width)
|
|
{
|
|
width = list[i].X;
|
|
}
|
|
}
|
|
return width;
|
|
}
|
|
|
|
int interval = 1;
|
|
if (max > 1500)
|
|
{
|
|
interval = 5;
|
|
}
|
|
else if (max > 1000)
|
|
{
|
|
interval = 3;
|
|
}
|
|
else
|
|
{
|
|
interval = 2;
|
|
}
|
|
for (int i = 0; i < max; i += interval)
|
|
{
|
|
if (list[i].X > width)
|
|
{
|
|
width = list[i].X;
|
|
}
|
|
}
|
|
if (list[1].X > width)
|
|
{
|
|
width = list[1].X;
|
|
}
|
|
if (list[2].X > width)
|
|
{
|
|
width = list[2].X;
|
|
}
|
|
if (list[max - 1].X > width)
|
|
{
|
|
width = list[max - 1].X;
|
|
}
|
|
if (list[max - 2].X > width)
|
|
{
|
|
width = list[max - 2].X;
|
|
}
|
|
|
|
return width;
|
|
}
|
|
}
|
|
}
|
|
|
|
public static float MeasureTextHeight(Font font, string text, bool bold)
|
|
{
|
|
using (var sf = new StringFormat { Alignment = StringAlignment.Near, LineAlignment = StringAlignment.Near })
|
|
{
|
|
using (var path = new GraphicsPath())
|
|
{
|
|
var sb = new StringBuilder(text);
|
|
bool newLine = false;
|
|
const int leftMargin = 0;
|
|
int pathPointsStart = -1;
|
|
DrawText(font, sf, path, sb, false, bold, false, 0, 0, ref newLine, leftMargin, ref pathPointsStart);
|
|
|
|
float height = 0;
|
|
var list = (PointF[])path.PathPoints.Clone(); // avoid using very slow path.PathPoints indexer!!!
|
|
int index = System.Math.Max(list.Length - 80, 0);
|
|
for (int i = index; i < list.Length; i += 2)
|
|
{
|
|
if (list[i].Y > height)
|
|
{
|
|
height = list[i].Y;
|
|
}
|
|
}
|
|
|
|
for (int i = 0; i < list.Length; i += 2)
|
|
{
|
|
if (list[i].Y > height)
|
|
{
|
|
height = list[i].Y;
|
|
}
|
|
}
|
|
|
|
return height;
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|