protected override void DoLayoutTextComponent(IPDFTextComponent text, Style style) { var region = this.Context.DocumentLayout.CurrentPage.LastOpenBlock().CurrentRegion; var line = region.CurrentItem as PDFLayoutLine; if (null == line) { line = region.BeginNewLine(); } var bmc = line.AddMarkedContentStart(this, this.Component, PDFMarkedContentType.Text); base.DoLayoutTextComponent(text, style); if (this._addedProxyText) { for (int i = line.Runs.Count - 1; i >= 0; i--) { if (line.Runs[i] is PDFTextRunCharacter) { PDFTextRunCharacter chars = (PDFTextRunCharacter)line.Runs[i]; chars.Characters = ""; break; } } } line.AddMarkedContentEnd(this, bmc); }
/// <summary> /// Creates a new Text character run and adds it to the current line. /// </summary> /// <param name="size">the size of the run in PDFUnits</param> /// <param name="chars">The characters that should be rendered in the run</param> private void AddCharactersToCurrentLine(PDFSize size, string chars) { this.AssertCurrentLine(); PDFTextRunCharacter run = new PDFTextRunCharacter(size, chars, this.CurrentLine, this.TextComponent); this.CurrentLine.AddRun(run); }
private bool EndsInASpace(PDFTextRunCharacter runChars) { if (string.IsNullOrEmpty(runChars.Characters)) { return(false); } char last = runChars.Characters[runChars.Characters.Length - 1]; return(last == ' '); }
internal bool JustifyContent(PDFUnit total, PDFUnit current, PDFUnit available, bool all, List <PDFTextRunCharacter> runCache, ref PDFTextRenderOptions currOptions) { if (this.Runs.Count < 1) { return(false); } bool shouldJustify = all; PDFLayoutRun last = this.Runs[this.Runs.Count - 1]; if (last is PDFTextRunNewLine && (last as PDFTextRunNewLine).IsHardReturn == false) { shouldJustify = true; } if (shouldJustify) { runCache.Clear(); bool intext = (null != currOptions); //if we have text render options then even if we are the first run we can be considered as inside a text block int charCount = 0; int spaceCount = 0; PDFTextRunCharacter lastchars = null; for (int i = 0; i < this.Runs.Count; i++) { PDFLayoutRun cur = this.Runs[i]; if (cur is PDFTextRunBegin) { currOptions = ((PDFTextRunBegin)cur).TextRenderOptions; if (!intext) { intext = true; } } else if (cur is PDFTextRunCharacter && intext) { PDFTextRunCharacter chars = cur as PDFTextRunCharacter; if (!(currOptions.WordSpacing.HasValue || currOptions.CharacterSpacing.HasValue)) { AddCharactersAndSpaces(chars.Characters, ref charCount, ref spaceCount); lastchars = chars; } } else if (cur is PDFLayoutComponentRun) { lastchars = null; } } // Post process to calculate the required spacing // if we have some text in our line. if (intext && (spaceCount + charCount > 0)) { if (null != lastchars && lastchars.Characters.EndsWith(" ")) { lastchars.Characters = lastchars.Characters.Substring(0, lastchars.Characters.Length - 1); spaceCount -= 1; } double spaceToCharFactor = 10; // apply ten times more to spaces than characters. double full = (spaceCount * spaceToCharFactor) + charCount; this._linespacingOptions = new ExtraSpacingOptions() { CharSpace = available / full, WordSpace = (available / full) * spaceToCharFactor, Options = currOptions }; charCount = 0; spaceCount = 0; PDFUnit currWidth = 0; PDFUnit change = PDFUnit.Zero; for (int i = 0; i < this.Runs.Count; i++) { PDFLayoutRun cur = this.Runs[i]; if (cur is PDFTextRunBegin) { PDFTextRunBegin begin = (PDFTextRunBegin)cur; currOptions = begin.TextRenderOptions; if (i > 0) { change = (_linespacingOptions.WordSpace * spaceCount) + (_linespacingOptions.CharSpace * charCount); begin.LineInset += change; } } else if (cur is PDFTextRunCharacter) { if (!currOptions.WordSpacing.HasValue || !currOptions.CharacterSpacing.HasValue) { PDFTextRunCharacter chars = cur as PDFTextRunCharacter; int runChars = 0; int runSpaces = 0; AddCharactersAndSpaces(chars.Characters, ref runChars, ref runSpaces); charCount += runChars; spaceCount += runSpaces; chars.ExtraSpace = (_linespacingOptions.WordSpace * runSpaces) + (_linespacingOptions.CharSpace * runChars); } } else if (cur is PDFLayoutComponentRun) { if (i > 0) { PDFLayoutComponentRun comprun = (cur as PDFLayoutComponentRun); PDFRect bounds = comprun.TotalBounds; bounds.X += (_linespacingOptions.WordSpace * spaceCount) + (_linespacingOptions.CharSpace * charCount); comprun.TotalBounds = bounds; } } else if (cur is PDFTextRunNewLine) { PDFTextRunNewLine newLine = (cur as PDFTextRunNewLine); newLine.Offset = new PDFSize(newLine.Offset.Width + change, newLine.Offset.Height); } } } } return(shouldJustify); }
protected virtual void RenderTextDecoration(PDFTextRunEnd endRun, PDFRenderContext context, PDFWriter writer, PDFUnit vOffset, PDFUnit linethickness) { if (context.ShouldLogDebug) { context.TraceLog.Begin(TraceLevel.Debug, "Text Decoration", "Starting to render text decorations"); } //set up the graphics context PDFPen pen = PDFPen.Create(this.TextRenderOptions.FillBrush, linethickness); context.Graphics.SaveGraphicsState(); pen.SetUpGraphics(context.Graphics, this.TotalBounds); bool drawing = false; PDFPoint linestart = new PDFPoint(this.StartTextCursor.Width, this.StartTextCursor.Height + vOffset); foreach (PDFLayoutLine line in this.Lines) { PDFUnit linewidth = 0; foreach (PDFLayoutRun run in line.Runs) { if (run == this) { drawing = true; //lineoffset += this.LineInset; } else if (run == endRun) { drawing = false; break; } else if (drawing) { if (run is PDFTextRunCharacter) { PDFTextRunCharacter chars = (PDFTextRunCharacter)run; PDFPoint start = new PDFPoint(linestart.X + linewidth, linestart.Y); PDFPoint end = new PDFPoint(linestart.X + linewidth + chars.Width + chars.ExtraSpace, linestart.Y); context.Graphics.DrawLine(start, end); if (context.ShouldLogDebug) { context.TraceLog.Add(TraceLevel.Debug, "Text Decoration", "Drawn line from " + start + " to " + end); } linewidth += chars.Width; } else if (run is PDFTextRunEnd) { } else if (run is PDFTextRunNewLine) { PDFTextRunNewLine newline = (PDFTextRunNewLine)run; PDFSize offset = newline.Offset; if (null != newline.NextLineSpacer) { PDFUnit nextoffset = newline.NextLineSpacer.Width; offset.Width = nextoffset - offset.Width; } linestart.X += offset.Width; linestart.Y += offset.Height; } else if (run is PDFTextRunSpacer) { //PDFTextRunSpacer spacer = (PDFTextRunSpacer)run; //cursor.X += spacer.Width; } else if (run is PDFTextRunProxy) { PDFTextRunProxy chars = (PDFTextRunProxy)run; PDFPoint start = new PDFPoint(linestart.X + linewidth, linestart.Y); PDFPoint end = new PDFPoint(linestart.X + linewidth + chars.Width, linestart.Y); context.Graphics.DrawLine(start, end); if (context.ShouldLogDebug) { context.TraceLog.Add(TraceLevel.Debug, "Text Decoration", "Drawn line from " + start + " to " + end); } linewidth += chars.Width; } } } } if (context.ShouldLogDebug) { context.TraceLog.End(TraceLevel.Debug, "Text Decoration", "Completed the renderering of text decorations"); } //tear down the current graphics state context.Graphics.RestoreGraphicsState(); }