001/* 002 * $Id: PdfPRow.java 4845 2011-05-05 18:05:38Z blowagie $ 003 * 004 * This file is part of the iText (R) project. 005 * Copyright (c) 1998-2011 1T3XT BVBA 006 * Authors: Bruno Lowagie, Paulo Soares, et al. 007 * 008 * This program is free software; you can redistribute it and/or modify 009 * it under the terms of the GNU Affero General Public License version 3 010 * as published by the Free Software Foundation with the addition of the 011 * following permission added to Section 15 as permitted in Section 7(a): 012 * FOR ANY PART OF THE COVERED WORK IN WHICH THE COPYRIGHT IS OWNED BY 1T3XT, 013 * 1T3XT DISCLAIMS THE WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS. 014 * 015 * This program is distributed in the hope that it will be useful, but 016 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 017 * or FITNESS FOR A PARTICULAR PURPOSE. 018 * See the GNU Affero General Public License for more details. 019 * You should have received a copy of the GNU Affero General Public License 020 * along with this program; if not, see http://www.gnu.org/licenses or write to 021 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 022 * Boston, MA, 02110-1301 USA, or download the license from the following URL: 023 * http://itextpdf.com/terms-of-use/ 024 * 025 * The interactive user interfaces in modified source and object code versions 026 * of this program must display Appropriate Legal Notices, as required under 027 * Section 5 of the GNU Affero General Public License. 028 * 029 * In accordance with Section 7(b) of the GNU Affero General Public License, 030 * a covered work must retain the producer line in every PDF that is created 031 * or manipulated using iText. 032 * 033 * You can be released from the requirements of the license by purchasing 034 * a commercial license. Buying such a license is mandatory as soon as you 035 * develop commercial activities involving the iText software without 036 * disclosing the source code of your own applications. 037 * These activities include: offering paid services to customers as an ASP, 038 * serving PDFs on the fly in a web application, shipping iText with a closed 039 * source product. 040 * 041 * For more information, please contact iText Software Corp. at this 042 * address: sales@itextpdf.com 043 */ 044package com.itextpdf.text.pdf; 045 046import com.itextpdf.text.DocumentException; 047import com.itextpdf.text.Element; 048import com.itextpdf.text.ExceptionConverter; 049import com.itextpdf.text.Image; 050import com.itextpdf.text.Rectangle; 051import com.itextpdf.text.BaseColor; 052 053/** 054 * A row in a PdfPTable. 055 * 056 * @author Paulo Soares 057 */ 058public class PdfPRow { 059 060 /** the bottom limit (bottom right y) */ 061 public static final float BOTTOM_LIMIT = -(1 << 30); 062 /** 063 * the right limit 064 * @since 2.1.5 065 */ 066 public static final float RIGHT_LIMIT = 20000; 067 068 protected PdfPCell cells[]; 069 070 protected float widths[]; 071 072 /** 073 * extra heights that needs to be added to a cell because of rowspans. 074 * @since 2.1.6 075 */ 076 protected float extraHeights[]; 077 078 protected float maxHeight = 0; 079 080 protected boolean calculated = false; 081 082 private int[] canvasesPos; 083 084 /** 085 * Constructs a new PdfPRow with the cells in the array that was passed 086 * as a parameter. 087 * 088 * @param cells 089 */ 090 public PdfPRow(PdfPCell cells[]) { 091 this.cells = cells; 092 widths = new float[cells.length]; 093 initExtraHeights(); 094 } 095 096 /** 097 * Makes a copy of an existing row. 098 * 099 * @param row 100 */ 101 public PdfPRow(PdfPRow row) { 102 maxHeight = row.maxHeight; 103 calculated = row.calculated; 104 cells = new PdfPCell[row.cells.length]; 105 for (int k = 0; k < cells.length; ++k) { 106 if (row.cells[k] != null) 107 cells[k] = new PdfPCell(row.cells[k]); 108 } 109 widths = new float[cells.length]; 110 System.arraycopy(row.widths, 0, widths, 0, cells.length); 111 initExtraHeights(); 112 } 113 114 /** 115 * Sets the widths of the columns in the row. 116 * 117 * @param widths 118 * @return true if everything went right 119 */ 120 public boolean setWidths(float widths[]) { 121 if (widths.length != cells.length) 122 return false; 123 System.arraycopy(widths, 0, this.widths, 0, cells.length); 124 float total = 0; 125 calculated = false; 126 for (int k = 0; k < widths.length; ++k) { 127 PdfPCell cell = cells[k]; 128 129 if (cell == null) { 130 total += widths[k]; 131 continue; 132 } 133 134 cell.setLeft(total); 135 int last = k + cell.getColspan(); 136 for (; k < last; ++k) 137 total += widths[k]; 138 --k; 139 cell.setRight(total); 140 cell.setTop(0); 141 } 142 return true; 143 } 144 145 /** 146 * Initializes the extra heights array. 147 * @since 2.1.6 148 */ 149 protected void initExtraHeights() { 150 extraHeights = new float[cells.length]; 151 for (int i = 0; i < extraHeights.length; i++) { 152 extraHeights[i] = 0; 153 } 154 } 155 156 /** 157 * Sets an extra height for a cell. 158 * @param cell the index of the cell that needs an extra height 159 * @param height the extra height 160 * @since 2.1.6 161 */ 162 public void setExtraHeight(int cell, float height) { 163 if (cell < 0 || cell >= cells.length) 164 return; 165 extraHeights[cell] = height; 166 } 167 168 /** 169 * Calculates the heights of each cell in the row. 170 */ 171 protected void calculateHeights() { 172 maxHeight = 0; 173 for (int k = 0; k < cells.length; ++k) { 174 PdfPCell cell = cells[k]; 175 float height = 0; 176 if (cell == null) { 177 continue; 178 } 179 else { 180 height = cell.getMaxHeight(); 181 if ((height > maxHeight) && (cell.getRowspan() == 1)) 182 maxHeight = height; 183 } 184 } 185 calculated = true; 186 } 187 188 /** 189 * Writes the border and background of one cell in the row. 190 * 191 * @param xPos The x-coordinate where the table starts on the canvas 192 * @param yPos The y-coordinate where the table starts on the canvas 193 * @param currentMaxHeight The height of the cell to be drawn. 194 * @param cell 195 * @param canvases 196 * @since 2.1.6 extra parameter currentMaxHeight 197 */ 198 public void writeBorderAndBackground(float xPos, float yPos, float currentMaxHeight, PdfPCell cell, PdfContentByte[] canvases) { 199 BaseColor background = cell.getBackgroundColor(); 200 if (background != null || cell.hasBorders()) { 201 // Add xPos resp. yPos to the cell's coordinates for absolute coordinates 202 float right = cell.getRight() + xPos; 203 float top = cell.getTop() + yPos; 204 float left = cell.getLeft() + xPos; 205 float bottom = top - currentMaxHeight; 206 207 if (background != null) { 208 PdfContentByte backgr = canvases[PdfPTable.BACKGROUNDCANVAS]; 209 backgr.setColorFill(background); 210 backgr.rectangle(left, bottom, right - left, top - bottom); 211 backgr.fill(); 212 } 213 if (cell.hasBorders()) { 214 Rectangle newRect = new Rectangle(left, bottom, right, top); 215 // Clone non-position parameters except for the background color 216 newRect.cloneNonPositionParameters(cell); 217 newRect.setBackgroundColor(null); 218 // Write the borders on the line canvas 219 PdfContentByte lineCanvas = canvases[PdfPTable.LINECANVAS]; 220 lineCanvas.rectangle(newRect); 221 } 222 } 223 } 224 225 /** 226 * @since 2.1.6 private is now protected 227 */ 228 protected void saveAndRotateCanvases(PdfContentByte[] canvases, float a, float b, float c, float d, float e, float f) { 229 int last = PdfPTable.TEXTCANVAS + 1; 230 if (canvasesPos == null) 231 canvasesPos = new int[last * 2]; 232 for (int k = 0; k < last; ++k) { 233 ByteBuffer bb = canvases[k].getInternalBuffer(); 234 canvasesPos[k * 2] = bb.size(); 235 canvases[k].saveState(); 236 canvases[k].concatCTM(a, b, c, d, e, f); 237 canvasesPos[k * 2 + 1] = bb.size(); 238 } 239 } 240 241 /** 242 * @since 2.1.6 private is now protected 243 */ 244 protected void restoreCanvases(PdfContentByte[] canvases) { 245 int last = PdfPTable.TEXTCANVAS + 1; 246 for (int k = 0; k < last; ++k) { 247 ByteBuffer bb = canvases[k].getInternalBuffer(); 248 int p1 = bb.size(); 249 canvases[k].restoreState(); 250 if (p1 == canvasesPos[k * 2 + 1]) 251 bb.setSize(canvasesPos[k * 2]); 252 } 253 } 254 255 /** 256 * @since 3.0.0 protected is now public static 257 */ 258 public static float setColumn(ColumnText ct, float left, float bottom, float right, float top) { 259 if (left > right) 260 right = left; 261 if (bottom > top) 262 top = bottom; 263 ct.setSimpleColumn(left, bottom, right, top); 264 return top; 265 } 266 267 /** 268 * Writes a number of cells (not necessarily all cells). 269 * 270 * @param colStart The first column to be written. 271 * Remember that the column index starts with 0. 272 * @param colEnd The last column to be written. 273 * Remember that the column index starts with 0. 274 * If -1, all the columns to the end are written. 275 * @param xPos The x-coordinate where the table starts on the canvas 276 * @param yPos The y-coordinate where the table starts on the canvas 277 * @param reusable if set to false, the content in the cells is "consumed"; 278 * if true, you can reuse the cells, the row, the parent table as many times you want. 279 * @since 5.1.0 added the reusable parameter 280 */ 281 public void writeCells(int colStart, int colEnd, float xPos, float yPos, PdfContentByte[] canvases, boolean reusable) { 282 if (!calculated) 283 calculateHeights(); 284 if (colEnd < 0) 285 colEnd = cells.length; 286 else 287 colEnd = Math.min(colEnd, cells.length); 288 if (colStart < 0) 289 colStart = 0; 290 if (colStart >= colEnd) 291 return; 292 293 int newStart; 294 for (newStart = colStart; newStart >= 0; --newStart) { 295 if (cells[newStart] != null) 296 break; 297 if (newStart > 0) 298 xPos -= widths[newStart - 1]; 299 } 300 301 if (newStart < 0) 302 newStart = 0; 303 if (cells[newStart] != null) 304 xPos -= cells[newStart].getLeft(); 305 306 for (int k = newStart; k < colEnd; ++k) { 307 PdfPCell cell = cells[k]; 308 if (cell == null) 309 continue; 310 float currentMaxHeight = maxHeight + extraHeights[k]; 311 312 writeBorderAndBackground(xPos, yPos, currentMaxHeight, cell, canvases); 313 314 Image img = cell.getImage(); 315 316 float tly = cell.getTop() + yPos - cell.getEffectivePaddingTop(); 317 if (cell.getHeight() <= currentMaxHeight) { 318 switch (cell.getVerticalAlignment()) { 319 case Element.ALIGN_BOTTOM: 320 tly = cell.getTop() + yPos - currentMaxHeight + cell.getHeight() 321 - cell.getEffectivePaddingTop(); 322 break; 323 case Element.ALIGN_MIDDLE: 324 tly = cell.getTop() + yPos + (cell.getHeight() - currentMaxHeight) / 2 325 - cell.getEffectivePaddingTop(); 326 break; 327 default: 328 break; 329 } 330 } 331 if (img != null) { 332 if (cell.getRotation() != 0) { 333 img = Image.getInstance(img); 334 img.setRotation(img.getImageRotation() + (float)(cell.getRotation() * Math.PI / 180.0)); 335 } 336 boolean vf = false; 337 if (cell.getHeight() > currentMaxHeight) { 338 img.scalePercent(100); 339 float scale = (currentMaxHeight - cell.getEffectivePaddingTop() - cell 340 .getEffectivePaddingBottom()) 341 / img.getScaledHeight(); 342 img.scalePercent(scale * 100); 343 vf = true; 344 } 345 float left = cell.getLeft() + xPos 346 + cell.getEffectivePaddingLeft(); 347 if (vf) { 348 switch (cell.getHorizontalAlignment()) { 349 case Element.ALIGN_CENTER: 350 left = xPos 351 + (cell.getLeft() + cell.getEffectivePaddingLeft() 352 + cell.getRight() 353 - cell.getEffectivePaddingRight() - img 354 .getScaledWidth()) / 2; 355 break; 356 case Element.ALIGN_RIGHT: 357 left = xPos + cell.getRight() 358 - cell.getEffectivePaddingRight() 359 - img.getScaledWidth(); 360 break; 361 default: 362 break; 363 } 364 tly = cell.getTop() + yPos - cell.getEffectivePaddingTop(); 365 } 366 img.setAbsolutePosition(left, tly - img.getScaledHeight()); 367 try { 368 canvases[PdfPTable.TEXTCANVAS].addImage(img); 369 } catch (DocumentException e) { 370 throw new ExceptionConverter(e); 371 } 372 } else { 373 // rotation sponsored by Connection GmbH 374 if (cell.getRotation() == 90 || cell.getRotation() == 270) { 375 float netWidth = currentMaxHeight - cell.getEffectivePaddingTop() - cell.getEffectivePaddingBottom(); 376 float netHeight = cell.getWidth() - cell.getEffectivePaddingLeft() - cell.getEffectivePaddingRight(); 377 ColumnText ct = ColumnText.duplicate(cell.getColumn()); 378 ct.setCanvases(canvases); 379 ct.setSimpleColumn(0, 0, netWidth + 0.001f, -netHeight); 380 try { 381 ct.go(true); 382 } catch (DocumentException e) { 383 throw new ExceptionConverter(e); 384 } 385 float calcHeight = -ct.getYLine(); 386 if (netWidth <= 0 || netHeight <= 0) 387 calcHeight = 0; 388 if (calcHeight > 0) { 389 if (cell.isUseDescender()) 390 calcHeight -= ct.getDescender(); 391 ct = ColumnText.duplicate(cell.getColumn()); 392 ct.setCanvases(canvases); 393 ct.setSimpleColumn(-0.003f, -0.001f, netWidth + 0.003f, calcHeight); 394 float pivotX; 395 float pivotY; 396 if (cell.getRotation() == 90) { 397 pivotY = cell.getTop() + yPos - currentMaxHeight + cell.getEffectivePaddingBottom(); 398 switch (cell.getVerticalAlignment()) { 399 case Element.ALIGN_BOTTOM: 400 pivotX = cell.getLeft() + xPos + cell.getWidth() - cell.getEffectivePaddingRight(); 401 break; 402 case Element.ALIGN_MIDDLE: 403 pivotX = cell.getLeft() + xPos + (cell.getWidth() + cell.getEffectivePaddingLeft() - cell.getEffectivePaddingRight() + calcHeight) / 2; 404 break; 405 default: //top 406 pivotX = cell.getLeft() + xPos + cell.getEffectivePaddingLeft() + calcHeight; 407 break; 408 } 409 saveAndRotateCanvases(canvases, 0,1,-1,0,pivotX,pivotY); 410 } 411 else { 412 pivotY = cell.getTop() + yPos - cell.getEffectivePaddingTop(); 413 switch (cell.getVerticalAlignment()) { 414 case Element.ALIGN_BOTTOM: 415 pivotX = cell.getLeft() + xPos + cell.getEffectivePaddingLeft(); 416 break; 417 case Element.ALIGN_MIDDLE: 418 pivotX = cell.getLeft() + xPos + (cell.getWidth() + cell.getEffectivePaddingLeft() - cell.getEffectivePaddingRight() - calcHeight) / 2; 419 break; 420 default: //top 421 pivotX = cell.getLeft() + xPos + cell.getWidth() - cell.getEffectivePaddingRight() - calcHeight; 422 break; 423 } 424 saveAndRotateCanvases(canvases, 0,-1,1,0,pivotX,pivotY); 425 } 426 try { 427 ct.go(); 428 } catch (DocumentException e) { 429 throw new ExceptionConverter(e); 430 } finally { 431 restoreCanvases(canvases); 432 } 433 } 434 } 435 else { 436 float fixedHeight = cell.getFixedHeight(); 437 float rightLimit = cell.getRight() + xPos 438 - cell.getEffectivePaddingRight(); 439 float leftLimit = cell.getLeft() + xPos 440 + cell.getEffectivePaddingLeft(); 441 if (cell.isNoWrap()) { 442 switch (cell.getHorizontalAlignment()) { 443 case Element.ALIGN_CENTER: 444 rightLimit += 10000; 445 leftLimit -= 10000; 446 break; 447 case Element.ALIGN_RIGHT: 448 if (cell.getRotation() == 180) { 449 rightLimit += RIGHT_LIMIT; 450 } 451 else { 452 leftLimit -= RIGHT_LIMIT; 453 } 454 break; 455 default: 456 if (cell.getRotation() == 180) { 457 leftLimit -= RIGHT_LIMIT; 458 } 459 else { 460 rightLimit += RIGHT_LIMIT; 461 } 462 break; 463 } 464 } 465 ColumnText ct; 466 if (reusable) 467 ct = ColumnText.duplicate(cell.getColumn()); 468 else 469 ct = cell.getColumn(); 470 ct.setCanvases(canvases); 471 float bry = tly 472 - (currentMaxHeight 473 - cell.getEffectivePaddingTop() - cell.getEffectivePaddingBottom()); 474 if (fixedHeight > 0) { 475 if (cell.getHeight() > currentMaxHeight) { 476 tly = cell.getTop() + yPos - cell.getEffectivePaddingTop(); 477 bry = cell.getTop() + yPos - currentMaxHeight + cell.getEffectivePaddingBottom(); 478 } 479 } 480 if ((tly > bry || ct.zeroHeightElement()) && leftLimit < rightLimit) { 481 ct.setSimpleColumn(leftLimit, bry - 0.001f, rightLimit, tly); 482 if (cell.getRotation() == 180) { 483 float shx = leftLimit + rightLimit; 484 float shy = yPos + yPos - currentMaxHeight + cell.getEffectivePaddingBottom() - cell.getEffectivePaddingTop(); 485 saveAndRotateCanvases(canvases, -1,0,0,-1,shx,shy); 486 } 487 try { 488 ct.go(); 489 } catch (DocumentException e) { 490 throw new ExceptionConverter(e); 491 } finally { 492 if (cell.getRotation() == 180) { 493 restoreCanvases(canvases); 494 } 495 } 496 } 497 } 498 } 499 PdfPCellEvent evt = cell.getCellEvent(); 500 if (evt != null) { 501 Rectangle rect = new Rectangle(cell.getLeft() + xPos, cell.getTop() 502 + yPos - currentMaxHeight, cell.getRight() + xPos, cell.getTop() 503 + yPos); 504 evt.cellLayout(cell, rect, canvases); 505 } 506 } 507 } 508 509 /** 510 * Checks if the dimensions of the columns were calculated. 511 * 512 * @return true if the dimensions of the columns were calculated 513 */ 514 public boolean isCalculated() { 515 return calculated; 516 } 517 518 /** 519 * Gets the maximum height of the row (i.e. of the 'highest' cell). 520 * 521 * @return the maximum height of the row 522 */ 523 public float getMaxHeights() { 524 if (!calculated) 525 calculateHeights(); 526 return maxHeight; 527 } 528 529 /** 530 * Changes the maximum height of the row (to make it higher). 531 * (added by Jin-Hsia Yang) 532 * 533 * @param maxHeight the new maximum height 534 */ 535 public void setMaxHeights(float maxHeight) { 536 this.maxHeight = maxHeight; 537 } 538 539 //end add 540 541 float[] getEventWidth(float xPos, float[] absoluteWidths) { 542 int n = 1; 543 for (int k = 0; k < cells.length; ) { 544 if (cells[k] != null) { 545 n++; 546 k += cells[k].getColspan(); 547 } 548 else { 549 while (k < cells.length && cells[k] == null) { 550 n++; 551 k++; 552 } 553 } 554 } 555 float width[] = new float[n]; 556 width[0] = xPos; 557 n = 1; 558 for (int k = 0; k < cells.length && n < width.length; ) { 559 if (cells[k] != null) { 560 int colspan = cells[k].getColspan(); 561 width[n] = width[n - 1]; 562 for (int i = 0; i < colspan && k < absoluteWidths.length; i++) { 563 width[n] += absoluteWidths[k++]; 564 } 565 n++; 566 } 567 else { 568 width[n] = width[n - 1]; 569 while (k < cells.length && cells[k] == null) { 570 width[n] += absoluteWidths[k++]; 571 } 572 n++; 573 } 574 } 575 return width; 576 } 577 578 /** 579 * Copies the content of a specific row in a table to this row. 580 * Don't do this if the rows have a different number of cells. 581 * @param table the table from which you want to copy a row 582 * @param idx the index of the row that needs to be copied 583 * @since 5.1.0 584 */ 585 public void copyRowContent(PdfPTable table, int idx) { 586 if (table == null) { 587 return; 588 } 589 PdfPCell copy; 590 for (int i = 0; i < cells.length; ++i) { 591 int lastRow = idx; 592 copy = table.getRow(lastRow).getCells()[i]; 593 while (copy == null && lastRow > 0) { 594 copy = table.getRow(--lastRow).getCells()[i]; 595 } 596 if (cells[i] != null && copy != null) { 597 cells[i].setColumn(copy.getColumn()); 598 this.calculated = false; 599 } 600 } 601 } 602 603 /** 604 * Splits a row to newHeight. 605 * The returned row is the remainder. It will return null if the newHeight 606 * was so small that only an empty row would result. 607 * 608 * @param new_height the new height 609 * @return the remainder row or null if the newHeight was so small that only 610 * an empty row would result 611 */ 612 public PdfPRow splitRow(PdfPTable table, int rowIndex, float new_height) { 613 // second part of the row 614 PdfPCell newCells[] = new PdfPCell[cells.length]; 615 float fixHs[] = new float[cells.length]; 616 float minHs[] = new float[cells.length]; 617 boolean allEmpty = true; 618 // loop over all the cells 619 for (int k = 0; k < cells.length; ++k) { 620 float newHeight = new_height; 621 PdfPCell cell = cells[k]; 622 if (cell == null) { 623 int index = rowIndex; 624 if (table.rowSpanAbove(index, k)) { 625 while (table.rowSpanAbove(--index, k)) { 626 newHeight += table.getRow(index).getMaxHeights(); 627 } 628 PdfPRow row = table.getRow(index); 629 if (row != null && row.getCells()[k] != null) { 630 newCells[k] = new PdfPCell(row.getCells()[k]); 631 newCells[k].setColumn(null); 632 newCells[k].setRowspan(row.getCells()[k].getRowspan() - rowIndex + index); 633 allEmpty = false; 634 } 635 } 636 continue; 637 } 638 fixHs[k] = cell.getFixedHeight(); 639 minHs[k] = cell.getMinimumHeight(); 640 Image img = cell.getImage(); 641 PdfPCell newCell = new PdfPCell(cell); 642 if (img != null) { 643 if (newHeight > cell.getEffectivePaddingBottom() + cell.getEffectivePaddingTop() + 2) { 644 newCell.setPhrase(null); 645 allEmpty = false; 646 } 647 } 648 else { 649 float y; 650 ColumnText ct = ColumnText.duplicate(cell.getColumn()); 651 float left = cell.getLeft() + cell.getEffectivePaddingLeft(); 652 float bottom = cell.getTop() + cell.getEffectivePaddingBottom() - newHeight; 653 float right = cell.getRight() - cell.getEffectivePaddingRight(); 654 float top = cell.getTop() - cell.getEffectivePaddingTop(); 655 switch (cell.getRotation()) { 656 case 90: 657 case 270: 658 y = setColumn(ct, bottom, left, top, right); 659 break; 660 default: 661 y = setColumn(ct, left, bottom + 0.00001f, cell.isNoWrap() ? RIGHT_LIMIT : right, top); 662 break; 663 } 664 int status; 665 try { 666 status = ct.go(true); 667 } 668 catch (DocumentException e) { 669 throw new ExceptionConverter(e); 670 } 671 boolean thisEmpty = (ct.getYLine() == y); 672 if (thisEmpty) { 673 newCell.setColumn(ColumnText.duplicate(cell.getColumn())); 674 ct.setFilledWidth(0); 675 } 676 else if ((status & ColumnText.NO_MORE_TEXT) == 0) { 677 newCell.setColumn(ct); 678 ct.setFilledWidth(0); 679 } 680 else 681 newCell.setPhrase(null); 682 allEmpty = (allEmpty && thisEmpty); 683 } 684 newCells[k] = newCell; 685 cell.setFixedHeight(newHeight); 686 } 687 if (allEmpty) { 688 for (int k = 0; k < cells.length; ++k) { 689 PdfPCell cell = cells[k]; 690 if (cell == null) 691 continue; 692 if (fixHs[k] > 0) 693 cell.setFixedHeight(fixHs[k]); 694 else 695 cell.setMinimumHeight(minHs[k]); 696 } 697 return null; 698 } 699 calculateHeights(); 700 PdfPRow split = new PdfPRow(newCells); 701 split.widths = (float[]) widths.clone(); 702 return split; 703 } 704 705 /** 706 * Returns the array of cells in the row. 707 * Please be extremely careful with this method. 708 * Use the cells as read only objects. 709 * 710 * @return an array of cells 711 * @since 2.1.1 712 */ 713 public PdfPCell[] getCells() { 714 return cells; 715 } 716 717 /** 718 * Checks if a cell in the row has a rowspan greater than 1. 719 * @since 5.1.0 720 */ 721 public boolean hasRowspan() { 722 for (int i = 0; i < cells.length; i++) { 723 if (cells[i] != null && cells[i].getRowspan() > 1) 724 return true; 725 } 726 return false; 727 } 728}