Beispiel #1
0
    void AddToList()
    {
        bool hasFootnotes = footnotes.length() > 0;
        if ( !pageend )
            pageend = pagestart;
        if ( !pagestart && !hasFootnotes )
            return;
        int start = (pagestart && pageend) ? pagestart->getStart() : lastpageend;
        int h = (pagestart && pageend) ? pageend->getEnd()-pagestart->getStart() : 0;
#ifdef DEBUG_FOOTNOTES
        if ( CRLog::isTraceEnabled() ) {
            if ( pagestart && pageend ) {
                //CRLog::trace("AddToList(%d, %d) footnotes: %d  pageHeight=%d", pagestart->start, pageend->start+pageend->height, footnotes.length(), h);
            }
            else {
                //CRLog::trace("AddToList(Only footnote: %d) footnotes: %d  pageHeight=%d", lastpageend, footnotes.length(), h);
            }
        }
#endif
        LVRendPageInfo * page = new LVRendPageInfo(start, h, page_list->length());
        lastpageend = start + h;//上一页末尾高度
        if ( footnotes.length()>0 ) {
            page->footnotes.add( footnotes );
            footnotes.clear();
            footheight = 0;
        }
        page_list->add(page);
    }
 void moveBy( int delta )
 {
     current_ += delta;
     if ( current_ < 0 )
         current_ = candidates_.length()-1;
     if ( current_ >= candidates_.length() )
         current_ = 0;
     if ( current_ < 0 )
         current_ = 0;
     if ( candidates_.length() )
         words_.highlight(candidates_[current_]);
 }
 void init()
 {
     _words.clear();
     //ldomDocument * doc = docview.getDocument();
     int pageIndex = -1; //docview.getCurPage();
     LVRef<ldomXRange> range = docview_.getPageDocumentRange( pageIndex );
     crtrace trace;
     if( !range.isNull() ) {
         LVArray<ldomWord> words;
         range->getRangeWords(words);
         for ( int i=0; i<words.length(); i++ ) {
             lString16 w = words[i].getText();
             lString8 encoded = encoding_.encode_string( w );
             if ( w.length() < DICT_MIN_WORD_LENGTH )
                 continue;
             /*
             trace << "string " << w <<
                 " encoded as " << encoded << "\n";
             */
             int index = -1;
             for ( int j=0; j<_words.length(); j++ )
                 if ( _words[j]->equals(w) ) {
                     index = j;
                     break;
                 }
             if ( index>=0 )
                 _words[index]->add( words[i] );  // add range to existing word
             else
                 _words.add( new WordWithRanges( w, encoded, words[i] ) ); // add new word
         }
     }
 }
Beispiel #4
0
    virtual ~LVRtfPictDestination()
    {
        if (!_fmt || _buf.empty())
            return;
        // add Image BLOB
        lString16 name(BLOB_NAME_PREFIX); // L"@blob#"
        name << L"image";
        name << lString16::itoa(m_parser.nextImageIndex());
        name << (_fmt==rtf_img_jpeg ? L".jpg" : L".png");
        m_callback->OnBlob(name, _buf.get(), _buf.length());
#if 0
        {
            LVStreamRef stream = LVOpenFileStream((lString16(L"/tmp/") + name).c_str(), LVOM_WRITE);
            stream->Write(_buf.get(), _buf.length(), NULL);
        }
#endif
        m_callback->OnTagOpen(LXML_NS_NONE, L"img");
        m_callback->OnAttribute(LXML_NS_NONE, L"src", name.c_str());
        m_callback->OnTagClose(LXML_NS_NONE, L"img");
    }
Beispiel #5
0
 bool setManglingKey(lString16 key) {
     if (key.startsWith(lString16(L"urn:uuid:")))
         key = key.substr(9);
     _fontManglingKey.clear();
     _fontManglingKey.reserve(16);
     lUInt8 b = 0;
     int n = 0;
     for (int i=0; i<key.length(); i++) {
         int d = hexDigit(key[i]);
         if (d>=0) {
             b = (b << 4) | d;
             if (++n > 1) {
                 _fontManglingKey.add(b);
                 n = 0;
                 b = 0;
             }
         }
     }
     return _fontManglingKey.length() == 16;
 }
Beispiel #6
0
bool ImportEpubDocument( LVStreamRef stream, ldomDocument * m_doc, LVDocViewCallback * progressCallback, CacheLoadingCallback * formatCallback )
{
    LVContainerRef arc = LVOpenArchieve( stream );
    if ( arc.isNull() )
        return false; // not a ZIP archive

    // check root media type
    lString16 rootfilePath = EpubGetRootFilePath(arc);
    if ( rootfilePath.empty() )
    	return false;

    EncryptedDataContainer * decryptor = new EncryptedDataContainer(arc);
    if (decryptor->open()) {
        CRLog::debug("EPUB: encrypted items detected");
    }

    LVContainerRef m_arc = LVContainerRef(decryptor);

    if (decryptor->hasUnsupportedEncryption()) {
        // DRM!!!
        createEncryptedEpubWarningDocument(m_doc);
        return true;
    }

    m_doc->setContainer(m_arc);

    // read content.opf
    EpubItems epubItems;
    //EpubItem * epubToc = NULL; //TODO
    LVArray<EpubItem*> spineItems;
    lString16 codeBase;
    //lString16 css;

    //
    {
        codeBase=LVExtractPath(rootfilePath, false);
        CRLog::trace("codeBase=%s", LCSTR(codeBase));
    }

    LVStreamRef content_stream = m_arc->OpenStream(rootfilePath.c_str(), LVOM_READ);
    if ( content_stream.isNull() )
        return false;


    lString16 ncxHref;
    lString16 coverId;

    LVEmbeddedFontList fontList;
    EmbeddedFontStyleParser styleParser(fontList);

    // reading content stream
    {
        ldomDocument * doc = LVParseXMLStream( content_stream );
        if ( !doc )
            return false;

        CRPropRef m_doc_props = m_doc->getProps();
        lString16 author = doc->textFromXPath( lString16(L"package/metadata/creator"));
        lString16 title = doc->textFromXPath( lString16(L"package/metadata/title"));
        m_doc_props->setString(DOC_PROP_TITLE, title);
        m_doc_props->setString(DOC_PROP_AUTHORS, author );

        for ( int i=1; i<50; i++ ) {
            ldomNode * item = doc->nodeFromXPath( lString16(L"package/metadata/identifier[") + lString16::itoa(i) + L"]" );
            if (!item)
                break;
            lString16 key = item->getText();
            if (decryptor->setManglingKey(key)) {
                CRLog::debug("Using font mangling key %s", LCSTR(key));
                break;
            }
        }

        CRLog::info("Author: %s Title: %s", LCSTR(author), LCSTR(title));
        for ( int i=1; i<20; i++ ) {
            ldomNode * item = doc->nodeFromXPath( lString16(L"package/metadata/meta[") + lString16::itoa(i) + L"]" );
            if ( !item )
                break;
            lString16 name = item->getAttributeValue(L"name");
            lString16 content = item->getAttributeValue(L"content");
            if ( name == L"cover" )
                coverId = content;
            else if ( name==L"calibre:series" )
                m_doc_props->setString(DOC_PROP_SERIES_NAME, content );
            else if ( name==L"calibre:series_index" )
                m_doc_props->setInt(DOC_PROP_SERIES_NUMBER, content.atoi() );
        }

        // items
        for ( int i=1; i<50000; i++ ) {
            ldomNode * item = doc->nodeFromXPath( lString16(L"package/manifest/item[") + lString16::itoa(i) + L"]" );
            if ( !item )
                break;
            lString16 href = item->getAttributeValue(L"href");
            lString16 mediaType = item->getAttributeValue(L"media-type");
            lString16 id = item->getAttributeValue(L"id");
            if ( !href.empty() && !id.empty() ) {
                if ( id==coverId ) {
                    // coverpage file
                    lString16 coverFileName = codeBase + href;
                    CRLog::info("EPUB coverpage file: %s", LCSTR(coverFileName));
                    LVStreamRef stream = m_arc->OpenStream(coverFileName.c_str(), LVOM_READ);
                    if ( !stream.isNull() ) {
                        LVImageSourceRef img = LVCreateStreamImageSource(stream);
                        if ( !img.isNull() ) {
                            CRLog::info("EPUB coverpage image is correct: %d x %d", img->GetWidth(), img->GetHeight() );
                            m_doc_props->setString(DOC_PROP_COVER_FILE, coverFileName);
                        }
                    }
                }
                EpubItem * epubItem = new EpubItem;
                epubItem->href = href;
                epubItem->id = id;
                epubItem->mediaType = mediaType;
                epubItems.add( epubItem );

//                // register embedded document fonts
//                if (mediaType == L"application/vnd.ms-opentype"
//                        || mediaType == L"application/x-font-otf"
//                        || mediaType == L"application/x-font-ttf") { // TODO: more media types?
//                    // TODO:
//                    fontList.add(codeBase + href);
//                }
            }
            if ( mediaType==L"text/css" ) {
                lString16 name = LVCombinePaths(codeBase, href);
                LVStreamRef cssStream = m_arc->OpenStream(name.c_str(), LVOM_READ);
                if (!cssStream.isNull()) {
                    lString8 cssFile = UnicodeToUtf8(LVReadTextFile(cssStream));
                    lString16 base = name;
                    LVExtractLastPathElement(base);
                    CRLog::trace("style: %s", cssFile.c_str());
                    styleParser.parse(base, cssFile);
                }
            }
        }

        // spine == itemrefs
        if ( epubItems.length()>0 ) {
            ldomNode * spine = doc->nodeFromXPath( lString16(L"package/spine") );
            if ( spine ) {

                EpubItem * ncx = epubItems.findById( spine->getAttributeValue(L"toc") ); //TODO
                //EpubItem * ncx = epubItems.findById(lString16("ncx"));
                if ( ncx!=NULL )
                    ncxHref = codeBase + ncx->href;

                for ( int i=1; i<50000; i++ ) {
                    ldomNode * item = doc->nodeFromXPath( lString16(L"package/spine/itemref[") + lString16::itoa(i) + L"]" );
                    if ( !item )
                        break;
                    EpubItem * epubItem = epubItems.findById( item->getAttributeValue(L"idref") );
                    if ( epubItem ) {
                        // TODO: add to document
                        spineItems.add( epubItem );
                    }
                }
            }
        }
        delete doc;
    }

    if ( spineItems.length()==0 )
        return false;


#if BUILD_LITE!=1
    if ( m_doc->openFromCache(formatCallback) ) {
        if ( progressCallback ) {
            progressCallback->OnLoadFileEnd( );
        }
        return true;
    }
#endif

    lUInt32 saveFlags = m_doc->getDocFlags();
    m_doc->setDocFlags( saveFlags );
    m_doc->setContainer( m_arc );

    ldomDocumentWriter writer(m_doc);
#if 0
    m_doc->setNodeTypes( fb2_elem_table );
    m_doc->setAttributeTypes( fb2_attr_table );
    m_doc->setNameSpaceTypes( fb2_ns_table );
#endif
    //m_doc->setCodeBase( codeBase );

    ldomDocumentFragmentWriter appender(&writer, lString16(L"body"), lString16(L"DocFragment"), lString16::empty_str );
    writer.OnStart(NULL);
    writer.OnTagOpenNoAttr(L"", L"body");
    int fragmentCount = 0;
    for ( int i=0; i<spineItems.length(); i++ ) {
        if ( spineItems[i]->mediaType==L"application/xhtml+xml" ) {
            lString16 name = codeBase + spineItems[i]->href;
            appender.addPathSubstitution( name, lString16(L"_doc_fragment_") + lString16::itoa(i) );
        }
    }
    for ( int i=0; i<spineItems.length(); i++ ) {
        if ( spineItems[i]->mediaType==L"application/xhtml+xml" ) {
            lString16 name = codeBase + spineItems[i]->href;
            {
                CRLog::debug("Checking fragment: %s", LCSTR(name));
                LVStreamRef stream = m_arc->OpenStream(name.c_str(), LVOM_READ);
                if ( !stream.isNull() ) {
                    appender.setCodeBase( name );
                    lString16 base = name;
                    LVExtractLastPathElement(base);
                    //CRLog::trace("base: %s", LCSTR(base));
                    //LVXMLParser
                    LVHTMLParser parser(stream, &appender);
                    if ( parser.CheckFormat() && parser.Parse() ) {
                        // valid
                        fragmentCount++;
                        lString8 headCss = appender.getHeadStyleText();
                        //CRLog::trace("style: %s", headCss.c_str());
                        styleParser.parse(base, headCss);
                    } else {
                        CRLog::error("Document type is not XML/XHTML for fragment %s", LCSTR(name));
                    }
                }
            }
        }
    }

    ldomDocument * ncxdoc = NULL;
    if ( !ncxHref.empty() ) {
        LVStreamRef stream = m_arc->OpenStream(ncxHref.c_str(), LVOM_READ);
        lString16 codeBase = LVExtractPath( ncxHref );
        if ( codeBase.length()>0 && codeBase.lastChar()!='/' )
            codeBase.append(1, L'/');
        appender.setCodeBase(codeBase);
        if ( !stream.isNull() ) {
            ldomDocument * ncxdoc = LVParseXMLStream( stream );
            if ( ncxdoc!=NULL ) {
                ldomNode * navMap = ncxdoc->nodeFromXPath( lString16(L"ncx/navMap"));
                if ( navMap!=NULL )
                    ReadEpubToc( m_doc, navMap, m_doc->getToc(), appender );
                delete ncxdoc;
            }
        }
    }

    writer.OnTagClose(L"", L"body");
    writer.OnStop();
    CRLog::debug("EPUB: %d documents merged", fragmentCount);

    if (!fontList.empty()) {
        // set document font list, and register fonts
        m_doc->getEmbeddedFontList().set(fontList);
        m_doc->registerEmbeddedFonts();
        m_doc->forceReinitStyles();
    }

    if ( fragmentCount==0 )
        return false;

#if 0
    // set stylesheet
    //m_doc->getStyleSheet()->clear();
    m_doc->setStyleSheet( NULL, true );
    //m_doc->getStyleSheet()->parse(m_stylesheet.c_str());
    if ( !css.empty() && m_doc->getDocFlag(DOC_FLAG_ENABLE_INTERNAL_STYLES) ) {

        m_doc->setStyleSheet( "p.p { text-align: justify }\n"
            "svg { text-align: center }\n"
            "i { display: inline; font-style: italic }\n"
            "b { display: inline; font-weight: bold }\n"
            "abbr { display: inline }\n"
            "acronym { display: inline }\n"
            "address { display: inline }\n"
            "p.title-p { hyphenate: none }\n"
//abbr, acronym, address, blockquote, br, cite, code, dfn, div, em, h1, h2, h3, h4, h5, h6, kbd, p, pre, q, samp, span, strong, var
        , false);
        m_doc->setStyleSheet( UnicodeToUtf8(css).c_str(), false );
        //m_doc->getStyleSheet()->parse(UnicodeToUtf8(css).c_str());
    } else {
        //m_doc->getStyleSheet()->parse(m_stylesheet.c_str());
        //m_doc->setStyleSheet( m_stylesheet.c_str(), false );
    }
#endif
#if 0
    LVStreamRef out = LVOpenFileStream( L"c:\\doc.xml" , LVOM_WRITE );
    if ( !out.isNull() )
        m_doc->saveToStream( out, "utf-8" );
#endif

    // DONE!
    if ( progressCallback ) {
        progressCallback->OnLoadFileEnd( );
        m_doc->compact();
        m_doc->dumpStatistics();
    }
    return true;

}
 const lString16 get()
 {
     if ( current_ >= 0 && current_ < candidates_.length() )
         return candidates_[current_]->getWord();
     return lString16::empty_str;
 }
Beispiel #8
0
static int findText(lua_State *L) {
	CreDocument *doc		= (CreDocument*) luaL_checkudata(L, 1, "credocument");
	const char *l_pattern   = luaL_checkstring(L, 2);
	lString16 pattern		= lString16(l_pattern);
	int origin				= luaL_checkint(L, 3);
	bool reverse			= luaL_checkint(L, 4);
	bool caseInsensitive	= luaL_checkint(L, 5);

    if ( pattern.empty() )
        return 0;

    LVArray<ldomWord> words;
    lvRect rc;
    doc->text_view->GetPos( rc );
    int pageHeight = rc.height();
    int start = -1;
    int end = -1;
    if ( reverse ) {
        // backward
        if ( origin == 0 ) {
            // from end of current page to first page
            end = rc.bottom;
        } else if ( origin == -1 ) {
            // from the last page to end of current page
            start = rc.bottom + 1;
        } else { // origin == 1
            // from prev page to the first page
            end = rc.top - 1;
        }
    } else {
        // forward
        if ( origin == 0 ) {
            // from current page to the last page
            start = rc.top;
        } else if ( origin == -1 ) {
            // from the first page to current page
            end = rc.top + 1;
        } else { // origin == 1
            // from next page to the last page
            start = rc.bottom + 1;
        }
    }
    CRLog::debug("CRViewDialog::findText: Current page: %d .. %d", rc.top, rc.bottom);
    CRLog::debug("CRViewDialog::findText: searching for text '%s' from %d to %d origin %d", LCSTR(pattern), start, end, origin );
    if ( doc->text_view->getDocument()->findText( pattern, caseInsensitive, reverse, start, end, words, 200, pageHeight ) ) {
        CRLog::debug("CRViewDialog::findText: pattern found");
        doc->text_view->clearSelection();
        doc->text_view->selectWords( words );
        ldomMarkedRangeList * ranges = doc->text_view->getMarkedRanges();
        if ( ranges && ranges->length() > 0 ) {
            lua_newtable(L); // hold all words
            for (int i = 0; i < words.length(); i++) {
                ldomWord word = words[i];
                lua_newtable(L); // new word
                lua_pushstring(L, "start");
                lua_pushstring(L, UnicodeToLocal(word.getStartXPointer().toString()).c_str());
                lua_settable(L, -3);
                lua_pushstring(L, "end");
                lua_pushstring(L, UnicodeToLocal(word.getEndXPointer().toString()).c_str());
                lua_settable(L, -3);
                lua_rawseti(L, -2, i + 1);
            }
            return 1;
        }
    }
    CRLog::debug("CRViewDialog::findText: pattern not found");
    return 0;
}
Beispiel #9
0
static int getWordBoxesFromPositions(lua_State *L) {
	CreDocument *doc = (CreDocument*) luaL_checkudata(L, 1, "credocument");
	const char* pos0 = luaL_checkstring(L, 2);
	const char* pos1 = luaL_checkstring(L, 3);

	LVDocView *tv = doc->text_view;
	ldomDocument *dv = doc->dom_doc;

	ldomXPointer startp = dv->createXPointer(lString16(pos0));
	ldomXPointer endp = dv->createXPointer(lString16(pos1));
	lua_newtable(L); // new word boxes
	if (!startp.isNull() && !endp.isNull()) {
		ldomXRange r(startp, endp);
		if (r.getStart().isNull() || r.getEnd().isNull())
			return 0;
		r.sort();

		if (!r.getStart().isVisibleWordStart())
			r.getStart().prevVisibleWordStart();
		if (!r.getEnd().isVisibleWordEnd())
			r.getEnd().nextVisibleWordEnd();
		if (r.isNull())
			return 0;

		r.setFlags(1);
		//tv->selectRange(r);  // we don't need native highlight of selection

		/*  accumulate text lines */
		LVArray<ldomWord> words;
		r.getRangeWords(words);
		lvRect charRect, wordRect, lineRect;
		int lcount = 1;
		int lastx = -1;
		lua_newtable(L); // first line box
		for (int i=0; i<words.length(); i++) {
			if (ldomXRange(words[i]).getRectEx(wordRect)) {
				if (!docToWindowRect(tv, wordRect)) continue;//docToWindowRect returns false means it is not on current showing page.
				if (wordRect.left < lastx) {
					lua_pushLineRect(L, lineRect.left, lineRect.top,
									    lineRect.right, lineRect.bottom, lcount++);
					lua_newtable(L); // new line box
					lineRect.clear();
				}
				lineRect.extend(wordRect);
				lastx = wordRect.left;
			} else {  // word is hyphenated
				ldomWord word = words[i];
				int y = -1;
				for (int j=word.getStart(); j < word.getEnd(); j++) {
					if (ldomXPointer(word.getNode(), j).getRectEx(charRect)) {
						if (!docToWindowRect(tv, charRect)) continue;
						if (y == -1) y = charRect.top;
						if (j != word.getStart() && y == charRect.top) continue;
						y = charRect.top;
						if (charRect.left < lastx) {
							lua_pushLineRect(L, lineRect.left, lineRect.top,
												lineRect.right, lineRect.bottom, lcount++);
							lua_newtable(L); // new line box
							lineRect.clear();
						}
						lineRect.extend(charRect);
						lastx = charRect.left;
					}
				}
			}
		}
		lua_pushLineRect(L, lineRect.left, lineRect.top,
							lineRect.right, lineRect.bottom, lcount);
	}
	return 1;
}