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