Пример #1
0
        /// <summary>
        /// Applies vertical and horizontal alignment to words in lineboxes
        /// </summary>
        /// <param name="g"></param>
        /// <param name="lineBox"></param>
        private static void ApplyHorizontalAlignment(RGraphics g, CssLineBox lineBox)
        {
            switch (lineBox.OwnerBox.TextAlign)
            {
            case CssConstants.Right:
                ApplyRightAlignment(g, lineBox);
                break;

            case CssConstants.Center:
                ApplyCenterAlignment(g, lineBox);
                break;

            case CssConstants.Justify:
                ApplyJustifyAlignment(g, lineBox);
                break;

            default:
                ApplyLeftAlignment(g, lineBox);
                break;
            }
        }
Пример #2
0
        /// <summary>
        /// Get pen to be used for border draw respecting its style.
        /// </summary>
        private static RPen GetPen(RGraphics g, string style, RColor color, double width)
        {
            var p = g.GetPen(color);

            p.Width = width;
            switch (style)
            {
            case "solid":
                p.DashStyle = RDashStyle.Solid;
                break;

            case "dotted":
                p.DashStyle = RDashStyle.Dot;
                break;

            case "dashed":
                p.DashStyle = RDashStyle.Dash;
                break;
            }
            return(p);
        }
        /// <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);
                }
            }
        }
Пример #4
0
        /// <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);
            }
        }
Пример #5
0
 /// <summary>
 /// Draws all the border of the box with respect to style, width, etc.
 /// </summary>
 /// <param name="g">the device to draw into</param>
 /// <param name="box">the box to draw borders for</param>
 /// <param name="rect">the bounding rectangle to draw in</param>
 /// <param name="isFirst">is it the first rectangle of the element</param>
 /// <param name="isLast">is it the last rectangle of the element</param>
 public static void DrawBoxBorders(RGraphics g, CssBox box, RRect rect, bool isFirst, bool isLast)
 {
     if (rect.Width > 0 && rect.Height > 0)
     {
         if (!(string.IsNullOrEmpty(box.BorderTopStyle) || box.BorderTopStyle == CssConstants.None || box.BorderTopStyle == CssConstants.Hidden) && box.ActualBorderTopWidth > 0)
         {
             DrawBorder(Border.Top, box, g, rect, isFirst, isLast);
         }
         if (isFirst && !(string.IsNullOrEmpty(box.BorderLeftStyle) || box.BorderLeftStyle == CssConstants.None || box.BorderLeftStyle == CssConstants.Hidden) && box.ActualBorderLeftWidth > 0)
         {
             DrawBorder(Border.Left, box, g, rect, true, isLast);
         }
         if (!(string.IsNullOrEmpty(box.BorderBottomStyle) || box.BorderBottomStyle == CssConstants.None || box.BorderBottomStyle == CssConstants.Hidden) && box.ActualBorderBottomWidth > 0)
         {
             DrawBorder(Border.Bottom, box, g, rect, isFirst, isLast);
         }
         if (isLast && !(string.IsNullOrEmpty(box.BorderRightStyle) || box.BorderRightStyle == CssConstants.None || box.BorderRightStyle == CssConstants.Hidden) && box.ActualBorderRightWidth > 0)
         {
             DrawBorder(Border.Right, box, g, rect, isFirst, true);
         }
     }
 }
Пример #6
0
        /// <summary>
        /// Render the html using the given device.
        /// </summary>
        /// <param name="g">the device to use to render</param>
        public void PerformPaint(RGraphics g)
        {
            ArgChecker.AssertArgNotNull(g, "g");

            bool pushedClip = false;

            if (MaxSize.Height > 0)
            {
                pushedClip = true;
                g.PushClip(new RRect(_location, _maxSize));
            }

            if (_root != null)
            {
                _root.Paint(g);
            }

            if (pushedClip)
            {
                g.PopClip();
            }
        }
Пример #7
0
        /// <summary>
        /// Applies centered alignment to the text on the linebox
        /// </summary>
        /// <param name="g"></param>
        /// <param name="lineBox"></param>
        private static void ApplyJustifyAlignment(RGraphics g, CssLineBox lineBox)
        {
            if (lineBox.Equals(lineBox.OwnerBox.LineBoxes[lineBox.OwnerBox.LineBoxes.Count - 1]))
            {
                return;
            }

            double indent     = lineBox.Equals(lineBox.OwnerBox.LineBoxes[0]) ? lineBox.OwnerBox.ActualTextIndent : 0f;
            double textSum    = 0f;
            double words      = 0f;
            double availWidth = lineBox.OwnerBox.ClientRectangle.Width - indent;

            // Gather text sum
            foreach (CssRect w in lineBox.Words)
            {
                textSum += w.Width;
                words   += 1f;
            }

            if (words <= 0f)
            {
                return;                                      //Avoid Zero division
            }
            double spacing = (availWidth - textSum) / words; //Spacing that will be used
            double curx    = lineBox.OwnerBox.ClientLeft + indent;

            foreach (CssRect word in lineBox.Words)
            {
                word.Left = curx;
                curx      = word.Right + spacing;

                if (word == lineBox.Words[lineBox.Words.Count - 1])
                {
                    word.Left = lineBox.OwnerBox.ClientRight - word.Width;
                }
            }
        }
Пример #8
0
        private static void LayoutCells(RGraphics g, Table table)
        {
            double top  = table.tableBox.Location.Y;
            double left = table.tableBox.Location.X;

            for (int row = 0; row < table.rows; row++)
            {
                left = table.tableBox.Location.X;
                for (int col = 0; col < table.cols; col++)
                {
                    if (table[row, col] != null)
                    {
                        var    td      = table[row, col];
                        int    colspan = GetColSpan(td);
                        int    rowspan = GetRowSpan(td);
                        double height  = 0;
                        for (int xr = 0; xr < rowspan; xr++)
                        {
                            height += table.rows_limits[row + xr].value;
                        }

                        double width = 0;
                        for (int xc = 0; xc < colspan; xc++)
                        {
                            width += table.cols_limits[col + xc].value;
                        }
                        td.PerformLayout(g);
                        td.Location = new RPoint(left, top);
                        td.Size     = new RSize(width, height);
                        //That will automatically set the bottom of the cell
                    }
                    left += table.cols_limits[col].value;
                }
                top += table.rows_limits[row].value;
            }
        }
Пример #9
0
        /// <summary>
        /// Assigns words its width and height
        /// </summary>
        /// <param name="g">the device to use</param>
        internal override void MeasureWordsSize(RGraphics g)
        {
            if (!_wordsSizeMeasured)
            {
                if (_imageLoadHandler == null && (HtmlContainer.AvoidAsyncImagesLoading || HtmlContainer.AvoidImagesLateLoading))
                {
                    _imageLoadHandler = new ImageLoadHandler(HtmlContainer, OnLoadImageComplete);

                    if (this.Content != null && this.Content != CssConstants.Normal)
                    {
                        _imageLoadHandler.LoadImage(this.Content, HtmlTag != null ? HtmlTag.Attributes : null);
                    }
                    else
                    {
                        _imageLoadHandler.LoadImage(GetAttribute("src"), HtmlTag != null ? HtmlTag.Attributes : null);
                    }
                }

                MeasureWordSpacing(g);
                _wordsSizeMeasured = true;
            }

            CssLayoutEngine.MeasureImageSize(_imageWord);
        }
Пример #10
0
        /// <summary>
        /// Creates a rounded rectangle using the specified corner radius<br/>
        /// NW-----NE
        ///  |       |
        ///  |       |
        /// SW-----SE
        /// </summary>
        /// <param name="g">the device to draw into</param>
        /// <param name="rect">Rectangle to round</param>
        /// <param name="nwRadius">Radius of the north east corner</param>
        /// <param name="neRadius">Radius of the north west corner</param>
        /// <param name="seRadius">Radius of the south east corner</param>
        /// <param name="swRadius">Radius of the south west corner</param>
        /// <returns>GraphicsPath with the lines of the rounded rectangle ready to be painted</returns>
        public static RGraphicsPath GetRoundRect(RGraphics g, RRect rect, double nwRadius, double neRadius, double seRadius, double swRadius)
        {
            var path = g.GetGraphicsPath();

            path.Start(rect.Left + nwRadius, rect.Top);

            path.LineTo(rect.Right - neRadius, rect.Y);

            if (neRadius > 0f)
            {
                path.ArcTo(rect.Right, rect.Top + neRadius, neRadius, RGraphicsPath.Corner.TopRight);
            }

            path.LineTo(rect.Right, rect.Bottom - seRadius);

            if (seRadius > 0f)
            {
                path.ArcTo(rect.Right - seRadius, rect.Bottom, seRadius, RGraphicsPath.Corner.BottomRight);
            }

            path.LineTo(rect.Left + swRadius, rect.Bottom);

            if (swRadius > 0f)
            {
                path.ArcTo(rect.Left, rect.Bottom - swRadius, swRadius, RGraphicsPath.Corner.BottomLeft);
            }

            path.LineTo(rect.Left, rect.Top + nwRadius);

            if (nwRadius > 0f)
            {
                path.ArcTo(rect.Left + nwRadius, rect.Top, nwRadius, RGraphicsPath.Corner.TopLeft);
            }

            return(path);
        }
Пример #11
0
        /// <summary>
        /// Makes a border path for rounded borders.<br/>
        /// To support rounded dotted/dashed borders we need to use arc in the border path.<br/>
        /// Return null if the border is not rounded.<br/>
        /// </summary>
        /// <param name="g">the device to draw into</param>
        /// <param name="border">Desired border</param>
        /// <param name="b">Box which the border corresponds</param>
        /// <param name="r">the rectangle the border is enclosing</param>
        /// <returns>Beveled border path, null if there is no rounded corners</returns>
        private static RGraphicsPath GetRoundedBorderPath(RGraphics g, Border border, CssBox b, RRect r)
        {
            RGraphicsPath path = null;

            switch (border)
            {
            case Border.Top:
                if (b.ActualCornerNw > 0 || b.ActualCornerNe > 0)
                {
                    path = g.GetGraphicsPath();
                    path.Start(r.Left + b.ActualBorderLeftWidth / 2, r.Top + b.ActualBorderTopWidth / 2 + b.ActualCornerNw);

                    if (b.ActualCornerNw > 0)
                    {
                        path.ArcTo(r.Left + b.ActualBorderLeftWidth / 2 + b.ActualCornerNw, r.Top + b.ActualBorderTopWidth / 2, b.ActualCornerNw, RGraphicsPath.Corner.TopLeft);
                    }

                    path.LineTo(r.Right - b.ActualBorderRightWidth / 2 - b.ActualCornerNe, r.Top + b.ActualBorderTopWidth / 2);

                    if (b.ActualCornerNe > 0)
                    {
                        path.ArcTo(r.Right - b.ActualBorderRightWidth / 2, r.Top + b.ActualBorderTopWidth / 2 + b.ActualCornerNe, b.ActualCornerNe, RGraphicsPath.Corner.TopRight);
                    }
                }
                break;

            case Border.Bottom:
                if (b.ActualCornerSw > 0 || b.ActualCornerSe > 0)
                {
                    path = g.GetGraphicsPath();
                    path.Start(r.Right - b.ActualBorderRightWidth / 2, r.Bottom - b.ActualBorderBottomWidth / 2 - b.ActualCornerSe);

                    if (b.ActualCornerSe > 0)
                    {
                        path.ArcTo(r.Right - b.ActualBorderRightWidth / 2 - b.ActualCornerSe, r.Bottom - b.ActualBorderBottomWidth / 2, b.ActualCornerSe, RGraphicsPath.Corner.BottomRight);
                    }

                    path.LineTo(r.Left + b.ActualBorderLeftWidth / 2 + b.ActualCornerSw, r.Bottom - b.ActualBorderBottomWidth / 2);

                    if (b.ActualCornerSw > 0)
                    {
                        path.ArcTo(r.Left + b.ActualBorderLeftWidth / 2, r.Bottom - b.ActualBorderBottomWidth / 2 - b.ActualCornerSw, b.ActualCornerSw, RGraphicsPath.Corner.BottomLeft);
                    }
                }
                break;

            case Border.Right:
                if (b.ActualCornerNe > 0 || b.ActualCornerSe > 0)
                {
                    path = g.GetGraphicsPath();

                    var noTop    = b.BorderTopStyle == CssConstants.None || b.BorderTopStyle == CssConstants.Hidden;
                    var noBottom = b.BorderBottomStyle == CssConstants.None || b.BorderBottomStyle == CssConstants.Hidden;
                    path.Start(r.Right - b.ActualBorderRightWidth / 2 - (noTop ? b.ActualCornerNe : 0), r.Top + b.ActualBorderTopWidth / 2 + (noTop ? 0 : b.ActualCornerNe));

                    if (b.ActualCornerNe > 0 && noTop)
                    {
                        path.ArcTo(r.Right - b.ActualBorderLeftWidth / 2, r.Top + b.ActualBorderTopWidth / 2 + b.ActualCornerNe, b.ActualCornerNe, RGraphicsPath.Corner.TopRight);
                    }

                    path.LineTo(r.Right - b.ActualBorderRightWidth / 2, r.Bottom - b.ActualBorderBottomWidth / 2 - b.ActualCornerSe);

                    if (b.ActualCornerSe > 0 && noBottom)
                    {
                        path.ArcTo(r.Right - b.ActualBorderRightWidth / 2 - b.ActualCornerSe, r.Bottom - b.ActualBorderBottomWidth / 2, b.ActualCornerSe, RGraphicsPath.Corner.BottomRight);
                    }
                }
                break;

            case Border.Left:
                if (b.ActualCornerNw > 0 || b.ActualCornerSw > 0)
                {
                    path = g.GetGraphicsPath();

                    var noTop    = b.BorderTopStyle == CssConstants.None || b.BorderTopStyle == CssConstants.Hidden;
                    var noBottom = b.BorderBottomStyle == CssConstants.None || b.BorderBottomStyle == CssConstants.Hidden;
                    path.Start(r.Left + b.ActualBorderLeftWidth / 2 + (noBottom ? b.ActualCornerSw : 0), r.Bottom - b.ActualBorderBottomWidth / 2 - (noBottom ? 0 : b.ActualCornerSw));

                    if (b.ActualCornerSw > 0 && noBottom)
                    {
                        path.ArcTo(r.Left + b.ActualBorderLeftWidth / 2, r.Bottom - b.ActualBorderBottomWidth / 2 - b.ActualCornerSw, b.ActualCornerSw, RGraphicsPath.Corner.BottomLeft);
                    }

                    path.LineTo(r.Left + b.ActualBorderLeftWidth / 2, r.Top + b.ActualBorderTopWidth / 2 + b.ActualCornerNw);

                    if (b.ActualCornerNw > 0 && noTop)
                    {
                        path.ArcTo(r.Left + b.ActualBorderLeftWidth / 2 + b.ActualCornerNw, r.Top + b.ActualBorderTopWidth / 2, b.ActualCornerNw, RGraphicsPath.Corner.TopLeft);
                    }
                }
                break;
            }

            return(path);
        }
Пример #12
0
        /// <summary>
        /// Paints the fragment
        /// </summary>
        /// <param name="g">the device to draw to</param>
        protected override void PaintImp(RGraphics g)
        {
            // load image if it is in visible rectangle
            if (_imageLoadHandler == null)
            {
                _imageLoadHandler = new ImageLoadHandler(HtmlContainer, OnLoadImageComplete);
                _imageLoadHandler.LoadImage(GetAttribute("src"), HtmlTag != null ? HtmlTag.Attributes : null);
            }

            var    rect   = CommonUtils.GetFirstValueOrDefault(Rectangles);
            RPoint offset = RPoint.Empty;

            if (!IsFixed)
            {
                offset = HtmlContainer.ScrollOffset;
            }

            rect.Offset(offset);

            var clipped = RenderUtils.ClipGraphicsByOverflow(g, this);

            PaintBackground(g, rect, true, true);
            BordersDrawHandler.DrawBoxBorders(g, this, rect, true, true);

            RRect r = _imageWord.Rectangle;

            r.Offset(offset);
            r.Height -= ActualBorderTopWidth + ActualBorderBottomWidth + ActualPaddingTop + ActualPaddingBottom;
            r.Y      += ActualBorderTopWidth + ActualPaddingTop;
            r.X       = Math.Floor(r.X);
            r.Y       = Math.Floor(r.Y);

            if (_imageWord.Image != null)
            {
                if (r.Width > 0 && r.Height > 0)
                {
                    if (_imageWord.ImageRectangle == RRect.Empty)
                    {
                        g.DrawImage(_imageWord.Image, r);
                    }
                    else
                    {
                        g.DrawImage(_imageWord.Image, r, _imageWord.ImageRectangle);
                    }

                    if (_imageWord.Selected)
                    {
                        g.DrawRectangle(GetSelectionBackBrush(g, true), _imageWord.Left + offset.X, _imageWord.Top + offset.Y, _imageWord.Width + 2, DomUtils.GetCssLineBoxByWord(_imageWord).LineHeight);
                    }
                }
            }
            else if (_imageLoadingComplete)
            {
                if (_imageLoadingComplete && r.Width > 19 && r.Height > 19)
                {
                    RenderUtils.DrawImageErrorIcon(g, HtmlContainer, r);
                }
            }
            else
            {
                RenderUtils.DrawImageLoadingIcon(g, HtmlContainer, r);
                if (r.Width > 19 && r.Height > 19)
                {
                    g.DrawRectangle(g.GetPen(RColor.LightGray), r.X, r.Y, r.Width, r.Height);
                }
            }

            if (clipped)
            {
                g.PopClip();
            }
        }
Пример #13
0
        /// <summary>
        /// Recursively flows the content of the box using the inline model
        /// </summary>
        /// <param name="g">Device Info</param>
        /// <param name="blockbox">Blockbox that contains the text flow</param>
        /// <param name="box">Current box to flow its content</param>
        /// <param name="limitRight">Maximum reached right</param>
        /// <param name="linespacing">Space to use between rows of text</param>
        /// <param name="startx">x starting coordinate for when breaking lines of text</param>
        /// <param name="line">Current linebox being used</param>
        /// <param name="curx">Current x coordinate that will be the left of the next word</param>
        /// <param name="cury">Current y coordinate that will be the top of the next word</param>
        /// <param name="maxRight">Maximum right reached so far</param>
        /// <param name="maxbottom">Maximum bottom reached so far</param>
        private static void FlowBox(RGraphics g, CssBox blockbox, CssBox box, double limitRight, double linespacing, double startx, ref CssLineBox line, ref double curx, ref double cury, ref double maxRight, ref double maxbottom)
        {
            var startX = curx;
            var startY = cury;

            box.FirstHostingLineBox = line;
            var localCurx      = curx;
            var localMaxRight  = maxRight;
            var localmaxbottom = maxbottom;

            foreach (CssBox b in box.Boxes)
            {
                double leftspacing  = (b.Position != CssConstants.Absolute && b.Position != CssConstants.Fixed) ? b.ActualMarginLeft + b.ActualBorderLeftWidth + b.ActualPaddingLeft : 0;
                double rightspacing = (b.Position != CssConstants.Absolute && b.Position != CssConstants.Fixed) ? b.ActualMarginRight + b.ActualBorderRightWidth + b.ActualPaddingRight : 0;

                b.RectanglesReset();
                b.MeasureWordsSize(g);

                curx += leftspacing;

                if (b.Words.Count > 0)
                {
                    bool wrapNoWrapBox = false;
                    if (b.WhiteSpace == CssConstants.NoWrap && curx > startx)
                    {
                        var boxRight = curx;
                        foreach (var word in b.Words)
                        {
                            boxRight += word.FullWidth;
                        }
                        if (boxRight > limitRight)
                        {
                            wrapNoWrapBox = true;
                        }
                    }

                    if (DomUtils.IsBoxHasWhitespace(b))
                    {
                        curx += box.ActualWordSpacing;
                    }

                    foreach (var word in b.Words)
                    {
                        if (maxbottom - cury < box.ActualLineHeight)
                        {
                            maxbottom += box.ActualLineHeight - (maxbottom - cury);
                        }

                        if ((b.WhiteSpace != CssConstants.NoWrap && b.WhiteSpace != CssConstants.Pre && curx + word.Width + rightspacing > limitRight &&
                             (b.WhiteSpace != CssConstants.PreWrap || !word.IsSpaces)) ||
                            word.IsLineBreak || wrapNoWrapBox)
                        {
                            wrapNoWrapBox = false;
                            curx          = startx;

                            // handle if line is wrapped for the first text element where parent has left margin\padding
                            if (b == box.Boxes[0] && !word.IsLineBreak && (word == b.Words[0] || (box.ParentBox != null && box.ParentBox.IsBlock)))
                            {
                                curx += box.ActualMarginLeft + box.ActualBorderLeftWidth + box.ActualPaddingLeft;
                            }

                            cury = maxbottom + linespacing;

                            line = new CssLineBox(blockbox);

                            if (word.IsImage || word.Equals(b.FirstWord))
                            {
                                curx += leftspacing;
                            }
                        }

                        line.ReportExistanceOf(word);

                        word.Left = curx;
                        word.Top  = cury;

                        if (!box.IsFixed)
                        {
                            word.BreakPage();
                        }

                        curx = word.Left + word.FullWidth;

                        maxRight  = Math.Max(maxRight, word.Right);
                        maxbottom = Math.Max(maxbottom, word.Bottom);

                        if (b.Position == CssConstants.Absolute)
                        {
                            word.Left += box.ActualMarginLeft;
                            word.Top  += box.ActualMarginTop;
                        }
                    }
                }
                else
                {
                    FlowBox(g, blockbox, b, limitRight, linespacing, startx, ref line, ref curx, ref cury, ref maxRight, ref maxbottom);
                }

                curx += rightspacing;
            }

            // handle height setting
            if (maxbottom - startY < box.ActualHeight)
            {
                maxbottom += box.ActualHeight - (maxbottom - startY);
            }

            // handle width setting
            if (box.IsInline && 0 <= curx - startX && curx - startX < box.ActualWidth)
            {
                // hack for actual width handling
                curx += box.ActualWidth - (curx - startX);
                line.Rectangles.Add(box, new RRect(startX, startY, box.ActualWidth, box.ActualHeight));
            }

            // handle box that is only a whitespace
            if (box.Text != null && box.Text.IsWhitespace() && !box.IsImage && box.IsInline && box.Boxes.Count == 0 && box.Words.Count == 0)
            {
                curx += box.ActualWordSpacing;
            }

            // hack to support specific absolute position elements
            if (box.Position == CssConstants.Absolute)
            {
                curx      = localCurx;
                maxRight  = localMaxRight;
                maxbottom = localmaxbottom;
                AdjustAbsolutePosition(box, 0, 0);
            }

            box.LastHostingLineBox = line;
        }
        /// <summary>
        /// Layout the cells by the calculated table layout
        /// </summary>
        /// <param name="g"></param>
        private void LayoutCells(RGraphics g)
        {
            double startx     = Math.Max(_tableBox.ClientLeft + GetHorizontalSpacing(), 0);
            double starty     = Math.Max(_tableBox.ClientTop + GetVerticalSpacing(), 0);
            double cury       = starty;
            double maxRight   = startx;
            double maxBottom  = 0f;
            int    currentrow = 0;

            for (int i = 0; i < _allRows.Count; i++)
            {
                var    row    = _allRows[i];
                double curx   = startx;
                int    curCol = 0;

                for (int j = 0; j < row.Boxes.Count; j++)
                {
                    CssBox cell = row.Boxes[j];
                    if (curCol >= _columnWidths.Length)
                    {
                        break;
                    }

                    int    rowspan     = GetRowSpan(cell);
                    var    columnIndex = GetCellRealColumnIndex(row, cell);
                    double width       = GetCellWidth(columnIndex, cell);
                    cell.Location = new RPoint(curx, cury);
                    cell.Size     = new RSize(width, 0f);
                    cell.PerformLayout(g); //That will automatically set the bottom of the cell

                    //Alter max bottom only if row is cell's row + cell's rowspan - 1
                    CssSpacingBox sb = cell as CssSpacingBox;
                    if (sb != null)
                    {
                        if (sb.EndRow == currentrow)
                        {
                            maxBottom = Math.Max(maxBottom, sb.ExtendedBox.ActualBottom);
                        }
                    }
                    else if (rowspan == 1)
                    {
                        maxBottom = Math.Max(maxBottom, cell.ActualBottom);
                    }
                    maxRight = Math.Max(maxRight, cell.ActualRight);
                    curCol++;
                    curx = cell.ActualRight + GetHorizontalSpacing();
                }

                foreach (CssBox cell in row.Boxes)
                {
                    CssSpacingBox spacer = cell as CssSpacingBox;

                    if (spacer == null && GetRowSpan(cell) == 1)
                    {
                        cell.ActualBottom = maxBottom;
                        CssLayoutEngine.ApplyCellVerticalAlignment(g, cell);
                    }
                    else if (spacer != null && spacer.EndRow == currentrow)
                    {
                        spacer.ExtendedBox.ActualBottom = maxBottom;
                        CssLayoutEngine.ApplyCellVerticalAlignment(g, spacer.ExtendedBox);
                    }
                }

                cury = maxBottom + GetVerticalSpacing();
                currentrow++;
            }

            maxRight = Math.Max(maxRight, _tableBox.Location.X + _tableBox.ActualWidth);
            _tableBox.ActualRight  = maxRight + GetHorizontalSpacing() + _tableBox.ActualBorderRightWidth;
            _tableBox.ActualBottom = Math.Max(maxBottom, starty) + GetVerticalSpacing() + _tableBox.ActualBorderBottomWidth;
        }
Пример #15
0
 public abstract double GetWhitespaceWidth(RGraphics graphics);
Пример #16
0
 public abstract double GetWhitespaceWidth(RGraphics graphics);
Пример #17
0
 /// <summary>
 /// Draw simple border.
 /// </summary>
 /// <param name="border">Desired border</param>
 /// <param name="g">the device to draw to</param>
 /// <param name="box">Box which the border corresponds</param>
 /// <param name="brush">the brush to use</param>
 /// <param name="rectangle">the bounding rectangle to draw in</param>
 /// <returns>Beveled border path, null if there is no rounded corners</returns>
 public static void DrawBorder(Border border, RGraphics g, CssBox box, RBrush brush, RRect rectangle)
 {
     SetInOutsetRectanglePoints(border, box, rectangle, true, true);
     g.DrawPolygon(brush, _borderPts);
 }
Пример #18
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(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>
        /// 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, RGraphicsPath roundrect = null)
        {
            // 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, box);

            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);



            //rectangle - box to draw in
            //imgSize - image size
            //localion - inital location of image wo repeat
            //destRect - RRect(location, imgSize)
            //srcRect (0,0,imgSize)

            //brushRect - This is rectangle which needs to be filled with Image from brushRect.Location with brushRect.Size multiple to Image size.
            RRect brushRect = new RRect(location, imgSize);

            switch (box.BackgroundRepeat)
            {
            case "no-repeat":
                //brushRect = destRect;
                break;

            case "repeat-x":
                if (brushRect.X > rectangle.X)
                {
                    brushRect.X -= imgSize.Width * ((int)((brushRect.X - rectangle.X) / imgSize.Width) + 1);
                }
                if (brushRect.X + brushRect.Width < rectangle.X + rectangle.Width)
                {
                    brushRect.Width = imgSize.Width * ((int)((rectangle.X + rectangle.Width - brushRect.X) / imgSize.Width) + 1);
                }
                break;

            case "repeat-y":
                if (brushRect.Y > rectangle.Y)
                {
                    brushRect.Y -= imgSize.Height * ((int)((brushRect.Y - rectangle.Y) / imgSize.Height) + 1);
                }
                if (brushRect.Y + brushRect.Height < rectangle.Y + rectangle.Height)
                {
                    brushRect.Height = imgSize.Height * ((int)((rectangle.Y + rectangle.Height - brushRect.Y) / imgSize.Height) + 1);
                }
                break;

            default:
                if (brushRect.X > rectangle.X)
                {
                    brushRect.X -= imgSize.Width * ((int)((brushRect.X - rectangle.X) / imgSize.Width) + 1);
                }
                if (brushRect.X + brushRect.Width < rectangle.X + rectangle.Width)
                {
                    brushRect.Width = imgSize.Width * ((int)((rectangle.X + rectangle.Width - brushRect.X) / imgSize.Width) + 1);
                }
                if (brushRect.Y > rectangle.Y)
                {
                    brushRect.Y -= imgSize.Height * ((int)((brushRect.Y - rectangle.Y) / imgSize.Height) + 1);
                }
                if (brushRect.Y + brushRect.Height < rectangle.Y + rectangle.Height)
                {
                    brushRect.Height = imgSize.Height * ((int)((rectangle.Y + rectangle.Height - brushRect.Y) / imgSize.Height) + 1);
                }
                break;
            }
            using (var brush = g.GetTextureBrush(imageLoadHandler.Image, brushRect, brushRect.Location))
            {
                if (roundrect == null)
                {
                    g.DrawRectangle(brush, rectangle.X, rectangle.Y, rectangle.Width, rectangle.Height);
                }
                else
                {
                    g.DrawPath(brush, roundrect);
                }
            }

            g.PopClip();
        }
Пример #20
0
        /// <summary>
        /// Layout the cells by the calculated table layout
        /// </summary>
        /// <param name="g"></param>
        private void LayoutCells(RGraphics g)
        {
            double startx     = Math.Max(_tableBox.ClientLeft + GetHorizontalSpacing(), 0);
            double starty     = Math.Max(_tableBox.ClientTop + GetVerticalSpacing(), 0);
            double cury       = starty;
            double maxRight   = startx;
            double maxBottom  = 0f;
            int    currentrow = 0;

            // change start X by if the table should align to center or right
            if (_tableBox.TextAlign == CssConstants.Center || _tableBox.TextAlign == CssConstants.Right)
            {
                double maxRightCalc = GetWidthSum();
                startx = _tableBox.TextAlign == CssConstants.Right
                    ? GetAvailableTableWidth() - maxRightCalc
                    : startx + (GetAvailableTableWidth() - maxRightCalc) / 2;

                _tableBox.Location = new RPoint(startx - _tableBox.ActualBorderLeftWidth - _tableBox.ActualPaddingLeft - GetHorizontalSpacing(), _tableBox.Location.Y);
            }

            for (int i = 0; i < _allRows.Count; i++)
            {
                var    row       = _allRows[i];
                double curx      = startx;
                int    curCol    = 0;
                bool   breakPage = false;

                for (int j = 0; j < row.Boxes.Count; j++)
                {
                    CssBox cell = row.Boxes[j];
                    if (curCol >= _columnWidths.Length)
                    {
                        break;
                    }

                    int    rowspan     = GetRowSpan(cell);
                    var    columnIndex = GetCellRealColumnIndex(row, cell);
                    double width       = GetCellWidth(columnIndex, cell);
                    cell.Location = new RPoint(curx, cury);
                    cell.Size     = new RSize(width, 0f);
                    cell.PerformLayout(g); //That will automatically set the bottom of the cell

                    //Alter max bottom only if row is cell's row + cell's rowspan - 1
                    CssSpacingBox sb = cell as CssSpacingBox;
                    if (sb != null)
                    {
                        if (sb.EndRow == currentrow)
                        {
                            maxBottom = Math.Max(maxBottom, sb.ExtendedBox.ActualBottom);
                        }
                    }
                    else if (rowspan == 1)
                    {
                        maxBottom = Math.Max(maxBottom, cell.ActualBottom);
                    }
                    maxRight = Math.Max(maxRight, cell.ActualRight);
                    curCol++;
                    curx = cell.ActualRight + GetHorizontalSpacing();
                }

                foreach (CssBox cell in row.Boxes)
                {
                    CssSpacingBox spacer = cell as CssSpacingBox;

                    if (spacer == null && GetRowSpan(cell) == 1)
                    {
                        cell.ActualBottom = maxBottom;
                        CssLayoutEngine.ApplyCellVerticalAlignment(g, cell);
                    }
                    else if (spacer != null && spacer.EndRow == currentrow)
                    {
                        spacer.ExtendedBox.ActualBottom = maxBottom;
                        CssLayoutEngine.ApplyCellVerticalAlignment(g, spacer.ExtendedBox);
                    }

                    // If one cell crosses page borders then don't need to check other cells in the row
                    if (_tableBox.PageBreakInside == CssConstants.Avoid)
                    {
                        breakPage = cell.BreakPage();
                        if (breakPage)
                        {
                            cury = cell.Location.Y;
                            break;
                        }
                    }
                }

                if (breakPage)  // go back to move the whole row to the next page
                {
                    if (i == 1) // do not leave single row in previous page
                    {
                        i = -1; // Start layout from the first row on new page
                    }
                    else
                    {
                        i--;
                    }

                    maxBottom = 0;
                    continue;
                }

                cury = maxBottom + GetVerticalSpacing();

                currentrow++;
            }

            maxRight = Math.Max(maxRight, _tableBox.Location.X + _tableBox.ActualWidth);
            _tableBox.ActualRight  = maxRight + GetHorizontalSpacing() + _tableBox.ActualBorderRightWidth;
            _tableBox.ActualBottom = Math.Max(maxBottom, starty) + GetVerticalSpacing() + _tableBox.ActualBorderBottomWidth;
        }
Пример #21
0
        /// <summary>
        /// Draw specific border (top/bottom/left/right) with the box data (style/width/rounded).<br/>
        /// </summary>
        /// <param name="border">desired border to draw</param>
        /// <param name="box">the box to draw its borders, contain the borders data</param>
        /// <param name="g">the device to draw into</param>
        /// <param name="rect">the rectangle the border is enclosing</param>
        /// <param name="isLineStart">Specifies if the border is for a starting line (no bevel on left)</param>
        /// <param name="isLineEnd">Specifies if the border is for an ending line (no bevel on right)</param>
        private static void DrawBorder(Border border, CssBox box, RGraphics g, RRect rect, bool isLineStart,
                                       bool isLineEnd)
        {
            var style = GetStyle(border, box);
            var color = GetColor(border, box, style);

            var borderPath = GetRoundedBorderPath(g, border, box, rect);

            if (borderPath != null)
            {
                // rounded border need special path
                Object prevMode = null;
                if (box.HtmlContainer != null && !box.HtmlContainer.AvoidGeometryAntialias && box.IsRounded)
                {
                    prevMode = g.SetAntiAliasSmoothingMode();
                }

                var pen = GetPen(g, style, color, GetWidth(border, box));
                using (borderPath)
                    g.DrawPath(pen, borderPath);

                g.ReturnPreviousSmoothingMode(prevMode);
            }
            else
            {
                // non rounded border
                if (style == CssConstants.Inset || style == CssConstants.Outset)
                {
                    // inset/outset border needs special rectangle
                    SetInOutsetRectanglePoints(border, box, rect, isLineStart, isLineEnd);
                    g.DrawPolygon(g.GetSolidBrush(color), _borderPts);
                }
                else
                {
                    // solid/dotted/dashed border draw as simple line
                    var pen = GetPen(g, style, color, GetWidth(border, box));
                    switch (border)
                    {
                    case Border.Top:
                        g.DrawLine(pen, Math.Ceiling(rect.Left), rect.Top + box.ActualBorderTopWidth / 2,
                                   rect.Right - 1, rect.Top + box.ActualBorderTopWidth / 2);
                        break;

                    case Border.Left:
                        g.DrawLine(pen, rect.Left + box.ActualBorderLeftWidth / 2, Math.Ceiling(rect.Top),
                                   rect.Left + box.ActualBorderLeftWidth / 2, Math.Floor(rect.Bottom));
                        break;

                    case Border.Bottom:
                        g.DrawLine(pen, Math.Ceiling(rect.Left), rect.Bottom - box.ActualBorderBottomWidth / 2,
                                   rect.Right - 1, rect.Bottom - box.ActualBorderBottomWidth / 2);
                        break;

                    case Border.Right:
                        g.DrawLine(pen, rect.Right - box.ActualBorderRightWidth / 2, Math.Ceiling(rect.Top),
                                   rect.Right - box.ActualBorderRightWidth / 2, Math.Floor(rect.Bottom));
                        break;
                    }
                }
            }
        }