diff options
author | Herbert Duerr <hdu@openoffice.org> | 2007-02-20 14:24:21 +0000 |
---|---|---|
committer | Herbert Duerr <hdu@openoffice.org> | 2007-02-20 14:24:21 +0000 |
commit | b72eefb1659f837f1ad037e2023b32cdd97a824f (patch) | |
tree | 9e14a41730a1711aa1052c2642c1e36d414fa184 /drawinglayer | |
parent | 1389fccf9a44de9bdfab2f3f5b8302ec41e06bd9 (diff) |
support text underlining
Diffstat (limited to 'drawinglayer')
-rw-r--r-- | drawinglayer/source/primitive2d/textprimitive2d.cxx | 180 |
1 files changed, 175 insertions, 5 deletions
diff --git a/drawinglayer/source/primitive2d/textprimitive2d.cxx b/drawinglayer/source/primitive2d/textprimitive2d.cxx index 22859e36482f..a3a7b886b03e 100644 --- a/drawinglayer/source/primitive2d/textprimitive2d.cxx +++ b/drawinglayer/source/primitive2d/textprimitive2d.cxx @@ -4,9 +4,9 @@ * * $RCSfile: textprimitive2d.cxx,v $ * - * $Revision: 1.6 $ + * $Revision: 1.7 $ * - * last change: $Author: hdu $ $Date: 2007-02-15 13:25:26 $ + * last change: $Author: hdu $ $Date: 2007-02-20 15:24:21 $ * * The Contents of this file are made available subject to * the terms of GNU Lesser General Public License Version 2.1. @@ -81,6 +81,8 @@ #include <basegfx/tools/canvastools.hxx> #endif +#include <numeric> + ////////////////////////////////////////////////////////////////////////////// namespace drawinglayer @@ -331,18 +333,186 @@ namespace drawinglayer { Primitive2DSequence TextComplexPortionPrimitive2D::createLocalDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const { - Primitive2DSequence aRetval(1); + Primitive2DSequence aRetval(3); // First create a simple text primitive and ignore other attributes aRetval[0] = new TextSimplePortionPrimitive2D(getTextTransform(), getText(), getDXArray(), getFontAttributes(), getFontColor()); + if( meFontUnderline != FONT_UNDERLINE_NONE ) + { + basegfx::B2DVector aScale, aTranslate; + double fRotate, fShearX; + getTextTransform().decompose(aScale, aTranslate, fRotate, fShearX); + basegfx::B2DHomMatrix aUnscaledTransform; + aUnscaledTransform.rotate( fRotate ); + aUnscaledTransform.shearX( fShearX ); + aUnscaledTransform.translate( aTranslate.getX(), aTranslate.getY() ); + + basegfx::B2DHomMatrix aUnrotatedTransform = getTextTransform(); + aUnrotatedTransform.rotate( -fRotate ); + + TextLayouterDevice aTextLayouter; + aTextLayouter.setFontAttributes(getFontAttributes(), aUnrotatedTransform ); + +// const double fLineHeight = aTextLayouter.getTextHeight(); + double fUnderlineOffset = aTextLayouter.getUnderlineOffset(); + double fUnderlineHeight = aTextLayouter.getUnderlineHeight(); +// const double fStrikeoutOffset = aTextLayouter.getStrikeoutOffset(); + basegfx::tools::B2DLineJoin eLineJoin = basegfx::tools::B2DLINEJOIN_NONE; + bool bDoubleLine = false; + bool bWaveLine = false; + + const int* pDashDotArray = NULL; + static const int aDottedArray[] = { 1, 1, 0}; // DOTTED LINE + static const int aDashDotArray[] = { 1, 1, 4, 1, 0}; // DASHDOT + static const int aDashDotDotArray[] = { 1, 1, 1, 1, 4, 1, 0}; // DASHDOTDOT + static const int aDashedArray[] = { 5, 2, 0}; // DASHED LINE + static const int aLongDashArray[] = { 7, 2, 0}; // LONGDASH + + // set Underline attribute + switch( getFontUnderline() ) + { + default: + DBG_WARNING1( "DrawingLayer: Unknown underline attribute (%d)!", getFontUnderline() ); + // fall through + case primitive2d::FONT_UNDERLINE_NONE: + fUnderlineHeight = 0; + break; + case primitive2d::FONT_UNDERLINE_BOLD: + fUnderlineHeight *= 2; + // fall through + case primitive2d::FONT_UNDERLINE_SINGLE: + break; + case primitive2d::FONT_UNDERLINE_DOUBLE: + bDoubleLine = true; + break; + case primitive2d::FONT_UNDERLINE_BOLDDOTTED: + fUnderlineHeight *= 2; + // fall through + case primitive2d::FONT_UNDERLINE_DOTTED: + eLineJoin = basegfx::tools::B2DLINEJOIN_ROUND; + pDashDotArray = aDottedArray; + break; + case primitive2d::FONT_UNDERLINE_BOLDDASH: + fUnderlineHeight *= 2; + // fall through + case primitive2d::FONT_UNDERLINE_DASH: + pDashDotArray = aDashedArray; + break; + case primitive2d::FONT_UNDERLINE_BOLDLONGDASH: + fUnderlineHeight *= 2; + // fall through + case primitive2d::FONT_UNDERLINE_LONGDASH: + pDashDotArray = aLongDashArray; + break; + case primitive2d::FONT_UNDERLINE_BOLDDASHDOT: + fUnderlineHeight *= 2; + // fall through + case primitive2d::FONT_UNDERLINE_DASHDOT: + pDashDotArray = aDashDotArray; + break; + case primitive2d::FONT_UNDERLINE_BOLDDASHDOTDOT: + fUnderlineHeight *= 2; + // fall through + case primitive2d::FONT_UNDERLINE_DASHDOTDOT: + eLineJoin = basegfx::tools::B2DLINEJOIN_ROUND; + pDashDotArray = aDashDotDotArray; + break; + case primitive2d::FONT_UNDERLINE_SMALLWAVE: + // TODO + bWaveLine = true; + break; + case primitive2d::FONT_UNDERLINE_BOLDWAVE: + fUnderlineHeight *= 2; + // fall through + case primitive2d::FONT_UNDERLINE_WAVE: + // TODO + bWaveLine = true; + break; + case primitive2d::FONT_UNDERLINE_DOUBLEWAVE: + bWaveLine = true; + bDoubleLine = true; + break; + } + + double fTextWidth = 0.0; + if( getDXArray().empty() ) + fTextWidth = aTextLayouter.getTextWidth( getText(), 0/*TODO*/, getText().Len()/*TODO*/ ); + else + fTextWidth = getDXArray().back() * aScale.getX(); + + if( bDoubleLine ) + { + fUnderlineOffset -= 0.50 * fUnderlineHeight; + fUnderlineHeight *= 0.64; + } + + basegfx::B2DPolygon aUnderline; + ::basegfx::B2DPoint aPoint( 0.0, fUnderlineOffset ); + aUnderline.append( aPoint ); + if( !bWaveLine ) + { + // straight underline + aUnderline.append( aPoint + ::basegfx::B2DPoint( fTextWidth, 0.0 ) ); + } + else + { + // wavy underline + basegfx::B2DPolygon& aWavePoly = aUnderline; + double fWaveWidth = 4 * fUnderlineHeight; + if( getFontUnderline() == primitive2d::FONT_UNDERLINE_SMALLWAVE ) + fWaveWidth *= 0.7; + const double fWaveHeight = 0.5 * fWaveWidth; + const ::basegfx::B2DPoint aCtrlOffset( fWaveWidth * 0.467308, fWaveHeight ); + for( double fPos = fWaveWidth; fPos < fTextWidth; fPos += fWaveWidth ) { + // create a symmetrical wave using one cubic bezier curve + // with y==0 for {x==0, x==0.5*fW or x==1.0*fW} + // and ymin/ymax at {x=0.25*fW or 0.75*fW} + const int n = aWavePoly.count(); + aWavePoly.setControlPointA( n-1, aPoint + aCtrlOffset ); + aWavePoly.append( aPoint += ::basegfx::B2DPoint( fWaveWidth, 0.0 ) ); + aWavePoly.setControlPointB( n-1, aPoint - aCtrlOffset ); + } + // adjust stroke style + eLineJoin = basegfx::tools::B2DLINEJOIN_ROUND; + fUnderlineHeight *= 0.5; + } + + const basegfx::BColor& rLineColor = getFontColor(); + attribute::StrokeAttribute aStrokeAttr( rLineColor, fUnderlineHeight, eLineJoin ); + if( pDashDotArray != NULL ) + { + ::std::vector< double > aDoubleArray; + for( const int* p = pDashDotArray; *p; ++p ) + aDoubleArray.push_back( *p * fUnderlineHeight); + const double fFullDashDotLen = ::std::accumulate(aDoubleArray.begin(), aDoubleArray.end(), 0.0); + aStrokeAttr = attribute::StrokeAttribute( rLineColor, + fUnderlineHeight, eLineJoin, aDoubleArray, fFullDashDotLen ); + } + aUnderline.transform( aUnscaledTransform ); + aRetval[1] = new PolygonStrokePrimitive2D( aUnderline, aStrokeAttr ); + + if( bDoubleLine ) + { + // add another underline below the first underline + const double fLineDist = (bWaveLine ? 3 : 2) * fUnderlineHeight; + ::basegfx::B2DPoint aOffsetPoint( 0.0, fLineDist ); + aUnscaledTransform.translate( -aTranslate.getX(), -aTranslate.getY() ); + aOffsetPoint = aUnscaledTransform * aOffsetPoint; + basegfx::B2DHomMatrix aOffsetTransform; + aOffsetTransform.translate( aOffsetPoint.getX(), aOffsetPoint.getY() ); + aUnderline.transform( aOffsetTransform ); + aRetval[2] = new PolygonStrokePrimitive2D( aUnderline, aStrokeAttr ); + } + // TODO: need to take care of - // -underline // -strikethrough // -emphasis mark // -relief (embosses/engraved) // -shadow - // -outline + // if( getWordLineMode() ) + // if( getUnderlineAbove() ) + } return aRetval; } |