committed by
GitHub
8 changed files with 745 additions and 296 deletions
@ -1,56 +0,0 @@ |
|||||
namespace Avalonia.Media.TextFormatting.Unicode |
|
||||
{ |
|
||||
internal static class BreakPairTable |
|
||||
{ |
|
||||
private static readonly byte[][] s_breakPairTable = |
|
||||
{ |
|
||||
new byte[] {4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,3,4,4,4,4,4,4,4,4,4,4,4}, |
|
||||
new byte[] {0,4,4,1,1,4,4,4,4,1,1,0,0,0,0,4,1,1,0,0,4,2,4,0,0,0,0,0,0,0,0,1,0}, |
|
||||
new byte[] {0,4,4,1,1,4,4,4,4,1,1,1,1,1,0,4,1,1,0,0,4,2,4,0,0,0,0,0,0,0,0,1,0}, |
|
||||
new byte[] {4,4,4,1,1,1,4,4,4,1,1,1,1,1,1,1,1,1,1,1,4,2,4,1,1,1,1,1,1,1,1,1,1}, |
|
||||
new byte[] {1,4,4,1,1,1,4,4,4,1,1,1,1,1,1,1,1,1,1,1,4,2,4,1,1,1,1,1,1,1,1,1,1}, |
|
||||
new byte[] {0,4,4,1,1,1,4,4,4,0,0,0,0,0,0,0,1,1,0,0,4,2,4,0,0,0,0,0,0,0,0,1,0}, |
|
||||
new byte[] {0,4,4,1,1,1,4,4,4,0,0,0,0,0,0,1,1,1,0,0,4,2,4,0,0,0,0,0,0,0,0,1,0}, |
|
||||
new byte[] {0,4,4,1,1,1,4,4,4,0,0,1,0,1,0,0,1,1,0,0,4,2,4,0,0,0,0,0,0,0,0,1,0}, |
|
||||
new byte[] {0,4,4,1,1,1,4,4,4,0,0,1,1,1,0,0,1,1,0,0,4,2,4,0,0,0,0,0,0,0,0,1,0}, |
|
||||
new byte[] {1,4,4,1,1,1,4,4,4,0,0,1,1,1,1,0,1,1,0,0,4,2,4,1,1,1,1,1,0,1,1,1,0}, |
|
||||
new byte[] {1,4,4,1,1,1,4,4,4,0,0,1,1,1,0,0,1,1,0,0,4,2,4,0,0,0,0,0,0,0,0,1,0}, |
|
||||
new byte[] {1,4,4,1,1,1,4,4,4,1,1,1,1,1,0,1,1,1,0,0,4,2,4,0,0,0,0,0,0,0,0,1,0}, |
|
||||
new byte[] {1,4,4,1,1,1,4,4,4,1,1,1,1,1,0,1,1,1,0,0,4,2,4,0,0,0,0,0,0,0,0,1,0}, |
|
||||
new byte[] {1,4,4,1,1,1,4,4,4,1,1,1,1,1,0,1,1,1,0,0,4,2,4,0,0,0,0,0,0,0,0,1,0}, |
|
||||
new byte[] {0,4,4,1,1,1,4,4,4,0,1,0,0,0,0,1,1,1,0,0,4,2,4,0,0,0,0,0,0,0,0,1,0}, |
|
||||
new byte[] {0,4,4,1,1,1,4,4,4,0,0,0,0,0,0,1,1,1,0,0,4,2,4,0,0,0,0,0,0,0,0,1,0}, |
|
||||
new byte[] {0,4,4,1,0,1,4,4,4,0,0,1,0,0,0,0,1,1,0,0,4,2,4,0,0,0,0,0,0,0,0,1,0}, |
|
||||
new byte[] {0,4,4,1,0,1,4,4,4,0,0,0,0,0,0,0,1,1,0,0,4,2,4,0,0,0,0,0,0,0,0,1,0}, |
|
||||
new byte[] {1,4,4,1,1,1,4,4,4,1,1,1,1,1,1,1,1,1,1,1,4,2,4,1,1,1,1,1,1,1,1,1,0}, |
|
||||
new byte[] {0,4,4,1,1,1,4,4,4,0,0,0,0,0,0,0,1,1,0,4,4,2,4,0,0,0,0,0,0,0,0,1,0}, |
|
||||
new byte[] {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0}, |
|
||||
new byte[] {1,4,4,1,1,1,4,4,4,1,1,1,1,1,0,1,1,1,0,0,4,2,4,0,0,0,0,0,0,0,0,1,0}, |
|
||||
new byte[] {1,4,4,1,1,1,4,4,4,1,1,1,1,1,1,1,1,1,1,1,4,2,4,1,1,1,1,1,1,1,1,1,1}, |
|
||||
new byte[] {0,4,4,1,1,1,4,4,4,0,1,0,0,0,0,1,1,1,0,0,4,2,4,0,0,0,1,1,0,0,0,1,0}, |
|
||||
new byte[] {0,4,4,1,1,1,4,4,4,0,1,0,0,0,0,1,1,1,0,0,4,2,4,0,0,0,0,1,0,0,0,1,0}, |
|
||||
new byte[] {0,4,4,1,1,1,4,4,4,0,1,0,0,0,0,1,1,1,0,0,4,2,4,1,1,1,1,0,0,0,0,1,0}, |
|
||||
new byte[] {0,4,4,1,1,1,4,4,4,0,1,0,0,0,0,1,1,1,0,0,4,2,4,0,0,0,1,1,0,0,0,1,0}, |
|
||||
new byte[] {0,4,4,1,1,1,4,4,4,0,1,0,0,0,0,1,1,1,0,0,4,2,4,0,0,0,0,1,0,0,0,1,0}, |
|
||||
new byte[] {0,4,4,1,1,1,4,4,4,0,0,0,0,0,0,0,1,1,0,0,4,2,4,0,0,0,0,0,1,0,0,1,0}, |
|
||||
new byte[] {0,4,4,1,1,1,4,4,4,0,1,0,0,0,0,1,1,1,0,0,4,2,4,0,0,0,0,0,0,0,1,1,0}, |
|
||||
new byte[] {0,4,4,1,1,1,4,4,4,0,1,0,0,0,0,1,1,1,0,0,4,2,4,0,0,0,0,0,0,0,0,1,0}, |
|
||||
new byte[] {1,4,4,1,1,1,4,4,4,1,1,1,1,1,0,1,1,1,0,0,4,2,4,0,0,0,0,0,0,0,0,1,0}, |
|
||||
new byte[] {0,4,4,1,1,0,4,4,4,0,0,0,0,0,0,0,0,0,0,0,4,2,4,0,0,0,0,0,0,0,0,1,0}, |
|
||||
}; |
|
||||
|
|
||||
public static PairBreakType Map(LineBreakClass first, LineBreakClass second) |
|
||||
{ |
|
||||
return (PairBreakType)s_breakPairTable[(int)first][(int)second]; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
internal enum PairBreakType : byte |
|
||||
{ |
|
||||
DI = 0, // Direct break opportunity
|
|
||||
IN = 1, // Indirect break opportunity
|
|
||||
CI = 2, // Indirect break opportunity for combining marks
|
|
||||
CP = 3, // Prohibited break for combining marks
|
|
||||
PR = 4 // Prohibited break
|
|
||||
} |
|
||||
} |
|
||||
@ -0,0 +1,74 @@ |
|||||
|
// Copyright (c) Six Labors.
|
||||
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
// Ported from: https://github.com/SixLabors/Fonts/
|
||||
|
|
||||
|
namespace Avalonia.Media.TextFormatting.Unicode |
||||
|
{ |
||||
|
internal static class LineBreakPairTable |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Direct break opportunity
|
||||
|
/// </summary>
|
||||
|
public const byte DIBRK = 0; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Indirect break opportunity
|
||||
|
/// </summary>
|
||||
|
public const byte INBRK = 1; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Indirect break opportunity for combining marks
|
||||
|
/// </summary>
|
||||
|
public const byte CIBRK = 2; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Prohibited break for combining marks
|
||||
|
/// </summary>
|
||||
|
public const byte CPBRK = 3; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Prohibited break
|
||||
|
/// </summary>
|
||||
|
public const byte PRBRK = 4; |
||||
|
|
||||
|
// Based on example pair table from https://www.unicode.org/reports/tr14/tr14-37.html#Table2
|
||||
|
// - ZWJ special processing for LB8a
|
||||
|
// - CB manually added as per Rule LB20
|
||||
|
public static byte[][] Table { get; } = { |
||||
|
// . OP CL CP QU GL NS EX SY IS PR PO NU AL HL ID IN HY BA BB B2 ZW CM WJ H2 H3 JL JV JT RI EB EM ZWJ CB
|
||||
|
new[] { PRBRK, PRBRK, PRBRK, PRBRK, PRBRK, PRBRK, PRBRK, PRBRK, PRBRK, PRBRK, PRBRK, PRBRK, PRBRK, PRBRK, PRBRK, PRBRK, PRBRK, PRBRK, PRBRK, PRBRK, PRBRK, CPBRK, PRBRK, PRBRK, PRBRK, PRBRK, PRBRK, PRBRK, PRBRK, PRBRK, PRBRK, PRBRK, PRBRK }, // OP
|
||||
|
new[] { DIBRK, PRBRK, PRBRK, INBRK, INBRK, PRBRK, PRBRK, PRBRK, PRBRK, INBRK, INBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, INBRK, INBRK, DIBRK, DIBRK, PRBRK, CIBRK, PRBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, INBRK, DIBRK }, // CL
|
||||
|
new[] { DIBRK, PRBRK, PRBRK, INBRK, INBRK, PRBRK, PRBRK, PRBRK, PRBRK, INBRK, INBRK, INBRK, INBRK, INBRK, DIBRK, DIBRK, INBRK, INBRK, DIBRK, DIBRK, PRBRK, CIBRK, PRBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, INBRK, DIBRK }, // CP
|
||||
|
new[] { PRBRK, PRBRK, PRBRK, INBRK, INBRK, INBRK, PRBRK, PRBRK, PRBRK, INBRK, INBRK, INBRK, INBRK, INBRK, INBRK, INBRK, INBRK, INBRK, INBRK, INBRK, PRBRK, CIBRK, PRBRK, INBRK, INBRK, INBRK, INBRK, INBRK, INBRK, INBRK, INBRK, INBRK, INBRK }, // QU
|
||||
|
new[] { INBRK, PRBRK, PRBRK, INBRK, INBRK, INBRK, PRBRK, PRBRK, PRBRK, INBRK, INBRK, INBRK, INBRK, INBRK, INBRK, INBRK, INBRK, INBRK, INBRK, INBRK, PRBRK, CIBRK, PRBRK, INBRK, INBRK, INBRK, INBRK, INBRK, INBRK, INBRK, INBRK, INBRK, INBRK }, // GL
|
||||
|
new[] { DIBRK, PRBRK, PRBRK, INBRK, INBRK, INBRK, PRBRK, PRBRK, PRBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, INBRK, INBRK, DIBRK, DIBRK, PRBRK, CIBRK, PRBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, INBRK, DIBRK }, // NS
|
||||
|
new[] { DIBRK, PRBRK, PRBRK, INBRK, INBRK, INBRK, PRBRK, PRBRK, PRBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, INBRK, INBRK, INBRK, DIBRK, DIBRK, PRBRK, CIBRK, PRBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, INBRK, DIBRK }, // EX
|
||||
|
new[] { DIBRK, PRBRK, PRBRK, INBRK, INBRK, INBRK, PRBRK, PRBRK, PRBRK, DIBRK, DIBRK, INBRK, DIBRK, INBRK, DIBRK, DIBRK, INBRK, INBRK, DIBRK, DIBRK, PRBRK, CIBRK, PRBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, INBRK, DIBRK }, // SY
|
||||
|
new[] { DIBRK, PRBRK, PRBRK, INBRK, INBRK, INBRK, PRBRK, PRBRK, PRBRK, DIBRK, DIBRK, INBRK, INBRK, INBRK, DIBRK, DIBRK, INBRK, INBRK, DIBRK, DIBRK, PRBRK, CIBRK, PRBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, INBRK, DIBRK }, // IS
|
||||
|
new[] { INBRK, PRBRK, PRBRK, INBRK, INBRK, INBRK, PRBRK, PRBRK, PRBRK, DIBRK, DIBRK, INBRK, INBRK, INBRK, INBRK, DIBRK, INBRK, INBRK, DIBRK, DIBRK, PRBRK, CIBRK, PRBRK, INBRK, INBRK, INBRK, INBRK, INBRK, DIBRK, INBRK, INBRK, INBRK, DIBRK }, // PR
|
||||
|
new[] { INBRK, PRBRK, PRBRK, INBRK, INBRK, INBRK, PRBRK, PRBRK, PRBRK, DIBRK, DIBRK, INBRK, INBRK, INBRK, DIBRK, DIBRK, INBRK, INBRK, DIBRK, DIBRK, PRBRK, CIBRK, PRBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, INBRK, DIBRK }, // PO
|
||||
|
new[] { INBRK, PRBRK, PRBRK, INBRK, INBRK, INBRK, PRBRK, PRBRK, PRBRK, INBRK, INBRK, INBRK, INBRK, INBRK, DIBRK, INBRK, INBRK, INBRK, DIBRK, DIBRK, PRBRK, CIBRK, PRBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, INBRK, DIBRK }, // NU
|
||||
|
new[] { INBRK, PRBRK, PRBRK, INBRK, INBRK, INBRK, PRBRK, PRBRK, PRBRK, INBRK, INBRK, INBRK, INBRK, INBRK, DIBRK, INBRK, INBRK, INBRK, DIBRK, DIBRK, PRBRK, CIBRK, PRBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, INBRK, DIBRK }, // AL
|
||||
|
new[] { INBRK, PRBRK, PRBRK, INBRK, INBRK, INBRK, PRBRK, PRBRK, PRBRK, INBRK, INBRK, INBRK, INBRK, INBRK, DIBRK, INBRK, INBRK, INBRK, DIBRK, DIBRK, PRBRK, CIBRK, PRBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, INBRK, DIBRK }, // HL
|
||||
|
new[] { DIBRK, PRBRK, PRBRK, INBRK, INBRK, INBRK, PRBRK, PRBRK, PRBRK, DIBRK, INBRK, DIBRK, DIBRK, DIBRK, DIBRK, INBRK, INBRK, INBRK, DIBRK, DIBRK, PRBRK, CIBRK, PRBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, INBRK, DIBRK }, // ID
|
||||
|
new[] { DIBRK, PRBRK, PRBRK, INBRK, INBRK, INBRK, PRBRK, PRBRK, PRBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, INBRK, INBRK, INBRK, DIBRK, DIBRK, PRBRK, CIBRK, PRBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, INBRK, DIBRK }, // IN
|
||||
|
new[] { DIBRK, PRBRK, PRBRK, INBRK, DIBRK, INBRK, PRBRK, PRBRK, PRBRK, DIBRK, DIBRK, INBRK, DIBRK, DIBRK, DIBRK, DIBRK, INBRK, INBRK, DIBRK, DIBRK, PRBRK, CIBRK, PRBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, INBRK, DIBRK }, // HY
|
||||
|
new[] { DIBRK, PRBRK, PRBRK, INBRK, DIBRK, INBRK, PRBRK, PRBRK, PRBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, INBRK, INBRK, DIBRK, DIBRK, PRBRK, CIBRK, PRBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, INBRK, DIBRK }, // BA
|
||||
|
new[] { INBRK, PRBRK, PRBRK, INBRK, INBRK, INBRK, PRBRK, PRBRK, PRBRK, INBRK, INBRK, INBRK, INBRK, INBRK, INBRK, INBRK, INBRK, INBRK, INBRK, INBRK, PRBRK, CIBRK, PRBRK, INBRK, INBRK, INBRK, INBRK, INBRK, INBRK, INBRK, INBRK, INBRK, DIBRK }, // BB
|
||||
|
new[] { DIBRK, PRBRK, PRBRK, INBRK, INBRK, INBRK, PRBRK, PRBRK, PRBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, INBRK, INBRK, DIBRK, PRBRK, PRBRK, CIBRK, PRBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, INBRK, DIBRK }, // B2
|
||||
|
new[] { DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, PRBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK }, // ZW
|
||||
|
new[] { INBRK, PRBRK, PRBRK, INBRK, INBRK, INBRK, PRBRK, PRBRK, PRBRK, INBRK, INBRK, INBRK, INBRK, INBRK, DIBRK, INBRK, INBRK, INBRK, DIBRK, DIBRK, PRBRK, CIBRK, PRBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, INBRK, DIBRK }, // CM
|
||||
|
new[] { INBRK, PRBRK, PRBRK, INBRK, INBRK, INBRK, PRBRK, PRBRK, PRBRK, INBRK, INBRK, INBRK, INBRK, INBRK, INBRK, INBRK, INBRK, INBRK, INBRK, INBRK, PRBRK, CIBRK, PRBRK, INBRK, INBRK, INBRK, INBRK, INBRK, INBRK, INBRK, INBRK, INBRK, INBRK }, // WJ
|
||||
|
new[] { DIBRK, PRBRK, PRBRK, INBRK, INBRK, INBRK, PRBRK, PRBRK, PRBRK, DIBRK, INBRK, DIBRK, DIBRK, DIBRK, DIBRK, INBRK, INBRK, INBRK, DIBRK, DIBRK, PRBRK, CIBRK, PRBRK, DIBRK, DIBRK, DIBRK, INBRK, INBRK, DIBRK, DIBRK, DIBRK, INBRK, DIBRK }, // H2
|
||||
|
new[] { DIBRK, PRBRK, PRBRK, INBRK, INBRK, INBRK, PRBRK, PRBRK, PRBRK, DIBRK, INBRK, DIBRK, DIBRK, DIBRK, DIBRK, INBRK, INBRK, INBRK, DIBRK, DIBRK, PRBRK, CIBRK, PRBRK, DIBRK, DIBRK, DIBRK, DIBRK, INBRK, DIBRK, DIBRK, DIBRK, INBRK, DIBRK }, // H3
|
||||
|
new[] { DIBRK, PRBRK, PRBRK, INBRK, INBRK, INBRK, PRBRK, PRBRK, PRBRK, DIBRK, INBRK, DIBRK, DIBRK, DIBRK, DIBRK, INBRK, INBRK, INBRK, DIBRK, DIBRK, PRBRK, CIBRK, PRBRK, INBRK, INBRK, INBRK, INBRK, DIBRK, DIBRK, DIBRK, DIBRK, INBRK, DIBRK }, // JL
|
||||
|
new[] { DIBRK, PRBRK, PRBRK, INBRK, INBRK, INBRK, PRBRK, PRBRK, PRBRK, DIBRK, INBRK, DIBRK, DIBRK, DIBRK, DIBRK, INBRK, INBRK, INBRK, DIBRK, DIBRK, PRBRK, CIBRK, PRBRK, DIBRK, DIBRK, DIBRK, INBRK, INBRK, DIBRK, DIBRK, DIBRK, INBRK, DIBRK }, // JV
|
||||
|
new[] { DIBRK, PRBRK, PRBRK, INBRK, INBRK, INBRK, PRBRK, PRBRK, PRBRK, DIBRK, INBRK, DIBRK, DIBRK, DIBRK, DIBRK, INBRK, INBRK, INBRK, DIBRK, DIBRK, PRBRK, CIBRK, PRBRK, DIBRK, DIBRK, DIBRK, DIBRK, INBRK, DIBRK, DIBRK, DIBRK, INBRK, DIBRK }, // JT
|
||||
|
new[] { DIBRK, PRBRK, PRBRK, INBRK, INBRK, INBRK, PRBRK, PRBRK, PRBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, INBRK, INBRK, DIBRK, DIBRK, PRBRK, CIBRK, PRBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, INBRK, DIBRK, DIBRK, INBRK, DIBRK }, // RI
|
||||
|
new[] { DIBRK, PRBRK, PRBRK, INBRK, INBRK, INBRK, PRBRK, PRBRK, PRBRK, DIBRK, INBRK, DIBRK, DIBRK, DIBRK, DIBRK, INBRK, INBRK, INBRK, DIBRK, DIBRK, PRBRK, CIBRK, PRBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, INBRK, INBRK, DIBRK }, // EB
|
||||
|
new[] { DIBRK, PRBRK, PRBRK, INBRK, INBRK, INBRK, PRBRK, PRBRK, PRBRK, DIBRK, INBRK, DIBRK, DIBRK, DIBRK, DIBRK, INBRK, INBRK, INBRK, DIBRK, DIBRK, PRBRK, CIBRK, PRBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, INBRK, DIBRK }, // EM
|
||||
|
new[] { INBRK, PRBRK, PRBRK, INBRK, INBRK, INBRK, PRBRK, PRBRK, PRBRK, INBRK, INBRK, INBRK, INBRK, INBRK, DIBRK, INBRK, INBRK, INBRK, DIBRK, DIBRK, PRBRK, CIBRK, PRBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, INBRK, DIBRK }, // ZWJ
|
||||
|
new[] { DIBRK, PRBRK, PRBRK, INBRK, INBRK, DIBRK, PRBRK, PRBRK, PRBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, PRBRK, CIBRK, PRBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, DIBRK, INBRK, DIBRK } // CB
|
||||
|
}; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,259 @@ |
|||||
|
using System; |
||||
|
using System.Collections; |
||||
|
using System.Collections.Generic; |
||||
|
using System.IO; |
||||
|
using System.Linq; |
||||
|
using System.Net.Http; |
||||
|
using Avalonia.Media.TextFormatting.Unicode; |
||||
|
using Xunit; |
||||
|
using Xunit.Abstractions; |
||||
|
|
||||
|
namespace Avalonia.Visuals.UnitTests.Media.TextFormatting |
||||
|
{ |
||||
|
public class LineBreakEnumeratorTests |
||||
|
{ |
||||
|
private readonly ITestOutputHelper _outputHelper; |
||||
|
|
||||
|
public LineBreakEnumeratorTests(ITestOutputHelper outputHelper) |
||||
|
{ |
||||
|
_outputHelper = outputHelper; |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void BasicLatinTest() |
||||
|
{ |
||||
|
var lineBreaker = new LineBreakEnumerator("Hello World\r\nThis is a test.".AsMemory()); |
||||
|
|
||||
|
Assert.True(lineBreaker.MoveNext()); |
||||
|
Assert.Equal(6, lineBreaker.Current.PositionWrap); |
||||
|
Assert.False(lineBreaker.Current.Required); |
||||
|
|
||||
|
Assert.True(lineBreaker.MoveNext()); |
||||
|
Assert.Equal(13, lineBreaker.Current.PositionWrap); |
||||
|
Assert.True(lineBreaker.Current.Required); |
||||
|
|
||||
|
Assert.True(lineBreaker.MoveNext()); |
||||
|
Assert.Equal(18, lineBreaker.Current.PositionWrap); |
||||
|
Assert.False(lineBreaker.Current.Required); |
||||
|
|
||||
|
Assert.True(lineBreaker.MoveNext()); |
||||
|
Assert.Equal(21, lineBreaker.Current.PositionWrap); |
||||
|
Assert.False(lineBreaker.Current.Required); |
||||
|
|
||||
|
Assert.True(lineBreaker.MoveNext()); |
||||
|
Assert.Equal(23, lineBreaker.Current.PositionWrap); |
||||
|
Assert.False(lineBreaker.Current.Required); |
||||
|
|
||||
|
Assert.True(lineBreaker.MoveNext()); |
||||
|
Assert.Equal(28, lineBreaker.Current.PositionWrap); |
||||
|
Assert.False(lineBreaker.Current.Required); |
||||
|
|
||||
|
Assert.False(lineBreaker.MoveNext()); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
[Fact] |
||||
|
public void ForwardTextWithOuterWhitespace() |
||||
|
{ |
||||
|
var lineBreaker = new LineBreakEnumerator(" Apples Pears Bananas ".AsMemory()); |
||||
|
var positionsF = GetBreaks(lineBreaker); |
||||
|
Assert.Equal(1, positionsF[0].PositionWrap); |
||||
|
Assert.Equal(0, positionsF[0].PositionMeasure); |
||||
|
Assert.Equal(8, positionsF[1].PositionWrap); |
||||
|
Assert.Equal(7, positionsF[1].PositionMeasure); |
||||
|
Assert.Equal(14, positionsF[2].PositionWrap); |
||||
|
Assert.Equal(13, positionsF[2].PositionMeasure); |
||||
|
Assert.Equal(24, positionsF[3].PositionWrap); |
||||
|
Assert.Equal(21, positionsF[3].PositionMeasure); |
||||
|
} |
||||
|
|
||||
|
private static List<LineBreak> GetBreaks(LineBreakEnumerator lineBreaker) |
||||
|
{ |
||||
|
var breaks = new List<LineBreak>(); |
||||
|
|
||||
|
while (lineBreaker.MoveNext()) |
||||
|
{ |
||||
|
breaks.Add(lineBreaker.Current); |
||||
|
} |
||||
|
|
||||
|
return breaks; |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void ForwardTest() |
||||
|
{ |
||||
|
var lineBreaker = new LineBreakEnumerator("Apples Pears Bananas".AsMemory()); |
||||
|
|
||||
|
var positionsF = GetBreaks(lineBreaker); |
||||
|
Assert.Equal(7, positionsF[0].PositionWrap); |
||||
|
Assert.Equal(6, positionsF[0].PositionMeasure); |
||||
|
Assert.Equal(13, positionsF[1].PositionWrap); |
||||
|
Assert.Equal(12, positionsF[1].PositionMeasure); |
||||
|
Assert.Equal(20, positionsF[2].PositionWrap); |
||||
|
Assert.Equal(20, positionsF[2].PositionMeasure); |
||||
|
} |
||||
|
|
||||
|
[Theory(Skip = "Only run when the Unicode spec changes.")] |
||||
|
[ClassData(typeof(LineBreakTestDataGenerator))] |
||||
|
public void ShouldFindBreaks(int lineNumber, int[] codePoints, int[] breakPoints) |
||||
|
{ |
||||
|
var text = string.Join(null, codePoints.Select(char.ConvertFromUtf32)); |
||||
|
|
||||
|
var lineBreaker = new LineBreakEnumerator(text.AsMemory()); |
||||
|
|
||||
|
var foundBreaks = new List<int>(); |
||||
|
|
||||
|
while (lineBreaker.MoveNext()) |
||||
|
{ |
||||
|
foundBreaks.Add(lineBreaker.Current.PositionWrap); |
||||
|
} |
||||
|
|
||||
|
// Check the same
|
||||
|
var pass = true; |
||||
|
|
||||
|
if (foundBreaks.Count != breakPoints.Length) |
||||
|
{ |
||||
|
pass = false; |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
for (var i = 0; i < foundBreaks.Count; i++) |
||||
|
{ |
||||
|
if (foundBreaks[i] != breakPoints[i]) |
||||
|
{ |
||||
|
pass = false; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if (!pass) |
||||
|
{ |
||||
|
_outputHelper.WriteLine($"Failed test on line {lineNumber}"); |
||||
|
_outputHelper.WriteLine(""); |
||||
|
_outputHelper.WriteLine($" Code Points: {string.Join(" ", codePoints)}"); |
||||
|
_outputHelper.WriteLine($"Expected Breaks: {string.Join(" ", breakPoints)}"); |
||||
|
_outputHelper.WriteLine($" Actual Breaks: {string.Join(" ", foundBreaks)}"); |
||||
|
_outputHelper.WriteLine($" Text: {text}"); |
||||
|
_outputHelper.WriteLine($" Char Props: {string.Join(" ", codePoints.Select(x => new Codepoint(x).LineBreakClass))}"); |
||||
|
_outputHelper.WriteLine(""); |
||||
|
} |
||||
|
|
||||
|
Assert.True(pass); |
||||
|
} |
||||
|
|
||||
|
private class LineBreakTestDataGenerator : IEnumerable<object[]> |
||||
|
{ |
||||
|
private readonly List<object[]> _testData; |
||||
|
|
||||
|
public LineBreakTestDataGenerator() |
||||
|
{ |
||||
|
_testData = GenerateTestData(); |
||||
|
} |
||||
|
|
||||
|
public IEnumerator<object[]> GetEnumerator() |
||||
|
{ |
||||
|
return _testData.GetEnumerator(); |
||||
|
} |
||||
|
|
||||
|
IEnumerator IEnumerable.GetEnumerator() |
||||
|
{ |
||||
|
return GetEnumerator(); |
||||
|
} |
||||
|
|
||||
|
private static List<object[]> GenerateTestData() |
||||
|
{ |
||||
|
// Process each line
|
||||
|
var tests = new List<object[]>(); |
||||
|
|
||||
|
// Read the test file
|
||||
|
var url = Path.Combine(UnicodeDataGenerator.Ucd, "auxiliary/LineBreakTest.txt"); |
||||
|
|
||||
|
using (var client = new HttpClient()) |
||||
|
using (var result = client.GetAsync(url).GetAwaiter().GetResult()) |
||||
|
{ |
||||
|
if (!result.IsSuccessStatusCode) |
||||
|
{ |
||||
|
return tests; |
||||
|
} |
||||
|
|
||||
|
using (var stream = result.Content.ReadAsStreamAsync().GetAwaiter().GetResult()) |
||||
|
using (var reader = new StreamReader(stream)) |
||||
|
{ |
||||
|
var lineNumber = 1; |
||||
|
|
||||
|
while (!reader.EndOfStream) |
||||
|
{ |
||||
|
var line = reader.ReadLine(); |
||||
|
|
||||
|
if (line is null) |
||||
|
{ |
||||
|
break; |
||||
|
} |
||||
|
|
||||
|
// Get the line, remove comments
|
||||
|
line = line.Split('#')[0].Trim(); |
||||
|
|
||||
|
// Ignore blank/comment only lines
|
||||
|
if (string.IsNullOrWhiteSpace(line)) |
||||
|
{ |
||||
|
lineNumber++; |
||||
|
continue; |
||||
|
} |
||||
|
|
||||
|
var codePoints = new List<int>(); |
||||
|
var breakPoints = new List<int>(); |
||||
|
|
||||
|
// Parse the test
|
||||
|
var p = 0; |
||||
|
|
||||
|
while (p < line.Length) |
||||
|
{ |
||||
|
// Ignore white space
|
||||
|
if (char.IsWhiteSpace(line[p])) |
||||
|
{ |
||||
|
p++; |
||||
|
continue; |
||||
|
} |
||||
|
|
||||
|
if (line[p] == '×') |
||||
|
{ |
||||
|
p++; |
||||
|
continue; |
||||
|
} |
||||
|
|
||||
|
if (line[p] == '÷') |
||||
|
{ |
||||
|
breakPoints.Add(codePoints.Select(x=> x > ushort.MaxValue ? 2 : 1).Sum()); |
||||
|
p++; |
||||
|
continue; |
||||
|
} |
||||
|
|
||||
|
var codePointPos = p; |
||||
|
|
||||
|
while (p < line.Length && IsHexDigit(line[p])) |
||||
|
{ |
||||
|
p++; |
||||
|
} |
||||
|
|
||||
|
var codePointStr = line.Substring(codePointPos, p - codePointPos); |
||||
|
var codePoint = Convert.ToInt32(codePointStr, 16); |
||||
|
codePoints.Add(codePoint); |
||||
|
} |
||||
|
|
||||
|
tests.Add(new object[] { lineNumber, codePoints.ToArray(), breakPoints.ToArray() }); |
||||
|
|
||||
|
lineNumber++; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return tests; |
||||
|
} |
||||
|
|
||||
|
private static bool IsHexDigit(char ch) |
||||
|
{ |
||||
|
return char.IsDigit(ch) || (ch >= 'A' && ch <= 'F') || (ch >= 'a' && ch <= 'f'); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -1,56 +0,0 @@ |
|||||
using System; |
|
||||
using Avalonia.Media.TextFormatting.Unicode; |
|
||||
using Avalonia.Utilities; |
|
||||
using Xunit; |
|
||||
|
|
||||
namespace Avalonia.Visuals.UnitTests.Media.TextFormatting |
|
||||
{ |
|
||||
public class LineBreakerTests |
|
||||
{ |
|
||||
[Fact] |
|
||||
public void Should_Split_Text_By_Explicit_Breaks() |
|
||||
{ |
|
||||
//ABC [0 3]
|
|
||||
//DEF\r[4 7]
|
|
||||
//\r[8]
|
|
||||
//Hello\r\n[9 15]
|
|
||||
const string text = "ABC DEF\r\rHELLO\r\n"; |
|
||||
|
|
||||
var buffer = new ReadOnlySlice<char>(text.AsMemory()); |
|
||||
|
|
||||
var lineBreaker = new LineBreakEnumerator(buffer); |
|
||||
|
|
||||
var current = 0; |
|
||||
|
|
||||
Assert.True(lineBreaker.MoveNext()); |
|
||||
|
|
||||
var a = text.Substring(current, lineBreaker.Current.PositionMeasure - current + 1); |
|
||||
|
|
||||
Assert.Equal("ABC ", a); |
|
||||
|
|
||||
current += a.Length; |
|
||||
|
|
||||
Assert.True(lineBreaker.MoveNext()); |
|
||||
|
|
||||
var b = text.Substring(current, lineBreaker.Current.PositionMeasure - current + 1); |
|
||||
|
|
||||
Assert.Equal("DEF\r", b); |
|
||||
|
|
||||
current += b.Length; |
|
||||
|
|
||||
Assert.True(lineBreaker.MoveNext()); |
|
||||
|
|
||||
var c = text.Substring(current, lineBreaker.Current.PositionMeasure - current + 1); |
|
||||
|
|
||||
Assert.Equal("\r", c); |
|
||||
|
|
||||
current += c.Length; |
|
||||
|
|
||||
Assert.True(lineBreaker.MoveNext()); |
|
||||
|
|
||||
var d = text.Substring(current, text.Length - current); |
|
||||
|
|
||||
Assert.Equal("HELLO\r\n", d); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
Loading…
Reference in new issue