//////////////////////////////////////////////////////////////////// // Default constructor // Default page size is letter (height 11”, width 8.5”) // Page orientation is portrait // Unit of measure is points (scale factor 1.0) //////////////////////////////////////////////////////////////////// public PdfDocument() { // initialize object array ObjectArray = new List <PdfObject>(); // PDF document root object the Catalog object PdfObject Catalog = new PdfObject(this, false, "/Catalog"); // add viewer preferences Catalog.AddToDictionary("/ViewerPreferences", "<</PrintScaling/None>>"); // Parent object for all pages PagesObject = new PdfObject(this, false, "/Pages"); // add indirect reference to pages within the catalog object Catalog.AddToDictionary("/Pages", PagesObject); // create standard proc set ProcSetObject = new PdfObject(this, false); ProcSetObject.ContentsString = new StringBuilder("[/PDF/Text/ImageB/ImageC/ImageI]"); // save page default size PageSize = new SizeD(8.5 * 72.0, 11.0 * 72.0); // scale factor ScaleFactor = 1.0; // exit return; }
//////////////////////////////////////////////////////////////////// // Initial Object Array //////////////////////////////////////////////////////////////////// internal void InitialObjectArray() { // PDF document root object the Catalog object PdfObject CatalogObject = new PdfObject(this, false, "/Catalog"); // add viewer preferences CatalogObject.AddToDictionary("/ViewerPreferences", "<</PrintScaling/None>>"); // Parent object for all pages PagesObject = new PdfObject(this, false, "/Pages"); // add indirect reference to pages within the catalog object CatalogObject.AddToDictionary("/Pages", PagesObject); // reset page count PageCount = 0; // document id DocumentID = RandomByteArray(16); // exit return; }
//////////////////////////////////////////////////////////////////// // Write object to PDF file //////////////////////////////////////////////////////////////////// internal override void WriteObjectToPdfFile ( BinaryWriter PdfFile ) { // look for first and last character Int32 FirstChar; Int32 LastChar; for (FirstChar = 0; FirstChar < 256 && !ActiveChar[FirstChar]; FirstChar++) { ; } if (FirstChar == 256) { return; } for (LastChar = 255; !ActiveChar[LastChar]; LastChar--) { ; } // pdf font name StringBuilder PdfFontName = new StringBuilder("/"); // for embedded font add 6 alpha characters prefix if (EmbeddedFont) { PdfFontName.Append("PFWAAA+"); Int32 Ptr1 = 6; for (Int32 Ptr2 = ResourceCode.Length - 1; Ptr2 >= 0 && Char.IsDigit(ResourceCode[Ptr2]); Ptr2--) { PdfFontName[Ptr1--] = (Char)((Int32)ResourceCode[Ptr2] + ('A' - '0')); } } // PDF readers are not happy with space in font name PdfFontName.Append(FontFamily.Name.Replace(" ", "#20")); // font name if ((DesignFont.Style & FontStyle.Bold) != 0) { if ((DesignFont.Style & FontStyle.Italic) != 0) { PdfFontName.Append(",BoldItalic"); } else { PdfFontName.Append(",Bold"); } } else if ((DesignFont.Style & FontStyle.Italic) != 0) { PdfFontName.Append(",Italic"); } // add items to dictionary AddToDictionary("/Subtype", "/TrueType"); AddToDictionary("/BaseFont", PdfFontName.ToString()); // add first and last characters AddToDictionary("/FirstChar", FirstChar.ToString()); AddToDictionary("/LastChar", LastChar.ToString()); // create font descriptor FontDescriptor = new PdfObject(Document, false, "/FontDescriptor"); // add link to font object AddToDictionary("/FontDescriptor", FontDescriptor); // font descriptor dictionary FontDescriptor.AddToDictionary("/FontName", PdfFontName.ToString()); // must be the same as BaseFont above FontDescriptor.AddToDictionary("/Flags", ((Int32)FontFlags).ToString()); FontDescriptor.AddToDictionary("/ItalicAngle", String.Format(NFI.DecSep, "{0}", (Single)PdfItalicAngle)); FontDescriptor.AddToDictionary("/FontWeight", PdfFontWeight.ToString()); FontDescriptor.AddToDictionary("/Leading", String.Format(NFI.DecSep, "{0}", (Single)FontUnitsToPdfDic(PdfLeading))); FontDescriptor.AddToDictionary("/Ascent", String.Format(NFI.DecSep, "{0}", (Single)FontUnitsToPdfDic(PdfAscent))); FontDescriptor.AddToDictionary("/Descent", String.Format(NFI.DecSep, "{0}", (Single)FontUnitsToPdfDic(-PdfDescent))); // alphabetic (non symbolic) fonts if ((FontFlags & PdfFontFlags.Symbolic) == 0) { AddToDictionary("/Encoding", "/WinAnsiEncoding"); BoundingBox Box = FontInfo.GetGlyphMetricsApi('x'); FontDescriptor.AddToDictionary("/XHeight", String.Format(NFI.DecSep, "{0}", (Single)FontUnitsToPdfDic(Box.Rect.Top))); FontDescriptor.AddToDictionary("/AvgWidth", String.Format(NFI.DecSep, "{0}", (Single)FontUnitsToPdfDic(Box.Width))); Box = FontInfo.GetGlyphMetricsApi('M'); PdfCapHeight = Box.Rect.Top; FontDescriptor.AddToDictionary("/CapHeight", String.Format(NFI.DecSep, "{0}", (Single)FontUnitsToPdfDic(Box.Rect.Top))); FontDescriptor.AddToDictionary("/StemV", String.Format(NFI.DecSep, "{0}", (Single)StemV())); } // create width object array FontWidthArray = new PdfObject(Document, false); // add link to font object AddToDictionary("/Widths", FontWidthArray); // build bounding box and width array Double Left = Double.MaxValue; Double Bottom = Double.MaxValue; Double Right = Double.MinValue; Double Top = Double.MinValue; Double MaxWidth = Double.MinValue; FontWidthArray.ContentsString = new StringBuilder("["); Int32 EolLength = 100; for (Int32 Index = FirstChar; Index <= LastChar; Index++) { Double CharWidth; // not used if (!ActiveChar[Index]) { CharWidth = 0; } // used else { // bounding box BoundingBox GM = GlyphArray[Index]; if (GM.Rect.Left < Left) { Left = GM.Rect.Left; } if (GM.Rect.Bottom < Bottom) { Bottom = GM.Rect.Bottom; } if (GM.Rect.Right > Right) { Right = GM.Rect.Right; } if (GM.Rect.Top > Top) { Top = GM.Rect.Top; } // character advance width CharWidth = GM.Width; // max width if (CharWidth > MaxWidth) { MaxWidth = CharWidth; } } // add width to width array if (FontWidthArray.ContentsString.Length > EolLength) { FontWidthArray.ContentsString.Append('\n'); EolLength = FontWidthArray.ContentsString.Length + 100; } // add width to width array FontWidthArray.ContentsString.AppendFormat(NFI.DecSep, "{0} ", FontUnitsToPdfDic(CharWidth)); } // add to font descriptor array FontDescriptor.AddToDictionary("/MaxWidth", String.Format(NFI.DecSep, "{0}", (Single)FontUnitsToPdfDic(MaxWidth))); FontDescriptor.AddToDictionary("/FontBBox", String.Format(NFI.DecSep, "[{0} {1} {2} {3}]", FontUnitsToPdfDic(Left), FontUnitsToPdfDic(Bottom), FontUnitsToPdfDic(Right), FontUnitsToPdfDic(Top))); // terminate width array FontWidthArray.ContentsString.Length--; FontWidthArray.ContentsString.Append("]"); // create font file if (EmbeddedFont) { // create font file stream PdfFontFile EmbeddedFontObj = new PdfFontFile(this); // add link to font object FontDescriptor.AddToDictionary("/FontFile2", EmbeddedFontObj); } // call base write PdfObject to file method base.WriteObjectToPdfFile(PdfFile); // exit return; }
//////////////////////////////////////////////////////////////////// // Constructor for web link // NOTE: // The four position arguments are in relation to the // bottom left corner of the paper //////////////////////////////////////////////////////////////////// public void AddWebLink ( Double LeftPos, Double BottomPos, Double RightPos, Double TopPos, String WebLink ) { // if web link is empty, ignore this call if (String.IsNullOrWhiteSpace(WebLink)) { return; } // search list Int32 ObjNo; StrObject StrObj = new StrObject(WebLink); Int32 Index = Document.StrObjects.BinarySearch(StrObj); // this string is a duplicate if (Index >= 0) { // get object number ObjNo = Document.StrObjects[Index].ObjNo; } // new string else { // copy text to temp string builder StringBuilder PdfText = new StringBuilder("("); // scan string foreach (Char TestChar in WebLink) { // validate character if (TestChar < ' ' || TestChar > '~' && TestChar < 161 || TestChar > 255) { throw new ApplicationException("Web link invalid character"); } if (TestChar == '\\' || TestChar == '(' || TestChar == ')') { PdfText.Append('\\'); } PdfText.Append(TestChar); } PdfText.Append(')'); // create indirect string object for web link PdfObject WebLinkObject = new PdfIndirectString(Document, PdfText); // get object number ObjNo = WebLinkObject.ObjectNumber; // save new string StrObj.ObjNo = ObjNo; Document.StrObjects.Insert(~Index, StrObj); } // create PdfObject for annotation PdfObject Annotation = new PdfObject(Document, false, "/Annot"); Annotation.AddToDictionary("/A", String.Format("<</S/URI/Type/Action/URI {0} 0 R>>", ObjNo)); Annotation.AddToDictionary("/BS", "<</W 0>>"); Annotation.AddToDictionary("/F", "4"); Annotation.AddToDictionary("/Rect", String.Format(NFI.DecSep, "[{0} {1} {2} {3}]", ToPt(LeftPos), ToPt(BottomPos), ToPt(RightPos), ToPt(TopPos))); Annotation.AddToDictionary("/Subtype", "/Link"); // add annotation object to page dictionary String Value = GetDictionaryValue("/Annots"); if (Value == null) { AddToDictionary("/Annots", String.Format("[{0} 0 R]", Annotation.ObjectNumber)); } else { AddToDictionary("/Annots", Value.Replace("]", String.Format(" {0} 0 R]", Annotation.ObjectNumber))); } // exit return; }