001/* 002 * $Id: Chunk.java 4847 2011-05-05 19:46:13Z redlab_b $ 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; 045 046import java.net.URL; 047import java.util.List; 048import java.util.ArrayList; 049import java.util.HashMap; 050 051import com.itextpdf.text.error_messages.MessageLocalization; 052import com.itextpdf.text.pdf.HyphenationEvent; 053import com.itextpdf.text.pdf.PdfAction; 054import com.itextpdf.text.pdf.PdfAnnotation; 055import com.itextpdf.text.pdf.PdfContentByte; 056import com.itextpdf.text.pdf.draw.DrawInterface; 057 058/** 059 * This is the smallest significant part of text that can be added to a 060 * document. 061 * <P> 062 * Most elements can be divided in one or more <CODE>Chunk</CODE>s. A chunk 063 * is a <CODE>String</CODE> with a certain <CODE>Font</CODE>. All other 064 * layout parameters should be defined in the object to which this chunk of text 065 * is added. 066 * <P> 067 * Example: <BLOCKQUOTE> 068 * 069 * <PRE> 070 * 071 * <STRONG>Chunk chunk = new Chunk("Hello world", 072 * FontFactory.getFont(FontFactory.COURIER, 20, Font.ITALIC, new BaseColor(255, 0, 073 * 0))); </STRONG> document.add(chunk); 074 * 075 * </PRE> 076 * 077 * </BLOCKQUOTE> 078 */ 079 080public class Chunk implements Element { 081 082 // public static membervariables 083 084 /** The character stand in for an image or a separator. */ 085 public static final String OBJECT_REPLACEMENT_CHARACTER = "\ufffc"; 086 087 /** This is a Chunk containing a newline. */ 088 public static final Chunk NEWLINE = new Chunk("\n"); 089 090 /** This is a Chunk containing a newpage. */ 091 public static final Chunk NEXTPAGE = new Chunk(""); 092 static { 093 NEXTPAGE.setNewPage(); 094 } 095 096 // member variables 097 098 /** This is the content of this chunk of text. */ 099 protected StringBuffer content = null; 100 101 /** This is the <CODE>Font</CODE> of this chunk of text. */ 102 protected Font font = null; 103 104 /** Contains some of the attributes for this Chunk. */ 105 protected HashMap<String, Object> attributes = null; 106 107 // constructors 108 109 /** 110 * Empty constructor. 111 */ 112 public Chunk() { 113 this.content = new StringBuffer(); 114 this.font = new Font(); 115 } 116 117 /** 118 * A <CODE>Chunk</CODE> copy constructor. 119 * @param ck the <CODE>Chunk</CODE> to be copied 120 */ 121 public Chunk(final Chunk ck) { 122 if (ck.content != null) { 123 content = new StringBuffer(ck.content.toString()); 124 } 125 if (ck.font != null) { 126 font = new Font(ck.font); 127 } 128 if (ck.attributes != null) { 129 attributes = new HashMap<String, Object>(ck.attributes); 130 } 131 } 132 133 /** 134 * Constructs a chunk of text with a certain content and a certain <CODE> 135 * Font</CODE>. 136 * 137 * @param content 138 * the content 139 * @param font 140 * the font 141 */ 142 public Chunk(final String content, final Font font) { 143 this.content = new StringBuffer(content); 144 this.font = font; 145 } 146 147 /** 148 * Constructs a chunk of text with a certain content, without specifying a 149 * <CODE>Font</CODE>. 150 * 151 * @param content 152 * the content 153 */ 154 public Chunk(final String content) { 155 this(content, new Font()); 156 } 157 158 /** 159 * Constructs a chunk of text with a char and a certain <CODE>Font</CODE>. 160 * 161 * @param c 162 * the content 163 * @param font 164 * the font 165 */ 166 public Chunk(final char c, final Font font) { 167 this.content = new StringBuffer(); 168 this.content.append(c); 169 this.font = font; 170 } 171 172 /** 173 * Constructs a chunk of text with a char, without specifying a <CODE>Font 174 * </CODE>. 175 * 176 * @param c 177 * the content 178 */ 179 public Chunk(final char c) { 180 this(c, new Font()); 181 } 182 183 /** 184 * Constructs a chunk containing an <CODE>Image</CODE>. 185 * 186 * @param image 187 * the image 188 * @param offsetX 189 * the image offset in the x direction 190 * @param offsetY 191 * the image offset in the y direction 192 */ 193 public Chunk(final Image image, final float offsetX, final float offsetY) { 194 this(OBJECT_REPLACEMENT_CHARACTER, new Font()); 195 Image copyImage = Image.getInstance(image); 196 copyImage.setAbsolutePosition(Float.NaN, Float.NaN); 197 setAttribute(IMAGE, new Object[] { copyImage, new Float(offsetX), 198 new Float(offsetY), Boolean.FALSE }); 199 } 200 201 /** 202 * Key for drawInterface of the Separator. 203 * @since 2.1.2 204 */ 205 public static final String SEPARATOR = "SEPARATOR"; 206 207 /** 208 * Creates a separator Chunk. 209 * Note that separator chunks can't be used in combination with tab chunks! 210 * @param separator the drawInterface to use to draw the separator. 211 * @since 2.1.2 212 */ 213 public Chunk(final DrawInterface separator) { 214 this(separator, false); 215 } 216 217 /** 218 * Creates a separator Chunk. 219 * Note that separator chunks can't be used in combination with tab chunks! 220 * @param separator the drawInterface to use to draw the separator. 221 * @param vertical true if this is a vertical separator 222 * @since 2.1.2 223 */ 224 public Chunk(final DrawInterface separator, final boolean vertical) { 225 this(OBJECT_REPLACEMENT_CHARACTER, new Font()); 226 setAttribute(SEPARATOR, new Object[] {separator, Boolean.valueOf(vertical)}); 227 } 228 229 /** 230 * Key for drawInterface of the tab. 231 * @since 2.1.2 232 */ 233 public static final String TAB = "TAB"; 234 235 /** 236 * Creates a tab Chunk. 237 * Note that separator chunks can't be used in combination with tab chunks! 238 * @param separator the drawInterface to use to draw the tab. 239 * @param tabPosition an X coordinate that will be used as start position for the next Chunk. 240 * @since 2.1.2 241 */ 242 public Chunk(final DrawInterface separator, final float tabPosition) { 243 this(separator, tabPosition, false); 244 } 245 246 /** 247 * Creates a tab Chunk. 248 * Note that separator chunks can't be used in combination with tab chunks! 249 * @param separator the drawInterface to use to draw the tab. 250 * @param tabPosition an X coordinate that will be used as start position for the next Chunk. 251 * @param newline if true, a newline will be added if the tabPosition has already been reached. 252 * @since 2.1.2 253 */ 254 public Chunk(final DrawInterface separator, final float tabPosition, final boolean newline) { 255 this(OBJECT_REPLACEMENT_CHARACTER, new Font()); 256 if (tabPosition < 0) { 257 throw new IllegalArgumentException(MessageLocalization.getComposedMessage("a.tab.position.may.not.be.lower.than.0.yours.is.1", String.valueOf(tabPosition))); 258 } 259 setAttribute(TAB, new Object[] {separator, new Float(tabPosition), Boolean.valueOf(newline), new Float(0)}); 260 } 261 262 /** 263 * Constructs a chunk containing an <CODE>Image</CODE>. 264 * 265 * @param image 266 * the image 267 * @param offsetX 268 * the image offset in the x direction 269 * @param offsetY 270 * the image offset in the y direction 271 * @param changeLeading 272 * true if the leading has to be adapted to the image 273 */ 274 public Chunk(final Image image, final float offsetX, final float offsetY, 275 final boolean changeLeading) { 276 this(OBJECT_REPLACEMENT_CHARACTER, new Font()); 277 setAttribute(IMAGE, new Object[] { image, new Float(offsetX), 278 new Float(offsetY), Boolean.valueOf(changeLeading) }); 279 } 280 281 // implementation of the Element-methods 282 283 /** 284 * Processes the element by adding it (or the different parts) to an <CODE> 285 * ElementListener</CODE>. 286 * 287 * @param listener 288 * an <CODE>ElementListener</CODE> 289 * @return <CODE>true</CODE> if the element was processed successfully 290 */ 291 public boolean process(final ElementListener listener) { 292 try { 293 return listener.add(this); 294 } catch (DocumentException de) { 295 return false; 296 } 297 } 298 299 /** 300 * Gets the type of the text element. 301 * 302 * @return a type 303 */ 304 public int type() { 305 return Element.CHUNK; 306 } 307 308 /** 309 * Gets all the chunks in this element. 310 * 311 * @return an <CODE>ArrayList</CODE> 312 */ 313 public List<Chunk> getChunks() { 314 List<Chunk> tmp = new ArrayList<Chunk>(); 315 tmp.add(this); 316 return tmp; 317 } 318 319 // methods that change the member variables 320 321 /** 322 * appends some text to this <CODE>Chunk</CODE>. 323 * 324 * @param string 325 * <CODE>String</CODE> 326 * @return a <CODE>StringBuffer</CODE> 327 */ 328 public StringBuffer append(final String string) { 329 return content.append(string); 330 } 331 332 /** 333 * Sets the font of this <CODE>Chunk</CODE>. 334 * 335 * @param font 336 * a <CODE>Font</CODE> 337 */ 338 public void setFont(final Font font) { 339 this.font = font; 340 } 341 342 // methods to retrieve information 343 344 /** 345 * Gets the font of this <CODE>Chunk</CODE>. 346 * 347 * @return a <CODE>Font</CODE> 348 */ 349 public Font getFont() { 350 return font; 351 } 352 353 /** 354 * Returns the content of this <CODE>Chunk</CODE>. 355 * 356 * @return a <CODE>String</CODE> 357 */ 358 public String getContent() { 359 return content.toString(); 360 } 361 362 /** 363 * Returns the content of this <CODE>Chunk</CODE>. 364 * 365 * @return a <CODE>String</CODE> 366 */ 367 @Override 368 public String toString() { 369 return getContent(); 370 } 371 372 /** 373 * Checks is this <CODE>Chunk</CODE> is empty. 374 * 375 * @return <CODE>false</CODE> if the Chunk contains other characters than 376 * space. 377 */ 378 public boolean isEmpty() { 379 return content.toString().trim().length() == 0 380 && content.toString().indexOf("\n") == -1 381 && attributes == null; 382 } 383 384 /** 385 * Gets the width of the Chunk in points. 386 * 387 * @return a width in points 388 */ 389 public float getWidthPoint() { 390 if (getImage() != null) { 391 return getImage().getScaledWidth(); 392 } 393 return font.getCalculatedBaseFont(true).getWidthPoint(getContent(), 394 font.getCalculatedSize()) 395 * getHorizontalScaling(); 396 } 397 398 // attributes 399 400 /** 401 * Checks the attributes of this <CODE>Chunk</CODE>. 402 * 403 * @return false if there aren't any. 404 */ 405 406 public boolean hasAttributes() { 407 return attributes != null; 408 } 409 410 /** 411 * Gets the attributes for this <CODE>Chunk</CODE>. 412 * <P> 413 * It may be null. 414 * 415 * @return the attributes for this <CODE>Chunk</CODE> 416 */ 417 418 public HashMap<String, Object> getAttributes() { 419 return attributes; 420 } 421 422 /** 423 * Sets the attributes all at once. 424 * @param attributes the attributes of a Chunk 425 */ 426 public void setAttributes(final HashMap<String, Object> attributes) { 427 this.attributes = attributes; 428 } 429 430 /** 431 * Sets an arbitrary attribute. 432 * 433 * @param name 434 * the key for the attribute 435 * @param obj 436 * the value of the attribute 437 * @return this <CODE>Chunk</CODE> 438 */ 439 440 private Chunk setAttribute(final String name, final Object obj) { 441 if (attributes == null) 442 attributes = new HashMap<String, Object>(); 443 attributes.put(name, obj); 444 return this; 445 } 446 447 // the attributes are ordered as they appear in the book 'iText in Action' 448 449 /** Key for text horizontal scaling. */ 450 public static final String HSCALE = "HSCALE"; 451 452 /** 453 * Sets the text horizontal scaling. A value of 1 is normal and a value of 454 * 0.5f shrinks the text to half it's width. 455 * 456 * @param scale 457 * the horizontal scaling factor 458 * @return this <CODE>Chunk</CODE> 459 */ 460 public Chunk setHorizontalScaling(final float scale) { 461 return setAttribute(HSCALE, new Float(scale)); 462 } 463 464 /** 465 * Gets the horizontal scaling. 466 * 467 * @return a percentage in float 468 */ 469 public float getHorizontalScaling() { 470 if (attributes == null) 471 return 1f; 472 Float f = (Float) attributes.get(HSCALE); 473 if (f == null) 474 return 1f; 475 return f.floatValue(); 476 } 477 478 /** Key for underline. */ 479 public static final String UNDERLINE = "UNDERLINE"; 480 481 /** 482 * Sets an horizontal line that can be an underline or a strikethrough. 483 * Actually, the line can be anywhere vertically and has always the <CODE> 484 * Chunk</CODE> width. Multiple call to this method will produce multiple 485 * lines. 486 * 487 * @param thickness 488 * the absolute thickness of the line 489 * @param yPosition 490 * the absolute y position relative to the baseline 491 * @return this <CODE>Chunk</CODE> 492 */ 493 public Chunk setUnderline(final float thickness, final float yPosition) { 494 return setUnderline(null, thickness, 0f, yPosition, 0f, 495 PdfContentByte.LINE_CAP_BUTT); 496 } 497 498 /** 499 * Sets an horizontal line that can be an underline or a strikethrough. 500 * Actually, the line can be anywhere vertically and has always the <CODE> 501 * Chunk</CODE> width. Multiple call to this method will produce multiple 502 * lines. 503 * 504 * @param color 505 * the color of the line or <CODE>null</CODE> to follow the 506 * text color 507 * @param thickness 508 * the absolute thickness of the line 509 * @param thicknessMul 510 * the thickness multiplication factor with the font size 511 * @param yPosition 512 * the absolute y position relative to the baseline 513 * @param yPositionMul 514 * the position multiplication factor with the font size 515 * @param cap 516 * the end line cap. Allowed values are 517 * PdfContentByte.LINE_CAP_BUTT, PdfContentByte.LINE_CAP_ROUND 518 * and PdfContentByte.LINE_CAP_PROJECTING_SQUARE 519 * @return this <CODE>Chunk</CODE> 520 */ 521 public Chunk setUnderline(final BaseColor color, final float thickness, final float thicknessMul, 522 final float yPosition, final float yPositionMul, final int cap) { 523 if (attributes == null) 524 attributes = new HashMap<String, Object>(); 525 Object obj[] = { 526 color, 527 new float[] { thickness, thicknessMul, yPosition, yPositionMul, cap } }; 528 Object unders[][] = Utilities.addToArray((Object[][]) attributes.get(UNDERLINE), 529 obj); 530 return setAttribute(UNDERLINE, unders); 531 } 532 533 /** Key for sub/superscript. */ 534 public static final String SUBSUPSCRIPT = "SUBSUPSCRIPT"; 535 536 /** 537 * Sets the text displacement relative to the baseline. Positive values rise 538 * the text, negative values lower the text. 539 * <P> 540 * It can be used to implement sub/superscript. 541 * 542 * @param rise 543 * the displacement in points 544 * @return this <CODE>Chunk</CODE> 545 */ 546 547 public Chunk setTextRise(final float rise) { 548 return setAttribute(SUBSUPSCRIPT, new Float(rise)); 549 } 550 551 /** 552 * Gets the text displacement relative to the baseline. 553 * 554 * @return a displacement in points 555 */ 556 public float getTextRise() { 557 if (attributes != null && attributes.containsKey(SUBSUPSCRIPT)) { 558 Float f = (Float) attributes.get(SUBSUPSCRIPT); 559 return f.floatValue(); 560 } 561 return 0.0f; 562 } 563 564 /** Key for text skewing. */ 565 public static final String SKEW = "SKEW"; 566 567 /** 568 * Skews the text to simulate italic and other effects. Try <CODE>alpha=0 569 * </CODE> and <CODE>beta=12</CODE>. 570 * 571 * @param alpha 572 * the first angle in degrees 573 * @param beta 574 * the second angle in degrees 575 * @return this <CODE>Chunk</CODE> 576 */ 577 public Chunk setSkew(float alpha, float beta) { 578 alpha = (float) Math.tan(alpha * Math.PI / 180); 579 beta = (float) Math.tan(beta * Math.PI / 180); 580 return setAttribute(SKEW, new float[] { alpha, beta }); 581 } 582 583 /** Key for background. */ 584 public static final String BACKGROUND = "BACKGROUND"; 585 586 /** 587 * Sets the color of the background <CODE>Chunk</CODE>. 588 * 589 * @param color 590 * the color of the background 591 * @return this <CODE>Chunk</CODE> 592 */ 593 public Chunk setBackground(final BaseColor color) { 594 return setBackground(color, 0, 0, 0, 0); 595 } 596 597 /** 598 * Sets the color and the size of the background <CODE>Chunk</CODE>. 599 * 600 * @param color 601 * the color of the background 602 * @param extraLeft 603 * increase the size of the rectangle in the left 604 * @param extraBottom 605 * increase the size of the rectangle in the bottom 606 * @param extraRight 607 * increase the size of the rectangle in the right 608 * @param extraTop 609 * increase the size of the rectangle in the top 610 * @return this <CODE>Chunk</CODE> 611 */ 612 public Chunk setBackground(final BaseColor color, final float extraLeft, final float extraBottom, 613 final float extraRight, final float extraTop) { 614 return setAttribute(BACKGROUND, new Object[] { color, 615 new float[] { extraLeft, extraBottom, extraRight, extraTop } }); 616 } 617 618 /** Key for text rendering mode. */ 619 public static final String TEXTRENDERMODE = "TEXTRENDERMODE"; 620 621 /** 622 * Sets the text rendering mode. It can outline text, simulate bold and make 623 * text invisible. 624 * 625 * @param mode 626 * the text rendering mode. It can be <CODE> 627 * PdfContentByte.TEXT_RENDER_MODE_FILL</CODE>,<CODE> 628 * PdfContentByte.TEXT_RENDER_MODE_STROKE</CODE>,<CODE> 629 * PdfContentByte.TEXT_RENDER_MODE_FILL_STROKE</CODE> and <CODE> 630 * PdfContentByte.TEXT_RENDER_MODE_INVISIBLE</CODE>. 631 * @param strokeWidth 632 * the stroke line width for the modes <CODE> 633 * PdfContentByte.TEXT_RENDER_MODE_STROKE</CODE> and <CODE> 634 * PdfContentByte.TEXT_RENDER_MODE_FILL_STROKE</CODE>. 635 * @param strokeColor 636 * the stroke color or <CODE>null</CODE> to follow the text 637 * color 638 * @return this <CODE>Chunk</CODE> 639 */ 640 public Chunk setTextRenderMode(final int mode, final float strokeWidth, 641 final BaseColor strokeColor) { 642 return setAttribute(TEXTRENDERMODE, new Object[] { Integer.valueOf(mode), 643 new Float(strokeWidth), strokeColor }); 644 } 645 646 /** Key for split character. */ 647 public static final String SPLITCHARACTER = "SPLITCHARACTER"; 648 649 /** 650 * Sets the split characters. 651 * 652 * @param splitCharacter 653 * the <CODE>SplitCharacter</CODE> interface 654 * @return this <CODE>Chunk</CODE> 655 */ 656 657 public Chunk setSplitCharacter(final SplitCharacter splitCharacter) { 658 return setAttribute(SPLITCHARACTER, splitCharacter); 659 } 660 661 /** Key for hyphenation. */ 662 public static final String HYPHENATION = "HYPHENATION"; 663 664 /** 665 * sets the hyphenation engine to this <CODE>Chunk</CODE>. 666 * 667 * @param hyphenation 668 * the hyphenation engine 669 * @return this <CODE>Chunk</CODE> 670 */ 671 public Chunk setHyphenation(final HyphenationEvent hyphenation) { 672 return setAttribute(HYPHENATION, hyphenation); 673 } 674 675 /** Key for remote goto. */ 676 public static final String REMOTEGOTO = "REMOTEGOTO"; 677 678 /** 679 * Sets a goto for a remote destination for this <CODE>Chunk</CODE>. 680 * 681 * @param filename 682 * the file name of the destination document 683 * @param name 684 * the name of the destination to go to 685 * @return this <CODE>Chunk</CODE> 686 */ 687 688 public Chunk setRemoteGoto(final String filename, final String name) { 689 return setAttribute(REMOTEGOTO, new Object[] { filename, name }); 690 } 691 692 /** 693 * Sets a goto for a remote destination for this <CODE>Chunk</CODE>. 694 * 695 * @param filename 696 * the file name of the destination document 697 * @param page 698 * the page of the destination to go to. First page is 1 699 * @return this <CODE>Chunk</CODE> 700 */ 701 702 public Chunk setRemoteGoto(final String filename, final int page) { 703 return setAttribute(REMOTEGOTO, new Object[] { filename, 704 Integer.valueOf(page) }); 705 } 706 707 /** Key for local goto. */ 708 public static final String LOCALGOTO = "LOCALGOTO"; 709 710 /** 711 * Sets a local goto for this <CODE>Chunk</CODE>. 712 * <P> 713 * There must be a local destination matching the name. 714 * 715 * @param name 716 * the name of the destination to go to 717 * @return this <CODE>Chunk</CODE> 718 */ 719 720 public Chunk setLocalGoto(final String name) { 721 return setAttribute(LOCALGOTO, name); 722 } 723 724 /** Key for local destination. */ 725 public static final String LOCALDESTINATION = "LOCALDESTINATION"; 726 727 /** 728 * Sets a local destination for this <CODE>Chunk</CODE>. 729 * 730 * @param name 731 * the name for this destination 732 * @return this <CODE>Chunk</CODE> 733 */ 734 public Chunk setLocalDestination(final String name) { 735 return setAttribute(LOCALDESTINATION, name); 736 } 737 738 /** Key for generic tag. */ 739 public static final String GENERICTAG = "GENERICTAG"; 740 741 /** 742 * Sets the generic tag <CODE>Chunk</CODE>. 743 * <P> 744 * The text for this tag can be retrieved with <CODE>PdfPageEvent</CODE>. 745 * 746 * @param text 747 * the text for the tag 748 * @return this <CODE>Chunk</CODE> 749 */ 750 751 public Chunk setGenericTag(final String text) { 752 return setAttribute(GENERICTAG, text); 753 } 754 755 /** Key for image. */ 756 public static final String IMAGE = "IMAGE"; 757 758 /** 759 * Returns the image. 760 * 761 * @return the image 762 */ 763 764 public Image getImage() { 765 if (attributes == null) 766 return null; 767 Object obj[] = (Object[]) attributes.get(Chunk.IMAGE); 768 if (obj == null) 769 return null; 770 else { 771 return (Image) obj[0]; 772 } 773 } 774 775 /** Key for Action. */ 776 public static final String ACTION = "ACTION"; 777 778 /** 779 * Sets an action for this <CODE>Chunk</CODE>. 780 * 781 * @param action 782 * the action 783 * @return this <CODE>Chunk</CODE> 784 */ 785 786 public Chunk setAction(final PdfAction action) { 787 return setAttribute(ACTION, action); 788 } 789 790 /** 791 * Sets an anchor for this <CODE>Chunk</CODE>. 792 * 793 * @param url 794 * the <CODE>URL</CODE> to link to 795 * @return this <CODE>Chunk</CODE> 796 */ 797 798 public Chunk setAnchor(final URL url) { 799 return setAttribute(ACTION, new PdfAction(url.toExternalForm())); 800 } 801 802 /** 803 * Sets an anchor for this <CODE>Chunk</CODE>. 804 * 805 * @param url 806 * the url to link to 807 * @return this <CODE>Chunk</CODE> 808 */ 809 810 public Chunk setAnchor(final String url) { 811 return setAttribute(ACTION, new PdfAction(url)); 812 } 813 814 /** Key for newpage. */ 815 public static final String NEWPAGE = "NEWPAGE"; 816 817 /** 818 * Sets a new page tag.. 819 * 820 * @return this <CODE>Chunk</CODE> 821 */ 822 823 public Chunk setNewPage() { 824 return setAttribute(NEWPAGE, null); 825 } 826 827 /** Key for annotation. */ 828 public static final String PDFANNOTATION = "PDFANNOTATION"; 829 830 /** 831 * Sets a generic annotation to this <CODE>Chunk</CODE>. 832 * 833 * @param annotation 834 * the annotation 835 * @return this <CODE>Chunk</CODE> 836 */ 837 public Chunk setAnnotation(final PdfAnnotation annotation) { 838 return setAttribute(PDFANNOTATION, annotation); 839 } 840 841 /** 842 * @see com.itextpdf.text.Element#isContent() 843 * @since iText 2.0.8 844 */ 845 public boolean isContent() { 846 return true; 847 } 848 849 /** 850 * @see com.itextpdf.text.Element#isNestable() 851 * @since iText 2.0.8 852 */ 853 public boolean isNestable() { 854 return true; 855 } 856 857 /** 858 * Returns the hyphenation (if present). 859 * @return the HypenationEvent of this Chunk 860 * @since 2.1.2 861 */ 862 public HyphenationEvent getHyphenation() { 863 if (attributes == null) return null; 864 return (HyphenationEvent) attributes.get(Chunk.HYPHENATION); 865 } 866 867 // keys used in PdfChunk 868 869 /** Key for color. */ 870 public static final String COLOR = "COLOR"; 871 872 /** Key for encoding. */ 873 public static final String ENCODING = "ENCODING"; 874 875 /** 876 * Key for character spacing. 877 */ 878 public static final String CHAR_SPACING = "CHAR_SPACING"; 879 880 /** 881 * Sets the character spacing. 882 * 883 * @param charSpace the character spacing value 884 * @return this <CODE>Chunk</CODE> 885 */ 886 public Chunk setCharacterSpacing(final float charSpace) { 887 return setAttribute(CHAR_SPACING, new Float(charSpace)); 888 } 889 890 /** 891 * Gets the character spacing. 892 * 893 * @return a value in float 894 */ 895 public float getCharacterSpacing() { 896 if (attributes != null && attributes.containsKey(CHAR_SPACING)) { 897 Float f = (Float) attributes.get(CHAR_SPACING); 898 return f.floatValue(); 899 } 900 return 0.0f; 901 } 902}