diff options
author | Rüdiger Timm <rt@openoffice.org> | 2005-03-30 07:30:28 +0000 |
---|---|---|
committer | Rüdiger Timm <rt@openoffice.org> | 2005-03-30 07:30:28 +0000 |
commit | 6fdad545b4056a3500b07ab87610aaf8a69d1b3c (patch) | |
tree | 89a5e24ca623d1dcd4e2ada763b5399d416976a3 /cppcanvas/source/mtfrenderer/mtftools.cxx | |
parent | ce119e8dd5979b4f7a43a60b720ce8f23c73120e (diff) |
INTEGRATION: CWS presfixes02 (1.4.2); FILE MERGED
2005/03/14 16:04:52 thb 1.4.2.1: #i35136# #i36914# #i41113# #i44100# #i40115# #i41839# #i44404# Merge from presfixes01 patches
Diffstat (limited to 'cppcanvas/source/mtfrenderer/mtftools.cxx')
-rw-r--r-- | cppcanvas/source/mtfrenderer/mtftools.cxx | 493 |
1 files changed, 487 insertions, 6 deletions
diff --git a/cppcanvas/source/mtfrenderer/mtftools.cxx b/cppcanvas/source/mtfrenderer/mtftools.cxx index bbd3101f4372..5de3a01920c1 100644 --- a/cppcanvas/source/mtfrenderer/mtftools.cxx +++ b/cppcanvas/source/mtfrenderer/mtftools.cxx @@ -2,9 +2,9 @@ * * $RCSfile: mtftools.cxx,v $ * - * $Revision: 1.4 $ + * $Revision: 1.5 $ * - * last change: $Author: vg $ $Date: 2005-03-10 13:25:00 $ + * last change: $Author: rt $ $Date: 2005-03-30 08:30:28 $ * * The Contents of this file are made available subject to the terms of * either of the following licenses @@ -59,27 +59,67 @@ * ************************************************************************/ +#include <canvas/debug.hxx> +#include <canvas/verbosetrace.hxx> + #include <mtftools.hxx> #include <outdevstate.hxx> +#include <polypolyaction.hxx> #ifndef _COM_SUN_STAR_RENDERING_RENDERSTATE_HPP__ #include <com/sun/star/rendering/RenderState.hpp> #endif +#ifndef _COM_SUN_STAR_RENDERING_XCANVAS_HPP__ +#include <com/sun/star/rendering/XCanvas.hpp> +#endif +#ifndef _BGFX_NUMERIC_FTOOLS_HXX +#include <basegfx/numeric/ftools.hxx> +#endif +#ifndef _BGFX_TOOLS_CANVASTOOLS_HXX +#include <basegfx/tools/canvastools.hxx> +#endif +#ifndef _BGFX_POLYGON_B2DPOLYGONTOOLS_HXX +#include <basegfx/polygon/b2dpolygontools.hxx> +#endif +#ifndef _BGFX_POLYGON_B2DPOLYGON_HXX +#include <basegfx/polygon/b2dpolygon.hxx> +#endif +#ifndef _BGFX_RANGE_B2DRECTANGLE_HXX +#include <basegfx/range/b2drectangle.hxx> +#endif +#ifndef _BGFX_VECTOR_B2DVECTOR_HXX +#include <basegfx/vector/b2dvector.hxx> +#endif #ifndef _CANVAS_CANVASTOOLS_HXX #include <canvas/canvastools.hxx> #endif +#ifndef _SV_GDIMTF_HXX +#include <vcl/gdimtf.hxx> +#endif +#ifndef _SV_METAACT_HXX +#include <vcl/metaact.hxx> +#endif +#ifndef _SV_VIRDEV_HXX +#include <vcl/virdev.hxx> +#endif +#ifndef _SV_METRIC_HXX +#include <vcl/metric.hxx> +#endif +#ifndef _TL_POLY_HXX +#include <tools/poly.hxx> +#endif + using namespace ::com::sun::star; namespace cppcanvas { - namespace tools { - void initRenderState( ::com::sun::star::rendering::RenderState& renderState, - const struct ::cppcanvas::internal::OutDevState& outdevState ) + void initRenderState( rendering::RenderState& renderState, + const ::cppcanvas::internal::OutDevState& outdevState ) { ::canvas::tools::initRenderState( renderState ); ::canvas::tools::setRenderStateTransform( renderState, @@ -87,6 +127,447 @@ namespace cppcanvas renderState.Clip = outdevState.xClipPoly; } - } + ::Size getBaselineOffset( const ::cppcanvas::internal::OutDevState& outdevState, + const VirtualDevice& rVDev ) + { + const ::FontMetric& aMetric = rVDev.GetFontMetric(); + + // calc offset for text output, the XCanvas always renders + // baseline offset. + switch( outdevState.textReferencePoint ) + { + case ALIGN_TOP: + return ::Size( 0, + aMetric.GetIntLeading() + aMetric.GetAscent() ); + + case ALIGN_BASELINE: + return ::Size( 0, 0 ); + + case ALIGN_BOTTOM: + return ::Size( 0, + -aMetric.GetDescent() ); + + default: + ENSURE_AND_THROW( false, + "tools::getBaselineOffset(): Unexpected TextAlign value" ); + } + } + + ::basegfx::B2DHomMatrix& calcLogic2PixelLinearTransform( ::basegfx::B2DHomMatrix& o_rMatrix, + const VirtualDevice& rVDev ) + { + // select size value in the middle of the available range, + // to have headroom both when map mode scales up, and when + // it scales down. + const ::Size aSizeLogic( 0x00010000L, + 0x00010000L ); + + const ::Size aSizePixel( rVDev.LogicToPixel( aSizeLogic ) ); + + o_rMatrix.identity(); + o_rMatrix.scale( aSizePixel.Width() / (double)aSizeLogic.Width(), + aSizePixel.Height() / (double)aSizeLogic.Height() ); + + return o_rMatrix; + } + + bool modifyClip( rendering::RenderState& o_rRenderState, + const struct ::cppcanvas::internal::OutDevState& rOutdevState, + const CanvasSharedPtr& rCanvas, + const ::basegfx::B2DPoint& rOffset, + const ::basegfx::B2DVector* pScaling ) + { + const ::Point aEmptyPoint; + + const bool bOffsetting( !rOffset.equalZero() ); + const bool bScaling( pScaling && + pScaling->getX() != 1.0 && + pScaling->getY() != 1.0 ); + + if( !bOffsetting && !bScaling ) + return false; // nothing to do + + if( rOutdevState.clip.count() ) + { + // general polygon case + + ::basegfx::B2DPolyPolygon aLocalClip( rOutdevState.clip ); + ::basegfx::B2DHomMatrix aTransform; + + if( bOffsetting ) + aTransform.translate( -rOffset.getX(), + -rOffset.getY() ); + if( bScaling ) + aTransform.scale( 1.0/pScaling->getX(), 1.0/pScaling->getY() ); + + aLocalClip.transform( aTransform ); + + o_rRenderState.Clip = ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon( + rCanvas->getUNOCanvas()->getDevice(), + aLocalClip ); + + return true; + } + else if( !rOutdevState.clipRect.IsEmpty() ) + { + // simple rect case + + const ::Rectangle aLocalClipRect( rOutdevState.clipRect ); + + if( bScaling ) + { + // scale and offset - do it on the fly, have to + // convert to float anyway. + o_rRenderState.Clip = ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon( + rCanvas->getUNOCanvas()->getDevice(), + ::basegfx::B2DPolyPolygon( + ::basegfx::tools::createPolygonFromRect( + ::basegfx::B2DRectangle( + (double)(aLocalClipRect.Left() - rOffset.getX())/pScaling->getX(), + (double)(aLocalClipRect.Top() - rOffset.getY())/pScaling->getY(), + (double)(aLocalClipRect.Right() - rOffset.getX())/pScaling->getX(), + (double)(aLocalClipRect.Bottom() - rOffset.getY())/pScaling->getY() ) ) ) ); + } + else + { + // offset only - do it on the fly, have to convert + // to float anyway. + o_rRenderState.Clip = ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon( + rCanvas->getUNOCanvas()->getDevice(), + ::basegfx::B2DPolyPolygon( + ::basegfx::tools::createPolygonFromRect( + ::basegfx::B2DRectangle( aLocalClipRect.Left() - rOffset.getX(), + aLocalClipRect.Top() - rOffset.getY(), + aLocalClipRect.Right() - rOffset.getX(), + aLocalClipRect.Bottom() - rOffset.getY() ) ) ) ); + } + + return true; + } + + // empty clip, nothing to do + return false; + } + + bool modifyClip( rendering::RenderState& o_rRenderState, + const struct ::cppcanvas::internal::OutDevState& rOutdevState, + const CanvasSharedPtr& rCanvas, + const ::Point& rOffset, + const ::basegfx::B2DVector* pScaling ) + { + return modifyClip( o_rRenderState, + rOutdevState, + rCanvas, + ::basegfx::B2DPoint( rOffset.X(), + rOffset.Y() ), + pScaling ); + } + + bool modifyClip( rendering::RenderState& o_rRenderState, + const struct ::cppcanvas::internal::OutDevState& rOutdevState, + const CanvasSharedPtr& rCanvas, + const ::basegfx::B2DHomMatrix& rTransform ) + { + if( !rTransform.isIdentity() || + !rTransform.isInvertible() ) + return false; // nothing to do + ::basegfx::B2DPolyPolygon aLocalClip; + + if( rOutdevState.clip.count() ) + { + aLocalClip = rOutdevState.clip; + } + else if( !rOutdevState.clipRect.IsEmpty() ) + { + const ::Rectangle aLocalClipRect( rOutdevState.clipRect ); + + aLocalClip = ::basegfx::B2DPolyPolygon( + ::basegfx::tools::createPolygonFromRect( + ::basegfx::B2DRectangle( + aLocalClipRect.Left(), + aLocalClipRect.Top(), + aLocalClipRect.Right(), + aLocalClipRect.Bottom() ) ) ); + } + else + { + // empty clip, nothing to do + return false; + } + + // invert transformation and modify + ::basegfx::B2DHomMatrix aLocalTransform( rTransform ); + aLocalTransform.invert(); + + aLocalClip.transform( aLocalTransform ); + + o_rRenderState.Clip = ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon( + rCanvas->getUNOCanvas()->getDevice(), + aLocalClip ); + + return true; + } + + // create underline/strikeout line info struct + TextLineInfo createTextLineInfo( const ::VirtualDevice& rVDev, + const ::cppcanvas::internal::OutDevState& rState ) + { + const BOOL bOldMode( rVDev.IsMapModeEnabled() ); + + // will restore map mode below + const_cast< ::VirtualDevice& >(rVDev).EnableMapMode( FALSE ); + + const ::FontMetric aMetric = rVDev.GetFontMetric(); + + TextLineInfo aTextInfo( + (aMetric.GetDescent() + 2) / 4.0, + aMetric.GetDescent() / 2.0, + (aMetric.GetIntLeading() - aMetric.GetAscent()) / 3.0, + rState.textUnderlineStyle, + rState.textStrikeoutStyle ); + + const_cast< ::VirtualDevice& >(rVDev).EnableMapMode( bOldMode ); + + return aTextInfo; + } + + namespace + { + void appendRect( ::basegfx::B2DPolyPolygon& o_rPoly, + const ::basegfx::B2DPoint& rStartPos, + const double nX1, + const double nY1, + const double nX2, + const double nY2 ) + { + const double x( rStartPos.getX() ); + const double y( rStartPos.getY() ); + + o_rPoly.append( + ::basegfx::tools::createPolygonFromRect( + ::basegfx::B2DRectangle( x + nX1, y + nY1, x + nX2, y + nY2 ) ) ); + } + + void appendRect( ::basegfx::B2DPolyPolygon& o_rPoly, + const double nX1, + const double nY1, + const double nX2, + const double nY2 ) + { + o_rPoly.append( + ::basegfx::tools::createPolygonFromRect( + ::basegfx::B2DRectangle( nX1, nY1, nX2, nY2 ) ) ); + } + + void appendDashes( ::basegfx::B2DPolyPolygon& o_rPoly, + const double nX, + const double nY, + const double nLineWidth, + const double nLineHeight, + const double nDashWidth, + const double nDashSkip ) + { + const sal_Int32 nNumLoops( + static_cast< sal_Int32 >( + ::std::max( 1.0, + nLineWidth / nDashSkip ) + .5) ); + + double x = nX; + for( sal_Int32 i=0; i<nNumLoops; ++i ) + { + appendRect( o_rPoly, + x, nY, + x + nDashWidth, nY + nLineHeight ); + + x += nDashSkip; + } + } + } + + // create line actions for text such as underline and + // strikeout + ::basegfx::B2DPolyPolygon createTextLinesPolyPolygon( const ::basegfx::B2DPoint rStartPos, + const double& rLineWidth, + const TextLineInfo& rTextLineInfo ) + { + // fill the polypolygon with all text lines + ::basegfx::B2DPolyPolygon aTextLinesPolyPoly; + + switch( rTextLineInfo.mnUnderlineStyle ) + { + case UNDERLINE_NONE: // nothing to do + // FALLTHROUGH intended + case UNDERLINE_DONTKNOW: + break; + + case UNDERLINE_SMALLWAVE: // TODO(F3): NYI + // FALLTHROUGH intended + case UNDERLINE_WAVE: // TODO(F3): NYI + // FALLTHROUGH intended + case UNDERLINE_SINGLE: + appendRect( + aTextLinesPolyPoly, + rStartPos, + 0, + rTextLineInfo.mnUnderlineOffset, + rLineWidth, + rTextLineInfo.mnUnderlineOffset + rTextLineInfo.mnLineHeight ); + break; + + case UNDERLINE_BOLDDOTTED: // TODO(F3): NYI + // FALLTHROUGH intended + case UNDERLINE_BOLDDASH: // TODO(F3): NYI + // FALLTHROUGH intended + case UNDERLINE_BOLDLONGDASH: // TODO(F3): NYI + // FALLTHROUGH intended + case UNDERLINE_BOLDDASHDOT: // TODO(F3): NYI + // FALLTHROUGH intended + case UNDERLINE_BOLDDASHDOTDOT:// TODO(F3): NYI + // FALLTHROUGH intended + case UNDERLINE_BOLDWAVE: // TODO(F3): NYI + // FALLTHROUGH intended + case UNDERLINE_BOLD: + appendRect( + aTextLinesPolyPoly, + rStartPos, + 0, + rTextLineInfo.mnUnderlineOffset, + rLineWidth, + rTextLineInfo.mnUnderlineOffset + 2*rTextLineInfo.mnLineHeight ); + break; + + case UNDERLINE_DOUBLEWAVE: // TODO(F3): NYI + // FALLTHROUGH intended + case UNDERLINE_DOUBLE: + appendRect( + aTextLinesPolyPoly, + rStartPos, + 0, + rTextLineInfo.mnUnderlineOffset - rTextLineInfo.mnLineHeight, + rLineWidth, + rTextLineInfo.mnUnderlineOffset ); + + appendRect( + aTextLinesPolyPoly, + rStartPos, + 0, + rTextLineInfo.mnUnderlineOffset + 2*rTextLineInfo.mnLineHeight, + rLineWidth, + rTextLineInfo.mnUnderlineOffset + 3*rTextLineInfo.mnLineHeight ); + break; + + case UNDERLINE_DASHDOTDOT: // TODO(F3): NYI + // FALLTHROUGH intended + case UNDERLINE_DOTTED: + appendDashes( + aTextLinesPolyPoly, + rStartPos.getX(), + rStartPos.getY() + rTextLineInfo.mnUnderlineOffset, + rLineWidth, + rTextLineInfo.mnLineHeight, + rTextLineInfo.mnLineHeight, + 2*rTextLineInfo.mnLineHeight ); + break; + + case UNDERLINE_DASHDOT: // TODO(F3): NYI + // FALLTHROUGH intended + case UNDERLINE_DASH: + appendDashes( + aTextLinesPolyPoly, + rStartPos.getX(), + rStartPos.getY() + rTextLineInfo.mnUnderlineOffset, + rLineWidth, + rTextLineInfo.mnLineHeight, + 3*rTextLineInfo.mnLineHeight, + 6*rTextLineInfo.mnLineHeight ); + break; + + case UNDERLINE_LONGDASH: + appendDashes( + aTextLinesPolyPoly, + rStartPos.getX(), + rStartPos.getY() + rTextLineInfo.mnUnderlineOffset, + rLineWidth, + rTextLineInfo.mnLineHeight, + 6*rTextLineInfo.mnLineHeight, + 12*rTextLineInfo.mnLineHeight ); + break; + + default: + ENSURE_AND_THROW( false, + "::cppcanvas::internal::createTextLinesPolyPolygon(): Unexpected underline case" ); + } + + switch( rTextLineInfo.mnStrikeoutStyle ) + { + case STRIKEOUT_NONE: // nothing to do + // FALLTHROUGH intended + case STRIKEOUT_DONTKNOW: + break; + + case STRIKEOUT_SLASH: // TODO(Q1): we should handle this in the text layer + // FALLTHROUGH intended + case STRIKEOUT_X: + break; + + case STRIKEOUT_SINGLE: + appendRect( + aTextLinesPolyPoly, + rStartPos, + 0, + rTextLineInfo.mnStrikeoutOffset, + rLineWidth, + rTextLineInfo.mnStrikeoutOffset + rTextLineInfo.mnLineHeight ); + break; + + case STRIKEOUT_BOLD: + appendRect( + aTextLinesPolyPoly, + rStartPos, + 0, + rTextLineInfo.mnStrikeoutOffset, + rLineWidth, + rTextLineInfo.mnStrikeoutOffset + 2*rTextLineInfo.mnLineHeight ); + break; + + case STRIKEOUT_DOUBLE: + appendRect( + aTextLinesPolyPoly, + rStartPos, + 0, + rTextLineInfo.mnStrikeoutOffset - rTextLineInfo.mnLineHeight, + rLineWidth, + rTextLineInfo.mnStrikeoutOffset ); + + appendRect( + aTextLinesPolyPoly, + rStartPos, + 0, + rTextLineInfo.mnStrikeoutOffset + 2*rTextLineInfo.mnLineHeight, + rLineWidth, + rTextLineInfo.mnStrikeoutOffset + 3*rTextLineInfo.mnLineHeight ); + break; + + default: + ENSURE_AND_THROW( false, + "::cppcanvas::internal::createTextLinesPolyPolygon(): Unexpected strikeout case" ); + } + + return aTextLinesPolyPoly; + } + + // create line actions for text such as underline and + // strikeout + ::basegfx::B2DPolyPolygon createTextLinesPolyPolygon( const double& rStartOffset, + const double& rLineWidth, + const TextLineInfo& rTextLineInfo ) + { + return createTextLinesPolyPolygon( + ::basegfx::B2DPoint( rStartOffset, + 0.0 ), + rLineWidth, + rTextLineInfo ); + } + } } |