blob: 223acda004fcacc96d3c369d48c2fb3f8cb652c1 [file] [log] [blame]
/**************************************************************
*
* 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();
}
}