tdf#154285 Check upper bound of arguments in SbRtl_Minute function
[LibreOffice.git] / sd / source / ui / dlg / vectdlg.cxx
blob3d378b7c8384c4fd8ed5f3435adebe5b6d618885
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 <officecfg/Office/Common.hxx>
21 #include <vcl/vclenum.hxx>
22 #include <vcl/BitmapReadAccess.hxx>
23 #include <vcl/bitmap/BitmapSimpleColorQuantizationFilter.hxx>
24 #include <vcl/bitmap/Vectorizer.hxx>
25 #include <vcl/metaact.hxx>
26 #include <vcl/svapp.hxx>
28 #include <DrawDocShell.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, u"modules/sdraw/ui/vectorize.ui"_ustr, u"VectorizeDialog"_ustr)
35 , m_pDocSh(pDocShell)
36 , aBmp(rBmp)
37 , m_aBmpWin(m_xDialog.get())
38 , m_aMtfWin(m_xDialog.get())
39 , m_xNmLayers(m_xBuilder->weld_spin_button(u"colors"_ustr))
40 , m_xMtReduce(m_xBuilder->weld_metric_spin_button(u"points"_ustr, FieldUnit::PIXEL))
41 , m_xFtFillHoles(m_xBuilder->weld_label(u"tilesft"_ustr))
42 , m_xMtFillHoles(m_xBuilder->weld_metric_spin_button(u"tiles"_ustr, FieldUnit::PIXEL))
43 , m_xCbFillHoles(m_xBuilder->weld_check_button(u"fillholes"_ustr))
44 , m_xBmpWin(new weld::CustomWeld(*m_xBuilder, u"source"_ustr, m_aBmpWin))
45 , m_xMtfWin(new weld::CustomWeld(*m_xBuilder, u"vectorized"_ustr, m_aMtfWin))
46 , m_xPrgs(m_xBuilder->weld_progress_bar(u"progressbar"_ustr))
47 , m_xBtnOK(m_xBuilder->weld_button(u"ok"_ustr))
48 , m_xBtnPreview(m_xBuilder->weld_button(u"preview"_ustr))
50 const int nWidth = m_xFtFillHoles->get_approximate_digit_width() * 32;
51 const int nHeight = m_xFtFillHoles->get_text_height() * 16;
52 m_xBmpWin->set_size_request(nWidth, nHeight);
53 m_xMtfWin->set_size_request(nWidth, nHeight);
55 m_xBtnPreview->connect_clicked( LINK( this, SdVectorizeDlg, ClickPreviewHdl ) );
56 m_xBtnOK->connect_clicked( LINK( this, SdVectorizeDlg, ClickOKHdl ) );
57 m_xNmLayers->connect_value_changed( LINK( this, SdVectorizeDlg, ModifyHdl ) );
58 m_xMtReduce->connect_value_changed( LINK( this, SdVectorizeDlg, MetricModifyHdl ) );
59 m_xMtFillHoles->connect_value_changed( LINK( this, SdVectorizeDlg, MetricModifyHdl ) );
60 m_xCbFillHoles->connect_toggled( LINK( this, SdVectorizeDlg, ToggleHdl ) );
62 LoadSettings();
63 InitPreviewBmp();
66 SdVectorizeDlg::~SdVectorizeDlg()
70 ::tools::Rectangle SdVectorizeDlg::GetRect( const Size& rDispSize, const Size& rBmpSize )
72 ::tools::Rectangle aRect;
74 if( rBmpSize.Width() && rBmpSize.Height() && rDispSize.Width() && rDispSize.Height() )
76 Size aBmpSize( rBmpSize );
77 const double fGrfWH = static_cast<double>(aBmpSize.Width()) / aBmpSize.Height();
78 const double fWinWH = static_cast<double>(rDispSize.Width()) / rDispSize.Height();
80 if( fGrfWH < fWinWH )
82 aBmpSize.setWidth( static_cast<tools::Long>( rDispSize.Height() * fGrfWH ) );
83 aBmpSize.setHeight( rDispSize.Height() );
85 else
87 aBmpSize.setWidth( rDispSize.Width() );
88 aBmpSize.setHeight( static_cast<tools::Long>( rDispSize.Width() / fGrfWH) );
91 const Point aBmpPos( ( rDispSize.Width() - aBmpSize.Width() ) >> 1,
92 ( rDispSize.Height() - aBmpSize.Height() ) >> 1 );
94 aRect = ::tools::Rectangle( aBmpPos, aBmpSize );
97 return aRect;
100 void SdVectorizeDlg::InitPreviewBmp()
102 const ::tools::Rectangle aRect( GetRect( m_aBmpWin.GetOutputSizePixel(), aBmp.GetSizePixel() ) );
104 aPreviewBmp = aBmp;
105 aPreviewBmp.Scale( aRect.GetSize() );
106 m_aBmpWin.SetGraphic(BitmapEx(aPreviewBmp));
109 Bitmap SdVectorizeDlg::GetPreparedBitmap( Bitmap const & rBmp, Fraction& rScale )
111 Bitmap aNew( rBmp );
112 const Size aSizePix( aNew.GetSizePixel() );
114 if( aSizePix.Width() > VECTORIZE_MAX_EXTENT || aSizePix.Height() > VECTORIZE_MAX_EXTENT )
116 const ::tools::Rectangle aRect( GetRect( Size( VECTORIZE_MAX_EXTENT, VECTORIZE_MAX_EXTENT ), aSizePix ) );
117 rScale = Fraction( aSizePix.Width(), aRect.GetWidth() );
118 aNew.Scale( aRect.GetSize() );
120 else
121 rScale = Fraction( 1, 1 );
123 BitmapEx aNewBmpEx(aNew);
124 BitmapFilter::Filter(aNewBmpEx, BitmapSimpleColorQuantizationFilter(m_xNmLayers->get_value()));
125 aNew = aNewBmpEx.GetBitmap();
127 return aNew;
130 void SdVectorizeDlg::Calculate( Bitmap const & rBmp, GDIMetaFile& rMtf )
132 m_pDocSh->SetWaitCursor( true );
133 m_xPrgs->set_percentage(0);
135 Fraction aScale;
136 BitmapEx aBitmapEx(GetPreparedBitmap(rBmp, aScale));
138 if (!aBitmapEx.IsEmpty())
140 const Link<::tools::Long,void> aPrgsHdl( LINK( this, SdVectorizeDlg, ProgressHdl ) );
141 sal_uInt8 nReduce = sal_uInt8(m_xMtReduce->get_value(FieldUnit::NONE));
142 vcl::Vectorizer aVecotrizer(nReduce);
143 aVecotrizer.vectorize(aBitmapEx, rMtf);
144 aVecotrizer.setProgressCallback(&aPrgsHdl);
146 if (m_xCbFillHoles->get_active())
148 GDIMetaFile aNewMtf;
149 BitmapScopedReadAccess pRAcc(aBitmapEx.GetBitmap());
151 if( pRAcc )
153 const tools::Long nWidth = pRAcc->Width();
154 const tools::Long nHeight = pRAcc->Height();
155 const tools::Long nTileX = m_xMtFillHoles->get_value(FieldUnit::NONE);
156 const tools::Long nTileY = m_xMtFillHoles->get_value(FieldUnit::NONE);
157 assert(nTileX && "div-by-zero");
158 const tools::Long nCountX = nWidth / nTileX;
159 assert(nTileY && "div-by-zero");
160 const tools::Long nCountY = nHeight / nTileY;
161 const tools::Long nRestX = nWidth % nTileX;
162 const tools::Long nRestY = nHeight % nTileY;
164 MapMode aMap( rMtf.GetPrefMapMode() );
165 aNewMtf.SetPrefSize( rMtf.GetPrefSize() );
166 aNewMtf.SetPrefMapMode( aMap );
168 for( tools::Long nTY = 0; nTY < nCountY; nTY++ )
170 const tools::Long nY = nTY * nTileY;
172 for( tools::Long nTX = 0; nTX < nCountX; nTX++ )
173 AddTile( pRAcc.get(), aNewMtf, nTX * nTileX, nTY * nTileY, nTileX, nTileY );
175 if( nRestX )
176 AddTile( pRAcc.get(), aNewMtf, nCountX * nTileX, nY, nRestX, nTileY );
179 if( nRestY )
181 const tools::Long nY = nCountY * nTileY;
183 for( tools::Long nTX = 0; nTX < nCountX; nTX++ )
184 AddTile( pRAcc.get(), aNewMtf, nTX * nTileX, nY, nTileX, nRestY );
186 if( nRestX )
187 AddTile( pRAcc.get(), aNewMtf, nCountX * nTileX, nCountY * nTileY, nRestX, nRestY );
190 pRAcc.reset();
192 for( size_t n = 0, nCount = rMtf.GetActionSize(); n < nCount; n++ )
193 aNewMtf.AddAction( rMtf.GetAction( n )->Clone() );
195 aMap.SetScaleX( aMap.GetScaleX() * aScale );
196 aMap.SetScaleY( aMap.GetScaleY() * aScale );
197 aNewMtf.SetPrefMapMode( aMap );
198 rMtf = aNewMtf;
203 m_xPrgs->set_percentage(0);
204 m_pDocSh->SetWaitCursor( false );
207 void SdVectorizeDlg::AddTile( BitmapReadAccess const * pRAcc, GDIMetaFile& rMtf,
208 tools::Long nPosX, tools::Long nPosY, tools::Long nWidth, tools::Long nHeight )
210 sal_uLong nSumR = 0, nSumG = 0, nSumB = 0;
211 const tools::Long nRight = nPosX + nWidth - 1;
212 const tools::Long nBottom = nPosY + nHeight - 1;
213 const double fMult = 1.0 / ( nWidth * nHeight );
215 for( tools::Long nY = nPosY; nY <= nBottom; nY++ )
217 for( tools::Long nX = nPosX; nX <= nRight; nX++ )
219 const BitmapColor aPixel( pRAcc->GetColor( nY, nX ) );
221 nSumR += aPixel.GetRed();
222 nSumG += aPixel.GetGreen();
223 nSumB += aPixel.GetBlue();
227 const Color aColor( basegfx::fround<sal_uInt8>( nSumR * fMult ),
228 basegfx::fround<sal_uInt8>( nSumG * fMult ),
229 basegfx::fround<sal_uInt8>( nSumB * fMult ) );
231 ::tools::Rectangle aRect( Point( nPosX, nPosY ), Size( nWidth + 1, nHeight + 1 ) );
232 const Size& rMaxSize = rMtf.GetPrefSize();
234 aRect = Application::GetDefaultDevice()->PixelToLogic(aRect, rMtf.GetPrefMapMode());
236 if( aRect.Right() > ( rMaxSize.Width() - 1 ) )
237 aRect.SetRight( rMaxSize.Width() - 1 );
239 if( aRect.Bottom() > ( rMaxSize.Height() - 1 ) )
240 aRect.SetBottom( rMaxSize.Height() - 1 );
242 rMtf.AddAction( new MetaLineColorAction( aColor, true ) );
243 rMtf.AddAction( new MetaFillColorAction( aColor, true ) );
244 rMtf.AddAction( new MetaRectAction( aRect ) );
247 IMPL_LINK( SdVectorizeDlg, ProgressHdl, tools::Long, nData, void )
249 m_xPrgs->set_percentage(nData);
252 IMPL_LINK_NOARG(SdVectorizeDlg, ClickPreviewHdl, weld::Button&, void)
254 Calculate( aBmp, aMtf );
255 m_aMtfWin.SetGraphic( aMtf );
256 m_xBtnPreview->set_sensitive(false);
259 IMPL_LINK_NOARG(SdVectorizeDlg, ClickOKHdl, weld::Button&, void)
261 if (m_xBtnPreview->get_sensitive())
262 Calculate( aBmp, aMtf );
264 SaveSettings();
265 m_xDialog->response(RET_OK);
268 IMPL_LINK( SdVectorizeDlg, ToggleHdl, weld::Toggleable&, rCb, void )
270 if (rCb.get_active())
272 m_xFtFillHoles->set_sensitive(true);
273 m_xMtFillHoles->set_sensitive(true);
275 else
277 m_xFtFillHoles->set_sensitive(false);
278 m_xMtFillHoles->set_sensitive(false);
281 m_xBtnPreview->set_sensitive(true);
284 IMPL_LINK_NOARG(SdVectorizeDlg, ModifyHdl, weld::SpinButton&, void)
286 m_xBtnPreview->set_sensitive(true);
289 IMPL_LINK_NOARG(SdVectorizeDlg, MetricModifyHdl, weld::MetricSpinButton&, void)
291 m_xBtnPreview->set_sensitive(true);
294 void SdVectorizeDlg::LoadSettings()
296 m_xNmLayers->set_value(officecfg::Office::Common::Vectorize::ColorCount::get());
297 m_xMtReduce->set_value(officecfg::Office::Common::Vectorize::PointReduce::get(), FieldUnit::NONE);
298 m_xCbFillHoles->set_active(officecfg::Office::Common::Vectorize::FillHole::get());
299 m_xMtFillHoles->set_value(officecfg::Office::Common::Vectorize::TileExtent::get(), FieldUnit::NONE);
301 ToggleHdl(*m_xCbFillHoles);
304 void SdVectorizeDlg::SaveSettings() const
306 std::shared_ptr<comphelper::ConfigurationChanges> batch(
307 comphelper::ConfigurationChanges::create());
308 officecfg::Office::Common::Vectorize::ColorCount::set(m_xNmLayers->get_value(),batch);
309 officecfg::Office::Common::Vectorize::PointReduce::set(m_xMtReduce->get_value(FieldUnit::NONE),batch);
310 officecfg::Office::Common::Vectorize::FillHole::set(m_xCbFillHoles->get_active(),batch);
311 officecfg::Office::Common::Vectorize::TileExtent::set(m_xMtFillHoles->get_value(FieldUnit::NONE),batch);
312 batch->commit();
315 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */