feat: rebrand to MMD PDF, single corporate theme, and remove original text under an edit

- Services/PdfRedactText.cs: strip text whose origin falls inside a CoverAnnotation
  from the page content stream at save time, hooked into PdfBurn.DrawAnnotationsIntoDoc.
  Fixes edited values staying recoverable by text extraction.
- Themes/MMD.xaml replaces all thirteen themes; picker and accent strip removed; no dark mode.
- Rename KillerPDF -> MMD PDF across code, resources, packaging and locale strings; new icon.
- Remove the upstream author credit and the in-app install button.
This commit is contained in:
2026-08-27 07:37:09 +02:00
parent 532485a830
commit 6610acfa44
230 changed files with 9362 additions and 11508 deletions
+69
View File
@@ -0,0 +1,69 @@
using PdfSharpCore.Drawing;
using PdfSharpCore.Drawing.Layout;
using PdfSharpCore.Pdf;
using Xunit;
namespace MmdPdf.Tests
{
/// <summary>
/// Regression cover for burning multi-line text annotations into a document (#142).
/// CreateBlocks emits a Block(BlockType.LineBreak) per newline, and that constructor never sets
/// Text. CreateLayout then skips assigning those blocks a Location, so they keep XPoint(0,0) and
/// GetLines' GroupBy lumps them in with the first line. The Justify branch of DrawString called
/// block.Text.Trim() on them and threw NullReferenceException.
/// Only the Justify path was affected - the other alignments join blocks with string.Join, which
/// tolerates nulls. The short DrawString overload defaults to Justify, so MmdPdf hit it.
/// </summary>
public class TextFormatterTests
{
static void Draw(string content, TextFormatAlignment? alignment = null)
{
var doc = new PdfDocument();
var page = doc.AddPage();
var gfx = XGraphics.FromPdfPage(page);
var font = new XFont("Segoe UI", 12, XFontStyle.Regular);
var rect = new XRect(20, 20, 300, 200);
var tf = new XTextFormatter(gfx);
if (alignment == null)
tf.DrawString(content, font, XBrushes.Black, rect);
else
tf.DrawString(content, font, XBrushes.Black, rect, alignment);
}
[Fact]
public void DrawString_SingleLine_DoesNotThrow()
{
Draw("Hello world");
}
[Fact]
public void DrawString_MultiLine_DoesNotThrow()
{
// The short overload defaults to Justify - this is the exact call MmdPdf makes when
// burning a text annotation, and the one that crashed.
Draw("Hello\nworld");
}
[Fact]
public void DrawString_MultiLineCrLf_DoesNotThrow()
{
Draw("Hello\r\nworld");
}
[Fact]
public void DrawString_MultiLineLeftAligned_DoesNotThrow()
{
// What the annotation burn now passes explicitly, matching the on-screen TextBlock.
Draw("Hello\nworld", new TextFormatAlignment { Horizontal = XParagraphAlignment.Left });
}
[Fact]
public void DrawString_ConsecutiveNewlines_DoesNotThrow()
{
// A blank line produces two adjacent LineBreak blocks, so the line group is entirely
// non-drawable. Guards the empty-after-filter path.
Draw("Hello\n\n\nworld");
}
}
}