private List <Run> Itemize(string s, bool rtl, int maxItems) { SCRIPT_ITEM[] pItems = new SCRIPT_ITEM[maxItems]; int pcItems = 0; // initialize Control and State SCRIPT_CONTROL control = new SCRIPT_CONTROL(); SCRIPT_STATE state = new SCRIPT_STATE(); if (rtl) { // this is needed to start paragraph from right state.SetRtl(); // to substitute arabic digits ScriptApplyDigitSubstitution(ref FDigitSubstitute, ref control, ref state); } // itemize ScriptItemize(s, s.Length, pItems.Length, ref control, ref state, pItems, ref pcItems); // create Run list. Note that ScriptItemize actually returns pcItems+1 items, // so this can be used to calculate char range easily List <Run> list = new List <Run>(); for (int i = 0; i < pcItems; i++) { string text = s.Substring(pItems[i].iCharPos, pItems[i + 1].iCharPos - pItems[i].iCharPos); list.Add(new Run(text, pItems[i].analysis)); } return(list); }
public int ScriptItemize(string inChars, out SCRIPT_ITEM[] items, out OPENTYPE_TAG[] scriptTags) { if (string.IsNullOrEmpty(inChars)) { throw new ArgumentException("inChars"); } int length = inChars.Length; items = new SCRIPT_ITEM[length + 1]; for (int index = 0; index < length + 1; index++) { items[index] = default(SCRIPT_ITEM); } scriptTags = new OPENTYPE_TAG[length]; for (int index = 0; index < length; index++) { scriptTags[index] = new OPENTYPE_TAG('\0', '\0', '\0', '\0'); } int itemsCount = 0; int hresult = Usp10.ScriptItemizeOpenType(inChars, length, length + 1, null, 0, items, scriptTags, ref itemsCount); Marshal.ThrowExceptionForHR(hresult); return(itemsCount); }
/// <summary> /// Converts visual string to logical. /// </summary> /// <param name="value">A value to convert.</param> /// <param name="rtl">A base direction.</param> /// <param name="direction"> /// true for visual to logical, and false for logical to visual. /// </param> /// <returns>Converted string.</returns> public static string Convert(string value, bool rtl, bool direction) { if (value == null) { return(null); } int count = value.Length; if (count <= 1) { return(value); } if (NativeMethods.ScriptIsComplex( value, count, Constants.SIC_COMPLEX | Constants.SIC_NEUTRAL) != Constants.S_OK) { return(value); } var control = new SCRIPT_CONTROL(); var state = new SCRIPT_STATE(); int resultCount = 0; int maxCount = count + 1; //control.fInvertPreBoundDir = rtl ? 1 : 0; //control.fInvertPostBoundDir = rtl ? 1 : 0; state.uBidiLevel = rtl ? (ushort)1 : (ushort)0; var items = new SCRIPT_ITEM[maxCount]; if (NativeMethods.ScriptItemize( value, count, maxCount, ref control, ref state, items, out resultCount) != 0) { return(value); } byte[] levels = new byte[count]; for (int i = 0; i < resultCount; i++) { var level = items[i].a.s.uBidiLevel; for (int j = items[i].iCharPos, k = items[i + 1].iCharPos; j < k; j++) { levels[j] = (byte)level; } } var orders = new int[count]; if (NativeMethods.ScriptLayout(count, levels, orders, null) != 0) { return(value); } var result = new char[count]; for (int i = 0; i < count; i++) { var index = orders[i]; var c = value[index]; var level = levels[index]; if (direction && ((level & 1) == 1)) { // Minimal mirroring. switch (c) { case '{': { c = '}'; break; } case '}': { c = '{'; break; } case '(': { c = ')'; break; } case ')': { c = '('; break; } case '<': { c = '>'; break; } case '>': { c = '<'; break; } } } result[i] = c; } return(new string(result, 0, count)); }
/// <summary> /// Converts visual string to logical. /// </summary> /// <param name="value">A value to convert.</param> /// <param name="rtl">A base direction.</param> /// <param name="direction"> /// true for visual to logical, and false for logical to visual. /// </param> /// <returns>Converted string.</returns> public static string Convert(string value, bool rtl, bool direction) { if (value == null) { return null; } int count = value.Length; if (count <= 1) { return value; } if (NativeMethods.ScriptIsComplex( value, count, Constants.SIC_COMPLEX | Constants.SIC_NEUTRAL) != Constants.S_OK) { return value; } var control = new SCRIPT_CONTROL(); var state = new SCRIPT_STATE(); int resultCount = 0; int maxCount = count + 1; //control.fInvertPreBoundDir = rtl ? 1 : 0; //control.fInvertPostBoundDir = rtl ? 1 : 0; state.uBidiLevel = rtl ? (ushort)1 : (ushort)0; var items = new SCRIPT_ITEM[maxCount]; if (NativeMethods.ScriptItemize( value, count, maxCount, ref control, ref state, items, out resultCount) != 0) { return value; } byte[] levels = new byte[count]; for(int i = 0; i < resultCount; i++) { var level = items[i].a.s.uBidiLevel; for(int j = items[i].iCharPos, k = items[i + 1].iCharPos; j < k; j++) { levels[j] = (byte)level; } } var orders = new int[count]; if (NativeMethods.ScriptLayout(count, levels, orders, null) != 0) { return value; } var result = new char[count]; for(int i = 0; i < count; i++) { var index = orders[i]; var c = value[index]; var level = levels[index]; if (direction && ((level & 1) == 1)) { // Minimal mirroring. switch(c) { case '{': { c = '}'; break; } case '}': { c = '{'; break; } case '(': { c = ')'; break; } case ')': { c = '('; break; } case '<': { c = '>'; break; } case '>': { c = '<'; break; } } } result[i] = c; } return new string(result, 0, count); }