Version 6.1.0.2, tag libreoffice-6.1.0.2
[LibreOffice.git] / sd / source / ui / dlg / vectdlg.cxx
blob2bbc2810b203785ebd7ba89869cc0fdb10aa62b0
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <vcl/vclenum.hxx>
21 #include <vcl/wrkwin.hxx>
22 #include <vcl/bitmapaccess.hxx>
23 #include <vcl/metaact.hxx>
24 #include <vcl/BitmapSimpleColorQuantizationFilter.hxx>
26 #include <DrawDocShell.hxx>
27 #include <sdmod.hxx>
28 #include <sdiocmpt.hxx>
29 #include <vectdlg.hxx>
31 #define VECTORIZE_MAX_EXTENT 512
33 SdVectorizeDlg::SdVectorizeDlg(weld::Window* pParent, const Bitmap& rBmp, ::sd::DrawDocShell* pDocShell)
34 : GenericDialogController(pParent, "modules/sdraw/ui/vectorize.ui", "VectorizeDialog")
35 , m_pDocSh(pDocShell)
36 , aBmp(rBmp)
37 , m_xNmLayers(m_xBuilder->weld_spin_button("colors"))
38 , m_xMtReduce(m_xBuilder->weld_metric_spin_button("points", FUNIT_PIXEL))
39 , m_xFtFillHoles(m_xBuilder->weld_label("tilesft"))
40 , m_xMtFillHoles(m_xBuilder->weld_metric_spin_button("tiles", FUNIT_PIXEL))
41 , m_xCbFillHoles(m_xBuilder->weld_check_button("fillholes"))
42 , m_xBmpWin(new weld::CustomWeld(*m_xBuilder, "source", m_aBmpWin))
43 , m_xMtfWin(new weld::CustomWeld(*m_xBuilder, "vectorized", m_aMtfWin))
44 , m_xPrgs(m_xBuilder->weld_progress_bar("progressbar"))
45 , m_xBtnOK(m_xBuilder->weld_button("ok"))
46 , m_xBtnPreview(m_xBuilder->weld_button("preview"))
48 const int nWidth = m_xFtFillHoles->get_approximate_digit_width() * 32;
49 const int nHeight = m_xFtFillHoles->get_text_height() * 16;
50 m_xBmpWin->set_size_request(nWidth, nHeight);
51 m_xMtfWin->set_size_request(nWidth, nHeight);
53 m_xBtnPreview->connect_clicked( LINK( this, SdVectorizeDlg, ClickPreviewHdl ) );
54 m_xBtnOK->connect_clicked( LINK( this, SdVectorizeDlg, ClickOKHdl ) );
55 m_xNmLayers->connect_value_changed( LINK( this, SdVectorizeDlg, ModifyHdl ) );
56 m_xMtReduce->connect_value_changed( LINK( this, SdVectorizeDlg, MetricModifyHdl ) );
57 m_xMtFillHoles->connect_value_changed( LINK( this, SdVectorizeDlg, MetricModifyHdl ) );
58 m_xCbFillHoles->connect_toggled( LINK( this, SdVectorizeDlg, ToggleHdl ) );
60 LoadSettings();
61 InitPreviewBmp();
64 SdVectorizeDlg::~SdVectorizeDlg()
68 ::tools::Rectangle SdVectorizeDlg::GetRect( const Size& rDispSize, const Size& rBmpSize )
70 ::tools::Rectangle aRect;
72 if( rBmpSize.Width() && rBmpSize.Height() && rDispSize.Width() && rDispSize.Height() )
74 Size aBmpSize( rBmpSize );
75 const double fGrfWH = static_cast<double>(aBmpSize.Width()) / aBmpSize.Height();
76 const double fWinWH = static_cast<double>(rDispSize.Width()) / rDispSize.Height();
78 if( fGrfWH < fWinWH )
80 aBmpSize.setWidth( static_cast<long>( rDispSize.Height() * fGrfWH ) );
81 aBmpSize.setHeight( rDispSize.Height() );
83 else
85 aBmpSize.setWidth( rDispSize.Width() );
86 aBmpSize.setHeight( static_cast<long>( rDispSize.Width() / fGrfWH) );
89 const Point aBmpPos( ( rDispSize.Width() - aBmpSize.Width() ) >> 1,
90 ( rDispSize.Height() - aBmpSize.Height() ) >> 1 );
92 aRect = ::tools::Rectangle( aBmpPos, aBmpSize );
95 return aRect;
98 void SdVectorizeDlg::InitPreviewBmp()
100 const ::tools::Rectangle aRect( GetRect( m_aBmpWin.GetOutputSizePixel(), aBmp.GetSizePixel() ) );
102 aPreviewBmp = aBmp;
103 aPreviewBmp.Scale( aRect.GetSize() );
104 m_aBmpWin.SetGraphic( aPreviewBmp );
107 Bitmap SdVectorizeDlg::GetPreparedBitmap( Bitmap const & rBmp, Fraction& rScale )
109 Bitmap aNew( rBmp );
110 const Size aSizePix( aNew.GetSizePixel() );
112 if( aSizePix.Width() > VECTORIZE_MAX_EXTENT || aSizePix.Height() > VECTORIZE_MAX_EXTENT )
114 const ::tools::Rectangle aRect( GetRect( Size( VECTORIZE_MAX_EXTENT, VECTORIZE_MAX_EXTENT ), aSizePix ) );
115 rScale = Fraction( aSizePix.Width(), aRect.GetWidth() );
116 aNew.Scale( aRect.GetSize() );
118 else
119 rScale = Fraction( 1, 1 );
121 BitmapEx aNewBmpEx(aNew);
122 BitmapFilter::Filter(aNewBmpEx, BitmapSimpleColorQuantizationFilter(m_xNmLayers->get_value()));
123 aNew = aNewBmpEx.GetBitmap();
125 return aNew;
128 void SdVectorizeDlg::Calculate( Bitmap const & rBmp, GDIMetaFile& rMtf )
130 m_pDocSh->SetWaitCursor( true );
131 m_xPrgs->set_percentage(0);
133 Fraction aScale;
134 Bitmap aTmp( GetPreparedBitmap( rBmp, aScale ) );
136 if( !!aTmp )
138 const Link<long,void> aPrgsHdl( LINK( this, SdVectorizeDlg, ProgressHdl ) );
139 aTmp.Vectorize( rMtf, static_cast<sal_uInt8>(m_xMtReduce->get_value(FUNIT_NONE)), &aPrgsHdl );
141 if (m_xCbFillHoles->get_active())
143 GDIMetaFile aNewMtf;
144 Bitmap::ScopedReadAccess pRAcc(aTmp);
146 if( pRAcc )
148 const long nWidth = pRAcc->Width();
149 const long nHeight = pRAcc->Height();
150 const long nTileX = m_xMtFillHoles->get_value(FUNIT_NONE);
151 const long nTileY = m_xMtFillHoles->get_value(FUNIT_NONE);
152 assert(nTileX && "div-by-zero");
153 const long nCountX = nWidth / nTileX;
154 assert(nTileY && "div-by-zero");
155 const long nCountY = nHeight / nTileY;
156 const long nRestX = nWidth % nTileX;
157 const long nRestY = nHeight % nTileY;
159 MapMode aMap( rMtf.GetPrefMapMode() );
160 aNewMtf.SetPrefSize( rMtf.GetPrefSize() );
161 aNewMtf.SetPrefMapMode( aMap );
163 for( long nTY = 0; nTY < nCountY; nTY++ )
165 const long nY = nTY * nTileY;
167 for( long nTX = 0; nTX < nCountX; nTX++ )
168 AddTile( pRAcc.get(), aNewMtf, nTX * nTileX, nTY * nTileY, nTileX, nTileY );
170 if( nRestX )
171 AddTile( pRAcc.get(), aNewMtf, nCountX * nTileX, nY, nRestX, nTileY );
174 if( nRestY )
176 const long nY = nCountY * nTileY;
178 for( long nTX = 0; nTX < nCountX; nTX++ )
179 AddTile( pRAcc.get(), aNewMtf, nTX * nTileX, nY, nTileX, nRestY );
181 if( nRestX )
182 AddTile( pRAcc.get(), aNewMtf, nCountX * nTileX, nCountY * nTileY, nRestX, nRestY );
185 pRAcc.reset();
187 for( size_t n = 0, nCount = rMtf.GetActionSize(); n < nCount; n++ )
188 aNewMtf.AddAction( rMtf.GetAction( n )->Clone() );
190 aMap.SetScaleX( aMap.GetScaleX() * aScale );
191 aMap.SetScaleY( aMap.GetScaleY() * aScale );
192 aNewMtf.SetPrefMapMode( aMap );
193 rMtf = aNewMtf;
198 m_xPrgs->set_percentage(0);
199 m_pDocSh->SetWaitCursor( false );
202 void SdVectorizeDlg::AddTile( BitmapReadAccess const * pRAcc, GDIMetaFile& rMtf,
203 long nPosX, long nPosY, long nWidth, long nHeight )
205 sal_uLong nSumR = 0, nSumG = 0, nSumB = 0;
206 const long nRight = nPosX + nWidth - 1;
207 const long nBottom = nPosY + nHeight - 1;
208 const double fMult = 1.0 / ( nWidth * nHeight );
210 for( long nY = nPosY; nY <= nBottom; nY++ )
212 for( long nX = nPosX; nX <= nRight; nX++ )
214 const BitmapColor aPixel( pRAcc->GetColor( nY, nX ) );
216 nSumR += aPixel.GetRed();
217 nSumG += aPixel.GetGreen();
218 nSumB += aPixel.GetBlue();
222 const Color aColor( static_cast<sal_uInt8>(FRound( nSumR * fMult )),
223 static_cast<sal_uInt8>(FRound( nSumG * fMult )),
224 static_cast<sal_uInt8>(FRound( nSumB * fMult )) );
226 ::tools::Rectangle aRect( Point( nPosX, nPosY ), Size( nWidth + 1, nHeight + 1 ) );
227 const Size& rMaxSize = rMtf.GetPrefSize();
229 aRect = Application::GetDefaultDevice()->PixelToLogic(aRect, rMtf.GetPrefMapMode());
231 if( aRect.Right() > ( rMaxSize.Width() - 1 ) )
232 aRect.SetRight( rMaxSize.Width() - 1 );
234 if( aRect.Bottom() > ( rMaxSize.Height() - 1 ) )
235 aRect.SetBottom( rMaxSize.Height() - 1 );
237 rMtf.AddAction( new MetaLineColorAction( aColor, true ) );
238 rMtf.AddAction( new MetaFillColorAction( aColor, true ) );
239 rMtf.AddAction( new MetaRectAction( aRect ) );
242 IMPL_LINK( SdVectorizeDlg, ProgressHdl, long, nData, void )
244 m_xPrgs->set_percentage(nData);
247 IMPL_LINK_NOARG(SdVectorizeDlg, ClickPreviewHdl, weld::Button&, void)
249 Calculate( aBmp, aMtf );
250 m_aMtfWin.SetGraphic( aMtf );
251 m_xBtnPreview->set_sensitive(false);
254 IMPL_LINK_NOARG(SdVectorizeDlg, ClickOKHdl, weld::Button&, void)
256 if (m_xBtnPreview->get_sensitive())
257 Calculate( aBmp, aMtf );
259 SaveSettings();
260 m_xDialog->response(RET_OK);
263 IMPL_LINK( SdVectorizeDlg, ToggleHdl, weld::ToggleButton&, rCb, void )
265 if (rCb.get_active())
267 m_xFtFillHoles->set_sensitive(true);
268 m_xMtFillHoles->set_sensitive(true);
270 else
272 m_xFtFillHoles->set_sensitive(false);
273 m_xMtFillHoles->set_sensitive(false);
276 m_xBtnPreview->set_sensitive(true);
279 IMPL_LINK_NOARG(SdVectorizeDlg, ModifyHdl, weld::SpinButton&, void)
281 m_xBtnPreview->set_sensitive(true);
284 IMPL_LINK_NOARG(SdVectorizeDlg, MetricModifyHdl, weld::MetricSpinButton&, void)
286 m_xBtnPreview->set_sensitive(true);
289 void SdVectorizeDlg::LoadSettings()
291 tools::SvRef<SotStorageStream> xIStm( SD_MOD()->GetOptionStream(
292 SD_OPTION_VECTORIZE ,
293 SD_OPTION_LOAD ) );
294 sal_uInt16 nLayers;
295 sal_uInt16 nReduce;
296 sal_uInt16 nFillHoles;
297 bool bFillHoles;
299 if( xIStm.is() )
301 SdIOCompat aCompat( *xIStm, StreamMode::READ );
302 xIStm->ReadUInt16( nLayers ).ReadUInt16( nReduce ).ReadUInt16( nFillHoles ).ReadCharAsBool( bFillHoles );
304 else
306 nLayers = 8;
307 nReduce = 0;
308 nFillHoles = 32;
309 bFillHoles = false;
312 m_xNmLayers->set_value(nLayers);
313 m_xMtReduce->set_value(nReduce, FUNIT_NONE);
314 m_xMtFillHoles->set_value(nFillHoles, FUNIT_NONE);
315 m_xCbFillHoles->set_active(bFillHoles);
317 ToggleHdl(*m_xCbFillHoles);
320 void SdVectorizeDlg::SaveSettings() const
322 tools::SvRef<SotStorageStream> xOStm( SD_MOD()->GetOptionStream(
323 SD_OPTION_VECTORIZE ,
324 SD_OPTION_STORE ) );
326 if( xOStm.is() )
328 SdIOCompat aCompat( *xOStm, StreamMode::WRITE, 1 );
329 xOStm->WriteUInt16( m_xNmLayers->get_value() ).WriteUInt16(m_xMtReduce->get_value(FUNIT_NONE));
330 xOStm->WriteUInt16( m_xMtFillHoles->get_value(FUNIT_NONE) ).WriteBool(m_xCbFillHoles->get_active());
334 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */