Save This Page
Home » iText-src-2.1.3 » com.lowagie » text » pdf » [javadoc | source]
    1   /*
    2    * $Id: PdfChunk.java 3407 2008-05-21 16:56:55Z blowagie $
    3    *
    4    * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
    5    *
    6    * The contents of this file are subject to the Mozilla Public License Version 1.1
    7    * (the "License"); you may not use this file except in compliance with the License.
    8    * You may obtain a copy of the License at http://www.mozilla.org/MPL/
    9    *
   10    * Software distributed under the License is distributed on an "AS IS" basis,
   11    * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
   12    * for the specific language governing rights and limitations under the License.
   13    *
   14    * The Original Code is 'iText, a free JAVA-PDF library'.
   15    *
   16    * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
   17    * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
   18    * All Rights Reserved.
   19    * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
   20    * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
   21    *
   22    * Contributor(s): all the names of the contributors are added in the source code
   23    * where applicable.
   24    *
   25    * Alternatively, the contents of this file may be used under the terms of the
   26    * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
   27    * provisions of LGPL are applicable instead of those above.  If you wish to
   28    * allow use of your version of this file only under the terms of the LGPL
   29    * License and not to allow others to use your version of this file under
   30    * the MPL, indicate your decision by deleting the provisions above and
   31    * replace them with the notice and other provisions required by the LGPL.
   32    * If you do not delete the provisions above, a recipient may use your version
   33    * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
   34    *
   35    * This library is free software; you can redistribute it and/or modify it
   36    * under the terms of the MPL as stated above or under the terms of the GNU
   37    * Library General Public License as published by the Free Software Foundation;
   38    * either version 2 of the License, or any later version.
   39    *
   40    * This library is distributed in the hope that it will be useful, but WITHOUT
   41    * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
   42    * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
   43    * details.
   44    *
   45    * If you didn't download this code from the following link, you should check if
   46    * you aren't using an obsolete version:
   47    * http://www.lowagie.com/iText/
   48    */
   49   
   50   package com.lowagie.text.pdf;
   51   
   52   import java.awt.Color;
   53   import java.util.HashMap;
   54   import java.util.Iterator;
   55   import java.util.Map;
   56   
   57   import com.lowagie.text.Chunk;
   58   import com.lowagie.text.Font;
   59   import com.lowagie.text.Image;
   60   import com.lowagie.text.SplitCharacter;
   61   import com.lowagie.text.Utilities;
   62   
   63   /**
   64    * A <CODE>PdfChunk</CODE> is the PDF translation of a <CODE>Chunk</CODE>.
   65    * <P>
   66    * A <CODE>PdfChunk</CODE> is a <CODE>PdfString</CODE> in a certain
   67    * <CODE>PdfFont</CODE> and <CODE>Color</CODE>.
   68    *
   69    * @see		PdfString
   70    * @see		com.lowagie.text.Chunk
   71    * @see		com.lowagie.text.Font
   72    */
   73   
   74   public class PdfChunk {
   75   
   76       private static final char singleSpace[] = {' '};
   77       private static final PdfChunk thisChunk[] = new PdfChunk[1];
   78       private static final float ITALIC_ANGLE = 0.21256f;
   79   /** The allowed attributes in variable <CODE>attributes</CODE>. */
   80       private static final HashMap keysAttributes = new HashMap();
   81       
   82   /** The allowed attributes in variable <CODE>noStroke</CODE>. */
   83       private static final HashMap keysNoStroke = new HashMap();
   84       
   85       static {
   86           keysAttributes.put(Chunk.ACTION, null);
   87           keysAttributes.put(Chunk.UNDERLINE, null);
   88           keysAttributes.put(Chunk.REMOTEGOTO, null);
   89           keysAttributes.put(Chunk.LOCALGOTO, null);
   90           keysAttributes.put(Chunk.LOCALDESTINATION, null);
   91           keysAttributes.put(Chunk.GENERICTAG, null);
   92           keysAttributes.put(Chunk.NEWPAGE, null);
   93           keysAttributes.put(Chunk.IMAGE, null);
   94           keysAttributes.put(Chunk.BACKGROUND, null);
   95           keysAttributes.put(Chunk.PDFANNOTATION, null);
   96           keysAttributes.put(Chunk.SKEW, null);
   97           keysAttributes.put(Chunk.HSCALE, null);
   98           keysAttributes.put(Chunk.SEPARATOR, null);
   99           keysAttributes.put(Chunk.TAB, null);
  100           keysNoStroke.put(Chunk.SUBSUPSCRIPT, null);
  101           keysNoStroke.put(Chunk.SPLITCHARACTER, null);
  102           keysNoStroke.put(Chunk.HYPHENATION, null);
  103           keysNoStroke.put(Chunk.TEXTRENDERMODE, null);
  104       }
  105       
  106       // membervariables
  107   
  108       /** The value of this object. */
  109       protected String value = PdfObject.NOTHING;
  110       
  111       /** The encoding. */
  112       protected String encoding = BaseFont.WINANSI;
  113       
  114       
  115   /** The font for this <CODE>PdfChunk</CODE>. */
  116       protected PdfFont font;
  117       
  118       protected BaseFont baseFont;
  119       
  120       protected SplitCharacter splitCharacter;
  121   /**
  122    * Metric attributes.
  123    * <P>
  124    * This attributes require the measurement of characters widths when rendering
  125    * such as underline.
  126    */
  127       protected HashMap attributes = new HashMap();
  128       
  129   /**
  130    * Non metric attributes.
  131    * <P>
  132    * This attributes do not require the measurement of characters widths when rendering
  133    * such as Color.
  134    */
  135       protected HashMap noStroke = new HashMap();
  136       
  137   /** <CODE>true</CODE> if the chunk split was cause by a newline. */
  138       protected boolean newlineSplit;
  139       
  140   /** The image in this <CODE>PdfChunk</CODE>, if it has one */
  141       protected Image image;
  142       
  143   /** The offset in the x direction for the image */
  144       protected float offsetX;
  145       
  146   /** The offset in the y direction for the image */
  147       protected float offsetY;
  148   
  149   /** Indicates if the height and offset of the Image has to be taken into account */
  150       protected boolean changeLeading = false;
  151   
  152       // constructors
  153       
  154   /**
  155    * Constructs a <CODE>PdfChunk</CODE>-object.
  156    *
  157    * @param string the content of the <CODE>PdfChunk</CODE>-object
  158    * @param other Chunk with the same style you want for the new Chunk
  159    */
  160       
  161       PdfChunk(String string, PdfChunk other) {
  162           thisChunk[0] = this;
  163           value = string;
  164           this.font = other.font;
  165           this.attributes = other.attributes;
  166           this.noStroke = other.noStroke;
  167           this.baseFont = other.baseFont;
  168           Object obj[] = (Object[])attributes.get(Chunk.IMAGE);
  169           if (obj == null)
  170               image = null;
  171           else {
  172               image = (Image)obj[0];
  173               offsetX = ((Float)obj[1]).floatValue();
  174               offsetY = ((Float)obj[2]).floatValue();
  175               changeLeading = ((Boolean)obj[3]).booleanValue();
  176           }
  177           encoding = font.getFont().getEncoding();
  178           splitCharacter = (SplitCharacter)noStroke.get(Chunk.SPLITCHARACTER);
  179           if (splitCharacter == null)
  180               splitCharacter = DefaultSplitCharacter.DEFAULT;
  181       }
  182       
  183   /**
  184    * Constructs a <CODE>PdfChunk</CODE>-object.
  185    *
  186    * @param chunk the original <CODE>Chunk</CODE>-object
  187    * @param action the <CODE>PdfAction</CODE> if the <CODE>Chunk</CODE> comes from an <CODE>Anchor</CODE>
  188    */
  189       
  190       PdfChunk(Chunk chunk, PdfAction action) {
  191           thisChunk[0] = this;
  192           value = chunk.getContent();
  193           
  194           Font f = chunk.getFont();
  195           float size = f.getSize();
  196           if (size == Font.UNDEFINED)
  197               size = 12;
  198           baseFont = f.getBaseFont();
  199           int style = f.getStyle();
  200           if (style == Font.UNDEFINED) {
  201               style = Font.NORMAL;
  202           }
  203           if (baseFont == null) {
  204               // translation of the font-family to a PDF font-family
  205               baseFont = f.getCalculatedBaseFont(false);
  206           }
  207           else {
  208               // bold simulation
  209               if ((style & Font.BOLD) != 0)
  210                   attributes.put(Chunk.TEXTRENDERMODE, new Object[]{new Integer(PdfContentByte.TEXT_RENDER_MODE_FILL_STROKE), new Float(size / 30f), null});
  211               // italic simulation
  212               if ((style & Font.ITALIC) != 0)
  213                   attributes.put(Chunk.SKEW, new float[]{0, ITALIC_ANGLE});
  214           }
  215           font = new PdfFont(baseFont, size);
  216           // other style possibilities
  217           HashMap attr = chunk.getAttributes();
  218           if (attr != null) {
  219               for (Iterator i = attr.entrySet().iterator(); i.hasNext();) {
  220                   Map.Entry entry = (Map.Entry) i.next();
  221                   Object name = entry.getKey();
  222                   if (keysAttributes.containsKey(name)) {
  223                       attributes.put(name, entry.getValue());
  224                   }
  225                   else if (keysNoStroke.containsKey(name)) {
  226                       noStroke.put(name, entry.getValue());
  227                   }
  228               }
  229               if ("".equals(attr.get(Chunk.GENERICTAG))) {
  230                   attributes.put(Chunk.GENERICTAG, chunk.getContent());
  231               }
  232           }
  233           if (f.isUnderlined()) {
  234               Object obj[] = {null, new float[]{0, 1f / 15, 0, -1f / 3, 0}};
  235               Object unders[][] = Utilities.addToArray((Object[][])attributes.get(Chunk.UNDERLINE), obj);
  236               attributes.put(Chunk.UNDERLINE, unders);
  237           }
  238           if (f.isStrikethru()) {
  239               Object obj[] = {null, new float[]{0, 1f / 15, 0, 1f / 3, 0}};
  240               Object unders[][] = Utilities.addToArray((Object[][])attributes.get(Chunk.UNDERLINE), obj);
  241               attributes.put(Chunk.UNDERLINE, unders);
  242           }
  243           if (action != null)
  244               attributes.put(Chunk.ACTION, action);
  245           // the color can't be stored in a PdfFont
  246           noStroke.put(Chunk.COLOR, f.getColor());
  247           noStroke.put(Chunk.ENCODING, font.getFont().getEncoding());
  248           Object obj[] = (Object[])attributes.get(Chunk.IMAGE);
  249           if (obj == null) {
  250               image = null;
  251           }
  252           else {
  253               attributes.remove(Chunk.HSCALE); // images are scaled in other ways
  254               image = (Image)obj[0];
  255               offsetX = ((Float)obj[1]).floatValue();
  256               offsetY = ((Float)obj[2]).floatValue();
  257               changeLeading = ((Boolean)obj[3]).booleanValue();
  258           }
  259           font.setImage(image);
  260           Float hs = (Float)attributes.get(Chunk.HSCALE);
  261           if (hs != null)
  262               font.setHorizontalScaling(hs.floatValue());
  263           encoding = font.getFont().getEncoding();
  264           splitCharacter = (SplitCharacter)noStroke.get(Chunk.SPLITCHARACTER);
  265           if (splitCharacter == null)
  266               splitCharacter = DefaultSplitCharacter.DEFAULT;
  267       }
  268       
  269       // methods
  270       
  271       /** Gets the Unicode equivalent to a CID.
  272        * The (inexistent) CID <FF00> is translated as '\n'. 
  273        * It has only meaning with CJK fonts with Identity encoding.
  274        * @param c the CID code
  275        * @return the Unicode equivalent
  276        */    
  277       public int getUnicodeEquivalent(int c) {
  278           return baseFont.getUnicodeEquivalent(c);
  279       }
  280   
  281       protected int getWord(String text, int start) {
  282           int len = text.length();
  283           while (start < len) {
  284               if (!Character.isLetter(text.charAt(start)))
  285                   break;
  286               ++start;
  287           }
  288           return start;
  289       }
  290       
  291   /**
  292    * Splits this <CODE>PdfChunk</CODE> if it's too long for the given width.
  293    * <P>
  294    * Returns <VAR>null</VAR> if the <CODE>PdfChunk</CODE> wasn't truncated.
  295    *
  296    * @param		width		a given width
  297    * @return		the <CODE>PdfChunk</CODE> that doesn't fit into the width.
  298    */
  299       
  300       PdfChunk split(float width) {
  301           newlineSplit = false;
  302           if (image != null) {
  303               if (image.getScaledWidth() > width) {
  304                   PdfChunk pc = new PdfChunk(Chunk.OBJECT_REPLACEMENT_CHARACTER, this);
  305                   value = "";
  306                   attributes = new HashMap();
  307                   image = null;
  308                   font = PdfFont.getDefaultFont();
  309                   return pc;
  310               }
  311               else
  312                   return null;
  313           }
  314           HyphenationEvent hyphenationEvent = (HyphenationEvent)noStroke.get(Chunk.HYPHENATION);
  315           int currentPosition = 0;
  316           int splitPosition = -1;
  317           float currentWidth = 0;
  318           
  319           // loop over all the characters of a string
  320           // or until the totalWidth is reached
  321           int lastSpace = -1;
  322           float lastSpaceWidth = 0;
  323           int length = value.length();
  324           char valueArray[] = value.toCharArray();
  325           char character = 0;
  326           BaseFont ft = font.getFont();
  327           boolean surrogate = false;
  328           if (ft.getFontType() == BaseFont.FONT_TYPE_CJK && ft.getUnicodeEquivalent(' ') != ' ') {
  329               while (currentPosition < length) {
  330                   // the width of every character is added to the currentWidth
  331                   char cidChar = valueArray[currentPosition];
  332                   character = (char)ft.getUnicodeEquivalent(cidChar);
  333                   // if a newLine or carriageReturn is encountered
  334                   if (character == '\n') {
  335                       newlineSplit = true;
  336                       String returnValue = value.substring(currentPosition + 1);
  337                       value = value.substring(0, currentPosition);
  338                       if (value.length() < 1) {
  339                           value = "\u0001";
  340                       }
  341                       PdfChunk pc = new PdfChunk(returnValue, this);
  342                       return pc;
  343                   }
  344                   currentWidth += font.width(cidChar);
  345                   if (character == ' ') {
  346                       lastSpace = currentPosition + 1;
  347                       lastSpaceWidth = currentWidth;
  348                   }
  349                   if (currentWidth > width)
  350                       break;
  351                   // if a split-character is encountered, the splitPosition is altered
  352                   if (splitCharacter.isSplitCharacter(0, currentPosition, length, valueArray, thisChunk))
  353                       splitPosition = currentPosition + 1;
  354                   currentPosition++;
  355               }
  356           }
  357           else {
  358               while (currentPosition < length) {
  359                   // the width of every character is added to the currentWidth
  360                   character = valueArray[currentPosition];
  361                   // if a newLine or carriageReturn is encountered
  362                   if (character == '\r' || character == '\n') {
  363                       newlineSplit = true;
  364                       int inc = 1;
  365                       if (character == '\r' && currentPosition + 1 < length && valueArray[currentPosition + 1] == '\n')
  366                           inc = 2;
  367                       String returnValue = value.substring(currentPosition + inc);
  368                       value = value.substring(0, currentPosition);
  369                       if (value.length() < 1) {
  370                           value = " ";
  371                       }
  372                       PdfChunk pc = new PdfChunk(returnValue, this);
  373                       return pc;
  374                   }
  375                   surrogate = Utilities.isSurrogatePair(valueArray, currentPosition);
  376                   if (surrogate)
  377                       currentWidth += font.width(Utilities.convertToUtf32(valueArray[currentPosition], valueArray[currentPosition + 1]));
  378                   else
  379                       currentWidth += font.width(character);
  380                   if (character == ' ') {
  381                       lastSpace = currentPosition + 1;
  382                       lastSpaceWidth = currentWidth;
  383                   }
  384                   if (surrogate)
  385                       currentPosition++;
  386                   if (currentWidth > width)
  387                       break;
  388                   // if a split-character is encountered, the splitPosition is altered
  389                   if (splitCharacter.isSplitCharacter(0, currentPosition, length, valueArray, null))
  390                       splitPosition = currentPosition + 1;
  391                   currentPosition++;
  392               }
  393           }
  394           
  395           // if all the characters fit in the total width, null is returned (there is no overflow)
  396           if (currentPosition == length) {
  397               return null;
  398           }
  399           // otherwise, the string has to be truncated
  400           if (splitPosition < 0) {
  401               String returnValue = value;
  402               value = "";
  403               PdfChunk pc = new PdfChunk(returnValue, this);
  404               return pc;
  405           }
  406           if (lastSpace > splitPosition && splitCharacter.isSplitCharacter(0, 0, 1, singleSpace, null))
  407               splitPosition = lastSpace;
  408           if (hyphenationEvent != null && lastSpace >= 0 && lastSpace < currentPosition) {
  409               int wordIdx = getWord(value, lastSpace);
  410               if (wordIdx > lastSpace) {
  411                   String pre = hyphenationEvent.getHyphenatedWordPre(value.substring(lastSpace, wordIdx), font.getFont(), font.size(), width - lastSpaceWidth);
  412                   String post = hyphenationEvent.getHyphenatedWordPost();
  413                   if (pre.length() > 0) {
  414                       String returnValue = post + value.substring(wordIdx);
  415                       value = trim(value.substring(0, lastSpace) + pre);
  416                       PdfChunk pc = new PdfChunk(returnValue, this);
  417                       return pc;
  418                   }
  419               }
  420           }
  421           String returnValue = value.substring(splitPosition);
  422           value = trim(value.substring(0, splitPosition));
  423           PdfChunk pc = new PdfChunk(returnValue, this);
  424           return pc;
  425       }
  426       
  427   /**
  428    * Truncates this <CODE>PdfChunk</CODE> if it's too long for the given width.
  429    * <P>
  430    * Returns <VAR>null</VAR> if the <CODE>PdfChunk</CODE> wasn't truncated.
  431    *
  432    * @param		width		a given width
  433    * @return		the <CODE>PdfChunk</CODE> that doesn't fit into the width.
  434    */
  435       
  436       PdfChunk truncate(float width) {
  437           if (image != null) {
  438               if (image.getScaledWidth() > width) {
  439                   PdfChunk pc = new PdfChunk("", this);
  440                   value = "";
  441                   attributes.remove(Chunk.IMAGE);
  442                   image = null;
  443                   font = PdfFont.getDefaultFont();
  444                   return pc;
  445               }
  446               else
  447                   return null;
  448           }
  449           
  450           int currentPosition = 0;
  451           float currentWidth = 0;
  452           
  453           // it's no use trying to split if there isn't even enough place for a space
  454           if (width < font.width()) {
  455               String returnValue = value.substring(1);
  456               value = value.substring(0, 1);
  457               PdfChunk pc = new PdfChunk(returnValue, this);
  458               return pc;
  459           }
  460           
  461           // loop over all the characters of a string
  462           // or until the totalWidth is reached
  463           int length = value.length();
  464           boolean surrogate = false;
  465           char character;
  466           while (currentPosition < length) {
  467               // the width of every character is added to the currentWidth
  468               surrogate = Utilities.isSurrogatePair(value, currentPosition);
  469               if (surrogate)
  470                   currentWidth += font.width(Utilities.convertToUtf32(value, currentPosition));
  471               else
  472                   currentWidth += font.width(value.charAt(currentPosition));
  473               if (currentWidth > width)
  474                   break;
  475               if (surrogate)
  476                   currentPosition++;
  477               currentPosition++;
  478           }
  479           
  480           // if all the characters fit in the total width, null is returned (there is no overflow)
  481           if (currentPosition == length) {
  482               return null;
  483           }
  484           
  485           // otherwise, the string has to be truncated
  486           //currentPosition -= 2;
  487           // we have to chop off minimum 1 character from the chunk
  488           if (currentPosition == 0) {
  489               currentPosition = 1;
  490               if (surrogate)
  491                   ++currentPosition;
  492           }
  493           String returnValue = value.substring(currentPosition);
  494           value = value.substring(0, currentPosition);
  495           PdfChunk pc = new PdfChunk(returnValue, this);
  496           return pc;
  497       }
  498       
  499       // methods to retrieve the membervariables
  500       
  501   /**
  502    * Returns the font of this <CODE>Chunk</CODE>.
  503    *
  504    * @return	a <CODE>PdfFont</CODE>
  505    */
  506       
  507       PdfFont font() {
  508           return font;
  509       }
  510       
  511   /**
  512    * Returns the color of this <CODE>Chunk</CODE>.
  513    *
  514    * @return	a <CODE>Color</CODE>
  515    */
  516       
  517       Color color() {
  518           return (Color)noStroke.get(Chunk.COLOR);
  519       }
  520       
  521   /**
  522    * Returns the width of this <CODE>PdfChunk</CODE>.
  523    *
  524    * @return	a width
  525    */
  526       
  527       float width() {
  528           return font.width(value);
  529       }
  530       
  531   /**
  532    * Checks if the <CODE>PdfChunk</CODE> split was caused by a newline.
  533    * @return <CODE>true</CODE> if the <CODE>PdfChunk</CODE> split was caused by a newline.
  534    */
  535       
  536       public boolean isNewlineSplit()
  537       {
  538           return newlineSplit;
  539       }
  540       
  541   /**
  542    * Gets the width of the <CODE>PdfChunk</CODE> taking into account the
  543    * extra character and word spacing.
  544    * @param charSpacing the extra character spacing
  545    * @param wordSpacing the extra word spacing
  546    * @return the calculated width
  547    */
  548       
  549       public float getWidthCorrected(float charSpacing, float wordSpacing)
  550       {
  551           if (image != null) {
  552               return image.getScaledWidth() + charSpacing;
  553           }
  554           int numberOfSpaces = 0;
  555           int idx = -1;
  556           while ((idx = value.indexOf(' ', idx + 1)) >= 0)
  557               ++numberOfSpaces;
  558           return width() + (value.length() * charSpacing + numberOfSpaces * wordSpacing);
  559       }
  560       
  561       /**
  562        * Gets the text displacement relative to the baseline.
  563        * @return a displacement in points
  564        */
  565       public float getTextRise() {
  566       	Float f = (Float) getAttribute(Chunk.SUBSUPSCRIPT);
  567       	if (f != null) {
  568       		return f.floatValue();
  569       	}
  570       	return 0.0f;
  571       }
  572       
  573   /**
  574    * Trims the last space.
  575    * @return the width of the space trimmed, otherwise 0
  576    */
  577       
  578       public float trimLastSpace()
  579       {
  580           BaseFont ft = font.getFont();
  581           if (ft.getFontType() == BaseFont.FONT_TYPE_CJK && ft.getUnicodeEquivalent(' ') != ' ') {
  582               if (value.length() > 1 && value.endsWith("\u0001")) {
  583                   value = value.substring(0, value.length() - 1);
  584                   return font.width('\u0001');
  585               }
  586           }
  587           else {
  588               if (value.length() > 1 && value.endsWith(" ")) {
  589                   value = value.substring(0, value.length() - 1);
  590                   return font.width(' ');
  591               }
  592           }
  593           return 0;
  594       }    
  595       public float trimFirstSpace()
  596       {
  597           BaseFont ft = font.getFont();
  598           if (ft.getFontType() == BaseFont.FONT_TYPE_CJK && ft.getUnicodeEquivalent(' ') != ' ') {
  599               if (value.length() > 1 && value.startsWith("\u0001")) {
  600                   value = value.substring(1);
  601                   return font.width('\u0001');
  602               }
  603           }
  604           else {
  605               if (value.length() > 1 && value.startsWith(" ")) {
  606                   value = value.substring(1);
  607                   return font.width(' ');
  608               }
  609           }
  610           return 0;
  611       }
  612       
  613   /**
  614    * Gets an attribute. The search is made in <CODE>attributes</CODE>
  615    * and <CODE>noStroke</CODE>.
  616    * @param name the attribute key
  617    * @return the attribute value or null if not found
  618    */
  619       
  620       Object getAttribute(String name)
  621       {
  622           if (attributes.containsKey(name))
  623               return attributes.get(name);
  624           return noStroke.get(name);
  625       }
  626       
  627   /**
  628    *Checks if the attribute exists.
  629    * @param name the attribute key
  630    * @return <CODE>true</CODE> if the attribute exists
  631    */
  632       
  633       boolean isAttribute(String name)
  634       {
  635           if (attributes.containsKey(name))
  636               return true;
  637           return noStroke.containsKey(name);
  638       }
  639       
  640   /**
  641    * Checks if this <CODE>PdfChunk</CODE> needs some special metrics handling.
  642    * @return <CODE>true</CODE> if this <CODE>PdfChunk</CODE> needs some special metrics handling.
  643    */
  644       
  645       boolean isStroked()
  646       {
  647           return (!attributes.isEmpty());
  648       }
  649       
  650       /**
  651        * Checks if this <CODE>PdfChunk</CODE> is a Separator Chunk.
  652        * @return	true if this chunk is a separator.
  653        * @since	2.1.2
  654        */
  655       boolean isSeparator() {
  656       	return isAttribute(Chunk.SEPARATOR);
  657       }
  658       
  659       /**
  660        * Checks if this <CODE>PdfChunk</CODE> is a horizontal Separator Chunk.
  661        * @return	true if this chunk is a horizontal separator.
  662        * @since	2.1.2
  663        */
  664       boolean isHorizontalSeparator() {
  665       	if (isAttribute(Chunk.SEPARATOR)) {
  666       		Object[] o = (Object[])getAttribute(Chunk.SEPARATOR);
  667       		return !((Boolean)o[1]).booleanValue();
  668       	}
  669       	return false;
  670       }
  671       
  672       /**
  673        * Checks if this <CODE>PdfChunk</CODE> is a tab Chunk.
  674        * @return	true if this chunk is a separator.
  675        * @since	2.1.2
  676        */
  677       boolean isTab() {
  678       	return isAttribute(Chunk.TAB);
  679       }
  680       
  681       /**
  682        * Correction for the tab position based on the left starting position.
  683        * @param	newValue	the new value for the left X.
  684        * @since	2.1.2
  685        */
  686       void adjustLeft(float newValue) {
  687       	Object[] o = (Object[])attributes.get(Chunk.TAB);
  688       	if (o != null) {
  689       		attributes.put(Chunk.TAB, new Object[]{o[0], o[1], o[2], new Float(newValue)});
  690       	}
  691       }
  692       
  693   /**
  694    * Checks if there is an image in the <CODE>PdfChunk</CODE>.
  695    * @return <CODE>true</CODE> if an image is present
  696    */
  697       
  698       boolean isImage()
  699       {
  700           return image != null;
  701       }
  702       
  703   /**
  704    * Gets the image in the <CODE>PdfChunk</CODE>.
  705    * @return the image or <CODE>null</CODE>
  706    */
  707       
  708       Image getImage()
  709       {
  710           return image;
  711       }
  712       
  713   /**
  714    * Sets the image offset in the x direction
  715    * @param  offsetX the image offset in the x direction
  716    */
  717       
  718       void setImageOffsetX(float offsetX)
  719       {
  720           this.offsetX = offsetX;
  721       }
  722       
  723   /**
  724    * Gets the image offset in the x direction
  725    * @return the image offset in the x direction
  726    */
  727       
  728       float getImageOffsetX()
  729       {
  730           return offsetX;
  731       }
  732       
  733   /**
  734    * Sets the image offset in the y direction
  735    * @param  offsetY the image offset in the y direction
  736    */
  737       
  738       void setImageOffsetY(float offsetY)
  739       {
  740           this.offsetY = offsetY;
  741       }
  742       
  743   /**
  744    * Gets the image offset in the y direction
  745    * @return Gets the image offset in the y direction
  746    */
  747       
  748       float getImageOffsetY()
  749       {
  750           return offsetY;
  751       }
  752       
  753   /**
  754    * sets the value.
  755    * @param value content of the Chunk
  756    */
  757       
  758       void setValue(String value)
  759       {
  760           this.value = value;
  761       }
  762   
  763       /**
  764        * @see java.lang.Object#toString()
  765        */
  766       public String toString() {
  767           return value;
  768       }
  769   
  770       /**
  771        * Tells you if this string is in Chinese, Japanese, Korean or Identity-H.
  772        * @return true if the Chunk has a special encoding
  773        */
  774       
  775       boolean isSpecialEncoding() {
  776           return encoding.equals(CJKFont.CJK_ENCODING) || encoding.equals(BaseFont.IDENTITY_H);
  777       }
  778       
  779       /**
  780        * Gets the encoding of this string.
  781        *
  782        * @return		a <CODE>String</CODE>
  783        */
  784       
  785       String getEncoding() {
  786           return encoding;
  787       }
  788   
  789       int length() {
  790           return value.length();
  791       }
  792       
  793       int lengthUtf32() {
  794           if (!BaseFont.IDENTITY_H.equals(encoding))
  795               return value.length();
  796           int total = 0;
  797           int len = value.length();
  798           for (int k = 0; k < len; ++k) {
  799               if (Utilities.isSurrogateHigh(value.charAt(k)))
  800                   ++k;
  801               ++total;
  802           }
  803           return total;
  804       }
  805       
  806       boolean isExtSplitCharacter(int start, int current, int end, char[] cc, PdfChunk[] ck) {
  807           return splitCharacter.isSplitCharacter(start, current, end, cc, ck);
  808       }
  809       
  810   /**
  811    * Removes all the <VAR>' '</VAR> and <VAR>'-'</VAR>-characters on the right of a <CODE>String</CODE>.
  812    * <P>
  813    * @param	string		the <CODE>String<CODE> that has to be trimmed.
  814    * @return	the trimmed <CODE>String</CODE>
  815    */    
  816       String trim(String string) {
  817           BaseFont ft = font.getFont();
  818           if (ft.getFontType() == BaseFont.FONT_TYPE_CJK && ft.getUnicodeEquivalent(' ') != ' ') {
  819               while (string.endsWith("\u0001")) {
  820                   string = string.substring(0, string.length() - 1);
  821               }
  822           }
  823           else {
  824               while (string.endsWith(" ") || string.endsWith("\t")) {
  825                   string = string.substring(0, string.length() - 1);
  826               }
  827           }
  828           return string;
  829       }
  830   
  831       public boolean changeLeading() {
  832           return changeLeading;
  833       }
  834       
  835       float getCharWidth(int c) {
  836           if (noPrint(c))
  837               return 0;
  838           return font.width(c);
  839       }
  840       
  841       public static boolean noPrint(int c) {
  842           return ((c >= 0x200b && c <= 0x200f) || (c >= 0x202a && c <= 0x202e));
  843       }
  844       
  845   }

Save This Page
Home » iText-src-2.1.3 » com.lowagie » text » pdf » [javadoc | source]