Как получить символы для контекстного ввода в сложном сценарии?
В некоторых языках RightToLeft (таких как арабский, персидский, урду и т. Д.) Каждая буква может иметь различную форму. Существует изолированная форма, начальная форма и средняя форма (вы можете просто найти ее на карте символов окон для любого шрифта Unicode).
Представьте, что вам нужны точные символы, которые пользователь ввел в текстовое поле, по умолчанию, когда вы преобразуете String в CharArray, он преобразует каждый символ в изолированную форму.
(потому что, когда пользователь вводит символы с клавиатуры, он находится в изолированной форме, а когда он отображается на экране, он будет преобразован в правильный формат; это всего лишь предположение. потому что, если вы создаете строку с использованием точных кодов символов, он будет генерировать правильный массив).
У меня вопрос, как мы можем получить эту форму строки, форму, которая была отображена в текстовом поле.
Если в.NET нет пути, то это означает, что мне нужно создать свой собственный класс для преобразования этого T_T.
3 ответа
Windows использует Uniscribe для выполнения контекстного шейпинга для сложных сценариев (которые могут применяться к языкам от l до to, а также от r до l). Отображаемый текст в текстовом поле основан на информации о глифе после подачи символов в Uniscribe. Хотя стандарт Unicode определяет кодовые точки для каждой из изолированных, начальных, медиальных и конечных форм символов, не все шрифты обязательно поддерживают их, однако они могут иметь предварительно сформированные глифы или использовать комбинацию глифов - Uniscribe использует механизм формирования из языковой пакет Windows, чтобы определить, какой глиф (ы) использовать, на основе cmap шрифта. Вот некоторые соответствующие ссылки:
- Больше Uniscribe Mysteries (объясняет разницу между глифами и символами)
- Microsoft Bhasha, Обработка глифов: Uniscribe
- MSDN: Сложное понимание сценариев
- В недрах кода Mozilla скрыт код, который обрабатывает сложные сценарии рендеринга с использованием Uniscribe. Также имеется дополнительный код, который сканирует список шрифтов в системе и считывает таблицы cmap каждого шрифта. (Из комментариев на http://www.siao2.com/2005/12/06/500485.aspx).
- Сортировка всего: Out: Он сказал, шейпинг? Это не в сценарии!
Метод 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";
(Затем, возможно, потом добавьте комментарий, показывающий неэкранированное значение; по крайней мере, если оно выглядит правильно, оно не будет слишком вводящим в заблуждение. По общему признанию, тогда двум легко выйти из синхронизации...)