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); } } }
/** * 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; }
/** * 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; }
private String decodeString(PdfString ps) { if (ps.isHexWriting()) return PdfEncodings.convertToString(ps.getBytes(), "UnicodeBigUnmarked"); else return ps.toUnicodeString(); }
/** * 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; }
/** * 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); }
/** * 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); }
/** * 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); }