/**
  * Process the text so that it will render with a combination of fonts if needed.
  *
  * @param text the text
  * @return a <CODE>Phrase</CODE> with one or more chunks
  */
 public Phrase process(String text) {
   int fsize = fonts.size();
   if (fsize == 0) throw new IndexOutOfBoundsException("No font is defined.");
   char cc[] = text.toCharArray();
   int len = cc.length;
   StringBuffer sb = new StringBuffer();
   Font font = null;
   int lastidx = -1;
   Phrase ret = new Phrase();
   for (int k = 0; k < len; ++k) {
     char c = cc[k];
     if (c == '\n' || c == '\r') {
       sb.append(c);
       continue;
     }
     if (Utilities.isSurrogatePair(cc, k)) {
       int u = Utilities.convertToUtf32(cc, k);
       for (int f = 0; f < fsize; ++f) {
         font = (Font) fonts.get(f);
         if (font.getBaseFont().charExists(u)) {
           if (lastidx != f) {
             if (sb.length() > 0 && lastidx != -1) {
               Chunk ck = new Chunk(sb.toString(), (Font) fonts.get(lastidx));
               ret.add(ck);
               sb.setLength(0);
             }
             lastidx = f;
           }
           sb.append(c);
           sb.append(cc[++k]);
           break;
         }
       }
     } else {
       for (int f = 0; f < fsize; ++f) {
         font = (Font) fonts.get(f);
         if (font.getBaseFont().charExists(c)) {
           if (lastidx != f) {
             if (sb.length() > 0 && lastidx != -1) {
               Chunk ck = new Chunk(sb.toString(), (Font) fonts.get(lastidx));
               ret.add(ck);
               sb.setLength(0);
             }
             lastidx = f;
           }
           sb.append(c);
           break;
         }
       }
     }
   }
   if (sb.length() > 0) {
     Chunk ck = new Chunk(sb.toString(), (Font) fonts.get(lastidx == -1 ? 0 : lastidx));
     ret.add(ck);
   }
   return ret;
 }
  /**
   * Truncates this <CODE>PdfChunk</CODE> if it's too long for the given width.
   *
   * <p>Returns <VAR>null</VAR> if the <CODE>PdfChunk</CODE> wasn't truncated.
   *
   * @param width a given width
   * @return the <CODE>PdfChunk</CODE> that doesn't fit into the width.
   */
  PdfChunk truncate(float width) {
    if (image != null) {
      if (image.getScaledWidth() > width) {
        PdfChunk pc = new PdfChunk("", this);
        value = "";
        attributes.remove(Chunk.IMAGE);
        image = null;
        font = PdfFont.getDefaultFont();
        return pc;
      } else return null;
    }

    int currentPosition = 0;
    float currentWidth = 0;

    // it's no use trying to split if there isn't even enough place for a space
    if (width < font.width()) {
      String returnValue = value.substring(1);
      value = value.substring(0, 1);
      PdfChunk pc = new PdfChunk(returnValue, this);
      return pc;
    }

    // loop over all the characters of a string
    // or until the totalWidth is reached
    int length = value.length();
    boolean surrogate = false;
    char character;
    while (currentPosition < length) {
      // the width of every character is added to the currentWidth
      surrogate = Utilities.isSurrogatePair(value, currentPosition);
      if (surrogate) currentWidth += font.width(Utilities.convertToUtf32(value, currentPosition));
      else currentWidth += font.width(value.charAt(currentPosition));
      if (currentWidth > width) break;
      if (surrogate) currentPosition++;
      currentPosition++;
    }

    // if all the characters fit in the total width, null is returned (there is no overflow)
    if (currentPosition == length) {
      return null;
    }

    // otherwise, the string has to be truncated
    // currentPosition -= 2;
    // we have to chop off minimum 1 character from the chunk
    if (currentPosition == 0) {
      currentPosition = 1;
      if (surrogate) ++currentPosition;
    }
    String returnValue = value.substring(currentPosition);
    value = value.substring(0, currentPosition);
    PdfChunk pc = new PdfChunk(returnValue, this);
    return pc;
  }
 int lengthUtf32() {
   if (!BaseFont.IDENTITY_H.equals(encoding)) return value.length();
   int total = 0;
   int len = value.length();
   for (int k = 0; k < len; ++k) {
     if (Utilities.isSurrogateHigh(value.charAt(k))) ++k;
     ++total;
   }
   return total;
 }
Exemple #4
0
 /**
  * Constructs an <CODE>ImgWMF</CODE>-object, using a <VAR>filename</VAR>.
  *
  * @param filename a <CODE>String</CODE>-representation of the file that contains the image.
  * @throws BadElementException on error
  * @throws MalformedURLException on error
  * @throws IOException on error
  */
 public ImgWMF(String filename) throws BadElementException, MalformedURLException, IOException {
   this(Utilities.toURL(filename));
 }
  /**
   * Splits this <CODE>PdfChunk</CODE> if it's too long for the given width.
   *
   * <p>Returns <VAR>null</VAR> if the <CODE>PdfChunk</CODE> wasn't truncated.
   *
   * @param width a given width
   * @return the <CODE>PdfChunk</CODE> that doesn't fit into the width.
   */
  PdfChunk split(float width) {
    newlineSplit = false;
    if (image != null) {
      if (image.getScaledWidth() > width) {
        PdfChunk pc = new PdfChunk(Chunk.OBJECT_REPLACEMENT_CHARACTER, this);
        value = "";
        attributes = new HashMap();
        image = null;
        font = PdfFont.getDefaultFont();
        return pc;
      } else return null;
    }
    HyphenationEvent hyphenationEvent = (HyphenationEvent) noStroke.get(Chunk.HYPHENATION);
    int currentPosition = 0;
    int splitPosition = -1;
    float currentWidth = 0;

    // loop over all the characters of a string
    // or until the totalWidth is reached
    int lastSpace = -1;
    float lastSpaceWidth = 0;
    int length = value.length();
    char valueArray[] = value.toCharArray();
    char character = 0;
    BaseFont ft = font.getFont();
    boolean surrogate = false;
    if (ft.getFontType() == BaseFont.FONT_TYPE_CJK && ft.getUnicodeEquivalent(' ') != ' ') {
      while (currentPosition < length) {
        // the width of every character is added to the currentWidth
        char cidChar = valueArray[currentPosition];
        character = (char) ft.getUnicodeEquivalent(cidChar);
        // if a newLine or carriageReturn is encountered
        if (character == '\n') {
          newlineSplit = true;
          String returnValue = value.substring(currentPosition + 1);
          value = value.substring(0, currentPosition);
          if (value.length() < 1) {
            value = "\u0001";
          }
          PdfChunk pc = new PdfChunk(returnValue, this);
          return pc;
        }
        currentWidth += font.width(cidChar);
        if (character == ' ') {
          lastSpace = currentPosition + 1;
          lastSpaceWidth = currentWidth;
        }
        if (currentWidth > width) break;
        // if a split-character is encountered, the splitPosition is altered
        if (splitCharacter.isSplitCharacter(0, currentPosition, length, valueArray, thisChunk))
          splitPosition = currentPosition + 1;
        currentPosition++;
      }
    } else {
      while (currentPosition < length) {
        // the width of every character is added to the currentWidth
        character = valueArray[currentPosition];
        // if a newLine or carriageReturn is encountered
        if (character == '\r' || character == '\n') {
          newlineSplit = true;
          int inc = 1;
          if (character == '\r'
              && currentPosition + 1 < length
              && valueArray[currentPosition + 1] == '\n') inc = 2;
          String returnValue = value.substring(currentPosition + inc);
          value = value.substring(0, currentPosition);
          if (value.length() < 1) {
            value = " ";
          }
          PdfChunk pc = new PdfChunk(returnValue, this);
          return pc;
        }
        surrogate = Utilities.isSurrogatePair(valueArray, currentPosition);
        if (surrogate)
          currentWidth +=
              font.width(
                  Utilities.convertToUtf32(
                      valueArray[currentPosition], valueArray[currentPosition + 1]));
        else currentWidth += font.width(character);
        if (character == ' ') {
          lastSpace = currentPosition + 1;
          lastSpaceWidth = currentWidth;
        }
        if (surrogate) currentPosition++;
        if (currentWidth > width) break;
        // if a split-character is encountered, the splitPosition is altered
        if (splitCharacter.isSplitCharacter(0, currentPosition, length, valueArray, null))
          splitPosition = currentPosition + 1;
        currentPosition++;
      }
    }

    // if all the characters fit in the total width, null is returned (there is no overflow)
    if (currentPosition == length) {
      return null;
    }
    // otherwise, the string has to be truncated
    if (splitPosition < 0) {
      String returnValue = value;
      value = "";
      PdfChunk pc = new PdfChunk(returnValue, this);
      return pc;
    }
    if (lastSpace > splitPosition && splitCharacter.isSplitCharacter(0, 0, 1, singleSpace, null))
      splitPosition = lastSpace;
    if (hyphenationEvent != null && lastSpace >= 0 && lastSpace < currentPosition) {
      int wordIdx = getWord(value, lastSpace);
      if (wordIdx > lastSpace) {
        String pre =
            hyphenationEvent.getHyphenatedWordPre(
                value.substring(lastSpace, wordIdx),
                font.getFont(),
                font.size(),
                width - lastSpaceWidth);
        String post = hyphenationEvent.getHyphenatedWordPost();
        if (pre.length() > 0) {
          String returnValue = post + value.substring(wordIdx);
          value = trim(value.substring(0, lastSpace) + pre);
          PdfChunk pc = new PdfChunk(returnValue, this);
          return pc;
        }
      }
    }
    String returnValue = value.substring(splitPosition);
    value = trim(value.substring(0, splitPosition));
    PdfChunk pc = new PdfChunk(returnValue, this);
    return pc;
  }
  /**
   * Constructs a <CODE>PdfChunk</CODE>-object.
   *
   * @param chunk the original <CODE>Chunk</CODE>-object
   * @param action the <CODE>PdfAction</CODE> if the <CODE>Chunk</CODE> comes from an <CODE>Anchor
   *     </CODE>
   */
  PdfChunk(Chunk chunk, PdfAction action) {
    thisChunk[0] = this;
    value = chunk.getContent();

    Font f = chunk.getFont();
    float size = f.getSize();
    if (size == Font.UNDEFINED) size = 12;
    baseFont = f.getBaseFont();
    int style = f.getStyle();
    if (style == Font.UNDEFINED) {
      style = Font.NORMAL;
    }
    if (baseFont == null) {
      // translation of the font-family to a PDF font-family
      baseFont = f.getCalculatedBaseFont(false);
    } else {
      // bold simulation
      if ((style & Font.BOLD) != 0)
        attributes.put(
            Chunk.TEXTRENDERMODE,
            new Object[] {
              new Integer(PdfContentByte.TEXT_RENDER_MODE_FILL_STROKE), new Float(size / 30f), null
            });
      // italic simulation
      if ((style & Font.ITALIC) != 0) attributes.put(Chunk.SKEW, new float[] {0, ITALIC_ANGLE});
    }
    font = new PdfFont(baseFont, size);
    // other style possibilities
    HashMap attr = chunk.getAttributes();
    if (attr != null) {
      for (Iterator i = attr.entrySet().iterator(); i.hasNext(); ) {
        Map.Entry entry = (Map.Entry) i.next();
        Object name = entry.getKey();
        if (keysAttributes.containsKey(name)) {
          attributes.put(name, entry.getValue());
        } else if (keysNoStroke.containsKey(name)) {
          noStroke.put(name, entry.getValue());
        }
      }
      if ("".equals(attr.get(Chunk.GENERICTAG))) {
        attributes.put(Chunk.GENERICTAG, chunk.getContent());
      }
    }
    if (f.isUnderlined()) {
      Object obj[] = {null, new float[] {0, 1f / 15, 0, -1f / 3, 0}};
      Object unders[][] = Utilities.addToArray((Object[][]) attributes.get(Chunk.UNDERLINE), obj);
      attributes.put(Chunk.UNDERLINE, unders);
    }
    if (f.isStrikethru()) {
      Object obj[] = {null, new float[] {0, 1f / 15, 0, 1f / 3, 0}};
      Object unders[][] = Utilities.addToArray((Object[][]) attributes.get(Chunk.UNDERLINE), obj);
      attributes.put(Chunk.UNDERLINE, unders);
    }
    if (action != null) attributes.put(Chunk.ACTION, action);
    // the color can't be stored in a PdfFont
    noStroke.put(Chunk.COLOR, f.getColor());
    noStroke.put(Chunk.ENCODING, font.getFont().getEncoding());
    Object obj[] = (Object[]) attributes.get(Chunk.IMAGE);
    if (obj == null) {
      image = null;
    } else {
      attributes.remove(Chunk.HSCALE); // images are scaled in other ways
      image = (Image) obj[0];
      offsetX = ((Float) obj[1]).floatValue();
      offsetY = ((Float) obj[2]).floatValue();
      changeLeading = ((Boolean) obj[3]).booleanValue();
    }
    font.setImage(image);
    Float hs = (Float) attributes.get(Chunk.HSCALE);
    if (hs != null) font.setHorizontalScaling(hs.floatValue());
    encoding = font.getFont().getEncoding();
    splitCharacter = (SplitCharacter) noStroke.get(Chunk.SPLITCHARACTER);
    if (splitCharacter == null) splitCharacter = DefaultSplitCharacter.DEFAULT;
  }
 /**
  * Converts the text into bytes to be placed in the document. The conversion is done according to
  * the font and the encoding and the characters used are stored.
  *
  * @param text the text to convert
  * @return the conversion
  */
 byte[] convertToBytes(final String text) {
   byte b[] = null;
   switch (this.fontType) {
     case BaseFont.FONT_TYPE_T3:
       return this.baseFont.convertToBytes(text);
     case BaseFont.FONT_TYPE_T1:
     case BaseFont.FONT_TYPE_TT:
       {
         b = this.baseFont.convertToBytes(text);
         final int len = b.length;
         for (int k = 0; k < len; ++k) {
           this.shortTag[b[k] & 0xff] = 1;
         }
         break;
       }
     case BaseFont.FONT_TYPE_CJK:
       {
         final int len = text.length();
         for (int k = 0; k < len; ++k) {
           this.cjkTag.put(this.cjkFont.getCidCode(text.charAt(k)), 0);
         }
         b = this.baseFont.convertToBytes(text);
         break;
       }
     case BaseFont.FONT_TYPE_DOCUMENT:
       {
         b = this.baseFont.convertToBytes(text);
         break;
       }
     case BaseFont.FONT_TYPE_TTUNI:
       {
         try {
           int len = text.length();
           int metrics[] = null;
           final char glyph[] = new char[len];
           int i = 0;
           if (this.symbolic) {
             b = PdfEncodings.convertToBytes(text, "symboltt");
             len = b.length;
             for (int k = 0; k < len; ++k) {
               metrics = this.ttu.getMetricsTT(b[k] & 0xff);
               if (metrics == null) {
                 continue;
               }
               this.longTag.put(
                   new Integer(metrics[0]),
                   new int[] {
                     metrics[0], metrics[1], this.ttu.getUnicodeDifferences(b[k] & 0xff)
                   });
               glyph[i++] = (char) metrics[0];
             }
           } else {
             for (int k = 0; k < len; ++k) {
               int val;
               if (Utilities.isSurrogatePair(text, k)) {
                 val = Utilities.convertToUtf32(text, k);
                 k++;
               } else {
                 val = text.charAt(k);
               }
               metrics = this.ttu.getMetricsTT(val);
               if (metrics == null) {
                 continue;
               }
               final int m0 = metrics[0];
               final Integer gl = new Integer(m0);
               if (!this.longTag.containsKey(gl)) {
                 this.longTag.put(gl, new int[] {m0, metrics[1], val});
               }
               glyph[i++] = (char) m0;
             }
           }
           final String s = new String(glyph, 0, i);
           b = s.getBytes(CJKFont.CJK_ENCODING);
         } catch (final UnsupportedEncodingException e) {
           throw new ExceptionConverter(e);
         }
         break;
       }
   }
   return b;
 }
  void readPng() throws IOException {
    for (int i = 0; i < PNGID.length; i++) {
      if (PNGID[i] != is.read()) {
        throw new IOException("File is not a valid PNG.");
      }
    }
    byte buffer[] = new byte[TRANSFERSIZE];
    while (true) {
      int len = getInt(is);
      String marker = getString(is);
      if (len < 0 || !checkMarker(marker)) throw new IOException("Corrupted PNG file.");
      if (IDAT.equals(marker)) {
        int size;
        while (len != 0) {
          size = is.read(buffer, 0, Math.min(len, TRANSFERSIZE));
          if (size < 0) return;
          idat.write(buffer, 0, size);
          len -= size;
        }
      } else if (tRNS.equals(marker)) {
        switch (colorType) {
          case 0:
            if (len >= 2) {
              len -= 2;
              int gray = getWord(is);
              if (bitDepth == 16) transRedGray = gray;
              else additional.put(PdfName.MASK, new PdfLiteral("[" + gray + " " + gray + "]"));
            }
            break;
          case 2:
            if (len >= 6) {
              len -= 6;
              int red = getWord(is);
              int green = getWord(is);
              int blue = getWord(is);
              if (bitDepth == 16) {
                transRedGray = red;
                transGreen = green;
                transBlue = blue;
              } else
                additional.put(
                    PdfName.MASK,
                    new PdfLiteral(
                        "[" + red + " " + red + " " + green + " " + green + " " + blue + " " + blue
                            + "]"));
            }
            break;
          case 3:
            if (len > 0) {
              trans = new byte[len];
              for (int k = 0; k < len; ++k) trans[k] = (byte) is.read();
              len = 0;
            }
            break;
        }
        Utilities.skip(is, len);
      } else if (IHDR.equals(marker)) {
        width = getInt(is);
        height = getInt(is);

        bitDepth = is.read();
        colorType = is.read();
        compressionMethod = is.read();
        filterMethod = is.read();
        interlaceMethod = is.read();
      } else if (PLTE.equals(marker)) {
        if (colorType == 3) {
          PdfArray colorspace = new PdfArray();
          colorspace.add(PdfName.INDEXED);
          colorspace.add(getColorspace());
          colorspace.add(new PdfNumber(len / 3 - 1));
          ByteBuffer colortable = new ByteBuffer();
          while ((len--) > 0) {
            colortable.append_i(is.read());
          }
          colorspace.add(new PdfString(colorTable = colortable.toByteArray()));
          additional.put(PdfName.COLORSPACE, colorspace);
        } else {
          Utilities.skip(is, len);
        }
      } else if (pHYs.equals(marker)) {
        int dx = getInt(is);
        int dy = getInt(is);
        int unit = is.read();
        if (unit == 1) {
          dpiX = (int) ((float) dx * 0.0254f + 0.5f);
          dpiY = (int) ((float) dy * 0.0254f + 0.5f);
        } else {
          if (dy != 0) XYRatio = (float) dx / (float) dy;
        }
      } else if (cHRM.equals(marker)) {
        xW = (float) getInt(is) / 100000f;
        yW = (float) getInt(is) / 100000f;
        xR = (float) getInt(is) / 100000f;
        yR = (float) getInt(is) / 100000f;
        xG = (float) getInt(is) / 100000f;
        yG = (float) getInt(is) / 100000f;
        xB = (float) getInt(is) / 100000f;
        yB = (float) getInt(is) / 100000f;
        hasCHRM =
            !(Math.abs(xW) < 0.0001f
                || Math.abs(yW) < 0.0001f
                || Math.abs(xR) < 0.0001f
                || Math.abs(yR) < 0.0001f
                || Math.abs(xG) < 0.0001f
                || Math.abs(yG) < 0.0001f
                || Math.abs(xB) < 0.0001f
                || Math.abs(yB) < 0.0001f);
      } else if (sRGB.equals(marker)) {
        int ri = is.read();
        intent = intents[ri];
        gamma = 2.2f;
        xW = 0.3127f;
        yW = 0.329f;
        xR = 0.64f;
        yR = 0.33f;
        xG = 0.3f;
        yG = 0.6f;
        xB = 0.15f;
        yB = 0.06f;
        hasCHRM = true;
      } else if (gAMA.equals(marker)) {
        int gm = getInt(is);
        if (gm != 0) {
          gamma = 100000f / (float) gm;
          if (!hasCHRM) {
            xW = 0.3127f;
            yW = 0.329f;
            xR = 0.64f;
            yR = 0.33f;
            xG = 0.3f;
            yG = 0.6f;
            xB = 0.15f;
            yB = 0.06f;
            hasCHRM = true;
          }
        }
      } else if (iCCP.equals(marker)) {
        do {
          --len;
        } while (is.read() != 0);
        is.read();
        --len;
        byte icccom[] = new byte[len];
        int p = 0;
        while (len > 0) {
          int r = is.read(icccom, p, len);
          if (r < 0) throw new IOException("Premature end of file.");
          p += r;
          len -= r;
        }
        byte iccp[] = PdfReader.FlateDecode(icccom, true);
        icccom = null;
        //                try {
        //                    icc_profile = ICC_Profile.getInstance(iccp);
        //                }
        // catch (Exception e) {
        icc_profile = null;
        // }
      } else if (IEND.equals(marker)) {
        break;
      } else {
        Utilities.skip(is, len);
      }
      Utilities.skip(is, 4);
    }
  }
 /**
  * Reads a PNG from a file.
  *
  * @param file the file
  * @throws IOException on error
  * @return the image
  */
 public static Image getImage(String file) throws IOException {
   return getImage(Utilities.toURL(file));
 }