2004-03-18 09:41:15 +00:00
|
|
|
/*************************************************************************
|
|
|
|
*
|
2008-04-11 09:10:30 +00:00
|
|
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
2004-03-18 09:41:15 +00:00
|
|
|
*
|
2008-04-11 09:10:30 +00:00
|
|
|
* Copyright 2008 by Sun Microsystems, Inc.
|
2004-03-18 09:41:15 +00:00
|
|
|
*
|
2008-04-11 09:10:30 +00:00
|
|
|
* OpenOffice.org - a multi-platform office productivity suite
|
2004-03-18 09:41:15 +00:00
|
|
|
*
|
2008-04-11 09:10:30 +00:00
|
|
|
* $RCSfile: implrenderer.cxx,v $
|
2008-08-19 23:38:45 +00:00
|
|
|
* $Revision: 1.26 $
|
2004-03-18 09:41:15 +00:00
|
|
|
*
|
2008-04-11 09:10:30 +00:00
|
|
|
* This file is part of OpenOffice.org.
|
2004-03-18 09:41:15 +00:00
|
|
|
*
|
2008-04-11 09:10:30 +00:00
|
|
|
* OpenOffice.org is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU Lesser General Public License version 3
|
|
|
|
* only, as published by the Free Software Foundation.
|
2004-03-18 09:41:15 +00:00
|
|
|
*
|
2008-04-11 09:10:30 +00:00
|
|
|
* OpenOffice.org is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU Lesser General Public License version 3 for more details
|
|
|
|
* (a copy is included in the LICENSE file that accompanied this code).
|
2004-03-18 09:41:15 +00:00
|
|
|
*
|
2008-04-11 09:10:30 +00:00
|
|
|
* You should have received a copy of the GNU Lesser General Public License
|
|
|
|
* version 3 along with OpenOffice.org. If not, see
|
|
|
|
* <http://www.openoffice.org/license.html>
|
|
|
|
* for a copy of the LGPLv3 License.
|
2004-03-18 09:41:15 +00:00
|
|
|
*
|
|
|
|
************************************************************************/
|
|
|
|
|
2006-09-17 11:49:12 +00:00
|
|
|
// MARKER(update_precomp.py): autogen include statement, do not remove
|
|
|
|
#include "precompiled_cppcanvas.hxx"
|
|
|
|
|
2004-11-26 19:54:32 +00:00
|
|
|
#include <canvas/debug.hxx>
|
2008-06-24 10:47:23 +00:00
|
|
|
#include <tools/diagnose_ex.h>
|
2004-11-26 19:54:32 +00:00
|
|
|
#include <canvas/verbosetrace.hxx>
|
|
|
|
|
2004-03-18 09:41:15 +00:00
|
|
|
#include <osl/mutex.hxx>
|
|
|
|
#include <vos/mutex.hxx>
|
|
|
|
#include <vcl/svapp.hxx>
|
|
|
|
|
2004-11-26 19:54:32 +00:00
|
|
|
#include <rtl/logfile.hxx>
|
|
|
|
|
2004-03-18 09:41:15 +00:00
|
|
|
#include <comphelper/sequence.hxx>
|
2007-07-17 14:24:30 +00:00
|
|
|
#include <comphelper/anytostring.hxx>
|
|
|
|
#include <cppuhelper/exc_hlp.hxx>
|
2004-03-18 09:41:15 +00:00
|
|
|
|
|
|
|
#include <cppcanvas/canvas.hxx>
|
|
|
|
|
2005-03-10 12:24:15 +00:00
|
|
|
#include <com/sun/star/rendering/XGraphicDevice.hpp>
|
|
|
|
#include <com/sun/star/rendering/TexturingMode.hpp>
|
|
|
|
#include <com/sun/star/rendering/XParametricPolyPolygon2DFactory.hpp>
|
2007-01-22 10:49:42 +00:00
|
|
|
#include <com/sun/star/uno/Sequence.hxx>
|
|
|
|
#include <com/sun/star/geometry/RealPoint2D.hpp>
|
|
|
|
#include <com/sun/star/rendering/ViewState.hpp>
|
|
|
|
#include <com/sun/star/rendering/RenderState.hpp>
|
|
|
|
#include <com/sun/star/rendering/XCanvasFont.hpp>
|
|
|
|
#include <com/sun/star/rendering/XPolyPolygon2D.hpp>
|
|
|
|
#include <com/sun/star/rendering/XCanvas.hpp>
|
|
|
|
#include <com/sun/star/rendering/PathCapType.hpp>
|
|
|
|
#include <com/sun/star/rendering/PathJoinType.hpp>
|
2004-11-26 19:54:32 +00:00
|
|
|
|
2004-03-18 09:41:15 +00:00
|
|
|
#include <basegfx/tools/canvastools.hxx>
|
2004-11-26 19:54:32 +00:00
|
|
|
#include <basegfx/numeric/ftools.hxx>
|
|
|
|
#include <basegfx/polygon/b2dpolypolygontools.hxx>
|
|
|
|
#include <basegfx/polygon/b2dpolygontools.hxx>
|
2007-01-22 10:49:42 +00:00
|
|
|
#include <basegfx/polygon/b2dpolygon.hxx>
|
|
|
|
#include <basegfx/polygon/b2dpolypolygon.hxx>
|
|
|
|
#include <basegfx/matrix/b2dhommatrix.hxx>
|
|
|
|
#include <basegfx/vector/b2dsize.hxx>
|
|
|
|
#include <basegfx/range/b2drectangle.hxx>
|
|
|
|
#include <basegfx/point/b2dpoint.hxx>
|
|
|
|
#include <basegfx/tuple/b2dtuple.hxx>
|
2008-08-19 23:38:45 +00:00
|
|
|
#include <basegfx/polygon/b2dpolygonclipper.hxx>
|
|
|
|
#include <basegfx/polygon/b2dpolypolygoncutter.hxx>
|
2007-01-22 10:49:42 +00:00
|
|
|
|
2004-03-18 09:41:15 +00:00
|
|
|
#include <canvas/canvastools.hxx>
|
2004-11-26 19:54:32 +00:00
|
|
|
#include <vcl/canvastools.hxx>
|
2005-11-02 12:40:15 +00:00
|
|
|
#include <vcl/salbtype.hxx>
|
2007-01-22 10:49:42 +00:00
|
|
|
#include <vcl/gdimtf.hxx>
|
|
|
|
#include <vcl/metaact.hxx>
|
|
|
|
#include <vcl/virdev.hxx>
|
|
|
|
#include <vcl/metric.hxx>
|
|
|
|
#include <vcl/graphictools.hxx>
|
|
|
|
#include <tools/poly.hxx>
|
2004-03-18 09:41:15 +00:00
|
|
|
|
2004-11-26 19:54:32 +00:00
|
|
|
#include <implrenderer.hxx>
|
|
|
|
#include <tools.hxx>
|
|
|
|
#include <outdevstate.hxx>
|
2004-03-18 09:41:15 +00:00
|
|
|
|
2004-11-26 19:54:32 +00:00
|
|
|
#include <action.hxx>
|
|
|
|
#include <bitmapaction.hxx>
|
|
|
|
#include <lineaction.hxx>
|
|
|
|
#include <pointaction.hxx>
|
|
|
|
#include <polypolyaction.hxx>
|
|
|
|
#include <textaction.hxx>
|
|
|
|
#include <transparencygroupaction.hxx>
|
2004-03-18 09:41:15 +00:00
|
|
|
|
|
|
|
#include <vector>
|
|
|
|
#include <algorithm>
|
2005-03-30 07:27:39 +00:00
|
|
|
#include <iterator>
|
|
|
|
|
|
|
|
#include <boost/scoped_array.hpp>
|
2004-03-18 09:41:15 +00:00
|
|
|
|
2005-03-30 07:27:39 +00:00
|
|
|
#include "mtftools.hxx"
|
|
|
|
#include "outdevstate.hxx"
|
2004-03-18 09:41:15 +00:00
|
|
|
|
|
|
|
|
|
|
|
using namespace ::com::sun::star;
|
|
|
|
|
|
|
|
|
|
|
|
// free support functions
|
|
|
|
// ======================
|
|
|
|
namespace
|
|
|
|
{
|
|
|
|
template < class MetaActionType > void setStateColor( MetaActionType* pAct,
|
|
|
|
bool& rIsColorSet,
|
|
|
|
uno::Sequence< double >& rColorSequence,
|
|
|
|
const cppcanvas::CanvasSharedPtr& rCanvas )
|
|
|
|
{
|
|
|
|
// set rIsColorSet and check for true at the same time
|
2006-10-12 13:59:41 +00:00
|
|
|
if( (rIsColorSet=pAct->IsSetting()) != false )
|
2004-03-18 09:41:15 +00:00
|
|
|
{
|
|
|
|
::Color aColor( pAct->GetColor() );
|
|
|
|
|
|
|
|
// force alpha part of color to
|
|
|
|
// opaque. transparent painting is done
|
|
|
|
// explicitely via META_TRANSPARENT_ACTION
|
|
|
|
aColor.SetTransparency(0);
|
|
|
|
//aColor.SetTransparency(128);
|
|
|
|
|
2008-06-24 10:47:23 +00:00
|
|
|
rColorSequence = ::vcl::unotools::colorToDoubleSequence(
|
|
|
|
aColor,
|
|
|
|
rCanvas->getUNOCanvas()->getDevice()->getDeviceColorSpace() );
|
2004-03-18 09:41:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-01-28 14:30:12 +00:00
|
|
|
|
2004-03-18 09:41:15 +00:00
|
|
|
// state stack manipulators
|
|
|
|
// ------------------------
|
|
|
|
void clearStateStack( ::cppcanvas::internal::VectorOfOutDevStates& rStates )
|
|
|
|
{
|
|
|
|
rStates.clear();
|
|
|
|
const ::cppcanvas::internal::OutDevState aDefaultState;
|
|
|
|
rStates.push_back( aDefaultState );
|
|
|
|
}
|
|
|
|
|
|
|
|
::cppcanvas::internal::OutDevState& getState( ::cppcanvas::internal::VectorOfOutDevStates& rStates )
|
|
|
|
{
|
|
|
|
return rStates.back();
|
|
|
|
}
|
|
|
|
|
2005-03-30 07:27:39 +00:00
|
|
|
const ::cppcanvas::internal::OutDevState& getState( const ::cppcanvas::internal::VectorOfOutDevStates& rStates )
|
|
|
|
{
|
|
|
|
return rStates.back();
|
|
|
|
}
|
|
|
|
|
2005-01-28 14:30:12 +00:00
|
|
|
void pushState( ::cppcanvas::internal::VectorOfOutDevStates& rStates,
|
|
|
|
USHORT nFlags )
|
2004-03-18 09:41:15 +00:00
|
|
|
{
|
|
|
|
rStates.push_back( getState( rStates ) );
|
2005-01-28 14:30:12 +00:00
|
|
|
getState( rStates ).pushFlags = nFlags;
|
2004-03-18 09:41:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void popState( ::cppcanvas::internal::VectorOfOutDevStates& rStates )
|
|
|
|
{
|
2005-01-28 14:30:12 +00:00
|
|
|
if( getState( rStates ).pushFlags != PUSH_ALL )
|
|
|
|
{
|
|
|
|
// a state is pushed which is incomplete, i.e. does not
|
|
|
|
// restore everything to the previous stack level when
|
|
|
|
// popped.
|
|
|
|
// That means, we take the old state, and restore every
|
|
|
|
// OutDevState member whose flag is set, from the new to the
|
|
|
|
// old state. Then the new state gets overwritten by the
|
|
|
|
// calculated state
|
|
|
|
|
|
|
|
// preset to-be-calculated new state with old state
|
|
|
|
::cppcanvas::internal::OutDevState aCalculatedNewState( getState( rStates ) );
|
|
|
|
|
|
|
|
// selectively copy to-be-restored content over saved old
|
|
|
|
// state
|
|
|
|
rStates.pop_back();
|
|
|
|
|
|
|
|
const ::cppcanvas::internal::OutDevState& rNewState( getState( rStates ) );
|
|
|
|
|
|
|
|
if( (aCalculatedNewState.pushFlags & PUSH_LINECOLOR) )
|
|
|
|
{
|
2005-03-30 07:27:39 +00:00
|
|
|
aCalculatedNewState.lineColor = rNewState.lineColor;
|
|
|
|
aCalculatedNewState.isLineColorSet = rNewState.isLineColorSet;
|
2005-01-28 14:30:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if( (aCalculatedNewState.pushFlags & PUSH_FILLCOLOR) )
|
|
|
|
{
|
2005-03-30 07:27:39 +00:00
|
|
|
aCalculatedNewState.fillColor = rNewState.fillColor;
|
|
|
|
aCalculatedNewState.isFillColorSet = rNewState.isFillColorSet;
|
2005-01-28 14:30:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if( (aCalculatedNewState.pushFlags & PUSH_FONT) )
|
|
|
|
{
|
2005-03-30 07:27:39 +00:00
|
|
|
aCalculatedNewState.xFont = rNewState.xFont;
|
|
|
|
aCalculatedNewState.fontRotation = rNewState.fontRotation;
|
|
|
|
aCalculatedNewState.textReliefStyle = rNewState.textReliefStyle;
|
|
|
|
aCalculatedNewState.textUnderlineStyle = rNewState.textUnderlineStyle;
|
|
|
|
aCalculatedNewState.textStrikeoutStyle = rNewState.textStrikeoutStyle;
|
|
|
|
aCalculatedNewState.textEmphasisMarkStyle = rNewState.textEmphasisMarkStyle;
|
|
|
|
aCalculatedNewState.isTextEffectShadowSet = rNewState.isTextEffectShadowSet;
|
|
|
|
aCalculatedNewState.isTextWordUnderlineSet = rNewState.isTextWordUnderlineSet;
|
|
|
|
aCalculatedNewState.isTextOutlineModeSet = rNewState.isTextOutlineModeSet;
|
2005-01-28 14:30:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if( (aCalculatedNewState.pushFlags & PUSH_TEXTCOLOR) )
|
|
|
|
{
|
|
|
|
aCalculatedNewState.textColor = rNewState.textColor;
|
|
|
|
}
|
|
|
|
|
2007-01-22 10:49:42 +00:00
|
|
|
if( (aCalculatedNewState.pushFlags & PUSH_MAPMODE) )
|
|
|
|
{
|
|
|
|
aCalculatedNewState.mapModeTransform = rNewState.mapModeTransform;
|
|
|
|
}
|
2005-01-28 14:30:12 +00:00
|
|
|
|
|
|
|
if( (aCalculatedNewState.pushFlags & PUSH_CLIPREGION) )
|
|
|
|
{
|
|
|
|
aCalculatedNewState.clip = rNewState.clip;
|
|
|
|
aCalculatedNewState.clipRect = rNewState.clipRect;
|
|
|
|
aCalculatedNewState.xClipPoly = rNewState.xClipPoly;
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO(F2): Raster ops NYI
|
|
|
|
// if( (aCalculatedNewState.pushFlags & PUSH_RASTEROP) )
|
|
|
|
// {
|
|
|
|
// }
|
|
|
|
|
|
|
|
if( (aCalculatedNewState.pushFlags & PUSH_TEXTFILLCOLOR) )
|
|
|
|
{
|
2005-03-30 07:27:39 +00:00
|
|
|
aCalculatedNewState.textFillColor = rNewState.textFillColor;
|
|
|
|
aCalculatedNewState.isTextFillColorSet = rNewState.isTextFillColorSet;
|
2005-01-28 14:30:12 +00:00
|
|
|
}
|
|
|
|
|
2005-03-30 07:27:39 +00:00
|
|
|
if( (aCalculatedNewState.pushFlags & PUSH_TEXTALIGN) )
|
|
|
|
{
|
|
|
|
aCalculatedNewState.textReferencePoint = rNewState.textReferencePoint;
|
|
|
|
}
|
2005-01-28 14:30:12 +00:00
|
|
|
|
|
|
|
// TODO(F1): Refpoint handling NYI
|
|
|
|
// if( (aCalculatedNewState.pushFlags & PUSH_REFPOINT) )
|
|
|
|
// {
|
|
|
|
// }
|
|
|
|
|
|
|
|
if( (aCalculatedNewState.pushFlags & PUSH_TEXTLINECOLOR) )
|
|
|
|
{
|
2005-03-30 07:27:39 +00:00
|
|
|
aCalculatedNewState.textLineColor = rNewState.textLineColor;
|
|
|
|
aCalculatedNewState.isTextLineColorSet = rNewState.isTextLineColorSet;
|
2005-01-28 14:30:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if( (aCalculatedNewState.pushFlags & PUSH_TEXTLAYOUTMODE) )
|
|
|
|
{
|
|
|
|
aCalculatedNewState.textAlignment = rNewState.textAlignment;
|
|
|
|
aCalculatedNewState.textDirection = rNewState.textDirection;
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO(F2): Text language handling NYI
|
|
|
|
// if( (aCalculatedNewState.pushFlags & PUSH_TEXTLANGUAGE) )
|
|
|
|
// {
|
|
|
|
// }
|
|
|
|
|
|
|
|
// always copy push mode
|
|
|
|
aCalculatedNewState.pushFlags = rNewState.pushFlags;
|
|
|
|
|
|
|
|
// flush to stack
|
|
|
|
getState( rStates ) = aCalculatedNewState;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
rStates.pop_back();
|
|
|
|
}
|
2004-03-18 09:41:15 +00:00
|
|
|
}
|
2005-11-02 12:40:15 +00:00
|
|
|
|
2007-01-22 10:49:42 +00:00
|
|
|
void setupStrokeAttributes( rendering::StrokeAttributes& o_rStrokeAttributes,
|
|
|
|
const ::cppcanvas::internal::ActionFactoryParameters& rParms,
|
|
|
|
const LineInfo& rLineInfo )
|
|
|
|
{
|
|
|
|
const ::basegfx::B2DSize aWidth( rLineInfo.GetWidth(), 0 );
|
|
|
|
o_rStrokeAttributes.StrokeWidth =
|
|
|
|
(getState( rParms.mrStates ).mapModeTransform * aWidth).getX();
|
|
|
|
|
|
|
|
// setup reasonable defaults
|
|
|
|
o_rStrokeAttributes.MiterLimit = 1.0;
|
|
|
|
o_rStrokeAttributes.StartCapType = rendering::PathCapType::BUTT;
|
|
|
|
o_rStrokeAttributes.EndCapType = rendering::PathCapType::BUTT;
|
|
|
|
o_rStrokeAttributes.JoinType = rendering::PathJoinType::MITER;
|
|
|
|
|
|
|
|
if( LINE_DASH == rLineInfo.GetStyle() )
|
|
|
|
{
|
|
|
|
const ::cppcanvas::internal::OutDevState& rState( getState( rParms.mrStates ) );
|
|
|
|
|
2007-08-03 10:56:05 +00:00
|
|
|
// TODO(F1): Interpret OutDev::GetRefPoint() for the start of the dashing.
|
|
|
|
|
2007-01-22 10:49:42 +00:00
|
|
|
// interpret dash info only if explicitely enabled as
|
|
|
|
// style
|
|
|
|
const ::basegfx::B2DSize aDistance( rLineInfo.GetDistance(), 0 );
|
|
|
|
const double nDistance( (rState.mapModeTransform * aDistance).getX() );
|
|
|
|
|
|
|
|
const ::basegfx::B2DSize aDashLen( rLineInfo.GetDashLen(), 0 );
|
|
|
|
const double nDashLen( (rState.mapModeTransform * aDashLen).getX() );
|
|
|
|
|
|
|
|
const ::basegfx::B2DSize aDotLen( rLineInfo.GetDotLen(), 0 );
|
|
|
|
const double nDotLen( (rState.mapModeTransform * aDotLen).getX() );
|
|
|
|
|
|
|
|
const sal_Int32 nNumArryEntries( 2*rLineInfo.GetDashCount() +
|
|
|
|
2*rLineInfo.GetDotCount() );
|
|
|
|
|
|
|
|
o_rStrokeAttributes.DashArray.realloc( nNumArryEntries );
|
|
|
|
double* pDashArray = o_rStrokeAttributes.DashArray.getArray();
|
|
|
|
|
|
|
|
|
|
|
|
// iteratively fill dash array, first with dashs, then
|
|
|
|
// with dots.
|
|
|
|
// ===================================================
|
|
|
|
|
|
|
|
sal_Int32 nCurrEntry=0;
|
|
|
|
|
|
|
|
for( sal_Int32 i=0; i<rLineInfo.GetDashCount(); ++i )
|
|
|
|
{
|
|
|
|
pDashArray[nCurrEntry++] = nDashLen;
|
|
|
|
pDashArray[nCurrEntry++] = nDistance;
|
|
|
|
}
|
|
|
|
for( sal_Int32 i=0; i<rLineInfo.GetDotCount(); ++i )
|
|
|
|
{
|
|
|
|
pDashArray[nCurrEntry++] = nDotLen;
|
|
|
|
pDashArray[nCurrEntry++] = nDistance;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-11-02 12:40:15 +00:00
|
|
|
/** Create masked BitmapEx, where the white areas of rBitmap are
|
|
|
|
transparent, and the other appear in rMaskColor.
|
|
|
|
*/
|
|
|
|
BitmapEx createMaskBmpEx( const Bitmap& rBitmap,
|
|
|
|
const ::Color& rMaskColor )
|
|
|
|
{
|
|
|
|
const ::Color aWhite( COL_WHITE );
|
|
|
|
BitmapPalette aBiLevelPalette(2);
|
|
|
|
aBiLevelPalette[0] = aWhite;
|
|
|
|
aBiLevelPalette[1] = rMaskColor;
|
|
|
|
|
|
|
|
Bitmap aMask( rBitmap.CreateMask( aWhite ));
|
|
|
|
Bitmap aSolid( rBitmap.GetSizePixel(),
|
|
|
|
1,
|
|
|
|
&aBiLevelPalette );
|
|
|
|
aSolid.Erase( rMaskColor );
|
|
|
|
|
|
|
|
return BitmapEx( aSolid, aMask );
|
|
|
|
}
|
2007-08-03 10:56:05 +00:00
|
|
|
|
|
|
|
/** Shameless rip from vcl/source/gdi/outdev3.cxx
|
|
|
|
|
|
|
|
Should consolidate, into something like basetxt...
|
|
|
|
*/
|
|
|
|
sal_Unicode getLocalizedChar( sal_Unicode nChar, LanguageType eLang )
|
|
|
|
{
|
|
|
|
// currently only conversion from ASCII digits is interesting
|
|
|
|
if( (nChar < '0') || ('9' < nChar) )
|
|
|
|
return nChar;
|
|
|
|
|
|
|
|
sal_Unicode nOffset(0);
|
|
|
|
switch( eLang )
|
|
|
|
{
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case LANGUAGE_ARABIC:
|
|
|
|
// FALLTHROUGS intended
|
|
|
|
case LANGUAGE_ARABIC_SAUDI_ARABIA:
|
|
|
|
case LANGUAGE_ARABIC_IRAQ:
|
|
|
|
case LANGUAGE_ARABIC_EGYPT:
|
|
|
|
case LANGUAGE_ARABIC_LIBYA:
|
|
|
|
case LANGUAGE_ARABIC_ALGERIA:
|
|
|
|
case LANGUAGE_ARABIC_MOROCCO:
|
|
|
|
case LANGUAGE_ARABIC_TUNISIA:
|
|
|
|
case LANGUAGE_ARABIC_OMAN:
|
|
|
|
case LANGUAGE_ARABIC_YEMEN:
|
|
|
|
case LANGUAGE_ARABIC_SYRIA:
|
|
|
|
case LANGUAGE_ARABIC_JORDAN:
|
|
|
|
case LANGUAGE_ARABIC_LEBANON:
|
|
|
|
case LANGUAGE_ARABIC_KUWAIT:
|
|
|
|
case LANGUAGE_ARABIC_UAE:
|
|
|
|
case LANGUAGE_ARABIC_BAHRAIN:
|
|
|
|
case LANGUAGE_ARABIC_QATAR:
|
|
|
|
case LANGUAGE_URDU:
|
|
|
|
case LANGUAGE_URDU_PAKISTAN:
|
|
|
|
case LANGUAGE_URDU_INDIA:
|
|
|
|
case LANGUAGE_PUNJABI: //???
|
|
|
|
nOffset = 0x0660 - '0'; // arabic/persian/urdu
|
|
|
|
break;
|
|
|
|
case LANGUAGE_BENGALI:
|
|
|
|
nOffset = 0x09E6 - '0'; // bengali
|
|
|
|
break;
|
|
|
|
case LANGUAGE_HINDI:
|
|
|
|
nOffset = 0x0966 - '0'; // devanagari
|
|
|
|
break;
|
|
|
|
case LANGUAGE_GUJARATI:
|
|
|
|
nOffset = 0x0AE6 - '0'; // gujarati
|
|
|
|
break;
|
|
|
|
case LANGUAGE_KANNADA:
|
|
|
|
nOffset = 0x0CE6 - '0'; // kannada
|
|
|
|
break;
|
|
|
|
case LANGUAGE_KHMER:
|
|
|
|
nOffset = 0x17E0 - '0'; // khmer
|
|
|
|
break;
|
|
|
|
case LANGUAGE_LAO:
|
|
|
|
nOffset = 0x0ED0 - '0'; // lao
|
|
|
|
break;
|
|
|
|
case LANGUAGE_MALAYALAM:
|
|
|
|
nOffset = 0x0D66 - '0'; // malayalam
|
|
|
|
break;
|
|
|
|
case LANGUAGE_MONGOLIAN:
|
|
|
|
nOffset = 0x1810 - '0'; // mongolian
|
|
|
|
break;
|
|
|
|
case LANGUAGE_ORIYA:
|
|
|
|
nOffset = 0x0B66 - '0'; // oriya
|
|
|
|
break;
|
|
|
|
case LANGUAGE_TAMIL:
|
|
|
|
nOffset = 0x0BE7 - '0'; // tamil
|
|
|
|
break;
|
|
|
|
case LANGUAGE_TELUGU:
|
|
|
|
nOffset = 0x0C66 - '0'; // telugu
|
|
|
|
break;
|
|
|
|
case LANGUAGE_THAI:
|
|
|
|
nOffset = 0x0E50 - '0'; // thai
|
|
|
|
break;
|
|
|
|
case LANGUAGE_TIBETAN:
|
|
|
|
nOffset = 0x0F20 - '0'; // tibetan
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
nChar = sal::static_int_cast<sal_Unicode>(nChar + nOffset);
|
|
|
|
return nChar;
|
|
|
|
}
|
|
|
|
|
|
|
|
void convertToLocalizedNumerals( XubString& rStr,
|
|
|
|
LanguageType eTextLanguage )
|
|
|
|
{
|
|
|
|
const sal_Unicode* pBase = rStr.GetBuffer();
|
|
|
|
const sal_Unicode* pBegin = pBase + 0;
|
|
|
|
const xub_StrLen nEndIndex = rStr.Len();
|
|
|
|
const sal_Unicode* pEnd = pBase + nEndIndex;
|
|
|
|
|
|
|
|
for( ; pBegin < pEnd; ++pBegin )
|
|
|
|
{
|
|
|
|
// TODO: are there non-digit localizations?
|
|
|
|
if( (*pBegin >= '0') && (*pBegin <= '9') )
|
|
|
|
{
|
|
|
|
// translate characters to local preference
|
|
|
|
sal_Unicode cChar = getLocalizedChar( *pBegin, eTextLanguage );
|
|
|
|
if( cChar != *pBegin )
|
|
|
|
rStr.SetChar( sal::static_int_cast<USHORT>(pBegin - pBase), cChar );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2004-03-18 09:41:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
namespace cppcanvas
|
|
|
|
{
|
|
|
|
namespace internal
|
|
|
|
{
|
2007-01-22 10:49:42 +00:00
|
|
|
bool ImplRenderer::createFillAndStroke( const ::basegfx::B2DPolyPolygon& rPolyPoly,
|
|
|
|
const ActionFactoryParameters& rParms )
|
2004-03-18 09:41:15 +00:00
|
|
|
{
|
2007-01-22 10:49:42 +00:00
|
|
|
const OutDevState& rState( getState( rParms.mrStates ) );
|
2005-03-30 07:27:39 +00:00
|
|
|
if( (!rState.isLineColorSet &&
|
|
|
|
!rState.isFillColorSet) ||
|
|
|
|
(rState.lineColor.getLength() == 0 &&
|
|
|
|
rState.fillColor.getLength() == 0) )
|
2004-11-26 19:54:32 +00:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2005-03-30 07:27:39 +00:00
|
|
|
ActionSharedPtr pPolyAction(
|
|
|
|
internal::PolyPolyActionFactory::createPolyPolyAction(
|
2007-01-22 10:49:42 +00:00
|
|
|
rPolyPoly, rParms.mrCanvas, rState ) );
|
2005-03-30 07:27:39 +00:00
|
|
|
|
|
|
|
if( pPolyAction )
|
|
|
|
{
|
|
|
|
maActions.push_back(
|
|
|
|
MtfAction(
|
|
|
|
pPolyAction,
|
2007-01-22 10:49:42 +00:00
|
|
|
rParms.mrCurrActionIndex ) );
|
2005-03-30 07:27:39 +00:00
|
|
|
|
2007-01-22 10:49:42 +00:00
|
|
|
rParms.mrCurrActionIndex += pPolyAction->getActionCount()-1;
|
2005-03-30 07:27:39 +00:00
|
|
|
}
|
2004-03-18 09:41:15 +00:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2007-01-22 10:49:42 +00:00
|
|
|
bool ImplRenderer::createFillAndStroke( const ::basegfx::B2DPolygon& rPoly,
|
|
|
|
const ActionFactoryParameters& rParms )
|
|
|
|
{
|
|
|
|
return createFillAndStroke( ::basegfx::B2DPolyPolygon( rPoly ),
|
|
|
|
rParms );
|
|
|
|
}
|
|
|
|
|
2004-03-18 09:41:15 +00:00
|
|
|
void ImplRenderer::skipContent( GDIMetaFile& rMtf,
|
2005-03-30 07:27:39 +00:00
|
|
|
const char* pCommentString,
|
|
|
|
sal_Int32& io_rCurrActionIndex ) const
|
2004-03-18 09:41:15 +00:00
|
|
|
{
|
2008-06-24 10:47:23 +00:00
|
|
|
ENSURE_OR_THROW( pCommentString,
|
2005-03-30 07:27:39 +00:00
|
|
|
"ImplRenderer::skipContent(): NULL string given" );
|
|
|
|
|
2004-03-18 09:41:15 +00:00
|
|
|
MetaAction* pCurrAct;
|
2006-10-12 13:59:41 +00:00
|
|
|
while( (pCurrAct=rMtf.NextAction()) != NULL )
|
2004-03-18 09:41:15 +00:00
|
|
|
{
|
2005-03-30 07:27:39 +00:00
|
|
|
// increment action index, we've skipped an action.
|
|
|
|
++io_rCurrActionIndex;
|
|
|
|
|
2004-03-18 09:41:15 +00:00
|
|
|
if( pCurrAct->GetType() == META_COMMENT_ACTION &&
|
2005-03-30 07:27:39 +00:00
|
|
|
static_cast<MetaCommentAction*>(pCurrAct)->GetComment().CompareIgnoreCaseToAscii(
|
|
|
|
pCommentString ) == COMPARE_EQUAL )
|
2004-03-18 09:41:15 +00:00
|
|
|
{
|
|
|
|
// requested comment found, done
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// EOF
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2005-03-30 07:27:39 +00:00
|
|
|
bool ImplRenderer::isActionContained( GDIMetaFile& rMtf,
|
|
|
|
const char* pCommentString,
|
|
|
|
USHORT nType ) const
|
|
|
|
{
|
2008-06-24 10:47:23 +00:00
|
|
|
ENSURE_OR_THROW( pCommentString,
|
2005-03-30 07:27:39 +00:00
|
|
|
"ImplRenderer::isActionContained(): NULL string given" );
|
|
|
|
|
|
|
|
bool bRet( false );
|
|
|
|
|
|
|
|
// at least _one_ call to GDIMetaFile::NextAction() is
|
|
|
|
// executed
|
|
|
|
ULONG nPos( 1 );
|
|
|
|
|
|
|
|
MetaAction* pCurrAct;
|
2006-10-12 13:59:41 +00:00
|
|
|
while( (pCurrAct=rMtf.NextAction()) != NULL )
|
2005-03-30 07:27:39 +00:00
|
|
|
{
|
|
|
|
if( pCurrAct->GetType() == nType )
|
|
|
|
{
|
|
|
|
bRet = true; // action type found
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( pCurrAct->GetType() == META_COMMENT_ACTION &&
|
|
|
|
static_cast<MetaCommentAction*>(pCurrAct)->GetComment().CompareIgnoreCaseToAscii(
|
|
|
|
pCommentString ) == COMPARE_EQUAL )
|
|
|
|
{
|
|
|
|
// delimiting end comment found, done
|
|
|
|
bRet = false; // not yet found
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
++nPos;
|
|
|
|
}
|
|
|
|
|
|
|
|
// rewind metafile to previous position (this method must
|
|
|
|
// not change the current metaaction)
|
|
|
|
while( nPos-- )
|
|
|
|
rMtf.WindPrev();
|
|
|
|
|
|
|
|
if( !pCurrAct )
|
|
|
|
{
|
|
|
|
// EOF, and not yet found
|
|
|
|
bRet = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return bRet;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ImplRenderer::createGradientAction( const ::PolyPolygon& rPoly,
|
|
|
|
const ::Gradient& rGradient,
|
2007-01-22 10:49:42 +00:00
|
|
|
const ActionFactoryParameters& rParms,
|
2005-03-30 07:27:39 +00:00
|
|
|
bool bIsPolygonRectangle,
|
|
|
|
bool bSubsettableActions )
|
2004-03-18 09:41:15 +00:00
|
|
|
{
|
|
|
|
DBG_TESTSOLARMUTEX();
|
|
|
|
|
2007-01-22 10:49:42 +00:00
|
|
|
::basegfx::B2DPolyPolygon aDevicePoly( rPoly.getB2DPolyPolygon() );
|
|
|
|
aDevicePoly.transform( getState( rParms.mrStates ).mapModeTransform );
|
2004-11-26 19:54:32 +00:00
|
|
|
|
|
|
|
// decide, whether this gradient can be rendered natively
|
|
|
|
// by the canvas, or must be emulated via VCL gradient
|
|
|
|
// action extraction.
|
|
|
|
const USHORT nSteps( rGradient.GetSteps() );
|
2004-03-18 09:41:15 +00:00
|
|
|
|
2004-11-26 19:54:32 +00:00
|
|
|
if( // step count is infinite, can use native canvas
|
|
|
|
// gradients here
|
|
|
|
nSteps == 0 ||
|
|
|
|
// step count is sufficiently high, such that no
|
|
|
|
// discernible difference should be visible.
|
|
|
|
nSteps > 64 )
|
|
|
|
{
|
|
|
|
uno::Reference< rendering::XParametricPolyPolygon2DFactory > xFactory(
|
2007-01-22 10:49:42 +00:00
|
|
|
rParms.mrCanvas->getUNOCanvas()->getDevice()->getParametricPolyPolygonFactory() );
|
2004-11-26 19:54:32 +00:00
|
|
|
|
|
|
|
if( xFactory.is() )
|
|
|
|
{
|
|
|
|
::basegfx::B2DHomMatrix aTextureTransformation;
|
|
|
|
rendering::Texture aTexture;
|
|
|
|
|
|
|
|
aTexture.RepeatModeX = rendering::TexturingMode::CLAMP;
|
|
|
|
aTexture.RepeatModeY = rendering::TexturingMode::CLAMP;
|
|
|
|
aTexture.Alpha = 1.0;
|
|
|
|
|
|
|
|
|
|
|
|
// setup start/end color values
|
|
|
|
// ----------------------------
|
|
|
|
|
|
|
|
// scale color coefficients with gradient intensities
|
|
|
|
const USHORT nStartIntensity( rGradient.GetStartIntensity() );
|
|
|
|
::Color aVCLStartColor( rGradient.GetStartColor() );
|
2006-10-12 13:59:41 +00:00
|
|
|
aVCLStartColor.SetRed( (UINT8)(aVCLStartColor.GetRed() * nStartIntensity / 100) );
|
|
|
|
aVCLStartColor.SetGreen( (UINT8)(aVCLStartColor.GetGreen() * nStartIntensity / 100) );
|
|
|
|
aVCLStartColor.SetBlue( (UINT8)(aVCLStartColor.GetBlue() * nStartIntensity / 100) );
|
2004-11-26 19:54:32 +00:00
|
|
|
|
|
|
|
const USHORT nEndIntensity( rGradient.GetEndIntensity() );
|
|
|
|
::Color aVCLEndColor( rGradient.GetEndColor() );
|
2006-10-12 13:59:41 +00:00
|
|
|
aVCLEndColor.SetRed( (UINT8)(aVCLEndColor.GetRed() * nEndIntensity / 100) );
|
|
|
|
aVCLEndColor.SetGreen( (UINT8)(aVCLEndColor.GetGreen() * nEndIntensity / 100) );
|
|
|
|
aVCLEndColor.SetBlue( (UINT8)(aVCLEndColor.GetBlue() * nEndIntensity / 100) );
|
2004-11-26 19:54:32 +00:00
|
|
|
|
2008-06-24 10:47:23 +00:00
|
|
|
uno::Reference<rendering::XColorSpace> xColorSpace(
|
|
|
|
rParms.mrCanvas->getUNOCanvas()->getDevice()->getDeviceColorSpace());
|
2004-11-26 19:54:32 +00:00
|
|
|
const uno::Sequence< double > aStartColor(
|
2008-06-24 10:47:23 +00:00
|
|
|
::vcl::unotools::colorToDoubleSequence( aVCLStartColor,
|
|
|
|
xColorSpace ));
|
2004-11-26 19:54:32 +00:00
|
|
|
const uno::Sequence< double > aEndColor(
|
2008-06-24 10:47:23 +00:00
|
|
|
::vcl::unotools::colorToDoubleSequence( aVCLEndColor,
|
|
|
|
xColorSpace ));
|
|
|
|
|
|
|
|
uno::Sequence< uno::Sequence < double > > aColors(2);
|
|
|
|
uno::Sequence< double > aStops(2);
|
|
|
|
|
|
|
|
aStops[0] = 0.0;
|
|
|
|
aStops[1] = 1.0;
|
|
|
|
|
|
|
|
aColors[0] = aStartColor;
|
|
|
|
aColors[1] = aEndColor;
|
|
|
|
|
2004-11-26 19:54:32 +00:00
|
|
|
|
|
|
|
// Setup texture transformation
|
|
|
|
// ----------------------------
|
|
|
|
|
2007-01-22 10:49:42 +00:00
|
|
|
const ::basegfx::B2DRectangle aBounds(
|
|
|
|
::basegfx::tools::getRange(aDevicePoly) );
|
2004-11-26 19:54:32 +00:00
|
|
|
|
|
|
|
// setup rotation angle. VCL rotates
|
|
|
|
// counter-clockwise, while canvas transformation
|
|
|
|
// rotates clockwise
|
|
|
|
double nRotation( -rGradient.GetAngle() * M_PI / 1800.0 );
|
|
|
|
|
|
|
|
switch( rGradient.GetStyle() )
|
|
|
|
{
|
|
|
|
case GRADIENT_LINEAR:
|
|
|
|
// FALLTHROUGH intended
|
|
|
|
case GRADIENT_AXIAL:
|
|
|
|
{
|
|
|
|
// standard orientation for VCL linear
|
|
|
|
// gradient is vertical, thus, rotate 90
|
|
|
|
// degrees
|
|
|
|
nRotation += M_PI/2.0;
|
|
|
|
|
|
|
|
const double nBorder(
|
|
|
|
::basegfx::pruneScaleValue(
|
|
|
|
(1.0 - rGradient.GetBorder() / 100.0) ) );
|
|
|
|
|
|
|
|
// shrink texture, to account for border
|
|
|
|
// (only in x direction, linear gradient
|
|
|
|
// is constant in y direction, anyway)
|
|
|
|
aTextureTransformation.scale( nBorder,
|
|
|
|
1.0 );
|
|
|
|
|
|
|
|
// linear gradients don't respect offsets
|
|
|
|
// (they are implicitely assumed to be
|
|
|
|
// 50%). linear gradients don't have
|
|
|
|
// border on both sides, only on the
|
|
|
|
// startColor side, axial gradients have
|
|
|
|
// border on both sides. As both gradients
|
|
|
|
// are invariant in y direction: leave y
|
|
|
|
// offset alone.
|
|
|
|
double nOffsetX( rGradient.GetBorder() / 200.0 );
|
|
|
|
|
|
|
|
// determine type of gradient (and necessary
|
|
|
|
// transformation matrix, should it be emulated by a
|
|
|
|
// generic gradient)
|
|
|
|
switch( rGradient.GetStyle() )
|
|
|
|
{
|
|
|
|
case GRADIENT_LINEAR:
|
|
|
|
nOffsetX = rGradient.GetBorder() / 100.0;
|
2008-06-24 10:47:23 +00:00
|
|
|
aTexture.Gradient = xFactory->createLinearHorizontalGradient( aColors,
|
|
|
|
aStops );
|
2004-11-26 19:54:32 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case GRADIENT_AXIAL:
|
2008-06-24 10:47:23 +00:00
|
|
|
aTexture.Gradient = xFactory->createAxialHorizontalGradient( aColors,
|
|
|
|
aStops );
|
2004-11-26 19:54:32 +00:00
|
|
|
break;
|
2006-10-12 13:59:41 +00:00
|
|
|
|
|
|
|
default: // other cases can't happen
|
|
|
|
break;
|
2004-11-26 19:54:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// apply border offset values
|
|
|
|
aTextureTransformation.translate( nOffsetX,
|
|
|
|
0.0 );
|
|
|
|
|
|
|
|
// rotate texture according to gradient rotation
|
|
|
|
aTextureTransformation.translate( -0.5, -0.5 );
|
|
|
|
aTextureTransformation.rotate( nRotation );
|
|
|
|
|
|
|
|
// to let the first strip of a rotated
|
|
|
|
// gradient start at the _edge_ of the
|
|
|
|
// bound rect (and not, due to rotation,
|
|
|
|
// slightly inside), slightly enlarge the
|
|
|
|
// gradient:
|
|
|
|
//
|
|
|
|
// y/2 sin(alpha) + x/2 cos(alpha)
|
|
|
|
//
|
|
|
|
// (values to change are not actual
|
|
|
|
// gradient scales, but original bound
|
|
|
|
// rect dimensions. Since we still want
|
|
|
|
// the border setting to apply after that,
|
|
|
|
// we multiply with that as above for
|
|
|
|
// nScaleX)
|
|
|
|
const double nScale(
|
|
|
|
::basegfx::pruneScaleValue(
|
2007-01-22 10:49:42 +00:00
|
|
|
fabs( aBounds.getHeight()*sin(nRotation) ) +
|
|
|
|
fabs( aBounds.getWidth()*cos(nRotation) )));
|
2004-11-26 19:54:32 +00:00
|
|
|
|
|
|
|
aTextureTransformation.scale( nScale, nScale );
|
|
|
|
|
|
|
|
// translate back origin to center of
|
|
|
|
// primitive
|
2007-01-22 10:49:42 +00:00
|
|
|
aTextureTransformation.translate( 0.5*aBounds.getWidth(),
|
|
|
|
0.5*aBounds.getHeight() );
|
2004-11-26 19:54:32 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GRADIENT_RADIAL:
|
|
|
|
// FALLTHROUGH intended
|
|
|
|
case GRADIENT_ELLIPTICAL:
|
|
|
|
// FALLTHROUGH intended
|
|
|
|
case GRADIENT_SQUARE:
|
|
|
|
// FALLTHROUGH intended
|
|
|
|
case GRADIENT_RECT:
|
|
|
|
{
|
|
|
|
// determine scale factors for the gradient (must
|
|
|
|
// be scaled up from [0,1]x[0,1] rect to object
|
|
|
|
// bounds). Will potentially changed in switch
|
|
|
|
// statement below.
|
|
|
|
// Respect border value, while doing so, the VCL
|
|
|
|
// gradient's border will effectively shrink the
|
|
|
|
// resulting gradient.
|
2007-01-22 10:49:42 +00:00
|
|
|
double nScaleX( aBounds.getWidth() * (1.0 - rGradient.GetBorder() / 100.0) );
|
|
|
|
double nScaleY( aBounds.getHeight()* (1.0 - rGradient.GetBorder() / 100.0) );
|
2004-11-26 19:54:32 +00:00
|
|
|
|
|
|
|
// determine offset values. Since the border is
|
|
|
|
// divided half-by-half to both sides of the
|
|
|
|
// gradient, divide translation offset by an
|
|
|
|
// additional 2. Also respect offset here, but
|
|
|
|
// since VCL gradients have their center at [0,0]
|
|
|
|
// for zero offset, but canvas gradients have
|
|
|
|
// their top, left edge aligned with the
|
|
|
|
// primitive, and offset of 50% effectively must
|
|
|
|
// yield zero shift. Both values will potentially
|
|
|
|
// be adapted in switch statement below.
|
2007-01-22 10:49:42 +00:00
|
|
|
double nOffsetX( aBounds.getWidth() *
|
2004-11-26 19:54:32 +00:00
|
|
|
(2.0 * rGradient.GetOfsX() - 100.0 + rGradient.GetBorder()) / 200.0 );
|
2007-01-22 10:49:42 +00:00
|
|
|
double nOffsetY( aBounds.getHeight() *
|
2004-11-26 19:54:32 +00:00
|
|
|
(2.0 * rGradient.GetOfsY() - 100.0 + rGradient.GetBorder()) / 200.0 );
|
|
|
|
|
|
|
|
// determine type of gradient (and necessary
|
|
|
|
// transformation matrix, should it be emulated by a
|
|
|
|
// generic gradient)
|
|
|
|
switch( rGradient.GetStyle() )
|
|
|
|
{
|
|
|
|
case GRADIENT_RADIAL:
|
|
|
|
{
|
|
|
|
// create isotrophic scaling
|
|
|
|
if( nScaleX > nScaleY )
|
|
|
|
{
|
|
|
|
nOffsetY -= (nScaleX - nScaleY) * 0.5;
|
|
|
|
nScaleY = nScaleX;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
nOffsetX -= (nScaleY - nScaleX) * 0.5;
|
|
|
|
nScaleX = nScaleY;
|
|
|
|
}
|
|
|
|
|
2005-01-13 17:04:46 +00:00
|
|
|
// enlarge gradient to match bound rect diagonal
|
|
|
|
aTextureTransformation.translate( -0.5, -0.5 );
|
2007-01-22 10:49:42 +00:00
|
|
|
const double nScale( hypot(aBounds.getWidth(), aBounds.getHeight()) / nScaleX );
|
2005-01-13 17:04:46 +00:00
|
|
|
aTextureTransformation.scale( nScale, nScale );
|
|
|
|
aTextureTransformation.translate( 0.5, 0.5 );
|
|
|
|
|
2008-06-24 10:47:23 +00:00
|
|
|
aTexture.Gradient = xFactory->createEllipticalGradient( aColors,
|
|
|
|
aStops,
|
2005-01-13 17:04:46 +00:00
|
|
|
geometry::RealRectangle2D(0.0,0.0,
|
|
|
|
1.0,1.0) );
|
2004-11-26 19:54:32 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GRADIENT_ELLIPTICAL:
|
|
|
|
{
|
|
|
|
// enlarge gradient slightly
|
|
|
|
aTextureTransformation.translate( -0.5, -0.5 );
|
|
|
|
const double nSqrt2( sqrt(2.0) );
|
|
|
|
aTextureTransformation.scale( nSqrt2,nSqrt2 );
|
|
|
|
aTextureTransformation.translate( 0.5, 0.5 );
|
|
|
|
|
2007-01-22 10:49:42 +00:00
|
|
|
aTexture.Gradient = xFactory->createEllipticalGradient(
|
2008-06-24 10:47:23 +00:00
|
|
|
aColors,
|
|
|
|
aStops,
|
2007-01-22 10:49:42 +00:00
|
|
|
::basegfx::unotools::rectangle2DFromB2DRectangle(
|
|
|
|
aBounds ));
|
2004-11-26 19:54:32 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GRADIENT_SQUARE:
|
|
|
|
// create isotrophic scaling
|
|
|
|
if( nScaleX > nScaleY )
|
|
|
|
{
|
|
|
|
nOffsetY -= (nScaleX - nScaleY) * 0.5;
|
|
|
|
nScaleY = nScaleX;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
nOffsetX -= (nScaleY - nScaleX) * 0.5;
|
|
|
|
nScaleX = nScaleY;
|
|
|
|
}
|
|
|
|
|
2008-06-24 10:47:23 +00:00
|
|
|
aTexture.Gradient = xFactory->createRectangularGradient( aColors,
|
|
|
|
aStops,
|
2004-11-26 19:54:32 +00:00
|
|
|
geometry::RealRectangle2D(0.0,0.0,
|
|
|
|
1.0,1.0) );
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GRADIENT_RECT:
|
|
|
|
aTexture.Gradient = xFactory->createRectangularGradient(
|
2008-06-24 10:47:23 +00:00
|
|
|
aColors,
|
|
|
|
aStops,
|
2007-01-22 10:49:42 +00:00
|
|
|
::basegfx::unotools::rectangle2DFromB2DRectangle(
|
|
|
|
aBounds ) );
|
2004-11-26 19:54:32 +00:00
|
|
|
break;
|
2006-10-12 13:59:41 +00:00
|
|
|
|
|
|
|
default: // other cases can't happen
|
|
|
|
break;
|
2004-11-26 19:54:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
nScaleX = ::basegfx::pruneScaleValue( nScaleX );
|
|
|
|
nScaleY = ::basegfx::pruneScaleValue( nScaleY );
|
|
|
|
|
|
|
|
aTextureTransformation.scale( nScaleX, nScaleY );
|
|
|
|
|
|
|
|
// rotate texture according to gradient rotation
|
|
|
|
aTextureTransformation.translate( -0.5*nScaleX, -0.5*nScaleY );
|
|
|
|
aTextureTransformation.rotate( nRotation );
|
|
|
|
aTextureTransformation.translate( 0.5*nScaleX, 0.5*nScaleY );
|
|
|
|
|
|
|
|
aTextureTransformation.translate( nOffsetX, nOffsetY );
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2008-06-24 10:47:23 +00:00
|
|
|
ENSURE_OR_THROW( false,
|
2004-11-26 19:54:32 +00:00
|
|
|
"ImplRenderer::createGradientAction(): Unexpected gradient type" );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2005-01-13 17:04:46 +00:00
|
|
|
// As the texture coordinate space is relative to
|
|
|
|
// the polygon coordinate space (NOT to the
|
|
|
|
// polygon itself), move gradient to the start of
|
|
|
|
// the actual polygon. If we skip this, the
|
|
|
|
// gradient will always display at the origin, and
|
|
|
|
// not within the polygon bound (which might be
|
|
|
|
// miles away from the origin).
|
2007-01-22 10:49:42 +00:00
|
|
|
aTextureTransformation.translate( aBounds.getMinX(),
|
|
|
|
aBounds.getMinY() );
|
2005-01-13 17:04:46 +00:00
|
|
|
|
2004-11-26 19:54:32 +00:00
|
|
|
::basegfx::unotools::affineMatrixFromHomMatrix( aTexture.AffineTransform,
|
|
|
|
aTextureTransformation );
|
|
|
|
|
2005-03-30 07:27:39 +00:00
|
|
|
ActionSharedPtr pPolyAction(
|
|
|
|
internal::PolyPolyActionFactory::createPolyPolyAction(
|
|
|
|
aDevicePoly,
|
2007-01-22 10:49:42 +00:00
|
|
|
rParms.mrCanvas,
|
|
|
|
getState( rParms.mrStates ),
|
2005-03-30 07:27:39 +00:00
|
|
|
aTexture ) );
|
|
|
|
|
|
|
|
if( pPolyAction )
|
|
|
|
{
|
|
|
|
maActions.push_back(
|
|
|
|
MtfAction(
|
|
|
|
pPolyAction,
|
2007-01-22 10:49:42 +00:00
|
|
|
rParms.mrCurrActionIndex ) );
|
2005-03-30 07:27:39 +00:00
|
|
|
|
2007-01-22 10:49:42 +00:00
|
|
|
rParms.mrCurrActionIndex += pPolyAction->getActionCount()-1;
|
2005-03-30 07:27:39 +00:00
|
|
|
}
|
2004-11-26 19:54:32 +00:00
|
|
|
|
|
|
|
// done, using native gradients
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-01-13 17:04:46 +00:00
|
|
|
// cannot currently use native canvas gradients, as a
|
|
|
|
// finite step size is given (this funny feature is not
|
|
|
|
// supported by the XCanvas API)
|
2007-01-22 10:49:42 +00:00
|
|
|
pushState( rParms.mrStates, PUSH_ALL );
|
2004-11-26 19:54:32 +00:00
|
|
|
|
|
|
|
if( !bIsPolygonRectangle )
|
|
|
|
{
|
|
|
|
// only clip, if given polygon is not a rectangle in
|
|
|
|
// the first place (the gradient is always limited to
|
|
|
|
// the given bound rect)
|
|
|
|
updateClipping(
|
2007-01-22 10:49:42 +00:00
|
|
|
aDevicePoly,
|
|
|
|
rParms,
|
2004-11-26 19:54:32 +00:00
|
|
|
true );
|
|
|
|
}
|
|
|
|
|
|
|
|
GDIMetaFile aTmpMtf;
|
2007-01-22 10:49:42 +00:00
|
|
|
rParms.mrVDev.AddGradientActions( rPoly.GetBoundRect(),
|
|
|
|
rGradient,
|
|
|
|
aTmpMtf );
|
2004-03-18 09:41:15 +00:00
|
|
|
|
2007-01-22 10:49:42 +00:00
|
|
|
createActions( aTmpMtf, rParms, bSubsettableActions );
|
2004-11-26 19:54:32 +00:00
|
|
|
|
2007-01-22 10:49:42 +00:00
|
|
|
popState( rParms.mrStates );
|
2004-11-26 19:54:32 +00:00
|
|
|
}
|
|
|
|
|
2007-01-22 10:49:42 +00:00
|
|
|
uno::Reference< rendering::XCanvasFont > ImplRenderer::createFont( double& o_rFontRotation,
|
|
|
|
const ::Font& rFont,
|
|
|
|
const ActionFactoryParameters& rParms ) const
|
2004-11-26 19:54:32 +00:00
|
|
|
{
|
|
|
|
rendering::FontRequest aFontRequest;
|
|
|
|
|
2007-01-22 10:49:42 +00:00
|
|
|
if( rParms.mrParms.maFontName.isValid() )
|
|
|
|
aFontRequest.FontDescription.FamilyName = rParms.mrParms.maFontName.getValue();
|
2004-11-26 19:54:32 +00:00
|
|
|
else
|
|
|
|
aFontRequest.FontDescription.FamilyName = rFont.GetName();
|
|
|
|
|
|
|
|
aFontRequest.FontDescription.StyleName = rFont.GetStyleName();
|
|
|
|
|
|
|
|
aFontRequest.FontDescription.IsSymbolFont = (rFont.GetCharSet() == RTL_TEXTENCODING_SYMBOL) ? util::TriState_YES : util::TriState_NO;
|
|
|
|
aFontRequest.FontDescription.IsVertical = rFont.IsVertical() ? util::TriState_YES : util::TriState_NO;
|
|
|
|
|
|
|
|
// TODO(F2): improve vclenum->panose conversion
|
|
|
|
aFontRequest.FontDescription.FontDescription.Weight =
|
2007-01-22 10:49:42 +00:00
|
|
|
rParms.mrParms.maFontWeight.isValid() ?
|
|
|
|
rParms.mrParms.maFontWeight.getValue() :
|
2004-11-26 19:54:32 +00:00
|
|
|
::canvas::tools::numeric_cast<sal_Int8>( ::basegfx::fround( rFont.GetWeight() ) );
|
|
|
|
aFontRequest.FontDescription.FontDescription.Letterform =
|
2007-01-22 10:49:42 +00:00
|
|
|
rParms.mrParms.maFontLetterForm.isValid() ?
|
|
|
|
rParms.mrParms.maFontLetterForm.getValue() :
|
2004-11-26 19:54:32 +00:00
|
|
|
(rFont.GetItalic() == ITALIC_NONE) ? 0 : 9;
|
|
|
|
|
|
|
|
// setup state-local text transformation,
|
|
|
|
// if the font be rotated
|
|
|
|
const short nFontAngle( rFont.GetOrientation() );
|
|
|
|
if( nFontAngle != 0 )
|
|
|
|
{
|
|
|
|
// set to unity transform rotated by font angle
|
2005-03-30 07:27:39 +00:00
|
|
|
const double nAngle( nFontAngle * (F_PI / 1800.0) );
|
|
|
|
o_rFontRotation = -nAngle;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
o_rFontRotation = 0.0;
|
2004-11-26 19:54:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
geometry::Matrix2D aFontMatrix;
|
|
|
|
::canvas::tools::setIdentityMatrix2D( aFontMatrix );
|
|
|
|
|
2005-09-23 13:30:27 +00:00
|
|
|
// TODO(F2): use correct scale direction, font
|
|
|
|
// height might be width or anything else
|
2007-01-22 10:49:42 +00:00
|
|
|
|
|
|
|
// TODO(Q3): This code smells of programming by
|
|
|
|
// coincidence (the next two if statements)
|
2005-09-23 13:30:27 +00:00
|
|
|
const ::Size rFontSizeLog( rFont.GetSize() );
|
|
|
|
const sal_Int32 nFontWidthLog = rFontSizeLog.Width();
|
|
|
|
if( nFontWidthLog != 0 )
|
2004-11-26 19:54:32 +00:00
|
|
|
{
|
|
|
|
::Font aTestFont = rFont;
|
|
|
|
aTestFont.SetWidth( 0 );
|
2007-01-22 10:49:42 +00:00
|
|
|
sal_Int32 nNormalWidth = rParms.mrVDev.GetFontMetric( aTestFont ).GetWidth();
|
2005-09-23 13:30:27 +00:00
|
|
|
if( nNormalWidth != nFontWidthLog )
|
2004-11-26 19:54:32 +00:00
|
|
|
if( nNormalWidth )
|
2005-09-23 13:30:27 +00:00
|
|
|
aFontMatrix.m00 = (double)nFontWidthLog / nNormalWidth;
|
|
|
|
}
|
|
|
|
|
|
|
|
// #i52608# apply map mode scale also to font matrix - an
|
|
|
|
// anisotrophic mapmode must be reflected in an
|
|
|
|
// anisotrophic font matrix scale.
|
2007-01-22 10:49:42 +00:00
|
|
|
const OutDevState& rState( getState( rParms.mrStates ) );
|
|
|
|
if( !::basegfx::fTools::equal(
|
|
|
|
rState.mapModeTransform.get(0,0),
|
|
|
|
rState.mapModeTransform.get(1,1)) )
|
2005-09-23 13:30:27 +00:00
|
|
|
{
|
2007-01-22 10:49:42 +00:00
|
|
|
const double nScaleX( rState.mapModeTransform.get(0,0) );
|
|
|
|
const double nScaleY( rState.mapModeTransform.get(1,1) );
|
|
|
|
|
2005-09-23 13:30:27 +00:00
|
|
|
// note: no reason to check for division by zero, we
|
|
|
|
// always have the value closer (or equal) to zero as
|
|
|
|
// the nominator.
|
2007-01-22 10:49:42 +00:00
|
|
|
if( fabs(nScaleX) < fabs(nScaleY) )
|
|
|
|
aFontMatrix.m00 *= nScaleX / nScaleY;
|
2005-09-23 13:30:27 +00:00
|
|
|
else
|
2007-01-22 10:49:42 +00:00
|
|
|
aFontMatrix.m11 *= nScaleY / nScaleX;
|
2004-11-26 19:54:32 +00:00
|
|
|
}
|
2007-01-22 10:49:42 +00:00
|
|
|
aFontRequest.CellSize = (rState.mapModeTransform * ::vcl::unotools::b2DSizeFromSize(rFontSizeLog)).getY();
|
2004-11-26 19:54:32 +00:00
|
|
|
|
2007-01-22 10:49:42 +00:00
|
|
|
return rParms.mrCanvas->getUNOCanvas()->createFont( aFontRequest,
|
|
|
|
uno::Sequence< beans::PropertyValue >(),
|
|
|
|
aFontMatrix );
|
2004-11-26 19:54:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// create text effects such as shadow/relief/embossed
|
2007-01-22 10:49:42 +00:00
|
|
|
void ImplRenderer::createTextAction( const ::Point& rStartPoint,
|
|
|
|
const String rString,
|
|
|
|
int nIndex,
|
|
|
|
int nLength,
|
|
|
|
const sal_Int32* pCharWidths,
|
|
|
|
const ActionFactoryParameters& rParms,
|
|
|
|
bool bSubsettableActions )
|
2004-11-26 19:54:32 +00:00
|
|
|
{
|
2008-06-24 10:47:23 +00:00
|
|
|
ENSURE_OR_THROW( nIndex >= 0 && nLength <= rString.Len() + nIndex,
|
2004-11-26 19:54:32 +00:00
|
|
|
"ImplRenderer::createTextWithEffectsAction(): Invalid text index" );
|
|
|
|
|
2005-03-30 07:27:39 +00:00
|
|
|
if( !nLength )
|
|
|
|
return; // zero-length text, no visible output
|
|
|
|
|
2007-01-22 10:49:42 +00:00
|
|
|
const OutDevState& rState( getState( rParms.mrStates ) );
|
2005-03-30 07:27:39 +00:00
|
|
|
|
2004-11-26 19:54:32 +00:00
|
|
|
// TODO(F2): implement all text effects
|
2006-10-12 13:59:41 +00:00
|
|
|
// if( rState.textAlignment ); // TODO(F2): NYI
|
2004-11-26 19:54:32 +00:00
|
|
|
|
2005-03-30 07:27:39 +00:00
|
|
|
::Color aShadowColor( COL_AUTO );
|
|
|
|
::Color aReliefColor( COL_AUTO );
|
|
|
|
::Size aShadowOffset;
|
|
|
|
::Size aReliefOffset;
|
|
|
|
|
2008-06-24 10:47:23 +00:00
|
|
|
uno::Reference<rendering::XColorSpace> xColorSpace(
|
|
|
|
rParms.mrCanvas->getUNOCanvas()->getDevice()->getDeviceColorSpace() );
|
|
|
|
|
2005-03-30 07:27:39 +00:00
|
|
|
if( rState.isTextEffectShadowSet )
|
2004-11-26 19:54:32 +00:00
|
|
|
{
|
2005-03-30 07:27:39 +00:00
|
|
|
// calculate shadow offset (similar to outdev3.cxx)
|
2004-11-26 19:54:32 +00:00
|
|
|
// TODO(F3): better match with outdev3.cxx
|
2007-01-22 10:49:42 +00:00
|
|
|
sal_Int32 nShadowOffset = static_cast<sal_Int32>(1.5 + ((rParms.mrVDev.GetFont().GetHeight()-24.0)/24.0));
|
2004-11-26 19:54:32 +00:00
|
|
|
if( nShadowOffset < 1 )
|
|
|
|
nShadowOffset = 1;
|
2005-03-30 07:27:39 +00:00
|
|
|
|
|
|
|
aShadowOffset.setWidth( nShadowOffset );
|
|
|
|
aShadowOffset.setHeight( nShadowOffset );
|
2004-11-26 19:54:32 +00:00
|
|
|
|
|
|
|
// determine shadow color (from outdev3.cxx)
|
2008-06-24 10:47:23 +00:00
|
|
|
::Color aTextColor = ::vcl::unotools::doubleSequenceToColor(
|
|
|
|
rState.textColor, xColorSpace );
|
2004-11-26 19:54:32 +00:00
|
|
|
bool bIsDark = (aTextColor.GetColor() == COL_BLACK)
|
|
|
|
|| (aTextColor.GetLuminance() < 8);
|
|
|
|
|
2005-03-30 07:27:39 +00:00
|
|
|
aShadowColor = bIsDark ? COL_LIGHTGRAY : COL_BLACK;
|
|
|
|
aShadowColor.SetTransparency( aTextColor.GetTransparency() );
|
2004-11-26 19:54:32 +00:00
|
|
|
}
|
|
|
|
|
2005-03-30 07:27:39 +00:00
|
|
|
if( rState.textReliefStyle )
|
2004-11-26 19:54:32 +00:00
|
|
|
{
|
|
|
|
// calculate relief offset (similar to outdev3.cxx)
|
2007-01-22 10:49:42 +00:00
|
|
|
sal_Int32 nReliefOffset = rParms.mrVDev.PixelToLogic( Size( 1, 1 ) ).Height();
|
2004-11-26 19:54:32 +00:00
|
|
|
nReliefOffset += nReliefOffset/2;
|
|
|
|
if( nReliefOffset < 1 )
|
|
|
|
nReliefOffset = 1;
|
|
|
|
|
2005-11-02 12:40:15 +00:00
|
|
|
if( rState.textReliefStyle == RELIEF_ENGRAVED )
|
2004-11-26 19:54:32 +00:00
|
|
|
nReliefOffset = -nReliefOffset;
|
2005-03-30 07:27:39 +00:00
|
|
|
|
|
|
|
aReliefOffset.setWidth( nReliefOffset );
|
|
|
|
aReliefOffset.setHeight( nReliefOffset );
|
2004-11-26 19:54:32 +00:00
|
|
|
|
|
|
|
// determine relief color (from outdev3.cxx)
|
2008-06-24 10:47:23 +00:00
|
|
|
::Color aTextColor = ::vcl::unotools::doubleSequenceToColor(
|
|
|
|
rState.textColor, xColorSpace );
|
2005-03-30 07:27:39 +00:00
|
|
|
|
|
|
|
aReliefColor = ::Color( COL_LIGHTGRAY );
|
2005-11-02 12:40:15 +00:00
|
|
|
|
|
|
|
// we don't have a automatic color, so black is always
|
|
|
|
// drawn on white (literally copied from
|
|
|
|
// vcl/source/gdi/outdev3.cxx)
|
2004-11-26 19:54:32 +00:00
|
|
|
if( aTextColor.GetColor() == COL_BLACK )
|
2005-11-02 12:40:15 +00:00
|
|
|
{
|
|
|
|
aTextColor = ::Color( COL_WHITE );
|
2007-01-22 10:49:42 +00:00
|
|
|
getState( rParms.mrStates ).textColor =
|
2008-06-24 10:47:23 +00:00
|
|
|
::vcl::unotools::colorToDoubleSequence(
|
|
|
|
aTextColor, xColorSpace );
|
2005-11-02 12:40:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if( aTextColor.GetColor() == COL_WHITE )
|
2004-11-26 19:54:32 +00:00
|
|
|
aReliefColor = ::Color( COL_BLACK );
|
|
|
|
aReliefColor.SetTransparency( aTextColor.GetTransparency() );
|
|
|
|
}
|
|
|
|
|
2005-03-30 07:27:39 +00:00
|
|
|
// create the actual text action
|
|
|
|
ActionSharedPtr pTextAction(
|
|
|
|
TextActionFactory::createTextAction(
|
|
|
|
rStartPoint,
|
|
|
|
aReliefOffset,
|
|
|
|
aReliefColor,
|
|
|
|
aShadowOffset,
|
|
|
|
aShadowColor,
|
|
|
|
rString,
|
|
|
|
nIndex,
|
|
|
|
nLength,
|
|
|
|
pCharWidths,
|
2007-01-22 10:49:42 +00:00
|
|
|
rParms.mrVDev,
|
|
|
|
rParms.mrCanvas,
|
2005-03-30 07:27:39 +00:00
|
|
|
rState,
|
2007-01-22 10:49:42 +00:00
|
|
|
rParms.mrParms,
|
2005-03-30 07:27:39 +00:00
|
|
|
bSubsettableActions ) );
|
2004-11-26 19:54:32 +00:00
|
|
|
|
2008-06-24 10:47:23 +00:00
|
|
|
ActionSharedPtr pStrikeoutTextAction;
|
|
|
|
|
|
|
|
if ( rState.textStrikeoutStyle == STRIKEOUT_X || rState.textStrikeoutStyle == STRIKEOUT_SLASH )
|
|
|
|
{
|
|
|
|
long nWidth = rParms.mrVDev.GetTextWidth( rString,nIndex,nLength );
|
|
|
|
|
|
|
|
xub_Unicode pChars[5];
|
|
|
|
if ( rState.textStrikeoutStyle == STRIKEOUT_X )
|
|
|
|
pChars[0] = 'X';
|
|
|
|
else
|
|
|
|
pChars[0] = '/';
|
|
|
|
pChars[3]=pChars[2]=pChars[1]=pChars[0];
|
|
|
|
|
|
|
|
long nStrikeoutWidth = nWidth;
|
|
|
|
String aStrikeoutTest( pChars, 4 );
|
|
|
|
|
|
|
|
if( aStrikeoutTest.Len() )
|
|
|
|
{
|
|
|
|
nStrikeoutWidth = ( rParms.mrVDev.GetTextWidth( aStrikeoutTest ) + 2 ) / 4;
|
|
|
|
aStrikeoutTest.Erase();
|
|
|
|
|
|
|
|
if( nStrikeoutWidth <= 0 )
|
|
|
|
nStrikeoutWidth = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
long nMaxWidth = nStrikeoutWidth/2;
|
|
|
|
if ( nMaxWidth < 2 )
|
|
|
|
nMaxWidth = 2;
|
|
|
|
nMaxWidth += nWidth + 1;
|
|
|
|
|
|
|
|
long nFullStrikeoutWidth = 0;
|
|
|
|
String aStrikeoutText( pChars, 0 );
|
|
|
|
while( (nFullStrikeoutWidth+=nStrikeoutWidth ) < nMaxWidth+1 )
|
|
|
|
aStrikeoutText += pChars[0];
|
|
|
|
|
|
|
|
|
|
|
|
sal_Int32 nStartPos = 0;
|
|
|
|
xub_StrLen nLen = aStrikeoutText.Len();
|
|
|
|
|
|
|
|
if( nLen )
|
|
|
|
{
|
|
|
|
long nInterval = ( nWidth - nStrikeoutWidth * nLen ) / nLen;
|
|
|
|
nStrikeoutWidth += nInterval;
|
|
|
|
sal_Int32* pStrikeoutCharWidths = new sal_Int32[nLen];
|
|
|
|
|
|
|
|
for ( int i = 0;i<nLen; i++)
|
|
|
|
{
|
|
|
|
pStrikeoutCharWidths[i] = nStrikeoutWidth;
|
|
|
|
}
|
|
|
|
|
|
|
|
for ( int i = 1;i< nLen; i++ )
|
|
|
|
{
|
|
|
|
pStrikeoutCharWidths[ i ] += pStrikeoutCharWidths[ i-1 ];
|
|
|
|
}
|
|
|
|
|
|
|
|
pStrikeoutTextAction =
|
|
|
|
TextActionFactory::createTextAction(
|
|
|
|
rStartPoint,
|
|
|
|
aReliefOffset,
|
|
|
|
aReliefColor,
|
|
|
|
aShadowOffset,
|
|
|
|
aShadowColor,
|
|
|
|
aStrikeoutText,
|
|
|
|
nStartPos,
|
|
|
|
aStrikeoutText.Len(),
|
|
|
|
pStrikeoutCharWidths,
|
|
|
|
rParms.mrVDev,
|
|
|
|
rParms.mrCanvas,
|
|
|
|
rState,
|
|
|
|
rParms.mrParms,
|
|
|
|
bSubsettableActions ) ;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-03-30 07:27:39 +00:00
|
|
|
if( pTextAction )
|
2004-11-26 19:54:32 +00:00
|
|
|
{
|
2005-03-30 07:27:39 +00:00
|
|
|
maActions.push_back(
|
|
|
|
MtfAction(
|
|
|
|
pTextAction,
|
2007-01-22 10:49:42 +00:00
|
|
|
rParms.mrCurrActionIndex ) );
|
2004-11-26 19:54:32 +00:00
|
|
|
|
2008-06-24 10:47:23 +00:00
|
|
|
if ( pStrikeoutTextAction )
|
|
|
|
{
|
|
|
|
maActions.push_back(
|
|
|
|
MtfAction(
|
|
|
|
pStrikeoutTextAction,
|
|
|
|
rParms.mrCurrActionIndex ) );
|
|
|
|
}
|
|
|
|
|
2007-01-22 10:49:42 +00:00
|
|
|
rParms.mrCurrActionIndex += pTextAction->getActionCount()-1;
|
2004-11-26 19:54:32 +00:00
|
|
|
}
|
2004-03-18 09:41:15 +00:00
|
|
|
}
|
|
|
|
|
2007-01-22 10:49:42 +00:00
|
|
|
void ImplRenderer::updateClipping( const ::basegfx::B2DPolyPolygon& rClipPoly,
|
|
|
|
const ActionFactoryParameters& rParms,
|
2004-11-26 19:54:32 +00:00
|
|
|
bool bIntersect )
|
|
|
|
{
|
2007-01-22 10:49:42 +00:00
|
|
|
::cppcanvas::internal::OutDevState& rState( getState( rParms.mrStates ) );
|
2004-11-26 19:54:32 +00:00
|
|
|
::basegfx::B2DPolyPolygon aClipPoly( rClipPoly );
|
|
|
|
|
2005-01-28 14:30:12 +00:00
|
|
|
const bool bEmptyClipRect( rState.clipRect.IsEmpty() );
|
|
|
|
const bool bEmptyClipPoly( rState.clip.count() == 0 );
|
|
|
|
|
2008-06-24 10:47:23 +00:00
|
|
|
ENSURE_OR_THROW( bEmptyClipPoly || bEmptyClipRect,
|
2005-01-28 14:30:12 +00:00
|
|
|
"ImplRenderer::updateClipping(): Clip rect and polygon are both set!" );
|
|
|
|
|
2004-11-26 19:54:32 +00:00
|
|
|
if( !bIntersect ||
|
2005-01-28 14:30:12 +00:00
|
|
|
(bEmptyClipRect && bEmptyClipPoly) )
|
2004-11-26 19:54:32 +00:00
|
|
|
{
|
|
|
|
rState.clip = rClipPoly;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2005-01-28 14:30:12 +00:00
|
|
|
if( !bEmptyClipRect )
|
|
|
|
{
|
|
|
|
// TODO(P3): Use Liang-Barsky polygon clip here,
|
|
|
|
// after all, one object is just a rectangle!
|
|
|
|
|
|
|
|
// convert rect to polygon beforehand, must revert
|
|
|
|
// to general polygon clipping here.
|
|
|
|
rState.clip = ::basegfx::B2DPolyPolygon(
|
|
|
|
::basegfx::tools::createPolygonFromRect(
|
2005-09-23 13:30:27 +00:00
|
|
|
// #121100# VCL rectangular clips always
|
|
|
|
// include one more pixel to the right
|
|
|
|
// and the bottom
|
2005-01-28 14:30:12 +00:00
|
|
|
::basegfx::B2DRectangle( rState.clipRect.Left(),
|
|
|
|
rState.clipRect.Top(),
|
2005-09-23 13:30:27 +00:00
|
|
|
rState.clipRect.Right()+1,
|
|
|
|
rState.clipRect.Bottom()+1 ) ) );
|
2005-01-28 14:30:12 +00:00
|
|
|
}
|
|
|
|
|
2008-08-19 23:38:45 +00:00
|
|
|
// AW: Simplified
|
|
|
|
rState.clip = basegfx::tools::clipPolyPolygonOnPolyPolygon(
|
|
|
|
aClipPoly, rState.clip, true, false);
|
2004-11-26 19:54:32 +00:00
|
|
|
}
|
|
|
|
|
2005-02-08 10:31:24 +00:00
|
|
|
// by now, our clip resides in the OutDevState::clip
|
|
|
|
// poly-polygon.
|
|
|
|
rState.clipRect.SetEmpty();
|
|
|
|
|
2004-11-26 19:54:32 +00:00
|
|
|
if( rState.clip.count() == 0 )
|
|
|
|
{
|
2005-03-30 07:27:39 +00:00
|
|
|
if( rState.clipRect.IsEmpty() )
|
|
|
|
{
|
|
|
|
rState.xClipPoly.clear();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
rState.xClipPoly = ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
|
2007-01-22 10:49:42 +00:00
|
|
|
rParms.mrCanvas->getUNOCanvas()->getDevice(),
|
2005-03-30 07:27:39 +00:00
|
|
|
::basegfx::B2DPolyPolygon(
|
|
|
|
::basegfx::tools::createPolygonFromRect(
|
2005-09-23 13:30:27 +00:00
|
|
|
// #121100# VCL rectangular clips
|
|
|
|
// always include one more pixel to
|
|
|
|
// the right and the bottom
|
2005-03-30 07:27:39 +00:00
|
|
|
::basegfx::B2DRectangle( rState.clipRect.Left(),
|
|
|
|
rState.clipRect.Top(),
|
2005-09-23 13:30:27 +00:00
|
|
|
rState.clipRect.Right()+1,
|
|
|
|
rState.clipRect.Bottom()+1 ) ) ) );
|
2005-03-30 07:27:39 +00:00
|
|
|
}
|
2004-11-26 19:54:32 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
rState.xClipPoly = ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
|
2007-01-22 10:49:42 +00:00
|
|
|
rParms.mrCanvas->getUNOCanvas()->getDevice(),
|
2004-11-26 19:54:32 +00:00
|
|
|
rState.clip );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-01-22 10:49:42 +00:00
|
|
|
void ImplRenderer::updateClipping( const ::Rectangle& rClipRect,
|
|
|
|
const ActionFactoryParameters& rParms,
|
|
|
|
bool bIntersect )
|
2005-01-28 14:30:12 +00:00
|
|
|
{
|
2007-01-22 10:49:42 +00:00
|
|
|
::cppcanvas::internal::OutDevState& rState( getState( rParms.mrStates ) );
|
2005-01-28 14:30:12 +00:00
|
|
|
|
|
|
|
const bool bEmptyClipRect( rState.clipRect.IsEmpty() );
|
|
|
|
const bool bEmptyClipPoly( rState.clip.count() == 0 );
|
|
|
|
|
2008-06-24 10:47:23 +00:00
|
|
|
ENSURE_OR_THROW( bEmptyClipPoly || bEmptyClipRect,
|
2005-01-28 14:30:12 +00:00
|
|
|
"ImplRenderer::updateClipping(): Clip rect and polygon are both set!" );
|
|
|
|
|
|
|
|
if( !bIntersect ||
|
|
|
|
(bEmptyClipRect && bEmptyClipPoly) )
|
|
|
|
{
|
|
|
|
rState.clipRect = rClipRect;
|
2005-02-08 10:31:24 +00:00
|
|
|
rState.clip.clear();
|
2005-01-28 14:30:12 +00:00
|
|
|
}
|
|
|
|
else if( bEmptyClipPoly )
|
|
|
|
{
|
|
|
|
rState.clipRect.Intersection( rClipRect );
|
2005-02-08 10:31:24 +00:00
|
|
|
rState.clip.clear();
|
2005-01-28 14:30:12 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// TODO(P3): Handle a fourth case here, when all clip
|
|
|
|
// polygons are rectangular, once B2DMultiRange's
|
|
|
|
// sweep line implementation is done.
|
|
|
|
|
|
|
|
// general case: convert to polygon and clip
|
|
|
|
// -----------------------------------------
|
|
|
|
|
|
|
|
// convert rect to polygon beforehand, must revert
|
|
|
|
// to general polygon clipping here.
|
|
|
|
::basegfx::B2DPolyPolygon aClipPoly(
|
|
|
|
::basegfx::tools::createPolygonFromRect(
|
|
|
|
::basegfx::B2DRectangle( rClipRect.Left(),
|
|
|
|
rClipRect.Top(),
|
|
|
|
rClipRect.Right(),
|
|
|
|
rClipRect.Bottom() ) ) );
|
|
|
|
|
2005-02-08 10:31:24 +00:00
|
|
|
rState.clipRect.SetEmpty();
|
2008-08-19 23:38:45 +00:00
|
|
|
|
|
|
|
// AW: Simplified
|
|
|
|
rState.clip = basegfx::tools::clipPolyPolygonOnPolyPolygon(
|
|
|
|
aClipPoly, rState.clip, true, false);
|
2005-01-28 14:30:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if( rState.clip.count() == 0 )
|
|
|
|
{
|
|
|
|
if( rState.clipRect.IsEmpty() )
|
|
|
|
{
|
|
|
|
rState.xClipPoly.clear();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
rState.xClipPoly = ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
|
2007-01-22 10:49:42 +00:00
|
|
|
rParms.mrCanvas->getUNOCanvas()->getDevice(),
|
2005-01-28 14:30:12 +00:00
|
|
|
::basegfx::B2DPolyPolygon(
|
|
|
|
::basegfx::tools::createPolygonFromRect(
|
2005-09-23 13:30:27 +00:00
|
|
|
// #121100# VCL rectangular clips
|
|
|
|
// always include one more pixel to
|
|
|
|
// the right and the bottom
|
2005-01-28 14:30:12 +00:00
|
|
|
::basegfx::B2DRectangle( rState.clipRect.Left(),
|
|
|
|
rState.clipRect.Top(),
|
2005-09-23 13:30:27 +00:00
|
|
|
rState.clipRect.Right()+1,
|
|
|
|
rState.clipRect.Bottom()+1 ) ) ) );
|
2005-01-28 14:30:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
rState.xClipPoly = ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
|
2007-01-22 10:49:42 +00:00
|
|
|
rParms.mrCanvas->getUNOCanvas()->getDevice(),
|
2005-01-28 14:30:12 +00:00
|
|
|
rState.clip );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-01-22 10:49:42 +00:00
|
|
|
bool ImplRenderer::createActions( GDIMetaFile& rMtf,
|
|
|
|
const ActionFactoryParameters& rFactoryParms,
|
|
|
|
bool bSubsettableActions )
|
2004-03-18 09:41:15 +00:00
|
|
|
{
|
2004-11-26 19:54:32 +00:00
|
|
|
/* TODO(P2): interpret mtf-comments
|
|
|
|
================================
|
2004-03-18 09:41:15 +00:00
|
|
|
|
|
|
|
- gradient fillings (do that via comments)
|
|
|
|
|
|
|
|
- think about mapping. _If_ we do everything in logical
|
|
|
|
coordinates (which would solve the probs for stroke
|
2004-11-26 19:54:32 +00:00
|
|
|
widths and text offsets), then we would have to
|
2004-03-18 09:41:15 +00:00
|
|
|
recalc scaling for every drawing operation. This is
|
|
|
|
because the outdev map mode might change at any time.
|
2004-11-26 19:54:32 +00:00
|
|
|
Also keep in mind, that, although we've double precision
|
|
|
|
float arithmetic now, different offsets might still
|
|
|
|
generate different roundings (aka
|
|
|
|
'OutputDevice::SetPixelOffset())
|
2004-03-18 09:41:15 +00:00
|
|
|
|
|
|
|
*/
|
|
|
|
|
2007-01-22 10:49:42 +00:00
|
|
|
// alias common parameters
|
|
|
|
VectorOfOutDevStates& rStates(rFactoryParms.mrStates);
|
|
|
|
const CanvasSharedPtr& rCanvas(rFactoryParms.mrCanvas);
|
|
|
|
::VirtualDevice& rVDev(rFactoryParms.mrVDev);
|
|
|
|
const Parameters& rParms(rFactoryParms.mrParms);
|
|
|
|
sal_Int32& io_rCurrActionIndex(rFactoryParms.mrCurrActionIndex);
|
|
|
|
|
|
|
|
|
2004-03-18 09:41:15 +00:00
|
|
|
// Loop over every metaaction
|
|
|
|
// ==========================
|
|
|
|
MetaAction* pCurrAct;
|
|
|
|
|
2004-11-26 19:54:32 +00:00
|
|
|
// TODO(P1): think about caching
|
|
|
|
for( pCurrAct=rMtf.FirstAction();
|
2004-03-18 09:41:15 +00:00
|
|
|
pCurrAct;
|
2005-03-30 07:27:39 +00:00
|
|
|
pCurrAct = rMtf.NextAction() )
|
2004-03-18 09:41:15 +00:00
|
|
|
{
|
|
|
|
// execute every action, to keep VDev state up-to-date
|
2004-11-26 19:54:32 +00:00
|
|
|
// currently used only for
|
|
|
|
// - the map mode
|
|
|
|
// - the line/fill color when processing a META_TRANSPARENT_ACTION
|
|
|
|
// - SetFont to process font metric specific actions
|
2004-03-18 09:41:15 +00:00
|
|
|
pCurrAct->Execute( &rVDev );
|
|
|
|
|
|
|
|
switch( pCurrAct->GetType() )
|
|
|
|
{
|
|
|
|
// ------------------------------------------------------------
|
|
|
|
|
|
|
|
// In the first part of this monster-switch, we
|
|
|
|
// handle all state-changing meta actions. These
|
|
|
|
// are all handled locally.
|
|
|
|
|
|
|
|
// ------------------------------------------------------------
|
|
|
|
|
|
|
|
case META_PUSH_ACTION:
|
2005-01-28 14:30:12 +00:00
|
|
|
{
|
|
|
|
MetaPushAction* pPushAction = static_cast<MetaPushAction*>(pCurrAct);
|
|
|
|
pushState( rStates,
|
|
|
|
pPushAction->GetFlags() );
|
|
|
|
}
|
|
|
|
break;
|
2004-03-18 09:41:15 +00:00
|
|
|
|
|
|
|
case META_POP_ACTION:
|
|
|
|
popState( rStates );
|
|
|
|
break;
|
|
|
|
|
2007-08-03 10:56:05 +00:00
|
|
|
case META_TEXTLANGUAGE_ACTION:
|
|
|
|
// FALLTHROUGH intended
|
|
|
|
case META_REFPOINT_ACTION:
|
|
|
|
// handled via pCurrAct->Execute( &rVDev )
|
|
|
|
break;
|
|
|
|
|
2005-03-30 07:27:39 +00:00
|
|
|
case META_MAPMODE_ACTION:
|
2007-01-22 10:49:42 +00:00
|
|
|
// modify current mapModeTransformation
|
|
|
|
// transformation, such that subsequent
|
|
|
|
// coordinates map correctly
|
|
|
|
tools::calcLogic2PixelAffineTransform( getState( rStates ).mapModeTransform,
|
|
|
|
rVDev );
|
2005-03-30 07:27:39 +00:00
|
|
|
break;
|
|
|
|
|
2004-03-18 09:41:15 +00:00
|
|
|
// monitor clip regions, to assemble clip polygon on our own
|
|
|
|
case META_CLIPREGION_ACTION:
|
2004-11-26 19:54:32 +00:00
|
|
|
{
|
|
|
|
MetaClipRegionAction* pClipAction = static_cast<MetaClipRegionAction*>(pCurrAct);
|
|
|
|
|
|
|
|
if( !pClipAction->IsClipping() )
|
|
|
|
{
|
|
|
|
// clear clipping
|
|
|
|
getState( rStates ).clip.clear();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if( !pClipAction->GetRegion().HasPolyPolygon() )
|
|
|
|
{
|
|
|
|
VERBOSE_TRACE( "ImplRenderer::createActions(): non-polygonal clip "
|
|
|
|
"region encountered, falling back to bounding box!" );
|
|
|
|
|
2007-01-22 10:49:42 +00:00
|
|
|
// #121806# explicitely kept integer
|
2004-11-26 19:54:32 +00:00
|
|
|
Rectangle aClipRect(
|
|
|
|
rVDev.LogicToPixel(
|
|
|
|
pClipAction->GetRegion().GetBoundRect() ) );
|
|
|
|
|
|
|
|
// intersect current clip with given rect
|
|
|
|
updateClipping(
|
2005-01-28 14:30:12 +00:00
|
|
|
aClipRect,
|
2007-01-22 10:49:42 +00:00
|
|
|
rFactoryParms,
|
2004-11-26 19:54:32 +00:00
|
|
|
false );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// set new clip polygon (don't intersect
|
|
|
|
// with old one, just set it)
|
2007-01-22 10:49:42 +00:00
|
|
|
|
|
|
|
// #121806# explicitely kept integer
|
2004-11-26 19:54:32 +00:00
|
|
|
updateClipping(
|
|
|
|
rVDev.LogicToPixel(
|
|
|
|
pClipAction->GetRegion().GetPolyPolygon() ).getB2DPolyPolygon(),
|
2007-01-22 10:49:42 +00:00
|
|
|
rFactoryParms,
|
2004-11-26 19:54:32 +00:00
|
|
|
false );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2004-03-18 09:41:15 +00:00
|
|
|
case META_ISECTRECTCLIPREGION_ACTION:
|
2004-11-26 19:54:32 +00:00
|
|
|
{
|
|
|
|
MetaISectRectClipRegionAction* pClipAction = static_cast<MetaISectRectClipRegionAction*>(pCurrAct);
|
2007-01-22 10:49:42 +00:00
|
|
|
|
|
|
|
// #121806# explicitely kept integer
|
2004-11-26 19:54:32 +00:00
|
|
|
Rectangle aClipRect(
|
|
|
|
rVDev.LogicToPixel( pClipAction->GetRect() ) );
|
|
|
|
|
|
|
|
// intersect current clip with given rect
|
|
|
|
updateClipping(
|
2005-01-28 14:30:12 +00:00
|
|
|
aClipRect,
|
2007-01-22 10:49:42 +00:00
|
|
|
rFactoryParms,
|
2004-11-26 19:54:32 +00:00
|
|
|
true );
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2004-03-18 09:41:15 +00:00
|
|
|
case META_ISECTREGIONCLIPREGION_ACTION:
|
2004-11-26 19:54:32 +00:00
|
|
|
{
|
|
|
|
MetaISectRegionClipRegionAction* pClipAction = static_cast<MetaISectRegionClipRegionAction*>(pCurrAct);
|
|
|
|
|
|
|
|
if( !pClipAction->GetRegion().HasPolyPolygon() )
|
|
|
|
{
|
|
|
|
VERBOSE_TRACE( "ImplRenderer::createActions(): non-polygonal clip "
|
|
|
|
"region encountered, falling back to bounding box!" );
|
|
|
|
|
2007-01-22 10:49:42 +00:00
|
|
|
// #121806# explicitely kept integer
|
2004-11-26 19:54:32 +00:00
|
|
|
Rectangle aClipRect(
|
|
|
|
rVDev.LogicToPixel( pClipAction->GetRegion().GetBoundRect() ) );
|
|
|
|
|
|
|
|
// intersect current clip with given rect
|
|
|
|
updateClipping(
|
2005-01-28 14:30:12 +00:00
|
|
|
aClipRect,
|
2007-01-22 10:49:42 +00:00
|
|
|
rFactoryParms,
|
2004-11-26 19:54:32 +00:00
|
|
|
true );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// intersect current clip with given clip polygon
|
2007-01-22 10:49:42 +00:00
|
|
|
|
|
|
|
// #121806# explicitely kept integer
|
2004-11-26 19:54:32 +00:00
|
|
|
updateClipping(
|
|
|
|
rVDev.LogicToPixel(
|
|
|
|
pClipAction->GetRegion().GetPolyPolygon() ).getB2DPolyPolygon(),
|
2007-01-22 10:49:42 +00:00
|
|
|
rFactoryParms,
|
2004-11-26 19:54:32 +00:00
|
|
|
true );
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2004-03-18 09:41:15 +00:00
|
|
|
case META_MOVECLIPREGION_ACTION:
|
2004-11-26 19:54:32 +00:00
|
|
|
// TODO(F2): NYI
|
2004-03-18 09:41:15 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case META_LINECOLOR_ACTION:
|
2004-11-26 19:54:32 +00:00
|
|
|
if( !rParms.maLineColor.isValid() )
|
|
|
|
{
|
|
|
|
setStateColor( static_cast<MetaLineColorAction*>(pCurrAct),
|
|
|
|
getState( rStates ).isLineColorSet,
|
|
|
|
getState( rStates ).lineColor,
|
|
|
|
rCanvas );
|
|
|
|
}
|
2004-03-18 09:41:15 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case META_FILLCOLOR_ACTION:
|
2004-11-26 19:54:32 +00:00
|
|
|
if( !rParms.maFillColor.isValid() )
|
|
|
|
{
|
|
|
|
setStateColor( static_cast<MetaFillColorAction*>(pCurrAct),
|
|
|
|
getState( rStates ).isFillColorSet,
|
|
|
|
getState( rStates ).fillColor,
|
|
|
|
rCanvas );
|
|
|
|
}
|
2004-03-18 09:41:15 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case META_TEXTCOLOR_ACTION:
|
|
|
|
{
|
2004-11-26 19:54:32 +00:00
|
|
|
if( !rParms.maTextColor.isValid() )
|
|
|
|
{
|
|
|
|
// Text color is set unconditionally, thus, no
|
|
|
|
// use of setStateColor here
|
|
|
|
::Color aColor( static_cast<MetaTextColorAction*>(pCurrAct)->GetColor() );
|
|
|
|
|
|
|
|
// force alpha part of color to
|
|
|
|
// opaque. transparent painting is done
|
|
|
|
// explicitely via META_TRANSPARENT_ACTION
|
|
|
|
aColor.SetTransparency(0);
|
|
|
|
|
|
|
|
getState( rStates ).textColor =
|
2008-06-24 10:47:23 +00:00
|
|
|
::vcl::unotools::colorToDoubleSequence(
|
|
|
|
aColor,
|
|
|
|
rCanvas->getUNOCanvas()->getDevice()->getDeviceColorSpace() );
|
2004-11-26 19:54:32 +00:00
|
|
|
}
|
2004-03-18 09:41:15 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case META_TEXTFILLCOLOR_ACTION:
|
2004-11-26 19:54:32 +00:00
|
|
|
if( !rParms.maTextColor.isValid() )
|
|
|
|
{
|
|
|
|
setStateColor( static_cast<MetaTextFillColorAction*>(pCurrAct),
|
|
|
|
getState( rStates ).isTextFillColorSet,
|
|
|
|
getState( rStates ).textFillColor,
|
|
|
|
rCanvas );
|
|
|
|
}
|
2004-03-18 09:41:15 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case META_TEXTLINECOLOR_ACTION:
|
2004-11-26 19:54:32 +00:00
|
|
|
if( !rParms.maTextColor.isValid() )
|
|
|
|
{
|
|
|
|
setStateColor( static_cast<MetaTextLineColorAction*>(pCurrAct),
|
|
|
|
getState( rStates ).isTextLineColorSet,
|
|
|
|
getState( rStates ).textLineColor,
|
|
|
|
rCanvas );
|
|
|
|
}
|
2004-03-18 09:41:15 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case META_TEXTALIGN_ACTION:
|
2005-03-30 07:27:39 +00:00
|
|
|
{
|
|
|
|
::cppcanvas::internal::OutDevState& rState = getState( rStates );
|
|
|
|
const TextAlign eTextAlign( static_cast<MetaTextAlignAction*>(pCurrAct)->GetTextAlign() );
|
|
|
|
|
|
|
|
rState.textReferencePoint = eTextAlign;
|
|
|
|
}
|
|
|
|
break;
|
2004-03-18 09:41:15 +00:00
|
|
|
|
|
|
|
case META_FONT_ACTION:
|
|
|
|
{
|
2004-11-26 19:54:32 +00:00
|
|
|
::cppcanvas::internal::OutDevState& rState = getState( rStates );
|
2004-03-18 09:41:15 +00:00
|
|
|
const ::Font& rFont( static_cast<MetaFontAction*>(pCurrAct)->GetFont() );
|
|
|
|
|
2005-03-30 07:27:39 +00:00
|
|
|
rState.xFont = createFont( rState.fontRotation,
|
2004-11-26 19:54:32 +00:00
|
|
|
rFont,
|
2007-01-22 10:49:42 +00:00
|
|
|
rFactoryParms );
|
2004-11-26 19:54:32 +00:00
|
|
|
|
|
|
|
// TODO(Q2): define and use appropriate enumeration types
|
|
|
|
rState.textReliefStyle = (sal_Int8)rFont.GetRelief();
|
|
|
|
rState.textUnderlineStyle = rParms.maFontUnderline.isValid() ?
|
2006-10-12 13:59:41 +00:00
|
|
|
(rParms.maFontUnderline.getValue() ? (sal_Int8)UNDERLINE_SINGLE : (sal_Int8)UNDERLINE_NONE) :
|
2004-11-26 19:54:32 +00:00
|
|
|
(sal_Int8)rFont.GetUnderline();
|
|
|
|
rState.textStrikeoutStyle = (sal_Int8)rFont.GetStrikeout();
|
|
|
|
rState.textEmphasisMarkStyle = (sal_Int8)rFont.GetEmphasisMark();
|
|
|
|
rState.isTextEffectShadowSet = (rFont.IsShadow() != FALSE);
|
|
|
|
rState.isTextWordUnderlineSet = (rFont.IsWordLineMode() != FALSE);
|
|
|
|
rState.isTextOutlineModeSet = (rFont.IsOutline() != FALSE);
|
2004-03-18 09:41:15 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case META_RASTEROP_ACTION:
|
2004-11-26 19:54:32 +00:00
|
|
|
// TODO(F2): NYI
|
2004-03-18 09:41:15 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case META_LAYOUTMODE_ACTION:
|
|
|
|
{
|
2004-11-26 19:54:32 +00:00
|
|
|
// TODO(F2): A lot is missing here
|
|
|
|
int nLayoutMode = static_cast<MetaLayoutModeAction*>(pCurrAct)->GetLayoutMode();
|
|
|
|
::cppcanvas::internal::OutDevState& rState = getState( rStates );
|
|
|
|
switch( nLayoutMode & (TEXT_LAYOUT_BIDI_RTL|TEXT_LAYOUT_BIDI_STRONG) )
|
2004-03-18 09:41:15 +00:00
|
|
|
{
|
2004-11-26 19:54:32 +00:00
|
|
|
case TEXT_LAYOUT_BIDI_LTR:
|
|
|
|
rState.textDirection = rendering::TextDirection::WEAK_LEFT_TO_RIGHT;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case (TEXT_LAYOUT_BIDI_LTR | TEXT_LAYOUT_BIDI_STRONG):
|
|
|
|
rState.textDirection = rendering::TextDirection::STRONG_LEFT_TO_RIGHT;
|
|
|
|
break;
|
|
|
|
|
2004-03-18 09:41:15 +00:00
|
|
|
case TEXT_LAYOUT_BIDI_RTL:
|
2004-11-26 19:54:32 +00:00
|
|
|
rState.textDirection = rendering::TextDirection::WEAK_RIGHT_TO_LEFT;
|
2004-03-18 09:41:15 +00:00
|
|
|
break;
|
|
|
|
|
2004-11-26 19:54:32 +00:00
|
|
|
case (TEXT_LAYOUT_BIDI_RTL | TEXT_LAYOUT_BIDI_STRONG):
|
|
|
|
rState.textDirection = rendering::TextDirection::STRONG_RIGHT_TO_LEFT;
|
2004-03-18 09:41:15 +00:00
|
|
|
break;
|
|
|
|
}
|
2004-11-26 19:54:32 +00:00
|
|
|
|
|
|
|
rState.textAlignment = 0; // TODO(F2): rendering::TextAlignment::LEFT_ALIGNED;
|
|
|
|
if( (nLayoutMode & (TEXT_LAYOUT_BIDI_RTL | TEXT_LAYOUT_TEXTORIGIN_RIGHT) )
|
|
|
|
&& !(nLayoutMode & TEXT_LAYOUT_TEXTORIGIN_LEFT ) )
|
|
|
|
{
|
|
|
|
rState.textAlignment = 1; // TODO(F2): rendering::TextAlignment::RIGHT_ALIGNED;
|
|
|
|
}
|
2004-03-18 09:41:15 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
// ------------------------------------------------------------
|
|
|
|
|
|
|
|
// In the second part of this monster-switch, we
|
|
|
|
// handle all recursing meta actions. These are the
|
|
|
|
// ones generating a metafile by themselves, which is
|
|
|
|
// then processed by recursively calling this method.
|
|
|
|
|
|
|
|
// ------------------------------------------------------------
|
|
|
|
|
|
|
|
case META_GRADIENT_ACTION:
|
|
|
|
{
|
|
|
|
MetaGradientAction* pGradAct = static_cast<MetaGradientAction*>(pCurrAct);
|
2004-11-26 19:54:32 +00:00
|
|
|
createGradientAction( ::Polygon( pGradAct->GetRect() ),
|
2004-03-18 09:41:15 +00:00
|
|
|
pGradAct->GetGradient(),
|
2007-01-22 10:49:42 +00:00
|
|
|
rFactoryParms,
|
2005-03-30 07:27:39 +00:00
|
|
|
true,
|
|
|
|
bSubsettableActions );
|
2004-03-18 09:41:15 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case META_HATCH_ACTION:
|
|
|
|
{
|
2004-11-26 19:54:32 +00:00
|
|
|
// TODO(F2): use native Canvas hatches here
|
2004-03-18 09:41:15 +00:00
|
|
|
GDIMetaFile aTmpMtf;
|
|
|
|
|
|
|
|
rVDev.AddHatchActions( static_cast<MetaHatchAction*>(pCurrAct)->GetPolyPolygon(),
|
|
|
|
static_cast<MetaHatchAction*>(pCurrAct)->GetHatch(),
|
|
|
|
aTmpMtf );
|
2007-01-22 10:49:42 +00:00
|
|
|
createActions( aTmpMtf, rFactoryParms,
|
|
|
|
bSubsettableActions );
|
2004-03-18 09:41:15 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case META_EPS_ACTION:
|
|
|
|
{
|
|
|
|
MetaEPSAction* pAct = static_cast<MetaEPSAction*>(pCurrAct);
|
2005-09-23 13:30:27 +00:00
|
|
|
const GDIMetaFile& rSubstitute = pAct->GetSubstitute();
|
|
|
|
|
2007-01-22 10:49:42 +00:00
|
|
|
// #121806# explicitely kept integer
|
2005-09-23 13:30:27 +00:00
|
|
|
const Size aMtfSize( rSubstitute.GetPrefSize() );
|
|
|
|
const Size aMtfSizePixPre( rVDev.LogicToPixel( aMtfSize,
|
|
|
|
rSubstitute.GetPrefMapMode() ) );
|
|
|
|
|
|
|
|
// #i44110# correct null-sized output - there
|
|
|
|
// are metafiles which have zero size in at
|
|
|
|
// least one dimension
|
|
|
|
const Size aMtfSizePix( ::std::max( aMtfSizePixPre.Width(), 1L ),
|
|
|
|
::std::max( aMtfSizePixPre.Height(), 1L ) );
|
|
|
|
|
|
|
|
// Setup local transform, such that the
|
|
|
|
// metafile renders itself into the given
|
|
|
|
// output rectangle
|
|
|
|
pushState( rStates, PUSH_ALL );
|
|
|
|
|
2007-08-03 10:56:05 +00:00
|
|
|
rVDev.Push();
|
|
|
|
rVDev.SetMapMode( rSubstitute.GetPrefMapMode() );
|
|
|
|
|
2005-09-23 13:30:27 +00:00
|
|
|
const ::Point& rPos( rVDev.LogicToPixel( pAct->GetPoint() ) );
|
|
|
|
const ::Size& rSize( rVDev.LogicToPixel( pAct->GetSize() ) );
|
|
|
|
|
|
|
|
getState( rStates ).transform.translate( rPos.X(),
|
|
|
|
rPos.Y() );
|
|
|
|
getState( rStates ).transform.scale( (double)rSize.Width() / aMtfSizePix.Width(),
|
|
|
|
(double)rSize.Height() / aMtfSizePix.Height() );
|
|
|
|
|
2007-01-22 10:49:42 +00:00
|
|
|
createActions( const_cast<GDIMetaFile&>(pAct->GetSubstitute()),
|
|
|
|
rFactoryParms,
|
|
|
|
bSubsettableActions );
|
2004-03-18 09:41:15 +00:00
|
|
|
|
2005-09-23 13:30:27 +00:00
|
|
|
rVDev.Pop();
|
|
|
|
popState( rStates );
|
2004-03-18 09:41:15 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
// handle metafile comments, to retrieve
|
|
|
|
// meta-information for gradients, fills and
|
|
|
|
// strokes. May skip actions, and may recurse.
|
|
|
|
case META_COMMENT_ACTION:
|
|
|
|
{
|
|
|
|
MetaCommentAction* pAct = static_cast<MetaCommentAction*>(pCurrAct);
|
|
|
|
|
|
|
|
// Handle gradients
|
|
|
|
if ( pAct->GetComment().CompareIgnoreCaseToAscii( "XGRAD_SEQ_BEGIN" ) == COMPARE_EQUAL )
|
|
|
|
{
|
|
|
|
MetaGradientExAction* pGradAction = NULL;
|
|
|
|
bool bDone( false );
|
|
|
|
while( !bDone &&
|
2006-10-12 13:59:41 +00:00
|
|
|
(pCurrAct=rMtf.NextAction()) != NULL )
|
2004-03-18 09:41:15 +00:00
|
|
|
{
|
|
|
|
switch( pCurrAct->GetType() )
|
|
|
|
{
|
|
|
|
// extract gradient info
|
|
|
|
case META_GRADIENTEX_ACTION:
|
|
|
|
pGradAction = static_cast<MetaGradientExAction*>(pCurrAct);
|
|
|
|
break;
|
|
|
|
|
|
|
|
// skip broken-down rendering, output gradient when sequence is ended
|
|
|
|
case META_COMMENT_ACTION:
|
|
|
|
if( static_cast<MetaCommentAction*>(pCurrAct)->GetComment().CompareIgnoreCaseToAscii( "XGRAD_SEQ_END" ) == COMPARE_EQUAL )
|
|
|
|
{
|
|
|
|
bDone = true;
|
|
|
|
|
|
|
|
if( pGradAction )
|
|
|
|
{
|
2004-11-26 19:54:32 +00:00
|
|
|
createGradientAction( pGradAction->GetPolyPolygon(),
|
2004-03-18 09:41:15 +00:00
|
|
|
pGradAction->GetGradient(),
|
2007-01-22 10:49:42 +00:00
|
|
|
rFactoryParms,
|
2005-03-30 07:27:39 +00:00
|
|
|
false,
|
|
|
|
bSubsettableActions );
|
2004-03-18 09:41:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2005-03-30 07:27:39 +00:00
|
|
|
// TODO(P2): Handle drawing layer strokes, via
|
|
|
|
// XPATHSTROKE_SEQ_BEGIN comment
|
2004-03-18 09:41:15 +00:00
|
|
|
|
|
|
|
// Handle drawing layer fills
|
|
|
|
else if( pAct->GetComment().Equals( "XPATHFILL_SEQ_BEGIN" ) )
|
|
|
|
{
|
|
|
|
const BYTE* pData = pAct->GetData();
|
|
|
|
if ( pData )
|
|
|
|
{
|
2005-03-30 07:27:39 +00:00
|
|
|
SvMemoryStream aMemStm( (void*)pData, pAct->GetDataSize(), STREAM_READ );
|
2004-03-18 09:41:15 +00:00
|
|
|
|
|
|
|
SvtGraphicFill aFill;
|
|
|
|
aMemStm >> aFill;
|
|
|
|
|
2005-03-30 07:27:39 +00:00
|
|
|
// TODO(P2): Also handle gradients and
|
|
|
|
// hatches like this
|
|
|
|
|
|
|
|
// only evaluate comment for pure
|
|
|
|
// bitmap fills. If a transparency
|
|
|
|
// gradient is involved (denoted by
|
|
|
|
// the FloatTransparent action), take
|
|
|
|
// the normal meta actions.
|
|
|
|
if( aFill.getFillType() == SvtGraphicFill::fillTexture &&
|
|
|
|
!isActionContained( rMtf,
|
|
|
|
"XPATHFILL_SEQ_END",
|
|
|
|
META_FLOATTRANSPARENT_ACTION ) )
|
2004-03-18 09:41:15 +00:00
|
|
|
{
|
2005-03-30 07:27:39 +00:00
|
|
|
rendering::Texture aTexture;
|
|
|
|
|
|
|
|
// TODO(F1): the SvtGraphicFill
|
|
|
|
// can also transport metafiles
|
|
|
|
// here, handle that case, too
|
|
|
|
Graphic aGraphic;
|
|
|
|
aFill.getGraphic( aGraphic );
|
|
|
|
|
|
|
|
BitmapEx aBmpEx( aGraphic.GetBitmapEx() );
|
|
|
|
const ::Size aBmpSize( aBmpEx.GetSizePixel() );
|
|
|
|
|
|
|
|
::SvtGraphicFill::Transform aTransform;
|
|
|
|
aFill.getTransform( aTransform );
|
|
|
|
|
|
|
|
::basegfx::B2DHomMatrix aMatrix;
|
|
|
|
|
|
|
|
// convert to basegfx matrix
|
|
|
|
aMatrix.set(0,0, aTransform.matrix[ 0 ] );
|
|
|
|
aMatrix.set(0,1, aTransform.matrix[ 1 ] );
|
|
|
|
aMatrix.set(0,2, aTransform.matrix[ 2 ] );
|
|
|
|
aMatrix.set(1,0, aTransform.matrix[ 3 ] );
|
|
|
|
aMatrix.set(1,1, aTransform.matrix[ 4 ] );
|
|
|
|
aMatrix.set(1,2, aTransform.matrix[ 5 ] );
|
|
|
|
|
|
|
|
::basegfx::B2DHomMatrix aScale;
|
|
|
|
aScale.scale( aBmpSize.Width(),
|
|
|
|
aBmpSize.Height() );
|
|
|
|
|
|
|
|
// post-multiply with the bitmap
|
|
|
|
// size (XCanvas' texture assumes
|
|
|
|
// the given bitmap to be
|
|
|
|
// normalized to [0,1]x[0,1]
|
|
|
|
// rectangle)
|
|
|
|
aMatrix = aMatrix * aScale;
|
|
|
|
|
|
|
|
// pre-multiply with the
|
|
|
|
// logic-to-pixel scale factor
|
|
|
|
// (the metafile comment works in
|
|
|
|
// logical coordinates).
|
|
|
|
::basegfx::B2DHomMatrix aLogic2PixelTransform;
|
|
|
|
aMatrix *= tools::calcLogic2PixelLinearTransform( aLogic2PixelTransform,
|
|
|
|
rVDev );
|
|
|
|
|
|
|
|
::basegfx::unotools::affineMatrixFromHomMatrix(
|
|
|
|
aTexture.AffineTransform,
|
|
|
|
aMatrix );
|
|
|
|
|
|
|
|
aTexture.Alpha = 1.0 - aFill.getTransparency();
|
|
|
|
aTexture.Bitmap =
|
|
|
|
::vcl::unotools::xBitmapFromBitmapEx(
|
|
|
|
rCanvas->getUNOCanvas()->getDevice(),
|
|
|
|
aBmpEx );
|
|
|
|
aTexture.RepeatModeX = rendering::TexturingMode::REPEAT;
|
|
|
|
aTexture.RepeatModeY = rendering::TexturingMode::REPEAT;
|
|
|
|
|
|
|
|
::PolyPolygon aPath;
|
|
|
|
aFill.getPath( aPath );
|
|
|
|
|
2007-01-22 10:49:42 +00:00
|
|
|
::basegfx::B2DPolyPolygon aPoly( aPath.getB2DPolyPolygon() );
|
|
|
|
aPoly.transform( getState( rStates ).mapModeTransform );
|
2005-03-30 07:27:39 +00:00
|
|
|
ActionSharedPtr pPolyAction(
|
|
|
|
internal::PolyPolyActionFactory::createPolyPolyAction(
|
2007-01-22 10:49:42 +00:00
|
|
|
aPoly,
|
2005-03-30 07:27:39 +00:00
|
|
|
rCanvas,
|
|
|
|
getState( rStates ),
|
|
|
|
aTexture ) );
|
2004-03-18 09:41:15 +00:00
|
|
|
|
2005-03-30 07:27:39 +00:00
|
|
|
if( pPolyAction )
|
2004-03-18 09:41:15 +00:00
|
|
|
{
|
2005-03-30 07:27:39 +00:00
|
|
|
maActions.push_back(
|
|
|
|
MtfAction(
|
|
|
|
pPolyAction,
|
|
|
|
io_rCurrActionIndex ) );
|
2004-03-18 09:41:15 +00:00
|
|
|
|
2005-03-30 07:27:39 +00:00
|
|
|
io_rCurrActionIndex += pPolyAction->getActionCount()-1;
|
2004-03-18 09:41:15 +00:00
|
|
|
}
|
|
|
|
|
2005-03-30 07:27:39 +00:00
|
|
|
// skip broken-down render output
|
|
|
|
skipContent( rMtf,
|
|
|
|
"XPATHFILL_SEQ_END",
|
|
|
|
io_rCurrActionIndex );
|
|
|
|
}
|
2004-03-18 09:41:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
// ------------------------------------------------------------
|
|
|
|
|
|
|
|
// In the third part of this monster-switch, we
|
|
|
|
// handle all 'acting' meta actions. These are all
|
|
|
|
// processed by constructing function objects for
|
|
|
|
// them, which will later ease caching.
|
|
|
|
|
|
|
|
// ------------------------------------------------------------
|
|
|
|
|
|
|
|
case META_POINT_ACTION:
|
|
|
|
{
|
2004-11-26 19:54:32 +00:00
|
|
|
const OutDevState& rState( getState( rStates ) );
|
|
|
|
if( rState.lineColor.getLength() )
|
|
|
|
{
|
2005-03-30 07:27:39 +00:00
|
|
|
ActionSharedPtr pPointAction(
|
|
|
|
internal::PointActionFactory::createPointAction(
|
2007-01-22 10:49:42 +00:00
|
|
|
rState.mapModeTransform * ::vcl::unotools::b2DPointFromPoint(
|
|
|
|
static_cast<MetaPointAction*>(pCurrAct)->GetPoint() ),
|
2005-03-30 07:27:39 +00:00
|
|
|
rCanvas,
|
|
|
|
rState ) );
|
|
|
|
|
|
|
|
if( pPointAction )
|
|
|
|
{
|
|
|
|
maActions.push_back(
|
|
|
|
MtfAction(
|
|
|
|
pPointAction,
|
|
|
|
io_rCurrActionIndex ) );
|
|
|
|
|
|
|
|
io_rCurrActionIndex += pPointAction->getActionCount()-1;
|
|
|
|
}
|
2004-11-26 19:54:32 +00:00
|
|
|
}
|
2004-03-18 09:41:15 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case META_PIXEL_ACTION:
|
|
|
|
{
|
2004-11-26 19:54:32 +00:00
|
|
|
const OutDevState& rState( getState( rStates ) );
|
|
|
|
if( rState.lineColor.getLength() )
|
|
|
|
{
|
2005-03-30 07:27:39 +00:00
|
|
|
ActionSharedPtr pPointAction(
|
|
|
|
internal::PointActionFactory::createPointAction(
|
2007-01-22 10:49:42 +00:00
|
|
|
rState.mapModeTransform * ::vcl::unotools::b2DPointFromPoint(
|
2005-03-30 07:27:39 +00:00
|
|
|
static_cast<MetaPixelAction*>(pCurrAct)->GetPoint() ),
|
|
|
|
rCanvas,
|
|
|
|
rState,
|
|
|
|
static_cast<MetaPixelAction*>(pCurrAct)->GetColor() ) );
|
|
|
|
|
|
|
|
if( pPointAction )
|
|
|
|
{
|
|
|
|
maActions.push_back(
|
|
|
|
MtfAction(
|
|
|
|
pPointAction,
|
|
|
|
io_rCurrActionIndex ) );
|
|
|
|
|
|
|
|
io_rCurrActionIndex += pPointAction->getActionCount()-1;
|
|
|
|
}
|
2004-11-26 19:54:32 +00:00
|
|
|
}
|
2004-03-18 09:41:15 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case META_LINE_ACTION:
|
|
|
|
{
|
2004-11-26 19:54:32 +00:00
|
|
|
const OutDevState& rState( getState( rStates ) );
|
|
|
|
if( rState.lineColor.getLength() )
|
|
|
|
{
|
2005-01-28 14:30:12 +00:00
|
|
|
MetaLineAction* pLineAct = static_cast<MetaLineAction*>(pCurrAct);
|
|
|
|
|
2005-03-30 07:27:39 +00:00
|
|
|
const LineInfo& rLineInfo( pLineAct->GetLineInfo() );
|
|
|
|
|
2007-01-22 10:49:42 +00:00
|
|
|
const ::basegfx::B2DPoint aStartPoint(
|
|
|
|
rState.mapModeTransform * ::vcl::unotools::b2DPointFromPoint( pLineAct->GetStartPoint() ));
|
|
|
|
const ::basegfx::B2DPoint aEndPoint(
|
|
|
|
rState.mapModeTransform * ::vcl::unotools::b2DPointFromPoint( pLineAct->GetEndPoint() ));
|
2005-03-30 07:27:39 +00:00
|
|
|
|
|
|
|
ActionSharedPtr pLineAction;
|
|
|
|
|
|
|
|
if( rLineInfo.IsDefault() )
|
|
|
|
{
|
|
|
|
// plain hair line
|
|
|
|
pLineAction =
|
|
|
|
internal::LineActionFactory::createLineAction(
|
2007-01-22 10:49:42 +00:00
|
|
|
aStartPoint,
|
|
|
|
aEndPoint,
|
2005-03-30 07:27:39 +00:00
|
|
|
rCanvas,
|
|
|
|
rState );
|
|
|
|
|
|
|
|
if( pLineAction )
|
|
|
|
{
|
|
|
|
maActions.push_back(
|
|
|
|
MtfAction(
|
|
|
|
pLineAction,
|
|
|
|
io_rCurrActionIndex ) );
|
|
|
|
|
|
|
|
io_rCurrActionIndex += pLineAction->getActionCount()-1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if( LINE_NONE != rLineInfo.GetStyle() )
|
|
|
|
{
|
|
|
|
// 'thick' line
|
|
|
|
rendering::StrokeAttributes aStrokeAttributes;
|
|
|
|
|
|
|
|
setupStrokeAttributes( aStrokeAttributes,
|
2007-01-22 10:49:42 +00:00
|
|
|
rFactoryParms,
|
2005-03-30 07:27:39 +00:00
|
|
|
rLineInfo );
|
|
|
|
|
|
|
|
// XCanvas can only stroke polygons,
|
|
|
|
// not simple lines - thus, handle
|
|
|
|
// this case via the polypolygon
|
|
|
|
// action
|
2007-01-22 10:49:42 +00:00
|
|
|
::basegfx::B2DPolygon aPoly;
|
|
|
|
aPoly.append( aStartPoint );
|
|
|
|
aPoly.append( aEndPoint );
|
2005-03-30 07:27:39 +00:00
|
|
|
pLineAction =
|
|
|
|
internal::PolyPolyActionFactory::createPolyPolyAction(
|
2007-01-22 10:49:42 +00:00
|
|
|
::basegfx::B2DPolyPolygon( aPoly ),
|
2005-03-30 07:27:39 +00:00
|
|
|
rCanvas, rState, aStrokeAttributes );
|
|
|
|
|
|
|
|
if( pLineAction )
|
|
|
|
{
|
|
|
|
maActions.push_back(
|
|
|
|
MtfAction(
|
|
|
|
pLineAction,
|
|
|
|
io_rCurrActionIndex ) );
|
|
|
|
|
|
|
|
io_rCurrActionIndex += pLineAction->getActionCount()-1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// else: line style is default
|
|
|
|
// (i.e. invisible), don't generate action
|
2004-11-26 19:54:32 +00:00
|
|
|
}
|
2004-03-18 09:41:15 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case META_RECT_ACTION:
|
2005-09-23 13:30:27 +00:00
|
|
|
{
|
2007-01-22 10:49:42 +00:00
|
|
|
const Rectangle& rRect(
|
|
|
|
static_cast<MetaRectAction*>(pCurrAct)->GetRect() );
|
|
|
|
|
|
|
|
if( rRect.IsEmpty() )
|
|
|
|
break;
|
|
|
|
|
|
|
|
const OutDevState& rState( getState( rStates ) );
|
|
|
|
const ::basegfx::B2DPoint aTopLeftPixel(
|
|
|
|
rState.mapModeTransform * ::vcl::unotools::b2DPointFromPoint( rRect.TopLeft() ) );
|
|
|
|
const ::basegfx::B2DPoint aBottomRightPixel(
|
|
|
|
rState.mapModeTransform * ::vcl::unotools::b2DPointFromPoint( rRect.BottomRight() ) +
|
|
|
|
// #121100# OutputDevice::DrawRect() fills
|
|
|
|
// rectangles Apple-like, i.e. with one
|
|
|
|
// additional pixel to the right and bottom.
|
|
|
|
::basegfx::B2DPoint(1,1) );
|
|
|
|
|
|
|
|
createFillAndStroke( ::basegfx::tools::createPolygonFromRect(
|
|
|
|
::basegfx::B2DRange( aTopLeftPixel,
|
|
|
|
aBottomRightPixel )),
|
|
|
|
rFactoryParms );
|
2004-03-18 09:41:15 +00:00
|
|
|
break;
|
2005-09-23 13:30:27 +00:00
|
|
|
}
|
2004-03-18 09:41:15 +00:00
|
|
|
|
|
|
|
case META_ROUNDRECT_ACTION:
|
2007-01-22 10:49:42 +00:00
|
|
|
{
|
|
|
|
const Rectangle& rRect(
|
|
|
|
static_cast<MetaRoundRectAction*>(pCurrAct)->GetRect());
|
|
|
|
|
|
|
|
if( rRect.IsEmpty() )
|
|
|
|
break;
|
|
|
|
|
|
|
|
::basegfx::B2DPolygon aPoly(
|
|
|
|
::basegfx::tools::createPolygonFromRect(
|
|
|
|
::basegfx::B2DRange(
|
|
|
|
::vcl::unotools::b2DPointFromPoint( rRect.TopLeft() ),
|
|
|
|
::vcl::unotools::b2DPointFromPoint( rRect.BottomRight() ) +
|
|
|
|
::basegfx::B2DPoint(1,1) ),
|
|
|
|
static_cast<MetaRoundRectAction*>(pCurrAct)->GetHorzRound(),
|
|
|
|
static_cast<MetaRoundRectAction*>(pCurrAct)->GetVertRound() ));
|
|
|
|
aPoly.transform( getState( rStates ).mapModeTransform );
|
|
|
|
|
|
|
|
createFillAndStroke( aPoly,
|
|
|
|
rFactoryParms );
|
|
|
|
}
|
|
|
|
break;
|
2004-03-18 09:41:15 +00:00
|
|
|
|
|
|
|
case META_ELLIPSE_ACTION:
|
|
|
|
{
|
2007-01-22 10:49:42 +00:00
|
|
|
const Rectangle& rRect(
|
|
|
|
static_cast<MetaEllipseAction*>(pCurrAct)->GetRect() );
|
|
|
|
|
|
|
|
if( rRect.IsEmpty() )
|
|
|
|
break;
|
|
|
|
|
|
|
|
const ::basegfx::B2DRange aRange(
|
|
|
|
::vcl::unotools::b2DPointFromPoint( rRect.TopLeft() ),
|
|
|
|
::vcl::unotools::b2DPointFromPoint( rRect.BottomRight() ) +
|
|
|
|
::basegfx::B2DPoint(1,1) );
|
|
|
|
|
|
|
|
::basegfx::B2DPolygon aPoly(
|
|
|
|
::basegfx::tools::createPolygonFromEllipse(
|
|
|
|
aRange.getCenter(),
|
|
|
|
aRange.getWidth(),
|
|
|
|
aRange.getHeight() ));
|
|
|
|
aPoly.transform( getState( rStates ).mapModeTransform );
|
|
|
|
|
|
|
|
createFillAndStroke( aPoly,
|
|
|
|
rFactoryParms );
|
2004-03-18 09:41:15 +00:00
|
|
|
}
|
2007-01-22 10:49:42 +00:00
|
|
|
break;
|
2004-03-18 09:41:15 +00:00
|
|
|
|
|
|
|
case META_ARC_ACTION:
|
2007-01-22 10:49:42 +00:00
|
|
|
{
|
|
|
|
// TODO(F1): Missing basegfx functionality. Mind empty rects!
|
|
|
|
const Polygon aToolsPoly( static_cast<MetaArcAction*>(pCurrAct)->GetRect(),
|
|
|
|
static_cast<MetaArcAction*>(pCurrAct)->GetStartPoint(),
|
|
|
|
static_cast<MetaArcAction*>(pCurrAct)->GetEndPoint(), POLY_ARC );
|
|
|
|
::basegfx::B2DPolygon aPoly( aToolsPoly.getB2DPolygon() );
|
|
|
|
aPoly.transform( getState( rStates ).mapModeTransform );
|
|
|
|
|
|
|
|
createFillAndStroke( aPoly,
|
|
|
|
rFactoryParms );
|
|
|
|
}
|
|
|
|
break;
|
2004-03-18 09:41:15 +00:00
|
|
|
|
|
|
|
case META_PIE_ACTION:
|
2007-01-22 10:49:42 +00:00
|
|
|
{
|
|
|
|
// TODO(F1): Missing basegfx functionality. Mind empty rects!
|
|
|
|
const Polygon aToolsPoly( static_cast<MetaPieAction*>(pCurrAct)->GetRect(),
|
|
|
|
static_cast<MetaPieAction*>(pCurrAct)->GetStartPoint(),
|
|
|
|
static_cast<MetaPieAction*>(pCurrAct)->GetEndPoint(), POLY_PIE );
|
|
|
|
::basegfx::B2DPolygon aPoly( aToolsPoly.getB2DPolygon() );
|
|
|
|
aPoly.transform( getState( rStates ).mapModeTransform );
|
|
|
|
|
|
|
|
createFillAndStroke( aPoly,
|
|
|
|
rFactoryParms );
|
|
|
|
}
|
|
|
|
break;
|
2004-03-18 09:41:15 +00:00
|
|
|
|
|
|
|
case META_CHORD_ACTION:
|
2007-01-22 10:49:42 +00:00
|
|
|
{
|
|
|
|
// TODO(F1): Missing basegfx functionality. Mind empty rects!
|
|
|
|
const Polygon aToolsPoly( static_cast<MetaChordAction*>(pCurrAct)->GetRect(),
|
|
|
|
static_cast<MetaChordAction*>(pCurrAct)->GetStartPoint(),
|
|
|
|
static_cast<MetaChordAction*>(pCurrAct)->GetEndPoint(), POLY_CHORD );
|
|
|
|
::basegfx::B2DPolygon aPoly( aToolsPoly.getB2DPolygon() );
|
|
|
|
aPoly.transform( getState( rStates ).mapModeTransform );
|
|
|
|
|
|
|
|
createFillAndStroke( aPoly,
|
|
|
|
rFactoryParms );
|
|
|
|
}
|
|
|
|
break;
|
2004-03-18 09:41:15 +00:00
|
|
|
|
|
|
|
case META_POLYLINE_ACTION:
|
|
|
|
{
|
2004-11-26 19:54:32 +00:00
|
|
|
const OutDevState& rState( getState( rStates ) );
|
|
|
|
if( rState.lineColor.getLength() ||
|
|
|
|
rState.fillColor.getLength() )
|
|
|
|
{
|
2005-01-28 14:30:12 +00:00
|
|
|
MetaPolyLineAction* pPolyLineAct = static_cast<MetaPolyLineAction*>(pCurrAct);
|
|
|
|
|
2005-03-30 07:27:39 +00:00
|
|
|
const LineInfo& rLineInfo( pPolyLineAct->GetLineInfo() );
|
2007-01-22 10:49:42 +00:00
|
|
|
::basegfx::B2DPolygon aPoly( pPolyLineAct->GetPolygon().getB2DPolygon() );
|
|
|
|
aPoly.transform( rState.mapModeTransform );
|
2005-03-30 07:27:39 +00:00
|
|
|
|
|
|
|
ActionSharedPtr pLineAction;
|
|
|
|
|
|
|
|
if( rLineInfo.IsDefault() )
|
|
|
|
{
|
|
|
|
// plain hair line polygon
|
|
|
|
pLineAction =
|
|
|
|
internal::PolyPolyActionFactory::createLinePolyPolyAction(
|
2007-01-22 10:49:42 +00:00
|
|
|
::basegfx::B2DPolyPolygon(aPoly),
|
2005-03-30 07:27:39 +00:00
|
|
|
rCanvas,
|
|
|
|
rState );
|
|
|
|
|
|
|
|
if( pLineAction )
|
|
|
|
{
|
|
|
|
maActions.push_back(
|
|
|
|
MtfAction(
|
|
|
|
pLineAction,
|
|
|
|
io_rCurrActionIndex ) );
|
|
|
|
|
|
|
|
io_rCurrActionIndex += pLineAction->getActionCount()-1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if( LINE_NONE != rLineInfo.GetStyle() )
|
|
|
|
{
|
|
|
|
// 'thick' line polygon
|
|
|
|
rendering::StrokeAttributes aStrokeAttributes;
|
|
|
|
|
|
|
|
setupStrokeAttributes( aStrokeAttributes,
|
2007-01-22 10:49:42 +00:00
|
|
|
rFactoryParms,
|
2005-03-30 07:27:39 +00:00
|
|
|
rLineInfo );
|
|
|
|
|
|
|
|
pLineAction =
|
|
|
|
internal::PolyPolyActionFactory::createPolyPolyAction(
|
2007-01-22 10:49:42 +00:00
|
|
|
::basegfx::B2DPolyPolygon(aPoly),
|
2005-03-30 07:27:39 +00:00
|
|
|
rCanvas,
|
|
|
|
rState,
|
|
|
|
aStrokeAttributes ) ;
|
|
|
|
|
|
|
|
if( pLineAction )
|
|
|
|
{
|
|
|
|
maActions.push_back(
|
|
|
|
MtfAction(
|
|
|
|
pLineAction,
|
|
|
|
io_rCurrActionIndex ) );
|
|
|
|
|
|
|
|
io_rCurrActionIndex += pLineAction->getActionCount()-1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// else: line style is default
|
|
|
|
// (i.e. invisible), don't generate action
|
2004-11-26 19:54:32 +00:00
|
|
|
}
|
2004-03-18 09:41:15 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case META_POLYGON_ACTION:
|
2007-01-22 10:49:42 +00:00
|
|
|
{
|
|
|
|
::basegfx::B2DPolygon aPoly( static_cast<MetaPolygonAction*>(pCurrAct)->GetPolygon().getB2DPolygon() );
|
|
|
|
aPoly.transform( getState( rStates ).mapModeTransform );
|
|
|
|
createFillAndStroke( aPoly,
|
|
|
|
rFactoryParms );
|
|
|
|
}
|
|
|
|
break;
|
2004-03-18 09:41:15 +00:00
|
|
|
|
|
|
|
case META_POLYPOLYGON_ACTION:
|
2007-01-22 10:49:42 +00:00
|
|
|
{
|
|
|
|
::basegfx::B2DPolyPolygon aPoly( static_cast<MetaPolyPolygonAction*>(pCurrAct)->GetPolyPolygon().getB2DPolyPolygon() );
|
|
|
|
aPoly.transform( getState( rStates ).mapModeTransform );
|
|
|
|
createFillAndStroke( aPoly,
|
|
|
|
rFactoryParms );
|
|
|
|
}
|
|
|
|
break;
|
2004-03-18 09:41:15 +00:00
|
|
|
|
|
|
|
case META_BMP_ACTION:
|
|
|
|
{
|
|
|
|
MetaBmpAction* pAct = static_cast<MetaBmpAction*>(pCurrAct);
|
|
|
|
|
2005-03-30 07:27:39 +00:00
|
|
|
ActionSharedPtr pBmpAction(
|
|
|
|
internal::BitmapActionFactory::createBitmapAction(
|
|
|
|
pAct->GetBitmap(),
|
2007-01-22 10:49:42 +00:00
|
|
|
getState( rStates ).mapModeTransform *
|
|
|
|
::vcl::unotools::b2DPointFromPoint( pAct->GetPoint() ),
|
2005-03-30 07:27:39 +00:00
|
|
|
rCanvas,
|
|
|
|
getState( rStates ) ) );
|
|
|
|
|
|
|
|
if( pBmpAction )
|
|
|
|
{
|
|
|
|
maActions.push_back(
|
|
|
|
MtfAction(
|
|
|
|
pBmpAction,
|
|
|
|
io_rCurrActionIndex ) );
|
|
|
|
|
|
|
|
io_rCurrActionIndex += pBmpAction->getActionCount()-1;
|
|
|
|
}
|
2004-03-18 09:41:15 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case META_BMPSCALE_ACTION:
|
|
|
|
{
|
|
|
|
MetaBmpScaleAction* pAct = static_cast<MetaBmpScaleAction*>(pCurrAct);
|
|
|
|
|
2005-03-30 07:27:39 +00:00
|
|
|
ActionSharedPtr pBmpAction(
|
|
|
|
internal::BitmapActionFactory::createBitmapAction(
|
|
|
|
pAct->GetBitmap(),
|
2007-01-22 10:49:42 +00:00
|
|
|
getState( rStates ).mapModeTransform *
|
|
|
|
::vcl::unotools::b2DPointFromPoint( pAct->GetPoint() ),
|
|
|
|
getState( rStates ).mapModeTransform *
|
|
|
|
::vcl::unotools::b2DSizeFromSize( pAct->GetSize() ),
|
2005-03-30 07:27:39 +00:00
|
|
|
rCanvas,
|
|
|
|
getState( rStates ) ) );
|
|
|
|
|
|
|
|
if( pBmpAction )
|
|
|
|
{
|
|
|
|
maActions.push_back(
|
|
|
|
MtfAction(
|
|
|
|
pBmpAction,
|
|
|
|
io_rCurrActionIndex ) );
|
|
|
|
|
|
|
|
io_rCurrActionIndex += pBmpAction->getActionCount()-1;
|
|
|
|
}
|
2004-03-18 09:41:15 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case META_BMPSCALEPART_ACTION:
|
|
|
|
{
|
|
|
|
MetaBmpScalePartAction* pAct = static_cast<MetaBmpScalePartAction*>(pCurrAct);
|
|
|
|
|
2005-03-30 07:27:39 +00:00
|
|
|
// crop bitmap to given source rectangle (no
|
|
|
|
// need to copy and convert the whole bitmap)
|
|
|
|
Bitmap aBmp( pAct->GetBitmap() );
|
|
|
|
const Rectangle aCropRect( pAct->GetSrcPoint(),
|
|
|
|
pAct->GetSrcSize() );
|
|
|
|
aBmp.Crop( aCropRect );
|
|
|
|
|
|
|
|
ActionSharedPtr pBmpAction(
|
|
|
|
internal::BitmapActionFactory::createBitmapAction(
|
|
|
|
aBmp,
|
2007-01-22 10:49:42 +00:00
|
|
|
getState( rStates ).mapModeTransform *
|
|
|
|
::vcl::unotools::b2DPointFromPoint( pAct->GetDestPoint() ),
|
|
|
|
getState( rStates ).mapModeTransform *
|
|
|
|
::vcl::unotools::b2DSizeFromSize( pAct->GetDestSize() ),
|
2005-03-30 07:27:39 +00:00
|
|
|
rCanvas,
|
|
|
|
getState( rStates ) ) );
|
|
|
|
|
|
|
|
if( pBmpAction )
|
|
|
|
{
|
|
|
|
maActions.push_back(
|
|
|
|
MtfAction(
|
|
|
|
pBmpAction,
|
|
|
|
io_rCurrActionIndex ) );
|
|
|
|
|
|
|
|
io_rCurrActionIndex += pBmpAction->getActionCount()-1;
|
|
|
|
}
|
2004-03-18 09:41:15 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case META_BMPEX_ACTION:
|
|
|
|
{
|
|
|
|
MetaBmpExAction* pAct = static_cast<MetaBmpExAction*>(pCurrAct);
|
|
|
|
|
2005-03-30 07:27:39 +00:00
|
|
|
ActionSharedPtr pBmpAction(
|
|
|
|
internal::BitmapActionFactory::createBitmapAction(
|
|
|
|
pAct->GetBitmapEx(),
|
2007-01-22 10:49:42 +00:00
|
|
|
getState( rStates ).mapModeTransform *
|
|
|
|
::vcl::unotools::b2DPointFromPoint( pAct->GetPoint() ),
|
2005-03-30 07:27:39 +00:00
|
|
|
rCanvas,
|
|
|
|
getState( rStates ) ) );
|
|
|
|
|
|
|
|
if( pBmpAction )
|
|
|
|
{
|
|
|
|
maActions.push_back(
|
|
|
|
MtfAction(
|
|
|
|
pBmpAction,
|
|
|
|
io_rCurrActionIndex ) );
|
|
|
|
|
|
|
|
io_rCurrActionIndex += pBmpAction->getActionCount()-1;
|
|
|
|
}
|
2004-03-18 09:41:15 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case META_BMPEXSCALE_ACTION:
|
|
|
|
{
|
|
|
|
MetaBmpExScaleAction* pAct = static_cast<MetaBmpExScaleAction*>(pCurrAct);
|
|
|
|
|
2005-03-30 07:27:39 +00:00
|
|
|
ActionSharedPtr pBmpAction(
|
|
|
|
internal::BitmapActionFactory::createBitmapAction(
|
|
|
|
pAct->GetBitmapEx(),
|
2007-01-22 10:49:42 +00:00
|
|
|
getState( rStates ).mapModeTransform *
|
|
|
|
::vcl::unotools::b2DPointFromPoint( pAct->GetPoint() ),
|
|
|
|
getState( rStates ).mapModeTransform *
|
|
|
|
::vcl::unotools::b2DSizeFromSize( pAct->GetSize() ),
|
2005-03-30 07:27:39 +00:00
|
|
|
rCanvas,
|
|
|
|
getState( rStates ) ) );
|
|
|
|
|
|
|
|
if( pBmpAction )
|
|
|
|
{
|
|
|
|
maActions.push_back(
|
|
|
|
MtfAction(
|
|
|
|
pBmpAction,
|
|
|
|
io_rCurrActionIndex ) );
|
|
|
|
|
|
|
|
io_rCurrActionIndex += pBmpAction->getActionCount()-1;
|
|
|
|
}
|
2004-03-18 09:41:15 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case META_BMPEXSCALEPART_ACTION:
|
|
|
|
{
|
|
|
|
MetaBmpExScalePartAction* pAct = static_cast<MetaBmpExScalePartAction*>(pCurrAct);
|
|
|
|
|
2005-03-30 07:27:39 +00:00
|
|
|
// crop bitmap to given source rectangle (no
|
|
|
|
// need to copy and convert the whole bitmap)
|
|
|
|
BitmapEx aBmp( pAct->GetBitmapEx() );
|
|
|
|
const Rectangle aCropRect( pAct->GetSrcPoint(),
|
|
|
|
pAct->GetSrcSize() );
|
|
|
|
aBmp.Crop( aCropRect );
|
|
|
|
|
|
|
|
ActionSharedPtr pBmpAction(
|
|
|
|
internal::BitmapActionFactory::createBitmapAction(
|
|
|
|
aBmp,
|
2007-01-22 10:49:42 +00:00
|
|
|
getState( rStates ).mapModeTransform *
|
|
|
|
::vcl::unotools::b2DPointFromPoint( pAct->GetDestPoint() ),
|
|
|
|
getState( rStates ).mapModeTransform *
|
|
|
|
::vcl::unotools::b2DSizeFromSize( pAct->GetDestSize() ),
|
2005-03-30 07:27:39 +00:00
|
|
|
rCanvas,
|
|
|
|
getState( rStates ) ) );
|
|
|
|
|
|
|
|
if( pBmpAction )
|
|
|
|
{
|
|
|
|
maActions.push_back(
|
|
|
|
MtfAction(
|
|
|
|
pBmpAction,
|
|
|
|
io_rCurrActionIndex ) );
|
|
|
|
|
|
|
|
io_rCurrActionIndex += pBmpAction->getActionCount()-1;
|
|
|
|
}
|
2004-03-18 09:41:15 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case META_MASK_ACTION:
|
|
|
|
{
|
|
|
|
MetaMaskAction* pAct = static_cast<MetaMaskAction*>(pCurrAct);
|
|
|
|
|
2005-03-30 07:27:39 +00:00
|
|
|
// create masked BitmapEx right here, as the
|
|
|
|
// canvas does not provide equivalent
|
|
|
|
// functionality
|
2005-11-02 12:40:15 +00:00
|
|
|
BitmapEx aBmp( createMaskBmpEx( pAct->GetBitmap(),
|
|
|
|
pAct->GetColor() ));
|
2005-03-30 07:27:39 +00:00
|
|
|
|
|
|
|
ActionSharedPtr pBmpAction(
|
|
|
|
internal::BitmapActionFactory::createBitmapAction(
|
|
|
|
aBmp,
|
2007-01-22 10:49:42 +00:00
|
|
|
getState( rStates ).mapModeTransform *
|
|
|
|
::vcl::unotools::b2DPointFromPoint( pAct->GetPoint() ),
|
2005-03-30 07:27:39 +00:00
|
|
|
rCanvas,
|
|
|
|
getState( rStates ) ) );
|
|
|
|
|
|
|
|
if( pBmpAction )
|
|
|
|
{
|
|
|
|
maActions.push_back(
|
|
|
|
MtfAction(
|
|
|
|
pBmpAction,
|
|
|
|
io_rCurrActionIndex ) );
|
|
|
|
|
|
|
|
io_rCurrActionIndex += pBmpAction->getActionCount()-1;
|
|
|
|
}
|
2004-03-18 09:41:15 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case META_MASKSCALE_ACTION:
|
|
|
|
{
|
|
|
|
MetaMaskScaleAction* pAct = static_cast<MetaMaskScaleAction*>(pCurrAct);
|
|
|
|
|
2005-03-30 07:27:39 +00:00
|
|
|
// create masked BitmapEx right here, as the
|
|
|
|
// canvas does not provide equivalent
|
|
|
|
// functionality
|
2005-11-02 12:40:15 +00:00
|
|
|
BitmapEx aBmp( createMaskBmpEx( pAct->GetBitmap(),
|
|
|
|
pAct->GetColor() ));
|
2005-03-30 07:27:39 +00:00
|
|
|
|
|
|
|
ActionSharedPtr pBmpAction(
|
|
|
|
internal::BitmapActionFactory::createBitmapAction(
|
|
|
|
aBmp,
|
2007-01-22 10:49:42 +00:00
|
|
|
getState( rStates ).mapModeTransform *
|
|
|
|
::vcl::unotools::b2DPointFromPoint( pAct->GetPoint() ),
|
|
|
|
getState( rStates ).mapModeTransform *
|
|
|
|
::vcl::unotools::b2DSizeFromSize( pAct->GetSize() ),
|
2005-03-30 07:27:39 +00:00
|
|
|
rCanvas,
|
|
|
|
getState( rStates ) ) );
|
|
|
|
|
|
|
|
if( pBmpAction )
|
|
|
|
{
|
|
|
|
maActions.push_back(
|
|
|
|
MtfAction(
|
|
|
|
pBmpAction,
|
|
|
|
io_rCurrActionIndex ) );
|
|
|
|
|
|
|
|
io_rCurrActionIndex += pBmpAction->getActionCount()-1;
|
|
|
|
}
|
2004-03-18 09:41:15 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case META_MASKSCALEPART_ACTION:
|
|
|
|
{
|
|
|
|
MetaMaskScalePartAction* pAct = static_cast<MetaMaskScalePartAction*>(pCurrAct);
|
|
|
|
|
2005-03-30 07:27:39 +00:00
|
|
|
// create masked BitmapEx right here, as the
|
|
|
|
// canvas does not provide equivalent
|
|
|
|
// functionality
|
2005-11-02 12:40:15 +00:00
|
|
|
BitmapEx aBmp( createMaskBmpEx( pAct->GetBitmap(),
|
|
|
|
pAct->GetColor() ));
|
2005-03-30 07:27:39 +00:00
|
|
|
|
|
|
|
// crop bitmap to given source rectangle (no
|
|
|
|
// need to copy and convert the whole bitmap)
|
|
|
|
const Rectangle aCropRect( pAct->GetSrcPoint(),
|
|
|
|
pAct->GetSrcSize() );
|
|
|
|
aBmp.Crop( aCropRect );
|
|
|
|
|
|
|
|
ActionSharedPtr pBmpAction(
|
|
|
|
internal::BitmapActionFactory::createBitmapAction(
|
|
|
|
aBmp,
|
2007-01-22 10:49:42 +00:00
|
|
|
getState( rStates ).mapModeTransform *
|
|
|
|
::vcl::unotools::b2DPointFromPoint( pAct->GetDestPoint() ),
|
|
|
|
getState( rStates ).mapModeTransform *
|
|
|
|
::vcl::unotools::b2DSizeFromSize( pAct->GetDestSize() ),
|
2005-03-30 07:27:39 +00:00
|
|
|
rCanvas,
|
|
|
|
getState( rStates ) ) );
|
|
|
|
|
|
|
|
if( pBmpAction )
|
|
|
|
{
|
|
|
|
maActions.push_back(
|
|
|
|
MtfAction(
|
|
|
|
pBmpAction,
|
|
|
|
io_rCurrActionIndex ) );
|
|
|
|
|
|
|
|
io_rCurrActionIndex += pBmpAction->getActionCount()-1;
|
|
|
|
}
|
2004-03-18 09:41:15 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case META_GRADIENTEX_ACTION:
|
2004-11-26 19:54:32 +00:00
|
|
|
// TODO(F1): use native Canvas gradients here
|
2004-03-18 09:41:15 +00:00
|
|
|
// action is ignored here, because redundant to META_GRADIENT_ACTION
|
|
|
|
break;
|
|
|
|
|
|
|
|
case META_WALLPAPER_ACTION:
|
2004-11-26 19:54:32 +00:00
|
|
|
// TODO(F2): NYI
|
2004-03-18 09:41:15 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case META_TRANSPARENT_ACTION:
|
|
|
|
{
|
2004-11-26 19:54:32 +00:00
|
|
|
const OutDevState& rState( getState( rStates ) );
|
|
|
|
if( rState.lineColor.getLength() ||
|
|
|
|
rState.fillColor.getLength() )
|
|
|
|
{
|
|
|
|
MetaTransparentAction* pAct = static_cast<MetaTransparentAction*>(pCurrAct);
|
2007-01-22 10:49:42 +00:00
|
|
|
::basegfx::B2DPolyPolygon aPoly( pAct->GetPolyPolygon().getB2DPolyPolygon() );
|
|
|
|
aPoly.transform( rState.mapModeTransform );
|
2004-11-26 19:54:32 +00:00
|
|
|
|
2005-03-30 07:27:39 +00:00
|
|
|
ActionSharedPtr pPolyAction(
|
|
|
|
internal::PolyPolyActionFactory::createPolyPolyAction(
|
2007-01-22 10:49:42 +00:00
|
|
|
aPoly,
|
2005-03-30 07:27:39 +00:00
|
|
|
rCanvas,
|
|
|
|
rState,
|
|
|
|
pAct->GetTransparence() ) );
|
|
|
|
|
|
|
|
if( pPolyAction )
|
|
|
|
{
|
|
|
|
maActions.push_back(
|
|
|
|
MtfAction(
|
|
|
|
pPolyAction,
|
|
|
|
io_rCurrActionIndex ) );
|
|
|
|
|
|
|
|
io_rCurrActionIndex += pPolyAction->getActionCount()-1;
|
|
|
|
}
|
2004-11-26 19:54:32 +00:00
|
|
|
}
|
|
|
|
}
|
2004-03-18 09:41:15 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case META_FLOATTRANSPARENT_ACTION:
|
|
|
|
{
|
2004-11-26 19:54:32 +00:00
|
|
|
MetaFloatTransparentAction* pAct = static_cast<MetaFloatTransparentAction*>(pCurrAct);
|
|
|
|
|
|
|
|
internal::MtfAutoPtr pMtf(
|
|
|
|
new ::GDIMetaFile( pAct->GetGDIMetaFile() ) );
|
|
|
|
|
|
|
|
// TODO(P2): Use native canvas gradients here (saves a lot of UNO calls)
|
|
|
|
internal::GradientAutoPtr pGradient(
|
|
|
|
new Gradient( pAct->GetGradient() ) );
|
|
|
|
|
|
|
|
DBG_TESTSOLARMUTEX();
|
2004-03-18 09:41:15 +00:00
|
|
|
|
2005-03-30 07:27:39 +00:00
|
|
|
ActionSharedPtr pFloatTransAction(
|
|
|
|
internal::TransparencyGroupActionFactory::createTransparencyGroupAction(
|
|
|
|
pMtf,
|
|
|
|
pGradient,
|
|
|
|
rParms,
|
2007-01-22 10:49:42 +00:00
|
|
|
getState( rStates ).mapModeTransform *
|
|
|
|
::vcl::unotools::b2DPointFromPoint( pAct->GetPoint() ),
|
|
|
|
getState( rStates ).mapModeTransform *
|
|
|
|
::vcl::unotools::b2DSizeFromSize( pAct->GetSize() ),
|
2005-03-30 07:27:39 +00:00
|
|
|
rCanvas,
|
|
|
|
getState( rStates ) ) );
|
|
|
|
|
|
|
|
if( pFloatTransAction )
|
|
|
|
{
|
|
|
|
maActions.push_back(
|
|
|
|
MtfAction(
|
|
|
|
pFloatTransAction,
|
|
|
|
io_rCurrActionIndex ) );
|
|
|
|
|
|
|
|
io_rCurrActionIndex += pFloatTransAction->getActionCount()-1;
|
|
|
|
}
|
2004-11-26 19:54:32 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case META_TEXT_ACTION:
|
|
|
|
{
|
|
|
|
MetaTextAction* pAct = static_cast<MetaTextAction*>(pCurrAct);
|
2007-08-03 10:56:05 +00:00
|
|
|
XubString sText = XubString( pAct->GetText() );
|
|
|
|
|
|
|
|
if( rVDev.GetDigitLanguage())
|
|
|
|
convertToLocalizedNumerals ( sText,rVDev.GetDigitLanguage() );
|
2005-03-30 07:27:39 +00:00
|
|
|
|
|
|
|
createTextAction(
|
2004-11-26 19:54:32 +00:00
|
|
|
pAct->GetPoint(),
|
2007-08-03 10:56:05 +00:00
|
|
|
sText,
|
2004-11-26 19:54:32 +00:00
|
|
|
pAct->GetIndex(),
|
|
|
|
pAct->GetLen() == (USHORT)STRING_LEN ? pAct->GetText().Len() - pAct->GetIndex() : pAct->GetLen(),
|
|
|
|
NULL,
|
2007-01-22 10:49:42 +00:00
|
|
|
rFactoryParms,
|
|
|
|
bSubsettableActions );
|
2004-03-18 09:41:15 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case META_TEXTARRAY_ACTION:
|
|
|
|
{
|
|
|
|
MetaTextArrayAction* pAct = static_cast<MetaTextArrayAction*>(pCurrAct);
|
2007-08-03 10:56:05 +00:00
|
|
|
XubString sText = XubString( pAct->GetText() );
|
|
|
|
|
|
|
|
if( rVDev.GetDigitLanguage())
|
|
|
|
convertToLocalizedNumerals ( sText,rVDev.GetDigitLanguage() );
|
2005-03-30 07:27:39 +00:00
|
|
|
|
|
|
|
createTextAction(
|
2004-11-26 19:54:32 +00:00
|
|
|
pAct->GetPoint(),
|
2007-08-03 10:56:05 +00:00
|
|
|
sText,
|
2004-11-26 19:54:32 +00:00
|
|
|
pAct->GetIndex(),
|
|
|
|
pAct->GetLen() == (USHORT)STRING_LEN ? pAct->GetText().Len() - pAct->GetIndex() : pAct->GetLen(),
|
|
|
|
pAct->GetDXArray(),
|
2007-01-22 10:49:42 +00:00
|
|
|
rFactoryParms,
|
|
|
|
bSubsettableActions );
|
2004-11-26 19:54:32 +00:00
|
|
|
}
|
|
|
|
break;
|
2004-03-18 09:41:15 +00:00
|
|
|
|
2004-11-26 19:54:32 +00:00
|
|
|
case META_TEXTLINE_ACTION:
|
|
|
|
{
|
2007-01-22 10:49:42 +00:00
|
|
|
MetaTextLineAction* pAct = static_cast<MetaTextLineAction*>(pCurrAct);
|
2005-03-30 07:27:39 +00:00
|
|
|
|
2007-01-22 10:49:42 +00:00
|
|
|
const OutDevState& rState( getState( rStates ) );
|
|
|
|
const ::Size aBaselineOffset( tools::getBaselineOffset( rState,
|
|
|
|
rVDev ) );
|
|
|
|
const ::Point aStartPoint( pAct->GetStartPoint() );
|
|
|
|
const ::basegfx::B2DSize aSize( rState.mapModeTransform *
|
|
|
|
::basegfx::B2DSize(pAct->GetWidth(),
|
|
|
|
0 ));
|
2005-03-30 07:27:39 +00:00
|
|
|
|
|
|
|
ActionSharedPtr pPolyAction(
|
|
|
|
PolyPolyActionFactory::createPolyPolyAction(
|
2007-01-22 10:49:42 +00:00
|
|
|
tools::createTextLinesPolyPolygon(
|
|
|
|
rState.mapModeTransform *
|
|
|
|
::basegfx::B2DPoint(
|
|
|
|
::vcl::unotools::b2DPointFromPoint(pAct->GetStartPoint()) +
|
|
|
|
::vcl::unotools::b2DSizeFromSize(aBaselineOffset)),
|
|
|
|
aSize.getX(),
|
|
|
|
tools::createTextLineInfo( rVDev,
|
|
|
|
rState )),
|
2005-03-30 07:27:39 +00:00
|
|
|
rCanvas,
|
|
|
|
rState ) );
|
|
|
|
|
|
|
|
if( pPolyAction.get() )
|
|
|
|
{
|
|
|
|
maActions.push_back(
|
|
|
|
MtfAction(
|
|
|
|
pPolyAction,
|
|
|
|
io_rCurrActionIndex ) );
|
|
|
|
|
|
|
|
io_rCurrActionIndex += pPolyAction->getActionCount()-1;
|
|
|
|
}
|
2004-03-18 09:41:15 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case META_TEXTRECT_ACTION:
|
2005-09-23 13:30:27 +00:00
|
|
|
{
|
|
|
|
MetaTextRectAction* pAct = static_cast<MetaTextRectAction*>(pCurrAct);
|
|
|
|
|
|
|
|
pushState( rStates, PUSH_ALL );
|
|
|
|
|
|
|
|
// use the VDev to break up the text rect
|
|
|
|
// action into readily formatted lines
|
|
|
|
GDIMetaFile aTmpMtf;
|
|
|
|
rVDev.AddTextRectActions( pAct->GetRect(),
|
|
|
|
pAct->GetText(),
|
|
|
|
pAct->GetStyle(),
|
|
|
|
aTmpMtf );
|
|
|
|
|
2007-01-22 10:49:42 +00:00
|
|
|
createActions( aTmpMtf,
|
|
|
|
rFactoryParms,
|
|
|
|
bSubsettableActions );
|
2005-09-23 13:30:27 +00:00
|
|
|
|
|
|
|
popState( rStates );
|
|
|
|
|
2004-11-26 19:54:32 +00:00
|
|
|
break;
|
2005-09-23 13:30:27 +00:00
|
|
|
}
|
2004-11-26 19:54:32 +00:00
|
|
|
|
2004-03-18 09:41:15 +00:00
|
|
|
case META_STRETCHTEXT_ACTION:
|
2005-01-28 14:30:12 +00:00
|
|
|
{
|
|
|
|
MetaStretchTextAction* pAct = static_cast<MetaStretchTextAction*>(pCurrAct);
|
2007-08-03 10:56:05 +00:00
|
|
|
XubString sText = XubString( pAct->GetText() );
|
|
|
|
|
|
|
|
if( rVDev.GetDigitLanguage())
|
|
|
|
convertToLocalizedNumerals ( sText,rVDev.GetDigitLanguage() );
|
2005-01-28 14:30:12 +00:00
|
|
|
|
|
|
|
const USHORT nLen( pAct->GetLen() == (USHORT)STRING_LEN ?
|
|
|
|
pAct->GetText().Len() - pAct->GetIndex() : pAct->GetLen() );
|
|
|
|
|
2007-01-22 10:49:42 +00:00
|
|
|
// #i70897# Nothing to do, actually...
|
|
|
|
if( nLen == 0 )
|
|
|
|
break;
|
|
|
|
|
2005-01-28 14:30:12 +00:00
|
|
|
// have to fit the text into the given
|
|
|
|
// width. This is achieved by internally
|
|
|
|
// generating a DX array, and uniformly
|
|
|
|
// distributing the excess/insufficient width
|
|
|
|
// to every logical character.
|
|
|
|
::boost::scoped_array< sal_Int32 > pDXArray( new sal_Int32[nLen] );
|
|
|
|
|
|
|
|
rVDev.GetTextArray( pAct->GetText(), pDXArray.get(),
|
|
|
|
pAct->GetIndex(), pAct->GetLen() );
|
|
|
|
|
|
|
|
const sal_Int32 nWidthDifference( pAct->GetWidth() - pDXArray[ nLen-1 ] );
|
|
|
|
|
|
|
|
// Last entry of pDXArray contains total width of the text
|
|
|
|
sal_Int32* p=pDXArray.get();
|
|
|
|
for( USHORT i=1; i<=nLen; ++i )
|
|
|
|
{
|
|
|
|
// calc ratio for every array entry, to
|
|
|
|
// distribute rounding errors 'evenly'
|
|
|
|
// across the characters. Note that each
|
|
|
|
// entry represents the 'end' position of
|
|
|
|
// the corresponding character, thus, we
|
|
|
|
// let i run from 1 to nLen.
|
|
|
|
*p++ += (sal_Int32)i*nWidthDifference/nLen;
|
|
|
|
}
|
|
|
|
|
2005-03-30 07:27:39 +00:00
|
|
|
createTextAction(
|
2005-01-28 14:30:12 +00:00
|
|
|
pAct->GetPoint(),
|
2007-08-03 10:56:05 +00:00
|
|
|
sText,
|
2005-01-28 14:30:12 +00:00
|
|
|
pAct->GetIndex(),
|
|
|
|
pAct->GetLen() == (USHORT)STRING_LEN ? pAct->GetText().Len() - pAct->GetIndex() : pAct->GetLen(),
|
|
|
|
pDXArray.get(),
|
2007-01-22 10:49:42 +00:00
|
|
|
rFactoryParms,
|
|
|
|
bSubsettableActions );
|
2005-01-28 14:30:12 +00:00
|
|
|
}
|
|
|
|
break;
|
2004-03-18 09:41:15 +00:00
|
|
|
|
|
|
|
default:
|
2005-03-30 07:27:39 +00:00
|
|
|
OSL_ENSURE( false,
|
|
|
|
"Unknown meta action type encountered" );
|
2004-03-18 09:41:15 +00:00
|
|
|
break;
|
|
|
|
}
|
2005-03-30 07:27:39 +00:00
|
|
|
|
|
|
|
// increment action index (each mtf action counts _at
|
|
|
|
// least_ one. Some count for more, therefore,
|
|
|
|
// io_rCurrActionIndex is sometimes incremented by
|
|
|
|
// pAct->getActionCount()-1 above, the -1 being the
|
|
|
|
// correction for the unconditional increment here).
|
|
|
|
++io_rCurrActionIndex;
|
2004-03-18 09:41:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2005-04-18 08:59:07 +00:00
|
|
|
|
|
|
|
namespace
|
|
|
|
{
|
|
|
|
class ActionRenderer
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
ActionRenderer( const ::basegfx::B2DHomMatrix& rTransformation ) :
|
|
|
|
maTransformation( rTransformation ),
|
|
|
|
mbRet( true )
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
bool result()
|
|
|
|
{
|
|
|
|
return mbRet;
|
|
|
|
}
|
|
|
|
|
|
|
|
void operator()( const ::cppcanvas::internal::ImplRenderer::MtfAction& rAction )
|
|
|
|
{
|
|
|
|
// ANDing the result. We want to fail if at least
|
|
|
|
// one action failed.
|
|
|
|
mbRet &= rAction.mpAction->render( maTransformation );
|
|
|
|
}
|
|
|
|
|
|
|
|
void operator()( const ::cppcanvas::internal::ImplRenderer::MtfAction& rAction,
|
|
|
|
const Action::Subset& rSubset )
|
|
|
|
{
|
|
|
|
// ANDing the result. We want to fail if at least
|
|
|
|
// one action failed.
|
|
|
|
mbRet &= rAction.mpAction->render( maTransformation,
|
|
|
|
rSubset );
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
2005-05-03 13:11:22 +00:00
|
|
|
::basegfx::B2DHomMatrix maTransformation;
|
|
|
|
bool mbRet;
|
2005-04-18 08:59:07 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
class AreaQuery
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
AreaQuery( const ::basegfx::B2DHomMatrix& rTransformation ) :
|
|
|
|
maTransformation( rTransformation ),
|
|
|
|
maBounds()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
bool result()
|
|
|
|
{
|
|
|
|
return true; // nothing can fail here
|
|
|
|
}
|
|
|
|
|
|
|
|
void operator()( const ::cppcanvas::internal::ImplRenderer::MtfAction& rAction )
|
|
|
|
{
|
|
|
|
maBounds.expand( rAction.mpAction->getBounds( maTransformation ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
void operator()( const ::cppcanvas::internal::ImplRenderer::MtfAction& rAction,
|
|
|
|
const Action::Subset& rSubset )
|
|
|
|
{
|
|
|
|
maBounds.expand( rAction.mpAction->getBounds( maTransformation,
|
|
|
|
rSubset ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
::basegfx::B2DRange getBounds() const
|
|
|
|
{
|
|
|
|
return maBounds;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
2005-05-03 13:11:22 +00:00
|
|
|
::basegfx::B2DHomMatrix maTransformation;
|
|
|
|
::basegfx::B2DRange maBounds;
|
2005-04-18 08:59:07 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
// Doing that via inline class. Compilers tend to not inline free
|
|
|
|
// functions.
|
|
|
|
struct UpperBoundActionIndexComparator
|
|
|
|
{
|
|
|
|
bool operator()( const ::cppcanvas::internal::ImplRenderer::MtfAction& rLHS,
|
|
|
|
const ::cppcanvas::internal::ImplRenderer::MtfAction& rRHS )
|
|
|
|
{
|
|
|
|
const sal_Int32 nLHSCount( rLHS.mpAction ?
|
|
|
|
rLHS.mpAction->getActionCount() : 0 );
|
|
|
|
const sal_Int32 nRHSCount( rRHS.mpAction ?
|
|
|
|
rRHS.mpAction->getActionCount() : 0 );
|
|
|
|
|
|
|
|
// compare end of action range, to have an action selected
|
|
|
|
// by lower_bound even if the requested index points in
|
|
|
|
// the middle of the action's range
|
|
|
|
return rLHS.mnOrigIndex + nLHSCount < rRHS.mnOrigIndex + nRHSCount;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
/** Algorithm to apply given functor to a subset range
|
|
|
|
|
|
|
|
@tpl Functor
|
|
|
|
|
|
|
|
Functor to call for each element of the subset
|
|
|
|
range. Must provide the following method signatures:
|
|
|
|
bool result() (returning false if operation failed)
|
|
|
|
|
|
|
|
*/
|
|
|
|
template< typename Functor > bool
|
|
|
|
forSubsetRange( Functor& rFunctor,
|
|
|
|
ImplRenderer::ActionVector::const_iterator aRangeBegin,
|
|
|
|
ImplRenderer::ActionVector::const_iterator aRangeEnd,
|
|
|
|
sal_Int32 nStartIndex,
|
|
|
|
sal_Int32 nEndIndex,
|
|
|
|
const ImplRenderer::ActionVector::const_iterator& rEnd )
|
|
|
|
{
|
|
|
|
if( aRangeBegin == aRangeEnd )
|
|
|
|
{
|
|
|
|
// only a single action. Setup subset, and call functor
|
|
|
|
Action::Subset aSubset;
|
2006-02-28 09:48:34 +00:00
|
|
|
aSubset.mnSubsetBegin = ::std::max( sal_Int32( 0 ),
|
2005-04-18 08:59:07 +00:00
|
|
|
nStartIndex - aRangeBegin->mnOrigIndex );
|
|
|
|
aSubset.mnSubsetEnd = ::std::min( aRangeBegin->mpAction->getActionCount(),
|
|
|
|
nEndIndex - aRangeBegin->mnOrigIndex );
|
|
|
|
|
2008-06-24 10:47:23 +00:00
|
|
|
ENSURE_OR_RETURN( aSubset.mnSubsetBegin >= 0 && aSubset.mnSubsetEnd >= 0,
|
|
|
|
"ImplRenderer::forSubsetRange(): Invalid indices" );
|
2005-04-18 08:59:07 +00:00
|
|
|
|
|
|
|
rFunctor( *aRangeBegin, aSubset );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// more than one action.
|
|
|
|
|
|
|
|
// render partial first, full intermediate, and
|
|
|
|
// partial last action
|
|
|
|
Action::Subset aSubset;
|
2006-02-28 09:48:34 +00:00
|
|
|
aSubset.mnSubsetBegin = ::std::max( sal_Int32( 0 ),
|
2005-04-18 08:59:07 +00:00
|
|
|
nStartIndex - aRangeBegin->mnOrigIndex );
|
|
|
|
aSubset.mnSubsetEnd = aRangeBegin->mpAction->getActionCount();
|
|
|
|
|
2008-06-24 10:47:23 +00:00
|
|
|
ENSURE_OR_RETURN( aSubset.mnSubsetBegin >= 0 && aSubset.mnSubsetEnd >= 0,
|
|
|
|
"ImplRenderer::forSubsetRange(): Invalid indices" );
|
2005-04-18 08:59:07 +00:00
|
|
|
|
|
|
|
rFunctor( *aRangeBegin, aSubset );
|
|
|
|
|
|
|
|
// first action rendered, skip to next
|
|
|
|
++aRangeBegin;
|
|
|
|
|
|
|
|
// render full middle actions
|
2005-11-02 12:40:15 +00:00
|
|
|
while( aRangeBegin != aRangeEnd )
|
|
|
|
rFunctor( *aRangeBegin++ );
|
2005-04-18 08:59:07 +00:00
|
|
|
|
|
|
|
if( aRangeEnd == rEnd ||
|
|
|
|
aRangeEnd->mnOrigIndex > nEndIndex )
|
|
|
|
{
|
|
|
|
// aRangeEnd denotes end of action vector,
|
|
|
|
//
|
|
|
|
// or
|
|
|
|
//
|
|
|
|
// nEndIndex references something _after_
|
|
|
|
// aRangeBegin, but _before_ aRangeEnd
|
|
|
|
//
|
|
|
|
// either way: no partial action left
|
2005-11-02 12:40:15 +00:00
|
|
|
return rFunctor.result();
|
2005-04-18 08:59:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
aSubset.mnSubsetBegin = 0;
|
|
|
|
aSubset.mnSubsetEnd = nEndIndex - aRangeEnd->mnOrigIndex;
|
|
|
|
|
2008-06-24 10:47:23 +00:00
|
|
|
ENSURE_OR_RETURN( aSubset.mnSubsetBegin >= 0 && aSubset.mnSubsetEnd >= 0,
|
|
|
|
"ImplRenderer::forSubsetRange(): Invalid indices" );
|
2005-04-18 08:59:07 +00:00
|
|
|
|
|
|
|
rFunctor( *aRangeEnd, aSubset );
|
|
|
|
}
|
2005-11-02 12:40:15 +00:00
|
|
|
|
|
|
|
return rFunctor.result();
|
2005-04-18 08:59:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ImplRenderer::getSubsetIndices( sal_Int32& io_rStartIndex,
|
|
|
|
sal_Int32& io_rEndIndex,
|
|
|
|
ActionVector::const_iterator& o_rRangeBegin,
|
|
|
|
ActionVector::const_iterator& o_rRangeEnd ) const
|
|
|
|
{
|
2008-06-24 10:47:23 +00:00
|
|
|
ENSURE_OR_RETURN( io_rStartIndex<=io_rEndIndex,
|
|
|
|
"ImplRenderer::getSubsetIndices(): invalid action range" );
|
2005-04-18 08:59:07 +00:00
|
|
|
|
2008-06-24 10:47:23 +00:00
|
|
|
ENSURE_OR_RETURN( !maActions.empty(),
|
|
|
|
"ImplRenderer::getSubsetIndices(): no actions to render" );
|
2005-04-18 08:59:07 +00:00
|
|
|
|
|
|
|
const sal_Int32 nMinActionIndex( maActions.front().mnOrigIndex );
|
|
|
|
const sal_Int32 nMaxActionIndex( maActions.back().mnOrigIndex +
|
|
|
|
maActions.back().mpAction->getActionCount() );
|
|
|
|
|
|
|
|
// clip given range to permissible values (there might be
|
|
|
|
// ranges before and behind the valid indices)
|
|
|
|
io_rStartIndex = ::std::max( nMinActionIndex,
|
|
|
|
io_rStartIndex );
|
|
|
|
io_rEndIndex = ::std::min( nMaxActionIndex,
|
|
|
|
io_rEndIndex );
|
|
|
|
|
|
|
|
if( io_rStartIndex == io_rEndIndex ||
|
|
|
|
io_rStartIndex > io_rEndIndex )
|
|
|
|
{
|
|
|
|
// empty range, don't render anything. The second
|
|
|
|
// condition e.g. happens if the requested range lies
|
|
|
|
// fully before or behind the valid action indices.
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const ActionVector::const_iterator aBegin( maActions.begin() );
|
|
|
|
const ActionVector::const_iterator aEnd( maActions.end() );
|
|
|
|
|
|
|
|
|
|
|
|
// find start and end action
|
|
|
|
// =========================
|
|
|
|
o_rRangeBegin = ::std::lower_bound( aBegin, aEnd,
|
|
|
|
MtfAction( ActionSharedPtr(), io_rStartIndex ),
|
|
|
|
UpperBoundActionIndexComparator() );
|
|
|
|
o_rRangeEnd = ::std::lower_bound( aBegin, aEnd,
|
|
|
|
MtfAction( ActionSharedPtr(), io_rEndIndex ),
|
|
|
|
UpperBoundActionIndexComparator() );
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Public methods
|
|
|
|
// ====================================================================
|
|
|
|
|
2004-03-18 09:41:15 +00:00
|
|
|
ImplRenderer::ImplRenderer( const CanvasSharedPtr& rCanvas,
|
2004-11-26 19:54:32 +00:00
|
|
|
const GDIMetaFile& rMtf,
|
|
|
|
const Parameters& rParams ) :
|
2004-03-18 09:41:15 +00:00
|
|
|
CanvasGraphicHelper( rCanvas ),
|
|
|
|
maActions()
|
|
|
|
{
|
2004-11-26 19:54:32 +00:00
|
|
|
RTL_LOGFILE_CONTEXT( aLog, "::cppcanvas::internal::ImplRenderer::ImplRenderer(mtf)" );
|
|
|
|
|
2004-03-18 09:41:15 +00:00
|
|
|
OSL_ENSURE( rCanvas.get() != NULL && rCanvas->getUNOCanvas().is(),
|
|
|
|
"ImplRenderer::ImplRenderer(): Invalid canvas" );
|
|
|
|
OSL_ENSURE( rCanvas->getUNOCanvas()->getDevice().is(),
|
|
|
|
"ImplRenderer::ImplRenderer(): Invalid graphic device" );
|
|
|
|
|
|
|
|
// make sure canvas and graphic device are valid; action
|
|
|
|
// creation don't check that every time
|
|
|
|
if( rCanvas.get() == NULL ||
|
|
|
|
!rCanvas->getUNOCanvas().is() ||
|
|
|
|
!rCanvas->getUNOCanvas()->getDevice().is() )
|
|
|
|
{
|
|
|
|
// leave actions empty
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
VectorOfOutDevStates aStateStack;
|
|
|
|
|
|
|
|
VirtualDevice aVDev;
|
|
|
|
aVDev.EnableOutput( FALSE );
|
|
|
|
|
|
|
|
// Setup VDev for state tracking and mapping
|
|
|
|
// =========================================
|
|
|
|
|
|
|
|
aVDev.SetMapMode( rMtf.GetPrefMapMode() );
|
|
|
|
|
2004-11-26 19:54:32 +00:00
|
|
|
const Size aMtfSize( rMtf.GetPrefSize() );
|
2005-03-30 07:27:39 +00:00
|
|
|
const Size aMtfSizePixPre( aVDev.LogicToPixel( aMtfSize,
|
|
|
|
rMtf.GetPrefMapMode() ) );
|
2004-03-18 09:41:15 +00:00
|
|
|
const Point aEmptyPt;
|
|
|
|
const Point aMtfOriginPix( aVDev.LogicToPixel( aEmptyPt ) );
|
|
|
|
|
2005-03-30 07:27:39 +00:00
|
|
|
// #i44110# correct null-sized output - there are shapes
|
|
|
|
// which have zero size in at least one dimension
|
|
|
|
const Size aMtfSizePix( ::std::max( aMtfSizePixPre.Width(), 1L ),
|
|
|
|
::std::max( aMtfSizePixPre.Height(), 1L ) );
|
2004-03-18 09:41:15 +00:00
|
|
|
|
2007-01-22 10:49:42 +00:00
|
|
|
sal_Int32 nCurrActions(0);
|
|
|
|
ActionFactoryParameters aParms(aStateStack,
|
|
|
|
rCanvas,
|
|
|
|
aVDev,
|
|
|
|
rParams,
|
|
|
|
nCurrActions );
|
|
|
|
|
2005-03-30 07:27:39 +00:00
|
|
|
// init state stack
|
|
|
|
clearStateStack( aStateStack );
|
2004-03-18 09:41:15 +00:00
|
|
|
|
2005-03-30 07:27:39 +00:00
|
|
|
// Setup local state, such that the metafile renders
|
2005-10-11 08:03:07 +00:00
|
|
|
// itself into a one-by-one square at the origin for
|
|
|
|
// identity view and render transformations
|
2005-03-30 07:27:39 +00:00
|
|
|
getState( aStateStack ).transform.scale( 1.0 / aMtfSizePix.Width(),
|
|
|
|
1.0 / aMtfSizePix.Height() );
|
2004-11-26 19:54:32 +00:00
|
|
|
|
2007-01-22 10:49:42 +00:00
|
|
|
tools::calcLogic2PixelAffineTransform( getState( aStateStack ).mapModeTransform,
|
|
|
|
aVDev );
|
|
|
|
|
2005-03-30 07:27:39 +00:00
|
|
|
ColorSharedPtr pColor( getCanvas()->createColor() );
|
2004-11-26 19:54:32 +00:00
|
|
|
|
2005-03-30 07:27:39 +00:00
|
|
|
// setup default text color to black
|
|
|
|
getState( aStateStack ).textColor =
|
|
|
|
getState( aStateStack ).textFillColor =
|
|
|
|
getState( aStateStack ).textLineColor = pColor->getDeviceColor( 0x000000FF );
|
2004-11-26 19:54:32 +00:00
|
|
|
|
2005-03-30 07:27:39 +00:00
|
|
|
// apply overrides from the Parameters struct
|
|
|
|
if( rParams.maFillColor.isValid() )
|
|
|
|
{
|
|
|
|
getState( aStateStack ).isFillColorSet = true;
|
|
|
|
getState( aStateStack ).fillColor = pColor->getDeviceColor( rParams.maFillColor.getValue() );
|
|
|
|
}
|
|
|
|
if( rParams.maLineColor.isValid() )
|
|
|
|
{
|
|
|
|
getState( aStateStack ).isLineColorSet = true;
|
|
|
|
getState( aStateStack ).lineColor = pColor->getDeviceColor( rParams.maLineColor.getValue() );
|
|
|
|
}
|
|
|
|
if( rParams.maTextColor.isValid() )
|
|
|
|
{
|
|
|
|
getState( aStateStack ).isTextFillColorSet = true;
|
|
|
|
getState( aStateStack ).isTextLineColorSet = true;
|
|
|
|
getState( aStateStack ).textColor =
|
|
|
|
getState( aStateStack ).textFillColor =
|
|
|
|
getState( aStateStack ).textLineColor = pColor->getDeviceColor( rParams.maTextColor.getValue() );
|
|
|
|
}
|
|
|
|
if( rParams.maFontName.isValid() ||
|
|
|
|
rParams.maFontWeight.isValid() ||
|
|
|
|
rParams.maFontLetterForm.isValid() ||
|
|
|
|
rParams.maFontUnderline.isValid() )
|
|
|
|
{
|
|
|
|
::cppcanvas::internal::OutDevState& rState = getState( aStateStack );
|
2004-11-26 19:54:32 +00:00
|
|
|
|
2005-03-30 07:27:39 +00:00
|
|
|
rState.xFont = createFont( rState.fontRotation,
|
|
|
|
::Font(), // default font
|
2007-01-22 10:49:42 +00:00
|
|
|
aParms );
|
2004-03-18 09:41:15 +00:00
|
|
|
}
|
2005-03-30 07:27:39 +00:00
|
|
|
|
2007-01-22 10:49:42 +00:00
|
|
|
createActions( const_cast<GDIMetaFile&>(rMtf), // HACK(Q2):
|
2005-03-30 07:27:39 +00:00
|
|
|
// we're
|
|
|
|
// changing
|
|
|
|
// the
|
|
|
|
// current
|
|
|
|
// action
|
|
|
|
// in
|
|
|
|
// createActions!
|
2007-01-22 10:49:42 +00:00
|
|
|
aParms,
|
|
|
|
true // TODO(P1): make subsettability configurable
|
|
|
|
);
|
2004-03-18 09:41:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ImplRenderer::ImplRenderer( const CanvasSharedPtr& rCanvas,
|
2004-11-26 19:54:32 +00:00
|
|
|
const BitmapEx& rBmpEx,
|
|
|
|
const Parameters& rParams ) :
|
2004-03-18 09:41:15 +00:00
|
|
|
CanvasGraphicHelper( rCanvas ),
|
|
|
|
maActions()
|
|
|
|
{
|
2006-10-12 13:59:41 +00:00
|
|
|
// TODO(F3): property modification parameters are
|
|
|
|
// currently ignored for Bitmaps
|
|
|
|
(void)rParams;
|
|
|
|
|
2004-11-26 19:54:32 +00:00
|
|
|
RTL_LOGFILE_CONTEXT( aLog, "::cppcanvas::internal::ImplRenderer::ImplRenderer(bitmap)" );
|
|
|
|
|
2004-03-18 09:41:15 +00:00
|
|
|
OSL_ENSURE( rCanvas.get() != NULL && rCanvas->getUNOCanvas().is(),
|
|
|
|
"ImplRenderer::ImplRenderer(): Invalid canvas" );
|
|
|
|
OSL_ENSURE( rCanvas->getUNOCanvas()->getDevice().is(),
|
|
|
|
"ImplRenderer::ImplRenderer(): Invalid graphic device" );
|
|
|
|
|
|
|
|
// make sure canvas and graphic device are valid; action
|
|
|
|
// creation don't check that every time
|
|
|
|
if( rCanvas.get() == NULL ||
|
|
|
|
!rCanvas->getUNOCanvas().is() ||
|
|
|
|
!rCanvas->getUNOCanvas()->getDevice().is() )
|
|
|
|
{
|
|
|
|
// leave actions empty
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
OutDevState aState;
|
|
|
|
|
|
|
|
const Size aBmpSize( rBmpEx.GetSizePixel() );
|
|
|
|
|
|
|
|
// Setup local state, such that the bitmap renders itself
|
|
|
|
// into a one-by-one square for identity view and render
|
|
|
|
// transformations
|
|
|
|
aState.transform.scale( 1.0 / aBmpSize.Width(),
|
|
|
|
1.0 / aBmpSize.Height() );
|
|
|
|
|
|
|
|
// create a single action for the provided BitmapEx
|
|
|
|
maActions.push_back(
|
|
|
|
MtfAction(
|
2005-03-30 07:27:39 +00:00
|
|
|
BitmapActionFactory::createBitmapAction(
|
|
|
|
rBmpEx,
|
2007-01-22 10:49:42 +00:00
|
|
|
::basegfx::B2DPoint(),
|
2005-03-30 07:27:39 +00:00
|
|
|
rCanvas,
|
|
|
|
aState),
|
2004-03-18 09:41:15 +00:00
|
|
|
0 ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
ImplRenderer::~ImplRenderer()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2005-03-30 07:27:39 +00:00
|
|
|
bool ImplRenderer::drawSubset( sal_Int32 nStartIndex,
|
|
|
|
sal_Int32 nEndIndex ) const
|
2004-03-18 09:41:15 +00:00
|
|
|
{
|
2005-04-18 08:59:07 +00:00
|
|
|
RTL_LOGFILE_CONTEXT( aLog, "::cppcanvas::internal::ImplRenderer::drawSubset()" );
|
2005-03-30 07:27:39 +00:00
|
|
|
|
2005-04-18 08:59:07 +00:00
|
|
|
ActionVector::const_iterator aRangeBegin;
|
|
|
|
ActionVector::const_iterator aRangeEnd;
|
2004-03-18 09:41:15 +00:00
|
|
|
|
2007-07-17 14:24:30 +00:00
|
|
|
try
|
|
|
|
{
|
|
|
|
if( !getSubsetIndices( nStartIndex, nEndIndex,
|
|
|
|
aRangeBegin, aRangeEnd ) )
|
|
|
|
return true; // nothing to render (but _that_ was successful)
|
2005-03-30 07:27:39 +00:00
|
|
|
|
2007-07-17 14:24:30 +00:00
|
|
|
// now, aRangeBegin references the action in which the
|
|
|
|
// subset rendering must start, and aRangeEnd references
|
|
|
|
// the action in which the subset rendering must end (it
|
|
|
|
// might also end right at the start of the referenced
|
|
|
|
// action, such that zero of that action needs to be
|
|
|
|
// rendered).
|
2005-03-30 07:27:39 +00:00
|
|
|
|
|
|
|
|
2007-07-17 14:24:30 +00:00
|
|
|
// render subset of actions
|
|
|
|
// ========================
|
2004-03-18 09:41:15 +00:00
|
|
|
|
2007-07-17 14:24:30 +00:00
|
|
|
::basegfx::B2DHomMatrix aMatrix;
|
|
|
|
::canvas::tools::getRenderStateTransform( aMatrix,
|
|
|
|
getRenderState() );
|
|
|
|
|
|
|
|
ActionRenderer aRenderer( aMatrix );
|
2004-11-26 19:54:32 +00:00
|
|
|
|
2007-07-17 14:24:30 +00:00
|
|
|
return forSubsetRange( aRenderer,
|
|
|
|
aRangeBegin,
|
|
|
|
aRangeEnd,
|
|
|
|
nStartIndex,
|
|
|
|
nEndIndex,
|
|
|
|
maActions.end() );
|
|
|
|
}
|
|
|
|
catch( uno::Exception& )
|
|
|
|
{
|
|
|
|
OSL_ENSURE( false,
|
|
|
|
rtl::OUStringToOString(
|
|
|
|
comphelper::anyToString( cppu::getCaughtException() ),
|
|
|
|
RTL_TEXTENCODING_UTF8 ).getStr() );
|
2005-03-30 07:27:39 +00:00
|
|
|
|
2007-07-17 14:24:30 +00:00
|
|
|
// convert error to return value
|
|
|
|
return false;
|
|
|
|
}
|
2005-04-18 08:59:07 +00:00
|
|
|
}
|
2005-03-30 07:27:39 +00:00
|
|
|
|
2005-04-18 08:59:07 +00:00
|
|
|
::basegfx::B2DRange ImplRenderer::getSubsetArea( sal_Int32 nStartIndex,
|
|
|
|
sal_Int32 nEndIndex ) const
|
|
|
|
{
|
|
|
|
RTL_LOGFILE_CONTEXT( aLog, "::cppcanvas::internal::ImplRenderer::getSubsetArea()" );
|
2005-03-30 07:27:39 +00:00
|
|
|
|
2005-04-18 08:59:07 +00:00
|
|
|
ActionVector::const_iterator aRangeBegin;
|
|
|
|
ActionVector::const_iterator aRangeEnd;
|
2005-03-30 07:27:39 +00:00
|
|
|
|
2005-04-18 08:59:07 +00:00
|
|
|
if( !getSubsetIndices( nStartIndex, nEndIndex,
|
|
|
|
aRangeBegin, aRangeEnd ) )
|
|
|
|
return ::basegfx::B2DRange(); // nothing to render -> empty range
|
2005-03-30 07:27:39 +00:00
|
|
|
|
2005-04-18 08:59:07 +00:00
|
|
|
// now, aRangeBegin references the action in which the
|
|
|
|
// subset querying must start, and aRangeEnd references
|
|
|
|
// the action in which the subset querying must end (it
|
|
|
|
// might also end right at the start of the referenced
|
|
|
|
// action, such that zero of that action needs to be
|
|
|
|
// queried).
|
2005-03-30 07:27:39 +00:00
|
|
|
|
|
|
|
|
2005-04-18 08:59:07 +00:00
|
|
|
// query bounds for subset of actions
|
|
|
|
// ==================================
|
2005-03-30 07:27:39 +00:00
|
|
|
|
2005-04-18 08:59:07 +00:00
|
|
|
::basegfx::B2DHomMatrix aMatrix;
|
2005-11-02 12:40:15 +00:00
|
|
|
::canvas::tools::getRenderStateTransform( aMatrix,
|
|
|
|
getRenderState() );
|
2005-03-30 07:27:39 +00:00
|
|
|
|
2005-04-18 08:59:07 +00:00
|
|
|
AreaQuery aQuery( aMatrix );
|
|
|
|
forSubsetRange( aQuery,
|
|
|
|
aRangeBegin,
|
|
|
|
aRangeEnd,
|
|
|
|
nStartIndex,
|
|
|
|
nEndIndex,
|
|
|
|
maActions.end() );
|
2005-03-30 07:27:39 +00:00
|
|
|
|
2005-11-17 15:14:06 +00:00
|
|
|
return aQuery.getBounds();
|
2004-03-18 09:41:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool ImplRenderer::draw() const
|
|
|
|
{
|
2004-11-26 19:54:32 +00:00
|
|
|
RTL_LOGFILE_CONTEXT( aLog, "::cppcanvas::internal::ImplRenderer::draw()" );
|
|
|
|
|
|
|
|
::basegfx::B2DHomMatrix aMatrix;
|
2005-11-02 12:40:15 +00:00
|
|
|
::canvas::tools::getRenderStateTransform( aMatrix,
|
|
|
|
getRenderState() );
|
2004-11-26 19:54:32 +00:00
|
|
|
|
2007-07-17 14:24:30 +00:00
|
|
|
try
|
|
|
|
{
|
|
|
|
return ::std::for_each( maActions.begin(), maActions.end(), ActionRenderer( aMatrix ) ).result();
|
|
|
|
}
|
|
|
|
catch( uno::Exception& )
|
|
|
|
{
|
|
|
|
OSL_ENSURE( false,
|
|
|
|
rtl::OUStringToOString(
|
|
|
|
comphelper::anyToString( cppu::getCaughtException() ),
|
|
|
|
RTL_TEXTENCODING_UTF8 ).getStr() );
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
2004-03-18 09:41:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|