summaryrefslogtreecommitdiff
path: root/cppcanvas/source/mtfrenderer/mtftools.cxx
diff options
context:
space:
mode:
authorRüdiger Timm <rt@openoffice.org>2005-03-30 07:30:28 +0000
committerRüdiger Timm <rt@openoffice.org>2005-03-30 07:30:28 +0000
commit6fdad545b4056a3500b07ab87610aaf8a69d1b3c (patch)
tree89a5e24ca623d1dcd4e2ada763b5399d416976a3 /cppcanvas/source/mtfrenderer/mtftools.cxx
parentce119e8dd5979b4f7a43a60b720ce8f23c73120e (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.cxx493
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 );
+ }
+ }
}