123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811 |
- /*
- * $Id$
- * Copyright (C) 2001 The Apache Software Foundation. All rights reserved.
- * For details on use and redistribution please refer to the
- * LICENSE file included with these sources.
- */
-
- package org.apache.fop.fonts;
- import java.io.*;
- import java.util.Iterator;
- import java.util.HashMap;
- import java.util.ArrayList;
-
- /**
- * Reads a TrueType file and generates a subset
- * That can be used to embed a TrueType CID font
- * TrueType tables needed for embedded CID fonts are:
- * "head", "hhea", "loca", "maxp", "cvt ", "prep", "glyf", "hmtx" and "fpgm"
- * The TrueType spec can be found at the Microsoft
- * Typography site: http://www.microsoft.com/truetype/
- */
- public class TTFSubSetFile extends TTFFile {
- byte[] output = null;
- int realSize = 0;
- int currentPos = 0;
-
- /*
- * Offsets in name table to be filled out by table.
- * The offsets are to the checkSum field
- */
- int cvtDirOffset = 0;
- int fpgmDirOffset = 0;
- int glyfDirOffset = 0;
- int headDirOffset = 0;
- int hheaDirOffset = 0;
- int hmtxDirOffset = 0;
- int locaDirOffset = 0;
- int maxpDirOffset = 0;
- int prepDirOffset = 0;
-
- int checkSumAdjustmentOffset = 0;
- int locaOffset = 0;
-
- /**
- * Initalize the output array
- */
- private void init(int size) {
- output = new byte[size];
- realSize = 0;
- currentPos = 0;
-
- // createDirectory()
- }
-
- /**
- * Create the directory table
- */
- private void createDirectory() {
- int numTables = 9;
- // Create the TrueType header
- writeByte((byte)0);
- writeByte((byte)1);
- writeByte((byte)0);
- writeByte((byte)0);
- realSize += 4;
-
- writeUShort(numTables);
- realSize += 2;
-
- // Create searchRange, entrySelector and rangeShift
- int maxPow = maxPow2(numTables);
- int searchRange = maxPow * 16;
- writeUShort(searchRange);
- realSize += 2;
-
- writeUShort(maxPow);
- realSize += 2;
-
- writeUShort((numTables * 16) - searchRange);
- realSize += 2;
-
- // Create space for the table entries
- writeString("cvt ");
- cvtDirOffset = currentPos;
- currentPos += 12;
- realSize += 16;
-
- writeString("fpgm");
- fpgmDirOffset = currentPos;
- currentPos += 12;
- realSize += 16;
-
- writeString("glyf");
- glyfDirOffset = currentPos;
- currentPos += 12;
- realSize += 16;
-
- writeString("head");
- headDirOffset = currentPos;
- currentPos += 12;
- realSize += 16;
-
- writeString("hhea");
- hheaDirOffset = currentPos;
- currentPos += 12;
- realSize += 16;
-
- writeString("hmtx");
- hmtxDirOffset = currentPos;
- currentPos += 12;
- realSize += 16;
-
- writeString("loca");
- locaDirOffset = currentPos;
- currentPos += 12;
- realSize += 16;
-
- writeString("maxp");
- maxpDirOffset = currentPos;
- currentPos += 12;
- realSize += 16;
-
- writeString("prep");
- prepDirOffset = currentPos;
- currentPos += 12;
- realSize += 16;
- }
-
-
- /**
- * Copy the cvt table as is from original font to subset font
- */
- private void createCvt(FontFileReader in) throws IOException {
- TTFDirTabEntry entry = (TTFDirTabEntry)dirTabs.get("cvt ");
- if (entry != null) {
- pad4();
- seek_tab(in, "cvt ", 0);
- System.arraycopy(in.getBytes((int)entry.offset, (int)entry.length),
- 0, output, currentPos, (int)entry.length);
-
- int checksum = getCheckSum(currentPos, (int)entry.length);
- writeULong(cvtDirOffset, checksum);
- writeULong(cvtDirOffset + 4, currentPos);
- writeULong(cvtDirOffset + 8, (int)entry.length);
- currentPos += (int)entry.length;
- realSize += (int)entry.length;
- } else {
- throw new IOException("Can't find cvt table");
- }
- }
-
-
-
- /**
- * Copy the fpgm table as is from original font to subset font
- */
- private void createFpgm(FontFileReader in) throws IOException {
- TTFDirTabEntry entry = (TTFDirTabEntry)dirTabs.get("fpgm");
- if (entry != null) {
- pad4();
- seek_tab(in, "fpgm", 0);
- System.arraycopy(in.getBytes((int)entry.offset, (int)entry.length),
- 0, output, currentPos, (int)entry.length);
- int checksum = getCheckSum(currentPos, (int)entry.length);
- writeULong(fpgmDirOffset, checksum);
- writeULong(fpgmDirOffset + 4, currentPos);
- writeULong(fpgmDirOffset + 8, (int)entry.length);
- currentPos += (int)entry.length;
- realSize += (int)entry.length;
- } else {
- throw new IOException("Can't find fpgm table");
- }
- }
-
-
-
- /**
- * Create an empty loca table without updating checksum
- */
- private void createLoca(int size) throws IOException {
- pad4();
- locaOffset = currentPos;
- writeULong(locaDirOffset + 4, currentPos);
- writeULong(locaDirOffset + 8, size * 4 + 4);
- currentPos += size * 4 + 4;
- realSize += size * 4 + 4;
- }
-
-
- /**
- * Copy the maxp table as is from original font to subset font
- * and set num glyphs to size
- */
- private void createMaxp(FontFileReader in, int size) throws IOException {
- TTFDirTabEntry entry = (TTFDirTabEntry)dirTabs.get("maxp");
- if (entry != null) {
- pad4();
- seek_tab(in, "maxp", 0);
- System.arraycopy(in.getBytes((int)entry.offset, (int)entry.length),
- 0, output, currentPos, (int)entry.length);
- writeUShort(currentPos + 4, size);
-
- int checksum = getCheckSum(currentPos, (int)entry.length);
- writeULong(maxpDirOffset, checksum);
- writeULong(maxpDirOffset + 4, currentPos);
- writeULong(maxpDirOffset + 8, (int)entry.length);
- currentPos += (int)entry.length;
- realSize += (int)entry.length;
- } else {
- throw new IOException("Can't find maxp table");
- }
- }
-
-
- /**
- * Copy the prep table as is from original font to subset font
- */
- private void createPrep(FontFileReader in) throws IOException {
- TTFDirTabEntry entry = (TTFDirTabEntry)dirTabs.get("prep");
- if (entry != null) {
- pad4();
- seek_tab(in, "prep", 0);
- System.arraycopy(in.getBytes((int)entry.offset, (int)entry.length),
- 0, output, currentPos, (int)entry.length);
-
- int checksum = getCheckSum(currentPos, (int)entry.length);
- writeULong(prepDirOffset, checksum);
- writeULong(prepDirOffset + 4, currentPos);
- writeULong(prepDirOffset + 8, (int)entry.length);
- currentPos += (int)entry.length;
- realSize += (int)entry.length;
- } else {
- throw new IOException("Can't find prep table");
- }
- }
-
-
- /**
- * Copy the hhea table as is from original font to subset font
- * and fill in size of hmtx table
- */
- private void createHhea(FontFileReader in, int size) throws IOException {
- TTFDirTabEntry entry = (TTFDirTabEntry)dirTabs.get("hhea");
- if (entry != null) {
- pad4();
- seek_tab(in, "hhea", 0);
- System.arraycopy(in.getBytes((int)entry.offset, (int)entry.length),
- 0, output, currentPos, (int)entry.length);
- writeUShort((int)entry.length + currentPos - 2, size);
-
- int checksum = getCheckSum(currentPos, (int)entry.length);
- writeULong(hheaDirOffset, checksum);
- writeULong(hheaDirOffset + 4, currentPos);
- writeULong(hheaDirOffset + 8, (int)entry.length);
- currentPos += (int)entry.length;
- realSize += (int)entry.length;
- } else {
- throw new IOException("Can't find hhea table");
- }
- }
-
-
- /**
- * Copy the head table as is from original font to subset font
- * and set indexToLocaFormat to long and set
- * checkSumAdjustment to 0, store offset to checkSumAdjustment
- * in checkSumAdjustmentOffset
- */
- private void createHead(FontFileReader in) throws IOException {
- TTFDirTabEntry entry = (TTFDirTabEntry)dirTabs.get("head");
- if (entry != null) {
- pad4();
- seek_tab(in, "head", 0);
- System.arraycopy(in.getBytes((int)entry.offset, (int)entry.length),
- 0, output, currentPos, (int)entry.length);
-
- checkSumAdjustmentOffset = currentPos + 8;
- output[currentPos + 8] = 0; // Set checkSumAdjustment to 0
- output[currentPos + 9] = 0;
- output[currentPos + 10] = 0;
- output[currentPos + 11] = 0;
- output[currentPos + 50] = 0; // long locaformat
- output[currentPos + 51] = 1; // long locaformat
-
- int checksum = getCheckSum(currentPos, (int)entry.length);
- writeULong(headDirOffset, checksum);
- writeULong(headDirOffset + 4, currentPos);
- writeULong(headDirOffset + 8, (int)entry.length);
-
- currentPos += (int)entry.length;
- realSize += (int)entry.length;
- } else {
- throw new IOException("Can't find head table");
- }
- }
-
-
- /**
- * Create the glyf table and fill in loca table
- */
- private void createGlyf(FontFileReader in,
- HashMap glyphs) throws IOException {
- TTFDirTabEntry entry = (TTFDirTabEntry)dirTabs.get("glyf");
- int size = 0;
- int start = 0;
- int endOffset = 0; // Store this as the last loca
- if (entry != null) {
- pad4();
- start = currentPos;
-
- for (Iterator e = glyphs.keySet().iterator(); e.hasNext(); ) {
- int glyphLength = 0;
- Integer origIndex = (Integer)e.next();
- Integer subsetIndex = (Integer)glyphs.get(origIndex);
-
- int nextOffset = 0;
- if (origIndex.intValue() >= (mtx_tab.length - 1))
- nextOffset = (int)lastLoca;
- else
- nextOffset =
- (int)mtx_tab[origIndex.intValue() + 1].offset;
-
- glyphLength = nextOffset
- - (int)mtx_tab[origIndex.intValue()].offset;
-
- // Copy glyph
- System.arraycopy(in.getBytes((int)entry.offset + (int)mtx_tab[origIndex.intValue()].offset, glyphLength),
- 0, output, currentPos, glyphLength);
-
-
- // Update loca table
- writeULong(locaOffset + subsetIndex.intValue() * 4,
- currentPos - start);
- if ((currentPos - start + glyphLength) > endOffset)
- endOffset = (currentPos - start + glyphLength);
-
- currentPos += glyphLength;
- realSize += glyphLength;
-
- }
-
- size = currentPos - start;
-
- int checksum = getCheckSum(start, size);
- writeULong(glyfDirOffset, checksum);
- writeULong(glyfDirOffset + 4, start);
- writeULong(glyfDirOffset + 8, size);
- currentPos += 12;
- realSize += 12;
-
- // Update loca checksum and last loca index
- writeULong(locaOffset + glyphs.size() * 4, endOffset);
-
- checksum = getCheckSum(locaOffset, glyphs.size() * 4 + 4);
- writeULong(locaDirOffset, checksum);
- } else {
- throw new IOException("Can't find glyf table");
- }
- }
-
-
- /**
- * Create the hmtx table by copying metrics from original
- * font to subset font. The glyphs hashtable contains an
- * Integer key and Integer value that maps the original
- * metric (key) to the subset metric (value)
- */
- private void createHmtx(FontFileReader in,
- HashMap glyphs) throws IOException {
- TTFDirTabEntry entry = (TTFDirTabEntry)dirTabs.get("hmtx");
-
- int longHorMetricSize = glyphs.size() * 2;
- int leftSideBearingSize = glyphs.size() * 2;
- int hmtxSize = longHorMetricSize + leftSideBearingSize;
-
- if (entry != null) {
- pad4();
- int offset = (int)entry.offset;
- for (Iterator e = glyphs.keySet().iterator(); e.hasNext(); ) {
- Integer origIndex = (Integer)e.next();
- Integer subsetIndex = (Integer)glyphs.get(origIndex);
-
- writeUShort(currentPos + subsetIndex.intValue() * 4,
- mtx_tab[origIndex.intValue()].wx);
- writeUShort(currentPos + subsetIndex.intValue() * 4 + 2,
- mtx_tab[origIndex.intValue()].lsb);
- }
-
- int checksum = getCheckSum(currentPos, hmtxSize);
- writeULong(hmtxDirOffset, checksum);
- writeULong(hmtxDirOffset + 4, currentPos);
- writeULong(hmtxDirOffset + 8, hmtxSize);
- currentPos += hmtxSize;
- realSize += hmtxSize;
- } else {
- throw new IOException("Can't find hmtx table");
- }
- }
-
- /**
- * Returns a List containing the glyph itself plus all glyphs
- * that this composite glyph uses
- */
- private ArrayList getIncludedGlyphs(FontFileReader in, int glyphOffset,
- Integer glyphIdx) throws IOException {
- ArrayList ret = new ArrayList();
- ret.add(glyphIdx);
- int offset = glyphOffset + (int)mtx_tab[glyphIdx.intValue()].offset
- + 10;
- Integer compositeIdx = null;
- int flags = 0;
- boolean moreComposites = true;
- while (moreComposites) {
- flags = in.readTTFUShort(offset);
- compositeIdx = new Integer(in.readTTFUShort(offset + 2));
- ret.add(compositeIdx);
-
- offset += 4;
- if ((flags & 1) > 0) {
- // ARG_1_AND_ARG_2_ARE_WORDS
- offset += 4;
- } else {
- offset += 2;
- }
-
- if ((flags & 8) > 0)
- offset += 2; // WE_HAVE_A_SCALE
- else if ((flags & 64) > 0)
- offset += 4; // WE_HAVE_AN_X_AND_Y_SCALE
- else if ((flags & 128) > 0)
- offset += 8; // WE_HAVE_A_TWO_BY_TWO
-
- if ((flags & 32) > 0)
- moreComposites = true;
- else
- moreComposites = false;
- }
-
- return ret;
- }
-
-
- /**
- * Rewrite all compositepointers in glyphindex glyphIdx
- *
- */
- private void remapComposite(FontFileReader in, HashMap glyphs,
- int glyphOffset,
- Integer glyphIdx) throws IOException {
- int offset = glyphOffset + (int)mtx_tab[glyphIdx.intValue()].offset
- + 10;
-
- Integer compositeIdx = null;
- int flags = 0;
- boolean moreComposites = true;
-
- while (moreComposites) {
- flags = in.readTTFUShort(offset);
- compositeIdx = new Integer(in.readTTFUShort(offset + 2));
- Integer newIdx = (Integer)glyphs.get(compositeIdx);
- if (newIdx == null) {
- // This errormessage would look much better
- // if the fontname was printed to
- //log.error("An embedded font "
- // + "contains bad glyph data. "
- // + "Characters might not display "
- // + "correctly.");
- moreComposites = false;
- continue;
- }
-
- in.writeTTFUShort(offset + 2, newIdx.intValue());
-
- offset += 4;
-
- if ((flags & 1) > 0) {
- // ARG_1_AND_ARG_2_ARE_WORDS
- offset += 4;
- } else {
- offset += 2;
- }
-
- if ((flags & 8) > 0) {
- offset += 2; // WE_HAVE_A_SCALE
- } else if ((flags & 64) > 0) {
- offset += 4; // WE_HAVE_AN_X_AND_Y_SCALE
- } else if ((flags & 128) > 0) {
- offset += 8; // WE_HAVE_A_TWO_BY_TWO
- }
-
- if ((flags & 32) > 0)
- moreComposites = true;
- else
- moreComposites = false;
- }
- }
-
-
- /**
- * Scan all the original glyphs for composite glyphs and add those glyphs
- * to the glyphmapping also rewrite the composite glyph pointers to the new
- * mapping
- */
- private void scanGlyphs(FontFileReader in,
- HashMap glyphs) throws IOException {
- TTFDirTabEntry entry = (TTFDirTabEntry)dirTabs.get("glyf");
- HashMap newComposites = null;
- HashMap allComposites = new HashMap();
-
- int newIndex = glyphs.size();
-
- if (entry != null) {
- while (newComposites == null || newComposites.size() > 0) {
- // Inefficient to iterate through all glyphs
- newComposites = new HashMap();
-
- for (Iterator e = glyphs.keySet().iterator(); e.hasNext(); ) {
- Integer origIndex = (Integer)e.next();
-
- if (in.readTTFShort(entry.offset
- + mtx_tab[origIndex.intValue()].offset) < 0) {
- // origIndex is a composite glyph
- allComposites.put(origIndex, glyphs.get(origIndex));
- ArrayList composites =
- getIncludedGlyphs(in, (int)entry.offset,
- origIndex);
-
- // Iterate through all composites pointed to
- // by this composite and check if they exists
- // in the glyphs map, add them if not.
- for (Iterator cps = composites.iterator();
- cps.hasNext(); ) {
-
- Integer cIdx = (Integer)cps.next();
- if (glyphs.get(cIdx) == null
- && newComposites.get(cIdx) == null) {
- newComposites.put(cIdx,
- new Integer(newIndex));
- newIndex++;
- }
- }
- }
- }
-
- // Add composites to glyphs
- for (Iterator m = newComposites.keySet().iterator();
- m.hasNext(); ) {
- Integer im = (Integer)m.next();
- glyphs.put(im, newComposites.get(im));
- }
- }
-
- // Iterate through all composites to remap their composite index
-
- for (Iterator ce = allComposites.keySet().iterator();
- ce.hasNext(); ) {
- remapComposite(in, glyphs, (int)entry.offset,
- (Integer)ce.next());
- }
-
- } else {
- throw new IOException("Can't find glyf table");
- }
- }
-
-
-
- /**
- * glyphs has old index as (Integer) key and new index
- * as (Integer) value
- */
-
- public byte[] readFont(FontFileReader in, String name,
- HashMap glyphs) throws IOException {
-
- /*
- * Check if TrueType collection, and that the name
- * exists in the collection
- */
- if (!checkTTC(in, name, false))
- throw new IOException("Failed to read font");
-
- output = new byte[in.getFileSize()];
-
- readDirTabs(in);
- readFontHeader(in);
- getNumGlyphs(in);
- readHorizontalHeader(in);
- readHorizontalMetrics(in);
- readIndexToLocation(in);
-
- scanGlyphs(in, glyphs);
-
- createDirectory(); // Create the TrueType header and directory
-
- createHead(in);
- createHhea(in, glyphs.size()); // Create the hhea table
- createHmtx(in, glyphs); // Create hmtx table
- createMaxp(in, glyphs.size()); // copy the maxp table
-
- try {
- createCvt(in); // copy the cvt table
- } catch (IOException ex) {
- // Cvt is optional (only required for OpenType (MS) fonts)
- //log.error("TrueType warning: " + ex.getMessage());
- }
-
- try {
- createFpgm(in); // copy fpgm table
- } catch (IOException ex) {
- // Fpgm is optional (only required for OpenType (MS) fonts)
- //log.error("TrueType warning: " + ex.getMessage());
- }
-
- try {
- createPrep(in); // copy prep table
- } catch (IOException ex) {
- // Prep is optional (only required for OpenType (MS) fonts)
- //log.error("TrueType warning: " + ex.getMessage());
- }
-
- try {
- createLoca(glyphs.size()); // create empty loca table
- } catch (IOException ex) {
- // Loca is optional (only required for OpenType (MS) fonts)
- //log.error("TrueType warning: " + ex.getMessage());
- }
-
- try {
- createGlyf(in, glyphs);
- } catch (IOException ex) {
- // Glyf is optional (only required for OpenType (MS) fonts)
- //log.error("TrueType warning: " + ex.getMessage());
- }
-
- pad4();
- createCheckSumAdjustment();
-
- byte[] ret = new byte[realSize];
- System.arraycopy(output, 0, ret, 0, realSize);
-
- return ret;
- }
-
- /**
- * writes a ISO-8859-1 string at the currentPosition
- * updates currentPosition but not realSize
- * @return number of bytes written
- */
- private int writeString(String str) {
- int length = 0;
- try {
- byte[] buf = str.getBytes("ISO-8859-1");
- System.arraycopy(buf, 0, output, currentPos, buf.length);
- length = buf.length;
- currentPos += length;
- } catch (Exception e) {
- // This should never happen!
- }
-
- return length;
- }
-
- /**
- * Appends a byte to the output array,
- * updates currentPost but not realSize
- */
- private void writeByte(byte b) {
- output[currentPos++] = b;
- }
-
- /**
- * Appends a USHORT to the output array,
- * updates currentPost but not realSize
- */
- private void writeUShort(int s) {
- byte b1 = (byte)((s >> 8) & 0xff);
- byte b2 = (byte)(s & 0xff);
- writeByte(b1);
- writeByte(b2);
- }
-
- /**
- * Appends a USHORT to the output array,
- * at the given position without changing currentPos
- */
- private void writeUShort(int pos, int s) {
- byte b1 = (byte)((s >> 8) & 0xff);
- byte b2 = (byte)(s & 0xff);
- output[pos] = b1;
- output[pos + 1] = b2;
- }
-
- /**
- * Appends a ULONG to the output array,
- * updates currentPos but not realSize
- */
- private void writeULong(int s) {
- byte b1 = (byte)((s >> 24) & 0xff);
- byte b2 = (byte)((s >> 16) & 0xff);
- byte b3 = (byte)((s >> 8) & 0xff);
- byte b4 = (byte)(s & 0xff);
- writeByte(b1);
- writeByte(b2);
- writeByte(b3);
- writeByte(b4);
- }
-
- /**
- * Appends a ULONG to the output array,
- * at the given position without changing currentPos
- */
- private void writeULong(int pos, int s) {
- byte b1 = (byte)((s >> 24) & 0xff);
- byte b2 = (byte)((s >> 16) & 0xff);
- byte b3 = (byte)((s >> 8) & 0xff);
- byte b4 = (byte)(s & 0xff);
- output[pos] = b1;
- output[pos + 1] = b2;
- output[pos + 2] = b3;
- output[pos + 3] = b4;
- }
-
- /**
- * Read a signed short value at given position
- */
- private short readShort(int pos) {
- int ret = readUShort(pos);
- return (short)ret;
- }
-
- /**
- * Read a unsigned short value at given position
- */
- private int readUShort(int pos) {
- int ret = (int)output[pos];
- if (ret < 0)
- ret += 256;
- ret = ret << 8;
- if ((int)output[pos + 1] < 0) {
- ret |= (int)output[pos + 1] + 256;
- } else
- ret |= (int)output[pos + 1];
-
- return ret;
- }
-
- /**
- * Create a padding in the fontfile to align
- * on a 4-byte boundary
- */
- private void pad4() {
- int padSize = currentPos % 4;
- for (int i = 0; i < padSize; i++) {
- output[currentPos++] = 0;
- realSize++;
- }
- }
-
- /**
- * Returns the maximum power of 2 <= max
- */
- private int maxPow2(int max) {
- int i = 0;
- while (Math.pow(2, (double)i) < max)
- i++;
-
- return (i - 1);
- }
-
- private int log2(int num) {
- return (int)(Math.log((double)num) / Math.log(2));
- }
-
-
- private int getCheckSum(int start, int size) {
- return (int)getLongCheckSum(start, size);
- }
-
- private long getLongCheckSum(int start, int size) {
- // All the tables here are aligned on four byte boundaries
- // Add remainder to size if it's not a multiple of 4
- int remainder = size % 4;
- if (remainder != 0)
- size += remainder;
-
- long sum = 0;
-
- for (int i = 0; i < size; i += 4) {
- int l = (int)(output[start + i] << 24);
- l += (int)(output[start + i + 1] << 16);
- l += (int)(output[start + i + 2] << 16);
- l += (int)(output[start + i + 3] << 16);
- sum += l;
- if (sum > 0xffffffff)
- sum = sum - 0xffffffff;
- }
-
- return sum;
- }
-
- private void createCheckSumAdjustment() {
- long sum = getLongCheckSum(0, realSize);
- int checksum = (int)(0xb1b0afba - sum);
- writeULong(checkSumAdjustmentOffset, checksum);
- }
-
- }
-
-
|