PushLocalClipArea() private method

push clip area relative to (0,0) of current CssBox
private PushLocalClipArea ( float w, float h ) : bool
w float
h float
return bool
Exemplo n.º 1
0
        protected virtual void PaintImp(PaintVisitor p)
        {
            //if (this.dbugMark2 == 10 || this.dbugMark2 == 12)
            //{

            //}

            Css.CssDisplay display = this.CssDisplay;
            if (display == Css.CssDisplay.TableCell &&
                this.EmptyCells == Css.CssEmptyCell.Hide &&
                this.IsSpaceOrEmpty)
            {
                return;
            }
#if DEBUG
            p.dbugEnterNewContext(this, PaintVisitor.PaintVisitorContextName.Init);
#endif

            //----------------------------------------------- 
            bool hasPrevClip = false;
            RectangleF prevClip = RectangleF.Empty;
            p.EnterNewLatePaintContext();
            //---------------------------------------------
            //if (display != Css.CssDisplay.Inline ||
            //    this.Position == Css.CssPosition.Absolute ||
            //    this.Position == Css.CssPosition.Fixed)
            if (this._renderBGAndBorder)
            {
                RectangleF bound = new RectangleF(0, 0, this.VisualWidth, this.VisualHeight);
                PaintBackground(p, bound, true, true);
                if (this.HasSomeVisibleBorder)
                {
                    p.PaintBorders(this, bound, true, true);
                }
#if DEBUG
                dbugPaint(p, bound);
#endif
            }

            //---------------------------------------------
            if (this.LineBoxCount > 0)
            {
                float viewport_top = p.ViewportTop;
                float viewport_bottom = p.ViewportBottom;
                int drawState = 0;
                var c_lineNode = this._clientLineBoxes.First;
                while (c_lineNode != null)
                {
                    CssLineBox line = c_lineNode.Value;
                    if (line.CachedLineBottom >= viewport_top &&
                        line.CachedLineTop <= viewport_bottom)
                    {
#if DEBUG
                        dbugCounter.dbugLinePaintCount++;
#endif

                        drawState = 1;//drawing in viewport area
                        int cX = p.CanvasOriginX;
                        int cy = p.CanvasOriginY;
                        p.SetCanvasOrigin(cX, cy + (int)line.CachedLineTop);
                        //1.                                 
                        line.PaintBackgroundAndBorder(p);
                        if (line.SelectionSegment != null)
                        {
                            line.SelectionSegment.PaintSelection(p, line);
                        }
                        //2.                                
                        line.PaintRuns(p);
                        //3. 
                        line.PaintDecoration(p);
#if DEBUG
                        line.dbugPaintRuns(p);
#endif

                        p.SetCanvasOrigin(cX, cy);//back
                    }
                    else if (drawState == 1)
                    {
                        //outof viewport -> break
                        break;
                    }

                    //----------------------------------------
                    c_lineNode = c_lineNode.Next;
                }
            }
            else
            {
                if (this.HasContainingBlockProperty)
                {
                    p.PushContaingBlock(this);
                    int ox = p.CanvasOriginX;
                    int oy = p.CanvasOriginY;
                    var node = this._aa_boxes.GetFirstLinkedNode();
                    while (node != null)
                    {
                        CssBox b = node.Value;
                        if (b.CssDisplay == Css.CssDisplay.None)
                        {
                            node = node.Next;
                            continue;
                        }
                        else if (b.IsOutOfFlowBox)
                        {
                            //
                            p.AddToLatePaintList(b);
                            node = node.Next;
                            continue;
                        }
                        //move to left-top of client box 
                        p.SetCanvasOrigin(ox + (int)b.LocalX, oy + (int)b.LocalY);
                        if (b.decorator != null)
                        {
                            b.decorator.Paint(b, p);
                        }

                        if (b.HasClipArea)
                        {
                            if (p.PushLocalClipArea(b.VisualWidth, b.VisualHeight))
                            {
                                b.Paint(p);
                            }
                            p.PopLocalClipArea();
                        }
                        else
                        {
                            b.Paint(p);
                        }

                        node = node.Next;
                    }
                    p.SetCanvasOrigin(ox, oy);
                    p.PopContainingBlock();
                }
                else
                {
                    //if not
                    int ox = p.CanvasOriginX;
                    int oy = p.CanvasOriginY;
                    var node = this._aa_boxes.GetFirstLinkedNode();
                    while (node != null)
                    {
                        CssBox b = node.Value;
                        if (b.CssDisplay == Css.CssDisplay.None)
                        {
                            node = node.Next;
                            continue;
                        }
                        p.SetCanvasOrigin(ox + (int)b.LocalX, oy + (int)b.LocalY);
                        b.Paint(p);
                        node = node.Next;
                    }
                    p.SetCanvasOrigin(ox, oy);
                }
            }
            //------------------------------------------
            //debug
            //var clientLeft = this.ClientLeft;
            //g.DrawRectangle(Pens.GreenYellow, 0, 0, 5, 10);
            //g.DrawRectangle(Pens.HotPink, this.ClientRight - 5, 0, 5, 10);
            //------------------------------------------   

            if (this.HasAbsoluteLayer)
            {
                p.PushContaingBlock(this);
                int ox = p.CanvasOriginX;
                int oy = p.CanvasOriginY;
                var node = this._absPosLayer.GetFirstLinkedNode();
                while (node != null)
                {
                    CssBox b = node.Value;
                    if (b.CssDisplay == Css.CssDisplay.None)
                    {
                        node = node.Next;
                        continue;
                    }
                    p.SetCanvasOrigin(ox + (int)b.LocalX, oy + (int)b.LocalY);
                    b.Paint(p);
                    node = node.Next;
                }
                p.SetCanvasOrigin(ox, oy);
                p.PopContainingBlock();
            }

            if (p.LatePaintItemCount > 0)
            {
                //late paint -> floatBox 
                Rectangle latestClipRect = p.CurrentClipRect;
                p.PopLocalClipArea(); //temp
                p.PushContaingBlock(this);
                int j = p.LatePaintItemCount;
                int ox = p.CanvasOriginX;
                int oy = p.CanvasOriginY;
                for (int i = 0; i < j; ++i)
                {
                    CssBox box = p.GetLatePaintItem(i);
                    if (box.CssDisplay == Css.CssDisplay.None)
                    {
                        continue;
                    }
                    p.SetCanvasOrigin(ox + (int)box.LocalX, oy + (int)box.LocalY);
                    box.Paint(p);
                    p.SetCanvasOrigin(ox, oy);
                }
                p.PopContainingBlock();
                p.PushLocalClipArea(latestClipRect.Width, latestClipRect.Height);//push back
            }
            p.ExitCurrentLatePaintContext();
            //must! , 
            if (hasPrevClip)
            {
                p.PopLocalClipArea();
            }

#if DEBUG
            p.dbugExitContext();
#endif
        }
Exemplo n.º 2
0
        protected override void RenderClientContent(DrawBoard d, UpdateArea updateArea)
        {
            //TODO: review here,
            if (_myHtmlVisualRoot == null)
            {
                return;
            }

            bool useBackbuffer = d.IsGpuDrawBoard;

            //useBackbuffer = false;

            //... TODO: review here, check doc update here?
            _myHtmlVisualRoot.CheckDocUpdate();

            if (useBackbuffer)
            {
                PaintVisitor painter = PaintVisitorStock.GetSharedPaintVisitor(_myHtmlVisualRoot, d);

                if (_builtInBackBuffer == null)
                {
                    _builtInBackBuffer = painter.CreateOffscreenDrawBoard(this.Width, this.Height);
                }

#if DEBUG
                painter.dbugDrawDiagonalBox(Color.Blue, this.X, this.Y, this.Width, this.Height);
#endif
                if (!_builtInBackBuffer.IsValid)
                {
                    //painter.FillRectangle(Color.Red, 0, 0, 100, 100);//debug
                    //painter.DrawText(i.ToString().ToCharArray(), 0, 1, new PointF(0, 0), new SizeF(100, 100)); //debug


                    float backupViewportW = painter.ViewportWidth;       //backup
                    float backupViewportH = painter.ViewportHeight;      //backup

                    painter.EnterNewDrawboardBuffer(_builtInBackBuffer); //*** switch to builtInBackbuffer
                    painter.SetViewportSize(this.Width, this.Height);

                    if (!_hasAccumRect)
                    {
                        _invalidateRect = new Rectangle(0, 0, Width, Height);
                    }

#if DEBUG
                    //System.Diagnostics.Debug.WriteLine("inv_rect:" + _invalidateRect + "," + painter.ToString());
#endif
                    if (painter.PushLocalClipArea(
                            _invalidateRect.Left, _invalidateRect.Top,
                            _invalidateRect.Width, _invalidateRect.Height))
                    {
#if DEBUG
                        //for debug , test clear with random color
                        //another useful technique to see latest clear area frame-by-frame => use random color
                        //painter.Clear(ColorEx.dbugGetRandomColor());

                        painter.Clear(Color.White);
#else
                        painter.Clear(Color.White);
#endif
                        _myHtmlVisualRoot.PerformPaint(painter);

                        painter.PopLocalClipArea();
                    }


                    //
                    _builtInBackBuffer.IsValid = true;
                    _hasAccumRect = false;

                    painter.ExitCurrentDrawboardBuffer();                      //*** switch back
                    painter.SetViewportSize(backupViewportW, backupViewportH); //restore viewport size
                }

                painter.DrawImage(_builtInBackBuffer.GetImage(), 0, 0, this.Width, this.Height);

                PaintVisitorStock.ReleaseSharedPaintVisitor(painter);
            }
#if DEBUG
            else if (dbugPreferSoftwareRenderer && d.IsGpuDrawBoard)
            {
                //TODO: review this again ***
                //test built-in 'shared' software rendering surface
                DrawBoard cpuDrawBoard = null;
                if ((cpuDrawBoard = d.GetCpuBlitDrawBoard()) != null)
                {
                    cpuDrawBoard.Clear(Color.White);
                    PaintVisitor painter = PaintVisitorStock.GetSharedPaintVisitor(_myHtmlVisualRoot, cpuDrawBoard);

                    painter.SetViewportSize(this.Width, this.Height);

#if DEBUG
                    painter.dbugDrawDiagonalBox(Color.Blue, this.X, this.Y, this.Width, this.Height);
#endif


                    _myHtmlVisualRoot.PerformPaint(painter);
                    PaintVisitorStock.ReleaseSharedPaintVisitor(painter);

                    //then copy from cpu to gpu
                    d.BlitFrom(cpuDrawBoard, X, Y, this.Width, this.Height, 0, 0);
                }
            }
#endif
            else
            {
                PaintVisitor painter = PaintVisitorStock.GetSharedPaintVisitor(_myHtmlVisualRoot, d);
                painter.SetViewportSize(this.Width, this.Height);
#if DEBUG
                //System.Diagnostics.Debug.WriteLine(">> 500x500");
                painter.dbugDrawDiagonalBox(Color.Blue, this.X, this.Y, this.Width, this.Height);

                //for debug , test clear with random color
                //another useful technique to see latest clear area frame-by-frame => use random color
                //painter.Clear(Color.FromArgb(255, dbugRandom.Next(0, 255), dbugRandom.Next(0, 255), dbugRandom.Next(0, 255)));
#endif

#if DEBUG
                //System.Diagnostics.Debug.WriteLine("inv_rect:" + _invalidateRect + "," + painter.ToString());
#endif
                //painter.SetClipRect(new Rectangle(0, 0, 200, 200));
                _myHtmlVisualRoot.PerformPaint(painter);
#if DEBUG
                //System.Diagnostics.Debug.WriteLine("<< 500x500");
                //painter.dbugDrawDiagonalBox(Color.Blue, this.X, this.Y, this.Width, this.Height);
#endif
                PaintVisitorStock.ReleaseSharedPaintVisitor(painter);
            }
        }
Exemplo n.º 3
0
        protected virtual void PaintImp(PaintVisitor p)
        {
            //if (this.dbugMark2 == 10 || this.dbugMark2 == 12)
            //{

            //}

            Css.CssDisplay display = this.CssDisplay;
            if (display == Css.CssDisplay.TableCell &&
                this.EmptyCells == Css.CssEmptyCell.Hide &&
                this.IsSpaceOrEmpty)
            {
                return;
            }
#if DEBUG
            p.dbugEnterNewContext(this, PaintVisitor.PaintVisitorContextName.Init);
#endif

            //-----------------------------------------------
            bool       hasPrevClip = false;
            RectangleF prevClip    = RectangleF.Empty;
            p.EnterNewLatePaintContext();
            //---------------------------------------------
            //if (display != Css.CssDisplay.Inline ||
            //    this.Position == Css.CssPosition.Absolute ||
            //    this.Position == Css.CssPosition.Fixed)
            if (this._renderBGAndBorder)
            {
                RectangleF bound = new RectangleF(0, 0, this.VisualWidth, this.VisualHeight);
                PaintBackground(p, bound, true, true);
                if (this.HasSomeVisibleBorder)
                {
                    p.PaintBorders(this, bound, true, true);
                }
#if DEBUG
                dbugPaint(p, bound);
#endif
            }

            //---------------------------------------------
            if (this.LineBoxCount > 0)
            {
                float viewport_top    = p.ViewportTop;
                float viewport_bottom = p.ViewportBottom;
                int   drawState       = 0;
                var   c_lineNode      = this._clientLineBoxes.First;
                while (c_lineNode != null)
                {
                    CssLineBox line = c_lineNode.Value;
                    if (line.CachedLineBottom >= viewport_top &&
                        line.CachedLineTop <= viewport_bottom)
                    {
#if DEBUG
                        dbugCounter.dbugLinePaintCount++;
#endif

                        drawState = 1;//drawing in viewport area
                        int cX = p.CanvasOriginX;
                        int cy = p.CanvasOriginY;
                        p.SetCanvasOrigin(cX, cy + (int)line.CachedLineTop);
                        //1.
                        line.PaintBackgroundAndBorder(p);
                        if (line.SelectionSegment != null)
                        {
                            line.SelectionSegment.PaintSelection(p, line);
                        }
                        //2.
                        line.PaintRuns(p);
                        //3.
                        line.PaintDecoration(p);
#if DEBUG
                        line.dbugPaintRuns(p);
#endif

                        p.SetCanvasOrigin(cX, cy);//back
                    }
                    else if (drawState == 1)
                    {
                        //outof viewport -> break
                        break;
                    }

                    //----------------------------------------
                    c_lineNode = c_lineNode.Next;
                }
            }
            else
            {
                if (this.HasContainingBlockProperty)
                {
                    p.PushContaingBlock(this);
                    int ox   = p.CanvasOriginX;
                    int oy   = p.CanvasOriginY;
                    var node = this._aa_boxes.GetFirstLinkedNode();
                    while (node != null)
                    {
                        CssBox b = node.Value;
                        if (b.CssDisplay == Css.CssDisplay.None)
                        {
                            node = node.Next;
                            continue;
                        }
                        else if (b.IsOutOfFlowBox)
                        {
                            //
                            p.AddToLatePaintList(b);
                            node = node.Next;
                            continue;
                        }
                        //move to left-top of client box
                        p.SetCanvasOrigin(ox + (int)b.LocalX, oy + (int)b.LocalY);
                        if (b.decorator != null)
                        {
                            b.decorator.Paint(b, p);
                        }

                        if (b.HasClipArea)
                        {
                            if (p.PushLocalClipArea(b.VisualWidth, b.VisualHeight))
                            {
                                b.Paint(p);
                            }
                            p.PopLocalClipArea();
                        }
                        else
                        {
                            b.Paint(p);
                        }

                        node = node.Next;
                    }
                    p.SetCanvasOrigin(ox, oy);
                    p.PopContainingBlock();
                }
                else
                {
                    //if not
                    int ox   = p.CanvasOriginX;
                    int oy   = p.CanvasOriginY;
                    var node = this._aa_boxes.GetFirstLinkedNode();
                    while (node != null)
                    {
                        CssBox b = node.Value;
                        if (b.CssDisplay == Css.CssDisplay.None)
                        {
                            node = node.Next;
                            continue;
                        }
                        p.SetCanvasOrigin(ox + (int)b.LocalX, oy + (int)b.LocalY);
                        b.Paint(p);
                        node = node.Next;
                    }
                    p.SetCanvasOrigin(ox, oy);
                }
            }
            //------------------------------------------
            //debug
            //var clientLeft = this.ClientLeft;
            //g.DrawRectangle(Pens.GreenYellow, 0, 0, 5, 10);
            //g.DrawRectangle(Pens.HotPink, this.ClientRight - 5, 0, 5, 10);
            //------------------------------------------

            if (this.HasAbsoluteLayer)
            {
                p.PushContaingBlock(this);
                int ox   = p.CanvasOriginX;
                int oy   = p.CanvasOriginY;
                var node = this._absPosLayer.GetFirstLinkedNode();
                while (node != null)
                {
                    CssBox b = node.Value;
                    if (b.CssDisplay == Css.CssDisplay.None)
                    {
                        node = node.Next;
                        continue;
                    }
                    p.SetCanvasOrigin(ox + (int)b.LocalX, oy + (int)b.LocalY);
                    b.Paint(p);
                    node = node.Next;
                }
                p.SetCanvasOrigin(ox, oy);
                p.PopContainingBlock();
            }

            if (p.LatePaintItemCount > 0)
            {
                //late paint -> floatBox
                Rectangle latestClipRect = p.CurrentClipRect;
                p.PopLocalClipArea(); //temp
                p.PushContaingBlock(this);
                int j  = p.LatePaintItemCount;
                int ox = p.CanvasOriginX;
                int oy = p.CanvasOriginY;
                for (int i = 0; i < j; ++i)
                {
                    CssBox box = p.GetLatePaintItem(i);
                    if (box.CssDisplay == Css.CssDisplay.None)
                    {
                        continue;
                    }
                    p.SetCanvasOrigin(ox + (int)box.LocalX, oy + (int)box.LocalY);
                    box.Paint(p);
                    p.SetCanvasOrigin(ox, oy);
                }
                p.PopContainingBlock();
                p.PushLocalClipArea(latestClipRect.Width, latestClipRect.Height);//push back
            }
            p.ExitCurrentLatePaintContext();
            //must! ,
            if (hasPrevClip)
            {
                p.PopLocalClipArea();
            }

#if DEBUG
            p.dbugExitContext();
#endif
        }
Exemplo n.º 4
0
        protected virtual void PaintImp(PaintVisitor p)
        {
#if DEBUG
            //if (__aa_dbugId == 6)
            //{

            //}
            //if (this.dbugMark2 == 10 || this.dbugMark2 == 12)
            //{
            //}
#endif


            Css.CssDisplay display = this.CssDisplay;
            //
            if (display == Css.CssDisplay.TableCell &&
                this.EmptyCells == Css.CssEmptyCell.Hide &&
                this.IsSpaceOrEmpty)
            {
                return;
            }


#if DEBUG
            p.dbugEnterNewContext(this, PaintVisitor.PaintVisitorContextName.Init);
#endif
            Color prevBgColorHint = p.CurrentSolidBackgroundColorHint;
            //-----------------------------------------------
            bool       hasPrevClip = false;
            RectangleF prevClip    = RectangleF.Empty;
            p.EnterNewLatePaintContext();
            //---------------------------------------------
            //if (display != Css.CssDisplay.Inline ||
            //    this.Position == Css.CssPosition.Absolute ||
            //    this.Position == Css.CssPosition.Fixed)
            if (_renderBGAndBorder)
            {
                RectangleF bounds = new RectangleF(0, 0, this.VisualWidth, this.VisualHeight);
                PaintBackground(p, bounds, true, true);
                if (this.HasSomeVisibleBorder)
                {
                    p.PaintBorders(this, bounds, true, true);
                }
#if DEBUG
                dbugPaint(p, bounds);
#endif
            }

            //---------------------------------------------
            if (this.LineBoxCount > 0)
            {
                float viewport_top    = p.ViewportTop;
                float viewport_bottom = p.ViewportBottom;
                int   drawState       = 0;
                var   c_lineNode      = _clientLineBoxes.First;
                while (c_lineNode != null)
                {
                    CssLineBox line = c_lineNode.Value;
                    if (line.CachedLineBottom >= viewport_top &&
                        line.CachedLineTop <= viewport_bottom)
                    {
                        Rectangle currentClipRect = p.CurrentClipRect;
                        drawState = 1;//drawing in viewport area
#if DEBUG
                        //System.Diagnostics.Debug.WriteLine("clip_rect:" + currentClipRect);
                        dbugCounter.dbugLinePaintCount++;
#endif

                        int cX    = p.CanvasOriginX;
                        int cy    = p.CanvasOriginY;
                        int newCy = cy + (int)line.CachedLineTop;

                        if (newCy <= (cy + currentClipRect.Bottom) &&
                            newCy + line.CacheLineHeight >= (cy + currentClipRect.Top))
                        {
                            p.SetCanvasOrigin(cX, newCy);
                            //1.
                            line.PaintBackgroundAndBorder(p);

                            SelectionSegment selSegment = line.SelectionSegment;
                            if (selSegment != null)
                            {
                                switch (selSegment.Kind)
                                {
                                case SelectionSegmentKind.FullLine:
                                {
                                    Color prevColor2 = p.CurrentSolidBackgroundColorHint;        //save2
                                    p.CurrentSolidBackgroundColorHint = p.CssBoxSelectionColor;

                                    selSegment.PaintSelection(p, line);

                                    line.PaintRuns(p);

                                    p.CurrentSolidBackgroundColorHint = prevColor2;         //restore2
                                }
                                break;

                                case SelectionSegmentKind.PartialBegin:
                                case SelectionSegmentKind.SingleLine:
                                case SelectionSegmentKind.PartialEnd:
                                {
                                    //TODO: review here again***
                                    //partial line

                                    //[A]
                                    line.PaintRuns(p);         //normal line
                                                               //-----

                                    //[B]
                                    //selection part with clip rect

                                    Color prevColor2 = p.CurrentSolidBackgroundColorHint;        //save2
                                    //p.CurrentSolidBackgroundColorHint = prevBgColorHint;


                                    int xpos = selSegment.BeginAtPx;
                                    int w    = selSegment.WidthPx;

                                    Rectangle clipRect = p.CurrentClipRect;
                                    p.SetClipArea(xpos, 0, w, (int)line.CacheLineHeight);
                                    selSegment.PaintSelection(p, line);

                                    p.CurrentSolidBackgroundColorHint = p.CssBoxSelectionColor;

                                    line.PaintRuns(p);
                                    p.SetClipArea(clipRect.X, clipRect.Top, clipRect.Width, clipRect.Height); //restore

                                    p.CurrentSolidBackgroundColorHint = prevColor2;                           //restore2
                                }
                                break;
                                }
                            }
                            else
                            {
                                //2.

                                line.PaintRuns(p);
                            }


                            //3.
                            line.PaintDecoration(p);
#if DEBUG
                            line.dbugPaintRuns(p);
#endif

                            p.SetCanvasOrigin(cX, cy);//back
                        }
                    }
                    else if (drawState == 1)
                    {
                        //outof viewport -> break
                        break;
                    }

                    //----------------------------------------
                    c_lineNode = c_lineNode.Next;
                }
            }
            else
            {
                if (this.HasContainingBlockProperty)
                {
                    p.PushContaingBlock(this);
                    int ox   = p.CanvasOriginX;
                    int oy   = p.CanvasOriginY;
                    var node = _aa_boxes.GetFirstLinkedNode();
                    while (node != null)
                    {
                        CssBox b = node.Value;
                        if (b.CssDisplay == Css.CssDisplay.None || b.IsAddedToAbsoluteLayer)
                        {
                            node = node.Next;
                            continue;
                        }
                        else if (b.IsOutOfFlowBox)
                        {
                            //
                            p.AddToLatePaintList(b);
                            node = node.Next;
                            continue;
                        }
                        //move to left-top of client box
                        p.SetCanvasOrigin(ox + (int)b.LocalX, oy + (int)b.LocalY);
                        if (b._decorator != null)
                        {
                            b._decorator.Paint(b, p);
                        }

                        if (b.HasClipArea)
                        {
                            if (p.PushLocalClipArea(b.VisualWidth, b.VisualHeight))
                            {
                                CssBox.Paint(b, p);
                                p.PopLocalClipArea();
                            }
                        }
                        else
                        {
                            CssBox.Paint(b, p);
                        }

                        node = node.Next;
                    }
                    p.SetCanvasOrigin(ox, oy);
                    p.PopContainingBlock();
                }
                else
                {
                    //if not
                    int ox   = p.CanvasOriginX;
                    int oy   = p.CanvasOriginY;
                    var node = _aa_boxes.GetFirstLinkedNode();
                    while (node != null)
                    {
                        CssBox b = node.Value;
                        if (b.CssDisplay == Css.CssDisplay.None || b.IsAddedToAbsoluteLayer)
                        {
                            node = node.Next;
                            continue;
                        }
                        p.SetCanvasOrigin(ox + (int)b.LocalX, oy + (int)b.LocalY);

                        CssBox.Paint(b, p);
                        node = node.Next;
                    }
                    p.SetCanvasOrigin(ox, oy);
                }
            }
            //------------------------------------------
            //debug
            //var clientLeft = this.ClientLeft;
            //g.DrawRectangle(Pens.GreenYellow, 0, 0, 5, 10);
            //g.DrawRectangle(Pens.HotPink, this.ClientRight - 5, 0, 5, 10);
            //------------------------------------------

            if (this.HasAbsoluteLayer)
            {
                p.PushContaingBlock(this);
                int ox = p.CanvasOriginX;
                int oy = p.CanvasOriginY;
                int j  = _absPosLayer.Count;
                for (int i = 0; i < j; ++i)
                {
                    CssBox b = _absPosLayer.GetBox(i);
                    if (b.CssDisplay == Css.CssDisplay.None)
                    {
                        continue;
                    }
                    p.SetCanvasOrigin(ox + (int)b.LocalX, oy + (int)b.LocalY);
                    CssBox.Paint(b, p);
                }
                //var node = _absPosLayer.GetFirstLinkedNode();
                //while (node != null)
                //{
                //    CssBox b = node.Value;
                //    if (b.CssDisplay == Css.CssDisplay.None)
                //    {
                //        node = node.Next;
                //        continue;
                //    }
                //    p.SetCanvasOrigin(ox + (int)b.LocalX, oy + (int)b.LocalY);
                //    b.Paint(p);
                //    node = node.Next;
                //}
                p.SetCanvasOrigin(ox, oy);
                p.PopContainingBlock();
            }

            if (p.LatePaintItemCount > 0)
            {
                //late paint -> floatBox
                Rectangle latestClipRect = p.CurrentClipRect;
                p.PopLocalClipArea(); //temp
                p.PushContaingBlock(this);
                int j  = p.LatePaintItemCount;
                int ox = p.CanvasOriginX;
                int oy = p.CanvasOriginY;
                for (int i = 0; i < j; ++i)
                {
                    CssBox box = p.GetLatePaintItem(i);
                    if (box.CssDisplay == Css.CssDisplay.None)
                    {
                        continue;
                    }
                    p.SetCanvasOrigin(ox + (int)box.LocalX, oy + (int)box.LocalY);
                    CssBox.Paint(box, p);
                    p.SetCanvasOrigin(ox, oy);
                }
                p.PopContainingBlock();
                p.PushLocalClipArea(latestClipRect.Width, latestClipRect.Height);//push back
            }
            p.ExitCurrentLatePaintContext();
            //must! ,
            if (hasPrevClip)
            {
                p.PopLocalClipArea();
            }

            p.CurrentSolidBackgroundColorHint = prevBgColorHint;


#if DEBUG
            p.dbugExitContext();
#endif
        }