Beispiel #1
0
        /**
          <summary>Gets the direction corresponding to the given value.</summary>
        */
        public static RotationEnum Get(
      PdfInteger value
      )
        {
            if(value == null)
            return RotationEnum.Downward;

              int normalizedValue = (int)(Math.Round(value.RawValue / 90d) % 4) * 90;
              if(normalizedValue < 0)
              {normalizedValue += 360 * (int)Math.Ceiling(-normalizedValue / 360d);}
              return (RotationEnum)normalizedValue;
        }
 /// <summary>
 /// Writes the specified value to the PDF stream.
 /// </summary>
 public void Write(PdfInteger value)
 {
     WriteSeparator(CharCat.Character);
     _lastCat = CharCat.Character;
     WriteRaw(value.Value.ToString(CultureInfo.InvariantCulture));
 }
        /**
         * <summary>Loads the font data.</summary>
         */
        private void Load(
            OpenFontParser parser
            )
        {
            glyphIndexes  = parser.GlyphIndexes;
            glyphKernings = parser.GlyphKernings;
            glyphWidths   = parser.GlyphWidths;

            PdfDictionary baseDataObject = BaseDataObject;

            // BaseFont.
            baseDataObject[PdfName.BaseFont] = new PdfName(parser.FontName);

            // Subtype.
            baseDataObject[PdfName.Subtype] = PdfName.Type0;

            // Encoding.
            baseDataObject[PdfName.Encoding] = PdfName.IdentityH; //TODO: this is a simplification (to refine later).

            // Descendant font.
            PdfDictionary cidFontDictionary = new PdfDictionary(
                new PdfName[] { PdfName.Type },
                new PdfDirectObject[] { PdfName.Font }
                ); // CIDFont dictionary [PDF:1.6:5.6.3].

            {
                // Subtype.
                PdfName subType;
                switch (parser.OutlineFormat)
                {
                case OpenFontParser.OutlineFormatEnum.TrueType: subType = PdfName.CIDFontType2; break;

                case OpenFontParser.OutlineFormatEnum.CFF: subType = PdfName.CIDFontType0; break;

                default: throw new NotImplementedException();
                }
                cidFontDictionary[PdfName.Subtype] = subType;

                // BaseFont.
                cidFontDictionary[PdfName.BaseFont] = new PdfName(parser.FontName);

                // CIDSystemInfo.
                cidFontDictionary[PdfName.CIDSystemInfo] = new PdfDictionary(
                    new PdfName[]
                {
                    PdfName.Registry,
                    PdfName.Ordering,
                    PdfName.Supplement
                },
                    new PdfDirectObject[]
                {
                    new PdfTextString("Adobe"),
                    new PdfTextString("Identity"),
                    PdfInteger.Get(0)
                }
                    ); // Generic predefined CMap (Identity-H/V (Adobe-Identity-0)) [PDF:1.6:5.6.4].

                // FontDescriptor.
                cidFontDictionary[PdfName.FontDescriptor] = Load_CreateFontDescriptor(parser);

                // Encoding.
                Load_CreateEncoding(baseDataObject, cidFontDictionary);
            }
            baseDataObject[PdfName.DescendantFonts] = new PdfArray(new PdfDirectObject[] { File.Register(cidFontDictionary) });

            Load();
        }
Beispiel #4
0
 /// <summary>
 /// Writes the specified value to the PDF stream.
 /// </summary>
 public void Write(PdfInteger value)
 {
     WriteSeparator(CharCat.Character);
     this.lastCat = CharCat.Character;
     WriteRaw(value.Value.ToString());
 }
Beispiel #5
0
        /**
         * <summary>Serializes the xref stream entries into the stream body.</summary>
         */
        private void Flush(
            IOutputStream stream
            )
        {
            // 1. Body.
            PdfArray indexArray = new PdfArray();

            int[] entryFieldSizes = new int[]
            {
                EntryField0Size,
                GetFieldSize((int)stream.Length), // NOTE: We assume this xref stream is the last indirect object.
                EntryField2Size
            };
            {
                // Get the stream buffer!
                IBuffer body = Body;

                // Delete the old entries!
                body.SetLength(0);

                // Serializing the entries into the stream buffer...
                int prevObjectNumber = -2; // Previous-entry object number.
                foreach (XRefEntry entry in entries.Values)
                {
                    int entryNumber = entry.Number;
                    if (entryNumber - prevObjectNumber != 1) // Current subsection terminated.
                    {
                        if (indexArray.Count > 0)
                        {
                            indexArray.Add(PdfInteger.Get(prevObjectNumber - ((PdfInteger)indexArray[indexArray.Count - 1]).IntValue + 1));
                        }                                            // Number of entries in the previous subsection.
                        indexArray.Add(PdfInteger.Get(entryNumber)); // First object number in the next subsection.
                    }
                    prevObjectNumber = entryNumber;

                    switch (entry.Usage)
                    {
                    case XRefEntry.UsageEnum.Free:
                        body.Append((byte)FreeEntryType);
                        body.Append(NumberToByteArray(entry.Offset, entryFieldSizes[1]));
                        body.Append(NumberToByteArray(entry.Generation, entryFieldSizes[2]));
                        break;

                    case XRefEntry.UsageEnum.InUse:
                        body.Append((byte)InUseEntryType);
                        body.Append(NumberToByteArray(entry.Offset, entryFieldSizes[1]));
                        body.Append(NumberToByteArray(entry.Generation, entryFieldSizes[2]));
                        break;

                    case XRefEntry.UsageEnum.InUseCompressed:
                        body.Append((byte)InUseCompressedEntryType);
                        body.Append(NumberToByteArray(entry.StreamNumber, entryFieldSizes[1]));
                        body.Append(NumberToByteArray(entry.Offset, entryFieldSizes[2]));
                        break;

                    default:
                        throw new NotSupportedException();
                    }
                }
                indexArray.Add(PdfInteger.Get(prevObjectNumber - ((PdfInteger)indexArray[indexArray.Count - 1]).IntValue + 1)); // Number of entries in the previous subsection.
            }

            // 2. Header.
            {
                PdfDictionary header = Header;
                header[PdfName.Index] = indexArray;
                header[PdfName.Size]  = PdfInteger.Get(File.IndirectObjects.Count + 1);
                header[PdfName.W]     = new PdfArray(
                    PdfInteger.Get(entryFieldSizes[0]),
                    PdfInteger.Get(entryFieldSizes[1]),
                    PdfInteger.Get(entryFieldSizes[2])
                    );
            }
        }
        /**
         * <summary>Creates the character code mapping for composite fonts.</summary>
         */
        private void Load_CreateEncoding(
            PdfDictionary font,
            PdfDictionary cidFont
            )
        {
            /*
             * NOTE: Composite fonts map text shown by content stream strings through a 2-level encoding
             * scheme:
             *  character code -> CID (character index) -> GID (glyph index)
             * This works for rendering purposes, but if we want our text data to be intrinsically meaningful,
             * we need a further mapping towards some standard character identification scheme (Unicode):
             *  Unicode <- character code -> CID -> GID
             * Such mapping may be provided by a known CID collection or (in case of custom encodings like
             * Identity-H) by an explicit ToUnicode CMap.
             * CID -> GID mapping is typically identity, that is CIDS correspond to GIDS, so we don't bother
             * about that. Our base encoding is Identity-H, that is character codes correspond to CIDs;
             * however, sometimes a font maps multiple Unicode codepoints to the same GID (for example, the
             * hyphen glyph may be associated to the hyphen (\u2010) and minus (\u002D) symbols), breaking
             * the possibility to recover their original Unicode values once represented as character codes
             * in content stream strings. In this case, we are forced to remap the exceeding codes and
             * generate an explicit CMap (TODO: I tried to emit a differential CMap using the usecmap
             * operator in order to import Identity-H as base encoding, but it failed in several engines
             * (including Acrobat, Ghostscript, Poppler, whilst it surprisingly worked with pdf.js), so we
             * have temporarily to stick with full CMaps).
             */

            // Encoding [PDF:1.7:5.6.1,5.6.4].
            PdfDirectObject encodingObject = PdfName.IdentityH;
            SortedDictionary <ByteArray, int> sortedCodes;

            {
                codes = new BiDictionary <ByteArray, int>(glyphIndexes.Count);
                int         lastRemappedCharCodeValue = 0;
                IList <int> removedGlyphIndexKeys     = null;
                foreach (KeyValuePair <int, int> glyphIndexEntry in glyphIndexes.ToList())
                {
                    int       glyphIndex = glyphIndexEntry.Value;
                    ByteArray charCode   = new ByteArray(new byte[]
                    {
                        (byte)((glyphIndex >> 8) & 0xFF),
                        (byte)(glyphIndex & 0xFF)
                    });

                    // Checking for multiple Unicode codepoints which map to the same glyph index...

                    /*
                     * NOTE: In case the same glyph index maps to multiple Unicode codepoints, we are forced to
                     * alter the identity encoding creating distinct cmap entries for the exceeding codepoints.
                     */
                    if (codes.ContainsKey(charCode))
                    {
                        if (glyphIndex == 0) // .notdef glyph already mapped.
                        {
                            if (removedGlyphIndexKeys == null)
                            {
                                removedGlyphIndexKeys = new List <int>();
                            }
                            removedGlyphIndexKeys.Add(glyphIndexEntry.Key);
                            continue;
                        }

                        // Assigning the new character code...

                        /*
                         * NOTE: As our base encoding is identity, we have to look for a value that doesn't
                         * collide with existing glyph indices.
                         */
                        while (glyphIndexes.ContainsValue(++lastRemappedCharCodeValue))
                        {
                            ;
                        }
                        charCode.Data[0] = (byte)((lastRemappedCharCodeValue >> 8) & 0xFF);
                        charCode.Data[1] = (byte)(lastRemappedCharCodeValue & 0xFF);
                    }
                    else if (glyphIndex == 0) // .notdef glyph.
                    {
                        DefaultCode = glyphIndexEntry.Key;
                    }

                    codes[charCode] = glyphIndexEntry.Key;
                }
                if (removedGlyphIndexKeys != null)
                {
                    foreach (int removedGlyphIndexKey in removedGlyphIndexKeys)
                    {
                        glyphIndexes.Remove(removedGlyphIndexKey);
                    }
                }
                sortedCodes = new SortedDictionary <ByteArray, int>(codes);
                if (lastRemappedCharCodeValue > 0) // Custom encoding.
                {
                    string         cmapName   = "Custom";
                    bytes::IBuffer cmapBuffer = CMapBuilder.Build(
                        CMapBuilder.EntryTypeEnum.CID,
                        cmapName,
                        sortedCodes,
                        delegate(KeyValuePair <ByteArray, int> codeEntry)
                        { return(glyphIndexes[codeEntry.Value]); }
                        );
                    encodingObject = File.Register(
                        new PdfStream(
                            new PdfDictionary(
                                new PdfName[]
                    {
                        PdfName.Type,
                        PdfName.CMapName,
                        PdfName.CIDSystemInfo
                    },
                                new PdfDirectObject[]
                    {
                        PdfName.CMap,
                        new PdfName(cmapName),
                        new PdfDictionary(
                            new PdfName[]
                        {
                            PdfName.Registry,
                            PdfName.Ordering,
                            PdfName.Supplement
                        },
                            new PdfDirectObject[]
                        {
                            PdfTextString.Get("Adobe"),
                            PdfTextString.Get("Identity"),
                            PdfInteger.Get(0)
                        }
                            )
                    }
                                ),
                            cmapBuffer
                            )
                        );
                }
            }
            font[PdfName.Encoding]       = encodingObject;   // Character-code-to-CID mapping.
            cidFont[PdfName.CIDToGIDMap] = PdfName.Identity; // CID-to-glyph-index mapping.

            // ToUnicode [PDF:1.6:5.9.2].
            PdfDirectObject toUnicodeObject = null;

            {
                bytes::IBuffer toUnicodeBuffer = CMapBuilder.Build(
                    CMapBuilder.EntryTypeEnum.BaseFont,
                    null,
                    sortedCodes,
                    delegate(KeyValuePair <ByteArray, int> codeEntry)
                    { return(codeEntry.Value); }
                    );
                toUnicodeObject = File.Register(new PdfStream(toUnicodeBuffer));
            }
            font[PdfName.ToUnicode] = toUnicodeObject; // Character-code-to-Unicode mapping.

            // Glyph widths.
            PdfArray widthsObject = new PdfArray();

            {
                int      lastGlyphIndex            = -10;
                PdfArray lastGlyphWidthRangeObject = null;
                foreach (int glyphIndex in glyphIndexes.Values.OrderBy(x => x).ToList())
                {
                    int width;
                    if (!glyphWidths.TryGetValue(glyphIndex, out width))
                    {
                        width = 0;
                    }
                    if (glyphIndex - lastGlyphIndex != 1)
                    {
                        widthsObject.Add(PdfInteger.Get(glyphIndex));
                        widthsObject.Add(lastGlyphWidthRangeObject = new PdfArray());
                    }
                    lastGlyphWidthRangeObject.Add(PdfInteger.Get(width));
                    lastGlyphIndex = glyphIndex;
                }
            }
            cidFont[PdfName.W] = widthsObject; // Glyph widths.
        }
Beispiel #7
0
        public PdfObject ParseObject(List <PdfObject> knownObjects)
        {
            PdfObject obj           = null;
            long      startPosition = _streamPosition;

            do
            {
                SkipWhitespace();
                byte character = PeekChar();

                if (character == '%')
                {
                    SkipComment();
                }
                else if (IsDigit(character))
                {
                    IPdfElement objectID = ParseNumber();
                    SkipWhitespace();
                    IPdfElement objectGeneration = ParseNumber();
                    SkipWhitespace();
                    string token = ParseToken();
                    if (token == "obj")
                    {
                        SkipWhitespace();
                        IPdfElement element  = ParseElement();
                        string      endToken = ParseToken();

                        // Intercept streams
                        if (endToken == "stream")
                        {
                            PdfDictionary streamDict = element as PdfDictionary;
                            if (streamDict == null)
                            {
                                throw new Exception(string.Format("Stream after a not dictionary element at: {0}", _streamPosition));
                            }
                            SkipEndOfLine();

                            // Find the length of the stream
                            long length = -1;
                            if (streamDict.Values.ContainsKey("Length"))
                            {
                                length = PdfElementUtils.GetInt(streamDict.Values["Length"], -1);
                                if (length == -1 && streamDict.Values["Length"] is PdfObjectReference)
                                {
                                    IPdfElement lenghtObj = SearchObjectID(knownObjects, ((PdfObjectReference)streamDict.Values["Length"]).ObjectID);
                                    length = PdfElementUtils.GetInt(lenghtObj, -1);
                                }
                            }
                            if (length == -1)
                            {
                                byte lineFeed       = 0x0A;
                                byte carriageReturn = 0x0D;
                                length = MeasureToMarkers(new char[][] {
                                    new char[] { (char)carriageReturn, (char)lineFeed, 'e', 'n', 'd', 's', 't', 'r', 'e', 'a', 'm' },
                                    new char[] { (char)lineFeed, 'e', 'n', 'd', 's', 't', 'r', 'e', 'a', 'm' },
                                    new char[] { 'e', 'n', 'd', 's', 't', 'r', 'e', 'a', 'm', (char)lineFeed },
                                    new char[] { 'e', 'n', 'd', 's', 't', 'r', 'e', 'a', 'm', (char)carriageReturn, (char)lineFeed },
                                });
                            }

                            // Get the stream
                            byte[] streamBody = GetRawData(length);
                            SkipEndOfLine();
                            endToken = ParseToken();
                            if (endToken != "endstream")
                            {
                                throw new Exception(string.Format("Expected \"endstream\" token, \"{0}\" found at: {1}", token, _streamPosition));
                            }
                            SkipWhitespace();
                            endToken = ParseToken();
                            PdfStream stream = new PdfStream();
                            stream.Dictionary = streamDict;
                            stream.Data       = streamBody;
                            element           = stream;
                        }

                        if (endToken == "endobj")
                        {
                            obj                  = new PdfObject();
                            obj.ObjectID         = (int)((PdfInteger)objectID).Value;
                            obj.ObjectGeneration = (int)((PdfInteger)objectGeneration).Value;
                            obj.Data             = element;
                            break;
                        }
                    }
                }
                else
                {
                    long   streamPosition = _streamPosition;
                    string token          = ParseToken();
                    if (token == "startxref")
                    {
                        // TODO: PdfParser: Ignoring startxref for now
                        SkipEndOfLine();
                        SkipToEndOfLine();
                        SkipEndOfLine();
                        SkipToEndOfLine();
                        SkipEndOfLine();
                        SkipWhitespace();
                        continue;
                    }
                    if (token == "xref")
                    {
                        // TODO: PdfParser: Ignoring xref for now
                        SkipToEndOfLine();
                        SkipEndOfLine();
                        do
                        {
                            SkipWhitespace();
                            IPdfElement objNumber = ParseNumber();
                            SkipWhitespace();
                            objNumber = ParseNumber();
                            SkipEndOfLine();
                            PdfInteger refNumber = objNumber as PdfInteger;
                            for (int i = 0; i < refNumber.Value; i++)
                            {
                                SkipToEndOfLine();
                                SkipEndOfLine();
                            }
                            long        currentPosition = _streamPosition;
                            IPdfElement testElem        = ParseElement();
                            _streamPosition = currentPosition;
                            if ((testElem is PdfInteger) == false)
                            {
                                break;
                            }
                        } while (IsEndOfStream() == false);
                        continue;
                    }
                    if (token == "trailer")
                    {
                        // TODO: PdfParser: Ignoring trailer for now
                        SkipEndOfLine();
                        ParseElement();
                        SkipWhitespace();

                        SkipToEndOfLine();
                        SkipEndOfLine();
                        SkipToEndOfLine();
                        SkipEndOfLine();
                        SkipToEndOfLine();
                        SkipEndOfLine();
                        SkipWhitespace();
                        continue;
                    }

                    // Try to find an object marker
                    byte lineFeed       = 0x0A;
                    byte carriageReturn = 0x0D;
                    long distToObject   = MeasureToMarkers(new char[][] {
                        new char[] { ' ', 'o', 'b', 'j', (char)lineFeed },
                        new char[] { ' ', 'o', 'b', 'j', (char)carriageReturn, (char)lineFeed },
                    });
                    if (distToObject > 0)
                    {
                        // Object marker found, backtrack and retry
                        long originalPosition = _streamPosition;
                        _streamPosition += distToObject;
                        long marker = _streamPosition;
                        SkipWhitespaceBack();
                        if (_streamPosition == marker)
                        {
                            // Abort backtrack, skip garbage
                            _streamPosition = originalPosition + distToObject + 4;
                            continue;
                        }
                        marker = _streamPosition;
                        SkipDigitsBack();
                        if (_streamPosition == marker)
                        {
                            // Abort backtrack, skip garbage
                            _streamPosition = originalPosition + distToObject + 4;
                            continue;
                        }
                        marker = _streamPosition;
                        SkipWhitespaceBack();
                        if (_streamPosition == marker)
                        {
                            // Abort backtrack, skip garbage
                            _streamPosition = originalPosition + distToObject + 4;
                            continue;
                        }
                        marker = _streamPosition;
                        SkipDigitsBack();
                        if (_streamPosition == marker)
                        {
                            // Abort backtrack, skip garbage
                            _streamPosition = originalPosition + distToObject + 4;
                            continue;
                        }
                        NextChar();
                    }
                    else
                    {
                        // No more obj markers found, abort all.
                        _streamPosition = _stream.Length;
                    }
                }
            } while (IsEndOfStream() == false);
            return(obj);
        }
Beispiel #8
0
 public SetLineCap(LineCapEnum value)
     : base(OperatorKeyword, PdfInteger.Get((int)value))
 {
 }
Beispiel #9
0
        /**
         * <summary>Ends the content row.</summary>
         * <param name="broken">Indicates whether this is the end of a paragraph.</param>
         */
        private void EndRow(
            bool broken
            )
        {
            if (rowEnded)
            {
                return;
            }

            rowEnded = true;

            List <RowObject> objects = currentRow.Objects;

            double[] objectXOffsets = new double[objects.Count]; // Horizontal object displacements.
            double   wordSpace      = 0;                         // Exceeding space among words.
            double   rowXOffset     = 0;                         // Horizontal row offset.

            // Horizontal alignment.
            XAlignmentEnum xAlignment = this.xAlignment;

            switch (xAlignment)
            {
            case XAlignmentEnum.Left:
                break;

            case XAlignmentEnum.Right:
                rowXOffset = frame.Width - currentRow.Width;
                break;

            case XAlignmentEnum.Center:
                rowXOffset = (frame.Width - currentRow.Width) / 2;
                break;

            case XAlignmentEnum.Justify:
                if (currentRow.SpaceCount == 0 ||
                    broken) // NO spaces.
                {
                    /* NOTE: This situation equals a simple left alignment. */
                    xAlignment = XAlignmentEnum.Left;
                }
                else // Spaces exist.
                {
                    // Calculate the exceeding spacing among the words!
                    wordSpace = (frame.Width - currentRow.Width) / currentRow.SpaceCount;

                    // Define the horizontal offsets for justified alignment.
                    for (
                        int index = 1,
                        count = objects.Count;
                        index < count;
                        index++
                        )
                    {
                        /*
                         * NOTE: The offset represents the horizontal justification gap inserted at the left
                         * side of each object.
                         */
                        objectXOffsets[index] = objectXOffsets[index - 1] + objects[index - 1].SpaceCount * wordSpace;
                    }
                }
                currentRow.WordSpaceAdjustment.Value = wordSpace;
                break;
            }

            // Vertical alignment and translation.
            for (
                int index = objects.Count - 1;
                index >= 0;
                index--
                )
            {
                RowObject obj = objects[index];

                // Vertical alignment.
                double objectYOffset = 0;
                {
                    LineAlignmentEnum lineAlignment;
                    double            lineRise;
                    {
                        object objectLineAlignment = obj.LineAlignment;
                        if (objectLineAlignment is Double)
                        {
                            lineAlignment = LineAlignmentEnum.BaseLine;
                            lineRise      = (double)objectLineAlignment;
                        }
                        else
                        {
                            lineAlignment = (LineAlignmentEnum)objectLineAlignment;
                            lineRise      = 0;
                        }
                    }
                    switch (lineAlignment)
                    {
                    case LineAlignmentEnum.Top:
                        /* NOOP */
                        break;

                    case LineAlignmentEnum.Middle:
                        objectYOffset = -(currentRow.Height - obj.Height) / 2;
                        break;

                    case LineAlignmentEnum.BaseLine:
                        objectYOffset = -(currentRow.BaseLine - obj.BaseLine - lineRise);
                        break;

                    case LineAlignmentEnum.Bottom:
                        objectYOffset = -(currentRow.Height - obj.Height);
                        break;

                    default:
                        throw new NotImplementedException("Line alignment " + lineAlignment + " unknown.");
                    }
                }

                IList <ContentObject> containedGraphics = obj.Container.Objects;
                // Translation.
                containedGraphics.Insert(
                    0,
                    new ModifyCTM(
                        1, 0, 0, 1,
                        objectXOffsets[index] + rowXOffset, // Horizontal alignment.
                        objectYOffset                       // Vertical alignment.
                        )
                    );
                // Word spacing.
                if (obj.Type == RowObject.TypeEnum.Text)
                {
                    /*
                     * TODO: This temporary hack adjusts the word spacing in case of composite font.
                     * When DocumentComposer replaces BlockComposer, all the graphical properties of contents
                     * will be declared as styles and their composition will occur as a single pass without such
                     * ugly tweakings.
                     */
                    ShowText showTextOperation = (ShowText)((Text)((LocalGraphicsState)containedGraphics[1]).Objects[1]).Objects[1];
                    if (showTextOperation is ShowAdjustedText)
                    {
                        PdfInteger wordSpaceObject = PdfInteger.Get((int)Math.Round(-wordSpace * 1000 * obj.Scale / obj.FontSize));
                        PdfArray   textParams      = (PdfArray)showTextOperation.Operands[0];
                        for (int textParamIndex = 1, textParamsLength = textParams.Count; textParamIndex < textParamsLength; textParamIndex += 2)
                        {
                            textParams[textParamIndex] = wordSpaceObject;
                        }
                    }
                }
            }

            // Update the actual block height!
            boundBox.Height = (float)(currentRow.Y + currentRow.Height);

            // Update the actual block vertical location!
            double yOffset;

            switch (yAlignment)
            {
            case YAlignmentEnum.Bottom:
                yOffset = frame.Height - boundBox.Height;
                break;

            case YAlignmentEnum.Middle:
                yOffset = (frame.Height - boundBox.Height) / 2;
                break;

            case YAlignmentEnum.Top:
            default:
                yOffset = 0;
                break;
            }
            boundBox.Y = (float)(frame.Y + yOffset);

            // Discard the current row!
            currentRow = null;
        }
        private PdfArray GetVerticalMetrics(int[] values)
        {
            if (values.Length == 0)
            {
                throw new ArgumentException("length of values must be > 0");
            }

            float scaling = 1000f / ttf.Header.UnitsPerEm;

            long lastCid     = values[0];
            long lastW1Value = (long)Math.Round(-values[1] * scaling);
            long lastVxValue = (long)Math.Round(values[2] * scaling / 2f);
            long lastVyValue = (long)Math.Round(values[3] * scaling);

            PdfArray inner = new PdfArray();
            PdfArray outer = new PdfArray();

            outer.Add(PdfInteger.Get(lastCid));

            State state = State.FIRST;

            for (int i = 4; i < values.Length; i += 4)
            {
                long cid = values[i];
                if (cid == int.MinValue)
                {
                    // no glyph for this cid
                    continue;
                }
                long w1Value = (long)Math.Round(-values[i + 1] * scaling);
                long vxValue = (long)Math.Round(values[i + 2] * scaling / 2);
                long vyValue = (long)Math.Round(values[i + 3] * scaling);

                switch (state)
                {
                case State.FIRST:
                    if (cid == lastCid + 1 && w1Value == lastW1Value && vxValue == lastVxValue && vyValue == lastVyValue)
                    {
                        state = State.SERIAL;
                    }
                    else if (cid == lastCid + 1)
                    {
                        state = State.BRACKET;
                        inner = new PdfArray();
                        inner.Add(PdfInteger.Get(lastW1Value));
                        inner.Add(PdfInteger.Get(lastVxValue));
                        inner.Add(PdfInteger.Get(lastVyValue));
                    }
                    else
                    {
                        inner = new PdfArray();
                        inner.Add(PdfInteger.Get(lastW1Value));
                        inner.Add(PdfInteger.Get(lastVxValue));
                        inner.Add(PdfInteger.Get(lastVyValue));
                        outer.Add(inner);
                        outer.Add(PdfInteger.Get(cid));
                    }
                    break;

                case State.BRACKET:
                    if (cid == lastCid + 1 && w1Value == lastW1Value && vxValue == lastVxValue && vyValue == lastVyValue)
                    {
                        state = State.SERIAL;
                        outer.Add(inner);
                        outer.Add(PdfInteger.Get(lastCid));
                    }
                    else if (cid == lastCid + 1)
                    {
                        inner.Add(PdfInteger.Get(lastW1Value));
                        inner.Add(PdfInteger.Get(lastVxValue));
                        inner.Add(PdfInteger.Get(lastVyValue));
                    }
                    else
                    {
                        state = State.FIRST;
                        inner.Add(PdfInteger.Get(lastW1Value));
                        inner.Add(PdfInteger.Get(lastVxValue));
                        inner.Add(PdfInteger.Get(lastVyValue));
                        outer.Add(inner);
                        outer.Add(PdfInteger.Get(cid));
                    }
                    break;

                case State.SERIAL:
                    if (cid != lastCid + 1 || w1Value != lastW1Value || vxValue != lastVxValue || vyValue != lastVyValue)
                    {
                        outer.Add(PdfInteger.Get(lastCid));
                        outer.Add(PdfInteger.Get(lastW1Value));
                        outer.Add(PdfInteger.Get(lastVxValue));
                        outer.Add(PdfInteger.Get(lastVyValue));
                        outer.Add(PdfInteger.Get(cid));
                        state = State.FIRST;
                    }
                    break;
                }
                lastW1Value = w1Value;
                lastVxValue = vxValue;
                lastVyValue = vyValue;
                lastCid     = cid;
            }

            switch (state)
            {
            case State.FIRST:
                inner = new PdfArray();
                inner.Add(PdfInteger.Get(lastW1Value));
                inner.Add(PdfInteger.Get(lastVxValue));
                inner.Add(PdfInteger.Get(lastVyValue));
                outer.Add(inner);
                break;

            case State.BRACKET:
                inner.Add(PdfInteger.Get(lastW1Value));
                inner.Add(PdfInteger.Get(lastVxValue));
                inner.Add(PdfInteger.Get(lastVyValue));
                outer.Add(inner);
                break;

            case State.SERIAL:
                outer.Add(PdfInteger.Get(lastCid));
                outer.Add(PdfInteger.Get(lastW1Value));
                outer.Add(PdfInteger.Get(lastVxValue));
                outer.Add(PdfInteger.Get(lastVyValue));
                break;
            }
            return(outer);
        }
        private PdfArray GetWidths(int[] widths)
        {
            if (widths.Length == 0)
            {
                throw new ArgumentException("length of widths must be > 0");
            }

            float scaling = 1000f / ttf.Header.UnitsPerEm;

            long lastCid   = widths[0];
            long lastValue = (long)Math.Round(widths[1] * scaling);

            PdfArray inner = new PdfArray();
            PdfArray outer = new PdfArray();

            outer.Add(PdfInteger.Get(lastCid));

            State state = State.FIRST;

            for (int i = 2; i < widths.Length; i += 2)
            {
                long cid   = widths[i];
                long value = (long)Math.Round(widths[i + 1] * scaling);

                switch (state)
                {
                case State.FIRST:
                    if (cid == lastCid + 1 && value == lastValue)
                    {
                        state = State.SERIAL;
                    }
                    else if (cid == lastCid + 1)
                    {
                        state = State.BRACKET;
                        inner = new PdfArray();
                        inner.Add(PdfInteger.Get(lastValue));
                    }
                    else
                    {
                        inner = new PdfArray();
                        inner.Add(PdfInteger.Get(lastValue));
                        outer.Add(inner);
                        outer.Add(PdfInteger.Get(cid));
                    }
                    break;

                case State.BRACKET:
                    if (cid == lastCid + 1 && value == lastValue)
                    {
                        state = State.SERIAL;
                        outer.Add(inner);
                        outer.Add(PdfInteger.Get(lastCid));
                    }
                    else if (cid == lastCid + 1)
                    {
                        inner.Add(PdfInteger.Get(lastValue));
                    }
                    else
                    {
                        state = State.FIRST;
                        inner.Add(PdfInteger.Get(lastValue));
                        outer.Add(inner);
                        outer.Add(PdfInteger.Get(cid));
                    }
                    break;

                case State.SERIAL:
                    if (cid != lastCid + 1 || value != lastValue)
                    {
                        outer.Add(PdfInteger.Get(lastCid));
                        outer.Add(PdfInteger.Get(lastValue));
                        outer.Add(PdfInteger.Get(cid));
                        state = State.FIRST;
                    }
                    break;
                }
                lastValue = value;
                lastCid   = cid;
            }

            switch (state)
            {
            case State.FIRST:
                inner = new PdfArray();
                inner.Add(PdfInteger.Get(lastValue));
                outer.Add(inner);
                break;

            case State.BRACKET:
                inner.Add(PdfInteger.Get(lastValue));
                outer.Add(inner);
                break;

            case State.SERIAL:
                outer.Add(PdfInteger.Get(lastCid));
                outer.Add(PdfInteger.Get(lastValue));
                break;
            }
            return(outer);
        }
Beispiel #12
0
 /// <summary>
 /// Writes the specified value to the PDF stream.
 /// </summary>
 public void Write(PdfInteger value)
 {
     WriteSeparator(CharCat.Character);
     _lastCat = CharCat.Character;
     WriteRaw(value.Value.ToString(CultureInfo.InvariantCulture));
 }
        protected override void WriteIncremental()
        {
            // 1. Original content (header, body and previous trailer).
            FileParser parser = file.Reader.Parser;

            stream.Write(parser.Stream);

            // 2. Body update (modified indirect objects insertion).
            XRefEntry xrefStreamEntry;

            {
                // Create the xref stream!

                /*
                 * NOTE: Incremental xref information structure comprises multiple sections; this update adds
                 * a new section.
                 */
                XRefStream xrefStream = new XRefStream(file);

                // 2.1. Indirect objects.
                IndirectObjects indirectObjects = file.IndirectObjects;

                // 2.1.1. Modified indirect objects serialization.
                XRefEntry prevFreeEntry = null;

                /*
                 * NOTE: Any uncompressed indirect object will be compressed.
                 */
                ObjectStream objectStream = null;

                /*
                 * NOTE: Any previously-compressed indirect object will have its original object stream
                 * updated through a new extension object stream.
                 */
                IDictionary <int, ObjectStream> extensionObjectStreams = new Dictionary <int, ObjectStream>();
                int indirectObjectsPrecompressCount = indirectObjects.Count;
                foreach (PdfIndirectObject indirectObject in new List <PdfIndirectObject>(indirectObjects.ModifiedObjects.Values))
                {
                    if (indirectObject.IsCompressible())
                    {
                        if (objectStream == null ||
                            objectStream.Count >= ObjectStreamMaxEntryCount)
                        {
                            file.Register(objectStream = new ObjectStream());
                        }

                        indirectObject.Compress(objectStream);
                    }

                    prevFreeEntry = AddXRefEntry(
                        indirectObject,
                        xrefStream,
                        prevFreeEntry,
                        extensionObjectStreams
                        );
                }
                // 2.1.2. Additional object streams serialization.
                for (int index = indirectObjectsPrecompressCount, limit = indirectObjects.Count; index < limit; index++)
                {
                    prevFreeEntry = AddXRefEntry(
                        indirectObjects[index],
                        xrefStream,
                        prevFreeEntry,
                        null
                        );
                }
                if (prevFreeEntry != null)
                {
                    prevFreeEntry.Offset = 0; // Links back to the first free object. NOTE: The first entry in the table (object number 0) is always free.
                }

                // 2.2. XRef stream.
                UpdateTrailer(xrefStream.Header, stream);
                xrefStream.Header[PdfName.Prev] = PdfInteger.Get((int)parser.RetrieveXRefOffset());
                AddXRefEntry(

                    /*
                     * NOTE: This xref stream indirect object is purposely temporary (i.e. not registered into
                     * the file's indirect objects collection).
                     */
                    new PdfIndirectObject(
                        file,
                        xrefStream,
                        xrefStreamEntry = new XRefEntry(indirectObjects.Count, 0, (int)stream.Length, XRefEntry.UsageEnum.InUse)
                        ),
                    xrefStream,
                    null,
                    null
                    );
            }

            // 3. Tail.
            WriteTail(xrefStreamEntry.Offset);
        }
        /**
         * <summary>Creates the character code mapping for composite fonts.</summary>
         */
        private void Load_CreateEncoding(
            PdfDictionary font,
            PdfDictionary cidFont
            )
        {
            // CMap [PDF:1.6:5.6.4].
            bytes::Buffer cmapBuffer = new bytes::Buffer();

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

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

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

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

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

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

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

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

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

            PdfStream gIdStream = new PdfStream(gIdBuffer);

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

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

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

            font[PdfName.ToUnicode] = File.Register(toUnicodeStream);
        }
Beispiel #15
0
        /**
         * <summary>Retrieves the file information.</summary>
         */
        public FileInfo ReadInfo()
        {
            //TODO:hybrid xref table/stream
            Version       version = Version.Get(parser.RetrieveVersion());
            PdfDictionary trailer = null;
            SortedDictionary <int, XRefEntry> xrefEntries = new SortedDictionary <int, XRefEntry>();

            {
                long sectionOffset = parser.RetrieveXRefOffset();
                while (sectionOffset > -1)
                {
                    // Move to the start of the xref section!
                    parser.Seek(sectionOffset);

                    PdfDictionary sectionTrailer;
                    if (parser.GetToken(1).Equals(Keyword.XRef)) // XRef-table section.
                    {
                        // Looping sequentially across the subsections inside the current xref-table section...
                        while (true)
                        {
                            /*
                             * NOTE: Each iteration of this block represents the scanning of one subsection.
                             * We get its bounds (first and last object numbers within its range) and then collect
                             * its entries.
                             */
                            // 1. First object number.
                            parser.MoveNext();
                            if ((parser.TokenType == PostScriptParser.TokenTypeEnum.Keyword) &&
                                parser.Token.Equals(Keyword.Trailer))    // XRef-table section ended.
                            {
                                break;
                            }
                            else if (parser.TokenType != PostScriptParser.TokenTypeEnum.Integer)
                            {
                                throw new PostScriptParseException("Neither object number of the first object in this xref subsection nor end of xref section found.", parser);
                            }

                            // Get the object number of the first object in this xref-table subsection!
                            int startObjectNumber = (int)parser.Token;

                            // 2. Last object number.
                            parser.MoveNext();
                            if (parser.TokenType != PostScriptParser.TokenTypeEnum.Integer)
                            {
                                throw new PostScriptParseException("Number of entries in this xref subsection not found.", parser);
                            }

                            // Get the object number of the last object in this xref-table subsection!
                            int endObjectNumber = (int)parser.Token + startObjectNumber;

                            // 3. XRef-table subsection entries.
                            for (int index = startObjectNumber; index < endObjectNumber; index++)
                            {
                                if (xrefEntries.ContainsKey(index)) // Already-defined entry.
                                {
                                    // Skip to the next entry!
                                    parser.MoveNext(3);
                                    continue;
                                }

                                // Get the indirect object offset!
                                int offset = (int)parser.GetToken(1);
                                // Get the object generation number!
                                int generation = (int)parser.GetToken(1);
                                // Get the usage tag!
                                XRefEntry.UsageEnum usage;
                                {
                                    string usageToken = (string)parser.GetToken(1);
                                    if (usageToken.Equals(Keyword.InUseXrefEntry, StringComparison.Ordinal))
                                    {
                                        usage = XRefEntry.UsageEnum.InUse;
                                    }
                                    else if (usageToken.Equals(Keyword.FreeXrefEntry, StringComparison.Ordinal))
                                    {
                                        usage = XRefEntry.UsageEnum.Free;
                                    }
                                    else
                                    {
                                        throw new PostScriptParseException("Invalid xref entry.", parser);
                                    }
                                }

                                // Define entry!
                                xrefEntries[index] = new XRefEntry(
                                    index,
                                    generation,
                                    offset,
                                    usage
                                    );
                            }
                        }

                        // Get the previous trailer!
                        sectionTrailer = (PdfDictionary)parser.ParsePdfObject(1);
                    }
                    else // XRef-stream section.
                    {
                        XRefStream stream = (XRefStream)parser.ParsePdfObject(3); // Gets the xref stream skipping the indirect-object header.
                                                                                  // XRef-stream subsection entries.
                        foreach (XRefEntry xrefEntry in stream.Values)
                        {
                            if (xrefEntries.ContainsKey(xrefEntry.Number)) // Already-defined entry.
                            {
                                continue;
                            }

                            // Define entry!
                            xrefEntries[xrefEntry.Number] = xrefEntry;
                        }

                        // Get the previous trailer!
                        sectionTrailer = stream.Header;
                    }

                    if (trailer == null)
                    {
                        trailer = sectionTrailer;
                    }

                    // Get the previous xref-table section's offset!
                    PdfInteger prevXRefOffset = (PdfInteger)sectionTrailer[PdfName.Prev];
                    sectionOffset = (prevXRefOffset != null ? prevXRefOffset.IntValue : -1);
                }
            }
            return(new FileInfo(version, trailer, xrefEntries));
        }
Beispiel #16
0
 public SetTextRenderMode(
     TextRenderModeEnum value
     ) : base(OperatorKeyword, PdfInteger.Get((int)value))
 {
 }
Beispiel #17
0
 private static void HandleInteger(PdfInteger item, StringBuilder target)
 {
     target.Append(item.Value);
 }
Beispiel #18
0
        public Dictionary <char, string> ParseToUnicode()
        {
            var  toUnicode = new Dictionary <char, string>();
            long skip      = MeasureToMarkers(new char[][] {
                new char[] { 'b', 'e', 'g', 'i', 'n', 'c', 'm', 'a', 'p' },
            });

            _streamPosition = skip;
            var stack = new List <IPdfElement>();

            do
            {
                SkipWhitespace();
                IPdfElement elem = ParseElement();
                if (elem != null)
                {
                    stack.Add(elem);
                }
                else
                {
                    string token = ParseToken();
                    if (token == "begincodespacerange")
                    {
                        PdfInteger numCodespaces = stack.Last() as PdfInteger;
                        if (numCodespaces == null)
                        {
                            throw new Exception(string.Format("ParseToUnicode: \"begincodespacerange\" found without preceding count at: {0}", _streamPosition));
                        }
                        for (int i = 0; i < numCodespaces.Value; i++)
                        {
                            // Skip CodeSpaceRanges
                            SkipWhitespace();
                            PdfString strStart = ParseString();
                            SkipWhitespace();
                            PdfString strEnd = ParseString();
                        }
                        SkipWhitespace();
                        string endToken = ParseToken();
                        if (endToken != "endcodespacerange")
                        {
                            throw new Exception(string.Format("ParseToUnicode: Expected \"endcodespacerange\", found \"{0}\", at: {1}", endToken, _streamPosition));
                        }
                    }
                    else if (token == "beginbfrange")
                    {
                        PdfInteger numRanges = stack.Last() as PdfInteger;
                        if (numRanges == null)
                        {
                            throw new Exception(string.Format("ParseToUnicode: \"beginbfrange\" found without preceding count at: {0}", _streamPosition));
                        }
                        for (int i = 0; i < numRanges.Value; i++)
                        {
                            SkipWhitespace();
                            PdfString pdfStrStart = ParseString();
                            SkipWhitespace();
                            PdfString pdfStrEnd = ParseString();
                            SkipWhitespace();
                            IPdfElement pdfElemDest = ParseElement();

                            char chStart = ReencodeStringToUTF16BE(pdfStrStart.Value)[0];
                            char chEnd   = ReencodeStringToUTF16BE(pdfStrEnd.Value)[0];

                            if (chStart == chEnd && pdfElemDest is PdfString)
                            {
                                string strDst = ReencodeStringToUTF16BE(((PdfString)pdfElemDest).Value);
                                toUnicode.Add(chStart, strDst);
                                continue;
                            }
                            if (chEnd > chStart && pdfElemDest is PdfString)
                            {
                                string strDst  = ReencodeStringToUTF16BE(((PdfString)pdfElemDest).Value);
                                char[] chsDest = strDst.ToArray();
                                for (char c = chStart; c <= chEnd; c++)
                                {
                                    toUnicode.Add(c, new string(chsDest));
                                    chsDest[chsDest.Length - 1]++;
                                }
                                continue;
                            }
                            if (chEnd > chStart && pdfElemDest is PdfArray)
                            {
                                PdfArray array  = pdfElemDest as PdfArray;
                                int      length = chEnd - chStart;
                                for (int j = 0; j <= length; j++)
                                {
                                    char   c      = (char)(chStart + j);
                                    string strDst = ReencodeStringToUTF16BE(((PdfString)array.Values[j]).Value);
                                    toUnicode.Add(c, strDst);
                                }
                                continue;
                            }
                        }
                        SkipWhitespace();
                        string endToken = ParseToken();
                        if (endToken != "endbfrange")
                        {
                            throw new Exception(string.Format("ParseToUnicode: Expected \"endbfrange\", found \"{0}\", at: {1}", endToken, _streamPosition));
                        }
                    }
                    else if (token == "beginbfchar")
                    {
                        PdfInteger numChars = stack.Last() as PdfInteger;
                        if (numChars == null)
                        {
                            throw new Exception(string.Format("ParseToUnicode: \"beginbfchar\" found without preceding count at: {0}", _streamPosition));
                        }
                        for (int i = 0; i < numChars.Value; i++)
                        {
                            SkipWhitespace();
                            PdfString pdfStrOrig = ParseString();
                            SkipWhitespace();
                            PdfString pdfStrDest = ParseString();

                            char   chOrig = ReencodeStringToUTF16BE(pdfStrOrig.Value)[0];
                            string strDst = ReencodeStringToUTF16BE(((PdfString)pdfStrDest).Value);
                            toUnicode.Add(chOrig, strDst);
                        }
                        SkipWhitespace();
                        string endToken = ParseToken();
                        if (endToken != "endbfchar")
                        {
                            throw new Exception(string.Format("ParseToUnicode: Expected \"endbfchar\", found \"{0}\", at: {1}", endToken, _streamPosition));
                        }
                    }
                    else
                    {
                        // Ignore rest of tokens
                    }
                }
            } while (IsEndOfStream() == false);
            return(toUnicode);
        }
Beispiel #19
0
        /**
         * <summary>Parses the current PDF object [PDF:1.6:3.2].</summary>
         */
        public virtual PdfDataObject ParsePdfObject()
        {
            switch (TokenType)
            {
            case TokenTypeEnum.Integer:
                return(PdfInteger.Get((int)Token));

            case TokenTypeEnum.Name:
                return(new PdfName((string)Token, true));

            case TokenTypeEnum.DictionaryBegin:
            {
                PdfDictionary dictionary = new PdfDictionary();
                dictionary.Updateable = false;
                while (true)
                {
                    // Key.
                    MoveNext(); if (TokenType == TokenTypeEnum.DictionaryEnd)
                    {
                        break;
                    }
                    PdfName key = (PdfName)ParsePdfObject();
                    // Value.
                    MoveNext();
                    PdfDirectObject value = (PdfDirectObject)ParsePdfObject();
                    // Add the current entry to the dictionary!
                    if (dictionary.ContainsKey(key))
                    {
                        key = new PdfName(key.StringValue + "Dublicat");
                    }
                    dictionary[key] = value;
                }
                dictionary.Updateable = true;
                return(dictionary);
            }

            case TokenTypeEnum.ArrayBegin:
            {
                PdfArray array = new PdfArray();
                array.Updateable = false;
                while (true)
                {
                    // Value.
                    MoveNext(); if (TokenType == TokenTypeEnum.ArrayEnd)
                    {
                        break;
                    }
                    // Add the current item to the array!
                    array.Add((PdfDirectObject)ParsePdfObject());
                }
                array.Updateable = true;
                return(array);
            }

            case TokenTypeEnum.Literal:
                if (Token is DateTime)
                {
                    return(PdfDate.Get((DateTime)Token));
                }
                else
                {
                    return(new PdfTextString(Token == null ? null : Encoding.Pdf.Encode((string)Token)));
                }

            case TokenTypeEnum.Hex:
                return(new PdfTextString((string)Token, PdfString.SerializationModeEnum.Hex));

            case TokenTypeEnum.Real:
                return(PdfReal.Get((double)Token));

            case TokenTypeEnum.Boolean:
                return(PdfBoolean.Get((bool)Token));

            case TokenTypeEnum.Null:
                return(null);

            default:
                throw new PostScriptParseException(String.Format("Unknown type beginning: '{0}'", Token), this);
            }
        }
 /// <summary>
 /// Writes the specified value to the PDF stream.
 /// </summary>
 public void Write(PdfInteger value)
 {
   WriteSeparator(CharCat.Character);
   this.lastCat = CharCat.Character;
   WriteRaw(value.Value.ToString());
 }
Beispiel #21
0
 public IndexedColor(int index)
     : this(new PdfArray(new PdfDirectObject[] { PdfInteger.Get(index) }))
 {
 }
        /**
         * <summary>Creates the font descriptor.</summary>
         */
        private PdfReference Load_CreateFontDescriptor(
            OpenFontParser parser
            )
        {
            PdfDictionary fontDescriptor = new PdfDictionary();

            {
                OpenFontParser.FontMetrics metrics = parser.Metrics;

                // Type.
                fontDescriptor[PdfName.Type] = PdfName.FontDescriptor;

                // FontName.
                fontDescriptor[PdfName.FontName] = BaseDataObject[PdfName.BaseFont];

                // Flags [PDF:1.6:5.7.1].
                FlagsEnum flags = 0;
                if (metrics.IsFixedPitch)
                {
                    flags |= FlagsEnum.FixedPitch;
                }
                if (metrics.IsCustomEncoding)
                {
                    flags |= FlagsEnum.Symbolic;
                }
                else
                {
                    flags |= FlagsEnum.Nonsymbolic;
                }
                fontDescriptor[PdfName.Flags] = PdfInteger.Get(Convert.ToInt32(flags));

                // FontBBox.
                fontDescriptor[PdfName.FontBBox] = new Rectangle(
                    new drawing::PointF(metrics.XMin * metrics.UnitNorm, metrics.YMin * metrics.UnitNorm),
                    new drawing::PointF(metrics.XMax * metrics.UnitNorm, metrics.YMax * metrics.UnitNorm)
                    ).BaseDataObject;

                // ItalicAngle.
                fontDescriptor[PdfName.ItalicAngle] = PdfReal.Get(metrics.ItalicAngle);

                // Ascent.
                fontDescriptor[PdfName.Ascent] = PdfReal.Get(
                    metrics.STypoAscender == 0
            ? metrics.Ascender * metrics.UnitNorm
            : (metrics.STypoLineGap == 0 ? metrics.SCapHeight : metrics.STypoAscender) * metrics.UnitNorm
                    );

                // Descent.
                fontDescriptor[PdfName.Descent] = PdfReal.Get(
                    metrics.STypoDescender == 0
            ? metrics.Descender * metrics.UnitNorm
            : metrics.STypoDescender * metrics.UnitNorm
                    );

                // CapHeight.
                fontDescriptor[PdfName.CapHeight] = PdfReal.Get(metrics.SCapHeight * metrics.UnitNorm);

                // StemV.

                /*
                 * NOTE: '100' is just a rule-of-thumb value, 'cause I've still to solve the
                 * 'cvt' table puzzle (such a harsh headache!) for TrueType fonts...
                 * TODO:IMPL TrueType and CFF stemv real value to extract!!!
                 */
                fontDescriptor[PdfName.StemV] = PdfInteger.Get(100);

                // FontFile.
                fontDescriptor[PdfName.FontFile2] = File.Register(
                    new PdfStream(new bytes::Buffer(parser.FontData.ToByteArray()))
                    );
            }
            return(File.Register(fontDescriptor));
        }
        public static MonitorSpecifierEnum? Get(
      PdfInteger code
      )
        {
            if(code == null)
            return MonitorSpecifierEnum.LargestDocumentWindowSection;

              MonitorSpecifierEnum? monitorSpecifier = codes.GetKey(code);
              if(!monitorSpecifier.HasValue)
            throw new NotSupportedException("Monitor specifier unknown: " + code);

              return monitorSpecifier;
        }
Beispiel #24
0
        /// <summary>
        /// Prepares the security handler for encrypting the document.
        /// </summary>
        public void PrepareEncryption()
        {
            //#if !SILVERLIGHT
            Debug.Assert(_document._securitySettings.DocumentSecurityLevel != PdfDocumentSecurityLevel.None);
            int  permissions      = (int)Permission;
            bool strongEncryption = _document._securitySettings.DocumentSecurityLevel == PdfDocumentSecurityLevel.Encrypted128Bit;

            PdfInteger vValue;
            PdfInteger length;
            PdfInteger rValue;

            if (strongEncryption)
            {
                vValue = new PdfInteger(2);
                length = new PdfInteger(128);
                rValue = new PdfInteger(3);
            }
            else
            {
                vValue = new PdfInteger(1);
                length = new PdfInteger(40);
                rValue = new PdfInteger(2);
            }

            if (String.IsNullOrEmpty(_userPassword))
            {
                _userPassword = "";
            }
            // Use user password twice if no owner password provided.
            if (String.IsNullOrEmpty(_ownerPassword))
            {
                _ownerPassword = _userPassword;
            }

            // Correct permission bits
            permissions |= (int)(strongEncryption ? (uint)0xfffff0c0 : (uint)0xffffffc0);
            permissions &= unchecked ((int)0xfffffffc);

            PdfInteger pValue = new PdfInteger(permissions);

            Debug.Assert(_ownerPassword.Length > 0, "Empty owner password.");
            byte[] userPad  = PadPassword(_userPassword);
            byte[] ownerPad = PadPassword(_ownerPassword);

            _md5.Initialize();
            _ownerKey = ComputeOwnerKey(userPad, ownerPad, strongEncryption);
            byte[] documentID = PdfEncoders.RawEncoding.GetBytes(_document.Internals.FirstDocumentID);
            InitWithUserPassword(documentID, _userPassword, _ownerKey, permissions, strongEncryption);

            PdfString oValue = new PdfString(PdfEncoders.RawEncoding.GetString(_ownerKey, 0, _ownerKey.Length));
            PdfString uValue = new PdfString(PdfEncoders.RawEncoding.GetString(_userKey, 0, _userKey.Length));

            Elements[Keys.Filter] = new PdfName("/Standard");
            Elements[Keys.V]      = vValue;
            Elements[Keys.Length] = length;
            Elements[Keys.R]      = rValue;
            Elements[Keys.O]      = oValue;
            Elements[Keys.U]      = uValue;
            Elements[Keys.P]      = pValue;
            //#endif
        }
Beispiel #25
0
        /**
         * Add a collection of pages at the specified position.
         * <param name="index">Addition position. To append, use value -1.</param>
         * <param name="pages">Collection of pages to add.</param>
         */
        private void CommonAddAll <TPage>(int index, ICollection <TPage> pages) where TPage : Page
        {
            PdfDirectObject parent;
            PdfDictionary   parentData;
            PdfDirectObject kids;
            PdfArray        kidsData;
            int             offset;

            // Append operation?
            if (index == -1) // Append operation.
            {
                // Get the parent tree node!
                parent     = BaseObject;
                parentData = BaseDataObject;
                // Get the parent's page collection!
                kids     = parentData[PdfName.Kids];
                kidsData = (PdfArray)PdfObject.Resolve(kids);
                offset   = 0; // Not used.
            }
            else // Insert operation.
            {
                // Get the page currently at the specified position!
                Page pivotPage = this[index];
                // Get the parent tree node!
                parent     = pivotPage.BaseDataObject[PdfName.Parent];
                parentData = (PdfDictionary)parent.Resolve();
                // Get the parent's page collection!
                kids     = parentData[PdfName.Kids];
                kidsData = (PdfArray)kids.Resolve();
                // Get the insertion's relative position within the parent's page collection!
                offset = kidsData.IndexOf(pivotPage.BaseObject);
            }

            // Adding the pages...
            foreach (Page page in pages)
            {
                // Append?
                if (index == -1) // Append.
                {
                    // Append the page to the collection!
                    kidsData.Add(page.BaseObject);
                }
                else // Insert.
                {
                    // Insert the page into the collection!
                    kidsData.Insert(offset++, page.BaseObject);
                }
                // Bind the page to the collection!
                page.BaseDataObject[PdfName.Parent] = parent;
            }

            // Incrementing the pages counters...
            do
            {
                // Get the page collection counter!
                PdfInteger countObject = (PdfInteger)parentData[PdfName.Count];
                // Increment the counter at the current level!
                parentData[PdfName.Count] = PdfInteger.Get(countObject.IntValue + pages.Count);

                // Iterate upward!
                parent     = parentData[PdfName.Parent];
                parentData = (PdfDictionary)PdfObject.Resolve(parent);
            } while (parent != null);
        }
Beispiel #26
0
 public virtual PdfObject Visit(
     PdfInteger obj,
     object data
     )
 {
     return obj;
 }
Beispiel #27
0
        public static Render.OperationEnum? Get(
            PdfInteger code
            )
        {
            if(code == null)
            return null;

              Render.OperationEnum? operation = codes.GetKey(code);
              if(!operation.HasValue)
            throw new NotSupportedException("Operation unknown: " + code);

              return operation;
        }