• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

orion-ecs / keen-eye / 20737823009

06 Jan 2026 04:16AM UTC coverage: 71.324% (-2.6%) from 73.964%
20737823009

push

github

tyevco
feat(localization): Add RTL layout support and advanced localization features

- Add TextDirection enum for distinguishing LTR/RTL text flow
- Add IsRightToLeft property and RTL locale constants to Locale struct
- Add MirrorForRtl property to UIRect for automatic layout mirroring
- Update UILayoutSystem to handle RTL-aware anchor and flexbox layouts
- Add text shaping infrastructure with ITextShaper interface
- Implement ArabicTextShaper for contextual letter forms
- Add BidirectionalTextShaper for mixed LTR/RTL text handling
- Add ComplexScriptInfo for Thai, Hindi, Bengali, Tamil shaping info
- Add CsvStringSource for CSV import/export translator workflows
- Add comprehensive unit tests for all new functionality

Closes #635

5865 of 7851 branches covered (74.7%)

Branch coverage included in aggregate %.

26 of 764 new or added lines in 9 files covered. (3.4%)

452 existing lines in 6 files now uncovered.

37040 of 52304 relevant lines covered (70.82%)

1.02 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/KeenEyes.Localization/TextShaping/ComplexScriptInfo.cs
1
namespace KeenEyes.Localization.TextShaping;
2

3
/// <summary>
4
/// Provides information about complex script requirements for different languages.
5
/// </summary>
6
/// <remarks>
7
/// <para>
8
/// Complex scripts like Thai and Devanagari (Hindi) require special handling for proper
9
/// text rendering. This class provides information about what features are needed.
10
/// </para>
11
/// <para>
12
/// For full rendering support, these scripts typically require:
13
/// <list type="bullet">
14
///   <item><description>OpenType font with appropriate GSUB/GPOS tables</description></item>
15
///   <item><description>HarfBuzz or similar text shaping library integration</description></item>
16
///   <item><description>Proper handling of combining characters and diacritics</description></item>
17
/// </list>
18
/// </para>
19
/// </remarks>
20
/// <example>
21
/// <code>
22
/// var info = ComplexScriptInfo.GetInfo(ScriptType.Thai);
23
/// if (info.RequiresShaping)
24
/// {
25
///     Console.WriteLine($"Thai text requires: {string.Join(", ", info.ShapingFeatures)}");
26
/// }
27
/// </code>
28
/// </example>
29
public sealed class ComplexScriptInfo
30
{
NEW
31
    private ComplexScriptInfo(
×
NEW
32
        ScriptType script,
×
NEW
33
        string scriptName,
×
NEW
34
        string[] languages,
×
NEW
35
        bool requiresShaping,
×
NEW
36
        string[] shapingFeatures,
×
NEW
37
        string? notes)
×
NEW
38
    {
×
NEW
39
        Script = script;
×
NEW
40
        ScriptName = scriptName;
×
NEW
41
        Languages = languages;
×
NEW
42
        RequiresShaping = requiresShaping;
×
NEW
43
        ShapingFeatures = shapingFeatures;
×
NEW
44
        Notes = notes;
×
NEW
45
    }
×
46

47
    /// <summary>
48
    /// Gets the script type.
49
    /// </summary>
NEW
50
    public ScriptType Script { get; }
×
51

52
    /// <summary>
53
    /// Gets the human-readable name of the script.
54
    /// </summary>
NEW
55
    public string ScriptName { get; }
×
56

57
    /// <summary>
58
    /// Gets the languages that use this script.
59
    /// </summary>
NEW
60
    public string[] Languages { get; }
×
61

62
    /// <summary>
63
    /// Gets whether this script requires text shaping for proper rendering.
64
    /// </summary>
NEW
65
    public bool RequiresShaping { get; }
×
66

67
    /// <summary>
68
    /// Gets the OpenType features required for proper rendering.
69
    /// </summary>
NEW
70
    public string[] ShapingFeatures { get; }
×
71

72
    /// <summary>
73
    /// Gets additional notes about rendering this script.
74
    /// </summary>
NEW
75
    public string? Notes { get; }
×
76

77
    /// <summary>
78
    /// Gets information about a specific script type.
79
    /// </summary>
80
    /// <param name="script">The script type to get information for.</param>
81
    /// <returns>Information about the script, or null if unknown.</returns>
NEW
82
    public static ComplexScriptInfo? GetInfo(ScriptType script) => script switch
×
NEW
83
    {
×
NEW
84
        ScriptType.Arabic => arabicInfo,
×
NEW
85
        ScriptType.Hebrew => hebrewInfo,
×
NEW
86
        ScriptType.Thai => thaiInfo,
×
NEW
87
        ScriptType.Devanagari => devanagariInfo,
×
NEW
88
        ScriptType.Tamil => tamilInfo,
×
NEW
89
        ScriptType.Bengali => bengaliInfo,
×
NEW
90
        ScriptType.CJK => cjkInfo,
×
NEW
91
        ScriptType.Hangul => hangulInfo,
×
NEW
92
        _ => null
×
NEW
93
    };
×
94

95
    /// <summary>
96
    /// Gets information about the script used by a locale.
97
    /// </summary>
98
    /// <param name="locale">The locale to get script information for.</param>
99
    /// <returns>Information about the primary script used by the locale.</returns>
100
    public static ComplexScriptInfo? GetInfoForLocale(Locale locale)
NEW
101
    {
×
NEW
102
        var script = GetScriptForLanguage(locale.Language);
×
NEW
103
        return script.HasValue ? GetInfo(script.Value) : null;
×
NEW
104
    }
×
105

106
    /// <summary>
107
    /// Determines the primary script used by a language code.
108
    /// </summary>
109
    /// <param name="language">The ISO 639-1 language code.</param>
110
    /// <returns>The script type, or null if unknown.</returns>
NEW
111
    public static ScriptType? GetScriptForLanguage(string language) => language switch
×
NEW
112
    {
×
NEW
113
        "ar" => ScriptType.Arabic,
×
NEW
114
        "fa" => ScriptType.Arabic, // Persian uses Arabic script
×
NEW
115
        "ur" => ScriptType.Arabic, // Urdu uses Arabic script
×
NEW
116
        "he" => ScriptType.Hebrew,
×
NEW
117
        "yi" => ScriptType.Hebrew, // Yiddish uses Hebrew script
×
NEW
118
        "th" => ScriptType.Thai,
×
NEW
119
        "hi" => ScriptType.Devanagari,
×
NEW
120
        "mr" => ScriptType.Devanagari, // Marathi
×
NEW
121
        "ne" => ScriptType.Devanagari, // Nepali
×
NEW
122
        "sa" => ScriptType.Devanagari, // Sanskrit
×
NEW
123
        "ta" => ScriptType.Tamil,
×
NEW
124
        "bn" => ScriptType.Bengali,
×
NEW
125
        "zh" => ScriptType.CJK,
×
NEW
126
        "ja" => ScriptType.CJK, // Japanese uses multiple scripts but CJK for main text
×
NEW
127
        "ko" => ScriptType.Hangul,
×
NEW
128
        _ => null
×
NEW
129
    };
×
130

NEW
131
    private static readonly ComplexScriptInfo arabicInfo = new(
×
NEW
132
        ScriptType.Arabic,
×
NEW
133
        "Arabic",
×
NEW
134
        ["Arabic", "Persian", "Urdu", "Pashto", "Kurdish"],
×
NEW
135
        requiresShaping: true,
×
NEW
136
        ["init", "medi", "fina", "isol", "liga", "rlig", "calt"],
×
NEW
137
        "Arabic requires contextual letter forms (initial, medial, final, isolated) and right-to-left layout. " +
×
NEW
138
        "Built-in ArabicTextShaper provides basic support. For complex Arabic typography, integrate HarfBuzz.");
×
139

NEW
140
    private static readonly ComplexScriptInfo hebrewInfo = new(
×
NEW
141
        ScriptType.Hebrew,
×
NEW
142
        "Hebrew",
×
NEW
143
        ["Hebrew", "Yiddish"],
×
NEW
144
        requiresShaping: true,
×
NEW
145
        ["fina", "liga"],
×
NEW
146
        "Hebrew requires right-to-left layout. Some letters have final forms. " +
×
NEW
147
        "Simpler shaping requirements than Arabic.");
×
148

NEW
149
    private static readonly ComplexScriptInfo thaiInfo = new(
×
NEW
150
        ScriptType.Thai,
×
NEW
151
        "Thai",
×
NEW
152
        ["Thai"],
×
NEW
153
        requiresShaping: true,
×
NEW
154
        ["ccmp", "liga", "mark", "mkmk"],
×
NEW
155
        "Thai has stacking diacritics (tone marks, vowel signs) that appear above or below consonants. " +
×
NEW
156
        "Requires proper handling of combining characters and glyph positioning. " +
×
NEW
157
        "For proper rendering, use a font with Thai OpenType tables and HarfBuzz integration.");
×
158

NEW
159
    private static readonly ComplexScriptInfo devanagariInfo = new(
×
NEW
160
        ScriptType.Devanagari,
×
NEW
161
        "Devanagari",
×
NEW
162
        ["Hindi", "Marathi", "Nepali", "Sanskrit"],
×
NEW
163
        requiresShaping: true,
×
NEW
164
        ["akhn", "rphf", "blwf", "half", "pstf", "vatu", "cjct", "pres", "abvs", "blws", "psts", "haln", "calt"],
×
NEW
165
        "Devanagari has conjunct consonants (consonant clusters) formed using the virama (halant). " +
×
NEW
166
        "Complex rendering with above and below marks. Requires HarfBuzz for proper rendering.");
×
167

NEW
168
    private static readonly ComplexScriptInfo tamilInfo = new(
×
NEW
169
        ScriptType.Tamil,
×
NEW
170
        "Tamil",
×
NEW
171
        ["Tamil"],
×
NEW
172
        requiresShaping: true,
×
NEW
173
        ["akhn", "pref", "blwf", "pstf", "abvs", "blws", "psts", "haln", "calt"],
×
NEW
174
        "Tamil has special character combinations and diacritics. " +
×
NEW
175
        "Similar complexity to Devanagari. Requires HarfBuzz for proper rendering.");
×
176

NEW
177
    private static readonly ComplexScriptInfo bengaliInfo = new(
×
NEW
178
        ScriptType.Bengali,
×
NEW
179
        "Bengali",
×
NEW
180
        ["Bengali", "Assamese"],
×
NEW
181
        requiresShaping: true,
×
NEW
182
        ["akhn", "rphf", "blwf", "half", "pstf", "vatu", "cjct", "pres", "abvs", "blws", "psts", "haln", "calt"],
×
NEW
183
        "Bengali has conjunct consonants similar to Devanagari. " +
×
NEW
184
        "Complex shaping requirements. Requires HarfBuzz for proper rendering.");
×
185

NEW
186
    private static readonly ComplexScriptInfo cjkInfo = new(
×
NEW
187
        ScriptType.CJK,
×
NEW
188
        "CJK (Chinese/Japanese/Korean)",
×
NEW
189
        ["Chinese", "Japanese", "Korean"],
×
NEW
190
        requiresShaping: false,
×
NEW
191
        ["vert", "vrt2"],
×
NEW
192
        "CJK ideographs generally don't require complex shaping, but may need: " +
×
NEW
193
        "vertical text layout support, full-width punctuation, and proper line breaking. " +
×
NEW
194
        "Japanese may need ruby text (furigana) support for kanji readings.");
×
195

NEW
196
    private static readonly ComplexScriptInfo hangulInfo = new(
×
NEW
197
        ScriptType.Hangul,
×
NEW
198
        "Hangul",
×
NEW
199
        ["Korean"],
×
NEW
200
        requiresShaping: false,
×
NEW
201
        ["ccmp", "ljmo", "vjmo", "tjmo"],
×
NEW
202
        "Modern Hangul uses precomposed syllable blocks. " +
×
NEW
203
        "Old Hangul or text with individual jamo may need composition. " +
×
NEW
204
        "Generally simpler than other complex scripts.");
×
205
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc