LibreOffice Module sd (master) 1
vectdlg.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20#include <vcl/vclenum.hxx>
22#include <vcl/metaact.hxx>
24#include <vcl/svapp.hxx>
25
26#include <DrawDocShell.hxx>
27#include <sdmod.hxx>
28#include <sdiocmpt.hxx>
29#include <vectdlg.hxx>
30
31#define VECTORIZE_MAX_EXTENT 512
32
34 : GenericDialogController(pParent, "modules/sdraw/ui/vectorize.ui", "VectorizeDialog")
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("colors"))
40 , m_xMtReduce(m_xBuilder->weld_metric_spin_button("points", FieldUnit::PIXEL))
41 , m_xFtFillHoles(m_xBuilder->weld_label("tilesft"))
42 , m_xMtFillHoles(m_xBuilder->weld_metric_spin_button("tiles", FieldUnit::PIXEL))
43 , m_xCbFillHoles(m_xBuilder->weld_check_button("fillholes"))
44 , m_xBmpWin(new weld::CustomWeld(*m_xBuilder, "source", m_aBmpWin))
45 , m_xMtfWin(new weld::CustomWeld(*m_xBuilder, "vectorized", m_aMtfWin))
46 , m_xPrgs(m_xBuilder->weld_progress_bar("progressbar"))
47 , m_xBtnOK(m_xBuilder->weld_button("ok"))
48 , m_xBtnPreview(m_xBuilder->weld_button("preview"))
49{
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);
54
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 ) );
61
64}
65
67{
68}
69
70::tools::Rectangle SdVectorizeDlg::GetRect( const Size& rDispSize, const Size& rBmpSize )
71{
73
74 if( rBmpSize.Width() && rBmpSize.Height() && rDispSize.Width() && rDispSize.Height() )
75 {
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();
79
80 if( fGrfWH < fWinWH )
81 {
82 aBmpSize.setWidth( static_cast<tools::Long>( rDispSize.Height() * fGrfWH ) );
83 aBmpSize.setHeight( rDispSize.Height() );
84 }
85 else
86 {
87 aBmpSize.setWidth( rDispSize.Width() );
88 aBmpSize.setHeight( static_cast<tools::Long>( rDispSize.Width() / fGrfWH) );
89 }
90
91 const Point aBmpPos( ( rDispSize.Width() - aBmpSize.Width() ) >> 1,
92 ( rDispSize.Height() - aBmpSize.Height() ) >> 1 );
93
94 aRect = ::tools::Rectangle( aBmpPos, aBmpSize );
95 }
96
97 return aRect;
98}
99
101{
102 const ::tools::Rectangle aRect( GetRect( m_aBmpWin.GetOutputSizePixel(), aBmp.GetSizePixel() ) );
103
105 aPreviewBmp.Scale( aRect.GetSize() );
107}
108
110{
111 Bitmap aNew( rBmp );
112 const Size aSizePix( aNew.GetSizePixel() );
113
114 if( aSizePix.Width() > VECTORIZE_MAX_EXTENT || aSizePix.Height() > VECTORIZE_MAX_EXTENT )
115 {
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() );
119 }
120 else
121 rScale = Fraction( 1, 1 );
122
123 BitmapEx aNewBmpEx(aNew);
125 aNew = aNewBmpEx.GetBitmap();
126
127 return aNew;
128}
129
131{
132 m_pDocSh->SetWaitCursor( true );
133 m_xPrgs->set_percentage(0);
134
135 Fraction aScale;
136 Bitmap aTmp( GetPreparedBitmap( rBmp, aScale ) );
137
138 if( !aTmp.IsEmpty() )
139 {
140 const Link<::tools::Long,void> aPrgsHdl( LINK( this, SdVectorizeDlg, ProgressHdl ) );
141 aTmp.Vectorize( rMtf, static_cast<sal_uInt8>(m_xMtReduce->get_value(FieldUnit::NONE)), &aPrgsHdl );
142
143 if (m_xCbFillHoles->get_active())
144 {
145 GDIMetaFile aNewMtf;
146 Bitmap::ScopedReadAccess pRAcc(aTmp);
147
148 if( pRAcc )
149 {
150 const tools::Long nWidth = pRAcc->Width();
151 const tools::Long nHeight = pRAcc->Height();
152 const tools::Long nTileX = m_xMtFillHoles->get_value(FieldUnit::NONE);
153 const tools::Long nTileY = m_xMtFillHoles->get_value(FieldUnit::NONE);
154 assert(nTileX && "div-by-zero");
155 const tools::Long nCountX = nWidth / nTileX;
156 assert(nTileY && "div-by-zero");
157 const tools::Long nCountY = nHeight / nTileY;
158 const tools::Long nRestX = nWidth % nTileX;
159 const tools::Long nRestY = nHeight % nTileY;
160
161 MapMode aMap( rMtf.GetPrefMapMode() );
162 aNewMtf.SetPrefSize( rMtf.GetPrefSize() );
163 aNewMtf.SetPrefMapMode( aMap );
164
165 for( tools::Long nTY = 0; nTY < nCountY; nTY++ )
166 {
167 const tools::Long nY = nTY * nTileY;
168
169 for( tools::Long nTX = 0; nTX < nCountX; nTX++ )
170 AddTile( pRAcc.get(), aNewMtf, nTX * nTileX, nTY * nTileY, nTileX, nTileY );
171
172 if( nRestX )
173 AddTile( pRAcc.get(), aNewMtf, nCountX * nTileX, nY, nRestX, nTileY );
174 }
175
176 if( nRestY )
177 {
178 const tools::Long nY = nCountY * nTileY;
179
180 for( tools::Long nTX = 0; nTX < nCountX; nTX++ )
181 AddTile( pRAcc.get(), aNewMtf, nTX * nTileX, nY, nTileX, nRestY );
182
183 if( nRestX )
184 AddTile( pRAcc.get(), aNewMtf, nCountX * nTileX, nCountY * nTileY, nRestX, nRestY );
185 }
186
187 pRAcc.reset();
188
189 for( size_t n = 0, nCount = rMtf.GetActionSize(); n < nCount; n++ )
190 aNewMtf.AddAction( rMtf.GetAction( n )->Clone() );
191
192 aMap.SetScaleX( aMap.GetScaleX() * aScale );
193 aMap.SetScaleY( aMap.GetScaleY() * aScale );
194 aNewMtf.SetPrefMapMode( aMap );
195 rMtf = aNewMtf;
196 }
197 }
198 }
199
200 m_xPrgs->set_percentage(0);
201 m_pDocSh->SetWaitCursor( false );
202}
203
205 tools::Long nPosX, tools::Long nPosY, tools::Long nWidth, tools::Long nHeight )
206{
207 sal_uLong nSumR = 0, nSumG = 0, nSumB = 0;
208 const tools::Long nRight = nPosX + nWidth - 1;
209 const tools::Long nBottom = nPosY + nHeight - 1;
210 const double fMult = 1.0 / ( nWidth * nHeight );
211
212 for( tools::Long nY = nPosY; nY <= nBottom; nY++ )
213 {
214 for( tools::Long nX = nPosX; nX <= nRight; nX++ )
215 {
216 const BitmapColor aPixel( pRAcc->GetColor( nY, nX ) );
217
218 nSumR += aPixel.GetRed();
219 nSumG += aPixel.GetGreen();
220 nSumB += aPixel.GetBlue();
221 }
222 }
223
224 const Color aColor( static_cast<sal_uInt8>(FRound( nSumR * fMult )),
225 static_cast<sal_uInt8>(FRound( nSumG * fMult )),
226 static_cast<sal_uInt8>(FRound( nSumB * fMult )) );
227
228 ::tools::Rectangle aRect( Point( nPosX, nPosY ), Size( nWidth + 1, nHeight + 1 ) );
229 const Size& rMaxSize = rMtf.GetPrefSize();
230
232
233 if( aRect.Right() > ( rMaxSize.Width() - 1 ) )
234 aRect.SetRight( rMaxSize.Width() - 1 );
235
236 if( aRect.Bottom() > ( rMaxSize.Height() - 1 ) )
237 aRect.SetBottom( rMaxSize.Height() - 1 );
238
239 rMtf.AddAction( new MetaLineColorAction( aColor, true ) );
240 rMtf.AddAction( new MetaFillColorAction( aColor, true ) );
241 rMtf.AddAction( new MetaRectAction( aRect ) );
242}
243
244IMPL_LINK( SdVectorizeDlg, ProgressHdl, tools::Long, nData, void )
245{
246 m_xPrgs->set_percentage(nData);
247}
248
250{
251 Calculate( aBmp, aMtf );
252 m_aMtfWin.SetGraphic( aMtf );
253 m_xBtnPreview->set_sensitive(false);
254}
255
257{
258 if (m_xBtnPreview->get_sensitive())
259 Calculate( aBmp, aMtf );
260
261 SaveSettings();
262 m_xDialog->response(RET_OK);
263}
264
265IMPL_LINK( SdVectorizeDlg, ToggleHdl, weld::Toggleable&, rCb, void )
266{
267 if (rCb.get_active())
268 {
269 m_xFtFillHoles->set_sensitive(true);
270 m_xMtFillHoles->set_sensitive(true);
271 }
272 else
273 {
274 m_xFtFillHoles->set_sensitive(false);
275 m_xMtFillHoles->set_sensitive(false);
276 }
277
278 m_xBtnPreview->set_sensitive(true);
279}
280
282{
283 m_xBtnPreview->set_sensitive(true);
284}
285
287{
288 m_xBtnPreview->set_sensitive(true);
289}
290
292{
293 tools::SvRef<SotStorageStream> xIStm( SD_MOD()->GetOptionStream(
296 sal_uInt16 nLayers;
297 sal_uInt16 nReduce;
298 sal_uInt16 nFillHoles;
299 bool bFillHoles;
300
301 if( xIStm.is() )
302 {
303 SdIOCompat aCompat( *xIStm, StreamMode::READ );
304 xIStm->ReadUInt16( nLayers ).ReadUInt16( nReduce ).ReadUInt16( nFillHoles ).ReadCharAsBool( bFillHoles );
305 }
306 else
307 {
308 nLayers = 8;
309 nReduce = 0;
310 nFillHoles = 32;
311 bFillHoles = false;
312 }
313
314 m_xNmLayers->set_value(nLayers);
315 m_xMtReduce->set_value(nReduce, FieldUnit::NONE);
316 m_xMtFillHoles->set_value(nFillHoles, FieldUnit::NONE);
317 m_xCbFillHoles->set_active(bFillHoles);
318
319 ToggleHdl(*m_xCbFillHoles);
320}
321
323{
324 tools::SvRef<SotStorageStream> xOStm( SD_MOD()->GetOptionStream(
327
328 if( xOStm.is() )
329 {
330 SdIOCompat aCompat( *xOStm, StreamMode::WRITE, 1 );
331 xOStm->WriteUInt16( m_xNmLayers->get_value() ).WriteUInt16(m_xMtReduce->get_value(FieldUnit::NONE));
332 xOStm->WriteUInt16( m_xMtFillHoles->get_value(FieldUnit::NONE) ).WriteBool(m_xCbFillHoles->get_active());
333 }
334}
335
336/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Reference< XExecutableDialog > m_xDialog
static OutputDevice * GetDefaultDevice()
Bitmap GetBitmap(Color aTransparentReplaceColor) const
static bool Filter(BitmapEx &rBmpEx, BitmapFilter const &rFilter)
BitmapColor GetColor(tools::Long nY, tools::Long nX) const
Size GetSizePixel() const
bool Scale(const Size &rNewSize, BmpScaleFlag nScaleFlag=BmpScaleFlag::Default)
bool IsEmpty() const
void Vectorize(GDIMetaFile &rMtf, sal_uInt8 cReduce, const Link< tools::Long, void > *pProgress)
size_t GetActionSize() const
const Size & GetPrefSize() const
MetaAction * GetAction(size_t nAction) const
void AddAction(const rtl::Reference< MetaAction > &pAction)
void SetPrefMapMode(const MapMode &rMapMode)
const MapMode & GetPrefMapMode() const
void SetPrefSize(const Size &rSize)
void SetGraphic(const Graphic &rGraphic, bool bNewModel=true)
virtual rtl::Reference< MetaAction > Clone() const
SAL_WARN_UNUSED_RESULT Point PixelToLogic(const Point &rDevicePt) const
void InitPreviewBmp()
Definition: vectdlg.cxx:100
void SaveSettings() const
Definition: vectdlg.cxx:322
std::unique_ptr< weld::SpinButton > m_xNmLayers
Definition: vectdlg.hxx:45
Bitmap GetPreparedBitmap(Bitmap const &rBmp, Fraction &rScale)
Definition: vectdlg.cxx:109
Bitmap aPreviewBmp
Definition: vectdlg.hxx:39
std::unique_ptr< weld::CustomWeld > m_xBmpWin
Definition: vectdlg.hxx:50
virtual ~SdVectorizeDlg() override
Definition: vectdlg.cxx:66
static void AddTile(BitmapReadAccess const *pRAcc, GDIMetaFile &rMtf, tools::Long nPosX, tools::Long nPosY, tools::Long nWidth, tools::Long nHeight)
Definition: vectdlg.cxx:204
GraphCtrl m_aBmpWin
Definition: vectdlg.hxx:42
std::unique_ptr< weld::ProgressBar > m_xPrgs
Definition: vectdlg.hxx:52
std::unique_ptr< weld::CheckButton > m_xCbFillHoles
Definition: vectdlg.hxx:49
void LoadSettings()
Definition: vectdlg.cxx:291
::tools::Rectangle GetRect(const Size &rDispSize, const Size &rBmpSize)
Definition: vectdlg.cxx:70
std::unique_ptr< weld::MetricSpinButton > m_xMtReduce
Definition: vectdlg.hxx:46
void Calculate(Bitmap const &rBmp, GDIMetaFile &rMtf)
Definition: vectdlg.cxx:130
std::unique_ptr< weld::Button > m_xBtnPreview
Definition: vectdlg.hxx:54
::sd::DrawDocShell * m_pDocSh
Definition: vectdlg.hxx:37
Bitmap aBmp
Definition: vectdlg.hxx:38
SdVectorizeDlg(weld::Window *pParent, const Bitmap &rBmp, ::sd::DrawDocShell *pDocShell)
Definition: vectdlg.cxx:33
std::unique_ptr< weld::Button > m_xBtnOK
Definition: vectdlg.hxx:53
std::unique_ptr< weld::Label > m_xFtFillHoles
Definition: vectdlg.hxx:47
std::unique_ptr< weld::MetricSpinButton > m_xMtFillHoles
Definition: vectdlg.hxx:48
std::unique_ptr< weld::CustomWeld > m_xMtfWin
Definition: vectdlg.hxx:51
void SetWaitCursor(bool bSet) const
constexpr tools::Long Height() const
void setWidth(tools::Long nWidth)
void setHeight(tools::Long nHeight)
constexpr tools::Long Width() const
constexpr void SetRight(tools::Long v)
constexpr tools::Long Right() const
constexpr void SetBottom(tools::Long v)
constexpr tools::Long Bottom() const
bool is() const
int nCount
FieldUnit
#define SD_OPTION_VECTORIZE
Definition: glob.hxx:53
tools::Long FRound(double fVal)
sal_Int64 n
css::uno::Reference< css::linguistic2::XProofreadingIterator > get(css::uno::Reference< css::uno::XComponentContext > const &context)
long Long
HashMap_OWString_Interface aMap
#define SD_MOD()
Definition: sdmod.hxx:184
sal_uIntPtr sal_uLong
unsigned char sal_uInt8
RET_OK
IMPL_LINK_NOARG(SdVectorizeDlg, ClickPreviewHdl, weld::Button &, void)
Definition: vectdlg.cxx:249
IMPL_LINK(SdVectorizeDlg, ProgressHdl, tools::Long, nData, void)
Definition: vectdlg.cxx:244
#define VECTORIZE_MAX_EXTENT
Definition: vectdlg.cxx:31