xref: /trunk/main/sd/source/ui/dlg/vectdlg.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sd.hxx"
30 
31 #ifdef SD_DLLIMPLEMENTATION
32 #undef SD_DLLIMPLEMENTATION
33 #endif
34 #include <vcl/vclenum.hxx>
35 #include <vcl/wrkwin.hxx>
36 
37 #include "strings.hrc"
38 #include "sdresid.hxx"
39 #include "DrawDocShell.hxx"
40 #include "sdmod.hxx"
41 #include "sdiocmpt.hxx"
42 #include "DrawDocShell.hxx"
43 #include "vectdlg.hxx"
44 #include "vectdlg.hrc"
45 #include <tools/config.hxx>
46 #include <vcl/bmpacc.hxx>
47 #include <vcl/msgbox.hxx>
48 #include <vcl/metaact.hxx>
49 
50 // -----------
51 // - Defines -
52 // -----------
53 
54 #define VECTORIZE_MAX_EXTENT 512
55 
56 // ------------------
57 // - SdVectorizeDlg -
58 // ------------------
59 
60 SdVectorizeDlg::SdVectorizeDlg(
61     Window* pParent, const Bitmap& rBmp, ::sd::DrawDocShell* pDocShell ) :
62         ModalDialog     ( pParent, SdResId( DLG_VECTORIZE ) ),
63         mpDocSh          ( pDocShell ),
64         aGrpSettings    ( this, SdResId( GRP_SETTINGS ) ),
65         aFtLayers       ( this, SdResId( FT_LAYERS ) ),
66         aNmLayers       ( this, SdResId( NM_LAYERS ) ),
67         aFtReduce       ( this, SdResId( FT_REDUCE ) ),
68         aMtReduce       ( this, SdResId( MT_REDUCE ) ),
69         aFtFillHoles    ( this, SdResId( FT_FILLHOLES ) ),
70         aMtFillHoles    ( this, SdResId( MT_FILLHOLES ) ),
71         aCbFillHoles    ( this, SdResId( CB_FILLHOLES ) ),
72         aFtOriginal     ( this, SdResId( FT_ORIGINAL ) ),
73         aBmpWin         ( this, SdResId( CTL_BMP ) ),
74         aFtVectorized   ( this, SdResId( FT_VECTORIZED ) ),
75         aMtfWin         ( this, SdResId( CTL_WMF ) ),
76         aGrpPrgs        ( this, SdResId( GRP_PRGS ) ),
77         aPrgs           ( this, SdResId( WND_PRGS ) ),
78         aBtnOK          ( this, SdResId( BTN_OK ) ),
79         aBtnCancel      ( this, SdResId( BTN_CANCEL ) ),
80         aBtnHelp        ( this, SdResId( BTN_HELP ) ),
81         aBtnPreview     ( this, SdResId( BTN_PREVIEW ) ),
82         aBmp            ( rBmp )
83 {
84     FreeResource();
85 
86     aBtnPreview.SetClickHdl( LINK( this, SdVectorizeDlg, ClickPreviewHdl ) );
87     aBtnOK.SetClickHdl( LINK( this, SdVectorizeDlg, ClickOKHdl ) );
88     aNmLayers.SetModifyHdl( LINK( this, SdVectorizeDlg, ModifyHdl ) );
89     aMtReduce.SetModifyHdl( LINK( this, SdVectorizeDlg, ModifyHdl ) );
90     aMtFillHoles.SetModifyHdl( LINK( this, SdVectorizeDlg, ModifyHdl ) );
91     aCbFillHoles.SetToggleHdl( LINK( this, SdVectorizeDlg, ToggleHdl ) );
92 
93     // disable 3D border
94     aBmpWin.SetBorderStyle(WINDOW_BORDER_MONO);
95     aMtfWin.SetBorderStyle(WINDOW_BORDER_MONO);
96 
97     LoadSettings();
98     InitPreviewBmp();
99 }
100 
101 // -----------------------------------------------------------------------------
102 
103 SdVectorizeDlg::~SdVectorizeDlg()
104 {
105 }
106 
107 // -----------------------------------------------------------------------------
108 
109 Rectangle SdVectorizeDlg::GetRect( const Size& rDispSize, const Size& rBmpSize ) const
110 {
111     Rectangle aRect;
112 
113     if( rBmpSize.Width() && rBmpSize.Height() && rDispSize.Width() && rDispSize.Height() )
114     {
115         Size         aBmpSize( rBmpSize );
116         const double fGrfWH = (double) aBmpSize.Width() / aBmpSize.Height();
117         const double fWinWH = (double) rDispSize.Width() / rDispSize.Height();
118 
119         if( fGrfWH < fWinWH )
120         {
121             aBmpSize.Width() = (long) ( rDispSize.Height() * fGrfWH );
122             aBmpSize.Height()= rDispSize.Height();
123         }
124         else
125         {
126             aBmpSize.Width() = rDispSize.Width();
127             aBmpSize.Height()= (long) ( rDispSize.Width() / fGrfWH);
128         }
129 
130         const Point aBmpPos( ( rDispSize.Width()  - aBmpSize.Width() ) >> 1,
131                              ( rDispSize.Height() - aBmpSize.Height() ) >> 1 );
132 
133         aRect = Rectangle( aBmpPos, aBmpSize );
134     }
135 
136     return aRect;
137 }
138 
139 // -----------------------------------------------------------------------------
140 
141 void SdVectorizeDlg::InitPreviewBmp()
142 {
143     const Rectangle aRect( GetRect( aBmpWin.GetSizePixel(), aBmp.GetSizePixel() ) );
144 
145     aPreviewBmp = aBmp;
146     aPreviewBmp.Scale( aRect.GetSize() );
147     aBmpWin.SetGraphic( aPreviewBmp );
148 }
149 
150 // -----------------------------------------------------------------------------
151 
152 Bitmap SdVectorizeDlg::GetPreparedBitmap( Bitmap& rBmp, Fraction& rScale )
153 {
154     Bitmap      aNew( rBmp );
155     const Size  aSizePix( aNew.GetSizePixel() );
156 
157     if( aSizePix.Width() > VECTORIZE_MAX_EXTENT || aSizePix.Height() > VECTORIZE_MAX_EXTENT )
158     {
159         const Rectangle aRect( GetRect( Size( VECTORIZE_MAX_EXTENT, VECTORIZE_MAX_EXTENT ), aSizePix ) );
160         rScale = Fraction( aSizePix.Width(), aRect.GetWidth() );
161         aNew.Scale( aRect.GetSize() );
162     }
163     else
164         rScale = Fraction( 1, 1 );
165 
166     aNew.ReduceColors( (sal_uInt16) aNmLayers.GetValue(), BMP_REDUCE_SIMPLE );
167 
168     return aNew;
169 }
170 
171 // -----------------------------------------------------------------------------
172 
173 void SdVectorizeDlg::Calculate( Bitmap& rBmp, GDIMetaFile& rMtf )
174 {
175     mpDocSh->SetWaitCursor( sal_True );
176     aPrgs.SetValue( 0 );
177 
178     Fraction    aScale;
179     Bitmap      aTmp( GetPreparedBitmap( rBmp, aScale ) );
180 
181     if( !!aTmp )
182     {
183         const Link aPrgsHdl( LINK( this, SdVectorizeDlg, ProgressHdl ) );
184         aTmp.Vectorize( rMtf, (sal_uInt8) aMtReduce.GetValue(), BMP_VECTORIZE_OUTER | BMP_VECTORIZE_REDUCE_EDGES, &aPrgsHdl );
185 
186         if( aCbFillHoles.IsChecked() )
187         {
188             GDIMetaFile         aNewMtf;
189             BitmapReadAccess*   pRAcc = aTmp.AcquireReadAccess();
190 
191             if( pRAcc )
192             {
193                 const long      nWidth = pRAcc->Width();
194                 const long      nHeight = pRAcc->Height();
195                 const long      nTileX = static_cast<long>(aMtFillHoles.GetValue());
196                 const long      nTileY = static_cast<long>(aMtFillHoles.GetValue());
197                 const long      nCountX = nWidth / nTileX;
198                 const long      nCountY = nHeight / nTileY;
199                 const long      nRestX = nWidth % nTileX;
200                 const long      nRestY = nHeight % nTileY;
201 
202                 MapMode aMap( rMtf.GetPrefMapMode() );
203                 aNewMtf.SetPrefSize( rMtf.GetPrefSize() );
204                 aNewMtf.SetPrefMapMode( aMap );
205 
206                 for( long nTY = 0; nTY < nCountY; nTY++ )
207                 {
208                     const long nY = nTY * nTileY;
209 
210                     for( long nTX = 0; nTX < nCountX; nTX++ )
211                         AddTile( pRAcc, aNewMtf, nTX * nTileX, nTY * nTileY, nTileX, nTileY );
212 
213                     if( nRestX )
214                         AddTile( pRAcc, aNewMtf, nCountX * nTileX, nY, nRestX, nTileY );
215                 }
216 
217                 if( nRestY )
218                 {
219                     const long nY = nCountY * nTileY;
220 
221                     for( long nTX = 0; nTX < nCountX; nTX++ )
222                         AddTile( pRAcc, aNewMtf, nTX * nTileX, nY, nTileX, nRestY );
223 
224                     if( nRestX )
225                         AddTile( pRAcc, aNewMtf, nCountX * nTileX, nCountY * nTileY, nRestX, nRestY );
226                 }
227 
228 
229                 aTmp.ReleaseAccess( pRAcc );
230 
231                 for( sal_uLong n = 0UL, nCount = rMtf.GetActionCount(); n < nCount; n++ )
232                     aNewMtf.AddAction( rMtf.GetAction( n )->Clone() );
233 
234                 aMap.SetScaleX( aMap.GetScaleX() * aScale );
235                 aMap.SetScaleY( aMap.GetScaleY() * aScale );
236                 aNewMtf.SetPrefMapMode( aMap );
237                 rMtf = aNewMtf;
238             }
239         }
240     }
241 
242     aPrgs.SetValue( 0 );
243     mpDocSh->SetWaitCursor( sal_False );
244 }
245 
246 // -----------------------------------------------------------------------------
247 
248 void SdVectorizeDlg::AddTile( BitmapReadAccess* pRAcc, GDIMetaFile& rMtf,
249                               long nPosX, long nPosY, long nWidth, long nHeight )
250 {
251     sal_uLong           nSumR = 0UL, nSumG = 0UL, nSumB = 0UL;
252     const long      nRight = nPosX + nWidth - 1L;
253     const long      nBottom = nPosY + nHeight - 1L;
254     const double    fMult = 1.0 / ( nWidth * nHeight );
255 
256     for( long nY = nPosY; nY <= nBottom; nY++ )
257     {
258         for( long nX = nPosX; nX <= nRight; nX++ )
259         {
260             const BitmapColor aPixel( pRAcc->GetColor( nY, nX ) );
261 
262             nSumR += aPixel.GetRed();
263             nSumG += aPixel.GetGreen();
264             nSumB += aPixel.GetBlue();
265         }
266     }
267 
268     const Color aColor( (sal_uInt8) FRound( nSumR * fMult ),
269                         (sal_uInt8) FRound( nSumG * fMult ),
270                         (sal_uInt8) FRound( nSumB * fMult ) );
271 
272     Rectangle   aRect( Point( nPosX, nPosY ), Size( nWidth + 1, nHeight + 1 ) );
273     const Size& rMaxSize = rMtf.GetPrefSize();
274 
275     aRect = PixelToLogic( aRect, rMtf.GetPrefMapMode() );
276 
277     if( aRect.Right() > ( rMaxSize.Width() - 1L ) )
278         aRect.Right() = rMaxSize.Width() - 1L;
279 
280     if( aRect.Bottom() > ( rMaxSize.Height() - 1L ) )
281         aRect.Bottom() = rMaxSize.Height() - 1L;
282 
283     rMtf.AddAction( new MetaLineColorAction( aColor, sal_True ) );
284     rMtf.AddAction( new MetaFillColorAction( aColor, sal_True ) );
285     rMtf.AddAction( new MetaRectAction( aRect ) );
286 }
287 
288 // -----------------------------------------------------------------------------
289 
290 IMPL_LINK( SdVectorizeDlg, ProgressHdl, void*, pData )
291 {
292     aPrgs.SetValue( (sal_uInt16)(sal_uLong) pData );
293     return 0L;
294 }
295 
296 // -----------------------------------------------------------------------------
297 
298 IMPL_LINK( SdVectorizeDlg, ClickPreviewHdl, PushButton*, EMPTYARG )
299 {
300     Calculate( aBmp, aMtf );
301     aMtfWin.SetGraphic( aMtf );
302     aBtnPreview.Disable();
303 
304     return 0L;
305 }
306 
307 // -----------------------------------------------------------------------------
308 
309 IMPL_LINK( SdVectorizeDlg, ClickOKHdl, OKButton*, EMPTYARG )
310 {
311     if( aBtnPreview.IsEnabled() )
312         Calculate( aBmp, aMtf );
313 
314     SaveSettings();
315     EndDialog( RET_OK );
316 
317     return 0L;
318 }
319 
320 // -----------------------------------------------------------------------------
321 
322 IMPL_LINK( SdVectorizeDlg, ToggleHdl, CheckBox*, pCb )
323 {
324     if( pCb->IsChecked() )
325     {
326         aFtFillHoles.Enable();
327         aMtFillHoles.Enable();
328     }
329     else
330     {
331         aFtFillHoles.Disable();
332         aMtFillHoles.Disable();
333     }
334 
335     ModifyHdl( NULL );
336 
337     return 0L;
338 }
339 
340 // -----------------------------------------------------------------------------
341 
342 IMPL_LINK( SdVectorizeDlg, ModifyHdl, void*, EMPTYARG )
343 {
344     aBtnPreview.Enable();
345     return 0L;
346 }
347 
348 // -----------------------------------------------------------------------------
349 
350 void SdVectorizeDlg::LoadSettings()
351 {
352     SvStorageStreamRef  xIStm( SD_MOD()->GetOptionStream(
353                                UniString::CreateFromAscii(
354                                RTL_CONSTASCII_STRINGPARAM( SD_OPTION_VECTORIZE ) ),
355                                SD_OPTION_LOAD ) );
356     sal_uInt16              nLayers;
357     sal_uInt16              nReduce;
358     sal_uInt16              nFillHoles;
359     sal_Bool                bFillHoles;
360 
361     if( xIStm.Is() )
362     {
363         SdIOCompat aCompat( *xIStm, STREAM_READ );
364         *xIStm >> nLayers >> nReduce >> nFillHoles >> bFillHoles;
365     }
366     else
367     {
368         nLayers = 8;
369         nReduce = 0;
370         nFillHoles = 32;
371         bFillHoles = sal_False;
372     }
373 
374     aNmLayers.SetValue( nLayers );
375     aMtReduce.SetValue( nReduce );
376     aMtFillHoles.SetValue( nFillHoles );
377     aCbFillHoles.Check( bFillHoles );
378 
379     ToggleHdl( &aCbFillHoles );
380 }
381 
382 // -----------------------------------------------------------------------------
383 
384 void SdVectorizeDlg::SaveSettings() const
385 {
386     SvStorageStreamRef xOStm( SD_MOD()->GetOptionStream(
387                               UniString::CreateFromAscii(
388                               RTL_CONSTASCII_STRINGPARAM( SD_OPTION_VECTORIZE ) ),
389                               SD_OPTION_STORE ) );
390 
391     if( xOStm.Is() )
392     {
393         SdIOCompat aCompat( *xOStm, STREAM_WRITE, 1 );
394         *xOStm << (sal_uInt16) aNmLayers.GetValue() << (sal_uInt16) aMtReduce.GetValue();
395         *xOStm << (sal_uInt16) aMtFillHoles.GetValue() << aCbFillHoles.IsChecked();
396     }
397 }
398