[Libreoffice-commits] core.git: Branch 'private/swe/libreoffice-5-2+backports' - 3 commits - vcl/inc vcl/source

Armin Le Grand Armin.Le.Grand at cib.de
Wed Apr 4 15:30:43 UTC 2018


 vcl/inc/printdlg.hxx           |    6 -
 vcl/source/window/printdlg.cxx |  176 +++++++++++++++++++++++++++++------------
 2 files changed, 129 insertions(+), 53 deletions(-)

New commits:
commit f886ddd7764acf6f7d523ebec3905af86fbd4876
Author: Armin Le Grand <Armin.Le.Grand at cib.de>
Date:   Wed Apr 4 12:31:08 2018 +0200

    PrintPreviewWindow dynamic preview Bitmap III
    
    Corrected condition for test if maximum is reached
    
    Change-Id: I24795dfa15093fe0f4eb71d94e18b9f0a33a6891
    Reviewed-on: https://gerrit.libreoffice.org/52372
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Armin Le Grand <Armin.Le.Grand at cib.de>

diff --git a/vcl/source/window/printdlg.cxx b/vcl/source/window/printdlg.cxx
index bc7ef63434f2..4761ab68e8c2 100644
--- a/vcl/source/window/printdlg.cxx
+++ b/vcl/source/window/printdlg.cxx
@@ -331,7 +331,7 @@ void PrintDialog::PrintPreviewWindow::preparePreviewBitmap()
     const double fPreviewSizeSquare(static_cast<double>(maPreviewBitmap.GetSizePixel().getWidth() * maPreviewBitmap.GetSizePixel().getHeight()));
 
     // test as equal up to 0.1% (0.001)
-    if(fabs((fScaledSizeSquare / fPreviewSizeSquare) - 1.0) < 0.001)
+    if(fPreviewSizeSquare != 0.0 && fabs((fScaledSizeSquare / fPreviewSizeSquare) - 1.0) < 0.001)
     {
         // maximum is reached, avoid bigger scaling
         return;
commit 5e4822f6f9a7c346c192fa1832344d8eb4a4ded5
Author: Armin Le Grand <Armin.Le.Grand at cib.de>
Date:   Mon Apr 2 15:44:45 2018 +0200

    PrintPreviewWindow dynamic preview Bitmap II
    
    Added reset of PreviewBitmap when new/different Metafile
    gets set
    
    Change-Id: Ib8053c21fc868607adfff4f1a75f005d29ce356b

diff --git a/vcl/source/window/printdlg.cxx b/vcl/source/window/printdlg.cxx
index d7686e367625..bc7ef63434f2 100644
--- a/vcl/source/window/printdlg.cxx
+++ b/vcl/source/window/printdlg.cxx
@@ -243,6 +243,10 @@ void PrintDialog::PrintPreviewWindow::setPreview( const GDIMetaFile& i_rNewPrevi
     aBuf.appendAscii( eUnit == MAP_MM ? "mm" : "in" );
     maVertDim->SetText( aBuf.makeStringAndClear() );
 
+    // We have a new Metafile and evtl. a new page, so we need to reset
+    // the PreviewBitmap to force new creation
+    maPreviewBitmap = Bitmap();
+
     // sets/calculates e.g. maPreviewSize
     // also triggers preparePreviewBitmap()
     Resize();
commit 18c4dd445520c1a0dbae0d9118ff392373123843
Author: Armin Le Grand <Armin.Le.Grand at cib.de (CIB)>
Date:   Fri Mar 30 13:02:02 2018 +0200

    PrintPreviewWindow dynamic preview Bitmap
    
    The PrintDialog includes a preview (PrintPreviewWindow)
    that currently used a fixed-pixel-size preview that takes
    the aspect ratio into account (which may already explode
    due to just growing vertically - try a much higher than
    wide page). It is not dynamic and by using the high-quality
    scale (BmpScaleFlag::BestQuality) for output it can get
    rather slow in repainting. Also holds the VDev for creating
    the preview all the time without need.
    Made that process dynamic and responding to real resizing,
    thus not using that huge number of pixels from the start.
    Also use a VDev only temporary and use intelligent size
    management.
    Still keeping the high-quality scale due to ::DrawBitmap
    with a target size not scaling well (still) and also
    ::DrawOutDev not good in quality. Those two should work
    better nowadays, but adaption would be risky.
    
    Change-Id: I211412a063def33a4e8f40c7442702770cd11a8e
    Reviewed-on: https://gerrit.libreoffice.org/52150
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Armin Le Grand <Armin.Le.Grand at cib.de>

diff --git a/vcl/inc/printdlg.hxx b/vcl/inc/printdlg.hxx
index be7641109f64..1017f509c78b 100644
--- a/vcl/inc/printdlg.hxx
+++ b/vcl/inc/printdlg.hxx
@@ -39,12 +39,11 @@ namespace vcl
     public:
         class PrintPreviewWindow : public vcl::Window
         {
-            static const sal_Int32 PREVIEW_BITMAP_WIDTH;
-
             GDIMetaFile         maMtf;
             Size                maOrigSize;
             Size                maPreviewSize;
-            VclPtr<VirtualDevice> maPageVDev;
+            sal_Int32           mnDPIX;
+            sal_Int32           mnDPIY;
             Bitmap              maPreviewBitmap;
             OUString            maReplacementString;
             OUString            maToolTipString;
@@ -62,7 +61,6 @@ namespace vcl
             virtual void Paint( vcl::RenderContext& rRenderContext, const Rectangle& rRect ) override;
             virtual void Command( const CommandEvent& ) override;
             virtual void Resize() override;
-            virtual void DataChanged( const DataChangedEvent& ) override;
 
             void setPreview( const GDIMetaFile&, const Size& i_rPaperSize,
                              const OUString& i_rPaperName,
diff --git a/vcl/source/window/printdlg.cxx b/vcl/source/window/printdlg.cxx
index bf819aebf351..d7686e367625 100644
--- a/vcl/source/window/printdlg.cxx
+++ b/vcl/source/window/printdlg.cxx
@@ -66,16 +66,20 @@ VCL_BUILDER_DECL_FACTORY(ShowNupOrderWindow)
 
 PrintDialog::PrintPreviewWindow::PrintPreviewWindow( vcl::Window* i_pParent )
     : Window( i_pParent, 0 )
+    , maMtf()
     , maOrigSize( 10, 10 )
-    , maPageVDev( VclPtr<VirtualDevice>::Create(*this) )
-    , maToolTipString(VclResId( SV_PRINT_PRINTPREVIEW_TXT).toString())
+    , maPreviewSize()
+    , mnDPIX(Application::GetDefaultDevice()->GetDPIX())
+    , mnDPIY(Application::GetDefaultDevice()->GetDPIY())
+    , maPreviewBitmap()
+    , maReplacementString()
+    , maToolTipString(VclResId( SV_PRINT_PRINTPREVIEW_TXT))
     , mbGreyscale( false )
     , maHorzDim(VclPtr<FixedLine>::Create(this, WB_HORZ | WB_CENTER))
     , maVertDim(VclPtr<FixedLine>::Create(this, WB_VERT | WB_VCENTER))
 {
     SetPaintTransparent( true );
     SetBackground();
-    maPageVDev->SetBackground( Color( COL_WHITE ) );
     maHorzDim->Show();
     maVertDim->Show();
 
@@ -92,22 +96,9 @@ void PrintDialog::PrintPreviewWindow::dispose()
 {
     maHorzDim.disposeAndClear();
     maVertDim.disposeAndClear();
-    maPageVDev.disposeAndClear();
     Window::dispose();
 }
 
-const sal_Int32 PrintDialog::PrintPreviewWindow::PREVIEW_BITMAP_WIDTH = 1600;
-
-void PrintDialog::PrintPreviewWindow::DataChanged( const DataChangedEvent& i_rDCEvt )
-{
-    // react on settings changed
-    if( i_rDCEvt.GetType() == DataChangedEventType::SETTINGS )
-    {
-        maPageVDev->SetBackground( Color( COL_WHITE ) );
-    }
-    Window::DataChanged( i_rDCEvt );
-}
-
 void PrintDialog::PrintPreviewWindow::Resize()
 {
     Size aNewSize( GetSizePixel() );
@@ -141,19 +132,6 @@ void PrintDialog::PrintPreviewWindow::Resize()
 
     maPreviewSize = aScaledSize;
 
-    // #i104784# if we render the page too small then rounding issues result in
-    // layout artifacts looking really bad. So scale the page unto a device that is not
-    // full page size but not too small either. This also results in much better visual
-    // quality of the preview, e.g. when its height approaches the number of text lines
-    // find a good scaling factor
-
-    double aAspectRatio = aScaledSize.Height() / (double) aScaledSize.Width();
-
-    aScaledSize.Width()  = PREVIEW_BITMAP_WIDTH;
-    aScaledSize.Height() = PREVIEW_BITMAP_WIDTH * aAspectRatio;
-
-    maPageVDev->SetOutputSizePixel( aScaledSize, false );
-
     // position dimension lines
     Point aRef( nTextHeight + (aNewSize.Width() - maPreviewSize.Width())/2,
                 nTextHeight + (aNewSize.Height() - maPreviewSize.Height())/2 );
@@ -162,6 +140,8 @@ void PrintDialog::PrintPreviewWindow::Resize()
     maVertDim->SetPosSizePixel( Point( aRef.X() - nTextHeight, aRef.Y() ),
                                Size( nTextHeight, maPreviewSize.Height() ) );
 
+    // check and evtl. recreate preview bitmap
+    preparePreviewBitmap();
 }
 
 void PrintDialog::PrintPreviewWindow::Paint(vcl::RenderContext& rRenderContext, const Rectangle&)
@@ -186,6 +166,11 @@ void PrintDialog::PrintPreviewWindow::Paint(vcl::RenderContext& rRenderContext,
     else
     {
         Bitmap aPreviewBitmap(maPreviewBitmap);
+
+        // This explicit force-to-scale allows us to get the
+        // mentioned best quality here. Unfortunately this is
+        // currently not sure when using just ::DrawBitmap with
+        // a defined size or ::DrawOutDev
         aPreviewBitmap.Scale(maPreviewSize, BmpScaleFlag::BestQuality);
         rRenderContext.DrawBitmap(aOffset, aPreviewBitmap);
     }
@@ -224,12 +209,11 @@ void PrintDialog::PrintPreviewWindow::setPreview( const GDIMetaFile& i_rNewPrevi
     aBuf.append( maToolTipString );
     SetQuickHelpText( aBuf.makeStringAndClear() );
     maMtf = i_rNewPreview;
-
+    mnDPIX = i_nDPIX;
+    mnDPIY = i_nDPIY;
     maOrigSize = i_rOrigSize;
     maReplacementString = i_rReplacement;
     mbGreyscale = i_bGreyscale;
-    maPageVDev->SetReferenceDevice( i_nDPIX, i_nDPIY );
-    maPageVDev->EnableOutput();
 
     // use correct measurements
     const LocaleDataWrapper& rLocWrap( GetSettings().GetLocaleDataWrapper() );
@@ -259,17 +243,107 @@ void PrintDialog::PrintPreviewWindow::setPreview( const GDIMetaFile& i_rNewPrevi
     aBuf.appendAscii( eUnit == MAP_MM ? "mm" : "in" );
     maVertDim->SetText( aBuf.makeStringAndClear() );
 
+    // sets/calculates e.g. maPreviewSize
+    // also triggers preparePreviewBitmap()
     Resize();
-    preparePreviewBitmap();
+
     Invalidate();
 }
 
 void PrintDialog::PrintPreviewWindow::preparePreviewBitmap()
 {
+    if(maPreviewSize.getWidth() < 0 || maPreviewSize.getHeight() < 0)
+    {
+        // not yet fully initialized, no need to prepare anything
+        return;
+    }
+
+    // define an allowed number of pixels, also see
+    // defaults for primitive renderers and similar. This
+    // might be centralized and made dependent of 32/64bit
+    const sal_uInt32 nMaxSquarePixels(500000);
+
+    // check how big (squarePixels) the preview is currently (with
+    // max value of MaxSquarePixels)
+    const sal_uInt32 nCurrentSquarePixels(
+        std::min(
+            nMaxSquarePixels,
+            static_cast<sal_uInt32>(maPreviewBitmap.GetSizePixel().getWidth())
+            * static_cast<sal_uInt32>(maPreviewBitmap.GetSizePixel().getHeight())));
+
+    // check how big (squarePixels) the preview needs to be (with
+    // max value of MaxSquarePixels)
+    const sal_uInt32 nRequiredSquarePixels(
+        std::min(
+            nMaxSquarePixels,
+            static_cast<sal_uInt32>(maPreviewSize.getWidth())
+            * static_cast<sal_uInt32>(maPreviewSize.getHeight())));
+
+    // check if preview is big enough. Use a scaling value in
+    // the comparison to not get bigger at the last possible moment
+    // what may look awkward and pixelated (again). This means
+    // to use a percentage value - if we have at least
+    // that value of required pixels, we are good.
+    static double fPreventAwkwardFactor(1.35); // 35%
+    if(nCurrentSquarePixels >= static_cast<sal_uInt32>(nRequiredSquarePixels * fPreventAwkwardFactor))
+    {
+        // at this place we also could add a mechanism to let the preview
+        // bitmap 'shrink' again if it is currently 'too big' -> bigger
+        // than required. I think this is not necessary for now.
+
+        // already sufficient, done.
+        return;
+    }
+
+    // check if we have enough square pixels e.g for 8x8 pixels
+    if(nRequiredSquarePixels < 64)
+    {
+        // too small preview - let it empty
+        return;
+    }
+
+    // Calculate nPlannedSquarePixels which is the required size
+    // expanded by a percentage (with max value of MaxSquarePixels)
+    static double fExtraSpaceFactor(1.65); // 65%
+    const sal_uInt32 nPlannedSquarePixels(
+        std::min(
+            nMaxSquarePixels,
+            static_cast<sal_uInt32>(maPreviewSize.getWidth() * fExtraSpaceFactor)
+            * static_cast<sal_uInt32>(maPreviewSize.getHeight() * fExtraSpaceFactor)));
+
+    // calculate back new width and height - it might have been
+    // truncated by MaxSquarePixels.
+    // We know that w*h == nPlannedSquarePixels and w/h == ratio
+    const double fRatio(static_cast<double>(maPreviewSize.getWidth()) / static_cast<double>(maPreviewSize.getHeight()));
+    const double fNewWidth(sqrt(static_cast<double>(nPlannedSquarePixels) * fRatio));
+    const double fNewHeight(sqrt(static_cast<double>(nPlannedSquarePixels) / fRatio));
+    const Size aScaledSize(basegfx::fround(fNewWidth), basegfx::fround(fNewHeight));
+
+    // check if this eventual maximum is already reached
+    // due to having hit the MaxSquarePixels. Due to using
+    // an integer AspectRatio, we cannot make a numeric exact
+    // comparison - we need to compare if we are close
+    const double fScaledSizeSquare(static_cast<double>(aScaledSize.getWidth() * aScaledSize.getHeight()));
+    const double fPreviewSizeSquare(static_cast<double>(maPreviewBitmap.GetSizePixel().getWidth() * maPreviewBitmap.GetSizePixel().getHeight()));
+
+    // test as equal up to 0.1% (0.001)
+    if(fabs((fScaledSizeSquare / fPreviewSizeSquare) - 1.0) < 0.001)
+    {
+        // maximum is reached, avoid bigger scaling
+        return;
+    }
+
+    // create temporary VDev and render to it
+    ScopedVclPtrInstance<VirtualDevice> pPrerenderVDev(*Application::GetDefaultDevice());
+    pPrerenderVDev->SetOutputSizePixel(aScaledSize, false);
+    pPrerenderVDev->SetReferenceDevice( mnDPIX, mnDPIY );
+    pPrerenderVDev->EnableOutput();
+    pPrerenderVDev->SetBackground( Wallpaper(COL_WHITE) );
+
     GDIMetaFile aMtf( maMtf );
 
-    Size aVDevSize( maPageVDev->GetOutputSizePixel() );
-    const Size aLogicSize( maPageVDev->PixelToLogic( aVDevSize, MapMode( MAP_100TH_MM ) ) );
+    Size aVDevSize( pPrerenderVDev->GetOutputSizePixel() );
+    const Size aLogicSize( pPrerenderVDev->PixelToLogic( aVDevSize, MapMode( MAP_100TH_MM ) ) );
     Size aOrigSize( maOrigSize );
     if( aOrigSize.Width() < 1 )
         aOrigSize.Width() = aLogicSize.Width();
@@ -277,31 +351,31 @@ void PrintDialog::PrintPreviewWindow::preparePreviewBitmap()
         aOrigSize.Height() = aLogicSize.Height();
     double fScale = double(aLogicSize.Width())/double(aOrigSize.Width());
 
-    maPageVDev->Erase();
-    maPageVDev->Push();
-    maPageVDev->SetMapMode( MAP_100TH_MM );
-    DrawModeFlags nOldDrawMode = maPageVDev->GetDrawMode();
+    pPrerenderVDev->Erase();
+    pPrerenderVDev->Push();
+    pPrerenderVDev->SetMapMode(MapMode(MAP_100TH_MM));
+    DrawModeFlags nOldDrawMode = pPrerenderVDev->GetDrawMode();
     if( mbGreyscale )
-        maPageVDev->SetDrawMode( maPageVDev->GetDrawMode() |
+        pPrerenderVDev->SetDrawMode( pPrerenderVDev->GetDrawMode() |
                                 ( DrawModeFlags::GrayLine | DrawModeFlags::GrayFill | DrawModeFlags::GrayText |
                                   DrawModeFlags::GrayBitmap | DrawModeFlags::GrayGradient ) );
     aMtf.WindStart();
     aMtf.Scale( fScale, fScale );
     aMtf.WindStart();
 
-    const AntialiasingFlags nOriginalAA(maPageVDev->GetAntialiasing());
-    maPageVDev->SetAntialiasing(nOriginalAA | AntialiasingFlags::EnableB2dDraw);
-    aMtf.Play( maPageVDev.get(), Point( 0, 0 ), aLogicSize );
-    maPageVDev->SetAntialiasing(nOriginalAA);
+    const AntialiasingFlags nOriginalAA(pPrerenderVDev->GetAntialiasing());
+    pPrerenderVDev->SetAntialiasing(nOriginalAA | AntialiasingFlags::EnableB2dDraw);
+    aMtf.Play( pPrerenderVDev.get(), Point( 0, 0 ), aLogicSize );
+    pPrerenderVDev->SetAntialiasing(nOriginalAA);
 
-    maPageVDev->Pop();
+    pPrerenderVDev->Pop();
 
-    SetMapMode( MAP_PIXEL );
-    maPageVDev->SetMapMode( MAP_PIXEL );
+    SetMapMode(MAP_PIXEL);
+    pPrerenderVDev->SetMapMode(MAP_PIXEL);
 
-    maPreviewBitmap = Bitmap(maPageVDev->GetBitmap(Point(0, 0), aVDevSize));
+    maPreviewBitmap = pPrerenderVDev->GetBitmap(Point(0, 0), aVDevSize);
 
-    maPageVDev->SetDrawMode( nOldDrawMode );
+    pPrerenderVDev->SetDrawMode( nOldDrawMode );
 }
 
 PrintDialog::ShowNupOrderWindow::ShowNupOrderWindow( vcl::Window* i_pParent )


More information about the Libreoffice-commits mailing list