summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiklos Vajna <vmiklos@collabora.co.uk>2018-04-20 16:32:00 +0200
committerMiklos Vajna <vmiklos@collabora.co.uk>2018-04-20 21:04:35 +0200
commitedda1e5fc8113aa4744e32f97c96a3cc311485ca (patch)
treeb6da5a4a637a9a3ae3ed9307fe59d6f1df80b197
parente9c52f55f0cc7155d6883e4d2abf14f1638b03b3 (diff)
DOCX import: lazy-read images without external headers
So that similar to ODT, images are not loaded on file open, only when the user scrolls there. Notes: 1) GraphicDescriptor::ImpDetectJPG() would try to calculate the logic size before the pixel size is available, so the logic size would be 0x0. Also, ImpGraphic::ImplSetPrepared() would always work with a pixel map mode. Any of these two would result in a failure of testDMLShapeFillBitmapCrop in CppunitTest_sw_ooxmlexport6. 2) Lazy-loading seems to (at the moment) not recognize EMF files, so don't lazy-load in case an external header is provided. This probably has to be revisited, since the ODF import doesn't go via GraphicProvider::queryGraphic(). Change-Id: I44754e659effebca8339715df114dbaadb9b5e9f Reviewed-on: https://gerrit.libreoffice.org/53215 Reviewed-by: Miklos Vajna <vmiklos@collabora.co.uk> Tested-by: Jenkins <ci@libreoffice.org>
-rw-r--r--oox/source/helper/graphichelper.cxx15
-rw-r--r--sw/qa/extras/ooxmlimport/data/image-lazy-read.docxbin0 -> 9392 bytes
-rw-r--r--sw/qa/extras/ooxmlimport/ooxmlimport.cxx8
-rw-r--r--vcl/source/filter/graphicfilter2.cxx9
-rw-r--r--vcl/source/gdi/impgraph.cxx16
-rw-r--r--vcl/source/graphic/UnoGraphicProvider.cxx19
6 files changed, 58 insertions, 9 deletions
diff --git a/oox/source/helper/graphichelper.cxx b/oox/source/helper/graphichelper.cxx
index 7f4262de787c..002d54b946b5 100644
--- a/oox/source/helper/graphichelper.cxx
+++ b/oox/source/helper/graphichelper.cxx
@@ -238,11 +238,13 @@ Reference< XGraphic > GraphicHelper::importGraphic( const Reference< XInputStrea
Reference< XGraphic > xGraphic;
if( rxInStrm.is() && mxGraphicProvider.is() ) try
{
- Sequence< PropertyValue > aArgs( 1 );
+ Sequence< PropertyValue > aArgs( 2 );
aArgs[ 0 ].Name = "InputStream";
aArgs[ 0 ].Value <<= rxInStrm;
+ aArgs[ 1 ].Name = "LazyRead";
+ aArgs[ 1 ].Value <<= true;
- if ( pExtHeader && pExtHeader->mapMode > 0 )
+ if ( pExtHeader )
{
aArgs.realloc( aArgs.getLength() + 1 );
Sequence< PropertyValue > aFilterData( 3 );
@@ -252,8 +254,8 @@ Reference< XGraphic > GraphicHelper::importGraphic( const Reference< XInputStrea
aFilterData[ 1 ].Value <<= pExtHeader->yExt;
aFilterData[ 2 ].Name = "ExternalMapMode";
aFilterData[ 2 ].Value <<= pExtHeader->mapMode;
- aArgs[ 1 ].Name = "FilterData";
- aArgs[ 1 ].Value <<= aFilterData;
+ aArgs[ 2 ].Name = "FilterData";
+ aArgs[ 2 ].Value <<= aFilterData;
}
xGraphic = mxGraphicProvider->queryGraphic( aArgs );
@@ -339,6 +341,11 @@ Reference< XGraphic > GraphicHelper::importEmbeddedGraphic( const OUString& rStr
EmbeddedGraphicMap::const_iterator aIt = maEmbeddedGraphics.find( rStreamName );
if( aIt == maEmbeddedGraphics.end() )
{
+ // TODO make lazy-load work for EMF as well.
+ WmfExternal aHeader;
+ if (rStreamName.endsWith(".emf") && !pExtHeader)
+ pExtHeader = &aHeader;
+
xGraphic = importGraphic(mxStorage->openInputStream(rStreamName), pExtHeader);
if( xGraphic.is() )
maEmbeddedGraphics[ rStreamName ] = xGraphic;
diff --git a/sw/qa/extras/ooxmlimport/data/image-lazy-read.docx b/sw/qa/extras/ooxmlimport/data/image-lazy-read.docx
new file mode 100644
index 000000000000..faf80e41dcd6
--- /dev/null
+++ b/sw/qa/extras/ooxmlimport/data/image-lazy-read.docx
Binary files differ
diff --git a/sw/qa/extras/ooxmlimport/ooxmlimport.cxx b/sw/qa/extras/ooxmlimport/ooxmlimport.cxx
index 439658a63b39..7b60b191df67 100644
--- a/sw/qa/extras/ooxmlimport/ooxmlimport.cxx
+++ b/sw/qa/extras/ooxmlimport/ooxmlimport.cxx
@@ -1422,6 +1422,14 @@ DECLARE_OOXMLIMPORT_TEST(testTdf108714, "tdf108714.docx")
CPPUNIT_ASSERT_EQUAL(style::BreakType_PAGE_BEFORE, breakType);
}
+DECLARE_OOXMLIMPORT_TEST(testImageLazyRead, "image-lazy-read.docx")
+{
+ auto xGraphic = getProperty<uno::Reference<graphic::XGraphic>>(getShape(1), "Graphic");
+ Graphic aGraphic(xGraphic);
+ // This failed, import loaded the graphic, it wasn't lazy-read.
+ CPPUNIT_ASSERT(!aGraphic.isAvailable());
+}
+
DECLARE_OOXMLIMPORT_TEST(testTdf108995, "xml_space.docx")
{
CPPUNIT_ASSERT_EQUAL(1, getParagraphs());
diff --git a/vcl/source/filter/graphicfilter2.cxx b/vcl/source/filter/graphicfilter2.cxx
index f35ac1c37c81..4439c2ab8b50 100644
--- a/vcl/source/filter/graphicfilter2.cxx
+++ b/vcl/source/filter/graphicfilter2.cxx
@@ -262,6 +262,7 @@ bool GraphicDescriptor::ImpDetectJPG( SvStream& rStm, bool bExtendedInfo )
bool bScanFailure = false;
bool bScanFinished = false;
+ MapMode aMap;
while (!bScanFailure && !bScanFinished && rStm.good())
{
@@ -331,7 +332,6 @@ bool GraphicDescriptor::ImpDetectJPG( SvStream& rStm, bool bExtendedInfo )
// setting the logical size
if ( nUnits && nHorizontalResolution && nVerticalResolution )
{
- MapMode aMap;
aMap.SetMapUnit( nUnits == 1 ? MapUnit::MapInch : MapUnit::MapCM );
aMap.SetScaleX( Fraction( 1, nHorizontalResolution ) );
aMap.SetScaleY( Fraction( 1, nVerticalResolution ) );
@@ -380,6 +380,13 @@ bool GraphicDescriptor::ImpDetectJPG( SvStream& rStm, bool bExtendedInfo )
nBitsPerPixel = ( nNumberOfImageComponents == 3 ? 24 : nNumberOfImageComponents == 1 ? 8 : 0 );
nPlanes = 1;
+ if (aMap.GetMapUnit() != MapUnit::MapPixel)
+ // We already know the DPI, but the
+ // pixel size arrived later, so do the
+ // conversion again.
+ aLogSize = OutputDevice::LogicToLogic(
+ aPixSize, aMap, MapMode(MapUnit::Map100thMM));
+
bScanFinished = true;
}
break;
diff --git a/vcl/source/gdi/impgraph.cxx b/vcl/source/gdi/impgraph.cxx
index 9cd9bbb11717..1a9cca6ce0da 100644
--- a/vcl/source/gdi/impgraph.cxx
+++ b/vcl/source/gdi/impgraph.cxx
@@ -523,8 +523,20 @@ void ImpGraphic::ImplSetPrepared()
GraphicDescriptor aDescriptor(aMemoryStream, nullptr);
if (aDescriptor.Detect(true))
{
- maSwapInfo.maPrefSize = aDescriptor.GetSizePixel();
- maSwapInfo.maPrefMapMode = MapMode(MapUnit::MapPixel);
+ // If we have logic size, work with that, as later pixel -> logic
+ // conversion will work with the output device DPI, not the graphic
+ // DPI.
+ Size aLogSize = aDescriptor.GetSize_100TH_MM();
+ if (aLogSize.getWidth() && aLogSize.getHeight())
+ {
+ maSwapInfo.maPrefSize = aLogSize;
+ maSwapInfo.maPrefMapMode = MapMode(MapUnit::Map100thMM);
+ }
+ else
+ {
+ maSwapInfo.maPrefSize = aDescriptor.GetSizePixel();
+ maSwapInfo.maPrefMapMode = MapMode(MapUnit::MapPixel);
+ }
}
maSwapInfo.mnAnimationLoopCount = 0;
maSwapInfo.mbIsAnimated = false;
diff --git a/vcl/source/graphic/UnoGraphicProvider.cxx b/vcl/source/graphic/UnoGraphicProvider.cxx
index 50c273006b85..8b9ccb93bf94 100644
--- a/vcl/source/graphic/UnoGraphicProvider.cxx
+++ b/vcl/source/graphic/UnoGraphicProvider.cxx
@@ -304,6 +304,7 @@ uno::Reference< ::graphic::XGraphic > SAL_CALL GraphicProvider::queryGraphic( co
uno::Sequence< ::beans::PropertyValue > aFilterData;
+ bool bLazyRead = false;
for( sal_Int32 i = 0; ( i < rMediaProperties.getLength() ) && !pIStm && !xRet.is(); ++i )
{
const OUString aName( rMediaProperties[ i ].Name );
@@ -327,6 +328,8 @@ uno::Reference< ::graphic::XGraphic > SAL_CALL GraphicProvider::queryGraphic( co
{
aValue >>= aFilterData;
}
+ else if (aName == "LazyRead")
+ aValue >>= bLazyRead;
}
// Check for the goal width and height if they are defined
@@ -352,6 +355,9 @@ uno::Reference< ::graphic::XGraphic > SAL_CALL GraphicProvider::queryGraphic( co
}
}
+ if (bLazyRead && aFilterData.hasElements())
+ bLazyRead = false;
+
SolarMutexGuard g;
if( xIStm.is() )
@@ -392,8 +398,17 @@ uno::Reference< ::graphic::XGraphic > SAL_CALL GraphicProvider::queryGraphic( co
if ( nExtMapMode > 0 )
pExtHeader = &aExtHeader;
- ErrCode error = rFilter.ImportGraphic( aVCLGraphic, aPath, *pIStm,
- GRFILTER_FORMAT_DONTKNOW, nullptr, GraphicFilterImportFlags::NONE, pExtHeader );
+ ErrCode error = ERRCODE_NONE;
+ if (bLazyRead)
+ {
+ Graphic aGraphic = rFilter.ImportUnloadedGraphic(*pIStm);
+ if (aGraphic)
+ aVCLGraphic = aGraphic;
+ }
+ if (!aVCLGraphic)
+ error = rFilter.ImportGraphic(aVCLGraphic, aPath, *pIStm, GRFILTER_FORMAT_DONTKNOW,
+ nullptr, GraphicFilterImportFlags::NONE, pExtHeader);
+
if( (error == ERRCODE_NONE ) &&
( aVCLGraphic.GetType() != GraphicType::NONE ) )
{