/**
         * <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);
        }
Beispiel #2
0
        public override ContentObject ToInlineObject(PrimitiveComposer composer)
        {
            ContentObject barcodeObject = composer.BeginLocalState();

            {
                fonts::Font font     = fonts::PdfType1Font.Load(composer.Scanner.Contents.Document, fonts::PdfType1Font.FamilyEnum.Helvetica, false, false);
                double      fontSize = (DigitGlyphWidth / font.GetWidth(code.Substring(0, 1), 1));

                // 1. Bars.
                {
                    double elementX      = DigitWidth;
                    int[]  elementWidths = GetElementWidths();

                    double guardBarIndentY = DigitHeight / 2;
                    bool   isBar           = true;
                    for (int elementIndex = 0; elementIndex < elementWidths.Length; elementIndex++)
                    {
                        double elementWidth = elementWidths[elementIndex];
                        // Dark element?

                        /*
                         * NOTE: EAN symbol elements alternate bars to spaces.
                         */
                        if (isBar)
                        {
                            composer.DrawRectangle(
                                SKRect.Create(
                                    (float)elementX,
                                    0,
                                    (float)elementWidth,
                                    (float)(BarHeight + (
                                                // Guard bar?
                                                Array.BinarySearch <int>(GuardBarIndexes, elementIndex) >= 0
                                    ? guardBarIndentY // Guard bar.
                                    : 0               // Symbol character.
                                                ))
                                    )
                                );
                        }

                        elementX += elementWidth;
                        isBar     = !isBar;
                    }
                    composer.Fill();
                }

                // 2. Digits.
                {
                    composer.SetFont(font, fontSize);
                    double digitY = BarHeight + (DigitHeight - (font.GetAscent(fontSize))) / 2;
                    // Showing the digits...
                    for (int digitIndex = 0; digitIndex < 13; digitIndex++)
                    {
                        string digit = code.Substring(digitIndex, 1);
                        double pX    = DigitGlyphXs[digitIndex]              // Digit position.
                                       - font.GetWidth(digit, fontSize) / 2; // Centering.
                                                                             // Show the current digit!
                        composer.ShowText(
                            digit,
                            new SKPoint((float)pX, (float)digitY)
                            );
                    }
                }
                composer.End();
            }
            return(barcodeObject);
        }
        public FormXObject Build(
            )
        {
            bool   isRound         = type == TypeEnum.Round;
            bool   isStriped       = type == TypeEnum.Striped;
            double textScale       = .5;
            double borderWidth     = this.borderWidth.GetValue(width);
            double doubleBorderGap = borderDoubled ? borderWidth : 0;
            double fontSize        = 10;

            fontSize *= ((width - (isStriped ? 2 : doubleBorderGap * 2 + (borderWidth * (borderDoubled ? 1.5 : 1) * 2) + width * (isRound ?  .15 : .05))) / textScale) / font.GetWidth(text, fontSize);
            float height = (float)(isRound ? width : (font.GetAscent(fontSize) * 1.2 + doubleBorderGap * 2 + (borderWidth * (borderDoubled ? 1.5 : 1) * 2)));
            SizeF size   = new SizeF(width, height);

            FormXObject appearance = new FormXObject(document, size);

            {
                PrimitiveComposer composer = new PrimitiveComposer(appearance);
                if (color != null)
                {
                    composer.SetStrokeColor(color);
                    composer.SetFillColor(color);
                }
                composer.SetTextScale(textScale);
                composer.SetFont(font, fontSize);
                composer.ShowText(text, new PointF(size.Width / 2, (float)(size.Height / 2 - font.GetDescent(fontSize) * .4)), XAlignmentEnum.Center, YAlignmentEnum.Middle, 0);

                double     borderRadius  = isRound ? 0 : this.borderRadius.GetValue((size.Width + size.Height) / 2);
                RectangleF prevBorderBox = appearance.Box;
                for (int borderStep = 0, borderStepLimit = (borderDoubled ? 2 : 1); borderStep < borderStepLimit; borderStep++)
                {
                    if (borderStep == 0)
                    {
                        composer.SetLineWidth(borderWidth);
                    }
                    else
                    {
                        composer.SetLineWidth(composer.State.LineWidth / 2);
                    }

                    float      lineWidth = (float)(borderStep > 0 ? composer.State.LineWidth / 2 : borderWidth);
                    float      marginY   = (float)(lineWidth / 2 + (borderStep > 0 ? composer.State.LineWidth + doubleBorderGap : 0));
                    float      marginX   = isStriped ? 0 : marginY;
                    RectangleF borderBox = new RectangleF(prevBorderBox.X + marginX, prevBorderBox.Y + marginY, prevBorderBox.Width - marginX * 2, prevBorderBox.Height - marginY * 2);

                    if (isRound)
                    {
                        composer.DrawEllipse(borderBox);
                    }
                    else
                    {
                        if (isStriped)
                        {
                            composer.DrawLine(new PointF(borderBox.Left, borderBox.Top), new PointF(borderBox.Right, borderBox.Top));
                            composer.DrawLine(new PointF(borderBox.Left, borderBox.Bottom), new PointF(borderBox.Right, borderBox.Bottom));
                        }
                        else
                        {
                            composer.DrawRectangle(borderBox, borderRadius * (1 - .5 * borderStep));
                        }
                    }
                    composer.Stroke();
                    prevBorderBox = borderBox;
                }
                composer.Flush();
            }
            return(appearance);
        }