Represents a line of text.
To learn more about line-boxes see CSS spec: http://www.w3.org/TR/CSS21/visuren.html
예제 #1
0
 internal HitInfo(CssLineBox lineBox, int x, int y)
 {
     this.hitObject = lineBox;
     this.hitObjectKind = HitObjectKind.LineBox;
     this.localX = x;
     this.localY = y;
 }
예제 #2
0
        Rectangle GetSelectionRectArea()
        {
            if (_selectedLines != null)
            {
                int j = _selectedLines.Count;

                if (j > 0)
                {
                    CssBox ownerCssBox = null;

                    float      fx1 = 0, fy1 = 0; //left top
                    RectangleF selArea = RectangleF.Empty;

                    for (int i = 0; i < j; ++i)
                    {
                        CssLineBox line = _selectedLines[i];
                        if (line.OwnerBox != ownerCssBox)
                        {
                            ownerCssBox = line.OwnerBox;
                            ownerCssBox.GetGlobalLocationRelativeToRoot(out fx1, out fy1);
                        }
                        if (i == 0)
                        {
                            selArea = new RectangleF(fx1,
                                                     fy1 + line.CachedLineTop,
                                                     line.CachedLineContentWidth,
                                                     line.CacheLineHeight);
                        }
                        else
                        {
                            selArea = RectangleF.Union(selArea,
                                                       new RectangleF(fx1,
                                                                      fy1 + line.CachedLineTop,
                                                                      line.CachedLineContentWidth,
                                                                      line.CacheLineHeight));
                        }
                    }
                    //if want to debug then send a big rect

                    //Console.WriteLine(new Rectangle((int)selArea.X, (int)selArea.Y, (int)selArea.Width, (int)selArea.Height).ToString());
                    //return new Rectangle(0, 0, 800, 600);
                    return(new Rectangle((int)selArea.Left, (int)selArea.Top, (int)selArea.Width, (int)selArea.Height));
                }
            }
            return(Rectangle.Empty);
        }
예제 #3
0
 public void PaintSelection(PaintVisitor p, CssLineBox line)
 {
     if (this.Kind == SelectionSegmentKind.FullLine)
     {
         p.FillRectangle(Color.LightGray,
                0,
                0,
                line.CachedLineContentWidth,
                line.CacheLineHeight);
     }
     else
     {
         p.FillRectangle(
          Color.LightGray,
          this.BeginAtPx, 0,
          this.WidthPx,
         (int)line.CacheLineHeight);
     }
 }
예제 #4
0
            void InnerWalk(CssLineBox endLineBox, VisitLineDelegate del, IEnumerable <CssLineBox> lineIter)
            {
                //recursive


                foreach (var ln in lineIter)
                {
                    this.currentVisitLineBox = ln;
                    if (ln == endLineBox)
                    {
                        del(LineCoverage.EndLine, ln, null);
                        //found endline
                        return;
                    }
                    else if (this.IsWalkTargetInCurrentLineArea())
                    {
                        int  j    = ln.RunCount;
                        bool isOK = false;
                        for (int i = 0; i < j && !isOK; ++i)
                        {
                            var run3 = ln.GetRun(i) as CssBlockRun;
                            if (run3 == null)
                            {
                                continue;
                            }

                            //recursive here
                            InnerWalk(endLineBox, del, GetLineWalkDownIter(this, run3.ContentBox));

                            if (i > 0)
                            {
                                del(LineCoverage.PartialLine, ln, ln.GetRun(i - 1));
                            }
                            isOK = true;
                            break;
                        }
                    }
                    else
                    {
                        del(LineCoverage.FullLine, ln, null);
                    }
                }
            }
예제 #5
0
 public void PaintSelection(PaintVisitor p, CssLineBox line)
 {
     if (this.Kind == SelectionSegmentKind.FullLine)
     {
         p.FillRectangle(Color.LightGray,
                         0,
                         0,
                         line.CachedLineContentWidth,
                         line.CacheLineHeight);
     }
     else
     {
         p.FillRectangle(
             Color.LightGray,
             this.BeginAtPx, 0,
             this.WidthPx,
             (int)line.CacheLineHeight);
     }
 }
예제 #6
0
        internal static void GetSplitInfo(CssBox box, CssLineBox lineBox, out bool isFirstLine, out bool isLastLine)
        {
            CssLineBox firstHostLine, lastHostLine;
            var        runList = box.Runs;

            if (runList == null)
            {
                firstHostLine = lastHostLine = null;
            }
            else
            {
                int j = runList.Count;

                firstHostLine = runList[0].HostLine;
                lastHostLine  = runList[j - 1].HostLine;
            }
            if (firstHostLine == lastHostLine)
            {
                //is on the same line
                if (lineBox == firstHostLine)
                {
                    isFirstLine = isLastLine = true;
                }
                else
                {
                    isFirstLine = isLastLine = false;
                }
            }
            else
            {
                if (firstHostLine == lineBox)
                {
                    isFirstLine = true;
                    isLastLine  = false;
                }
                else
                {
                    isFirstLine = false;
                    isLastLine  = true;
                }
            }
        }
예제 #7
0
            void InnerWalk(CssLineBox endLineBox, VisitLineDelegate del, IEnumerable <CssLineBox> lineIter)
            {
                //recursive
                foreach (CssLineBox ln in lineIter)
                {
#if DEBUG
                    //System.Diagnostics.Debug.WriteLine("pre_sel:" + ln.dbugId);
#endif
                    _currentVisitLineBox = ln;
                    if (ln == endLineBox)
                    {
                        del(LineCoverage.EndLine, ln, null);
                        //found endline
                        return;
                    }
                    else if (this.IsWalkTargetInCurrentLineArea())
                    {
                        int  j    = ln.RunCount;
                        bool isOK = false;
                        for (int i = 0; i < j && !isOK; ++i)
                        {
                            if (!(ln.GetRun(i) is CssBlockRun run3))
                            {
                                continue;
                            }
                            //recursive here
                            InnerWalk(endLineBox, del, GetLineWalkDownIter(this, run3.ContentBox));
                            if (i > 0)
                            {
                                del(LineCoverage.PartialLine, ln, ln.GetRun(i - 1));
                            }
                            isOK = true;
                            break;
                        }
                    }
                    else
                    {
                        del(LineCoverage.FullLine, ln, null);
                    }
                }
            }
예제 #8
0
        static CssLineBox FindNearestLine(CssBox startBox, int globalY, int yRange)
        {
            CssLineBox latestLine              = null;
            CssBox     latestLineBoxOwner      = null;
            float      latestLineBoxGlobalYPos = 0;

            foreach (CssLineBox lineBox in BoxHitUtils.GetDeepDownLineBoxIter(startBox))
            {
                if (lineBox.CacheLineHeight == 0)
                {
                    continue;
                }
                if (latestLineBoxOwner != lineBox.OwnerBox)
                {
                    //find global position of box
                    latestLineBoxOwner = lineBox.OwnerBox;
                    //TODO: review here , duplicate GetGlobalLocation
                    float gx, gy;
                    latestLineBoxOwner.GetGlobalLocation(out gx, out gy);
                    latestLineBoxGlobalYPos = gy;
                }

                float lineGlobalBottom = lineBox.CachedLineBottom + latestLineBoxGlobalYPos;

                if (lineGlobalBottom <= globalY)
                {
                    latestLine = lineBox;
                }
                else
                {
                    latestLine = lineBox;
                    break;
                }
            }
            return(latestLine);
        }
예제 #9
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);
            }
        }
예제 #10
0
        internal void CopyText(StringBuilder stbuilder)
        {
            //copy selected text to stbuilder
            //this version just copy a plain text
            int j = _selectedLines.Count;

            for (int i = 0; i < j; ++i)
            {
                CssLineBox       selLine = _selectedLines[i];
                SelectionSegment selSeg  = selLine.SelectionSegment;
                switch (selSeg.Kind)
                {
                case SelectionSegmentKind.Partial:
                {
                    CssRun startRun     = selSeg.StartHitRun;
                    CssRun endHitRun    = selSeg.EndHitRun;
                    bool   autoFirstRun = false;
                    bool   autoLastRun  = false;
                    if (startRun == null)
                    {
                        startRun     = selLine.GetFirstRun();
                        autoFirstRun = true;
                    }
                    if (endHitRun == null)
                    {
                        endHitRun   = selLine.GetLastRun();
                        autoLastRun = true;
                    }

                    if (startRun == endHitRun)
                    {
                        if (startRun != null && _startHitRunCharIndex >= 0)
                        {
                            startRun.WriteContent(stbuilder, _startHitRunCharIndex, _endHitRunCharIndex - _startHitRunCharIndex);

                            //string alltext = rr.Text;
                            //string sub1 = alltext.Substring(_startHitRunCharIndex, _endHitRunCharIndex - _startHitRunCharIndex);
                            //stbuilder.Append(sub1);
                        }
                    }
                    else
                    {
                        int  runCount      = selLine.RunCount;
                        bool foundStartRun = false;
                        for (int n = 0; n < runCount; ++n)
                        {
                            //temp fix here!
                            //TODO: review this for other cssrun type

                            CssRun run = selLine.GetRun(n);

                            if (run == startRun)
                            {
                                foundStartRun = true;
                                if (autoFirstRun)
                                {
                                    run.WriteContent(stbuilder);
                                }
                                else
                                {
                                    if (_startHitRunCharIndex >= 0)
                                    {
                                        run.WriteContent(stbuilder, _startHitRunCharIndex);
                                    }
                                }
                            }
                            else if (run == endHitRun)
                            {
                                if (autoLastRun)
                                {
                                    run.WriteContent(stbuilder);
                                    //stbuilder.Append(alltext);
                                }
                                else
                                {
                                    if (_endHitRunCharIndex >= 0)
                                    {
                                        run.WriteContent(stbuilder, 0, _endHitRunCharIndex);
                                        //string sub1 = alltext.Substring(0, _endHitRunCharIndex);
                                        //stbuilder.Append(sub1);
                                    }
                                }
                                //stop
                                break;
                            }
                            else
                            {
                                if (foundStartRun)
                                {
                                    run.WriteContent(stbuilder);
                                    //stbuilder.Append(rr.Text);
                                }
                            }
                        }
                    }
                }
                break;

                default:
                {
                    int runCount = selLine.RunCount;
                    for (int n = 0; n < runCount; ++n)
                    {
                        CssRun run = selLine.GetRun(n);
                        run.WriteContent(stbuilder);
                        //CssTextRun r = run as CssTextRun;
                        //if (r != null)
                        //{
                        //    stbuilder.Append(r.Text);
                        //}
                        //else
                        //{

                        //}
                    }
                }
                break;
                }

                if (i < j - 1)
                {
                    //if not lastline
                    stbuilder.AppendLine();
                }
            }
        }
예제 #11
0
            ///// walk down and up
            ///// </summary>
            ///// <param name="startLine"></param>
            ///// <returns></returns>
            //static IEnumerable<CssLineBox> GetLineWalkDownAndUpIter(LineWalkVisitor visitor, CssLineBox startLine)
            //{
            //    float sx, sy;
            //    startLine.OwnerBox.GetGlobalLocation(out sx, out sy);
            //    CssLineBox curLine = startLine;
            //    //walk up and down the tree
            //    CssLineBox nextline = curLine.NextLine;
            //    while (nextline != null)
            //    {
            //        visitor._globalY = sy + startLine.CachedLineTop;
            //        yield return nextline;
            //        nextline = nextline.NextLine;
            //    }
            //    //--------------------
            //    //no next line
            //    //then walk up  ***
            //    CssBox curBox = startLine.OwnerBox;

            //    RETRY://***
            //    CssBox level1Sibling = BoxHitUtils.GetNextSibling(curBox);
            //    while (level1Sibling != null)
            //    {
            //        level1Sibling.GetGlobalLocation(out sx, out sy);
            //        visitor._globalY = sy;
            //        //walk down
            //        foreach (CssLineBox line in GetLineWalkDownIter(visitor, level1Sibling))
            //        {
            //            yield return line;
            //        }

            //        level1Sibling = BoxHitUtils.GetNextSibling(level1Sibling);
            //    }
            //    //--------------------
            //    //other further sibling
            //    //then step to parent of lineOwner
            //    if (curBox.ParentBox != null)
            //    {
            //        //if has parent
            //        //walk up***
            //        curBox = curBox.ParentBox;
            //        goto RETRY;
            //    }
            //}



            /// walk down and up
            /// </summary>
            /// <param name="startLine"></param>
            /// <returns></returns>
            static IEnumerable <CssLineBox> GetLineWalkDownAndUpIter(LineWalkVisitor visitor, CssLineBox startLine)
            {
                PointF p = new PointF();

                startLine.OwnerBox.GetGlobalLocationRelativeToRoot(ref p);
                CssLineBox curLine = startLine;
                //walk up and down the tree
                CssLineBox nextline = curLine.NextLine;

                while (nextline != null)
                {
                    visitor._globalY = p.Y + startLine.CachedLineTop;
                    yield return(nextline);

                    nextline = nextline.NextLine;
                }
                //--------------------
                //no next line
                //then walk up  ***
                CssBox curBox = startLine.OwnerBox;

RETRY:          //***
                CssBox level1Sibling = BoxHitUtils.GetNextSibling(curBox);

                while (level1Sibling != null)
                {
                    p = new PointF();
                    level1Sibling.GetGlobalLocationRelativeToRoot(ref p);
                    visitor._globalY = p.Y;
                    //walk down
                    foreach (CssLineBox line in GetLineWalkDownIter(visitor, level1Sibling))
                    {
                        yield return(line);
                    }

                    level1Sibling = BoxHitUtils.GetNextSibling(level1Sibling);
                }
                //--------------------
                //other further sibling
                //then step to parent of lineOwner
                if (curBox.ParentBox != null)
                {
                    //if has parent
                    //walk up***
                    curBox = curBox.ParentBox;
                    goto RETRY;
                }
            }
예제 #12
0
        public static bool HitTest(CssBox box, float x, float y, CssBoxHitChain hitChain)
        {
            //--------------------------------------
            float boxHitLocalX  = x - box.LocalX;
            float boxHitLocalY  = y - box.LocalY;
            bool  isPointInArea = box.IsPointInArea(x, y);

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

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

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

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

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

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

                                HitTest(((CssBlockRun)foundRun).ContentBox, (int)(boxHitLocalX - foundRun.Left), boxHitLocalY - hostLine.CachedLineTop, hitChain);
                            }
                        }
                        //found line box
                        hitChain.PopContextBox(box);
                        return(true);
                    }
                    else if (foundSomeLine)
                    {
                        return(false);
                    }
                }
            }
            else
            {
                //iterate in child
                foreach (var childBox in box.GetChildBoxIter())
                {
                    if (HitTest(childBox, boxHitLocalX, boxHitLocalY, hitChain))
                    {
                        //recursive
                        hitChain.PopContextBox(box);
                        return(true);
                    }
                }
            }
            hitChain.PopContextBox(box);
            return(true);
        }
예제 #13
0
        void SetupEndHitPoint(CssBoxHitChain startChain, CssBoxHitChain endChain, ITextService ifonts)
        {
            //find global location of end point
            HitInfo    endHit         = endChain.GetLastHit();
            int        xposOnEndLine  = 0;
            CssLineBox endline        = null;
            int        run_sel_offset = 0;

            //find endline first
            this.endHitRunCharIndex = 0;
            this.endHitRun          = null;
            switch (endHit.hitObjectKind)
            {
            default:
            {
                throw new NotSupportedException();
            }

            case HitObjectKind.Run:
            {
                CssRun endRun = (CssRun)endHit.hitObject;
                //if (endRun.Text != null && endRun.Text.Contains("Jose"))
                //{
                //}

                int run_sel_index;
                endRun.FindSelectionPoint(ifonts,
                                          endHit.localX,
                                          out run_sel_index,
                                          out run_sel_offset);
                endline                 = endRun.HostLine;
                xposOnEndLine           = (int)(endRun.Left + run_sel_offset);
                this.endHitRunCharIndex = run_sel_index;
                this.endHitRun          = endRun;
            }
            break;

            case HitObjectKind.LineBox:
            {
                endline       = (CssLineBox)endHit.hitObject;
                xposOnEndLine = endHit.localX;
            }
            break;

            case HitObjectKind.CssBox:
            {
                CssBox hitBox = (CssBox)endHit.hitObject;
                endline       = FindNearestLine(hitBox, endChain.RootGlobalY, 5);
                xposOnEndLine = endHit.localX;
            }
            break;
            }

#if DEBUG
            if (xposOnEndLine == 0)
            {
            }
#endif

            //----------------------------------
            this.selectedLines = new List <CssLineBox>();
            if (startHitHostLine == endline)
            {
                this.selectedLines.Add(endline);
                startHitHostLine.Select(startLineBeginSelectionAtPixel, xposOnEndLine,
                                        this.startHitRun, this.startHitRunCharIndex,
                                        this.endHitRun, this.endHitRunCharIndex);
                return; //early exit here ***
            }
            //----------------------------------
            //select on different line
            LineWalkVisitor lineWalkVisitor = null;
            int             breakAtLevel;
            if (FindCommonGround(startChain, endChain, out breakAtLevel) && breakAtLevel > 0)
            {
                var hit1        = endChain.GetHitInfo(breakAtLevel).hitObject;
                var hitBlockRun = hit1 as CssBlockRun;
                //multiple select
                //1. first part
                if (hitBlockRun != null)
                {
                    startHitHostLine.Select(startLineBeginSelectionAtPixel, (int)hitBlockRun.Left,
                                            this.startHitRun, this.startHitRunCharIndex,
                                            this.endHitRun, this.endHitRunCharIndex);
                    selectedLines.Add(this.startHitHostLine);
                    lineWalkVisitor = new LineWalkVisitor(hitBlockRun);
                }
                else
                {
                    startHitHostLine.SelectPartialToEnd(startLineBeginSelectionAtPixel, this.startHitRun, this.startHitRunCharIndex);
                    selectedLines.Add(this.startHitHostLine);
                    lineWalkVisitor = new LineWalkVisitor(startHitHostLine);
                }
            }
            else
            {
                startHitHostLine.SelectPartialToEnd(startLineBeginSelectionAtPixel, this.startHitRun, this.startHitRunCharIndex);
                selectedLines.Add(this.startHitHostLine);
                lineWalkVisitor = new LineWalkVisitor(startHitHostLine);
            }

            lineWalkVisitor.SetWalkTargetPosition(endChain.RootGlobalX, endChain.RootGlobalY);
            lineWalkVisitor.Walk(endline, (lineCoverage, linebox, partialLineRun) =>
            {
                switch (lineCoverage)
                {
                case LineCoverage.EndLine:
                    {
                        //found end line
                        linebox.SelectPartialFromStart(xposOnEndLine, this.endHitRun, this.endHitRunCharIndex);
                        selectedLines.Add(linebox);
                    }
                    break;

                case LineCoverage.PartialLine:
                    {
                        linebox.SelectPartialFromStart((int)partialLineRun.Right, this.endHitRun, this.endHitRunCharIndex);
                        selectedLines.Add(linebox);
                    }
                    break;

                case LineCoverage.FullLine:
                    {
                        //check if hitpoint is in the line area
                        linebox.SelectFull();
                        selectedLines.Add(linebox);
                    }
                    break;
                }
            });
        }
예제 #14
0
 /// <summary>
 /// Applies right alignment to the text on the linebox
 /// </summary>
 /// <param name="g"></param>
 /// <param name="line"></param>
 static void ApplyRightAlignment(CssLineBox line)
 {
     if (line.RunCount == 0)
     {
         return;
     }
     CssRun lastRun = line.GetLastRun();
     float diff = line.OwnerBox.GetClientWidth() - line.GetLastRun().Right;
     if (diff > CSS_OFFSET_THRESHOLD)
     {
         foreach (CssRun word in line.GetRunIter())
         {
             word.Left += diff;
         }
     }
 }
예제 #15
0
 void SetupStartHitPoint(CssBoxHitChain startChain, IFonts ifonts)
 {
     //find global location of start point
     HitInfo startHit = startChain.GetLastHit();
     //-----------------------------
     this.startHitRun = null;
     this.startHitRunCharIndex = 0;
     switch (startHit.hitObjectKind)
     {
         case HitObjectKind.Run:
             {
                 CssRun run = (CssRun)startHit.hitObject;
                 //-------------------------------------------------------
                 int sel_index;
                 int sel_offset;
                 run.FindSelectionPoint(ifonts,
                      startHit.localX,
                      out sel_index,
                      out sel_offset);
                 this.startHitRunCharIndex = sel_index;
                 //modify hitpoint
                 this.startHitHostLine = (CssLineBox)startChain.GetHitInfo(startChain.Count - 2).hitObject;
                 this.startLineBeginSelectionAtPixel = (int)(run.Left + sel_offset);
                 this.startHitRun = run;
             }
             break;
         case HitObjectKind.LineBox:
             {
                 this.startHitHostLine = (CssLineBox)startHit.hitObject;
                 this.startLineBeginSelectionAtPixel = startHit.localX;
                 //make global            
             }
             break;
         case HitObjectKind.CssBox:
             {
                 CssBox box = (CssBox)startHit.hitObject;
                 //find first nearest line at point   
                 CssLineBox startHitLine = FindNearestLine(box, startChain.RootGlobalY, 5);
                 this.startLineBeginSelectionAtPixel = 0;
                 if (startHitLine != null)
                 {
                     this.startHitHostLine = startHitLine;
                 }
                 else
                 {
                     //if not found?
                     this.startHitHostLine = null;
                 }
             }
             break;
         default:
             {
                 throw new NotSupportedException();
             }
     }
 }
예제 #16
0
        static void ApplyJustifyAlignment(CssLineBox lineBox)
        {
            if (lineBox.IsLastLine) return;
            float indent = lineBox.IsFirstLine ? lineBox.OwnerBox.ActualTextIndent : 0f;
            float runWidthSum = 0f;
            int runCount = 0;
            float availableWidth = lineBox.OwnerBox.GetClientWidth() - indent;
            // Gather text sum
            foreach (CssRun w in lineBox.GetRunIter())
            {
                runWidthSum += w.Width;
                runCount++;
            }

            if (runCount == 0) return; //Avoid Zero division
            float spaceOfEachRun = (availableWidth - runWidthSum) / runCount; //Spacing that will be used
            float cX = lineBox.OwnerBox.GetClientLeft() + indent;
            CssRun lastRun = lineBox.GetLastRun();
            foreach (CssRun run in lineBox.GetRunIter())
            {
                run.Left = cX;
                cX = run.Right + spaceOfEachRun;
                if (run == lastRun)
                {
                    run.Left = lineBox.OwnerBox.GetClientRight() - run.Width;
                }
            }
        }
예제 #17
0
 /// <summary>
 /// Applies centered alignment to the text on the linebox
 /// </summary>
 /// <param name="g"></param>
 /// <param name="line"></param>
 static void ApplyCenterAlignment(CssLineBox line)
 {
     if (line.RunCount == 0) return;
     CssRun lastRun = line.GetLastRun();
     float diff = (line.OwnerBox.GetClientWidth() - lastRun.Right) / 2;
     if (diff > CSS_OFFSET_THRESHOLD)
     {
         foreach (CssRun word in line.GetRunIter())
         {
             word.Left += diff;
         }
         line.CachedLineContentWidth += diff;
     }
 }
예제 #18
0
 /// <summary>
 /// Applies right to left direction to words
 /// </summary>
 /// <param name="blockBox"></param>
 /// <param name="lineBox"></param>
 static void ApplyRightToLeft(CssLineBox lineBox)
 {
     if (lineBox.RunCount > 0)
     {
         float left = lineBox.GetFirstRun().Left;
         float right = lineBox.GetLastRun().Right;
         foreach (CssRun run in lineBox.GetRunIter())
         {
             float diff = run.Left - left;
             float w_right = right - diff;
             run.Left = w_right - run.Width;
         }
     }
 }
예제 #19
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));
     //---------------------------------------------  
 }
예제 #20
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);
        }
예제 #21
0
 internal static void GetSplitInfo(CssBox box, CssLineBox lineBox, out bool isFirstLine, out bool isLastLine)
 {
     CssLineBox firstHostLine, lastHostLine;
     var runList = box.Runs;
     if (runList == null)
     {
         firstHostLine = lastHostLine = null;
     }
     else
     {
         int j = runList.Count;
         firstHostLine = runList[0].HostLine;
         lastHostLine = runList[j - 1].HostLine;
     }
     if (firstHostLine == lastHostLine)
     {
         //is on the same line 
         if (lineBox == firstHostLine)
         {
             isFirstLine = isLastLine = true;
         }
         else
         {
             isFirstLine = isLastLine = false;
         }
     }
     else
     {
         if (firstHostLine == lineBox)
         {
             isFirstLine = true;
             isLastLine = false;
         }
         else
         {
             isFirstLine = false;
             isLastLine = true;
         }
     }
 }
예제 #22
0
 public LineWalkVisitor(CssLineBox startLineBox)
 {
     this.startLineBox = startLineBox;
     float endElemX = 0, endElemY = 0;
     startLineBox.OwnerBox.GetGlobalLocation(out endElemX, out endElemY);
     this.globalX = endElemX;
     this.globalY = endElemY + startLineBox.CachedLineTop;
 }
예제 #23
0
 internal static CssRun GetCssRunOnLocation(CssLineBox lineBox, int x, int y)
 {
     foreach (CssRun word in lineBox.GetRunIter())
     {
         // add word spacing to word width so sentance won't have hols in it when moving the mouse
         var rect = word.Rectangle;
         //rect.Width += word.OwnerBox.ActualWordSpacing;
         if (rect.Contains(x, y))
         {
             return word;
         }
     }
     return null;
 }
예제 #24
0
 public void Walk(CssLineBox endLineBox, VisitLineDelegate del)
 {
     //2 cases :
     //1. start with BlockRun 
     //2. start with LineBox 
     InnerWalk(endLineBox,
               del,
               (startBlockRun != null) ?
                         GetLineWalkDownIter(this, startBlockRun.ContentBox) :
                         GetLineWalkDownAndUpIter(this, startLineBox));
 }
예제 #25
0
        void SetupStartHitPoint(CssBoxHitChain startChain, IFonts ifonts)
        {
            //find global location of start point
            HitInfo startHit = startChain.GetLastHit();

            //-----------------------------
            this.startHitRun          = null;
            this.startHitRunCharIndex = 0;

            switch (startHit.hitObjectKind)
            {
            case HitObjectKind.Run:
            {
                CssRun run = (CssRun)startHit.hitObject;
                //-------------------------------------------------------
                int sel_index;
                int sel_offset;

                run.FindSelectionPoint(ifonts,
                                       startHit.localX,
                                       out sel_index,
                                       out sel_offset);

                this.startHitRunCharIndex = sel_index;

                //modify hitpoint
                this.startHitHostLine = (CssLineBox)startChain.GetHitInfo(startChain.Count - 2).hitObject;
                this.startLineBeginSelectionAtPixel = (int)(run.Left + sel_offset);
                this.startHitRun = run;
            } break;

            case HitObjectKind.LineBox:
            {
                this.startHitHostLine = (CssLineBox)startHit.hitObject;
                this.startLineBeginSelectionAtPixel = startHit.localX;
                //make global
            } break;

            case HitObjectKind.CssBox:
            {
                CssBox box = (CssBox)startHit.hitObject;
                //find first nearest line at point
                CssLineBox startHitLine = FindNearestLine(box, startChain.RootGlobalY, 5);

                this.startLineBeginSelectionAtPixel = 0;
                if (startHitLine != null)
                {
                    this.startHitHostLine = startHitLine;
                }
                else
                {
                    //if not found?
                    this.startHitHostLine = null;
                }
            } break;

            default:
            {
                throw new NotSupportedException();
            }
            }
        }
예제 #26
0
            void InnerWalk(CssLineBox endLineBox, VisitLineDelegate del, IEnumerable<CssLineBox> lineIter)
            {
                //recursive


                foreach (var ln in lineIter)
                {
                    this.currentVisitLineBox = ln;
                    if (ln == endLineBox)
                    {
                        del(LineCoverage.EndLine, ln, null);
                        //found endline 
                        return;
                    }
                    else if (this.IsWalkTargetInCurrentLineArea())
                    {
                        int j = ln.RunCount;
                        bool isOK = false;
                        for (int i = 0; i < j && !isOK; ++i)
                        {
                            var run3 = ln.GetRun(i) as CssBlockRun;
                            if (run3 == null) continue;
                            //recursive here 
                            InnerWalk(endLineBox, del, GetLineWalkDownIter(this, run3.ContentBox));
                            if (i > 0)
                            {
                                del(LineCoverage.PartialLine, ln, ln.GetRun(i - 1));
                            }
                            isOK = true;
                            break;
                        }
                    }
                    else
                    {
                        del(LineCoverage.FullLine, ln, null);
                    }
                }
            }
예제 #27
0
 internal void AddHit(CssLineBox lineBox, int x, int y)
 {
     //position x,y relate with (0,0) of its linebox
     hitInfoList.Add(new HitInfo(lineBox, x, y));
 }
예제 #28
0
            /// walk down and up
            /// </summary>
            /// <param name="startLine"></param>
            /// <returns></returns>
            static IEnumerable<CssLineBox> GetLineWalkDownAndUpIter(LineWalkVisitor visitor, CssLineBox startLine)
            {
                float sx, sy;
                startLine.OwnerBox.GetGlobalLocation(out sx, out sy);
                CssLineBox curLine = startLine;
                //walk up and down the tree
                CssLineBox nextline = curLine.NextLine;
                while (nextline != null)
                {
                    visitor.globalY = sy + startLine.CachedLineTop;
                    yield return nextline;
                    nextline = nextline.NextLine;
                }
                //--------------------
                //no next line 
                //then walk up  ***
                CssBox curBox = startLine.OwnerBox;
            RETRY:
                CssBox level1Sibling = BoxHitUtils.GetNextSibling(curBox);
                while (level1Sibling != null)
                {
                    level1Sibling.GetGlobalLocation(out sx, out sy);
                    visitor.globalY = sy;
                    //walk down
                    foreach (var line in GetLineWalkDownIter(visitor, level1Sibling))
                    {
                        yield return line;
                    }

                    level1Sibling = BoxHitUtils.GetNextSibling(level1Sibling);
                }
                //--------------------
                //other further sibling
                //then step to parent of lineOwner
                if (curBox.ParentBox != null)
                {
                    //if has parent    
                    //walk up***
                    curBox = curBox.ParentBox;
                    goto RETRY;
                }
            }
예제 #29
0
            /// walk down and up
            /// </summary>
            /// <param name="startLine"></param>
            /// <returns></returns>
            static IEnumerable <CssLineBox> GetLineWalkDownAndUpIter(LineWalkVisitor visitor, CssLineBox startLine)
            {
                float sx, sy;

                startLine.OwnerBox.GetGlobalLocation(out sx, out sy);
                CssLineBox curLine = startLine;
                //walk up and down the tree
                CssLineBox nextline = curLine.NextLine;

                while (nextline != null)
                {
                    visitor.globalY = sy + startLine.CachedLineTop;
                    yield return(nextline);

                    nextline = nextline.NextLine;
                }
                //--------------------
                //no next line
                //then walk up  ***
                CssBox curBox = startLine.OwnerBox;

RETRY:
                CssBox level1Sibling = BoxHitUtils.GetNextSibling(curBox);

                while (level1Sibling != null)
                {
                    level1Sibling.GetGlobalLocation(out sx, out sy);
                    visitor.globalY = sy;
                    //walk down
                    foreach (var line in GetLineWalkDownIter(visitor, level1Sibling))
                    {
                        yield return(line);
                    }

                    level1Sibling = BoxHitUtils.GetNextSibling(level1Sibling);
                }
                //--------------------
                //other further sibling
                //then step to parent of lineOwner
                if (curBox.ParentBox != null)
                {
                    //if has parent
                    //walk up***
                    curBox = curBox.ParentBox;
                    goto RETRY;
                }
            }
예제 #30
0
 internal void AddHit(CssLineBox lineBox, int x, int y)
 {
     //position x,y relate with (0,0) of its linebox
     _hitInfoList.Add(new HitInfo(lineBox, x, y));
 }
예제 #31
0
        void SetupEndHitPoint(CssBoxHitChain startChain, CssBoxHitChain endChain, ITextService textService)
        {
            //find global location of end point
            HitInfo    endHit        = endChain.GetLastHit();
            int        xposOnEndLine = 0;
            CssLineBox endline       = null;

            //find endline first
            _endHitRunCharIndex = 0;
            _endHitRun          = null;
            switch (endHit.hitObjectKind)
            {
            default:
            {
                throw new NotSupportedException();
            }

            case HitObjectKind.Run:
            {
                CssRun endRun = (CssRun)endHit.hitObject;
#if DEBUG
                //if (endRun.Text != null && endRun.Text.Contains("Jose"))
                //{
                //}
                if (endHit.localX > 23)
                {
                }
                System.Diagnostics.Debug.WriteLine(endHit.localX);
#endif
                endRun.FindSelectionPoint(textService,
                                          endHit.localX,
                                          out int run_sel_index,
                                          out int run_sel_offset);
                endline             = endRun.HostLine;
                xposOnEndLine       = (int)(endRun.Left + run_sel_offset);
                _endHitRunCharIndex = run_sel_index;

#if DEBUG
                System.Diagnostics.Debug.WriteLine(_endHitRunCharIndex);
#endif
                _endHitRun = endRun;
            }
            break;

            case HitObjectKind.LineBox:
            {
                endline       = (CssLineBox)endHit.hitObject;
                xposOnEndLine = endHit.localX;
            }
            break;

            case HitObjectKind.CssBox:
            {
                CssBox hitBox = (CssBox)endHit.hitObject;
                endline       = FindNearestLine(hitBox, endChain.RootGlobalY, 5);
                xposOnEndLine = endHit.localX;
            }
            break;
            }

#if DEBUG
            if (xposOnEndLine == 0)
            {
            }
#endif

            //----------------------------------
            _selectedLines = new List <CssLineBox>();
            if (_startHitHostLine == endline)
            {
                _selectedLines.Add(endline);
                _startHitHostLine.Select(_startLineBeginSelectionAtPixel, xposOnEndLine,
                                         _startHitRun, _startHitRunCharIndex,
                                         _endHitRun, _endHitRunCharIndex);
                return; //early exit here ***
            }
            //----------------------------------
            //select on different line
            LineWalkVisitor lineWalkVisitor = null;

            if (FindCommonGround(startChain, endChain, out int breakAtLevel) && breakAtLevel > 0)
            {
                CssBlockRun hitBlockRun = endChain.GetHitInfo(breakAtLevel).hitObject as CssBlockRun;
                //multiple select
                //1. first part
                if (hitBlockRun != null)
                {
                    _startHitHostLine.Select(_startLineBeginSelectionAtPixel, (int)hitBlockRun.Left,
                                             _startHitRun, _startHitRunCharIndex,
                                             _endHitRun, _endHitRunCharIndex);
                    _selectedLines.Add(_startHitHostLine);
                    lineWalkVisitor = new LineWalkVisitor(hitBlockRun);
                }
                else
                {
                    _startHitHostLine.SelectPartialToEnd(_startLineBeginSelectionAtPixel, _startHitRun, _startHitRunCharIndex);
                    _selectedLines.Add(_startHitHostLine);
                    lineWalkVisitor = new LineWalkVisitor(_startHitHostLine);
                }
            }
            else
            {
                _startHitHostLine.SelectPartialToEnd(_startLineBeginSelectionAtPixel, _startHitRun, _startHitRunCharIndex);
                _selectedLines.Add(_startHitHostLine);
                lineWalkVisitor = new LineWalkVisitor(_startHitHostLine);
            }

            lineWalkVisitor.SetWalkTargetPosition(endChain.RootGlobalX, endChain.RootGlobalY);

#if DEBUG
            int dbugExpectedId = 1;
#endif
            lineWalkVisitor.Walk(endline, (lineCoverage, linebox, partialLineRun) =>
            {
#if DEBUG
                //System.Diagnostics.Debug.WriteLine("sel:" + linebox.dbugId);
                if (dbugExpectedId != linebox.dbugId)
                {
                }
                dbugExpectedId++;
#endif
                switch (lineCoverage)
                {
                case LineCoverage.EndLine:
                    {
                        //found end line
                        linebox.SelectPartialFromStart(xposOnEndLine, _endHitRun, _endHitRunCharIndex);
                        _selectedLines.Add(linebox);
                    }
                    break;

                case LineCoverage.PartialLine:
                    {
                        linebox.SelectPartialFromStart((int)partialLineRun.Right, _endHitRun, _endHitRunCharIndex);
                        _selectedLines.Add(linebox);
                    }
                    break;

                case LineCoverage.FullLine:
                    {
                        //check if hitpoint is in the line area
                        linebox.SelectFull();
                        _selectedLines.Add(linebox);
                    }
                    break;
                }
            });
        }
예제 #32
0
        public static bool HitTest(CssBox box, float x, float y, CssBoxHitChain hitChain)
        {
#if DEBUG
            //if (box.ViewportY != 0 && hitChain.debugEventPhase == CssBoxHitChain.dbugEventPhase.MouseDown)
            //{
            //}
#endif
            //--------------------------------------
            bool  isPointInArea = box.IsPointInArea(x, y);
            float boxHitLocalX  = x - box.LocalX; //**
            float boxHitLocalY  = y - box.LocalY; //**
            //----------------------------------------------------------------------
            if (isPointInArea)
            {
                hitChain.AddHit(box, (int)boxHitLocalX, (int)boxHitLocalY);
            }

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


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

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


                        CssRun foundRun = BoxHitUtils.GetCssRunOnLocation(lineBox, (int)boxHitLocalX, (int)lineBoxLocalY);
                        //CssRun foundRun = BoxHitUtils.GetCssRunOnLocation(lineBox, (int)x, (int)y);
                        if (foundRun != null)
                        {
                            //3.
                            hitChain.AddHit(foundRun, (int)(boxHitLocalX - foundRun.Left), (int)lineBoxLocalY);
                            //4. go deeper for block run
                            if (foundRun.Kind == CssRunKind.BlockRun)
                            {
                                CssBlockRun blockRun = (CssBlockRun)foundRun;
                                CssLineBox  hostLine = blockRun.HostLine;
                                //adjust with hostline
                                HitTest(blockRun.ContentBox,
                                        (int)(boxHitLocalX + blockRun.ContentBox.LocalX - foundRun.Left),
                                        (int)(boxHitLocalY - hostLine.CachedLineTop),
                                        hitChain);
                            }
                        }
                        //found line box
                        hitChain.PopContextBox(box);
                        return(true);
                    }
                    else if (foundSomeLine)
                    {
                        return(false);
                    }
                }
            }
            else
            {
                //iterate in child
                //foreach (var childBox in box.GetChildBoxIter())
                foreach (CssBox childBox in box.GetChildBoxBackwardIter())
                {
                    if (HitTest(childBox, boxHitLocalX, boxHitLocalY, hitChain))
                    {
                        //recursive
                        hitChain.PopContextBox(box);
                        return(true);
                    }
                }
            }
            hitChain.PopContextBox(box);
            return(true);
        }
예제 #33
0
 public static void SelectFull(this CssLineBox lineBox)
 {
     //full line selection
     lineBox.SelectionSegment = SelectionSegment.FullLine;
 }
예제 #34
0
 internal void AddLineBox(CssLineBox linebox)
 {
     linebox.linkedNode = this._clientLineBoxes.AddLast(linebox);
 }
예제 #35
0
 internal static void SetHostLine(CssRun run, CssLineBox hostline)
 {
     run._hostline = hostline;
 }
예제 #36
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;
            }
        }
예제 #37
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
        }
예제 #38
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
        }
예제 #39
0
 internal void AddLineBox(CssLineBox linebox)
 {
     linebox.linkedNode = _clientLineBoxes.AddLast(linebox);
 }
예제 #40
0
 internal static void SetHostLine(CssRun run, CssLineBox hostline)
 {
     run._hostline = hostline;
 }