private void CalcTableSize(RGraphics g) { if (Display != CssConstants.None) { RectanglesReset(); MeasureWordsSize(g); } double width = ContainingBlock.Size.Width - ContainingBlock.ActualPaddingLeft - ContainingBlock.ActualPaddingRight - ContainingBlock.ActualBorderLeftWidth - ContainingBlock.ActualBorderRightWidth; double height = ContainingBlock.Size.Height - ContainingBlock.ActualPaddingTop - ContainingBlock.ActualPaddingBottom - ContainingBlock.ActualBorderTopWidth - ContainingBlock.ActualBorderBottomWidth; bool _widthSpecified = false; bool _heightSpecified = false; if (Width != CssConstants.Auto && !string.IsNullOrEmpty(Width)) { width = CssValueParser.ParseLength(Width, width, this); _widthSpecified = width > 0 ? true : false; } if (Height != CssConstants.Auto && !string.IsNullOrEmpty(Height)) { height = CssValueParser.ParseLength(Height, height, this); _heightSpecified = height > 0 ? true : false; } Size = new RSize(_widthSpecified ? width : 0, _heightSpecified ? height : 0); }
/// <summary> /// Measures the bounds of box and children, recursively.<br/> /// Performs layout of the DOM structure creating lines by set bounds restrictions. /// </summary> /// <param name="g">Device context to use</param> protected override void PerformLayoutImp(IGraphics g) { if (Display == CssConstants.None) { return; } RectanglesReset(); CssBox prevSibling = DomUtils.GetPreviousSibling(this); float left = ContainingBlock.Location.X + ContainingBlock.ActualPaddingLeft + ActualMarginLeft + ContainingBlock.ActualBorderLeftWidth; float top = (prevSibling == null && ParentBox != null ? ParentBox.ClientTop : ParentBox == null ? Location.Y : 0) + MarginTopCollapse(prevSibling) + (prevSibling != null ? prevSibling.ActualBottom + prevSibling.ActualBorderBottomWidth : 0); Location = new PointF(left, top); ActualBottom = top; //width at 100% (or auto) float minwidth = GetMinimumWidth(); float width = ContainingBlock.Size.Width - ContainingBlock.ActualPaddingLeft - ContainingBlock.ActualPaddingRight - ContainingBlock.ActualBorderLeftWidth - ContainingBlock.ActualBorderRightWidth - ActualMarginLeft - ActualMarginRight - ActualBorderLeftWidth - ActualBorderRightWidth; //Check width if not auto if (Width != CssConstants.Auto && !string.IsNullOrEmpty(Width)) { width = CssValueParser.ParseLength(Width, width, this); } if (width < minwidth || width >= 9999) { width = minwidth; } float height = ActualHeight; if (height < 1) { height = Size.Height + ActualBorderTopWidth + ActualBorderBottomWidth; } if (height < 1) { height = 2; } if (height <= 2 && ActualBorderTopWidth < 1 && ActualBorderBottomWidth < 1) { BorderTopStyle = BorderBottomStyle = CssConstants.Solid; BorderTopWidth = "1px"; BorderBottomWidth = "1px"; } Size = new SizeF(width, height); ActualBottom = Location.Y + ActualPaddingTop + ActualPaddingBottom + height; }
/// <summary> /// Gets the white space width of the specified box /// </summary> /// <param name="g"></param> /// <param name="box"></param> /// <returns></returns> public static double WhiteSpace(RGraphics g, CssBoxProperties box) { double w = box.ActualFont.GetWhitespaceWidth(g); if (!(String.IsNullOrEmpty(box.WordSpacing) || box.WordSpacing == CssConstants.Normal)) { w += CssValueParser.ParseLength(box.WordSpacing, 0, box, true); } return(w); }
/// <summary> /// Gets the white space width of the specified box /// </summary> /// <param name="g"></param> /// <param name="box"></param> /// <returns></returns> public static float WhiteSpace(Graphics g, CssBoxProperties box) { float w = MeasureWhitespace(g, box.ActualFont); if (!(String.IsNullOrEmpty(box.WordSpacing) || box.WordSpacing == CssConstants.Normal)) { w += CssValueParser.ParseLength(box.WordSpacing, 0, box, true); } return(w); }
/// <summary> /// Measures the bounds of box and children, recursively.<br/> /// Performs layout of the DOM structure creating lines by set bounds restrictions. /// </summary> /// <param name="g">Device context to use</param> protected override void PerformLayoutImp(RGraphics g) { if (this.Display == CssConstants.None) { return; } this.RectanglesReset(); var prevSibling = DomUtils.GetPreviousSibling(this); double left = this.ContainingBlock.Location.X + this.ContainingBlock.ActualPaddingLeft + this.ActualMarginLeft + this.ContainingBlock.ActualBorderLeftWidth; double top = (prevSibling == null && this.ParentBox != null ? this.ParentBox.ClientTop : this.ParentBox == null ? this.Location.Y : 0) + this.MarginTopCollapse(prevSibling) + (prevSibling != null ? prevSibling.ActualBottom + prevSibling.ActualBorderBottomWidth : 0); this.Location = new RPoint(left, top); this.ActualBottom = top; //width at 100% (or auto) double minwidth = this.GetMinimumWidth(); double width = this.ContainingBlock.Size.Width - this.ContainingBlock.ActualPaddingLeft - this.ContainingBlock.ActualPaddingRight - this.ContainingBlock.ActualBorderLeftWidth - this.ContainingBlock.ActualBorderRightWidth - this.ActualMarginLeft - this.ActualMarginRight - this.ActualBorderLeftWidth - this.ActualBorderRightWidth; //Check width if not auto if (this.Width != CssConstants.Auto && !string.IsNullOrEmpty(this.Width)) { width = CssValueParser.ParseLength(this.Width, width, this); } if (width < minwidth || width >= 9999) { width = minwidth; } double height = this.ActualHeight; if (height < 1) { height = this.Size.Height + this.ActualBorderTopWidth + this.ActualBorderBottomWidth; } if (height < 1) { height = 2; } if (height <= 2 && this.ActualBorderTopWidth < 1 && this.ActualBorderBottomWidth < 1) { this.BorderTopStyle = this.BorderBottomStyle = CssConstants.Solid; this.BorderTopWidth = "1px"; this.BorderBottomWidth = "1px"; } this.Size = new RSize(width, height); this.ActualBottom = this.Location.Y + this.ActualPaddingTop + this.ActualPaddingBottom + height; }
/// <summary> /// Gets the available width for the whole table. /// It also sets the value of WidthSpecified /// </summary> /// <returns></returns> /// <remarks> /// The table's width can be larger than the result of this method, because of the minimum /// size that individual boxes. /// </remarks> private double GetMaxTableWidth() { var tblen = new CssLength(_tableBox.MaxWidth); if (tblen.Number > 0) { _widthSpecified = true; return(CssValueParser.ParseLength(_tableBox.MaxWidth, _tableBox.ParentBox.AvailableWidth, _tableBox)); } return(9999f); }
/// <summary> /// Measures the width of whitespace between words (set <see cref="ActualWordSpacing"/>). /// </summary> protected void MeasureWordSpacing(RGraphics g) { if (double.IsNaN(ActualWordSpacing)) { _actualWordSpacing = CssUtils.WhiteSpace(g, this); if (WordSpacing != CssConstants.Normal) { string len = RegexParserUtils.Search(RegexParserUtils.CssLength, WordSpacing); _actualWordSpacing += CssValueParser.ParseLength(len, 1, this); } } }
/// <summary> /// Gets the available width for the whole table. /// It also sets the value of WidthSpecified /// </summary> /// <returns></returns> /// <remarks> /// The table's width can be larger than the result of this method, because of the minimum /// size that individual boxes. /// </remarks> private double GetAvailableTableWidth() { CssLength tblen = new CssLength(_tableBox.Width); if (tblen.Number > 0) { _widthSpecified = true; return(CssValueParser.ParseLength(_tableBox.Width, _tableBox.ParentBox.AvailableWidth, _tableBox)); } else { return(_tableBox.ParentBox.AvailableWidth); } }
public void ParseCssBoxWidth(CssBox box) { if (!(_parentLength == 0 && box.Width.Trim().EndsWith("%"))) { value = CssValueParser.ParseLength(box.Width, _parentLength, box); } if (!(_parentLength == 0 && box.MaxWidth.Trim().EndsWith("%"))) { max = CssValueParser.ParseLength(box.MaxWidth, _parentLength, box); } if (!(_parentLength == 0 && box.MinWidth.Trim().EndsWith("%"))) { min = CssValueParser.ParseLength(box.MinWidth, _parentLength, box); } }
public void ParseCssBoxHeight(CssBox box) { if (!(_parentLength == 0 && box.Height.Trim().EndsWith("%"))) { value = CssValueParser.ParseLength(box.Height, _parentLength, box); } if (!(_parentLength == 0 && box.MaxHeight.Trim().EndsWith("%"))) { max = CssValueParser.ParseLength(box.MaxHeight, _parentLength, box); } if (!(_parentLength == 0 && box.MinHeight.Trim().EndsWith("%"))) { min = CssValueParser.ParseLength(box.MinHeight, _parentLength, box); } }
/// <summary> /// Determine Row and Column Count, and ColumnWidths /// </summary> /// <returns></returns> private double CalculateCountAndWidth() { //Columns if (_columns.Count > 0) { _columnCount = _columns.Count; } else { foreach (CssBox b in _allRows) { _columnCount = Math.Max(_columnCount, b.Boxes.Count); } } //Initialize column widths array with NaNs _columnWidths = new double[_columnCount]; for (int i = 0; i < _columnWidths.Length; i++) { _columnWidths[i] = double.NaN; } double availCellSpace = GetAvailableCellWidth(); if (_columns.Count > 0) { // Fill ColumnWidths array by scanning column widths for (int i = 0; i < _columns.Count; i++) { CssLength len = new CssLength(_columns[i].Width); //Get specified width if (len.Number > 0) //If some width specified { if (len.IsPercentage) //Get width as a percentage { _columnWidths[i] = CssValueParser.ParseNumber(_columns[i].Width, availCellSpace); } else if (len.Unit == CssUnit.Pixels || len.Unit == CssUnit.None) { _columnWidths[i] = len.Number; //Get width as an absolute-pixel value } } } } else { // Fill ColumnWidths array by scanning width in table-cell definitions foreach (CssBox row in _allRows) { //Check for column width in table-cell definitions for (int i = 0; i < _columnCount; i++) { if (i < 20 || double.IsNaN(_columnWidths[i])) // limit column width check { if (i < row.Boxes.Count && row.Boxes[i].Display == CssConstants.TableCell) { double len = CssValueParser.ParseLength(row.Boxes[i].Width, availCellSpace, row.Boxes[i]); if (len > 0) //If some width specified { int colspan = GetColSpan(row.Boxes[i]); len /= Convert.ToSingle(colspan); for (int j = i; j < i + colspan; j++) { _columnWidths[j] = double.IsNaN(_columnWidths[j]) ? len : Math.Max(_columnWidths[j], len); } } } } } } } return(availCellSpace); }
/// <summary> /// Get top-left location to start drawing the image at depending on background-position value. /// </summary> /// <param name="backgroundPosition">the background-position value</param> /// <param name="rectangle">the rectangle to position image in</param> /// <param name="imgSize">the size of the image</param> /// <returns>the top-left location</returns> private static RPoint GetLocation(string backgroundPosition, RRect rectangle, RSize imgSize, CssBox box) { double left = rectangle.Left; double top = rectangle.Top; if (backgroundPosition.Trim().ToLower() == "inherit") { return(new RPoint(left, top)); } string[] bp = backgroundPosition.Trim().Split(' '); string lr_str = ""; string tb_str = ""; foreach (var value in bp) { var val = value.Trim(); if (val == "") { continue; } if (lr_str == "") { lr_str = val.ToLower(); continue; } if (tb_str == "") { tb_str = val.ToLower(); continue; } //3d word found fallback to (0,0) return(new RPoint(left, top)); } if (tb_str == "") { tb_str = lr_str; } switch (lr_str) { case "left": break; case "right": left = rectangle.Right - imgSize.Width; break; case "center": left += (rectangle.Width - imgSize.Width) / 2; break; default: left += CssValueParser.ParseLength(lr_str, rectangle.Width, box); break; } switch (tb_str) { case "top": break; case "bottom": top = rectangle.Bottom - imgSize.Height; break; case "center": top += (rectangle.Height - imgSize.Height) / 2; break; default: top += CssValueParser.ParseLength(tb_str, rectangle.Height, box); break; } return(new RPoint(left, top)); }
/// <summary> /// Measures the bounds of box and children, recursively.<br/> /// Performs layout of the DOM structure creating lines by set bounds restrictions. /// </summary> /// <param name="g">Device context to use</param> private void MeasureBoundsImp(Graphics g) { if (Display == CssConstants.None) { return; } RectanglesReset(); MeasureWordsSize(g); if (Display == CssConstants.Block || Display == CssConstants.ListItem || Display == CssConstants.Table || Display == CssConstants.InlineTable || Display == CssConstants.TableCell || Display == CssConstants.None) { if (Display != CssConstants.TableCell) { var prevSibling = DomUtils.GetPreviousSibling(this); float left = ContainingBlock.Location.X + ContainingBlock.ActualPaddingLeft + ActualMarginLeft + ContainingBlock.ActualBorderLeftWidth; float top = (prevSibling == null && ParentBox != null ? ParentBox.ClientTop : ParentBox == null ? Location.Y : 0) + MarginTopCollapse(prevSibling) + (prevSibling != null ? prevSibling.ActualBottom + prevSibling.ActualBorderBottomWidth : 0); Location = new PointF(left, top); ActualBottom = top; } // Because their width and height are set by CssTable if (Display != CssConstants.TableCell && Display != CssConstants.Table) { //width at 100% (or auto) float minwidth = GetMinimumWidth(); float width = ContainingBlock.Size.Width - ContainingBlock.ActualPaddingLeft - ContainingBlock.ActualPaddingRight - ContainingBlock.ActualBorderLeftWidth - ContainingBlock.ActualBorderRightWidth - ActualMarginLeft - ActualMarginRight - ActualBorderLeftWidth - ActualBorderRightWidth; //Check width if not auto if (Width != CssConstants.Auto && !string.IsNullOrEmpty(Width)) { width = CssValueParser.ParseLength(Width, width, this); } if (width < minwidth || width >= 9999) { width = minwidth; } Size = new SizeF(width, Size.Height); } //If we're talking about a table here.. if (Display == CssConstants.Table || Display == CssConstants.InlineTable) { new CssTable(this, g); } else { //If there's just inlines, create LineBoxes if (DomUtils.ContainsInlinesOnly(this)) { ActualBottom = Location.Y; CssLayoutEngine.CreateLineBoxes(g, this); //This will automatically set the bottom of this block } else if (_boxes.Count > 0) { foreach (var childBox in Boxes) { childBox.MeasureBoundsImp(g); } ActualBottom = MarginBottomCollapse(); } } } if (HtmlContainer != null) { HtmlContainer.ActualSize = new SizeF(Math.Max(HtmlContainer.ActualSize.Width, Size.Width < 9999 ? Size.Width : 0), Math.Max(HtmlContainer.ActualSize.Height, Size.Height)); } }