Как получить символы для контекстного ввода в сложном сценарии?

В некоторых языках RightToLeft (таких как арабский, персидский, урду и т. Д.) Каждая буква может иметь различную форму. Существует изолированная форма, начальная форма и средняя форма (вы можете просто найти ее на карте символов окон для любого шрифта Unicode).

Представьте, что вам нужны точные символы, которые пользователь ввел в текстовое поле, по умолчанию, когда вы преобразуете String в CharArray, он преобразует каждый символ в изолированную форму.

(потому что, когда пользователь вводит символы с клавиатуры, он находится в изолированной форме, а когда он отображается на экране, он будет преобразован в правильный формат; это всего лишь предположение. потому что, если вы создаете строку с использованием точных кодов символов, он будет генерировать правильный массив).

У меня вопрос, как мы можем получить эту форму строки, форму, которая была отображена в текстовом поле.

Если в.NET нет пути, то это означает, что мне нужно создать свой собственный класс для преобразования этого T_T.

3 ответа

Решение

Windows использует Uniscribe для выполнения контекстного шейпинга для сложных сценариев (которые могут применяться к языкам от l до to, а также от r до l). Отображаемый текст в текстовом поле основан на информации о глифе после подачи символов в Uniscribe. Хотя стандарт Unicode определяет кодовые точки для каждой из изолированных, начальных, медиальных и конечных форм символов, не все шрифты обязательно поддерживают их, однако они могут иметь предварительно сформированные глифы или использовать комбинацию глифов - Uniscribe использует механизм формирования из языковой пакет Windows, чтобы определить, какой глиф (ы) использовать, на основе cmap шрифта. Вот некоторые соответствующие ссылки:

Метод TextRenderer.DrawText () использует Uniscribe через функцию Win32 DrawTextExW (), используя следующий P/Invoke:

[DllImport("user32.dll", CharSet=CharSet.Unicode, SetLastError=true)]
public static extern int DrawTextExW( HandleRef hDC
                                     ,string lpszString
                                     ,int nCount
                                     ,ref RECT lpRect
                                     ,int nFormat
                                     ,[In, Out] DRAWTEXTPARAMS lpDTParams);

[StructLayout(LayoutKind.Sequential)]
public struct RECT
 {
   public int left;
   public int top;
   public int right;
   public int bottom;
 }

[StructLayout(LayoutKind.Sequential)]
public class DRAWTEXTPARAMS
{
  public int iTabLength;
  public int iLeftMargin;
  public int iRightMargin;
  public int uiLengthDrawn;
}

Это немного дикое предположение, но помогает ли здесь String.Normalize()? Мне неясно, охватывает ли это просто композицию персонажей или она также включает в себя позиционные формы.

Итак, как вы создаете "неправильную" строку? Если вы просто помещаете его в строковый литерал, то вполне возможно, что это просто неправильный метод ввода. Если вы скопируете "правильную" строку после ее отображения, а затем вставите ее в строковый литерал, что произойдет? Вы также можете проверить, какую кодировку Visual Studio использует для ваших исходных файлов. Если вы не помещаете строку в исходный код как литерал, как вы ее создаете?

Учитывая возможность сбить с толку, я думаю, я бы хотел либо сохранить эти строки в ресурсе, либо жестко закодировать их, используя экранирование Юникода:

string text = "\ufb64\ufea0\ufe91\feea";

(Затем, возможно, потом добавьте комментарий, показывающий неэкранированное значение; по крайней мере, если оно выглядит правильно, оно не будет слишком вводящим в заблуждение. По общему признанию, тогда двум легко выйти из синхронизации...)

Другие вопросы по тегам