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