diff --git a/build.bat b/build.bat
index cbc9bb8ec..057fb0209 100644
--- a/build.bat
+++ b/build.bat
@@ -186,6 +186,7 @@ COPY /Y /V "zlib.net.dll" "temp_zip\"
COPY /Y /V "NHunspell.dll" "temp_zip\"
COPY /Y /V "UtfUnknown.dll" "temp_zip\"
COPY /Y /V "Vosk.dll" "temp_zip\"
+COPY /Y /V "NCalc.dll" "temp_zip\"
COPY /Y /V "..\..\DLLs\Interop.QuartzTypeLib.dll" "temp_zip\"
COPY /Y /V "System.Net.Http.Extensions.dll" "temp_zip\"
COPY /Y /V "Newtonsoft.Json.dll" "temp_zip\"
diff --git a/build_beta.bat b/build_beta.bat
index 17292d388..ceed5eac1 100644
--- a/build_beta.bat
+++ b/build_beta.bat
@@ -174,6 +174,7 @@ COPY /Y /V "zlib.net.dll" "temp_zip\"
COPY /Y /V "NHunspell.dll" "temp_zip\"
COPY /Y /V "UtfUnknown.dll" "temp_zip\"
COPY /Y /V "Vosk.dll" "temp_zip\"
+COPY /Y /V "NCalc.dll" "temp_zip\"
COPY /Y /V "..\..\DLLs\Interop.QuartzTypeLib.dll" "temp_zip\"
COPY /Y /V "System.Net.Http.Extensions.dll" "temp_zip\"
COPY /Y /V "Newtonsoft.Json.dll" "temp_zip\"
diff --git a/installer/Subtitle_Edit_installer.iss b/installer/Subtitle_Edit_installer.iss
index 426862d06..670f58afc 100644
--- a/installer/Subtitle_Edit_installer.iss
+++ b/installer/Subtitle_Edit_installer.iss
@@ -305,6 +305,7 @@ Source: {#bindir}\zlib.net.dll; DestDir: {app};
Source: {#bindir}\NHunspell.dll; DestDir: {app}; Flags: ignoreversion; Components: main
Source: {#bindir}\UtfUnknown.dll; DestDir: {app}; Flags: ignoreversion; Components: main
Source: {#bindir}\Vosk.dll; DestDir: {app}; Flags: ignoreversion; Components: main
+Source: {#bindir}\NCalc.dll; DestDir: {app}; Flags: ignoreversion; Components: main
Source: ..\src\ui\DLLs\Interop.QuartzTypeLib.dll; DestDir: {app}; Flags: ignoreversion; Components: main
Source: {#bindir}\Newtonsoft.Json.dll; DestDir: {app}; Flags: ignoreversion; Components: main
Source: {#bindir}\System.Net.Http.Extensions.dll; DestDir: {app}; Flags: ignoreversion; Components: main
@@ -343,6 +344,7 @@ Type: files; Name: {app}\zlib.net.dll; Check: IsU
Type: files; Name: {app}\NHunspell.dll; Check: IsUpgrade()
Type: files; Name: {app}\UtfUnknown.dll; Check: IsUpgrade()
Type: files; Name: {app}\Vosk.dll; Check: IsUpgrade()
+Type: files; Name: {app}\NCalc.dll; Check: IsUpgrade()
Type: files; Name: {app}\Interop.QuartzTypeLib.dll; Check: IsUpgrade()
Type: files; Name: {app}\Newtonsoft.Json.dll; Check: IsUpgrade()
Type: files; Name: {app}\System.Net.Http.Extensions.dll; Check: IsUpgrade()
diff --git a/src/ui/Forms/Assa/AssSetBackground.cs b/src/ui/Forms/Assa/AssSetBackground.cs
index 686d34537..861b38504 100644
--- a/src/ui/Forms/Assa/AssSetBackground.cs
+++ b/src/ui/Forms/Assa/AssSetBackground.cs
@@ -14,6 +14,7 @@ using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows.Forms;
+using NCalc;
namespace Nikse.SubtitleEdit.Forms.Assa
{
@@ -496,7 +497,7 @@ namespace Nikse.SubtitleEdit.Forms.Assa
}
else if (radioButtonTopCenter.Checked)
{
- pos = $"{{\\pos({x + (width / 2) + marginH},{top+ marginV})}}";
+ pos = $"{{\\pos({x + (width / 2) + marginH},{top + marginV})}}";
}
else if (radioButtonTopRight.Checked)
{
@@ -530,10 +531,8 @@ namespace Nikse.SubtitleEdit.Forms.Assa
var layerAdd = 1;
foreach (var dp in _drawing.Paragraphs.OrderBy(pa => pa.Layer))
{
- var pDrawing = new Paragraph(dp.Text, 0, 1000);
- pDrawing.Text = pos + pDrawing.Text;
- pDrawing.StartTime.TotalMilliseconds = p.StartTime.TotalMilliseconds;
- pDrawing.EndTime.TotalMilliseconds = p.EndTime.TotalMilliseconds;
+ var pDrawing = new Paragraph(dp.Text, p.StartTime.TotalMilliseconds, p.EndTime.TotalMilliseconds);
+ pDrawing.Text = pos + TranslateTemplate(pDrawing.Text, x, top, right, bottom);
pDrawing.Layer = Configuration.Settings.Tools.AssaBgBoxLayer + layerAdd;
pDrawing.Extra = "SE-box-drawing";
subtitle.InsertParagraphInCorrectTimeOrder(pDrawing);
@@ -542,6 +541,63 @@ namespace Nikse.SubtitleEdit.Forms.Assa
}
}
+ private string TranslateTemplate(string input, int left, int top, int right, int bottom)
+ {
+ var text = input;
+ var width = right - left;
+ var height = bottom - top;
+
+ try
+ {
+ var startIdx = text.IndexOf('[');
+ while (startIdx >= 0)
+ {
+ var endIdx = text.IndexOf(']', startIdx);
+ if (endIdx < 0)
+ {
+ return input;
+ }
+
+ var expr = text.Substring(startIdx+1, endIdx - startIdx - 1);
+ expr = expr.ToUpperInvariant()
+ .Replace("LEFT", left.ToString(CultureInfo.InvariantCulture))
+ .Replace("TOP", top.ToString(CultureInfo.InvariantCulture))
+ .Replace("RIGHT", right.ToString(CultureInfo.InvariantCulture))
+ .Replace("BOTTOM", bottom.ToString(CultureInfo.InvariantCulture))
+ .Replace("WIDTH", width.ToString(CultureInfo.InvariantCulture))
+ .Replace("HEIGHT", height.ToString(CultureInfo.InvariantCulture));
+
+ var calcExpression = new Expression(expr);
+ var calcObj = calcExpression.Evaluate();
+ var calcResult = calcExpression.Evaluate().ToString();
+ if (calcObj is double numberDouble)
+ {
+ calcResult = numberDouble.ToString(CultureInfo.InvariantCulture);
+ }
+ else if (calcObj is float numberFloat)
+ {
+ calcResult = numberFloat.ToString(CultureInfo.InvariantCulture);
+ }
+ else if (calcObj is decimal numberDecimal)
+ {
+ calcResult = numberDecimal.ToString(CultureInfo.InvariantCulture);
+ }
+
+ text = text
+ .Remove(startIdx, endIdx - startIdx + 1)
+ .Insert(startIdx, calcResult);
+
+ startIdx = text.IndexOf('[', startIdx);
+ }
+
+ return text;
+ }
+ catch
+ {
+ return input;
+ }
+ }
+
private void ApplyCustomStyles_FormClosing(object sender, FormClosingEventArgs e)
{
_closing = true;
diff --git a/src/ui/SubtitleEdit.csproj b/src/ui/SubtitleEdit.csproj
index c9e5c24d7..a9cc67758 100644
--- a/src/ui/SubtitleEdit.csproj
+++ b/src/ui/SubtitleEdit.csproj
@@ -61,6 +61,9 @@
DLLs\Interop.QuartzTypeLib.dll
False
+
+ ..\..\packages\ncalc.1.3.8\lib\NCalc.dll
+
..\..\packages\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll
diff --git a/src/ui/packages.config b/src/ui/packages.config
index 90793642a..6bbaf2dfd 100644
--- a/src/ui/packages.config
+++ b/src/ui/packages.config
@@ -3,6 +3,7 @@
+