| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_sd.hxx" |
| |
| #ifdef SD_DLLIMPLEMENTATION |
| #undef SD_DLLIMPLEMENTATION |
| #endif |
| #include <vcl/vclenum.hxx> |
| #include <vcl/wrkwin.hxx> |
| |
| #include "strings.hrc" |
| #include "sdresid.hxx" |
| #include "DrawDocShell.hxx" |
| #include "sdmod.hxx" |
| #include "sdiocmpt.hxx" |
| #include "DrawDocShell.hxx" |
| #include "vectdlg.hxx" |
| #include "vectdlg.hrc" |
| #include <tools/config.hxx> |
| #include <vcl/bmpacc.hxx> |
| #include <vcl/msgbox.hxx> |
| #include <vcl/metaact.hxx> |
| |
| // ----------- |
| // - Defines - |
| // ----------- |
| |
| #define VECTORIZE_MAX_EXTENT 512 |
| |
| // ------------------ |
| // - SdVectorizeDlg - |
| // ------------------ |
| |
| SdVectorizeDlg::SdVectorizeDlg( |
| Window* pParent, const Bitmap& rBmp, ::sd::DrawDocShell* pDocShell ) : |
| ModalDialog ( pParent, SdResId( DLG_VECTORIZE ) ), |
| mpDocSh ( pDocShell ), |
| aGrpSettings ( this, SdResId( GRP_SETTINGS ) ), |
| aFtLayers ( this, SdResId( FT_LAYERS ) ), |
| aNmLayers ( this, SdResId( NM_LAYERS ) ), |
| aFtReduce ( this, SdResId( FT_REDUCE ) ), |
| aMtReduce ( this, SdResId( MT_REDUCE ) ), |
| aFtFillHoles ( this, SdResId( FT_FILLHOLES ) ), |
| aMtFillHoles ( this, SdResId( MT_FILLHOLES ) ), |
| aCbFillHoles ( this, SdResId( CB_FILLHOLES ) ), |
| aFtOriginal ( this, SdResId( FT_ORIGINAL ) ), |
| aBmpWin ( this, SdResId( CTL_BMP ) ), |
| aFtVectorized ( this, SdResId( FT_VECTORIZED ) ), |
| aMtfWin ( this, SdResId( CTL_WMF ) ), |
| aGrpPrgs ( this, SdResId( GRP_PRGS ) ), |
| aPrgs ( this, SdResId( WND_PRGS ) ), |
| aBtnOK ( this, SdResId( BTN_OK ) ), |
| aBtnCancel ( this, SdResId( BTN_CANCEL ) ), |
| aBtnHelp ( this, SdResId( BTN_HELP ) ), |
| aBtnPreview ( this, SdResId( BTN_PREVIEW ) ), |
| aBmp ( rBmp ) |
| { |
| FreeResource(); |
| |
| aBtnPreview.SetClickHdl( LINK( this, SdVectorizeDlg, ClickPreviewHdl ) ); |
| aBtnOK.SetClickHdl( LINK( this, SdVectorizeDlg, ClickOKHdl ) ); |
| aNmLayers.SetModifyHdl( LINK( this, SdVectorizeDlg, ModifyHdl ) ); |
| aMtReduce.SetModifyHdl( LINK( this, SdVectorizeDlg, ModifyHdl ) ); |
| aMtFillHoles.SetModifyHdl( LINK( this, SdVectorizeDlg, ModifyHdl ) ); |
| aCbFillHoles.SetToggleHdl( LINK( this, SdVectorizeDlg, ToggleHdl ) ); |
| |
| // disable 3D border |
| aBmpWin.SetBorderStyle(WINDOW_BORDER_MONO); |
| aMtfWin.SetBorderStyle(WINDOW_BORDER_MONO); |
| |
| LoadSettings(); |
| InitPreviewBmp(); |
| } |
| |
| // ----------------------------------------------------------------------------- |
| |
| SdVectorizeDlg::~SdVectorizeDlg() |
| { |
| } |
| |
| // ----------------------------------------------------------------------------- |
| |
| Rectangle SdVectorizeDlg::GetRect( const Size& rDispSize, const Size& rBmpSize ) const |
| { |
| Rectangle aRect; |
| |
| if( rBmpSize.Width() && rBmpSize.Height() && rDispSize.Width() && rDispSize.Height() ) |
| { |
| Size aBmpSize( rBmpSize ); |
| const double fGrfWH = (double) aBmpSize.Width() / aBmpSize.Height(); |
| const double fWinWH = (double) rDispSize.Width() / rDispSize.Height(); |
| |
| if( fGrfWH < fWinWH ) |
| { |
| aBmpSize.Width() = (long) ( rDispSize.Height() * fGrfWH ); |
| aBmpSize.Height()= rDispSize.Height(); |
| } |
| else |
| { |
| aBmpSize.Width() = rDispSize.Width(); |
| aBmpSize.Height()= (long) ( rDispSize.Width() / fGrfWH); |
| } |
| |
| const Point aBmpPos( ( rDispSize.Width() - aBmpSize.Width() ) >> 1, |
| ( rDispSize.Height() - aBmpSize.Height() ) >> 1 ); |
| |
| aRect = Rectangle( aBmpPos, aBmpSize ); |
| } |
| |
| return aRect; |
| } |
| |
| // ----------------------------------------------------------------------------- |
| |
| void SdVectorizeDlg::InitPreviewBmp() |
| { |
| const Rectangle aRect( GetRect( aBmpWin.GetSizePixel(), aBmp.GetSizePixel() ) ); |
| |
| aPreviewBmp = aBmp; |
| aPreviewBmp.Scale( aRect.GetSize() ); |
| aBmpWin.SetGraphic( aPreviewBmp ); |
| } |
| |
| // ----------------------------------------------------------------------------- |
| |
| Bitmap SdVectorizeDlg::GetPreparedBitmap( Bitmap& rBmp, Fraction& rScale ) |
| { |
| Bitmap aNew( rBmp ); |
| const Size aSizePix( aNew.GetSizePixel() ); |
| |
| if( aSizePix.Width() > VECTORIZE_MAX_EXTENT || aSizePix.Height() > VECTORIZE_MAX_EXTENT ) |
| { |
| const Rectangle aRect( GetRect( Size( VECTORIZE_MAX_EXTENT, VECTORIZE_MAX_EXTENT ), aSizePix ) ); |
| rScale = Fraction( aSizePix.Width(), aRect.GetWidth() ); |
| aNew.Scale( aRect.GetSize() ); |
| } |
| else |
| rScale = Fraction( 1, 1 ); |
| |
| aNew.ReduceColors( (sal_uInt16) aNmLayers.GetValue(), BMP_REDUCE_SIMPLE ); |
| |
| return aNew; |
| } |
| |
| // ----------------------------------------------------------------------------- |
| |
| void SdVectorizeDlg::Calculate( Bitmap& rBmp, GDIMetaFile& rMtf ) |
| { |
| mpDocSh->SetWaitCursor( sal_True ); |
| aPrgs.SetValue( 0 ); |
| |
| Fraction aScale; |
| Bitmap aTmp( GetPreparedBitmap( rBmp, aScale ) ); |
| |
| if( !!aTmp ) |
| { |
| const Link aPrgsHdl( LINK( this, SdVectorizeDlg, ProgressHdl ) ); |
| aTmp.Vectorize( rMtf, (sal_uInt8) aMtReduce.GetValue(), BMP_VECTORIZE_OUTER | BMP_VECTORIZE_REDUCE_EDGES, &aPrgsHdl ); |
| |
| if( aCbFillHoles.IsChecked() ) |
| { |
| GDIMetaFile aNewMtf; |
| BitmapReadAccess* pRAcc = aTmp.AcquireReadAccess(); |
| |
| if( pRAcc ) |
| { |
| const long nWidth = pRAcc->Width(); |
| const long nHeight = pRAcc->Height(); |
| const long nTileX = static_cast<long>(aMtFillHoles.GetValue()); |
| const long nTileY = static_cast<long>(aMtFillHoles.GetValue()); |
| const long nCountX = nWidth / nTileX; |
| const long nCountY = nHeight / nTileY; |
| const long nRestX = nWidth % nTileX; |
| const long nRestY = nHeight % nTileY; |
| |
| MapMode aMap( rMtf.GetPrefMapMode() ); |
| aNewMtf.SetPrefSize( rMtf.GetPrefSize() ); |
| aNewMtf.SetPrefMapMode( aMap ); |
| |
| for( long nTY = 0; nTY < nCountY; nTY++ ) |
| { |
| const long nY = nTY * nTileY; |
| |
| for( long nTX = 0; nTX < nCountX; nTX++ ) |
| AddTile( pRAcc, aNewMtf, nTX * nTileX, nTY * nTileY, nTileX, nTileY ); |
| |
| if( nRestX ) |
| AddTile( pRAcc, aNewMtf, nCountX * nTileX, nY, nRestX, nTileY ); |
| } |
| |
| if( nRestY ) |
| { |
| const long nY = nCountY * nTileY; |
| |
| for( long nTX = 0; nTX < nCountX; nTX++ ) |
| AddTile( pRAcc, aNewMtf, nTX * nTileX, nY, nTileX, nRestY ); |
| |
| if( nRestX ) |
| AddTile( pRAcc, aNewMtf, nCountX * nTileX, nCountY * nTileY, nRestX, nRestY ); |
| } |
| |
| |
| aTmp.ReleaseAccess( pRAcc ); |
| |
| for( sal_uLong n = 0UL, nCount = rMtf.GetActionCount(); n < nCount; n++ ) |
| aNewMtf.AddAction( rMtf.GetAction( n )->Clone() ); |
| |
| aMap.SetScaleX( aMap.GetScaleX() * aScale ); |
| aMap.SetScaleY( aMap.GetScaleY() * aScale ); |
| aNewMtf.SetPrefMapMode( aMap ); |
| rMtf = aNewMtf; |
| } |
| } |
| } |
| |
| aPrgs.SetValue( 0 ); |
| mpDocSh->SetWaitCursor( sal_False ); |
| } |
| |
| // ----------------------------------------------------------------------------- |
| |
| void SdVectorizeDlg::AddTile( BitmapReadAccess* pRAcc, GDIMetaFile& rMtf, |
| long nPosX, long nPosY, long nWidth, long nHeight ) |
| { |
| sal_uLong nSumR = 0UL, nSumG = 0UL, nSumB = 0UL; |
| const long nRight = nPosX + nWidth - 1L; |
| const long nBottom = nPosY + nHeight - 1L; |
| const double fMult = 1.0 / ( nWidth * nHeight ); |
| |
| for( long nY = nPosY; nY <= nBottom; nY++ ) |
| { |
| for( long nX = nPosX; nX <= nRight; nX++ ) |
| { |
| const BitmapColor aPixel( pRAcc->GetColor( nY, nX ) ); |
| |
| nSumR += aPixel.GetRed(); |
| nSumG += aPixel.GetGreen(); |
| nSumB += aPixel.GetBlue(); |
| } |
| } |
| |
| const Color aColor( (sal_uInt8) FRound( nSumR * fMult ), |
| (sal_uInt8) FRound( nSumG * fMult ), |
| (sal_uInt8) FRound( nSumB * fMult ) ); |
| |
| Rectangle aRect( Point( nPosX, nPosY ), Size( nWidth + 1, nHeight + 1 ) ); |
| const Size& rMaxSize = rMtf.GetPrefSize(); |
| |
| aRect = PixelToLogic( aRect, rMtf.GetPrefMapMode() ); |
| |
| if( aRect.Right() > ( rMaxSize.Width() - 1L ) ) |
| aRect.Right() = rMaxSize.Width() - 1L; |
| |
| if( aRect.Bottom() > ( rMaxSize.Height() - 1L ) ) |
| aRect.Bottom() = rMaxSize.Height() - 1L; |
| |
| rMtf.AddAction( new MetaLineColorAction( aColor, sal_True ) ); |
| rMtf.AddAction( new MetaFillColorAction( aColor, sal_True ) ); |
| rMtf.AddAction( new MetaRectAction( aRect ) ); |
| } |
| |
| // ----------------------------------------------------------------------------- |
| |
| IMPL_LINK( SdVectorizeDlg, ProgressHdl, void*, pData ) |
| { |
| aPrgs.SetValue( (sal_uInt16)(sal_uLong) pData ); |
| return 0L; |
| } |
| |
| // ----------------------------------------------------------------------------- |
| |
| IMPL_LINK( SdVectorizeDlg, ClickPreviewHdl, PushButton*, EMPTYARG ) |
| { |
| Calculate( aBmp, aMtf ); |
| aMtfWin.SetGraphic( aMtf ); |
| aBtnPreview.Disable(); |
| |
| return 0L; |
| } |
| |
| // ----------------------------------------------------------------------------- |
| |
| IMPL_LINK( SdVectorizeDlg, ClickOKHdl, OKButton*, EMPTYARG ) |
| { |
| if( aBtnPreview.IsEnabled() ) |
| Calculate( aBmp, aMtf ); |
| |
| SaveSettings(); |
| EndDialog( RET_OK ); |
| |
| return 0L; |
| } |
| |
| // ----------------------------------------------------------------------------- |
| |
| IMPL_LINK( SdVectorizeDlg, ToggleHdl, CheckBox*, pCb ) |
| { |
| if( pCb->IsChecked() ) |
| { |
| aFtFillHoles.Enable(); |
| aMtFillHoles.Enable(); |
| } |
| else |
| { |
| aFtFillHoles.Disable(); |
| aMtFillHoles.Disable(); |
| } |
| |
| ModifyHdl( NULL ); |
| |
| return 0L; |
| } |
| |
| // ----------------------------------------------------------------------------- |
| |
| IMPL_LINK( SdVectorizeDlg, ModifyHdl, void*, EMPTYARG ) |
| { |
| aBtnPreview.Enable(); |
| return 0L; |
| } |
| |
| // ----------------------------------------------------------------------------- |
| |
| void SdVectorizeDlg::LoadSettings() |
| { |
| SvStorageStreamRef xIStm( SD_MOD()->GetOptionStream( |
| UniString::CreateFromAscii( |
| RTL_CONSTASCII_STRINGPARAM( SD_OPTION_VECTORIZE ) ), |
| SD_OPTION_LOAD ) ); |
| sal_uInt16 nLayers; |
| sal_uInt16 nReduce; |
| sal_uInt16 nFillHoles; |
| sal_Bool bFillHoles; |
| |
| if( xIStm.Is() ) |
| { |
| SdIOCompat aCompat( *xIStm, STREAM_READ ); |
| *xIStm >> nLayers >> nReduce >> nFillHoles >> bFillHoles; |
| } |
| else |
| { |
| nLayers = 8; |
| nReduce = 0; |
| nFillHoles = 32; |
| bFillHoles = sal_False; |
| } |
| |
| aNmLayers.SetValue( nLayers ); |
| aMtReduce.SetValue( nReduce ); |
| aMtFillHoles.SetValue( nFillHoles ); |
| aCbFillHoles.Check( bFillHoles ); |
| |
| ToggleHdl( &aCbFillHoles ); |
| } |
| |
| // ----------------------------------------------------------------------------- |
| |
| void SdVectorizeDlg::SaveSettings() const |
| { |
| SvStorageStreamRef xOStm( SD_MOD()->GetOptionStream( |
| UniString::CreateFromAscii( |
| RTL_CONSTASCII_STRINGPARAM( SD_OPTION_VECTORIZE ) ), |
| SD_OPTION_STORE ) ); |
| |
| if( xOStm.Is() ) |
| { |
| SdIOCompat aCompat( *xOStm, STREAM_WRITE, 1 ); |
| *xOStm << (sal_uInt16) aNmLayers.GetValue() << (sal_uInt16) aMtReduce.GetValue(); |
| *xOStm << (sal_uInt16) aMtFillHoles.GetValue() << aCbFillHoles.IsChecked(); |
| } |
| } |