Standard14WritingFontTests Add tests of invalid characters for each standard font

This commit is contained in:
Fred Natzke
2022-12-20 14:17:02 +10:00
parent 8f13e2f11c
commit 7b441a3b0a
2 changed files with 373 additions and 6 deletions

View File

@@ -13,11 +13,9 @@
using System.Reflection;
using System.Collections.Generic;
using UglyToad.PdfPig.Fonts.AdobeFontMetrics;
using System.IO;
using System.Drawing;
using System.IO;
using System.Diagnostics;
using System.Reflection.Emit;
using System.Text;
public class Standard14WritingFontTests
{
@@ -38,6 +36,7 @@
double leftX = 1 * cm;
var point = new PdfPoint(leftX, topPageY);
DateTimeStampPage(pdfBuilder, page, point, cm);
var letters = page.AddText("Adobe Standard Font ZapfDingbats", 21, point, F2);
var newY = topPageY - letters.Select(v => v.GlyphRectangle.Height).Max() * 1.2;
point = new PdfPoint(leftX, newY);
@@ -122,6 +121,89 @@
}
}
[Fact]
public void ZapfDingbatsFontErrorResponseAddingInvalidText()
{
PdfDocumentBuilder pdfBuilder = new PdfDocumentBuilder();
PdfDocumentBuilder.AddedFont F1 = pdfBuilder.AddStandard14Font(Standard14Font.ZapfDingbats);
var EncodingTable = GetEncodingTable(typeof(UglyToad.PdfPig.Fonts.Encodings.ZapfDingbatsEncoding));
{
PdfPageBuilder page = pdfBuilder.AddPage(PageSize.A4);
var cm = (page.PageSize.Width / 8.5 / 2.54);
var point = new PdfPoint(cm, page.PageSize.Top - cm);
{
// Get the codes that have no character associated in the font specific coding.
var codesUnder255 = Enumerable.Range(0, 255).Select(v => (char)v).ToArray();
var codesFromEncodingTable = EncodingTable.Select(v => (char)v.code).ToArray();
var invalidCharactersUnder255 = codesUnder255.Except(codesFromEncodingTable);
//Debug.WriteLine($"Number of invalid under 255 characters: {invalidCharactersUnder255.Count()}");
Assert.Equal(67, invalidCharactersUnder255.Count());
foreach (var ch in invalidCharactersUnder255)
{
try
{
var letter = page.AddText($"{ch}", 12, point, F1);
Assert.True(true, $"Unexpected. Character: '{ch}' (0x{(int)ch:X}) should throw. Not supported.");
}
catch (InvalidOperationException ex)
{
// Expected
// "The font does not contain a character: '?' (0xnn)." where ? is a character and nn is hex number.
Assert.Contains("The font does not contain a character", ex.Message);
}
try
{
var letter = page.MeasureText($"{ch}", 12, point, F1);
Assert.True(true, $"Unexpected. Character: '{ch}' (0x{(int)ch:X}) should throw. Not supported.");
}
catch (InvalidOperationException ex)
{
// Expected
// "The font does not contain a character: '?' (0xnn)." where ? is a character and nn is hex number.
Assert.Contains("The font does not contain a character", ex.Message);
}
}
}
{
// UnicodeRanges.Dingbats - 0x2700 - 0x27BF
var codesFromUnicodeDingbatBlock = Enumerable.Range(0x2700, 0xBF).Select(v => (char)v).ToArray();
var unicodesCharacters = GetUnicodeCharacters(EncodingTable, GlyphList.ZapfDingbats);
var invalidCharactersInUnicodeDingbaBlock = codesFromUnicodeDingbatBlock.Except(unicodesCharacters);
//Debug.WriteLine($"Number of invalid unicode characters: {invalidCharactersInUnicodeDingbaBlock.Count()}");
Assert.Equal(31, invalidCharactersInUnicodeDingbaBlock.Count());
foreach (var ch in invalidCharactersInUnicodeDingbaBlock)
{
try
{
var letter = page.AddText($"{ch}", 12, point, F1);
Assert.True(true, $"Unexpected. Character: '{ch}' (0x{(int)ch:X}) should throw. Not supported.");
}
catch (InvalidOperationException ex)
{
// Expected
// "The font does not contain a character: '?' (0xnn)." where ? is a character and nn is hex number.
Assert.Contains("The font does not contain a character", ex.Message);
}
try
{
var letter = page.MeasureText($"{ch}", 12, point, F1);
Assert.True(true, $"Unexpected. Character: '{ch}' (0x{(int)ch:X}) should throw. Not supported.");
}
catch (InvalidOperationException ex)
{
// Expected
// "The font does not contain a character: '?' (0xnn)." where ? is a character and nn is hex number.
Assert.Contains("The font does not contain a character", ex.Message);
}
}
}
}
}
[Fact]
public void SymbolFontAddText()
{
@@ -139,6 +221,7 @@
double leftX = 1 * cm;
var point = new PdfPoint(leftX, topPageY);
DateTimeStampPage(pdfBuilder, page, point, cm);
var letters = page.AddText("Adobe Standard Font Symbol ", 21, point, F2);
var newY = topPageY - letters.Select(v => v.GlyphRectangle.Height).Max() * 1.2;
point = new PdfPoint(leftX, newY);
@@ -238,6 +321,110 @@
}
}
[Fact]
public void SymbolFontErrorResponseAddingInvalidText()
{
PdfDocumentBuilder pdfBuilder = new PdfDocumentBuilder();
PdfDocumentBuilder.AddedFont F1 = pdfBuilder.AddStandard14Font(Standard14Font.Symbol);
var EncodingTable = GetEncodingTable(typeof(UglyToad.PdfPig.Fonts.Encodings.SymbolEncoding));
{
PdfPageBuilder page = pdfBuilder.AddPage(PageSize.A4);
var cm = (page.PageSize.Width / 8.5 / 2.54);
var point = new PdfPoint(cm, page.PageSize.Top - cm);
{
// Get the codes that have no character associated in the font specific coding.
var codesUnder255 = Enumerable.Range(0, 255).Select(v => (char)v).ToArray();
var codesFromEncodingTable = EncodingTable.Select(v => (char)v.code).ToArray();
var invalidCharactersUnder255 = codesUnder255.Except(codesFromEncodingTable);
Debug.WriteLine($"Number of invalid under 255 characters: {invalidCharactersUnder255.Count()}");
foreach (var ch in invalidCharactersUnder255)
{
try
{
var letter = page.AddText($"{ch}", 12, point, F1);
Assert.True(true, $"Unexpected. Character: '{ch}' (0x{(int)ch:X}) should throw. Not supported.");
}
catch (InvalidOperationException ex)
{
// Expected
// "The font does not contain a character: '?' (0xnn)." where ? is a character and nn is hex number.
Assert.Contains("The font does not contain a character", ex.Message);
}
try
{
var letter = page.MeasureText($"{ch}", 12, point, F1);
Assert.True(true, $"Unexpected. Character: '{ch}' (0x{(int)ch:X}) should throw. Not supported.");
}
catch (InvalidOperationException ex)
{
// Expected
// "The font does not contain a character: '?' (0xnn)." where ? is a character and nn is hex number.
Assert.Contains("The font does not contain a character", ex.Message);
}
}
}
{
var unicodesCharacters = GetUnicodeCharacters(EncodingTable, GlyphList.AdobeGlyphList);
var randomCharacters = new char[10];
{
var listUnicodeCharacters = unicodesCharacters.Select(v => (int)v).ToList();
var rnd = new Random();
int nextIndex = 0;
while (nextIndex < randomCharacters.Length)
{
var value = rnd.Next(0x10ffff);
if (listUnicodeCharacters.Contains(value)) { continue; }
char ch = (char)value;
int i = (int)ch;
if (i >= 0xd800 && i <= 0xdfff) { continue; }
randomCharacters[nextIndex++] = ch;
Debug.WriteLine($"{value:X}");
}
}
foreach (var ch in randomCharacters)
{
int i = (int)ch;
if (i > 0x10ffff) {
Debug.WriteLine("Unexpected unicode point. Too large to be unicode. Expected: <0x10ffff. Got: 0x{i:X}");
continue;
}
if (i >= 0xd800 && i<=0xdfff)
{
Debug.WriteLine("Unexpected unicode point that is not a surrogate Expected: <0xd800 && >0xdfff. Got: 0x{i:X}");
continue;
}
try
{
var letter = page.AddText($"{ch}", 12, point, F1);
Assert.True(true, $"Unexpected. Character: '{ch}' (0x{(int)ch:X}) should throw. Not supported.");
}
catch (InvalidOperationException ex)
{
// Expected
// "The font does not contain a character: '?' (0xnn)." where ? is a character and nn is hex number.
Assert.Contains("The font does not contain a character", ex.Message);
}
try
{
var letter = page.MeasureText($"{ch}", 12, point, F1);
Assert.True(true, $"Unexpected. Character: '{ch}' (0x{(int)ch:X}) should throw. Not supported.");
}
catch (InvalidOperationException ex)
{
// Expected
// "The font does not contain a character: '?' (0xnn)." where ? is a character and nn is hex number.
Assert.Contains("The font does not contain a character", ex.Message);
}
}
}
}
}
[Fact]
public void StandardFontsAddText()
{
@@ -309,6 +496,7 @@
double leftX = 1 * cm;
var point = new PdfPoint(leftX, topPageY);
DateTimeStampPage(pdfBuilder, page, point, cm);
var letters = page.AddText("Adobe Standard Font "+ fontName, 21, point, F2);
var newY = topPageY - letters.Select(v => v.GlyphRectangle.Height).Max() * 1.2;
point = new PdfPoint(leftX, newY);
@@ -446,7 +634,155 @@
}
}
[Fact]
public void StandardFontErrorResponseAddingInvalidText()
{
PdfDocumentBuilder pdfBuilder = new PdfDocumentBuilder();
PdfPageBuilder page = pdfBuilder.AddPage(PageSize.A4);
var cm = (page.PageSize.Width / 8.5 / 2.54);
var point = new PdfPoint(cm, page.PageSize.Top - cm);
PdfDocumentBuilder.AddedFont[] standardFontsWithStandardEncoding;
{
PdfDocumentBuilder.AddedFont F1 = pdfBuilder.AddStandard14Font(Standard14Font.TimesRoman);
PdfDocumentBuilder.AddedFont F2 = pdfBuilder.AddStandard14Font(Standard14Font.TimesBold);
PdfDocumentBuilder.AddedFont F3 = pdfBuilder.AddStandard14Font(Standard14Font.TimesItalic);
PdfDocumentBuilder.AddedFont F4 = pdfBuilder.AddStandard14Font(Standard14Font.TimesBoldItalic);
PdfDocumentBuilder.AddedFont F5 = pdfBuilder.AddStandard14Font(Standard14Font.Helvetica);
PdfDocumentBuilder.AddedFont F6 = pdfBuilder.AddStandard14Font(Standard14Font.HelveticaBold);
PdfDocumentBuilder.AddedFont F7 = pdfBuilder.AddStandard14Font(Standard14Font.HelveticaOblique);
PdfDocumentBuilder.AddedFont F8 = pdfBuilder.AddStandard14Font(Standard14Font.HelveticaBoldOblique);
PdfDocumentBuilder.AddedFont F9 = pdfBuilder.AddStandard14Font(Standard14Font.Courier);
PdfDocumentBuilder.AddedFont F10 = pdfBuilder.AddStandard14Font(Standard14Font.CourierBold);
PdfDocumentBuilder.AddedFont F11 = pdfBuilder.AddStandard14Font(Standard14Font.CourierOblique);
PdfDocumentBuilder.AddedFont F12 = pdfBuilder.AddStandard14Font(Standard14Font.CourierBoldOblique);
standardFontsWithStandardEncoding = new PdfDocumentBuilder.AddedFont[]
{
F1,
F2,
F3,
F4,
F5,
F6,
F7,
F8,
F9,
F10,
F11,
F12
};
}
var EncodingTable = GetEncodingTable(typeof(UglyToad.PdfPig.Fonts.Encodings.StandardEncoding));
// Get the codes that have no character associated in the font specific coding.
char[] invalidCharactersUnder255;
{
var codesUnder255 = Enumerable.Range(0, 255).Select(v => (char)v).ToArray();
var codesFromEncodingTable = EncodingTable.Select(v => (char)v.code).ToArray();
invalidCharactersUnder255 = codesUnder255.Except(codesFromEncodingTable).ToArray();
Debug.WriteLine($"Number of invalid under 255 characters: {invalidCharactersUnder255.Count()}");
}
// Get random unicodes not valid for any font with Standard encoding.
var randomUnicodeCharacters = new char[10];
{
var unicodesCharacters = GetUnicodeCharacters(EncodingTable, GlyphList.AdobeGlyphList);
{
var listUnicodeCharacters = unicodesCharacters.Select(v => (int)v).ToList();
var rnd = new Random();
int nextIndex = 0;
while (nextIndex < randomUnicodeCharacters.Length)
{
var value = rnd.Next(0x10ffff);
if (listUnicodeCharacters.Contains(value)) { continue; }
char ch = (char)value;
int i = (int)ch;
if (i >= 0xd800 && i <= 0xdfff) { continue; }
randomUnicodeCharacters[nextIndex++] = ch;
Debug.WriteLine($"{value:X}");
}
}
}
int fontNumber = 0;
foreach (var font in standardFontsWithStandardEncoding)
{
fontNumber++;
var storedFont = pdfBuilder.Fonts[font.Id];
var fontProgram = storedFont.FontProgram;
var fontName = fontProgram.Name;
foreach (var ch in invalidCharactersUnder255)
{
try
{
var letter = page.AddText($"{ch}", 12, point, font);
Assert.True(true, $"Unexpected. Character: '{ch}' (0x{(int)ch:X}) should throw. Not supported. Font: '{fontName}'");
}
catch (InvalidOperationException ex)
{
// Expected
// "The font does not contain a character: '?' (0xnn)." where ? is a character and nn is hex number.
Assert.Contains("The font does not contain a character", ex.Message);
}
try
{
var letter = page.MeasureText($"{ch}", 12, point, font);
Assert.True(true, $"Unexpected. Character: '{ch}' (0x{(int)ch:X}) should throw. Not supported. Font: '{fontName}'");
}
catch (InvalidOperationException ex)
{
// Expected
// "The font does not contain a character: '?' (0xnn)." where ? is a character and nn is hex number.
Assert.Contains("The font does not contain a character", ex.Message);
}
}
foreach (var ch in randomUnicodeCharacters)
{
int i = (int)ch;
if (i > 0x10ffff)
{
Debug.WriteLine("Unexpected unicode point. Too large to be unicode. Expected: <0x10ffff. Got: 0x{i:X}");
continue;
}
if (i >= 0xd800 && i <= 0xdfff)
{
Debug.WriteLine("Unexpected unicode point that is not a surrogate Expected: <0xd800 && >0xdfff. Got: 0x{i:X}");
continue;
}
try
{
var letter = page.AddText($"{ch}", 12, point, font);
Assert.True(true, $"Unexpected. Character: '{ch}' (0x{(int)ch:X}) should throw. Not supported.");
}
catch (InvalidOperationException ex)
{
// Expected
// "The font does not contain a character: '?' (0xnn)." where ? is a character and nn is hex number.
Assert.Contains("The font does not contain a character", ex.Message);
}
try
{
var letter = page.MeasureText($"{ch}", 12, point, font);
Assert.True(true, "Unexpected. Character: '{ch}' (0x{(int)ch:X}) should throw. Not supported.");
}
catch (InvalidOperationException ex)
{
// Expected
// "The font does not contain a character: '?' (0xnn)." where ? is a character and nn is hex number.
Assert.Contains("The font does not contain a character", ex.Message);
}
}
}
}
internal PdfPoint AddLetterWithContext( PdfPoint point, string stringToAdd, ( PdfDocumentBuilder.AddedFont font, PdfPageBuilder page, string fontName, PdfDocumentBuilder.AddedFont fontLabel, double maxCharacterHeight, double maxCharacterWidth)context, bool isOctalLabel = false, bool isHexLabel = false)
{
var font = context.font;
@@ -578,5 +914,36 @@
var Standard14Cache = (Dictionary<string, AdobeFontMetrics>)Standard14CacheFieldInfos.FirstOrDefault(v => v.Name == "Standard14Cache").GetValue(null);
return Standard14Cache;
}
private static void DateTimeStampPage(PdfDocumentBuilder pdfBuilder, PdfPageBuilder page, PdfPoint point, double cm)
{
var courierFont = pdfBuilder.AddStandard14Font(Standard14Font.Courier);
var stampTextUTC = " UTC: " + DateTime.UtcNow.ToString("yyyy-MMM-dd HH:mm");
var stampTextLocal = "Local: " + DateTimeOffset.Now.ToString("yyyy-MMM-dd HH:mm zzz");
const decimal fontSize = 7m;
var indentFromLeft = page.PageSize.Width - cm;
{
var mtUTC = page.MeasureText(stampTextUTC, fontSize, point, courierFont);
var mtlocal = page.MeasureText(stampTextLocal, fontSize, point, courierFont);
var widthUTC = mtUTC.Sum(v => v.GlyphRectangle.Width);
var widthLocal = mtlocal.Sum(v => v.GlyphRectangle.Width);
indentFromLeft -= Math.Max(widthUTC, widthLocal);
}
{
point = new PdfPoint(indentFromLeft, point.Y);
var letters = page.AddText(stampTextUTC, 7m, point, courierFont);
var maxHeight = letters.Max(v=>v.GlyphRectangle.Height);
point = new PdfPoint(indentFromLeft, point.Y - maxHeight * 1.2);
}
{
var letters = page.AddText(stampTextLocal, 7m, point, courierFont);
}
}
}
}

View File

@@ -849,7 +849,7 @@
if (!font.TryGetBoundingBox(c, out var rect))
{
throw new InvalidOperationException($"The font does not contain a character: {c}.");
throw new InvalidOperationException($"The font does not contain a character: '{c}' (0x{(int)c:X}).");
}
if (!font.TryGetAdvanceWidth(c, out var charWidth))