/// <summary>Generates the CIDFontTyte2 dictionary.</summary>
        /// <param name="fontDescriptor">the indirect reference to the font descriptor</param>
        /// <param name="fontName">a name of the font</param>
        /// <param name="metrics">the horizontal width metrics</param>
        /// <returns>fully initialized CIDFont</returns>
        protected internal virtual PdfDictionary GetCidFontType2(TrueTypeFont ttf, PdfDictionary fontDescriptor, String
                                                                 fontName, int[][] metrics)
        {
            PdfDictionary cidFont = new PdfDictionary();

            MarkObjectAsIndirect(cidFont);
            cidFont.Put(PdfName.Type, PdfName.Font);
            // sivan; cff
            cidFont.Put(PdfName.FontDescriptor, fontDescriptor);
            if (ttf == null || ttf.IsCff())
            {
                cidFont.Put(PdfName.Subtype, PdfName.CIDFontType0);
            }
            else
            {
                cidFont.Put(PdfName.Subtype, PdfName.CIDFontType2);
                cidFont.Put(PdfName.CIDToGIDMap, PdfName.Identity);
            }
            cidFont.Put(PdfName.BaseFont, new PdfName(fontName));
            PdfDictionary cidInfo = new PdfDictionary();

            cidInfo.Put(PdfName.Registry, new PdfString(cmapEncoding.GetRegistry()));
            cidInfo.Put(PdfName.Ordering, new PdfString(cmapEncoding.GetOrdering()));
            cidInfo.Put(PdfName.Supplement, new PdfNumber(cmapEncoding.GetSupplement()));
            cidFont.Put(PdfName.CIDSystemInfo, cidInfo);
            if (!vertical)
            {
                cidFont.Put(PdfName.DW, new PdfNumber(FontProgram.DEFAULT_WIDTH));
                StringBuilder buf        = new StringBuilder("[");
                int           lastNumber = -10;
                bool          firstTime  = true;
                foreach (int[] metric in metrics)
                {
                    Glyph glyph = fontProgram.GetGlyphByCode(metric[0]);
                    if (glyph.GetWidth() == FontProgram.DEFAULT_WIDTH)
                    {
                        continue;
                    }
                    if (glyph.GetCode() == lastNumber + 1)
                    {
                        buf.Append(' ').Append(glyph.GetWidth());
                    }
                    else
                    {
                        if (!firstTime)
                        {
                            buf.Append(']');
                        }
                        firstTime = false;
                        buf.Append(glyph.GetCode()).Append('[').Append(glyph.GetWidth());
                    }
                    lastNumber = glyph.GetCode();
                }
                if (buf.Length > 1)
                {
                    buf.Append("]]");
                    cidFont.Put(PdfName.W, new PdfLiteral(buf.ToString()));
                }
            }
            else
            {
                throw new NotSupportedException("Vertical writing has not implemented yet.");
            }
            return(cidFont);
        }
 protected internal virtual PdfDictionary GetCidFontType2(TrueTypeFont ttf, PdfDictionary fontDescriptor, String
                                                          fontName, int[] glyphIds)
 {
     return(GetCidFont(fontDescriptor, fontName, ttf != null && !ttf.IsCff()));
 }
 private void FlushFontData()
 {
     if (cidFontType == CID_FONT_TYPE_0)
     {
         GetPdfObject().Put(PdfName.Type, PdfName.Font);
         GetPdfObject().Put(PdfName.Subtype, PdfName.Type0);
         String name  = fontProgram.GetFontNames().GetFontName();
         String style = fontProgram.GetFontNames().GetStyle();
         if (style.Length > 0)
         {
             name += "-" + style;
         }
         GetPdfObject().Put(PdfName.BaseFont, new PdfName(String.Format("{0}-{1}", name, cmapEncoding.GetCmapName()
                                                                        )));
         GetPdfObject().Put(PdfName.Encoding, new PdfName(cmapEncoding.GetCmapName()));
         PdfDictionary fontDescriptor = GetFontDescriptor(name);
         int[][]       metrics        = longTag.Values.ToArray(new int[0][]);
         iText.IO.Util.JavaUtil.Sort(metrics, new PdfType0Font.MetricComparator());
         PdfDictionary cidFont = GetCidFontType2(null, fontDescriptor, fontProgram.GetFontNames().GetFontName(), metrics
                                                 );
         GetPdfObject().Put(PdfName.DescendantFonts, new PdfArray(cidFont));
         fontDescriptor.Flush();
         cidFont.Flush();
     }
     else
     {
         if (cidFontType == CID_FONT_TYPE_2)
         {
             TrueTypeFont ttf = (TrueTypeFont)GetFontProgram();
             AddRangeUni(ttf, longTag, true);
             int[][] metrics = longTag.Values.ToArray(new int[0][]);
             iText.IO.Util.JavaUtil.Sort(metrics, new PdfType0Font.MetricComparator());
             PdfStream fontStream;
             String    fontName = ttf.GetFontNames().GetFontName();
             if (subset)
             {
                 fontName = CreateSubsetPrefix() + fontName;
             }
             PdfDictionary fontDescriptor = GetFontDescriptor(fontName);
             if (ttf.IsCff())
             {
                 byte[] cffBytes = ttf.GetFontStreamBytes();
                 if (subset || subsetRanges != null)
                 {
                     CFFFontSubset cff = new CFFFontSubset(ttf.GetFontStreamBytes(), longTag);
                     cffBytes = cff.Process(cff.GetNames()[0]);
                 }
                 fontStream = GetPdfFontStream(cffBytes, new int[] { cffBytes.Length });
                 fontStream.Put(PdfName.Subtype, new PdfName("CIDFontType0C"));
                 // The PDF Reference manual advises to add -cmap in case CIDFontType0
                 GetPdfObject().Put(PdfName.BaseFont, new PdfName(String.Format("{0}-{1}", fontName, cmapEncoding.GetCmapName
                                                                                    ())));
                 fontDescriptor.Put(PdfName.FontFile3, fontStream);
             }
             else
             {
                 byte[] ttfBytes;
                 if (subset || ttf.GetDirectoryOffset() != 0)
                 {
                     ttfBytes = ttf.GetSubset(new LinkedHashSet <int>(longTag.Keys), true);
                 }
                 else
                 {
                     ttfBytes = ttf.GetFontStreamBytes();
                 }
                 fontStream = GetPdfFontStream(ttfBytes, new int[] { ttfBytes.Length });
                 GetPdfObject().Put(PdfName.BaseFont, new PdfName(fontName));
                 fontDescriptor.Put(PdfName.FontFile2, fontStream);
             }
             // CIDSet shall be based on font.maxGlyphId property of the font, it is maxp.numGlyphs for ttf,
             // because technically we convert all unused glyphs to space, e.g. just remove outlines.
             int    maxGlyphId  = ttf.GetFontMetrics().GetMaxGlyphId();
             byte[] cidSetBytes = new byte[ttf.GetFontMetrics().GetMaxGlyphId() / 8 + 1];
             for (int i = 0; i < maxGlyphId / 8; i++)
             {
                 cidSetBytes[i] |= 0xff;
             }
             for (int i_1 = 0; i_1 < maxGlyphId % 8; i_1++)
             {
                 cidSetBytes[cidSetBytes.Length - 1] |= rotbits[i_1];
             }
             fontDescriptor.Put(PdfName.CIDSet, new PdfStream(cidSetBytes));
             PdfDictionary cidFont = GetCidFontType2(ttf, fontDescriptor, fontName, metrics);
             GetPdfObject().Put(PdfName.Type, PdfName.Font);
             GetPdfObject().Put(PdfName.Subtype, PdfName.Type0);
             GetPdfObject().Put(PdfName.Encoding, new PdfName(cmapEncoding.GetCmapName()));
             GetPdfObject().Put(PdfName.DescendantFonts, new PdfArray(cidFont));
             PdfStream toUnicode = GetToUnicode(metrics);
             if (toUnicode != null)
             {
                 GetPdfObject().Put(PdfName.ToUnicode, toUnicode);
                 toUnicode.Flush();
             }
             fontDescriptor.Flush();
             cidFont.Flush();
         }
         else
         {
             throw new InvalidOperationException("Unsupported CID Font");
         }
     }
 }
 private void FlushFontData()
 {
     if (cidFontType == CID_FONT_TYPE_0)
     {
         GetPdfObject().Put(PdfName.Type, PdfName.Font);
         GetPdfObject().Put(PdfName.Subtype, PdfName.Type0);
         String name  = fontProgram.GetFontNames().GetFontName();
         String style = fontProgram.GetFontNames().GetStyle();
         if (style.Length > 0)
         {
             name += "-" + style;
         }
         GetPdfObject().Put(PdfName.BaseFont, new PdfName(MessageFormatUtil.Format("{0}-{1}", name, cmapEncoding.GetCmapName
                                                                                       ())));
         GetPdfObject().Put(PdfName.Encoding, new PdfName(cmapEncoding.GetCmapName()));
         PdfDictionary fontDescriptor = GetFontDescriptor(name);
         PdfDictionary cidFont        = GetCidFont(fontDescriptor, fontProgram.GetFontNames().GetFontName(), false);
         GetPdfObject().Put(PdfName.DescendantFonts, new PdfArray(cidFont));
         fontDescriptor.Flush();
         cidFont.Flush();
     }
     else
     {
         if (cidFontType == CID_FONT_TYPE_2)
         {
             TrueTypeFont  ttf            = (TrueTypeFont)GetFontProgram();
             String        fontName       = UpdateSubsetPrefix(ttf.GetFontNames().GetFontName(), subset, embedded);
             PdfDictionary fontDescriptor = GetFontDescriptor(fontName);
             PdfStream     fontStream;
             ttf.UpdateUsedGlyphs((SortedSet <int>)longTag, subset, subsetRanges);
             if (ttf.IsCff())
             {
                 byte[] cffBytes;
                 if (subset)
                 {
                     cffBytes = new CFFFontSubset(ttf.GetFontStreamBytes(), longTag).Process();
                 }
                 else
                 {
                     cffBytes = ttf.GetFontStreamBytes();
                 }
                 fontStream = GetPdfFontStream(cffBytes, new int[] { cffBytes.Length });
                 fontStream.Put(PdfName.Subtype, new PdfName("CIDFontType0C"));
                 // The PDF Reference manual advises to add -cmap in case CIDFontType0
                 GetPdfObject().Put(PdfName.BaseFont, new PdfName(MessageFormatUtil.Format("{0}-{1}", fontName, cmapEncoding
                                                                                           .GetCmapName())));
                 fontDescriptor.Put(PdfName.FontFile3, fontStream);
             }
             else
             {
                 byte[] ttfBytes = null;
                 //getDirectoryOffset() > 0 means ttc, which shall be subsetted anyway.
                 if (subset || ttf.GetDirectoryOffset() > 0)
                 {
                     try {
                         ttfBytes = ttf.GetSubset(longTag, subset);
                     }
                     catch (iText.IO.IOException) {
                         ILog logger = LogManager.GetLogger(typeof(iText.Kernel.Font.PdfType0Font));
                         logger.Warn(iText.IO.LogMessageConstant.FONT_SUBSET_ISSUE);
                         ttfBytes = null;
                     }
                 }
                 if (ttfBytes == null)
                 {
                     ttfBytes = ttf.GetFontStreamBytes();
                 }
                 fontStream = GetPdfFontStream(ttfBytes, new int[] { ttfBytes.Length });
                 GetPdfObject().Put(PdfName.BaseFont, new PdfName(fontName));
                 fontDescriptor.Put(PdfName.FontFile2, fontStream);
             }
             // CIDSet shall be based on font.numberOfGlyphs property of the font, it is maxp.numGlyphs for ttf,
             // because technically we convert all unused glyphs to space, e.g. just remove outlines.
             int    numOfGlyphs = ttf.GetFontMetrics().GetNumberOfGlyphs();
             byte[] cidSetBytes = new byte[ttf.GetFontMetrics().GetNumberOfGlyphs() / 8 + 1];
             for (int i = 0; i < numOfGlyphs / 8; i++)
             {
                 cidSetBytes[i] |= 0xff;
             }
             for (int i = 0; i < numOfGlyphs % 8; i++)
             {
                 cidSetBytes[cidSetBytes.Length - 1] |= rotbits[i];
             }
             fontDescriptor.Put(PdfName.CIDSet, new PdfStream(cidSetBytes));
             PdfDictionary cidFont = GetCidFont(fontDescriptor, fontName, !ttf.IsCff());
             GetPdfObject().Put(PdfName.Type, PdfName.Font);
             GetPdfObject().Put(PdfName.Subtype, PdfName.Type0);
             GetPdfObject().Put(PdfName.Encoding, new PdfName(cmapEncoding.GetCmapName()));
             GetPdfObject().Put(PdfName.DescendantFonts, new PdfArray(cidFont));
             PdfStream toUnicode = GetToUnicode();
             if (toUnicode != null)
             {
                 GetPdfObject().Put(PdfName.ToUnicode, toUnicode);
                 if (toUnicode.GetIndirectReference() != null)
                 {
                     toUnicode.Flush();
                 }
             }
             // getPdfObject().getIndirectReference() != null by assertion of PdfType0Font#flush()
             // This means, that fontDescriptor, cidFont and fontStream already are indirects
             if (GetPdfObject().GetIndirectReference().GetDocument().GetPdfVersion().CompareTo(PdfVersion.PDF_2_0) >= 0
                 )
             {
                 // CIDSet is deprecated in PDF 2.0
                 fontDescriptor.Remove(PdfName.CIDSet);
             }
             fontDescriptor.Flush();
             cidFont.Flush();
             fontStream.Flush();
         }
         else
         {
             throw new InvalidOperationException("Unsupported CID Font");
         }
     }
 }