Ejemplo n.º 1
0
        private InlineImage ParseInlineImage(
            )
        {
            /*
             * NOTE: Inline images use a peculiar syntax that's an exception to the usual rule
             * that the data in a content stream is interpreted according to the standard PDF syntax
             * for objects.
             */
            InlineImageHeader header;
            {
                List <PdfDirectObject> operands = new List <PdfDirectObject>();
                // Parsing the image entries...
                while (MoveNext() &&
                       tokenType != TokenTypeEnum.Keyword) // Not keyword (i.e. end at image data beginning (ID operator)).
                {
                    operands.Add(ParsePdfObject());
                }
                header = new InlineImageHeader(operands);
            }

            InlineImageBody body;

            {
                MoveNext();
                bytes::Buffer data = new bytes::Buffer();
                byte          c1 = 0, c2 = 0;
                do
                {
                    try
                    {
                        while (true)
                        {
                            c1 = (byte)stream.ReadByte();
                            c2 = (byte)stream.ReadByte();
                            if (c1 == 'E' && c2 == 'I')
                            {
                                break;
                            }

                            data.Append(c1);
                            data.Append(c2);
                        }
                        break;
                    }
                    catch
                    {
                        /* NOTE: Current stream has finished. */
                        // Move to the next stream!
                        MoveNextStream();
                    }
                } while(stream != null);
                body = new InlineImageBody(data);
            }

            return(new InlineImage(
                       header,
                       body
                       ));
        }
Ejemplo n.º 2
0
        private InlineImage ParseInlineImage()
        {
            /*
             * NOTE: Inline images use a peculiar syntax that's an exception to the usual rule
             * that the data in a content stream is interpreted according to the standard PDF syntax
             * for objects.
             */
            InlineImageHeader header;
            {
                List <PdfDirectObject> operands = new List <PdfDirectObject>();
                // Parsing the image entries...
                while (MoveNext() && TokenType != TokenTypeEnum.Keyword) // Not keyword (i.e. end at image data beginning (ID operator)).
                {
                    operands.Add((PdfDirectObject)ParsePdfObject());
                }
                header = new InlineImageHeader(operands);
            }

            InlineImageBody body;

            {
                // [FIX:51,74] Wrong 'EI' token handling on inline image parsing.
                bytes::IInputStream stream = Stream;
                stream.ReadByte(); // Should be the whitespace following the 'ID' token.
                bytes::Buffer data = new bytes::Buffer();
                while (true)
                {
                    int curByte1 = stream.ReadByte();
                    if (curByte1 == -1)
                    {
                        break;
                    }
                    int curByte2 = stream.ReadByte();
                    if (curByte2 == -1)
                    {
                        break;
                    }

                    if (((char)curByte1 == 'E' && (char)curByte2 == 'I'))
                    {
                        break;
                    }
                    if (((char)curByte1 == ' ' && (char)curByte2 == 'E'))
                    {
                        break;
                    }
                    data.Append((byte)curByte1);
                    data.Append((byte)curByte2);
                }
                body = new InlineImageBody(data);
            }

            return(new InlineImage(header, body));
        }
Ejemplo n.º 3
0
        private InlineImage ParseInlineImage(
            )
        {
            /*
             * NOTE: Inline images use a peculiar syntax that's an exception to the usual rule
             * that the data in a content stream is interpreted according to the standard PDF syntax
             * for objects.
             */
            InlineImageHeader header;
            {
                List <PdfDirectObject> operands = new List <PdfDirectObject>();
                // Parsing the image entries...
                while (MoveNext() &&
                       TokenType != TokenTypeEnum.Keyword) // Not keyword (i.e. end at image data beginning (ID operator)).
                {
                    operands.Add((PdfDirectObject)ParsePdfObject());
                }
                header = new InlineImageHeader(operands);
            }

            InlineImageBody body;

            {
                bytes::IInputStream stream = Stream;
                MoveNext();
                bytes::Buffer data     = new bytes::Buffer();
                byte          prevByte = 0;
                while (true)
                {
                    byte curByte = (byte)stream.ReadByte();
                    if (prevByte == 'E' && curByte == 'I')
                    {
                        break;
                    }

                    data.Append(prevByte = curByte);
                }
                body = new InlineImageBody(data);
            }

            return(new InlineImage(
                       header,
                       body
                       ));
        }
Ejemplo n.º 4
0
        private InlineImage ParseInlineImage(
      )
        {
            /*
            NOTE: Inline images use a peculiar syntax that's an exception to the usual rule
            that the data in a content stream is interpreted according to the standard PDF syntax
            for objects.
              */
              InlineImageHeader header;
              {
            List<PdfDirectObject> operands = new List<PdfDirectObject>();
            // Parsing the image entries...
            while(MoveNext()
              && TokenType != TokenTypeEnum.Keyword) // Not keyword (i.e. end at image data beginning (ID operator)).
            {operands.Add((PdfDirectObject)ParsePdfObject());}
            header = new InlineImageHeader(operands);
              }

              InlineImageBody body;
              {
            bytes::IInputStream stream = Stream;
            MoveNext();
            bytes::Buffer data = new bytes::Buffer();
            while(true)
            {
              byte c1 = (byte)stream.ReadByte();
              byte c2 = (byte)stream.ReadByte();
              if(c1 == 'E' && c2 == 'I')
            break;

              data.Append(c1);
              data.Append(c2);
            }
            body = new InlineImageBody(data);
              }

              return new InlineImage(
            header,
            body
            );
        }
Ejemplo n.º 5
0
        private InlineImage ParseInlineImage(
            )
        {
            /*
             * NOTE: Inline images use a peculiar syntax that's an exception to the usual rule
             * that the data in a content stream is interpreted according to the standard PDF syntax
             * for objects.
             */
            InlineImageHeader header;
            {
                List <PdfDirectObject> operands = new List <PdfDirectObject>();
                // Parsing the image entries...
                while (MoveNext() &&
                       TokenType != TokenTypeEnum.Keyword) // Not keyword (i.e. end at image data beginning (ID operator)).
                {
                    operands.Add((PdfDirectObject)ParsePdfObject());
                }
                header = new InlineImageHeader(operands);
            }

            InlineImageBody body;

            {
                // [FIX:51,74] Wrong 'EI' token handling on inline image parsing.
                bytes::IInputStream stream = Stream;
                stream.ReadByte(); // Should be the whitespace following the 'ID' token.
                bytes::Buffer data           = new bytes::Buffer();
                var           endChunkBuffer = new sysIO::MemoryStream(3);
                int           endChunkIndex  = -1;
                while (true)
                {
                    int curByte = stream.ReadByte();
                    if (curByte == -1)
                    {
                        throw new PostScriptParseException("No 'EI' token found to close inline image data stream.");
                    }

                    if (endChunkIndex == -1)
                    {
                        if (IsWhitespace(curByte))
                        {
                            /*
                             * NOTE: Whitespace characters may announce the beginning of the end image operator.
                             */
                            endChunkBuffer.WriteByte((byte)curByte);
                            endChunkIndex++;
                        }
                        else
                        {
                            data.Append((byte)curByte);
                        }
                    }
                    else if (endChunkIndex == 0 && IsWhitespace(curByte))
                    {
                        /*
                         * NOTE: Only the last whitespace character may announce the beginning of the end image
                         * operator.
                         */
                        data.Append(endChunkBuffer.ToArray());
                        endChunkBuffer.SetLength(0);
                        endChunkBuffer.WriteByte((byte)curByte);
                    }
                    else if ((endChunkIndex == 0 && curByte == 'E') ||
                             (endChunkIndex == 1 && curByte == 'I'))
                    {
                        /*
                         * NOTE: End image operator characters.
                         */
                        endChunkBuffer.WriteByte((byte)curByte);
                        endChunkIndex++;
                    }
                    else if (endChunkIndex == 2 && IsWhitespace(curByte))
                    {
                        /*
                         * NOTE: The whitespace character after the end image operator completes the pattern.
                         */
                        break;
                    }
                    else
                    {
                        if (endChunkIndex > -1)
                        {
                            data.Append(endChunkBuffer.ToArray());
                            endChunkBuffer.SetLength(0);
                            endChunkIndex = -1;
                        }
                        data.Append((byte)curByte);
                    }
                }
                body = new InlineImageBody(data);
            }

            return(new InlineImage(
                       header,
                       body
                       ));
        }
Ejemplo n.º 6
0
        /**
         * <summary>Builds a CMap according to the specified arguments.</summary>
         * <param name="entryType"></param>
         * <param name="cmapName">CMap name (<code>null</code> in case no custom name is needed).</param>
         * <param name="codes"></param>
         * <param name="outCodeFunction"></param>
         * <returns>Buffer containing the serialized CMap.</returns>
         */
        public static bytes::IBuffer Build(
            EntryTypeEnum entryType,
            string cmapName,
            SortedDictionary <ByteArray, int> codes,
            GetOutCodeDelegate outCodeFunction
            )
        {
            bytes::IBuffer buffer = new bytes::Buffer();

            // Header.
            string outCodeFormat;

            switch (entryType)
            {
            case EntryTypeEnum.BaseFont:
            {
                if (cmapName == null)
                {
                    cmapName = "Adobe-Identity-UCS";
                }
                buffer.Append(
                    "/CIDInit /ProcSet findresource begin\n"
                    + "12 dict begin\n"
                    + "begincmap\n"
                    + "/CIDSystemInfo\n"
                    + "<< /Registry (Adobe)\n"
                    + "/Ordering (UCS)\n"
                    + "/Supplement 0\n"
                    + ">> def\n"
                    + "/CMapName /").Append(cmapName).Append(" def\n"
                                                             + "/CMapVersion 10.001 def\n"
                                                             + "/CMapType 2 def\n"
                                                             + "1 begincodespacerange\n"
                                                             + "<0000> <FFFF>\n"
                                                             + "endcodespacerange\n"
                                                             );
                outCodeFormat = "<{0:X4}>";
                break;
            }

            case EntryTypeEnum.CID:
            {
                if (cmapName == null)
                {
                    cmapName = "Custom";
                }
                buffer.Append(
                    "%!PS-Adobe-3.0 Resource-CMap\n"
                    + "%%DocumentNeededResources: ProcSet (CIDInit)\n"
                    + "%%IncludeResource: ProcSet (CIDInit)\n"
                    + "%%BeginResource: CMap (").Append(cmapName).Append(")\n"
                                                                         + "%%Title: (").Append(cmapName).Append(" Adobe Identity 0)\n"
                                                                                                                 + "%%Version: 1\n"
                                                                                                                 + "%%EndComments\n"
                                                                                                                 + "/CIDInit /ProcSet findresource begin\n"
                                                                                                                 + "12 dict begin\n"
                                                                                                                 + "begincmap\n"
                                                                                                                 + "/CIDSystemInfo 3 dict dup begin\n"
                                                                                                                 + "/Registry (Adobe) def\n"
                                                                                                                 + "/Ordering (Identity) def\n"
                                                                                                                 + "/Supplement 0 def\n"
                                                                                                                 + "end def\n"
                                                                                                                 + "/CMapVersion 1 def\n"
                                                                                                                 + "/CMapType 1 def\n"
                                                                                                                 + "/CMapName /").Append(cmapName).Append(" def\n"
                                                                                                                                                          + "/WMode 0 def\n"
                                                                                                                                                          + "1 begincodespacerange\n"
                                                                                                                                                          + "<0000> <FFFF>\n"
                                                                                                                                                          + "endcodespacerange\n"
                                                                                                                                                          );
                outCodeFormat = "{0}";
                break;
            }

            default:
                throw new NotImplementedException();
            }

            // Entries.
            {
                IList <KeyValuePair <ByteArray, int> >  cidChars  = new List <KeyValuePair <ByteArray, int> >();
                IList <KeyValuePair <ByteArray, int>[]> cidRanges = new List <KeyValuePair <ByteArray, int>[]>();
                {
                    KeyValuePair <ByteArray, int>?  lastCodeEntry = null;
                    KeyValuePair <ByteArray, int>[] lastCodeRange = null;
                    foreach (KeyValuePair <ByteArray, int> codeEntry in codes)
                    {
                        if (lastCodeEntry.HasValue)
                        {
                            int codeLength = codeEntry.Key.Data.Length;
                            if (codeLength == lastCodeEntry.Value.Key.Data.Length &&
                                codeEntry.Key.Data[codeLength - 1] - lastCodeEntry.Value.Key.Data[codeLength - 1] == 1 &&
                                outCodeFunction(codeEntry) - outCodeFunction(lastCodeEntry.Value) == 1) // Contiguous codes.
                            {
                                if (lastCodeRange == null)
                                {
                                    lastCodeRange = new KeyValuePair <ByteArray, int>[] { lastCodeEntry.Value, default(KeyValuePair <ByteArray, int>) };
                                }
                            }
                            else // Separated codes.
                            {
                                AddEntry(cidRanges, cidChars, lastCodeEntry.Value, lastCodeRange);
                                lastCodeRange = null;
                            }
                        }
                        lastCodeEntry = codeEntry;
                    }
                    AddEntry(cidRanges, cidChars, lastCodeEntry.Value, lastCodeRange);
                }
                // Ranges section.
                BuildEntriesSection(buffer, entryType, cidRanges, BuildRangeEntry, "range", outCodeFunction, outCodeFormat);
                // Chars section.
                BuildEntriesSection(buffer, entryType, cidChars, BuildCharEntry, "char", outCodeFunction, outCodeFormat);
            }

            // Trailer.
            switch (entryType)
            {
            case EntryTypeEnum.BaseFont:
                buffer.Append(
                    "endcmap\n"
                    + "CMapName currentdict /CMap defineresource pop\n"
                    + "end\n"
                    + "end\n"
                    );
                break;

            case EntryTypeEnum.CID:
                buffer.Append(
                    "endcmap\n"
                    + "CMapName currentdict /CMap defineresource pop\n"
                    + "end\n"
                    + "end\n"
                    + "%%EndResource\n"
                    + "%%EOF"
                    );
                break;

            default:
                throw new NotImplementedException();
            }

            return(buffer);
        }
Ejemplo n.º 7
0
        /**
          <summary>Creates the character code mapping for composite fonts.</summary>
        */
        private void Load_CreateEncoding(
            PdfDictionary font,
            PdfDictionary cidFont
            )
        {
            // CMap [PDF:1.6:5.6.4].
              bytes::Buffer cmapBuffer = new bytes::Buffer();
              cmapBuffer.Append(
            "%!PS-Adobe-3.0 Resource-CMap\n"
              + "%%DocumentNeededResources: ProcSet (CIDInit)\n"
              + "%%IncludeResource: ProcSet (CIDInit)\n"
              + "%%BeginResource: CMap (Adobe-Identity-UCS)\n"
              + "%%Title: (Adobe-Identity-UCS Adobe Identity 0)\n"
              + "%%Version: 1\n"
              + "%%EndComments\n"
              + "/CIDInit /ProcSet findresource begin\n"
              + "12 dict begin\n"
              + "begincmap\n"
              + "/CIDSystemInfo\n"
              + "3 dict dup begin\n"
              + "/Registry (Adobe) def\n"
              + "/Ordering (Identity) def\n"
              + "/Supplement 0 def\n"
              + "end def\n"
              + "/CMapName /Adobe-Identity-UCS def\n"
              + "/CMapVersion 1 def\n"
              + "/CMapType 0 def\n"
              + "/WMode 0 def\n"
              + "2 begincodespacerange\n"
              + "<20> <20>\n"
              + "<0000> <19FF>\n"
              + "endcodespacerange\n"
              + glyphIndexes.Count + " begincidchar\n"
            );
              // ToUnicode [PDF:1.6:5.9.2].
              bytes::Buffer toUnicodeBuffer = new bytes::Buffer();
              toUnicodeBuffer.Append(
            "/CIDInit /ProcSet findresource begin\n"
              + "12 dict begin\n"
              + "begincmap\n"
              + "/CIDSystemInfo\n"
              + "<< /Registry (Adobe)\n"
              + "/Ordering (UCS)\n"
              + "/Supplement 0\n"
              + ">> def\n"
              + "/CMapName /Adobe-Identity-UCS def\n"
              + "/CMapVersion 10.001 def\n"
              + "/CMapType 2 def\n"
              + "2 begincodespacerange\n"
              + "<20> <20>\n"
              + "<0000> <19FF>\n"
              + "endcodespacerange\n"
              + glyphIndexes.Count + " beginbfchar\n"
            );
              // CIDToGIDMap [PDF:1.6:5.6.3].
              bytes::Buffer gIdBuffer = new bytes::Buffer();
              gIdBuffer.Append((byte)0);
              gIdBuffer.Append((byte)0);
              int code = 0;
              codes = new BiDictionary<ByteArray,int>(glyphIndexes.Count);
              PdfArray widthsObject = new PdfArray(glyphWidths.Count);
              foreach(KeyValuePair<int,int> glyphIndexEntry in glyphIndexes)
              {
            // Character code (unicode to codepoint) entry.
            code++;
            byte[] charCode = (glyphIndexEntry.Key == 32
              ? new byte[]{32}
              : new byte[]
            {
              (byte)((code >> 8) & 0xFF),
              (byte)(code & 0xFF)
            });
            codes[new ByteArray(charCode)] = glyphIndexEntry.Key;

            // CMap entry.
            cmapBuffer.Append("<");
            toUnicodeBuffer.Append("<");
            for(int charCodeBytesIndex = 0,
            charCodeBytesLength = charCode.Length;
              charCodeBytesIndex < charCodeBytesLength;
              charCodeBytesIndex++
              )
            {
              string hex = ((int)charCode[charCodeBytesIndex]).ToString("X2");
              cmapBuffer.Append(hex);
              toUnicodeBuffer.Append(hex);
            }
            cmapBuffer.Append("> " + code + "\n");
            toUnicodeBuffer.Append("> <" + glyphIndexEntry.Key.ToString("X4") + ">\n");

            // CID-to-GID entry.
            int glyphIndex = glyphIndexEntry.Value;
            gIdBuffer.Append((byte)((glyphIndex >> 8) & 0xFF));
            gIdBuffer.Append((byte)(glyphIndex & 0xFF));

            // Width.
            int width;
            if(!glyphWidths.TryGetValue(glyphIndex, out width))
            {width = 0;}
            else if(width > 1000)
            {width = 1000;}
            widthsObject.Add(PdfInteger.Get(width));
              }
              cmapBuffer.Append(
            "endcidchar\n"
              + "endcmap\n"
              + "CMapName currentdict /CMap defineresource pop\n"
              + "end\n"
              + "end\n"
              + "%%EndResource\n"
              + "%%EOF"
            );
              PdfStream cmapStream = new PdfStream(cmapBuffer);
              PdfDictionary cmapHead = cmapStream.Header;
              cmapHead[PdfName.Type] = PdfName.CMap;
              cmapHead[PdfName.CMapName] = new PdfName("Adobe-Identity-UCS");
              cmapHead[PdfName.CIDSystemInfo] = new PdfDictionary(
            new PdfName[]
            {
              PdfName.Registry,
              PdfName.Ordering,
              PdfName.Supplement
            },
            new PdfDirectObject[]
            {
              new PdfTextString("Adobe"),
              new PdfTextString("Identity"),
              PdfInteger.Get(0)
            }
            ); // Generic predefined CMap (Identity-H/V (Adobe-Identity-0)) [PDF:1.6:5.6.4].
              font[PdfName.Encoding] = File.Register(cmapStream);

              PdfStream gIdStream = new PdfStream(gIdBuffer);
              cidFont[PdfName.CIDToGIDMap] = File.Register(gIdStream);

              cidFont[PdfName.W] = new PdfArray(new PdfDirectObject[]{PdfInteger.Get(1),widthsObject});

              toUnicodeBuffer.Append(
            "endbfchar\n"
              + "endcmap\n"
              + "CMapName currentdict /CMap defineresource pop\n"
              + "end\n"
              + "end\n"
            );
              PdfStream toUnicodeStream = new PdfStream(toUnicodeBuffer);
              font[PdfName.ToUnicode] = File.Register(toUnicodeStream);
        }
Ejemplo n.º 8
0
        /**
         * <summary>Creates the character code mapping for composite fonts.</summary>
         */
        private void Load_CreateEncoding(
            PdfDictionary font,
            PdfDictionary cidFont
            )
        {
            // CMap [PDF:1.6:5.6.4].
            bytes::Buffer cmapBuffer = new bytes::Buffer();

            cmapBuffer.Append(
                "%!PS-Adobe-3.0 Resource-CMap\n"
                + "%%DocumentNeededResources: ProcSet (CIDInit)\n"
                + "%%IncludeResource: ProcSet (CIDInit)\n"
                + "%%BeginResource: CMap (Adobe-Identity-UCS)\n"
                + "%%Title: (Adobe-Identity-UCS Adobe Identity 0)\n"
                + "%%Version: 1\n"
                + "%%EndComments\n"
                + "/CIDInit /ProcSet findresource begin\n"
                + "12 dict begin\n"
                + "begincmap\n"
                + "/CIDSystemInfo\n"
                + "3 dict dup begin\n"
                + "/Registry (Adobe) def\n"
                + "/Ordering (Identity) def\n"
                + "/Supplement 0 def\n"
                + "end def\n"
                + "/CMapName /Adobe-Identity-UCS def\n"
                + "/CMapVersion 1 def\n"
                + "/CMapType 0 def\n"
                + "/WMode 0 def\n"
                + "2 begincodespacerange\n"
                + "<20> <20>\n"
                + "<0000> <19FF>\n"
                + "endcodespacerange\n"
                + glyphIndexes.Count + " begincidchar\n"
                );
            // ToUnicode [PDF:1.6:5.9.2].
            bytes::Buffer toUnicodeBuffer = new bytes::Buffer();

            toUnicodeBuffer.Append(
                "/CIDInit /ProcSet findresource begin\n"
                + "12 dict begin\n"
                + "begincmap\n"
                + "/CIDSystemInfo\n"
                + "<< /Registry (Adobe)\n"
                + "/Ordering (UCS)\n"
                + "/Supplement 0\n"
                + ">> def\n"
                + "/CMapName /Adobe-Identity-UCS def\n"
                + "/CMapVersion 10.001 def\n"
                + "/CMapType 2 def\n"
                + "2 begincodespacerange\n"
                + "<20> <20>\n"
                + "<0000> <19FF>\n"
                + "endcodespacerange\n"
                + glyphIndexes.Count + " beginbfchar\n"
                );
            // CIDToGIDMap [PDF:1.6:5.6.3].
            bytes::Buffer gIdBuffer = new bytes::Buffer();

            gIdBuffer.Append((byte)0);
            gIdBuffer.Append((byte)0);
            int code = 0;

            codes = new BiDictionary <ByteArray, int>(glyphIndexes.Count);
            PdfArray widthsObject = new PdfArray(glyphWidths.Count);

            foreach (KeyValuePair <int, int> glyphIndexEntry in glyphIndexes)
            {
                // Character code (unicode to codepoint) entry.
                code++;
                byte[] charCode = (glyphIndexEntry.Key == 32
          ? new byte[] { 32 }
          : new byte[]
                {
                    (byte)((code >> 8) & 0xFF),
                    (byte)(code & 0xFF)
                });
                codes[new ByteArray(charCode)] = glyphIndexEntry.Key;

                // CMap entry.
                cmapBuffer.Append("<");
                toUnicodeBuffer.Append("<");
                for (int charCodeBytesIndex = 0,
                     charCodeBytesLength = charCode.Length;
                     charCodeBytesIndex < charCodeBytesLength;
                     charCodeBytesIndex++
                     )
                {
                    string hex = ((int)charCode[charCodeBytesIndex]).ToString("X2");
                    cmapBuffer.Append(hex);
                    toUnicodeBuffer.Append(hex);
                }
                cmapBuffer.Append("> " + code + "\n");
                toUnicodeBuffer.Append("> <" + glyphIndexEntry.Key.ToString("X4") + ">\n");

                // CID-to-GID entry.
                int glyphIndex = glyphIndexEntry.Value;
                gIdBuffer.Append((byte)((glyphIndex >> 8) & 0xFF));
                gIdBuffer.Append((byte)(glyphIndex & 0xFF));

                // Width.
                int width;
                if (!glyphWidths.TryGetValue(glyphIndex, out width))
                {
                    width = 0;
                }
                else if (width > 1000)
                {
                    width = 1000;
                }
                widthsObject.Add(PdfInteger.Get(width));
            }
            cmapBuffer.Append(
                "endcidchar\n"
                + "endcmap\n"
                + "CMapName currentdict /CMap defineresource pop\n"
                + "end\n"
                + "end\n"
                + "%%EndResource\n"
                + "%%EOF"
                );
            PdfStream     cmapStream = new PdfStream(cmapBuffer);
            PdfDictionary cmapHead   = cmapStream.Header;

            cmapHead[PdfName.Type]          = PdfName.CMap;
            cmapHead[PdfName.CMapName]      = new PdfName("Adobe-Identity-UCS");
            cmapHead[PdfName.CIDSystemInfo] = new PdfDictionary(
                new PdfName[]
            {
                PdfName.Registry,
                PdfName.Ordering,
                PdfName.Supplement
            },
                new PdfDirectObject[]
            {
                new PdfTextString("Adobe"),
                new PdfTextString("Identity"),
                PdfInteger.Get(0)
            }
                ); // Generic predefined CMap (Identity-H/V (Adobe-Identity-0)) [PDF:1.6:5.6.4].
            font[PdfName.Encoding] = File.Register(cmapStream);

            PdfStream gIdStream = new PdfStream(gIdBuffer);

            cidFont[PdfName.CIDToGIDMap] = File.Register(gIdStream);

            cidFont[PdfName.W] = new PdfArray(new PdfDirectObject[] { PdfInteger.Get(1), widthsObject });

            toUnicodeBuffer.Append(
                "endbfchar\n"
                + "endcmap\n"
                + "CMapName currentdict /CMap defineresource pop\n"
                + "end\n"
                + "end\n"
                );
            PdfStream toUnicodeStream = new PdfStream(toUnicodeBuffer);

            font[PdfName.ToUnicode] = File.Register(toUnicodeStream);
        }