From 9f511be811821d7b6f823300db0c8f238012f1d1 Mon Sep 17 00:00:00 2001 From: Denis Averin Date: Tue, 11 Nov 2025 19:05:20 +0700 Subject: [PATCH 1/2] Fix test command in Makefile --- Makefile | 4 ++-- scripts/run_snippet.sh | 7 +++---- scripts/run_snippets.sh | 0 3 files changed, 5 insertions(+), 6 deletions(-) mode change 100644 => 100755 scripts/run_snippet.sh mode change 100644 => 100755 scripts/run_snippets.sh diff --git a/Makefile b/Makefile index e952296..a63ada9 100644 --- a/Makefile +++ b/Makefile @@ -22,9 +22,9 @@ format-doc: find . -iname "*.md" -exec sed -i -e 's_[[:space:]]*$$__' {} \; .PHONY: test -test: +test: nuget dotnet test -v normal --framework=net$(LATEST_SDK_VERSION) - ./scripts/run_snippests.sh + ./scripts/run_snippets.sh .PHONY: build build: diff --git a/scripts/run_snippet.sh b/scripts/run_snippet.sh old mode 100644 new mode 100755 index bcba53c..357cc43 --- a/scripts/run_snippet.sh +++ b/scripts/run_snippet.sh @@ -7,11 +7,10 @@ RUN_DIR=$2 SCRIPT_DIR=$3 CONFIG_FILE_PATH=$4 -rm $RUN_DIR/*.cs || true +rm "$RUN_DIR"/*.cs || true echo "Run snippet file: $FILE_PATH" -python ${SCRIPT_DIR}/insert-credentials.py $FILE_PATH $CONFIG_FILE_PATH $RUN_DIR - -dotnet run --project ./$RUN_DIR/Snippets.csproj || exit 1 +python "${SCRIPT_DIR}/insert-credentials.py" "$FILE_PATH" "$CONFIG_FILE_PATH" "$RUN_DIR" +dotnet run --project "./$RUN_DIR/Snippets.csproj" || exit 1 diff --git a/scripts/run_snippets.sh b/scripts/run_snippets.sh old mode 100644 new mode 100755 From ca9bf4dd61452f89f199f9af5664a0d2fa63c00c Mon Sep 17 00:00:00 2001 From: Denis Averin Date: Tue, 11 Nov 2025 19:50:41 +0700 Subject: [PATCH 2/2] Added example how to combine 2 SVG into 1 --- snippets/generate/svg/Combine.cs | 152 +++++++++++++++++++++++++++++++ 1 file changed, 152 insertions(+) create mode 100644 snippets/generate/svg/Combine.cs diff --git a/snippets/generate/svg/Combine.cs b/snippets/generate/svg/Combine.cs new file mode 100644 index 0000000..38f5009 --- /dev/null +++ b/snippets/generate/svg/Combine.cs @@ -0,0 +1,152 @@ +using Aspose.BarCode.Cloud.Sdk.Api; +using Aspose.BarCode.Cloud.Sdk.Model; + +using System; +using System.Globalization; +using System.IO; +using System.Text; +using System.Threading.Tasks; +using System.Xml.Linq; + +namespace GenerateSnippets; + +/// +/// Demonstrates generating two SVG barcodes via Aspose.BarCode Cloud and combining +/// them into a single SVG containing both codes side-by-side. +/// +internal static class Program +{ + private static readonly Encoding Utf8NoBom = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false); + private const double BarcodeSpacing = 20d; + + private static Configuration MakeConfiguration() + { + var config = new Configuration(); + + string? envToken = Environment.GetEnvironmentVariable("TEST_CONFIGURATION_ACCESS_TOKEN"); + if (string.IsNullOrEmpty(envToken)) + { + config.ClientId = "Client Id from https://dashboard.aspose.cloud/applications"; + config.ClientSecret = "Client Secret from https://dashboard.aspose.cloud/applications"; + } + else + { + config.JwtToken = envToken; + } + + return config; + } + + public static async Task Main(string[] args) + { + string fileName = Path.GetFullPath(Path.Join("Tests", "test_data", "combined.svg")); + + GenerateApi generateApi = new GenerateApi(MakeConfiguration()); + + Task eanTask = GenerateSvgAsync(generateApi, + barcodeType: EncodeBarcodeType.EAN13, + data: "5901234123457"); + + Task qrTask = GenerateSvgAsync(generateApi, + barcodeType: EncodeBarcodeType.QR, + data: "https://products.aspose.cloud/barcode/"); + + await Task.WhenAll(eanTask, qrTask); + + string combinedSvg = CombineSvg(eanTask.Result, qrTask.Result); + + await File.WriteAllTextAsync(fileName, combinedSvg, Utf8NoBom); + + Console.WriteLine($"File '{fileName}' generated."); + } + + private static async Task GenerateSvgAsync(GenerateApi api, EncodeBarcodeType barcodeType, string data) + { + await using Stream generated = await api.GenerateAsync( + barcodeType: barcodeType, + data: data, + imageFormat: BarcodeImageFormat.Svg); + + using var reader = new StreamReader(generated, Utf8NoBom, detectEncodingFromByteOrderMarks: true); + return await reader.ReadToEndAsync(); + } + + private static string CombineSvg(string eanSvg, string qrSvg) + { + XDocument eanDoc = XDocument.Parse(eanSvg); + XDocument qrDoc = XDocument.Parse(qrSvg); + + double eanWidth = ParseLength(eanDoc.Root?.Attribute("width")); + double eanHeight = ParseLength(eanDoc.Root?.Attribute("height")); + double qrWidth = ParseLength(qrDoc.Root?.Attribute("width")); + double qrHeight = ParseLength(qrDoc.Root?.Attribute("height")); + + double combinedWidth = eanWidth + BarcodeSpacing + qrWidth; + double combinedHeight = Math.Max(eanHeight, qrHeight); + + XNamespace svgNamespace = eanDoc.Root?.Name.Namespace ?? "http://www.w3.org/2000/svg"; + var combinedRoot = new XElement(svgNamespace + "svg", + new XAttribute("xmlns", svgNamespace.NamespaceName), + new XAttribute(XNamespace.Xmlns + "xlink", "http://www.w3.org/1999/xlink"), + new XAttribute("width", ToInvariantLength(combinedWidth)), + new XAttribute("height", ToInvariantLength(combinedHeight)), + new XAttribute("viewBox", $"0 0 {ToInvariantLength(combinedWidth)} {ToInvariantLength(combinedHeight)}")); + + double eanOffsetY = Math.Max(0, (combinedHeight - eanHeight) / 2); + double qrOffsetY = Math.Max(0, (combinedHeight - qrHeight) / 2); + + combinedRoot.Add(CreateNestedSvg(eanDoc, 0, eanOffsetY, "EAN13")); + combinedRoot.Add(CreateNestedSvg(qrDoc, eanWidth + BarcodeSpacing, qrOffsetY, "QR")); + + return combinedRoot.ToString(SaveOptions.OmitDuplicateNamespaces); + } + + private static XElement CreateNestedSvg(XDocument source, double offsetX, double offsetY, string label) + { + if (source.Root == null) + { + throw new InvalidOperationException("SVG document does not have a root element."); + } + + var nested = new XElement(source.Root); + nested.SetAttributeValue("x", ToInvariantLength(offsetX)); + nested.SetAttributeValue("y", ToInvariantLength(offsetY)); + nested.SetAttributeValue("data-barcode", label); + return nested; + } + + private static double ParseLength(XAttribute? attribute, double fallback = 100d) + { + return ParseLength(attribute?.Value, fallback); + } + + private static double ParseLength(string? rawValue, double fallback = 100d) + { + if (string.IsNullOrWhiteSpace(rawValue)) + { + return fallback; + } + + var buffer = new StringBuilder(); + foreach (char c in rawValue) + { + if (char.IsDigit(c) || c == '.' || c == '-') + { + buffer.Append(c); + } + else if (buffer.Length > 0) + { + break; + } + } + + return double.TryParse(buffer.ToString(), NumberStyles.Float, CultureInfo.InvariantCulture, out double parsed) + ? parsed + : fallback; + } + + private static string ToInvariantLength(double value) + { + return value.ToString("0.##", CultureInfo.InvariantCulture); + } +}