From 210f3614eaf53cf454d7fc481030049167746265 Mon Sep 17 00:00:00 2001 From: geht <2947093423@qq.com> Date: Wed, 13 May 2026 14:06:13 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E6=9D=A1=E7=A0=81=E5=85=83?= =?UTF-8?q?=E7=B4=A0=E7=9A=84=E5=A1=AB=E5=85=85=E9=80=89=E9=A1=B9=EF=BC=8C?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E6=97=A0=E6=8D=9F=E5=A1=AB=E6=BB=A1=E5=A4=96?= =?UTF-8?q?=E5=B1=82=E5=AE=B9=E5=99=A8=E7=9A=84=E9=85=8D=E7=BD=AE=E3=80=82?= =?UTF-8?q?=E6=9B=B4=E6=96=B0=E7=9B=B8=E5=85=B3=E6=B8=B2=E6=9F=93=E9=80=BB?= =?UTF-8?q?=E8=BE=91=E5=92=8C=E6=8E=A5=E5=8F=A3=EF=BC=8C=E6=8F=90=E5=8D=87?= =?UTF-8?q?=E6=9D=A1=E7=A0=81=E6=98=BE=E7=A4=BA=E7=9A=84=E7=81=B5=E6=B4=BB?= =?UTF-8?q?=E6=80=A7=E5=92=8C=E7=94=A8=E6=88=B7=E4=BD=93=E9=AA=8C=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../native/components/PropertiesPanel.vue | 7 + .../components/elements/BarcodeElement.vue | 2 + .../template/native/core/barcodeRenderer.ts | 12 +- .../template/native/core/printRenderer.ts | 1 + .../views/print/template/native/core/types.ts | 9 + .../Service/Print/NativePrintRenderService.cs | 259 +++++++++++++----- 6 files changed, 221 insertions(+), 69 deletions(-) diff --git a/jeecgboot-vue3/src/views/print/template/native/components/PropertiesPanel.vue b/jeecgboot-vue3/src/views/print/template/native/components/PropertiesPanel.vue index c14f03c..a8f5caa 100644 --- a/jeecgboot-vue3/src/views/print/template/native/components/PropertiesPanel.vue +++ b/jeecgboot-vue3/src/views/print/template/native/components/PropertiesPanel.vue @@ -225,6 +225,13 @@ un-checked-children="隐藏条码下文字" @update:checked="updateField('displayValue', $event)" /> +
,让浏览器把字符间距自动拉伸到条码宽度 if (opts.displayValue && opts.justifyText) { applyJustifyTextAlign(svg); diff --git a/jeecgboot-vue3/src/views/print/template/native/core/printRenderer.ts b/jeecgboot-vue3/src/views/print/template/native/core/printRenderer.ts index 7d9f9ea..d6086bd 100644 --- a/jeecgboot-vue3/src/views/print/template/native/core/printRenderer.ts +++ b/jeecgboot-vue3/src/views/print/template/native/core/printRenderer.ts @@ -558,6 +558,7 @@ export async function renderNativePrintHtml(schema: NativeTemplateSchema, data: lineWidth: (item as any).lineWidth, barHeight: (item as any).barHeight, textAlign: (item as any).textAlign, + fillCell: (item as any).fillCell === true, }); if (svgStr) { // 让 SVG 100% 充满定位 div;preserveAspectRatio 在 SVG 内部已设为 xMidYMid meet, diff --git a/jeecgboot-vue3/src/views/print/template/native/core/types.ts b/jeecgboot-vue3/src/views/print/template/native/core/types.ts index 937f783..62278b5 100644 --- a/jeecgboot-vue3/src/views/print/template/native/core/types.ts +++ b/jeecgboot-vue3/src/views/print/template/native/core/types.ts @@ -73,6 +73,15 @@ export interface NativeImageElement extends NativeElementBase { export interface NativeCodeElement extends NativeElementBase { type: 'qrcode' | 'barcode'; value: string; + /** + * 是否无损铺满整个编辑框(条码): + * - false / undefined(默认):preserveAspectRatio="xMidYMid meet",保比例居中, + * 扁容器中上下会留白,但条宽比例严格 1:1,扫码兼容性最佳。 + * - true:preserveAspectRatio="none",SVG 矢量按容器宽高拉伸铺满; + * 放大缩小不会失真(仍是矢量),但条宽/条高比会随容器变化, + * 适合需要"卡片整格塞满"的小票/标签场景。 + */ + fillCell?: boolean; } export interface NativeTableColumn { diff --git a/yy-admin-master/YY.Admin.Services/Service/Print/NativePrintRenderService.cs b/yy-admin-master/YY.Admin.Services/Service/Print/NativePrintRenderService.cs index 99dffbc..25aca51 100644 --- a/yy-admin-master/YY.Admin.Services/Service/Print/NativePrintRenderService.cs +++ b/yy-admin-master/YY.Admin.Services/Service/Print/NativePrintRenderService.cs @@ -345,8 +345,12 @@ public static class NativePrintRenderService var lineWidthPx = Math.Max(1, (int)Math.Round(el["lineWidth"]?.GetValue() ?? 2d)); var barHeightPx = Math.Max(10, (int)Math.Round(el["barHeight"]?.GetValue() ?? 60d)); var barFontSize = Math.Max(8, (int)Math.Round(el["fontSize"]?.GetValue() ?? 14d)); + // 与后端对齐:优先读元素级 fillCell;兼容旧模板的 style.fillCell。 + // 均未配置时默认 false(保比例居中)。 + var fillCellNode = el["fillCell"] ?? el["style"]?["fillCell"]; + var fillCell = string.Equals(ReadAsString(fillCellNode, "false"), "true", StringComparison.OrdinalIgnoreCase); - var inner = BuildBarcodeSvgInner(value, format, displayValue, textAlign, lineWidthPx, barHeightPx, barFontSize); + var inner = BuildBarcodeSvgInner(value, format, displayValue, textAlign, lineWidthPx, barHeightPx, barFontSize, fillCell); var wrapStyle = "display:flex;align-items:center;justify-content:center;overflow:hidden;"; @@ -426,38 +430,53 @@ public static class NativePrintRenderService } /// - /// 把 ZXing 输出的 SVG 转换为"由外层 CSS 控制尺寸 + 保持原始条宽比例"的形式: - /// 1) 若原 SVG 无 viewBox,用原 width/height 派生(让 preserveAspectRatio 生效); - /// 2) 删除根 svg 节点的 width/height 属性(移交给 CSS); - /// 3) 强制 preserveAspectRatio="xMidYMid meet"(与 web 端 jsbarcode 一致); - /// 4) 重新挂上 width="100%" height="100%",确保 div 100% 铺满。 - /// 防护层:若 ZXing 输出的 SVG 已带 viewBox,直接复用;否则从 width/height 推导。 + /// 把 ZXing 输出的 SVG 转换为"由外层 CSS 控制尺寸 + 可配置铺满策略"的形式: + /// 1) 强制清除根 svg 节点上原有的 width / height / viewBox / preserveAspectRatio 属性 + /// (不再依赖 ZXing 自身输出格式,无论它用单引号、双引号、无引号都覆写); + /// 2) 用调用方传入的 viewBoxWidth × viewBoxHeight 作为 viewBox,保证容器内 + /// 条码比例与 BuildBarcodeSvgInner 计算的画布比例一致; + /// 3) preserveAspectRatio:fillCell=true → "none"(按容器拉伸铺满,矢量缩放无损); + /// fillCell=false → "xMidYMid meet"(保比例居中,与 web jsbarcode 默认一致); + /// 4) 重新挂上 width="100%" height="100%",确保外层 div 100% 铺满。 + /// 这里不再"尝试从原 SVG 派生 viewBox",否则 regex 不匹配 ZXing 实际输出(单引号 / + /// 无属性 / 顺序差异)时,viewBox 会被漏掉,导致 SVG 被 CSS 双向拉伸,条码视觉变粗、变高。 /// - private static string? NormalizeBarcodeSvg(string svg) + private static string? NormalizeBarcodeSvg(string svg, bool fillCell = false, + double viewBoxWidth = 0, double viewBoxHeight = 0) { if (string.IsNullOrWhiteSpace(svg)) return null; + var targetAspect = fillCell ? "none" : "xMidYMid meet"; return Regex.Replace(svg, @"]*)>", m => { var attrs = m.Groups[1].Value; - // 取原 width/height 数值(若有),用于派生 viewBox - var widthMatch = Regex.Match(attrs, @"\swidth\s*=\s*""([^""]+)""", RegexOptions.IgnoreCase); - var heightMatch = Regex.Match(attrs, @"\sheight\s*=\s*""([^""]+)""", RegexOptions.IgnoreCase); - var hasViewBox = Regex.IsMatch(attrs, @"\sviewBox\s*=", RegexOptions.IgnoreCase); + // 同时兼容单/双引号,彻底清理可能影响最终缩放策略的属性 + attrs = Regex.Replace(attrs, @"\s(width|height|viewBox|preserveAspectRatio)\s*=\s*(""[^""]*""|'[^']*')", + string.Empty, RegexOptions.IgnoreCase); - if (!hasViewBox && widthMatch.Success && heightMatch.Success - && double.TryParse(Regex.Replace(widthMatch.Groups[1].Value, @"[^\d.]", ""), - NumberStyles.Any, CultureInfo.InvariantCulture, out var w) && w > 0 - && double.TryParse(Regex.Replace(heightMatch.Groups[1].Value, @"[^\d.]", ""), - NumberStyles.Any, CultureInfo.InvariantCulture, out var h) && h > 0) + // 用调用方提供的稳定画布比例作为 viewBox;调用方没传时再回退去读原属性 + var vbW = viewBoxWidth; + var vbH = viewBoxHeight; + if (vbW <= 0 || vbH <= 0) { - attrs += $" viewBox=\"0 0 {w.ToString("0.###", CultureInfo.InvariantCulture)} {h.ToString("0.###", CultureInfo.InvariantCulture)}\""; + // 兼容回退路径:从原 svg 标签 attrs 中再读一次 width/height(无 viewBox 时) + // 这段在调用方传入了 viewBoxWidth/Height 时不会走,保留兜底防御 + var widthMatch = Regex.Match(m.Groups[1].Value, @"\swidth\s*=\s*(""[^""]+""|'[^']+')", RegexOptions.IgnoreCase); + var heightMatch = Regex.Match(m.Groups[1].Value, @"\sheight\s*=\s*(""[^""]+""|'[^']+')", RegexOptions.IgnoreCase); + if (widthMatch.Success && heightMatch.Success) + { + var ws = widthMatch.Groups[1].Value.Trim('"', '\''); + var hs = heightMatch.Groups[1].Value.Trim('"', '\''); + double.TryParse(Regex.Replace(ws, @"[^\d.]", ""), NumberStyles.Any, CultureInfo.InvariantCulture, out vbW); + double.TryParse(Regex.Replace(hs, @"[^\d.]", ""), NumberStyles.Any, CultureInfo.InvariantCulture, out vbH); + } } + // 实在拿不到时按 jsbarcode 风格的兜底比例(避免 SVG 被纯拉伸) + if (vbW <= 0) vbW = 200; + if (vbH <= 0) vbH = 60; - attrs = Regex.Replace(attrs, @"\s(width|height)\s*=\s*""[^""]*""", string.Empty, RegexOptions.IgnoreCase); - if (!Regex.IsMatch(attrs, @"preserveAspectRatio", RegexOptions.IgnoreCase)) - attrs += " preserveAspectRatio=\"xMidYMid meet\""; - return $""; + var vbStr = $"0 0 {vbW.ToString("0.###", CultureInfo.InvariantCulture)} {vbH.ToString("0.###", CultureInfo.InvariantCulture)}"; + return $""; }, RegexOptions.IgnoreCase); } @@ -483,37 +502,47 @@ public static class NativePrintRenderService /// Width/Height,使生成的 SVG 内部 viewBox 比例稳定(与 web 视觉风格对齐),不会随 /// 元素框形状(90×60 / 50×30 mm)漂移成 1.5:1。外层 div 用 100%+preserveAspectRatio /// ="xMidYMid meet" 自适应铺满。 - /// textAlign 控制底部文字对齐:center / left / right / justify(两端),通过 SVG - /// 后处理修改 ZXing 输出的 <text> 节点 x/text-anchor 实现,与 web 端逻辑同源。 + /// textAlign 控制底部文字对齐:center / left / right / justify(两端), + /// 文字通过 InjectBarcodeText 向 SVG 底部注入 <text> 元素实现,与 web 端 jsbarcode 行为对齐。 + /// 注意:ZXing.Net 的 SVG 渲染器不生成人类可读文字(PureBarcode=false 在 SvgRenderer 无效), + /// 必须手动注入;同时只将 barHeight 传给 ZXing 渲染条形,避免条形撑满含文字区的总高度。 /// private static string BuildBarcodeSvgInner(string value, BarcodeFormat format, bool displayValue, - string? textAlign = null, int lineWidth = 2, int barHeight = 60, int barFontSize = 14) + string? textAlign = null, int lineWidth = 2, int barHeight = 60, int barFontSize = 14, bool fillCell = false) { if (string.IsNullOrWhiteSpace(value)) return string.Empty; try { - // moduleCount 仅用于派生稳定的 SVG viewBox 宽度,ZXing 实际按编码后的真实模块数 - // 1:1 绘制;多给一点宽度不会让条变粗,只会让两侧留白略多。 var moduleCount = EstimateBarcodeModuleCount(value, format); - var fontFooter = displayValue ? Math.Max(8, barFontSize) + 4 : 0; // fontSize + padding ≈ jsbarcode 行为 var widthPx = Math.Max(120, moduleCount * lineWidth); - var heightPx = Math.Max(10, barHeight) + fontFooter; + var barOnlyH = Math.Max(10, barHeight); // 只把条高给 ZXing;文字由 InjectBarcodeText 注入 var writer = new BarcodeWriterSvg { Format = format, Options = new ZXing.Common.EncodingOptions { - Width = widthPx, - Height = heightPx, - Margin = 0, - PureBarcode = !displayValue, + Width = widthPx, + Height = barOnlyH, + Margin = 0, + PureBarcode = true, // ZXing SVG renderer 不支持文字,统一用 PureBarcode=true }, }; - var svgStr = writer.Write(value)?.Content ?? string.Empty; - var normalized = NormalizeBarcodeSvg(svgStr) ?? BuildFallbackBarcodeSvg(value); - // 仅当显示文字时执行对齐后处理 - if (displayValue) normalized = ApplyBarcodeTextAlign(normalized, textAlign); + var svgStr = writer.Write(value)?.Content ?? string.Empty; + // 关键:把我们提供给 ZXing 的 widthPx × barOnlyH 作为目标 viewBox 强制写入, + // 让桌面端 SVG 与 web jsbarcode 同样进入"viewBox + preserveAspectRatio=meet"渲染 + // 路径,避免某些 ZXing 输出顺序/引号风格让 regex 漏掉 viewBox 派生导致条码被 CSS 双向拉伸。 + //(注:底部文字区由后续 InjectBarcodeText 再把 viewBox 的高度扩展上去, + // 因此此处只用条形高度 barOnlyH。) + var normalized = NormalizeBarcodeSvg(svgStr, fillCell, widthPx, barOnlyH) + ?? BuildFallbackBarcodeSvg(value); + // 裁掉 ZXing 可能保留的左右静区,让条码主体宽度更贴近 web 端 jsbarcode 观感。 + normalized = TightenBarcodeHorizontalViewBox(normalized, widthPx); + + // 文字注入:在 viewBox 底部添加 ,扩展 viewBox 高度以容纳文字区 + if (displayValue) + normalized = InjectBarcodeText(normalized, value, barFontSize, textAlign); + return normalized; } catch @@ -523,45 +552,139 @@ public static class NativePrintRenderService } /// - /// 后处理 ZXing 输出 SVG 中的底部文字 <text> 节点,按 textAlign 修改 x/text-anchor, - /// justify(两端对齐)通过 textLength + lengthAdjust=spacing 让浏览器自动拉伸字符间距。 - /// 宽度从 SVG 自身的 viewBox 第三个分量读取,不依赖 ZXing 的内部缩放策略,保证 - /// "user units 坐标系内对齐 + 浏览器渲染" 一致。 + /// 向 ZXing 条码 SVG 底部注入人类可读文字并扩展 viewBox 高度,与 web 端 jsbarcode displayValue 行为对齐。 + /// textAlign 支持 center / left / right / justify(两端对齐,通过 textLength+lengthAdjust 实现)。 /// - private static string ApplyBarcodeTextAlign(string svg, string? textAlign) + private static string InjectBarcodeText(string svg, string text, int fontSize, string? textAlign) { - if (string.IsNullOrEmpty(svg)) return svg; - var align = (textAlign ?? "center").Trim().ToLowerInvariant(); - if (align is not ("left" or "right" or "justify")) return svg; // center 即 ZXing 默认,不动 + var (x0, y0, vbWidth, vbHeight) = ParseViewBoxOrDefault(svg); + var safeFs = Math.Max(8, fontSize); + const double textMargin = 2d; // 对齐 jsbarcode 默认 textMargin + var footerH = safeFs + textMargin + 2d; // 预留文字区 + 底部余量,避免裁切 + var newH = vbHeight + footerH; + var wStr = vbWidth.ToString("0.###", CultureInfo.InvariantCulture); + var hStr = newH.ToString("0.###", CultureInfo.InvariantCulture); - // 解析 viewBox 取 user units 宽度,作为对齐坐标参照 - double vbWidth = 0; - var vbMatch = Regex.Match(svg, @"viewBox\s*=\s*""([^""]+)""", RegexOptions.IgnoreCase); - if (vbMatch.Success) + // 扩展 viewBox 高度(保留原始 x0/y0) + svg = Regex.Replace(svg, @"viewBox\s*=\s*""([^""]+)""", m => { - var parts = Regex.Split(vbMatch.Groups[1].Value.Trim(), @"[\s,]+"); + return $"viewBox=\"{x0.ToString("0.###", CultureInfo.InvariantCulture)} {y0.ToString("0.###", CultureInfo.InvariantCulture)} {wStr} {hStr}\""; + }, RegexOptions.IgnoreCase); + + // 计算文字 y 基线(条形底边 + textMargin + fontSize),与 jsbarcode 版式一致 + var yStr = (y0 + vbHeight + textMargin + safeFs).ToString("0.###", CultureInfo.InvariantCulture); + // 关键:文字水平对齐基于“条码墨迹真实范围”而非整块 viewBox。 + // 否则当 SVG 内部存在左右静区/内缩时,文字会看起来和条码不对齐。 + var (inkLeft, inkRight) = ResolveBarcodeInkBounds(svg, vbWidth); + var inkWidth = Math.Max(1e-6, inkRight - inkLeft); + var leftStr = inkLeft.ToString("0.###", CultureInfo.InvariantCulture); + var rightStr = inkRight.ToString("0.###", CultureInfo.InvariantCulture); + var widthStr = inkWidth.ToString("0.###", CultureInfo.InvariantCulture); + var midX = (inkLeft + inkWidth / 2d).ToString("0.###", CultureInfo.InvariantCulture); + var align = (textAlign ?? "center").Trim().ToLowerInvariant(); + var esc = EscapeHtml(text); + + var textElem = align switch + { + "left" => $"{esc}", + "right" => $"{esc}", + "justify" => $"{esc}", + _ => $"{esc}", + }; + + // 插入 闭合标签之前 + return Regex.Replace(svg, @"", $"{textElem}", RegexOptions.IgnoreCase); + } + + /// + /// 收紧条码水平 viewBox,裁掉左右静区;仅调整 x/width,不改 y/height。 + /// + private static string TightenBarcodeHorizontalViewBox(string svg, double fallbackWidth) + { + var (x0, y0, vbW, vbH) = ParseViewBoxOrDefault(svg, fallbackWidth); + var (inkLeft, inkRight) = ResolveBarcodeInkBounds(svg, vbW); + var inkW = inkRight - inkLeft; + if (inkW <= 1e-6) return svg; + + var newX = x0 + inkLeft; + var newViewBox = $"viewBox=\"{newX.ToString("0.###", CultureInfo.InvariantCulture)} {y0.ToString("0.###", CultureInfo.InvariantCulture)} {inkW.ToString("0.###", CultureInfo.InvariantCulture)} {vbH.ToString("0.###", CultureInfo.InvariantCulture)}\""; + return Regex.Replace(svg, @"viewBox\s*=\s*""[^""]+""", newViewBox, RegexOptions.IgnoreCase); + } + + private static (double x0, double y0, double w, double h) ParseViewBoxOrDefault(string svg, double fallbackWidth = 200, double fallbackHeight = 60) + { + var m = Regex.Match(svg ?? string.Empty, @"viewBox\s*=\s*""([^""]+)""", RegexOptions.IgnoreCase); + if (m.Success) + { + var parts = Regex.Split(m.Groups[1].Value.Trim(), @"[\s,]+"); if (parts.Length >= 4 - && double.TryParse(parts[2], NumberStyles.Any, CultureInfo.InvariantCulture, out var w) && w > 0) + && double.TryParse(parts[0], NumberStyles.Any, CultureInfo.InvariantCulture, out var x0) + && double.TryParse(parts[1], NumberStyles.Any, CultureInfo.InvariantCulture, out var y0) + && double.TryParse(parts[2], NumberStyles.Any, CultureInfo.InvariantCulture, out var w) + && double.TryParse(parts[3], NumberStyles.Any, CultureInfo.InvariantCulture, out var h) + && w > 0 && h > 0) { - vbWidth = w; + return (x0, y0, w, h); } } - if (vbWidth <= 0) return svg; // 拿不到 viewBox 宽度时不动,保持 ZXing 默认居中 + return (0d, 0d, Math.Max(1d, fallbackWidth), Math.Max(1d, fallbackHeight)); + } - return Regex.Replace(svg, @"]*)>", m => + /// + /// 从 SVG 中提取条码“黑色墨迹”的左右边界。 + /// 优先扫描 <rect>,忽略白色/透明填充;失败时回退到整块 viewBox。 + /// + private static (double left, double right) ResolveBarcodeInkBounds(string svg, double fallbackWidth) + { + if (string.IsNullOrWhiteSpace(svg)) + return (0d, Math.Max(1d, fallbackWidth)); + + var rects = Regex.Matches(svg, @"]*>", RegexOptions.IgnoreCase); + double minX = double.PositiveInfinity; + double maxX = double.NegativeInfinity; + + foreach (Match m in rects) { - var attrs = m.Groups[1].Value; - attrs = Regex.Replace(attrs, @"\s(x|text-anchor|textLength|lengthAdjust)\s*=\s*""[^""]*""", string.Empty, RegexOptions.IgnoreCase); - var widthStr = vbWidth.ToString("0.###", CultureInfo.InvariantCulture); + var tag = m.Value; - return align switch - { - "left" => $"", - "right" => $"", - "justify" => $"", - _ => m.Value, - }; - }, RegexOptions.IgnoreCase); + // 跳过明显的白底/透明背景 rect + var fill = ReadSvgAttr(tag, "fill")?.Trim().ToLowerInvariant(); + if (fill is "none" or "transparent" or "#fff" or "#ffffff" or "white") + continue; + + var xs = ReadSvgAttr(tag, "x"); + var ws = ReadSvgAttr(tag, "width"); + if (!TryParseSvgNumber(xs, out var x) || !TryParseSvgNumber(ws, out var w) || w <= 0) + continue; + + if (x < minX) minX = x; + if (x + w > maxX) maxX = x + w; + } + + if (double.IsInfinity(minX) || double.IsInfinity(maxX) || maxX <= minX) + return (0d, Math.Max(1d, fallbackWidth)); + + return (minX, maxX); + } + + private static string? ReadSvgAttr(string tag, string attr) + { + if (string.IsNullOrWhiteSpace(tag) || string.IsNullOrWhiteSpace(attr)) + return null; + var mm = Regex.Match(tag, $@"\b{Regex.Escape(attr)}\s*=\s*(""([^""]*)""|'([^']*)')", RegexOptions.IgnoreCase); + if (!mm.Success) return null; + return !string.IsNullOrEmpty(mm.Groups[2].Value) ? mm.Groups[2].Value : mm.Groups[3].Value; + } + + private static bool TryParseSvgNumber(string? raw, out double value) + { + value = 0; + if (string.IsNullOrWhiteSpace(raw)) return false; + var s = raw.Trim(); + // 支持 "123", "123.45", "123px";百分比不参与墨迹边界计算 + if (s.EndsWith("%", StringComparison.Ordinal)) return false; + s = Regex.Replace(s, @"[^\d\.\-+eE]", ""); + return double.TryParse(s, NumberStyles.Any, CultureInfo.InvariantCulture, out value); } /// @@ -1617,9 +1740,9 @@ public static class NativePrintRenderService } if (t == "barcode") { - var fmt = ReadAsString(col?["barcodeFormat"]); - var dv = !string.Equals(ReadAsString(col?["displayValue"]), "false", StringComparison.OrdinalIgnoreCase); - var bFontSize = Math.Max(8, (int)Math.Round(col?["barcodeFontSize"]?.GetValue() ?? 14d)); + var fmt = ReadAsString(col?["barcodeFormat"]); + var dv = !string.Equals(ReadAsString(col?["displayValue"]), "false", StringComparison.OrdinalIgnoreCase); + var bFontSize = Math.Max(8, (int)Math.Round(col?["barcodeFontSize"]?.GetValue() ?? 14d)); var svg = BuildBarcodeCellSvg(value, fmt, dv, null, bFontSize); return $"
{svg}
"; }