Beispiel #1
0
 private void fillEncoding(PdfName encoding) {
   if (PdfName.MAC_ROMAN_ENCODING.equals(encoding) || PdfName.WIN_ANSI_ENCODING.equals(encoding)) {
     byte b[] = new byte[256];
     for (int k = 0; k < 256; ++k) b[k] = (byte) k;
     String enc = WINANSI;
     if (PdfName.MAC_ROMAN_ENCODING.equals(encoding)) enc = MACROMAN;
     String cv = PdfEncodings.convertToString(b, enc);
     char arr[] = cv.toCharArray();
     for (int k = 0; k < 256; ++k) {
       uni2byte.put(arr[k], k);
     }
   } else {
     for (int k = 0; k < 256; ++k) {
       uni2byte.put(stdEnc[k], k);
     }
   }
 }
Beispiel #2
0
 /**
  * Creates a ToUnicode CMap to allow copy and paste from Acrobat.
  *
  * @param metrics metrics[0] contains the glyph index and metrics[2] contains the Unicode code
  * @return the stream representing this CMap or <CODE>null</CODE>
  */
 public PdfStream getToUnicode(Object metrics[]) {
   if (metrics.length == 0) return null;
   StringBuffer buf =
       new StringBuffer(
           "/CIDInit /ProcSet findresource begin\n"
               + "12 dict begin\n"
               + "begincmap\n"
               + "/CIDSystemInfo\n"
               + "<< /Registry (TTX+0)\n"
               + "/Ordering (T42UV)\n"
               + "/Supplement 0\n"
               + ">> def\n"
               + "/CMapName /TTX+0 def\n"
               + "/CMapType 2 def\n"
               + "1 begincodespacerange\n"
               + "<0000><FFFF>\n"
               + "endcodespacerange\n");
   int size = 0;
   for (int k = 0; k < metrics.length; ++k) {
     if (size == 0) {
       if (k != 0) {
         buf.append("endbfrange\n");
       }
       size = Math.min(100, metrics.length - k);
       buf.append(size).append(" beginbfrange\n");
     }
     --size;
     int metric[] = (int[]) metrics[k];
     String fromTo = toHex(metric[0]);
     buf.append(fromTo).append(fromTo).append(toHex(metric[2])).append('\n');
   }
   buf.append(
       "endbfrange\n"
           + "endcmap\n"
           + "CMapName currentdict /CMap defineresource pop\n"
           + "end end\n");
   String s = buf.toString();
   PdfStream stream = new PdfStream(PdfEncodings.convertToBytes(s, null));
   stream.flateCompress(compressionLevel);
   return stream;
 }
Beispiel #3
0
 /**
  * Creates a JavaScript action. If the JavaScript is smaller than 50 characters it will be placed
  * as a string, otherwise it will be placed as a compressed stream.
  *
  * @param code the JavaScript code
  * @param writer the writer for this action
  * @param unicode select JavaScript unicode. Note that the internal Acrobat JavaScript engine does
  *     not support unicode, so this may or may not work for you
  * @return the JavaScript action
  */
 public static PdfAction javaScript(String code, PdfWriter writer, boolean unicode) {
   PdfAction js = new PdfAction();
   js.put(PdfName.S, PdfName.JAVASCRIPT);
   if (unicode && code.length() < 50) {
     js.put(PdfName.JS, new PdfString(code, PdfObject.TEXT_UNICODE));
   } else if (!unicode && code.length() < 100) {
     js.put(PdfName.JS, new PdfString(code));
   } else {
     try {
       byte b[] =
           PdfEncodings.convertToBytes(
               code, unicode ? PdfObject.TEXT_UNICODE : PdfObject.TEXT_PDFDOCENCODING);
       PdfStream stream = new PdfStream(b);
       stream.flateCompress(writer.getCompressionLevel());
       js.put(PdfName.JS, writer.addToBody(stream).getIndirectReference());
     } catch (Exception e) {
       js.put(PdfName.JS, new PdfString(code));
     }
   }
   return js;
 }
Beispiel #4
0
 private String decodeString(PdfString ps) {
   if (ps.isHexWriting()) return PdfEncodings.convertToString(ps.getBytes(), "UnicodeBigUnmarked");
   else return ps.toUnicodeString();
 }
Beispiel #5
0
  /**
   * Outputs a <CODE>double</CODE> into a format suitable for the PDF.
   *
   * @param d a double
   * @param buf a ByteBuffer
   * @return the <CODE>String</CODE> representation of the <CODE>double</CODE> if <CODE>buf</CODE>
   *     is <CODE>null</CODE>. If <CODE>buf</CODE> is <B>not</B> <CODE>null</CODE>, then the double
   *     is appended directly to the buffer and this methods returns <CODE>null</CODE>.
   */
  public static String formatDouble(double d, ByteBuffer buf) {
    if (HIGH_PRECISION) {
      DecimalFormat dn = new DecimalFormat("0.######", dfs);
      String sform = dn.format(d);
      if (buf == null) return sform;
      else {
        buf.append(sform);
        return null;
      }
    }
    boolean negative = false;
    if (Math.abs(d) < 0.000015) {
      if (buf != null) {
        buf.append(ZERO);
        return null;
      } else {
        return "0";
      }
    }
    if (d < 0) {
      negative = true;
      d = -d;
    }
    if (d < 1.0) {
      d += 0.000005;
      if (d >= 1) {
        if (negative) {
          if (buf != null) {
            buf.append((byte) '-');
            buf.append((byte) '1');
            return null;
          } else {
            return "-1";
          }
        } else {
          if (buf != null) {
            buf.append((byte) '1');
            return null;
          } else {
            return "1";
          }
        }
      }
      if (buf != null) {
        int v = (int) (d * 100000);

        if (negative) buf.append((byte) '-');
        buf.append((byte) '0');
        buf.append((byte) '.');

        buf.append((byte) (v / 10000 + ZERO));
        if (v % 10000 != 0) {
          buf.append((byte) ((v / 1000) % 10 + ZERO));
          if (v % 1000 != 0) {
            buf.append((byte) ((v / 100) % 10 + ZERO));
            if (v % 100 != 0) {
              buf.append((byte) ((v / 10) % 10 + ZERO));
              if (v % 10 != 0) {
                buf.append((byte) ((v) % 10 + ZERO));
              }
            }
          }
        }
        return null;
      } else {
        int x = 100000;
        int v = (int) (d * x);

        StringBuffer res = new StringBuffer();
        if (negative) res.append('-');
        res.append("0.");

        while (v < x / 10) {
          res.append('0');
          x /= 10;
        }
        res.append(v);
        int cut = res.length() - 1;
        while (res.charAt(cut) == '0') {
          --cut;
        }
        res.setLength(cut + 1);
        return res.toString();
      }
    } else if (d <= 32767) {
      d += 0.005;
      int v = (int) (d * 100);

      if (v < byteCacheSize && byteCache[v] != null) {
        if (buf != null) {
          if (negative) buf.append((byte) '-');
          buf.append(byteCache[v]);
          return null;
        } else {
          String tmp = PdfEncodings.convertToString(byteCache[v], null);
          if (negative) tmp = "-" + tmp;
          return tmp;
        }
      }
      if (buf != null) {
        if (v < byteCacheSize) {
          // create the cachebyte[]
          byte[] cache;
          int size = 0;
          if (v >= 1000000) {
            // the original number is >=10000, we need 5 more bytes
            size += 5;
          } else if (v >= 100000) {
            // the original number is >=1000, we need 4 more bytes
            size += 4;
          } else if (v >= 10000) {
            // the original number is >=100, we need 3 more bytes
            size += 3;
          } else if (v >= 1000) {
            // the original number is >=10, we need 2 more bytes
            size += 2;
          } else if (v >= 100) {
            // the original number is >=1, we need 1 more bytes
            size += 1;
          }

          // now we must check if we have a decimal number
          if (v % 100 != 0) {
            // yes, do not forget the "."
            size += 2;
          }
          if (v % 10 != 0) {
            size++;
          }
          cache = new byte[size];
          int add = 0;
          if (v >= 1000000) {
            cache[add++] = bytes[(v / 1000000)];
          }
          if (v >= 100000) {
            cache[add++] = bytes[(v / 100000) % 10];
          }
          if (v >= 10000) {
            cache[add++] = bytes[(v / 10000) % 10];
          }
          if (v >= 1000) {
            cache[add++] = bytes[(v / 1000) % 10];
          }
          if (v >= 100) {
            cache[add++] = bytes[(v / 100) % 10];
          }

          if (v % 100 != 0) {
            cache[add++] = (byte) '.';
            cache[add++] = bytes[(v / 10) % 10];
            if (v % 10 != 0) {
              cache[add++] = bytes[v % 10];
            }
          }
          byteCache[v] = cache;
        }

        if (negative) buf.append((byte) '-');
        if (v >= 1000000) {
          buf.append(bytes[(v / 1000000)]);
        }
        if (v >= 100000) {
          buf.append(bytes[(v / 100000) % 10]);
        }
        if (v >= 10000) {
          buf.append(bytes[(v / 10000) % 10]);
        }
        if (v >= 1000) {
          buf.append(bytes[(v / 1000) % 10]);
        }
        if (v >= 100) {
          buf.append(bytes[(v / 100) % 10]);
        }

        if (v % 100 != 0) {
          buf.append((byte) '.');
          buf.append(bytes[(v / 10) % 10]);
          if (v % 10 != 0) {
            buf.append(bytes[v % 10]);
          }
        }
        return null;
      } else {
        StringBuffer res = new StringBuffer();
        if (negative) res.append('-');
        if (v >= 1000000) {
          res.append(chars[(v / 1000000)]);
        }
        if (v >= 100000) {
          res.append(chars[(v / 100000) % 10]);
        }
        if (v >= 10000) {
          res.append(chars[(v / 10000) % 10]);
        }
        if (v >= 1000) {
          res.append(chars[(v / 1000) % 10]);
        }
        if (v >= 100) {
          res.append(chars[(v / 100) % 10]);
        }

        if (v % 100 != 0) {
          res.append('.');
          res.append(chars[(v / 10) % 10]);
          if (v % 10 != 0) {
            res.append(chars[v % 10]);
          }
        }
        return res.toString();
      }
    } else {
      StringBuffer res = new StringBuffer();
      if (negative) res.append('-');
      d += 0.5;
      long v = (long) d;
      return res.append(v).toString();
    }
  }
  /**
   * Creates a new Type1 font.
   *
   * @param ttfAfm the AFM file if the input is made with a <CODE>byte</CODE> array
   * @param pfb the PFB file if the input is made with a <CODE>byte</CODE> array
   * @param afmFile the name of one of the 14 built-in fonts or the location of an AFM file. The
   *     file must end in '.afm'
   * @param enc the encoding to be applied to this font
   * @param emb true if the font is to be embedded in the PDF
   * @throws DocumentException the AFM file is invalid
   * @throws IOException the AFM file could not be read
   */
  Type1Font(String afmFile, String enc, boolean emb, byte ttfAfm[], byte pfb[])
      throws DocumentException, IOException {
    if (emb && ttfAfm != null && pfb == null)
      throw new DocumentException("Two byte arrays are needed if the Type1 font is embedded.");
    if (emb && ttfAfm != null) this.pfb = pfb;
    encoding = enc;
    embedded = emb;
    fileName = afmFile;
    fontType = FONT_TYPE_T1;
    RandomAccessFileOrArray rf = null;
    InputStream is = null;
    if (BuiltinFonts14.containsKey(afmFile)) {
      embedded = false;
      builtinFont = true;
      byte buf[] = new byte[1024];
      try {
        if (resourceAnchor == null) resourceAnchor = new FontsResourceAnchor();
        is =
            getResourceStream(
                RESOURCE_PATH + afmFile + ".afm", resourceAnchor.getClass().getClassLoader());
        if (is == null) {
          String msg =
              afmFile
                  + " not found as resource. (The *.afm files must exist as resources in the package com.lowagie.text.pdf.fonts)";
          System.err.println(msg);
          throw new DocumentException(msg);
        }
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        while (true) {
          int size = is.read(buf);
          if (size < 0) break;
          out.write(buf, 0, size);
        }
        buf = out.toByteArray();
      } finally {
        if (is != null) {
          try {
            is.close();
          } catch (Exception e) {
            // empty on purpose
          }
        }
      }
      try {
        rf = new RandomAccessFileOrArray(buf);
        process(rf);
      } finally {
        if (rf != null) {
          try {
            rf.close();
          } catch (Exception e) {
            // empty on purpose
          }
        }
      }
    } else if (afmFile.toLowerCase().endsWith(".afm")) {
      try {
        if (ttfAfm == null) rf = new RandomAccessFileOrArray(afmFile);
        else rf = new RandomAccessFileOrArray(ttfAfm);
        process(rf);
      } finally {
        if (rf != null) {
          try {
            rf.close();
          } catch (Exception e) {
            // empty on purpose
          }
        }
      }
    } else if (afmFile.toLowerCase().endsWith(".pfm")) {
      try {
        ByteArrayOutputStream ba = new ByteArrayOutputStream();
        if (ttfAfm == null) rf = new RandomAccessFileOrArray(afmFile);
        else rf = new RandomAccessFileOrArray(ttfAfm);
        Pfm2afm.convert(rf, ba);
        rf.close();
        rf = new RandomAccessFileOrArray(ba.toByteArray());
        process(rf);
      } finally {
        if (rf != null) {
          try {
            rf.close();
          } catch (Exception e) {
            // empty on purpose
          }
        }
      }
    } else throw new DocumentException(afmFile + " is not an AFM or PFM font file.");

    EncodingScheme = EncodingScheme.trim();
    if (EncodingScheme.equals("AdobeStandardEncoding")
        || EncodingScheme.equals("StandardEncoding")) {
      fontSpecific = false;
    }
    if (!encoding.startsWith("#"))
      PdfEncodings.convertToBytes(" ", enc); // check if the encoding exists
    createEncoding();
  }
 /**
  * Adds JavaScript to the global document
  *
  * @param js the JavaScript
  */
 public void addJavaScript(String js) {
   fc.addJavaScript(js, !PdfEncodings.isPdfDocEncoding(js));
 }
 /**
  * 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;
 }
Beispiel #9
0
 /**
  * Changes the content of this <CODE>PdfObject</CODE>.
  *
  * @param content the new content of this <CODE>PdfObject</CODE>
  */
 protected void setContent(String content) {
   bytes = PdfEncodings.convertToBytes(content, null);
 }
Beispiel #10
0
 /**
  * Returns the <CODE>String</CODE>-representation of this <CODE>PdfObject</CODE>.
  *
  * @return a <CODE>String</CODE>
  */
 public String toString() {
   if (bytes == null) return super.toString();
   else return PdfEncodings.convertToString(bytes, null);
 }
Beispiel #11
0
 /**
  * Constructs a <CODE>PdfObject</CODE> of a certain <VAR>type</VAR> with a certain
  * <VAR>content</VAR>.
  *
  * @param type type of the new <CODE>PdfObject</CODE>
  * @param content content of the new <CODE>PdfObject</CODE> as a <CODE>String</CODE>.
  */
 protected PdfObject(int type, String content) {
   this.type = type;
   bytes = PdfEncodings.convertToBytes(content, null);
 }