mirror of
https://github.com/SubtitleEdit/subtitleedit.git
synced 2024-10-27 14:32:35 +01:00
Add some Cea608
This commit is contained in:
parent
fb5d0380b4
commit
2769d3c2f9
186
src/libse/Cea608/CaptionScreen.cs
Normal file
186
src/libse/Cea608/CaptionScreen.cs
Normal file
@ -0,0 +1,186 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Nikse.SubtitleEdit.Core.Cea608
|
||||
{
|
||||
public class CaptionScreen
|
||||
{
|
||||
public CcRow[] Rows = {
|
||||
new CcRow(),
|
||||
new CcRow(),
|
||||
new CcRow(),
|
||||
new CcRow(),
|
||||
new CcRow(),
|
||||
new CcRow(),
|
||||
new CcRow(),
|
||||
new CcRow(),
|
||||
new CcRow(),
|
||||
new CcRow(),
|
||||
new CcRow(),
|
||||
new CcRow(),
|
||||
new CcRow(),
|
||||
new CcRow(),
|
||||
new CcRow(),
|
||||
};
|
||||
|
||||
public int CurrentRow { get; set; } = Constants.ScreenRowCount - 1;
|
||||
public int? NumberOfRollUpRows { get; set; }
|
||||
|
||||
public CaptionScreen()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
public SerializedRow[] Serialize()
|
||||
{
|
||||
var results = new List<SerializedRow>();
|
||||
for (var i = 0; i < Constants.ScreenRowCount; i++)
|
||||
{
|
||||
var row = Rows[i];
|
||||
if (row.IsEmpty())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
results.Add(new SerializedRow
|
||||
{
|
||||
Row = i,
|
||||
Position = row.FirstNonEmpty(),
|
||||
Style = row.CurrentPenState.Serialize(),
|
||||
Columns = row.Chars.Select(SerializeChar).ToArray()
|
||||
});
|
||||
}
|
||||
return results.ToArray();
|
||||
}
|
||||
|
||||
private SerializedStyledUnicodeChar SerializeChar(StyledUnicodeChar character)
|
||||
{
|
||||
return new SerializedStyledUnicodeChar
|
||||
{
|
||||
Character = character.Uchar,
|
||||
Style = character.PenState.Serialize(),
|
||||
};
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
for (var i = 0; i < Constants.ScreenRowCount; i++)
|
||||
{
|
||||
Rows[i].Clear();
|
||||
}
|
||||
CurrentRow = Constants.ScreenRowCount - 1;
|
||||
}
|
||||
|
||||
public bool Equals(CaptionScreen other)
|
||||
{
|
||||
var equal = true;
|
||||
for (var i = 0; i < Constants.ScreenRowCount; i++)
|
||||
{
|
||||
if (!Rows[i].Equals(other.Rows[i]))
|
||||
{
|
||||
equal = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return equal;
|
||||
}
|
||||
|
||||
public void Copy(CaptionScreen other)
|
||||
{
|
||||
for (var i = 0; i < Constants.ScreenRowCount; i++)
|
||||
{
|
||||
Rows[i].Copy(other.Rows[i]);
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsEmpty()
|
||||
{
|
||||
var empty = true;
|
||||
for (var i = 0; i < Constants.ScreenRowCount; i++)
|
||||
{
|
||||
if (!Rows[i].IsEmpty())
|
||||
{
|
||||
empty = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return empty;
|
||||
}
|
||||
|
||||
public void BackSpace()
|
||||
{
|
||||
Rows[CurrentRow].BackSpace();
|
||||
}
|
||||
|
||||
public void ClearToEndOfRow()
|
||||
{
|
||||
Rows[CurrentRow].ClearToEndOfRow();
|
||||
}
|
||||
|
||||
public void InsertChar(int character)
|
||||
{
|
||||
Rows[CurrentRow].InsertChar(character);
|
||||
}
|
||||
|
||||
public void SetPen(SerializedPenState styles)
|
||||
{
|
||||
Rows[CurrentRow].SetPenStyles(styles);
|
||||
}
|
||||
|
||||
public void MoveCursor(int relPos)
|
||||
{
|
||||
Rows[CurrentRow].MoveCursor(relPos);
|
||||
}
|
||||
|
||||
public void SetPac(PacData pacData)
|
||||
{
|
||||
var newRow = pacData.Row - 1;
|
||||
CurrentRow = newRow;
|
||||
var row = Rows[CurrentRow];
|
||||
if (pacData.Indent != null)
|
||||
{
|
||||
var indent = pacData.Indent;
|
||||
var prevPos = Math.Max(indent.Value - 1, 0);
|
||||
row.Position = pacData.Indent.Value;
|
||||
pacData.Color = row.Chars[prevPos].PenState.Foreground;
|
||||
}
|
||||
|
||||
SetPen(new SerializedPenState
|
||||
{
|
||||
Foreground = pacData.Color ?? Constants.ColorWhite,
|
||||
Underline = pacData.Underline,
|
||||
Italics = pacData.Italics ?? false,
|
||||
Background = Constants.ColorBlack,
|
||||
Flash = false,
|
||||
});
|
||||
}
|
||||
|
||||
public void SetBkgData(SerializedPenState bkgData)
|
||||
{
|
||||
BackSpace();
|
||||
SetPen(bkgData);
|
||||
InsertChar(0x20); // Space
|
||||
}
|
||||
|
||||
public void SetRollUpRows(int nrRows)
|
||||
{
|
||||
NumberOfRollUpRows = nrRows;
|
||||
}
|
||||
|
||||
public void RollUp()
|
||||
{
|
||||
// if the row is empty we have nothing to roll-up
|
||||
if (NumberOfRollUpRows == null || Rows[CurrentRow].IsEmpty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var rows = Rows.ToList();
|
||||
rows.RemoveAt(CurrentRow - NumberOfRollUpRows.Value + 1);
|
||||
rows.Add(new CcRow());
|
||||
Rows = rows.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
289
src/libse/Cea608/CcDataC608Parser.cs
Normal file
289
src/libse/Cea608/CcDataC608Parser.cs
Normal file
@ -0,0 +1,289 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Nikse.SubtitleEdit.Core.Cea608
|
||||
{
|
||||
public class CcDataC608Parser
|
||||
{
|
||||
public delegate void DisplayScreenDelegate(DataOutput data);
|
||||
|
||||
public Cea608Channel[] Channels { get; set; }
|
||||
public int? CurrentChannelNumber { get; set; }
|
||||
public int? LastTime { get; set; }
|
||||
|
||||
private int? _lastCmdA;
|
||||
private int? _lastCmdB;
|
||||
|
||||
public DisplayScreenDelegate DisplayScreen { get; set; }
|
||||
|
||||
public CcDataC608Parser()
|
||||
{
|
||||
Channels = new[]
|
||||
{
|
||||
new Cea608Channel(1, this),
|
||||
new Cea608Channel(2, this),
|
||||
};
|
||||
|
||||
CurrentChannelNumber = -1;
|
||||
}
|
||||
|
||||
public void AddData(int t, int[] byteList)
|
||||
{
|
||||
LastTime = t;
|
||||
|
||||
for (var i = 0; i < byteList.Length; i += 2)
|
||||
{
|
||||
var a = byteList[i] & 0x7f;
|
||||
var b = byteList[i + 1] & 0x7f;
|
||||
|
||||
if (a == 0 && b == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!(ParseCmd(a, b) ||
|
||||
ParseMidRow(a, b) ||
|
||||
ParsePac(a, b) ||
|
||||
ParseBackgroundAttributes(a, b)))
|
||||
{
|
||||
ParseCharacters(a, b);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ParseCharacters(int ccData1, int ccData2)
|
||||
{
|
||||
var charsFound = ParseChars(ccData1, ccData2);
|
||||
if (charsFound.Length > 0)
|
||||
{
|
||||
if (CurrentChannelNumber != null && CurrentChannelNumber >= 0)
|
||||
{
|
||||
var channel = Channels[CurrentChannelNumber.Value - 1];
|
||||
channel.InsertChars(charsFound);
|
||||
}
|
||||
else
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine("No channel found yet. TEXT-MODE?");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int[] ParseChars(int a, int b)
|
||||
{
|
||||
var charCodes = new List<int>();
|
||||
int charCode1;
|
||||
|
||||
if (a >= 0x19)
|
||||
{
|
||||
charCode1 = a - 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
charCode1 = a;
|
||||
}
|
||||
|
||||
if (0x11 <= charCode1 && charCode1 <= 0x13)
|
||||
{
|
||||
// Special character
|
||||
int oneCode;
|
||||
if (charCode1 == 0x11)
|
||||
{
|
||||
oneCode = b + 0x50;
|
||||
}
|
||||
else if (charCode1 == 0x12)
|
||||
{
|
||||
oneCode = b + 0x70;
|
||||
}
|
||||
else
|
||||
{
|
||||
oneCode = b + 0x90;
|
||||
}
|
||||
|
||||
charCodes.Add(oneCode);
|
||||
}
|
||||
else if (0x20 <= a && a <= 0x7f)
|
||||
{
|
||||
charCodes.Add(a);
|
||||
|
||||
if (b > 0)
|
||||
{
|
||||
charCodes.Add(b);
|
||||
}
|
||||
}
|
||||
|
||||
return charCodes.ToArray();
|
||||
}
|
||||
|
||||
private static bool HasCmd(int ccData1, int ccData2)
|
||||
{
|
||||
return ((ccData1 == 0x14 || ccData1 == 0x1C) && (0x20 <= ccData2 && ccData2 <= 0x2F)) ||
|
||||
((ccData1 == 0x17 || ccData1 == 0x1F) && (0x21 <= ccData2 && ccData2 <= 0x23));
|
||||
}
|
||||
|
||||
public bool ParseCmd(int a, int b)
|
||||
{
|
||||
if (HasCmd(a, b))
|
||||
{
|
||||
// Duplicate CMD commands get skipped once
|
||||
if (_lastCmdA == a && _lastCmdB == b)
|
||||
{
|
||||
_lastCmdA = null;
|
||||
_lastCmdB = null;
|
||||
return true;
|
||||
}
|
||||
|
||||
int chNr;
|
||||
if (a == 0x14 || a == 0x17)
|
||||
{
|
||||
chNr = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
chNr = 2; // (a == 0x1C || a== 0x1f)
|
||||
}
|
||||
|
||||
Channels[chNr - 1].RunCmd(a, b);
|
||||
CurrentChannelNumber = chNr;
|
||||
_lastCmdA = a;
|
||||
_lastCmdB = b;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool ParseMidRow(int a, int b)
|
||||
{
|
||||
if (((a == 0x11) || (a == 0x19)) && 0x20 <= b && b <= 0x2f)
|
||||
{
|
||||
int chNr;
|
||||
if (a == 0x11)
|
||||
{
|
||||
chNr = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
chNr = 2;
|
||||
}
|
||||
var channel = Channels[chNr - 1];
|
||||
channel.cc_MidRow(b);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool HasPac(int ccData1, int ccData2)
|
||||
{
|
||||
return (((0x11 <= ccData1 && ccData1 <= 0x17) || (0x19 <= ccData1 && ccData1 <= 0x1F)) && (0x40 <= ccData2 && ccData2 <= 0x7F)) ||
|
||||
((ccData1 == 0x10 || ccData1 == 0x18) && (0x40 <= ccData2 && ccData2 <= 0x5F));
|
||||
}
|
||||
|
||||
public bool ParsePac(int a, int b)
|
||||
{
|
||||
if (HasPac(a, b))
|
||||
{
|
||||
var chNr = (a <= 0x17) ? 1 : 2;
|
||||
|
||||
int row;
|
||||
if (0x40 <= b && b <= 0x5F)
|
||||
{
|
||||
row = (chNr == 1) ? Constants.Channel1RowsMap[a] : Constants.Channel2RowsMap[a];
|
||||
}
|
||||
else
|
||||
{ // 0x60 <= b <= 0x7F
|
||||
row = (chNr == 1) ? (Constants.Channel1RowsMap[a] + 1) : (Constants.Channel2RowsMap[a] + 1);
|
||||
}
|
||||
|
||||
var pacData = InterpretPac(row, b);
|
||||
var channel = Channels[chNr - 1];
|
||||
channel.SetPac(pacData);
|
||||
CurrentChannelNumber = chNr;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public PacData InterpretPac(int row, int b)
|
||||
{
|
||||
var pacData = new PacData
|
||||
{
|
||||
Color = null,
|
||||
Italics = false,
|
||||
Indent = null,
|
||||
Underline = false,
|
||||
Row = row,
|
||||
};
|
||||
|
||||
int pacIndex;
|
||||
if (b > 0x5F)
|
||||
{
|
||||
pacIndex = b - 0x60;
|
||||
}
|
||||
else
|
||||
{
|
||||
pacIndex = b - 0x40;
|
||||
}
|
||||
|
||||
pacData.Underline = (pacIndex & 1) == 1;
|
||||
if (pacIndex <= 0xd)
|
||||
{
|
||||
pacData.Color = Constants.PacDataColors[(int)Math.Floor(pacIndex / 2.0)];
|
||||
}
|
||||
else if (pacIndex <= 0xf)
|
||||
{
|
||||
pacData.Italics = true;
|
||||
pacData.Color = Constants.ColorWhite;
|
||||
}
|
||||
else
|
||||
{
|
||||
pacData.Indent = (int)((Math.Floor((pacIndex - 0x10) / 2.0)) * 4);
|
||||
}
|
||||
|
||||
return pacData;
|
||||
}
|
||||
|
||||
public bool ParseBackgroundAttributes(int a, int b)
|
||||
{
|
||||
var bkgData = new SerializedPenState();
|
||||
if (!HasBackgroundAttributes(a, b))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (a == 0x10 || a == 0x18)
|
||||
{
|
||||
var index = (int)Math.Round(Math.Floor((b - 0x20) / 2.0));
|
||||
bkgData.Background = Constants.PacDataColors[index];
|
||||
if (b % 2 == 1)
|
||||
{
|
||||
bkgData.Background += "_semi";
|
||||
}
|
||||
}
|
||||
else if (b == 0x2d)
|
||||
{
|
||||
bkgData.Background = Constants.ColorTransparent;
|
||||
}
|
||||
else
|
||||
{
|
||||
bkgData.Foreground = Constants.ColorBlack;
|
||||
if (b == 0x2f)
|
||||
{
|
||||
bkgData.Underline = true;
|
||||
}
|
||||
}
|
||||
var chNr = (a < 0x18) ? 1 : 2;
|
||||
var channel = Channels[chNr - 1];
|
||||
channel.SetBkgData(bkgData);
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool HasBackgroundAttributes(int ccData1, int ccData2)
|
||||
{
|
||||
return (((ccData1 == 0x10 || ccData1 == 0x18) && (0x20 <= ccData2 && ccData2 <= 0x2f)) ||
|
||||
((ccData1 == 0x17 || ccData1 == 0x1f) && (0x2d <= ccData2 && ccData2 <= 0x2f)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
167
src/libse/Cea608/CcRow.cs
Normal file
167
src/libse/Cea608/CcRow.cs
Normal file
@ -0,0 +1,167 @@
|
||||
namespace Nikse.SubtitleEdit.Core.Cea608
|
||||
{
|
||||
public class CcRow
|
||||
{
|
||||
public int Position { get; set; }
|
||||
|
||||
public PenState CurrentPenState = new PenState();
|
||||
|
||||
public StyledUnicodeChar[] Chars { get; } =
|
||||
{
|
||||
new StyledUnicodeChar(),
|
||||
new StyledUnicodeChar(),
|
||||
new StyledUnicodeChar(),
|
||||
new StyledUnicodeChar(),
|
||||
new StyledUnicodeChar(),
|
||||
new StyledUnicodeChar(),
|
||||
new StyledUnicodeChar(),
|
||||
new StyledUnicodeChar(),
|
||||
new StyledUnicodeChar(),
|
||||
new StyledUnicodeChar(),
|
||||
new StyledUnicodeChar(),
|
||||
new StyledUnicodeChar(),
|
||||
new StyledUnicodeChar(),
|
||||
new StyledUnicodeChar(),
|
||||
new StyledUnicodeChar(),
|
||||
new StyledUnicodeChar(),
|
||||
new StyledUnicodeChar(),
|
||||
new StyledUnicodeChar(),
|
||||
new StyledUnicodeChar(),
|
||||
new StyledUnicodeChar(),
|
||||
new StyledUnicodeChar(),
|
||||
new StyledUnicodeChar(),
|
||||
new StyledUnicodeChar(),
|
||||
new StyledUnicodeChar(),
|
||||
new StyledUnicodeChar(),
|
||||
new StyledUnicodeChar(),
|
||||
new StyledUnicodeChar(),
|
||||
new StyledUnicodeChar(),
|
||||
new StyledUnicodeChar(),
|
||||
new StyledUnicodeChar(),
|
||||
new StyledUnicodeChar(),
|
||||
new StyledUnicodeChar(),
|
||||
};
|
||||
|
||||
public bool Equals(CcRow other)
|
||||
{
|
||||
for (var i = 0; i < Constants.ScreenColCount; i++)
|
||||
{
|
||||
if (!Chars[i].Equals(other.Chars[i]))
|
||||
{
|
||||
if (!Chars[i].Equals(other.Chars[i]))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Copy(CcRow other)
|
||||
{
|
||||
for (var i = 0; i < Constants.ScreenColCount; i++)
|
||||
{
|
||||
Chars[i].Copy(other.Chars[i]);
|
||||
}
|
||||
}
|
||||
|
||||
public int FirstNonEmpty()
|
||||
{
|
||||
for (var i = 0; i < Constants.ScreenColCount; i++)
|
||||
{
|
||||
if (!Chars[i].IsEmpty())
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
public bool IsEmpty()
|
||||
{
|
||||
for (var i = 0; i < Constants.ScreenColCount; i++)
|
||||
{
|
||||
if (!Chars[i].IsEmpty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void MoveCursor(int relPos)
|
||||
{
|
||||
var newPos = Position + relPos;
|
||||
if (relPos > 1)
|
||||
{
|
||||
for (var i = Position + 1; i < newPos + 1; i++)
|
||||
{
|
||||
Chars[i].SetPenState(CurrentPenState);
|
||||
}
|
||||
}
|
||||
|
||||
Position = newPos;
|
||||
}
|
||||
|
||||
public void BackSpace()
|
||||
{
|
||||
MoveCursor(-1);
|
||||
Chars[Position].SetChar(Constants.EmptyChar, CurrentPenState);
|
||||
}
|
||||
|
||||
public void InsertChar(int b)
|
||||
{
|
||||
if (b >= 0x90)
|
||||
{ // Extended char
|
||||
BackSpace();
|
||||
}
|
||||
|
||||
var ch = GetCharForByte(b);
|
||||
Chars[Position].SetChar(ch, CurrentPenState);
|
||||
MoveCursor(1);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get Unicode Character from CEA-608 byte code.
|
||||
/// </summary>
|
||||
public static string GetCharForByte(int byteValue)
|
||||
{
|
||||
if (Constants.ExtendedCharCodes.TryGetValue(byteValue, out var v))
|
||||
{
|
||||
return char.ConvertFromUtf32(v);
|
||||
}
|
||||
|
||||
return char.ConvertFromUtf32(byteValue);
|
||||
}
|
||||
|
||||
public void ClearFromPos(int startPos)
|
||||
{
|
||||
for (var i = startPos; i < Constants.ScreenColCount; i++)
|
||||
{
|
||||
Chars[i].Reset();
|
||||
}
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
ClearFromPos(0);
|
||||
Position = 0;
|
||||
CurrentPenState.Reset();
|
||||
}
|
||||
|
||||
public void ClearToEndOfRow()
|
||||
{
|
||||
ClearFromPos(Position);
|
||||
}
|
||||
|
||||
public void SetPenStyles(SerializedPenState styles)
|
||||
{
|
||||
CurrentPenState.SetStyles(styles);
|
||||
var currentChar = Chars[Position];
|
||||
currentChar.SetPenState(CurrentPenState);
|
||||
}
|
||||
}
|
||||
}
|
11
src/libse/Cea608/CcStyle.cs
Normal file
11
src/libse/Cea608/CcStyle.cs
Normal file
@ -0,0 +1,11 @@
|
||||
namespace Nikse.SubtitleEdit.Core.Cea608
|
||||
{
|
||||
public class CcStyle
|
||||
{
|
||||
public string Foreground { get; set; }
|
||||
public bool? Underline { get; set; }
|
||||
public bool? Italics { get; set; }
|
||||
public string Background { get; set; }
|
||||
public bool? Flash { get; set; }
|
||||
}
|
||||
}
|
365
src/libse/Cea608/Cea608Channel.cs
Normal file
365
src/libse/Cea608/Cea608Channel.cs
Normal file
@ -0,0 +1,365 @@
|
||||
using System;
|
||||
|
||||
namespace Nikse.SubtitleEdit.Core.Cea608
|
||||
{
|
||||
public class Cea608Channel
|
||||
{
|
||||
public CaptionScreen DisplayedMemory { get; set; }
|
||||
public CaptionScreen NonDisplayedMemory { get; set; }
|
||||
public CaptionScreen LastOutputScreen { get; set; }
|
||||
public CaptionScreen WriteScreen { get; set; }
|
||||
public CcRow CurrentRollUpRow { get; set; }
|
||||
public int? CueStartTime { get; set; }
|
||||
public string Mode { get; set; }
|
||||
|
||||
public int ChannelNumber { get; set; }
|
||||
public CcDataC608Parser Parser { get; set; }
|
||||
|
||||
public Cea608Channel()
|
||||
{
|
||||
DisplayedMemory = new CaptionScreen();
|
||||
NonDisplayedMemory = new CaptionScreen();
|
||||
LastOutputScreen = new CaptionScreen();
|
||||
}
|
||||
|
||||
public Cea608Channel(int chNr, CcDataC608Parser parser)
|
||||
{
|
||||
Parser = parser;
|
||||
ChannelNumber = chNr;
|
||||
|
||||
DisplayedMemory = new CaptionScreen();
|
||||
NonDisplayedMemory = new CaptionScreen();
|
||||
LastOutputScreen = new CaptionScreen();
|
||||
|
||||
CurrentRollUpRow = DisplayedMemory.Rows[Constants.ScreenRowCount - 1];
|
||||
WriteScreen = DisplayedMemory;
|
||||
CueStartTime = null;
|
||||
}
|
||||
|
||||
private void CmdMap(int cmd)
|
||||
{
|
||||
switch (cmd)
|
||||
{
|
||||
case 0x20:
|
||||
cc_RCL();
|
||||
break;
|
||||
case 0x21:
|
||||
cc_BS();
|
||||
break;
|
||||
case 0x22:
|
||||
cc_AOF();
|
||||
break;
|
||||
case 0x23:
|
||||
cc_AON();
|
||||
break;
|
||||
case 0x24:
|
||||
cc_DER();
|
||||
break;
|
||||
case 0x25:
|
||||
cc_RU(2);
|
||||
break;
|
||||
case 0x26:
|
||||
cc_RU(3);
|
||||
break;
|
||||
case 0x27:
|
||||
cc_RU(4);
|
||||
break;
|
||||
case 0x28:
|
||||
cc_FON();
|
||||
break;
|
||||
case 0x29:
|
||||
cc_RDC();
|
||||
break;
|
||||
case 0x2A:
|
||||
cc_TR();
|
||||
break;
|
||||
case 0x2B:
|
||||
cc_RTD();
|
||||
break;
|
||||
case 0x2C:
|
||||
cc_EDM();
|
||||
break;
|
||||
case 0x2D:
|
||||
cc_CR();
|
||||
break;
|
||||
case 0x2E:
|
||||
cc_ENM();
|
||||
break;
|
||||
case 0x2F:
|
||||
cc_EOC();
|
||||
break;
|
||||
default:
|
||||
Console.WriteLine("Command not found");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
Mode = null;
|
||||
DisplayedMemory.Reset();
|
||||
NonDisplayedMemory.Reset();
|
||||
LastOutputScreen.Reset();
|
||||
CurrentRollUpRow = DisplayedMemory.Rows[Constants.ScreenRowCount - 1];
|
||||
WriteScreen = DisplayedMemory;
|
||||
CueStartTime = null;
|
||||
}
|
||||
|
||||
public void SetPac(PacData pacData)
|
||||
{
|
||||
WriteScreen.SetPac(pacData);
|
||||
}
|
||||
|
||||
public void RunCmd(int ccData1, int ccData2)
|
||||
{
|
||||
if (ccData1 == 0x14 || ccData1 == 0x1C)
|
||||
{
|
||||
CmdMap(ccData2);
|
||||
}
|
||||
else
|
||||
{ // a == 0x17 || a == 0x1F
|
||||
cc_TO(ccData2 - 0x20);
|
||||
}
|
||||
}
|
||||
|
||||
public void SetBkgData(SerializedPenState bkgData)
|
||||
{
|
||||
WriteScreen.SetBkgData(bkgData);
|
||||
}
|
||||
|
||||
public void SetMode(string newMode)
|
||||
{
|
||||
if (newMode == Mode)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Mode = newMode;
|
||||
|
||||
if (Mode == "MODE_POP-ON")
|
||||
{
|
||||
WriteScreen = NonDisplayedMemory;
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteScreen = DisplayedMemory;
|
||||
WriteScreen.Reset();
|
||||
}
|
||||
|
||||
if (Mode != "MODE_ROLL-UP")
|
||||
{
|
||||
DisplayedMemory.NumberOfRollUpRows = null;
|
||||
NonDisplayedMemory.NumberOfRollUpRows = null;
|
||||
}
|
||||
|
||||
Mode = newMode;
|
||||
}
|
||||
|
||||
public void InsertChars(int[] chars)
|
||||
{
|
||||
foreach (var ch in chars)
|
||||
{
|
||||
WriteScreen.InsertChar(ch);
|
||||
}
|
||||
|
||||
if (Mode == "MODE_PAINT-ON" || Mode == "MODE_ROLL-UP")
|
||||
{
|
||||
OutputDataUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resume Caption Loading (switch mode to Pop On).
|
||||
/// </summary>
|
||||
public void cc_RCL()
|
||||
{
|
||||
SetMode("MODE_POP-ON");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// BackSpace.
|
||||
/// </summary>
|
||||
public void cc_BS()
|
||||
{
|
||||
if (Mode == "MODE_TEXT")
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
WriteScreen.BackSpace();
|
||||
if (WriteScreen == DisplayedMemory)
|
||||
{
|
||||
OutputDataUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reserved (formerly Alarm Off).
|
||||
/// </summary>
|
||||
public void cc_AOF()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reserved (formerly Alarm On).
|
||||
/// </summary>
|
||||
public void cc_AON()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Delete to End of Row.
|
||||
/// </summary>
|
||||
public void cc_DER()
|
||||
{
|
||||
WriteScreen.ClearToEndOfRow();
|
||||
OutputDataUpdate();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Roll-Up Captions-2,3,or 4 Rows.
|
||||
/// </summary>
|
||||
public void cc_RU(int nrRows)
|
||||
{
|
||||
WriteScreen = DisplayedMemory;
|
||||
SetMode("MODE_ROLL-UP");
|
||||
WriteScreen.SetRollUpRows(nrRows);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Flash On.
|
||||
/// </summary>
|
||||
public void cc_FON()
|
||||
{
|
||||
WriteScreen.SetPen(new PacData { Flash = true });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resume Direct Captioning (switch mode to PaintOn).
|
||||
/// </summary>
|
||||
public void cc_RDC()
|
||||
{
|
||||
SetMode("MODE_PAINT-ON");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Text Restart in text mode (not supported, however).
|
||||
/// </summary>
|
||||
public void cc_TR()
|
||||
{
|
||||
SetMode("MODE_TEXT");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resume Text Display in Text mode (not supported, however)
|
||||
/// </summary>
|
||||
public void cc_RTD()
|
||||
{
|
||||
SetMode("MODE_TEXT");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Erase Displayed Memory.
|
||||
/// </summary>
|
||||
public void cc_EDM()
|
||||
{
|
||||
DisplayedMemory.Reset();
|
||||
OutputDataUpdate();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Carriage Return.
|
||||
/// </summary>
|
||||
public void cc_CR()
|
||||
{
|
||||
WriteScreen.RollUp();
|
||||
OutputDataUpdate(true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Erase Non-Displayed Memory.
|
||||
/// </summary>
|
||||
public void cc_ENM()
|
||||
{
|
||||
NonDisplayedMemory.Reset();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// End of Caption (Flip Memories).
|
||||
/// </summary>
|
||||
public void cc_EOC()
|
||||
{
|
||||
if (Mode == "MODE_POP-ON")
|
||||
{
|
||||
(DisplayedMemory, NonDisplayedMemory) = (NonDisplayedMemory, DisplayedMemory);
|
||||
WriteScreen = NonDisplayedMemory;
|
||||
}
|
||||
|
||||
OutputDataUpdate();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tab Offset 1,2, or 3 columns
|
||||
/// </summary>
|
||||
public void cc_TO(int nrCols)
|
||||
{
|
||||
WriteScreen.MoveCursor(nrCols);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse MIDROW command
|
||||
/// </summary>
|
||||
public void cc_MidRow(int secondByte)
|
||||
{
|
||||
//
|
||||
var styles = new SerializedPenState { Flash = false };
|
||||
styles.Underline = secondByte % 2 == 1;
|
||||
styles.Italics = secondByte >= 0x2e;
|
||||
if (!styles.Italics.Value)
|
||||
{
|
||||
var colorIndex = (int)Math.Floor(secondByte / 2.0) - 0x10;
|
||||
styles.Foreground = Constants.PacDataColors[colorIndex];
|
||||
}
|
||||
else
|
||||
{
|
||||
styles.Foreground = Constants.ColorWhite;
|
||||
}
|
||||
|
||||
WriteScreen.SetPen(styles);
|
||||
}
|
||||
|
||||
public void OutputDataUpdate(bool rolling = false)
|
||||
{
|
||||
var t = Parser.LastTime;
|
||||
if (t == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (CueStartTime == null && !DisplayedMemory.IsEmpty())
|
||||
{ // Start of a new cue
|
||||
CueStartTime = t;
|
||||
}
|
||||
else if (!DisplayedMemory.Equals(LastOutputScreen))
|
||||
{
|
||||
|
||||
if (CueStartTime != null && !LastOutputScreen.IsEmpty())
|
||||
{
|
||||
Parser.DisplayScreen?.Invoke(new DataOutput
|
||||
{
|
||||
Channel = ChannelNumber,
|
||||
Roll = rolling,
|
||||
Start = CueStartTime ?? 0,
|
||||
End = t ?? 0,
|
||||
Screen = LastOutputScreen.Serialize(),
|
||||
});
|
||||
}
|
||||
|
||||
CueStartTime = DisplayedMemory.IsEmpty() ? null : t;
|
||||
|
||||
}
|
||||
|
||||
LastOutputScreen.Copy(DisplayedMemory);
|
||||
}
|
||||
}
|
||||
}
|
161
src/libse/Cea608/Constants.cs
Normal file
161
src/libse/Cea608/Constants.cs
Normal file
@ -0,0 +1,161 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Nikse.SubtitleEdit.Core.Cea608
|
||||
{
|
||||
public static class Constants
|
||||
{
|
||||
public const string ColorWhite = "white";
|
||||
public const string ColorGreen = "green";
|
||||
public const string ColorBlue = "blue";
|
||||
public const string ColorCyan = "cyan";
|
||||
public const string ColorRed = "red";
|
||||
public const string ColorYellow = "yellow";
|
||||
public const string ColorMagenta = "magenta";
|
||||
public const string ColorBlack = "black";
|
||||
public const string ColorTransparent = "transparent";
|
||||
|
||||
public const string EmptyChar = " ";
|
||||
|
||||
public static string[] PacDataColors = new string[]
|
||||
{
|
||||
ColorWhite,
|
||||
ColorGreen,
|
||||
ColorBlue,
|
||||
ColorCyan,
|
||||
ColorRed,
|
||||
ColorYellow,
|
||||
ColorMagenta,
|
||||
ColorBlack,
|
||||
ColorTransparent
|
||||
};
|
||||
|
||||
public const int ScreenRowCount = 15;
|
||||
public const int ScreenColCount = 32;
|
||||
|
||||
|
||||
public static Dictionary<int, int> ExtendedCharCodes = new Dictionary<int, int>
|
||||
{
|
||||
{ 0x2a, 0xe1 }, // lowercase a, acute accent
|
||||
{ 0x5c, 0xe9 }, // lowercase e, acute accent
|
||||
{ 0x5e, 0xed }, // lowercase i, acute accent
|
||||
{ 0x5f, 0xf3 }, // lowercase o, acute accent
|
||||
{ 0x60, 0xfa }, // lowercase u, acute accent
|
||||
{ 0x7b, 0xe7 }, // lowercase c with cedilla
|
||||
{ 0x7c, 0xf7 }, // division symbol
|
||||
{ 0x7d, 0xd1 }, // uppercase N tilde
|
||||
{ 0x7e, 0xf1 }, // lowercase n tilde
|
||||
{ 0x7f, 0x2588 }, // Full block
|
||||
// THIS BLOCK INCLUDES THE 16 EXTENDED (TWO-BYTE) LINE 21 CHARACTERS
|
||||
// THAT COME FROM HI BYTE=0x11 AND LOW BETWEEN 0x30 AND 0x3F
|
||||
// THIS MEANS THAT \x50 MUST BE ADDED TO THE VALUES
|
||||
{ 0x80, 0xae }, // Registered symbol (R)
|
||||
{ 0x81, 0xb0 }, // degree sign
|
||||
{ 0x82, 0xbd }, // 1/2 symbol
|
||||
{ 0x83, 0xbf }, // Inverted (open) question mark
|
||||
{ 0x84, 0x2122 }, // Trademark symbol (TM)
|
||||
{ 0x85, 0xa2 }, // Cents symbol
|
||||
{ 0x86, 0xa3 }, // Pounds sterling
|
||||
{ 0x87, 0x266a }, // Music 8'th note
|
||||
{ 0x88, 0xe0 }, // lowercase a, grave accent
|
||||
{ 0x89, 0x20 }, // transparent space (regular)
|
||||
{ 0x8a, 0xe8 }, // lowercase e, grave accent
|
||||
{ 0x8b, 0xe2 }, // lowercase a, circumflex accent
|
||||
{ 0x8c, 0xea }, // lowercase e, circumflex accent
|
||||
{ 0x8d, 0xee }, // lowercase i, circumflex accent
|
||||
{ 0x8e, 0xf4 }, // lowercase o, circumflex accent
|
||||
{ 0x8f, 0xfb }, // lowercase u, circumflex accent
|
||||
// THIS BLOCK INCLUDES THE 32 EXTENDED (TWO-BYTE) LINE 21 CHARACTERS
|
||||
// THAT COME FROM HI BYTE=0x12 AND LOW BETWEEN 0x20 AND 0x3F
|
||||
{ 0x90, 0xc1 }, // capital letter A with acute
|
||||
{ 0x91, 0xc9 }, // capital letter E with acute
|
||||
{ 0x92, 0xd3 }, // capital letter O with acute
|
||||
{ 0x93, 0xda }, // capital letter U with acute
|
||||
{ 0x94, 0xdc }, // capital letter U with diaresis
|
||||
{ 0x95, 0xfc }, // lowercase letter U with diaeresis
|
||||
{ 0x96, 0x2018 }, // opening single quote
|
||||
{ 0x97, 0xa1 }, // inverted exclamation mark
|
||||
{ 0x98, 0x2a }, // asterisk
|
||||
{ 0x99, 0x2019 }, // closing single quote
|
||||
{ 0x9a, 0x2501 }, // box drawings heavy horizontal
|
||||
{ 0x9b, 0xa9 }, // copyright sign
|
||||
{ 0x9c, 0x2120 }, // Service mark
|
||||
{ 0x9d, 0x2022 }, // (round) bullet
|
||||
{ 0x9e, 0x201c }, // Left double quotation mark
|
||||
{ 0x9f, 0x201d }, // Right double quotation mark
|
||||
{ 0xa0, 0xc0 }, // uppercase A, grave accent
|
||||
{ 0xa1, 0xc2 }, // uppercase A, circumflex
|
||||
{ 0xa2, 0xc7 }, // uppercase C with cedilla
|
||||
{ 0xa3, 0xc8 }, // uppercase E, grave accent
|
||||
{ 0xa4, 0xca }, // uppercase E, circumflex
|
||||
{ 0xa5, 0xcb }, // capital letter E with diaresis
|
||||
{ 0xa6, 0xeb }, // lowercase letter e with diaresis
|
||||
{ 0xa7, 0xce }, // uppercase I, circumflex
|
||||
{ 0xa8, 0xcf }, // uppercase I, with diaresis
|
||||
{ 0xa9, 0xef }, // lowercase i, with diaresis
|
||||
{ 0xaa, 0xd4 }, // uppercase O, circumflex
|
||||
{ 0xab, 0xd9 }, // uppercase U, grave accent
|
||||
{ 0xac, 0xf9 }, // lowercase u, grave accent
|
||||
{ 0xad, 0xdb }, // uppercase U, circumflex
|
||||
{ 0xae, 0xab }, // left-pointing double angle quotation mark
|
||||
{ 0xaf, 0xbb }, // right-pointing double angle quotation mark
|
||||
// THIS BLOCK INCLUDES THE 32 EXTENDED (TWO-BYTE) LINE 21 CHARACTERS
|
||||
// THAT COME FROM HI BYTE=0x13 AND LOW BETWEEN 0x20 AND 0x3F
|
||||
{ 0xb0, 0xc3 }, // Uppercase A, tilde
|
||||
{ 0xb1, 0xe3 }, // Lowercase a, tilde
|
||||
{ 0xb2, 0xcd }, // Uppercase I, acute accent
|
||||
{ 0xb3, 0xcc }, // Uppercase I, grave accent
|
||||
{ 0xb4, 0xec }, // Lowercase i, grave accent
|
||||
{ 0xb5, 0xd2 }, // Uppercase O, grave accent
|
||||
{ 0xb6, 0xf2 }, // Lowercase o, grave accent
|
||||
{ 0xb7, 0xd5 }, // Uppercase O, tilde
|
||||
{ 0xb8, 0xf5 }, // Lowercase o, tilde
|
||||
{ 0xb9, 0x7b }, // Open curly brace
|
||||
{ 0xba, 0x7d }, // Closing curly brace
|
||||
{ 0xbb, 0x5c }, // Backslash
|
||||
{ 0xbc, 0x5e }, // Caret
|
||||
{ 0xbd, 0x5f }, // Underscore
|
||||
{ 0xbe, 0x7c }, // Pipe (vertical line)
|
||||
{ 0xbf, 0x223c }, // Tilde operator
|
||||
{ 0xc0, 0xc4 }, // Uppercase A, umlaut
|
||||
{ 0xc1, 0xe4 }, // Lowercase A, umlaut
|
||||
{ 0xc2, 0xd6 }, // Uppercase O, umlaut
|
||||
{ 0xc3, 0xf6 }, // Lowercase o, umlaut
|
||||
{ 0xc4, 0xdf }, // Esszett (sharp S)
|
||||
{ 0xc5, 0xa5 }, // Yen symbol
|
||||
{ 0xc6, 0xa4 }, // Generic currency sign
|
||||
{ 0xc7, 0x2503 }, // Box drawings heavy vertical
|
||||
{ 0xc8, 0xc5 }, // Uppercase A, ring
|
||||
{ 0xc9, 0xe5 }, // Lowercase A, ring
|
||||
{ 0xca, 0xd8 }, // Uppercase O, stroke
|
||||
{ 0xcb, 0xf8 }, // Lowercase o, strok
|
||||
{ 0xcc, 0x250f }, // Box drawings heavy down and right
|
||||
{ 0xcd, 0x2513 }, // Box drawings heavy down and left
|
||||
{ 0xce, 0x2517 }, // Box drawings heavy up and right
|
||||
{ 0xcf, 0x251b } // Box drawings heavy up and left
|
||||
};
|
||||
|
||||
public static Dictionary<int, int> Channel1RowsMap = new Dictionary<int, int>
|
||||
{
|
||||
{ 0x11, 1 },
|
||||
{ 0x12, 3 },
|
||||
{ 0x15, 5 },
|
||||
{ 0x16, 7 },
|
||||
{ 0x17, 9 },
|
||||
{ 0x10, 11 },
|
||||
{ 0x13, 12 },
|
||||
{ 0x14, 14 }
|
||||
};
|
||||
|
||||
public static Dictionary<int, int> Channel2RowsMap = new Dictionary<int, int>
|
||||
{
|
||||
{ 0x19, 1 },
|
||||
{ 0x1A, 3 },
|
||||
{ 0x1D, 5 },
|
||||
{ 0x1E, 7 },
|
||||
{ 0x1F, 9 },
|
||||
{ 0x18, 11 },
|
||||
{ 0x1B, 12 },
|
||||
{ 0x1C, 14 }
|
||||
};
|
||||
}
|
||||
}
|
11
src/libse/Cea608/DataOutput.cs
Normal file
11
src/libse/Cea608/DataOutput.cs
Normal file
@ -0,0 +1,11 @@
|
||||
namespace Nikse.SubtitleEdit.Core.Cea608
|
||||
{
|
||||
public class DataOutput
|
||||
{
|
||||
public int Channel { get; set; }
|
||||
public bool Roll { get; set; }
|
||||
public int End { get; set; }
|
||||
public int Start { get; set; }
|
||||
public SerializedRow[] Screen { get; set; }
|
||||
}
|
||||
}
|
9
src/libse/Cea608/PacData.cs
Normal file
9
src/libse/Cea608/PacData.cs
Normal file
@ -0,0 +1,9 @@
|
||||
namespace Nikse.SubtitleEdit.Core.Cea608
|
||||
{
|
||||
public class PacData: SerializedPenState
|
||||
{
|
||||
public int Row { get; set; }
|
||||
public string Color { get; set; }
|
||||
public int? Indent { get; set; }
|
||||
}
|
||||
}
|
93
src/libse/Cea608/PenState.cs
Normal file
93
src/libse/Cea608/PenState.cs
Normal file
@ -0,0 +1,93 @@
|
||||
namespace Nikse.SubtitleEdit.Core.Cea608
|
||||
{
|
||||
public class PenState
|
||||
{
|
||||
public string Foreground { get; set; } = Constants.ColorWhite;
|
||||
public bool Underline;
|
||||
public bool Italics { get; set; }
|
||||
public string Background { get; set; } = Constants.ColorBlack;
|
||||
public bool Flash { get; set; }
|
||||
|
||||
public PenState()
|
||||
{
|
||||
}
|
||||
|
||||
public PenState(string foreground, bool underline, bool italics, string background, bool flash1)
|
||||
{
|
||||
Foreground = foreground;
|
||||
Underline = underline;
|
||||
Italics = italics;
|
||||
Background = background;
|
||||
Flash = flash1;
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
Foreground = Constants.ColorWhite;
|
||||
Underline = false;
|
||||
Italics = false;
|
||||
Background = Constants.ColorBlack;
|
||||
Flash = false;
|
||||
}
|
||||
|
||||
public CcStyle Serialize()
|
||||
{
|
||||
return new CcStyle
|
||||
{
|
||||
|
||||
Foreground = Foreground,
|
||||
Underline = Underline,
|
||||
Italics = Italics,
|
||||
Flash = Flash,
|
||||
Background = Background
|
||||
};
|
||||
}
|
||||
|
||||
public void Copy(PenState newPenState)
|
||||
{
|
||||
Foreground = newPenState.Foreground;
|
||||
Underline = newPenState.Underline;
|
||||
Italics = newPenState.Italics;
|
||||
Background = newPenState.Background;
|
||||
Flash = newPenState.Flash;
|
||||
}
|
||||
|
||||
public bool Equals(PenState other)
|
||||
{
|
||||
return Foreground == other.Foreground &&
|
||||
Underline == other.Underline &&
|
||||
Italics == other.Italics &&
|
||||
Background == other.Background &&
|
||||
Flash == other.Flash;
|
||||
}
|
||||
|
||||
public bool IsDefault()
|
||||
{
|
||||
return Foreground == Constants.ColorWhite && !Underline && !Italics && Background == Constants.ColorBlack && !Flash;
|
||||
}
|
||||
|
||||
public void SetStyles(SerializedPenState styles)
|
||||
{
|
||||
if (styles.Foreground != null)
|
||||
{
|
||||
Foreground = styles.Foreground;
|
||||
}
|
||||
if (styles.Underline != null)
|
||||
{
|
||||
Underline = styles.Underline.Value;
|
||||
}
|
||||
if (styles.Background != null)
|
||||
{
|
||||
Background = styles.Background;
|
||||
}
|
||||
if (styles.Flash != null)
|
||||
{
|
||||
Flash = styles.Flash.Value;
|
||||
}
|
||||
if (styles.Italics != null)
|
||||
{
|
||||
Italics = styles.Italics.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
11
src/libse/Cea608/SerializedPenState.cs
Normal file
11
src/libse/Cea608/SerializedPenState.cs
Normal file
@ -0,0 +1,11 @@
|
||||
namespace Nikse.SubtitleEdit.Core.Cea608
|
||||
{
|
||||
public class SerializedPenState
|
||||
{
|
||||
public string Foreground { get; set; }
|
||||
public bool? Underline { get; set; }
|
||||
public bool? Italics { get; set; }
|
||||
public string Background { get; set; }
|
||||
public bool? Flash { get; set; }
|
||||
}
|
||||
}
|
15
src/libse/Cea608/SerializedRow.cs
Normal file
15
src/libse/Cea608/SerializedRow.cs
Normal file
@ -0,0 +1,15 @@
|
||||
namespace Nikse.SubtitleEdit.Core.Cea608
|
||||
{
|
||||
public class SerializedRow
|
||||
{
|
||||
public int Row { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Column indentation.
|
||||
/// </summary>
|
||||
public int Position { get; set; }
|
||||
|
||||
public CcStyle Style { get; set; }
|
||||
public SerializedStyledUnicodeChar[] Columns { get; set; }
|
||||
}
|
||||
}
|
8
src/libse/Cea608/SerializedStyledUnicodeChar.cs
Normal file
8
src/libse/Cea608/SerializedStyledUnicodeChar.cs
Normal file
@ -0,0 +1,8 @@
|
||||
namespace Nikse.SubtitleEdit.Core.Cea608
|
||||
{
|
||||
public class SerializedStyledUnicodeChar
|
||||
{
|
||||
public CcStyle Style { get; set; }
|
||||
public string Character { get; set; }
|
||||
}
|
||||
}
|
52
src/libse/Cea608/StyledUnicodeChar.cs
Normal file
52
src/libse/Cea608/StyledUnicodeChar.cs
Normal file
@ -0,0 +1,52 @@
|
||||
namespace Nikse.SubtitleEdit.Core.Cea608
|
||||
{
|
||||
public class StyledUnicodeChar
|
||||
{
|
||||
public PenState PenState { get; set; }
|
||||
|
||||
public string Uchar { get; set; } = Constants.EmptyChar;
|
||||
public string Foreground { get; set; }
|
||||
public bool? Underline { get; set; }
|
||||
public bool? Italics { get; set; }
|
||||
public string Background { get; set; }
|
||||
public bool? Flash { get; set; }
|
||||
|
||||
public StyledUnicodeChar()
|
||||
{
|
||||
PenState = new PenState(null, false, false, null, false);
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
Uchar = Constants.EmptyChar;
|
||||
PenState.Reset();
|
||||
}
|
||||
|
||||
public void SetChar(string uchar, PenState newPenState)
|
||||
{
|
||||
Uchar = uchar;
|
||||
PenState.Copy(newPenState);
|
||||
}
|
||||
|
||||
public void SetPenState(PenState newPenState)
|
||||
{
|
||||
PenState.Copy(newPenState);
|
||||
}
|
||||
|
||||
public bool Equals(StyledUnicodeChar other)
|
||||
{
|
||||
return Uchar == other.Uchar && PenState.Equals(other.PenState);
|
||||
}
|
||||
|
||||
public void Copy(StyledUnicodeChar newChar)
|
||||
{
|
||||
Uchar = newChar.Uchar;
|
||||
PenState.Copy(newChar.PenState);
|
||||
}
|
||||
|
||||
public bool IsEmpty()
|
||||
{
|
||||
return Uchar == Constants.EmptyChar && PenState.IsDefault();
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user