void SetupStartHitPoint(CssBoxHitChain startChain, ITextService textService) { //find global location of start point HitInfo startHit = startChain.GetLastHit(); //----------------------------- _startHitRun = null; _startHitRunCharIndex = 0; switch (startHit.hitObjectKind) { case HitObjectKind.Run: { CssRun run = (CssRun)startHit.hitObject; //------------------------------------------------------- int sel_index; int sel_offset; run.FindSelectionPoint(textService, startHit.localX, out sel_index, out sel_offset); _startHitRunCharIndex = sel_index; //modify hitpoint _startHitHostLine = (CssLineBox)startChain.GetHitInfo(startChain.Count - 2).hitObject; _startLineBeginSelectionAtPixel = (int)(run.Left + sel_offset); _startHitRun = run; } break; case HitObjectKind.LineBox: { _startHitHostLine = (CssLineBox)startHit.hitObject; _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); _startLineBeginSelectionAtPixel = 0; if (startHitLine != null) { _startHitHostLine = startHitLine; } else { //if not found? _startHitHostLine = null; } } break; default: { throw new NotSupportedException(); } } }
public HitInfo(CssRun run, int x, int y) { this.hitObject = run; this.hitObjectKind = HitObjectKind.Run; this.localX = x; this.localY = y; }
public HitInfo(CssRun run, int x, int y) { this.hitObject = run; this.hitObjectKind = HitObjectKind.Run; this.localX = x; this.localY = y; }
static void CalculateMinimumWidthAndWidestRun(CssBox box, out float maxWidth, out CssRun maxWidthRun) { //use line-base style *** float maxRunWidth = 0; CssRun foundRun = null; if (box._clientLineBoxes != null) { var lineNode = box._clientLineBoxes.First; while (lineNode != null) { //------------------------ CssLineBox line = lineNode.Value; CssRun tmpRun = line.FindMaxWidthRun(maxRunWidth); if (tmpRun != null) { maxRunWidth = tmpRun.Width; foundRun = tmpRun; } //------------------------ lineNode = lineNode.Next; } } maxWidth = maxRunWidth; maxWidthRun = foundRun; }
public static void Select(this CssLineBox lineBox, int startAtPx, int endAt, CssRun startRun, int startRunIndex, CssRun endRun, int endRunIndex) { lineBox.SelectionSegment = new SelectionSegment(startAtPx, endAt - startAtPx) { StartHitRun = startRun, StartHitCharIndex = startRunIndex, EndHitRun = endRun, EndHitCharIndex = endRunIndex }; }
// internal float CalculateLineHeight() { float maxBottom = 0; List <CssRun> myruns = _runs; int j = myruns.Count; for (int i = 0; i < j; ++i) { CssRun run = myruns[i]; //maxRight = run.Right > maxRight ? run.Right : maxRight; maxBottom = run.Bottom > maxBottom ? run.Bottom : maxBottom; } return(maxBottom); }
internal IEnumerable <CssRun> GetRunIter(CssBox box) { List <CssRun> tmpRuns = _runs; int j = tmpRuns.Count; CssRun run = null; for (int i = 0; i < j; ++i) { if ((run = tmpRuns[i]).OwnerBox == box) { yield return(run); } } }
//--------------------------------- internal CssRun FindMaxWidthRun(float minimum) { float max = minimum; CssRun maxRun = null; for (int i = _runs.Count - 1; i >= 0; --i) { CssRun r = _runs[i]; if (r.Width > max) { max = r.Width; maxRun = r; } } return(maxRun); }
static void ForEachEventListenerBubbleUp(UIEventArgs e, CssBoxHitChain hitChain, EventListenerAction listenerAction) { for (int i = hitChain.Count - 1; i >= 0; --i) { //propagate up var hitInfo = hitChain.GetHitInfo(i); IEventListener controller = null; switch (hitInfo.hitObjectKind) { default: { continue; } case HitObjectKind.Run: { CssRun run = (CssRun)hitInfo.hitObject; controller = CssBox.UnsafeGetController(run.OwnerBox) as IEventListener; } break; case HitObjectKind.CssBox: { CssBox box = (CssBox)hitInfo.hitObject; controller = CssBox.UnsafeGetController(box) as IEventListener; } break; } //--------------------- if (controller != null) { //found controller if (e.SourceHitElement == null) { e.SourceHitElement = controller; } e.CurrentContextElement = controller; e.SetLocation(hitInfo.localX, hitInfo.localY); if (listenerAction()) { return; } } } }
public void ApplyBaseline(float baseline) { //Important notes on http://www.w3.org/TR/CSS21/tables.html#height-layout //iterate from rectstrip //In a single LineBox , CssBox:RectStrip => 1:1 relation for (int i = _runs.Count - 1; i >= 0; --i) { CssRun run = _runs[i]; //adjust base line run.SetLocation(run.Left, baseline); } //if (_bottomUpBoxStrips == null) //{ // return; //} //for (int i = _bottomUpBoxStrips.Length - 1; i >= 0; --i) //{ // var rstrip = _bottomUpBoxStrips[i]; // var rstripOwnerBox = rstrip.owner; // switch (rstripOwnerBox.VerticalAlign) // { // case Css.CssVerticalAlign.Sub: // { // this.SetBaseLine(rstripOwnerBox, baseline + rstrip.Height * .2f); // } break; // case Css.CssVerticalAlign.Super: // { // this.SetBaseLine(rstripOwnerBox, baseline - rstrip.Height * .2f); // } break; // case Css.CssVerticalAlign.TextTop: // case Css.CssVerticalAlign.TextBottom: // case Css.CssVerticalAlign.Top: // case Css.CssVerticalAlign.Bottom: // case Css.CssVerticalAlign.Middle: // break; // default: // //case: baseline // this.SetBaseLine(rstripOwnerBox, baseline); // break; // } //} }
/// <summary> /// Lets the linebox add the word an its box to their lists if necessary. /// </summary> /// <param name="run"></param> internal void AddRun(CssRun run) { #if DEBUG if (this.dbugIsClosed) { throw new NotSupportedException(); } #endif //if (run is CssTextRun) //{ // CssTextRun textRun = (CssTextRun)run; // if (textRun.Text.Contains("Cell")) // { // } //} _runs.Add(run);//each word has only one owner linebox! CssRun.SetHostLine(run, this); }
// internal void ClearSelection() { if (_selectedLines != null) { for (int i = _selectedLines.Count - 1; i >= 0; --i) { _selectedLines[i].SelectionSegment = null; } _selectedLines.Clear(); } else { if (_startHitHostLine != null) { _startHitHostLine.SelectionSegment = null; } } _startHitRun = _endHitRun = null; _startHitRunCharIndex = _endHitRunCharIndex = 0; }
public void ClearSelection() { if (this.selectedLines != null) { for (int i = selectedLines.Count - 1; i >= 0; --i) { this.selectedLines[i].SelectionSegment = null; } this.selectedLines.Clear(); } else { if (this.startHitHostLine != null) { this.startHitHostLine.SelectionSegment = null; } } this.startHitRun = this.endHitRun = null; this.startHitRunCharIndex = this.endHitRunCharIndex = 0; }
public void ClearSelection() { if (this.selectedLines != null) { for (int i = selectedLines.Count - 1; i >= 0; --i) { this.selectedLines[i].SelectionSegment = null; } this.selectedLines.Clear(); } else { if (this.startHitHostLine != null) { this.startHitHostLine.SelectionSegment = null; } } this.startHitRun = this.endHitRun = null; this.startHitRunCharIndex = this.endHitRunCharIndex = 0; }
static void ForEachOnlyEventPortalBubbleUp(UIEventArgs e, CssBoxHitChain hitPointChain, EventPortalAction eventPortalAction) { //only listener that need tunnel down for (int i = hitPointChain.Count - 1; i >= 0; --i) { //propagate up var hitInfo = hitPointChain.GetHitInfo(i); IEventPortal controller = null; switch (hitInfo.hitObjectKind) { default: { continue; } case HitObjectKind.Run: { CssRun run = (CssRun)hitInfo.hitObject; controller = CssBox.UnsafeGetController(run.OwnerBox) as IEventPortal; } break; case HitObjectKind.CssBox: { CssBox box = (CssBox)hitInfo.hitObject; controller = CssBox.UnsafeGetController(box) as IEventPortal; } break; } //--------------------- if (controller != null) { e.SetLocation(hitInfo.localX, hitInfo.localY); if (eventPortalAction(controller)) { return; } } } }
/// <summary> /// Gets the minimum width that the box can be. /// *** The box can be as thin as the longest word plus padding /// </summary> /// <returns></returns> internal float CalculateMinimumWidth(int calculationEpisode) { float maxWidth = 0; float padding = 0f; if (this._lastCalculationEpisodeNum == calculationEpisode) { return(_cachedMinimumWidth); } //--------------------------------------------------- if (this.LineBoxCount > 0) { //use line box technique *** CssRun maxWidthRun = null; CalculateMinimumWidthAndWidestRun(this, out maxWidth, out maxWidthRun); //-------------------------------- if (maxWidthRun != null) { //bubble up*** var box = maxWidthRun.OwnerBox; while (box != null) { padding += (box.ActualBorderRightWidth + box.ActualPaddingRight) + (box.ActualBorderLeftWidth + box.ActualPaddingLeft); if (box == this) { break; } else { //bubble up*** box = box.ParentBox; } } } } this._lastCalculationEpisodeNum = calculationEpisode; return(_cachedMinimumWidth = maxWidth + padding); }
public float CalculateTotalBoxBaseLine(LayoutVisitor lay) { //not correct !! float maxRunHeight = 0; CssRun maxRun = null; for (int i = _runs.Count - 1; i >= 0; --i) { CssRun run = _runs[i]; if (run.Height > maxRunHeight) { maxRun = run; maxRunHeight = run.Height; } } if (maxRun != null) { //lay.GraphicsPlatform.SampleIFonts //var f = maxRun.OwnerBox.ResolvedFont; //PixelFarm.Drawing.Fonts.ActualFont ff = f.ActualFont; //return (float)(f.Height * ff.AscentInPixels / f.Height); //return fontHeight* fontAscent / lineSpacing ) } return(0); //int j = _runs.Count; //for (int i = _runs.Count - 1; i >= 0; --i) //{ // Font ownerFont = _runs[i].OwnerBox.ActualFont; // HtmlRenderer.Drawing.FontsUtils.GetDescent( //} //return 0; //float baseline = Single.MinValue; //for (int i = _bottomUpBoxStrips.Count - 1; i >= 0; --i) //{ // baseline = Math.Max(baseline, _bottomUpBoxStrips[i].Top);//?top //} //return baseline; }
public float CalculateTotalBoxBaseLine(LayoutVisitor lay) { //not correct !! float maxRunHeight = 0; CssRun maxRun = null; for (int i = this._runs.Count - 1; i >= 0; --i) { var run = this._runs[i]; if (run.Height > maxRunHeight) { maxRun = run; maxRunHeight = run.Height; } } if (maxRun != null) { var fontInfo = maxRun.OwnerBox.ActualFont.FontInfo; return(fontInfo.BaseLine); } return(0); //int j = this._runs.Count; //for (int i = this._runs.Count - 1; i >= 0; --i) //{ // Font ownerFont = _runs[i].OwnerBox.ActualFont; // HtmlRenderer.Drawing.FontsUtils.GetDescent( //} //return 0; //float baseline = Single.MinValue; //for (int i = _bottomUpBoxStrips.Count - 1; i >= 0; --i) //{ // baseline = Math.Max(baseline, _bottomUpBoxStrips[i].Top);//?top //} //return baseline; }
internal void CloseLine(LayoutVisitor lay) { #if DEBUG this.dbugIsClosed = true; #endif //============================================================= //part 1: MakeStrips() //============================================================= //*** List <CssRun> myruns = _runs; CssBox lineOwner = _ownerBox; List <PartialBoxStrip> tmpStrips = lay.GetReadyStripList(); //--------------------------------------------------------------------------- //first level Dictionary <CssBox, PartialBoxStrip> unqiueStrips = lay.GetReadyStripDic(); //location of run and strip related to its containng block float maxRight = 0; float maxBottom = 0; int j = myruns.Count; float firstRunStartAt = 0; for (int i = 0; i < j; ++i) { CssRun run = myruns[i]; if (i == 0) { firstRunStartAt = run.Left; } maxRight = run.Right > maxRight ? run.Right : maxRight; maxBottom = run.Bottom > maxBottom ? run.Bottom : maxBottom; if (run.IsSpaces) { //strip size include whitespace ? continue; } //------------- //first level data RegisterStripPart(run.OwnerBox, run.Left, run.Top, run.Right, run.Bottom, tmpStrips, unqiueStrips); } //--------------------------------------------------------------------------- //other step to upper layer, until no new strip int newStripIndex = 0; for (int numNewStripCreate = tmpStrips.Count; numNewStripCreate > 0; newStripIndex += numNewStripCreate) { numNewStripCreate = StepUpRegisterStrips(unqiueStrips, lineOwner, tmpStrips, newStripIndex); } _bottomUpBoxStrips = tmpStrips.ToArray(); lay.ReleaseStripList(tmpStrips); lay.ReleaseStripDic(unqiueStrips); //============================================================= //part 2: Calculate //============================================================= this.CacheLineHeight = maxBottom; this.CachedLineContentWidth = maxRight; this.CachedExactContentWidth = (maxRight - firstRunStartAt); if (lineOwner.VisualWidth < CachedLineContentWidth) { this.CachedLineContentWidth = this.OwnerBox.VisualWidth; } }
public static void SelectPartialToEnd(this CssLineBox lineBox, int startAtPx, CssRun startRun, int startRunIndex) { //from startAt to end of line //lineBox.SelectionStartAt = startAtPx; //lineBox.SelectionWidth = (int)lineBox.CachedLineContentWidth - startAtPx; lineBox.SelectionSegment = new SelectionSegment(startAtPx, (int)lineBox.CachedLineContentWidth - startAtPx) { StartHitRun = startRun, StartHitCharIndex = startRunIndex }; }
public static void SelectPartialFromStart(this CssLineBox lineBox, int endAtPx, CssRun endRun, int endRunIndex) { //from start of line to endAt //lineBox.SelectionStartAt = 0; //lineBox.SelectionWidth = endAtPx; lineBox.SelectionSegment = new SelectionSegment(0, endAtPx) { EndHitRun = endRun, EndHitCharIndex = endRunIndex }; }
static void CalculateMinimumWidthAndWidestRun(CssBox box, out float maxWidth, out CssRun maxWidthRun) { //use line-base style *** float maxRunWidth = 0; CssRun foundRun = null; if (box._clientLineBoxes != null) { var lineNode = box._clientLineBoxes.First; while (lineNode != null) { //------------------------ var line = lineNode.Value; var tmpRun = line.FindMaxWidthRun(maxRunWidth); if (tmpRun != null) { maxRunWidth = tmpRun.Width; foundRun = tmpRun; } //------------------------ lineNode = lineNode.Next; } } maxWidth = maxRunWidth; maxWidthRun = foundRun; }
internal void AddHit(CssRun run, int x, int y) { //position x,y relate with (0,0) of its run _hitInfoList.Add(new HitInfo(run, x, y)); }
internal void PaintRuns(PaintVisitor p) { List <CssRun> tmpRuns = _runs; int j = tmpRuns.Count; if (j < 1) { return; } //----------------------- //iterate from each words CssBox latestOwner = null; DrawBoard innerCanvas = p.InnerDrawBoard; RequestFont enterFont = innerCanvas.CurrentFont; Color enterColor = innerCanvas.CurrentTextColor; for (int i = 0; i < j; ++i) { //----------------- #if DEBUG dbugCounter.dbugRunPaintCount++; #endif //----------------- CssRun w = tmpRuns[i]; switch (w.Kind) { case CssRunKind.SolidContent: { w.OwnerBox.Paint(p, new RectangleF(w.Left, w.Top, w.Width, w.Height)); } break; case CssRunKind.BlockRun: { //Console.WriteLine("blockrun"); CssBlockRun blockRun = (CssBlockRun)w; int ox = p.CanvasOriginX; int oy = p.CanvasOriginY; //p.SetCanvasOrigin(ox + (int)(blockRun.Left + blockRun.ContentBox.LocalX), oy + (int)blockRun.Top); p.SetCanvasOrigin(ox + (int)(blockRun.Left), oy + (int)blockRun.Top); blockRun.ContentBox.Paint(p); p.SetCanvasOrigin(ox, oy); } break; case CssRunKind.Text: { if (latestOwner != w.OwnerBox) { //change latestOwner = w.OwnerBox; //change font when change owner p.InnerDrawBoard.CurrentFont = latestOwner.ResolvedFont; p.InnerDrawBoard.CurrentTextColor = latestOwner.ActualColor; } CssTextRun textRun = (CssTextRun)w; p.DrawText(CssBox.UnsafeGetTextBuffer(w.OwnerBox), textRun.TextStartIndex, textRun.TextLength, new PointF(w.Left, w.Top), new SizeF(w.Width, w.Height)); } break; default: { #if DEBUG // w.OwnerBox.dbugPaintTextWordArea(g, offset, w); #endif } break; } } innerCanvas.CurrentFont = enterFont; innerCanvas.CurrentTextColor = enterColor; }
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(); } } }
public static void SelectPartialFromStart(this CssLineBox lineBox, int endAtPx, CssRun endRun, int endRunIndex) { //from start of line to endAt lineBox.SelectionSegment = new SelectionSegment(0, endAtPx) { EndHitRun = endRun, EndHitCharIndex = endRunIndex }; }
public static void SelectPartialToEnd(this CssLineBox lineBox, int startAtPx, CssRun startRun, int startRunIndex) { //from startAt to end of line lineBox.SelectionSegment = new SelectionSegment(startAtPx, (int)lineBox.CachedLineContentWidth - startAtPx) { StartHitRun = startRun, StartHitCharIndex = startRunIndex }; }
internal static void SetHostLine(CssRun run, CssLineBox hostline) { run._hostline = hostline; }
internal void AddHit(CssRun run, int x, int y) { //position x,y relate with (0,0) of its run hitInfoList.Add(new HitInfo(run, x, y)); }
/// <summary> /// Assigns words its width and height /// </summary> /// <param name="g"></param> public virtual void MeasureRunsSize(LayoutVisitor lay) { //measure once ! if ((_boxCompactFlags & BoxFlags.LAY_RUNSIZE_MEASURE) != 0) { return; } //-------------------------------- if (this.BackgroundImageBinder != null) { //this has background if (this.BackgroundImageBinder.State == BinderState.Unload) { lay.RequestImage(this.BackgroundImageBinder, this); } } //-------------------------------- if (this.RunCount > 0) { //find word spacing float actualWordspacing = _actualWordSpacing; RequestFont actualFont = this.ResolvedFont; float fontHeight = (actualFont.AscentInPixels - actualFont.DescentInPixels + actualFont.LineGapInPixels); fontHeight += 4; //TODO: why +4 ????*** List <CssRun> tmpRuns = this.Runs; for (int i = tmpRuns.Count - 1; i >= 0; --i) { CssRun run = tmpRuns[i]; run.Height = fontHeight; //if this is newline then width =0 *** switch (run.Kind) { case CssRunKind.Text: { CssTextRun textRun = (CssTextRun)run; Size ss = lay.MeasureStringSize(CssBox.UnsafeGetTextBuffer(this), textRun.TextStartIndex, textRun.TextLength, actualFont); run.SetSize(ss.Width, ss.Height); } break; case CssRunKind.SingleSpace: { run.Width = actualWordspacing; } break; case CssRunKind.Space: { //other space size run.Width = actualWordspacing * ((CssTextRun)run).TextLength; } break; case CssRunKind.LineBreak: { run.Width = 0; } break; } } } _boxCompactFlags |= BoxFlags.LAY_RUNSIZE_MEASURE; }
internal void PaintRuns(PaintVisitor p) { List <CssRun> tmpRuns = _runs; int j = tmpRuns.Count; if (j < 1) { return; } //----------------------- //iterate from each words CssBox latestOwner = null; DrawBoard innerCanvas = p.InnerDrawBoard; RequestFont enterFont = innerCanvas.CurrentFont; Color enterColor = innerCanvas.CurrentTextColor; for (int i = 0; i < j; ++i) { //----------------- #if DEBUG dbugCounter.dbugRunPaintCount++; #endif //----------------- CssRun w = tmpRuns[i]; switch (w.Kind) { case CssRunKind.SolidContent: { #if DEBUG //System.Diagnostics.Debug.WriteLine("ox,oy=" + p.CanvasOriginX + "," + p.CanvasOriginY); //System.Diagnostics.Debug.WriteLine("clip=" + p.CurrentClipRect); #endif Rectangle currentClipRect = p.CurrentClipRect; Rectangle wRect = new Rectangle((int)w.Left, (int)w.Top, (int)w.Width, (int)w.Height); wRect.Intersect(currentClipRect); #if DEBUG //System.Diagnostics.Debug.WriteLine("empty_clip=" + (wRect.Height == 0 || wRect.Width == 0)); #endif if (wRect.Height != 0 && wRect.Width != 0) { w.OwnerBox.Paint(p, new RectangleF(w.Left, w.Top, w.Width, w.Height)); } } break; case CssRunKind.BlockRun: { //Console.WriteLine("blockrun"); CssBlockRun blockRun = (CssBlockRun)w; int ox = p.CanvasOriginX; int oy = p.CanvasOriginY; //p.SetCanvasOrigin(ox + (int)(blockRun.Left + blockRun.ContentBox.LocalX), oy + (int)blockRun.Top); p.SetCanvasOrigin(ox + (int)(blockRun.Left), oy + (int)blockRun.Top); blockRun.ContentBox.Paint(p); p.SetCanvasOrigin(ox, oy); } break; case CssRunKind.Text: { if (latestOwner != w.OwnerBox) { //change latestOwner = w.OwnerBox; //change font when change owner p.InnerDrawBoard.CurrentFont = latestOwner.ResolvedFont; p.InnerDrawBoard.CurrentTextColor = latestOwner.ActualColor; } CssTextRun textRun = (CssTextRun)w; p.DrawText(CssBox.UnsafeGetTextBuffer(w.OwnerBox), textRun.TextStartIndex, textRun.TextLength, new PointF(w.Left, w.Top), new SizeF(w.Width, w.Height)); //RenderVxFormattedString formattedStr = CssTextRun.GetCachedFormatString(textRun); //if (formattedStr == null) //{ // formattedStr = p.CreateRenderVx(CssBox.UnsafeGetTextBuffer(w.OwnerBox), // textRun.TextStartIndex, // textRun.TextLength); // CssTextRun.SetCachedFormattedString(textRun, formattedStr); //} //if (formattedStr != null) //{ // p.DrawText(formattedStr, // new PointF(w.Left, w.Top), // new SizeF(w.Width, w.Height)); //} //else //{ // p.DrawText(CssBox.UnsafeGetTextBuffer(w.OwnerBox), // textRun.TextStartIndex, // textRun.TextLength, // new PointF(w.Left, w.Top), // new SizeF(w.Width, w.Height)); //} } break; default: { #if DEBUG // w.OwnerBox.dbugPaintTextWordArea(g, offset, w); #endif } break; } } innerCanvas.CurrentFont = enterFont; innerCanvas.CurrentTextColor = enterColor; }
public 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) { var selLine = selectedLines[i]; var selSeg = selLine.SelectionSegment; switch (selSeg.Kind) { case SelectionSegmentKind.Partial: { var startRun = selSeg.StartHitRun; var 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) { var rr = startRun as CssTextRun; if (rr != null && this.startHitRunCharIndex >= 0) { var alltext = rr.Text; var sub1 = alltext.Substring(this.startHitRunCharIndex, this.endHitRunCharIndex - this.startHitRunCharIndex); stbuilder.Append(sub1); } } else { int runCount = selLine.RunCount; for (int n = 0; n < runCount; ++n) { //temp fix here! //TODO: review this for other cssrun type var rr = selLine.GetRun(n) as CssTextRun; if (rr == null) { continue; } if (rr == startRun) { var alltext = rr.Text; if (autoFirstRun) { stbuilder.Append(alltext); } else { if (this.startHitRunCharIndex >= 0) { var sub1 = alltext.Substring(this.startHitRunCharIndex); stbuilder.Append(sub1); } } } else if (rr == endHitRun) { var alltext = rr.Text; if (autoLastRun) { stbuilder.Append(alltext); } else { if (this.endHitRunCharIndex >= 0) { var sub1 = alltext.Substring(0, this.endHitRunCharIndex); stbuilder.Append(sub1); } } //stop break; } else { stbuilder.Append(rr.Text); } } } } break; default: { int runCount = selLine.RunCount; for (int n = 0; n < runCount; ++n) { var r = selLine.GetRun(n) as CssTextRun; if (r != null) { stbuilder.Append(r.Text); } } } break; } if (i < j - 1) { //if not lastline stbuilder.AppendLine(); } } }
void SetupEndHitPoint(CssBoxHitChain startChain, CssBoxHitChain endChain, IFonts 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; } }); }
public 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) { var selLine = selectedLines[i]; var selSeg = selLine.SelectionSegment; switch (selSeg.Kind) { case SelectionSegmentKind.Partial: { var startRun = selSeg.StartHitRun; var 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) { var rr = startRun as CssTextRun; if (this.startHitRunCharIndex >= 0) { var alltext = rr.Text; var sub1 = alltext.Substring(this.startHitRunCharIndex, this.endHitRunCharIndex - this.startHitRunCharIndex); stbuilder.Append(sub1); } } else { int runCount = selLine.RunCount; for (int n = 0; n < runCount; ++n) { //temp fix here! //TODO: review this for other cssrun type var rr = selLine.GetRun(n) as CssTextRun; if (rr == null) { continue; } if (rr == startRun) { var alltext = rr.Text; if (autoFirstRun) { stbuilder.Append(alltext); } else { if (this.startHitRunCharIndex >= 0) { var sub1 = alltext.Substring(this.startHitRunCharIndex); stbuilder.Append(sub1); } } } else if (rr == endHitRun) { var alltext = rr.Text; if (autoLastRun) { stbuilder.Append(alltext); } else { if (this.endHitRunCharIndex >= 0) { var sub1 = alltext.Substring(0, this.endHitRunCharIndex); stbuilder.Append(sub1); } } //stop break; } else { stbuilder.Append(rr.Text); } } } } break; default: { int runCount = selLine.RunCount; for (int n = 0; n < runCount; ++n) { var r = selLine.GetRun(n) as CssTextRun; if (r != null) { stbuilder.Append(r.Text); } } } break; } if (i < j - 1) { //if not lastline stbuilder.AppendLine(); } } }
/// <summary> /// Lets the linebox add the word an its box to their lists if necessary. /// </summary> /// <param name="run"></param> internal void AddRun(CssRun run) { #if DEBUG if (this.dbugIsClosed) { throw new NotSupportedException(); } #endif //if (run is CssTextRun) //{ // CssTextRun textRun = (CssTextRun)run; // if (textRun.Text.Contains("Cell")) // { // } //} this._runs.Add(run);//each word has only one owner linebox! CssRun.SetHostLine(run, this); }
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(); } } }
internal static void SetHostLine(CssRun run, CssLineBox hostline) { run._hostline = hostline; }
public static void Select(this CssLineBox lineBox, int startAtPx, int endAt, CssRun startRun, int startRunIndex, CssRun endRun, int endRunIndex) { lineBox.SelectionSegment = new SelectionSegment(startAtPx, endAt - startAtPx) { StartHitRun = startRun, StartHitCharIndex = startRunIndex, EndHitRun = endRun, EndHitCharIndex = endRunIndex }; }
/// <summary> /// Assigns words its width and height /// </summary> /// <param name="g"></param> public virtual void MeasureRunsSize(LayoutVisitor lay) { //measure once ! if ((this._boxCompactFlags & BoxFlags.LAY_RUNSIZE_MEASURE) != 0) { return; } //-------------------------------- if (this.BackgroundImageBinder != null) { //this has background if (this.BackgroundImageBinder.State == ImageBinderState.Unload) { lay.RequestImage(this.BackgroundImageBinder, this); } } //-------------------------------- if (this.RunCount > 0) { //find word spacing float actualWordspacing = this._actualWordSpacing; Font actualFont = this.ActualFont; var fontInfo = actualFont.FontInfo; float fontHeight = fontInfo.LineHeight; var tmpRuns = this.Runs; for (int i = tmpRuns.Count - 1; i >= 0; --i) { CssRun run = tmpRuns[i]; run.Height = fontHeight; //if this is newline then width =0 *** switch (run.Kind) { case CssRunKind.Text: { CssTextRun textRun = (CssTextRun)run; run.Width = lay.MeasureStringWidth( CssBox.UnsafeGetTextBuffer(this), textRun.TextStartIndex, textRun.TextLength, actualFont); } break; case CssRunKind.SingleSpace: { run.Width = actualWordspacing; } break; case CssRunKind.Space: { //other space size run.Width = actualWordspacing * ((CssTextRun)run).TextLength; } break; case CssRunKind.LineBreak: { run.Width = 0; } break; } } } this._boxCompactFlags |= BoxFlags.LAY_RUNSIZE_MEASURE; }
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; } }); }
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; } }); }
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); }