private PdfLine removeLine(int index) { PdfLine oldLine = (PdfLine) lines.remove(index); contentHeight -= oldLine.height(); if (index == 0) { if (lines.size() > 0) { firstLine = (PdfLine) lines.get(0); float firstLineRealHeight = firstLineRealHeight(); contentHeight -= firstLine.height(); firstLine.height = firstLineRealHeight; contentHeight += firstLineRealHeight; } } return oldLine; }
/** * Gets the lines of a cell that can be drawn between certain limits. * * <p>Remark: all the lines that can be drawn are removed from the object! * * @param top the top of the part of the table that can be drawn * @param bottom the bottom of the part of the table that can be drawn * @return an <CODE>ArrayList</CODE> of <CODE>PdfLine</CODE>s */ public ArrayList getLines(float top, float bottom) { float lineHeight; float currentPosition = Math.min(top(), top); setTop(currentPosition + cellspacing); ArrayList result = new ArrayList(); // if the bottom of the page is higher than the top of the cell: do nothing if (top() < bottom) { return result; } // we loop over the lines int size = lines.size(); boolean aboveBottom = true; for (int i = 0; i < size && aboveBottom; i++) { line = (PdfLine) lines.get(i); lineHeight = line.height(); currentPosition -= lineHeight; // if the currentPosition is higher than the bottom, we add the line to the result if (currentPosition > (bottom + cellpadding + getBorderWidthInside(BOTTOM))) { result.add(line); } else { aboveBottom = false; } } // if the bottom of the cell is higher than the bottom of the page, the cell is written, so we // can remove all lines float difference = 0f; if (!header) { if (aboveBottom) { lines = new ArrayList(); contentHeight = 0f; } else { size = result.size(); for (int i = 0; i < size; i++) { line = removeLine(0); difference += line.height(); } } } if (difference > 0) { Image image; for (Iterator i = images.iterator(); i.hasNext(); ) { image = (Image) i.next(); image.setAbsolutePosition(image.absoluteX(), image.absoluteY() - difference - leading); } } return result; }
/** * Adds an image to this Cell. * * @param i the image to add * @param left the left border * @param right the right border * @param extraHeight extra height to add above image * @param alignment horizontal alignment (constant from Element class) * @return the height of the image */ private float addImage(Image i, float left, float right, float extraHeight, int alignment) { Image image = Image.getInstance(i); if (image.scaledWidth() > right - left) { image.scaleToFit(right - left, Float.MAX_VALUE); } flushCurrentLine(); if (line == null) { line = new PdfLine(left, right, alignment, leading); } PdfLine imageLine = line; // left and right in chunk is relative to the start of the line right = right - left; left = 0f; if ((image.alignment() & Image.RIGHT) == Image.RIGHT) { left = right - image.scaledWidth(); } else if ((image.alignment() & Image.MIDDLE) == Image.MIDDLE) { left = left + ((right - left - image.scaledWidth()) / 2f); } Chunk imageChunk = new Chunk(image, left, 0); imageLine.add(new PdfChunk(imageChunk, null)); addLine(imageLine); return imageLine.height(); }
/** * Sets the bottom of the Rectangle and determines the proper {link #verticalOffset} to * appropriately align the contents vertically. * * @param value */ public void setBottom(float value) { super.setBottom(value); float firstLineRealHeight = firstLineRealHeight(); float totalHeight = ury - value; // can't use top (already compensates for cellspacing) float nonContentHeight = (cellpadding() * 2f) + (cellspacing() * 2f); nonContentHeight += getBorderWidthInside(TOP) + getBorderWidthInside(BOTTOM); float interiorHeight = totalHeight - nonContentHeight; float extraHeight = 0.0f; switch (verticalAlignment) { case Element.ALIGN_BOTTOM: extraHeight = interiorHeight - contentHeight; break; case Element.ALIGN_MIDDLE: extraHeight = (interiorHeight - contentHeight) / 2.0f; break; default: // ALIGN_TOP extraHeight = 0f; } extraHeight += cellpadding() + cellspacing(); extraHeight += getBorderWidthInside(TOP); if (firstLine != null) { firstLine.height = firstLineRealHeight + extraHeight; } }
private void addLine(PdfLine line) { lines.add(line); contentHeight += line.height(); lastLine = line; this.line = null; }
/** * 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) { // constructs a Rectangle (the bottomvalue will be changed afterwards) super(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.isUseAscender(); this.useDescender = cell.isUseDescender(); this.useBorderPadding = cell.isUseBorderPadding(); // initialisation of some parameters PdfChunk chunk; Element element; PdfChunk overflow; lines = new ArrayList(); images = new ArrayList(); leading = cell.leading(); int alignment = cell.horizontalAlignment(); left += cellspacing + cellpadding; right -= cellspacing + cellpadding; left += getBorderWidthInside(LEFT); right -= getBorderWidthInside(RIGHT); contentHeight = 0; rowspan = cell.rowspan(); ArrayList allActions; int aCounter; // we loop over all the elements of the cell for (Iterator i = cell.getElements(); i.hasNext(); ) { element = (Element) i.next(); switch (element.type()) { case Element.JPEG: case Element.IMGRAW: case Element.IMGTEMPLATE: addImage((Image) element, 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); } allActions = new ArrayList(); processActions(element, null, allActions); aCounter = 0; ListItem item; // we loop over all the listitems for (Iterator items = ((List) element).getItems().iterator(); items.hasNext(); ) { item = (ListItem) items.next(); line = new PdfLine(left + item.indentationLeft(), right, alignment, item.leading()); line.setListItem(item); for (Iterator j = item.getChunks().iterator(); j.hasNext(); ) { chunk = new PdfChunk((Chunk) j.next(), (PdfAction) (allActions.get(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); } } line = new PdfLine(left, right, alignment, leading); break; // if the element is something else default: allActions = new ArrayList(); processActions(element, null, allActions); aCounter = 0; float currentLineLeading = leading; float currentLeft = left; float currentRight = right; if (element instanceof Phrase) { currentLineLeading = ((Phrase) element).leading(); } if (element instanceof Paragraph) { Paragraph p = (Paragraph) element; currentLeft += p.indentationLeft(); currentRight -= p.indentationRight(); } if (line == null) { line = new PdfLine(currentLeft, currentRight, alignment, currentLineLeading); } // we loop over the chunks ArrayList chunks = element.getChunks(); if (chunks.isEmpty()) { addLine(line); // add empty line - all cells need some lines even if they are empty line = new PdfLine(currentLeft, currentRight, alignment, currentLineLeading); } else { for (Iterator j = chunks.iterator(); j.hasNext(); ) { Chunk c = (Chunk) j.next(); chunk = new PdfChunk(c, (PdfAction) (allActions.get(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 (element.type()) { case Element.PARAGRAPH: case Element.SECTION: case Element.CHAPTER: line.resetAlignment(); flushCurrentLine(); } } } flushCurrentLine(); if (lines.size() > cell.getMaxLines()) { while (lines.size() > cell.getMaxLines()) { removeLine(lines.size() - 1); } if (cell.getMaxLines() > 0) { String more = cell.getShowTruncation(); if (more != null && more.length() > 0) { // Denote that the content has been truncated lastLine = (PdfLine) lines.get(lines.size() - 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.setValue(lastChunk.toString().substring(0, lastChunk.length() - 1)); } lastChunk.setValue(lastChunk.toString() + more); } else { lastLine.add(new PdfChunk(new Chunk(more), null)); } } } } // we set some additional parameters if (useDescender && lastLine != null) { contentHeight -= lastLine.getDescender(); } // adjust first line height so that it touches the top if (lines.size() > 0) { firstLine = (PdfLine) lines.get(0); float firstLineRealHeight = firstLineRealHeight(); contentHeight -= firstLine.height(); firstLine.height = firstLineRealHeight; contentHeight += firstLineRealHeight; } float newBottom = top - contentHeight - (2f * cellpadding()) - (2f * cellspacing()); newBottom -= getBorderWidthInside(TOP) + getBorderWidthInside(BOTTOM); setBottom(newBottom); this.rownumber = rownumber; }