/// <summary> /// Add text to text box. /// </summary> /// <param name="Font">Font</param> /// <param name="FontSize">Font size</param> /// <param name="DrawStyle">Drawing style</param> /// <param name="FontColor">Text color</param> /// <param name="Text">Text</param> /// <param name="AnnotAction">Web link</param> public void AddText ( PdfFont Font, Double FontSize, DrawStyle DrawStyle, Color FontColor, String Text, AnnotAction AnnotAction ) { // text is null or empty if (String.IsNullOrEmpty(Text)) { return; } // create new text segment TextBoxSeg Seg; // segment array is empty or new segment is different than last one if (SegArray.Count == 0 || !SegArray[SegArray.Count - 1].IsEqual(Font, FontSize, DrawStyle, FontColor, AnnotAction)) { Seg = new TextBoxSeg(Font, FontSize, DrawStyle, FontColor, AnnotAction); SegArray.Add(Seg); } // add new text to most recent text segment else { Seg = SegArray[SegArray.Count - 1]; } // save text start pointer Int32 TextStart = 0; // loop for characters for (Int32 TextPtr = 0; TextPtr < Text.Length; TextPtr++) { // shortcut to current character Char CurChar = Text[TextPtr]; // end of paragraph if (CurChar == '\n' || CurChar == '\r') { // append text to current segemnt Seg.Text += Text.Substring(TextStart, TextPtr - TextStart); // test for new line after carriage return if (CurChar == '\r' && TextPtr + 1 < Text.Length && Text[TextPtr + 1] == '\n') { TextPtr++; } // move pointer to one after the eol TextStart = TextPtr + 1; // add line AddLine(true); // update last character PrevChar = ' '; // end of text if (TextPtr + 1 == Text.Length) { return; } // add new empty segment Seg = new TextBoxSeg(Font, FontSize, DrawStyle, FontColor, AnnotAction); SegArray.Add(Seg); continue; } // character width Double CharWidth = Font.CharWidth(FontSize, Seg.DrawStyle, CurChar); // space if (CurChar == ' ') { // test for transition from non space to space // this is a potential line break point if (PrevChar != ' ') { // save potential line break information LineBreakWidth = LineWidth; BreakSegIndex = SegArray.Count - 1; BreakPtr = Seg.Text.Length + TextPtr - TextStart; BreakWidth = Seg.SegWidth; } // add to line width LineWidth += CharWidth; Seg.SegWidth += CharWidth; // update last character PrevChar = CurChar; continue; } // add current segment width and to overall line width Seg.SegWidth += CharWidth; LineWidth += CharWidth; // for next loop set last character PrevChar = CurChar; // box width Double Width = BoxWidth; if (FirstLineIndent != 0 && (LineArray.Count == 0 || LineArray[LineArray.Count - 1].EndOfParagraph)) { Width -= FirstLineIndent; } // current line width is less than or equal box width if (LineWidth <= Width) { continue; } // append text to current segemnt Seg.Text += Text.Substring(TextStart, TextPtr - TextStart + 1); TextStart = TextPtr + 1; // there are no breaks in this line or last segment is too long if (LineBreakWidth < LineBreakFactor * Width) { BreakSegIndex = SegArray.Count - 1; BreakPtr = Seg.Text.Length - 1; BreakWidth = Seg.SegWidth - CharWidth; } // break line BreakLine(); // add line up to break point AddLine(false); } // save text Seg.Text += Text.Substring(TextStart); // exit return; }
//////////////////////////////////////////////////////////////////// // Convert resource dictionary to one String. // This method is called at the last step of document creation // from within PdfDocument.CreateFile(FileName). // it is relevant to page contents, X objects and tiled pattern // Return value is resource dictionary string. //////////////////////////////////////////////////////////////////// internal String BuildResourcesDictionary ( List <PdfObject> ResObjects, // list of resource objects for this contents Boolean AddProcSet // for page contents we need /ProcSet ) { // resource object list is empty // if there are no resources an empty dictionary must be returned if (ResObjects == null || ResObjects.Count == 0) { return(AddProcSet ? "<</ProcSet [/PDF/Text]>>" : "<<>>"); } // resources dictionary content initialization StringBuilder Resources = new StringBuilder("<<"); // for page object if (AddProcSet) { Resources.Append("/ProcSet [/PDF/Text/ImageB/ImageC/ImageI]\n"); } // add all resources Char ResCodeType = ' '; foreach (PdfObject Resource in ResObjects) { // resource code is /Xnnn if (Resource.ResourceCode[1] != ResCodeType) { // terminate last type if (ResCodeType != ' ') { Resources.Append(">>\n"); } // start new type ResCodeType = Resource.ResourceCode[1]; Resources.Append(ResCodeStr[ResCodeLetter.IndexOf(ResCodeType)]); } // append resource code if (Resource.GetType() != typeof(PdfFont)) { Resources.Append(String.Format("{0} {1} 0 R", Resource.ResourceCode, Resource.ObjectNumber)); } else { PdfFont Font = (PdfFont)Resource; if (Font.FontResCodeUsed) { Resources.Append(String.Format("{0} {1} 0 R", Font.ResourceCode, Font.ObjectNumber)); } if (Font.FontResGlyphUsed) { Resources.Append(String.Format("{0} {1} 0 R", Font.ResourceCodeGlyph, Font.GlyphIndexFont.ObjectNumber)); } } } // terminate last type and resource dictionary Resources.Append(">>\n>>"); // exit return(Resources.ToString()); }