using System; using System.Text; using Amphora; using Glass.Typesetting; using UnitTestSharp; namespace Glass.UnitTests.Typesetting { /// /// Typesetting a view of a char[] has to give what typesetting the same characters as a string does. /// public class CharArrayBackingTests : TestFixture { public static readonly string SoftHyphen = ((char)0x00AD).ToString(); public static readonly string LoneHighSurrogate = ((char)0xD800).ToString(); public static readonly string LoneLowSurrogate = ((char)0xDC00).ToString(); public static readonly string Grin = char.ConvertFromUtf32(0x1F600); public static readonly string[] Texts = { "", "a", "hello world", " padded on both sides ", "one two three four", "first\nsecond\r\nthird\rfourth\n", "soft" + SoftHyphen + "hyphenated word", "price 1,234.56 or 12% off (20%)", "grin " + Grin + " pair and " + Grin + Grin, "lone " + LoneHighSurrogate + " high and " + LoneLowSurrogate + " low", "AVAVAWAY To Ty Yo", "café naïve résumé", "漢字かな交じり文 mixed with latin", "the quick brown fox jumps over the lazy dog the quick brown fox jumps over the lazy dog " + "the quick brown fox jumps over the lazy dog", }; public static StringView InArray(string text) { char[] padded = ("<<" + text + ">>").ToCharArray(); return new StringView(padded, 2, 2 + text.Length); } public static StringView InString(string text) { return new StringView("<<" + text + ">>", 2, 2 + text.Length); } /// /// Returns what differs when reads the text from a char[] instead of a string, or /// an empty string when nothing does. /// public static string Mismatch(Func describe) { foreach (string text in Texts) { string expected = describe(new StringView(text)); string inString = describe(InString(text)); string inArray = describe(InArray(text)); if (inString != expected) { return "in a padded string \"" + text + "\": " + inString + " but alone " + expected; } if (inArray != expected) { return "in an array \"" + text + "\": " + inArray + " but alone " + expected; } } return ""; } public static string Breaks(StringView text) { var breaks = new LineBreakIterator(text); var described = new StringBuilder(); while (breaks.MoveNext()) { LineBreak found = breaks.Current; described.Append(found.Position).Append('/').Append(found.ContentEnd).Append('/') .Append(found.TrailingSpaces).Append('/').Append(found.Ending).Append(found.IsMandatory ? "!" : "") .Append(' '); } return described.ToString(); } public static string Glyphs(StringView text, int width, int? height, TextOverflow overflow, int? maxLines) { var placer = new GlyphPlacer(WordMeasurerTests.SharedFont, text, width, Alignment.Horizontal.Left, height, overflow, maxLines); var described = new StringBuilder(); while (placer.MoveNext()) { described.Append(placer.Index).Append(':').Append(placer.X).Append(':').Append(placer.Y).Append(':') .Append(placer.Advance).Append(' '); } return described.ToString() + placer.LineCount; } public static string Sizes(StringView text) { IFontMetrics font = WordMeasurerTests.SharedFont; return LineLayout.CalculateSize(font, text) + " " + LineLayout.CalculateSize(font, text, 60, null, TextOverflow.Clip) + " " + LineLayout.CalculateSize(font, text, 90, 40, TextOverflow.Ellipsis) + " " + LineLayout.CalculateSize(font, text, 90, null, TextOverflow.Ellipsis, maxLines: 2); } public class LineBreakIteratorBackingTests : TestFixture { public void FindsTheSameBreaks() { CheckEqual("", Mismatch(Breaks)); } } public class WordMeasurerBackingTests : TestFixture { public void MeasuresTheSameWords() { CheckEqual("", Mismatch(text => string.Join("|", WordMeasurerTests.Words(text)))); } } public class TextWidthBackingTests : TestFixture { public void CalculatesTheSameWidth() { CheckEqual("", Mismatch(text => TextWidth.Calculate(WordMeasurerTests.SharedFont, text).ToString())); } } public class LineLayoutBackingTests : TestFixture { public void CalculatesTheSameSizes() { CheckEqual("", Mismatch(Sizes)); } } public class GlyphPlacerBackingTests : TestFixture { public void PlacesTheSameGlyphsUnbounded() { CheckEqual("", Mismatch(text => Glyphs(text, int.MaxValue, null, TextOverflow.Clip, null))); } public void PlacesTheSameGlyphsWrapped() { CheckEqual("", Mismatch(text => Glyphs(text, 60, null, TextOverflow.Clip, null))); } public void PlacesTheSameGlyphsTruncatedWithAnEllipsis() { CheckEqual("", Mismatch(text => Glyphs(text, 90, 40, TextOverflow.Ellipsis, null))); } public void PlacesTheSameGlyphsInTwoLines() { CheckEqual("", Mismatch(text => Glyphs(text, 90, null, TextOverflow.Ellipsis, 2))); } } public class MismatchTests : TestFixture { public void ADescriptionThatDependsOnTheBacking_IsReported() { CheckTrue(Mismatch(text => (text.BackingForSave is string).ToString()) != ""); } public void ADescriptionThatDoesNot_IsNotReported() { CheckEqual("", Mismatch(text => text.ToString())); } } } }