sot/source/sdstor/stgstrms.cxx | 133 ++++++++++++++-- sot/source/sdstor/stgstrms.hxx | 4 writerfilter/source/dmapper/PropertyMap.cxx | 224 ++++++++++++++-------------- 3 files changed, 233 insertions(+), 128 deletions(-)
New commits: commit ae218f73ff4eaa4191e620abee8235f73ea0e1fc Author: Noel Power <noel.po...@novell.com> Date: Fri May 11 09:50:31 2012 +0100 Revert "another partial fix for bnc#693238" ( and fixes fdo#44292 ) This reverts commit cd1c434c4bd4756fa1355e906cb2e8de4aae0618. Conflicts: writerfilter/source/dmapper/PropertyMap.cxx Change-Id: I I83ae3418438aa02db744e6b6eb5a9c199938c91f (cherry picked from commit 2dee7d6205832a1212790ac1ab168a6b6fce686d) Signed-off-by: Caolán McNamara <caol...@redhat.com> diff --git a/writerfilter/source/dmapper/PropertyMap.cxx b/writerfilter/source/dmapper/PropertyMap.cxx index 4f03839..503052f 100644 --- a/writerfilter/source/dmapper/PropertyMap.cxx +++ b/writerfilter/source/dmapper/PropertyMap.cxx @@ -843,130 +843,130 @@ void SectionPropertyMap::CloseSectionGroup( DomainMapper_Impl& rDM_Impl ) if( m_nColumnCount > 0 && xSection.is()) ApplyColumnProperties( xSection ); } - //get the properties and create appropriate page styles - uno::Reference< beans::XPropertySet > xFollowPageStyle = GetPageStyle( rDM_Impl.GetPageStyles(), rDM_Impl.GetTextFactory(), false ); - - if( m_nDzaGutter > 0 ) + else { - //todo: iGutterPos from DocProperties are missing - if( m_bGutterRTL ) - m_nRightMargin += m_nDzaGutter; - else - m_nLeftMargin += m_nDzaGutter; - } - operator[]( PropertyDefinition( PROP_LEFT_MARGIN, false )) = uno::makeAny( m_nLeftMargin ); - operator[]( PropertyDefinition( PROP_RIGHT_MARGIN, false )) = uno::makeAny( m_nRightMargin ); - - /*** if headers/footers are available then the top/bottom margins of the - header/footer are copied to the top/bottom margin of the page - */ - CopyLastHeaderFooter( false, rDM_Impl ); - PrepareHeaderFooterProperties( false ); - - const ::rtl::OUString sTrayIndex = rPropNameSupplier.GetName( PROP_PRINTER_PAPER_TRAY_INDEX ); - if( m_nPaperBin >= 0 ) - xFollowPageStyle->setPropertyValue( sTrayIndex, uno::makeAny( m_nPaperBin ) ); - uno::Reference< text::XTextColumns > xColumns; - if( m_nColumnCount > 0 ) - xColumns = ApplyColumnProperties( xFollowPageStyle ); - - //prepare text grid properties - sal_Int32 nHeight = 1; - PropertyMap::iterator aElement = find(PropertyDefinition( PROP_HEIGHT, false )); - if( aElement != end()) - aElement->second >>= nHeight; - - sal_Int32 nWidth = 1; - aElement = find(PropertyDefinition( PROP_WIDTH, false )); - if( aElement != end()) - aElement->second >>= nWidth; - - text::WritingMode eWritingMode = text::WritingMode_LR_TB; - aElement = find(PropertyDefinition( PROP_WRITING_MODE, false )); - if( aElement != end()) - aElement->second >>= eWritingMode; - - - - sal_Int32 nTextAreaHeight = eWritingMode == text::WritingMode_LR_TB ? - nHeight - m_nTopMargin - m_nBottomMargin : - nWidth - m_nLeftMargin - m_nRightMargin; - - operator[]( PropertyDefinition( PROP_GRID_LINES, false )) = - uno::makeAny( static_cast<sal_Int16>(nTextAreaHeight/m_nGridLinePitch)); + //get the properties and create appropriate page styles + uno::Reference< beans::XPropertySet > xFollowPageStyle = GetPageStyle( rDM_Impl.GetPageStyles(), rDM_Impl.GetTextFactory(), false ); - sal_Int32 nCharWidth = 423; //240 twip/ 12 pt - //todo: is '0' the right index here? - const StyleSheetEntryPtr pEntry = rDM_Impl.GetStyleSheetTable()->FindStyleSheetByISTD(::rtl::OUString::valueOf(static_cast<sal_Int32>(0), 16)); - if( pEntry.get( ) ) - { - PropertyMap::iterator aElement_ = pEntry->pProperties->find(PropertyDefinition( PROP_CHAR_HEIGHT_ASIAN, false )); - if( aElement_ != pEntry->pProperties->end()) + if( m_nDzaGutter > 0 ) { - double fHeight = 0; - if( aElement_->second >>= fHeight ) - nCharWidth = ConversionHelper::convertTwipToMM100( (long)( fHeight * 20.0 + 0.5 )); + //todo: iGutterPos from DocProperties are missing + if( m_bGutterRTL ) + m_nRightMargin += m_nDzaGutter; + else + m_nLeftMargin += m_nDzaGutter; + } + operator[]( PropertyDefinition( PROP_LEFT_MARGIN, false )) = uno::makeAny( m_nLeftMargin ); + operator[]( PropertyDefinition( PROP_RIGHT_MARGIN, false )) = uno::makeAny( m_nRightMargin ); + + /*** if headers/footers are available then the top/bottom margins of the + header/footer are copied to the top/bottom margin of the page + */ + CopyLastHeaderFooter( false, rDM_Impl ); + PrepareHeaderFooterProperties( false ); + + const ::rtl::OUString sTrayIndex = rPropNameSupplier.GetName( PROP_PRINTER_PAPER_TRAY_INDEX ); + if( m_nPaperBin >= 0 ) + xFollowPageStyle->setPropertyValue( sTrayIndex, uno::makeAny( m_nPaperBin ) ); + uno::Reference< text::XTextColumns > xColumns; + if( m_nColumnCount > 0 ) + xColumns = ApplyColumnProperties( xFollowPageStyle ); + + //prepare text grid properties + sal_Int32 nHeight = 1; + PropertyMap::iterator aElement = find(PropertyDefinition( PROP_HEIGHT, false )); + if( aElement != end()) + aElement->second >>= nHeight; + + sal_Int32 nWidth = 1; + aElement = find(PropertyDefinition( PROP_WIDTH, false )); + if( aElement != end()) + aElement->second >>= nWidth; + + text::WritingMode eWritingMode = text::WritingMode_LR_TB; + aElement = find(PropertyDefinition( PROP_WRITING_MODE, false )); + if( aElement != end()) + aElement->second >>= eWritingMode; + + + + sal_Int32 nTextAreaHeight = eWritingMode == text::WritingMode_LR_TB ? + nHeight - m_nTopMargin - m_nBottomMargin : + nWidth - m_nLeftMargin - m_nRightMargin; + + operator[]( PropertyDefinition( PROP_GRID_LINES, false )) = + uno::makeAny( static_cast<sal_Int16>(nTextAreaHeight/m_nGridLinePitch)); + + sal_Int32 nCharWidth = 423; //240 twip/ 12 pt + //todo: is '0' the right index here? + const StyleSheetEntryPtr pEntry = rDM_Impl.GetStyleSheetTable()->FindStyleSheetByISTD(::rtl::OUString::valueOf(static_cast<sal_Int32>(0), 16)); + if( pEntry.get( ) ) + { + PropertyMap::iterator aElement_ = pEntry->pProperties->find(PropertyDefinition( PROP_CHAR_HEIGHT_ASIAN, false )); + if( aElement_ != pEntry->pProperties->end()) + { + double fHeight = 0; + if( aElement_->second >>= fHeight ) + nCharWidth = ConversionHelper::convertTwipToMM100( (long)( fHeight * 20.0 + 0.5 )); + } } - } - //dxtCharSpace - if(m_nDxtCharSpace) - { - sal_Int32 nCharSpace = m_nDxtCharSpace; - //main lives in top 20 bits, and is signed. - sal_Int32 nMain = (nCharSpace & 0xFFFFF000); - nMain /= 0x1000; - nCharWidth += ConversionHelper::convertTwipToMM100( nMain * 20 ); - - sal_Int32 nFraction = (nCharSpace & 0x00000FFF); - nFraction = (nFraction * 20)/0xFFF; - nCharWidth += ConversionHelper::convertTwipToMM100( nFraction ); - } - operator[]( PropertyDefinition( PROP_GRID_BASE_HEIGHT, false )) = uno::makeAny( nCharWidth ); - sal_Int32 nRubyHeight = m_nGridLinePitch - nCharWidth; - if(nRubyHeight < 0 ) - nRubyHeight = 0; - operator[]( PropertyDefinition( PROP_GRID_RUBY_HEIGHT, false )) = uno::makeAny( nRubyHeight ); + //dxtCharSpace + if(m_nDxtCharSpace) + { + sal_Int32 nCharSpace = m_nDxtCharSpace; + //main lives in top 20 bits, and is signed. + sal_Int32 nMain = (nCharSpace & 0xFFFFF000); + nMain /= 0x1000; + nCharWidth += ConversionHelper::convertTwipToMM100( nMain * 20 ); + + sal_Int32 nFraction = (nCharSpace & 0x00000FFF); + nFraction = (nFraction * 20)/0xFFF; + nCharWidth += ConversionHelper::convertTwipToMM100( nFraction ); + } + operator[]( PropertyDefinition( PROP_GRID_BASE_HEIGHT, false )) = uno::makeAny( nCharWidth ); + sal_Int32 nRubyHeight = m_nGridLinePitch - nCharWidth; + if(nRubyHeight < 0 ) + nRubyHeight = 0; + operator[]( PropertyDefinition( PROP_GRID_RUBY_HEIGHT, false )) = uno::makeAny( nRubyHeight ); - sal_Int16 nGridMode = text::TextGridMode::NONE; + sal_Int16 nGridMode = text::TextGridMode::NONE; - switch (m_nGridType) - { - case NS_ooxml::LN_Value_wordprocessingml_ST_DocGrid_lines: - nGridMode = text::TextGridMode::LINES; - break; - case NS_ooxml::LN_Value_wordprocessingml_ST_DocGrid_linesAndChars: - nGridMode = text::TextGridMode::LINES_AND_CHARS; - break; - default: - break; - } + switch (m_nGridType) + { + case NS_ooxml::LN_Value_wordprocessingml_ST_DocGrid_lines: + nGridMode = text::TextGridMode::LINES; + break; + case NS_ooxml::LN_Value_wordprocessingml_ST_DocGrid_linesAndChars: + nGridMode = text::TextGridMode::LINES_AND_CHARS; + break; + default: + break; + } - operator[](PropertyDefinition(PROP_GRID_MODE, false)) = uno::makeAny(nGridMode); + operator[](PropertyDefinition(PROP_GRID_MODE, false)) = uno::makeAny(nGridMode); - _ApplyProperties( xFollowPageStyle ); + _ApplyProperties( xFollowPageStyle ); - //todo: creating a "First Page" style depends on HasTitlePage und _fFacingPage_ - if( m_bTitlePage ) - { - CopyLastHeaderFooter( true, rDM_Impl ); - PrepareHeaderFooterProperties( true ); - uno::Reference< beans::XPropertySet > xFirstPageStyle = GetPageStyle( - rDM_Impl.GetPageStyles(), rDM_Impl.GetTextFactory(), true ); - _ApplyProperties( xFirstPageStyle ); - - sal_Int32 nPaperBin = m_nFirstPaperBin >= 0 ? m_nFirstPaperBin : m_nPaperBin >= 0 ? m_nPaperBin : 0; - if( nPaperBin ) - xFollowPageStyle->setPropertyValue( sTrayIndex, uno::makeAny( nPaperBin ) ); - if( xColumns.is() ) - xFollowPageStyle->setPropertyValue( - rPropNameSupplier.GetName( PROP_TEXT_COLUMNS ), uno::makeAny( xColumns )); - } + //todo: creating a "First Page" style depends on HasTitlePage und _fFacingPage_ + if( m_bTitlePage ) + { + CopyLastHeaderFooter( true, rDM_Impl ); + PrepareHeaderFooterProperties( true ); + uno::Reference< beans::XPropertySet > xFirstPageStyle = GetPageStyle( + rDM_Impl.GetPageStyles(), rDM_Impl.GetTextFactory(), true ); + _ApplyProperties( xFirstPageStyle ); + + sal_Int32 nPaperBin = m_nFirstPaperBin >= 0 ? m_nFirstPaperBin : m_nPaperBin >= 0 ? m_nPaperBin : 0; + if( nPaperBin ) + xFollowPageStyle->setPropertyValue( sTrayIndex, uno::makeAny( nPaperBin ) ); + if( xColumns.is() ) + xFollowPageStyle->setPropertyValue( + rPropNameSupplier.GetName( PROP_TEXT_COLUMNS ), uno::makeAny( xColumns )); + } - ApplyBorderToPageStyles( rDM_Impl.GetPageStyles( ), rDM_Impl.GetTextFactory( ), m_nBorderParams ); + ApplyBorderToPageStyles( rDM_Impl.GetPageStyles( ), rDM_Impl.GetTextFactory( ), m_nBorderParams ); - if ( m_nBreakType != 0 ) - { try { { commit e7c861e3ec9398436eda16bb748af22a2d9afc27 Author: Caolán McNamara <caol...@redhat.com> Date: Thu May 10 15:43:47 2012 +0100 Related: fdo#47644 for huge files build a page chain cache for seeks For huge ole2 structured storage files build a page chain cache on demand to speed up long distance seeks i.e. reduces .doc parse time for fdo#47644 from 1 minute 7 seconds to 18 seconds for me diff --git a/sot/source/sdstor/stgstrms.cxx b/sot/source/sdstor/stgstrms.cxx index 5e6c1ea..e982837 100644 --- a/sot/source/sdstor/stgstrms.cxx +++ b/sot/source/sdstor/stgstrms.cxx @@ -26,9 +26,10 @@ * ************************************************************************/ +#include <algorithm> #include <string.h> // memcpy() - +#include <sal/log.hxx> #include <osl/file.hxx> #include <tools/tempfile.hxx> #include <tools/debug.hxx> @@ -334,6 +335,56 @@ void StgStrm::SetEntry( StgDirEntry& r ) r.SetDirty(); } +namespace lcl +{ +#if defined(__GXX_EXPERIMENTAL_CXX0X__) || __cplusplus >= 201103L + using std::is_sorted; +#else + template <typename iter> bool is_sorted(iter aStart, iter aEnd) + { + if (aStart == aEnd) + return true; + + for (iter aNext = aStart + 1; aNext != aEnd; aStart = aNext, ++aNext) + { + if (*aNext < *aStart) + return false; + } + + return true; + } +#endif +} + +bool StgStrm::buildPageChainCache() +{ + if (nSize > 0) + m_aPagesCache.reserve(nSize/nPageSize); + + sal_Int32 nBgn = nStart; + while (nBgn >= 0) + { + m_aPagesCache.push_back(nBgn); + sal_Int32 nOldBgn = nBgn; + nBgn = pFat->GetNextPage(nBgn); + if (nBgn == nOldBgn) + return false; + } + + m_bSortedPageChain = lcl::is_sorted(m_aPagesCache.begin(), m_aPagesCache.end()); + + SAL_WARN_IF(!m_bSortedPageChain, "sot", "unsorted page chain, that's suspicious"); + + return true; +} + +//See fdo#47644 for a .doc with a vast amount of pages where seeking around the +//document takes a colossal amount of time +// +//There's a cost to building a page cache, so only build one if the number of +//pages to seek through hits some sufficiently high value where it's worth it. +#define ARBITRARY_LARGE_AMOUNT_OF_PAGES 256 + // Compute page number and offset for the given byte position. // If the position is behind the size, set the stream right // behind the EOF. @@ -355,7 +406,7 @@ sal_Bool StgStrm::Pos2Page( sal_Int32 nBytePos ) return sal_True; if( nNew > nOld ) { - // the new position is behind the current, so an incremental + // the new position is after the current, so an incremental // positioning is OK. Set the page relative position nRel = nNew - nOld; nBgn = nPage; @@ -369,13 +420,59 @@ sal_Bool StgStrm::Pos2Page( sal_Int32 nBytePos ) } // now, traverse the FAT chain. nRel /= nPageSize; + sal_Int32 nLast = STG_EOF; - while( nRel && nBgn >= 0 ) + if (m_aPagesCache.empty() && nRel < ARBITRARY_LARGE_AMOUNT_OF_PAGES) + { + while (nRel && nBgn >= 0) + { + nLast = nBgn; + nBgn = pFat->GetNextPage( nBgn ); + nRel--; + } + } + else if (nBgn >= 0) { - nLast = nBgn; - nBgn = pFat->GetNextPage( nBgn ); - nRel--; + //Seeking large distances is slow, so if we're starting seeking (some + //fairly arbitrary) large distances, build a cache and re-use it for + //subsequent seeks + if (m_aPagesCache.empty()) + { + SAL_INFO("sot", "kicking off large seek helper\n"); + buildPageChainCache(); + } + + std::vector<sal_Int32>::iterator aI; + + if (m_bSortedPageChain) + aI = std::lower_bound(m_aPagesCache.begin(), m_aPagesCache.end(), nBgn); + else + aI = std::find(m_aPagesCache.begin(), m_aPagesCache.end(), nBgn); + + if (aI == m_aPagesCache.end()) + { + SAL_WARN("sot", "Unknown page position"); + nBgn = STG_EOF; + } + else + { + size_t nBgnDistance = std::distance(m_aPagesCache.begin(), aI); + + size_t nIndex = nBgnDistance + nRel; + + if (nIndex > m_aPagesCache.size()) + { + nRel = m_aPagesCache.size() - nBgnDistance; + nIndex = m_aPagesCache.size() - 1; + } + else + nRel = 0; + + nLast = nIndex ? m_aPagesCache[nIndex - 1] : STG_EOF; + nBgn = m_aPagesCache[nIndex]; + } } + // special case: seek to 1st byte of new, unallocated page // (in case the file size is a multiple of the page size) if( nBytePos == nSize && nBgn == STG_EOF && !nRel && !nOffset ) @@ -404,6 +501,8 @@ StgPage* StgStrm::GetPhysPage( sal_Int32 nBytePos, sal_Bool bForce ) sal_Bool StgStrm::Copy( sal_Int32 nFrom, sal_Int32 nBytes ) { + m_aPagesCache.clear(); + sal_Int32 nTo = nStart; sal_Int32 nPgs = ( nBytes + nPageSize - 1 ) / nPageSize; while( nPgs-- ) @@ -430,6 +529,8 @@ sal_Bool StgStrm::Copy( sal_Int32 nFrom, sal_Int32 nBytes ) sal_Bool StgStrm::SetSize( sal_Int32 nBytes ) { + m_aPagesCache.clear(); + // round up to page size sal_Int32 nOld = ( ( nSize + nPageSize - 1 ) / nPageSize ) * nPageSize; sal_Int32 nNew = ( ( nBytes + nPageSize - 1 ) / nPageSize ) * nPageSize; @@ -528,6 +629,8 @@ sal_Int32 StgFATStrm::GetPage( short nOff, sal_Bool bMake, sal_uInt16 *pnMasterA { if( bMake ) { + m_aPagesCache.clear(); + // create a new master page nFAT = nMaxPage++; pMaster = rIo.Copy( nFAT, STG_FREE ); @@ -582,6 +685,8 @@ sal_Int32 StgFATStrm::GetPage( short nOff, sal_Bool bMake, sal_uInt16 *pnMasterA sal_Bool StgFATStrm::SetPage( short nOff, sal_Int32 nNewPage ) { + m_aPagesCache.clear(); + sal_Bool bRes = sal_True; if( nOff < rIo.aHdr.GetFAT1Size() ) rIo.aHdr.SetFATPage( nOff, nNewPage ); @@ -631,6 +736,8 @@ sal_Bool StgFATStrm::SetPage( short nOff, sal_Int32 nNewPage ) sal_Bool StgFATStrm::SetSize( sal_Int32 nBytes ) { + m_aPagesCache.clear(); + // Set the number of entries to a multiple of the page size short nOld = (short) ( ( nSize + ( nPageSize - 1 ) ) / nPageSize ); short nNew = (short) ( @@ -747,16 +854,10 @@ void StgDataStrm::Init( sal_Int32 nBgn, sal_Int32 nLen ) { // determine the actual size of the stream by scanning // the FAT chain and counting the # of pages allocated - nSize = 0; - sal_Int32 nOldBgn = -1; - while( nBgn >= 0 && nBgn != nOldBgn ) - { - nOldBgn = nBgn; - nBgn = pFat->GetNextPage( nBgn ); - if( nBgn == nOldBgn ) - rIo.SetError( ERRCODE_IO_WRONGFORMAT ); - nSize += nPageSize; - } + bool bOk = buildPageChainCache(); + if (!bOk) + rIo.SetError( ERRCODE_IO_WRONGFORMAT ); + nSize = m_aPagesCache.size() * nPageSize; } } diff --git a/sot/source/sdstor/stgstrms.hxx b/sot/source/sdstor/stgstrms.hxx index a6a0ad1..cfae9e2 100644 --- a/sot/source/sdstor/stgstrms.hxx +++ b/sot/source/sdstor/stgstrms.hxx @@ -30,6 +30,7 @@ #define _STGSTRMS_HXX #include <tools/stream.hxx> +#include <vector> class StgIo; class StgStrm; @@ -77,6 +78,9 @@ protected: sal_Int32 nPage; // current logical page short nOffset; // offset into current page short nPageSize; // logical page size + std::vector<sal_Int32> m_aPagesCache; + bool m_bSortedPageChain; + bool buildPageChainCache(); sal_Bool Copy( sal_Int32 nFrom, sal_Int32 nBytes ); StgStrm( StgIo& ); public:
_______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits