Exemplo n.º 1
0
        /**
         * <summary>Shows text.</summary>
         * <returns>Last shown character index.</returns>
         */
        public int ShowText(
            string text
            )
        {
            if (currentRow == null ||
                text == null)
            {
                return(0);
            }

            ContentScanner.GraphicsState state = baseComposer.State;
            fonts::Font font       = state.Font;
            float       fontSize   = state.FontSize;
            float       lineHeight = font.GetLineHeight(fontSize);

            TextFitter textFitter = new TextFitter(
                text,
                0,
                font,
                fontSize,
                hyphenation
                );
            int textLength = text.Length;
            int index      = 0;

            while (true)
            {
                // Beginning of current row?
                if (currentRow.Width == 0)
                {
                    // Removing leading space...
                    while (true)
                    {
                        // Did we reach the text end?
                        if (index == textLength)
                        {
                            goto endTextShowing; // NOTE: I know GOTO is evil, yet in this case it's a much cleaner solution.
                        }
                        if (text[index] != ' ')
                        {
                            break;
                        }

                        index++;
                    }
                }

                // Text height: exceeds current row's height?
                if (lineHeight > currentRow.Height)
                {
                    // Text height: exceeds block's remaining vertical space?
                    if (lineHeight > frame.Height - currentRow.Y) // Text exceeds.
                    {
                        // Terminate the current row!
                        EndRow(false);
                        goto endTextShowing; // NOTE: I know GOTO is evil, yet in this case it's a much cleaner solution.
                    }
                    else // Text doesn't exceed.
                    {
                        // Adapt current row's height!
                        currentRow.Height = lineHeight;
                    }
                }

                // Does the text fit?
                if (textFitter.Fit(
                        index,
                        frame.Width - currentRow.Width // Residual row width.
                        ))
                {
                    // Get the fitting text!
                    string textChunk         = textFitter.FittedText;
                    float  textChunkWidth    = textFitter.FittedWidth;
                    PointF textChunkLocation = new PointF(
                        (float)currentRow.Width,
                        (float)currentRow.Y
                        );

                    // Render the fitting text:
                    // - open the row object's local state!

                    /*
                     * NOTE: This device allows a fine-grained control over the row object's representation.
                     * It MUST be coupled with a closing statement on row object's end.
                     */
                    RowObject obj = new RowObject(
                        baseComposer.BeginLocalState(),
                        lineHeight,
                        textChunkWidth,
                        CountOccurrence(' ', textChunk)
                        );
                    currentRow.Objects.Add(obj);
                    currentRow.SpaceCount += obj.SpaceCount;
                    // - show the text chunk!
                    baseComposer.ShowText(
                        textChunk,
                        textChunkLocation
                        );
                    // - close the row object's local state!
                    baseComposer.End();

                    // Update ancillary parameters:
                    // - update row width!
                    currentRow.Width += textChunkWidth;
                    // - update cursor position!
                    index = textFitter.EndIndex;
                }

                // Evaluating trailing text...
                while (true)
                {
                    // Did we reach the text end?
                    if (index == textLength)
                    {
                        goto endTextShowing; // NOTE: I know GOTO is evil, yet in this case it's a much cleaner solution.
                    }
                    switch (text[index])
                    {
                    case '\r':
                        break;

                    case '\n':
                        // New paragraph!
                        index++;
                        ShowBreak();
                        goto endTrailParsing; // NOTE: I know GOTO is evil, yet in this case it's a much cleaner solution.

                    default:
                        // New row (within the same paragraph)!
                        EndRow(false); BeginRow();
                        goto endTrailParsing; // NOTE: I know GOTO is evil, yet in this case it's a much cleaner solution.
                    }

                    index++;
                }
                endTrailParsing :;
            }
            endTextShowing :;

            return(index);
        }
Exemplo n.º 2
0
        /**
         * <summary>Shows text.</summary>
         * <param name="text">Text to show.</param>
         * <param name="lineAlignment">Line alignment. It can be:
         *  <list type="bullet">
         *    <item><see cref="LineAlignmentEnum"/></item>
         *    <item><see cref="Length">: arbitrary super-/sub-script, depending on whether the value is
         *    positive or not.</item>
         *  </list>
         * </param>
         * <returns>Last shown character index.</returns>
         */
        public int ShowText(
            string text,
            object lineAlignment
            )
        {
            if (currentRow == null ||
                text == null)
            {
                return(0);
            }

            ContentScanner.GraphicsState state = baseComposer.State;
            fonts::Font font       = state.Font;
            double      fontSize   = state.FontSize;
            double      lineHeight = font.GetLineHeight(fontSize);
            double      baseLine   = font.GetAscent(fontSize);

            lineAlignment = ResolveLineAlignment(lineAlignment);

            TextFitter textFitter = new TextFitter(
                text,
                0,
                font,
                fontSize,
                hyphenation,
                hyphenationCharacter
                );
            int textLength = text.Length;
            int index      = 0;

            while (true)
            {
                if (currentRow.Width == 0) // Current row has just begun.
                {
                    // Removing leading space...
                    while (true)
                    {
                        if (index == textLength) // Text end reached.
                        {
                            goto endTextShowing;
                        }
                        else if (text[index] != ' ') // No more leading spaces.
                        {
                            break;
                        }

                        index++;
                    }
                }

                if (OperationUtils.Compare(currentRow.Y + lineHeight, frame.Height) == 1) // Text's height exceeds block's remaining vertical space.
                {
                    // Terminate the current row and exit!
                    EndRow(false);
                    goto endTextShowing;
                }

                // Does the text fit?
                if (textFitter.Fit(
                        index,
                        frame.Width - currentRow.Width, // Remaining row width.
                        currentRow.SpaceCount == 0
                        ))
                {
                    // Get the fitting text!
                    string textChunk         = textFitter.FittedText;
                    double textChunkWidth    = textFitter.FittedWidth;
                    PointF textChunkLocation = new PointF(
                        (float)currentRow.Width,
                        (float)currentRow.Y
                        );

                    // Insert the fitting text!
                    RowObject obj;
                    {
                        obj = new RowObject(
                            RowObject.TypeEnum.Text,
                            baseComposer.BeginLocalState(), // Opens the row object's local state.
                            lineHeight,
                            textChunkWidth,
                            CountOccurrence(' ', textChunk),
                            lineAlignment,
                            baseLine
                            );
                        baseComposer.ShowText(textChunk, textChunkLocation);
                        baseComposer.End(); // Closes the row object's local state.
                    }
                    AddRowObject(obj, lineAlignment);

                    index = textFitter.EndIndex;
                }

                // Evaluating trailing text...
                while (true)
                {
                    if (index == textLength) // Text end reached.
                    {
                        goto endTextShowing;
                    }

                    switch (text[index])
                    {
                    case '\r':
                        break;

                    case '\n':
                        // New paragraph!
                        index++;
                        ShowBreak();
                        goto endTrailParsing;

                    default:
                        // New row (within the same paragraph)!
                        EndRow(false);
                        BeginRow();
                        goto endTrailParsing;
                    }

                    index++;
                }
                endTrailParsing :;
            }
            endTextShowing :;
            if (index >= 0 &&
                lineAlignment.Equals(LineAlignmentEnum.BaseLine))
            {
                lastFontSize = fontSize;
            }

            return(index);
        }