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