From c44093c5ee990ea849c9c0f79efd7b1ee9e4460c Mon Sep 17 00:00:00 2001 From: Michael Babienco Date: Wed, 4 Mar 2026 21:10:15 +0900 Subject: [PATCH 01/13] Fix wrong About menu title --- src/App.axaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/App.axaml b/src/App.axaml index 3e63c9d..562527a 100644 --- a/src/App.axaml +++ b/src/App.axaml @@ -131,7 +131,7 @@ - + \ No newline at end of file From 4ad4a0852fc10b9e996bafd2231e031d995f991d Mon Sep 17 00:00:00 2001 From: Michael Babienco Date: Thu, 12 Mar 2026 19:02:17 +0900 Subject: [PATCH 02/13] Bump Magick.NET for vulnerability --- src/MayShow.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/MayShow.csproj b/src/MayShow.csproj index cfbdf7c..e08c7ca 100644 --- a/src/MayShow.csproj +++ b/src/MayShow.csproj @@ -58,7 +58,7 @@ All - + From 742ecb148a62504e0322e529181152bb6ded5bcf Mon Sep 17 00:00:00 2001 From: Michael Babienco Date: Thu, 12 Mar 2026 19:07:25 +0900 Subject: [PATCH 03/13] Simply if statement --- src/ViewModels/MainViewModel.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ViewModels/MainViewModel.cs b/src/ViewModels/MainViewModel.cs index 861fbb4..267693d 100644 --- a/src/ViewModels/MainViewModel.cs +++ b/src/ViewModels/MainViewModel.cs @@ -777,7 +777,7 @@ class MainViewModel : BaseViewModel, IFontResolver, ICanCheckShutdown paragraph.Format.Alignment = ParagraphAlignment.Center; var image = paragraph.AddImage(filePath); image.LockAspectRatio = true; - if (!isPDF && loadedImageHeight > 600) + if (loadedImageHeight > 600) { image.Height = 550; // make sure it will fit on one page } From 5dda88521d02c3bbebee5f26c27f2ee09b3f22ad Mon Sep 17 00:00:00 2001 From: Michael Babienco Date: Thu, 12 Mar 2026 19:34:56 +0900 Subject: [PATCH 04/13] Add black border around images/pdfs Makes viewing things with no border/white border much easier. --- src/ViewModels/MainViewModel.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/ViewModels/MainViewModel.cs b/src/ViewModels/MainViewModel.cs index 267693d..eb2a876 100644 --- a/src/ViewModels/MainViewModel.cs +++ b/src/ViewModels/MainViewModel.cs @@ -628,6 +628,11 @@ class MainViewModel : BaseViewModel, IFontResolver, ICanCheckShutdown var outputFileName = ReportTitle + ".pdf"; var folderName = new DirectoryInfo(folderPath).Name; const int imageWidth = 425; + var imageLineFormat = new MigraDoc.DocumentObjectModel.Shapes.LineFormat() + { + Color = Colors.Black, + Width = Unit.FromPoint(2), + };; if (folderName.Contains('-')) { // see if year/month format @@ -782,6 +787,7 @@ class MainViewModel : BaseViewModel, IFontResolver, ICanCheckShutdown image.Height = 550; // make sure it will fit on one page } else + image.LineFormat = imageLineFormat.Clone(); { image.Width = imageWidth; // can't be too wide now...not sure why...maybe due to margins... } @@ -828,6 +834,7 @@ class MainViewModel : BaseViewModel, IFontResolver, ICanCheckShutdown var image = paragraph.AddImage(convertedPdfImagePath); image.Width = imageWidth; image.LockAspectRatio = true; + image.LineFormat = imageLineFormat.Clone(); for (var j = 1; j < pgCount; j++) { section.AddPageBreak(); @@ -837,6 +844,7 @@ class MainViewModel : BaseViewModel, IFontResolver, ICanCheckShutdown image = paragraph.AddImage(convertedPdfImagePath); image.LockAspectRatio = true; image.Width = imageWidth; + image.LineFormat = imageLineFormat.Clone(); } } } @@ -848,6 +856,7 @@ class MainViewModel : BaseViewModel, IFontResolver, ICanCheckShutdown var image = paragraph.AddImage(filePath); image.LockAspectRatio = true; image.Width = imageWidth; // can't be too wide now...not sure why...maybe due to margins... + image.LineFormat = imageLineFormat.Clone(); // render other PDF pages, if any // see: https://stackoverflow.com/a/65091204/3938401 var pdfFileToAdd = PdfReader.Open(filePath, PdfDocumentOpenMode.Import); @@ -863,6 +872,7 @@ class MainViewModel : BaseViewModel, IFontResolver, ICanCheckShutdown image = paragraph.AddImage(filePath + "#" + j); image.LockAspectRatio = true; image.Width = imageWidth; + image.LineFormat = imageLineFormat.Clone(); } } } From 1fae3f5341ac1df6a36083aa56d01b05d92b749b Mon Sep 17 00:00:00 2001 From: Michael Babienco Date: Thu, 12 Mar 2026 20:21:41 +0900 Subject: [PATCH 05/13] Redo image resizing Hack fix guesswork sizing --- src/ViewModels/MainViewModel.cs | 50 ++++++++++++++++++++------------- 1 file changed, 31 insertions(+), 19 deletions(-) diff --git a/src/ViewModels/MainViewModel.cs b/src/ViewModels/MainViewModel.cs index eb2a876..c89dfb4 100644 --- a/src/ViewModels/MainViewModel.cs +++ b/src/ViewModels/MainViewModel.cs @@ -28,6 +28,7 @@ using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing; using System.Reflection.Metadata.Ecma335; using Docnet.Core.Readers; +using MigraDoc.DocumentObjectModel.Visitors; namespace MayShow.ViewModels; @@ -627,7 +628,7 @@ class MainViewModel : BaseViewModel, IFontResolver, ICanCheckShutdown var pdfDoc = new Document(); var outputFileName = ReportTitle + ".pdf"; var folderName = new DirectoryInfo(folderPath).Name; - const int imageWidth = 425; + const int maxImageWidth = 425; var imageLineFormat = new MigraDoc.DocumentObjectModel.Shapes.LineFormat() { Color = Colors.Black, @@ -649,12 +650,15 @@ class MainViewModel : BaseViewModel, IFontResolver, ICanCheckShutdown } var section = pdfDoc.AddSection(); section.PageSetup.PageFormat = PageFormat.Letter; - section.PageSetup.PageWidth = "8.5in"; - section.PageSetup.PageHeight = "11in"; - section.PageSetup.TopMargin = "0.5in"; - section.PageSetup.RightMargin = "0.5in"; - section.PageSetup.BottomMargin = "0.5in"; - section.PageSetup.LeftMargin = "0.5in"; + const decimal pageWidth = 8.5m; + const decimal pageHeight = 11.0m; + const decimal margin = 0.5m; + section.PageSetup.PageWidth = pageWidth + "in"; + section.PageSetup.PageHeight = pageHeight + "in"; + section.PageSetup.TopMargin = margin + "in"; + section.PageSetup.RightMargin = margin + "in"; + section.PageSetup.BottomMargin = margin + "in"; + section.PageSetup.LeftMargin = margin + "in"; // setup footer for page number var footerPar = new Paragraph(); footerPar.Format.Alignment = ParagraphAlignment.Center; @@ -781,18 +785,26 @@ class MainViewModel : BaseViewModel, IFontResolver, ICanCheckShutdown var paragraph = section.AddParagraph(); paragraph.Format.Alignment = ParagraphAlignment.Center; var image = paragraph.AddImage(filePath); - image.LockAspectRatio = true; - if (loadedImageHeight > 600) - { - image.Height = 550; // make sure it will fit on one page - } - else + const int imageResolution = 72; + image.Resolution = imageResolution; // dots per inch + paragraph.Tag = "ImageParagraphTag"; + // + //var maxItemPxWidth = ((pageWidth - (2 * margin)) * imageResolution) - 20; + //var maxItemPxHeight = ((pageHeight - (2 * margin)) * imageResolution) - 20; + //Console.WriteLine("Max width test: {0}; height: {1}", maxItemPxWidth, maxItemPxHeight); image.LineFormat = imageLineFormat.Clone(); + // image.LockAspectRatio = true; + while (loadedImageHeight > 600 || loadedImageWidth > 550) { - image.Width = imageWidth; // can't be too wide now...not sure why...maybe due to margins... + // Console.WriteLine("Image height = {0}, width = {1}; decreasing size by 5% to h={2}, w={3}", loadedImageHeight, loadedImageWidth, (uint)Math.Floor(loadedImageHeight * 0.95), (uint)Math.Floor(loadedImageWidth * 0.95)); + // keep reducing size by 10% until it fits on the page + loadedImageHeight = (uint)Math.Floor(loadedImageHeight * 0.95); + loadedImageWidth = (uint)Math.Floor(loadedImageWidth * 0.95); } + image.Height = loadedImageHeight; + image.Width = loadedImageWidth; } - else + else // isPDF { // need to render PDF to images if (_settings.UseDocnetPDFImageRendering) @@ -832,7 +844,7 @@ class MainViewModel : BaseViewModel, IFontResolver, ICanCheckShutdown var paragraph = section.AddParagraph(); paragraph.Format.Alignment = ParagraphAlignment.Center; var image = paragraph.AddImage(convertedPdfImagePath); - image.Width = imageWidth; + image.Width = maxImageWidth; image.LockAspectRatio = true; image.LineFormat = imageLineFormat.Clone(); for (var j = 1; j < pgCount; j++) @@ -843,7 +855,7 @@ class MainViewModel : BaseViewModel, IFontResolver, ICanCheckShutdown convertedPdfImagePath = RenderPdfPageToImage(docReader, j); image = paragraph.AddImage(convertedPdfImagePath); image.LockAspectRatio = true; - image.Width = imageWidth; + image.Width = maxImageWidth; image.LineFormat = imageLineFormat.Clone(); } } @@ -855,7 +867,7 @@ class MainViewModel : BaseViewModel, IFontResolver, ICanCheckShutdown paragraph.Format.Alignment = ParagraphAlignment.Center; var image = paragraph.AddImage(filePath); image.LockAspectRatio = true; - image.Width = imageWidth; // can't be too wide now...not sure why...maybe due to margins... + image.Width = maxImageWidth; // can't be too wide now...not sure why...maybe due to margins... image.LineFormat = imageLineFormat.Clone(); // render other PDF pages, if any // see: https://stackoverflow.com/a/65091204/3938401 @@ -871,7 +883,7 @@ class MainViewModel : BaseViewModel, IFontResolver, ICanCheckShutdown paragraph.Format.Alignment = ParagraphAlignment.Center; image = paragraph.AddImage(filePath + "#" + j); image.LockAspectRatio = true; - image.Width = imageWidth; + image.Width = maxImageWidth; image.LineFormat = imageLineFormat.Clone(); } } From 25f739667d00d54221b4f07d9dbda89503fe0727 Mon Sep 17 00:00:00 2001 From: Michael Babienco Date: Thu, 12 Mar 2026 20:56:38 +0900 Subject: [PATCH 06/13] Allow resolving Noto Sans font --- src/ViewModels/MainViewModel.cs | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/ViewModels/MainViewModel.cs b/src/ViewModels/MainViewModel.cs index c89dfb4..56d274f 100644 --- a/src/ViewModels/MainViewModel.cs +++ b/src/ViewModels/MainViewModel.cs @@ -577,6 +577,24 @@ class MainViewModel : BaseViewModel, IFontResolver, ICanCheckShutdown public byte[]? GetFont(string faceName) { LogInfo(string.Format("Loading font {0}", faceName)); + if (faceName == "Noto Sans") + { + var path = Path.Combine(_processDir, "Assets/Fonts/Noto_Sans/static/NotoSans-Regular.ttf"); + if (!File.Exists(path)) + { + path = Path.Combine(_processDir, "../Resources/Assets/Fonts/Noto_Sans/static/NotoSans-Regular.ttf"); + } + return File.ReadAllBytes(path); + } + if (faceName == "Noto Sans Bold") + { + var path = Path.Combine(_processDir, "Assets/Fonts/Noto_Sans/static/NotoSans-Bold.ttf"); + if (!File.Exists(path)) + { + path = Path.Combine(_processDir, "../Resources/Assets/Fonts/Noto_Sans/static/NotoSans-Bold.ttf"); + } + return File.ReadAllBytes(path); + } if (faceName == "Noto Sans JP") { var path = Path.Combine(_processDir, "Assets/Fonts/Noto_Sans_JP/static/NotoSansJP-Regular.ttf"); @@ -601,6 +619,14 @@ class MainViewModel : BaseViewModel, IFontResolver, ICanCheckShutdown public FontResolverInfo? ResolveTypeface(string familyName, bool bold, bool italic) { // LogInfo(string.Format("Resolving font name {0}", familyName)); + if (familyName == "Noto Sans") + { + if (bold) + { + return new FontResolverInfo(familyName + " Bold"); + } + return new FontResolverInfo(familyName); + } if (familyName == "Noto Sans JP") { if (bold) From aed85c755530bec061266efc7e65c5d504acdb72 Mon Sep 17 00:00:00 2001 From: Michael Babienco Date: Thu, 12 Mar 2026 20:58:20 +0900 Subject: [PATCH 07/13] Use page size and pg items to calc max image size --- src/ViewModels/MainViewModel.cs | 130 ++++++++++++++++++++++++-------- 1 file changed, 99 insertions(+), 31 deletions(-) diff --git a/src/ViewModels/MainViewModel.cs b/src/ViewModels/MainViewModel.cs index 56d274f..35eedf8 100644 --- a/src/ViewModels/MainViewModel.cs +++ b/src/ViewModels/MainViewModel.cs @@ -638,6 +638,43 @@ class MainViewModel : BaseViewModel, IFontResolver, ICanCheckShutdown return null; } + private Paragraph GetFooterParagraph() + { + var footerPar = new Paragraph(); + footerPar.Format.Alignment = ParagraphAlignment.Center; + footerPar.Format.Font.Size = 10; + footerPar.AddText("--Page "); + footerPar.AddPageField(); + footerPar.AddText(" of "); + footerPar.AddNumPagesField(); + footerPar.AddText("--"); + footerPar.AddLineBreak(); + footerPar.AddText("Report generated on " + DateTime.Now.ToString("f")); + footerPar.Tag = "FooterPar"; + footerPar.Format.Font.Name = "Noto Sans"; + return footerPar; + } + + private decimal GetExistingPageItemHeight(PdfDocumentRenderer pdfRenderer, decimal footerParagraphHeight) + { + pdfRenderer.DocumentRenderer.PrepareDocument(); + var currPageCount = pdfRenderer.DocumentRenderer.FormattedDocument?.PageCount; + var heightForExistingItemsOnPage = footerParagraphHeight; + if (currPageCount.HasValue) + { + var renderInfo = pdfRenderer.DocumentRenderer.GetRenderInfoFromPage(currPageCount.Value); + if (renderInfo != null) + { + // Console.WriteLine("Got render info for page: {0}", currPageCount); + foreach (var item in renderInfo) + { + heightForExistingItemsOnPage += (decimal)item.LayoutInfo.ContentArea.Height.Inch; + } + } + } + return heightForExistingItemsOnPage; + } + // https://forum.pdfsharp.net/viewtopic.php?f=2&t=1025 private async Task CreatePDF(string folderPath) { @@ -649,6 +686,15 @@ class MainViewModel : BaseViewModel, IFontResolver, ICanCheckShutdown await DialogHost.Show(new WarningViewModel("Output directory not found! Please adjust your application Settings before continuing. Output directory: " + outputDir)); return; } + // setup globals and consts... + GlobalFontSettings.FontResolver = this; + GlobalFontSettings.FallbackFontResolver = new FailsafeFontResolver(); + const decimal pageWidth = 8.5m; + const decimal pageHeight = 11.0m; + const decimal margin = 0.5m; + const int imageResolution = 72; + const int imageInsertMarginPixels = 30; // we calculate max available; use max - this # for max image size + var maxItemPxWidth = ((pageWidth - (2 * margin)) * imageResolution) - imageInsertMarginPixels; // start making PDF! IsCreatingPDF = true; var pdfDoc = new Document(); @@ -674,11 +720,9 @@ class MainViewModel : BaseViewModel, IFontResolver, ICanCheckShutdown LogInfo("Auto-changed output file name to " + outputFileName); } } + // setup initial section (for page characteristics) var section = pdfDoc.AddSection(); section.PageSetup.PageFormat = PageFormat.Letter; - const decimal pageWidth = 8.5m; - const decimal pageHeight = 11.0m; - const decimal margin = 0.5m; section.PageSetup.PageWidth = pageWidth + "in"; section.PageSetup.PageHeight = pageHeight + "in"; section.PageSetup.TopMargin = margin + "in"; @@ -686,24 +730,41 @@ class MainViewModel : BaseViewModel, IFontResolver, ICanCheckShutdown section.PageSetup.BottomMargin = margin + "in"; section.PageSetup.LeftMargin = margin + "in"; // setup footer for page number - var footerPar = new Paragraph(); - footerPar.Format.Alignment = ParagraphAlignment.Center; - footerPar.Format.Font.Size = 10; - footerPar.AddText("--Page "); - footerPar.AddPageField(); - footerPar.AddText(" of "); - footerPar.AddNumPagesField(); - footerPar.AddText("--"); - footerPar.AddLineBreak(); - footerPar.AddText("Report generated on " + DateTime.Now.ToString("f")); + var footerPar = GetFooterParagraph(); section.Footers.Primary.Add(footerPar); - // add report title + // create a quick PDF doc renderer to measure footer paragraph height + var footerParagraphHeight = 0.4m; // estimate + var footerOnlyPdfDoc = new Document(); + var sectionClone = section.Clone(); + footerOnlyPdfDoc.Add(sectionClone); + sectionClone.Add(GetFooterParagraph()); + var footerPdfRenderer = new PdfDocumentRenderer + { + Document = footerOnlyPdfDoc + }; + footerPdfRenderer.DocumentRenderer.PrepareDocument(); + var footerRenderInfo = footerPdfRenderer.DocumentRenderer.GetRenderInfoFromPage(1); + if (footerRenderInfo != null) + { + foreach (var item in footerRenderInfo) + { + if (item.DocumentObject.Tag?.ToString() == "FooterPar") + { + Console.WriteLine("Got footer paragraph height!"); + footerParagraphHeight = (decimal)item.LayoutInfo.ContentArea.Height.Inch; + break; + } + } + } + // continue setting up document + // First page only: add report title var reportTitlePar = section.AddParagraph(); reportTitlePar.Format.Alignment = ParagraphAlignment.Center; reportTitlePar.Format.Font.Size = 16; reportTitlePar.Format.Font.Bold = true; reportTitlePar.Format.Font.Name = "Noto Sans JP"; // has english letters in it, too reportTitlePar.AddText(ReportTitle); + reportTitlePar.Tag = "TitlePar"; // get converted files directory path and create it if necessary var convertedDir = Path.Combine(Utilities.GetInternalDataPath(), "converted"); if (!Directory.Exists(convertedDir)) @@ -711,8 +772,11 @@ class MainViewModel : BaseViewModel, IFontResolver, ICanCheckShutdown Directory.CreateDirectory(convertedDir); } // - GlobalFontSettings.FontResolver = this; - GlobalFontSettings.FallbackFontResolver = new FailsafeFontResolver(); + var pdfRenderer = new PdfDocumentRenderer + { + Document = pdfDoc, + WorkingDirectory = folderPath + }; var hasAddedData = false; for (var i = 0; i < ReportFiles.Count; i++) { @@ -739,12 +803,14 @@ class MainViewModel : BaseViewModel, IFontResolver, ICanCheckShutdown imageTitlePar.Format.Font.Bold = true; imageTitlePar.Format.Font.Name = "Noto Sans JP"; // has english letters in it, too imageTitlePar.AddText(string.IsNullOrWhiteSpace(file.Title) ? file.FileName : file.Title); + imageTitlePar.Tag = "ReceiptTitlePar"; var receiptDatePar = section.AddParagraph(); receiptDatePar.Format.Alignment = ParagraphAlignment.Center; receiptDatePar.Format.Font.Size = 12; receiptDatePar.Format.Font.Bold = true; receiptDatePar.Format.Font.Name = "Noto Sans JP"; // has english letters in it, too receiptDatePar.AddText(file.ReceiptDate.ToString("yyyy-MM-dd")); + receiptDatePar.Tag = "ReceiptDatePar"; if (!string.IsNullOrWhiteSpace(file.Notes)) { var imageNotesPar = section.AddParagraph(); @@ -753,8 +819,10 @@ class MainViewModel : BaseViewModel, IFontResolver, ICanCheckShutdown imageNotesPar.Format.Font.Bold = false; imageNotesPar.Format.Font.Name = "Noto Sans JP"; imageNotesPar.AddText(file.Notes); + imageNotesPar.Tag = "ReceiptNotesPar"; } - section.AddParagraph(); // add empty line for spacing + var emptyPar = section.AddParagraph(); // add empty line for spacing + emptyPar.Tag = "EmptyParagraph"; // now add the image var lowerName = fileName.ToLower(); var isPDF = lowerName.EndsWith(".pdf"); @@ -807,23 +875,26 @@ class MainViewModel : BaseViewModel, IFontResolver, ICanCheckShutdown filePath = convertedOutputPath; LogInfo(string.Format("Saved adjusted image to JPEG; file path is now {0}", filePath)); } + // do some calculations... + // render up to now on this page and get height remaining in inches + var currPageCount = pdfRenderer.DocumentRenderer.FormattedDocument?.PageCount; + var heightForExistingItemsOnPage = GetExistingPageItemHeight(pdfRenderer, footerParagraphHeight); + var remainingHeightInches = pageHeight - (2 * margin) - heightForExistingItemsOnPage; + var remainingHeightPixels = (remainingHeightInches * imageResolution) - imageInsertMarginPixels; // write to PDF var paragraph = section.AddParagraph(); paragraph.Format.Alignment = ParagraphAlignment.Center; var image = paragraph.AddImage(filePath); - const int imageResolution = 72; image.Resolution = imageResolution; // dots per inch - paragraph.Tag = "ImageParagraphTag"; - // - //var maxItemPxWidth = ((pageWidth - (2 * margin)) * imageResolution) - 20; - //var maxItemPxHeight = ((pageHeight - (2 * margin)) * imageResolution) - 20; - //Console.WriteLine("Max width test: {0}; height: {1}", maxItemPxWidth, maxItemPxHeight); + image.Tag = "ReceiptImageTag"; + paragraph.Tag = "ReceiptImageParagraphTag"; image.LineFormat = imageLineFormat.Clone(); - // image.LockAspectRatio = true; - while (loadedImageHeight > 600 || loadedImageWidth > 550) + // resize down until it will fit on the page + while (loadedImageHeight > remainingHeightPixels || loadedImageWidth > maxItemPxWidth) { // Console.WriteLine("Image height = {0}, width = {1}; decreasing size by 5% to h={2}, w={3}", loadedImageHeight, loadedImageWidth, (uint)Math.Floor(loadedImageHeight * 0.95), (uint)Math.Floor(loadedImageWidth * 0.95)); - // keep reducing size by 10% until it fits on the page + // keep reducing size by 5% (little by little) until it fits on the page + // ...might skew ever so slightly but should not be noticable... loadedImageHeight = (uint)Math.Floor(loadedImageHeight * 0.95); loadedImageWidth = (uint)Math.Floor(loadedImageWidth * 0.95); } @@ -917,13 +988,10 @@ class MainViewModel : BaseViewModel, IFontResolver, ICanCheckShutdown LogInfo(string.Format("Added image: {0} ({1})", file.Title, filePath)); hasAddedData = true; } - var pdfRenderer = new PdfDocumentRenderer - { - Document = pdfDoc, - WorkingDirectory = folderPath - }; LogInfo("Rendering document to PDF file..."); + pdfRenderer.DocumentRenderer.PrepareDocument(); // needed if you make edits after first PrepareDocument() is called pdfRenderer.RenderDocument(); + // actually save to disk now string outputPDFFilePath = Path.Join(outputDir, outputFileName); LogInfo("Saving PDF document to disk..."); pdfRenderer.PdfDocument.Save(outputPDFFilePath); From f34a7092e474e5e3c02d88ac6b15b269d733d85d Mon Sep 17 00:00:00 2001 From: Michael Babienco Date: Thu, 12 Mar 2026 21:09:34 +0900 Subject: [PATCH 08/13] Resize PDF images too (Docnet rendering) --- src/ViewModels/MainViewModel.cs | 46 ++++++++++++++++++++++++++++----- 1 file changed, 39 insertions(+), 7 deletions(-) diff --git a/src/ViewModels/MainViewModel.cs b/src/ViewModels/MainViewModel.cs index 35eedf8..fe9445b 100644 --- a/src/ViewModels/MainViewModel.cs +++ b/src/ViewModels/MainViewModel.cs @@ -834,6 +834,14 @@ class MainViewModel : BaseViewModel, IFontResolver, ICanCheckShutdown var info = new FileInfo(file.FilePath); uint loadedImageWidth = 0; uint loadedImageHeight = 0; + // get max pixel height remaining for items on this page + // (For multi-page PDFs, showing page 2 and on will have more height since they have no title, + // but to keep things consistent we will use the same height for all PDF pages.) + // render up to now on this page and get height remaining in inches + var currPageCount = pdfRenderer.DocumentRenderer.FormattedDocument?.PageCount; + var heightForExistingItemsOnPage = GetExistingPageItemHeight(pdfRenderer, footerParagraphHeight); + var remainingHeightInches = pageHeight - (2 * margin) - heightForExistingItemsOnPage; + var remainingHeightPixels = (remainingHeightInches * imageResolution) - imageInsertMarginPixels; if (!isPDF) { using var mImage = new MagickImage(info.FullName); @@ -875,12 +883,6 @@ class MainViewModel : BaseViewModel, IFontResolver, ICanCheckShutdown filePath = convertedOutputPath; LogInfo(string.Format("Saved adjusted image to JPEG; file path is now {0}", filePath)); } - // do some calculations... - // render up to now on this page and get height remaining in inches - var currPageCount = pdfRenderer.DocumentRenderer.FormattedDocument?.PageCount; - var heightForExistingItemsOnPage = GetExistingPageItemHeight(pdfRenderer, footerParagraphHeight); - var remainingHeightInches = pageHeight - (2 * margin) - heightForExistingItemsOnPage; - var remainingHeightPixels = (remainingHeightInches * imageResolution) - imageInsertMarginPixels; // write to PDF var paragraph = section.AddParagraph(); paragraph.Format.Alignment = ParagraphAlignment.Center; @@ -940,10 +942,23 @@ class MainViewModel : BaseViewModel, IFontResolver, ICanCheckShutdown pgCount == 1 ? "" : "s")); var paragraph = section.AddParagraph(); paragraph.Format.Alignment = ParagraphAlignment.Center; + // get image height/width off of disk so we can resize down if needed var image = paragraph.AddImage(convertedPdfImagePath); - image.Width = maxImageWidth; image.LockAspectRatio = true; image.LineFormat = imageLineFormat.Clone(); + using (var firstPdfPageImage = new MagickImage(convertedPdfImagePath)) + { + var pdfPageImageWidth = firstPdfPageImage.Width; + var pdfPageImageHeight = firstPdfPageImage.Height; + // resize down until it will fit on the page + while (pdfPageImageHeight > remainingHeightPixels || pdfPageImageWidth > maxItemPxWidth) + { + pdfPageImageHeight = (uint)Math.Floor(pdfPageImageHeight * 0.95); + pdfPageImageWidth = (uint)Math.Floor(pdfPageImageWidth * 0.95); + } + image.Height = pdfPageImageHeight; + image.Width = pdfPageImageWidth; + } for (var j = 1; j < pgCount; j++) { section.AddPageBreak(); @@ -954,11 +969,28 @@ class MainViewModel : BaseViewModel, IFontResolver, ICanCheckShutdown image.LockAspectRatio = true; image.Width = maxImageWidth; image.LineFormat = imageLineFormat.Clone(); + using (var otherPdfPageImage = new MagickImage(convertedPdfImagePath)) + { + var pdfPageImageWidth = otherPdfPageImage.Width; + var pdfPageImageHeight = otherPdfPageImage.Height; + // resize down until it will fit on the page + while (pdfPageImageHeight > remainingHeightPixels || pdfPageImageWidth > maxItemPxWidth) + { + pdfPageImageHeight = (uint)Math.Floor(pdfPageImageHeight * 0.95); + pdfPageImageWidth = (uint)Math.Floor(pdfPageImageWidth * 0.95); + } + image.Height = pdfPageImageHeight; + image.Width = pdfPageImageWidth; + } } } } else { + // use older, not-docnet rendering method. + // uses MigraDoc rendering. Does not work with annotations, and since Migradoc + // doesn't let us know how big the image is, we can't do the image resizing, so + // we just do our best. // render first page (eventually need to improve code to just do everything in a loop) var paragraph = section.AddParagraph(); paragraph.Format.Alignment = ParagraphAlignment.Center; From a1858443e8b7e8e4226c02682f4728b685f9a342 Mon Sep 17 00:00:00 2001 From: Michael Babienco Date: Thu, 12 Mar 2026 21:17:27 +0900 Subject: [PATCH 09/13] Bump version number --- installers/WindowsInstallerScript.iss | 2 +- installers/build-linux.sh | 2 +- src/Helpers/Constants.cs | 2 +- src/MayShow.csproj | 2 +- src/Views/AboutView.axaml | 2 +- src/app.manifest | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/installers/WindowsInstallerScript.iss b/installers/WindowsInstallerScript.iss index f779b13..7ba1045 100644 --- a/installers/WindowsInstallerScript.iss +++ b/installers/WindowsInstallerScript.iss @@ -3,7 +3,7 @@ ; Non-commercial use only #define MyAppName "MayShow" -#define MyAppVersion "1.4.0" +#define MyAppVersion "1.4.1" #define MyAppPublisher "Quickity Quack Productions" #define MyAppExeName "MayShow.exe" diff --git a/installers/build-linux.sh b/installers/build-linux.sh index ac41679..c8f1d93 100755 --- a/installers/build-linux.sh +++ b/installers/build-linux.sh @@ -1,6 +1,6 @@ #!/bin/bash -VERSION="1.4.0" +VERSION="1.4.1" SRC_DIR="src" # user ran script from main folder if [ ! -d "$SRC_DIR" ]; then SRC_DIR= "../src" # try diff --git a/src/Helpers/Constants.cs b/src/Helpers/Constants.cs index 754a9ea..c86ce7a 100644 --- a/src/Helpers/Constants.cs +++ b/src/Helpers/Constants.cs @@ -3,7 +3,7 @@ namespace MayShow.Helpers; class Constants { - public static string AppVersion = "1.4.0"; + public static string AppVersion = "1.4.1"; public static string[] AllowedFileExtensionPatterns = [ "*.png", "*.jpg", "*.jpeg", "*.gif", "*.bmp", "*.webp", "*.pdf", "*.heic", ]; public static string[] AllowedFileExtensionsNoStar = [ "png", "jpg", "jpeg", "gif", "bmp", "webp", "pdf", "heic", ]; diff --git a/src/MayShow.csproj b/src/MayShow.csproj index e08c7ca..6db71ab 100644 --- a/src/MayShow.csproj +++ b/src/MayShow.csproj @@ -12,7 +12,7 @@ true true MayShow - 1.4.0 + 1.4.1 MayShow-icon.ico diff --git a/src/Views/AboutView.axaml b/src/Views/AboutView.axaml index 6803d30..39f574c 100644 --- a/src/Views/AboutView.axaml +++ b/src/Views/AboutView.axaml @@ -11,7 +11,7 @@ MaxWidth="450"> - - + From de621fe9dc28698f08bb98e6add391f44f125498 Mon Sep 17 00:00:00 2001 From: Michael Babienco Date: Fri, 13 Mar 2026 08:05:11 +0900 Subject: [PATCH 10/13] Add another file name date parsing format Also redid code so more formats would be easy --- src/Helpers/Utilities.cs | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/src/Helpers/Utilities.cs b/src/Helpers/Utilities.cs index fb2ebc9..4e3444c 100644 --- a/src/Helpers/Utilities.cs +++ b/src/Helpers/Utilities.cs @@ -1,10 +1,12 @@ using System; +using System.Collections.Generic; using System.Globalization; using System.IO; using System.Text.Json; using System.Text.Json.Serialization; using System.Text.RegularExpressions; +using Tmds.DBus.Protocol; namespace MayShows.Helpers; @@ -23,16 +25,26 @@ class Utilities public static DateOnly? CheckValidDateInString(string str) { // https://stackoverflow.com/a/14918404/3938401 - var rgx = new Regex(@"\d{4}-\d{2}-\d{2}"); - var mat = rgx.Match(str); - if (mat.Success) + // formats = regex format -> DateTime parsing format + var formats = new Dictionary { - var dtStr = mat.ToString(); - string[] formats = ["yyyy-MM-dd"]; - DateTime parsedDateTime; - var didWork = DateTime.TryParseExact(dtStr, formats, CultureInfo.InvariantCulture, - DateTimeStyles.None, out parsedDateTime); - return didWork ? DateOnly.FromDateTime(parsedDateTime) : null; + {@"\d{4}-\d{2}-\d{2}", "yyyy-MM-dd"}, + {@"\d{8}", "yyyyMMdd"} + }; + foreach (var data in formats) + { + var rgx = new Regex(data.Key); + var mat = rgx.Match(str); + if (mat.Success) + { + var dtStr = mat.ToString(); + var didWork = DateTime.TryParseExact(dtStr, [data.Value], CultureInfo.InvariantCulture, + DateTimeStyles.None, out var parsedDateTime); + if (didWork) + { + return DateOnly.FromDateTime(parsedDateTime); + } + } } return null; } From cd71df8a8ea2a7ce15f1a0481a7a403de8cc78e3 Mon Sep 17 00:00:00 2001 From: Michael Babienco Date: Fri, 13 Mar 2026 08:10:11 +0900 Subject: [PATCH 11/13] Add yyyy.MM.dd to acceptable formats --- src/Helpers/Utilities.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Helpers/Utilities.cs b/src/Helpers/Utilities.cs index 4e3444c..eac9b18 100644 --- a/src/Helpers/Utilities.cs +++ b/src/Helpers/Utilities.cs @@ -29,6 +29,7 @@ class Utilities var formats = new Dictionary { {@"\d{4}-\d{2}-\d{2}", "yyyy-MM-dd"}, + {@"\d{4}.d{2}.d{2}", "yyyy.MM.dd"}, {@"\d{8}", "yyyyMMdd"} }; foreach (var data in formats) From f4dd498d22b9cf2ee7cf16006c01569e533330cc Mon Sep 17 00:00:00 2001 From: Michael Babienco Date: Fri, 13 Mar 2026 08:14:50 +0900 Subject: [PATCH 12/13] Shortcut to view settings dir --- src/ViewModels/SettingsViewModel.cs | 13 +++++++++++++ src/Views/SettingsView.axaml | 5 +++++ 2 files changed, 18 insertions(+) diff --git a/src/ViewModels/SettingsViewModel.cs b/src/ViewModels/SettingsViewModel.cs index 4b11678..06663c2 100644 --- a/src/ViewModels/SettingsViewModel.cs +++ b/src/ViewModels/SettingsViewModel.cs @@ -18,6 +18,7 @@ using PdfSharp.Snippets.Font; using MayShow.Interfaces; using MayShow.Models; using MayShow.Helpers; +using MayShows.Helpers; namespace MayShow.ViewModels; @@ -126,6 +127,18 @@ class SettingsViewModel: ChangeNotifier } } + public void OpenSettingsDir() + { + var topLevel = _topLevelGrabber?.GetTopLevel(); + Console.WriteLine(Utilities.GetInternalDataPath()); + var dirName = Utilities.GetInternalDataPath(); + if (topLevel is not null && dirName != null) + { + var launcher = topLevel.Launcher; + launcher.LaunchUriAsync(new Uri(dirName)); + } + } + public void Cancel() { DialogHost.Close("DialogHost", null); diff --git a/src/Views/SettingsView.axaml b/src/Views/SettingsView.axaml index 9187843..efa30b9 100644 --- a/src/Views/SettingsView.axaml +++ b/src/Views/SettingsView.axaml @@ -47,6 +47,11 @@ VerticalAlignment="Top"/> Save report data (names, notes, etc.) in MayShow settings directory (saves in working directory by default) + Date: Fri, 13 Mar 2026 08:18:32 +0900 Subject: [PATCH 13/13] Bump version --- installers/WindowsInstallerScript.iss | 2 +- installers/build-linux.sh | 2 +- src/Helpers/Constants.cs | 2 +- src/MayShow.csproj | 2 +- src/Views/AboutView.axaml | 2 +- src/app.manifest | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/installers/WindowsInstallerScript.iss b/installers/WindowsInstallerScript.iss index 7ba1045..0a8154e 100644 --- a/installers/WindowsInstallerScript.iss +++ b/installers/WindowsInstallerScript.iss @@ -3,7 +3,7 @@ ; Non-commercial use only #define MyAppName "MayShow" -#define MyAppVersion "1.4.1" +#define MyAppVersion "1.4.2" #define MyAppPublisher "Quickity Quack Productions" #define MyAppExeName "MayShow.exe" diff --git a/installers/build-linux.sh b/installers/build-linux.sh index c8f1d93..60d974a 100755 --- a/installers/build-linux.sh +++ b/installers/build-linux.sh @@ -1,6 +1,6 @@ #!/bin/bash -VERSION="1.4.1" +VERSION="1.4.2" SRC_DIR="src" # user ran script from main folder if [ ! -d "$SRC_DIR" ]; then SRC_DIR= "../src" # try diff --git a/src/Helpers/Constants.cs b/src/Helpers/Constants.cs index c86ce7a..11d8f05 100644 --- a/src/Helpers/Constants.cs +++ b/src/Helpers/Constants.cs @@ -3,7 +3,7 @@ namespace MayShow.Helpers; class Constants { - public static string AppVersion = "1.4.1"; + public static string AppVersion = "1.4.2"; public static string[] AllowedFileExtensionPatterns = [ "*.png", "*.jpg", "*.jpeg", "*.gif", "*.bmp", "*.webp", "*.pdf", "*.heic", ]; public static string[] AllowedFileExtensionsNoStar = [ "png", "jpg", "jpeg", "gif", "bmp", "webp", "pdf", "heic", ]; diff --git a/src/MayShow.csproj b/src/MayShow.csproj index 6db71ab..2ce8058 100644 --- a/src/MayShow.csproj +++ b/src/MayShow.csproj @@ -12,7 +12,7 @@ true true MayShow - 1.4.1 + 1.4.2 MayShow-icon.ico diff --git a/src/Views/AboutView.axaml b/src/Views/AboutView.axaml index 39f574c..90b7c28 100644 --- a/src/Views/AboutView.axaml +++ b/src/Views/AboutView.axaml @@ -11,7 +11,7 @@ MaxWidth="450"> - - +