상속: BoxVisitor
        public static MyHtmlVisualRoot CreateHtmlVisualRootFromFullHtml(
            HtmlHost htmlHost,
            string fullHtmlString,
            HtmlRenderBox htmlFrgmentRenderBox)
        {
            HtmlDocument htmldoc = WebDocumentParser.ParseDocument(
                htmlHost,
                new LayoutFarm.WebDom.Parser.TextSource(fullHtmlString.ToCharArray()));
            //1. builder
            RenderTreeBuilder renderTreeBuilder = htmlHost.GetRenderTreeBuilder();
            //-------------------------------------------------------------------
            //2. generate render tree
            ////build rootbox from htmldoc

            CssBox rootElement = renderTreeBuilder.BuildCssRenderTree(htmldoc,
                                                                      htmlHost.BaseStylesheet,
                                                                      htmlFrgmentRenderBox);
            //3. create small htmlContainer

            MyHtmlVisualRoot htmlContainer = new MyHtmlVisualRoot(htmlHost);

            htmlContainer.WebDocument = htmldoc;
            htmlContainer.SetRootCssBox(rootElement);
            htmlContainer.SetMaxSize(htmlFrgmentRenderBox.Width, 0);
            //
            LayoutVisitor lay = htmlHost.GetSharedHtmlLayoutVisitor(htmlContainer);

            htmlContainer.PerformLayout(lay);
            htmlHost.ReleaseHtmlLayoutVisitor(lay);
            htmlFrgmentRenderBox.SetHtmlContainer(htmlContainer, rootElement);
            return(htmlContainer);
        }
        public static MyHtmlVisualRoot CreateHtmlVisualRoot(
            HtmlHost htmlHost,
            WebDom.WebDocument htmldoc,
            HtmlRenderBox htmlFrgmentRenderBox)
        {
            //1. builder
            RenderTreeBuilder renderTreeBuilder = htmlHost.GetRenderTreeBuilder();
            //-------------------------------------------------------------------


            //2. generate render tree
            ////build rootbox from htmldoc

            CssBox rootElement = renderTreeBuilder.BuildCssRenderTree(htmldoc,
                                                                      htmlHost.BaseStylesheet,
                                                                      htmlFrgmentRenderBox);
            //3. create small htmlContainer

            MyHtmlVisualRoot htmlContainer = new MyHtmlVisualRoot(htmlHost);

            htmlContainer.WebDocument = htmldoc;
            htmlContainer.SetRootCssBox(rootElement);
            htmlContainer.SetMaxSize(htmlFrgmentRenderBox.Width, 0);
            //htmlContainer.SetRootRenderElement(htmlFrgmentRenderBox);

            LayoutVisitor lay = htmlHost.GetSharedHtmlLayoutVisitor(htmlContainer);

            htmlContainer.PerformLayout(lay);
            htmlHost.ReleaseHtmlLayoutVisitor(lay);
            htmlFrgmentRenderBox.SetHtmlContainer(htmlContainer, rootElement);
            return(htmlContainer);
        }
예제 #3
0
 /// <summary>
 /// 
 /// </summary>
 /// <param name="g"></param>
 /// <param name="tableBox"> </param>
 public static void PerformLayout(CssBox tableBox, float hostAvailableWidth, LayoutVisitor lay)
 {
     var table = new CssTableLayoutEngine(tableBox, hostAvailableWidth);
     table._tmpIFonts = lay.SampleIFonts;
     table.Layout(lay);
     table._tmpIFonts = null;
 }
예제 #4
0
        /// <summary>
        /// Assigns words its width and height
        /// </summary>
        /// <param name="g">the device to use</param>
        public override void MeasureRunsSize(LayoutVisitor lay)
        {
            if (this.RunSizeMeasurePass)
            {
                return;
            }

            this.RunSizeMeasurePass = true;
            MeasureImageSize(_imgRun, lay);
        }
예제 #5
0
        /// <summary>
        /// Measures the bounds of box and children, recursively.<br/>
        /// Performs layout of the DOM structure creating lines by set bounds restrictions.
        /// </summary>
        /// <param name="g">Device context to use</param>
        public void PerformLayout(LayoutVisitor lay)
        {
            //if (this.dbugMark1 > 0)
            //{

            //}
            //derived class can perform its own layout algo
            //by override performContentLayout
            PerformContentLayout(lay);
        }
예제 #6
0
        /// <summary>
        /// Measures the bounds of box and children, recursively.<br/>
        /// Performs layout of the DOM structure creating lines by set bounds restrictions.<br/>
        /// </summary>
        /// <param name="g">Device context to use</param>
        protected virtual void PerformContentLayout(LayoutVisitor lay)
        {
            switch (this.CssDisplay)
            {
            case Css.CssDisplay.None:
            {
                return;
            }

            default:
            {
                //others ...
                if (this.NeedComputedValueEvaluation)
                {
                    this.ReEvaluateComputedValues(lay.SampleIFonts, lay.LatestContainingBlock);
                }
                this.MeasureRunsSize(lay);
            }
            break;

            case Css.CssDisplay.Block:
            case Css.CssDisplay.ListItem:
            case Css.CssDisplay.Table:
            case Css.CssDisplay.InlineTable:
            case Css.CssDisplay.TableCell:
            case Css.CssDisplay.Flex:
            case Css.CssDisplay.InlineFlex:
            {
                //this box has its own  container property
                //this box may be used for ...
                // 1) line formatting context  , or
                // 2) block formatting context
                if (this.NeedComputedValueEvaluation)
                {
                    this.ReEvaluateComputedValues(lay.SampleIFonts, lay.LatestContainingBlock);
                }
                this.MeasureRunsSize(lay);

                //for general block layout
                CssLayoutEngine.PerformContentLayout(this, lay);
            }
            break;
            }

            //set height
            UpdateIfHigher(this, ExpectedHeight);
            //update back

            lay.UpdateRootSize(this);
        }
예제 #7
0
 public LayoutFarm.HtmlBoxes.LayoutVisitor GetSharedHtmlLayoutVisitor(HtmlContainer htmlCont)
 {
     LayoutFarm.HtmlBoxes.LayoutVisitor lay = null;
     if (htmlLayoutVisitorStock.Count == 0)
     {
         lay = new LayoutVisitor(this.gfxplatform);
     }
     else
     {
         lay = this.htmlLayoutVisitorStock.Dequeue();
     }
     lay.Bind(htmlCont);
     return(lay);
 }
예제 #8
0
 protected override void PerformContentLayout(LayoutVisitor lay)
 {
     base.PerformContentLayout(lay);
     if (_listItemBulletBox != null)
     {
         //layout list item
         var prevSibling = lay.LatestSiblingBox;
         lay.LatestSiblingBox = null;//reset
         _listItemBulletBox.PerformLayout(lay);
         lay.LatestSiblingBox = prevSibling;
         var fRun = _listItemBulletBox.FirstRun;
         _listItemBulletBox.FirstRun.SetSize(fRun.Width, fRun.Height);
         _listItemBulletBox.FirstRun.SetLocation(_listItemBulletBox.VisualWidth - 5, this.ActualPaddingTop);
     }
 }
예제 #9
0
 protected override void PerformContentLayout(LayoutVisitor lay)
 {
     base.PerformContentLayout(lay);
     if (_listItemBulletBox != null)
     {
         //layout list item
         var prevSibling = lay.LatestSiblingBox;
         lay.LatestSiblingBox = null;//reset
         _listItemBulletBox.PerformLayout(lay);
         lay.LatestSiblingBox = prevSibling;
         var fRun = _listItemBulletBox.FirstRun;
         _listItemBulletBox.FirstRun.SetSize(fRun.Width, fRun.Height);
         _listItemBulletBox.FirstRun.SetLocation(_listItemBulletBox.VisualWidth - 5, this.ActualPaddingTop);
     }
 }
예제 #10
0
        public void SetHtmlHost(HtmlHost htmlhost)
        {
            this.htmlhost = htmlhost;

            htmlhost.SetHtmlContainerUpdateHandler(htmlCont =>
            {
                var updatedHtmlCont = htmlCont as MyHtmlContainer;
                if (updatedHtmlCont != null && !updatedHtmlCont.IsInUpdateQueue)
                {
                    updatedHtmlCont.IsInUpdateQueue = true;
                    waitingUpdateList.Add(updatedHtmlCont);
                }
            });

            htmlContainer = new MyHtmlContainer(htmlhost);
            htmlContainer.AttachEssentialHandlers(
                OnRefresh,
                myHtmlContainer_NeedUpdateDom,
                OnRefresh,
                null);

            htmlLayoutVisitor = new LayoutVisitor(this.gfxPlatform);
            htmlLayoutVisitor.Bind(htmlContainer);


            //-------------------------------------------------------
            timer01.Interval = 20;//20ms?
            timer01.Tick    += (s, e) =>
            {
                //clear waiting
                int j = waitingUpdateList.Count;
                for (int i = 0; i < j; ++i)
                {
                    var htmlCont = waitingUpdateList[i];
                    htmlCont.IsInUpdateQueue = false;
                    htmlCont.RefreshDomIfNeed();
                }
                for (int i = j - 1; i >= 0; --i)
                {
                    waitingUpdateList.RemoveAt(i);
                }
            };
            timer01.Enabled = true;
            //-------------------------------------------
            _htmlInputEventAdapter = new HtmlInputEventAdapter(gfxPlatform.SampleIFonts);
            _htmlInputEventAdapter.Bind(htmlContainer);
            //-------------------------------------------
        }
예제 #11
0
        public LayoutVisitor GetSharedHtmlLayoutVisitor(HtmlContainer htmlCont)
        {
            LayoutVisitor lay = null;

            if (htmlLayoutVisitorStock.Count == 0)
            {
                RootGraphic rootgfx = (RootGraphic)htmlCont.RootCssBox.RootGfx;
                lay = new LayoutVisitor(rootgfx.IFonts);
            }
            else
            {
                lay = this.htmlLayoutVisitorStock.Dequeue();
            }
            lay.Bind(htmlCont);
            return(lay);
        }
예제 #12
0
        public LayoutVisitor GetSharedHtmlLayoutVisitor(HtmlContainer htmlCont)
        {
            LayoutVisitor lay = null;

            if (htmlLayoutVisitorStock.Count == 0)
            {
                RootGraphic rootgfx = (RootGraphic)htmlCont.RootCssBox.GetInternalRootGfx();
                lay = new LayoutVisitor(this.GetTextService());
            }
            else
            {
                lay = this.htmlLayoutVisitorStock.Dequeue();
            }
            lay.Bind(htmlCont);
            return(lay);
        }
        public static MyHtmlVisualRoot CreateHtmlVisualRootFromFragmentHtml(
            HtmlHost htmlHost,
            string htmlFragment,
            HtmlRenderBox htmlFrgmentRenderBox)
        {
            HtmlDocument htmldoc = htmlHost.CreateNewSharedHtmlDoc();

            WebDom.DomElement myHtmlBodyElement = htmldoc.CreateElement("body");
            htmldoc.RootNode.AddChild(myHtmlBodyElement);
            //data is wraped up within div?
            //TODO: review this, use shadow dom instead
            WebDom.DomElement newDivHost = htmldoc.CreateElement("div");
            myHtmlBodyElement.AddChild(newDivHost);
            WebDocumentParser.ParseHtmlDom(
                new LayoutFarm.WebDom.Parser.TextSource(htmlFragment.ToCharArray()),
                htmldoc,
                newDivHost);
            //1. builder
            RenderTreeBuilder renderTreeBuilder = htmlHost.GetRenderTreeBuilder();
            //-------------------------------------------------------------------
            //2. generate render tree
            CssBox rootElement = renderTreeBuilder.BuildCssRenderTree(
                htmldoc,
                htmldoc.CssActiveSheet,
                htmlFrgmentRenderBox);
            //3. create small htmlContainer

            MyHtmlVisualRoot htmlContainer = new MyHtmlVisualRoot(htmlHost);

            htmlContainer.WebDocument = newDivHost.OwnerDocument;
            htmlContainer.SetRootCssBox(rootElement);
            htmlContainer.SetMaxSize(htmlFrgmentRenderBox.Width, 0);
            //htmlContainer.SetRootRenderElement(htmlFrgmentRenderBox);

            //
            LayoutVisitor lay = htmlHost.GetSharedHtmlLayoutVisitor(htmlContainer);

            htmlContainer.PerformLayout(lay);
            htmlHost.ReleaseHtmlLayoutVisitor(lay);
            htmlFrgmentRenderBox.SetHtmlContainer(htmlContainer, rootElement);
            return(htmlContainer);
        }
예제 #14
0
        public float CalculateTotalBoxBaseLine(LayoutVisitor lay)
        {
            //not correct !!
            float  maxRunHeight = 0;
            CssRun maxRun       = null;

            for (int i = _runs.Count - 1; i >= 0; --i)
            {
                CssRun run = _runs[i];
                if (run.Height > maxRunHeight)
                {
                    maxRun       = run;
                    maxRunHeight = run.Height;
                }
            }
            if (maxRun != null)
            {
                //lay.GraphicsPlatform.SampleIFonts
                //var f = maxRun.OwnerBox.ResolvedFont;
                //PixelFarm.Drawing.Fonts.ActualFont ff = f.ActualFont;
                //return (float)(f.Height * ff.AscentInPixels / f.Height);

                //return fontHeight* fontAscent / lineSpacing )
            }
            return(0);
            //int j = _runs.Count;
            //for (int i = _runs.Count - 1; i >= 0; --i)
            //{
            //    Font ownerFont = _runs[i].OwnerBox.ActualFont;
            //    HtmlRenderer.Drawing.FontsUtils.GetDescent(
            //}
            //return 0;

            //float baseline = Single.MinValue;
            //for (int i = _bottomUpBoxStrips.Count - 1; i >= 0; --i)
            //{
            //    baseline = Math.Max(baseline, _bottomUpBoxStrips[i].Top);//?top
            //}
            //return baseline;
        }
예제 #15
0
        /// <summary>
        /// Analyzes the Table and assigns values to this CssTable object.
        /// To be called from the constructor
        /// </summary>
        void Layout(LayoutVisitor lay)
        {
            S1_RecursiveMeasureRunContentSize(_tableBox, lay);
            //------------------------------------------------ 
            // get the table boxes into the proper fields
            // Insert EmptyBoxes for vertical cell spanning.  

            List<CssBox> userColumnList = S2_PrepareTableCellBoxes();
            // Determine Row and Column Count, and ColumnWidths 
            float availableWidthForAllCells = S3_CalculateCountAndWidth(userColumnList);
            S4_DetermineMissingColumnWidths(availableWidthForAllCells);
            //
            S5_CalculateColumnMinWidths(lay.EpisodeId);
            // Check for minimum sizes (increment widths if necessary)
            S6_EnforceMinimumSize();
            // While table width is larger than it should, and width is reducible
            S7_EnforceMaximumSize();
            // Ensure there's no padding             
            //_tableBox.PaddingLeft = _tableBox.PaddingTop = _tableBox.PaddingRight = _tableBox.PaddingBottom = CssLength.ZeroPx;

            //Actually layout cells!
            S8_LayoutCells(lay);
        }
예제 #16
0
        public float CalculateTotalBoxBaseLine(LayoutVisitor lay)
        {
            //not correct !!
            float  maxRunHeight = 0;
            CssRun maxRun       = null;

            for (int i = this._runs.Count - 1; i >= 0; --i)
            {
                var run = this._runs[i];
                if (run.Height > maxRunHeight)
                {
                    maxRun       = run;
                    maxRunHeight = run.Height;
                }
            }
            if (maxRun != null)
            {
                var fontInfo = maxRun.OwnerBox.ActualFont.FontInfo;
                return(fontInfo.BaseLine);
            }
            return(0);
            //int j = this._runs.Count;
            //for (int i = this._runs.Count - 1; i >= 0; --i)
            //{
            //    Font ownerFont = _runs[i].OwnerBox.ActualFont;
            //    HtmlRenderer.Drawing.FontsUtils.GetDescent(
            //}
            //return 0;

            //float baseline = Single.MinValue;
            //for (int i = _bottomUpBoxStrips.Count - 1; i >= 0; --i)
            //{
            //    baseline = Math.Max(baseline, _bottomUpBoxStrips[i].Top);//?top
            //}
            //return baseline;
        }
예제 #17
0
        /// <summary>
        /// Assigns words its width and height
        /// </summary>
        /// <param name="g">the device to use</param>
        public override void MeasureRunsSize(LayoutVisitor lay)
        {
            if (this.RunSizeMeasurePass)
            {
                return;
            }

            this.RunSizeMeasurePass = true;
            MeasureImageSize(_imgRun, lay);
        }
예제 #18
0
        public void PerformLayout(LayoutVisitor lay)
        {
            if (this._rootBox == null)
            {
                return;
            }
            //-----------------------
            //reset
            _actualWidth = _actualHeight = 0;
            // if width is not restricted we set it to large value to get the actual later
            _rootBox.SetLocation(0, 0);
            _rootBox.SetVisualSize(this._maxWidth > 0 ? this._maxWidth : MAX_WIDTH, 0);
            CssBox.ValidateComputeValues(_rootBox);
            //-----------------------
            //LayoutVisitor layoutArgs = new LayoutVisitor(this.GraphicsPlatform, this);
            lay.PushContaingBlock(_rootBox);
            //-----------------------

            _rootBox.PerformLayout(lay);
            if (this._maxWidth <= 0.1)
            {
                // in case the width is not restricted we need to double layout, first will find the width so second can layout by it (center alignment)
                _rootBox.SetVisualWidth((int)Math.Ceiling(this._actualWidth));
                _actualWidth = _actualHeight = 0;
                _rootBox.PerformLayout(lay);
            }
            lay.PopContainingBlock();
            //-----------------------
            //TODO: review here again
            FloatingContextStack   floatStack    = lay.GetFloatingContextStack();
            List <FloatingContext> totalContexts = floatStack.GetTotalContexts();
            int j = totalContexts.Count;

            for (int i = 0; i < j; ++i)
            {
                FloatingContext floatingContext = totalContexts[i];
                int             floatBoxCount   = floatingContext.FloatBoxCount;
                if (floatBoxCount == 0)
                {
                    continue;
                }


                CssBox floatingOwner = floatingContext.Owner;
                float  rfx, rfy;
                floatingOwner.GetGlobalLocation(out rfx, out rfy);
                CssBox prevParent = null;
                //TODO: review here again
                float extraAdjustX = 0; //temp fixed
                for (int n = 0; n < floatBoxCount; ++n)
                {
                    float  bfx, bfy;
                    CssBox box = floatingContext.GetBox(n);
                    box.GetGlobalLocation(out bfx, out bfy);
                    //diff
                    float nx = bfx - rfx;
                    float ny = bfy - rfy;
                    if (prevParent != null && prevParent != box.ParentBox)
                    {
                        if (n > 0)
                        {
                            CssBox prevFloatChild = floatingContext.GetBox(n - 1);
                            //TODO: review here again
                            //temp fix
                            extraAdjustX = prevFloatChild.ActualMarginRight + box.ActualMarginLeft;
                            ny          += box.ActualMarginTop;
                        }
                    }
                    box.SetLocation(nx + extraAdjustX, ny);
                    prevParent = box.ParentBox;
                    floatingOwner.AppendToAbsoluteLayer(box);
                }
            }

            OnLayoutFinished();
            //-----------------------
            unchecked { layoutVersion++; }
            //-----------------------
        }
예제 #19
0
        /// <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="imgRun">the image word to measure</param>
        static void MeasureImageSize(CssImageRun imgRun, LayoutVisitor lay)
        {
            var width = imgRun.OwnerBox.Width;
            var height = imgRun.OwnerBox.Height;
            bool hasImageTagWidth = width.Number > 0 && width.UnitOrNames == Css.CssUnitOrNames.Pixels;
            bool hasImageTagHeight = height.Number > 0 && height.UnitOrNames == Css.CssUnitOrNames.Pixels;
            bool scaleImageHeight = false;
            if (hasImageTagWidth)
            {
                imgRun.Width = width.Number;
            }
            else if (width.Number > 0 && width.IsPercentage)
            {
                imgRun.Width = width.Number * lay.LatestContainingBlock.VisualWidth;
                scaleImageHeight = true;
            }
            else if (imgRun.HasUserImageContent)
            {
                imgRun.Width = imgRun.ImageRectangle == Rectangle.Empty ? imgRun.OriginalImageWidth : imgRun.ImageRectangle.Width;
            }
            else
            {
                imgRun.Width = hasImageTagHeight ? height.Number / 1.14f : 20;
            }

            var maxWidth = imgRun.OwnerBox.MaxWidth;// new CssLength(imageWord.OwnerBox.MaxWidth);
            if (maxWidth.Number > 0)
            {
                float maxWidthVal = -1;
                switch (maxWidth.UnitOrNames)
                {
                    case Css.CssUnitOrNames.Percent:
                        {
                            maxWidthVal = maxWidth.Number * lay.LatestContainingBlock.VisualWidth;
                        }
                        break;
                    case Css.CssUnitOrNames.Pixels:
                        {
                            maxWidthVal = maxWidth.Number;
                        }
                        break;
                }


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

            if (hasImageTagHeight)
            {
                imgRun.Height = height.Number;
            }
            else if (imgRun.HasUserImageContent)
            {
                imgRun.Height = imgRun.ImageRectangle == Rectangle.Empty ? imgRun.OriginalImageHeight : imgRun.ImageRectangle.Height;
            }
            else
            {
                imgRun.Height = imgRun.Width > 0 ? imgRun.Width * 1.14f : 22.8f;
            }

            if (imgRun.HasUserImageContent)
            {
                // 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 = imgRun.Width / imgRun.OriginalImageWidth;
                    imgRun.Height = imgRun.OriginalImageHeight * 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 = imgRun.Height / imgRun.OriginalImageHeight;
                    imgRun.Width = imgRun.OriginalImageWidth * ratio;
                }
            }
            //imageWord.Height += imageWord.OwnerBox.ActualBorderBottomWidth + imageWord.OwnerBox.ActualBorderTopWidth + imageWord.OwnerBox.ActualPaddingTop + imageWord.OwnerBox.ActualPaddingBottom;
        }
예제 #20
0
        static void DoLayoutBlocksContext(CssBox box, LayoutVisitor lay)
        {
            //block formatting context.... 
            lay.PushContaingBlock(box);
            var currentLevelLatestSibling = lay.LatestSiblingBox;
            lay.LatestSiblingBox = null;//reset 
            //------------------------------------------  
            var children = CssBox.UnsafeGetChildren(box);
            var cnode = children.GetFirstLinkedNode();
            while (cnode != null)
            {
                var childBox = cnode.Value;
                //----------------------------
                if (childBox.IsBrElement)
                {
                    //br always block
                    CssBox.ChangeDisplayType(childBox, Css.CssDisplay.Block);
                    childBox.SetVisualHeight(FontDefaultConfig.DEFAULT_FONT_SIZE * 0.95f);
                }
                //-----------------------------
                if (childBox.OutsideDisplayIsInline)
                {
                    //inline correction on-the-fly ! 
                    //1. collect consecutive inlinebox
                    //   and move to new anon block box

                    CssBox anoForInline = CreateAnonBlock(box, childBox);
                    anoForInline.ReEvaluateComputedValues(lay.SampleIFonts, box);
                    var tmp = cnode.Next;
                    do
                    {
                        children.Remove(childBox);
                        anoForInline.AppendChild(childBox);
                        if (tmp != null)
                        {
                            childBox = tmp.Value;
                            if (childBox.OutsideDisplayIsInline)
                            {
                                tmp = tmp.Next;
                                if (tmp == null)
                                {
                                    children.Remove(childBox);
                                    anoForInline.AppendChild(childBox);
                                    break;//break from do while
                                }
                            }
                            else
                            {
                                break;//break from do while
                            }
                        }
                        else
                        {
                            break;//break from do while
                        }
                    } while (true);
                    childBox = anoForInline;
                    //------------------------   
                    //2. move this inline box 
                    //to new anonbox 
                    cnode = tmp;
                    //------------------------ 
                    childBox.PerformLayout(lay);
                    if (childBox.CanBeReferenceSibling)
                    {
                        lay.LatestSiblingBox = childBox;
                    }
                }
                else
                {
                    //if(childBox.__aa_dbugId == 5)
                    //{ 
                    //}
                    childBox.PerformLayout(lay);
                    switch (childBox.Float)
                    {
                        case CssFloat.Left:
                            {
                                childBox.IsOutOfFlowBox = true;
                                // lay.LatestLeftFloatBox = childBox;

                            }
                            break;
                        case CssFloat.Right:
                            {
                                childBox.IsOutOfFlowBox = true;
                                //float box is out-of-flow box
                                //so move it to abs layer                                 
                                //lay.LatestRightFloatBox = childBox;

                            }
                            break;
                    }

                    if (childBox.Float == CssFloat.None && childBox.CanBeReferenceSibling)
                    {
                        lay.LatestSiblingBox = childBox;
                    }

                    cnode = cnode.Next;
                }
            }

            //------------------------------------------
            lay.LatestSiblingBox = currentLevelLatestSibling;
            lay.PopContainingBlock();
            //------------------------------------------------ 

            float boxWidth = CalculateActualWidth(box);
            if (lay.ContainerBlockGlobalX + boxWidth > CssBoxConstConfig.BOX_MAX_RIGHT)
            {
            }
            else
            {
                if (box.CssDisplay != Css.CssDisplay.TableCell)
                {
                    if (box.Width.IsEmptyOrAuto)
                    {
                        box.SetVisualWidth(boxWidth);
                    }
                }
            }


            float boxHeight = box.GetHeightAfterMarginBottomCollapse(lay.LatestContainingBlock);
            //TODO: review here again,
            box.SetVisualHeight(boxHeight);
            //--------------------------------------------------------------------------------
            //final  
            SetFinalInnerContentSize(box, boxWidth, boxHeight, lay);
        }
예제 #21
0
        /// <summary>
        /// do layout line formatting context
        /// </summary>
        /// <param name="hostBlock"></param>
        /// <param name="lay"></param>
        public static void DoLayoutLinesContext(CssBox hostBlock, LayoutVisitor lay)
        {
            //this in line formatting context
            //*** hostBlock must confirm that it has all inline children     
            hostBlock.SetHeightToZero();
            hostBlock.ResetLineBoxes();
            //----------------------------------------------------------------------------------------
            float limitLocalRight = hostBlock.VisualWidth - (hostBlock.ActualPaddingRight + hostBlock.ActualBorderRightWidth);
            float localX = hostBlock.ActualTextIndent + hostBlock.ActualPaddingLeft + hostBlock.ActualBorderLeftWidth;
            float localY = hostBlock.ActualPaddingTop + hostBlock.ActualBorderTopWidth;
            //----------------------------------------------------------------------------------------

            if (lay.HasFloatBoxInContext)
            {
                var recentLeftFloatBox = lay.LatestLeftFloatBox;
                var recentRightFloatBox = lay.LatestRightFloatBox;
                var latestSibling = lay.LatestSiblingBox;
                if (latestSibling != null)
                {
                    //check latest sibling first 
                    if (hostBlock.Float == CssFloat.None)
                    {
                        if (recentLeftFloatBox != null)
                        {
                            if (hostBlock.LocalY < recentLeftFloatBox.LocalVisualBottom)
                            {
                                localX = recentLeftFloatBox.LocalVisualRight;
                            }
                        }
                        else
                        {
                        }
                    }
                }
                else
                {
                    if (hostBlock.Float == CssFloat.None)
                    {
                        if (recentLeftFloatBox != null)
                        {
                            localX = recentLeftFloatBox.LocalVisualRight;
                        }
                        if (recentRightFloatBox != null)
                        {
                            limitLocalRight = recentRightFloatBox.LocalX;
                        }
                    }
                    //check if need newline or not 
                }
            }

            int interlineSpace = 0;
            //First line box 

            var line = new CssLineBox(hostBlock);
            hostBlock.AddLineBox(line);
            //****
            var floatCtx = new FloatFormattingContext();
            FlowBoxContentIntoHostLineFmtContext(lay, hostBlock, hostBlock,
                  limitLocalRight, localX,
                  ref line, ref localX, ref floatCtx);
            //**** 
            // if width is not restricted we need to lower it to the actual width
            if (hostBlock.VisualWidth + lay.ContainerBlockGlobalX >= CssBoxConstConfig.BOX_MAX_RIGHT)
            {
                float newWidth = localX + hostBlock.ActualPaddingRight + hostBlock.ActualBorderRightWidth;// CssBox.MAX_RIGHT - (args.ContainerBlockGlobalX + blockBox.LocalX);
                if (newWidth <= CSS_OFFSET_THRESHOLD)
                {
                    newWidth = CSS_OFFSET_THRESHOLD;
                }
                hostBlock.SetVisualWidth(newWidth);
            }
            //--------------------- 
            float maxLineWidth = 0;
            if (hostBlock.CssDirection == CssDirection.Rtl)
            {
                CssTextAlign textAlign = hostBlock.CssTextAlign;
                foreach (CssLineBox linebox in hostBlock.GetLineBoxIter())
                {
                    ApplyAlignment(linebox, textAlign, lay);
                    ApplyRightToLeft(linebox); //*** 
                    linebox.CloseLine(lay); //*** 
                    linebox.CachedLineTop = localY;
                    localY += linebox.CacheLineHeight + interlineSpace; // + interline space?
                    if (maxLineWidth < linebox.CachedExactContentWidth)
                    {
                        maxLineWidth = linebox.CachedExactContentWidth;
                    }
                }
            }
            else
            {
                CssTextAlign textAlign = hostBlock.CssTextAlign;
                foreach (CssLineBox linebox in hostBlock.GetLineBoxIter())
                {
                    ApplyAlignment(linebox, textAlign, lay);
                    linebox.CloseLine(lay); //***
                    linebox.CachedLineTop = localY;
                    localY += linebox.CacheLineHeight + interlineSpace;
                    if (maxLineWidth < linebox.CachedExactContentWidth)
                    {
                        maxLineWidth = linebox.CachedExactContentWidth;
                    }
                }
            }

            hostBlock.SetVisualHeight(localY + hostBlock.ActualPaddingBottom + hostBlock.ActualBorderBottomWidth);
            //final 
            SetFinalInnerContentSize(hostBlock, maxLineWidth, hostBlock.VisualHeight, lay);
        }
예제 #22
0
        //---------------------------
        static void FlowRunsIntoHost(LayoutVisitor lay,
          CssBox hostBox,
          CssBox splitableBox,
          CssBox b,
          int childNumber, //child number of b
          float limitRight,
          float firstRunStartX,
          float leftMostSpace,
          float rightMostSpace,
          List<CssRun> runs,
          ref CssLineBox hostLine,
          ref float cx)
        {
            //flow runs into hostLine, create new line if need  
            bool wrapNoWrapBox = false;
            CssWhiteSpace bWhiteSpace = b.WhiteSpace;
            bool hostBoxIsB = hostBox == b;
            if (bWhiteSpace == CssWhiteSpace.NoWrap && cx > firstRunStartX)
            {
                var tmpRight = cx;
                for (int i = runs.Count - 1; i >= 0; --i)
                {
                    tmpRight += runs[i].Width;
                }
                //----------------------------------------- 
                if (tmpRight > limitRight)
                {
                    wrapNoWrapBox = true;
                }
            }

            //----------------------------------------------------- 

            int lim = runs.Count - 1;
            for (int i = 0; i <= lim; ++i)
            {
                var run = runs[i];
                //---------------------------------------------------
                //check if need to start new line ? 
                if ((cx + run.Width + rightMostSpace > limitRight &&
                     bWhiteSpace != CssWhiteSpace.NoWrap &&
                     bWhiteSpace != CssWhiteSpace.Pre &&
                     (bWhiteSpace != CssWhiteSpace.PreWrap || !run.IsSpaces))
                     || run.IsLineBreak || wrapNoWrapBox)
                {
                    wrapNoWrapBox = false; //once! 
                    //-------------------------------
                    //create new line ***
                    hostLine = new CssLineBox(hostBox);
                    hostBox.AddLineBox(hostLine);
                    //reset x pos for new line
                    cx = firstRunStartX;
                    // handle if line is wrapped for the first text element where parent has left margin/padding
                    if (childNumber == 0 && //b is first child of splitable box ('b' == splitableBox.GetFirstChild())
                        !run.IsLineBreak &&
                        (i == 0 || splitableBox.ParentBox.IsBlock))//this run is first run of 'b' (run == b.FirstRun)
                    {
                        //TODO: review here again!!!!


                        //cx += splitableBox.ActualMarginLeft +
                        //    splitableBox.ActualBorderLeftWidth +
                        //    splitableBox.ActualPaddingLeft;
                    }

                    if (run.IsSolidContent || i == 0)
                    {
                        cx += leftMostSpace;
                    }
                }
                //---------------------------------------------------

                if (run.IsSpaces && hostLine.RunCount == 0)
                {
                    //not add 
                    continue;
                }
                //---------------------------------------------------

                hostLine.AddRun(run); //***
                if (lim == 0)
                {
                    //single one
                    if (!hostBoxIsB)
                    {
                        cx += b.ActualPaddingLeft;
                    }
                    run.SetLocation(cx, 0);
                    cx += run.Width + b.ActualPaddingRight;
                }
                else
                {
                    if (i == 0)
                    {
                        //first
                        if (!hostBoxIsB)
                        {
                            cx += b.ActualPaddingLeft;
                        }

                        run.SetLocation(cx, 0);
                        cx = run.Right;
                    }
                    else if (i == lim)
                    {
                        run.SetLocation(cx, 0);
                        cx += run.Width + b.ActualPaddingRight;
                    }
                    else
                    {
                        run.SetLocation(cx, 0);
                        cx = run.Right;
                    }
                }
                //---------------------------------------------------
                //move current_line_x to right of run
                //cx = run.Right;
            }
        }
예제 #23
0
        public static void PerformContentLayout(CssBox box, LayoutVisitor lay)
        {
            //recursive

            //this box has its own  container property
            //this box may use...
            // 1) line formatting context  , or
            // 2) block formatting context 

            CssBox myContainingBlock = lay.LatestContainingBlock;
            CssBox prevSibling = lay.LatestSiblingBox;
            if (box.CssDisplay != Css.CssDisplay.TableCell)
            {
                //-------------------------------------------
                if (box.CssDisplay != Css.CssDisplay.Table)
                {
                    float availableWidth = myContainingBlock.GetClientWidth();
                    // Console.WriteLine(availableWidth.ToString());

                    if (!box.Width.IsEmptyOrAuto)
                    {
                        float w = CssValueParser.ConvertToPx(box.Width, availableWidth, box);
                        //specific width
                        box.SetCssBoxWidth(w);
                    }
                    else
                    {
                        box.SetCssBoxFromContainerAvailableWidth(availableWidth);
                    }
                }
                //-------------------------------------------

                float localLeft = myContainingBlock.GetClientLeft() + box.ActualMarginLeft;
                float localTop = 0;
                if (prevSibling == null)
                {
                    //this is first child of parent
                    if (box.ParentBox != null)
                    {
                        localTop = myContainingBlock.GetClientTop();
                    }
                }
                else
                {
                    localTop = prevSibling.LocalVisualBottom;
                }

                //if (box.Float != CssFloat.None)
                //{
                //    //float box 
                //    //find context floating c
                //    if (lay.HasFloatBoxInContext)
                //    {


                //    }
                //}


                localTop += box.UpdateMarginTopCollapse(prevSibling);
                box.SetLocation(localLeft, localTop);
                box.SetHeightToZero();
            }
            //--------------------------------------------------------------------------

            switch (box.CssDisplay)
            {
                case Css.CssDisplay.Table:
                case Css.CssDisplay.InlineTable:
                    {
                        //If we're talking about a table here..

                        lay.PushContaingBlock(box);
                        var currentLevelLatestSibling = lay.LatestSiblingBox;
                        lay.LatestSiblingBox = null;//reset
                        CssTableLayoutEngine.PerformLayout(box, myContainingBlock.GetClientWidth(), lay);
                        lay.LatestSiblingBox = currentLevelLatestSibling;
                        lay.PopContainingBlock();
                        //TODO: check if this can have absolute layer? 
                    }
                    break;
                default:
                    {
                        //formatting context for...
                        //1. line formatting context
                        //2. block formatting context 
                        if (box.IsCustomCssBox)
                        {
                            //has custom layout method
                            box.ReEvaluateComputedValues(lay.SampleIFonts, lay.LatestContainingBlock);
                            box.CustomRecomputedValue(lay.LatestContainingBlock);
                        }
                        else
                        {
                            if (ContainsInlinesOnly(box))
                            {
                                //This will automatically set the bottom of this block 
                                LinesFormattingEngine.DoLayoutLinesContext(box, lay);
                            }
                            else if (box.ChildCount > 0)
                            {
                                DoLayoutBlocksContext(box, lay);
                            }

                            if (box.HasAbsoluteLayer)
                            {
                                LayoutContentInAbsoluteLayer(lay, box);
                            }
                        }
                        //---------------------
                        //again!
                        switch (box.CssDisplay)
                        {
                            case CssDisplay.Flex:
                            case CssDisplay.InlineFlex:
                                {
                                    //------------------------------------------------
                                    RearrangeWithFlexContext(box, lay);
                                    //------------------------------------------------
                                }
                                break;
                            default:
                                {    //TODO: review here again
                                    //if (box.Float != CssFloat.None)
                                    //{
                                    //    var iw = box.InnerContentWidth;
                                    //    var ew = box.VisualWidth;
                                    //    box.SetVisualSize(box.InnerContentWidth, box.InnerContentHeight);
                                    //    //float to specific position 
                                    //    //box.SetVisualSize(iw, box.VisualHeight);
                                    //}
                                }
                                break;
                        }
                        //---------------------
                    }
                    break;
            }


            switch (box.Float)
            {
                case CssFloat.Left:
                    {
#if DEBUG
                        CssBox a = box;
#endif

                        //place it to floating context
                        CssBox currentFloatOwner = lay.GetFloatingContextStack().CurrentTopOwner;
                        CssBox recentLeftFloatBox = lay.LatestLeftFloatBox;
                        CssBox recentRightFloatBox = lay.LatestRightFloatBox;
                        float availableWidth2 = myContainingBlock.GetClientWidth();
                        if (recentRightFloatBox != null)
                        {
                            availableWidth2 -= recentRightFloatBox.LocalX;
                        }

                        float sx = myContainingBlock.GetClientLeft();
                        //--------------------------------------------------------------------
                        float sy = 0;
                        if (myContainingBlock.LineBoxCount > 0)
                        {
                            //line context
                            sy = myContainingBlock.GetClientTop();
                        }
                        else
                        {
                            var prevNode = box.GetPrevNode();
                            if (prevNode != null)
                            {
                                if (prevNode.Float != CssFloat.None)
                                {
                                    //float left/right 
                                    //TODO: review inherit here
                                    if (box.VisualWidth < availableWidth2)
                                    {
                                        sy = prevNode.LocalY;
                                    }
                                    else
                                    {
                                        sy = prevNode.LocalVisualBottom;
                                    }
                                }
                                else
                                {
                                    sy = prevNode.LocalVisualBottom;
                                }
                            }
                            else
                            {
                                sy = myContainingBlock.GetClientTop();
                            }
                        }

                        if (recentLeftFloatBox != null)
                        {
                            availableWidth2 -= recentLeftFloatBox.LocalVisualRight;
                            //TODO: review here again
                            sx = recentLeftFloatBox.LocalVisualRight + recentLeftFloatBox.ActualMarginRight;
                            sy = recentLeftFloatBox.LocalY;
                        }

                        if (box.VisualWidth > availableWidth2)
                        {
                            //start newline
                            sx = myContainingBlock.GetClientLeft();
                            float sy1 = 0;
                            float sy2 = 0;
                            sy1 = sy2 = myContainingBlock.GetClientTop();
                            if (recentLeftFloatBox != null)
                            {
                                sy1 = recentLeftFloatBox.LocalVisualBottom + recentLeftFloatBox.ActualMarginBottom;
                            }
                            if (recentRightFloatBox != null)
                            {
                                sy2 = recentRightFloatBox.LocalVisualBottom + recentRightFloatBox.ActualMarginBottom;
                            }

                            sy = (sy1 > sy2) ? sy1 : sy2;
                        }
                        sx += box.ActualMarginLeft;
                        sy += box.ActualMarginTop;
                        box.SetLocation(sx, sy);
                        lay.AddFloatBox(box);
                    }
                    break;
                case CssFloat.Right:
                    {
                        CssBox recentLeftFloatBox = lay.LatestLeftFloatBox;
                        CssBox recentRightFloatBox = lay.LatestRightFloatBox;
                        float availableWidth2 = myContainingBlock.GetClientWidth();
                        if (recentLeftFloatBox != null)
                        {
                            availableWidth2 -= recentLeftFloatBox.LocalVisualRight;
                        }


                        float sx = myContainingBlock.GetClientRight() - (box.VisualWidth + box.ActualMarginLeft + box.ActualMarginRight);
                        //--------------------------------------------------------------------

                        float sy = 0;
                        if (myContainingBlock.LineBoxCount > 0)
                        {
                            //line context
                            sy = myContainingBlock.GetClientTop();
                        }
                        else
                        {
                            var prevNode = box.GetPrevNode();
                            if (prevNode != null)
                            {
                                if (prevNode.Float != CssFloat.None)
                                {
                                    //float left/right 
                                    //TODO: review inherit here
                                    if (box.VisualWidth < availableWidth2)
                                    {
                                        sy = prevNode.LocalY;
                                    }
                                    else
                                    {
                                        sy = prevNode.LocalVisualBottom;
                                    }
                                }
                                else
                                {
                                    sy = prevNode.LocalVisualBottom;
                                }
                            }
                            else
                            {
                                sy = myContainingBlock.GetClientTop();
                            }
                        }
                        //--------------------------------------------------------------------
                        if (recentRightFloatBox != null)
                        {
                            availableWidth2 -= recentRightFloatBox.LocalX;
                            sx = recentRightFloatBox.LocalX - box.VisualWidth;
                            sy = recentRightFloatBox.LocalY;
                        }

                        if (box.VisualWidth > availableWidth2)
                        {
                            //start newline
                            sx = myContainingBlock.GetClientRight() - (box.VisualWidth + box.ActualMarginLeft + box.ActualMarginRight);
                            float sy1 = 0;
                            float sy2 = 0;
                            sy1 = sy2 = myContainingBlock.GetClientTop();
                            //if (recentLeftFloatBox != null)
                            //{
                            //    sy1 = recentLeftFloatBox.LocalY + recentLeftFloatBox.InnerContentHeight +
                            //      recentLeftFloatBox.ActualPaddingBottom +
                            //      recentLeftFloatBox.ActualMarginBottom;
                            //}
                            //if (recentRightFloatBox != null)
                            //{
                            //    sy2 = recentRightFloatBox.LocalY + recentRightFloatBox.InnerContentHeight +
                            //       recentRightFloatBox.ActualPaddingBottom +
                            //       recentRightFloatBox.ActualMarginBottom;
                            //}
                            if (recentLeftFloatBox != null)
                            {
                                sy1 = recentLeftFloatBox.LocalVisualBottom + recentLeftFloatBox.ActualMarginBottom;
                            }
                            if (recentRightFloatBox != null)
                            {
                                sy2 = recentRightFloatBox.LocalVisualBottom + recentRightFloatBox.ActualMarginBottom;
                            }
                            sy = (sy1 > sy2) ? sy1 : sy2;
                        }

                        sx += box.ActualMarginLeft;
                        sy += box.ActualMarginTop;
                        box.SetLocation(sx, sy);
                        lay.AddFloatBox(box);
                    }
                    break;
                case CssFloat.None:
                default:
                    {
                        //review here for inherit property

                    }
                    break;
            }
        }
예제 #24
0
 /// <summary>
 /// Applies vertical and horizontal alignment to words in lineboxes
 /// </summary>
 /// <param name="g"></param>
 /// <param name="lineBox"></param> 
 static void ApplyAlignment(CssLineBox lineBox, CssTextAlign textAlign, LayoutVisitor lay)
 {
     switch (textAlign)
     {
         case CssTextAlign.Right:
             ApplyRightAlignment(lineBox);
             break;
         case CssTextAlign.Center:
             ApplyCenterAlignment(lineBox);
             break;
         case CssTextAlign.Justify:
             ApplyJustifyAlignment(lineBox);
             break;
         default:
             break;
     }
     //--------------------------------------------- 
     // Applies vertical alignment to the linebox 
     return;
     //TODO: review here
     lineBox.ApplyBaseline(lineBox.CalculateTotalBoxBaseLine(lay));
     //---------------------------------------------  
 }
예제 #25
0
        static void SetFinalInnerContentSize(CssBox box, float innerContentW, float innerContentH, LayoutVisitor lay)
        {
            box.InnerContentWidth = innerContentW;
            box.InnerContentHeight = innerContentH;
            if (!box.Height.IsEmptyOrAuto)
            {
                var h = CssValueParser.ConvertToPx(box.Height, lay.LatestContainingBlock.VisualWidth, lay.LatestContainingBlock);
                box.SetExpectedSize(box.ExpectedWidth, h);
                box.SetVisualHeight(h);
                box.SetCssBoxHeight(h);
            }
            else
            {
                switch (box.Position)
                {
                    case CssPosition.Fixed:
                    case CssPosition.Absolute:
                        box.SetVisualHeight(box.InnerContentHeight);
                        break;
                }
            }
            if (!box.Width.IsEmptyOrAuto)
            {
                //find max line width  
                var w = CssValueParser.ConvertToPx(box.Width, lay.LatestContainingBlock.VisualWidth, lay.LatestContainingBlock);
                box.SetExpectedSize(w, box.ExpectedHeight);
                box.SetVisualWidth(w);
                box.SetCssBoxWidth(w);
            }
            else
            {
                switch (box.Position)
                {
                    case CssPosition.Fixed:
                    case CssPosition.Absolute:
                        box.SetVisualWidth(box.InnerContentWidth);
                        break;
                }
            }

            switch (box.Overflow)
            {
                case CssOverflow.Scroll:
                case CssOverflow.Auto:
                    {
                        if ((box.InnerContentHeight > box.VisualHeight) ||
                        (box.InnerContentWidth > box.VisualWidth))
                        {
                            lay.RequestScrollView(box);
                        }
                    }
                    break;
            }
        }
예제 #26
0
 public LayoutFarm.HtmlBoxes.LayoutVisitor GetSharedHtmlLayoutVisitor(HtmlContainer htmlCont)
 {
     LayoutFarm.HtmlBoxes.LayoutVisitor lay = null;
     if (htmlLayoutVisitorStock.Count == 0)
     {
         lay = new LayoutVisitor();
     }
     else
     {
         lay = this.htmlLayoutVisitorStock.Dequeue();
     }
     lay.Bind(htmlCont);
     return lay;
 }
예제 #27
0
        /// <summary>
        /// Assigns words its width and height
        /// </summary>
        /// <param name="g"></param>
        public virtual void MeasureRunsSize(LayoutVisitor lay)
        {
            //measure once !
            if ((_boxCompactFlags & BoxFlags.LAY_RUNSIZE_MEASURE) != 0)
            {
                return;
            }
            //--------------------------------
            if (this.BackgroundImageBinder != null)
            {
                //this has background
                if (this.BackgroundImageBinder.State == BinderState.Unload)
                {
                    lay.RequestImage(this.BackgroundImageBinder, this);
                }
            }
            //--------------------------------
            if (this.RunCount > 0)
            {
                //find word spacing
                float       actualWordspacing = _actualWordSpacing;
                RequestFont actualFont        = this.ResolvedFont;


                float fontHeight = (actualFont.AscentInPixels - actualFont.DescentInPixels + actualFont.LineGapInPixels);
                fontHeight += 4; //TODO: why +4 ????***

                List <CssRun> tmpRuns = this.Runs;
                for (int i = tmpRuns.Count - 1; i >= 0; --i)
                {
                    CssRun run = tmpRuns[i];
                    run.Height = fontHeight;
                    //if this is newline then width =0 ***
                    switch (run.Kind)
                    {
                    case CssRunKind.Text:
                    {
                        CssTextRun textRun = (CssTextRun)run;
                        Size       ss      = lay.MeasureStringSize(CssBox.UnsafeGetTextBuffer(this),
                                                                   textRun.TextStartIndex,
                                                                   textRun.TextLength,
                                                                   actualFont);
                        run.SetSize(ss.Width, ss.Height);
                    }
                    break;

                    case CssRunKind.SingleSpace:
                    {
                        run.Width = actualWordspacing;
                    }
                    break;

                    case CssRunKind.Space:
                    {
                        //other space size
                        run.Width = actualWordspacing * ((CssTextRun)run).TextLength;
                    }
                    break;

                    case CssRunKind.LineBreak:
                    {
                        run.Width = 0;
                    }
                    break;
                    }
                }
            }
            _boxCompactFlags |= BoxFlags.LAY_RUNSIZE_MEASURE;
        }
예제 #28
0
        /// <summary>
        /// Layout the cells by the calculated table layout
        /// </summary>
        /// <param name="g"></param>
        void S8_LayoutCells(LayoutVisitor lay)
        {
            //each cell relative to its owner

            float table_globalX = lay.ContainerBlockGlobalX;
            float table_globalY = lay.ContainerBlockGlobalY;
            float vertical_spacing = GetVerticalSpacing(_tableBox);
            float horizontal_spacing = GetHorizontalSpacing(_tableBox);
            float startx_global = Math.Max(table_globalX + _tableBox.GetClientLeft() + horizontal_spacing, 0);
            float starty_global = Math.Max(table_globalY + _tableBox.GetClientTop() + vertical_spacing, 0);
            float startx_local = startx_global - table_globalX;
            float starty_local = starty_global - table_globalY;
            float curY_local = starty_local;
            float maxRight_local = startx_local;
            float maxBottom_local = 0f;
            int currentRow = 0;
            int col_count = this.columnCollection.Count;
            for (int i = 0; i < _allRowBoxes.Count; i++)
            {
                var row = _allRowBoxes[i];
                float curX_local = startx_local;//reset
                int col_index = 0;
                int grid_index = 0;
                foreach (CssBox cell in row.GetChildBoxIter())
                {
                    if (col_index >= col_count)
                    {
                        break;
                    }
                    else
                    {
                        int colspan = cell.ColSpan;
                        float width = this.columnCollection.GetCellWidth(grid_index, colspan, horizontal_spacing);
                        //HtmlRenderer.Boxes.BoxUtils.ForEachTextRunDeep(cell, trun =>
                        //{
                        //    if (trun.Text.Contains("Cell1"))
                        //    {
                        //        cell.dbugMark = 20;
                        //        return true;
                        //    }
                        //    //else if (trun.Text.Contains("You1"))
                        //    //{
                        //    //    cell.dbugMark = 19;
                        //    //    return true;
                        //    //}
                        //    return false;
                        //});

                        //-----------------------------------------
                        cell.SetLocation(curX_local, curY_local);
                        cell.FreezeWidth = false;
                        cell.SetVisualSize(width, 0);
                        cell.FreezeWidth = true;
                        //-----------------------------------------

                        cell.PerformLayout(lay); //That will automatically set the bottom of the cell
                        //Alter max bottom only if row is cell's row + cell's rowspan - 1
                        CssVerticalCellSpacingBox sb = cell as CssVerticalCellSpacingBox;
                        if (sb != null)
                        {
                            if (sb.EndRow == currentRow)
                            {
                                maxBottom_local = Math.Max(maxBottom_local, sb.ExtendedBox.LocalVisualBottom);
                            }
                        }
                        else if (cell.RowSpan == 1)
                        {
                            maxBottom_local = Math.Max(maxBottom_local, cell.LocalVisualBottom);
                        }

                        maxRight_local = Math.Max(maxRight_local, cell.LocalVisualRight);
                        curX_local = cell.LocalVisualRight + horizontal_spacing;
                        //-------------------------
                        col_index++;
                        grid_index += colspan;
                    }
                }


                foreach (CssBox cell in row.GetChildBoxIter())
                {
                    CssVerticalCellSpacingBox spacer = cell as CssVerticalCellSpacingBox;
                    if (spacer == null)
                    {
                        if (cell.RowSpan == 1)
                        {
                            cell.SetVisualHeight(maxBottom_local - curY_local);
                            ApplyCellVerticalAlignment(cell, starty_local);
                        }
                    }
                    else
                    {
                        if (spacer.EndRow == currentRow)
                        {
                            spacer.ExtendedBox.SetVisualHeight(maxBottom_local - curY_local);
                            ApplyCellVerticalAlignment(spacer.ExtendedBox, starty_local);
                        }
                    }
                }

                curY_local = maxBottom_local + vertical_spacing;
                currentRow++;
            }

            maxRight_local = Math.Max(maxRight_local, _tableBox.ExpectedWidth);
            _tableBox.SetVisualWidth(maxRight_local + horizontal_spacing + _tableBox.ActualBorderRightWidth);
            float globalBottom = Math.Max((maxBottom_local + table_globalY), starty_global) + vertical_spacing + _tableBox.ActualBorderBottomWidth;
            _tableBox.SetVisualHeight(globalBottom - table_globalY);
        }
예제 #29
0
        public void PerformLayout(LayoutVisitor lay)
        {
            if (this._rootBox == null)
            {
                return;
            }
            //----------------------- 
            //reset
            _actualWidth = _actualHeight = 0;
            // if width is not restricted we set it to large value to get the actual later    
            _rootBox.SetLocation(0, 0);
            _rootBox.SetVisualSize(this._maxWidth > 0 ? this._maxWidth : MAX_WIDTH, 0);
            CssBox.ValidateComputeValues(_rootBox);
            //----------------------- 
            //LayoutVisitor layoutArgs = new LayoutVisitor(this.GraphicsPlatform, this);
            lay.PushContaingBlock(_rootBox);
            //----------------------- 

            _rootBox.PerformLayout(lay);
            if (this._maxWidth <= 0.1)
            {
                // in case the width is not restricted we need to double layout, first will find the width so second can layout by it (center alignment)
                _rootBox.SetVisualWidth((int)Math.Ceiling(this._actualWidth));
                _actualWidth = _actualHeight = 0;
                _rootBox.PerformLayout(lay);
            }
            lay.PopContainingBlock();
            //----------------------- 
            //TODO: review here again
            FloatingContextStack floatStack = lay.GetFloatingContextStack();
            List<FloatingContext> totalContexts = floatStack.GetTotalContexts();
            int j = totalContexts.Count;
            for (int i = 0; i < j; ++i)
            {
                FloatingContext floatingContext = totalContexts[i];
                int floatBoxCount = floatingContext.FloatBoxCount;
                if (floatBoxCount == 0) { continue; }


                CssBox floatingOwner = floatingContext.Owner;
                float rfx, rfy;
                floatingOwner.GetGlobalLocation(out rfx, out rfy);
                CssBox prevParent = null;
                //TODO: review here again
                float extraAdjustX = 0; //temp fixed
                for (int n = 0; n < floatBoxCount; ++n)
                {
                    float bfx, bfy;
                    CssBox box = floatingContext.GetBox(n);
                    box.GetGlobalLocation(out bfx, out bfy);
                    //diff
                    float nx = bfx - rfx;
                    float ny = bfy - rfy;
                    if (prevParent != null && prevParent != box.ParentBox)
                    {
                        if (n > 0)
                        {
                            CssBox prevFloatChild = floatingContext.GetBox(n - 1);
                            //TODO: review here again
                            //temp fix
                            extraAdjustX = prevFloatChild.ActualMarginRight + box.ActualMarginLeft;
                            ny += box.ActualMarginTop;
                        }
                    }
                    box.SetLocation(nx + extraAdjustX, ny);
                    prevParent = box.ParentBox;
                    floatingOwner.AppendToAbsoluteLayer(box);
                }
            }

            OnLayoutFinished();
            //----------------------- 
            unchecked { layoutVersion++; }
            //----------------------- 
        }
예제 #30
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
         }
     }
 }
예제 #31
0
        /// <summary>
        /// Measures the bounds of box and children, recursively.<br/>
        /// Performs layout of the DOM structure creating lines by set bounds restrictions.
        /// </summary>
        /// <param name="g">Device context to use</param>
        protected override void PerformContentLayout(LayoutVisitor lay)
        {
            if (this.CssDisplay == Css.CssDisplay.None)
            {
                return;
            }
            var prevSibling = lay.LatestSiblingBox;
            var myContainingBlock = lay.LatestContainingBlock;
            if (this.NeedComputedValueEvaluation)
            {
                this.ReEvaluateComputedValues(lay.SampleIFonts, myContainingBlock);
            }

            float localLeft = myContainingBlock.GetClientLeft() + this.ActualMarginLeft;
            float localTop = 0;
            if (prevSibling == null)
            {
                if (this.ParentBox != null)
                {
                    localTop = myContainingBlock.GetClientTop();
                }
            }
            else
            {
                localTop = prevSibling.LocalVisualBottom;// +prevSibling.ActualBorderBottomWidth;
            }

            float maringTopCollapse = UpdateMarginTopCollapse(prevSibling);
            if (maringTopCollapse < 0.1)
            {
                maringTopCollapse = this.GetEmHeight() * 1.1f;
            }
            localTop += maringTopCollapse;
            this.SetLocation(localLeft, localTop);
            this.SetHeightToZero();
            //width at 100% (or auto)
            float minwidth = CalculateMinimumWidth(lay.EpisodeId);
            float width = myContainingBlock.VisualWidth
                          - myContainingBlock.ActualPaddingLeft - myContainingBlock.ActualPaddingRight
                          - myContainingBlock.ActualBorderLeftWidth - myContainingBlock.ActualBorderRightWidth
                          - ActualMarginLeft - ActualMarginRight - ActualBorderLeftWidth - ActualBorderRightWidth;
            //Check width if not auto
            if (!this.Width.IsEmptyOrAuto)
            {
                width = CssValueParser.ConvertToPx(Width, width, this);
            }


            if (width < minwidth || width >= CssBoxConstConfig.TABLE_MAX_WIDTH)
            {
                width = minwidth;
            }

            float height = ExpectedHeight;
            if (height < 1)
            {
                height = this.VisualHeight + ActualBorderTopWidth + ActualBorderBottomWidth;
            }
            if (height < 1)
            {
                height = 2;
            }
            if (height <= 2 && ActualBorderTopWidth < 1 && ActualBorderBottomWidth < 1)
            {
                DirectSetBorderWidth(CssSide.Top, 1);
                DirectSetBorderWidth(CssSide.Bottom, 1);
            }

            this.SetVisualSize(width, height);
            this.SetVisualHeight(ActualPaddingTop + ActualPaddingBottom + height);
        }
예제 #32
0
        internal void CloseLine(LayoutVisitor lay)
        {
#if DEBUG
            this.dbugIsClosed = true;
#endif

            //=============================================================
            //part 1: MakeStrips()
            //=============================================================
            //***
            List<CssRun> myruns = this._runs;
            CssBox lineOwner = this._ownerBox;
            List<PartialBoxStrip> tmpStrips = lay.GetReadyStripList();
            //--------------------------------------------------------------------------- 
            //first level 
            Dictionary<CssBox, PartialBoxStrip> unqiueStrips = lay.GetReadyStripDic();
            //location of run and strip related to its containng block
            float maxRight = 0;
            float maxBottom = 0;
            int j = myruns.Count;
            float firstRunStartAt = 0;
            for (int i = 0; i < j; ++i)
            {
                CssRun run = myruns[i];
                if (i == 0)
                {
                    firstRunStartAt = run.Left;
                }
                maxRight = run.Right > maxRight ? run.Right : maxRight;
                maxBottom = run.Bottom > maxBottom ? run.Bottom : maxBottom;
                if (run.IsSpaces)
                {
                    //strip size include whitespace ?
                    continue;
                }
                //-------------
                //first level data
                RegisterStripPart(run.OwnerBox, run.Left, run.Top, run.Right, run.Bottom, tmpStrips, unqiueStrips);
            }

            //---------------------------------------------------------------------------
            //other step to upper layer, until no new strip     
            int newStripIndex = 0;
            for (int numNewStripCreate = tmpStrips.Count; numNewStripCreate > 0; newStripIndex += numNewStripCreate)
            {
                numNewStripCreate = StepUpRegisterStrips(unqiueStrips, lineOwner, tmpStrips, newStripIndex);
            }

            this._bottomUpBoxStrips = tmpStrips.ToArray();
            lay.ReleaseStripList(tmpStrips);
            lay.ReleaseStripDic(unqiueStrips);
            //=============================================================
            //part 2: Calculate 
            //=============================================================     

            this.CacheLineHeight = maxBottom;
            this.CachedLineContentWidth = maxRight;
            this.CachedExactContentWidth = (maxRight - firstRunStartAt);
            if (lineOwner.VisualWidth < CachedLineContentWidth)
            {
                this.CachedLineContentWidth = this.OwnerBox.VisualWidth;
            }
        }
예제 #33
0
 /// <summary>
 /// Measures the bounds of box and children, recursively.<br/>
 /// Performs layout of the DOM structure creating lines by set bounds restrictions.
 /// </summary>
 /// <param name="g">Device context to use</param>
 public void PerformLayout(LayoutVisitor lay)
 {
     //derived class can perform its own layout algo
     //by override performContentLayout
     PerformContentLayout(lay);
 }
예제 #34
0
        public float CalculateTotalBoxBaseLine(LayoutVisitor lay)
        {
            //not correct !! 
            float maxRunHeight = 0;
            CssRun maxRun = null;
            for (int i = this._runs.Count - 1; i >= 0; --i)
            {
                var run = this._runs[i];
                if (run.Height > maxRunHeight)
                {
                    maxRun = run;
                    maxRunHeight = run.Height;
                }
            }
            if (maxRun != null)
            {
                //lay.GraphicsPlatform.SampleIFonts
                //var f = maxRun.OwnerBox.ResolvedFont;
                //PixelFarm.Drawing.Fonts.ActualFont ff = f.ActualFont;
                //return (float)(f.Height * ff.AscentInPixels / f.Height);

                //return fontHeight* fontAscent / lineSpacing )
            }
            return 0;
            //int j = this._runs.Count;
            //for (int i = this._runs.Count - 1; i >= 0; --i)
            //{
            //    Font ownerFont = _runs[i].OwnerBox.ActualFont;
            //    HtmlRenderer.Drawing.FontsUtils.GetDescent(
            //}
            //return 0;

            //float baseline = Single.MinValue;
            //for (int i = _bottomUpBoxStrips.Count - 1; i >= 0; --i)
            //{
            //    baseline = Math.Max(baseline, _bottomUpBoxStrips[i].Top);//?top 
            //}
            //return baseline;
        }
예제 #35
0
 public void ReleaseHtmlLayoutVisitor(LayoutVisitor lay)
 {
     lay.UnBind();
     this.htmlLayoutVisitorStock.Enqueue(lay);
 }
예제 #36
0
        static void RearrangeWithFlexContext(CssBox box, LayoutVisitor lay)
        {
            //this is an experiment!,  
            var children = CssBox.UnsafeGetChildren(box);
            var cnode = children.GetFirstLinkedNode();
            List<FlexItem> simpleFlexLine = new List<FlexItem>();
            FlexLine flexLine = new FlexLine(box);
            while (cnode != null)
            {
                flexLine.AddChild(new FlexItem(cnode.Value));
                cnode = cnode.Next;
            }
            flexLine.Arrange();
            if (box.Height.IsEmptyOrAuto)
            {
                //set new height                
                box.SetVisualHeight(flexLine.LineHeightAfterArrange);
                //check if it need scrollbar or not 
            }
            if (box.Width.IsEmptyOrAuto)
            {
                box.SetVisualWidth(flexLine.LineWidthAfterArrange);
            }

            SetFinalInnerContentSize(box, flexLine.LineWidthAfterArrange, flexLine.LineHeightAfterArrange, lay);
        }
예제 #37
0
        internal void CloseLine(LayoutVisitor lay)
        {
#if DEBUG
            this.dbugIsClosed = true;
#endif

            //=============================================================
            //part 1: MakeStrips()
            //=============================================================
            //***
            List <CssRun>          myruns    = _runs;
            CssBox                 lineOwner = _ownerBox;
            List <PartialBoxStrip> tmpStrips = lay.GetReadyStripList();
            //---------------------------------------------------------------------------
            //first level
            Dictionary <CssBox, PartialBoxStrip> unqiueStrips = lay.GetReadyStripDic();
            //location of run and strip related to its containng block
            float maxRight        = 0;
            float maxBottom       = 0;
            int   j               = myruns.Count;
            float firstRunStartAt = 0;
            for (int i = 0; i < j; ++i)
            {
                CssRun run = myruns[i];
                if (i == 0)
                {
                    firstRunStartAt = run.Left;
                }
                maxRight  = run.Right > maxRight ? run.Right : maxRight;
                maxBottom = run.Bottom > maxBottom ? run.Bottom : maxBottom;
                if (run.IsSpaces)
                {
                    //strip size include whitespace ?
                    continue;
                }
                //-------------
                //first level data
                RegisterStripPart(run.OwnerBox, run.Left, run.Top, run.Right, run.Bottom, tmpStrips, unqiueStrips);
            }

            //---------------------------------------------------------------------------
            //other step to upper layer, until no new strip
            int newStripIndex = 0;
            for (int numNewStripCreate = tmpStrips.Count; numNewStripCreate > 0; newStripIndex += numNewStripCreate)
            {
                numNewStripCreate = StepUpRegisterStrips(unqiueStrips, lineOwner, tmpStrips, newStripIndex);
            }

            _bottomUpBoxStrips = tmpStrips.ToArray();
            lay.ReleaseStripList(tmpStrips);
            lay.ReleaseStripDic(unqiueStrips);
            //=============================================================
            //part 2: Calculate
            //=============================================================

            this.CacheLineHeight         = maxBottom;
            this.CachedLineContentWidth  = maxRight;
            this.CachedExactContentWidth = (maxRight - firstRunStartAt);
            if (lineOwner.VisualWidth < CachedLineContentWidth)
            {
                this.CachedLineContentWidth = this.OwnerBox.VisualWidth;
            }
        }
예제 #38
0
 /// <summary>
 /// Measures the bounds of box and children, recursively.<br/>
 /// Performs layout of the DOM structure creating lines by set bounds restrictions.
 /// </summary>
 /// <param name="g">Device context to use</param>
 public void PerformLayout(LayoutVisitor lay)
 {
     //derived class can perform its own layout algo            
     //by override performContentLayout 
     PerformContentLayout(lay);
 }
예제 #39
0
        /// <summary>
        /// Measures the bounds of box and children, recursively.<br/>
        /// Performs layout of the DOM structure creating lines by set bounds restrictions.<br/>
        /// </summary>
        /// <param name="g">Device context to use</param>
        protected virtual void PerformContentLayout(LayoutVisitor lay)
        {
            switch (this.CssDisplay)
            {
                case Css.CssDisplay.None:
                    {
                        return;
                    }
                default:
                    {
                        //others ... 
                        if (this.NeedComputedValueEvaluation) { this.ReEvaluateComputedValues(lay.SampleIFonts, lay.LatestContainingBlock); }
                        this.MeasureRunsSize(lay);
                    }
                    break;
                case Css.CssDisplay.Block:
                case Css.CssDisplay.ListItem:
                case Css.CssDisplay.Table:
                case Css.CssDisplay.InlineTable:
                case Css.CssDisplay.TableCell:
                case Css.CssDisplay.Flex:
                case Css.CssDisplay.InlineFlex:
                    {
                        //this box has its own  container property
                        //this box may be used for ...
                        // 1) line formatting context  , or
                        // 2) block formatting context  
                        if (this.NeedComputedValueEvaluation) { this.ReEvaluateComputedValues(lay.SampleIFonts, lay.LatestContainingBlock); }
                        this.MeasureRunsSize(lay);
                        //for general block layout 
                        CssLayoutEngine.PerformContentLayout(this, lay);
                    }
                    break;
            }

            //set height  
            UpdateIfHigher(this, ExpectedHeight);
            //update back 

            lay.UpdateRootSize(this);
        }
예제 #40
0
        /// <summary>
        /// Assigns words its width and height
        /// </summary>
        /// <param name="g"></param>
        public virtual void MeasureRunsSize(LayoutVisitor lay)
        {
            //measure once !
            if ((this._boxCompactFlags & BoxFlags.LAY_RUNSIZE_MEASURE) != 0)
            {
                return;
            }
            //-------------------------------- 
            if (this.BackgroundImageBinder != null)
            {
                //this has background
                if (this.BackgroundImageBinder.State == ImageBinderState.Unload)
                {
                    lay.RequestImage(this.BackgroundImageBinder, this);
                }
            }
            //-------------------------------- 
            if (this.RunCount > 0)
            {
                //find word spacing  
                float actualWordspacing = this._actualWordSpacing;
                RequestFont actualFont = this.ResolvedFont;


                float fontHeight = (actualFont.AscentInPixels - actualFont.DescentInPixels + actualFont.LineGapInPixels);
                fontHeight += 4;



                var tmpRuns = this.Runs;
                for (int i = tmpRuns.Count - 1; i >= 0; --i)
                {
                    CssRun run = tmpRuns[i];
                    run.Height = fontHeight;
                    //if this is newline then width =0 ***                         
                    switch (run.Kind)
                    {
                        case CssRunKind.Text:
                            {
                                CssTextRun textRun = (CssTextRun)run;
                                //run.Width = lay.MeasureStringWidth(
                                //    CssBox.UnsafeGetTextBuffer(this),
                                //    textRun.TextStartIndex,
                                //    textRun.TextLength,
                                //    actualFont);
                                Size ss = lay.MeasureStringSize(CssBox.UnsafeGetTextBuffer(this),
                                    textRun.TextStartIndex,
                                    textRun.TextLength,
                                    actualFont);
                                run.SetSize(ss.Width, ss.Height);

                            }
                            break;
                        case CssRunKind.SingleSpace:
                            {
                                run.Width = actualWordspacing;
                            }
                            break;
                        case CssRunKind.Space:
                            {
                                //other space size                                     
                                run.Width = actualWordspacing * ((CssTextRun)run).TextLength;
                            }
                            break;
                        case CssRunKind.LineBreak:
                            {
                                run.Width = 0;
                            }
                            break;
                    }
                }
            }
            this._boxCompactFlags |= BoxFlags.LAY_RUNSIZE_MEASURE;
        }
예제 #41
0
 public void SetHtmlHost(HtmlHost htmlhost)
 {
     this.htmlhost = htmlhost;
     htmlhost.SetHtmlContainerUpdateHandler(htmlCont =>
     {
         var updatedHtmlCont = htmlCont as MyHtmlContainer;
         if (updatedHtmlCont != null && !updatedHtmlCont.IsInUpdateQueue)
         {
             updatedHtmlCont.IsInUpdateQueue = true;
             waitingUpdateList.Add(updatedHtmlCont);
         }
     });
     htmlContainer = new MyHtmlContainer(htmlhost);
     htmlContainer.AttachEssentialHandlers(
         OnRefresh,
         myHtmlContainer_NeedUpdateDom,
         OnRefresh,
         null);
     htmlLayoutVisitor = new LayoutVisitor();
     htmlLayoutVisitor.Bind(htmlContainer);
     //------------------------------------------------------- 
     timer01.Interval = 20;//20ms?
     timer01.Tick += (s, e) =>
     {
         //clear waiting
         int j = waitingUpdateList.Count;
         for (int i = 0; i < j; ++i)
         {
             var htmlCont = waitingUpdateList[i];
             htmlCont.IsInUpdateQueue = false;
             htmlCont.RefreshDomIfNeed();
         }
         for (int i = j - 1; i >= 0; --i)
         {
             waitingUpdateList.RemoveAt(i);
         }
     };
     timer01.Enabled = true;
     //-------------------------------------------
     _htmlInputEventAdapter = new HtmlInputEventAdapter();
     _htmlInputEventAdapter.Bind(htmlContainer);
     //-------------------------------------------
 }
예제 #42
0
        static void LayoutContentInAbsoluteLayer(LayoutVisitor lay, CssBox srcBox)
        {
            if (srcBox.JustTempContainer) return;
            var ifonts = lay.SampleIFonts;
            //css3 jan2015: absolute position
            //use offset relative to its normal the box's containing box***

            float containerW = lay.LatestContainingBlock.VisualWidth;
            float maxRight = 0;
            float maxBottom = 0;
            foreach (var b in srcBox.GetAbsoluteChildBoxIter())
            {
                if (b.JustTempContainer)
                {
                    continue;
                }

                if (b.NeedComputedValueEvaluation)
                {
                    b.ReEvaluateComputedValues(ifonts, lay.LatestContainingBlock);
                }

                b.MeasureRunsSize(lay);
                PerformContentLayout(b, lay);
                b.SetLocation(
                     CssValueParser.ConvertToPx(b.Left, containerW, b),
                     CssValueParser.ConvertToPx(b.Top, containerW, b));
                var localRight = b.LocalVisualRight;
                var localBottom = b.LocalVisualBottom;
                if (maxRight < localRight)
                {
                    maxRight = localRight;
                }
                if (maxBottom < localBottom)
                {
                    maxBottom = localBottom;
                }
            }

            int i_maxRight = (int)maxRight;
            int i_maxBottom = (int)maxBottom;
            srcBox.InnerContentWidth = i_maxRight;
            srcBox.InnerContentHeight = i_maxBottom;
        }
예제 #43
0
        /// <summary>
        /// Assigns words its width and height
        /// </summary>
        /// <param name="g"></param>
        public virtual void MeasureRunsSize(LayoutVisitor lay)
        {
            //measure once !
            if ((this._boxCompactFlags & BoxFlags.LAY_RUNSIZE_MEASURE) != 0)
            {
                return;
            }

            //--------------------------------
            if (this.BackgroundImageBinder != null)
            {
                //this has background
                if (this.BackgroundImageBinder.State == ImageBinderState.Unload)
                {
                    lay.RequestImage(this.BackgroundImageBinder, this);
                }
            }

            //--------------------------------
            if (this.RunCount > 0)
            {
                //find word spacing
                float actualWordspacing = this._actualWordSpacing;
                Font  actualFont        = this.ActualFont;
                var   fontInfo          = actualFont.FontInfo;
                float fontHeight        = fontInfo.LineHeight;

                var tmpRuns = this.Runs;
                for (int i = tmpRuns.Count - 1; i >= 0; --i)
                {
                    CssRun run = tmpRuns[i];
                    run.Height = fontHeight;
                    //if this is newline then width =0 ***
                    switch (run.Kind)
                    {
                    case CssRunKind.Text:
                    {
                        CssTextRun textRun = (CssTextRun)run;
                        run.Width = lay.MeasureStringWidth(
                            CssBox.UnsafeGetTextBuffer(this),
                            textRun.TextStartIndex,
                            textRun.TextLength,
                            actualFont);
                    }
                    break;

                    case CssRunKind.SingleSpace:
                    {
                        run.Width = actualWordspacing;
                    }
                    break;

                    case CssRunKind.Space:
                    {
                        //other space size
                        run.Width = actualWordspacing * ((CssTextRun)run).TextLength;
                    }
                    break;

                    case CssRunKind.LineBreak:
                    {
                        run.Width = 0;
                    }
                    break;
                    }
                }
            }
            this._boxCompactFlags |= BoxFlags.LAY_RUNSIZE_MEASURE;
        }
예제 #44
0
        /// <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="imgRun">the image word to measure</param>
        static void MeasureImageSize(CssImageRun imgRun, LayoutVisitor lay)
        {
            var  width             = imgRun.OwnerBox.Width;
            var  height            = imgRun.OwnerBox.Height;
            bool hasImageTagWidth  = width.Number > 0 && width.UnitOrNames == Css.CssUnitOrNames.Pixels;
            bool hasImageTagHeight = height.Number > 0 && height.UnitOrNames == Css.CssUnitOrNames.Pixels;
            bool scaleImageHeight  = false;

            if (hasImageTagWidth)
            {
                imgRun.Width = width.Number;
            }
            else if (width.Number > 0 && width.IsPercentage)
            {
                imgRun.Width     = width.Number * lay.LatestContainingBlock.VisualWidth;
                scaleImageHeight = true;
            }
            else if (imgRun.HasUserImageContent)
            {
                imgRun.Width = imgRun.ImageRectangle == Rectangle.Empty ? imgRun.OriginalImageWidth : imgRun.ImageRectangle.Width;
            }
            else
            {
                imgRun.Width = hasImageTagHeight ? height.Number / 1.14f : 20;
            }

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

            if (maxWidth.Number > 0)
            {
                float maxWidthVal = -1;
                switch (maxWidth.UnitOrNames)
                {
                case Css.CssUnitOrNames.Percent:
                {
                    maxWidthVal = maxWidth.Number * lay.LatestContainingBlock.VisualWidth;
                }
                break;

                case Css.CssUnitOrNames.Pixels:
                {
                    maxWidthVal = maxWidth.Number;
                }
                break;
                }


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

            if (hasImageTagHeight)
            {
                imgRun.Height = height.Number;
            }
            else if (imgRun.HasUserImageContent)
            {
                imgRun.Height = imgRun.ImageRectangle == Rectangle.Empty ? imgRun.OriginalImageHeight : imgRun.ImageRectangle.Height;
            }
            else
            {
                imgRun.Height = imgRun.Width > 0 ? imgRun.Width * 1.14f : 22.8f;
            }

            if (imgRun.HasUserImageContent)
            {
                // 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 = imgRun.Width / imgRun.OriginalImageWidth;
                    imgRun.Height = imgRun.OriginalImageHeight * 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 = imgRun.Height / imgRun.OriginalImageHeight;
                    imgRun.Width = imgRun.OriginalImageWidth * ratio;
                }
            }
            //imageWord.Height += imageWord.OwnerBox.ActualBorderBottomWidth + imageWord.OwnerBox.ActualBorderTopWidth + imageWord.OwnerBox.ActualPaddingTop + imageWord.OwnerBox.ActualPaddingBottom;
        }
예제 #45
0
        /// <summary>
        /// Measures the bounds of box and children, recursively.<br/>
        /// Performs layout of the DOM structure creating lines by set bounds restrictions.
        /// </summary>
        /// <param name="g">Device context to use</param>
        protected override void PerformContentLayout(LayoutVisitor lay)
        {
            if (this.CssDisplay == Css.CssDisplay.None)
            {
                return;
            }
            var prevSibling = lay.LatestSiblingBox;

            var myContainingBlock = lay.LatestContainingBlock;

            if (this.NeedComputedValueEvaluation)
            {
                this.ReEvaluateComputedValues(lay.SampleIFonts, myContainingBlock);
            }

            float localLeft = myContainingBlock.GetClientLeft() + this.ActualMarginLeft;
            float localTop  = 0;

            if (prevSibling == null)
            {
                if (this.ParentBox != null)
                {
                    localTop = myContainingBlock.GetClientTop();
                }
            }
            else
            {
                localTop = prevSibling.LocalVisualBottom;// +prevSibling.ActualBorderBottomWidth;
            }

            float maringTopCollapse = UpdateMarginTopCollapse(prevSibling);

            if (maringTopCollapse < 0.1)
            {
                maringTopCollapse = this.GetEmHeight() * 1.1f;
            }
            localTop += maringTopCollapse;


            this.SetLocation(localLeft, localTop);
            this.SetHeightToZero();

            //width at 100% (or auto)
            float minwidth = CalculateMinimumWidth(lay.EpisodeId);

            float width = myContainingBlock.VisualWidth
                          - myContainingBlock.ActualPaddingLeft - myContainingBlock.ActualPaddingRight
                          - myContainingBlock.ActualBorderLeftWidth - myContainingBlock.ActualBorderRightWidth
                          - ActualMarginLeft - ActualMarginRight - ActualBorderLeftWidth - ActualBorderRightWidth;


            //Check width if not auto
            if (!this.Width.IsEmptyOrAuto)
            {
                width = CssValueParser.ConvertToPx(Width, width, this);
            }


            if (width < minwidth || width >= CssBoxConstConfig.TABLE_MAX_WIDTH)
            {
                width = minwidth;
            }

            float height = ExpectedHeight;

            if (height < 1)
            {
                height = this.VisualHeight + ActualBorderTopWidth + ActualBorderBottomWidth;
            }
            if (height < 1)
            {
                height = 2;
            }
            if (height <= 2 && ActualBorderTopWidth < 1 && ActualBorderBottomWidth < 1)
            {
                DirectSetBorderWidth(CssSide.Top, 1);
                DirectSetBorderWidth(CssSide.Bottom, 1);
            }

            this.SetVisualSize(width, height);
            this.SetVisualHeight(ActualPaddingTop + ActualPaddingBottom + height);
        }
예제 #46
0
        /// <summary>
        /// Recursively flows the content of the box using the inline model
        /// </summary>
        /// <param name="lay"></param>
        /// <param name="hostBox"></param>
        /// <param name="srcBox"></param>
        /// <param name="limitLocalRight"></param>
        /// <param name="firstRunStartX"></param>
        /// <param name="hostLine"></param>
        /// <param name="cx"></param>
        static void FlowBoxContentIntoHostLineFmtContext(
          LayoutVisitor lay,
          CssBox hostBox, //target host box that contains line formatting context
          CssBox srcBox, //src that has  runs /splitable content) to flow into hostBox line model
          float limitLocalRight,
          float firstRunStartX,
          ref CssLineBox hostLine,
          ref float cx,
          ref FloatFormattingContext floatCtx)
        {
            //recursive *** 
            //-------------------------------------------------------------------- 
            var oX = cx;
            if (srcBox.HasOnlyRuns)
            {
                //condition 3 

                FlowRunsIntoHost(lay, hostBox, srcBox, srcBox, 0,
                     limitLocalRight, firstRunStartX,
                     0, 0,
                     CssBox.UnsafeGetRunList(srcBox),
                     ref hostLine, ref cx
                     );
            }
            else
            {
                int childNumber = 0;
                var ifonts = lay.SampleIFonts;
                CssBoxCollection children = CssBox.UnsafeGetChildren(srcBox);
                var cNode = children.GetFirstLinkedNode();
                while (cNode != null)
                {
                    float leftMostSpace = 0, rightMostSpace = 0;
                    CssBox b = cNode.Value;
                    //if b has absolute pos then it is removed from the flow 
                    if (b.NeedComputedValueEvaluation)
                    {
                        b.ReEvaluateComputedValues(ifonts, hostBox);
                    }
                    b.MeasureRunsSize(lay);
#if DEBUG
                    if (b.Position == CssPosition.Absolute)
                    {
                        //should not found here!
                        throw new NotSupportedException();
                    }
#endif


                    cx += leftMostSpace;
                    if (b.CssDisplayInside == CssDisplayInside.FlowRoot)//eg. inline block
                    {
                        //--------
                        // if inside display is FlowRoot *** 
                        //--------- 

                        //outside -> inline
                        //inside -> flow-root

                        //can't split 
                        //create 'block-run'  
                        CssLayoutEngine.PerformContentLayout(b, lay);
                        CssBlockRun blockRun = b.JustBlockRun;
                        if (blockRun == null)
                        {
                            blockRun = new CssBlockRun(b);
                            blockRun.SetOwner(srcBox);
                            b.JustBlockRun = blockRun;
                        }


                        if (b.Width.IsEmptyOrAuto)
                        {
                            blockRun.SetSize(CssBox.GetLatestCachedMinWidth(b), b.VisualHeight);
                        }
                        else
                        {
                            blockRun.SetSize(b.VisualWidth, b.VisualHeight);
                        }

                        b.SetLocation(b.LocalX, 0); //because of inline***
                        FlowRunsIntoHost(lay, hostBox, srcBox, b, childNumber,
                            limitLocalRight, firstRunStartX,
                            leftMostSpace, rightMostSpace,
                            new List<CssRun>() { b.JustBlockRun },
                            ref hostLine, ref cx);
                    }
                    else if (b.CssDisplayOutside == CssDisplayOutside.Block)
                    {
                        //warning : this code block not follow w3c spec ***


                        CssLayoutEngine.PerformContentLayout(b, lay);
                        CssBlockRun blockRun = b.JustBlockRun;
                        if (blockRun == null)
                        {
                            blockRun = new CssBlockRun(b);
                            blockRun.SetOwner(srcBox);
                            b.JustBlockRun = blockRun;
                        }

                        //set width to full ***
                        blockRun.SetSize(hostBox.GetClientWidth(), b.VisualHeight);
                        b.SetLocation(b.LocalX, 0); //because of inline***
                        FlowRunsIntoHost(lay, hostBox, srcBox, b, childNumber,
                            limitLocalRight, firstRunStartX,
                            leftMostSpace, rightMostSpace,
                            new List<CssRun>() { b.JustBlockRun },
                            ref hostLine, ref cx);
                    }
                    else if (b.HasOnlyRuns)
                    {
                        switch (b.Float)
                        {
                            default:
                            case CssFloat.None:
                                {
                                    FlowRunsIntoHost(lay, hostBox, srcBox, b, childNumber,
                                        limitLocalRight, firstRunStartX,
                                        leftMostSpace, rightMostSpace,
                                        CssBox.UnsafeGetRunList(b),
                                        ref hostLine, ref cx);
                                }
                                break;
                            case CssFloat.Left:
                                {
                                    //float is out of flow item 
                                    //1. current line is shortening
                                    //2. add 'b' to special container ***  

                                    var newAnonBlock = new CssFloatContainerBox(
                                        CssBox.UnsafeGetBoxSpec(b),
                                        b.RootGfx, CssDisplay.Block);
                                    newAnonBlock.ReEvaluateComputedValues(ifonts, hostBox);
                                    //add to abs layer
                                    hostBox.AppendToAbsoluteLayer(newAnonBlock);
                                    newAnonBlock.ResetLineBoxes();
                                    float localX1 = 0;
                                    var line = new CssLineBox(newAnonBlock);
                                    newAnonBlock.AddLineBox(line);
                                    var newFloatCtx = new FloatFormattingContext();
                                    FlowBoxContentIntoHostLineFmtContext(lay, newAnonBlock, b,
                                        limitLocalRight, 0,
                                        ref line, ref localX1, ref newFloatCtx);
                                    float localY = 0;
                                    int interlineSpace = 0;
                                    float maxLineWidth = 0;
                                    CssTextAlign textAlign = newAnonBlock.CssTextAlign;
                                    foreach (CssLineBox linebox in newAnonBlock.GetLineBoxIter())
                                    {
                                        ApplyAlignment(linebox, textAlign, lay);
                                        linebox.CloseLine(lay); //*** 
                                        linebox.CachedLineTop = localY;
                                        localY += linebox.CacheLineHeight + interlineSpace;
                                        if (maxLineWidth < linebox.CachedExactContentWidth)
                                        {
                                            maxLineWidth = linebox.CachedExactContentWidth;
                                        }
                                    }

                                    float hostSizeW = hostBox.VisualWidth;
                                    SetFinalInnerContentSize(newAnonBlock, maxLineWidth, localY, lay);
                                    //need to adjust line box   

                                    //TODO: review here!, 
                                    if (hostLine.CanDoMoreLeftOffset(newAnonBlock.InnerContentWidth, limitLocalRight))
                                    {
                                        hostLine.DoLeftOffset(newAnonBlock.InnerContentWidth);
                                        cx = hostLine.GetRightOfLastRun();
                                        newAnonBlock.SetLocation(floatCtx.lineLeftOffset, floatCtx.offsetFloatTop); //TODO: review top location again
                                        floatCtx.lineLeftOffset = newAnonBlock.LocalX + newAnonBlock.InnerContentWidth;
                                    }
                                    else
                                    {
                                        //newline
                                        newAnonBlock.SetLocation(hostBox.GetClientLeft(), hostLine.CalculateLineHeight());
                                        floatCtx.offsetFloatTop = newAnonBlock.LocalY;
                                    }
                                }
                                break;
                            case CssFloat.Right:
                                {
                                    //float is out of flow item      
                                    //1. create new block box and then
                                    //flow content in to this new box
                                    var newAnonBlock = new CssFloatContainerBox(
                                        CssBox.UnsafeGetBoxSpec(b),
                                        b.RootGfx, CssDisplay.Block);
                                    newAnonBlock.ReEvaluateComputedValues(ifonts, hostBox);
                                    //add to abs layer
                                    hostBox.AppendToAbsoluteLayer(newAnonBlock);
                                    newAnonBlock.ResetLineBoxes();
                                    float localX1 = 0;
                                    var line = new CssLineBox(newAnonBlock);
                                    newAnonBlock.AddLineBox(line);
                                    var newFloatCtx = new FloatFormattingContext();
                                    FlowBoxContentIntoHostLineFmtContext(lay, newAnonBlock, b,
                                        limitLocalRight, 0,
                                        ref line, ref localX1, ref newFloatCtx);
                                    float localY = 0;
                                    int interlineSpace = 0;
                                    float maxLineWidth = 0;
                                    CssTextAlign textAlign = newAnonBlock.CssTextAlign;
                                    foreach (CssLineBox linebox in newAnonBlock.GetLineBoxIter())
                                    {
                                        ApplyAlignment(linebox, textAlign, lay);
                                        linebox.CloseLine(lay); //*** 
                                        linebox.CachedLineTop = localY;
                                        localY += linebox.CacheLineHeight + interlineSpace;
                                        if (maxLineWidth < linebox.CachedExactContentWidth)
                                        {
                                            maxLineWidth = linebox.CachedExactContentWidth;
                                        }
                                    }
                                    SetFinalInnerContentSize(newAnonBlock, maxLineWidth, localY, lay);
                                    //todo: review here
                                    float hostSizeW = hostBox.VisualWidth;
                                    var rightOfLastRun = hostLine.GetRightOfLastRun();
                                    if (!floatCtx.floatingOutOfLine)
                                    {
                                        if (rightOfLastRun + maxLineWidth < hostSizeW - floatCtx.lineRightOffset)
                                        {
                                            float newX = hostSizeW - (maxLineWidth + floatCtx.lineRightOffset);
                                            newAnonBlock.SetLocation(newX, floatCtx.offsetFloatTop);
                                            floatCtx.lineRightOffset = newX;
                                            floatCtx.rightFloatBox = newAnonBlock;
                                            floatCtx.floatingOutOfLine = true;
                                        }
                                        else
                                        {
                                            //start newline 
                                            float newX = hostSizeW - maxLineWidth;
                                            newAnonBlock.SetLocation(newX, floatCtx.offsetFloatTop + hostLine.CalculateLineHeight());
                                            floatCtx.lineRightOffset = newX;
                                            floatCtx.rightFloatBox = newAnonBlock;
                                            floatCtx.floatingOutOfLine = true;
                                            floatCtx.offsetFloatTop = newAnonBlock.LocalY;
                                        }
                                    }
                                    else
                                    {
                                        //out-of-line mode
                                        if (floatCtx.rightFloatBox != null)
                                        {
                                            float newX = floatCtx.rightFloatBox.LocalX - maxLineWidth;
                                            if (newX > 0)
                                            {
                                                newAnonBlock.SetLocation(newX, floatCtx.offsetFloatTop);
                                                floatCtx.lineRightOffset = newX;
                                                floatCtx.rightFloatBox = newAnonBlock;
                                                floatCtx.offsetFloatTop = newAnonBlock.LocalY;
                                            }
                                            else
                                            {  //start new line
                                                newX = hostSizeW - maxLineWidth;
                                                newAnonBlock.SetLocation(newX, floatCtx.rightFloatBox.LocalY + floatCtx.rightFloatBox.InnerContentHeight);
                                                floatCtx.lineRightOffset = newX;
                                                floatCtx.rightFloatBox = newAnonBlock;
                                                floatCtx.offsetFloatTop = newAnonBlock.LocalY + newAnonBlock.InnerContentHeight;
                                            }
                                        }
                                        else
                                        {
                                            throw new NotSupportedException();
                                        }
                                    }
                                }
                                break;
                        }
                    }
                    else
                    {
                        //go deeper  
                        //recursive *** 
                        //not new lineFormatting context
                        FlowBoxContentIntoHostLineFmtContext(lay, hostBox, b,
                                   limitLocalRight, firstRunStartX,
                                   ref hostLine, ref cx, ref floatCtx);
                    }

                    cx += rightMostSpace;
                    childNumber++;
                    //---------------------
                    cNode = cNode.Next;
                }
            }
            if (srcBox.Position == CssPosition.Relative)
            {
                //offset content relative to it 'flow' position'
                var left = CssValueParser.ConvertToPx(srcBox.Left, hostBox.VisualWidth, srcBox);
                var top = CssValueParser.ConvertToPx(srcBox.Top, hostBox.VisualWidth, srcBox);
                srcBox.SetLocation(srcBox.LocalX + left, srcBox.LocalY + top);
            }
        }