// Note. Make this constructor protected. Only PdfFontFactory (kernel level) will
        // be able to create Type0 font based on predefined font.
        // Or not? Possible it will be convenient construct PdfType0Font based on custom CidFont.
        // There is no typography features in CJK fonts.
        internal PdfType0Font(CidFont font, String cmap)
            : base()
        {
            if (!CidFontProperties.IsCidFont(font.GetFontNames().GetFontName(), cmap))
            {
                throw new PdfException("Font {0} with {1} encoding is not a cjk font.").SetMessageParams(font.GetFontNames
                                                                                                             ().GetFontName(), cmap);
            }
            this.fontProgram = font;
            vertical         = cmap.EndsWith("V");
            String uniMap = GetCompatibleUniMap(fontProgram.GetRegistry());

            cmapEncoding = new CMapEncoding(cmap, uniMap);
            longTag      = new SortedSet <int>();
            cidFontType  = CID_FONT_TYPE_0;
        }
        internal PdfType0Font(CidFont font, String cmap)
            : base()
        {
            // Note. Make this constructor protected. Only PdfFontFactory (kernel level) will
            // be able to create Type0 font based on predefined font.
            // Or not? Possible it will be convenient construct PdfType0Font based on custom CidFont.
            // There is no typography features in CJK fonts.
            if (!CidFontProperties.IsCidFont(font.GetFontNames().GetFontName(), cmap))
            {
                throw new PdfException("font.1.with.2.encoding.is.not.a.cjk.font").SetMessageParams(font.GetFontNames().GetFontName
                                                                                                        (), cmap);
            }
            this.fontProgram = font;
            vertical         = cmap.EndsWith("V");
            String uniMap = GetCompatibleUniMap(fontProgram.GetRegistry());

            cmapEncoding = new CMapEncoding(cmap, uniMap);
            longTag      = new LinkedDictionary <int, int[]>();
            cidFontType  = CID_FONT_TYPE_0;
        }
        private String GetCompatibleUniMap(String registry)
        {
            String uniMap = "";

            foreach (String name in CidFontProperties.GetRegistryNames().Get(registry + "_Uni"))
            {
                uniMap = name;
                if (name.EndsWith("V") && vertical)
                {
                    break;
                }
                else
                {
                    if (!name.EndsWith("V") && !vertical)
                    {
                        break;
                    }
                }
            }
            return(uniMap);
        }
        internal PdfType0Font(PdfDictionary fontDictionary)
            : base(fontDictionary)
        {
            CheckFontDictionary(fontDictionary, PdfName.Type0);
            newFont = false;
            PdfDictionary cidFont = fontDictionary.GetAsArray(PdfName.DescendantFonts).GetAsDictionary(0);
            String        cmap    = fontDictionary.GetAsName(PdfName.Encoding).GetValue();

            if (PdfEncodings.IDENTITY_H.Equals(cmap) || PdfEncodings.IDENTITY_V.Equals(cmap))
            {
                PdfObject     toUnicode     = fontDictionary.Get(PdfName.ToUnicode);
                CMapToUnicode toUnicodeCMap = FontUtil.ProcessToUnicode(toUnicode);
                if (toUnicodeCMap == null)
                {
                    String uniMap = GetUniMapFromOrdering(GetOrdering(cidFont));
                    toUnicodeCMap = FontUtil.GetToUnicodeFromUniMap(uniMap);
                    if (toUnicodeCMap == null)
                    {
                        toUnicodeCMap = FontUtil.GetToUnicodeFromUniMap(PdfEncodings.IDENTITY_H);
                        ILogger logger = LoggerFactory.GetLogger(typeof(iText.Kernel.Font.PdfType0Font));
                        logger.Error(String.Format(LogMessageConstant.UNKNOWN_CMAP, uniMap));
                    }
                }
                fontProgram  = DocTrueTypeFont.CreateFontProgram(cidFont, toUnicodeCMap);
                cmapEncoding = new CMapEncoding(cmap);
                System.Diagnostics.Debug.Assert(fontProgram is IDocFontProgram);
                embedded    = ((IDocFontProgram)fontProgram).GetFontFile() != null;
                cidFontType = CID_FONT_TYPE_2;
            }
            else
            {
                String cidFontName = cidFont.GetAsName(PdfName.BaseFont).GetValue();
                String uniMap      = GetUniMapFromOrdering(GetOrdering(cidFont));
                if (uniMap != null && uniMap.StartsWith("Uni") && CidFontProperties.IsCidFont(cidFontName, uniMap))
                {
                    try {
                        fontProgram  = FontProgramFactory.CreateFont(cidFontName);
                        cmapEncoding = new CMapEncoding(cmap, uniMap);
                        embedded     = false;
                    }
                    catch (System.IO.IOException) {
                        fontProgram  = null;
                        cmapEncoding = null;
                    }
                }
                else
                {
                    CMapToUnicode toUnicodeCMap = FontUtil.GetToUnicodeFromUniMap(uniMap);
                    if (toUnicodeCMap != null)
                    {
                        fontProgram  = DocTrueTypeFont.CreateFontProgram(cidFont, toUnicodeCMap);
                        cmapEncoding = new CMapEncoding(cmap, uniMap);
                    }
                }
                if (fontProgram == null)
                {
                    throw new PdfException(String.Format("Cannot recognise document font {0} with {1} encoding", cidFontName,
                                                         cmap));
                }
                cidFontType = CID_FONT_TYPE_0;
            }
            longTag = new LinkedDictionary <int, int[]>();
            subset  = false;
        }
        internal PdfType0Font(PdfDictionary fontDictionary)
            : base(fontDictionary)
        {
            newFont = false;
            PdfDictionary cidFont       = fontDictionary.GetAsArray(PdfName.DescendantFonts).GetAsDictionary(0);
            PdfObject     cmap          = fontDictionary.Get(PdfName.Encoding);
            PdfObject     toUnicode     = fontDictionary.Get(PdfName.ToUnicode);
            CMapToUnicode toUnicodeCMap = FontUtil.ProcessToUnicode(toUnicode);

            if (cmap.IsName() && (PdfEncodings.IDENTITY_H.Equals(((PdfName)cmap).GetValue()) || PdfEncodings.IDENTITY_V
                                  .Equals(((PdfName)cmap).GetValue())))
            {
                if (toUnicodeCMap == null)
                {
                    String uniMap = GetUniMapFromOrdering(GetOrdering(cidFont));
                    toUnicodeCMap = FontUtil.GetToUnicodeFromUniMap(uniMap);
                    if (toUnicodeCMap == null)
                    {
                        toUnicodeCMap = FontUtil.GetToUnicodeFromUniMap(PdfEncodings.IDENTITY_H);
                        ILog logger = LogManager.GetLogger(typeof(iText.Kernel.Font.PdfType0Font));
                        logger.Error(MessageFormatUtil.Format(iText.IO.LogMessageConstant.UNKNOWN_CMAP, uniMap));
                    }
                }
                fontProgram  = DocTrueTypeFont.CreateFontProgram(cidFont, toUnicodeCMap);
                cmapEncoding = CreateCMap(cmap, null);
                System.Diagnostics.Debug.Assert(fontProgram is IDocFontProgram);
                embedded = ((IDocFontProgram)fontProgram).GetFontFile() != null;
            }
            else
            {
                String cidFontName = cidFont.GetAsName(PdfName.BaseFont).GetValue();
                String uniMap      = GetUniMapFromOrdering(GetOrdering(cidFont));
                if (uniMap != null && uniMap.StartsWith("Uni") && CidFontProperties.IsCidFont(cidFontName, uniMap))
                {
                    try {
                        fontProgram  = FontProgramFactory.CreateFont(cidFontName);
                        cmapEncoding = CreateCMap(cmap, uniMap);
                        embedded     = false;
                    }
                    catch (System.IO.IOException) {
                        fontProgram  = null;
                        cmapEncoding = null;
                    }
                }
                else
                {
                    if (toUnicodeCMap == null)
                    {
                        toUnicodeCMap = FontUtil.GetToUnicodeFromUniMap(uniMap);
                    }
                    if (toUnicodeCMap != null)
                    {
                        fontProgram  = DocTrueTypeFont.CreateFontProgram(cidFont, toUnicodeCMap);
                        cmapEncoding = CreateCMap(cmap, uniMap);
                    }
                }
                if (fontProgram == null)
                {
                    throw new PdfException(MessageFormatUtil.Format(PdfException.CannotRecogniseDocumentFontWithEncoding, cidFontName
                                                                    , cmap));
                }
            }
            // DescendantFonts is a one-element array specifying the CIDFont dictionary that is the descendant of this Type 0 font.
            PdfDictionary cidFontDictionary = fontDictionary.GetAsArray(PdfName.DescendantFonts).GetAsDictionary(0);
            // Required according to the spec
            PdfName subtype = cidFontDictionary.GetAsName(PdfName.Subtype);

            if (PdfName.CIDFontType0.Equals(subtype))
            {
                cidFontType = CID_FONT_TYPE_0;
            }
            else
            {
                if (PdfName.CIDFontType2.Equals(subtype))
                {
                    cidFontType = CID_FONT_TYPE_2;
                }
                else
                {
                    LogManager.GetLogger(GetType()).Error(iText.IO.LogMessageConstant.FAILED_TO_DETERMINE_CID_FONT_SUBTYPE);
                }
            }
            longTag = new SortedSet <int>();
            subset  = false;
        }