[Libreoffice-commits] .: Branch 'libreoffice-3-5' - 2 commits - sot/source writerfilter/source
Caolán McNamara
caolan at kemper.freedesktop.org
Fri May 11 08:34:53 PDT 2012
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.power at 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 <caolanm at 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 <caolanm at 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:
More information about the Libreoffice-commits
mailing list