Beispiel #1
0
        /// <summary>
        /// Ensures that the specified length is converted to pixels if necessary
        /// </summary>
        /// <param name="length"></param>
        protected string NoEms(string length)
        {
            var len = new CssLength(length);

            if (len.Unit == CssUnit.Ems)
            {
                length = len.ConvertEmToPixels(GetEmHeight()).ToString();
            }
            return(length);
        }
        /// <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 float GetMaxTableWidth()
        {
            var tblen = new CssLength(_tableBox.MaxWidth);

            if (tblen.Number > 0)
            {
                _widthSpecified = true;
                return(tblen.IsPercentage ? CssValueParser.ParseNumber(tblen.Length, _tableBox.ParentBox.AvailableWidth) : tblen.Number);
            }
            else
            {
                return(9999f);
            }
        }
Beispiel #3
0
        /// <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 float 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);
            }
        }
Beispiel #4
0
        /// <summary>
        /// On image load process is complete with image or without update the image box.
        /// </summary>
        /// <param name="image">the image loaded or null if failed</param>
        /// <param name="rectangle">the source rectangle to draw in the image (empty - draw everything)</param>
        /// <param name="async">is the callback was called async to load image call</param>
        private void OnLoadImageComplete(Image image, Rectangle rectangle, bool async)
        {
            _imageWord.Image          = image;
            _imageWord.ImageRectangle = rectangle;
            _imageLoadingComplete     = true;
            _wordsSizeMeasured        = false;

            if (_imageLoadingComplete && image == null)
            {
                SetErrorBorder();
            }

            if (async)
            {
                var width  = new CssLength(Width);
                var height = new CssLength(Height);
                var layout = (width.Number <= 0 || width.Unit != CssUnit.Pixels) || (height.Number <= 0 || height.Unit != CssUnit.Pixels);
                HtmlContainer.RequestRefresh(layout);
            }
        }
Beispiel #5
0
        /// <summary>
        /// Gets the available width for the whole table.
        /// It also sets the value of <see cref="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 float GetAvailableWidth()
        {
            CssLength tblen = new CssLength(TableBox.Width);

            if (tblen.Number > 0)
            {
                _widthSpecified = true;

                if (tblen.IsPercentage)
                {
                    return(CssValueParser.ParseNumber(tblen.Length, TableBox.ParentBox.AvailableWidth));
                }
                else
                {
                    return(tblen.Number);
                }
            }
            else
            {
                return(TableBox.ParentBox.AvailableWidth);
            }
        }
Beispiel #6
0
        /// <summary>
        /// Analyzes the Table and assigns values to this CssTable object.
        /// To be called from the constructor
        /// </summary>
        private void Analyze(Graphics g)
        {
            #region Assign box kinds
            foreach (CssBox box in TableBox.Boxes)
            {
                switch (box.Display)
                {
                case CssConstants.TableCaption:
                    _caption = box;
                    break;

                case CssConstants.TableColumn:
                    for (int i = 0; i < GetSpan(box); i++)
                    {
                        Columns.Add(CreateColumn(box));
                    }
                    break;

                case CssConstants.TableColumnGroup:
                    if (box.Boxes.Count == 0)
                    {
                        int gspan = GetSpan(box);
                        for (int i = 0; i < gspan; i++)
                        {
                            Columns.Add(CreateColumn(box));
                        }
                    }
                    else
                    {
                        foreach (CssBox bb in box.Boxes)
                        {
                            int bbspan = GetSpan(bb);
                            for (int i = 0; i < bbspan; i++)
                            {
                                Columns.Add(CreateColumn(bb));
                            }
                        }
                    }
                    break;

                case CssConstants.TableFooterGroup:
                    if (FooterBox != null)
                    {
                        BodyRows.Add(box);
                    }
                    else
                    {
                        _footerBox = box;
                    }
                    break;

                case CssConstants.TableHeaderGroup:
                    if (HeaderBox != null)
                    {
                        BodyRows.Add(box);
                    }
                    else
                    {
                        _headerBox = box;
                    }
                    break;

                case CssConstants.TableRow:
                    BodyRows.Add(box);
                    break;

                case CssConstants.TableRowGroup:
                    foreach (CssBox childBox in box.Boxes)
                    {
                        if (childBox.Display == CssConstants.TableRow)
                        {
                            BodyRows.Add(childBox);
                        }
                    }
                    break;
                }
            }
            #endregion

            #region Gather AllRows

            if (HeaderBox != null)
            {
                _allRows.AddRange(HeaderBox.Boxes);
            }
            _allRows.AddRange(BodyRows);
            if (FooterBox != null)
            {
                _allRows.AddRange(FooterBox.Boxes);
            }

            #endregion

            #region Insert EmptyBoxes for vertical cell spanning

            if (!TableBox._tableFixed)
            {
                int           currow = 0;
                int           curcol = 0;
                List <CssBox> rows   = BodyRows;

                foreach (CssBox row in rows)
                {
                    curcol = 0;
                    for (int k = 0; k < row.Boxes.Count; k++)
                    {
                        CssBox cell    = row.Boxes[k];
                        int    rowspan = GetRowSpan(cell);
                        int    realcol = GetCellRealColumnIndex(row, cell); //Real column of the cell

                        for (int i = currow + 1; i < currow + rowspan; i++)
                        {
                            int colcount = 0;
                            for (int j = 0; j <= rows[i].Boxes.Count; j++)
                            {
                                if (colcount == realcol)
                                {
                                    rows[i].Boxes.Insert(colcount, new CssSpacingBox(TableBox, ref cell, currow));
                                    break;
                                }
                                colcount++;
                                realcol -= GetColSpan(rows[i].Boxes[j]) - 1;
                            }
                        }
                        curcol++;
                    }
                    currow++;
                }

                TableBox._tableFixed = true;
            }

            #endregion

            #region Determine Row and Column Count, and ColumnWidths

            //Rows
            _rowCount = BodyRows.Count + (HeaderBox != null ? HeaderBox.Boxes.Count : 0) + (FooterBox != null ? FooterBox.Boxes.Count : 0);

            //Columns
            if (Columns.Count > 0)
            {
                _columnCount = Columns.Count;
            }
            else
            {
                foreach (CssBox b in AllRows) //Check trhough rows
                {
                    _columnCount = Math.Max(_columnCount, b.Boxes.Count);
                }
            }

            //Initialize column widths array
            _columnWidths = new float[_columnCount];

            //Fill them with NaNs
            for (int i = 0; i < _columnWidths.Length; i++)
            {
                _columnWidths[i] = float.NaN;
            }

            float availCellSpace = GetAvailableCellWidth();

            if (Columns.Count > 0)
            {
                #region 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
                        }
                    }
                }

                #endregion
            }
            else
            {
                #region 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 (float.IsNaN(ColumnWidths[i]) &&                    //Check if no width specified for column
                            i < row.Boxes.Count &&                             //And there's a box to check
                            row.Boxes[i].Display == CssConstants.TableCell)    //And the box is a table-cell
                        {
                            CssLength len = new CssLength(row.Boxes[i].Width); //Get specified width

                            if (len.Number > 0)                                //If some width specified
                            {
                                int   colspan = GetColSpan(row.Boxes[i]);
                                float flen    = 0f;
                                if (len.IsPercentage)//Get width as a percentage
                                {
                                    flen = CssValueParser.ParseNumber(row.Boxes[i].Width, availCellSpace);
                                }
                                else if (len.Unit == CssUnit.Pixels || len.Unit == CssUnit.None)
                                {
                                    flen = len.Number; //Get width as an absolute-pixel value
                                }
                                flen /= Convert.ToSingle(colspan);

                                for (int j = i; j < i + colspan; j++)
                                {
                                    ColumnWidths[j] = flen;
                                }
                            }
                        }
                    }
                }
                #endregion
            }

            #endregion

            #region Determine missing Column widths

            if (WidthSpecified) //If a width was specified,
            {
                //Assign NaNs equally with space left after gathering not-NaNs
                int   numberOfNans = 0;
                float occupedSpace = 0f;

                //Calculate number of NaNs and occuped space
                foreach (float t in ColumnWidths)
                {
                    if (float.IsNaN(t))
                    {
                        numberOfNans++;
                    }
                    else
                    {
                        occupedSpace += t;
                    }
                }

                //Determine width that will be assigned to un asigned widths
                float nanWidth = (availCellSpace - occupedSpace) / Convert.ToSingle(numberOfNans);

                for (int i = 0; i < ColumnWidths.Length; i++)
                {
                    if (float.IsNaN(ColumnWidths[i]))
                    {
                        ColumnWidths[i] = nanWidth;
                    }
                }
            }
            else
            {
                //Assign NaNs using full width
                float[] maxFullWidths = new float[ColumnWidths.Length];

                //Get the maximum full length of NaN boxes
                foreach (CssBox row in AllRows)
                {
                    for (int i = 0; i < row.Boxes.Count; i++)
                    {
                        int col = GetCellRealColumnIndex(row, row.Boxes[i]);

                        if (float.IsNaN(ColumnWidths[col]) &&
                            i < row.Boxes.Count &&
                            GetColSpan(row.Boxes[i]) == 1)
                        {
                            maxFullWidths[col] = Math.Max(maxFullWidths[col], row.Boxes[i].GetFullWidth(g));
                        }
                    }
                }

                for (int i = 0; i < ColumnWidths.Length; i++)
                {
                    if (float.IsNaN(ColumnWidths[i]))
                    {
                        ColumnWidths[i] = maxFullWidths[i];
                    }
                }
            }

            #endregion

            #region Reduce widths if necessary

            int curCol = 0;

            //While table width is larger than it should, and width is reductable
            while (GetWidthSum() > GetAvailableWidth() && CanReduceWidth())
            {
                while (!CanReduceWidth(curCol))
                {
                    curCol++;
                }

                ColumnWidths[curCol] -= 1f;

                curCol++;

                if (curCol >= ColumnWidths.Length)
                {
                    curCol = 0;
                }
            }

            #endregion

            #region Check for minimum sizes (increment widths if necessary)

            foreach (CssBox row in AllRows)
            {
                foreach (CssBox cell in row.Boxes)
                {
                    int colspan   = GetColSpan(cell);
                    int col       = GetCellRealColumnIndex(row, cell);
                    int affectcol = col + colspan - 1;

                    if (ColumnWidths[col] < ColumnMinWidths[col])
                    {
                        float diff = ColumnMinWidths[col] - ColumnWidths[col];
                        ColumnWidths[affectcol] = ColumnMinWidths[affectcol];

                        if (col < ColumnWidths.Length - 1)
                        {
                            ColumnWidths[col + 1] -= diff;
                        }
                    }
                }
            }

            #endregion

            #region Set table padding

            //Ensure there's no padding
            TableBox.PaddingLeft = TableBox.PaddingTop = TableBox.PaddingRight = TableBox.PaddingBottom = "0";

            #endregion

            #region Layout cells

            //Actually layout cells!
            float startx     = TableBox.ClientLeft + HorizontalSpacing;
            float starty     = TableBox.ClientTop + VerticalSpacing;
            float curx       = startx;
            float cury       = starty;
            float maxRight   = startx;
            float maxBottom  = 0f;
            int   currentrow = 0;

            for (int i = 0; i < AllRows.Count; i++)
            {
                var row = AllRows[i];
                curx   = startx;
                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);
                    float width       = GetCellWidth(columnIndex, cell);
                    cell.Location = new PointF(curx, cury);
                    cell.Size     = new SizeF(width, 0f);
                    cell.MeasureBounds(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 + HorizontalSpacing;
                }

                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 + VerticalSpacing;
                currentrow++;
            }

            TableBox.ActualRight  = maxRight + HorizontalSpacing + TableBox.ActualBorderRightWidth;
            TableBox.ActualBottom = maxBottom + VerticalSpacing + TableBox.ActualBorderBottomWidth;

            #endregion
        }
        /// <summary>
        /// Measure image box size by the width\height set on the box and the actual rendered image size.<br/>
        /// If no image exists for the box error icon will be set.
        /// </summary>
        /// <param name="imageWord">the image word to measure</param>
        public static void MeasureImageSize(CssRectImage imageWord)
        {
            ArgChecker.AssertArgNotNull(imageWord, "imageWord");
            ArgChecker.AssertArgNotNull(imageWord.OwnerBox, "imageWord.OwnerBox");

            var width  = new CssLength(imageWord.OwnerBox.Width);
            var height = new CssLength(imageWord.OwnerBox.Height);

            bool hasImageTagWidth  = width.Number > 0 && width.Unit == CssUnit.Pixels;
            bool hasImageTagHeight = height.Number > 0 && height.Unit == CssUnit.Pixels;
            bool scaleImageHeight  = false;

            if (hasImageTagWidth)
            {
                imageWord.Width = width.Number;
            }
            else if (width.Number > 0 && width.IsPercentage)
            {
                imageWord.Width  = width.Number * imageWord.OwnerBox.ContainingBlock.Size.Width;
                scaleImageHeight = true;
            }
            else if (imageWord.Image != null)
            {
                imageWord.Width = imageWord.ImageRectangle == Rectangle.Empty ? imageWord.Image.Width : imageWord.ImageRectangle.Width;
            }
            else
            {
                imageWord.Width = hasImageTagHeight ? height.Number / 1.14f : 20;
            }

            var maxWidth = new CssLength(imageWord.OwnerBox.MaxWidth);

            if (maxWidth.Number > 0)
            {
                float maxWidthVal = -1;
                if (maxWidth.Unit == CssUnit.Pixels)
                {
                    maxWidthVal = maxWidth.Number;
                }
                else if (maxWidth.IsPercentage)
                {
                    maxWidthVal = maxWidth.Number * imageWord.OwnerBox.ContainingBlock.Size.Width;
                }

                if (maxWidthVal > -1 && imageWord.Width > maxWidthVal)
                {
                    imageWord.Width  = maxWidthVal;
                    scaleImageHeight = !hasImageTagHeight;
                }
            }

            if (hasImageTagHeight)
            {
                imageWord.Height = height.Number;
            }
            else if (imageWord.Image != null)
            {
                imageWord.Height = imageWord.ImageRectangle == Rectangle.Empty ? imageWord.Image.Height : imageWord.ImageRectangle.Height;
            }
            else
            {
                imageWord.Height = imageWord.Width > 0 ? imageWord.Width * 1.14f : 22.8f;
            }

            if (imageWord.Image != null)
            {
                // If only the width was set in the html tag, ratio the height.
                if ((hasImageTagWidth && !hasImageTagHeight) || scaleImageHeight)
                {
                    // Divide the given tag width with the actual image width, to get the ratio.
                    float ratio = imageWord.Width / imageWord.Image.Width;
                    imageWord.Height = imageWord.Image.Height * ratio;
                }
                // If only the height was set in the html tag, ratio the width.
                else if (hasImageTagHeight && !hasImageTagWidth)
                {
                    // Divide the given tag height with the actual image height, to get the ratio.
                    float ratio = imageWord.Height / imageWord.Image.Height;
                    imageWord.Width = imageWord.Image.Width * ratio;
                }
            }

            imageWord.Height += imageWord.OwnerBox.ActualBorderBottomWidth + imageWord.OwnerBox.ActualBorderTopWidth + imageWord.OwnerBox.ActualPaddingTop + imageWord.OwnerBox.ActualPaddingBottom;
        }
        /// <summary>
        /// Determine Row and Column Count, and ColumnWidths
        /// </summary>
        /// <returns></returns>
        private float 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 float[_columnCount];
            for (int i = 0; i < _columnWidths.Length; i++)
            {
                _columnWidths[i] = float.NaN;
            }

            float 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 (float.IsNaN(_columnWidths[i]) &&                   //Check if no width specified for column
                            i < row.Boxes.Count &&                             //And there's a box to check
                            row.Boxes[i].Display == CssConstants.TableCell)    //And the box is a table-cell
                        {
                            CssLength len = new CssLength(row.Boxes[i].Width); //Get specified width

                            if (len.Number > 0)                                //If some width specified
                            {
                                int   colspan = GetColSpan(row.Boxes[i]);
                                float flen    = 0f;
                                if (len.IsPercentage) //Get width as a percentage
                                {
                                    flen = CssValueParser.ParseNumber(row.Boxes[i].Width, availCellSpace);
                                }
                                else if (len.Unit == CssUnit.Pixels || len.Unit == CssUnit.None)
                                {
                                    flen = len.Number; //Get width as an absolute-pixel value
                                }
                                flen /= Convert.ToSingle(colspan);

                                for (int j = i; j < i + colspan; j++)
                                {
                                    _columnWidths[j] = flen;
                                }
                            }
                        }
                    }
                }
            }
            return(availCellSpace);
        }