This class is used for a run of text with the same writing system on a single line. String boxes are created and destroyed quite frequently as (for example) the paragraph layout width changes. Accordingly references to string boxes should not be held. To discourage this, for now StringBox is not a public class. A StringBox wraps an ILgRenderSegment, which does much of the actual rendering etc.
Inheritance: LeafBox
Exemple #1
0
        private void AddBoxToLine(ILgSegment seg, int ichMin, int dichLim, LgEndSegmentType est, int spaceLeftOnCurrentLine)
        {
            var boxToAdd = new StringBox(m_para.Style, seg, ichMin);

            boxToAdd.Layout(m_layoutInfo);
            m_spaceLeftOnCurrentLine = spaceLeftOnCurrentLine - boxToAdd.Width;
            m_ichRendered            = ichMin + dichLim;
            boxToAdd.Container       = m_para;
            AddBoxToLine(boxToAdd, est);
        }
Exemple #2
0
        int GetDirectionDepth(Box box, int topDepth)
        {
            StringBox sbox = box as StringBox;

            if (sbox != null)
            {
                int depth;
                sbox.Segment.get_DirectionDepth(sbox.IchMin, out depth);
                return(depth);
            }
            return(topDepth);            // non-string boxes are always upstream top-level
        }
Exemple #3
0
		private void VerifyRangeSegmentDrawing(ParaBox para, StringBox stringBox, MockSegment seg, RangeSelection range,  int top, int ydTop, int bottom)
		{
			Assert.AreEqual(stringBox.IchMin, seg.LastDrawRangeCall.IchBase);
			Assert.AreEqual(m_gm.VwGraphics, seg.LastDrawRangeCall.Graphics);
			Assert.AreEqual(range.Start.StringPosition, seg.LastDrawRangeCall.IchMin);
			Assert.AreEqual(range.End.StringPosition, seg.LastDrawRangeCall.IchLim);
			ParaTests.VerifySimpleRect(seg.LastDrawRangeCall.RcSrc, -2, top, 96, 100);
			ParaTests.VerifySimpleRect(seg.LastDrawRangeCall.RcDst, 0, -10, 120, 128);
			Assert.AreEqual(ydTop, seg.LastDrawRangeCall.YdTop);
			Assert.AreEqual(bottom, seg.LastDrawRangeCall.YdBottom);
			Assert.AreEqual(seg.LastDrawRangeCall.On, true, "Should currently always pass true to segment drawRange On argument");
			// The old Views code appears to always pass true for this argument, so we should too, until I figure out what it's
			// really supposed to be, if anything.
			Assert.AreEqual(true, seg.LastDrawRangeCall.IsLastLineOfSelection);
		}
Exemple #4
0
		/// <summary>
		/// Add something to the line. Return true if we should keep trying to add more. (That is, all of the current thing fit,
		/// and there is still room left; this routine is not responsible to determine whether there IS anything else to add.)
		/// If there is not yet anything in the line, this routine MUST add something; otherwise, it is allowed to fail,
		/// returning false without changing anything.
		/// </summary>
		private bool AddSomethingToLine()
		{
			m_currentRenderRun = m_renderRuns[m_renderRunIndex];
			Box boxToAdd = m_currentRenderRun.Box;
			if (boxToAdd != null)
			{
				// The current run works out to a single box; add it if it fits. Add it anyway if the line
				// is currently empty.
				boxToAdd.Layout(m_layoutInfo);
				if (m_currentLine.FirstBox != null && boxToAdd.Width > m_spaceLeftOnCurrentLine)
					return false;
				m_spaceLeftOnCurrentLine -= boxToAdd.Width;
				AddBoxToLine(boxToAdd, LgEndSegmentType.kestOkayBreak); // always OK to break after non-string.
				boxToAdd.Container = m_para;
				m_ichRendered = m_currentRenderRun.RenderLim;
				m_renderRunIndex++;
			}
			else
			{
				// current run is not a simple box. Make a text box out of part or all of it, or possibly also subsequent
				// runs that are not boxes and use the same renderer.
				IRenderEngine renderer = m_layoutInfo.GetRenderer(m_currentRenderRun.Ws);
				// If our text source doesn't yet know about the writing system factory, make sure it does.
				if (m_para.Source.GetWsFactory() == null)
					m_para.Source.SetWsFactory(renderer.WritingSystemFactory);
				int ichRunLim = GetLimitOfRunWithSameRenderer(renderer, m_renderRunIndex);
				ILgSegment seg;
				int dichLim, dxWidth;
				LgEndSegmentType est;
				bool mustGetSomeSeg = m_currentLine.FirstBox == null;
				var twsh = GetNextTwsh();

				renderer.FindBreakPoint(m_layoutInfo.VwGraphics, m_para.Source, null, m_ichRendered,
					ichRunLim, ichRunLim, false, mustGetSomeSeg, m_spaceLeftOnCurrentLine, (mustGetSomeSeg ? LgLineBreak.klbClipBreak : LgLineBreak.klbWordBreak),
										m_currentLine.FirstBox == null ? LgLineBreak.klbClipBreak : LgLineBreak.klbWordBreak, twsh,
										false, out seg, out dichLim, out dxWidth, out est, null);
				if (est == LgEndSegmentType.kestNothingFit && twsh != LgTrailingWsHandling.ktwshAll)
				{
					// Nothing of the one we were trying for, try for the other.
					twsh = GetNextTwsh();
					renderer.FindBreakPoint(m_layoutInfo.VwGraphics, m_para.Source, null, m_ichRendered,
						ichRunLim, ichRunLim, false, mustGetSomeSeg, m_spaceLeftOnCurrentLine, (mustGetSomeSeg ? LgLineBreak.klbClipBreak : LgLineBreak.klbWordBreak),
											m_currentLine.FirstBox == null ? LgLineBreak.klbClipBreak : LgLineBreak.klbWordBreak, twsh,
										false, out seg, out dichLim, out dxWidth, out est, null);
				}
				switch (est)
				{
					case LgEndSegmentType.kestNoMore:
					case LgEndSegmentType.kestOkayBreak:
					case LgEndSegmentType.kestMoreLines:
					case LgEndSegmentType.kestWsBreak:
					case LgEndSegmentType.kestMoreWhtsp:
						boxToAdd = new StringBox(m_para.Style, seg, m_ichRendered);
						boxToAdd.Layout(m_layoutInfo);
						m_spaceLeftOnCurrentLine -= boxToAdd.Width;
						m_ichRendered += dichLim;
						boxToAdd.Container = m_para;
						// If we get NoMore, we should also check, because it might really be a ws break at the end
						// of the run.
						if (est == LgEndSegmentType.kestNoMore && ichRunLim < m_para.Source.Length && ichRunLim > 0
							&& WsInSource(ichRunLim - 1, m_para.Source) != WsInSource(ichRunLim, m_para.Source))
						{
							// The renderer failed to detect it because not told to look further in the source,
							// but there is in fact a writing system break.
							// However, if the next character is a box, we want to treat it as a definitely good break.
							if (m_para.Source.IsThereABoxAt(ichRunLim))
								est = LgEndSegmentType.kestOkayBreak;
							else
								est = LgEndSegmentType.kestWsBreak;
						}
						AddBoxToLine(boxToAdd, est);
						m_renderRunIndex = AdvanceRenderRunIndexToIch(m_ichRendered, m_renderRunIndex);
						// We want to return true if more could be put on this line.
						// Of the cases that take this branch, NoMore means no more input at all, so we can't add any more;
						// MoreLines means this line is full. So for both of those we return false. OkayBreak allows us to try
						// to put more segments on this line, as does ws break, and moreWhtsp.
						return est == LgEndSegmentType.kestOkayBreak || est == LgEndSegmentType.kestWsBreak || est == LgEndSegmentType.kestMoreWhtsp;
					case LgEndSegmentType.kestNothingFit:
						Debug.Assert(m_currentLine.FirstBox != null, "Making segment must not return kestNothingFit if line contains nothing");
						return false;
					//case LgEndSegmentType.kestHardBreak:
					//    if()
					//    return true;
					default:
						Debug.Assert(false);
						break;
				}
			}
			return true;
		}
Exemple #5
0
		private void AddBoxToLine(ILgSegment seg, int ichMin, int dichLim, LgEndSegmentType est, int spaceLeftOnCurrentLine)
		{
			var boxToAdd = new StringBox(m_para.Style, seg, ichMin);
			boxToAdd.Layout(m_layoutInfo);
			m_spaceLeftOnCurrentLine = spaceLeftOnCurrentLine - boxToAdd.Width;
			m_ichRendered = ichMin + dichLim;
			boxToAdd.Container = m_para;
			AddBoxToLine(boxToAdd, est);
		}
		private void VerifyRangeDrawingArgs(MockSegment.DrawRangeArgs args, StringBox stringBox, int ichMin, int ichLim, int top, int ydTop, int bottom)
		{
			Assert.AreEqual(stringBox.IchMin, args.IchBase);
			Assert.AreEqual(m_gm.VwGraphics, args.Graphics);
			Assert.That(args.IchMin, Is.EqualTo(ichMin));
			Assert.That(args.IchLim, Is.EqualTo(ichLim));
			ParaTests.VerifySimpleRect(args.RcSrc, -2, top, 96, 96);
			ParaTests.VerifySimpleRect(args.RcDst, 0, -10, 96, 96);
			Assert.AreEqual(ydTop, args.YdTop);
			Assert.AreEqual(bottom, args.YdBottom);
			Assert.AreEqual(args.On, true, "Should currently always pass true to segment drawRange On argument");
			// The old Views code appears to always pass true for this argument, so we should too, until I figure out what it's
			// really supposed to be, if anything.
			Assert.AreEqual(true, args.IsLastLineOfSelection);
		}
		private void VerifyRangeSegmentQuery(ParaBox para, StringBox stringBox, FakeSegment seg, int ichMin, int ichLim, int top, int ydTop, int bottom)
		{
			var args = seg.LastPositionOfRangeArgs;
			VerifyRangeDrawingArgs(args, stringBox, ichMin, ichLim, top, ydTop, bottom);
		}
		private void VerifyRangeSegmentDrawing(ParaBox para, StringBox stringBox, FakeSegment seg, int ichMin, int ichLim, int top, int ydTop, int bottom)
		{
			var args = seg.LastDrawRangeCall;
			VerifyRangeDrawingArgs(args, stringBox, ichMin, ichLim, top, ydTop, bottom);
		}
		private void VerifySegmentDrawing(ParaBox para, StringBox third, MockSegment.DrawInsertionPointArgs drawInsertionPointArgs, int top)
		{
			Assert.AreEqual(third.IchMin, drawInsertionPointArgs.IchBase);
			Assert.AreEqual(m_gm.VwGraphics, drawInsertionPointArgs.Graphics);
			Assert.AreEqual(true, drawInsertionPointArgs.AssocPrev, "assoc prev should match IP");
			ParaTests.VerifySimpleRect(drawInsertionPointArgs.RcSrc, -2, top, 96, 100);
			ParaTests.VerifySimpleRect(drawInsertionPointArgs.RcDst, 0, 10, 120, 128);
			Assert.AreEqual(drawInsertionPointArgs.Ich, para.Source.Length);
			Assert.AreEqual(drawInsertionPointArgs.On, true, "Should currently always pass true to segment drawIP routine");
			Assert.AreEqual(drawInsertionPointArgs.DrawMode, LgIPDrawMode.kdmNormal, "all drawing modes normal till we test BIDI with Graphite");
		}
		private void VerifySegmentDrawing(ParaBox para, StringBox third, MockSegment seg3, int top)
		{
			VerifySegmentDrawing(para, third, seg3.LastDrawIpCall, top);
		}
		private void VerifySelLocation(ParaBox para, StringBox third, MockSegment.PositionsOfIpArgs positionsOfIpArgs, int top)
		{
			Assert.AreEqual(third.IchMin, positionsOfIpArgs.IchBase);
			Assert.AreEqual(m_gm.VwGraphics, positionsOfIpArgs.Graphics);
			Assert.AreEqual(true, positionsOfIpArgs.AssocPrev, "assoc prev should match IP");
			ParaTests.VerifySimpleRect(positionsOfIpArgs.RcSrc, -2, top, 96, 100);
			ParaTests.VerifySimpleRect(positionsOfIpArgs.RcDst, 0, 10, 120, 128);
			Assert.AreEqual(positionsOfIpArgs.Ich, para.Source.Length);
			Assert.AreEqual(positionsOfIpArgs.DrawMode, LgIPDrawMode.kdmNormal, "all drawing modes normal till we test BIDI with Graphite");
		}
		private void VerifySelLocation(ParaBox para, StringBox third, MockSegment seg3, int top)
		{
			VerifySelLocation(para, third, seg3.LastPosIpCall, top);
		}
Exemple #13
0
        /// <summary>
        /// Add something to the line. Return true if we should keep trying to add more. (That is, all of the current thing fit,
        /// and there is still room left; this routine is not responsible to determine whether there IS anything else to add.)
        /// If there is not yet anything in the line, this routine MUST add something; otherwise, it is allowed to fail,
        /// returning false without changing anything.
        /// </summary>
        private bool AddSomethingToLine()
        {
            m_currentRenderRun = m_renderRuns[m_renderRunIndex];
            Box boxToAdd = m_currentRenderRun.Box;

            if (boxToAdd != null)
            {
                // The current run works out to a single box; add it if it fits. Add it anyway if the line
                // is currently empty.
                boxToAdd.Layout(m_layoutInfo);
                if (m_currentLine.FirstBox != null && boxToAdd.Width > m_spaceLeftOnCurrentLine)
                {
                    return(false);
                }
                m_spaceLeftOnCurrentLine -= boxToAdd.Width;
                AddBoxToLine(boxToAdd, LgEndSegmentType.kestOkayBreak);                 // always OK to break after non-string.
                boxToAdd.Container = m_para;
                m_ichRendered      = m_currentRenderRun.RenderLim;
                m_renderRunIndex++;
            }
            else
            {
                // current run is not a simple box. Make a text box out of part or all of it, or possibly also subsequent
                // runs that are not boxes and use the same renderer.
                IRenderEngine renderer = m_layoutInfo.GetRenderer(m_currentRenderRun.Ws);
                // If our text source doesn't yet know about the writing system factory, make sure it does.
                if (m_para.Source.GetWsFactory() == null)
                {
                    m_para.Source.SetWsFactory(renderer.WritingSystemFactory);
                }
                int              ichRunLim = GetLimitOfRunWithSameRenderer(renderer, m_renderRunIndex);
                ILgSegment       seg;
                int              dichLim, dxWidth;
                LgEndSegmentType est;
                bool             mustGetSomeSeg = m_currentLine.FirstBox == null;
                var              twsh           = GetNextTwsh();

                renderer.FindBreakPoint(m_layoutInfo.VwGraphics, m_para.Source, null, m_ichRendered,
                                        ichRunLim, ichRunLim, false, mustGetSomeSeg, m_spaceLeftOnCurrentLine, (mustGetSomeSeg ? LgLineBreak.klbClipBreak : LgLineBreak.klbWordBreak),
                                        m_currentLine.FirstBox == null ? LgLineBreak.klbClipBreak : LgLineBreak.klbWordBreak, twsh,
                                        false, out seg, out dichLim, out dxWidth, out est, null);
                if (est == LgEndSegmentType.kestNothingFit && twsh != LgTrailingWsHandling.ktwshAll)
                {
                    // Nothing of the one we were trying for, try for the other.
                    twsh = GetNextTwsh();
                    renderer.FindBreakPoint(m_layoutInfo.VwGraphics, m_para.Source, null, m_ichRendered,
                                            ichRunLim, ichRunLim, false, mustGetSomeSeg, m_spaceLeftOnCurrentLine, (mustGetSomeSeg ? LgLineBreak.klbClipBreak : LgLineBreak.klbWordBreak),
                                            m_currentLine.FirstBox == null ? LgLineBreak.klbClipBreak : LgLineBreak.klbWordBreak, twsh,
                                            false, out seg, out dichLim, out dxWidth, out est, null);
                }
                switch (est)
                {
                case LgEndSegmentType.kestNoMore:
                case LgEndSegmentType.kestOkayBreak:
                case LgEndSegmentType.kestMoreLines:
                case LgEndSegmentType.kestWsBreak:
                case LgEndSegmentType.kestMoreWhtsp:
                    boxToAdd = new StringBox(m_para.Style, seg, m_ichRendered);
                    boxToAdd.Layout(m_layoutInfo);
                    m_spaceLeftOnCurrentLine -= boxToAdd.Width;
                    m_ichRendered            += dichLim;
                    boxToAdd.Container        = m_para;
                    // If we get NoMore, we should also check, because it might really be a ws break at the end
                    // of the run.
                    if (est == LgEndSegmentType.kestNoMore && ichRunLim < m_para.Source.Length && ichRunLim > 0 &&
                        WsInSource(ichRunLim - 1, m_para.Source) != WsInSource(ichRunLim, m_para.Source))
                    {
                        // The renderer failed to detect it because not told to look further in the source,
                        // but there is in fact a writing system break.
                        // However, if the next character is a box, we want to treat it as a definitely good break.
                        if (m_para.Source.IsThereABoxAt(ichRunLim))
                        {
                            est = LgEndSegmentType.kestOkayBreak;
                        }
                        else
                        {
                            est = LgEndSegmentType.kestWsBreak;
                        }
                    }
                    AddBoxToLine(boxToAdd, est);
                    m_renderRunIndex = AdvanceRenderRunIndexToIch(m_ichRendered, m_renderRunIndex);
                    // We want to return true if more could be put on this line.
                    // Of the cases that take this branch, NoMore means no more input at all, so we can't add any more;
                    // MoreLines means this line is full. So for both of those we return false. OkayBreak allows us to try
                    // to put more segments on this line, as does ws break, and moreWhtsp.
                    return(est == LgEndSegmentType.kestOkayBreak || est == LgEndSegmentType.kestWsBreak || est == LgEndSegmentType.kestMoreWhtsp);

                case LgEndSegmentType.kestNothingFit:
                    Debug.Assert(m_currentLine.FirstBox != null, "Making segment must not return kestNothingFit if line contains nothing");
                    return(false);

                //case LgEndSegmentType.kestHardBreak:
                //    if()
                //    return true;
                default:
                    Debug.Assert(false);
                    break;
                }
            }
            return(true);
        }
Exemple #14
0
		private void VerifyRangeSegmentDrawing(ParaBox para, StringBox stringBox, RangeSelection range, int top, int ydTop, int bottom)
		{
			var seg = stringBox.Segment as FakeSegment;
			Assert.AreEqual(stringBox.IchMin, seg.LastDrawRangeCall.IchBase);
			Assert.AreEqual(m_gm.VwGraphics, seg.LastDrawRangeCall.Graphics);
			int startPosition = range.Start.StringPosition;
			if (range.Start.Para != stringBox.Container)// If we're painting this string box but it isn't in the start paragraph,
				startPosition = 0; // the we paint from the start of it.
			Assert.AreEqual(startPosition, seg.LastDrawRangeCall.IchMin);
			var endPosition = range.End.StringPosition;
			if (range.End.Para != stringBox.Container) // If we're painting this string box but it isn't in the end paragraph,
				endPosition = ((ParaBox) stringBox.Container).Source.RenderText.Length; // then we paint to the end of the paragraph.
			Assert.AreEqual(endPosition, seg.LastDrawRangeCall.IchLim);
			ParaTests.VerifySimpleRect(seg.LastDrawRangeCall.RcSrc, -2, top, 96, 96);
			ParaTests.VerifySimpleRect(seg.LastDrawRangeCall.RcDst, 0, 0, 96, 96);
			Assert.AreEqual(ydTop, seg.LastDrawRangeCall.YdTop);
			Assert.AreEqual(bottom, seg.LastDrawRangeCall.YdBottom);
			Assert.AreEqual(seg.LastDrawRangeCall.On, true, "Should currently always pass true to segment drawRange On argument");
			// The old Views code appears to always pass true for this argument, so we should too, until I figure out what it's
			// really supposed to be, if anything.
			Assert.AreEqual(true, seg.LastDrawRangeCall.IsLastLineOfSelection);
		}
Exemple #15
0
		private void ClearSegmentDrawing(StringBox sbox)
		{
			var fakeSeg = (FakeSegment)sbox.Segment;
			fakeSeg.LastDrawRangeCall = null;
		}
Exemple #16
0
		void SetSelectionLocation(StringBox sbox, int left, int right)
		{
			var fakeSeg = (FakeSegment)sbox.Segment;
			fakeSeg.LeftPositionOfRangeResult = left;
			fakeSeg.RightPositionOfRangeResult = right;
		}