242 lines
7.9 KiB
C#
242 lines
7.9 KiB
C#
using PrintService.Models;
|
|
using System.Text;
|
|
using System.Text.RegularExpressions;
|
|
|
|
namespace PrintService.Services;
|
|
|
|
/// <summary>
|
|
/// Handles content transformations from Rust CLI (cgwprint) logic
|
|
/// </summary>
|
|
public class ContentTransformer
|
|
{
|
|
private readonly ILogger<ContentTransformer> _logger;
|
|
|
|
public ContentTransformer(ILogger<ContentTransformer> logger)
|
|
{
|
|
_logger = logger;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Transform document content according to configuration
|
|
/// </summary>
|
|
public TransformedDocument TransformContent(string content, DocumentTypeConfig config, string? orderNumber = null)
|
|
{
|
|
// Step 1: Normalize font codes
|
|
content = NormalizeFontCodes(content);
|
|
|
|
// Step 2: Order number manipulation (if order number provided)
|
|
if (!string.IsNullOrEmpty(orderNumber))
|
|
{
|
|
content = ManipulateOrderNumber(content, orderNumber, config);
|
|
}
|
|
|
|
// Step 3: Parse font codes to identify bold/normal segments
|
|
var lines = content.Split(new[] { '\r', '\n' }, StringSplitOptions.None);
|
|
|
|
// Step 4: Apply row trim (modifies line content)
|
|
lines = ApplyRowTrim(lines, config.RowTrim);
|
|
|
|
// Step 5: Parse lines into segments with font styling
|
|
var styledLines = ParseStyledLines(lines);
|
|
|
|
return new TransformedDocument
|
|
{
|
|
Lines = styledLines,
|
|
RowShifts = config.RowShift,
|
|
LinePadding = config.LinePadding
|
|
};
|
|
}
|
|
|
|
/// <summary>
|
|
/// Step 1: Normalize font codes (pre-processing)
|
|
/// </summary>
|
|
private string NormalizeFontCodes(string content)
|
|
{
|
|
// Prefix with normal font at start
|
|
content = "\x1Bw0" + content;
|
|
|
|
// Normalize uppercase W to lowercase w
|
|
content = content.Replace("\x1BW1", "\x1Bw1");
|
|
content = content.Replace("\x1BW0", "\x1Bw0");
|
|
|
|
// Deduplicate consecutive bold sequences
|
|
content = Regex.Replace(content, @"(\x1Bw1)+", "\x1Bw1");
|
|
|
|
// Deduplicate consecutive normal sequences
|
|
content = Regex.Replace(content, @"(\x1Bw0)+", "\x1Bw0");
|
|
|
|
return content;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Step 2: Order number manipulation
|
|
/// </summary>
|
|
private string ManipulateOrderNumber(string content, string orderNumber, DocumentTypeConfig config)
|
|
{
|
|
var orderPattern = $"Order #: {orderNumber}";
|
|
|
|
// Only ONE operation executes based on configuration flags
|
|
if (config.RemoveOrderNumber)
|
|
{
|
|
// Replace entire "Order #: 12345" with spaces
|
|
var replacement = new string(' ', orderPattern.Length);
|
|
content = content.Replace(orderPattern, replacement);
|
|
_logger.LogDebug("Removed order number completely: {OrderNumber}", orderNumber);
|
|
}
|
|
else if (config.RemoveOrderNumberLabel)
|
|
{
|
|
// Replace "Order #: " with spaces, keep number and make it bold
|
|
var labelLength = "Order #: ".Length;
|
|
var spaces = new string(' ', labelLength);
|
|
var replacement = $"{spaces}\x1Bw1{orderNumber}\x1Bw0";
|
|
content = content.Replace(orderPattern, replacement);
|
|
_logger.LogDebug("Removed order number label, kept bold number: {OrderNumber}", orderNumber);
|
|
}
|
|
else if (!string.IsNullOrEmpty(config.IndentOrderNumber))
|
|
{
|
|
// Find and indent the order number (assumes it's already bold)
|
|
var boldPattern = $@"\x1Bw1{Regex.Escape(orderNumber)}\x1Bw0";
|
|
content = Regex.Replace(content, boldPattern, $"{config.IndentOrderNumber}\x1Bw1{orderNumber}\x1Bw0");
|
|
_logger.LogDebug("Indented order number: {OrderNumber}", orderNumber);
|
|
}
|
|
|
|
return content;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Step 3: Apply row trim (horizontal character removal)
|
|
/// </summary>
|
|
private string[] ApplyRowTrim(string[] lines, Dictionary<int, RowTrimConfig> rowTrim)
|
|
{
|
|
if (rowTrim.Count == 0)
|
|
return lines;
|
|
|
|
var result = new string[lines.Length];
|
|
|
|
for (int i = 0; i < lines.Length; i++)
|
|
{
|
|
if (rowTrim.TryGetValue(i, out var trim))
|
|
{
|
|
var line = lines[i];
|
|
|
|
if (trim.Start >= 0 && trim.End <= line.Length && trim.Start < trim.End)
|
|
{
|
|
// Remove characters from Start to End
|
|
result[i] = line.Substring(0, trim.Start) + line.Substring(trim.End);
|
|
_logger.LogDebug("Trimmed line {LineNum}: removed chars {Start}-{End}", i, trim.Start, trim.End);
|
|
}
|
|
else
|
|
{
|
|
result[i] = line;
|
|
_logger.LogWarning("Invalid row trim config for line {LineNum}: Start={Start}, End={End}, LineLength={Length}",
|
|
i, trim.Start, trim.End, line.Length);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
result[i] = lines[i];
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Step 4: Parse lines into segments with font styling
|
|
/// </summary>
|
|
private List<StyledLine> ParseStyledLines(string[] lines)
|
|
{
|
|
var styledLines = new List<StyledLine>();
|
|
|
|
foreach (var line in lines)
|
|
{
|
|
var segments = new List<TextSegment>();
|
|
var currentText = new StringBuilder();
|
|
var currentStyle = FontStyle.Regular;
|
|
|
|
for (int i = 0; i < line.Length; i++)
|
|
{
|
|
// Check for font code escape sequence
|
|
if (i + 2 < line.Length && line[i] == '\x1B' && line[i + 1] == 'w')
|
|
{
|
|
// Save current segment if any
|
|
if (currentText.Length > 0)
|
|
{
|
|
segments.Add(new TextSegment
|
|
{
|
|
Text = currentText.ToString(),
|
|
Style = currentStyle
|
|
});
|
|
currentText.Clear();
|
|
}
|
|
|
|
// Parse font code
|
|
char code = line[i + 2];
|
|
if (code == '1')
|
|
{
|
|
currentStyle = FontStyle.Bold;
|
|
}
|
|
else if (code == '0')
|
|
{
|
|
currentStyle = FontStyle.Regular;
|
|
}
|
|
|
|
// Skip the escape sequence
|
|
i += 2;
|
|
}
|
|
else
|
|
{
|
|
currentText.Append(line[i]);
|
|
}
|
|
}
|
|
|
|
// Add final segment
|
|
if (currentText.Length > 0 || segments.Count == 0)
|
|
{
|
|
segments.Add(new TextSegment
|
|
{
|
|
Text = currentText.ToString(),
|
|
Style = currentStyle
|
|
});
|
|
}
|
|
|
|
styledLines.Add(new StyledLine { Segments = segments });
|
|
}
|
|
|
|
return styledLines;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Transformed document with styled lines and layout adjustments
|
|
/// </summary>
|
|
public class TransformedDocument
|
|
{
|
|
public List<StyledLine> Lines { get; set; } = new();
|
|
public Dictionary<int, int> RowShifts { get; set; } = new();
|
|
public int LinePadding { get; set; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// A line with styled text segments
|
|
/// </summary>
|
|
public class StyledLine
|
|
{
|
|
public List<TextSegment> Segments { get; set; } = new();
|
|
}
|
|
|
|
/// <summary>
|
|
/// A text segment with font styling
|
|
/// </summary>
|
|
public class TextSegment
|
|
{
|
|
public string Text { get; set; } = string.Empty;
|
|
public FontStyle Style { get; set; } = FontStyle.Regular;
|
|
}
|
|
|
|
public enum FontStyle
|
|
{
|
|
Regular,
|
|
Bold
|
|
}
|