/// <summary>
        /// Converts a raw string into a raw hexadecimal string literal, possibly encrypted.
        /// </summary>
        public static string ToHexStringLiteral(string text, PdfStringEncoding encoding, PdfStandardSecurityHandler securityHandler)
        {
            if (String.IsNullOrEmpty(text))
            {
                return("<>");
            }

            byte[] bytes;
            switch (encoding)
            {
            case PdfStringEncoding.RawEncoding:
                bytes = RawEncoding.GetBytes(text);
                break;

            case PdfStringEncoding.WinAnsiEncoding:
                bytes = WinAnsiEncoding.GetBytes(text);
                break;

            case PdfStringEncoding.PDFDocEncoding:
                bytes = DocEncoding.GetBytes(text);
                break;

            case PdfStringEncoding.Unicode:
                //bytes = UnicodeEncoding.GetBytes(text);
                bytes = RawUnicodeEncoding.GetBytes(text);
                break;

            default:
                throw new NotImplementedException(encoding.ToString());
            }

            byte[] agTemp = FormatStringLiteral(bytes, encoding == PdfStringEncoding.Unicode, true, true, securityHandler);
            return(RawEncoding.GetString(agTemp, 0, agTemp.Length));
        }
        /// <summary>
        /// Converts a raw string into a raw hexadecimal string literal, possibly encrypted.
        /// </summary>
        public static string ToHexStringLiteral(byte[] bytes, bool unicode, PdfStandardSecurityHandler securityHandler)
        {
            if (bytes == null || bytes.Length == 0)
            {
                return("<>");
            }

            byte[] agTemp = FormatStringLiteral(bytes, unicode, true, true, securityHandler);
            return(RawEncoding.GetString(agTemp, 0, agTemp.Length));
        }
        /// <summary>
        /// Converts the specified byte array into a byte array representing a string literal.
        /// </summary>
        /// <param name="bytes">The bytes of the string.</param>
        /// <param name="unicode">Indicates whether one or two bytes are one character.</param>
        /// <param name="prefix">Indicates whether to use Unicode prefix.</param>
        /// <param name="hex">Indicates whether to create a hexadecimal string literal.</param>
        /// <param name="securityHandler">Encrypts the bytes if specified.</param>
        /// <returns>The PDF bytes.</returns>
        public static byte[] FormatStringLiteral(byte[] bytes, bool unicode, bool prefix, bool hex, PdfStandardSecurityHandler securityHandler)
        {
            if (bytes == null || bytes.Length == 0)
            {
                return hex ? new byte[] { (byte)'<', (byte)'>' }
            }
            : new byte[] { (byte)'(', (byte)')' };

            Debug.Assert(!unicode || bytes.Length % 2 == 0, "Odd number of bytes in Unicode string.");

            bool encrypted = false;

            if (securityHandler != null)
            {
                bytes = (byte[])bytes.Clone();

                bytes     = securityHandler.EncryptBytes(bytes);
                encrypted = true;
            }

            int           count = bytes.Length;
            StringBuilder pdf   = new StringBuilder();

            if (!unicode)
            {
                if (!hex)
                {
                    pdf.Append("(");
                    for (int idx = 0; idx < count; idx++)
                    {
                        char ch = (char)bytes[idx];
                        if (ch < 32)
                        {
                            switch (ch)
                            {
                            case '\n':
                                pdf.Append("\\n");
                                break;

                            case '\r':
                                pdf.Append("\\r");
                                break;

                            case '\t':
                                pdf.Append("\\t");
                                break;

                            case '\b':
                                pdf.Append("\\b");
                                break;

                            // Corrupts encrypted text.
                            //case '\f':
                            //  pdf.Append("\\f");
                            //  break;

                            default:
                                // Don't escape characters less than 32 if the string is encrypted, because it is
                                // unreadable anyway.
                                encrypted = true;
                                if (!encrypted)
                                {
                                    pdf.Append("\\0");
                                    pdf.Append((char)(ch % 8 + '0'));
                                    pdf.Append((char)(ch / 8 + '0'));
                                }
                                else
                                {
                                    pdf.Append(ch);
                                }
                                break;
                            }
                        }
                        else
                        {
                            switch (ch)
                            {
                            case '(':
                                pdf.Append("\\(");
                                break;

                            case ')':
                                pdf.Append("\\)");
                                break;

                            case '\\':
                                pdf.Append("\\\\");
                                break;

                            default:
                                pdf.Append(ch);
                                break;
                            }
                        }
                    }
                    pdf.Append(')');
                }
                else
                {
                    pdf.Append('<');
                    for (int idx = 0; idx < count; idx++)
                    {
                        pdf.AppendFormat("{0:X2}", bytes[idx]);
                    }
                    pdf.Append('>');
                }
            }
            else
            {
                Hex:
                if (hex)
                {
                    pdf.Append(prefix ? "<FEFF" : "<");
                    for (int idx = 0; idx < count; idx += 2)
                    {
                        pdf.AppendFormat("{0:X2}{1:X2}", bytes[idx], bytes[idx + 1]);
                        if (idx != 0 && (idx % 48) == 0)
                        {
                            pdf.Append("\n");
                        }
                    }
                    pdf.Append(">");
                }
                else
                {
                    // TODO non hex literals... not sure how to treat linefeeds, '(', '\' etc.
                    hex = true;
                    goto Hex;
                }
            }
            return(RawEncoding.GetBytes(pdf.ToString()));
        }