Пример #1
0
        // constructors

        /**
         * Constructs a <CODE>PdfChunk</CODE>-object.
         *
         * @param string the content of the <CODE>PdfChunk</CODE>-object
         * @param font the <CODE>PdfFont</CODE>
         * @param attributes the metrics attributes
         * @param noStroke the non metric attributes
         */

        internal PdfChunk(string str, PdfChunk other)
        {
            thisChunk[0]    = this;
            value           = str;
            this.font       = other.font;
            this.attributes = other.attributes;
            this.noStroke   = other.noStroke;
            this.baseFont   = other.baseFont;
            Object[] obj = (Object[])attributes[Chunk.IMAGE];
            if (obj == null)
            {
                image = null;
            }
            else
            {
                image         = (Image)obj[0];
                offsetX       = (float)obj[1];
                offsetY       = (float)obj[2];
                changeLeading = (bool)obj[3];
            }
            encoding       = font.Font.Encoding;
            splitCharacter = (ISplitCharacter)noStroke[Chunk.SPLITCHARACTER];
            if (splitCharacter == null)
            {
                splitCharacter = DefaultSplitCharacter.DEFAULT;
            }
        }
Пример #2
0
        /**
         * Creates a line from the chunk array.
         * @param width the width of the line
         * @return the line or null if no more chunks
         */
        protected PdfLine CreateLine(float width)
        {
            if (chunks.Count == 0)
            {
                return(null);
            }
            splittedChunkText   = null;
            currentStandbyChunk = null;
            PdfLine line = new PdfLine(0, width, alignment, 0);
            string  total;

            for (currentChunkMarker = 0; currentChunkMarker < chunks.Count; ++currentChunkMarker)
            {
                PdfChunk original = (PdfChunk)(chunks[currentChunkMarker]);
                total = original.ToString();
                currentStandbyChunk = line.Add(original);
                if (currentStandbyChunk != null)
                {
                    splittedChunkText = original.ToString();
                    original.Value    = total;
                    return(line);
                }
            }
            return(line);
        }
Пример #3
0
        public float GetWidthCorrected(float charSpacing, float wordSpacing)
        {
            float total = 0;

            for (int k = 0; k < line.Count; ++k)
            {
                PdfChunk ck = (PdfChunk)line[k];
                total += ck.GetWidthCorrected(charSpacing, wordSpacing);
            }
            return(total);
        }
Пример #4
0
 private void AddToLine(PdfChunk chunk)
 {
     if (chunk.ChangeLeading && chunk.IsImage())
     {
         float f = chunk.Image.ScaledHeight + chunk.ImageOffsetY + chunk.Image.BorderWidthTop;
         if (f > height)
         {
             height = f;
         }
     }
     line.Add(chunk);
 }
Пример #5
0
        /**
         * Normalizes the list of chunks when the line is accepted.
         */
        protected void ShortenChunkArray()
        {
            if (currentChunkMarker < 0)
            {
                return;
            }
            if (currentChunkMarker >= chunks.Count)
            {
                chunks.Clear();
                return;
            }
            PdfChunk split = (PdfChunk)(chunks[currentChunkMarker]);

            split.Value = splittedChunkText;
            chunks[currentChunkMarker] = currentStandbyChunk;
            for (int j = currentChunkMarker - 1; j >= 0; --j)
            {
                chunks.RemoveAt(j);
            }
        }
Пример #6
0
        private void AddList(List list, float left, float right, int alignment)
        {
            PdfChunk  chunk;
            PdfChunk  overflow;
            ArrayList allActions = new ArrayList();

            ProcessActions(list, null, allActions);
            int aCounter = 0;

            foreach (IElement ele in list.Items)
            {
                switch (ele.Type)
                {
                case Element.LISTITEM:
                    ListItem item = (ListItem)ele;
                    line          = new PdfLine(left + item.IndentationLeft, right, alignment, item.Leading);
                    line.ListItem = item;
                    foreach (Chunk c in item.Chunks)
                    {
                        chunk = new PdfChunk(c, (PdfAction)(allActions[aCounter++]));
                        while ((overflow = line.Add(chunk)) != null)
                        {
                            AddLine(line);
                            line  = new PdfLine(left + item.IndentationLeft, right, alignment, item.Leading);
                            chunk = overflow;
                        }
                        line.ResetAlignment();
                        AddLine(line);
                        line = new PdfLine(left + item.IndentationLeft, right, alignment, leading);
                    }
                    break;

                case Element.LIST:
                    List sublist = (List)ele;
                    AddList(sublist, left + sublist.IndentationLeft, right, alignment);
                    break;
                }
            }
        }
Пример #7
0
        // methods

        /**
         * Adds a <CODE>PdfChunk</CODE> to the <CODE>PdfLine</CODE>.
         *
         * @param        chunk        the <CODE>PdfChunk</CODE> to add
         * @return        <CODE>null</CODE> if the chunk could be added completely; if not
         *                a <CODE>PdfChunk</CODE> containing the part of the chunk that could
         *                not be added is returned
         */

        internal PdfChunk Add(PdfChunk chunk)
        {
            // nothing happens if the chunk is null.
            if (chunk == null || chunk.ToString().Equals(""))
            {
                return(null);
            }

            // we split the chunk to be added
            PdfChunk overflow = chunk.Split(width);

            newlineSplit = (chunk.IsNewlineSplit() || overflow == null);
            //        if (chunk.IsNewlineSplit() && alignment == Element.ALIGN_JUSTIFIED)
            //            alignment = Element.ALIGN_LEFT;
            if (chunk.IsTab())
            {
                Object[] tab         = (Object[])chunk.GetAttribute(Chunk.TAB);
                float    tabPosition = (float)tab[1];
                bool     newline     = (bool)tab[2];
                if (newline && tabPosition < originalWidth - width)
                {
                    return(chunk);
                }
                width = originalWidth - tabPosition;
                chunk.AdjustLeft(left);
                AddToLine(chunk);
            }
            // if the length of the chunk > 0 we add it to the line
            else if (chunk.Length > 0 || chunk.IsImage())
            {
                if (overflow != null)
                {
                    chunk.TrimLastSpace();
                }
                width -= chunk.Width;
                AddToLine(chunk);
            }

            // if the length == 0 and there were no other chunks added to the line yet,
            // we risk to end up in an endless loop trying endlessly to add the same chunk
            else if (line.Count < 1)
            {
                chunk    = overflow;
                overflow = chunk.Truncate(width);
                width   -= chunk.Width;
                if (chunk.Length > 0)
                {
                    AddToLine(chunk);
                    return(overflow);
                }
                // if the chunck couldn't even be truncated, we add everything, so be it
                else
                {
                    if (overflow != null)
                    {
                        AddToLine(chunk);
                    }
                    return(null);
                }
            }
            else
            {
                width += ((PdfChunk)(line[line.Count - 1])).TrimLastSpace();
            }
            return(overflow);
        }
Пример #8
0
        /**
         * Truncates this <CODE>PdfChunk</CODE> if it's too long for the given width.
         * <P>
         * Returns <VAR>null</VAR> if the <CODE>PdfChunk</CODE> wasn't truncated.
         *
         * @param       width       a given width
         * @return      the <CODE>PdfChunk</CODE> that doesn't fit into the width.
         */

        internal PdfChunk Truncate(float width)
        {
            if (image != null)
            {
                if (image.ScaledWidth > width)
                {
                    PdfChunk pc = new PdfChunk("", this);
                    value = "";
                    attributes.Remove(Chunk.IMAGE);
                    image = null;
                    font  = PdfFont.DefaultFont;
                    return(pc);
                }
                else
                {
                    return(null);
                }
            }

            int   currentPosition = 0;
            float currentWidth    = 0;

            // it's no use trying to split if there isn't even enough place for a space
            if (width < font.Width())
            {
                string returnValue = value.Substring(1);
                value = value.Substring(0, 1);
                PdfChunk pc = new PdfChunk(returnValue, this);
                return(pc);
            }

            // loop over all the characters of a string
            // or until the totalWidth is reached
            int  length    = value.Length;
            bool surrogate = false;

            while (currentPosition < length)
            {
                // the width of every character is added to the currentWidth
                surrogate = Utilities.IsSurrogatePair(value, currentPosition);
                if (surrogate)
                {
                    currentWidth += font.Width(Utilities.ConvertToUtf32(value, currentPosition));
                }
                else
                {
                    currentWidth += font.Width(value[currentPosition]);
                }
                if (currentWidth > width)
                {
                    break;
                }
                if (surrogate)
                {
                    currentPosition++;
                }
                currentPosition++;
            }

            // if all the characters fit in the total width, null is returned (there is no overflow)
            if (currentPosition == length)
            {
                return(null);
            }

            // otherwise, the string has to be truncated
            //currentPosition -= 2;
            // we have to chop off minimum 1 character from the chunk
            if (currentPosition == 0)
            {
                currentPosition = 1;
                if (surrogate)
                {
                    ++currentPosition;
                }
            }
            string retVal = value.Substring(currentPosition);

            value = value.Substring(0, currentPosition);
            PdfChunk tmp = new PdfChunk(retVal, this);

            return(tmp);
        }
Пример #9
0
        /**
         * Splits this <CODE>PdfChunk</CODE> if it's too long for the given width.
         * <P>
         * Returns <VAR>null</VAR> if the <CODE>PdfChunk</CODE> wasn't truncated.
         *
         * @param       width       a given width
         * @return      the <CODE>PdfChunk</CODE> that doesn't fit into the width.
         */

        internal PdfChunk Split(float width)
        {
            newlineSplit = false;
            if (image != null)
            {
                if (image.ScaledWidth > width)
                {
                    PdfChunk pc = new PdfChunk(Chunk.OBJECT_REPLACEMENT_CHARACTER, this);
                    value      = "";
                    attributes = new Hashtable();
                    image      = null;
                    font       = PdfFont.DefaultFont;
                    return(pc);
                }
                else
                {
                    return(null);
                }
            }
            IHyphenationEvent hyphenationEvent = (IHyphenationEvent)noStroke[Chunk.HYPHENATION];
            int   currentPosition = 0;
            int   splitPosition   = -1;
            float currentWidth    = 0;

            // loop over all the characters of a string
            // or until the totalWidth is reached
            int   lastSpace      = -1;
            float lastSpaceWidth = 0;
            int   length         = value.Length;

            char[]   valueArray = value.ToCharArray();
            char     character  = (char)0;
            BaseFont ft         = font.Font;
            bool     surrogate  = false;

            if (ft.FontType == BaseFont.FONT_TYPE_CJK && ft.GetUnicodeEquivalent(' ') != ' ')
            {
                while (currentPosition < length)
                {
                    // the width of every character is added to the currentWidth
                    char cidChar = valueArray[currentPosition];
                    character = (char)ft.GetUnicodeEquivalent(cidChar);
                    // if a newLine or carriageReturn is encountered
                    if (character == '\n')
                    {
                        newlineSplit = true;
                        string returnValue = value.Substring(currentPosition + 1);
                        value = value.Substring(0, currentPosition);
                        if (value.Length < 1)
                        {
                            value = "\u0001";
                        }
                        PdfChunk pc = new PdfChunk(returnValue, this);
                        return(pc);
                    }
                    currentWidth += font.Width(cidChar);
                    if (character == ' ')
                    {
                        lastSpace      = currentPosition + 1;
                        lastSpaceWidth = currentWidth;
                    }
                    if (currentWidth > width)
                    {
                        break;
                    }
                    // if a split-character is encountered, the splitPosition is altered
                    if (splitCharacter.IsSplitCharacter(0, currentPosition, length, valueArray, thisChunk))
                    {
                        splitPosition = currentPosition + 1;
                    }
                    currentPosition++;
                }
            }
            else
            {
                while (currentPosition < length)
                {
                    // the width of every character is added to the currentWidth
                    character = valueArray[currentPosition];
                    // if a newLine or carriageReturn is encountered
                    if (character == '\r' || character == '\n')
                    {
                        newlineSplit = true;
                        int inc = 1;
                        if (character == '\r' && currentPosition + 1 < length && valueArray[currentPosition + 1] == '\n')
                        {
                            inc = 2;
                        }
                        string returnValue = value.Substring(currentPosition + inc);
                        value = value.Substring(0, currentPosition);
                        if (value.Length < 1)
                        {
                            value = " ";
                        }
                        PdfChunk pc = new PdfChunk(returnValue, this);
                        return(pc);
                    }
                    surrogate = Utilities.IsSurrogatePair(valueArray, currentPosition);
                    if (surrogate)
                    {
                        currentWidth += font.Width(Utilities.ConvertToUtf32(valueArray[currentPosition], valueArray[currentPosition + 1]));
                    }
                    else
                    {
                        currentWidth += font.Width(character);
                    }
                    if (character == ' ')
                    {
                        lastSpace      = currentPosition + 1;
                        lastSpaceWidth = currentWidth;
                    }
                    if (surrogate)
                    {
                        currentPosition++;
                    }
                    if (currentWidth > width)
                    {
                        break;
                    }
                    // if a split-character is encountered, the splitPosition is altered
                    if (splitCharacter.IsSplitCharacter(0, currentPosition, length, valueArray, null))
                    {
                        splitPosition = currentPosition + 1;
                    }
                    currentPosition++;
                }
            }

            // if all the characters fit in the total width, null is returned (there is no overflow)
            if (currentPosition == length)
            {
                return(null);
            }
            // otherwise, the string has to be truncated
            if (splitPosition < 0)
            {
                string returnValue = value;
                value = "";
                PdfChunk pc = new PdfChunk(returnValue, this);
                return(pc);
            }
            if (lastSpace > splitPosition && splitCharacter.IsSplitCharacter(0, 0, 1, singleSpace, null))
            {
                splitPosition = lastSpace;
            }
            if (hyphenationEvent != null && lastSpace >= 0 && lastSpace < currentPosition)
            {
                int wordIdx = GetWord(value, lastSpace);
                if (wordIdx > lastSpace)
                {
                    string pre  = hyphenationEvent.GetHyphenatedWordPre(value.Substring(lastSpace, wordIdx - lastSpace), font.Font, font.Size, width - lastSpaceWidth);
                    string post = hyphenationEvent.HyphenatedWordPost;
                    if (pre.Length > 0)
                    {
                        string returnValue = post + value.Substring(wordIdx);
                        value = Trim(value.Substring(0, lastSpace) + pre);
                        PdfChunk pc = new PdfChunk(returnValue, this);
                        return(pc);
                    }
                }
            }
            string retVal = value.Substring(splitPosition);

            value = Trim(value.Substring(0, splitPosition));
            PdfChunk tmp = new PdfChunk(retVal, this);

            return(tmp);
        }
Пример #10
0
        // constructors

        /**
         * Constructs a <CODE>PdfCell</CODE>-object.
         *
         * @param   cell        the original <CODE>Cell</CODE>
         * @param   rownumber   the number of the <CODE>Row</CODE> the <CODE>Cell</CODE> was in.
         * @param   left        the left border of the <CODE>PdfCell</CODE>
         * @param   right       the right border of the <CODE>PdfCell</CODE>
         * @param   top         the top border of the <CODE>PdfCell</CODE>
         * @param   cellspacing the cellspacing of the <CODE>Table</CODE>
         * @param   cellpadding the cellpadding of the <CODE>Table</CODE>
         */

        public PdfCell(Cell cell, int rownumber, float left, float right, float top, float cellspacing, float cellpadding) : base(left, top, right, top)
        {
            // copying the other Rectangle attributes from class Cell
            CloneNonPositionParameters(cell);
            this.cellpadding       = cellpadding;
            this.cellspacing       = cellspacing;
            this.verticalAlignment = cell.VerticalAlignment;
            this.useAscender       = cell.UseAscender;
            this.useDescender      = cell.UseDescender;
            this.useBorderPadding  = cell.UseBorderPadding;

            // initialisation of some parameters
            PdfChunk chunk;
            PdfChunk overflow;

            lines   = new ArrayList();
            images  = new ArrayList();
            leading = cell.Leading;
            int alignment = cell.HorizontalAlignment;

            left  += cellspacing + cellpadding;
            right -= cellspacing + cellpadding;

            left         += GetBorderWidthInside(LEFT_BORDER);
            right        -= GetBorderWidthInside(RIGHT_BORDER);
            contentHeight = 0;
            rowspan       = cell.Rowspan;

            ArrayList allActions;
            int       aCounter;

            // we loop over all the elements of the cell
            foreach (IElement ele in cell.Elements)
            {
                switch (ele.Type)
                {
                case Element.JPEG:
                case Element.JPEG2000:
                case Element.JBIG2:
                case Element.IMGRAW:
                case Element.IMGTEMPLATE:
                    AddImage((Image)ele, left, right, 0.4f * leading, alignment);
                    break;

                // if the element is a list
                case Element.LIST:
                    if (line != null && line.Size > 0)
                    {
                        line.ResetAlignment();
                        AddLine(line);
                    }
                    // we loop over all the listitems
                    AddList((List)ele, left, right, alignment);
                    line = new PdfLine(left, right, alignment, leading);
                    break;

                // if the element is something else
                default:
                    allActions = new ArrayList();
                    ProcessActions(ele, null, allActions);
                    aCounter = 0;

                    float currentLineLeading = leading;
                    float currentLeft        = left;
                    float currentRight       = right;
                    if (ele is Phrase)
                    {
                        currentLineLeading = ((Phrase)ele).Leading;
                    }
                    if (ele is Paragraph)
                    {
                        Paragraph p = (Paragraph)ele;
                        currentLeft  += p.IndentationLeft;
                        currentRight -= p.IndentationRight;
                    }
                    if (line == null)
                    {
                        line = new PdfLine(currentLeft, currentRight, alignment, currentLineLeading);
                    }
                    // we loop over the chunks
                    ArrayList chunks = ele.Chunks;
                    if (chunks.Count == 0)
                    {
                        AddLine(line);     // add empty line - all cells need some lines even if they are empty
                        line = new PdfLine(currentLeft, currentRight, alignment, currentLineLeading);
                    }
                    else
                    {
                        foreach (Chunk c in chunks)
                        {
                            chunk = new PdfChunk(c, (PdfAction)allActions[aCounter++]);
                            while ((overflow = line.Add(chunk)) != null)
                            {
                                AddLine(line);
                                line  = new PdfLine(currentLeft, currentRight, alignment, currentLineLeading);
                                chunk = overflow;
                            }
                        }
                    }
                    // if the element is a paragraph, section or chapter, we reset the alignment and add the line
                    switch (ele.Type)
                    {
                    case Element.PARAGRAPH:
                    case Element.SECTION:
                    case Element.CHAPTER:
                        line.ResetAlignment();
                        FlushCurrentLine();
                        break;
                    }
                    break;
                }
            }
            FlushCurrentLine();
            if (lines.Count > cell.MaxLines)
            {
                while (lines.Count > cell.MaxLines)
                {
                    RemoveLine(lines.Count - 1);
                }
                if (cell.MaxLines > 0)
                {
                    String more = cell.ShowTruncation;
                    if (more != null && more.Length > 0)
                    {
                        // Denote that the content has been truncated
                        lastLine = (PdfLine)lines[lines.Count - 1];
                        if (lastLine.Size >= 0)
                        {
                            PdfChunk lastChunk = lastLine.GetChunk(lastLine.Size - 1);
                            float    moreWidth = new PdfChunk(more, lastChunk).Width;
                            while (lastChunk.ToString().Length > 0 && lastChunk.Width + moreWidth > right - left)
                            {
                                // Remove characters to leave room for the 'more' indicator
                                lastChunk.Value = lastChunk.ToString().Substring(0, lastChunk.Length - 1);
                            }
                            lastChunk.Value = lastChunk.ToString() + more;
                        }
                        else
                        {
                            lastLine.Add(new PdfChunk(new Chunk(more), null));
                        }
                    }
                }
            }
            // we set some additional parameters
            if (useDescender && lastLine != null)
            {
                contentHeight -= lastLine.Descender;
            }

            // adjust first line height so that it touches the top
            if (lines.Count > 0)
            {
                firstLine = (PdfLine)lines[0];
                float firstLineRealHeight = FirstLineRealHeight;
                contentHeight   -= firstLine.Height;
                firstLine.height = firstLineRealHeight;
                contentHeight   += firstLineRealHeight;
            }

            float newBottom = top - contentHeight - (2f * Cellpadding) - (2f * Cellspacing);

            newBottom -= GetBorderWidthInside(TOP_BORDER) + GetBorderWidthInside(BOTTOM_BORDER);
            Bottom     = newBottom;

            this.rownumber = rownumber;
        }