GetChildBoxIter() 공개 메소드

public GetChildBoxIter ( ) : IEnumerable
리턴 IEnumerable
예제 #1
0
            static IEnumerable <CssLineBox> GetLineWalkDownIter(LineWalkVisitor visitor, CssBox box)
            {
                //recursive
                float y = visitor._globalY;

                if (box.LineBoxCount > 0)
                {
                    foreach (CssLineBox linebox in box.GetLineBoxIter())
                    {
                        visitor._globalY = y + linebox.CachedLineTop;
                        yield return(linebox);
                    }
                }
                else
                {
                    //element based
                    foreach (CssBox childbox in box.GetChildBoxIter())
                    {
                        visitor._globalY = y + childbox.LocalY;
                        //recursive
                        foreach (var linebox in GetLineWalkDownIter(visitor, childbox))
                        {
                            yield return(linebox);
                        }
                    }
                }

                visitor._globalY = y;
            }
예제 #2
0
        internal static CssLineBox GetNearestLine(CssBox a, Point point, out bool found)
        {
            if (a.LineBoxCount > 0)
            {
                CssLineBox latestLine = null;
                int        y          = point.Y;
                found = false;
                foreach (CssLineBox linebox in a.GetLineBoxIter())
                {
                    if (linebox.CachedLineBottom < y)
                    {
                        latestLine = linebox;
                    }
                    else
                    {
                        if (latestLine != null)
                        {
                            found = true;
                        }
                        break;
                    }
                }

                return(latestLine);
            }
            else
            {
                bool       foundExact = false;
                CssLineBox lastLine   = null;
                foreach (CssBox cbox in a.GetChildBoxIter())
                {
                    CssLineBox candidateLine = GetNearestLine(cbox, point, out foundExact);
                    if (candidateLine != null)
                    {
                        if (foundExact)
                        {
                            found = true;
                            return(lastLine);
                        }
                        //not exact
                        lastLine = candidateLine;
                    }
                    else
                    {
                        if (lastLine != null)
                        {
                            found = false;
                            return(lastLine);
                        }
                    }
                }
                found = foundExact;
            }
            return(null);
        }
예제 #3
0
 internal static IEnumerable <CssLineBox> GetDeepDownLineBoxIter(CssBox box)
 {
     if (box.LineBoxCount > 0)
     {
         foreach (CssLineBox linebox in box.GetLineBoxIter())
         {
             yield return(linebox);
         }
     }
     else
     {
         if (box.ChildCount > 0)
         {
             foreach (CssBox child in box.GetChildBoxIter())
             {
                 foreach (CssLineBox linebox in GetDeepDownLineBoxIter(child))
                 {
                     yield return(linebox);
                 }
             }
         }
     }
 }
예제 #4
0
        public static bool HitTest(CssBox box, float x, float y, CssBoxHitChain hitChain)
        {
            //--------------------------------------
            float boxHitLocalX  = x - box.LocalX;
            float boxHitLocalY  = y - box.LocalY;
            bool  isPointInArea = box.IsPointInArea(x, y);

            //----------------------------------------------------------------------
            if (isPointInArea)
            {
                hitChain.AddHit(box, (int)boxHitLocalX, (int)boxHitLocalY);
            }

            //check absolute layer first ***
            if (box.HasAbsoluteLayer)
            {
                hitChain.PushContextBox(box);
                foreach (var absBox in box.GetAbsoluteChildBoxBackwardIter())
                {
                    if (HitTest(absBox, boxHitLocalX, boxHitLocalY, hitChain))
                    {
                        //found hit
                        hitChain.PopContextBox(box);
                        return(true);
                    }
                }
                hitChain.PopContextBox(box);
            }
            //----------------------------------------------------------------------
            if (!isPointInArea)
            {
                switch (box.CssDisplay)
                {
                case Css.CssDisplay.TableRow:
                {
                    foreach (var childBox in box.GetChildBoxIter())
                    {
                        if (HitTest(childBox, x, y, hitChain))
                        {
                            return(true);
                        }
                    }
                } break;
                }
                //exit
                return(false);
            }
            //----------------------------------------------------------------------
            //at here point is in the area***

            hitChain.PushContextBox(box);
            if (box.IsCustomCssBox)
            {
                //custom css box
                //return true= stop here
                if (box.CustomContentHitTest(x, y, hitChain))
                {
                    hitChain.PopContextBox(box);
                    return(true);
                }
            }

            if (box.LineBoxCount > 0)
            {
                bool foundSomeLine = false;
                foreach (var lineBox in box.GetLineBoxIter())
                {
                    //line box not overlap
                    if (lineBox.HitTest(boxHitLocalX, boxHitLocalY))
                    {
                        foundSomeLine = true;
                        float lineBoxLocalY = boxHitLocalY - lineBox.CachedLineTop;
                        //2.
                        hitChain.AddHit(lineBox, (int)boxHitLocalX, (int)lineBoxLocalY);

                        var foundRun = BoxHitUtils.GetCssRunOnLocation(lineBox, (int)boxHitLocalX, (int)lineBoxLocalY);

                        if (foundRun != null)
                        {
                            //3.
                            hitChain.AddHit(foundRun, (int)(boxHitLocalX - foundRun.Left), (int)lineBoxLocalY);
                            //4. go deeper for block run
                            if (foundRun.Kind == CssRunKind.BlockRun)
                            {
                                var        blockRun = (CssBlockRun)foundRun;
                                CssLineBox hostLine = blockRun.HostLine;
                                //adjust with hostline

                                HitTest(((CssBlockRun)foundRun).ContentBox, (int)(boxHitLocalX - foundRun.Left), boxHitLocalY - hostLine.CachedLineTop, hitChain);
                            }
                        }
                        //found line box
                        hitChain.PopContextBox(box);
                        return(true);
                    }
                    else if (foundSomeLine)
                    {
                        return(false);
                    }
                }
            }
            else
            {
                //iterate in child
                foreach (var childBox in box.GetChildBoxIter())
                {
                    if (HitTest(childBox, boxHitLocalX, boxHitLocalY, hitChain))
                    {
                        //recursive
                        hitChain.PopContextBox(box);
                        return(true);
                    }
                }
            }
            hitChain.PopContextBox(box);
            return(true);
        }
예제 #5
0
        public static bool HitTest(CssBox box, float x, float y, CssBoxHitChain hitChain)
        {
            //--------------------------------------
            float boxHitLocalX = x - box.LocalX;
            float boxHitLocalY = y - box.LocalY;
            bool isPointInArea = box.IsPointInArea(x, y);
            //----------------------------------------------------------------------
            if (isPointInArea)
            {
                hitChain.AddHit(box, (int)boxHitLocalX, (int)boxHitLocalY);
            }

            //check absolute layer first ***
            if (box.HasAbsoluteLayer)
            {
                hitChain.PushContextBox(box);
                foreach (var absBox in box.GetAbsoluteChildBoxBackwardIter())
                {
                    if (HitTest(absBox, boxHitLocalX, boxHitLocalY, hitChain))
                    {
                        //found hit 
                        hitChain.PopContextBox(box);
                        return true;
                    }
                }
                hitChain.PopContextBox(box);
            }
            //----------------------------------------------------------------------
            if (!isPointInArea)
            {
                switch (box.CssDisplay)
                {
                    case Css.CssDisplay.TableRow:
                        {
                            foreach (var childBox in box.GetChildBoxIter())
                            {
                                if (HitTest(childBox, x, y, hitChain))
                                {
                                    return true;
                                }
                            }
                        }
                        break;
                }
                //exit 
                return false;
            }
            //----------------------------------------------------------------------
            //at here point is in the area*** 

            hitChain.PushContextBox(box);
            if (box.IsCustomCssBox)
            {
                //custom css box
                //return true= stop here
                if (box.CustomContentHitTest(x, y, hitChain))
                {
                    hitChain.PopContextBox(box);
                    return true;
                }
            }

            if (box.LineBoxCount > 0)
            {
                bool foundSomeLine = false;
                foreach (var lineBox in box.GetLineBoxIter())
                {
                    //line box not overlap
                    if (lineBox.HitTest(boxHitLocalX, boxHitLocalY))
                    {
                        foundSomeLine = true;
                        float lineBoxLocalY = boxHitLocalY - lineBox.CachedLineTop;
                        //2.
                        hitChain.AddHit(lineBox, (int)boxHitLocalX, (int)lineBoxLocalY);
                        var foundRun = BoxHitUtils.GetCssRunOnLocation(lineBox, (int)boxHitLocalX, (int)lineBoxLocalY);
                        if (foundRun != null)
                        {
                            //3.
                            hitChain.AddHit(foundRun, (int)(boxHitLocalX - foundRun.Left), (int)lineBoxLocalY);
                            //4. go deeper for block run
                            if (foundRun.Kind == CssRunKind.BlockRun)
                            {
                                var blockRun = (CssBlockRun)foundRun;
                                CssLineBox hostLine = blockRun.HostLine;
                                //adjust with hostline 

                                HitTest(((CssBlockRun)foundRun).ContentBox, (int)(boxHitLocalX - foundRun.Left), boxHitLocalY - hostLine.CachedLineTop, hitChain);
                            }
                        }
                        //found line box
                        hitChain.PopContextBox(box);
                        return true;
                    }
                    else if (foundSomeLine)
                    {
                        return false;
                    }
                }
            }
            else
            {
                //iterate in child 
                foreach (var childBox in box.GetChildBoxIter())
                {
                    if (HitTest(childBox, boxHitLocalX, boxHitLocalY, hitChain))
                    {
                        //recursive
                        hitChain.PopContextBox(box);
                        return true;
                    }
                }
            }
            hitChain.PopContextBox(box);
            return true;
        }
예제 #6
0
        internal static CssLineBox GetNearestLine(CssBox a, Point point, out bool found)
        {
            if (a.LineBoxCount > 0)
            {
                CssLineBox latestLine = null;
                int y = point.Y;
                found = false;
                foreach (CssLineBox linebox in a.GetLineBoxIter())
                {
                    if (linebox.CachedLineBottom < y)
                    {
                        latestLine = linebox;
                    }
                    else
                    {
                        if (latestLine != null)
                        {
                            found = true;
                        }
                        break;
                    }
                }

                return latestLine;
            }
            else
            {
                bool foundExact = false;
                CssLineBox lastLine = null;
                foreach (CssBox cbox in a.GetChildBoxIter())
                {
                    CssLineBox candidateLine = GetNearestLine(cbox, point, out foundExact);
                    if (candidateLine != null)
                    {
                        if (foundExact)
                        {
                            found = true;
                            return lastLine;
                        }
                        //not exact
                        lastLine = candidateLine;
                    }
                    else
                    {
                        if (lastLine != null)
                        {
                            found = false;
                            return lastLine;
                        }
                    }
                }
                found = foundExact;
            }
            return null;
        }
예제 #7
0
 internal static IEnumerable<CssLineBox> GetDeepDownLineBoxIter(CssBox box)
 {
     if (box.LineBoxCount > 0)
     {
         foreach (CssLineBox linebox in box.GetLineBoxIter())
         {
             yield return linebox;
         }
     }
     else
     {
         if (box.ChildCount > 0)
         {
             foreach (CssBox child in box.GetChildBoxIter())
             {
                 foreach (CssLineBox linebox in GetDeepDownLineBoxIter(child))
                 {
                     yield return linebox;
                 }
             }
         }
     }
 }
예제 #8
0
            static IEnumerable<CssLineBox> GetLineWalkDownIter(LineWalkVisitor visitor, CssBox box)
            {
                //recursive
                float y = visitor.globalY;
                if (box.LineBoxCount > 0)
                {
                    foreach (var linebox in box.GetLineBoxIter())
                    {
                        visitor.globalY = y + linebox.CachedLineTop;
                        yield return linebox;
                    }
                }
                else
                {
                    //element based
                    foreach (var childbox in box.GetChildBoxIter())
                    {
                        visitor.globalY = y + childbox.LocalY;
                        //recursive
                        foreach (var linebox in GetLineWalkDownIter(visitor, childbox))
                        {
                            yield return linebox;
                        }
                    }
                }

                visitor.globalY = y;
            }
예제 #9
0
 static void ForEachCellInTable(CssBox table, Action<CssBox> cellAction)
 {
     foreach (var c1 in table.GetChildBoxIter())
     {
         foreach (var c2 in c1.GetChildBoxIter())
         {
             if (c2.CssDisplay == CssDisplay.TableCell)
             {
                 cellAction(c2);
             }
             else
             {
                 foreach (var c3 in c2.GetChildBoxIter())
                 {
                     cellAction(c3);
                 }
             }
         }
     }
 }
예제 #10
0
 /// <summary>
 /// Applies special vertical alignment for table-cells
 /// </summary>
 /// <param name="g"></param>
 /// <param name="cell"></param>
 static void ApplyCellVerticalAlignment(CssBox cell, float tableBoxOffset)
 {
     float dist = 0f;
     switch (cell.VerticalAlign)
     {
         case CssVerticalAlign.Bottom:
             dist = cell.GetClientHeight() - cell.CalculateInnerContentHeight();
             break;
         case CssVerticalAlign.Middle:
             dist = (cell.GetClientHeight() - cell.CalculateInnerContentHeight()) / 2;
             break;
         default:
             return;
     }
     if (dist > CssBoxConstConfig.TABLE_VERT_OFFSET_THESHOLD)
     {
         //more than our threshold
         if (cell.LineBoxCount > 0)
         {
             var linebox = cell.GetFirstLineBox();
             while (linebox != null)
             {
                 linebox.OffsetTop(dist);
                 linebox = linebox.NextLine;
             }
         }
         else
         {
             foreach (CssBox b in cell.GetChildBoxIter())
             {
                 b.OffsetLocalTop(dist);
             }
         }
     }
 }
예제 #11
0
 /// <summary>
 /// Recursively measures run inside the box
 /// </summary>
 /// <param name="box">the box to measure</param>
 /// <param name="g">Device to use</param>
 static void S1_RecursiveMeasureRunContentSize(CssBox box, LayoutVisitor lay)
 {
     //recursive
     if (box != null)
     {
         float box_fontsize = box.ResolvedFont.SizeInPixels;
         var ifonts = lay.SampleIFonts;
         foreach (var childBox in box.GetChildBoxIter())
         {
             childBox.ReEvaluateFont(ifonts, box_fontsize);
             childBox.MeasureRunsSize(lay);
             S1_RecursiveMeasureRunContentSize(childBox, lay); //recursive
         }
     }
 }
예제 #12
0
        /// <summary>
        /// Get the table cells spacing for all the cells in the table.<br/>
        /// Used to calculate the spacing the table has in addition to regular padding and borders.
        /// </summary>
        /// <param name="tableBox">the table box to calculate the spacing for</param>
        /// <returns>the calculated spacing</returns>
        static float CalculateTableSpacing(CssBox tableBox)
        {
            int count = 0;
            int columns = 0;
            foreach (var box in tableBox.GetChildBoxIter())
            {
                switch (box.CssDisplay)
                {
                    case CssDisplay.TableColumn:
                        {
                            columns += box.ColSpan;
                        }
                        break;
                    case CssDisplay.TableRowGroup:
                        {
                            foreach (CssBox cr in tableBox.GetChildBoxIter())
                            {
                                count++;
                                if (cr.CssDisplay == CssDisplay.TableRow)
                                {
                                    columns = Math.Max(columns, cr.ChildCount);
                                }
                            }
                        }
                        break;
                    case CssDisplay.TableRow:
                        {
                            count++;
                            columns = Math.Max(columns, box.ChildCount);
                        }
                        break;
                }
                // limit the amount of rows to process for performance ?
                if (count > MAX_COL_AT_THIS_VERSION)
                {
                    break;
                }
            }

            // +1 columns because padding is between the cell and table borders
            return (columns + 1) * GetHorizontalSpacing(tableBox);
        }
예제 #13
0
        /// <summary>
        /// Get the <paramref name="min"/> and <paramref name="maxSum"/> of the box words content and <paramref name="paddingSum"/>.<br/>
        /// </summary>
        /// <param name="box">the box to calculate for</param>
        /// <param name="min">the width that allows for each word to fit (width of the longest word)</param>
        /// <param name="maxSum">the max width a single line of words can take without wrapping</param>
        /// <param name="paddingSum">the total amount of padding the content has </param>
        /// <param name="marginSum"></param>
        /// <returns></returns>
        static void CalculateMinMaxSumWords(
            CssBox box,
            CssBox cbBox,
            IFonts iFonts,
            ref float min,
            ref float maxSum,
            ref float paddingSum,
            ref float marginSum)
        {
            //recursive 
            float? oldSum = null;
            // not inline (block) boxes start a new line so we need to reset the max sum 
            if (box.CssDisplay != CssDisplay.Inline &&
                box.CssDisplay != CssDisplay.TableCell &&
                box.WhiteSpace != CssWhiteSpace.NoWrap)
            {
                oldSum = maxSum;
                maxSum = marginSum;
            }

            // add the padding 
            paddingSum += box.ActualBorderLeftWidth + box.ActualBorderRightWidth + box.ActualPaddingRight + box.ActualPaddingLeft;
            // for tables the padding also contains the spacing between cells                
            if (box.CssDisplay == CssDisplay.Table)
            {
                paddingSum += CssTableLayoutEngine.CalculateTableSpacing(box);
            }

            if (box.HasOnlyRuns)
            {
                // calculate the min and max sum for all the words in the box 
                foreach (CssRun run in box.GetRunIter())
                {
                    maxSum += run.Width;
                    min = Math.Max(min, run.Width);
                }
            }
            else
            {
                // recursively on all the child boxes
                //if this box has containing property 
                if (box.HasContainingBlockProperty)
                {
                    foreach (CssBox childBox in box.GetChildBoxIter())
                    {
                        if (childBox.NeedComputedValueEvaluation) { childBox.ReEvaluateComputedValues(iFonts, box); }

                        float msum = childBox.ActualMarginLeft + childBox.ActualMarginRight;
                        marginSum += msum;
                        //recursive                        
                        CalculateMinMaxSumWords(childBox, box, iFonts, ref min, ref maxSum, ref paddingSum, ref marginSum);
                        marginSum -= msum;
                    }
                }
                else
                {
                    foreach (CssBox childBox in box.GetChildBoxIter())
                    {
                        if (childBox.NeedComputedValueEvaluation) { childBox.ReEvaluateComputedValues(iFonts, cbBox); }

                        float msum = childBox.ActualMarginLeft + childBox.ActualMarginRight;
                        marginSum += msum;
                        //recursive
                        CalculateMinMaxSumWords(childBox, cbBox, iFonts, ref min, ref maxSum, ref paddingSum, ref marginSum);
                        marginSum -= msum;
                    }
                }
            }

            // max sum is max of all the lines in the box
            if (oldSum.HasValue)
            {
                maxSum = Math.Max(maxSum, oldSum.Value);
            }
        }
예제 #14
0
        public static bool HitTest(CssBox box, float x, float y, CssBoxHitChain hitChain)
        {
#if DEBUG
            //if (box.ViewportY != 0 && hitChain.debugEventPhase == CssBoxHitChain.dbugEventPhase.MouseDown)
            //{
            //}
#endif
            //--------------------------------------
            bool  isPointInArea = box.IsPointInArea(x, y);
            float boxHitLocalX  = x - box.LocalX; //**
            float boxHitLocalY  = y - box.LocalY; //**
            //----------------------------------------------------------------------
            if (isPointInArea)
            {
                hitChain.AddHit(box, (int)boxHitLocalX, (int)boxHitLocalY);
            }

            //----------------------------------------------------------------------
            //enter children space -> offset with its viewport
            boxHitLocalX += box.ViewportX;
            boxHitLocalY += box.ViewportY;


            //check absolute layer first ***
            if (box.HasAbsoluteLayer)
            {
                hitChain.PushContextBox(box);
                foreach (CssBox absBox in box.GetAbsoluteChildBoxBackwardIter())
                {
                    if (HitTest(absBox, boxHitLocalX, boxHitLocalY, hitChain))
                    {
                        //found hit
                        hitChain.PopContextBox(box);
                        return(true);
                    }
                }
                hitChain.PopContextBox(box);
            }
            //----------------------------------------------------------------------
            if (!isPointInArea)
            {
                switch (box.CssDisplay)
                {
                case Css.CssDisplay.TableRow:
                {
                    foreach (CssBox childBox in box.GetChildBoxIter())
                    {
                        if (HitTest(childBox, boxHitLocalX, boxHitLocalY, hitChain))
                        {
                            return(true);
                        }
                    }
                }
                break;
                }
                //exit
                return(false);
            }
            //----------------------------------------------------------------------
            //at here point is in the area***
            hitChain.PushContextBox(box);
            if (box.IsCustomCssBox)
            {
                //custom css box
                //return true= stop here
                if (box.CustomContentHitTest(boxHitLocalX, boxHitLocalY, hitChain))
                {
                    hitChain.PopContextBox(box);
                    return(true);
                }
            }

            if (box.LineBoxCount > 0)
            {
                bool foundSomeLine = false;
                foreach (CssLineBox lineBox in box.GetLineBoxIter())
                {
                    //line box not overlap
                    if (lineBox.HitTest(boxHitLocalX, boxHitLocalY))
                    {
                        foundSomeLine = true;
                        float lineBoxLocalY = boxHitLocalY - lineBox.CachedLineTop;
                        //2.
                        hitChain.AddHit(lineBox, (int)boxHitLocalX, (int)lineBoxLocalY);


                        CssRun foundRun = BoxHitUtils.GetCssRunOnLocation(lineBox, (int)boxHitLocalX, (int)lineBoxLocalY);
                        //CssRun foundRun = BoxHitUtils.GetCssRunOnLocation(lineBox, (int)x, (int)y);
                        if (foundRun != null)
                        {
                            //3.
                            hitChain.AddHit(foundRun, (int)(boxHitLocalX - foundRun.Left), (int)lineBoxLocalY);
                            //4. go deeper for block run
                            if (foundRun.Kind == CssRunKind.BlockRun)
                            {
                                CssBlockRun blockRun = (CssBlockRun)foundRun;
                                CssLineBox  hostLine = blockRun.HostLine;
                                //adjust with hostline
                                HitTest(blockRun.ContentBox,
                                        (int)(boxHitLocalX + blockRun.ContentBox.LocalX - foundRun.Left),
                                        (int)(boxHitLocalY - hostLine.CachedLineTop),
                                        hitChain);
                            }
                        }
                        //found line box
                        hitChain.PopContextBox(box);
                        return(true);
                    }
                    else if (foundSomeLine)
                    {
                        return(false);
                    }
                }
            }
            else
            {
                //iterate in child
                //foreach (var childBox in box.GetChildBoxIter())
                foreach (CssBox childBox in box.GetChildBoxBackwardIter())
                {
                    if (HitTest(childBox, boxHitLocalX, boxHitLocalY, hitChain))
                    {
                        //recursive
                        hitChain.PopContextBox(box);
                        return(true);
                    }
                }
            }
            hitChain.PopContextBox(box);
            return(true);
        }