Пример #1
0
        /// <summary>Gets a text line for the specified width.</summary>
        /// <param name="sText">Text</param>
        /// <param name="rWidthMax">Width</param>
        /// <param name="iStart">Start position in sText</param>
        /// <param name="textSplitMode">Text split mode</param>
        /// <returns>Line of text</returns>
        internal String sGetTextLine(String sText, Double rWidthMax, ref Int32 iStart, TextSplitMode textSplitMode)
        {
            if (iStart > sText.Length)
            {
                throw new ReportException("start position out of range");
            }
            if (iStart == sText.Length)
            {
                iStart++;
                return("");
            }
            Int32 iStartCopy = iStart;

            StringBuilder sb            = new StringBuilder(120);
            Double        rWidth        = 0;
            Int32         iPos          = iStart;
            Int32         iResultLength = 0;
            LastChar      lastChar      = LastChar.Space;

            while (true)
            {
                Char c = sText[iPos];
                iPos++;
                Double          rWidthChar      = rGetRawWidth(c);
                UnicodeCategory unicodeCategory = Char.GetUnicodeCategory(c);
                switch (unicodeCategory)
                {
                case UnicodeCategory.Control: { // control character
                    if (c == '\n')
                    {
                        goto case UnicodeCategory.LineSeparator;
                    }
                    if (lastChar != LastChar.Space)
                    {
                        iResultLength = sb.Length;
                        lastChar      = LastChar.Space;
                    }
                    iStart = iPos;
                    break;
                }

                case UnicodeCategory.LineSeparator:
                case UnicodeCategory.ParagraphSeparator: {
                    iResultLength = sb.Length;
                    iStart        = iPos;
                    goto EndLoop;
                }

                case UnicodeCategory.ConnectorPunctuation: // connects two characters
                case UnicodeCategory.EnclosingMark:        // nonspacing combining character that surrounds all previous characters up to and including a base character
                case UnicodeCategory.Format:               // not normally rendered but affects the layout of text or the operation of text processes
                case UnicodeCategory.ModifierLetter:       // free-standing spacing character that indicates modifications of a preceding letter
                case UnicodeCategory.ModifierSymbol:       // indicates modifications of surrounding characters
                case UnicodeCategory.NonSpacingMark:       // indicates modifications of a base character
                case UnicodeCategory.PrivateUse:           // private-use character with unicode value in the range U+E000 through U+F8FF
                case UnicodeCategory.SpacingCombiningMark: // indicates modifications of a base character and affects the width of the glyph for that base character
                case UnicodeCategory.Surrogate: {          // high-surrogate or a low-surrogate with code values in the range U+D800 through U+DFFF
                    break;
                }

                case UnicodeCategory.SpaceSeparator: { // space
                    if (lastChar != LastChar.Space)
                    {
                        iResultLength = sb.Length;
                        lastChar      = LastChar.Space;
                    }
                    rWidth += rWidthChar;
                    sb.Append(c);
                    iStart = iPos;
                    break;
                }

                case UnicodeCategory.ClosePunctuation: // separator on this line: )]}
                case UnicodeCategory.DashPunctuation:  // -
                case UnicodeCategory.FinalQuotePunctuation: {
                    rWidth += rWidthChar;
                    if (rWidth > rWidthMax)
                    {
                        iPos--;
                        goto EndLoop;
                    }
                    sb.Append(c);
                    lastChar = LastChar.SeparatorAtEndOfLine;
                    break;
                }

                case UnicodeCategory.CurrencySymbol:          // separator for next line: €
                case UnicodeCategory.InitialQuotePunctuation: // opening or initial quotation mark
                case UnicodeCategory.OpenPunctuation: {       // ([{
                    if (lastChar == LastChar.SeparatorAtEndOfLine || lastChar == LastChar.Word)
                    {
                        iResultLength = sb.Length;
                        iStart        = iPos - 1;
                    }
                    rWidth += rWidthChar;
                    if (rWidth > rWidthMax)
                    {
                        iPos--;
                        goto EndLoop;
                    }
                    sb.Append(c);
                    lastChar = LastChar.SeparatorAtStartOfLine;
                    break;
                }

                case UnicodeCategory.OtherPunctuation: { // .,
                    rWidth += rWidthChar;
                    if (rWidth > rWidthMax)
                    {
                        iPos--;
                        goto EndLoop;
                    }
                    sb.Append(c);
                    lastChar = LastChar.Word;
                    break;
                }

                case UnicodeCategory.DecimalDigitNumber: // character
                case UnicodeCategory.LetterNumber:
                case UnicodeCategory.LowercaseLetter:
                case UnicodeCategory.MathSymbol: // + =
                case UnicodeCategory.OtherLetter:
                case UnicodeCategory.OtherNotAssigned:
                case UnicodeCategory.UppercaseLetter:
                case UnicodeCategory.TitlecaseLetter: {
                    if (lastChar == LastChar.SeparatorAtEndOfLine)
                    {
                        iResultLength = sb.Length;
                        iStart        = iPos;
                    }
                    rWidth += rWidthChar;
                    if (rWidth > rWidthMax)
                    {
                        iPos--;
                        goto EndLoop;
                    }
                    sb.Append(c);
                    lastChar = LastChar.Word;
                    break;
                }

                default: {
                    Debug.Fail("unknown unicode category");
                    break;
                }
                }
                if (iPos >= sText.Length)
                {
                    iResultLength = sb.Length;
                    iStart        = iPos + 1;
                    goto EndLoop;
                }
            }
EndLoop:
            if (textSplitMode == TextSplitMode.Truncate)
            {
                iStart = sb.Length;
                return(sb.ToString());
            }
            if (iStart == iStartCopy)
            {
                if (sb.Length > 0)
                {
                    iStart = iPos;
                    return(sb.ToString());
                }
                iStart++;
                return(sText[iStart - 1].ToString());
            }
            return(sb.ToString(0, iResultLength));
        }
Пример #2
0
        ////////////////////////////////////////////////////////////////////
        // Write object to PDF file
        ////////////////////////////////////////////////////////////////////

        internal override void WriteObjectToPdfFile
        (
            BinaryWriter PdfFile
        )
        {
            // look for first and last character
            Int32 FirstChar;
            Int32 LastChar;

            for (FirstChar = 0; FirstChar < 256 && !ActiveChar[FirstChar]; FirstChar++)
            {
                ;
            }
            if (FirstChar == 256)
            {
                return;
            }
            for (LastChar = 255; !ActiveChar[LastChar]; LastChar--)
            {
                ;
            }

            // pdf font name
            StringBuilder PdfFontName = new StringBuilder("/");

            // for embedded font add 6 alpha characters prefix
            if (EmbeddedFont)
            {
                PdfFontName.Append("PFWAAA+");
                Int32 Ptr1 = 6;
                for (Int32 Ptr2 = ResourceCode.Length - 1; Ptr2 >= 0 && Char.IsDigit(ResourceCode[Ptr2]); Ptr2--)
                {
                    PdfFontName[Ptr1--] = (Char)((Int32)ResourceCode[Ptr2] + ('A' - '0'));
                }
            }

            // PDF readers are not happy with space in font name
            PdfFontName.Append(FontFamily.Name.Replace(" ", "#20"));

            // font name
            if ((DesignFont.Style & FontStyle.Bold) != 0)
            {
                if ((DesignFont.Style & FontStyle.Italic) != 0)
                {
                    PdfFontName.Append(",BoldItalic");
                }
                else
                {
                    PdfFontName.Append(",Bold");
                }
            }
            else if ((DesignFont.Style & FontStyle.Italic) != 0)
            {
                PdfFontName.Append(",Italic");
            }

            // add items to dictionary
            AddToDictionary("/Subtype", "/TrueType");
            AddToDictionary("/BaseFont", PdfFontName.ToString());

            // add first and last characters
            AddToDictionary("/FirstChar", FirstChar.ToString());
            AddToDictionary("/LastChar", LastChar.ToString());

            // create font descriptor
            FontDescriptor = new PdfObject(Document, false, "/FontDescriptor");

            // add link to font object
            AddToDictionary("/FontDescriptor", FontDescriptor);

            // font descriptor dictionary
            FontDescriptor.AddToDictionary("/FontName", PdfFontName.ToString());        // must be the same as BaseFont above
            FontDescriptor.AddToDictionary("/Flags", ((Int32)FontFlags).ToString());
            FontDescriptor.AddToDictionary("/ItalicAngle", String.Format(NFI.DecSep, "{0}", (Single)PdfItalicAngle));
            FontDescriptor.AddToDictionary("/FontWeight", PdfFontWeight.ToString());
            FontDescriptor.AddToDictionary("/Leading", String.Format(NFI.DecSep, "{0}", (Single)FontUnitsToPdfDic(PdfLeading)));
            FontDescriptor.AddToDictionary("/Ascent", String.Format(NFI.DecSep, "{0}", (Single)FontUnitsToPdfDic(PdfAscent)));
            FontDescriptor.AddToDictionary("/Descent", String.Format(NFI.DecSep, "{0}", (Single)FontUnitsToPdfDic(-PdfDescent)));

            // alphabetic (non symbolic) fonts
            if ((FontFlags & PdfFontFlags.Symbolic) == 0)
            {
                AddToDictionary("/Encoding", "/WinAnsiEncoding");
                BoundingBox Box = FontInfo.GetGlyphMetricsApi('x');
                FontDescriptor.AddToDictionary("/XHeight", String.Format(NFI.DecSep, "{0}", (Single)FontUnitsToPdfDic(Box.Rect.Top)));
                FontDescriptor.AddToDictionary("/AvgWidth", String.Format(NFI.DecSep, "{0}", (Single)FontUnitsToPdfDic(Box.Width)));
                Box          = FontInfo.GetGlyphMetricsApi('M');
                PdfCapHeight = Box.Rect.Top;
                FontDescriptor.AddToDictionary("/CapHeight", String.Format(NFI.DecSep, "{0}", (Single)FontUnitsToPdfDic(Box.Rect.Top)));
                FontDescriptor.AddToDictionary("/StemV", String.Format(NFI.DecSep, "{0}", (Single)StemV()));
            }

            // create width object array
            FontWidthArray = new PdfObject(Document, false);

            // add link to font object
            AddToDictionary("/Widths", FontWidthArray);

            // build bounding box and width array
            Double Left     = Double.MaxValue;
            Double Bottom   = Double.MaxValue;
            Double Right    = Double.MinValue;
            Double Top      = Double.MinValue;
            Double MaxWidth = Double.MinValue;

            FontWidthArray.ContentsString = new StringBuilder("[");

            Int32 EolLength = 100;

            for (Int32 Index = FirstChar; Index <= LastChar; Index++)
            {
                Double CharWidth;

                // not used
                if (!ActiveChar[Index])
                {
                    CharWidth = 0;
                }

                // used
                else
                {
                    // bounding box
                    BoundingBox GM = GlyphArray[Index];
                    if (GM.Rect.Left < Left)
                    {
                        Left = GM.Rect.Left;
                    }
                    if (GM.Rect.Bottom < Bottom)
                    {
                        Bottom = GM.Rect.Bottom;
                    }
                    if (GM.Rect.Right > Right)
                    {
                        Right = GM.Rect.Right;
                    }
                    if (GM.Rect.Top > Top)
                    {
                        Top = GM.Rect.Top;
                    }

                    // character advance width
                    CharWidth = GM.Width;

                    // max width
                    if (CharWidth > MaxWidth)
                    {
                        MaxWidth = CharWidth;
                    }
                }

                // add width to width array
                if (FontWidthArray.ContentsString.Length > EolLength)
                {
                    FontWidthArray.ContentsString.Append('\n');
                    EolLength = FontWidthArray.ContentsString.Length + 100;
                }

                // add width to width array
                FontWidthArray.ContentsString.AppendFormat(NFI.DecSep, "{0} ", FontUnitsToPdfDic(CharWidth));
            }

            // add to font descriptor array
            FontDescriptor.AddToDictionary("/MaxWidth", String.Format(NFI.DecSep, "{0}", (Single)FontUnitsToPdfDic(MaxWidth)));
            FontDescriptor.AddToDictionary("/FontBBox", String.Format(NFI.DecSep, "[{0} {1} {2} {3}]",
                                                                      FontUnitsToPdfDic(Left), FontUnitsToPdfDic(Bottom), FontUnitsToPdfDic(Right), FontUnitsToPdfDic(Top)));

            // terminate width array
            FontWidthArray.ContentsString.Length--;
            FontWidthArray.ContentsString.Append("]");

            // create font file
            if (EmbeddedFont)
            {
                // create font file stream
                PdfFontFile EmbeddedFontObj = new PdfFontFile(this);

                // add link to font object
                FontDescriptor.AddToDictionary("/FontFile2", EmbeddedFontObj);
            }

            // call base write PdfObject to file method
            base.WriteObjectToPdfFile(PdfFile);

            // exit
            return;
        }