public void SectionOverflow() { const int PageWidth = 200; const int PageHeight = 300; Document doc = new Document(); Section section = new Section(); section.Style.PageStyle.Width = PageWidth; section.Style.PageStyle.Height = PageHeight; doc.Pages.Add(section); Div top = new Div() { Height = PageHeight - 100 }; section.Contents.Add(top); //div is too big for the remaining space on the page Div tooverflow = new Div() { Height = 150 }; section.Contents.Add(tooverflow); using (var ms = DocStreams.GetOutputStream("SectionOverflow.pdf")) { doc.LayoutComplete += Doc_LayoutComplete; doc.SaveAsPDF(ms); } Assert.AreEqual(2, layout.AllPages.Count); //Check that the first page has the same dimensions. PDFLayoutPage firstpage = layout.AllPages[0]; Assert.AreEqual(PageWidth, firstpage.Width); Assert.AreEqual(PageHeight, firstpage.Height); //Check that the overflowed page has the same dimensions. PDFLayoutPage lastpage = layout.AllPages[1]; Assert.AreEqual(PageWidth, lastpage.Width); Assert.AreEqual(PageHeight, lastpage.Height); //Check that the block has overflowed to 0 y offset PDFLayoutBlock overflowedblock = lastpage.ContentBlock.Columns[0].Contents[0] as PDFLayoutBlock; Assert.AreEqual(0, overflowedblock.TotalBounds.Y); Assert.AreEqual(150, overflowedblock.Height); }
public void PanelBeyondMinWidthAndHeight() { Document doc = new Document(); Page pg = new Page(); pg.Style.PageStyle.Width = PageWidth; pg.Style.PageStyle.Height = PageHeight; pg.Style.Font.FontSize = 18; doc.Pages.Add(pg); int expectedMinWidth = 200; int expectedMinHeight = 100; Panel panel = new Panel(); panel.MinimumWidth = expectedMinWidth; panel.MinimumHeight = expectedMinHeight; panel.BorderColor = Scryber.Drawing.PDFColors.Black; pg.Contents.Add(panel); Label lbl = new Label() { Text = "This label is wide enough to go beyond the 200pt minimum width of the panel " + "and also the width of the page, so should flow onto the next line and keep going beyond the minimum height of the " + "panel. Therefore extending beyond the bounds of both min- values." }; panel.Contents.Add(lbl); //WILL push the panel beyond its minimumn width using (var ms = DocStreams.GetOutputStream("PanelsBeyondMinWidthAndHeight.pdf")) { doc.LayoutComplete += Doc_LayoutComplete; doc.SaveAsPDF(ms); } PDFLayoutPage layoutpg = layout.AllPages[0]; PDFLayoutBlock pgcontent = layoutpg.ContentBlock; PDFLayoutRegion pgregion = pgcontent.Columns[0]; PDFLayoutBlock panelBlock = pgregion.Contents[0] as PDFLayoutBlock; PDFLayoutRegion panelregion = panelBlock.Columns[0]; Assert.IsNotNull(panelBlock, "The layout block in the page column should not be null"); //block width and height should be greater than the minimum width, but not beyond the height. Assert.IsTrue(expectedMinWidth < panelBlock.Width, "Panel block should be greater than " + expectedMinWidth + " wide"); Assert.IsTrue(PageWidth > panelBlock.Width, "Panel block should not go beyond the page width"); Assert.IsTrue(expectedMinHeight < panelBlock.Height, "Panel block should be greater than " + panelBlock.Height + " high"); }
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); }
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); }
/// <summary> /// Lays out all the content of this panel /// </summary> /// <param name="position"></param> protected virtual void DoLayoutBlockComponent(PDFPositionOptions position, PDFColumnOptions columnOptions) { PDFLayoutBlock containerBlock = CreateContinerBlock(position); if (null == containerBlock) { return; } CreateBlockRegions(containerBlock, position, columnOptions); this.DoLayoutChildren(); EnsureContentsFit(); }
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); }
/// <summary> /// Returns a new un-initialized block that is appended to the current open block /// </summary> /// <param name="owner"></param> /// <param name="fullstyle"></param> /// <returns></returns> public PDFLayoutBlock BeginNewBlock(IPDFComponent owner, IPDFLayoutEngine engine, Style fullstyle, PositionMode mode) { if (this.IsClosed) { throw new InvalidOperationException(Errors.CannotLayoutAPageThatHasBeenClosed); } PDFLayoutBlock last = this.LastOpenBlock(); if (null == last) { throw new InvalidOperationException(Errors.NoOpenBlocksToAppendTo); } else { return(last.BeginNewBlock(owner, engine, fullstyle, mode)); } }
/// <summary> /// Begins the footer on the current document page /// </summary> public void BeginFooter(PDFPageFooter owner, Style full, PDFLayoutContext context) { PDFLayoutBlock block = new PDFLayoutBlock(this, owner, this.Engine, full, OverflowSplit.Never); //Take the magins away from the total bounds before initializing the regions PDFRect content = this.ContentBlock.TotalBounds; if (this.PositionOptions.Margins.IsEmpty == false) { content.Width -= this.PositionOptions.Margins.Left + this.PositionOptions.Margins.Right; content.Height -= this.PositionOptions.Margins.Top + this.PositionOptions.Margins.Bottom; } block.InitRegions(content, this.ContentBlock.Position, full.CreateColumnOptions(), context); this._footer = block; //Make this block current this.CurrentBlock = block; }
/// <summary> /// Adds an existing block 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="block"></param> public virtual void AddExistingItem(PDFLayoutBlock block) { if (null == block) { throw new ArgumentNullException("block"); } if (block.Parent != this.Parent) //make sure the parent blocks match { block.SetParent(this.Parent); } this.Contents.Add(block); //Set the blocks new available bounds based on our size PDFRect newbounds = block.AvailableBounds; newbounds.Y = this.Height; newbounds.Height = (this.AvailableHeight - (block.Position.Padding.Top + block.Position.Padding.Bottom)) - this.Height; newbounds.X = 0; //newbounds.Width = this.TotalBounds.Width - (block.Position.Padding.Left + block.Position.Padding.Right) ; block.AvailableBounds = newbounds; newbounds = block.TotalBounds; newbounds.Y = this.Height; block.TotalBounds = newbounds; //move it back to the top //block.Offset(PDFUnit.Zero, PDFUnit.Zero - block.TotalBounds.Y); if (block.IsClosed) { this.AddToSize(block); } else { if (block.CurrentRegion.IsClosed == false) { newbounds = block.CurrentRegion.UnusedBounds; newbounds.Height = block.AvailableBounds.Height - block.Position.Margins.Top - block.Position.Margins.Bottom; newbounds.Y = PDFUnit.Zero; block.CurrentRegion.TotalBounds = newbounds; } } }
// // methods // #region public PDFLayoutBlock LastOpenBlock() /// <summary> /// Returns the last block in this region that is open. /// Returns null if this region does not contain any blocks, or the last block is closed. /// </summary> /// <returns></returns> public PDFLayoutBlock LastOpenBlock() { if (null != this.Contents && this.Contents.Count > 0) { PDFLayoutItem item = this.Contents[this.Contents.Count - 1]; if (item is PDFLayoutBlock) { PDFLayoutBlock block = item as PDFLayoutBlock; if (block.IsClosed == false) { return(block.LastOpenBlock()); } } else { //the last item is not a block, so any previous blocks must be closed. } } return(null); }
// // methods // #region public void InitPage(int index, PDFSize size, PDFThickness margthick ...) /// <summary> /// Initializes this page with the required top block size and other measurements /// </summary> /// <param name="size"></param> /// <param name="margthick"></param> /// <param name="padthick"></param> /// <param name="available"></param> /// <param name="mode"></param> /// <param name="cansplit"></param> /// <param name="colcount"></param> /// <param name="alley"></param> public virtual void InitPage(PDFSize size, PDFPositionOptions options, PDFColumnOptions columns, PDFLayoutContext context) { this.Size = size; this.PositionOptions = options; OverflowSplit split = options.OverflowSplit; PDFLayoutBlock block = new PDFLayoutBlock(this, this.Owner, this.Engine, this.FullStyle, split); PDFRect totalbounds = new PDFRect(PDFPoint.Empty, this.Size); block.InitRegions(totalbounds, options, columns, context); //We need to set the bounds of the page block to the total for a page //(as margins are taken off from the size of the page // - this is different to a block where margins increase any explicit sizes). block.TotalBounds = totalbounds; this.ContentBlock = block; this.CurrentBlock = block; }
protected virtual PDFLayoutBlock CreateContinerBlock(PDFPositionOptions position) { bool newPage = false; PDFLayoutBlock containerBlock = this.DocumentLayout.CurrentPage.LastOpenBlock(); PDFLayoutRegion containerRegion = containerBlock.CurrentRegion; if (containerRegion.HasOpenItem) { containerRegion.CloseCurrentItem(); } PDFUnit required = PDFUnit.Zero; if (position.Height.HasValue) { required = position.Height.Value; } //ADDED for min/max sizes. else if (position.MinimumHeight.HasValue) { required = position.MinimumHeight.Value; } //Do we have space if (containerRegion.AvailableHeight <= 0 || (containerRegion.AvailableHeight < required)) { if (this.MoveToNextRegion(required, ref containerRegion, ref containerBlock, out newPage) == false) { this.Context.TraceLog.Add(TraceLevel.Warning, LOG_CATEGORY, "Cannot fit the block for component " + this.Component.UniqueID + " in the avilable height (required = '" + position.Height + "', available = '" + containerRegion.AvailableHeight + "'), and we cannot overflow to a new region. Layout of component stopped and returning."); this.ContinueLayout = false; return(null); } } CurrentBlock = containerBlock.BeginNewContainerBlock(this.Component, this, this.FullStyle, position.PositionMode); CurrentBlock.BlockRepeatIndex = 0; return(containerBlock); }
/// <summary> /// Begins a header on a the current document page /// </summary> public void BeginHeader(PDFPageHeader owner, Style full, PDFLayoutContext context) { if (null != this.HeaderBlock) { throw RecordAndRaise.LayoutException(Errors.AlreadyAHeaderDefinedOnPage); } PDFLayoutBlock block = new PDFLayoutBlock(this, owner, this.Engine, full, OverflowSplit.Never); //Take the magins away from the total bounds before initializing the regions PDFRect content = this.ContentBlock.TotalBounds; if (this.PositionOptions.Margins.IsEmpty == false) { content.Width -= this.PositionOptions.Margins.Left + this.PositionOptions.Margins.Right; content.Height -= this.PositionOptions.Margins.Top + this.PositionOptions.Margins.Bottom; } block.InitRegions(content, this.ContentBlock.Position, full.CreateColumnOptions(), context); this._header = block; //Make this block current this.CurrentBlock = block; }
/// <summary> /// If there is no open line at the start, or after a hard return, then this created a new one (adding inset as required) /// </summary> /// <returns></returns> private PDFLayoutLine EnsureFirstLineAvailable(out bool startedLine) { startedLine = false; PDFLayoutPage pg = this.Context.DocumentLayout.CurrentPage; PDFLayoutBlock block = pg.LastOpenBlock(); if (null == block || block.IsClosed) { this.Context.TraceLog.Add(TraceLevel.Error, LOG_CATEGORY, "There is no open block on page '" + pg.ToString() + "' to add content to."); return(null); throw new InvalidOperationException("There is no open block to add the textual content to."); } PDFLayoutRegion reg = block.CurrentRegion; if (null == reg || reg.IsClosed) { this.Context.TraceLog.Add(TraceLevel.Error, LOG_CATEGORY, "There is no open region in block '" + block.ToString() + "' on page '" + pg.ToString() + "' to add content to."); return(null); throw new InvalidOperationException("There is no open block to add the textual content to."); } PDFLayoutLine line; if (reg.HasOpenItem) { line = (PDFLayoutLine)reg.CurrentItem; } else { line = reg.BeginNewLine(); startedLine = true; //No Inset spacer as this will be handled by the begin run } return(line); }
/// <summary> /// Returns the last open block in the hierarchy of layout blocks and regions. /// If there are no open blocks then returns null. /// </summary> /// <returns></returns> internal PDFLayoutBlock LastOpenBlock() { PDFLayoutBlock last = this.CurrentBlock; if (this.HeaderBlock != null && this.HeaderBlock.IsClosed == false) { last = this.HeaderBlock; } else if (this.FooterBlock != null && this.FooterBlock.IsClosed == false) { last = this.FooterBlock; } if (last.IsClosed) { last = null; } else { last = last.LastOpenBlock(); } return(last); }
public void PageWithMarginsPaddingAndFullWidthPanelWithMarginsAndPadding() { Document doc = new Document(); Page pg = new Page(); pg.Style.PageStyle.Width = PageWidth; pg.Style.PageStyle.Height = PageHeight; int margin = 20; int padding = 10; pg.Style.Padding.All = padding; pg.Style.Margins.All = margin; doc.Pages.Add(pg); int explicitHeight = 50; Panel panel = new Panel(); panel.FullWidth = true; panel.Height = explicitHeight; panel.Style.Margins.All = margin; panel.Style.Padding.All = padding; panel.BorderColor = Scryber.Drawing.PDFColors.Black; pg.Contents.Add(panel); using (var ms = DocStreams.GetOutputStream("PanelsFullWidthWithSpacingBoth.pdf")) { doc.LayoutComplete += Doc_LayoutComplete; doc.SaveAsPDF(ms); } PDFLayoutPage layoutpg = layout.AllPages[0]; PDFLayoutBlock content = layoutpg.ContentBlock; PDFLayoutRegion region = content.Columns[0]; //Panel in page content region PDFLayoutBlock panelBlock = region.Contents[0] as PDFLayoutBlock; Assert.IsNotNull(panelBlock, "The layout block in the page column should not be null"); //Expected measurements of the panel block //Width of fullwidth panel is reduced by margins and padding int expectedWidth = PageWidth - ((2 * margin) + (2 * padding)); //Actual height of the panel is explicit height + the margins int expectedHeight = explicitHeight + (2 * margin); //Position of panel is zero - margins and padding are accounted for when rendering int expectedX = 0; int expectedY = 0; //Panel width and height Assert.AreEqual(expectedWidth, panelBlock.Width, "Panel block should be " + expectedWidth + " wide"); Assert.AreEqual(expectedHeight, panelBlock.Height, "Panel block should be " + expectedHeight + " high"); //Panel Block Total bounds Assert.AreEqual(expectedWidth, panelBlock.TotalBounds.Width, "Panel block total width should be " + expectedWidth); Assert.AreEqual(expectedHeight, panelBlock.TotalBounds.Height, "Panel block total height should be " + expectedHeight); Assert.AreEqual(expectedX, panelBlock.TotalBounds.X, "Panel block total X should be " + expectedX); Assert.AreEqual(expectedY, panelBlock.TotalBounds.Y, "Panel block total Y should be " + expectedY); //As we have both padding and margins on the panel width and height are reduced for the available space. expectedWidth = (int)panelBlock.TotalBounds.Width.PointsValue - ((2 * margin) + (2 * padding)); expectedHeight = (int)panelBlock.TotalBounds.Height.PointsValue - ((2 * margin) + (2 * padding)); //X and Y of the available bounds (and also the inner region content) are offset by the padding. expectedX = padding + margin; expectedY = padding + margin; //Panel Block Available bounds Assert.AreEqual(expectedWidth, panelBlock.AvailableBounds.Width, "Panel block available width should be " + expectedWidth); Assert.AreEqual(expectedHeight, panelBlock.AvailableBounds.Height, "Panel block available height should be " + expectedHeight); Assert.AreEqual(expectedX, panelBlock.AvailableBounds.X, "Panel block available X should be " + expectedX); Assert.AreEqual(expectedY, panelBlock.AvailableBounds.Y, "Panel block available Y should be " + expectedY); //Panel inner region Assert.IsTrue(panelBlock.Columns.Length == 1, "There should be one region in the panel block"); region = panelBlock.Columns[0]; //region Total bounds Assert.AreEqual(expectedWidth, region.TotalBounds.Width, "Panel region total width should be " + expectedWidth); Assert.AreEqual(expectedHeight, region.TotalBounds.Height, "Panel region total height should be " + expectedHeight); Assert.AreEqual(0, region.TotalBounds.X, "Panel region total X should be 0"); Assert.AreEqual(0, region.TotalBounds.Y, "Panel region total Y should be 0"); //region Unused bounds Assert.AreEqual(expectedWidth, region.UnusedBounds.Width, "Panel region unused width should be " + expectedWidth); Assert.AreEqual(expectedHeight, region.UnusedBounds.Height, "Panel region unused height should be " + expectedHeight); Assert.AreEqual(0, region.UnusedBounds.X, "Panel region unused X should be 0"); Assert.AreEqual(0, region.UnusedBounds.Y, "Panel region unused Y should be 0"); //region Used Size Assert.AreEqual(0, region.UsedSize.Height, "Panel region used height should be 0"); Assert.AreEqual(0, region.UsedSize.Width, "Panel region used width should be 0"); //Region Offset and available height Assert.AreEqual(0, region.OffsetX, "Panel region offsetX should be 0"); Assert.AreEqual(expectedHeight, region.AvailableHeight, "Panel region available height should be " + expectedHeight); }
public void PageWithExplicitSizedPanel() { Document doc = new Document(); Page pg = new Page(); pg.Style.PageStyle.Width = PageWidth; pg.Style.PageStyle.Height = PageHeight; doc.Pages.Add(pg); int expectedWidth = 100; int expectedHeight = 50; Panel panel = new Panel(); panel.Width = expectedWidth; panel.Height = expectedHeight; panel.BorderColor = Scryber.Drawing.PDFColors.Black; pg.Contents.Add(panel); using (var ms = DocStreams.GetOutputStream("PanelsExplicitSizing.pdf")) { doc.LayoutComplete += Doc_LayoutComplete; doc.SaveAsPDF(ms); } Assert.AreEqual(1, layout.AllPages.Count, "There should be only 1 page"); PDFLayoutPage layoutpg = layout.AllPages[0]; //Page content block PDFLayoutBlock content = layoutpg.ContentBlock; Assert.IsTrue(content.Columns.Length == 1, "There should be only 1 column"); //Page content region PDFLayoutRegion region = content.Columns[0]; Assert.IsTrue(region.Contents.Count == 1, "There should be only one item in the region contents"); //Panel in content PDFLayoutBlock panelBlock = region.Contents[0] as PDFLayoutBlock; Assert.IsNotNull(panelBlock, "The layout block in the page column should not be null"); //Panel width and height Assert.AreEqual(expectedWidth, panelBlock.Width, "Panel block should be " + expectedWidth + " wide"); Assert.AreEqual(expectedHeight, panelBlock.Height, "Panel block should be " + expectedHeight + " high"); //Total bounds Assert.AreEqual(expectedWidth, panelBlock.TotalBounds.Width, "Panel block total width should be " + expectedWidth); Assert.AreEqual(expectedHeight, panelBlock.TotalBounds.Height, "Panel block total height should be " + expectedHeight); Assert.AreEqual(0, panelBlock.TotalBounds.X, "Panel block total X should be 0"); Assert.AreEqual(0, panelBlock.TotalBounds.Y, "Panel block total Y should be 0"); //Available bounds Assert.AreEqual(expectedWidth, panelBlock.AvailableBounds.Width, "Panel block available width should be " + expectedWidth); Assert.AreEqual(expectedHeight, panelBlock.AvailableBounds.Height, "Panel block available height should be " + expectedHeight); Assert.AreEqual(0, panelBlock.AvailableBounds.X, "Panel block available X should be 0"); Assert.AreEqual(0, panelBlock.AvailableBounds.Y, "Panel block available Y should be 0"); //Panel inner region Assert.IsTrue(panelBlock.Columns.Length == 1, "There should be one region in the panel block"); region = panelBlock.Columns[0]; //region Total bounds Assert.AreEqual(expectedWidth, region.TotalBounds.Width, "Panel region total width should be " + expectedWidth); Assert.AreEqual(expectedHeight, region.TotalBounds.Height, "Panel region total height should be " + expectedHeight); Assert.AreEqual(0, region.TotalBounds.X, "Panel region total X should be 0"); Assert.AreEqual(0, region.TotalBounds.Y, "Panel region total Y should be 0"); //region Unused bounds Assert.AreEqual(expectedWidth, region.UnusedBounds.Width, "Panel region unused width should be " + expectedWidth); Assert.AreEqual(expectedHeight, region.UnusedBounds.Height, "Panel region unused height should be " + expectedHeight); Assert.AreEqual(0, region.UnusedBounds.X, "Panel region unused X should be 0"); Assert.AreEqual(0, region.UnusedBounds.Y, "Panel region unused Y should be 0"); //region Used Size Assert.AreEqual(0, region.UsedSize.Height, "Panel region used height should be 0"); Assert.AreEqual(0, region.UsedSize.Width, "Panel region used width should be 0"); //Region Offset and available height Assert.AreEqual(0, region.OffsetX, "Panel region offsetX should be 0"); Assert.AreEqual(expectedHeight, region.AvailableHeight, "Panel region available height should be " + expectedHeight); }
public void PageWithMarginsPaddingAndFullWidthPanel() { Document doc = new Document(); Page pg = new Page(); pg.Style.PageStyle.Width = PageWidth; pg.Style.PageStyle.Height = PageHeight; int space = 20; pg.Style.Padding.All = space; pg.Style.Margins.All = space; doc.Pages.Add(pg); //Width of fullwidth panel is reduced by margins and padding int expectedWidth = PageWidth - ((2 * space) + (2 * space)); int expectedHeight = 50; //Position of panel is zero - margins and padding are accounted for when rendering int expectedX = 0; int expectedY = 0; Panel panel = new Panel(); panel.FullWidth = true; panel.Height = expectedHeight; panel.BorderColor = Scryber.Drawing.PDFColors.Black; pg.Contents.Add(panel); using (var ms = DocStreams.GetOutputStream("PanelsFullWidthWithSpacing.pdf")) { doc.LayoutComplete += Doc_LayoutComplete; doc.SaveAsPDF(ms); } Assert.AreEqual(1, layout.AllPages.Count, "There should be only 1 page"); PDFLayoutPage layoutpg = layout.AllPages[0]; //Page content block PDFLayoutBlock content = layoutpg.ContentBlock; Assert.IsTrue(content.Columns.Length == 1, "There should be only 1 column"); //Page content region PDFLayoutRegion region = content.Columns[0]; Assert.IsTrue(region.Contents.Count == 1, "There should be only one item in the region contents"); //Panel in content PDFLayoutBlock panelBlock = region.Contents[0] as PDFLayoutBlock; Assert.IsNotNull(panelBlock, "The layout block in the page column should not be null"); //Panel width and height Assert.AreEqual(expectedWidth, panelBlock.Width, "Panel block should be " + expectedWidth + " wide"); Assert.AreEqual(expectedHeight, panelBlock.Height, "Panel block should be " + expectedHeight + " high"); //Panel Block Total bounds Assert.AreEqual(expectedWidth, panelBlock.TotalBounds.Width, "Panel block total width should be " + expectedWidth); Assert.AreEqual(expectedHeight, panelBlock.TotalBounds.Height, "Panel block total height should be " + expectedHeight); Assert.AreEqual(expectedX, panelBlock.TotalBounds.X, "Panel block total X should be " + expectedX); Assert.AreEqual(expectedY, panelBlock.TotalBounds.Y, "Panel block total Y should be " + expectedY); //Panel Block Available bounds Assert.AreEqual(expectedWidth, panelBlock.AvailableBounds.Width, "Panel block available width should be " + expectedWidth); Assert.AreEqual(expectedHeight, panelBlock.AvailableBounds.Height, "Panel block available height should be " + expectedHeight); Assert.AreEqual(expectedX, panelBlock.AvailableBounds.X, "Panel block available X should be " + expectedX); Assert.AreEqual(expectedY, panelBlock.AvailableBounds.Y, "Panel block available Y should be " + expectedY); //Panel inner region Assert.IsTrue(panelBlock.Columns.Length == 1, "There should be one region in the panel block"); region = panelBlock.Columns[0]; //region Total bounds Assert.AreEqual(expectedWidth, region.TotalBounds.Width, "Panel region total width should be " + expectedWidth); Assert.AreEqual(expectedHeight, region.TotalBounds.Height, "Panel region total height should be " + expectedHeight); Assert.AreEqual(0, region.TotalBounds.X, "Panel region total X should be 0"); Assert.AreEqual(0, region.TotalBounds.Y, "Panel region total Y should be 0"); //region Unused bounds Assert.AreEqual(expectedWidth, region.UnusedBounds.Width, "Panel region unused width should be " + expectedWidth); Assert.AreEqual(expectedHeight, region.UnusedBounds.Height, "Panel region unused height should be " + expectedHeight); Assert.AreEqual(0, region.UnusedBounds.X, "Panel region unused X should be 0"); Assert.AreEqual(0, region.UnusedBounds.Y, "Panel region unused Y should be 0"); //region Used Size Assert.AreEqual(0, region.UsedSize.Height, "Panel region used height should be 0"); Assert.AreEqual(0, region.UsedSize.Width, "Panel region used width should be 0"); //Region Offset and available height Assert.AreEqual(0, region.OffsetX, "Panel region offsetX should be 0"); Assert.AreEqual(expectedHeight, region.AvailableHeight, "Panel region available height should be " + expectedHeight); }
/// <summary> /// Lays out a single list item based on the entry, and the list position options /// </summary> /// <param name="index"></param> /// <param name="entry"></param> /// <param name="listPosOpts"></param> /// <returns></returns> private PDFUnit LayoutAnItem(int index, ListNumberEntry entry, PDFPositionOptions listPosOpts) { //restore the items applied style onto the stack this.StyleStack.Push(entry.AppliedStyle); Style full = entry.FullStyle; PDFUnit numberWidth = entry.NumberWidth; PDFArtefactRegistrationSet artefacts = entry.ListItem.RegisterLayoutArtefacts(this.Context, full); PDFPositionOptions itemopts = full.CreatePostionOptions(); PDFUnit pageHeight = this.Context.DocumentLayout.CurrentPage.Height; PDFUnit h = pageHeight; PDFUnit w = _listBlock.AvailableBounds.Width; PDFUnit y = _itemoffset; PDFUnit alley = DefaultListItemAlley; if (itemopts.HasAlleyWidth) { alley = itemopts.AlleyWidth; } else if (listPosOpts.HasAlleyWidth) { alley = listPosOpts.AlleyWidth; } if (itemopts.Height.HasValue) { h = itemopts.Height.Value; } else if (itemopts.Margins.IsEmpty == false) { h -= itemopts.Margins.Top + itemopts.Margins.Bottom; } h -= itemopts.Padding.Top + itemopts.Padding.Bottom; if (itemopts.Width.HasValue) { w = itemopts.Width.Value; } else if (itemopts.Margins.IsEmpty == false) { w -= itemopts.Margins.Left + itemopts.Margins.Right; } w -= itemopts.Padding.Left + itemopts.Padding.Right; PDFRect totalBounds = new PDFRect(PDFUnit.Zero, y, w, h); this._itemblock = _listBlock.BeginNewContainerBlock(entry.ListItem, this, full, itemopts.PositionMode); PDFColumnOptions colOpts = new PDFColumnOptions() { AlleyWidth = alley, AutoFlow = false, ColumnCount = 2 }; this._itemblock.InitRegions(totalBounds, itemopts, colOpts, this.Context); //Alter the widths of the regions to allow for only the number width PDFRect region1bounds = this._itemblock.Columns[0].TotalBounds; PDFUnit difference = region1bounds.Width - numberWidth; region1bounds.Width = numberWidth; this._itemblock.Columns[0].TotalBounds = region1bounds; this._itemblock.Columns[0].HAlignment = entry.NumberAlignment; PDFRect region2Bounds = this._itemblock.Columns[1].TotalBounds; if (region2Bounds.X > 0) { region2Bounds.X -= difference; } region2Bounds.Width += difference; this._itemblock.Columns[1].TotalBounds = region2Bounds; PDFUnit numberHeight = this.LayoutItemNumber(entry, full); this._itemblock.CurrentRegion.Close(); bool success = this._itemblock.MoveToNextRegion(true, PDFUnit.Zero, this.Context); //Pass Zero as we are not interested in overflowing yet PDFUnit contentHeight = this.LayoutItemContent(entry); //check that we can fit - addind the margins and padding back in. PDFUnit itemHeight = PDFUnit.Max(numberHeight, contentHeight); if (itemopts.Height.HasValue) { itemHeight = itemopts.Height.Value; } else if (itemopts.Margins.IsEmpty == false) { itemHeight += itemopts.Margins.Top + itemopts.Margins.Bottom; } itemHeight += itemopts.Padding.Top + itemopts.Padding.Bottom; if (itemHeight > this._listBlock.AvailableBounds.Height - _itemoffset) { PDFLayoutBlock origparent = this.CurrentBlock; PDFLayoutRegion origregion = this.CurrentBlock.CurrentRegion; PDFLayoutBlock origlist = this._listBlock; PDFLayoutBlock origItem = this._itemblock; if (this._listBlock.Position.OverflowSplit == OverflowSplit.Never) { if (this.MoveFullListToNextRegion(_itemoffset + itemHeight)) { //_itemoffset += itemHeight; //PDFRect avail = _listBlock.AvailableBounds; //avail.Height = avail.Height - _itemoffset; } else { this.Context.TraceLog.Add(TraceLevel.Warning, LOG_CATEGORY, "List '" + this.List.UniqueID + "' has filled the available space, and cannot overflow onto a new region. Layout has stopped at item index " + index); this.ContinueLayout = false; return(0); } } else if (this.StartListInAnotherRegion(itemHeight, origItem, index)) { //origregion.AddToSize(origlist); _itemoffset = 0; origItem.Offset(0, 0); } else { (origItem.Parent as PDFLayoutBlock).CurrentRegion.RemoveItem(origItem); this.Context.TraceLog.Add(TraceLevel.Warning, LOG_CATEGORY, "List '" + this.List.UniqueID + "' has filled the available space, and cannot overflow onto a new region. Layout has stopped at item index " + index); this.ContinueLayout = false; } } else if (this._itemblock.CurrentRegion.IsClosed) { this._itemblock = this.CurrentBlock.LastOpenBlock(); this._listBlock = this._itemblock.Parent as PDFLayoutBlock; } if (null != this._itemblock) { if (this._itemblock.CurrentRegion.IsClosed == false) { this._itemblock.CurrentRegion.Close(); } if (this._itemblock.IsClosed == false) { this._itemblock.Close(); this._listBlock.CurrentRegion.AddToSize(this._itemblock); } } if (this.ContinueLayout) { RegisterChildLayout(entry.ListItem); } if (null != artefacts) { entry.ListItem.CloseLayoutArtefacts(this.Context, artefacts, full); } this.StyleStack.Pop(); return(itemHeight); }
/// <summary> /// Checks the overflow style and if new pages are supported closes the current page layout and /// creates a new page layout (becomming the current page) and returns true. /// If overflow is not supported - returns false /// </summary> /// <param name="region">If there is a change in current page, this is set to the new region</param> /// <param name="block">If there is a change in current page, this is set to the new block</param> /// <returns></returns> public override bool MoveToNextPage(IPDFComponent initiator, Style initiatorStyle, Stack <PDFLayoutBlock> depth, ref PDFLayoutRegion region, ref PDFLayoutBlock block) { StyleValue <OverflowAction> action; if (this.FullStyle.TryGetValue(StyleKeys.OverflowActionKey, out action) && action.Value == OverflowAction.NewPage) { PDFLayoutPage lastpage = this.DocumentLayout.CurrentPage; PDFLayoutBlock open = lastpage.ContentBlock; if (open.IsClosed) { open = null; } else { open = open.LastOpenBlock(); } List <PDFLayoutBlock> toclose = new List <PDFLayoutBlock>(depth); for (int i = toclose.Count - 1; i >= 0; i--) { open = toclose[i]; if (open.CurrentRegion != null && open.CurrentRegion.IsClosed == false) { PDFLayoutRegion openRegion = open.CurrentRegion; openRegion.Close(); } PDFLayoutBlock parent = open.Parent as PDFLayoutBlock; if (null != parent) { PDFLayoutRegion parentRegion = parent.CurrentRegion; if (null != parentRegion) { open.Close(); parentRegion.AddToSize(open); } } //open = parent; } lastpage.Close(); var pgSize = this.GetNextPageSize(initiator, initiatorStyle, lastpage.Size); PDFLayoutPage page = BuildContinuationPage(lastpage, pgSize); block = page.CurrentBlock; region = block.CurrentRegion; if (this.Context.ShouldLogVerbose) { this.Context.TraceLog.Add(TraceLevel.Verbose, LOG_CATEGORY, "Built a new continuation page for " + this.Component + " and recreated the " + toclose.Count + " blocks and regions on the new page"); } return(true); } else { if (this.Context.ShouldLogVerbose) { this.Context.TraceLog.Add(TraceLevel.Verbose, LOG_CATEGORY, "Cannot overflow content for page " + this.Component + " halting the continued layout by returning false"); } return(false); //Cannot overflow } }
public bool MoveToNextPage(IPDFComponent initiator, Style initiatorStyle, Stack <PDFLayoutBlock> depth, ref PDFLayoutRegion region, ref PDFLayoutBlock block) { throw new NotSupportedException("TextLayoutEngine should never be the top layout engine - and therefore should never control pages"); }
// // .ctor // #region public PDFLayoutPositionedRegion(...) /// <summary> /// Instantiates a new positioned region - relative or absolute. /// </summary> /// <param name="block"></param> /// <param name="owner"></param> /// <param name="contentbounds"></param> /// <param name="columnindex"></param> /// <param name="position"></param> public PDFLayoutPositionedRegion(PDFLayoutBlock block, IPDFComponent owner, PDFRect contentbounds, int columnindex, PDFPositionOptions position) : base(block, owner, contentbounds, columnindex, position.HAlign, position.VAlign, position.PositionMode) { this.PositionOptions = position; }
protected void EnsureContentsFit() { bool newPage; PDFLayoutBlock block = this.CurrentBlock; //re-retrieve our container block and region //it could have changed whilst laying out other regions / pages. PDFLayoutBlock containerBlock = block.Parent as PDFLayoutBlock; if (block.IsClosed == false) { block.Close(); } bool updateSize = false; PDFSize updated = block.Size; if (block.Position.MinimumHeight.HasValue && block.Height < block.Position.MinimumHeight.Value) { updated.Height = block.Position.MinimumHeight.Value - (block.Position.Padding.Top + block.Position.Padding.Bottom); updateSize = true; } if (block.Position.MinimumWidth.HasValue && block.Width < block.Position.MinimumWidth.Value) { updated.Width = block.Position.MinimumWidth.Value - (block.Position.Padding.Left + block.Position.Padding.Right); updateSize = true; } if (updateSize) { block.SetContentSize(updated.Width, updated.Height); } PDFLayoutRegion containerRegion = containerBlock.CurrentRegion; //ADDED to support blocks flowing to the next region or page PDFUnit vspace = containerRegion.TotalBounds.Height - containerRegion.UsedSize.Height; PDFUnit req = block.Height; bool canfitvertical = req <= vspace; if (!canfitvertical && containerRegion.Contents.Count > 1) { PDFLayoutRegion prev = containerRegion; if (this.MoveToNextRegion(req, ref containerRegion, ref containerBlock, out newPage)) { prev.Contents.Remove(block); containerRegion.AddExistingItem(block); } else { this.Context.TraceLog.Add(TraceLevel.Warning, LOG_CATEGORY, "Cannot fit the block for component " + this.Component.UniqueID + " in the avilable height (required = '" + req + "', available = '" + vspace + "'), and we cannot overflow to a new region. Layout of component stopped and returning."); this.ContinueLayout = false; } } else { //Region has not updated its size as the block was directly closed. containerRegion.AddToSize(block); } }
// // ctor(s) // #region public PDFLayoutRegion(PDFLayoutBlock block, IPDFComponent owner, PDFRect contentbounds, int columnindex, HorizontalAlignment halign, VerticalAlignment valign) public PDFLayoutRegion(PDFLayoutBlock block, IPDFComponent owner, PDFRect contentbounds, int columnindex, HorizontalAlignment halign, VerticalAlignment valign) : this(block, owner, contentbounds, columnindex, halign, valign, PositionMode.Block) { }
// // main override // #region protected override void DoLayoutComponent() /// <summary> /// Performs the actual layout of the list and items in it. /// </summary> protected override void DoLayoutComponent() { if (this.Context.ShouldLogDebug) { this.Context.TraceLog.Begin(TraceLevel.Debug, ListEngineLogCategory, string.Format("Starting the layout of the list {0}", this.List.ID)); } this.ContinueLayout = true; this.CurrentBlock = this.Context.DocumentLayout.CurrentPage.LastOpenBlock(); if (this.CurrentBlock.CurrentRegion != null && this.CurrentBlock.CurrentRegion.HasOpenItem) { this.CurrentBlock.CurrentRegion.CloseCurrentItem(); } PDFPositionOptions pos = this.FullStyle.CreatePostionOptions(); //Set up the outer container block that will hold the list and all it's items _listBlock = this.CurrentBlock.BeginNewContainerBlock(this.List, this, this.FullStyle, pos.PositionMode); PDFRect bounds = this.CurrentBlock.CurrentRegion.UnusedBounds; if (bounds.X > 0) { bounds.X = PDFUnit.Zero; } if (pos.Width.HasValue) { bounds.Width = pos.Width.Value; } else if (pos.Margins.IsEmpty == false) { bounds.Width -= pos.Margins.Left + pos.Margins.Right; } if (pos.Height.HasValue) { bounds.Height = pos.Height.Value; } else if (pos.Margins.IsEmpty == false) { bounds.Height -= pos.Margins.Top + pos.Margins.Bottom; } PDFColumnOptions columnOptions = new PDFColumnOptions() { AlleyWidth = PDFUnit.Zero, AutoFlow = false, ColumnCount = 1 }; _listBlock.InitRegions(bounds, pos, columnOptions, this.Context); this.OpenListNumbering(); this.BuildListEntries(out _itemNumberWidth); this.LayoutListItems(pos); _listBlock.CurrentRegion.CloseCurrentItem(); _listBlock.CurrentRegion.Close(); _listBlock.Close(); this.CurrentBlock.CurrentRegion.AddToSize(_listBlock); if (this.Context.ShouldLogDebug) { this.Context.TraceLog.End(TraceLevel.Debug, ListEngineLogCategory, string.Format("Completed the layout of the list {0}", this.List.ID)); } this.CloseListNumbering(); }
public PDFLayoutBlock CloseCurrentBlockAndStartNewInRegion(PDFLayoutBlock blockToClose, PDFLayoutRegion joinToRegion) { throw new NotSupportedException("CloseCurrentBlockAndStartNewInRegion should never be called on the text layout engine."); }