예제 #1
0
        public static bool ScriptIsComplex(string str)
        {
            uint res = 0;

            try
            {
                // Determines whether a Unicode string requires complex script processing.
                res = 0;
                res = Uniscribe.ScriptIsComplex(str, str.Length, (uint)Uniscribe.SCRIPT_IS_COMPLEX_FLAG.SIC_COMPLEX);

                if ((res != 0) && (res != 1))
                {
                    throw new Exception(); // Some kind of error.
                }
            }
            catch (System.Exception ex)
            {
                Console.WriteLine(ex.Message);
            }

            if (res == 0)
            {
                return(true);
            }

            if (res == 1)
            {
                return(false);
            }

            return(false);
        }
예제 #2
0
        private static bool callScriptTextOutForItem(IntPtr HDC, IntPtr psc, int x, int y, uint fuOptions, Win32.RECT lprc,
                                                     Uniscribe.SCRIPT_ANALYSIS psa, string pwcReserved, int iReserved,
                                                     ushort[] pwGlyphs, int cGlyphs,
                                                     int[] piAdvance, int[] piJustify, Uniscribe.GOFFSET[] pGoffset)
        {
            uint res = 0;

            try
            {
                res = 0;

                res = Uniscribe.ScriptTextOut(HDC, ref psc, /*x*/ 0, /*y*/ 0, /*fuOptions*/ 0,
                                              /*lprc*/ null, psa, /*pwcReserved*/ IntPtr.Zero, /*iReserved*/ 0,
                                              pwGlyphs, cGlyphs, piAdvance, piJustify, pGoffset);

                if (res != 0)
                {
                }
            }
            catch (System.Exception)
            {
            }

            return(res == 0);
        }
예제 #3
0
        public static bool ScriptLayout(string str, Uniscribe.SCRIPT_ITEM[] items,
                                        out int[] res_visual_to_logical, out int[] res_logical_to_visual)
        {
//             res_visual_to_logical = null;
//             res_logical_to_visual = null;

            // Output arrays
            int[] visual_to_logical;
            int[] logical_to_visual;

            // Construct the "embedding level" array for our list of runs that tell
            // Uniscribe what direction they are. Here, we do NOT count the magic last item
            // that is empty, we manually add it to the end of the lookup tables to keep
            // everything consistent (it is always at the end). I'm not sure what
            // ScriptLayout does with this item, so I prefer to handle it myself.
            byte[] directions;
            directions = new byte[items.Length];
            for (int i = 0; i < items.Length - 1; i++)
            {
                directions[i] = items[i].a.s.uBidiLevel;
            }

            visual_to_logical = new int[items.Length - 1];
            logical_to_visual = new int[items.Length - 1];

            uint res = 0;

            try
            {
                res = 0;
                res = Uniscribe.ScriptLayout(items.Length - 1, directions, visual_to_logical, logical_to_visual);

                if (res != 0)
                {
                    throw new Exception(); // Some kind of error.
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }

            // Now add the magic last item back
            res_visual_to_logical = new int[items.Length];
            Array.Copy(visual_to_logical, res_visual_to_logical, items.Length - 1);
            res_visual_to_logical[items.Length - 1] = items.Length - 1;

            res_logical_to_visual = new int[items.Length];
            Array.Copy(logical_to_visual, res_logical_to_visual, items.Length - 1);
            res_logical_to_visual[items.Length - 1] = items.Length - 1;

            return(res == 0);
        }
예제 #4
0
        private static bool callScriptJustifyForItem(Uniscribe.SCRIPT_VISATTR[] psva, int[] piAdvance, int cGlyphs,
                                                     int iDx, int iMinKashida, out int[] piJustify)
        {
            piJustify = new int[cGlyphs];

            uint res = 0;

            try
            {
                res = 0;
                res = Uniscribe.ScriptJustify(psva, piAdvance, cGlyphs, iDx, iMinKashida, piJustify);
            }
            catch (System.Exception)
            {
            }

            return(res == 0);
        }
예제 #5
0
        public static bool ScriptGetProperties(out Uniscribe.SCRIPT_PROPERTIES[] ppScriptProperties)
        {
            ppScriptProperties = null;

            uint res = 0;

            try
            {
                IntPtr p            = IntPtr.Zero;
                int    piNumScripts = 0;

                res = 0;
                res = Uniscribe.ScriptGetProperties(ref p, ref piNumScripts);

                if (res != 0)
                {
                    throw new Exception(); // Some kind of error.
                }

                IntPtr[] destination = new IntPtr[piNumScripts];
                Marshal.Copy(p, destination, 0, piNumScripts);

                ppScriptProperties = new Uniscribe.SCRIPT_PROPERTIES[piNumScripts];
                for (int i = 0; i < piNumScripts; i++)
                {
                    Uniscribe.SCRIPT_PROPERTIES ppSpi = (Uniscribe.SCRIPT_PROPERTIES)Marshal.PtrToStructure(
                        destination[i], typeof(Uniscribe.SCRIPT_PROPERTIES));
                    ppScriptProperties[i] = ppSpi;
                }
            }
            catch (System.Exception ex)
            {
                Console.WriteLine(ex.Message);
            }

            return(res == 0);
        }
예제 #6
0
        public static bool ScriptBreakForItem(string input, int input_length, Uniscribe.SCRIPT_ANALYSIS psa,
                                              out Uniscribe.SCRIPT_LOGATTR[] psla)
        {
            psla = new Uniscribe.SCRIPT_LOGATTR[input_length];

            uint res = 0;

            try
            {
                res = 0;
                res = Uniscribe.ScriptBreak(input, input_length, psa, psla);

                if (res != 0)
                {
                    psla = null;
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }

            return(res == 0);
        }
예제 #7
0
        public static bool ScriptGetFontProperties(System.Drawing.Font font, out Uniscribe.SCRIPT_FONTPROPERTIES sfp)
        {
            sfp = new Uniscribe.SCRIPT_FONTPROPERTIES();

            if (font == null)
            {
                return(false);
            }

            // HFONT hfont = initialize your font;
            IntPtr hfont = font.ToHfont();

            IntPtr psc = IntPtr.Zero; // Initialize to NULL, will be filled lazily.

            IntPtr hdcSrc = IntPtr.Zero;
            IntPtr HDC    = IntPtr.Zero; // Don't give it a DC unless we have to.

            // HFONT old_font = NULL;
            IntPtr old_font = IntPtr.Zero;

            uint res = 0;

            sfp        = new Uniscribe.SCRIPT_FONTPROPERTIES();
            sfp.cBytes = Marshal.SizeOf(typeof(Uniscribe.SCRIPT_FONTPROPERTIES));

            for (int i = 0; i < 2; i++)
            {
                try
                {
                    res = 0;
                    res = Uniscribe.ScriptGetFontProperties(HDC, ref psc, ref sfp);

                    if (res != 0)
                    {
                        if (res == Win32.E_PENDING)
                        {
                            throw new ArgumentException();
                        }
                        else
                        {
                            throw new Exception(); // Some kind of error.
                        }
                    }

                    break;
                }
                catch (ArgumentException)
                {
                    // ... select font into hdc ...

                    hdcSrc = Win32.GetDC(IntPtr.Zero);
                    HDC    = Win32.CreateCompatibleDC(hdcSrc);

                    old_font = Win32.SelectObject(HDC, hfont);

                    // Loop again...
                    continue;
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                    break;
                }
            }

            if (old_font != IntPtr.Zero)
            {
                Win32.SelectObject(HDC, old_font);  // Put back the previous font.
            }
            Win32.ReleaseDC(IntPtr.Zero, HDC);
            Win32.ReleaseDC(IntPtr.Zero, hdcSrc);

            // Need to tell Uniscribe to delete the cache we were using. If you are going
            // to keep the HFONT around, you should probably also keep the cache.
            //             ScriptFreeCache(psc);

            Win32.DeleteObject(hfont);

            return(res == 0);
        }
예제 #8
0
        private static bool callScriptPlaceForItem(ref IntPtr hfont, ref IntPtr psc,
                                                   ushort[] pwGlyphs, int cGlyphs, Uniscribe.SCRIPT_VISATTR[] psva,
                                                   ref Uniscribe.SCRIPT_ANALYSIS psa,
                                                   out int[] piAdvance, out Uniscribe.GOFFSET[] pGoffset, out Uniscribe.ABC pABC)
        {
            // All arrays are in visual order unless the fLogicalOrder member is set
            // in the SCRIPT_ANALYSIS structure indicated by the psa parameter.
            psa.fLogicalOrder = true;

            piAdvance = new int[cGlyphs];
            pGoffset  = new Uniscribe.GOFFSET[cGlyphs];

            pABC = new Uniscribe.ABC();

            IntPtr hdcSrc = IntPtr.Zero;
            IntPtr HDC    = IntPtr.Zero; // Don't give it a DC unless we have to.

            // HFONT old_font = NULL;
            IntPtr old_font = IntPtr.Zero;

            uint res = 0;

            //while (true)
            for (int max = 1000; max > 0; --max)
            {
                try
                {
                    res = 0;
                    res = Uniscribe.ScriptPlace(HDC, ref psc, pwGlyphs, cGlyphs, psva, ref psa, piAdvance, pGoffset, ref pABC);

                    if (res != 0)
                    {
                        // Different types of failure...
                        if (res == Win32.E_PENDING)
                        {
                            // Need to select the font for the call. Don't do this if we don't have to
                            // since it may be slow.
                            throw new ArgumentException();
                        }
                        else
                        {
                            throw new Exception(); // Some other failure.
                        }
                    }

                    break;
                }
                catch (ArgumentException)
                {
                    // ... select font into hdc ...

                    hdcSrc = Win32.GetDC(IntPtr.Zero);
                    HDC    = Win32.CreateCompatibleDC(hdcSrc);

                    old_font = Win32.SelectObject(HDC, hfont);

                    // Loop again...
                    continue;
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                    break;
                }
            }

            if (old_font != IntPtr.Zero)
            {
                Win32.SelectObject(HDC, old_font);  // Put back the previous font.
            }
            Win32.ReleaseDC(IntPtr.Zero, HDC);
            Win32.ReleaseDC(IntPtr.Zero, hdcSrc);

            return(res == 0);
        }
예제 #9
0
        // Called with the array output by callScriptItemize, this will
        private static bool callScriptShapeForItem(string input, int input_length,      // IN: characters
                                                   ref IntPtr hfont, ref IntPtr psc,    // IN: font info
                                                   Uniscribe.SCRIPT_ANALYSIS sa,        // IN: from ScriptItemize
                                                   out ushort[] pwOutGlyphs,            // OUT: one per glyph
                                                   out ushort[] pwLogClust,             // OUT: one per character
                                                   out Uniscribe.SCRIPT_VISATTR[] psva) // OUT: one per glyph
        {
            // Initial size guess for the number of glyphs recommended by Uniscribe
            int cMaxGlyphs = input_length * 3 / 2 + 16;

            pwOutGlyphs = new ushort[cMaxGlyphs];
            psva        = new Uniscribe.SCRIPT_VISATTR[cMaxGlyphs];

            // The logs array is the same size as the input.
            pwLogClust = new ushort[input_length];

            IntPtr hdcSrc = IntPtr.Zero;
            IntPtr HDC    = IntPtr.Zero; // Don't give it a DC unless we have to.

            // HFONT old_font = NULL;
            IntPtr old_font = IntPtr.Zero;

            uint res = 0;

            //while (true)
            for (int max = 1000; max > 0; --max)
            {
                try
                {
                    int pcGlyphs = 0;

                    res = 0;
                    res = Uniscribe.ScriptShape(HDC, ref psc, input, input_length, cMaxGlyphs, ref sa,
                                                pwOutGlyphs, pwLogClust, psva, ref pcGlyphs);

                    if (res != 0)
                    {
                        // Different types of failure...
                        if (res == Win32.E_PENDING)
                        {
                            // Need to select the font for the call. Don't do this if we don't have to
                            // since it may be slow.
                            throw new ArgumentException();
                        }
                        else if (res == Win32.E_OUTOFMEMORY)
                        {
                            // The glyph buffer needs to be larger. Just double it every time.
                            throw new OutOfMemoryException();
                        }
                        else if (res == Win32.USP_E_SCRIPT_NOT_IN_FONT)
                        {
                            // The font you selected doesn't have enough information to display
                            // what you want. You'll have to pick another one somehow...
                            // For our cases, we'll just return failure.
                            //throw new Exception(); // Some other failure.

                            sa.eScript = 0;
                            // Loop again...
                            continue;
                        }
                        else
                        {
                            throw new Exception(); // Some other failure.
                        }
                    }

                    // It worked, resize the output list to the exact number it returned.
                    ushort[] glyphs = new ushort[pcGlyphs];
                    Array.Copy(pwOutGlyphs, glyphs, pcGlyphs);
                    pwOutGlyphs = glyphs;

                    ushort[] logs = new ushort[pcGlyphs];
                    Array.Copy(pwLogClust, logs, pcGlyphs);
                    pwLogClust = logs;

                    Uniscribe.SCRIPT_VISATTR[] visattr = new Uniscribe.SCRIPT_VISATTR[pcGlyphs];
                    Array.Copy(psva, visattr, pcGlyphs);
                    psva = visattr;

                    break;
                }
                catch (ArgumentException)
                {
                    // ... select font into hdc ...

                    hdcSrc = Win32.GetDC(IntPtr.Zero);
                    HDC    = Win32.CreateCompatibleDC(hdcSrc);

                    old_font = Win32.SelectObject(HDC, hfont);

                    // Loop again...
                    continue;
                }
                catch (OutOfMemoryException)
                {
                    cMaxGlyphs  = pwOutGlyphs.Length * 2;
                    pwOutGlyphs = new ushort[cMaxGlyphs];
                    psva        = new Uniscribe.SCRIPT_VISATTR[cMaxGlyphs];
                    // Loop again...
                    continue;
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                    break;
                }
            }

            if (old_font != IntPtr.Zero)
            {
                Win32.SelectObject(HDC, old_font);  // Put back the previous font.
            }
            Win32.ReleaseDC(IntPtr.Zero, HDC);
            Win32.ReleaseDC(IntPtr.Zero, hdcSrc);

            return(res == 0);
        }
예제 #10
0
        public static bool ScriptGetCMap(string str, System.Drawing.Font font, Uniscribe.SCRIPT_FONTPROPERTIES sfp)
        {
            if (font == null)
            {
                return(false);
            }

            uint res = 0;

            // HFONT hfont = initialize your font;
            IntPtr hfont = font.ToHfont();

            IntPtr psc = IntPtr.Zero; // Initialize to NULL, will be filled lazily.

            IntPtr hdcSrc = IntPtr.Zero;
            IntPtr HDC    = IntPtr.Zero; // Don't give it a DC unless we have to.

            // HFONT old_font = NULL;
            IntPtr old_font = IntPtr.Zero;

            ushort[] pwOutGlyphs = new ushort[str.Length];

            for (int max = 1000; max > 0; --max)
            {
                try
                {
                    res = 0;
                    res = Uniscribe.ScriptGetCMap(HDC, ref psc, str, str.Length, 0, pwOutGlyphs);

                    if (res != 0)
                    {
                        // Different types of failure...
                        if (res == Win32.E_PENDING)
                        {
                            // Need to select the font for the call. Don't do this if we don't have to
                            // since it may be slow.
                            throw new ArgumentException();
                        }
                        if (res == Win32.E_HANDLE)
                        {
                            // The font or the operating system does not support glyph indexes.
                            throw new Exception();
                        }
                        else if (res == Win32.S_FALSE)
                        {
                            // Some of the Unicode code points were mapped to the default glyph.
                            throw new Exception();
                        }
                    }

                    // call ScriptGetFontProperties
                    int defaultGlyph = sfp.wgDefault;

                    for (int i = 0; i < str.Length; i++)
                    {
                        if (pwOutGlyphs[i] == defaultGlyph)
                        {
                            //  character with that index is not available in selected font
                        }
                    }

                    break;
                }
                catch (ArgumentException)
                {
                    // ... select font into hdc ...

                    hdcSrc = Win32.GetDC(IntPtr.Zero);
                    HDC    = Win32.CreateCompatibleDC(hdcSrc);

                    old_font = Win32.SelectObject(HDC, hfont);

                    // Loop again...
                    continue;
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                    break;
                }
            }

            if (old_font != IntPtr.Zero)
            {
                Win32.SelectObject(HDC, old_font);  // Put back the previous font.
            }
            Win32.ReleaseDC(IntPtr.Zero, HDC);
            Win32.ReleaseDC(IntPtr.Zero, hdcSrc);

            // Need to tell Uniscribe to delete the cache we were using. If you are going
            // to keep the HFONT around, you should probably also keep the cache.
            //             ScriptFreeCache(psc);

            Win32.DeleteObject(hfont);

            return(res == 0);
        }
예제 #11
0
        public static bool ScriptItemize(string str, out Uniscribe.SCRIPT_ITEM[] items, bool directionRightToLeft)
        {
            items = null;

            Uniscribe.SCRIPT_CONTROL psControl = new Uniscribe.SCRIPT_CONTROL();

            Uniscribe.SCRIPT_STATE psState = new Uniscribe.SCRIPT_STATE();

            // 0 means that the surrounding text is left-to-right.
            psState.uBidiLevel = (byte)((directionRightToLeft) ? 1 : 0);

            int  max_items = 16;
            uint res       = 0;

            for (int max = 1000; max > 0; --max)
            {
                Uniscribe.SCRIPT_ITEM[] pItems = new Uniscribe.SCRIPT_ITEM[max_items + 1];
                int pcItems = 0;

                try
                {
                    // We subtract one from max_items to work around a buffer overflow on some
                    // older versions of Windows.
                    res = 0;
                    res = Uniscribe.ScriptItemize(str, str.Length, max_items - 1, ref psControl, ref psState, pItems, ref pcItems);

                    if (res != 0)
                    {
                        if (res == Win32.E_OUTOFMEMORY)
                        {
                            throw new OutOfMemoryException();
                        }
                        else
                        {
                            throw new Exception(); // Some kind of error.
                        }
                    }

                    // It generated some items, so resize the array. Note that we add
                    // one to account for the magic last item.
                    pcItems += 1; // pcItems doesn't include the terminal item by default

                    items = new Uniscribe.SCRIPT_ITEM[pcItems];
                    Array.Copy(pItems, items, pcItems);

                    break;
                }
                catch (OutOfMemoryException)
                {
                    // The input array isn't big enough, double and loop again.
                    // thrown by ScriptItemize if items wasn't large enough
                    max_items *= 2;
                    continue;
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                    break;
                }
            }

            return(res == 0);
        }