Ejemplo n.º 1
0
        public xObjects::XObject ToXObject(
            Document context
            )
        {
            xObjects::FormXObject form;

            {
                form           = new xObjects::FormXObject(context, Box);
                form.Resources = (Resources)(context.Equals(Document)
          ? Resources                // Same document: reuses the existing resources.
          : Resources.Clone(context) // Alien document: clones the resources.
                                             );

                // Body (contents).
                {
                    IBuffer       formBody           = form.BaseDataObject.Body;
                    PdfDataObject contentsDataObject = BaseDataObject.Resolve(PdfName.Contents);
                    if (contentsDataObject is PdfStream)
                    {
                        formBody.Append(((PdfStream)contentsDataObject).Body);
                    }
                    else
                    {
                        foreach (PdfDirectObject contentStreamObject in (PdfArray)contentsDataObject)
                        {
                            formBody.Append(((PdfStream)contentStreamObject.Resolve()).Body);
                        }
                    }
                }
            }
            return(form);
        }
Ejemplo n.º 2
0
        public virtual SKTypeface GetTypeface()
        {
            if (typeface != null)
            {
                return(typeface);
            }

            var fontDescription = GetFontDescription();

            if (fontDescription != null)
            {
                if (fontDescription.Resolve(PdfName.FontFile) is PdfStream stream)
                {
                    return(typeface = GetTypeface(fontDescription, stream));
                }
                if (fontDescription.Resolve(PdfName.FontFile2) is PdfStream stream2)
                {
                    return(typeface = GetTypeface(fontDescription, stream2));
                }
                if (fontDescription.Resolve(PdfName.FontFile3) is PdfStream stream3)
                {
                    return(typeface = GetTypeface(fontDescription, stream3));
                }
                if (fontDescription.Resolve(PdfName.FontName) is PdfName fontName)
                {
                    return(typeface = ParseName(fontName.StringValue, fontDescription));
                }
            }
            else if (BaseDataObject.Resolve(PdfName.BaseFont) is PdfName baseFont)
            {
                return(typeface = ParseName(baseFont.StringValue, Dictionary));
            }

            return(null);
        }
Ejemplo n.º 3
0
        /**
         * <summary>Gets whether this is the first bead in its thread.</summary>
         */
        public bool IsHead(
            )
        {
            PdfDictionary thread = (PdfDictionary)BaseDataObject.Resolve(PdfName.T);

            return(thread != null && BaseObject.Equals(thread[PdfName.F]));
        }
Ejemplo n.º 4
0
        private object GetEntry <T, TPdf>(
            PdfName key
            ) where TPdf : PdfAtomicObject <T>
        {
            TPdf entry = (TPdf)BaseDataObject.Resolve(key);

            return(entry == null ? null : entry.Value);
        }
Ejemplo n.º 5
0
        protected override PdfDataObject GetDescriptorValue(
            PdfName key
            )
        {
            PdfDictionary fontDescriptor = (PdfDictionary)BaseDataObject.Resolve(PdfName.FontDescriptor);

            return(fontDescriptor != null?fontDescriptor.Resolve(key) : null);
        }
Ejemplo n.º 6
0
        protected override void OnLoad()
        {
            base.OnLoad();

            if (BaseDataObject.Resolve(PdfName.Encoding) is PdfDictionary encodingDictionary &&
                encodingDictionary.Values.Count > 0 &&
                encodingDictionary.Resolve(PdfName.Differences) is PdfArray differencesObject)
            {
                var fontMapping = (GlyphMapping)null;

                if (BaseDataObject.Resolve(PdfName.BaseFont) is PdfName pdfName)
                {
                    var name = Regex.Replace(pdfName.RawValue, @"[\/?:*""><|]+", "", RegexOptions.Compiled);
                    if (GlyphMapping.IsExist(name))
                    {
                        fontMapping = new GlyphMapping(name);
                    }
                }

                byte[] charCodeData = new byte[1];
                foreach (PdfDirectObject differenceObject in differencesObject)
                {
                    if (differenceObject is PdfInteger pdfInteger) // Subsequence initial code.
                    {
                        charCodeData[0] = (byte)(((int)pdfInteger.Value) & 0xFF);
                    }
                    else // Character name.
                    {
                        ByteArray charCode = new ByteArray(charCodeData);
                        string    charName = (string)((PdfName)differenceObject).Value;
                        if (charName.Equals(".notdef", StringComparison.Ordinal))
                        {
                            codes.Remove(charCode);
                        }
                        else
                        {
                            int?code = GlyphMapping.DLFONT.NameToCode(charName) ?? fontMapping?.NameToCode(charName);
                            if (code != null)
                            {
                                codes[charCode] = code.Value;
                            }
                            else
                            {
                                System.Diagnostics.Debug.WriteLine($" {charName}");
                            }
                        }
                        charCodeData[0]++;
                    }
                }
            }
        }
Ejemplo n.º 7
0
        protected override void OnLoad(
            )
        {
            LoadEncoding();

            // Glyph widths.
            if (glyphWidths == null)
            {
                glyphWidths = new Dictionary <int, int>();
                PdfArray glyphWidthObjects = (PdfArray)BaseDataObject.Resolve(PdfName.Widths);
                if (glyphWidthObjects != null)
                {
                    ByteArray charCode = new ByteArray(
                        new byte[]
                        { (byte)((PdfInteger)BaseDataObject[PdfName.FirstChar]).IntValue }
                        );
                    foreach (PdfDirectObject glyphWidthObject in glyphWidthObjects)
                    {
                        int glyphWidth = ((IPdfNumber)glyphWidthObject).IntValue;
                        if (glyphWidth > 0)
                        {
                            int code;
                            if (codes.TryGetValue(charCode, out code))
                            {   // [Zmiana]
                                try
                                {
                                    glyphWidths[glyphIndexes[code]] = glyphWidth;
                                }
                                catch (Exception)
                                {
                                }
                            }
                        }
                        charCode.Data[0]++;
                    }
                }
            }
            // Default glyph width.
            {
                IPdfNumber widthObject = (IPdfNumber)GetDescriptorValue(PdfName.AvgWidth);
                if (widthObject != null)
                {
                    AverageWidth = widthObject.IntValue;
                }
                widthObject = (IPdfNumber)GetDescriptorValue(PdfName.MissingWidth);
                if (widthObject != null)
                {
                    DefaultWidth = widthObject.IntValue;
                }
            }
        }
Ejemplo n.º 8
0
 public PdfDictionary GetFontDescription()
 {
     if (BaseDataObject.Resolve(PdfName.FontDescriptor) is PdfDictionary fontDescription)
     {
         return(fontDescription);
     }
     if (BaseDataObject.Resolve(PdfName.DescendantFonts) is PdfArray array &&
         array.Resolve(0) is PdfDictionary descendant &&
         descendant.Resolve(PdfName.FontDescriptor) is PdfDictionary descendantDescription)
     {
         return(descendantDescription);
     }
     return(null);
 }
Ejemplo n.º 9
0
        public virtual SKTypeface GetTypefaceByName()
        {
            var fontDescription = GetFontDescription();

            if (fontDescription != null)
            {
                return(ParseName(fontDescription.Resolve(PdfName.FontName)?.ToString(), fontDescription));
            }
            else if (BaseDataObject.Resolve(PdfName.BaseFont) is PdfName baseFont)
            {
                return(typeface = ParseName(baseFont.StringValue, Dictionary));
            }
            return(null);
        }
Ejemplo n.º 10
0
        protected override void LoadEncoding(
            )
        {
            //FIXME: consolidate with Type1Font and TrueTypeFont!
            // Encoding.
            if (this.codes == null)
            {
                IDictionary <ByteArray, int> codes;
                PdfDataObject encodingObject = BaseDataObject.Resolve(PdfName.Encoding);
                if (encodingObject == null) // Native encoding.
                {
                    codes = GetNativeEncoding();
                }
                else if (encodingObject is PdfName) // Predefined encoding.
                {
                    codes = Encoding.Get((PdfName)encodingObject).GetCodes();
                }
                else // Custom encoding.
                {
                    PdfDictionary encodingDictionary = (PdfDictionary)encodingObject;

                    // 1. Base encoding.
                    PdfName baseEncodingName = (PdfName)encodingDictionary[PdfName.BaseEncoding];
                    if (baseEncodingName == null) // Native base encoding.
                    {
                        codes = GetNativeEncoding();
                    }
                    else // Predefined base encoding.
                    {
                        codes = Encoding.Get(baseEncodingName).GetCodes();
                    }

                    // 2. Differences.
                    LoadEncodingDifferences(encodingDictionary, codes);
                }
                this.codes = new BiDictionary <ByteArray, int>(codes);
            }

            // Glyph indexes.
            if (glyphIndexes == null)
            {
                glyphIndexes = new Dictionary <int, int>();
                foreach (KeyValuePair <ByteArray, int> codeEntry in codes)
                {
                    glyphIndexes[codeEntry.Value] = ConvertUtils.ByteArrayToInt(codeEntry.Key.Data);
                }
            }
        }
        /**
         * <summary>Sets the usage application for the specified factors.</summary>
         * <param name="event">Situation in which this usage application should be used. May be
         *  <see cref="PdfName.View">View</see>, <see cref="PdfName.Print">Print</see> or <see
         *  cref="PdfName.Export">Export</see>.</param>
         * <param name="category">Layer usage entry to consider when managing the states of the layer.
         * </param>
         * <param name="layer">Layer which should have its state automatically managed based on its usage
         *  information.</param>
         * <param name="retain">Whether this usage application has to be kept or removed.</param>
         */
        internal void SetUsageApplication(
            PdfName @event,
            PdfName category,
            Layer layer,
            bool retain
            )
        {
            bool     matched = false;
            PdfArray usages  = BaseDataObject.Resolve <PdfArray>(PdfName.AS);

            foreach (PdfDirectObject usage in usages)
            {
                PdfDictionary usageDictionary = (PdfDictionary)usage;
                if (usageDictionary[PdfName.Event].Equals(@event) &&
                    ((PdfArray)usageDictionary[PdfName.Category]).Contains(category))
                {
                    PdfArray usageLayers = usageDictionary.Resolve <PdfArray>(PdfName.OCGs);
                    if (usageLayers.Contains(layer.BaseObject))
                    {
                        if (!retain)
                        {
                            usageLayers.Remove(layer.BaseObject);
                        }
                    }
                    else
                    {
                        if (retain)
                        {
                            usageLayers.Add(layer.BaseObject);
                        }
                    }
                    matched = true;
                }
            }
            if (!matched && retain)
            {
                PdfDictionary usageDictionary = new PdfDictionary();
                {
                    usageDictionary[PdfName.Event] = @event;
                    usageDictionary.Resolve <PdfArray>(PdfName.Category).Add(category);
                    usageDictionary.Resolve <PdfArray>(PdfName.OCGs).Add(layer.BaseObject);
                }
                usages.Add(usageDictionary);
            }
        }
Ejemplo n.º 12
0
 private void SetEntry <T, TPdf>(
     PdfName key,
     object value
     ) where TPdf : PdfAtomicObject <T>, new()
 {
     if (value == null)
     {
         BaseDataObject.Remove(key);
     }
     else
     {
         if (!BaseDataObject.ContainsKey(key))
         {
             BaseDataObject[key] = new TPdf();
         }
         ((TPdf)BaseDataObject.Resolve(key)).Value = value;
     }
 }
Ejemplo n.º 13
0
        public override void RemoveAt(int index)
        {
            int          baseIndex   = GetBaseIndex(index);
            IUILayerNode removedItem = base[baseIndex];

            base.RemoveAt(baseIndex);
            if (removedItem is Layer &&
                baseIndex < base.Count)
            {
                /*
                 * NOTE: Sublayers MUST be removed as well.
                 */
                if (BaseDataObject.Resolve(baseIndex) is PdfArray)
                {
                    BaseDataObject.RemoveAt(baseIndex);
                }
            }
        }
Ejemplo n.º 14
0
        public xObjects::XObject ToXObject(
            Document context
            )
        {
            File contextFile = context.File;

            xObjects::FormXObject form       = new xObjects::FormXObject(context);
            PdfStream             formStream = form.BaseDataObject;

            // Header.
            {
                PdfDictionary formHeader = formStream.Header;
                // Bounding box.
                formHeader[PdfName.BBox] = (PdfDirectObject)GetInheritableAttribute(PdfName.MediaBox).Clone(contextFile);
                // Resources.
                {
                    PdfDirectObject resourcesObject = GetInheritableAttribute(PdfName.Resources);
                    // Same document?
                    /* NOTE: Try to reuse the resource dictionary whenever possible. */
                    formHeader[PdfName.Resources] = (context.Equals(Document) ?
                                                     resourcesObject
            : (PdfDirectObject)resourcesObject.Clone(contextFile));
                }
            }

            // Body (contents).
            {
                IBuffer       formBody           = formStream.Body;
                PdfDataObject contentsDataObject = BaseDataObject.Resolve(PdfName.Contents);
                if (contentsDataObject is PdfStream)
                {
                    formBody.Append(((PdfStream)contentsDataObject).Body);
                }
                else
                {
                    foreach (PdfDirectObject contentStreamObject in (PdfArray)contentsDataObject)
                    {
                        formBody.Append(((PdfStream)File.Resolve(contentStreamObject)).Body);
                    }
                }
            }

            return(form);
        }
Ejemplo n.º 15
0
        protected override void OnLoad(
            )
        {
            LoadEncoding();

            // Glyph widths.
            if (glyphWidths == null)
            {
                glyphWidths = new Dictionary <int, int>();
                PdfArray glyphWidthObjects = (PdfArray)BaseDataObject.Resolve(PdfName.Widths);
                if (glyphWidthObjects != null)
                {
                    ByteArray charCode = new ByteArray(
                        new byte[]
                        { (byte)((PdfInteger)BaseDataObject[PdfName.FirstChar]).IntValue }
                        );
                    foreach (PdfDirectObject glyphWidthObject in glyphWidthObjects)
                    {
                        int glyphWidth = ((IPdfNumber)glyphWidthObject).IntValue;
                        if (glyphWidth > 0)
                        {
                            int code;
                            if (codes.TryGetValue(charCode, out code))
                            {
                                glyphWidths[glyphIndexes[code]] = glyphWidth;
                            }
                        }
                        charCode.Data[0]++;
                    }
                }
            }
            // Default glyph width.
            {
                PdfDictionary descriptor = Descriptor;
                if (descriptor != null)
                {
                    IPdfNumber defaultGlyphWidthObject = (IPdfNumber)descriptor[PdfName.MissingWidth];
                    defaultGlyphWidth = (defaultGlyphWidthObject != null ? defaultGlyphWidthObject.IntValue : 0);
                }
            }
        }
Ejemplo n.º 16
0
        /**
         * <summary>Loads font information from existing PDF font structure.</summary>
         */
        protected void Load(
            )
        {
            if (BaseDataObject.ContainsKey(PdfName.ToUnicode)) // To-Unicode explicit mapping.
            {
                PdfStream  toUnicodeStream = (PdfStream)BaseDataObject.Resolve(PdfName.ToUnicode);
                CMapParser parser          = new CMapParser(toUnicodeStream.Body);
                codes    = new BiDictionary <ByteArray, int>(parser.Parse());
                symbolic = false;
            }

            OnLoad();

            // Maximum character code length.
            foreach (ByteArray charCode in codes.Keys)
            {
                if (charCode.Data.Length > charCodeMaxLength)
                {
                    charCodeMaxLength = charCode.Data.Length;
                }
            }
            // Missing character substitute.
            if (defaultCode == UndefinedDefaultCode)
            {
                ICollection <int> codePoints = CodePoints;
                if (codePoints.Contains((int)'?'))
                {
                    DefaultCode = '?';
                }
                else if (codePoints.Contains((int)' '))
                {
                    DefaultCode = ' ';
                }
                else
                // PK 2017-03-08 - allow for encoding to fail, which should just result in a "?" or rectangle appearing instead of the correct character
                {
                    DefaultCode = codePoints.FirstOrDefault();
                }
            }
        }
Ejemplo n.º 17
0
        /**
         * <summary>Loads font information from existing PDF font structure.</summary>
         */
        protected void Load(
            )
        {
            if (BaseDataObject.ContainsKey(PdfName.ToUnicode)) // To-Unicode explicit mapping.
            {
                PdfStream  toUnicodeStream = (PdfStream)BaseDataObject.Resolve(PdfName.ToUnicode);
                CMapParser parser          = new CMapParser(toUnicodeStream.Body);
                codes    = new BiDictionary <ByteArray, int>(parser.Parse());
                symbolic = false;
            }

            OnLoad();

            // Maximum character code length.
            foreach (ByteArray charCode in codes.Keys)
            {
                if (charCode.Data.Length > charCodeMaxLength)
                {
                    charCodeMaxLength = charCode.Data.Length;
                }
            }
        }
Ejemplo n.º 18
0
        /**
         * <summary>Loads font information from existing PDF font structure.</summary>
         */
        protected void Load(
            )
        {
            if (BaseDataObject.ContainsKey(PdfName.ToUnicode)) // To-Unicode explicit mapping.
            {
                PdfStream  toUnicodeStream = (PdfStream)BaseDataObject.Resolve(PdfName.ToUnicode);
                CMapParser parser          = new CMapParser(toUnicodeStream.Body);
                codes    = new BiDictionary <ByteArray, int>(parser.Parse());
                symbolic = false;
            }

            OnLoad();

            // Maximum character code length.
            foreach (ByteArray charCode in codes.Keys)
            {
                if (charCode.Data.Length > charCodeMaxLength)
                {
                    charCodeMaxLength = charCode.Data.Length;
                }
            }
            // Missing character substitute.
            if (defaultCode == UndefinedDefaultCode)
            {
                ICollection <int> codePoints = CodePoints;
                if (codePoints.Contains((int)'?'))
                {
                    DefaultCode = '?';
                }
                else if (codePoints.Contains((int)' '))
                {
                    DefaultCode = ' ';
                }
                else
                {
                    DefaultCode = codePoints.First();
                }
            }
        }
Ejemplo n.º 19
0
        protected void LoadEncoding(
            )
        {
            // Mapping character codes...
            PdfDataObject encodingObject = BaseDataObject.Resolve(PdfName.Encoding);
            FlagsEnum     flags          = Flags;

            symbolic = (flags & FlagsEnum.Symbolic) != 0;
            if (this.codes == null)
            {
                IDictionary <ByteArray, int> codes;
                if (encodingObject is PdfDictionary) // Derived encoding.
                {
                    PdfDictionary encodingDictionary = (PdfDictionary)encodingObject;

                    // Base encoding.
                    codes = GetBaseEncoding((PdfName)encodingDictionary[PdfName.BaseEncoding]);

                    // Differences.
                    PdfArray differencesObject = (PdfArray)encodingDictionary.Resolve(PdfName.Differences);
                    if (differencesObject != null)
                    {
                        /*
                         * NOTE: Each code is the first index in a sequence of character codes to be changed: the
                         * first character name after a code associates that character to that code; subsequent
                         * names replace consecutive code indices until the next code appears in the array.
                         */
                        byte[] charCodeData = new byte[1];
                        foreach (PdfDirectObject differenceObject in differencesObject)
                        {
                            if (differenceObject is PdfInteger) // Subsequence initial code.
                            {
                                charCodeData[0] = (byte)(((int)((PdfInteger)differenceObject).Value) & 0xFF);
                            }
                            else // Character name.
                            {
                                ByteArray charCode = new ByteArray(charCodeData);
                                string    charName = (string)((PdfName)differenceObject).Value;
                                if (charName.Equals(".notdef"))
                                {
                                    codes.Remove(charCode);
                                }
                                else
                                {
                                    int?code = GlyphMapping.NameToCode(charName);
                                    codes[charCode] = (code ?? charCodeData[0]);
                                }
                                charCodeData[0]++;
                            }
                        }
                    }
                }
                else // Predefined encoding.
                {
                    codes = GetBaseEncoding((PdfName)encodingObject);
                }
                this.codes = new BiDictionary <ByteArray, int>(codes);
            }
            // Purging unused character codes...
            {
                PdfArray glyphWidthObjects = (PdfArray)BaseDataObject.Resolve(PdfName.Widths);
                if (glyphWidthObjects != null)
                {
                    ByteArray charCode = new ByteArray(new byte[] { (byte)((PdfInteger)BaseDataObject[PdfName.FirstChar]).IntValue });
                    foreach (PdfDirectObject glyphWidthObject in glyphWidthObjects)
                    {
                        // PK 2017-03-08 - Changed type from PdfInteger to IPdfNumber to avoid ClassCastException and allow for more granular font sizes
                        if (((IPdfNumber)glyphWidthObject).IntValue == 0)
                        {
                            codes.Remove(charCode);
                        }
                        charCode.Data[0]++;
                    }
                }
            }

            // Mapping glyph indices...
            glyphIndexes = new Dictionary <int, int>();
            foreach (KeyValuePair <ByteArray, int> code in codes)
            {
                glyphIndexes[code.Value] = (int)code.Key.Data[0] & 0xFF;
            }
        }
Ejemplo n.º 20
0
        protected void LoadEncoding(
            )
        {
            PdfDataObject encodingObject = BaseDataObject.Resolve(PdfName.Encoding);

            // CMap [PDF:1.6:5.6.4].
            IDictionary <ByteArray, int> cmap = CMap.Get(encodingObject);

            // 1. Unicode.
            if (codes == null)
            {
                codes = new BiDictionary <ByteArray, int>();
                if (encodingObject is PdfName &&
                    !(encodingObject.Equals(PdfName.IdentityH) ||
                      encodingObject.Equals(PdfName.IdentityV)))
                {
                    /*
                     * NOTE: According to [PDF:1.6:5.9.1], the fallback method to retrieve
                     * the character-code-to-Unicode mapping implies getting the UCS2 CMap
                     * (Unicode value to CID) corresponding to the font's one (character code to CID);
                     * CIDs are the bridge from character codes to Unicode values.
                     */
                    BiDictionary <ByteArray, int> ucs2CMap;
                    {
                        PdfDictionary cidSystemInfo = (PdfDictionary)CIDFontDictionary.Resolve(PdfName.CIDSystemInfo);
                        String        registry      = (String)((PdfTextString)cidSystemInfo[PdfName.Registry]).Value;
                        String        ordering      = (String)((PdfTextString)cidSystemInfo[PdfName.Ordering]).Value;
                        String        ucs2CMapName  = registry + "-" + ordering + "-" + "UCS2";
                        ucs2CMap = new BiDictionary <ByteArray, int>(CMap.Get(ucs2CMapName));
                    }
                    if (ucs2CMap.Count > 0)
                    {
                        foreach (KeyValuePair <ByteArray, int> cmapEntry in cmap)
                        {
                            codes[cmapEntry.Key] = ConvertUtils.ByteArrayToInt(ucs2CMap.GetKey(cmapEntry.Value).Data);
                        }
                    }
                }
                if (codes.Count == 0)
                {
                    /*
                     * NOTE: In case no clue is available to determine the Unicode resolution map,
                     * the font is considered symbolic and an identity map is synthesized instead.
                     */
                    symbolic = true;
                    foreach (KeyValuePair <ByteArray, int> cmapEntry in cmap)
                    {
                        codes[cmapEntry.Key] = ConvertUtils.ByteArrayToInt(cmapEntry.Key.Data);
                    }
                }
            }

            // 2. Glyph indexes.

            /*
             * TODO: gids map for glyph indexes as glyphIndexes is used to map cids!!!
             */
            // Character-code-to-CID mapping [PDF:1.6:5.6.4,5].
            glyphIndexes = new Dictionary <int, int>();
            foreach (KeyValuePair <ByteArray, int> cmapEntry in cmap)
            {
                if (!codes.ContainsKey(cmapEntry.Key))
                {
                    continue;
                }

                glyphIndexes[codes[cmapEntry.Key]] = cmapEntry.Value;
            }
        }
Ejemplo n.º 21
0
    protected override void LoadEncoding(
      )
    {
      OpenFontParser parser;
      {
        PdfDictionary descriptor = Descriptor;
        if(descriptor.ContainsKey(PdfName.FontFile2)) // Embedded TrueType font file (without 'glyf' table).
        {
          PdfStream fontFileStream = (PdfStream)descriptor.Resolve(PdfName.FontFile2);
          parser = new OpenFontParser(fontFileStream.Body);
        }
        else if(descriptor.ContainsKey(PdfName.FontFile3))
        {
          PdfStream fontFileStream = (PdfStream)descriptor.Resolve(PdfName.FontFile3);
          PdfName fontFileSubtype = (PdfName)fontFileStream.Header[PdfName.Subtype];
          if(fontFileSubtype.Equals(PdfName.OpenType)) // Embedded OpenFont/TrueType font file (with 'glyf' table).
          {parser = new OpenFontParser(fontFileStream.Body);}
          else // Unknown.
            throw new NotSupportedException("Unknown embedded font file format: " + fontFileSubtype);
        }
        else
        {parser = null;}
      }
      if(parser != null) // Embedded font file.
      {
        // Glyph indexes.
        glyphIndexes = parser.GlyphIndexes;
        if(codes != null
          && parser.Metrics.IsCustomEncoding)
        {
          /*
            NOTE: In case of symbolic font,
            glyph indices are natively mapped to character codes,
            so they must be remapped to Unicode whenever possible
            (i.e. when ToUnicode stream is available).
          */
          Dictionary<int,int> unicodeGlyphIndexes = new Dictionary<int,int>();
          foreach(KeyValuePair<int,int> glyphIndexEntry in glyphIndexes)
          {
            int code;
            if(!codes.TryGetValue(new ByteArray(new byte[]{(byte)(int)glyphIndexEntry.Key}),out code))
              continue;

            unicodeGlyphIndexes[code] = glyphIndexEntry.Value;
          }
          glyphIndexes = unicodeGlyphIndexes;
        }
      }

      PdfDataObject encodingObject = BaseDataObject.Resolve(PdfName.Encoding);
      FlagsEnum flags = Flags;
      if((flags & FlagsEnum.Symbolic) != 0
        || ((flags & FlagsEnum.Nonsymbolic) == 0 && encodingObject == null)) // Symbolic.
      {
        symbolic = true;

        if(glyphIndexes == null)
        {
          /*
            NOTE: In case no font file is available, we have to synthesize its metrics
            from existing entries.
          */
          glyphIndexes = new Dictionary<int,int>();
          PdfArray glyphWidthObjects = (PdfArray)BaseDataObject.Resolve(PdfName.Widths);
          if(glyphWidthObjects != null)
          {
            int code = ((PdfInteger)BaseDataObject[PdfName.FirstChar]).RawValue;
            foreach(PdfDirectObject glyphWidthObject in glyphWidthObjects)
            {
              if(((PdfInteger)glyphWidthObject).RawValue > 0)
              {glyphIndexes[code] = code;}

              code++;
            }
          }
        }

        if(this.codes == null)
        {
          Dictionary<ByteArray,int> codes = new Dictionary<ByteArray,int>();
          foreach(KeyValuePair<int,int> glyphIndexEntry in glyphIndexes)
          {
            if(glyphIndexEntry.Value > 0)
            {
              int glyphCharCode = glyphIndexEntry.Key;
              byte[] charCode = new byte[]{(byte)glyphCharCode};
              codes[new ByteArray(charCode)] = glyphCharCode;
            }
          }
          this.codes = new BiDictionary<ByteArray,int>(codes);
        }
      }
      else // Nonsymbolic.
      {
        symbolic = false;

        if(this.codes == null)
        {
          Dictionary<ByteArray,int> codes;
          if(encodingObject == null) // Default encoding.
          {codes = Encoding.Get(PdfName.StandardEncoding).GetCodes();}
          else if(encodingObject is PdfName) // Predefined encoding.
          {codes = Encoding.Get((PdfName)encodingObject).GetCodes();}
          else // Custom encoding.
          {
            PdfDictionary encodingDictionary = (PdfDictionary)encodingObject;

            // 1. Base encoding.
            PdfName baseEncodingName = (PdfName)encodingDictionary[PdfName.BaseEncoding];
            if(baseEncodingName == null) // Default base encoding.
            {codes = Encoding.Get(PdfName.StandardEncoding).GetCodes();}
            else // Predefined base encoding.
            {codes = Encoding.Get(baseEncodingName).GetCodes();}

            // 2. Differences.
            LoadEncodingDifferences(encodingDictionary, codes);
          }
          this.codes = new BiDictionary<ByteArray,int>(codes);
        }

        if(glyphIndexes == null)
        {
          /*
            NOTE: In case no font file is available, we have to synthesize its metrics
            from existing entries.
          */
          glyphIndexes = new Dictionary<int,int>();
          PdfArray glyphWidthObjects = (PdfArray)BaseDataObject.Resolve(PdfName.Widths);
          if(glyphWidthObjects != null)
          {
            ByteArray charCode = new ByteArray(
              new byte[]
              {(byte)(int)((PdfInteger)BaseDataObject[PdfName.FirstChar]).RawValue}
              );
            foreach(PdfDirectObject glyphWidthObject in glyphWidthObjects)
            {
              if(((PdfInteger)glyphWidthObject).RawValue > 0)
              {
                int code;
                if(codes.TryGetValue(charCode,out code))
                {glyphIndexes[code] = (int)charCode.Data[0];}
              }
              charCode.Data[0]++;
            }
          }
        }
      }
    }
 private DeviceColor GetColor(
     PdfName key
     )
 {
     return(DeviceColor.Get((PdfArray)BaseDataObject.Resolve(key)));
 }