iText 5 itextpdf.jar Source Code

itextpdf.jar is a component in iText 5 Java library to provide core functionalities. iText Java library allows you to generate and manage PDF documents.

The Source Code files are provided at iText GitHub site.

You can compile it to generate your JAR file, using pom.xml as the build configuration file.

The source code of itextpdf-5.5.14.jar is provided below:

✍: FYIcenter.com

com/itextpdf/text/pdf/ByteBuffer.java

/*
 *
 * This file is part of the iText (R) project.
    Copyright (c) 1998-2020 iText Group NV
 * Authors: Bruno Lowagie, Paulo Soares, et al.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License version 3
 * as published by the Free Software Foundation with the addition of the
 * following permission added to Section 15 as permitted in Section 7(a):
 * FOR ANY PART OF THE COVERED WORK IN WHICH THE COPYRIGHT IS OWNED BY
 * ITEXT GROUP. ITEXT GROUP DISCLAIMS THE WARRANTY OF NON INFRINGEMENT
 * OF THIRD PARTY RIGHTS
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU Affero General Public License
 * along with this program; if not, see http://www.gnu.org/licenses or write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA, 02110-1301 USA, or download the license from the following URL:
 * http://itextpdf.com/terms-of-use/
 *
 * The interactive user interfaces in modified source and object code versions
 * of this program must display Appropriate Legal Notices, as required under
 * Section 5 of the GNU Affero General Public License.
 *
 * In accordance with Section 7(b) of the GNU Affero General Public License,
 * a covered work must retain the producer line in every PDF that is created
 * or manipulated using iText.
 *
 * You can be released from the requirements of the license by purchasing
 * a commercial license. Buying such a license is mandatory as soon as you
 * develop commercial activities involving the iText software without
 * disclosing the source code of your own applications.
 * These activities include: offering paid services to customers as an ASP,
 * serving PDFs on the fly in a web application, shipping iText with a closed
 * source product.
 *
 * For more information, please contact iText Software Corp. at this
 * address: sales@itextpdf.com
 */
package com.itextpdf.text.pdf;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.util.Locale;
import com.itextpdf.text.error_messages.MessageLocalization;

import com.itextpdf.text.DocWriter;

/**
 * Acts like a <CODE>StringBuffer</CODE> but works with <CODE>byte</CODE> arrays.
 * Floating point is converted to a format suitable to the PDF.
 * @author Paulo Soares
 */

public class ByteBuffer extends OutputStream {
    /** The count of bytes in the buffer. */
    protected int count;
    
    /** The buffer where the bytes are stored. */
    protected byte buf[];
    
    private static int byteCacheSize = 0;
    
    private static byte[][] byteCache = new byte[byteCacheSize][];
    public static final byte ZERO = (byte)'0';
    private static final char[] chars = new char[] {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
    private static final byte[] bytes = new byte[] {48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102};
    /**
     * If <CODE>true</CODE> always output floating point numbers with 6 decimal digits.
     * If <CODE>false</CODE> uses the faster, although less precise, representation.
     */    
    public static boolean HIGH_PRECISION = false;
    private static final DecimalFormatSymbols dfs = new DecimalFormatSymbols(Locale.US);
    
    /** Creates new ByteBuffer with capacity 128 */
    public ByteBuffer() {
        this(128);
    }
    
    /**
     * Creates a byte buffer with a certain capacity.
     * @param size the initial capacity
     */
    public ByteBuffer(int size) {
        if (size < 1)
            size = 128;
        buf = new byte[size];
    }
    
    /**
     * Sets the cache size.
     * <P>
     * This can only be used to increment the size.
     * If the size that is passed through is smaller than the current size, nothing happens.
     *
     * @param   size    the size of the cache
     */
    
    public static void setCacheSize(int size) {
        if (size > 3276700) size = 3276700;
        if (size <= byteCacheSize) return;
        byte[][] tmpCache = new byte[size][];
        System.arraycopy(byteCache, 0, tmpCache, 0, byteCacheSize);
        byteCache = tmpCache;
        byteCacheSize = size;
    }
    
    /**
     * You can fill the cache in advance if you want to.
     *
     * @param   decimals
     */
    
    public static void fillCache(int decimals) {
        int step = 1;
        switch(decimals) {
            case 0:
                step = 100;
                break;
            case 1:
                step = 10;
                break;
        }
        for (int i = 1; i < byteCacheSize; i += step) {
            if (byteCache[i] != null) continue;
            byteCache[i] = convertToBytes(i);
        }
    }
    
    /**
     * Converts an double (multiplied by 100 and cast to an int) into an array of bytes.
     *
     * @param   i   the int
     * @return  a byte array
     */
    
    private static byte[] convertToBytes(int i) {
        int size = (int)Math.floor(Math.log(i) / Math.log(10));
        if (i % 100 != 0) {
            size += 2;
        }
        if (i % 10 != 0) {
            size++;
        }
        if (i < 100) {
            size++;
            if (i < 10) {
                size++;
            }
        }
        size--;
        byte[] cache = new byte[size];
        size --;
        if (i < 100) {
            cache[0] = (byte)'0';
        }
        if (i % 10 != 0) {
            cache[size--] = bytes[i % 10];
        }
        if (i % 100 != 0) {
            cache[size--] = bytes[(i / 10) % 10];
            cache[size--] = (byte)'.';
        }
        size = (int)Math.floor(Math.log(i) / Math.log(10)) - 1;
        int add = 0;
        while (add < size) {
            cache[add] = bytes[(i / (int)Math.pow(10, size - add + 1)) % 10];
            add++;
        }
        return cache;
    }
    
    /**
     * Appends an <CODE>int</CODE>. The size of the array will grow by one.
     * @param b the int to be appended
     * @return a reference to this <CODE>ByteBuffer</CODE> object
     */
    public ByteBuffer append_i(int b) {
        int newcount = count + 1;
        if (newcount > buf.length) {
            byte newbuf[] = new byte[Math.max(buf.length << 1, newcount)];
            System.arraycopy(buf, 0, newbuf, 0, count);
            buf = newbuf;
        }
        buf[count] = (byte)b;
        count = newcount;
        return this;
    }
    
    /**
     * Appends the subarray of the <CODE>byte</CODE> array. The buffer will grow by
     * <CODE>len</CODE> bytes.
     * @param b the array to be appended
     * @param off the offset to the start of the array
     * @param len the length of bytes to append
     * @return a reference to this <CODE>ByteBuffer</CODE> object
     */
    public ByteBuffer append(byte b[], int off, int len) {
        if ((off < 0) || (off > b.length) || (len < 0) ||
        ((off + len) > b.length) || ((off + len) < 0) || len == 0)
            return this;
        int newcount = count + len;
        if (newcount > buf.length) {
            byte newbuf[] = new byte[Math.max(buf.length << 1, newcount)];
            System.arraycopy(buf, 0, newbuf, 0, count);
            buf = newbuf;
        }
        System.arraycopy(b, off, buf, count, len);
        count = newcount;
        return this;
    }
    
    /**
     * Appends an array of bytes.
     * @param b the array to be appended
     * @return a reference to this <CODE>ByteBuffer</CODE> object
     */
    public ByteBuffer append(byte b[]) {
        return append(b, 0, b.length);
    }
    
    /**
     * Appends a <CODE>String</CODE> to the buffer. The <CODE>String</CODE> is
     * converted according to the encoding ISO-8859-1.
     * @param str the <CODE>String</CODE> to be appended
     * @return a reference to this <CODE>ByteBuffer</CODE> object
     */
    public ByteBuffer append(String str) {
        if (str != null)
            return append(DocWriter.getISOBytes(str));
        return this;
    }
    
    /**
     * Appends a <CODE>char</CODE> to the buffer. The <CODE>char</CODE> is
     * converted according to the encoding ISO-8859-1.
     * @param c the <CODE>char</CODE> to be appended
     * @return a reference to this <CODE>ByteBuffer</CODE> object
     */
    public ByteBuffer append(char c) {
        return append_i(c);
    }
    
    /**
     * Appends another <CODE>ByteBuffer</CODE> to this buffer.
     * @param buf the <CODE>ByteBuffer</CODE> to be appended
     * @return a reference to this <CODE>ByteBuffer</CODE> object
     */
    public ByteBuffer append(ByteBuffer buf) {
        return append(buf.buf, 0, buf.count);
    }
    
    /**
     * Appends the string representation of an <CODE>int</CODE>.
     * @param i the <CODE>int</CODE> to be appended
     * @return a reference to this <CODE>ByteBuffer</CODE> object
     */
    public ByteBuffer append(int i) {
        return append((double)i);
    }
    
    /**
     * Appends the string representation of a <CODE>long</CODE>.
     * @param i the <CODE>long</CODE> to be appended
     * @return a reference to this <CODE>ByteBuffer</CODE> object
     */
    public ByteBuffer append(long i) {
        return append(Long.toString(i));
    }
    
    public ByteBuffer append(byte b) {
        return append_i(b);
    }
    
    public ByteBuffer appendHex(byte b) {
        append(bytes[(b >> 4) & 0x0f]);
        return append(bytes[b & 0x0f]);
    }
    
    /**
     * Appends a string representation of a <CODE>float</CODE> according
     * to the Pdf conventions.
     * @param i the <CODE>float</CODE> to be appended
     * @return a reference to this <CODE>ByteBuffer</CODE> object
     */
    public ByteBuffer append(float i) {
        return append((double)i);
    }
    
    /**
     * Appends a string representation of a <CODE>double</CODE> according
     * to the Pdf conventions.
     * @param d the <CODE>double</CODE> to be appended
     * @return a reference to this <CODE>ByteBuffer</CODE> object
     */
    public ByteBuffer append(double d) {
        append(formatDouble(d, this));
        return this;
    }
    
    /**
     * Outputs a <CODE>double</CODE> into a format suitable for the PDF.
     * @param d a double
     * @return the <CODE>String</CODE> representation of the <CODE>double</CODE>
     */
    public static String formatDouble(double d) {
        return formatDouble(d, null);
    }
    
    /**
     * 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);
                
                StringBuilder res = new StringBuilder();
                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 {
                StringBuilder res = new StringBuilder();
                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 {
            d += 0.5;
            long v = (long) d;
            if (negative) 
                return "-" + Long.toString(v);
            else
                return Long.toString(v);
        }
    }
    
    /**
     * Sets the size to zero.
     */
    public void reset() {
        count = 0;
    }
    
    /**
     * Creates a newly allocated byte array. Its size is the current
     * size of this output stream and the valid contents of the buffer
     * have been copied into it.
     *
     * @return  the current contents of this output stream, as a byte array.
     */
    public byte[] toByteArray() {
        byte newbuf[] = new byte[count];
        System.arraycopy(buf, 0, newbuf, 0, count);
        return newbuf;
    }
    
    /**
     * Returns the current size of the buffer.
     *
     * @return the value of the <code>count</code> field, which is the number of valid bytes in this byte buffer.
     */
    public int size() {
        return count;
    }
    
    public void setSize(int size) {
        if (size > count || size < 0)
            throw new IndexOutOfBoundsException(MessageLocalization.getComposedMessage("the.new.size.must.be.positive.and.lt.eq.of.the.current.size"));
        count = size;
    }
    
    /**
     * Converts the buffer's contents into a string, translating bytes into
     * characters according to the platform's default character encoding.
     *
     * @return String translated from the buffer's contents.
     */
    @Override
    public String toString() {
        return new String(buf, 0, count);
    }
    
    /**
     * Converts the buffer's contents into a string, translating bytes into
     * characters according to the specified character encoding.
     *
     * @param   enc  a character-encoding name.
     * @return String translated from the buffer's contents.
     * @throws UnsupportedEncodingException
     *         If the named encoding is not supported.
     */
    public String toString(String enc) throws UnsupportedEncodingException {
        return new String(buf, 0, count, enc);
    }
    
    /**
     * Writes the complete contents of this byte buffer output to
     * the specified output stream argument, as if by calling the output
     * stream's write method using <code>out.write(buf, 0, count)</code>.
     *
     * @param      out   the output stream to which to write the data.
     * @exception  IOException  if an I/O error occurs.
     */
    public void writeTo(OutputStream out) throws IOException {
        out.write(buf, 0, count);
    }
    
    public void write(int b) throws IOException {
        append((byte)b);
    }
    
    @Override
    public void write(byte[] b, int off, int len) {
        append(b, off, len);
    }
    
    public byte[] getBuffer() {
        return buf;
    }
}

com/itextpdf/text/pdf/ByteBuffer.java

 

⇒ iText-2.1.6.jar - iText, a JAVA-PDF library

⇐ iText layout.jar Source Code

⇑ Download and Install iText Java Library

⇑⇑ iText for PDF Generation

2021-07-03, 47771👍, 0💬