/// <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) { double left = rectangle.Left; if (backgroundPosition.IndexOf("left", StringComparison.OrdinalIgnoreCase) > -1) { left = (rectangle.Left + .5f); } else if (backgroundPosition.IndexOf("right", StringComparison.OrdinalIgnoreCase) > -1) { left = rectangle.Right - imgSize.Width; } else if (backgroundPosition.IndexOf("0", StringComparison.OrdinalIgnoreCase) < 0) { left = (rectangle.Left + (rectangle.Width - imgSize.Width) / 2 + .5f); } double top = rectangle.Top; if (backgroundPosition.IndexOf("top", StringComparison.OrdinalIgnoreCase) > -1) { top = rectangle.Top; } else if (backgroundPosition.IndexOf("bottom", StringComparison.OrdinalIgnoreCase) > -1) { top = rectangle.Bottom - imgSize.Height; } else if (backgroundPosition.IndexOf("0", StringComparison.OrdinalIgnoreCase) < 0) { top = (rectangle.Top + (rectangle.Height - imgSize.Height) / 2 + .5f); } return new RPoint(left, top); }
/// <summary> /// Initializes a new instance of the <see cref="RRect" /> class with the specified location and size. /// </summary> /// <param name="location">A <see cref="RPoint" /> that represents the upper-left corner of the rectangular region.</param> /// <param name="size">A <see cref="RSize" /> that represents the width and height of the rectangular region.</param> public RRect(RPoint location, RSize size) { _x = location.X; _y = location.Y; _width = size.Width; _height = size.Height; }
/// <summary> /// Measure the size of the html by performing layout under the given restrictions. /// </summary> /// <param name="g">the graphics to use</param> /// <param name="htmlContainer">the html to calculate the layout for</param> /// <param name="minSize">the minimal size of the rendered html (zero - not limit the width/height)</param> /// <param name="maxSize">the maximum size of the rendered html, if not zero and html cannot be layout within the limit it will be clipped (zero - not limit the width/height)</param> /// <returns>return: the size of the html to be rendered within the min/max limits</returns> public static RSize MeasureHtmlByRestrictions(RGraphics g, HtmlContainerInt htmlContainer, RSize minSize, RSize maxSize) { // first layout without size restriction to know html actual size htmlContainer.PerformLayout(g); if (maxSize.Width > 0 && maxSize.Width < htmlContainer.ActualSize.Width) { // to allow the actual size be smaller than max we need to set max size only if it is really larger htmlContainer.MaxSize = new RSize(maxSize.Width, 0); htmlContainer.PerformLayout(g); } // restrict the final size by min/max var finalWidth = Math.Max(maxSize.Width > 0 ? Math.Min(maxSize.Width, (int)htmlContainer.ActualSize.Width) : (int)htmlContainer.ActualSize.Width, minSize.Width); // if the final width is larger than the actual we need to re-layout so the html can take the full given width. if (finalWidth > htmlContainer.ActualSize.Width) { htmlContainer.MaxSize = new RSize(finalWidth, 0); htmlContainer.PerformLayout(g); } var finalHeight = Math.Max(maxSize.Height > 0 ? Math.Min(maxSize.Height, (int)htmlContainer.ActualSize.Height) : (int)htmlContainer.ActualSize.Height, minSize.Height); return new RSize(finalWidth, finalHeight); }
/// <summary> /// Perform the layout of the html container by given size restrictions returning the final size.<br/> /// The layout can be effected by the HTML content in the <paramref name="htmlContainer"/> if <paramref name="autoSize"/> or /// <paramref name="autoSizeHeightOnly"/> is set to true.<br/> /// Handle minimum and maximum size restrictions.<br/> /// Handle auto size and auto size for height only. if <paramref name="autoSize"/> is true <paramref name="autoSizeHeightOnly"/> /// is ignored.<br/> /// </summary> /// <param name="g">the graphics used for layout</param> /// <param name="htmlContainer">the html container to layout</param> /// <param name="size">the current size</param> /// <param name="minSize">the min size restriction - can be empty for no restriction</param> /// <param name="maxSize">the max size restriction - can be empty for no restriction</param> /// <param name="autoSize">if to modify the size (width and height) by html content layout</param> /// <param name="autoSizeHeightOnly">if to modify the height by html content layout</param> public static RSize Layout(RGraphics g, HtmlContainerInt htmlContainer, RSize size, RSize minSize, RSize maxSize, bool autoSize, bool autoSizeHeightOnly) { if (autoSize) htmlContainer.MaxSize = new RSize(0, 0); else if (autoSizeHeightOnly) htmlContainer.MaxSize = new RSize(size.Width, 0); else htmlContainer.MaxSize = size; htmlContainer.PerformLayout(g); RSize newSize = size; if (autoSize || autoSizeHeightOnly) { if (autoSize) { if (maxSize.Width > 0 && maxSize.Width < htmlContainer.ActualSize.Width) { // to allow the actual size be smaller than max we need to set max size only if it is really larger htmlContainer.MaxSize = maxSize; htmlContainer.PerformLayout(g); } else if (minSize.Width > 0 && minSize.Width > htmlContainer.ActualSize.Width) { // if min size is larger than the actual we need to re-layout so all 100% layouts will be correct htmlContainer.MaxSize = new RSize(minSize.Width, 0); htmlContainer.PerformLayout(g); } newSize = htmlContainer.ActualSize; } else if (Math.Abs(size.Height - htmlContainer.ActualSize.Height) > 0.01) { var prevWidth = size.Width; // make sure the height is not lower than min if given newSize.Height = minSize.Height > 0 && minSize.Height > htmlContainer.ActualSize.Height ? minSize.Height : htmlContainer.ActualSize.Height; // handle if changing the height of the label affects the desired width and those require re-layout if (Math.Abs(prevWidth - size.Width) > 0.01) return Layout(g, htmlContainer, size, minSize, maxSize, false, true); } } return newSize; }
/// <summary> /// Draw the background image of the given box in the given rectangle.<br/> /// Handle background-repeat and background-position values. /// </summary> /// <param name="g">the device to draw into</param> /// <param name="box">the box to draw its background image</param> /// <param name="imageLoadHandler">the handler that loads image to draw</param> /// <param name="rectangle">the rectangle to draw image in</param> public static void DrawBackgroundImage(RGraphics g, CssBox box, ImageLoadHandler imageLoadHandler, RRect rectangle) { // image size depends if specific rectangle given in image loader var imgSize = new RSize(imageLoadHandler.Rectangle == RRect.Empty ? imageLoadHandler.Image.Width : imageLoadHandler.Rectangle.Width, imageLoadHandler.Rectangle == RRect.Empty ? imageLoadHandler.Image.Height : imageLoadHandler.Rectangle.Height); // get the location by BackgroundPosition value var location = GetLocation(box.BackgroundPosition, rectangle, imgSize); var srcRect = imageLoadHandler.Rectangle == RRect.Empty ? new RRect(0, 0, imgSize.Width, imgSize.Height) : new RRect(imageLoadHandler.Rectangle.Left, imageLoadHandler.Rectangle.Top, imgSize.Width, imgSize.Height); // initial image destination rectangle var destRect = new RRect(location, imgSize); // need to clip so repeated image will be cut on rectangle var lRectangle = rectangle; lRectangle.Intersect(g.GetClip()); g.PushClip(lRectangle); switch (box.BackgroundRepeat) { case "no-repeat": g.DrawImage(imageLoadHandler.Image, destRect, srcRect); break; case "repeat-x": DrawRepeatX(g, imageLoadHandler, rectangle, srcRect, destRect, imgSize); break; case "repeat-y": DrawRepeatY(g, imageLoadHandler, rectangle, srcRect, destRect, imgSize); break; default: DrawRepeat(g, imageLoadHandler, rectangle, srcRect, destRect, imgSize); break; } g.PopClip(); }
/// <summary> /// Perform the layout of the html in the control. /// </summary> protected override Size MeasureOverride(Size constraint) { if (_htmlContainer != null) { using (var ig = new GraphicsAdapter()) { var horizontal = Padding.Left + Padding.Right + BorderThickness.Left + BorderThickness.Right; var vertical = Padding.Top + Padding.Bottom + BorderThickness.Top + BorderThickness.Bottom; var size = new Size(Math.Min(MaxWidth, constraint.Width), Math.Min(MaxHeight, constraint.Height)); var maxSize = new RSize(size.Width < Double.PositiveInfinity ? size.Width - horizontal : 0, size.Height < Double.PositiveInfinity ? size.Height - vertical : 0); _htmlContainer.HtmlContainerInt.MaxSize = maxSize; _htmlContainer.HtmlContainerInt.PerformLayout(ig); var newSize = _htmlContainer.ActualSize; constraint = new Size(newSize.Width + horizontal, newSize.Height + vertical); } } if (double.IsPositiveInfinity(constraint.Width) || double.IsPositiveInfinity(constraint.Height)) constraint = Size.Empty; return constraint; }
/// <summary> /// Subtracts the width and height of one <see cref="RSize" /> structure from the width and height of another /// <see /// cref="RSize" /> /// structure. /// </summary> /// <returns> /// A <see cref="RSize" /> structure that is a result of the subtraction operation. /// </returns> /// <param name="sz1"> /// The <see cref="RSize" /> structure on the left side of the subtraction operator. /// </param> /// <param name="sz2"> /// The <see cref="RSize" /> structure on the right side of the subtraction operator. /// </param> public static RSize Subtract(RSize sz1, RSize sz2) { return new RSize(sz1.Width - sz2.Width, sz1.Height - sz2.Height); }
/// <summary> /// Initializes a new instance of the <see cref="RSize" /> structure from the specified existing /// <see /// cref="RSize" /> /// structure. /// </summary> /// <param name="size"> /// The <see cref="RSize" /> structure from which to create the new /// <see /// cref="RSize" /> /// structure. /// </param> public RSize(RSize size) { _width = size._width; _height = size._height; }
/// <summary> /// Convert from core size to WinForms size. /// </summary> public static Size ConvertRound(RSize s) { return new Size((int)Math.Round(s.Width), (int)Math.Round(s.Height)); }
/// <summary> /// Adds the width and height of one <see cref="RSize" /> structure to the width and height of another /// <see /// cref="RSize" /> /// structure. /// </summary> /// <returns> /// A <see cref="RSize" /> structure that is the result of the addition operation. /// </returns> /// <param name="sz1"> /// The first <see cref="RSize" /> structure to add. /// </param> /// <param name="sz2"> /// The second <see cref="RSize" /> structure to add. /// </param> public static RSize Add(RSize sz1, RSize sz2) { return new RSize(sz1.Width + sz2.Width, sz1.Height + sz2.Height); }
/// <summary> /// Subtracts the width and height of one <see cref="RSize" /> structure from the width and height of another /// <see /// cref="RSize" /> /// structure. /// </summary> /// <returns> /// A <see cref="RSize" /> structure that is a result of the subtraction operation. /// </returns> /// <param name="sz1"> /// The <see cref="RSize" /> structure on the left side of the subtraction operator. /// </param> /// <param name="sz2"> /// The <see cref="RSize" /> structure on the right side of the subtraction operator. /// </param> public static RSize Subtract(RSize sz1, RSize sz2) { return(new RSize(sz1.Width - sz2.Width, sz1.Height - sz2.Height)); }
/// <summary> /// Draw the given string using the given font and foreground color at given location. /// </summary> /// <param name="str">the string to draw</param> /// <param name="font">the font to use to draw the string</param> /// <param name="color">the text color to set</param> /// <param name="point">the location to start string draw (top-left)</param> /// <param name="size">used to know the size of the rendered text for transparent text support</param> /// <param name="rtl">is to render the string right-to-left (true - RTL, false - LTR)</param> public abstract void DrawString(String str, RFont font, RColor color, RPoint point, RSize size, bool rtl);
/// <summary> /// Convert from core point to WPF point. /// </summary> public static Size ConvertRound(RSize s) { return new Size((int)s.Width, (int)s.Height); }
public override void DrawString(string str, RFont font, RColor color, RPoint point, RSize size, bool rtl) { var xBrush = ((BrushAdapter)_adapter.GetSolidBrush(color)).Brush; _g.DrawString(str, ((FontAdapter)font).Font, (XBrush)xBrush, point.X, point.Y, _stringFormat); }
/// <summary> /// Translates a <see cref="RPoint" /> by the negative of a specified size. /// </summary> /// <returns> /// The translated <see cref="RPoint" />. /// </returns> /// <param name="pt"> /// The <see cref="RPoint" /> to translate. /// </param> /// <param name="sz"> /// The <see cref="T:System.Drawing.SizeF" /> that specifies the numbers to subtract from the coordinates of /// <paramref /// name="pt" /> /// . /// </param> public static RPoint Subtract(RPoint pt, RSize sz) { return new RPoint(pt.X - sz.Width, pt.Y - sz.Height); }
/// <summary> /// Convert from core size to WPF size. /// </summary> public static Size Convert(RSize s) { return new Size(s.Width, s.Height); }
/// <summary> /// Translates a given <see cref="RPoint" /> by a specified /// <see /// cref="T:System.Drawing.SizeF" /> /// . /// </summary> /// <returns> /// The translated <see cref="RPoint" />. /// </returns> /// <param name="pt"> /// The <see cref="RPoint" /> to translate. /// </param> /// <param name="sz"> /// The <see cref="T:System.Drawing.SizeF" /> that specifies the numbers to add to the coordinates of /// <paramref /// name="pt" /> /// . /// </param> public static RPoint Add(RPoint pt, RSize sz) { return new RPoint(pt.X + sz.Width, pt.Y + sz.Height); }
/// <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 (Display == CssConstants.None) return; RectanglesReset(); var prevSibling = DomUtils.GetPreviousSibling(this); double left = ContainingBlock.Location.X + ContainingBlock.ActualPaddingLeft + ActualMarginLeft + ContainingBlock.ActualBorderLeftWidth; double top = (prevSibling == null && ParentBox != null ? ParentBox.ClientTop : ParentBox == null ? Location.Y : 0) + MarginTopCollapse(prevSibling) + (prevSibling != null ? prevSibling.ActualBottom + prevSibling.ActualBorderBottomWidth : 0); Location = new RPoint(left, top); ActualBottom = top; //width at 100% (or auto) double minwidth = GetMinimumWidth(); double 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; double 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 RSize(width, height); ActualBottom = Location.Y + ActualPaddingTop + ActualPaddingBottom + height; }
/// <summary> /// Perform the layout of the html in the control. /// </summary> protected override Size MeasureOverride(Size constraint) { if (_htmlContainer != null) { using (var ig = new GraphicsAdapter()) { var horizontal = Padding.Left + Padding.Right + BorderThickness.Left + BorderThickness.Right; var vertical = Padding.Top + Padding.Bottom + BorderThickness.Top + BorderThickness.Bottom; var size = new RSize(constraint.Width < Double.PositiveInfinity ? constraint.Width - horizontal : 0, constraint.Height < Double.PositiveInfinity ? constraint.Height - vertical : 0); var minSize = new RSize(MinWidth < Double.PositiveInfinity ? MinWidth - horizontal : 0, MinHeight < Double.PositiveInfinity ? MinHeight - vertical : 0); var maxSize = new RSize(MaxWidth < Double.PositiveInfinity ? MaxWidth - horizontal : 0, MaxHeight < Double.PositiveInfinity ? MaxHeight - vertical : 0); var newSize = HtmlRendererUtils.Layout(ig, _htmlContainer.HtmlContainerInt, size, minSize, maxSize, AutoSize, AutoSizeHeightOnly); constraint = new Size(newSize.Width + horizontal, newSize.Height + vertical); } } if (double.IsPositiveInfinity(constraint.Width) || double.IsPositiveInfinity(constraint.Height)) constraint = Size.Empty; return constraint; }
/// <summary> /// Translates a given <see cref="RPoint" /> by a specified /// <see /// cref="T:System.Drawing.SizeF" /> /// . /// </summary> /// <returns> /// The translated <see cref="RPoint" />. /// </returns> /// <param name="pt"> /// The <see cref="RPoint" /> to translate. /// </param> /// <param name="sz"> /// The <see cref="T:System.Drawing.SizeF" /> that specifies the numbers to add to the coordinates of /// <paramref /// name="pt" /> /// . /// </param> public static RPoint Add(RPoint pt, RSize sz) { return(new RPoint(pt.X + sz.Width, pt.Y + sz.Height)); }
/// <summary> /// Draw play over the iframe if we found link url. /// </summary> private void DrawPlay(RGraphics g, RRect rect) { if (_isVideo && _imageWord.Width > 70 && _imageWord.Height > 50) { var prevMode = g.SetAntiAliasSmoothingMode(); var size = new RSize(60, 40); var left = rect.Left + (rect.Width - size.Width) / 2; var top = rect.Top + (rect.Height - size.Height) / 2; g.DrawRectangle(g.GetSolidBrush(RColor.FromArgb(160, 0, 0, 0)), left, top, size.Width, size.Height); RPoint[] points = { new RPoint(left + size.Width / 3f + 1,top + 3 * size.Height / 4f), new RPoint(left + size.Width / 3f + 1, top + size.Height / 4f), new RPoint(left + 2 * size.Width / 3f + 1, top + size.Height / 2f) }; g.DrawPolygon(g.GetSolidBrush(RColor.White), points); g.ReturnPreviousSmoothingMode(prevMode); } }
/// <summary> /// Translates a <see cref="RPoint" /> by the negative of a specified size. /// </summary> /// <returns> /// The translated <see cref="RPoint" />. /// </returns> /// <param name="pt"> /// The <see cref="RPoint" /> to translate. /// </param> /// <param name="sz"> /// The <see cref="T:System.Drawing.SizeF" /> that specifies the numbers to subtract from the coordinates of /// <paramref /// name="pt" /> /// . /// </param> public static RPoint Subtract(RPoint pt, RSize sz) { return(new RPoint(pt.X - sz.Width, pt.Y - sz.Height)); }
public override void DrawString(string str, RFont font, RColor color, RPoint point, RSize size, bool rtl) { var text = GetText(str, font); text.Constraint = Util.Convert(size); _g.DrawText(new SolidColorBrush(Util.Convert(color)), Util.Convert(point), text); }
/// <summary> /// Adds the width and height of one <see cref="RSize" /> structure to the width and height of another /// <see /// cref="RSize" /> /// structure. /// </summary> /// <returns> /// A <see cref="RSize" /> structure that is the result of the addition operation. /// </returns> /// <param name="sz1"> /// The first <see cref="RSize" /> structure to add. /// </param> /// <param name="sz2"> /// The second <see cref="RSize" /> structure to add. /// </param> public static RSize Add(RSize sz1, RSize sz2) { return(new RSize(sz1.Width + sz2.Width, sz1.Height + sz2.Height)); }
public override void DrawString(string str, RFont font, RColor color, RPoint point, RSize size, bool rtl) { var colorConv = ((BrushAdapter)_adapter.GetSolidBrush(color)).Brush; bool glyphRendered = false; GlyphTypeface glyphTypeface = ((FontAdapter)font).GlyphTypeface; if (glyphTypeface != null) { double width = 0; ushort[] glyphs = new ushort[str.Length]; double[] widths = new double[str.Length]; int i = 0; for (; i < str.Length; i++) { ushort glyph; if (!glyphTypeface.CharacterToGlyphMap.TryGetValue(str[i], out glyph)) break; glyphs[i] = glyph; width += glyphTypeface.AdvanceWidths[glyph]; widths[i] = 96d / 72d * font.Size * glyphTypeface.AdvanceWidths[glyph]; } if (i >= str.Length) { point.Y += glyphTypeface.Baseline * font.Size * 96d / 72d; point.X += rtl ? 96d / 72d * font.Size * width : 0; glyphRendered = true; var glyphRun = new GlyphRun(glyphTypeface, rtl ? 1 : 0, false, 96d / 72d * font.Size, glyphs, Utils.ConvertRound(point), widths, null, null, null, null, null, null); _g.DrawGlyphRun(colorConv, glyphRun); } } if (!glyphRendered) { var formattedText = new FormattedText(str, CultureInfo.CurrentCulture, rtl ? FlowDirection.RightToLeft : FlowDirection.LeftToRight, ((FontAdapter)font).Font, 96d / 72d * font.Size, colorConv); point.X += rtl ? formattedText.Width : 0; _g.DrawText(formattedText, Utils.ConvertRound(point)); } }
public override void DrawString(string str, RFont font, RColor color, RPoint point, RSize size, bool rtl) { if (_useGdiPlusTextRendering) { ReleaseHdc(); SetRtlAlignGdiPlus(rtl); var brush = ((BrushAdapter)_adapter.GetSolidBrush(color)).Brush; _g.DrawString(str, ((FontAdapter)font).Font, brush, (int)(Math.Round(point.X) + (rtl ? size.Width : 0)), (int)Math.Round(point.Y), _stringFormat2); } else { #if !MONO var pointConv = Utils.ConvertRound(point); var colorConv = Utils.Convert(color); if (color.A == 255) { SetFont(font); SetTextColor(colorConv); SetRtlAlignGdi(rtl); Win32Utils.TextOut(_hdc, pointConv.X, pointConv.Y, str, str.Length); } else { InitHdc(); SetRtlAlignGdi(rtl); DrawTransparentText(_hdc, str, font, pointConv, Utils.ConvertRound(size), colorConv); } #endif } }
/// <summary> /// Inflates this <see cref="RRect" /> by the specified amount. /// </summary> /// <param name="size">The amount to inflate this rectangle. </param> public void Inflate(RSize size) { Inflate(size.Width, size.Height); }
/// <summary> /// Convert from core size to WinForms size. /// </summary> public static SizeF Convert(RSize s) { return new SizeF((float)s.Width, (float)s.Height); }
/// <summary> /// Measures the bounds of box and children, recursively. /// </summary> /// <param name="g">Device context to draw</param> public void PerformLayout(RGraphics g) { ArgChecker.AssertArgNotNull(g, "g"); _actualSize = RSize.Empty; if (_root != null) { // if width is not restricted we set it to large value to get the actual later _root.Size = new RSize(_maxSize.Width > 0 ? _maxSize.Width : 99999, 0); _root.Location = _location; _root.PerformLayout(g); if (_maxSize.Width <= 0.1) { // in case the width is not restricted we need to double layout, first will find the width so second can layout by it (center alignment) _root.Size = new RSize((int)Math.Ceiling(_actualSize.Width), 0); _actualSize = RSize.Empty; _root.PerformLayout(g); } if (!_loadComplete) { _loadComplete = true; EventHandler handler = LoadComplete; if (handler != null) handler(this, EventArgs.Empty); } } }
/// <summary> /// Draw the background image at the required location repeating it over the X and Y axis.<br/> /// Adjust location to left-top if starting location doesn't include all the range (adjusted to center or bottom/right). /// </summary> private static void DrawRepeat(RGraphics g, ImageLoadHandler imageLoadHandler, RRect rectangle, RRect srcRect, RRect destRect, RSize imgSize) { while (destRect.X > rectangle.X) destRect.X -= imgSize.Width; while (destRect.Y > rectangle.Y) destRect.Y -= imgSize.Height; using (var brush = g.GetTextureBrush(imageLoadHandler.Image, srcRect, destRect.Location)) { g.DrawRectangle(brush, rectangle.X, rectangle.Y, rectangle.Width, rectangle.Height); } }
/// <summary> /// Measures the bounds of box and children, recursively.<br/> /// Performs layout of the DOM structure creating lines by set bounds restrictions.<br/> /// </summary> /// <param name="g">Device context to use</param> protected virtual void PerformLayoutImp(RGraphics g) { if (Display != CssConstants.None) { RectanglesReset(); MeasureWordsSize(g); } if (IsBlock || Display == CssConstants.ListItem || Display == CssConstants.Table || Display == CssConstants.InlineTable || Display == CssConstants.TableCell) { // Because their width and height are set by CssTable if (Display != CssConstants.TableCell && Display != CssConstants.Table) { double width = ContainingBlock.Size.Width - ContainingBlock.ActualPaddingLeft - ContainingBlock.ActualPaddingRight - ContainingBlock.ActualBorderLeftWidth - ContainingBlock.ActualBorderRightWidth; if (Width != CssConstants.Auto && !string.IsNullOrEmpty(Width)) { width = CssValueParser.ParseLength(Width, width, this); } Size = new RSize(width, Size.Height); // must be separate because the margin can be calculated by percentage of the width Size = new RSize(width - ActualMarginLeft - ActualMarginRight, Size.Height); } if (Display != CssConstants.TableCell) { var prevSibling = DomUtils.GetPreviousSibling(this); double left = ContainingBlock.Location.X + ContainingBlock.ActualPaddingLeft + ActualMarginLeft + ContainingBlock.ActualBorderLeftWidth; double top = (prevSibling == null && ParentBox != null ? ParentBox.ClientTop : ParentBox == null ? Location.Y : 0) + MarginTopCollapse(prevSibling) + (prevSibling != null ? prevSibling.ActualBottom + prevSibling.ActualBorderBottomWidth : 0); Location = new RPoint(left, top); ActualBottom = top; } //If we're talking about a table here.. if (Display == CssConstants.Table || Display == CssConstants.InlineTable) { CssLayoutEngineTable.PerformLayout(g, this); } else { //If there's just inline boxes, 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.PerformLayout(g); } ActualRight = CalculateActualRight(); ActualBottom = MarginBottomCollapse(); } } } else { var prevSibling = DomUtils.GetPreviousSibling(this); if (prevSibling != null) { if (Location == RPoint.Empty) Location = prevSibling.Location; ActualBottom = prevSibling.ActualBottom; } } ActualBottom = Math.Max(ActualBottom, Location.Y + ActualHeight); CreateListItemBox(g); var actualWidth = Math.Max(GetMinimumWidth() + GetWidthMarginDeep(this), Size.Width < 90999 ? ActualRight - HtmlContainer.Root.Location.X : 0); HtmlContainer.ActualSize = CommonUtils.Max(HtmlContainer.ActualSize, new RSize(actualWidth, ActualBottom - HtmlContainer.Root.Location.Y)); }