示例#1
0
 @Override
 public boolean endElementHandler(String tag) {
   tag = tag.toLowerCase().intern();
   switch (myReadState) {
     case READ_NONE:
       break;
     case READ_MAP:
       if (TAG_NAVMAP == tag) {
         myReadState = READ_NONE;
       }
       break;
     case READ_POINT:
       if (TAG_NAVPOINT == tag) {
         NavPoint last = myPointStack.get(myPointStack.size() - 1);
         if (last.Text.length() == 0) {
           last.Text = "...";
         }
         myNavigationMap.put(last.Order, last);
         myPointStack.remove(myPointStack.size() - 1);
         myReadState = (myPointStack.isEmpty()) ? READ_MAP : READ_POINT;
       }
     case READ_LABEL:
       if (TAG_NAVLABEL == tag) {
         myReadState = READ_POINT;
       }
       break;
     case READ_TEXT:
       if (TAG_TEXT == tag) {
         myReadState = READ_LABEL;
       }
       break;
   }
   return false;
 }
 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();
   }
 }
示例#3
0
 @Override
 public void characterDataHandler(char[] ch, int start, int length) {
   if (myReadState == READ_TEXT) {
     final ArrayList<NavPoint> stack = myPointStack;
     final NavPoint last = stack.get(stack.size() - 1);
     last.Text += new String(ch, start, length);
   }
 }
 private void safeAddHyperlinkControl(String id) {
   if (myParagraphStarted) {
     addHyperlinkControl(FBTextKind.INTERNAL_HYPERLINK, id);
   } else {
     myDelayedHyperlinks.add(id);
   }
 }
 private void safeAddControl(byte kind, boolean start) {
   if (myParagraphStarted) {
     addControl((Byte) kind, (Boolean) start);
   } else {
     myDelayedControls.add(new Pair(kind, start));
   }
 }
示例#6
0
  boolean readBook(ZLFile file) {
    myFilePrefix = MiscUtil.htmlDirectoryPrefix(file);

    myIdToHref.clear();
    myHtmlFileNames.clear();
    myParagraphIndexList.clear();
    myNCXTOCFileName = null;
    myTourTOC.clear();
    myGuideTOC.clear();
    myState = READ_NONE;

    if (!read(file)) {
      return false;
    }

    myModelReader.setMainTextModel();
    myModelReader.pushKind(FBTextKind.REGULAR);

    int count = 0;
    for (String name : myHtmlFileNames) {
      final ZLFile xhtmlFile = ZLFile.createFileByPath(myFilePrefix + name);
      if (xhtmlFile == null) {
        // NPE fix: null for bad attributes in .opf XML file
        return false;
      }
      if (count++ == 0 && xhtmlFile.getPath().equals(myCoverFileName)) {
        continue;
      }
      final XHTMLReader reader = new XHTMLReader(myModelReader, myFileNumbers);
      final String referenceName =
          reader.getFileAlias(MiscUtil.archiveEntryName(xhtmlFile.getPath()));

      myModelReader.addHyperlinkLabel(referenceName);
      myParagraphIndexList.add(myModelReader.Model.BookTextModel.getParagraphsNumber());
      myTOCLabels.put(referenceName, myModelReader.Model.BookTextModel.getParagraphsNumber());
      reader.readFile(xhtmlFile, referenceName + '#');
      myModelReader.insertEndOfSectionParagraph();
    }

    final FBReaderApp fbreader = (FBReaderApp) ZLApplication.Instance();
    //		fbreader.setTOCLabels(myTOCLabels);
    fbreader.setParagraphIndexList(myParagraphIndexList);
    fbreader.setHtmlFileNames(myHtmlFileNames, myFilePrefix, myCoverFileName);
    generateTOC();

    return true;
  }
  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();
  }
示例#9
0
  private void generateTOC() {
    if (myNCXTOCFileName != null) {
      final NCXReader ncxReader = new NCXReader(myModelReader);
      if (ncxReader.readFile(myFilePrefix + myNCXTOCFileName)) {
        final Map<Integer, NCXReader.NavPoint> navigationMap = ncxReader.navigationMap();
        if (!navigationMap.isEmpty()) {
          int level = 0;
          for (NCXReader.NavPoint point : navigationMap.values()) {
            final BookModel.Label label = getTOCLabel(point.ContentHRef);
            int index = (label != null) ? label.ParagraphIndex : -1;
            while (level > point.Level) {
              myModelReader.endContentsParagraph();
              --level;
            }
            while (++level <= point.Level) {
              myModelReader.beginContentsParagraph(-2);
              myModelReader.addContentsData(Dots);
              myModelReader.addPathData(Dots);
            }
            myModelReader.beginContentsParagraph(index);
            myModelReader.addContentsData(point.Text.toCharArray());
            myModelReader.addPathData(point.ContentHRef.toCharArray());
          }
          while (level > 0) {
            myModelReader.endContentsParagraph();
            --level;
          }
          return;
        }
      }
    }

    for (Reference ref : myTourTOC.isEmpty() ? myGuideTOC : myTourTOC) {
      final BookModel.Label label = getTOCLabel(ref.HRef);
      if (label != null) {
        final int index = label.ParagraphIndex;
        if (index != -1) {
          myModelReader.beginContentsParagraph(index);
          myModelReader.addContentsData(ref.Title.toCharArray());
          myModelReader.addPathData(ref.HRef.toCharArray());
          myModelReader.endContentsParagraph();
        }
      }
    }
  }
  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;
  }
示例#11
0
 @Override
 public boolean startElementHandler(String tag, ZLStringMap attributes) {
   tag = tag.toLowerCase().intern();
   switch (myReadState) {
     case READ_NONE:
       if (tag == TAG_NAVMAP) {
         myReadState = READ_MAP;
       }
       break;
     case READ_MAP:
       if (tag == TAG_NAVPOINT) {
         final String order = attributes.getValue(ATTRIBUTE_PLAYORDER);
         final int index = (order != null) ? atoi(order) : myPlayIndex++;
         myPointStack.add(new NavPoint(index, myPointStack.size()));
         myReadState = READ_POINT;
       }
       break;
     case READ_POINT:
       if (tag == TAG_NAVPOINT) {
         final String order = attributes.getValue(ATTRIBUTE_PLAYORDER);
         final int index = (order != null) ? atoi(order) : myPlayIndex++;
         myPointStack.add(new NavPoint(index, myPointStack.size()));
       } else if (tag == TAG_NAVLABEL) {
         myReadState = READ_LABEL;
       } else if (tag == TAG_CONTENT) {
         final int size = myPointStack.size();
         if (size > 0) {
           myPointStack.get(size - 1).ContentHRef =
               ZLArchiveEntryFile.normalizeEntryName(
                   myLocalPathPrefix + MiscUtil.decodeHtmlReference(attributes.getValue("src")));
         }
       }
       break;
     case READ_LABEL:
       if (TAG_TEXT == tag) {
         myReadState = READ_TEXT;
       }
       break;
     case READ_TEXT:
       break;
   }
   return false;
 }
 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 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
          {
            final String mime = "image/palm";
            ZLImage image = null;
            if (type == 2) {
              System.out.println("non-compressed image");
              image = new PluckerFileImage(mime, myFile, myStream.offset(), recordSize - 8);
            } else if (myCompressionVersion == 1) {
              System.out.println("DocCompressedImage");
              image = new DocCompressedFileImage(mime, myFile, myStream.offset(), recordSize - 8);
            } else if (myCompressionVersion == 2) {
              System.out.println("ZCompressedImage");
              image =
                  new ZCompressedFileImage(mime, 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;
      }
    }
  }
示例#14
0
 @Override
 public boolean startElementHandler(String tag, ZLStringMap xmlattributes, String[] tagStack) {
   tag = tag.toLowerCase();
   if (myOPFSchemePrefix != null && tag.startsWith(myOPFSchemePrefix)) {
     tag = tag.substring(myOPFSchemePrefix.length());
   }
   tag = tag.intern();
   if (MANIFEST == tag) {
     myState = READ_MANIFEST;
   } else if (SPINE == tag) {
     myNCXTOCFileName = myIdToHref.get(xmlattributes.getValue("toc"));
     myState = READ_SPINE;
   } else if (GUIDE == tag) {
     myState = READ_GUIDE;
   } else if (TOUR == tag) {
     myState = READ_TOUR;
   } else if (myState == READ_MANIFEST && ITEM == tag) {
     final String id = xmlattributes.getValue("id");
     String href = xmlattributes.getValue("href");
     if ((id != null) && (href != null)) {
       href = MiscUtil.decodeHtmlReference(href);
       myIdToHref.put(id, href);
     }
   } else if (myState == READ_SPINE && ITEMREF == tag) {
     final String id = xmlattributes.getValue("idref");
     if (id != null) {
       final String fileName = myIdToHref.get(id);
       if (fileName != null) {
         myHtmlFileNames.add(fileName);
       }
     }
   } else if (myState == READ_GUIDE && REFERENCE == tag) {
     final String type = xmlattributes.getValue("type");
     final String title = xmlattributes.getValue("title");
     String href = xmlattributes.getValue("href");
     if (href != null) {
       href = MiscUtil.decodeHtmlReference(href);
       if (title != null) {
         myGuideTOC.add(new Reference(title, href));
       }
       if (COVER.equals(type)) {
         final ZLFile imageFile = ZLFile.createFileByPath(myFilePrefix + href);
         myCoverFileName = imageFile.getPath();
         final String imageName = imageFile.getLongName();
         final ZLFileImage image = XHTMLImageFinder.getCoverImage(imageFile);
         if (image != null) {
           myModelReader.setMainTextModel();
           myModelReader.addImageReference(imageName, (short) 0, true);
           myModelReader.addImage(imageName, image);
           myModelReader.insertEndOfSectionParagraph();
         }
       } else if (COVER_IMAGE.equals(type)) {
         final ZLFile imageFile = ZLFile.createFileByPath(myFilePrefix + href);
         myCoverFileName = imageFile.getPath();
         final String imageName = imageFile.getLongName();
         myModelReader.setMainTextModel();
         myModelReader.addImageReference(imageName, (short) 0, true);
         myModelReader.addImage(imageName, new ZLFileImage(MimeType.IMAGE_AUTO, imageFile));
         myModelReader.insertEndOfSectionParagraph();
       }
     }
   } else if (myState == READ_TOUR && SITE == tag) {
     final String title = xmlattributes.getValue("title");
     String href = xmlattributes.getValue("href");
     if ((title != null) && (href != null)) {
       href = MiscUtil.decodeHtmlReference(href);
       myTourTOC.add(new Reference(title, href));
     }
   }
   return false;
 }