[Libreoffice-commits] core.git: filter/source include/vcl vcl/CppunitTest_vcl_mapmode.mk vcl/Module_vcl.mk vcl/qa vcl/source

Chris Sherlock chris.sherlock79 at gmail.com
Sun Feb 14 20:51:34 UTC 2016


 filter/source/graphicfilter/eps/eps.cxx |   49 ------------------------
 include/vcl/graph.hxx                   |    3 +
 include/vcl/mapmod.hxx                  |    3 +
 vcl/CppunitTest_vcl_mapmode.mk          |   53 ++++++++++++++++++++++++++
 vcl/Module_vcl.mk                       |    1 
 vcl/qa/cppunit/mapmode.cxx              |   65 ++++++++++++++++++++++++++++++++
 vcl/source/filter/jpeg/JpegWriter.cxx   |    6 ++
 vcl/source/filter/jpeg/jpeg.h           |    4 +
 vcl/source/filter/jpeg/jpegc.cxx        |    6 +-
 vcl/source/gdi/graph.cxx                |   26 +++++++++++-
 vcl/source/gdi/mapmod.cxx               |   47 ++++++++++++++++++++++-
 11 files changed, 207 insertions(+), 56 deletions(-)

New commits:
commit f8355221ae62b89a706f2d04b63eda658f3ccfa5
Author: Chris Sherlock <chris.sherlock79 at gmail.com>
Date:   Sat Feb 13 16:08:01 2016 +1100

    tdf#85761 vcl: JPEG export does not save PPI values correctly
    
    JPEG values are currently hardcoded to 96PPI when we export JPEGs. The
    Graphic class doesn't have an easy way to get the PPI, but this can
    actually be calculated from the pref size and pref map mode (no idea
    why it is called "Pref").
    
    Interestingly, you need to get a multiplier to work this out, relative
    to units of 100th mm. The EPS filter code had a function that does
    exactly this, but it's entirely based on MapMode units so it was really
    implemented in the wrong class IMO. I have thus moved it out of PSWriter
    and into MapMode.
    
    This also fixes tdf#65695, which was partially fixed, but had the JPEG
    PPI hardcoded to 96dpi.
    
    Also fixes tdf#97481.
    
    Change-Id: Iedb674141dd4e22fcbfb7be357dc777f732aa3aa
    Reviewed-on: https://gerrit.libreoffice.org/22339
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Tomaž Vajngerl <quikee at gmail.com>

diff --git a/filter/source/graphicfilter/eps/eps.cxx b/filter/source/graphicfilter/eps/eps.cxx
index 0800b4c..aaa5fd0 100644
--- a/filter/source/graphicfilter/eps/eps.cxx
+++ b/filter/source/graphicfilter/eps/eps.cxx
@@ -215,7 +215,6 @@ private:
     inline void         ImplWriteTextColor( sal_uLong nMode = PS_RET );
     void                ImplWriteColor( sal_uLong nMode );
 
-    static double       ImplGetScaling( const MapMode& );
     void                ImplGetMapMode( const MapMode& );
     static bool         ImplGetBoundingBox( double* nNumb, sal_uInt8* pSource, sal_uLong nSize );
     static sal_uInt8*   ImplSearchEntry( sal_uInt8* pSource, sal_uInt8 const * pDest, sal_uLong nComp, sal_uLong nSize );
@@ -2197,56 +2196,10 @@ void PSWriter::ImplWriteColor( sal_uLong nMode )
     ImplExecMode( nMode );
 }
 
-double PSWriter::ImplGetScaling( const MapMode& rMapMode )
-{
-    double  nMul;
-    switch ( rMapMode.GetMapUnit() )
-    {
-        case MAP_PIXEL :
-        case MAP_SYSFONT :
-        case MAP_APPFONT :
-
-        case MAP_100TH_MM :
-            nMul = 1;
-            break;
-        case MAP_10TH_MM :
-            nMul = 10;
-            break;
-        case MAP_MM :
-            nMul = 100;
-            break;
-        case MAP_CM :
-            nMul = 1000;
-            break;
-        case MAP_1000TH_INCH :
-            nMul = 2.54;
-            break;
-        case MAP_100TH_INCH :
-            nMul = 25.4;
-            break;
-        case MAP_10TH_INCH :
-            nMul = 254;
-            break;
-        case MAP_INCH :
-            nMul = 2540;
-            break;
-        case MAP_TWIP :
-            nMul = 1.76388889;
-            break;
-        case MAP_POINT :
-            nMul = 35.27777778;
-            break;
-        default:
-            nMul = 1.0;
-            break;
-    }
-    return nMul;
-}
-
 void PSWriter::ImplGetMapMode( const MapMode& rMapMode )
 {
     ImplWriteLine( "tm setmatrix" );
-    double fMul = ImplGetScaling( rMapMode );
+    double fMul = rMapMode.GetUnitMultiplier();
     double fScaleX = (double)rMapMode.GetScaleX() * fMul;
     double fScaleY = (double)rMapMode.GetScaleY() * fMul;
     ImplTranslate( rMapMode.GetOrigin().X() * fScaleX, rMapMode.GetOrigin().Y() * fScaleY );
diff --git a/include/vcl/graph.hxx b/include/vcl/graph.hxx
index 4ca9491..7514f87 100644
--- a/include/vcl/graph.hxx
+++ b/include/vcl/graph.hxx
@@ -31,6 +31,7 @@
 #include <vcl/gfxlink.hxx>
 #include <com/sun/star/uno/Reference.hxx>
 #include <vcl/svgdata.hxx>
+#include <basegfx/vector/b2dsize.hxx>
 
 
 enum GraphicType
@@ -163,6 +164,8 @@ public:
     MapMode         GetPrefMapMode() const;
     void            SetPrefMapMode( const MapMode& rPrefMapMode );
 
+    basegfx::B2DSize GetPPI() const;
+
     Size            GetSizePixel( const OutputDevice* pRefDevice = nullptr ) const;
 
     sal_uLong       GetSizeBytes() const;
diff --git a/include/vcl/mapmod.hxx b/include/vcl/mapmod.hxx
index 508bdd8..77aa83d 100644
--- a/include/vcl/mapmod.hxx
+++ b/include/vcl/mapmod.hxx
@@ -61,6 +61,9 @@ public:
     void            SetScaleY( const Fraction& rScaleY );
     const Fraction& GetScaleY() const;
 
+    /// Gets the multiplier, which is relative to 1/100 mm units
+    double          GetUnitMultiplier() const;
+
     MapMode&        operator=( const MapMode& rMapMode );
     bool            operator==( const MapMode& rMapMode ) const;
     bool            operator!=( const MapMode& rMapMode ) const
diff --git a/vcl/CppunitTest_vcl_mapmode.mk b/vcl/CppunitTest_vcl_mapmode.mk
new file mode 100644
index 0000000..daee480
--- /dev/null
+++ b/vcl/CppunitTest_vcl_mapmode.mk
@@ -0,0 +1,53 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+$(eval $(call gb_CppunitTest_CppunitTest,vcl_mapmode))
+
+$(eval $(call gb_CppunitTest_set_include,vcl_mapmode,\
+    $$(INCLUDE) \
+    -I$(SRCDIR)/vcl/inc \
+))
+
+$(eval $(call gb_CppunitTest_add_exception_objects,vcl_mapmode, \
+	vcl/qa/cppunit/mapmode \
+))
+
+$(eval $(call gb_CppunitTest_use_externals,vcl_mapmode,boost_headers))
+
+$(eval $(call gb_CppunitTest_use_libraries,vcl_mapmode, \
+	comphelper \
+	cppu \
+	cppuhelper \
+	sal \
+	svt \
+	test \
+	tl \
+	tk \
+	unotest \
+	vcl \
+	$(gb_UWINAPI) \
+))
+
+$(eval $(call gb_CppunitTest_use_api,vcl_mapmode,\
+	udkapi \
+	offapi \
+))
+
+$(eval $(call gb_CppunitTest_use_ure,vcl_mapmode))
+$(eval $(call gb_CppunitTest_use_vcl,vcl_mapmode))
+
+$(eval $(call gb_CppunitTest_use_components,vcl_mapmode,\
+	configmgr/source/configmgr \
+	i18npool/util/i18npool \
+	ucb/source/core/ucb1 \
+))
+
+$(eval $(call gb_CppunitTest_use_configuration,vcl_mapmode))
+
+# vim: set noet sw=4 ts=4:
diff --git a/vcl/Module_vcl.mk b/vcl/Module_vcl.mk
index 299ffb1..65fa586 100644
--- a/vcl/Module_vcl.mk
+++ b/vcl/Module_vcl.mk
@@ -101,6 +101,7 @@ $(eval $(call gb_Module_add_check_targets,vcl,\
 	CppunitTest_vcl_fontmetric \
 	CppunitTest_vcl_complextext \
 	CppunitTest_vcl_filters_test \
+	CppunitTest_vcl_mapmode \
 	CppunitTest_vcl_outdev \
 	CppunitTest_vcl_app_test \
 	CppunitTest_vcl_wmf_test \
diff --git a/vcl/qa/cppunit/mapmode.cxx b/vcl/qa/cppunit/mapmode.cxx
new file mode 100644
index 0000000..87c20a3
--- /dev/null
+++ b/vcl/qa/cppunit/mapmode.cxx
@@ -0,0 +1,65 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <test/bootstrapfixture.hxx>
+#include <cppunit/TestAssert.h>
+#include <cppunit/TestFixture.h>
+
+#include <osl/file.hxx>
+#include <osl/process.h>
+
+#include <vcl/mapmod.hxx>
+
+class VclMapModeTest : public test::BootstrapFixture
+{
+public:
+    VclMapModeTest() : BootstrapFixture(true, false) {}
+
+    void testMultiplier();
+
+    CPPUNIT_TEST_SUITE(VclMapModeTest);
+    CPPUNIT_TEST(testMultiplier);
+    CPPUNIT_TEST_SUITE_END();
+};
+
+void VclMapModeTest::testMultiplier()
+{
+    MapMode aMapMode;
+    CPPUNIT_ASSERT_MESSAGE( "Default map mode is MAP_PIXEL, multiplier should be 1", aMapMode.GetUnitMultiplier() == 1 );
+    aMapMode.SetMapUnit( MAP_SYSFONT );
+    CPPUNIT_ASSERT_MESSAGE( "Map mode is MAP_SYSFONT, multiplier should be 1", aMapMode.GetUnitMultiplier() == 1 );
+    aMapMode.SetMapUnit( MAP_APPFONT );
+    CPPUNIT_ASSERT_MESSAGE( "Map mode is MAP_APPFONT, multiplier should be 1", aMapMode.GetUnitMultiplier() == 1 );
+    aMapMode.SetMapUnit( MAP_100TH_MM );
+    CPPUNIT_ASSERT_MESSAGE( "Map mode is MAP_100TH_MM, multiplier should be 1", aMapMode.GetUnitMultiplier() == 1 );
+    aMapMode.SetMapUnit( MAP_10TH_MM );
+    CPPUNIT_ASSERT_MESSAGE( "Map mode is MAP_10TH_MM, multiplier should be 10", aMapMode.GetUnitMultiplier() == 10 );
+    aMapMode.SetMapUnit( MAP_MM );
+    CPPUNIT_ASSERT_MESSAGE( "Map mode is MAP_MM, multiplier should be 100", aMapMode.GetUnitMultiplier() == 100 );
+    aMapMode.SetMapUnit( MAP_CM );
+    CPPUNIT_ASSERT_MESSAGE( "Map mode is MAP_CM, multiplier should be 1000", aMapMode.GetUnitMultiplier() == 1000 );
+    aMapMode.SetMapUnit( MAP_1000TH_INCH );
+    CPPUNIT_ASSERT_MESSAGE( "Map mode is MAP_1000TH_INCH, multiplier should be 2.54", aMapMode.GetUnitMultiplier() == 2.54 );
+    aMapMode.SetMapUnit( MAP_100TH_INCH );
+    CPPUNIT_ASSERT_MESSAGE( "Map mode is MAP_100TH_INCH, multiplier should be 2.54", aMapMode.GetUnitMultiplier() == 25.4 );
+    aMapMode.SetMapUnit( MAP_10TH_INCH );
+    CPPUNIT_ASSERT_MESSAGE( "Map mode is MAP_10TH_INCH, multiplier should be 254", aMapMode.GetUnitMultiplier() == 254 );
+    aMapMode.SetMapUnit( MAP_INCH );
+    CPPUNIT_ASSERT_MESSAGE( "Map mode is MAP_INCH, multiplier should be 2540", aMapMode.GetUnitMultiplier() == 2540 );
+    aMapMode.SetMapUnit( MAP_TWIP );
+    CPPUNIT_ASSERT_MESSAGE( "Map mode is MAP_TWIP, multiplier should be 1.76388889", aMapMode.GetUnitMultiplier() == 1.76388889 );
+    aMapMode.SetMapUnit( MAP_POINT );
+    CPPUNIT_ASSERT_MESSAGE( "Map mode is MAP_POINT, multiplier should be 35.27777778", aMapMode.GetUnitMultiplier() == 35.27777778 );
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(VclMapModeTest);
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/filter/jpeg/JpegWriter.cxx b/vcl/source/filter/jpeg/JpegWriter.cxx
index 9463216..35c0479 100644
--- a/vcl/source/filter/jpeg/JpegWriter.cxx
+++ b/vcl/source/filter/jpeg/JpegWriter.cxx
@@ -227,7 +227,11 @@ bool JPEGWriter::Write( const Graphic& rGraphic )
         if( !mbNative )
             mpBuffer = new sal_uInt8[ AlignedWidth4Bytes( mbGreys ? mpReadAccess->Width() * 8L : mpReadAccess->Width() * 24L ) ];
 
-        bRet = WriteJPEG( this, &mrStream, mpReadAccess->Width(), mpReadAccess->Height(), mbGreys, mnQuality, maChromaSubsampling, mxStatusIndicator );
+        SAL_INFO("vcl", "\nJPEG Export - DPI X: " << rGraphic.GetPPI().getX() << "\nJPEG Export - DPI Y: " << rGraphic.GetPPI().getY());
+
+        bRet = WriteJPEG( this, &mrStream, mpReadAccess->Width(),
+                          mpReadAccess->Height(), rGraphic.GetPPI(), mbGreys,
+                          mnQuality, maChromaSubsampling, mxStatusIndicator );
 
         delete[] mpBuffer;
         mpBuffer = nullptr;
diff --git a/vcl/source/filter/jpeg/jpeg.h b/vcl/source/filter/jpeg/jpeg.h
index 1f8c21f..63c4b2a 100644
--- a/vcl/source/filter/jpeg/jpeg.h
+++ b/vcl/source/filter/jpeg/jpeg.h
@@ -24,6 +24,7 @@
 
 #include <com/sun/star/uno/Reference.hxx>
 #include <sal/types.h>
+#include <basegfx/vector/b2dsize.hxx>
 
 #include <jpeglib.h>
 
@@ -38,7 +39,8 @@ void jpeg_svstream_src (j_decompress_ptr cinfo, void* infile);
 
 void jpeg_svstream_dest (j_compress_ptr cinfo, void* outfile);
 
-bool    WriteJPEG( JPEGWriter* pJPEGWriter, void* pOutputStream, long nWidth, long nHeight, bool bGreyScale,
+bool    WriteJPEG( JPEGWriter* pJPEGWriter, void* pOutputStream,
+                   long nWidth, long nHeight, basegfx::B2DSize aPPI, bool bGreyScale,
                    long nQualityPercent, long aChromaSubsampling,
                    css::uno::Reference<css::task::XStatusIndicator> const & status);
 
diff --git a/vcl/source/filter/jpeg/jpegc.cxx b/vcl/source/filter/jpeg/jpegc.cxx
index d42ae78..ef3c91c 100644
--- a/vcl/source/filter/jpeg/jpegc.cxx
+++ b/vcl/source/filter/jpeg/jpegc.cxx
@@ -231,7 +231,7 @@ void ReadJPEG( JPEGReader* pJPEGReader, void* pInputStream, long* pLines,
 }
 
 bool WriteJPEG( JPEGWriter* pJPEGWriter, void* pOutputStream,
-                long nWidth, long nHeight, bool bGreys,
+                long nWidth, long nHeight, basegfx::B2DSize aPPI, bool bGreys,
                 long nQualityPercent, long aChromaSubsampling,
                 css::uno::Reference<css::task::XStatusIndicator> const & status )
 {
@@ -270,8 +270,8 @@ bool WriteJPEG( JPEGWriter* pJPEGWriter, void* pOutputStream,
     jpeg_set_quality( &cinfo, (int) nQualityPercent, FALSE );
 
     cinfo.density_unit = 1;
-    cinfo.X_density = 96;
-    cinfo.Y_density = 96;
+    cinfo.X_density = aPPI.getX();
+    cinfo.Y_density = aPPI.getY();
 
     if ( ( nWidth > 128 ) || ( nHeight > 128 ) )
         jpeg_simple_progression( &cinfo );
diff --git a/vcl/source/gdi/graph.cxx b/vcl/source/gdi/graph.cxx
index 6acf9b1..2c14d8f 100644
--- a/vcl/source/gdi/graph.cxx
+++ b/vcl/source/gdi/graph.cxx
@@ -37,8 +37,8 @@ static void ImplDrawDefault( OutputDevice* pOutDev, const OUString* pText,
                              vcl::Font* pFont, const Bitmap* pBitmap, const BitmapEx* pBitmapEx,
                              const Point& rDestPt, const Size& rDestSize )
 {
-    sal_uInt16      nPixel = (sal_uInt16) pOutDev->PixelToLogic( Size( 1, 1 ) ).Width();
-    sal_uInt16      nPixelWidth = nPixel;
+    sal_uInt16  nPixel = (sal_uInt16) pOutDev->PixelToLogic( Size( 1, 1 ) ).Width();
+    sal_uInt16  nPixelWidth = nPixel;
     Point       aPoint( rDestPt.X() + nPixelWidth, rDestPt.Y() + nPixelWidth );
     Size        aSize( rDestSize.Width() - ( nPixelWidth << 1 ), rDestSize.Height() - ( nPixelWidth << 1 ) );
     bool        bFilled = ( pBitmap != nullptr || pBitmapEx != nullptr || pFont != nullptr );
@@ -407,6 +407,28 @@ void Graphic::SetPrefMapMode( const MapMode& rPrefMapMode )
     mpImpGraphic->ImplSetPrefMapMode( rPrefMapMode );
 }
 
+basegfx::B2DSize Graphic::GetPPI() const
+{
+    MapMode aMapMode = GetPrefMapMode();
+
+    double fWidthInches = ( GetPrefSize().Width() * aMapMode.GetUnitMultiplier() ) / 2540;
+    double fHeightInches = ( GetPrefSize().Height() * aMapMode.GetUnitMultiplier() ) / 2540;
+    double fPpiX = 0;
+    double fPpiY = 0;
+
+    if ( fWidthInches > 0 || fHeightInches > 0 ) // we don't want a divide by 0 situation
+    {
+        fPpiX = GetSizePixel().Width() / fWidthInches;
+        fPpiY = GetSizePixel().Height() / fHeightInches;
+    }
+    else
+    {
+        SAL_WARN("vcl", "PPI X is " << fPpiX << " and PPI Y is " << fPpiY << ": thus we are making this 0 DPI. This is unlikely.");
+    }
+
+    return basegfx::B2DSize( fPpiX, fPpiY );
+}
+
 Size Graphic::GetSizePixel( const OutputDevice* pRefDevice ) const
 {
     Size aRet;
diff --git a/vcl/source/gdi/mapmod.cxx b/vcl/source/gdi/mapmod.cxx
index c953518..0c4bc51 100644
--- a/vcl/source/gdi/mapmod.cxx
+++ b/vcl/source/gdi/mapmod.cxx
@@ -25,7 +25,6 @@
 #include <tools/vcompat.hxx>
 #include <tools/debug.hxx>
 
-
 struct MapMode::ImplMapMode
 {
     sal_uLong       mnRefCount;
@@ -208,6 +207,52 @@ void MapMode::SetScaleY( const Fraction& rScaleY )
     mpImplMapMode->maScaleY.ReduceInaccurate(32);
 }
 
+double MapMode::GetUnitMultiplier() const
+{
+    double  nMul;
+    switch ( GetMapUnit() )
+    {
+        case MAP_PIXEL :
+        case MAP_SYSFONT :
+        case MAP_APPFONT :
+
+        case MAP_100TH_MM :
+            nMul = 1;
+            break;
+        case MAP_10TH_MM :
+            nMul = 10;
+            break;
+        case MAP_MM :
+            nMul = 100;
+            break;
+        case MAP_CM :
+            nMul = 1000;
+            break;
+        case MAP_1000TH_INCH :
+            nMul = 2.54;
+            break;
+        case MAP_100TH_INCH :
+            nMul = 25.4;
+            break;
+        case MAP_10TH_INCH :
+            nMul = 254;
+            break;
+        case MAP_INCH :
+            nMul = 2540;
+            break;
+        case MAP_TWIP :
+            nMul = 1.76388889;
+            break;
+        case MAP_POINT :
+            nMul = 35.27777778;
+            break;
+        default:
+            nMul = 1.0;
+            break;
+    }
+    return nMul;
+}
+
 MapMode& MapMode::operator=( const MapMode& rMapMode )
 {
     DBG_ASSERT( rMapMode.mpImplMapMode->mnRefCount < 0xFFFFFFFE, "MapMode: RefCount overflow" );


More information about the Libreoffice-commits mailing list