001: /**
002: * $Id: RtfCell.java 2759 2007-05-16 10:52:31Z psoares33 $
003: * $Name$
004: *
005: * Copyright 2001, 2002 by Mark Hall
006: *
007: * The contents of this file are subject to the Mozilla Public License Version 1.1
008: * (the "License"); you may not use this file except in compliance with the License.
009: * You may obtain a copy of the License at http://www.mozilla.org/MPL/
010: *
011: * Software distributed under the License is distributed on an "AS IS" basis,
012: * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
013: * for the specific language governing rights and limitations under the License.
014: *
015: * The Original Code is 'iText, a free JAVA-PDF library'.
016: *
017: * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
018: * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
019: * All Rights Reserved.
020: * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
021: * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
022: *
023: * Contributor(s): all the names of the contributors are added in the source code
024: * where applicable.
025: *
026: * Alternatively, the contents of this file may be used under the terms of the
027: * LGPL license (the ?GNU LIBRARY GENERAL PUBLIC LICENSE?), in which case the
028: * provisions of LGPL are applicable instead of those above. If you wish to
029: * allow use of your version of this file only under the terms of the LGPL
030: * License and not to allow others to use your version of this file under
031: * the MPL, indicate your decision by deleting the provisions above and
032: * replace them with the notice and other provisions required by the LGPL.
033: * If you do not delete the provisions above, a recipient may use your version
034: * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
035: *
036: * This library is free software; you can redistribute it and/or modify it
037: * under the terms of the MPL as stated above or under the terms of the GNU
038: * Library General Public License as published by the Free Software Foundation;
039: * either version 2 of the License, or any later version.
040: *
041: * This library is distributed in the hope that it will be useful, but WITHOUT
042: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
043: * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
044: * details.
045: *
046: * If you didn't download this code from the following link, you should check if
047: * you aren't using an obsolete version:
048: * http://www.lowagie.com/iText/
049: */package com.lowagie.text.rtf;
050:
051: import java.awt.Color;
052: import java.io.ByteArrayOutputStream;
053: import java.io.IOException;
054: import java.util.Iterator;
055:
056: import com.lowagie.text.Cell;
057: import com.lowagie.text.DocumentException;
058: import com.lowagie.text.Element;
059: import com.lowagie.text.Paragraph;
060: import com.lowagie.text.Rectangle;
061:
062: /**
063: * A Helper Class for the <CODE>RtfWriter</CODE>.
064: * <P>
065: * Do not use it directly
066: *
067: * ONLY FOR USE WITH THE RtfWriter NOT with the RtfWriter2.
068: *
069: * Parts of this Class were contributed by Steffen Stundzig. Many thanks for the
070: * improvements.
071: * Updates by Benoit Wiart
072: * @deprecated Please move to the RtfWriter2 and associated classes.
073: */
074: public class RtfCell {
075: /** Constants for merging Cells */
076:
077: /** A possible value for merging */
078: private static final int MERGE_HORIZ_FIRST = 1;
079: /** A possible value for merging */
080: private static final int MERGE_VERT_FIRST = 2;
081: /** A possible value for merging */
082: private static final int MERGE_BOTH_FIRST = 3;
083: /** A possible value for merging */
084: private static final int MERGE_HORIZ_PREV = 4;
085: /** A possible value for merging */
086: private static final int MERGE_VERT_PREV = 5;
087: /** A possible value for merging */
088: private static final int MERGE_BOTH_PREV = 6;
089:
090: /**
091: * RTF Tags
092: */
093:
094: /** First cell to merge with - Horizontal */
095: private static final byte[] cellMergeFirst = "clmgf".getBytes();
096: /** First cell to merge with - Vertical */
097: private static final byte[] cellVMergeFirst = "clvmgf".getBytes();
098: /** Merge cell with previous horizontal cell */
099: private static final byte[] cellMergePrev = "clmrg".getBytes();
100: /** Merge cell with previous vertical cell */
101: private static final byte[] cellVMergePrev = "clvmrg".getBytes();
102: /** Cell content vertical alignment bottom */
103: private static final byte[] cellVerticalAlignBottom = "clvertalb"
104: .getBytes();
105: /** Cell content vertical alignment center */
106: private static final byte[] cellVerticalAlignCenter = "clvertalc"
107: .getBytes();
108: /** Cell content vertical alignment top */
109: private static final byte[] cellVerticalAlignTop = "clvertalt"
110: .getBytes();
111: /** Cell border left */
112: private static final byte[] cellBorderLeft = "clbrdrl".getBytes();
113: /** Cell border right */
114: private static final byte[] cellBorderRight = "clbrdrr".getBytes();
115: /** Cell border top */
116: private static final byte[] cellBorderTop = "clbrdrt".getBytes();
117: /** Cell border bottom */
118: private static final byte[] cellBorderBottom = "clbrdrb".getBytes();
119: /** Cell background color */
120: private static final byte[] cellBackgroundColor = "clcbpat"
121: .getBytes();
122: /** Cell width format */
123: private static final byte[] cellWidthStyle = "clftsWidth3"
124: .getBytes();
125: /** Cell width */
126: private static final byte[] cellWidthTag = "clwWidth".getBytes();
127: /** Cell right border position */
128: private static final byte[] cellRightBorder = "cellx".getBytes();
129: /** Cell is part of table */
130: protected static final byte[] cellInTable = "intbl".getBytes();
131: /** End of cell */
132: private static final byte[] cellEnd = "cell".getBytes();
133:
134: /** padding top */
135: private static final byte[] cellPaddingTop = "clpadt".getBytes();
136: /** padding top unit */
137: private static final byte[] cellPaddingTopUnit = "clpadft3"
138: .getBytes();
139: /** padding bottom */
140: private static final byte[] cellPaddingBottom = "clpadb".getBytes();
141: /** padding bottom unit */
142: private static final byte[] cellPaddingBottomUnit = "clpadfb3"
143: .getBytes();
144: /** padding left */
145: private static final byte[] cellPaddingLeft = "clpadl".getBytes();
146: /** padding left unit */
147: private static final byte[] cellPaddingLeftUnit = "clpadfl3"
148: .getBytes();
149: /** padding right */
150: private static final byte[] cellPaddingRight = "clpadr".getBytes();
151: /** padding right unit */
152: private static final byte[] cellPaddingRightUnit = "clpadfr3"
153: .getBytes();
154:
155: /** The <code>RtfWriter</code> to which this <code>RtfCell</code> belongs. */
156: private RtfWriter writer = null;
157: /** The <code>RtfTable</code> to which this <code>RtfCell</code> belongs. */
158: private RtfTable mainTable = null;
159:
160: /** Cell width */
161: private int cellWidth = 0;
162: /** Cell right border position */
163: private int cellRight = 0;
164: /** <code>Cell</code> containing the actual data */
165: private Cell store = null;
166: /** Is this an empty cell */
167: private boolean emptyCell = true;
168: /** Type of merging to do */
169: private int mergeType = 0;
170: /** cell padding, because the table only renders the left and right cell padding
171: * and not the top and bottom one
172: */
173: private int cellpadding = 0;
174:
175: /**
176: * Create a new <code>RtfCell</code>.
177: *
178: * @param writer The <code>RtfWriter</code> that this <code>RtfCell</code> belongs to
179: * @param mainTable The <code>RtfTable</code> that created the
180: * <code>RtfRow</code> that created the <code>RtfCell</code> :-)
181: */
182: public RtfCell(RtfWriter writer, RtfTable mainTable) {
183: super ();
184: this .writer = writer;
185: this .mainTable = mainTable;
186: }
187:
188: /**
189: * Import a <code>Cell</code>.
190: * <P>
191: * @param cell The <code>Cell</code> containing the data for this
192: * <code>RtfCell</code>
193: * @param cellLeft The position of the left border
194: * @param cellWidth The default width of a cell
195: * @param x The column index of this <code>RtfCell</code>
196: * @param y The row index of this <code>RtfCell</code>
197: * @param cellpadding the cellpadding
198: * @return the position of the right side of the cell
199: */
200: public int importCell(Cell cell, int cellLeft, int cellWidth,
201: int x, int y, int cellpadding) {
202: this .cellpadding = cellpadding;
203:
204: // set this value in any case
205: this .cellWidth = cellWidth;
206: if (cell == null) {
207: cellRight = cellLeft + cellWidth;
208: return cellRight;
209: }
210: if (cell.getWidth() != 0) {
211: this .cellWidth = (int) (cell.getWidth() * RtfWriter.TWIPSFACTOR);
212: }
213: cellRight = cellLeft + this .cellWidth;
214: store = cell;
215: emptyCell = false;
216: if (cell.getColspan() > 1) {
217: if (cell.getRowspan() > 1) {
218: mergeType = MERGE_BOTH_FIRST;
219: for (int i = y; i < y + cell.getRowspan(); i++) {
220: if (i > y)
221: mainTable.setMerge(x, i, MERGE_VERT_PREV, this );
222: for (int j = x + 1; j < x + cell.getColspan(); j++) {
223: mainTable.setMerge(j, i, MERGE_BOTH_PREV, this );
224: }
225: }
226: } else {
227: mergeType = MERGE_HORIZ_FIRST;
228: for (int i = x + 1; i < x + cell.getColspan(); i++) {
229: mainTable.setMerge(i, y, MERGE_HORIZ_PREV, this );
230: }
231: }
232: } else if (cell.getRowspan() > 1) {
233: mergeType = MERGE_VERT_FIRST;
234: for (int i = y + 1; i < y + cell.getRowspan(); i++) {
235: mainTable.setMerge(x, i, MERGE_VERT_PREV, this );
236: }
237: }
238: return cellRight;
239: }
240:
241: /**
242: * Write the properties of the <code>RtfCell</code>.
243: *
244: * @param os The <code>OutputStream</code> to which to write the properties
245: * of the <code>RtfCell</code> to.
246: * @return true if writing the cell settings succeeded
247: * @throws DocumentException
248: */
249: public boolean writeCellSettings(ByteArrayOutputStream os) {
250: try {
251: float lWidth, tWidth, rWidth, bWidth;
252: byte[] lStyle, tStyle, rStyle, bStyle;
253:
254: if (store instanceof RtfTableCell) {
255: RtfTableCell c = (RtfTableCell) store;
256: lWidth = c.leftBorderWidth();
257: tWidth = c.topBorderWidth();
258: rWidth = c.rightBorderWidth();
259: bWidth = c.bottomBorderWidth();
260: lStyle = RtfTableCell.getStyleControlWord(c
261: .leftBorderStyle());
262: tStyle = RtfTableCell.getStyleControlWord(c
263: .topBorderStyle());
264: rStyle = RtfTableCell.getStyleControlWord(c
265: .rightBorderStyle());
266: bStyle = RtfTableCell.getStyleControlWord(c
267: .bottomBorderStyle());
268: } else {
269: lWidth = tWidth = rWidth = bWidth = store
270: .getBorderWidth();
271: lStyle = tStyle = rStyle = bStyle = RtfRow.tableBorder;
272: }
273:
274: if (mergeType == MERGE_HORIZ_PREV
275: || mergeType == MERGE_BOTH_PREV) {
276: return true;
277: }
278: switch (mergeType) {
279: case MERGE_VERT_FIRST:
280: os.write(RtfWriter.escape);
281: os.write(cellVMergeFirst);
282: break;
283: case MERGE_BOTH_FIRST:
284: os.write(RtfWriter.escape);
285: os.write(cellVMergeFirst);
286: break;
287: case MERGE_HORIZ_PREV:
288: os.write(RtfWriter.escape);
289: os.write(cellMergePrev);
290: break;
291: case MERGE_VERT_PREV:
292: os.write(RtfWriter.escape);
293: os.write(cellVMergePrev);
294: break;
295: case MERGE_BOTH_PREV:
296: os.write(RtfWriter.escape);
297: os.write(cellMergeFirst);
298: break;
299: }
300: switch (store.getVerticalAlignment()) {
301: case Element.ALIGN_BOTTOM:
302: os.write(RtfWriter.escape);
303: os.write(cellVerticalAlignBottom);
304: break;
305: case Element.ALIGN_CENTER:
306: case Element.ALIGN_MIDDLE:
307: os.write(RtfWriter.escape);
308: os.write(cellVerticalAlignCenter);
309: break;
310: case Element.ALIGN_TOP:
311: os.write(RtfWriter.escape);
312: os.write(cellVerticalAlignTop);
313: break;
314: }
315:
316: if (((store.getBorder() & Rectangle.LEFT) == Rectangle.LEFT)
317: && (lWidth > 0)) {
318: os.write(RtfWriter.escape);
319: os.write(cellBorderLeft);
320: os.write(RtfWriter.escape);
321: os.write(lStyle);
322: os.write(RtfWriter.escape);
323: os.write(RtfRow.tableBorderWidth);
324: writeInt(os, (int) (lWidth * RtfWriter.TWIPSFACTOR));
325: os.write(RtfWriter.escape);
326: os.write(RtfRow.tableBorderColor);
327: if (store.getBorderColor() == null)
328: writeInt(os, writer.addColor(new Color(0, 0, 0)));
329: else
330: writeInt(os, writer
331: .addColor(store.getBorderColor()));
332: os.write((byte) '\n');
333: }
334: if (((store.getBorder() & Rectangle.TOP) == Rectangle.TOP)
335: && (tWidth > 0)) {
336: os.write(RtfWriter.escape);
337: os.write(cellBorderTop);
338: os.write(RtfWriter.escape);
339: os.write(tStyle);
340: os.write(RtfWriter.escape);
341: os.write(RtfRow.tableBorderWidth);
342: writeInt(os, (int) (tWidth * RtfWriter.TWIPSFACTOR));
343: os.write(RtfWriter.escape);
344: os.write(RtfRow.tableBorderColor);
345: if (store.getBorderColor() == null)
346: writeInt(os, writer.addColor(new Color(0, 0, 0)));
347: else
348: writeInt(os, writer
349: .addColor(store.getBorderColor()));
350: os.write((byte) '\n');
351: }
352: if (((store.getBorder() & Rectangle.BOTTOM) == Rectangle.BOTTOM)
353: && (bWidth > 0)) {
354: os.write(RtfWriter.escape);
355: os.write(cellBorderBottom);
356: os.write(RtfWriter.escape);
357: os.write(bStyle);
358: os.write(RtfWriter.escape);
359: os.write(RtfRow.tableBorderWidth);
360: writeInt(os, (int) (bWidth * RtfWriter.TWIPSFACTOR));
361: os.write(RtfWriter.escape);
362: os.write(RtfRow.tableBorderColor);
363: if (store.getBorderColor() == null)
364: writeInt(os, writer.addColor(new Color(0, 0, 0)));
365: else
366: writeInt(os, writer
367: .addColor(store.getBorderColor()));
368: os.write((byte) '\n');
369: }
370: if (((store.getBorder() & Rectangle.RIGHT) == Rectangle.RIGHT)
371: && (rWidth > 0)) {
372: os.write(RtfWriter.escape);
373: os.write(cellBorderRight);
374: os.write(RtfWriter.escape);
375: os.write(rStyle);
376: os.write(RtfWriter.escape);
377: os.write(RtfRow.tableBorderWidth);
378: writeInt(os, (int) (rWidth * RtfWriter.TWIPSFACTOR));
379: os.write(RtfWriter.escape);
380: os.write(RtfRow.tableBorderColor);
381: if (store.getBorderColor() == null)
382: writeInt(os, writer.addColor(new Color(0, 0, 0)));
383: else
384: writeInt(os, writer
385: .addColor(store.getBorderColor()));
386: os.write((byte) '\n');
387: }
388: os.write(RtfWriter.escape);
389: os.write(cellBackgroundColor);
390: if (store.getBackgroundColor() == null) {
391: writeInt(os, writer.addColor(new Color(255, 255, 255)));
392: } else {
393: writeInt(os, writer
394: .addColor(store.getBackgroundColor()));
395: }
396: os.write((byte) '\n');
397: os.write(RtfWriter.escape);
398: os.write(cellWidthStyle);
399: os.write((byte) '\n');
400: os.write(RtfWriter.escape);
401: os.write(cellWidthTag);
402: writeInt(os, cellWidth);
403: os.write((byte) '\n');
404: if (cellpadding > 0) {
405: // values
406: os.write(RtfWriter.escape);
407: os.write(cellPaddingLeft);
408: writeInt(os, cellpadding / 2);
409: os.write(RtfWriter.escape);
410: os.write(cellPaddingTop);
411: writeInt(os, cellpadding / 2);
412: os.write(RtfWriter.escape);
413: os.write(cellPaddingRight);
414: writeInt(os, cellpadding / 2);
415: os.write(RtfWriter.escape);
416: os.write(cellPaddingBottom);
417: writeInt(os, cellpadding / 2);
418: // unit
419: os.write(RtfWriter.escape);
420: os.write(cellPaddingLeftUnit);
421: os.write(RtfWriter.escape);
422: os.write(cellPaddingTopUnit);
423: os.write(RtfWriter.escape);
424: os.write(cellPaddingRightUnit);
425: os.write(RtfWriter.escape);
426: os.write(cellPaddingBottomUnit);
427: }
428: os.write(RtfWriter.escape);
429: os.write(cellRightBorder);
430: writeInt(os, cellRight);
431: } catch (IOException e) {
432: return false;
433: }
434: return true;
435: }
436:
437: /**
438: * Write the content of the <code>RtfCell</code>.
439: *
440: * @param os The <code>OutputStream</code> to which to write the content of
441: * the <code>RtfCell</code> to.
442: * @return true if writing the cell content succeeded
443: * @throws DocumentException
444: */
445: public boolean writeCellContent(ByteArrayOutputStream os)
446: throws DocumentException {
447: try {
448: if (mergeType == MERGE_HORIZ_PREV
449: || mergeType == MERGE_BOTH_PREV) {
450: return true;
451: }
452:
453: if (!emptyCell) {
454: Iterator cellIterator = store.getElements();
455: Paragraph container = null;
456: while (cellIterator.hasNext()) {
457: Element element = (Element) cellIterator.next();
458: // should we wrap it in a paragraph
459: if (!(element instanceof Paragraph)) {
460: if (container != null) {
461: container.add(element);
462: } else {
463: container = new Paragraph();
464: container.setAlignment(store
465: .getHorizontalAlignment());
466: container.add(element);
467: }
468: } else {
469: if (container != null) {
470: writer.addElement(container, os);
471: container = null;
472: }
473:
474: // if horizontal alignment is undefined overwrite
475: // with that of enclosing cell
476: if (element instanceof Paragraph
477: && ((Paragraph) element).getAlignment() == Element.ALIGN_UNDEFINED) {
478: ((Paragraph) element).setAlignment(store
479: .getHorizontalAlignment());
480: }
481: writer.addElement(element, os);
482: if (element.type() == Element.PARAGRAPH
483: && cellIterator.hasNext()) {
484: os.write(RtfWriter.escape);
485: os.write(RtfWriter.paragraph);
486: }
487: }
488: }
489: if (container != null) {
490: writer.addElement(container, os);
491: container = null;
492: }
493: } else {
494: os.write(RtfWriter.escape);
495: os.write(RtfWriter.paragraphDefaults);
496: os.write(RtfWriter.escape);
497: os.write(cellInTable);
498: }
499: os.write(RtfWriter.escape);
500: os.write(cellEnd);
501: } catch (IOException e) {
502: return false;
503: }
504: return true;
505: }
506:
507: /**
508: * Sets the merge type and the <code>RtfCell</code> with which this
509: * <code>RtfCell</code> is to be merged.
510: *
511: * @param mergeType The merge type specifies the kind of merge to be applied
512: * (MERGE_HORIZ_PREV, MERGE_VERT_PREV, MERGE_BOTH_PREV)
513: * @param mergeCell The <code>RtfCell</code> that the cell at x and y is to
514: * be merged with
515: */
516: public void setMerge(int mergeType, RtfCell mergeCell) {
517: this .mergeType = mergeType;
518: store = mergeCell.getStore();
519: }
520:
521: /**
522: * Get the <code>Cell</code> with the actual content.
523: *
524: * @return <code>Cell</code> which is contained in the <code>RtfCell</code>
525: */
526: public Cell getStore() {
527: return store;
528: }
529:
530: /**
531: * Get the with of this <code>RtfCell</code>
532: *
533: * @return Width of the current <code>RtfCell</code>
534: */
535: public int getCellWidth() {
536: return cellWidth;
537: }
538:
539: /**
540: * sets the width of the cell
541: * @param value a width
542: */
543: public void setCellWidth(int value) {
544: cellWidth = value;
545: }
546:
547: /**
548: * Get the position of the right border of this <code>RtfCell</code>.
549: * @return position of the right border
550: */
551: public int getCellRight() {
552: return cellRight;
553: }
554:
555: /**
556: * Sets the right position of the cell
557: * @param value a cell position
558: */
559: public void setCellRight(int value) {
560: cellRight = value;
561: }
562:
563: /**
564: * Write an Integer to the Outputstream.
565: *
566: * @param out The <code>OutputStream</code> to be written to.
567: * @param i The int to be written.
568: * @throws IOException
569: */
570: private void writeInt(ByteArrayOutputStream out, int i)
571: throws IOException {
572: out.write(Integer.toString(i).getBytes());
573: }
574: }
|