/// <summary>
        /// Add characters to the line(s), and returns the last width of the characters that were laid out.
        /// </summary>
        protected virtual PDFUnit AddCharacters(string chars)
        {
            this.AssertCurrentLine();


            PDFUnit         lineheight = this.TextRenderOptions.GetLineHeight();
            int             offset     = 0;
            ZeroLineCounter zeros      = new ZeroLineCounter();

            PDFSize measured = PDFSize.Empty;
            PDFSize required = PDFSize.Empty;

            while (offset < chars.Length)
            {
                //Check that we have enough space for the next line

                PDFLayoutLine   line   = this.CurrentLine;
                PDFLayoutRegion reg    = line.Region;
                PDFUnit         availH = reg.AvailableHeight;
                PDFUnit         availW = line.AvailableWidth;

                if (availH < lineheight)
                {
                    if (this.Position.OverflowAction != OverflowAction.Clip)
                    {
                        this.DoMoveToNextRegion(lineheight);

                        if (!this.ContinueLayout)
                        {
                            return(PDFUnit.Zero);
                        }
                        else
                        {
                            line   = this.CurrentLine;
                            reg    = line.Region;
                            availW = line.AvailableWidth;
                            availH = reg.AvailableHeight;
                        }
                    }
                    else
                    {
                        availH = lineheight;
                    }
                }

                //Measure the string an get the fitted characters

                Context.PerformanceMonitor.Begin(PerformanceMonitorType.Text_Measure);

                int fitted;
                measured = this.MeasureString(availH, availW, chars, offset, out fitted);

                Context.PerformanceMonitor.End(PerformanceMonitorType.Text_Measure);

                required = new PDFSize(measured.Width, lineheight);

                if (fitted <= 0) //nothing fitted on the line
                {
                    this.AddSoftReturn(0);
                    if (!zeros.AssertIncrement(this.Context))
                    {
                        return(PDFUnit.Zero);
                    }
                }
                else if (fitted + offset == chars.Length) // everything fitted on the line
                {
                    zeros.Reset();
                    string all = chars.Substring(offset);
                    //if (offset == 0)
                    this.AddCharactersToCurrentLine(required, all);
                    //else
                    //    this.AddCharactersToCurrentLine(required, chars, offset, fitted);
                    offset += fitted;
                }
                else if (IsBrokenInWord(chars, offset, fitted) && CanSplitOnWordsOnly() && !IsEmptyLine()) //don't break on words unless we have to.
                {
                    this.AddSoftReturn(0);
                    if (!zeros.AssertIncrement(this.Context))
                    {
                        return(PDFUnit.Zero);
                    }
                }
                else //partial fit
                {
                    zeros.Reset();

                    string partial = chars.Substring(offset, fitted);
                    this.AddCharactersToCurrentLine(required, partial);
                    //this.AddCharactersToCurrentLine(required, chars, offset, fitted);
                    this.AddSoftReturn(measured.Width);
                    offset += fitted;

                    //Consume any white space as we are now on a new line.
                    //We should never get here for NoWrap as it will alywys fit all characters one one line.
                    while (offset < chars.Length && char.IsWhiteSpace(chars, offset))
                    {
                        offset++;
                    }
                }
            }
            return(required.Width);
        }
        /// <summary>
        /// Add characters to the line(s), and returns the last width of the characters that were laid out.
        /// </summary>
        protected virtual PDFUnit AddProxyCharacters(PDFTextProxyOp proxy)
        {
            this.AssertCurrentLine();


            PDFUnit         lineheight = this.TextRenderOptions.GetLineHeight();
            ZeroLineCounter zeros      = new ZeroLineCounter();

            PDFSize measured = PDFSize.Empty;
            PDFSize required = PDFSize.Empty;

            PDFLayoutLine   line = this.CurrentLine;
            PDFLayoutRegion reg  = line.Region;

            PDFUnit availH = reg.AvailableHeight;
            PDFUnit availW = line.AvailableWidth;


            if (availH < lineheight)
            {
                if (this.Position.OverflowAction != OverflowAction.Clip)
                {
                    availH = lineheight;
                }
                else
                {
                    this.DoMoveToNextRegion(lineheight);

                    if (!this.ContinueLayout)
                    {
                        return(PDFUnit.Zero);
                    }
                }
            }

            //Measure the string an get the fitted characters

            int fitted;

            this.Context.PerformanceMonitor.Begin(PerformanceMonitorType.Text_Measure);

            measured = this.MeasureString(availH, availW, proxy.Text, 0, out fitted);

            this.Context.PerformanceMonitor.End(PerformanceMonitorType.Text_Measure);

            required = new PDFSize(measured.Width, lineheight);

            if (fitted < proxy.Text.Length) //cannot split a proxy - must simply be a single run.
            {
                //try on the next line to see if we can put everything on there.
                this.AddSoftReturn(0);

                if (!zeros.AssertIncrement(this.Context))
                {
                    return(PDFUnit.Zero);
                }

                availW = this.CurrentLine.AvailableWidth;

                this.Context.PerformanceMonitor.Begin(PerformanceMonitorType.Text_Measure);

                measured = this.MeasureString(availH, availW, proxy.Text, 0, out fitted);

                this.Context.PerformanceMonitor.End(PerformanceMonitorType.Text_Measure);

                if (fitted < proxy.Text.Length) //Still cannot fit the proxy so not much we can do. Log it and return
                {
                    this.Context.TraceLog.Add(TraceLevel.Warning, LOG_CATEGORY, "The text proxy  for '" + proxy.Text + "' could not fit the characters on a single line. Overflow of proxies is not currently supported.");
                    return(measured.Width);
                }

                required = new PDFSize(measured.Width, lineheight);
            }

            // everything fitted on the line

            zeros.Reset();
            this.AddProxyToCurrentLine(required, proxy);


            return(required.Width);
        }