private void BreakLine() { // break segment at line break seg index into two segments TextBoxSeg BreakSeg = SegArray[BreakSegIndex]; // add extra segment to segment array if(BreakPtr != 0) { TextBoxSeg ExtraSeg = new TextBoxSeg(BreakSeg); ExtraSeg.SegWidth = BreakWidth; ExtraSeg.Text = BreakSeg.Text.Substring(0, BreakPtr); SegArray.Insert(BreakSegIndex, ExtraSeg); BreakSegIndex++; } // remove blanks from the area between the two sides of the segment for(; BreakPtr < BreakSeg.Text.Length && BreakSeg.Text[BreakPtr] == ' '; BreakPtr++); // save the area after the first line if(BreakPtr < BreakSeg.Text.Length) { BreakSeg.Text = BreakSeg.Text.Substring(BreakPtr); BreakSeg.SegWidth = BreakSeg.Font.TextWidth(BreakSeg.FontSize, BreakSeg.Text); } else { BreakSeg.Text = String.Empty; BreakSeg.SegWidth = 0.0; } BreakPtr = 0; BreakWidth = 0.0; return; }
/// <summary> /// TextBox segment copy constructor. /// </summary> /// <param name="CopySeg">Source TextBox segment.</param> public TextBoxSeg( TextBoxSeg CopySeg ) { this.Font = CopySeg.Font; this.FontSize = CopySeg.FontSize; this.DrawStyle = CopySeg.DrawStyle; this.FontColor = CopySeg.FontColor; Text = String.Empty; this.WebLink = CopySeg.WebLink; return; }
/// <summary> /// TextBox segment copy constructor. /// </summary> /// <param name="CopySeg">Source TextBox segment.</param> internal TextBoxSeg ( TextBoxSeg CopySeg ) { Font = CopySeg.Font; FontSize = CopySeg.FontSize; DrawStyle = CopySeg.DrawStyle; FontColor = CopySeg.FontColor; Text = string.Empty; AnnotAction = CopySeg.AnnotAction; }
/// <summary> /// TextBox segment copy constructor. /// </summary> /// <param name="CopySeg">Source TextBox segment.</param> internal TextBoxSeg ( TextBoxSeg CopySeg ) { this.Font = CopySeg.Font; this.FontSize = CopySeg.FontSize; this.DrawStyle = CopySeg.DrawStyle; this.FontColor = CopySeg.FontColor; Text = String.Empty; this.AnnotAction = CopySeg.AnnotAction; return; }
/// <summary> /// TextBoxLine constructor. /// </summary> /// <param name="Ascent">Line ascent.</param> /// <param name="Descent">Line descent.</param> /// <param name="EndOfParagraph">Line is end of paragraph.</param> /// <param name="SegArray">Segments' array.</param> public TextBoxLine( Double Ascent, Double Descent, Boolean EndOfParagraph, TextBoxSeg[] SegArray ) { this.Ascent = Ascent; this.Descent = Descent; this.EndOfParagraph = EndOfParagraph; this.SegArray = SegArray; return; }
private void AddLine( Boolean EndOfParagraph ) { // end of paragraph if(EndOfParagraph) BreakSegIndex = SegArray.Count; // test for box too narrow if(BreakSegIndex < 1) throw new ApplicationException("TextBox is too narrow."); // test for possible trailing blanks if(SegArray[BreakSegIndex - 1].Text.EndsWith(" ")) { // remove trailing blanks while(BreakSegIndex > 0) { TextBoxSeg TempSeg = SegArray[BreakSegIndex - 1]; TempSeg.Text = TempSeg.Text.TrimEnd(new Char[] {' '}); TempSeg.SegWidth = TempSeg.Font.TextWidth(TempSeg.FontSize, TempSeg.Text); if(TempSeg.Text.Length != 0 || BreakSegIndex == 1 && EndOfParagraph) break; BreakSegIndex--; SegArray.RemoveAt(BreakSegIndex); } } // test for abnormal case of a blank line and not end of paragraph if(BreakSegIndex > 0) { // allocate segment array TextBoxSeg[] LineSegArray = new TextBoxSeg[BreakSegIndex]; // copy segments SegArray.CopyTo(0, LineSegArray, 0, BreakSegIndex); // line ascent and descent Double LineAscent = 0; Double LineDescent = 0; // loop for segments until line break segment index foreach(TextBoxSeg Seg in LineSegArray) { Double Ascent = Seg.Font.AscentPlusLeading(Seg.FontSize); if(Ascent > LineAscent) LineAscent = Ascent; Double Descent = Seg.Font.DescentPlusLeading(Seg.FontSize); if(Descent > LineDescent) LineDescent = Descent; Int32 SpaceCount = 0; foreach(Char Chr in Seg.Text) if(Chr == ' ') SpaceCount++; Seg.SpaceCount = SpaceCount; } // add line LineArray.Add(new TextBoxLine(LineAscent, LineDescent, EndOfParagraph, LineSegArray)); // update column height BoxHeight += LineAscent + LineDescent; // update paragraph count if(EndOfParagraph) ParagraphCount++; // remove segments SegArray.RemoveRange(0, BreakSegIndex); } // switch to next line LineBreakWidth = 0.0; BreakSegIndex = 0; // new line width LineWidth = 0.0; foreach(TextBoxSeg Seg in SegArray) LineWidth += Seg.SegWidth; return; }
/// <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="WebLink">Web link</param> public void AddText( PdfFont Font, Double FontSize, DrawStyle DrawStyle, Color FontColor, String Text, String WebLink = null ) { // 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, WebLink)) { Seg = new TextBoxSeg(Font, FontSize, DrawStyle, FontColor, WebLink); 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, WebLink); SegArray.Add(Seg); continue; } // validate character Font.ValidateChar(CurChar); // 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; 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; }
private void AddLine ( bool EndOfParagraph ) { // end of paragraph if (EndOfParagraph) { BreakSegIndex = SegArray.Count; } // test for box too narrow if (BreakSegIndex < 1) { throw new ApplicationException("TextBox is too narrow."); } // test for possible trailing blanks if (SegArray[BreakSegIndex - 1].Text.EndsWith(" ")) { // remove trailing blanks while (BreakSegIndex > 0) { TextBoxSeg TempSeg = SegArray[BreakSegIndex - 1]; TempSeg.Text = TempSeg.Text.TrimEnd(new char[] { ' ' }); TempSeg.SegWidth = TempSeg.Font.TextWidth(TempSeg.FontSize, TempSeg.Text); if (TempSeg.Text.Length != 0 || BreakSegIndex == 1 && EndOfParagraph) { break; } BreakSegIndex--; SegArray.RemoveAt(BreakSegIndex); } } // test for abnormal case of a blank line and not end of paragraph if (BreakSegIndex > 0) { // allocate segment array TextBoxSeg[] LineSegArray = new TextBoxSeg[BreakSegIndex]; // copy segments SegArray.CopyTo(0, LineSegArray, 0, BreakSegIndex); // line ascent and descent double LineAscent = 0; double LineDescent = 0; // loop for segments until line break segment index foreach (TextBoxSeg Seg in LineSegArray) { double Ascent = Seg.Font.AscentPlusLeading(Seg.FontSize); if (Ascent > LineAscent) { LineAscent = Ascent; } double Descent = Seg.Font.DescentPlusLeading(Seg.FontSize); if (Descent > LineDescent) { LineDescent = Descent; } int SpaceCount = 0; foreach (char Chr in Seg.Text) { if (Chr == ' ') { SpaceCount++; } } Seg.SpaceCount = SpaceCount; } // add line LineArray.Add(new TextBoxLine(LineAscent, LineDescent, EndOfParagraph, LineSegArray)); // update column height BoxHeight += LineAscent + LineDescent; // update paragraph count if (EndOfParagraph) { ParagraphCount++; } // remove segments SegArray.RemoveRange(0, BreakSegIndex); } // switch to next line LineBreakWidth = 0.0; BreakSegIndex = 0; // new line width LineWidth = 0.0; foreach (TextBoxSeg Seg in SegArray) { LineWidth += Seg.SegWidth; } return; }
/// <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 int TextStart = 0; // loop for characters for (int 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; }