Esempio n. 1
0
        /**
         * Calculates the target width. First checks:
         * <ol>
         * <li>if the attribute or style "width" is found in the given tag and it is not wider than pageWidth - outerWidth, then the
         * targetWidth = width value</li>
         * <li>if the columnWidths array in total is not wider than pageWidth - outerWidth, then the
         * targetWidth = the total of the columnWidths array</li>
         * <li>if table's parent is a root tag or table has no parent, then the
         * targetWidth = width of the page - outerWidth
         * {@link Table#getTableOuterWidth(Tag, float)}.</li>
         * </ol>
         * If none of the above is true, the width of the table is set to its
         * default with the columnWidths array.
         *
         * @param tag containing attributes and css.
         * @param columnWidths float[] containing the widest lines of text found in
         *            the columns.
         * @param outerWidth width needed for margins and borders.
         * @param ctx
         * @return float the target width of a table.
         * @throws NoCustomContextException
         */
        private float CalculateTargetWidth(Tag tag, float[] columnWidths, float outerWidth,
                                           IWorkerContext ctx)
        {
            float targetWidth = 0;
            HtmlPipelineContext htmlPipelineContext = GetHtmlPipelineContext(ctx);
            float max   = htmlPipelineContext.GetPageSize().Width - outerWidth;
            float start = GetTableWidth(columnWidths, 0);

            if (tag.Attributes.ContainsKey(CSS.Property.WIDTH) || tag.CSS.ContainsKey(CSS.Property.WIDTH))
            {
                targetWidth = new WidthCalculator().GetWidth(tag, htmlPipelineContext.GetRootTags(), htmlPipelineContext
                                                             .GetPageSize().Width);
                if (targetWidth > max)
                {
                    targetWidth = max;
                }
            }
            else if (start <= max)
            {
                targetWidth = start;
            }
            else if (null == tag.Parent ||
                     (null != tag.Parent && htmlPipelineContext.GetRootTags().Contains(tag.Parent.Name)))
            {
                targetWidth = max;
            }
            else   /*
                    * this table is an inner table and width adjustment is done in
                    * outer table
                    */
            {
                targetWidth = GetTableWidth(columnWidths, outerWidth);
            }
            return(targetWidth);
        }
        /* (non-Javadoc)
         * @see com.itextpdf.tool.xml.css.CssApplier#apply(com.itextpdf.text.Element, com.itextpdf.tool.xml.Tag)
         */
        public LineSeparator Apply(LineSeparator ls, Tag t)
        {
            float lineWidth = 1;
            IDictionary <String, String> css = t.CSS;

            if (css.ContainsKey(CSS.Property.HEIGHT))
            {
                lineWidth = CssUtils.GetInstance().ParsePxInCmMmPcToPt(css[CSS.Property.HEIGHT]);
            }
            ls.LineWidth = lineWidth;
            BaseColor lineColor = BaseColor.BLACK;

            if (css.ContainsKey(CSS.Property.COLOR))
            {
                lineColor = HtmlUtilities.DecodeColor(css[CSS.Property.COLOR]);
            }
            else if (css.ContainsKey(CSS.Property.BACKGROUND_COLOR))
            {
                lineColor = HtmlUtilities.DecodeColor(css[CSS.Property.BACKGROUND_COLOR]);
            }
            ls.LineColor = lineColor;
            float  percentage = 100;
            String widthStr;

            css.TryGetValue(CSS.Property.WIDTH, out widthStr);
            if (widthStr != null)
            {
                if (widthStr.Contains("%"))
                {
                    percentage = float.Parse(widthStr.Replace("%", ""), CultureInfo.InvariantCulture);
                }
                else
                {
                    percentage = (CssUtils.GetInstance().ParsePxInCmMmPcToPt(widthStr) / configuration.GetPageSize().Width) * 100;
                }
            }
            ls.Percentage = percentage;
            ls.Offset     = 9;
            return(ls);
        }
Esempio n. 3
0
 /*
  * (non-Javadoc)
  *
  * @see
  * com.itextpdf.tool.xml.ITagProcessor#endElement(com.itextpdf.tool.xml.Tag,
  * java.util.List, com.itextpdf.text.Document)
  */
 public override IList <IElement> End(IWorkerContext ctx, Tag tag, IList <IElement> currentContent)
 {
     try {
         int numberOfColumns = 0;
         List <TableRowElement> tableRows          = new List <TableRowElement>(currentContent.Count);
         IList <IElement>       invalidRowElements = new List <IElement>(1);
         String repeatHeader;
         tag.CSS.TryGetValue(CSS.Property.REPEAT_HEADER, out repeatHeader);
         String repeatFooter;
         tag.CSS.TryGetValue(CSS.Property.REPEAT_FOOTER, out repeatFooter);
         int headerRows = 0;
         int footerRows = 0;
         foreach (IElement e in currentContent)
         {
             int localNumCols = 0;
             if (e is TableRowElement)
             {
                 TableRowElement tableRowElement = (TableRowElement)e;
                 foreach (HtmlCell cell in tableRowElement.Content)
                 {
                     localNumCols += cell.Colspan;
                 }
                 if (localNumCols > numberOfColumns)
                 {
                     numberOfColumns = localNumCols;
                 }
                 tableRows.Add(tableRowElement);
                 if (repeatHeader != null && Util.EqualsIgnoreCase(repeatHeader, "yes") && tableRowElement.RowPlace.Equals(TableRowElement.Place.HEADER))
                 {
                     headerRows++;
                 }
                 if (repeatFooter != null && Util.EqualsIgnoreCase(repeatFooter, "yes") && tableRowElement.RowPlace.Equals(TableRowElement.Place.FOOTER))
                 {
                     footerRows++;
                 }
             }
             else
             {
                 invalidRowElements.Add(e);
             }
         }
         if (repeatFooter == null || !Util.EqualsIgnoreCase(repeatFooter, "yes"))
         {
             InsertionSort <TableRowElement>(tableRows, delegate(TableRowElement o1, TableRowElement o2) {
                 return(o1.RowPlace.Normal.CompareTo(o2.RowPlace.Normal));
             });
         }
         else
         {
             InsertionSort <TableRowElement>(tableRows, delegate(TableRowElement o1, TableRowElement o2) {
                 return(o1.RowPlace.Repeated.CompareTo(o2.RowPlace.Repeated));
             });
         }
         PdfPTable table = new PdfPTable(numberOfColumns);
         table.HeaderRows = headerRows + footerRows;
         table.FooterRows = footerRows;
         TableStyleValues styleValues = SetStyleValues(tag);
         table.TableEvent = new TableBorderEvent(styleValues);
         SetVerticalMargin(table, tag, styleValues, ctx);
         WidenLastCell(tableRows, styleValues.HorBorderSpacing);
         float[] columnWidths         = new float[numberOfColumns];
         float[] widestWords          = new float[numberOfColumns];
         float[] fixedWidths          = new float[numberOfColumns];
         int[]   rowspanValue         = new int[numberOfColumns];
         float   largestColumn        = 0;
         int     indexOfLargestColumn = 0;
         // Initial fill of the widths arrays
         foreach (TableRowElement row in tableRows)
         {
             int column = 0;
             foreach (HtmlCell cell in row.Content)
             {
                 // check whether the current column should be skipped due to a
                 // rowspan value of higher cell in this column.
                 while (rowspanValue[column] > 1)
                 {
                     rowspanValue[column] = rowspanValue[column] - 1;
                     ++column;
                 }
                 // sets a rowspan counter for current column (counter not
                 // needed for last column).
                 if (cell.Rowspan > 1 && column != numberOfColumns - 1)
                 {
                     rowspanValue[column] = cell.Rowspan - 1;
                 }
                 int colspan = cell.Colspan;
                 if (cell.FixedWidth != 0)
                 {
                     float fixedWidth = cell.FixedWidth + GetCellStartWidth(cell);
                     fixedWidth /= colspan;
                     for (int i = 0; i < colspan; i++)
                     {
                         int c = column + i;
                         if (fixedWidth > fixedWidths[c])
                         {
                             fixedWidths[c]  = fixedWidth;
                             columnWidths[c] = fixedWidth;
                         }
                     }
                 }
                 if (cell.CompositeElements != null)
                 {
                     float[] widthValues      = SetCellWidthAndWidestWord(cell);
                     float   cellWidth        = widthValues[0] / colspan;
                     float   widestWordOfCell = widthValues[1] / colspan;
                     for (int i = 0; i < colspan; i++)
                     {
                         int c = column + i;
                         if (fixedWidths[c] == 0 && cellWidth > columnWidths[c])
                         {
                             columnWidths[c] = cellWidth;
                             if (cellWidth > largestColumn)
                             {
                                 largestColumn        = cellWidth;
                                 indexOfLargestColumn = c;
                             }
                         }
                         if (widestWordOfCell > widestWords[c])
                         {
                             widestWords[c] = widestWordOfCell;
                         }
                     }
                 }
                 if (colspan > 1)
                 {
                     if (LOG.IsLogging(Level.TRACE))
                     {
                         LOG.Trace(String.Format(LocaleMessages.GetInstance().GetMessage(LocaleMessages.COLSPAN), colspan));
                     }
                     column += colspan - 1;
                 }
                 column++;
             }
         }
         float outerWidth        = GetTableOuterWidth(tag, styleValues.HorBorderSpacing, ctx);
         float initialTotalWidth = GetTableWidth(columnWidths, 0);
         //          float targetWidth = calculateTargetWidth(tag, columnWidths, outerWidth, ctx);
         float targetWidth = 0;
         HtmlPipelineContext htmlPipelineContext = GetHtmlPipelineContext(ctx);
         float max             = htmlPipelineContext.GetPageSize().Width - outerWidth;
         bool  tableWidthFixed = false;
         if (tag.Attributes.ContainsKey(CSS.Property.WIDTH) || tag.CSS.ContainsKey(CSS.Property.WIDTH))
         {
             targetWidth = new WidthCalculator().GetWidth(tag, htmlPipelineContext.GetRootTags(), htmlPipelineContext.GetPageSize().Width);
             if (targetWidth > max)
             {
                 targetWidth = max;
             }
             tableWidthFixed = true;
         }
         else if (initialTotalWidth <= max)
         {
             targetWidth = initialTotalWidth;
         }
         else if (null == tag.Parent || (null != tag.Parent && htmlPipelineContext.GetRootTags().Contains(tag.Parent.Name)))
         {
             targetWidth = max;
         }
         else   /* this table is an inner table and width adjustment is done in outer table */
         {
             targetWidth = GetTableWidth(columnWidths, outerWidth);
         }
         float totalFixedColumnWidth = GetTableWidth(fixedWidths, 0);
         float targetPercentage      = 0;
         if (totalFixedColumnWidth == initialTotalWidth)   // all column widths are fixed
         {
             targetPercentage = targetWidth / initialTotalWidth;
             if (initialTotalWidth > targetWidth)
             {
                 for (int column = 0; column < columnWidths.Length; column++)
                 {
                     columnWidths[column] *= targetPercentage;
                 }
             }
             else if (tableWidthFixed && targetPercentage != 1)
             {
                 for (int column = 0; column < columnWidths.Length; column++)
                 {
                     columnWidths[column] *= targetPercentage;
                 }
             }
         }
         else
         {
             targetPercentage = (targetWidth - totalFixedColumnWidth) / (initialTotalWidth - totalFixedColumnWidth);
             // Reduce width of columns if the columnWidth array + borders +
             // paddings
             // is too large for the given targetWidth.
             if (initialTotalWidth > targetWidth)
             {
                 float leftToReduce = 0;
                 for (int column = 0; column < columnWidths.Length; column++)
                 {
                     if (fixedWidths[column] == 0)
                     {
                         // Reduce width of the column to its targetWidth, if
                         // widestWord of column still fits in the targetWidth of
                         // the
                         // column.
                         if (widestWords[column] <= columnWidths[column] * targetPercentage)
                         {
                             columnWidths[column] *= targetPercentage;
                             // else take the widest word and calculate space
                             // left to
                             // reduce.
                         }
                         else
                         {
                             columnWidths[column] = widestWords[column];
                             leftToReduce        += widestWords[column] - columnWidths[column] * targetPercentage;
                         }
                         // if widestWord of a column does not fit in the
                         // fixedWidth,
                         // set the column width to the widestWord.
                     }
                     else if (fixedWidths[column] < widestWords[column])
                     {
                         columnWidths[column] = widestWords[column];
                         leftToReduce        += widestWords[column] - fixedWidths[column];
                     }
                 }
                 if (leftToReduce != 0)
                 {
                     // Reduce width of the column with the most text, if its
                     // widestWord still fits in the reduced column.
                     if (widestWords[indexOfLargestColumn] <= columnWidths[indexOfLargestColumn] - leftToReduce)
                     {
                         columnWidths[indexOfLargestColumn] -= leftToReduce;
                     }
                     else     // set all columns to their minimum, with the
                              // widestWord array.
                     {
                         for (int column = 0; leftToReduce != 0 && column < columnWidths.Length; column++)
                         {
                             if (fixedWidths[column] == 0 && columnWidths[column] > widestWords[column])
                             {
                                 float difference = columnWidths[column] - widestWords[column];
                                 if (difference <= leftToReduce)
                                 {
                                     leftToReduce        -= difference;
                                     columnWidths[column] = widestWords[column];
                                 }
                                 else
                                 {
                                     columnWidths[column] -= leftToReduce;
                                     leftToReduce          = 0;
                                 }
                             }
                         }
                         if (leftToReduce != 0)
                         {
                             // If the table has an insufficient fixed width
                             // by
                             // an
                             // attribute or style, try to enlarge the table
                             // to
                             // its
                             // minimum width (= widestWords array).
                             float pageWidth = GetHtmlPipelineContext(ctx).GetPageSize().Width;
                             if (GetTableWidth(widestWords, outerWidth) < pageWidth)
                             {
                                 targetWidth  = GetTableWidth(widestWords, outerWidth);
                                 leftToReduce = 0;
                             }
                             else
                             {
                                 // If all columnWidths are set to the
                                 // widestWordWidths and the table is still
                                 // to
                                 // wide
                                 // content will fall off the edge of a page,
                                 // which
                                 // is similar to HTML.
                                 targetWidth  = pageWidth - outerWidth;
                                 leftToReduce = 0;
                             }
                         }
                     }
                 }
                 // Enlarge width of columns to fit the targetWidth.
             }
             else if (initialTotalWidth < targetWidth)
             {
                 for (int column = 0; column < columnWidths.Length; column++)
                 {
                     if (fixedWidths[column] == 0)
                     {
                         columnWidths[column] *= targetPercentage;
                     }
                 }
             }
         }
         try {
             table.SetTotalWidth(columnWidths);
             table.LockedWidth        = true;
             table.DefaultCell.Border = Rectangle.NO_BORDER;
         } catch (DocumentException e) {
             throw new RuntimeWorkerException(LocaleMessages.GetInstance().GetMessage(LocaleMessages.NO_CUSTOM_CONTEXT), e);
         }
         foreach (TableRowElement row in tableRows)
         {
             int columnNumber = -1;
             foreach (HtmlCell cell in row.Content)
             {
                 columnNumber += cell.Colspan;
                 IList <IElement> compositeElements = cell.CompositeElements;
                 if (compositeElements != null)
                 {
                     foreach (IElement baseLevel in compositeElements)
                     {
                         if (baseLevel is PdfPTable)
                         {
                             TableStyleValues cellValues        = cell.CellValues;
                             float            totalBordersWidth = cellValues.IsLastInRow ? styleValues.HorBorderSpacing * 2
                                     : styleValues.HorBorderSpacing;
                             totalBordersWidth += cellValues.BorderWidthLeft + cellValues.BorderWidthRight;
                             float            columnWidth      = columnWidths[columnNumber];
                             IPdfPTableEvent  tableEvent       = ((PdfPTable)baseLevel).TableEvent;
                             TableStyleValues innerStyleValues = ((TableBorderEvent)tableEvent).TableStyleValues;
                             totalBordersWidth += innerStyleValues.BorderWidthLeft;
                             totalBordersWidth += innerStyleValues.BorderWidthRight;
                             ((PdfPTable)baseLevel).TotalWidth = columnWidth - totalBordersWidth;
                         }
                     }
                 }
                 table.AddCell(cell);
             }
             table.CompleteRow();
         }
         List <IElement> elems = new List <IElement>();
         if (invalidRowElements.Count > 0)
         {
             // all invalid row elements taken as caption
             int i          = 0;
             Tag captionTag = tag.Children[i++];
             while (!Util.EqualsIgnoreCase(captionTag.Name, HTML.Tag.CAPTION) && i < tag.Children.Count)
             {
                 captionTag = tag.Children[i];
                 i++;
             }
             String captionSideValue;
             captionTag.CSS.TryGetValue(CSS.Property.CAPTION_SIDE, out captionSideValue);
             if (captionSideValue != null && Util.EqualsIgnoreCase(captionSideValue, CSS.Value.BOTTOM))
             {
                 elems.Add(table);
                 elems.AddRange(invalidRowElements);
             }
             else
             {
                 elems.AddRange(invalidRowElements);
                 elems.Add(table);
             }
         }
         else
         {
             elems.Add(table);
         }
         return(elems);
     } catch (NoCustomContextException e) {
         throw new RuntimeWorkerException(LocaleMessages.GetInstance().GetMessage(LocaleMessages.NO_CUSTOM_CONTEXT), e);
     }
 }
Esempio n. 4
0
        /*
         * (non-Javadoc)
         *
         * @see
         * com.itextpdf.tool.xml.css.CssApplier#apply(com.itextpdf.text.Element,
         * com.itextpdf.tool.xml.Tag)
         */
        public HtmlCell Apply(HtmlCell cell, Tag t)
        {
            TableStyleValues values = new TableStyleValues();
            Tag table = t.Parent;

            while (!table.Name.Equals("table"))
            {
                table = table.Parent;
            }
            String border;

            table.Attributes.TryGetValue(CSS.Property.BORDER, out border);
            if (border != null && !border.Equals("0"))
            {
                values.BorderColor = BaseColor.BLACK;
                values.BorderWidth = 0.75f;
            }
            IDictionary <String, String> css = t.CSS;
            String emptyCells;

            css.TryGetValue(CSS.Property.EMPTY_CELLS, out emptyCells);
            if (null != emptyCells && Util.EqualsIgnoreCase(CSS.Value.HIDE, emptyCells) && cell.CompositeElements == null)
            {
                cell.Border = Rectangle.NO_BORDER;
            }
            else
            {
                cell.VerticalAlignment = Element.ALIGN_MIDDLE; // Default css behavior. Implementation of "vertical-align" style further along.
                if (t.Attributes.ContainsKey(HTML.Attribute.WIDTH) || css.ContainsKey(HTML.Attribute.WIDTH))
                {
                    cell.FixedWidth = new WidthCalculator().GetWidth(t, configuration.GetRootTags(), configuration.GetPageSize().Width);
                }
                String colspan;
                t.Attributes.TryGetValue(HTML.Attribute.COLSPAN, out colspan);
                if (null != colspan)
                {
                    cell.Colspan = int.Parse(colspan);
                }
                String rowspan;
                t.Attributes.TryGetValue(HTML.Attribute.ROWSPAN, out rowspan);
                if (null != rowspan)
                {
                    cell.Rowspan = int.Parse(rowspan);
                }
                foreach (KeyValuePair <String, String> entry in css)
                {
                    String key   = entry.Key;
                    String value = entry.Value;
                    cell.UseBorderPadding = true;
                    if (Util.EqualsIgnoreCase(key, CSS.Property.HEIGHT))
                    {
                        cell.MinimumHeight = utils.ParsePxInCmMmPcToPt(value);
                    }
                    else if (Util.EqualsIgnoreCase(key, CSS.Property.BACKGROUND_COLOR))
                    {
                        values.Background = HtmlUtilities.DecodeColor(value);
                    }
                    else if (Util.EqualsIgnoreCase(key, CSS.Property.VERTICAL_ALIGN))
                    {
                        if (Util.EqualsIgnoreCase(value, CSS.Value.TOP))
                        {
                            cell.VerticalAlignment = Element.ALIGN_TOP;
                            cell.PaddingTop        = cell.PaddingTop + 6;
                        }
                        else if (Util.EqualsIgnoreCase(value, CSS.Value.BOTTOM))
                        {
                            cell.VerticalAlignment = Element.ALIGN_BOTTOM;
                            cell.PaddingBottom     = cell.PaddingBottom + 6;
                        }
                    }
                    else if (key.Contains(CSS.Property.BORDER))
                    {
                        if (key.Contains(CSS.Value.TOP))
                        {
                            SetTopOfBorder(cell, key, value, values);
                        }
                        else if (key.Contains(CSS.Value.BOTTOM))
                        {
                            SetBottomOfBorder(cell, key, value, values);
                        }
                        else if (key.Contains(CSS.Value.LEFT))
                        {
                            SetLeftOfBorder(cell, key, value, values);
                        }
                        else if (key.Contains(CSS.Value.RIGHT))
                        {
                            SetRightOfBorder(cell, key, value, values);
                        }
                    }
                    else if (key.Contains(CSS.Property.CELLPADDING) || key.Contains(CSS.Property.PADDING))
                    {
                        if (key.Contains(CSS.Value.TOP))
                        {
                            cell.PaddingTop = cell.PaddingTop + utils.ParsePxInCmMmPcToPt(value);
                        }
                        else if (key.Contains(CSS.Value.BOTTOM))
                        {
                            cell.PaddingBottom = cell.PaddingBottom + utils.ParsePxInCmMmPcToPt(value);
                        }
                        else if (key.Contains(CSS.Value.LEFT))
                        {
                            cell.PaddingLeft = cell.PaddingLeft + utils.ParsePxInCmMmPcToPt(value);
                        }
                        else if (key.Contains(CSS.Value.RIGHT))
                        {
                            cell.PaddingRight = cell.PaddingRight + utils.ParsePxInCmMmPcToPt(value);
                        }
                    }
                    else if (key.Contains(CSS.Property.TEXT_ALIGN))
                    {
                        if (Util.EqualsIgnoreCase(value, CSS.Value.LEFT))
                        {
                            cell.HorizontalAlignment = Element.ALIGN_LEFT;
                        }
                        else if (Util.EqualsIgnoreCase(value, CSS.Value.CENTER))
                        {
                            cell.HorizontalAlignment = Element.ALIGN_CENTER;
                        }
                        else if (Util.EqualsIgnoreCase(value, CSS.Value.RIGHT))
                        {
                            cell.HorizontalAlignment = Element.ALIGN_RIGHT;
                        }
                    }
                }
                float horSpacing = new Table().GetBorderOrCellSpacing(true, table.CSS, table.Attributes);
                float verSpacing = new Table().GetBorderOrCellSpacing(false, table.CSS, table.Attributes);
                values.HorBorderSpacing = horSpacing;
                values.VerBorderSpacing = verSpacing;
                cell.PaddingLeft        = cell.PaddingLeft + horSpacing + values.BorderWidthLeft;
                cell.PaddingRight       = cell.PaddingRight + values.BorderWidthRight;
                cell.PaddingTop         = cell.PaddingTop + verSpacing + values.BorderWidthTop;
                cell.PaddingBottom      = cell.PaddingBottom + values.BorderWidthBottom + 1;
            }
            cell.Border     = Rectangle.NO_BORDER;
            cell.CellEvent  = new CellSpacingEvent(values);
            cell.CellValues = values;
            return(cell);
        }