コード例 #1
0
 /// <summary>
 /// Applies right to left direction to words
 /// </summary>
 /// <param name="blockBox"></param>
 /// <param name="lineBox"></param>
 private static void ApplyRightToLeft(CssBox blockBox, CssLineBox lineBox)
 {
     if (blockBox.Direction == CssConstants.Rtl)
     {
         ApplyRightToLeftOnLine(lineBox);
     }
     else
     {
         foreach (var box in lineBox.RelatedBoxes)
         {
             if (box.Direction == CssConstants.Rtl)
             {
                 ApplyRightToLeftOnSingleBox(lineBox, box);
             }
         }
     }
 }
コード例 #2
0
        /// <summary>
        /// Creates line boxes for the specified blockbox
        /// </summary>
        /// <param name="g"></param>
        /// <param name="blockBox"></param>
        public static void CreateLineBoxes(Graphics g, CssBox blockBox)
        {
            ArgChecker.AssertArgNotNull(g, "g");
            ArgChecker.AssertArgNotNull(blockBox, "blockBox");

            blockBox.LineBoxes.Clear();

            float limitRight = blockBox.ActualRight - blockBox.ActualPaddingRight - blockBox.ActualBorderRightWidth;

            //Get the start x and y of the blockBox
            float startx = blockBox.Location.X + blockBox.ActualPaddingLeft - 0 + blockBox.ActualBorderLeftWidth;
            float starty = blockBox.Location.Y + blockBox.ActualPaddingTop - 0 + blockBox.ActualBorderTopWidth;
            float curx   = startx + blockBox.ActualTextIndent;
            float cury   = starty;

            //Reminds the maximum bottom reached
            float maxRight  = startx;
            float maxBottom = starty;

            //First line box
            CssLineBox line = new CssLineBox(blockBox);

            //Flow words and boxes
            FlowBox(g, blockBox, blockBox, limitRight, 0, startx, ref line, ref curx, ref cury, ref maxRight, ref maxBottom);

            // if width is not restricted we need to lower it to the actual width
            if (blockBox.ActualRight >= 99999)
            {
                blockBox.ActualRight = maxRight + blockBox.ActualPaddingRight + blockBox.ActualBorderRightWidth;
            }

            //Gets the rectangles foreach linebox
            foreach (var linebox in blockBox.LineBoxes)
            {
                BubbleRectangles(blockBox, linebox);
                linebox.AssignRectanglesToBoxes();
                ApplyAlignment(g, linebox);
                if (blockBox.Direction == CssConstants.Rtl)
                {
                    ApplyRightToLeft(linebox);
                }
            }

            blockBox.ActualBottom = maxBottom + blockBox.ActualPaddingBottom + blockBox.ActualBorderBottomWidth;
        }
コード例 #3
0
        /// <summary>
        /// Simplest alignment, just arrange words.
        /// </summary>
        /// <param name="g"></param>
        /// <param name="line"></param>
        private static void ApplyLeftAlignment(IGraphics g, CssLineBox line)
        {
            //No alignment needed.

            //foreach (LineBoxRectangle r in line.Rectangles)
            //{
            //    float curx = r.Left + (r.Index == 0 ? r.OwnerBox.ActualPaddingLeft + r.OwnerBox.ActualBorderLeftWidth / 2 : 0);

            //    if (r.SpaceBefore) curx += r.OwnerBox.ActualWordSpacing;

            //    foreach (BoxWord word in r.Words)
            //    {
            //        word.Left = curx;
            //        word.Top = r.Top;// +r.OwnerBox.ActualPaddingTop + r.OwnerBox.ActualBorderTopWidth / 2;

            //        curx = word.Right + r.OwnerBox.ActualWordSpacing;
            //    }
            //}
        }
コード例 #4
0
        /// <summary>
        /// Applies centered alignment to the text on the linebox
        /// </summary>
        /// <param name="g"></param>
        /// <param name="lineBox"></param>
        private static void ApplyJustifyAlignment(Graphics g, CssLineBox lineBox)
        {
            if (lineBox.Equals(lineBox.OwnerBox.LineBoxes[lineBox.OwnerBox.LineBoxes.Count - 1]))
            {
                return;
            }

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

            #region Gather text sum

            foreach (CssBoxWord w in lineBox.Words)
            {
                textSum += w.Width;
                words   += 1f;
            }

            #endregion

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

            foreach (CssBoxWord 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;
                }

                //TODO: Background rectangles are being deactivated when justifying text.
            }
        }
コード例 #5
0
        /// <summary>
        /// Applies centered alignment to the text on the linebox
        /// </summary>
        /// <param name="g"></param>
        /// <param name="lineBox"></param>
        private static void ApplyJustifyAlignment(Graphics g, CssLineBox lineBox)
        {
            if (lineBox.Equals(lineBox.OwnerBox.LineBoxes[lineBox.OwnerBox.LineBoxes.Count - 1])) return;

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

            #region Gather text sum

            foreach (CssBoxWord w in lineBox.Words)
            {
                textSum += w.Width;
                words += 1f;
            }

            #endregion

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

            foreach (CssBoxWord 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;
                }

                //TODO: Background rectangles are being deactivated when justifying text.
            }
        }
コード例 #6
0
        /// <summary>
        /// Applies vertical and horizontal alignment to words in lineboxes
        /// </summary>
        /// <param name="g"></param>
        /// <param name="lineBox"></param>
        private static void ApplyAlignment(Graphics g, CssLineBox lineBox)
        {
            #region Horizontal alignment

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

            #endregion

            ApplyVerticalAlignment(g, lineBox);
        }
コード例 #7
0
        /// <summary>
        /// Applies RTL direction to all the words on the line.
        /// </summary>
        /// <param name="line">the line to apply RTL to</param>
        private static void ApplyRightToLeftOnLine(CssLineBox line)
        {
            float left = line.Words[0].Left;
            float right = line.Words[line.Words.Count-1].Right;

            foreach (CssRect word in line.Words)
            {
                float diff = word.Left - left;
                float wright = right - diff;
                word.Left = wright - word.Width;
            }
        }
コード例 #8
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(IGraphics g, CssBox blockbox, CssBox box, float limitRight, float linespacing, float startx, ref CssLineBox line, ref float curx, ref float cury, ref float maxRight, ref float 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)
            {
                float leftspacing  = b.Position != CssConstants.Absolute ? b.ActualMarginLeft + b.ActualBorderLeftWidth + b.ActualPaddingLeft : 0;
                float rightspacing = b.Position != CssConstants.Absolute ? 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;

                        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 RectangleF(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;
        }
コード例 #9
0
        /// <summary>
        /// Creates line boxes for the specified blockbox
        /// </summary>
        /// <param name="g"></param>
        /// <param name="blockBox"></param>
        public static void CreateLineBoxes(Graphics g, CssBox blockBox)
        {
            blockBox.LineBoxes.Clear();

            float maxRight = blockBox.ActualRight - blockBox.ActualPaddingRight - blockBox.ActualBorderRightWidth;

            //Get the start x and y of the blockBox
            float startx = blockBox.Location.X + blockBox.ActualPaddingLeft - 0 + blockBox.ActualBorderLeftWidth;
            float starty = blockBox.Location.Y + blockBox.ActualPaddingTop - 0 + blockBox.ActualBorderTopWidth;
            float curx = startx + blockBox.ActualTextIndent;
            float cury = starty;

            //Reminds the maximum bottom reached
            float maxBottom = starty;

            //First line box
            CssLineBox line = new CssLineBox(blockBox);

            //Flow words and boxes
            FlowBox(g, blockBox, blockBox, maxRight, 0, startx,ref line, ref curx, ref cury, ref maxBottom);

            //Gets the rectangles foreach linebox
            foreach (var linebox in blockBox.LineBoxes)
            {
                BubbleRectangles(blockBox, linebox);
                linebox.AssignRectanglesToBoxes();
                ApplyAlignment(g, linebox);
                if (blockBox.Direction == CssConstants.Rtl)
                    ApplyRightToLeft(linebox);
            }

            blockBox.ActualBottom = maxBottom + blockBox.ActualPaddingBottom + blockBox.ActualBorderBottomWidth;
        }
コード例 #10
0
        /// <summary>
        /// Recursively creates the rectangles of the blockBox, by bubbling from deep to outside of the boxes 
        /// in the rectangle structure
        /// </summary>
        private static void BubbleRectangles(CssBox box, CssLineBox line)
        {
            if (box.Words.Count > 0)
            {
                float x = float.MaxValue, y = float.MaxValue, r = float.MinValue, b = float.MinValue;
                List<CssBoxWord> words = line.WordsOf(box);

                if (words.Count > 0)
                {
                    foreach (CssBoxWord word in words)
                    {
                        x = Math.Min(x, word.Left); // - word.SpacesBeforeWidth);
                        r = Math.Max(r, word.Right); // + word.SpacesAfterWidth);
                        y = Math.Min(y, word.Top);
                        b = Math.Max(b, word.Bottom);
                    }
                    line.UpdateRectangle(box, x, y, r, b);
                }
            }
            else
            {
                foreach (CssBox b in box.Boxes)
                {
                    BubbleRectangles(b, line);
                }
            }
        }
コード例 #11
0
        /// <summary>
        /// Applies right to left direction to words
        /// </summary>
        /// <param name="line"></param>
        private static void ApplyRightToLeft(CssLineBox line)
        {
            float left = line.OwnerBox.ClientLeft;
            float right = line.OwnerBox.ClientRight;

            foreach (CssBoxWord word in line.Words)
            {
                float diff = word.Left - left;
                float wright = right - diff;
                word.Left = wright - word.Width;
            }
        }
コード例 #12
0
ファイル: CssBox.cs プロジェクト: Alister742/ParseKit
        /// <summary>
        /// Searches for the first word occourence inside the box, on the specified linebox
        /// </summary>
        /// <param name="b"></param>
        /// <param name="line"> </param>
        /// <returns></returns>
        internal CssBoxWord FirstWordOccourence(CssBox b, CssLineBox line)
        {
            if (b.Words.Count == 0 && b.Boxes.Count == 0)
            {
                return null;
            }

            if (b.Words.Count > 0)
            {
                foreach (CssBoxWord word in b.Words)
                {
                    if (line.Words.Contains(word))
                    {
                        return word;
                    }
                }
                return null;
            }
            else
            {
                foreach (CssBox bb in b.Boxes)
                {
                    CssBoxWord w = FirstWordOccourence(bb, line);

                    if (w != null)
                    {
                        return w;
                    }
                }

                return null;
            }
        }
コード例 #13
0
ファイル: DomUtils.cs プロジェクト: havlenapetr/HTMLRenderer
 /// <summary>
 /// Get css word box under the given sub-tree at the given x,y location.<br/>
 /// the location must be in correct scroll offset.
 /// </summary>
 /// <param name="lineBox">the line box to search in</param>
 /// <param name="location">the location to find the box at</param>
 /// <returns>css word box if exists or null</returns>
 public static CssRect GetCssBoxWord(CssLineBox lineBox, Point location)
 {
     foreach (var rects in lineBox.Rectangles)
     {
         foreach (var word in rects.Key.Words)
         {
             // add word spacing to word width so sentance won't have hols in it when moving the mouse
             var rect = word.Rectangle;
             rect.Width += word.OwnerBox.ActualWordSpacing;
             if (rect.Contains(location))
             {
                 return word;
             }
         }
     }
     return null;
 }
コード例 #14
0
ファイル: CssBox.cs プロジェクト: Alister742/ParseKit
        /// <summary>
        /// Paints the fragment
        /// </summary>
        /// <param name="g"></param>
        private void PaintImp(Graphics g)
        {
            if (Display != CssConstants.None && (Display != CssConstants.TableCell || EmptyCells != CssConstants.Hide || !IsSpaceOrEmpty))
            {
                var areas = Rectangles.Count == 0 ? new List <RectangleF>(new[] { Bounds }) : new List <RectangleF>(Rectangles.Values);

                RectangleF[] rects  = areas.ToArray();
                PointF       offset = HtmlContainer != null ? HtmlContainer.ScrollOffset : PointF.Empty;

                for (int i = 0; i < rects.Length; i++)
                {
                    var actualRect = rects[i];
                    actualRect.Offset(offset);

                    PaintBackground(g, actualRect, i == rects.Length - 1);
                    PaintBorder(g, actualRect, i == 0, i == rects.Length - 1);
                }

                if (IsImage)
                {
                    var        word = Words[0];
                    RectangleF r    = word.Bounds;
                    r.Offset(offset);
                    r.Height -= ActualBorderTopWidth + ActualBorderBottomWidth + ActualPaddingTop + ActualPaddingBottom;
                    r.Y      += ActualBorderTopWidth + ActualPaddingTop;

                    //HACK: round rectangle only when necessary
                    g.DrawImage(word.Image, Rectangle.Round(r));

                    if (word.Selected)
                    {
                        g.FillRectangle(CssUtils.SelectionBackcolor, word.Left - word.LastMeasureOffset.X + offset.X, word.Top + offset.Y, word.Width, DomUtils.GetCssLineBoxByWord(word).LineHeight);
                    }
                }
                else if (Words.Count > 0)
                {
                    Font font  = ActualFont;
                    var  brush = CssUtils.GetSolidBrush(CssValueParser.GetActualColor(Color));
                    foreach (var word in Words)
                    {
                        if (word.Selected)
                        {
                            // handle paint selected word background and with partial word selection
                            var left  = word.SelectedStartOffset > -1 ? word.SelectedStartOffset : 0;
                            var width = word.SelectedEndOffset > -1 ? word.SelectedEndOffset + word.LastMeasureOffset.X : word.Width;


                            //REFACTOR THIS STUFF
                            Brush      b   = CssUtils.SelectionBackcolor;
                            CssLineBox box = DomUtils.GetCssLineBoxByWord(word);
                            float      h   = box != null ? box.LineHeight : 0;
                            float      w   = width - left;
                            float      x   = word.Left - word.LastMeasureOffset.X + offset.X + left;
                            float      y   = word.Top + offset.Y;


                            g.FillRectangle(b, x, y, w, h);
                        }

                        g.DrawString(word.Text, font, brush, word.Left - word.LastMeasureOffset.X + offset.X, word.Top + offset.Y);
                    }
                }

                for (int i = 0; i < rects.Length; i++)
                {
                    var actualRect = rects[i];
                    actualRect.Offset(offset);
                    PaintDecoration(g, actualRect, i == 0, i == rects.Length - 1);
                }

                foreach (CssBox b in Boxes)
                {
                    b.Paint(g);
                }

                CreateListItemBox(g);

                if (ListItemBox != null)
                {
                    ListItemBox.Paint(g);
                }
            }
        }
コード例 #15
0
        /// <summary>
        /// Creates line boxes for the specified blockbox
        /// </summary>
        /// <param name="g"></param>
        /// <param name="blockBox"></param>
        public static void CreateLineBoxes(IGraphics g, CssBox blockBox)
        {
            ArgChecker.AssertArgNotNull(g, "g");
            ArgChecker.AssertArgNotNull(blockBox, "blockBox");

            blockBox.LineBoxes.Clear();

            float limitRight = blockBox.ActualRight - blockBox.ActualPaddingRight - blockBox.ActualBorderRightWidth;

            //Get the start x and y of the blockBox
            float startx = blockBox.Location.X + blockBox.ActualPaddingLeft - 0 + blockBox.ActualBorderLeftWidth;
            float starty = blockBox.Location.Y + blockBox.ActualPaddingTop - 0 + blockBox.ActualBorderTopWidth;
            float curx = startx + blockBox.ActualTextIndent;
            float cury = starty;

            //Reminds the maximum bottom reached
            float maxRight = startx;
            float maxBottom = starty;

            //First line box
            CssLineBox line = new CssLineBox(blockBox);

            //Flow words and boxes
            FlowBox(g, blockBox, blockBox, limitRight, 0, startx, ref line, ref curx, ref cury, ref maxRight, ref maxBottom);

            // if width is not restricted we need to lower it to the actual width
            if( blockBox.ActualRight >= 90999 )
            {
                blockBox.ActualRight = maxRight + blockBox.ActualPaddingRight + blockBox.ActualBorderRightWidth;
            }

            //Gets the rectangles for each line-box
            foreach (var linebox in blockBox.LineBoxes)
            {
                ApplyAlignment(g, linebox);
                ApplyRightToLeft(blockBox, linebox);
                BubbleRectangles(blockBox, linebox);
                linebox.AssignRectanglesToBoxes();
            }

            blockBox.ActualBottom = maxBottom + blockBox.ActualPaddingBottom + blockBox.ActualBorderBottomWidth;

            // handle limiting block height when overflow is hidden
            if( blockBox.Height != null && blockBox.Height != CssConstants.Auto && blockBox.Overflow == CssConstants.Hidden && blockBox.ActualBottom - blockBox.Location.Y > blockBox.ActualHeight )
            {
                blockBox.ActualBottom = blockBox.Location.Y + blockBox.ActualHeight;
            }
        }
コード例 #16
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(IGraphics g, CssBox blockbox, CssBox box, float limitRight, float linespacing, float startx, ref CssLineBox line, ref float curx, ref float cury, ref float maxRight, ref float 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)
            {
                float leftspacing = b.Position != CssConstants.Absolute ? b.ActualMarginLeft + b.ActualBorderLeftWidth + b.ActualPaddingLeft : 0;
                float rightspacing = b.Position != CssConstants.Absolute ? 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) || 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.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;

                        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 RectangleF(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;
        }
コード例 #17
0
        /// <summary>
        /// Recursively creates the rectangles of the blockBox, by bubbling from deep to outside of the boxes 
        /// in the rectangle structure
        /// </summary>
        private static void BubbleRectangles(CssBox box, CssLineBox line)
        {
            if (box.Words.Count > 0)
            {
                float x = Single.MaxValue, y = Single.MaxValue, r = Single.MinValue, b = Single.MinValue;
                List<CssRect> words = line.WordsOf(box);

                if (words.Count > 0)
                {
                    foreach (CssRect word in words)
                    {
                        // handle if line is wrapped for the first text element where parent has left margin\padding
                        var left = word.Left;
                        if (box == box.ParentBox.Boxes[0] && word == box.Words[0] && word == line.Words[0] && line != line.OwnerBox.LineBoxes[0] && !word.IsLineBreak)
                            left -= box.ParentBox.ActualMarginLeft + box.ParentBox.ActualBorderLeftWidth + box.ParentBox.ActualPaddingLeft;

                        x = Math.Min(x, left);
                        r = Math.Max(r, word.Right - word.ActualWordSpacing);
                        y = Math.Min(y, word.Top);
                        b = Math.Max(b, word.Bottom);
                    }
                    line.UpdateRectangle(box, x, y, r, b);
                }
            }
            else
            {
                foreach (CssBox b in box.Boxes)
                {
                    BubbleRectangles(b, line);
                }
            }
        }
コード例 #18
0
        /// <summary>
        /// Applies RTL direction to specific box words on the line.
        /// </summary>
        /// <param name="lineBox"></param>
        /// <param name="box"></param>
        private static void ApplyRightToLeftOnSingleBox(CssLineBox lineBox, CssBox box)
        {
            int leftWordIdx = -1;
            int rightWordIdx = -1;
            for (int i = 0; i < lineBox.Words.Count; i++)
            {
                if (lineBox.Words[i].OwnerBox == box)
                {
                    if (leftWordIdx < 0)
                        leftWordIdx = i;
                    rightWordIdx = i;
                }
            }

            if (leftWordIdx > -1 && rightWordIdx > leftWordIdx)
            {
                float left = lineBox.Words[leftWordIdx].Left;
                float right = lineBox.Words[rightWordIdx].Right;

                for (int i = leftWordIdx; i <= rightWordIdx; i++)
                {
                    float diff = lineBox.Words[i].Left - left;
                    float wright = right - diff;
                    lineBox.Words[i].Left = wright - lineBox.Words[i].Width;
                }
            }
        }
コード例 #19
0
        /// <summary>
        /// Simplest alignment, just arrange words.
        /// </summary>
        /// <param name="g"></param>
        /// <param name="line"></param>
        private static void ApplyLeftAlignment(Graphics g, CssLineBox line)
        {
            //No alignment needed.

            //foreach (LineBoxRectangle r in line.Rectangles)
            //{
            //    float curx = r.Left + (r.Index == 0 ? r.OwnerBox.ActualPaddingLeft + r.OwnerBox.ActualBorderLeftWidth / 2 : 0);

            //    if (r.SpaceBefore) curx += r.OwnerBox.ActualWordSpacing;

            //    foreach (BoxWord word in r.Words)
            //    {
            //        word.Left = curx;
            //        word.Top = r.Top;// +r.OwnerBox.ActualPaddingTop + r.OwnerBox.ActualBorderTopWidth / 2;

            //        curx = word.Right + r.OwnerBox.ActualWordSpacing;
            //    }
            //}
        }
コード例 #20
0
        /// <summary>
        /// Applies right alignment to the text on the linebox
        /// </summary>
        /// <param name="g"></param>
        /// <param name="line"></param>
        private static void ApplyRightAlignment(Graphics g, CssLineBox line)
        {
            if (line.Words.Count == 0) return;

            CssBoxWord lastWord = line.Words[line.Words.Count - 1];
            float right = line.OwnerBox.ActualRight - line.OwnerBox.ActualPaddingRight - line.OwnerBox.ActualBorderRightWidth;
            float diff = right - lastWord.Right - lastWord.LastMeasureOffset.X - lastWord.OwnerBox.ActualBorderRightWidth - lastWord.OwnerBox.ActualPaddingRight;

            if (diff <= 0) return;

            //if (line.OwnerBox.Direction == CssConstants.Rtl)
            //{

            //}

            foreach (CssBoxWord word in line.Words)
            {
                word.Left += diff;
            }

            foreach (CssBox b in line.Rectangles.Keys)
            {
                RectangleF r = b.Rectangles[line];
                b.Rectangles[line] = new RectangleF(r.X + diff, r.Y, r.Width, r.Height);
            }
        }
コード例 #21
0
ファイル: CssBox.cs プロジェクト: Alister742/ParseKit
        /// <summary>
        /// Offsets the rectangle of the specified linebox by the specified gap,
        /// and goes deep for rectangles of children in that linebox.
        /// </summary>
        /// <param name="lineBox"></param>
        /// <param name="gap"></param>
        internal void OffsetRectangle(CssLineBox lineBox, float gap)
        {
            if (Rectangles.ContainsKey(lineBox))
            {
                RectangleF r = Rectangles[lineBox];
                Rectangles[lineBox] = new RectangleF(r.X, r.Y + gap, r.Width, r.Height);
            }

            //foreach (Box b in Boxes)
            //{
            //    b.OffsetRectangle(lineBox, gap);
            //}
        }
コード例 #22
0
        /// <summary>
        /// Applies vertical alignment to the linebox
        /// </summary>
        /// <param name="g"></param>
        /// <param name="lineBox"></param>
        private static void ApplyVerticalAlignment(Graphics g, CssLineBox lineBox)
        {
            float baseline = float.MinValue;
            foreach (var box in lineBox.Rectangles.Keys)
            {
                baseline = Math.Max(baseline, lineBox.Rectangles[box].Top);
            }

            var boxes = new List<CssBox>(lineBox.Rectangles.Keys);
            foreach (CssBox box in boxes)
            {
                //Important notes on http://www.w3.org/TR/CSS21/tables.html#height-layout
                switch (box.VerticalAlign)
                {
                    case CssConstants.Sub:
                        lineBox.SetBaseLine(g, box, baseline + lineBox.Rectangles[box].Height*.2f);
                        break;
                    case CssConstants.Super:
                        lineBox.SetBaseLine(g, box, baseline - lineBox.Rectangles[box].Height*.2f);
                        break;
                    case CssConstants.TextTop:

                        break;
                    case CssConstants.TextBottom:

                        break;
                    case CssConstants.Top:

                        break;
                    case CssConstants.Bottom:

                        break;
                    case CssConstants.Middle:

                        break;
                    default:
                        //case: baseline
                        lineBox.SetBaseLine(g, box, baseline);
                        break;
                }
            }
        }
コード例 #23
0
        /// <summary>
        /// Applies right alignment to the text on the linebox
        /// </summary>
        /// <param name="g"></param>
        /// <param name="line"></param>
        private static void ApplyRightAlignment(IGraphics g, CssLineBox line)
        {
            if (line.Words.Count == 0) return;

            CssRect lastWord = line.Words[line.Words.Count - 1];
            float right = line.OwnerBox.ActualRight - line.OwnerBox.ActualPaddingRight - line.OwnerBox.ActualBorderRightWidth;
            float diff = right - lastWord.Right - lastWord.OwnerBox.ActualBorderRightWidth - lastWord.OwnerBox.ActualPaddingRight;

            if (diff > 0)
            {
                foreach (CssRect word in line.Words)
                {
                    word.Left += diff;
                }

                foreach (CssBox b in line.Rectangles.Keys)
                {
                    RectangleF r = b.Rectangles[line];
                    b.Rectangles[line] = new RectangleF(r.X + diff, r.Y, r.Width, r.Height);
                }
            }
        }
コード例 #24
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="maxright">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="maxbottom">Maximum bottom reached so far</param>
        private static void FlowBox(Graphics g, CssBox blockbox, CssBox box, float maxright, float linespacing, float startx, ref CssLineBox line, ref float curx, ref float cury, ref float maxbottom)
        {
            var startY = cury;
            box.FirstHostingLineBox = line;

            foreach (CssBox b in box.Boxes)
            {
                float leftspacing = b.ActualMarginLeft + b.ActualBorderLeftWidth + b.ActualPaddingLeft;
                float rightspacing = b.ActualMarginRight + b.ActualBorderRightWidth + b.ActualPaddingRight;

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

                curx += leftspacing;

                if (b.Words.Count > 0)
                {
                    // fix word space for first word in inline tag
                    if (!b.Words[0].IsImage && b.Words[0].HasSpaceBefore && b.Display == CssConstants.Inline)
                    {
                        var sib = DomUtils.GetPreviousContainingBlockSibling(b);
                        if (sib != null && sib.Display == CssConstants.Inline)
                            curx += b.ActualWordSpacing;
                    }

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

                        if ((b.WhiteSpace != CssConstants.Nowrap && curx + word.Width + rightspacing > maxright) || word.IsLineBreak)
                        {
                            curx = startx;
                            cury = maxbottom + linespacing;

                            line = new CssLineBox(blockbox);

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

                        // atodo: why?
                        line.ReportExistanceOf(word);

                        word.Left = curx; // -word.LastMeasureOffset.X + 1;
                        word.Top = cury; // - word.LastMeasureOffset.Y;

                        curx = word.Right + (word.IsImage ? b.ActualWordSpacing : 0); // +word.SpacesAfterWidth;

                        maxbottom = Math.Max(maxbottom, word.Bottom); //+ (word.IsImage ? topspacing + bottomspacing : 0));
                    }

                    // fix word space for last word that is right before inline tag
                    var lastWord = b.Words[b.Words.Count-1];
                    if (!lastWord.IsImage && !lastWord.HasSpaceAfter)
                    {
                        var next = DomUtils.GetNextSibling(b);
                        if (next == null || next.Display == CssConstants.Inline)
                            curx -= b.ActualWordSpacing + CssUtils.GetWordEndWhitespace(b.ActualFont);
                    }
                }
                else
                {
                    FlowBox(g, blockbox, b, maxright, linespacing, startx, ref line, ref curx, ref cury, ref maxbottom);
                }

                curx += rightspacing;
            }

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

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

            box.LastHostingLineBox = line;
        }
コード例 #25
0
ファイル: CssBox.cs プロジェクト: havlenapetr/HTMLRenderer
 /// <summary>
 /// Offsets the rectangle of the specified linebox by the specified gap,
 /// and goes deep for rectangles of children in that linebox.
 /// </summary>
 /// <param name="lineBox"></param>
 /// <param name="gap"></param>
 internal void OffsetRectangle(CssLineBox lineBox, float gap)
 {
     if (Rectangles.ContainsKey(lineBox))
     {
         var r = Rectangles[lineBox];
         Rectangles[lineBox] = new RectangleF(r.X, r.Y + gap, r.Width, r.Height);
     }
 }
コード例 #26
0
ファイル: DomUtils.cs プロジェクト: Alister742/ParseKit
 /// <summary>
 /// Get css word box under the given sub-tree at the given x,y location.<br/>
 /// the location must be in correct scroll offset.
 /// </summary>
 /// <param name="lineBox">the line box to search in</param>
 /// <param name="location">the location to find the box at</param>
 /// <returns>css word box if exists or null</returns>
 public static CssBoxWord GetCssBoxWord(CssLineBox lineBox, Point location)
 {
     foreach (var rect in lineBox.Rectangles)
     {
         foreach (var word in rect.Key.Words)
         {
             if (word.Bounds.Contains(location))
             {
                 return word;
             }
         }
     }
     return null;
 }
コード例 #27
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="maxright">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="maxbottom">Maximum bottom reached so far</param>
        private static void FlowBox(Graphics g, CssBox blockbox, CssBox box, float maxright, float linespacing, float startx, ref CssLineBox line, ref float curx, ref float cury, ref float maxbottom)
        {
            var startY = cury;

            box.FirstHostingLineBox = line;

            foreach (CssBox b in box.Boxes)
            {
                float leftspacing  = b.ActualMarginLeft + b.ActualBorderLeftWidth + b.ActualPaddingLeft;
                float rightspacing = b.ActualMarginRight + b.ActualBorderRightWidth + b.ActualPaddingRight;

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

                curx += leftspacing;

                if (b.Words.Count > 0)
                {
                    // fix word space for first word in inline tag
                    if (!b.Words[0].IsImage && b.Words[0].HasSpaceBefore && b.Display == CssConstants.Inline)
                    {
                        var sib = DomUtils.GetPreviousContainingBlockSibling(b);
                        if (sib != null && sib.Display == CssConstants.Inline)
                        {
                            curx += b.ActualWordSpacing;
                        }
                    }

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

                        if ((b.WhiteSpace != CssConstants.Nowrap && curx + word.Width + rightspacing > maxright) || word.IsLineBreak)
                        {
                            curx = startx;
                            cury = maxbottom + linespacing;

                            line = new CssLineBox(blockbox);

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

                        // atodo: why?
                        line.ReportExistanceOf(word);

                        word.Left = curx;                                             // -word.LastMeasureOffset.X + 1;
                        word.Top  = cury;                                             // - word.LastMeasureOffset.Y;

                        curx = word.Right + (word.IsImage ? b.ActualWordSpacing : 0); // +word.SpacesAfterWidth;

                        maxbottom = Math.Max(maxbottom, word.Bottom);                 //+ (word.IsImage ? topspacing + bottomspacing : 0));
                    }

                    // fix word space for last word that is right before inline tag
                    var lastWord = b.Words[b.Words.Count - 1];
                    if (!lastWord.IsImage && !lastWord.HasSpaceAfter)
                    {
                        var next = DomUtils.GetNextSibling(b);
                        if (next == null || next.Display == CssConstants.Inline)
                        {
                            curx -= b.ActualWordSpacing + CssUtils.GetWordEndWhitespace(b.ActualFont);
                        }
                    }
                }
                else
                {
                    FlowBox(g, blockbox, b, maxright, linespacing, startx, ref line, ref curx, ref cury, ref maxbottom);
                }

                curx += rightspacing;
            }

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

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

            box.LastHostingLineBox = line;
        }
コード例 #28
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(Graphics g, CssBox blockbox, CssBox box, float limitRight, float linespacing, float startx, ref CssLineBox line, ref float curx, ref float cury, ref float maxRight, ref float maxbottom)
        {
            var startY = cury;

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

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

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

                curx += leftspacing;

                if (b.Words.Count > 0)
                {
                    // fix word space for first word in inline tag
                    if (!b.Words[0].IsImage && b.Words[0].HasSpaceBefore && b.IsInline)
                    {
                        var sib = DomUtils.GetPreviousContainingBlockSibling(b);
                        if (sib != null && sib.IsInline)
                        {
                            curx += b.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) || word.IsLineBreak)
                        {
                            curx = startx;

                            // handle if line is wrapped for the first text element where parent has left margin\padding
                            if (b == box.Boxes[0] && word == b.Words[0] && !word.IsLineBreak)
                            {
                                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;

                        curx = word.Left + word.FullWidth - word.LastMeasureOffset.X / 2;

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

                        if (b.Position != CssConstants.Absolute)
                        {
                        }
                        else
                        {
                            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 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 possition elements
            if (box.Position == CssConstants.Absolute)
            {
                curx      = localCurx;
                maxRight  = localMaxRight;
                maxbottom = localmaxbottom;
                AdjustAbsolutePosition(box, 0, 0);
            }

            box.LastHostingLineBox = line;
        }
コード例 #29
0
 /// <summary>
 /// Applies right to left direction to words
 /// </summary>
 /// <param name="blockBox"></param>
 /// <param name="lineBox"></param>
 private static void ApplyRightToLeft(CssBox blockBox, CssLineBox lineBox)
 {
     if( blockBox.Direction == CssConstants.Rtl )
     {
         ApplyRightToLeftOnLine(lineBox);
     }
     else
     {
         foreach(var box in lineBox.RelatedBoxes)
         {
             if (box.Direction == CssConstants.Rtl)
             {
                 ApplyRightToLeftOnSingleBox(lineBox, box);
             }
         }
     }
 }