/** * 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; }
/** * 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(); }
/** * 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); }
/** * 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); }