// // .ctor(s) // #region public PDFLayoutComponentRun(PDFLayoutLine line, IPDFComponent component, PDFStyle style) /// <summary> /// Creates a new Component Run /// </summary> /// <param name="line"></param> /// <param name="component"></param> /// <param name="style"></param> public PDFLayoutComponentRun(PDFLayoutLine line, IPDFComponent component, Style style) : base(line, component) { System.Diagnostics.Debug.Assert(null != component); System.Diagnostics.Debug.Assert(null != style); this.FullStyle = style; }
private PDFRect CalculateOnlyLineBounds(PDFTextRunEnd end) { PDFLayoutLine line = this._lines[0]; PDFRect full = new PDFRect(this.TotalBounds.Location, PDFSize.Empty); bool counting = false; PDFUnit linewidth = PDFUnit.Zero; foreach (PDFLayoutRun run in line.Runs) { if (run == this) { counting = true; } else if (run == end) { break; } else if (counting) { linewidth += run.Width; } } full.Width = linewidth; full.Height = line.Height; return(full); }
private PDFRect CalculateLastLineBounds(PDFUnit voffset, PDFTextRunEnd end) { PDFLayoutLine line = this._lines[this._lines.Count - 1]; PDFRect full = new PDFRect(this.TotalBounds.Location, PDFSize.Empty); full.Y += voffset; PDFUnit linewidth = PDFUnit.Zero; full.Height = line.Height; foreach (PDFLayoutRun run in line.Runs) { if (run == end) { break; } if (run is PDFTextRunSpacer) { full.X = run.Width; } else { linewidth += run.Width; } } full.Width = linewidth; return(full); }
// // overflow operations // protected virtual void DoMoveToNextRegion(PDFUnit lineheight) { PDFLayoutLine lastline = this.CurrentLine; this.EndText(); //Always end this block of text bool newPage; PDFLayoutRegion region = lastline.Region; PDFLayoutBlock block = (PDFLayoutBlock)region.Parent; LayoutEngineBase engine = this.Parent as LayoutEngineBase; if (null == engine) { throw new NullReferenceException("Parent engine was not the expected BlockLayoutEngine. A Hack that is needed for overflowing textual content"); } else if (engine.MoveToNextRegion(lineheight, ref region, ref block, out newPage)) { if (!this.StartText()) { return; } } else { if (this.Context.TraceLog.ShouldLog(TraceLevel.Message)) { this.Context.TraceLog.Add(TraceLevel.Message, LOG_CATEGORY, "Cannot layout any more text for component '" + this.TextComponent.ID + "'. Available space full and cannot move to another region."); } this.ContinueLayout = false; } }
/// <summary> /// Adds a spacer of the required width (and height) to the line - inheritors can override this value /// </summary> /// <param name="w"></param> /// <param name="h"></param> /// <param name="line"></param> protected virtual PDFTextRunSpacer AddLineInsetRun(PDFUnit w, PDFUnit h, PDFLayoutLine line) { PDFTextRunSpacer spacer = new PDFTextRunSpacer(w, h, line, this.TextComponent); line.AddRun(spacer); return(spacer); }
/// <summary> /// We need to start the text /// </summary> protected virtual bool StartText() { if (this.Context.ShouldLogDebug) { this.Context.TraceLog.Begin(TraceLevel.Verbose, LOG_CATEGORY, "Starting the layout of text component " + this.TextComponent.ID); } bool started; PDFLayoutLine line = this.EnsureFirstLineAvailable(out started); if (null == line) { this.ContinueLayout = false; return(false); } this.CurrentLine = line; this.Context.Graphics.SetCurrentFont(this.TextRenderOptions.Font); PDFUnit inset = PDFUnit.Zero; if (line.IsEmpty == false) { inset = line.Width; } else if (this.TextRenderOptions.FirstLineInset.HasValue && (this.Position.PositionMode != PositionMode.Inline || started)) { inset = this.TextRenderOptions.FirstLineInset.Value; if (inset > 0) { PDFTextRunSpacer spacer = new PDFTextRunSpacer(inset, 1, line, null); line.AddRun(spacer); } } PDFTextRunBegin begin = new PDFTextRunBegin(this.TextRenderOptions, this.CurrentLine, this.TextComponent); begin.LineInset = inset; this.CurrentLine.AddRun(begin); begin.SetOffsetY(this.CurrentLine.OffsetY); this.CurrentLineInset = inset; this.BeginningRun = begin; if (this.Context.ShouldLogDebug) { this.Context.TraceLog.End(TraceLevel.Verbose, LOG_CATEGORY, "Completed the layout of text component " + this.TextComponent.ID); } else if (this.Context.ShouldLogVerbose) { this.Context.TraceLog.Add(TraceLevel.Verbose, LOG_CATEGORY, "Laid out text component " + this.TextComponent.ID); } return(true); }
public PDFLayoutXObject(PDFLayoutLine parent, PDFLayoutRegion childContainer, PDFPositionOptions position, IPDFComponent owner) : base(parent, owner as IPDFComponent) { this._childContainer = childContainer; this._resources = new PDFResourceList(this, false); this.SubType = "Form"; this.Matrix = PDFTransformationMatrix.Identity(); this._position = position; }
protected virtual void AddReturn(PDFUnit widthOfLastTextDraw, bool hardReturn) { this.AssertCurrentLine(); PDFLayoutLine line = this.CurrentLine; PDFTextRunNewLine br = new PDFTextRunNewLine(false, line, this.TextRenderOptions, this.TextComponent); line.AddRun(br); //The offset is from the start of the last text drawing operation //and the offset of the start of the current line PDFUnit lineright = widthOfLastTextDraw; PDFUnit back = line.Width - lineright; //Previous - 27 Feb 2015 //br.Offset = new PDFSize(back, line.Height); //Updated if (line.BaseLineOffset == 0 || this.TextRenderOptions.Leading.HasValue) //we don't have any begins or ends affecting the flow (or an explicit leading) { br.Offset = new PDFSize(back, line.Height); } else { br.Offset = new PDFSize(back, (line.Height - line.BaseLineOffset) + this.TextRenderOptions.GetAscent()); } PDFLayoutRegion reg = line.Region; reg.CloseCurrentItem(); line = reg.BeginNewLine(); this.BeginningRun.Lines.Add(line); PDFUnit inset; if (hardReturn) { inset = this.TextRenderOptions.GetFirstLineInset(); } else { inset = PDFUnit.Zero; } PDFTextRunSpacer spacer = this.AddLineInsetRun(inset, 0, line); br.NextLineSpacer = spacer; this.CurrentLine = line; this.CurrentLineInset = inset; }
private PDFLayoutInlineBegin CreateAndAddInlineBegin(PDFPositionOptions pos) { PDFLayoutBlock containerBlock = this.DocumentLayout.CurrentPage.LastOpenBlock(); PDFLayoutRegion containerRegion = containerBlock.CurrentRegion; if (containerRegion.HasOpenItem == false) { containerRegion.BeginNewLine(); } PDFLayoutLine currline = containerRegion.CurrentItem as PDFLayoutLine; PDFLayoutInlineBegin begin = currline.AddInlineRunStart(this, this.Component, pos, this.FullStyle); return(begin); }
private PDFLayoutInlineEnd CreateAndAddInlineEnd(PDFPositionOptions pos, PDFLayoutInlineBegin begin) { PDFLayoutBlock containerBlock = this.DocumentLayout.CurrentPage.LastOpenBlock(); PDFLayoutRegion containerRegion = containerBlock.CurrentRegion; if (containerRegion.HasOpenItem == false) { containerRegion.BeginNewLine(); } PDFLayoutLine currline = containerRegion.CurrentItem as PDFLayoutLine; PDFLayoutInlineEnd end = currline.AddInlineRunEnd(this, this.Component, begin, pos); return(end); }
/// <summary> /// Begins a new line on the current region and sets up it's width. /// </summary> /// <param name="startparagraph">Set to true if this is the first line in a run or the first line in a new paragraph</param> /// <returns>The newly created and added line</returns> public PDFLayoutLine BeginNewLine() { this.AssertIsOpen(); this.AssertLastItemIsClosed(); PDFUnit width = this.GetAvailableWidth(); PDFLayoutLine line = new PDFLayoutLine(this, width, this.HAlignment, this.VAlignment, this.Contents.Count); line.OffsetY = this.UsedSize.Height; this.Contents.Add(line); return(line); }
/// <summary> /// Adds an existing line to this region, updating the items' parent in the process. /// And increasing the size of this region if the block is closed. /// </summary> /// <param name="item"></param> public virtual void AddExistingItem(PDFLayoutLine line) { if (null == line) { throw new ArgumentNullException("line"); } this._contents.Add(line); line.SetOffset(line.OffsetX, this.Height); line.SetParent(this); line.LineIndex = this.Contents.Count - 1; if (line.IsClosed) { this.AddToSize(line); } }
private PDFLayoutXObject CreateAndAddInput(PDFPositionOptions pos) { PDFLayoutBlock containerBlock = this.DocumentLayout.CurrentPage.LastOpenBlock(); PDFLayoutRegion containerRegion = containerBlock.CurrentRegion; if (containerRegion.HasOpenItem == false) { containerRegion.BeginNewLine(); } //pos.Y = 200; PDFLayoutRegion container = containerBlock.BeginNewPositionedRegion(pos, this.DocumentLayout.CurrentPage, this.Component, this.FullStyle, false); this.Line = containerRegion.CurrentItem as PDFLayoutLine; PDFLayoutXObject begin = this.Line.AddXObjectRun(this, this.Field, container, pos, this.FullStyle); return(begin); }
protected virtual PDFLayoutXObject ApplyViewPort(PDFPositionOptions oldpos, PDFRect viewPort) { //Set the size to the viewport size var newpos = oldpos.Clone(); newpos.X = viewPort.X; newpos.Y = viewPort.Y; //update to new widths newpos.Width = viewPort.Width; newpos.Height = viewPort.Height; //Set the style values to the viewport too. (and reset the cache) this.FullStyle.Size.Width = newpos.Width.Value; this.FullStyle.Size.Height = newpos.Height.Value; if (this.FullStyle is Scryber.Styles.StyleFull) { (this.FullStyle as StyleFull).ClearFullRefs(); } PDFLayoutBlock containerBlock = this.DocumentLayout.CurrentPage.LastOpenBlock(); PDFLayoutRegion containerRegion = containerBlock.CurrentRegion; if (containerRegion.HasOpenItem == false) { containerRegion.BeginNewLine(); } //pos.Y = 200; PDFLayoutRegion container = containerBlock.BeginNewPositionedRegion(newpos, this.DocumentLayout.CurrentPage, this.Component, this.FullStyle, false); this.Line = containerRegion.CurrentItem as PDFLayoutLine; PDFLayoutXObject begin = this.Line.AddXObjectRun(this, this.Component, container, newpos, this.FullStyle); begin.SetOutputSize(oldpos.Width, oldpos.Height); //this.CurrentBlock.IsFormXObject = true; //this.CurrentBlock.XObjectViewPort = pos.ViewPort.Value; return(begin); }
private PDFRect CalculateInnerTotalBounds(PDFUnit voffset, PDFTextRunEnd ending) { PDFRect full = this.TotalBounds.Clone(); full.Size = PDFSize.Empty; full.Y += voffset; //only want the lines that are between the first and last line int firstIndex = 1; int lastIndex = this.Lines.Count - 2; PDFUnit maxright = PDFUnit.Zero; PDFUnit minleft = new PDFUnit(Double.MaxValue); for (int i = firstIndex; i <= lastIndex; i++) { PDFLayoutLine line = this.Lines[i]; #if FULL_WIDTH minleft = 0; maxright = PDFUnit.Max(maxright, line.FullWidth); #else PDFUnit x = PDFUnit.Zero; PDFUnit w = line.Width; if (line.Runs[0] is PDFTextRunSpacer) { x = line.Runs[0].Width; } maxright = PDFUnit.Max(maxright, w); minleft = PDFUnit.Min(minleft, x); full.Height += line.Height; #endif } if (minleft > 0) { full.X = minleft; } full.Width = maxright - minleft; return(full); }
// // implementation // /// <summary> /// overrides the base implementation to also offset the new line with the spacer. /// </summary> /// <param name="context"></param> /// <param name="pageIndex"></param> /// <param name="xoffset"></param> /// <param name="yoffset"></param> protected override void DoPushComponentLayout(PDFLayoutContext context, int pageIndex, PDFUnit xoffset, PDFUnit yoffset) { if (NextLineSpacer != null) { PDFSize offset = this.Offset; offset.Width += xoffset; PDFLayoutLine line = this.NextLineSpacer.Line; if (line.BaseLineOffset > 0 && this.TextOptions.Leading.HasValue == false) { PDFUnit maxdescender = line.Height - line.BaseLineOffset; PDFUnit ourdescender = this.TextOptions.Font.FontMetrics.LineHeight - this.TextOptions.Font.FontMetrics.Ascent; PDFUnit difdescender = maxdescender - ourdescender; offset.Height = line.Height - difdescender; } this.Offset = offset; } base.DoPushComponentLayout(context, pageIndex, xoffset, yoffset); }
// // ctor // public PDFTextRunBegin(PDFTextRenderOptions renderopts, PDFLayoutLine line, IPDFComponent owner) : base(line, owner) { this.TextRenderOptions = renderopts; this.Lines.Add(line); }
// // ctor // public PDFTextRunEnd(PDFTextRunBegin start, PDFLayoutLine line, IPDFComponent owner) : base(line, owner) { this._start = start; }
public PDFTextRunCharacter(PDFSize size, string characters, PDFLayoutLine line, IPDFComponent owner) : base(line, owner) { this._measuredSize = size; this._chars = characters; }
// // ctor // #region public PDFTextRunSpacer(PDFUnit width, PDFUnit height, PDFLayoutLine line, IPDFComponent owner) public PDFTextRunSpacer(PDFUnit width, PDFUnit height, PDFLayoutLine line, IPDFComponent owner) : base(line, owner) { this.SetSpacing(width, height); }
// // overrides // #region protected override void DoPushComponentLayout(PDFLayoutContext context, int pageIndex, PDFUnit xoffset, PDFUnit yoffset) /// <summary> /// Overrides the default behaviour to push any arrangements for the child item of this region /// </summary> /// <param name="context"></param> protected override void DoPushComponentLayout(PDFLayoutContext context, int pageIndex, PDFUnit xoffset, PDFUnit yoffset) { bool logdebug = context.ShouldLogDebug; if (logdebug) { context.TraceLog.Begin(TraceLevel.Debug, "Layout Region", "Pushing the component layout for the region " + this.ToString()); } if (!this.IsClosed) { if (logdebug) { context.TraceLog.Add(TraceLevel.Debug, PDFLayoutItem.LOG_CATEGORY, "Closing the region " + this.ToString() + " before pushing the layout"); } this.Close(); } if (this._contents == null || this.Contents.Count == 0) { if (logdebug) { context.TraceLog.Add(TraceLevel.Debug, PDFLayoutItem.LOG_CATEGORY, "The region " + this.ToString() + " is empty. Exiting the push component early."); } return; } bool applyAlignments = this.ShouldApplyAlignment(); if (applyAlignments) { VerticalAlignment v = this.VAlignment; if (v != VerticalAlignment.Top) { this.EnsureCorrectHeight(); if (logdebug) { context.TraceLog.Add(TraceLevel.Debug, PDFLayoutItem.LOG_CATEGORY, "Adjusting the vertical offset of the region " + this.ToString() + " as it is not top aligned"); } PDFUnit space = this.AvailableHeight; if (v == VerticalAlignment.Middle) { space = space / 2; } yoffset += space; } } HorizontalAlignment h = this.HAlignment; PDFTextRenderOptions options = (this.Parent as PDFLayoutBlock).FullStyle.CreateTextOptions(); List <PDFTextRunCharacter> cache = new List <PDFTextRunCharacter>(); bool lastwasapplied = false; foreach (PDFLayoutItem item in this.Contents) { PDFUnit itemXOffset = xoffset; ///Individually calculate each lines horizontal offset if (applyAlignments && h != HorizontalAlignment.Left) { PDFUnit space = this.TotalBounds.Width - item.Width; if (h == HorizontalAlignment.Justified) { if (item is PDFLayoutLine) { PDFLayoutLine line = item as PDFLayoutLine; if (logdebug) { context.TraceLog.Add(TraceLevel.Debug, PDFLayoutItem.LOG_CATEGORY, "Justifying the textual content of the line " + line.LineIndex); } bool didjustify = line.JustifyContent(this.TotalBounds.Width, item.Width, space, false, cache, ref options); if (!didjustify && lastwasapplied && null != options && !(options.WordSpacing.HasValue || options.CharacterSpacing.HasValue)) { line.ResetJustifySpacing(options); } lastwasapplied = didjustify; } space = 0; // reset space to zero as already accounted for. } else if (h == HorizontalAlignment.Center) { space = space / 2; } itemXOffset = itemXOffset + space; } item.PushComponentLayout(context, pageIndex, itemXOffset, yoffset); } if (logdebug) { context.TraceLog.End(TraceLevel.Debug, "Layout Region", "Pushed all the component layouts for the region " + this.ToString()); } }
public PDFLayoutInlineBegin(PDFLayoutLine line, IPDFComponent owner, PDFPositionOptions pos, Style fullStyle) : base(line, owner) { this.InlinePosition = pos; this.FullStyle = fullStyle; }
public PDFLayoutInlineEnd(PDFLayoutLine line, PDFLayoutInlineBegin begin, IPDFComponent owner, PDFPositionOptions pos) : base(line, owner) { this.BeginMarker = begin; }
// // ctor // #region public PDFTextRunNewLine(bool isHardReturn, PDFLayoutLine line, IPDFComponent owner) /// <summary> /// Creates a new line text run. /// </summary> /// <param name="isHardReturn"></param> /// <param name="line"></param> /// <param name="owner"></param> public PDFTextRunNewLine(bool isHardReturn, PDFLayoutLine line, PDFTextRenderOptions opts, IPDFComponent owner) : base(line, owner) { this.IsHardReturn = isHardReturn; this.TextOptions = opts; }
public PDFLayoutPositionedRegionRun(PDFLayoutRegion region, PDFLayoutLine line, IPDFComponent owner) : base(line, owner) { this.Region = region; }
/// <summary> /// Add characters to the line(s), and returns the last width of the characters that were laid out. /// </summary> protected virtual PDFUnit AddProxyCharacters(PDFTextProxyOp proxy) { this.AssertCurrentLine(); PDFUnit lineheight = this.TextRenderOptions.GetLineHeight(); ZeroLineCounter zeros = new ZeroLineCounter(); PDFSize measured = PDFSize.Empty; PDFSize required = PDFSize.Empty; PDFLayoutLine line = this.CurrentLine; PDFLayoutRegion reg = line.Region; PDFUnit availH = reg.AvailableHeight; PDFUnit availW = line.AvailableWidth; if (availH < lineheight) { if (this.Position.OverflowAction != OverflowAction.Clip) { availH = lineheight; } else { this.DoMoveToNextRegion(lineheight); if (!this.ContinueLayout) { return(PDFUnit.Zero); } } } //Measure the string an get the fitted characters int fitted; this.Context.PerformanceMonitor.Begin(PerformanceMonitorType.Text_Measure); measured = this.MeasureString(availH, availW, proxy.Text, 0, out fitted); this.Context.PerformanceMonitor.End(PerformanceMonitorType.Text_Measure); required = new PDFSize(measured.Width, lineheight); if (fitted < proxy.Text.Length) //cannot split a proxy - must simply be a single run. { //try on the next line to see if we can put everything on there. this.AddSoftReturn(0); if (!zeros.AssertIncrement(this.Context)) { return(PDFUnit.Zero); } availW = this.CurrentLine.AvailableWidth; this.Context.PerformanceMonitor.Begin(PerformanceMonitorType.Text_Measure); measured = this.MeasureString(availH, availW, proxy.Text, 0, out fitted); this.Context.PerformanceMonitor.End(PerformanceMonitorType.Text_Measure); if (fitted < proxy.Text.Length) //Still cannot fit the proxy so not much we can do. Log it and return { this.Context.TraceLog.Add(TraceLevel.Warning, LOG_CATEGORY, "The text proxy for '" + proxy.Text + "' could not fit the characters on a single line. Overflow of proxies is not currently supported."); return(measured.Width); } required = new PDFSize(measured.Width, lineheight); } // everything fitted on the line zeros.Reset(); this.AddProxyToCurrentLine(required, proxy); return(required.Width); }
public PDFTextRunProxy(PDFSize size, Scryber.Text.PDFTextProxyOp proxy, PDFLayoutLine line, IPDFComponent owner) : base(line, owner) { this._measuredSize = size; this._proxy = proxy; }
/// <summary> /// Add characters to the line(s), and returns the last width of the characters that were laid out. /// </summary> protected virtual PDFUnit AddCharacters(string chars) { this.AssertCurrentLine(); PDFUnit lineheight = this.TextRenderOptions.GetLineHeight(); int offset = 0; ZeroLineCounter zeros = new ZeroLineCounter(); PDFSize measured = PDFSize.Empty; PDFSize required = PDFSize.Empty; while (offset < chars.Length) { //Check that we have enough space for the next line PDFLayoutLine line = this.CurrentLine; PDFLayoutRegion reg = line.Region; PDFUnit availH = reg.AvailableHeight; PDFUnit availW = line.AvailableWidth; if (availH < lineheight) { if (this.Position.OverflowAction != OverflowAction.Clip) { this.DoMoveToNextRegion(lineheight); if (!this.ContinueLayout) { return(PDFUnit.Zero); } else { line = this.CurrentLine; reg = line.Region; availW = line.AvailableWidth; availH = reg.AvailableHeight; } } else { availH = lineheight; } } //Measure the string an get the fitted characters Context.PerformanceMonitor.Begin(PerformanceMonitorType.Text_Measure); int fitted; measured = this.MeasureString(availH, availW, chars, offset, out fitted); Context.PerformanceMonitor.End(PerformanceMonitorType.Text_Measure); required = new PDFSize(measured.Width, lineheight); if (fitted <= 0) //nothing fitted on the line { this.AddSoftReturn(0); if (!zeros.AssertIncrement(this.Context)) { return(PDFUnit.Zero); } } else if (fitted + offset == chars.Length) // everything fitted on the line { zeros.Reset(); string all = chars.Substring(offset); //if (offset == 0) this.AddCharactersToCurrentLine(required, all); //else // this.AddCharactersToCurrentLine(required, chars, offset, fitted); offset += fitted; } else if (IsBrokenInWord(chars, offset, fitted) && CanSplitOnWordsOnly() && !IsEmptyLine()) //don't break on words unless we have to. { this.AddSoftReturn(0); if (!zeros.AssertIncrement(this.Context)) { return(PDFUnit.Zero); } } else //partial fit { zeros.Reset(); string partial = chars.Substring(offset, fitted); this.AddCharactersToCurrentLine(required, partial); //this.AddCharactersToCurrentLine(required, chars, offset, fitted); this.AddSoftReturn(measured.Width); offset += fitted; //Consume any white space as we are now on a new line. //We should never get here for NoWrap as it will alywys fit all characters one one line. while (offset < chars.Length && char.IsWhiteSpace(chars, offset)) { offset++; } } } return(required.Width); }
public PDFTextRun(PDFLayoutLine line, IPDFComponent owner) : base(line, owner) { }
public PDFTextRunPartialCharacter(PDFSize size, string characters, int offset, int count, PDFLayoutLine line, IPDFComponent owner) : base(line, owner) { this._measuredSize = size; this._chars = characters; this._offset = offset; this._count = count; }