/* * Copyright (C) 2007-2010 Geometer Plus <contact@geometerplus.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. */ package org.geometerplus.fbreader.formats.plucker; //import java.io.IOException; //import java.util.*; //import java.util.zip.*; // //import org.geometerplus.zlibrary.core.constants.MimeTypes; //import org.geometerplus.zlibrary.core.filesystem.ZLFile; //import org.geometerplus.zlibrary.core.util.ZLInputStreamWithOffset; //import org.geometerplus.zlibrary.core.image.*; //import org.geometerplus.zlibrary.text.model.*; // //import org.geometerplus.fbreader.bookmodel.*; //import org.geometerplus.fbreader.formats.pdb.*; // //public class PluckerBookReader extends BookReader { // private final ZLFile myFile; // private final int myFileSize; // private ZLInputStreamWithOffset myStream; // private int myFont; // private char[] myCharBuffer; // private String myConvertedTextBuffer; // private boolean myParagraphStarted = false; // private boolean myBufferIsEmpty; // //private ZLTextForcedControlEntry myForcedEntry; // private final ArrayList/*<std::pair<FBTextKind,bool> >*/ myDelayedControls = new ArrayList(); // private final ArrayList/*<std::string> */myDelayedHyperlinks = new ArrayList(); // private short myCompressionVersion; // private char myBytesToSkip; // // private final ArrayList/*<std::pair<int, int> >*/ myReferencedParagraphs = new ArrayList(); // private final HashMap/*<int, std::vector<int> >*/ myParagraphMap = new HashMap(); /*<int, vector<pair<int, int>>>*/ // private ArrayList/*<Integer, Integer>*/ myParagraphVector = new ArrayList(); // private boolean myParagraphStored; // // public PluckerBookReader(ZLFile file, BookModel model, String encoding){ // super(model); // //myConverter = new EncodedTextReader(encoding).getConverter(); // myFile = file; // myFileSize = (int)file.size(); // //System.out.println(filePath + " " + encoding); // myFont = FontType.FT_REGULAR; // myCharBuffer = new char[65535]; // //myForcedEntry = null; // } // // public boolean readDocument() { // try { // myStream = new ZLInputStreamWithOffset(myFile.getInputStream()); // // PdbHeader header = new PdbHeader(myStream); // // setMainTextModel(); // myFont = FontType.FT_REGULAR; // // for (int index = 0; index < header.Offsets.length; ++index) { // int currentOffset = myStream.offset(); // int pit = header.Offsets[index]; // if (currentOffset > pit) { // break; // } // //myStream.seek(pit - currentOffset, false); // myStream.skip(pit - currentOffset); // // if (myStream.offset() != pit) { // break; // } // int recordSize = ((index != header.Offsets.length - 1) ? header.Offsets[index + 1] : myFileSize) - pit; // readRecord(recordSize); // } // myStream.close(); // } catch (IOException e) { // return false; // } // // for (Iterator it = myReferencedParagraphs.iterator(); it.hasNext();) { // Pair pair = (Pair)it.next(); // int first = (Integer)pair.myFirst; // int second = (Integer)pair.mySecond; // ArrayList/*<Integer>*/ list = (ArrayList)myParagraphMap.get(first); // if (list != null) { // for(int k = second; k < list.size(); ++k) { // if (((Integer) ((Pair)list.get(k)).myFirst) != -1) { // //addHyperlinkLabel(fromNumber(first) + '#' + fromNumber(second), (Integer)list.get(k)); // final Pair p = (Pair)list.get(k); // //addHyperlinkLabel(fromNumber(first) + '#' + fromNumber(second), (Integer) p.mySecond, (Integer) p.myFirst); // break; // } // } // } // } // myReferencedParagraphs.clear(); // myParagraphMap.clear(); // return true; // } // // private class FontType { // public static final int FT_REGULAR = 0; // public static final int FT_H1 = 1; // public static final int FT_H2 = 2; // public static final int FT_H3 = 3; // public static final int FT_H4 = 4; // public static final int FT_H5 = 5; // public static final int FT_H6 = 6; // public static final int FT_BOLD = 7; // public static final int FT_TT = 8; // public static final int FT_SMALL = 9; // public static final int FT_SUB = 10; // public static final int FT_SUP = 11; // }; // // private void readRecord(int recordSize) throws IOException { // int uid = PdbUtil.readShort(myStream); // if (uid == 1) { // myCompressionVersion = (short) PdbUtil.readShort(myStream ); // } else { // int paragraphs = PdbUtil.readShort(myStream); // // int size = PdbUtil.readShort(myStream); // //TODO ?????? // int type = myStream.read(); // // int flags = myStream.read(); // // switch (type) { // case 0: // text (TODO: found sample file and test this code) // case 1: // compressed text // { // ArrayList/*<Integer>*/ pars = new ArrayList(); // for (int i = 0; i < paragraphs; ++i) { // int pSize = PdbUtil.readShort(myStream); // pars.add(pSize); // myStream.skip(2); // } // // boolean doProcess = false; // if (type == 0) {//? // byte[] buf = new byte[size]; // doProcess = myStream.read(buf, 0, (int)size) == size; // if (doProcess) { // // TODO: use encoding!!!! // // TODO: don't create any new objects!!!! // myCharBuffer = new String(buf).toCharArray(); // } // } else if (myCompressionVersion == 1) { // byte[] buf = new byte[size]; // doProcess = // DocDecompressor.decompress(myStream, buf, recordSize - 8 - 4 * paragraphs) == size; // if (doProcess) { // myCharBuffer = new String(buf).toCharArray(); // } // } else if (myCompressionVersion == 2) { // byte input [] = new byte[(int) (recordSize - 10 - 4 * paragraphs)]; // final int inputSize = myStream.read(input); // Inflater decompressor = new Inflater(); // decompressor.setInput(input, 0, inputSize); // byte output [] = new byte[size]; // try { // doProcess = decompressor.inflate(output) == size; // decompressor.end(); // myCharBuffer = new String(output, 0, size).toCharArray(); // } catch (DataFormatException e) { // // TODO Auto-generated catch block // // e.printStackTrace(); // System.out.println(e.getMessage()); // } // //doProcess = // //ZLZDecompressor(recordSize - 10 - 4 * paragraphs). // //decompress(myStream, myCharBuffer, size) == size; // } // if (doProcess) { // addHyperlinkLabel(fromNumber(uid)); // myParagraphMap.put(uid, new ArrayList()); // myParagraphVector = (ArrayList)myParagraphMap.get(uid); // processTextRecord(size, pars); // if ((flags & 0x1) == 0) { //// insertEndOfTextParagraph(); // //setNewTextModel(); // } // } // break; // } // case 2: // image // case 3: // compressed image // { // ZLImage image = null; // if (type == 2) { // System.out.println("non-compressed image"); // image = new PluckerFileImage(MimeTypes.MIME_IMAGE_PALM, myFile, myStream.offset(), recordSize - 8); // } else if (myCompressionVersion == 1) { // System.out.println("DocCompressedImage"); // image = new DocCompressedFileImage(MimeTypes.MIME_IMAGE_PALM, myFile, myStream.offset(), recordSize - 8); // } else if (myCompressionVersion == 2) { // System.out.println("ZCompressedImage"); // image = new ZCompressedFileImage(MimeTypes.MIME_IMAGE_PALM, myFile, myStream.offset() + 2, recordSize - 10); // } // if (image != null) { // addImage(fromNumber(uid), image); // } // break; // } // case 9: // category record is ignored // break; // case 10: // short typeCode = (short) PdbUtil.readShort(myStream); // break; // case 11: // style sheet record is ignored // break; // case 12: // font page record is ignored // break; // case 13: // TODO: process tables // case 14: // TODO: process tables // break; // case 15: // multiimage // { // short columns = (short) PdbUtil.readShort(myStream); // short rows = (short) PdbUtil.readShort(myStream); // System.out.println("multiimage"); // /*PluckerMultiImage image = new PluckerMultiImage(rows, columns, Model.getImageMap()); // for (int i = 0; i < size / 2 - 2; ++i) { // short us = (short)myStream.read(); // PdbUtil.readShort(myStream, us); // image.addId(fromNumber(us)); // } // addImage(fromNumber(uid), image); // */break; // } // default: // //std::cerr << "type = " << (int)type << "\n"; // break; // } // } // } // // private void processTextRecord(int size, ArrayList/*<Integer>*/ pars) { // int start = 0; // int end = 0; // // for (Iterator it = pars.iterator(); it.hasNext();) { // start = end; // end = start + (Integer)it.next(); // if (end > size) { // return; // } // myParagraphStored = false; // processTextParagraph(myCharBuffer, start, end); // if (!myParagraphStored) { // myParagraphVector.add(new Pair(-1, -1)); // } // } // } // // private void processTextParagraph(char[] data, int start, int end) { // changeFont(FontType.FT_REGULAR); // while (popKind()) {} // // myParagraphStarted = false; // myBytesToSkip = 0; // // int textStart = start; // boolean functionFlag = false; // for (int ptr = start; ptr < end; ++ptr) { // if (data[ptr] == 0) { // functionFlag = true; // if (ptr > textStart) { // safeBeginParagraph(); // // myConvertedTextBuffer = "";//.erase(); // myConvertedTextBuffer = "";//myConverter.convert(data, textStart, ptr); // addData(myConvertedTextBuffer.toCharArray()); // myBufferIsEmpty = false; // } // } else if (functionFlag) { // int paramCounter = (data[ptr]) % 8; // if (end - ptr > paramCounter) { // processTextFunction(data, ptr); // ptr += paramCounter; // } else { // ptr = end - 1; // } // functionFlag = false; // if (myBytesToSkip > 0) { // ptr += myBytesToSkip; // myBytesToSkip = 0; // } // textStart = ptr + 1; // } else { // if (data[ptr] == 0xA0) { // data[ptr] = 0x20; // } // if (!myParagraphStarted && (textStart == ptr) && (data[ptr] == ' ')) { // ++textStart; // } // } // } // if (end > textStart) { // safeBeginParagraph(); // // myConvertedTextBuffer = "";//erase(); // myConvertedTextBuffer = "";//myConverter.convert(data, textStart, end); // addData(myConvertedTextBuffer.toCharArray()); // myBufferIsEmpty = false; // } // safeEndParagraph(); // //if (myForcedEntry != null) { // // myForcedEntry = null; // //} // myDelayedControls.clear(); // } // // private void processTextFunction(char[] ptr, int cur) { // switch (ptr[cur]) { // case 0x08: // safeAddControl(FBTextKind.INTERNAL_HYPERLINK, false); // break; // case 0x0A: // safeAddHyperlinkControl(fromNumber(twoBytes(ptr, cur+ 1))); // break; // case 0x0C: // { // int sectionNum = twoBytes(ptr, cur + 1); // int paragraphNum = twoBytes(ptr, cur + 3); // safeAddHyperlinkControl(fromNumber(sectionNum) + '#' + fromNumber(paragraphNum)); // myReferencedParagraphs.add(new Pair(sectionNum, paragraphNum)); // break; // } // case 0x11: // changeFont((ptr[cur + 1])); // break; // case 0x1A: // safeBeginParagraph(); // // System.out.println("image ref"); // addImageReference(fromNumber(twoBytes(ptr, cur + 1)), (short) 0); // break; // case 0x22: // if (!myParagraphStarted) { // //if (myForcedEntry == null) { // // myForcedEntry = new ZLTextForcedControlEntry(); // //} // //myForcedEntry.setLeftIndent((short)ptr[cur + 1]); // //myForcedEntry.setRightIndent((short)ptr[cur + 2]); // } // break; // case 0x29: // if (!myParagraphStarted) { // //if (myForcedEntry == null) { // // myForcedEntry = new ZLTextForcedControlEntry(); // //} // //switch (ptr[cur + 1]) { // // case 0: myForcedEntry.setAlignmentType(ZLTextAlignmentType.ALIGN_LEFT); break; // // case 1: myForcedEntry.setAlignmentType(ZLTextAlignmentType.ALIGN_RIGHT); break; // // case 2: myForcedEntry.setAlignmentType(ZLTextAlignmentType.ALIGN_CENTER); break; // // case 3: myForcedEntry.setAlignmentType(ZLTextAlignmentType.ALIGN_JUSTIFY); break; // //} // } // break; // case 0x33: // just break line instead of horizontal rule (TODO: draw horizontal rule?) // safeEndParagraph(); // break; // case 0x38: // safeEndParagraph(); // break; // case 0x40: // safeAddControl(FBTextKind.EMPHASIS, true); // break; // case 0x48: // safeAddControl(FBTextKind.EMPHASIS, false); // break; // case 0x53: // color setting is ignored // break; // case 0x5C: // // System.out.println("image ref"); // addImageReference(fromNumber(twoBytes(ptr, cur + 3)), (short) 0); // break; // case 0x60: // underlined text is ignored // break; // case 0x68: // underlined text is ignored // break; // case 0x70: // strike-through text is ignored // break; // case 0x78: // strike-through text is ignored // break; // case 0x83: // { // safeBeginParagraph(); // addData(new char[] { (char)twoBytes(ptr, cur + 2) }); // myBufferIsEmpty = false; // myBytesToSkip = ptr[cur+1]; // break; // } // case 0x85: // TODO: process 4-byte unicode character // break; // case 0x8E: // custom font operations are ignored // case 0x8C: // case 0x8A: // case 0x88: // break; // case 0x90: // TODO: add table processing // case 0x92: // TODO: process table // case 0x97: // TODO: process table // break; // default: // this should be impossible // //std::cerr << "Oops... function #" << (int)(unsigned char)*ptr << "\n"; // break; // } // } // // private void setFont(int font, boolean start) { // switch (font) { // case FontType.FT_REGULAR: // break; // case FontType.FT_H1: // case FontType.FT_H2: // case FontType.FT_H3: // case FontType.FT_H4: // case FontType.FT_H5: // case FontType.FT_H6: // processHeader(font, start); // break; // case FontType.FT_BOLD: // safeAddControl(FBTextKind.BOLD, start); // break; // case FontType.FT_TT: // safeAddControl(FBTextKind.CODE, start); // break; // case FontType.FT_SMALL: // break; // case FontType.FT_SUB: // safeAddControl(FBTextKind.SUB, start); // break; // case FontType.FT_SUP: // safeAddControl(FBTextKind.SUP, start); // break; // } // } // // private void changeFont(int font) { // if (myFont == font) { // return; // } // setFont(myFont, false); // myFont = font; // setFont(myFont, true); // } // // private void safeAddControl(byte kind, boolean start) { // if (myParagraphStarted) { // addControl((Byte)kind, (Boolean)start); // } else { // myDelayedControls.add(new Pair(kind, start)); // } // } // private void safeAddHyperlinkControl(String id) { // if (myParagraphStarted) { // addHyperlinkControl(FBTextKind.INTERNAL_HYPERLINK, id); // } else { // myDelayedHyperlinks.add(id); // } // } // // private void safeBeginParagraph() { // if (!myParagraphStarted) { // myParagraphStarted = true; // myBufferIsEmpty = true; // beginParagraph(ZLTextParagraph.Kind.TEXT_PARAGRAPH); // if (!myParagraphStored) { // //final ArrayList models = Model.getBookTextModels(); // //myParagraphVector.add(new Pair(((ZLTextPlainModel) models.get(models.size()-1)/*BookTextModel*/).getParagraphsNumber() - 1, models.size() - 1)); // myParagraphStored = true; // } // for (Iterator it = myDelayedControls.iterator(); it.hasNext(); ) { // Pair pit = (Pair)it.next(); // addControl((Byte)pit.myFirst, (Boolean)pit.mySecond); // } // //if (myForcedEntry != null) { // // addControl(myForcedEntry); // //} else { // addControl(FBTextKind.REGULAR, true); // //} // for (Iterator it = myDelayedHyperlinks.iterator(); it.hasNext(); ) { // addHyperlinkControl(FBTextKind.INTERNAL_HYPERLINK, (String)it.next()); // } // myDelayedHyperlinks.clear(); // } // } // // private void safeEndParagraph() { // if (myParagraphStarted) { // if (myBufferIsEmpty) { // final String SPACE = " "; // addData(SPACE.toCharArray()); // } // endParagraph(); // myParagraphStarted = false; // } // } // // private void processHeader(int font, boolean start) { // if (start) { // enterTitle(); // int kind; // switch (font) { // case FontType.FT_H1: // kind = FBTextKind.H1; // break; // case FontType.FT_H2: // kind = FBTextKind.H2; // break; // case FontType.FT_H3: // kind = FBTextKind.H3; // break; // case FontType.FT_H4: // kind = FBTextKind.H4; // break; // case FontType.FT_H5: // kind = FBTextKind.H5; // break; // case FontType.FT_H6: // default: // kind = FBTextKind.H6; // break; // } // pushKind((byte)kind); // } else { // popKind(); // exitTitle(); // } // } // // static private class Pair { // public Object myFirst; // public Object mySecond; // Pair(Object first, Object second) { // this.myFirst = first; // this.mySecond = second; // } // } // // static private int twoBytes(char[] ptr, int offset) { // return 256 * ptr[offset] + ptr[offset+1]; // } // // static String fromNumber(int num) { // String str = ""; // str += num; // //ZLStringUtil.appendNumber(str, num); // return str; // } //}