Example #1
0
        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);
        }
Example #2
0
        public SCRIPT_STATE GetAs_SCRIPT_STATE()
        {
            SCRIPT_STATE result = default(SCRIPT_STATE);

            result.word1 = (ushort)((this.uBidiLevel & 0x1F) | (this.fOverrideDirection & 1) << 5 | (this.fInhibitSymSwap & 1) << 6 | (this.fCharShape & 1) << 7 | (this.fDigitSubstitute & 1) << 8 | (this.fInhibitLigate & 1) << 9 | (this.fDisplayZWG & 1) << 10 | (this.fArabicNumContext & 1) << 11 | (this.fGcpClusters & 1) << 12 | (this.fReserved & 1) << 13 | (this.fEngineReserved & 3) << 14);
            return(result);
        }
        internal SCRIPT_STATE GetAs_SCRIPT_STATE()
        {
            SCRIPT_STATE result = default(SCRIPT_STATE);

            result.word1 = (ushort)((uBidiLevel & 0x1F) | ((fOverrideDirection & 1) << 5) | ((fInhibitSymSwap & 1) << 6) | ((fCharShape & 1) << 7) | ((fDigitSubstitute & 1) << 8) | ((fInhibitLigate & 1) << 9) | ((fDisplayZWG & 1) << 10) | ((fArabicNumContext & 1) << 11) | ((fGcpClusters & 1) << 12) | ((fReserved & 1) << 13) | ((fEngineReserved & 3) << 14));
            return(result);
        }
Example #4
0
 public static extern uint ScriptItemize(
     [MarshalAs(UnmanagedType.LPWStr)] string pwcInChars,
     int cInChars,
     int cMaxItems,
     ref SCRIPT_CONTROL psControl,
     ref SCRIPT_STATE psState,
     [In, Out] SCRIPT_ITEM[] pItems,
     ref int pcItems
     );
Example #5
0
 private static extern int ScriptApplyDigitSubstitution(
     ref SCRIPT_DIGITSUBSTITUTE psds, ref SCRIPT_CONTROL psc, ref SCRIPT_STATE pss);
        /// <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);
    }