/// <summary> /// Adds a new page to the PDF and creates the needed PDF objects. /// </summary> public void AddPage() { currentContentStream = CreateContentStream(PDFStream.Filter.None); pageContentStreams.Add(currentContentStream); currentPageDictionary = CreateIndirectDictionary(); currentPageDictionary.Put("Type", new PDFName("Page")); currentPageDictionary.Put("Parent", pagesDictionary); currentPageDictionary.Put("Contents", currentContentStream); currentPageDictionary.Put("MediaBox", mediaBox); currentPageDictionary.Put("Resources", _commonResources); pageDictionaries.Add(currentPageDictionary); pageKidsArray.Array.Add(currentPageDictionary); }
public PDFCreator(string pdfFileName) { this.pdfFileName = pdfFileName; pageKidsArray = CreateIndirectArray(); mediaBox = new PDFArray(PDFObject.DirectObject, 0.0, 0.0, 595.2756, 841.8898); // A4 pagesDictionary = CreateIndirectDictionary(); pagesDictionary.Put("Type", new PDFName("Pages")); pagesDictionary.Put("Kids", pageKidsArray); //pagesDictionary.Put("Resources", ); // all PDF pages would inherit these resources PDFDictionary catalog = CreateIndirectDictionary(); catalog.Put("Type", new PDFName("Catalog")); catalog.Put("Pages", pagesDictionary); PDFDictionary infoDictionary = CreateIndirectDictionary(); infoDictionary.Put("Creator", new PDFString("Menu Master")); infoDictionary.Put("CreationDate", PDFString.GetDateString()); PDFString fileIdString = PDFString.CreateFileIDString(); trailerDictionary = new PDFDictionary(PDFObject.DirectObject); trailerDictionary.Put("Root", catalog); trailerDictionary.Put("ID", new PDFArray(PDFObject.DirectObject, fileIdString, fileIdString)); trailerDictionary.Put("Info", infoDictionary); _commonResources = CreateIndirectDictionary(); _commonFontResources = CreateIndirectDictionary(); _commonResources.Put("Font", _commonFontResources); // PDF must have at least one page AddPage(); }
/// <summary> /// Finishes PDF creation and writes all PDF objects to the specified file. /// This must be called as the final step when creating a PDF. /// </summary> public void Finish() { // Set actual page count pagesDictionary.Put("Count", new PDFInt(pageDictionaries.Count)); // Set actual number of objects trailerDictionary.Put("Size", new PDFInt(indirectObjects.Count + 1)); foreach (PDFFont font in _fontMapping.Values) { font.CreatePDFData(this); _commonFontResources.Put($"F{font.ResourceKeyId}", font.GetFontDictionary()); } WritePDFFile(); }
private void AddFontMetrics(PDFDictionary fontDescriptor, GlyphTypeface glyphTypeface, byte[] subsetData) { // We must parse the 'head' table of the font file to get FontBBox. using (Stream stream = new MemoryStream(subsetData)) { ReadSfntVersion(stream); int numTables = ReadInt16(stream) & 0xFFFF; ReadInt16(stream); // searchRange ReadInt16(stream); // entrySelector ReadInt16(stream); // rangeShift int headTableOffset = -1; for (int i = 0; i < numTables; i++) { int tag = ReadInt32(stream); ReadInt32(stream); // checksum int offset = ReadInt32(stream); ReadInt32(stream); // length switch (tag) { case 0x68656164: // 'head' headTableOffset = offset; break; } } if (headTableOffset == -1) { throw new IOException("Cannot find 'head' table in font"); } stream.Seek(headTableOffset + 12, SeekOrigin.Begin); int magic = ReadInt32(stream); if (magic != 0x5F0F3CF5) { throw new IOException("Invalid magic code in 'head' table"); } ReadInt16(stream); // flags int unitsPerEm = ReadInt16(stream) & 0xFFFF; stream.Seek(2 * 8, SeekOrigin.Current); // Skip creation and modification dates int left = ReadInt16(stream); int bottom = ReadInt16(stream); int right = ReadInt16(stream); int top = ReadInt16(stream); // Convert to font size 1000 left = (int)Math.Floor(1000.0 * left / unitsPerEm); bottom = (int)Math.Floor(1000.0 * bottom / unitsPerEm); right = (int)Math.Ceiling(1000.0 * right / unitsPerEm); top = (int)Math.Ceiling(1000.0 * top / unitsPerEm); PDFArray fontBBox = new PDFArray(PDFObject.DirectObject); fontBBox.Array.Add(new PDFInt(left)); fontBBox.Array.Add(new PDFInt(bottom)); fontBBox.Array.Add(new PDFInt(right)); fontBBox.Array.Add(new PDFInt(top)); fontDescriptor.Put("FontBBox", fontBBox); fontDescriptor.Put("Descent", new PDFInt(bottom)); fontDescriptor.Put("Ascent", new PDFInt((int)(1000 * glyphTypeface.Baseline))); fontDescriptor.Put("CapHeight", new PDFInt((int)(1000 * glyphTypeface.CapsHeight))); fontDescriptor.Put("StemV", new PDFInt(90)); // just a guess FontStyle style = _typeface.Style; double italicAngle = (style == FontStyles.Italic || style == FontStyles.Oblique) ? -12.0 : 0.0; // just a guess fontDescriptor.Put("ItalicAngle", new PDFReal(italicAngle)); } }