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}