/// <summary>
        /// Formats content of <see cref="DictionaryToken"/>.
        /// </summary>
        /// <param name="token">Token to be formatted.</param>
        public void Format(DictionaryToken token)
        {
            _output.Write('[');
            var elements   = token.Elements.ToArray();
            int allButLast = elements.Length - 1;

            for (int i = 0; i < allButLast; i++)
            {
                _output.Write("{\"key\": ");
                elements[i].Key.Render(this);
                _output.Write(", \"value\": ");
                elements[i].Value.Render(this);
                _output.Write("}, ");
            }

            if (elements.Length > 0)
            {
                var last = elements[elements.Length - 1];
                _output.Write("{\"key\": ");
                last.Key.Render(this);
                _output.Write(", \"value\": ");
                last.Value.Render(this);
                _output.Write('}');
            }

            _output.Write(']');
        }
Exemple #2
0
        public IFont Generate(DictionaryToken dictionary, bool isLenientParsing)
        {
            var baseFont = dictionary.GetNameOrDefault(NameToken.BaseFont);

            var cMap = ReadEncoding(dictionary, out var isCMapPredefined);

            ICidFont cidFont;

            if (TryGetFirstDescendant(dictionary, out var descendantObject))
            {
                DictionaryToken descendantFontDictionary;

                if (descendantObject is IndirectReferenceToken obj)
                {
                    var parsed = DirectObjectFinder.Get<DictionaryToken>(obj, scanner);

                    descendantFontDictionary = parsed;
                }
                else
                {
                    descendantFontDictionary = (DictionaryToken) descendantObject;
                }

                cidFont = ParseDescendant(descendantFontDictionary, isLenientParsing);
            }
            else
            {
                throw new InvalidFontFormatException("No descendant font dictionary was declared for this Type 0 font. This dictionary should contain the CIDFont for the Type 0 font. " + dictionary);
            }

            var (ucs2CMap, isChineseJapaneseOrKorean) = GetUcs2CMap(dictionary, isCMapPredefined, cidFont);

            CMap toUnicodeCMap = null;
            if (dictionary.ContainsKey(NameToken.ToUnicode))
            {
                var toUnicodeValue = dictionary.Data[NameToken.ToUnicode];

                if (DirectObjectFinder.TryGet<StreamToken>(toUnicodeValue, scanner, out var toUnicodeStream))
                {
                    var decodedUnicodeCMap = toUnicodeStream?.Decode(filterProvider);

                    if (decodedUnicodeCMap != null)
                    {
                        toUnicodeCMap = CMapCache.Parse(new ByteArrayInputBytes(decodedUnicodeCMap), isLenientParsing);
                    }
                }
                else if (DirectObjectFinder.TryGet<NameToken>(toUnicodeValue, scanner, out var toUnicodeName))
                {
                    toUnicodeCMap = CMapCache.Get(toUnicodeName.Data);
                }
                else
                {
                    throw new PdfDocumentFormatException($"Invalid type of toUnicode CMap encountered. Got: {toUnicodeValue}.");
                }
            }

            var font = new Type0Font(baseFont, cidFont, cMap, toUnicodeCMap, ucs2CMap, isChineseJapaneseOrKorean);

            return font;
        }
        private static DescriptorFontFile GetFontFile(DictionaryToken dictionary)
        {
            if (dictionary.TryGet(NameToken.FontFile, out var value))
            {
                if (!(value is IndirectReferenceToken obj))
                {
                    throw new NotSupportedException("We currently expect the FontFile to be an object reference.");
                }

                return(new DescriptorFontFile(obj, DescriptorFontFile.FontFileType.Type1));
            }

            if (dictionary.TryGet(NameToken.FontFile2, out value))
            {
                if (!(value is IndirectReferenceToken obj))
                {
                    throw new NotSupportedException("We currently expect the FontFile2 to be an object reference.");
                }

                return(new DescriptorFontFile(obj, DescriptorFontFile.FontFileType.TrueType));
            }

            if (dictionary.TryGet(NameToken.FontFile3, out value))
            {
                if (!(value is IndirectReferenceToken obj))
                {
                    throw new NotSupportedException("We currently expect the FontFile3 to be an object reference.");
                }

                return(new DescriptorFontFile(obj, DescriptorFontFile.FontFileType.FromSubtype));
            }

            return(null);
        }
Exemple #4
0
        public IFont Generate(DictionaryToken dictionary)
        {
            var boundingBox = GetBoundingBox(dictionary);

            var fontMatrix = GetFontMatrix(dictionary);

            var firstCharacter = FontDictionaryAccessHelper.GetFirstCharacter(dictionary);
            var lastCharacter  = FontDictionaryAccessHelper.GetLastCharacter(dictionary);
            var widths         = FontDictionaryAccessHelper.GetWidths(scanner, dictionary);

            Encoding encoding = encodingReader.Read(dictionary);

            CMap toUnicodeCMap = null;

            if (dictionary.TryGet(NameToken.ToUnicode, out var toUnicodeObj))
            {
                var toUnicode = DirectObjectFinder.Get <StreamToken>(toUnicodeObj, scanner);

                var decodedUnicodeCMap = toUnicode?.Decode(filterProvider, scanner);

                if (decodedUnicodeCMap != null)
                {
                    toUnicodeCMap = CMapCache.Parse(new ByteArrayInputBytes(decodedUnicodeCMap));
                }
            }

            var name = GetFontName(dictionary);

            return(new Type3Font(name, boundingBox, fontMatrix, encoding, firstCharacter,
                                 lastCharacter, widths, toUnicodeCMap));
        }
Exemple #5
0
        public MarkedContentElement(int markedContentIdentifier, NameToken tag, DictionaryToken properties,
                                    string language,
                                    string actualText,
                                    string alternateDescription,
                                    string expandedForm,
                                    bool isArtifact,
                                    IReadOnlyList <MarkedContentElement> children,
                                    IReadOnlyList <Letter> letters,
                                    IReadOnlyList <PdfPath> paths,
                                    IReadOnlyList <IPdfImage> images,
                                    int index)
        {
            MarkedContentIdentifier = markedContentIdentifier;
            Tag                  = tag;
            Language             = language;
            ActualText           = actualText;
            AlternateDescription = alternateDescription;
            ExpandedForm         = expandedForm;
            Properties           = properties ?? new DictionaryToken(new Dictionary <NameToken, IToken>());
            IsArtifact           = isArtifact;

            Children = children ?? throw new ArgumentNullException(nameof(children));
            Letters  = letters ?? throw new ArgumentNullException(nameof(letters));
            Paths    = paths ?? throw new ArgumentNullException(nameof(paths));
            Images   = images ?? throw new ArgumentNullException(nameof(images));

            Index = index;
        }
Exemple #6
0
        public IFont Get(DictionaryToken dictionary, bool isLenientParsing)
        {
            var type = dictionary.GetNameOrDefault(NameToken.Type);

            if (type != null && !type.Equals(NameToken.Font))
            {
                var message = "The font dictionary did not have type 'Font'. " + dictionary;

                if (isLenientParsing)
                {
                    log?.Error(message);
                }
                else
                {
                    throw new InvalidFontFormatException(message);
                }
            }

            var subtype = dictionary.GetNameOrDefault(NameToken.Subtype);

            if (handlers.TryGetValue(subtype, out var handler))
            {
                return(handler.Generate(dictionary, isLenientParsing));
            }

            throw new NotImplementedException($"Parsing not implemented for fonts of type: {subtype}, please submit a pull request or an issue.");
        }
Exemple #7
0
 /// <summary>
 /// Creates a new <see cref="XObjectImage"/>.
 /// </summary>
 internal XObjectImage(PdfRectangle bounds, int widthInSamples, int heightInSamples, int bitsPerComponent,
                       ColorSpace?colorSpace,
                       bool isJpxEncoded,
                       bool isImageMask,
                       RenderingIntent renderingIntent,
                       bool interpolate,
                       IReadOnlyList <decimal> decode,
                       DictionaryToken imageDictionary,
                       IReadOnlyList <byte> rawBytes,
                       Lazy <IReadOnlyList <byte> > bytes)
 {
     Bounds           = bounds;
     WidthInSamples   = widthInSamples;
     HeightInSamples  = heightInSamples;
     BitsPerComponent = bitsPerComponent;
     ColorSpace       = colorSpace;
     IsJpxEncoded     = isJpxEncoded;
     IsImageMask      = isImageMask;
     RenderingIntent  = renderingIntent;
     Interpolate      = interpolate;
     Decode           = decode;
     ImageDictionary  = imageDictionary ?? throw new ArgumentNullException(nameof(imageDictionary));
     RawBytes         = rawBytes;
     this.bytes       = bytes ?? throw new ArgumentNullException(nameof(bytes));
 }
Exemple #8
0
        private CMap ReadEncoding(DictionaryToken dictionary, out bool isCMapPredefined)
        {
            isCMapPredefined = false;
            CMap result;

            if (dictionary.TryGet(NameToken.Encoding, scanner, out NameToken encodingName))
            {
                if (!CMapCache.TryGet(encodingName.Data, out var cmap))
                {
                    throw new InvalidOperationException($"Missing CMap named {encodingName.Data}.");
                }

                result = cmap ?? throw new InvalidOperationException($"Missing CMap named {encodingName.Data}.");

                isCMapPredefined = true;
            }
            else if (dictionary.TryGet(NameToken.Encoding, scanner, out StreamToken stream))
            {
                var decoded = stream.Decode(filterProvider, scanner);

                var cmap = CMapCache.Parse(new ByteArrayInputBytes(decoded));

                result = cmap ?? throw new InvalidOperationException($"Could not read CMap from stream in the dictionary: {dictionary}");
            }
            else
            {
                throw new InvalidOperationException(
                          $"Could not read the encoding, expected a name or a stream but it was not found in the dictionary: {dictionary}");
            }

            return(result);
        }
Exemple #9
0
        public static Dictionary <string, IToken> GetOrCreateDict(this Dictionary <string, IToken> dict, string key)
        {
            if (dict.TryGetValue(key, out var item))
            {
                if (!(item is DictionaryToken dt))
                {
                    throw new ApplicationException("Expected dictionary token, got " + item.GetType());
                }

                if (dt.Data is Dictionary <string, IToken> mutable)
                {
                    return(mutable);
                }

                mutable = dt.Data.
                          ToDictionary(x => x.Key, x => x.Value);
                dict[key] = DictionaryToken.With(mutable);
                return(mutable);
            }

            var created = new Dictionary <string, IToken>();

            dict[key] = DictionaryToken.With(created);
            return(created);
        }
Exemple #10
0
        private static IEnumerable <long> GetObjectNumbers(DictionaryToken dictionary)
        {
            //  The number one greater than the highest object number used in this section or in any section for which this is an update.
            if (!dictionary.TryGet(NameToken.Size, out var sizeToken) || !(sizeToken is NumericToken sizeNumeric))
            {
                throw new PdfDocumentFormatException($"The stream dictionary must contain a numeric size value: {dictionary}.");
            }

            var objNums = new List <long>();

            if (dictionary.TryGet(NameToken.Index, out var indexToken) && indexToken is ArrayToken indexArrayToken)
            {
                // An array containing a pair of integers for each subsection in this section.
                // Pair[0] is the first object number in the subsection; Pair[1] is the number of entries in the subsection.
                for (var i = 0; i < indexArrayToken.Length; i += 2)
                {
                    var firstObjectNumber = indexArrayToken.GetNumeric(i).Int;
                    var size = indexArrayToken.GetNumeric(i + 1).Int;

                    for (var j = 0; j < size; j++)
                    {
                        objNums.Add(firstObjectNumber + j);
                    }
                }
            }
            else
            {
                for (var i = 0; i < sizeNumeric.Int; i++)
                {
                    objNums.Add(i);
                }
            }

            return(objNums);
        }
Exemple #11
0
        private Encoding ReadEncodingDictionary(DictionaryToken encodingDictionary, Encoding fontEncoding)
        {
            if (encodingDictionary == null)
            {
                return(null);
            }

            Encoding baseEncoding;

            if (encodingDictionary.TryGet(NameToken.BaseEncoding, out var baseEncodingToken) && baseEncodingToken is NameToken baseEncodingName)
            {
                if (!Encoding.TryGetNamedEncoding(baseEncodingName, out baseEncoding))
                {
                    throw new InvalidFontFormatException($"No encoding found with name {baseEncodingName} to use as base encoding.");
                }
            }
            else
            {
                // TODO: This isn't true for non-symbolic fonts or latin fonts (based on OS?) see section 5.5.5
                baseEncoding = fontEncoding ?? StandardEncoding.Instance;
            }

            if (!encodingDictionary.TryGet(NameToken.Differences, out var differencesBase))
            {
                return(baseEncoding);
            }

            var differenceArray = DirectObjectFinder.Get <ArrayToken>(differencesBase, pdfScanner);

            var differences = ProcessDifferences(differenceArray);

            var newEncoding = new DifferenceBasedEncoding(baseEncoding, differences);

            return(newEncoding);
        }
Exemple #12
0
        private CropBox GetCropBox(DictionaryToken dictionary, PageTreeMembers pageTreeMembers, MediaBox mediaBox, bool isLenientParsing)
        {
            CropBox cropBox;

            if (dictionary.TryGet(NameToken.CropBox, out var cropBoxObject) &&
                DirectObjectFinder.TryGet(cropBoxObject, pdfScanner, out ArrayToken cropBoxArray))
            {
                if (cropBoxArray.Length != 4 && isLenientParsing)
                {
                    log.Error($"The CropBox was the wrong length in the dictionary: {dictionary}. Array was: {cropBoxArray}.");

                    cropBox = new CropBox(mediaBox.Bounds);

                    return(cropBox);
                }

                cropBox = new CropBox(cropBoxArray.ToIntRectangle());
            }
            else
            {
                cropBox = pageTreeMembers.GetCropBox() ?? new CropBox(mediaBox.Bounds);
            }

            return(cropBox);
        }
        /// <inheritdoc />
        public IReadOnlyList <IFilter> GetFilters(DictionaryToken dictionary)
        {
            if (dictionary == null)
            {
                throw new ArgumentNullException(nameof(dictionary));
            }

            var token = dictionary.GetObjectOrDefault(NameToken.Filter, NameToken.F);

            if (token == null)
            {
                return(EmptyArray <IFilter> .Instance);
            }

            switch (token)
            {
            case ArrayToken filters:
                var result = new IFilter[filters.Data.Count];
                for (var i = 0; i < filters.Data.Count; i++)
                {
                    var filterToken = filters.Data[i];
                    var filterName  = ((NameToken)filterToken).Data;
                    result[i] = GetFilterStrict(filterName);
                }

                return(result);

            case NameToken name:
                return(new[] { GetFilterStrict(name.Data) });

            default:
                throw new PdfDocumentFormatException($"The filter for the stream was not a valid object. Expected name or array, instead got: {token}.");
            }
        }
Exemple #14
0
        private MediaBox GetMediaBox(int number, DictionaryToken dictionary, PageTreeMembers pageTreeMembers)
        {
            MediaBox mediaBox;

            if (dictionary.TryGet(NameToken.MediaBox, out var mediaboxObject) &&
                DirectObjectFinder.TryGet(mediaboxObject, pdfScanner, out ArrayToken mediaboxArray))
            {
                if (mediaboxArray.Length != 4)
                {
                    log.Error($"The MediaBox was the wrong length in the dictionary: {dictionary}. Array was: {mediaboxArray}. Defaulting to US Letter.");

                    mediaBox = MediaBox.Letter;

                    return(mediaBox);
                }

                mediaBox = new MediaBox(mediaboxArray.ToIntRectangle(pdfScanner));
            }
            else
            {
                mediaBox = pageTreeMembers.MediaBox;

                if (mediaBox == null)
                {
                    log.Error($"The MediaBox was the wrong missing for page {number}. Using US Letter.");

                    // PDFBox defaults to US Letter.
                    mediaBox = MediaBox.Letter;
                }
            }

            return(mediaBox);
        }
Exemple #15
0
 /// <inheritdoc />
 /// <summary>
 /// Create a new <see cref="T:UglyToad.PdfPig.AcroForms.Fields.AcroSignatureField" />.
 /// </summary>
 public AcroSignatureField(DictionaryToken dictionary, string fieldType, uint fieldFlags,
                           AcroFieldCommonInformation information,
                           int?pageNumber,
                           PdfRectangle?bounds) :
     base(dictionary, fieldType, fieldFlags, AcroFieldType.Signature, information, pageNumber, bounds)
 {
 }
Exemple #16
0
        public IReadOnlyList <IFilter> GetFilters(DictionaryToken dictionary)
        {
            if (dictionary == null)
            {
                throw new ArgumentNullException(nameof(dictionary));
            }

            if (!dictionary.TryGet(NameToken.Filter, out var token))
            {
                return(new IFilter[0]);
            }

            switch (token)
            {
            case ArrayToken filters:
                // TODO: presumably this may be invalid...
                return(filters.Data.Select(x => GetFilterStrict(((NameToken)x).Data)).ToList());

            case NameToken name:
                return(new[] { GetFilterStrict(name.Data) });

            default:
                throw new PdfDocumentFormatException($"The filter for the stream was not a valid object. Expected name or array, instead got: {token}.");
            }
        }
Exemple #17
0
 /// <summary>
 /// Create a new <see cref="AcroFieldBase"/>.
 /// </summary>
 /// <param name="dictionary">The dictionary for this field.</param>
 /// <param name="fieldType">The type of this field.</param>
 /// <param name="fieldFlags">The flags specifying behaviour for this field.</param>
 /// <param name="information">Additional information for this field.</param>
 protected AcroFieldBase(DictionaryToken dictionary, string fieldType, uint fieldFlags, AcroFieldCommonInformation information)
 {
     Dictionary  = dictionary ?? throw new ArgumentNullException(nameof(dictionary));
     FieldType   = fieldType ?? throw new ArgumentNullException(nameof(fieldType));
     FieldFlags  = fieldFlags;
     Information = information ?? new AcroFieldCommonInformation(null, null, null, null);
 }
Exemple #18
0
            public void Build()
            {
                if (pagesTokenReferences.Count < 1)
                {
                    throw new PdfDocumentFormatException("Empty document");
                }

                var pagesDictionary = new DictionaryToken(new Dictionary <NameToken, IToken>
                {
                    { NameToken.Type, NameToken.Pages },
                    { NameToken.Kids, new ArrayToken(pagesTokenReferences) },
                    { NameToken.Count, new NumericToken(pageCount) }
                });

                var pagesRef = context.WriteToken(pagesDictionary, (int)rootPagesReference.Data.ObjectNumber);

                var catalog = new DictionaryToken(new Dictionary <NameToken, IToken>
                {
                    { NameToken.Type, NameToken.Catalog },
                    { NameToken.Pages, pagesRef }
                });

                var catalogRef = context.WriteToken(catalog);

                context.Flush(currentVersion, catalogRef);

                Close();
            }
        public static decimal[] GetWidths(IPdfTokenScanner pdfScanner, DictionaryToken dictionary, bool isLenientParsing)
        {
            if (!dictionary.TryGet(NameToken.Widths, out var token))
            {
                throw new InvalidFontFormatException($"No widths array found for the font: {dictionary}.");
            }

            var widthArray = DirectObjectFinder.Get <ArrayToken>(token, pdfScanner);

            var result = new decimal[widthArray.Data.Count];

            for (int i = 0; i < widthArray.Data.Count; i++)
            {
                var arrayToken = widthArray.Data[i];

                if (!(arrayToken is NumericToken number))
                {
                    throw new InvalidFontFormatException($"Token which was not a number found in the widths array: {arrayToken}.");
                }

                result[i] = number.Data;
            }

            return(result);
        }
Exemple #20
0
        private string SafeKeyAccess(DictionaryToken dictionary, NameToken keyName)
        {
            if (!dictionary.TryGet(keyName, out var token))
            {
                return(string.Empty);
            }

            if (token is StringToken str)
            {
                return(str.Data);
            }

            if (token is HexToken hex)
            {
                return(hex.Data);
            }

            if (token is IndirectReferenceToken obj)
            {
                if (DirectObjectFinder.TryGet(obj, pdfScanner, out StringToken stringToken))
                {
                    return(stringToken.Data);
                }

                if (DirectObjectFinder.TryGet(obj, pdfScanner, out HexToken hexToken))
                {
                    return(hexToken.Data);
                }

                throw new PdfDocumentFormatException($"Could not get key for name: {keyName} in {dictionary}.");
            }

            return(string.Empty);
        }
Exemple #21
0
        private static List <long> GetObjectNumbers(DictionaryToken dictionary)
        {
            if (!dictionary.TryGet(NameToken.Size, out var sizeToken) || !(sizeToken is NumericToken sizeNumeric))
            {
                throw new PdfDocumentFormatException($"The stream dictionary must contain a numeric size value: {dictionary}.");
            }

            var indexArray = new[] { 0, sizeNumeric.Int };

            if (dictionary.TryGet(NameToken.Index, out var indexToken) && indexToken is ArrayToken indexArrayToken)
            {
                indexArray = new[]
                {
                    indexArrayToken.GetNumeric(0).Int,
                    indexArrayToken.GetNumeric(1).Int
                };
            }

            List <long> objNums = new List <long>();

            var firstObjectNumber = indexArray[0];
            var size = indexArray[1];

            for (var i = 0; i < size; i++)
            {
                objNums.Add(firstObjectNumber + i);
            }

            return(objNums);
        }
Exemple #22
0
        private void LoadFontDictionary(DictionaryToken fontDictionary, bool isLenientParsing)
        {
            foreach (var pair in fontDictionary.Data)
            {
                if (!(pair.Value is IndirectReferenceToken objectKey))
                {
                    if (isLenientParsing)
                    {
                        continue;
                    }

                    throw new InvalidOperationException($"The font with name {pair.Key} did not link to an object key. Value was: {pair.Value}.");
                }

                var reference = objectKey.Data;

                currentResourceState[NameToken.Create(pair.Key)] = reference;

                if (loadedFonts.ContainsKey(reference))
                {
                    continue;
                }

                var fontObject = DirectObjectFinder.Get <DictionaryToken>(objectKey, scanner);

                if (fontObject == null)
                {
                    throw new InvalidOperationException($"Could not retrieve the font with name: {pair.Key} which should have been object {objectKey}");
                }

                loadedFonts[reference] = fontFactory.Get(fontObject, isLenientParsing);
            }
        }
 public ImageStored(DictionaryToken streamDictionary, byte[] streamData, int objectNumber)
 {
     Id = Guid.NewGuid();
     StreamDictionary = streamDictionary;
     StreamData       = streamData;
     ObjectNumber     = objectNumber;
 }
Exemple #24
0
        /// <summary>
        /// Create a new <see cref="InlineImage"/>.
        /// </summary>
        internal InlineImage(PdfRectangle bounds, int widthInSamples, int heightInSamples, int bitsPerComponent, bool isImageMask,
                             RenderingIntent renderingIntent,
                             bool interpolate,
                             ColorSpace?colorSpace,
                             IReadOnlyList <decimal> decode,
                             IReadOnlyList <byte> bytes,
                             IReadOnlyList <IFilter> filters,
                             DictionaryToken streamDictionary)
        {
            Bounds           = bounds;
            WidthInSamples   = widthInSamples;
            HeightInSamples  = heightInSamples;
            ColorSpace       = colorSpace;
            Decode           = decode;
            BitsPerComponent = bitsPerComponent;
            IsImageMask      = isImageMask;
            RenderingIntent  = renderingIntent;
            Interpolate      = interpolate;

            RawBytes     = bytes;
            bytesFactory = new Lazy <IReadOnlyList <byte> >(() =>
            {
                var b = bytes.ToArray();
                for (var i = 0; i < filters.Count; i++)
                {
                    var filter = filters[i];
                    b          = filter.Decode(b, streamDictionary, i);
                }

                return(b);
            });
        }
Exemple #25
0
        private CMap ReadEncoding(DictionaryToken dictionary, out bool isCMapPredefined)
        {
            isCMapPredefined = false;
            CMap result = default(CMap);

            if (dictionary.TryGet(NameToken.Encoding, out var value))
            {
                if (value is NameToken encodingName)
                {
                    var cmap = CMapCache.Get(encodingName.Data);

                    result = cmap ?? throw new InvalidOperationException("Missing CMap for " + encodingName.Data);

                    isCMapPredefined = true;
                }
                else if (value is StreamToken stream)
                {
                    var decoded = stream.Decode(filterProvider);

                    var cmap = CMapCache.Parse(new ByteArrayInputBytes(decoded), false);

                    result = cmap ?? throw new InvalidOperationException("Could not read CMap for " + dictionary);
                }
                else
                {
                    throw new InvalidOperationException("Could not read the encoding, expected a name or a stream but got a: " + value.GetType().Name);
                }
            }

            return result;
        }
        public IFont Generate(DictionaryToken dictionary, bool isLenientParsing)
        {
            var firstCharacter = FontDictionaryAccessHelper.GetFirstCharacter(dictionary);

            var widths = FontDictionaryAccessHelper.GetWidths(pdfScanner, dictionary, isLenientParsing);

            var descriptor = FontDictionaryAccessHelper.GetFontDescriptor(pdfScanner, fontDescriptorFactory, dictionary, isLenientParsing);

            // TODO: use the parsed font fully.
            var font = ParseTrueTypeFont(descriptor);

            var name = FontDictionaryAccessHelper.GetName(pdfScanner, dictionary, descriptor, isLenientParsing);

            CMap toUnicodeCMap = null;

            if (dictionary.TryGet(NameToken.ToUnicode, out var toUnicodeObj))
            {
                var toUnicode = DirectObjectFinder.Get <StreamToken>(toUnicodeObj, pdfScanner);

                var decodedUnicodeCMap = toUnicode.Decode(filterProvider);

                if (decodedUnicodeCMap != null)
                {
                    toUnicodeCMap = cMapCache.Parse(new ByteArrayInputBytes(decodedUnicodeCMap), isLenientParsing);
                }
            }

            Encoding encoding = encodingReader.Read(dictionary, isLenientParsing, descriptor);

            return(new TrueTypeSimpleFont(name, descriptor, toUnicodeCMap, encoding, font, firstCharacter, widths));
        }
Exemple #27
0
        private static bool TryGetFirstDescendant(DictionaryToken dictionary, out IToken descendant)
        {
            descendant = null;

            if (!dictionary.TryGet(NameToken.DescendantFonts, out var value))
            {
                return false;
            }

            if (value is IndirectReferenceToken obj)
            {
                descendant = obj;
                return true;
            }

            if (value is ArrayToken array && array.Data.Count > 0)
            {
                if (array.Data[0] is IndirectReferenceToken objArr)
                {
                descendant = objArr;
                }
                else if (array.Data[0] is DictionaryToken dict)
                {
                    descendant = dict;
                }
                else
                {
                    return false;
                }

                return true;
            }

            return false;
        }
Exemple #28
0
        internal Page(int number, DictionaryToken dictionary, MediaBox mediaBox, CropBox cropBox, PageRotationDegrees rotation, PageContent content,
                      AnnotationProvider annotationProvider,
                      IPdfTokenScanner pdfScanner)
        {
            if (number <= 0)
            {
                throw new ArgumentOutOfRangeException(nameof(number), "Page number cannot be 0 or negative.");
            }

            Dictionary = dictionary ?? throw new ArgumentNullException(nameof(dictionary));

            Number   = number;
            MediaBox = mediaBox;
            CropBox  = cropBox;
            Rotation = rotation;
            Content  = content;
            textLazy = new Lazy <string>(() => GetText(Content));

            Width  = mediaBox.Bounds.Width;
            Height = mediaBox.Bounds.Height;

            Size = mediaBox.Bounds.GetPageSize();
            ExperimentalAccess      = new Experimental(this, annotationProvider);
            this.annotationProvider = annotationProvider;
            this.pdfScanner         = pdfScanner ?? throw new ArgumentNullException(nameof(pdfScanner));
        }
Exemple #29
0
        private static CMap GetUcs2CMap(DictionaryToken dictionary, bool isCMapPredefined, bool usesDescendantAdobeFont)
        {
            if (!isCMapPredefined)
            {
                return(null);
            }

            /*
             * If the font is a composite font that uses one of the predefined CMaps except Identity–H and Identity–V or whose descendant
             * CIDFont uses the Adobe-GB1, Adobe-CNS1, Adobe-Japan1, or Adobe-Korea1 character collection use a UCS2 CMap.
             */

            var encodingName = dictionary.GetNameOrDefault(NameToken.Encoding);

            if (encodingName == null)
            {
                return(null);
            }

            var isPredefinedIdentityMap = encodingName.Equals(NameToken.IdentityH) || encodingName.Equals(NameToken.IdentityV);

            if (isPredefinedIdentityMap && !usesDescendantAdobeFont)
            {
                return(null);
            }

            throw new NotSupportedException("Support for UCS2 CMaps are not implemented yet. Please raise an issue.");
        }
Exemple #30
0
        public bool FindPage(DictionaryToken currentPageDictionary, int soughtPageNumber, List <int> pageNumbersObserved, PageTreeMembers pageTreeMembers)
        {
            var type = currentPageDictionary.GetNameOrDefault(NameToken.Type);

            if (type?.Equals(NameToken.Page) == true)
            {
                var pageNumber = GetNextPageNumber(pageNumbersObserved);

                bool found = pageNumber == soughtPageNumber;

                locatedPages[pageNumber] = currentPageDictionary;
                pageNumbersObserved.Add(pageNumber);

                return(found);
            }

            if (type?.Equals(NameToken.Pages) != true)
            {
                log.Warn("Did not find the expected type (Page or Pages) in dictionary: " + currentPageDictionary);

                return(false);
            }

            if (currentPageDictionary.TryGet(NameToken.MediaBox, out var token))
            {
                var mediaBox = DirectObjectFinder.Get <ArrayToken>(token, pdfScanner);

                pageTreeMembers.MediaBox = new MediaBox(new PdfRectangle(mediaBox.GetNumeric(0).Data,
                                                                         mediaBox.GetNumeric(1).Data,
                                                                         mediaBox.GetNumeric(2).Data,
                                                                         mediaBox.GetNumeric(3).Data));
            }

            if (!currentPageDictionary.TryGet(NameToken.Kids, out var kids) ||
                !(kids is ArrayToken kidsArray))
            {
                return(false);
            }

            pageFactory.LoadResources(currentPageDictionary, isLenientParsing);

            bool childFound = false;

            foreach (var kid in kidsArray.Data)
            {
                // todo: exit early
                var child = DirectObjectFinder.Get <DictionaryToken>(kid, pdfScanner);

                var thisPageMatches = FindPage(child, soughtPageNumber, pageNumbersObserved, pageTreeMembers);

                if (thisPageMatches)
                {
                    childFound = true;
                    break;
                }
            }

            return(childFound);
        }