diff options
author | Armin Weiss <aw@openoffice.org> | 2007-09-26 10:36:58 +0000 |
---|---|---|
committer | Armin Weiss <aw@openoffice.org> | 2007-09-26 10:36:58 +0000 |
commit | 9260ca65470b0e7e8310772865023addaa393ca8 (patch) | |
tree | 17931f5b22df163d8cf1dec2ac4a28c195995c53 | |
parent | 553365ad85673d3d3f42bc32d817a387fba1a85e (diff) |
#i73860# text decomposition extended
18 files changed, 1151 insertions, 498 deletions
diff --git a/drawinglayer/inc/drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx b/drawinglayer/inc/drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx index fdd625966bfb..c56ddd68b67a 100644 --- a/drawinglayer/inc/drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx +++ b/drawinglayer/inc/drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx @@ -4,9 +4,9 @@ * * $RCSfile: drawinglayer_primitivetypes2d.hxx,v $ * - * $Revision: 1.5 $ + * $Revision: 1.6 $ * - * last change: $Author: aw $ $Date: 2007-09-20 09:51:21 $ + * last change: $Author: aw $ $Date: 2007-09-26 11:36:28 $ * * The Contents of this file are made available subject to * the terms of GNU Lesser General Public License Version 2.1. @@ -90,6 +90,7 @@ #define PRIMITIVE2D_ID_TEXTHIERARCHYBLOCKPRIMITIVE2D (PRIMITIVE2D_ID_RANGE_DRAWINGLAYER| 41) #define PRIMITIVE2D_ID_POLYGONWAVEPRIMITIVE2D (PRIMITIVE2D_ID_RANGE_DRAWINGLAYER| 42) #define PRIMITIVE2D_ID_WRONGSPELLPRIMITIVE2D (PRIMITIVE2D_ID_RANGE_DRAWINGLAYER| 43) +#define PRIMITIVE2D_ID_TEXTEFFECTPRIMITIVE2D (PRIMITIVE2D_ID_RANGE_DRAWINGLAYER| 44) ////////////////////////////////////////////////////////////////////////////// diff --git a/drawinglayer/inc/drawinglayer/primitive2d/polygonprimitive2d.hxx b/drawinglayer/inc/drawinglayer/primitive2d/polygonprimitive2d.hxx index ef3ad8117670..12b4306dc6a0 100644 --- a/drawinglayer/inc/drawinglayer/primitive2d/polygonprimitive2d.hxx +++ b/drawinglayer/inc/drawinglayer/primitive2d/polygonprimitive2d.hxx @@ -4,9 +4,9 @@ * * $RCSfile: polygonprimitive2d.hxx,v $ * - * $Revision: 1.3 $ + * $Revision: 1.4 $ * - * last change: $Author: aw $ $Date: 2007-09-20 09:51:21 $ + * last change: $Author: aw $ $Date: 2007-09-26 11:36:28 $ * * The Contents of this file are made available subject to * the terms of GNU Lesser General Public License Version 2.1. @@ -163,7 +163,7 @@ namespace drawinglayer } // end of namespace drawinglayer ////////////////////////////////////////////////////////////////////////////// -// PolygonStrokePrimitive2D class +// PolygonWavePrimitive2D class namespace drawinglayer { @@ -173,7 +173,7 @@ namespace drawinglayer { private: basegfx::B2DPolygon maPolygon; - basegfx::BColor maBColor; + attribute::StrokeAttribute maStrokeAttribute; double mfWaveWidth; double mfWaveHeight; @@ -184,13 +184,13 @@ namespace drawinglayer public: PolygonWavePrimitive2D( const basegfx::B2DPolygon& rPolygon, - const basegfx::BColor& rBColor, + const attribute::StrokeAttribute& rStrokeAttribute, double fWaveWidth, double fWaveHeight); // get data basegfx::B2DPolygon getB2DPolygon() const { return maPolygon; } - const basegfx::BColor& getBColor() const { return maBColor; } + const attribute::StrokeAttribute& getStrokeAttribute() const { return maStrokeAttribute; } double getWaveWidth() const { return mfWaveWidth; } double getWaveHeight() const { return mfWaveHeight; } diff --git a/drawinglayer/inc/drawinglayer/primitive2d/textdecoratedprimitive2d.hxx b/drawinglayer/inc/drawinglayer/primitive2d/textdecoratedprimitive2d.hxx index 5a505129e6f9..755c1f1a9de9 100644 --- a/drawinglayer/inc/drawinglayer/primitive2d/textdecoratedprimitive2d.hxx +++ b/drawinglayer/inc/drawinglayer/primitive2d/textdecoratedprimitive2d.hxx @@ -4,9 +4,9 @@ * * $RCSfile: textdecoratedprimitive2d.hxx,v $ * - * $Revision: 1.3 $ + * $Revision: 1.4 $ * - * last change: $Author: aw $ $Date: 2007-09-20 09:51:21 $ + * last change: $Author: aw $ $Date: 2007-09-26 11:36:28 $ * * The Contents of this file are made available subject to * the terms of GNU Lesser General Public License Version 2.1. @@ -40,9 +40,12 @@ #include <drawinglayer/primitive2d/textprimitive2d.hxx> #endif -#ifndef _COM_SUN_STAR_I18N_XBREAKITERATOR_HPP_ -#include <com/sun/star/i18n/XBreakIterator.hpp> -#endif +////////////////////////////////////////////////////////////////////////////// +// predeclarations + +namespace basegfx { + class DecomposedB2DHomMatrixContainer; +} // end of namespace basegfx ////////////////////////////////////////////////////////////////////////////// @@ -114,11 +117,16 @@ namespace drawinglayer unsigned mbEmphasisMarkBelow : 1; unsigned mbShadow : 1; - // break iterator support - // made static so it only needs to be fetched once, even with many single - // constructed VclMetafileProcessor2D. It's still incarnated on demand, - // but exists for OOo runtime now by purpose. - static ::com::sun::star::uno::Reference< ::com::sun::star::i18n::XBreakIterator > mxBreakIterator; + // helper methods + void impCreateGeometryContent( + std::vector< Primitive2DReference >& rTarget, + basegfx::DecomposedB2DHomMatrixContainer& rDecTrans, + const rtl::OUString& rText, + const ::std::vector< double >& rDXArray, + const FontAttributes& rFontAttributes) const; + void impSplitSingleWords( + std::vector< Primitive2DReference >& rTarget, + basegfx::DecomposedB2DHomMatrixContainer& rDecTrans) const; protected: // local decomposition. @@ -129,7 +137,7 @@ namespace drawinglayer // TextSimplePortionPrimitive2D parameters const basegfx::B2DHomMatrix& rNewTransform, - const String& rText, + const rtl::OUString& rText, const ::std::vector< double >& rDXArray, const FontAttributes& rFontAttributes, const ::com::sun::star::lang::Locale& rLocale, diff --git a/drawinglayer/inc/drawinglayer/primitive2d/texteffectprimitive2d.hxx b/drawinglayer/inc/drawinglayer/primitive2d/texteffectprimitive2d.hxx new file mode 100644 index 000000000000..67e2ab4afd34 --- /dev/null +++ b/drawinglayer/inc/drawinglayer/primitive2d/texteffectprimitive2d.hxx @@ -0,0 +1,111 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: texteffectprimitive2d.hxx,v $ + * + * $Revision: 1.1 $ + * + * last change: $Author: aw $ $Date: 2007-09-26 11:36:28 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library 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 for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#ifndef INCLUDED_DRAWINGLAYER_PRIMITIVE2D_TEXTEFFECTPRIMITIVE2D_HXX +#define INCLUDED_DRAWINGLAYER_PRIMITIVE2D_TEXTEFFECTPRIMITIVE2D_HXX + +#ifndef INCLUDED_DRAWINGLAYER_PRIMITIVE2D_GROUPPRIMITIVE2D_HXX +#include <drawinglayer/primitive2d/groupprimitive2d.hxx> +#endif + +#ifndef _BGFX_MATRIX_B2DHOMMATRIX_HXX +#include <basegfx/matrix/b2dhommatrix.hxx> +#endif + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace primitive2d + { + enum TextEffectStyle2D + { + TEXTEFFECTSTYLE2D_RELIEF_EMBOSSED_DEFAULT, + TEXTEFFECTSTYLE2D_RELIEF_ENGRAVED_DEFAULT, + TEXTEFFECTSTYLE2D_RELIEF_EMBOSSED, + TEXTEFFECTSTYLE2D_RELIEF_ENGRAVED, + TEXTEFFECTSTYLE2D_OUTLINE + }; + + class TextEffectPrimitive2D : public GroupPrimitive2D + { + private: + // the style to apply, the direction and the rotation center + const basegfx::B2DPoint maRotationCenter; + double mfDirection; + TextEffectStyle2D meTextEffectStyle2D; + + // the last used viewTransformation, used from getDecomposition for buffering + basegfx::B2DHomMatrix maLastViewTransformation; + + protected: + // create local decomposition + virtual Primitive2DSequence createLocalDecomposition(const geometry::ViewInformation2D& rViewInformation) const; + + public: + TextEffectPrimitive2D( + const Primitive2DSequence& rChildren, + const basegfx::B2DPoint& rRotationCenter, + double fDirection, + TextEffectStyle2D eTextEffectStyle2D); + + // get data + const basegfx::B2DPoint& getRotationCenter() const { return maRotationCenter; } + double getDirection() const { return mfDirection; } + TextEffectStyle2D getTextEffectStyle2D() const { return meTextEffectStyle2D; } + + // compare operator + virtual bool operator==(const BasePrimitive2D& rPrimitive) const; + + // own get range implementation to solve more effective. Content is by definition displaced + // by a fixed discrete unit, thus the contained geometry needs only once be asked for it's + // own basegfx::B2DRange + virtual basegfx::B2DRange getB2DRange(const geometry::ViewInformation2D& rViewInformation) const; + + // provide unique ID + DeclPrimitrive2DIDBlock() + + // Overload standard getDecomposition call to be view-dependent here + virtual Primitive2DSequence get2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const; + }; + } // end of namespace primitive2d +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// + +#endif //INCLUDED_DRAWINGLAYER_PRIMITIVE2D_TEXTEFFECTPRIMITIVE2D_HXX + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/drawinglayer/inc/drawinglayer/primitive2d/texthierarchyprimitive2d.hxx b/drawinglayer/inc/drawinglayer/primitive2d/texthierarchyprimitive2d.hxx index 39bd7f1a1615..459ad26a5e90 100644 --- a/drawinglayer/inc/drawinglayer/primitive2d/texthierarchyprimitive2d.hxx +++ b/drawinglayer/inc/drawinglayer/primitive2d/texthierarchyprimitive2d.hxx @@ -4,9 +4,9 @@ * * $RCSfile: texthierarchyprimitive2d.hxx,v $ * - * $Revision: 1.1 $ + * $Revision: 1.2 $ * - * last change: $Author: aw $ $Date: 2007-08-03 10:43:04 $ + * last change: $Author: aw $ $Date: 2007-09-26 11:36:28 $ * * The Contents of this file are made available subject to * the terms of GNU Lesser General Public License Version 2.1. @@ -127,17 +127,17 @@ namespace drawinglayer { private: FieldType meType; - String maString; + rtl::OUString maString; public: TextHierarchyFieldPrimitive2D( const Primitive2DSequence& rChildren, const FieldType& rFieldType, - const String& rString); + const rtl::OUString& rString); // get data FieldType getType() const { return meType; } - const String& getString() const { return maString; } + const rtl::OUString& getString() const { return maString; } // compare operator virtual bool operator==(const BasePrimitive2D& rPrimitive) const; diff --git a/drawinglayer/inc/drawinglayer/primitive2d/textlayoutdevice.hxx b/drawinglayer/inc/drawinglayer/primitive2d/textlayoutdevice.hxx index e80dfe199a98..e3d014cdae82 100644 --- a/drawinglayer/inc/drawinglayer/primitive2d/textlayoutdevice.hxx +++ b/drawinglayer/inc/drawinglayer/primitive2d/textlayoutdevice.hxx @@ -4,9 +4,9 @@ * * $RCSfile: textlayoutdevice.hxx,v $ * - * $Revision: 1.3 $ + * $Revision: 1.4 $ * - * last change: $Author: hdu $ $Date: 2007-02-14 14:53:01 $ + * last change: $Author: aw $ $Date: 2007-09-26 11:36:28 $ * * The Contents of this file are made available subject to * the terms of GNU Lesser General Public License Version 2.1. @@ -58,10 +58,10 @@ // predefines class VirtualDevice; class Font; -class String; +class rtl::OUString; namespace drawinglayer { namespace primitive2d { - struct FontAttributes; + class FontAttributes; }} namespace basegfx { @@ -93,11 +93,11 @@ namespace drawinglayer double getUnderlineOffset() const; double getStrikeoutOffset() const; - double getTextWidth(const String& rText, xub_StrLen nIndex, xub_StrLen nLength) const; + double getTextWidth(const rtl::OUString& rText, sal_Int32 nIndex, sal_Int32 nLength) const; bool getTextOutlines( basegfx::B2DPolyPolygonVector&, - const String&, xub_StrLen nIndex, xub_StrLen nLength, + const rtl::OUString&, sal_Int32 nIndex, sal_Int32 nLength, const ::std::vector< sal_Int32 >& rDXArray ); - basegfx::B2DRange getTextBoundRect(const String& rText, xub_StrLen nIndex, xub_StrLen nLength) const; + basegfx::B2DRange getTextBoundRect(const rtl::OUString& rText, sal_Int32 nIndex, sal_Int32 nLength) const; }; } // end of namespace primitive2d } // end of namespace drawinglayer diff --git a/drawinglayer/inc/drawinglayer/primitive2d/textprimitive2d.hxx b/drawinglayer/inc/drawinglayer/primitive2d/textprimitive2d.hxx index 75669cf53a55..dba663395e84 100644 --- a/drawinglayer/inc/drawinglayer/primitive2d/textprimitive2d.hxx +++ b/drawinglayer/inc/drawinglayer/primitive2d/textprimitive2d.hxx @@ -4,9 +4,9 @@ * * $RCSfile: textprimitive2d.hxx,v $ * - * $Revision: 1.8 $ + * $Revision: 1.9 $ * - * last change: $Author: aw $ $Date: 2007-08-02 11:43:43 $ + * last change: $Author: aw $ $Date: 2007-09-26 11:36:28 $ * * The Contents of this file are made available subject to * the terms of GNU Lesser General Public License Version 2.1. @@ -68,10 +68,12 @@ namespace drawinglayer { namespace primitive2d { - struct FontAttributes + class FontAttributes { - String maFamilyName; - String maStyleName; + private: + // core data + rtl::OUString maFamilyName; + rtl::OUString maStyleName; sal_uInt16 mnWeight; // bitfield @@ -81,17 +83,36 @@ namespace drawinglayer unsigned mbOutline : 1; // TODO: pair kerning and CJK kerning - // compare operator - bool operator==(const FontAttributes& rCompare) const + public: + FontAttributes( + const rtl::OUString& rFamilyName, + const rtl::OUString& rStyleName, + sal_uInt16 nWeight, + bool bSymbol = false, + bool bVertical = false, + bool bItalic = false, + bool bOutline = false) + : maFamilyName(rFamilyName), + maStyleName(rStyleName), + mnWeight(nWeight), + mbSymbol(bSymbol), + mbVertical(bVertical), + mbItalic(bItalic), + mbOutline(bOutline) { - return (maFamilyName == rCompare.maFamilyName - && maStyleName == rCompare.maStyleName - && mnWeight == rCompare.mnWeight - && mbSymbol == rCompare.mbSymbol - && mbVertical == rCompare.mbVertical - && mbItalic == rCompare.mbItalic - && mbOutline == rCompare.mbOutline); } + + // compare operator + bool operator==(const FontAttributes& rCompare) const; + + // data access + const rtl::OUString& getFamilyName() const { return maFamilyName; } + const rtl::OUString& getStyleName() const { return maStyleName; } + sal_uInt16 getWeight() const { return mnWeight; } + bool getSymbol() const { return mbSymbol; } + bool getVertical() const { return mbVertical; } + bool getItalic() const { return mbItalic; } + bool getOutline() const { return mbOutline; } }; // helper methods for vcl font @@ -112,7 +133,7 @@ namespace drawinglayer { private: basegfx::B2DHomMatrix maTextTransform; // text range transformation from unit range ([0.0 .. 1.0]) to text range - String maText; // the text + rtl::OUString maText; // the text ::std::vector< double > maDXArray; // the DX array scale-independent in unit coordinates FontAttributes maFontAttributes; // the font to use ::com::sun::star::lang::Locale maLocale; // the Locale for the text @@ -125,7 +146,7 @@ namespace drawinglayer public: TextSimplePortionPrimitive2D( const basegfx::B2DHomMatrix& rNewTransform, - const String& rText, + const rtl::OUString& rText, const ::std::vector< double >& rDXArray, const FontAttributes& rFontAttributes, const ::com::sun::star::lang::Locale& rLocale, @@ -133,7 +154,7 @@ namespace drawinglayer // get data const basegfx::B2DHomMatrix& getTextTransform() const { return maTextTransform; } - const String& getText() const { return maText; } + const rtl::OUString& getText() const { return maText; } const ::std::vector< double >& getDXArray() const { return maDXArray; } const FontAttributes& getFontAttributes() const { return maFontAttributes; } const ::com::sun::star::lang::Locale& getLocale() const { return maLocale; } diff --git a/drawinglayer/prj/d.lst b/drawinglayer/prj/d.lst index 250866a5398d..5ebf8f708b3b 100644 --- a/drawinglayer/prj/d.lst +++ b/drawinglayer/prj/d.lst @@ -33,6 +33,7 @@ mkdir: %_DEST%\inc%_EXT%\drawinglayer\primitive2d ..\inc\drawinglayer\primitive2d\polypolygonprimitive2d.hxx %_DEST%\inc%_EXT%\drawinglayer\primitive2d\polypolygonprimitive2d.hxx ..\inc\drawinglayer\primitive2d\sceneprimitive2d.hxx %_DEST%\inc%_EXT%\drawinglayer\primitive2d\sceneprimitive2d.hxx ..\inc\drawinglayer\primitive2d\shadowprimitive2d.hxx %_DEST%\inc%_EXT%\drawinglayer\primitive2d\shadowprimitive2d.hxx +..\inc\drawinglayer\primitive2d\texteffectprimitive2d.hxx %_DEST%\inc%_EXT%\drawinglayer\primitive2d\texteffectprimitive2d.hxx ..\inc\drawinglayer\primitive2d\textlayoutdevice.hxx %_DEST%\inc%_EXT%\drawinglayer\primitive2d\textlayoutdevice.hxx ..\inc\drawinglayer\primitive2d\textprimitive2d.hxx %_DEST%\inc%_EXT%\drawinglayer\primitive2d\textprimitive2d.hxx ..\inc\drawinglayer\primitive2d\textdecoratedprimitive2d.hxx %_DEST%\inc%_EXT%\drawinglayer\primitive2d\textdecoratedprimitive2d.hxx diff --git a/drawinglayer/source/primitive2d/makefile.mk b/drawinglayer/source/primitive2d/makefile.mk index 3b28b07ce7ce..c09562ca545d 100644 --- a/drawinglayer/source/primitive2d/makefile.mk +++ b/drawinglayer/source/primitive2d/makefile.mk @@ -4,9 +4,9 @@ # # $RCSfile: makefile.mk,v $ # -# $Revision: 1.7 $ +# $Revision: 1.8 $ # -# last change: $Author: aw $ $Date: 2007-09-20 09:51:38 $ +# last change: $Author: aw $ $Date: 2007-09-26 11:36:36 $ # # The Contents of this file are made available subject to # the terms of GNU Lesser General Public License Version 2.1. @@ -70,6 +70,7 @@ SLOFILES= \ $(SLO)$/polygonprimitive2d.obj \ $(SLO)$/sceneprimitive2d.obj \ $(SLO)$/shadowprimitive2d.obj \ + $(SLO)$/texteffectprimitive2d.obj \ $(SLO)$/textlayoutdevice.obj \ $(SLO)$/textprimitive2d.obj \ $(SLO)$/textdecoratedprimitive2d.obj \ diff --git a/drawinglayer/source/primitive2d/polygonprimitive2d.cxx b/drawinglayer/source/primitive2d/polygonprimitive2d.cxx index 336bfaf7d097..76ccb50c92db 100644 --- a/drawinglayer/source/primitive2d/polygonprimitive2d.cxx +++ b/drawinglayer/source/primitive2d/polygonprimitive2d.cxx @@ -4,9 +4,9 @@ * * $RCSfile: polygonprimitive2d.cxx,v $ * - * $Revision: 1.4 $ + * $Revision: 1.5 $ * - * last change: $Author: aw $ $Date: 2007-09-20 09:51:38 $ + * last change: $Author: aw $ $Date: 2007-09-26 11:36:36 $ * * The Contents of this file are made available subject to * the terms of GNU Lesser General Public License Version 2.1. @@ -332,13 +332,13 @@ namespace drawinglayer { // create waveline curve const basegfx::B2DPolygon aWaveline(basegfx::tools::createWaveline(getB2DPolygon(), getWaveWidth(), getWaveHeight())); - const Primitive2DReference xRef(new PolygonHairlinePrimitive2D(aWaveline, getBColor())); + const Primitive2DReference xRef(new PolygonStrokePrimitive2D(aWaveline, getStrokeAttribute())); aRetval = Primitive2DSequence(&xRef, 1); } else { - // flat waveline, decompose to PolygonHairlinePrimitive2D - const Primitive2DReference xRef(new PolygonHairlinePrimitive2D(getB2DPolygon(), getBColor())); + // flat waveline, decompose to simple line primitive + const Primitive2DReference xRef(new PolygonStrokePrimitive2D(getB2DPolygon(), getStrokeAttribute())); aRetval = Primitive2DSequence(&xRef, 1); } } @@ -348,12 +348,12 @@ namespace drawinglayer PolygonWavePrimitive2D::PolygonWavePrimitive2D( const basegfx::B2DPolygon& rPolygon, - const basegfx::BColor& rBColor, + const attribute::StrokeAttribute& rStrokeAttribute, double fWaveWidth, double fWaveHeight) : BasePrimitive2D(), maPolygon(rPolygon), - maBColor(rBColor), + maStrokeAttribute(rStrokeAttribute), mfWaveWidth(fWaveWidth), mfWaveHeight(fWaveHeight) { @@ -375,7 +375,7 @@ namespace drawinglayer const PolygonWavePrimitive2D& rCompare = (PolygonWavePrimitive2D&)rPrimitive; return (getB2DPolygon() == rCompare.getB2DPolygon() - && getBColor() == rCompare.getBColor() + && getStrokeAttribute() == rCompare.getStrokeAttribute() && getWaveWidth() == rCompare.getWaveWidth() && getWaveHeight() == rCompare.getWaveHeight()); } @@ -394,6 +394,12 @@ namespace drawinglayer aRetval.grow(getWaveHeight()); } + // if line width, grow by it + if(!basegfx::fTools::equalZero(getStrokeAttribute().getWidth())) + { + aRetval.grow(getStrokeAttribute().getWidth()); + } + return aRetval; } diff --git a/drawinglayer/source/primitive2d/textdecoratedprimitive2d.cxx b/drawinglayer/source/primitive2d/textdecoratedprimitive2d.cxx index 80c00afe22e8..84a1e75cb826 100644 --- a/drawinglayer/source/primitive2d/textdecoratedprimitive2d.cxx +++ b/drawinglayer/source/primitive2d/textdecoratedprimitive2d.cxx @@ -4,9 +4,9 @@ * * $RCSfile: textdecoratedprimitive2d.cxx,v $ * - * $Revision: 1.5 $ + * $Revision: 1.6 $ * - * last change: $Author: aw $ $Date: 2007-09-20 09:51:38 $ + * last change: $Author: aw $ $Date: 2007-09-26 11:36:36 $ * * The Contents of this file are made available subject to * the terms of GNU Lesser General Public License Version 2.1. @@ -53,6 +53,34 @@ #include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx> #endif +#ifndef _BGFX_MATRIX_B2DHOMMATRIXTOOLS_HXX +#include <basegfx/matrix/b2dhommatrixtools.hxx> +#endif + +#ifndef _COMPHELPER_PROCESSFACTORY_HXX_ +#include <comphelper/processfactory.hxx> +#endif + +#ifndef _COM_SUN_STAR_I18N_WORDTYPE_HPP_ +#include <com/sun/star/i18n/WordType.hpp> +#endif + +#ifndef INCLUDED_DRAWINGLAYER_PRIMITIVE_TEXTEFFECTPRIMITIVE2D_HXX +#include <drawinglayer/primitive2d/texteffectprimitive2d.hxx> +#endif + +#ifndef INCLUDED_DRAWINGLAYER_PRIMITIVE2D_SHADOWPRIMITIVE2D_HXX +#include <drawinglayer/primitive2d/shadowprimitive2d.hxx> +#endif + +#ifndef _COM_SUN_STAR_I18N_XBREAKITERATOR_HPP_ +#include <com/sun/star/i18n/XBreakIterator.hpp> +#endif + +#ifndef INCLUDED_DRAWINGLAYER_PRIMITIVE2D_TRANSFORMPRIMITIVE2D_HXX +#include <drawinglayer/primitive2d/transformprimitive2d.hxx> +#endif + #include <numeric> ////////////////////////////////////////////////////////////////////////////// @@ -61,408 +89,581 @@ namespace drawinglayer { namespace primitive2d { -/* Primitive2DSequence TextDecoratedPortionPrimitive2D::createLocalDecomposition(const geometry::ViewInformation2D& rViewInformation) const + void TextDecoratedPortionPrimitive2D::impCreateGeometryContent( + std::vector< Primitive2DReference >& rTarget, + basegfx::DecomposedB2DHomMatrixContainer& rDecTrans, + const rtl::OUString& rText, + const ::std::vector< double >& rDXArray, + const FontAttributes& rFontAttributes) const { - const sal_uInt16 nTextLength(getText().Len()); - Primitive2DSequence aRetval; - - if(nTextLength) + // create the SimpleTextPrimitive needed in any case + rTarget.push_back(Primitive2DReference(new TextSimplePortionPrimitive2D( + rDecTrans.getB2DHomMatrix(), + rText, + rDXArray, + rFontAttributes, + getLocale(), + getFontColor()))); + + // see if something else needs to be done + const bool bUnderlineUsed(FONT_UNDERLINE_NONE != getFontUnderline()); + const bool bStrikeoutUsed(FONT_STRIKEOUT_NONE != getFontStrikeout()); + + if(bUnderlineUsed || bStrikeoutUsed) { - if(getWordLineMode()) + // common preparations + basegfx::B2DHomMatrix aUnscaledTransform; + TextLayouterDevice aTextLayouter; + + // unscaled is needed since scale contains already the font size + aUnscaledTransform.rotate(rDecTrans.getRotate()); + aUnscaledTransform.shearX(rDecTrans.getShearX()); + aUnscaledTransform.translate(rDecTrans.getTranslate().getX(), rDecTrans.getTranslate().getY()); + + // TextLayouterDevice is needed to get metrics for text decorations like + // underline/strikeout/emphasis marks from it. For setup, the unrotated transform + // is needed + basegfx::B2DHomMatrix aUnrotatedTransform(rDecTrans.getB2DHomMatrix()); + aUnrotatedTransform.rotate(-rDecTrans.getRotate()); + aTextLayouter.setFontAttributes(getFontAttributes(), aUnrotatedTransform ); + + // get text width + double fTextWidth(0.0); + + if(rDXArray.empty()) { - // support for single word mode - if(!mxBreakIterator.is()) - { - ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > xMSF(::comphelper::getProcessServiceFactory()); - mxBreakIterator.set(xMSF->createInstance(rtl::OUString::createFromAscii("com.sun.star.i18n.BreakIterator")), ::com::sun::star::uno::UNO_QUERY); - } + fTextWidth = aTextLayouter.getTextWidth(rText, 0/*TODO*/, rText.getLength()/*TODO*/ ); + } + else + { + fTextWidth = rDXArray.back() * rDecTrans.getScale().getX(); + } - if(mxBreakIterator.is()) + if(bUnderlineUsed) + { + // create primitive geometry for underline + bool bDoubleLine(false); + bool bWaveLine(false); + bool bBoldLine(false); + const int* pDashDotArray(0); + basegfx::tools::B2DLineJoin eLineJoin(basegfx::tools::B2DLINEJOIN_NONE); + double fUnderlineOffset(aTextLayouter.getUnderlineOffset()); + double fUnderlineHeight(aTextLayouter.getUnderlineHeight()); + + 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 + + switch(getFontUnderline()) { - for(sal_Int32 nPos(0); nPos < nTextLength;) + default: // case FONT_UNDERLINE_SINGLE: + { + break; + } + case FONT_UNDERLINE_DOUBLE: + { + bDoubleLine = true; + break; + } + case FONT_UNDERLINE_DOTTED: + { + pDashDotArray = aDottedArray; + break; + } + case FONT_UNDERLINE_DASH: + { + pDashDotArray = aDashedArray; + break; + } + case FONT_UNDERLINE_LONGDASH: + { + pDashDotArray = aLongDashArray; + break; + } + case FONT_UNDERLINE_DASHDOT: + { + pDashDotArray = aDashDotArray; + break; + } + case FONT_UNDERLINE_DASHDOTDOT: + { + pDashDotArray = aDashDotDotArray; + break; + } + case FONT_UNDERLINE_SMALLWAVE: + { + bWaveLine = true; + break; + } + case FONT_UNDERLINE_WAVE: + { + bWaveLine = true; + break; + } + case FONT_UNDERLINE_DOUBLEWAVE: + { + bDoubleLine = true; + bWaveLine = true; + break; + } + case FONT_UNDERLINE_BOLD: + { + bBoldLine = true; + break; + } + case FONT_UNDERLINE_BOLDDOTTED: + { + bBoldLine = true; + pDashDotArray = aDottedArray; + break; + } + case FONT_UNDERLINE_BOLDDASH: + { + bBoldLine = true; + pDashDotArray = aDashedArray; + break; + } + case FONT_UNDERLINE_BOLDLONGDASH: + { + bBoldLine = true; + pDashDotArray = aLongDashArray; + break; + } + case FONT_UNDERLINE_BOLDDASHDOT: + { + bBoldLine = true; + pDashDotArray = aDashDotArray; + break; + } + case FONT_UNDERLINE_BOLDDASHDOTDOT: + { + bBoldLine = true; + pDashDotArray = aDashDotDotArray; + break; + } + case FONT_UNDERLINE_BOLDWAVE: { - ::com::sun::star::i18n::Boundary nNextWordBoundary(mxBreakIterator->getWordBoundary( - getText(), nPos, getLocale(), ::com::sun::star::i18n::WordType::ANY_WORD, sal_True)); - const String aNewText(getText(), nPos, nNextWordBoundary - nPos); - ::std::vector< double > aNewDXArray(getDXArray().begin() + nPos, getDXArray().end() + nNextWordBoundary); - - TextDecoratedPortionPrimitive2D aNewPrimitive( - getTextTransform(), - aNewText, - aNewDXArray, - getFontAttributes(), - getLocale(), - getFontColor(), - getTextlineColor(), - getFontUnderline(), - getUnderlineAbove(), - getFontStrikeout(), - false, // no WordLineMode - getFontEmphasisMark(), - getEmphasisMarkAbove(), - getEmphasisMarkBelow(), - RELIEF_NONE, // no relief - false); // no shadow - - appendPrimitive2DSequenceToPrimitive2DSequence(aRetval, aNewPrimitive.get2DDecomposition(rViewInformation)); - - nPos = nNextWordBoundary; + bWaveLine = true; + bBoldLine = true; + break; } } - } - else - { - // no single words needed, decompose - std::vector< BasePrimitive2D* > aNewPrimitives; - - - // prepare return sequence - for(sal_uInt32 a(0); a < aNewPrimitives.size(); a++) + if(bBoldLine) { - aRetval[a] = Primitive2DReference(aNewPrimitives[a]); + fUnderlineHeight *= 2.0; } - } - if(aRetval.hasElements()) - { - Primitive2DSequence aContent(aRetval); - - if(getShadow()) + if(bDoubleLine) { + fUnderlineOffset -= 0.50 * fUnderlineHeight; + fUnderlineHeight *= 0.64; } - if(RELIEF_NONE != getFontRelief()) + if(bWaveLine) { + eLineJoin = basegfx::tools::B2DLINEJOIN_ROUND; + fUnderlineHeight *= 0.5; } - } - } - return aRetval; - } */ + // prepare StrokeAttributes + attribute::StrokeAttribute aStrokeAttribute(getTextlineColor(), fUnderlineHeight, eLineJoin); - Primitive2DSequence TextDecoratedPortionPrimitive2D::createLocalDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const - { - std::vector< BasePrimitive2D* > aNewPrimitives; + if(pDashDotArray) + { + ::std::vector< double > aDoubleArray; - // First create a simple text primitive and ignore other attributes - aNewPrimitives.push_back(new TextSimplePortionPrimitive2D(getTextTransform(), getText(), getDXArray(), getFontAttributes(), getLocale(), getFontColor())); + for(const int* p = pDashDotArray; *p; ++p) + { + aDoubleArray.push_back((double)(*p) * fUnderlineHeight); + } - // more to be done? - const bool bNeedFontUnderline(getFontUnderline() != FONT_UNDERLINE_NONE); - const bool bNeedFontStrikeout(getFontStrikeout() != FONT_STRIKEOUT_NONE); - const bool bNeedEmphasisMarkAbove(getEmphasisMarkAbove() != FONT_EMPHASISMARK_NONE); - const bool bNeedEmphasisMarkBelow(getEmphasisMarkBelow() != FONT_EMPHASISMARK_NONE); + const double fFullDashDotLen(::std::accumulate(aDoubleArray.begin(), aDoubleArray.end(), 0.0)); - if(bNeedFontUnderline - || bNeedFontStrikeout - || bNeedEmphasisMarkAbove - || bNeedEmphasisMarkBelow) - { - // prepare transformations - basegfx::B2DVector aScale, aTranslate; - double fRotate, fShearX; - getTextTransform().decompose(aScale, aTranslate, fRotate, fShearX); + aStrokeAttribute = attribute::StrokeAttribute( + aStrokeAttribute.getColor(), + aStrokeAttribute.getWidth(), + aStrokeAttribute.getLineJoin(), + aDoubleArray, + fFullDashDotLen); + } - // unscaled transform is needed since the scale in the text transform describes the font size - basegfx::B2DHomMatrix aUnscaledTransform; - aUnscaledTransform.rotate( fRotate ); - aUnscaledTransform.shearX( fShearX ); - aUnscaledTransform.translate( aTranslate.getX(), aTranslate.getY() ); + // create base polygon and new primitive + basegfx::B2DPolygon aUnderline; + Primitive2DReference aNewPrimitive; - // prepare TextLayouterDevice to get metrics for text decorations like - // underline/strikeout/emphasis marks from it - TextLayouterDevice aTextLayouter; + aUnderline.append(basegfx::B2DPoint(0.0, fUnderlineOffset)); + aUnderline.append(basegfx::B2DPoint(fTextWidth, fUnderlineOffset)); + aUnderline.transform(aUnscaledTransform); - { - // unrotated transform is needed for TextLayouterDevice setup - basegfx::B2DHomMatrix aUnrotatedTransform = getTextTransform(); - aUnrotatedTransform.rotate( -fRotate ); - aTextLayouter.setFontAttributes(getFontAttributes(), aUnrotatedTransform ); - } + if(bWaveLine) + { + double fWaveWidth(4.0 * fUnderlineHeight); - // init metrics to defaults -// const double fLineHeight(aTextLayouter.getTextHeight()); - double fUnderlineOffset(aTextLayouter.getUnderlineOffset()); - double fUnderlineHeight(aTextLayouter.getUnderlineHeight()); - basegfx::tools::B2DLineJoin eLineJoin(basegfx::tools::B2DLINEJOIN_NONE); - bool bDoubleLine(false); - bool bWaveLine(false); - double fTextWidth(0.0); + if(primitive2d::FONT_UNDERLINE_SMALLWAVE == getFontUnderline()) + { + fWaveWidth *= 0.7; + } + else if(primitive2d::FONT_UNDERLINE_WAVE == getFontUnderline()) + { + // extra multiply to get the same WaveWidth as with the bold version + fWaveWidth *= 2.0; + } - if(getDXArray().empty()) - { - fTextWidth = aTextLayouter.getTextWidth( getText(), 0/*TODO*/, getText().Len()/*TODO*/ ); - } - else - { - fTextWidth = getDXArray().back() * aScale.getX(); - } + aNewPrimitive = Primitive2DReference(new PolygonWavePrimitive2D(aUnderline, aStrokeAttribute, fWaveWidth, 0.5 * fWaveWidth)); + } + else + { + aNewPrimitive = Primitive2DReference(new PolygonStrokePrimitive2D(aUnderline, aStrokeAttribute)); + } - // prepare line styles for text decoration lines - const int* pDashDotArray(0); + // add primitive + rTarget.push_back(aNewPrimitive); - 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 + if(bDoubleLine) + { + // double line, create 2nd primitive with offset using TransformPrimitive based on + // already created NewPrimitive + const double fLineDist((bWaveLine ? 3.0 : 2.0) * fUnderlineHeight); + basegfx::B2DHomMatrix aTransform; - // 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; + // move base point of text to 0.0 and de-rotate + aTransform.translate(-rDecTrans.getTranslate().getX(), -rDecTrans.getTranslate().getY()); + aTransform.rotate(-rDecTrans.getRotate()); + + // translate in Y by offset + aTransform.translate(0.0, fLineDist); + + // move back and rotate + aTransform.rotate(rDecTrans.getRotate()); + aTransform.translate(rDecTrans.getTranslate().getX(), rDecTrans.getTranslate().getY()); + + // add transform primitive + const Primitive2DSequence aContent(&aNewPrimitive, 1); + rTarget.push_back(Primitive2DReference(new TransformPrimitive2D(aTransform, aContent))); + } } - if(fUnderlineHeight > 0.0) + if(bStrikeoutUsed) { - if(bDoubleLine) + // create primitive geometry for strikeout + if(FONT_STRIKEOUT_SLASH == getFontStrikeout() || FONT_STRIKEOUT_X == getFontStrikeout()) { - fUnderlineOffset -= 0.50 * fUnderlineHeight; - fUnderlineHeight *= 0.64; - } - - basegfx::B2DPolygon aUnderline; - ::basegfx::B2DPoint aPoint( 0.0, fUnderlineOffset ); - aUnderline.append( aPoint ); + // strikeout with character + const sal_Unicode aStrikeoutChar(FONT_STRIKEOUT_SLASH == getFontStrikeout() ? '/' : 'X'); + const rtl::OUString aSingleCharString(aStrikeoutChar); + const double fStrikeCharWidth(aTextLayouter.getTextWidth(aSingleCharString, 0, 1)); + const double fStrikeCharCount(fabs(fTextWidth/fStrikeCharWidth)); + const sal_uInt32 nStrikeCharCount(static_cast< sal_uInt32 >(fStrikeCharCount + 0.9)); + const double fScaleX(rDecTrans.getScale().getX()); + const double fStrikeCharWidthUnscaled(basegfx::fTools::equalZero(fScaleX) ? fStrikeCharWidth : fStrikeCharWidth/fScaleX); + + std::vector<double> aDXArray(nStrikeCharCount); + rtl::OUString aStrikeoutString; + + for(sal_uInt32 a(0); a < nStrikeCharCount; a++) + { + aStrikeoutString += aSingleCharString; + aDXArray[a] = (a + 1) * fStrikeCharWidthUnscaled; + } - if(!bWaveLine) - { - // straight underline - aUnderline.append( aPoint + ::basegfx::B2DPoint( fTextWidth, 0.0 ) ); + rTarget.push_back(Primitive2DReference(new TextSimplePortionPrimitive2D( + rDecTrans.getB2DHomMatrix(), + aStrikeoutString, + aDXArray, + rFontAttributes, + getLocale(), + getFontColor()))); } else { - // wavy underline - basegfx::B2DPolygon& aWavePoly = aUnderline; - double fWaveWidth(4.0 * fUnderlineHeight); + // strikeout with geometry + double fStrikeoutHeight(aTextLayouter.getUnderlineHeight()); + double fStrikeoutOffset(aTextLayouter.getStrikeoutOffset()); + bool bDoubleLine(false); - if(primitive2d::FONT_UNDERLINE_SMALLWAVE == getFontUnderline()) + // set Underline attribute + switch(getFontStrikeout()) { - fWaveWidth *= 0.7; + default : // case primitive2d::FONT_STRIKEOUT_SINGLE: + { + break; + } + case primitive2d::FONT_STRIKEOUT_DOUBLE: + { + bDoubleLine = true; + break; + } + case primitive2d::FONT_STRIKEOUT_BOLD: + { + fStrikeoutHeight *= 2.0; + break; + } } - const double fWaveHeight(0.5 * fWaveWidth); - const ::basegfx::B2DPoint aCtrlOffset( fWaveWidth * 0.467308, fWaveHeight ); - - for(double fPos = fWaveWidth; fPos < fTextWidth; fPos += fWaveWidth) + if(bDoubleLine) { - // 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.setNextControlPoint( n-1, aPoint + aCtrlOffset ); - aWavePoly.append(aPoint += ::basegfx::B2DPoint( fWaveWidth, 0.0 ) ); - aWavePoly.setPrevControlPoint( n-1, aPoint - aCtrlOffset ); + fStrikeoutOffset -= 0.50 * fStrikeoutHeight; + fStrikeoutHeight *= 0.64; } - // adjust stroke style - eLineJoin = basegfx::tools::B2DLINEJOIN_ROUND; - fUnderlineHeight *= 0.5; - } + // create base polygon and new primitive + basegfx::B2DPolygon aStrikeoutLine; - const basegfx::BColor& rLineColor = getTextlineColor(); - attribute::StrokeAttribute aStrokeAttr(rLineColor, fUnderlineHeight, eLineJoin); + aStrikeoutLine.append(basegfx::B2DPoint(0.0, -fStrikeoutOffset)); + aStrikeoutLine.append(basegfx::B2DPoint(fTextWidth, -fStrikeoutOffset)); + aStrikeoutLine.transform(aUnscaledTransform); - if(pDashDotArray) - { - ::std::vector< double > aDoubleArray; + const attribute::StrokeAttribute aStrokeAttribute(getFontColor(), fStrikeoutHeight, basegfx::tools::B2DLINEJOIN_NONE); + Primitive2DReference aNewPrimitive(new PolygonStrokePrimitive2D(aStrikeoutLine, aStrokeAttribute)); - for( const int* p = pDashDotArray; *p; ++p ) + // add primitive + rTarget.push_back(aNewPrimitive); + + if(bDoubleLine) { - aDoubleArray.push_back( *p * fUnderlineHeight); - } + // double line, create 2nd primitive with offset using TransformPrimitive based on + // already created NewPrimitive + const double fLineDist(2.0 * fStrikeoutHeight); + basegfx::B2DHomMatrix aTransform; - const double fFullDashDotLen(::std::accumulate(aDoubleArray.begin(), aDoubleArray.end(), 0.0)); - aStrokeAttr = attribute::StrokeAttribute(rLineColor, fUnderlineHeight, eLineJoin, aDoubleArray, fFullDashDotLen); - } + // move base point of text to 0.0 and de-rotate + aTransform.translate(-rDecTrans.getTranslate().getX(), -rDecTrans.getTranslate().getY()); + aTransform.rotate(-rDecTrans.getRotate()); - aUnderline.transform( aUnscaledTransform ); - aNewPrimitives.push_back(new PolygonStrokePrimitive2D( aUnderline, aStrokeAttr )); + // translate in Y by offset + aTransform.translate(0.0, -fLineDist); - if( bDoubleLine ) - { - // add another underline below the first underline - const double fLineDist((bWaveLine ? 3.0 : 2.0) * fUnderlineHeight); - ::basegfx::B2DVector aOffsetVector( 0.0, fLineDist ); - basegfx::B2DHomMatrix aOffsetTransform; + // move back and rotate + aTransform.rotate(rDecTrans.getRotate()); + aTransform.translate(rDecTrans.getTranslate().getX(), rDecTrans.getTranslate().getY()); - aOffsetVector = aUnscaledTransform * aOffsetVector; - aOffsetTransform.translate( aOffsetVector.getX(), aOffsetVector.getY() ); - aUnderline.transform( aOffsetTransform ); - aNewPrimitives.push_back(new PolygonStrokePrimitive2D( aUnderline, aStrokeAttr )); + // add transform primitive + const Primitive2DSequence aContent(&aNewPrimitive, 1); + rTarget.push_back(Primitive2DReference(new TransformPrimitive2D(aTransform, aContent))); + } } } + } + + // TODO: Handle Font Emphasis Above/Below + } - double fStrikeoutHeight(aTextLayouter.getUnderlineHeight()); - double fStrikeoutOffset(aTextLayouter.getStrikeoutOffset()); - eLineJoin = basegfx::tools::B2DLINEJOIN_NONE; - bDoubleLine = false; - sal_Unicode aStrikeoutChar('\0'); + void TextDecoratedPortionPrimitive2D::impSplitSingleWords( + std::vector< Primitive2DReference >& rTarget, + basegfx::DecomposedB2DHomMatrixContainer& rDecTrans) const + { + // break iterator support + // made static so it only needs to be fetched once, even with many single + // constructed VclMetafileProcessor2D. It's still incarnated on demand, + // but exists for OOo runtime now by purpose. + static ::com::sun::star::uno::Reference< ::com::sun::star::i18n::XBreakIterator > xLocalBreakIterator; - // set Underline attribute - switch( getFontStrikeout() ) - { - default: - DBG_WARNING1( "DrawingLayer: Unknown underline attribute (%d)!", getFontUnderline() ); - // fall through - case primitive2d::FONT_STRIKEOUT_NONE: - fStrikeoutHeight = 0; - break; - case primitive2d::FONT_STRIKEOUT_SINGLE: - break; - case primitive2d::FONT_STRIKEOUT_DOUBLE: - bDoubleLine = true; - break; - case primitive2d::FONT_STRIKEOUT_BOLD: - fStrikeoutHeight *= 2; - break; - case primitive2d::FONT_STRIKEOUT_SLASH: - aStrikeoutChar = '/'; - fStrikeoutHeight = 0; - break; - case primitive2d::FONT_STRIKEOUT_X: - aStrikeoutChar = 'X'; - fStrikeoutHeight = 0; - break; - } + if(!xLocalBreakIterator.is()) + { + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > xMSF(::comphelper::getProcessServiceFactory()); + xLocalBreakIterator.set(xMSF->createInstance(rtl::OUString::createFromAscii("com.sun.star.i18n.BreakIterator")), ::com::sun::star::uno::UNO_QUERY); + } - if(fStrikeoutHeight > 0.0) + if(xLocalBreakIterator.is()) + { + // init word iterator, get first word + ::com::sun::star::i18n::Boundary aNextWordBoundary(xLocalBreakIterator->getWordBoundary( + getText(), 0, getLocale(), ::com::sun::star::i18n::WordType::ANYWORD_IGNOREWHITESPACES, sal_True)); + + // prepare new font attributes WITHOUT outline + const FontAttributes aNewFontAttributes( + getFontAttributes().getFamilyName(), + getFontAttributes().getStyleName(), + getFontAttributes().getWeight(), + getFontAttributes().getSymbol(), + getFontAttributes().getVertical(), + getFontAttributes().getItalic(), + false); // no outline anymore, handled locally + + while(aNextWordBoundary.startPos != aNextWordBoundary.endPos) { - if( bDoubleLine ) - { - fStrikeoutOffset -= 0.50 * fStrikeoutHeight; - fStrikeoutHeight *= 0.64; - } + const sal_uInt32 nLength(aNextWordBoundary.endPos - aNextWordBoundary.startPos); + + // prepare data for the single word + const rtl::OUString aNewText(getText().copy(aNextWordBoundary.startPos, nLength)); - basegfx::B2DPolygon aStrikeoutLine; - basegfx::B2DPoint aPoint( 0.0, -fStrikeoutOffset ); - aStrikeoutLine.append( aPoint ); + // prepare transform for the single word + basegfx::B2DHomMatrix aNewTransform; - if( 1/*####*/ ) + if(aNextWordBoundary.startPos) { - // straight underline - aStrikeoutLine.append( aPoint + ::basegfx::B2DPoint( fTextWidth, 0.0 ) ); + // needs to be moved to a new start position (get from DXArray) + const double fDistance(getDXArray()[aNextWordBoundary.startPos - 1]); + aNewTransform.translate(fDistance, 0.0); } - const basegfx::BColor& rStrikeoutColor = getTextlineColor(); - attribute::StrokeAttribute aStrokeAttr( rStrikeoutColor, fStrikeoutHeight, eLineJoin ); + aNewTransform *= rDecTrans.getB2DHomMatrix(); - aStrikeoutLine.transform( aUnscaledTransform ); - aNewPrimitives.push_back(new PolygonStrokePrimitive2D( aStrikeoutLine, aStrokeAttr )); + // prepare new DXArray for the single word + ::std::vector< double > aNewDXArray( + getDXArray().begin() + aNextWordBoundary.startPos, + getDXArray().begin() + aNextWordBoundary.endPos); - if( bDoubleLine ) + if(aNextWordBoundary.startPos) { - // add another strikeout below the first strikeout - const double fLineDist(2.0 * fStrikeoutHeight); - ::basegfx::B2DVector aOffsetVector( 0.0, -fLineDist ); - basegfx::B2DHomMatrix aOffsetTransform; - - aOffsetVector = aUnscaledTransform * aOffsetVector; - aOffsetTransform.translate( aOffsetVector.getX(), aOffsetVector.getY() ); - aStrikeoutLine.transform( aOffsetTransform ); - aNewPrimitives.push_back(new PolygonStrokePrimitive2D( aStrikeoutLine, aStrokeAttr )); + // DXArray values need to be corrected + const double fDistance(getDXArray()[aNextWordBoundary.startPos - 1]); + + for(sal_uInt32 a(0); a < nLength; a++) + { + aNewDXArray[a] -= fDistance; + } } + + // create geometry content for the single word + basegfx::DecomposedB2DHomMatrixContainer aDecTrans(aNewTransform); + impCreateGeometryContent(rTarget, aDecTrans, aNewText, aNewDXArray, aNewFontAttributes); + + // prepare next word + aNextWordBoundary = xLocalBreakIterator->nextWord( + getText(), aNextWordBoundary.endPos, getLocale(), + ::com::sun::star::i18n::WordType::ANYWORD_IGNOREWHITESPACES); } + } + } - if( aStrikeoutChar != '\0' ) - { - const String aSingleCharString( &aStrikeoutChar, 1 ); - const double fStrikeCharWidth(aTextLayouter.getTextWidth( aSingleCharString, 0, 1 )); - const double fStrikeCharCount(fabs(fTextWidth / fStrikeCharWidth)); - const sal_uInt32 nStrikeCharCount(static_cast< sal_uInt32 >(fStrikeCharCount + 0.9)); - const double fStrikeCharWidthUnscaled(aScale.getX() == 0.0 ? fStrikeCharWidth : fStrikeCharWidth / aScale.getX()); - const basegfx::BColor& rStrikeoutColor = getFontColor(); + Primitive2DSequence TextDecoratedPortionPrimitive2D::createLocalDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const + { + std::vector< Primitive2DReference > aNewPrimitives; + basegfx::DecomposedB2DHomMatrixContainer aDecTrans(getTextTransform()); + Primitive2DSequence aRetval; + + // create basic geometry such as SimpleTextPrimitive, Underline, + // Strikeuot, etc... + if(getWordLineMode()) + { + // support for single word mode + impSplitSingleWords(aNewPrimitives, aDecTrans); + } + else + { + // prepare new font attributes WITHOUT outline + const FontAttributes aNewFontAttributes( + getFontAttributes().getFamilyName(), + getFontAttributes().getStyleName(), + getFontAttributes().getWeight(), + getFontAttributes().getSymbol(), + getFontAttributes().getVertical(), + getFontAttributes().getItalic(), + false); // no outline anymore, handled locally + + // handle as one word + impCreateGeometryContent(aNewPrimitives, aDecTrans, getText(), getDXArray(), aNewFontAttributes); + } - std::vector<double> aDXArray(nStrikeCharCount); - String aStrikeoutString; + // convert to Primitive2DSequence + const sal_uInt32 nMemberCount(aNewPrimitives.size()); - for(sal_uInt32 a(0); a < nStrikeCharCount; a++) - { - aStrikeoutString += aStrikeoutChar; - aDXArray[a] = (a + 1) * fStrikeCharWidthUnscaled; - } + if(nMemberCount) + { + aRetval.realloc(nMemberCount); - aNewPrimitives.push_back(new TextSimplePortionPrimitive2D(getTextTransform(), aStrikeoutString, aDXArray, getFontAttributes(), getLocale(), rStrikeoutColor )); + for(sal_uInt32 a(0); a < nMemberCount; a++) + { + aRetval[a] = aNewPrimitives[a]; } + } - // TODO: need to take care of - // -emphasis mark - // -relief (embosses/engraved) - // -shadow - // if( getWordLineMode() ) - // if( getUnderlineAbove() ) + // Handle Shadow, Outline and FontRelief + if(aRetval.hasElements()) + { + // outline AND shadow depend on NO FontRelief (see dialog) + const bool bHasFontRelief(FONT_RELIEF_NONE != getFontRelief()); + const bool bHasShadow(!bHasFontRelief && getShadow()); + const bool bHasOutline(!bHasFontRelief && getFontAttributes().getOutline()); + if(bHasShadow || bHasFontRelief || bHasOutline) + { + Primitive2DReference aShadow; - } + if(bHasShadow) + { + // create shadow with current content (in aRetval). Text shadow + // is constant, relative to font size, rotated with the text and has a + // constant color. + // shadow parameter values + static double fFactor(1.0 / 24.0); + const double fTextShadowOffset(aDecTrans.getScale().getY() * fFactor); + static basegfx::BColor aShadowColor(0.3, 0.3, 0.3); + + // preapare shadow transform matrix + basegfx::B2DHomMatrix aShadowTransform; + aShadowTransform.translate(fTextShadowOffset, fTextShadowOffset); + + // create shadow primitive + aShadow = Primitive2DReference(new ShadowPrimitive2D( + aShadowTransform, + aShadowColor, + aRetval)); + } - // prepare return sequence - Primitive2DSequence aRetval(aNewPrimitives.size()); + if(bHasFontRelief) + { + // create emboss using an own helper primitive since this will + // be view-dependent + const basegfx::BColor aBBlack(0.0, 0.0, 0.0); + const bool bDefaultTextColor(aBBlack == getFontColor()); + TextEffectStyle2D aTextEffectStyle2D(TEXTEFFECTSTYLE2D_RELIEF_EMBOSSED); - for(sal_uInt32 a(0); a < aNewPrimitives.size(); a++) - { - aRetval[a] = Primitive2DReference(aNewPrimitives[a]); + if(bDefaultTextColor) + { + if(FONT_RELIEF_ENGRAVED == getFontRelief()) + { + aTextEffectStyle2D = TEXTEFFECTSTYLE2D_RELIEF_ENGRAVED_DEFAULT; + } + else + { + aTextEffectStyle2D = TEXTEFFECTSTYLE2D_RELIEF_EMBOSSED_DEFAULT; + } + } + else + { + if(FONT_RELIEF_ENGRAVED == getFontRelief()) + { + aTextEffectStyle2D = TEXTEFFECTSTYLE2D_RELIEF_ENGRAVED; + } + else + { + aTextEffectStyle2D = TEXTEFFECTSTYLE2D_RELIEF_EMBOSSED; + } + } + + Primitive2DReference aNewTextEffect(new TextEffectPrimitive2D( + aRetval, + aDecTrans.getTranslate(), + aDecTrans.getRotate(), + aTextEffectStyle2D)); + aRetval = Primitive2DSequence(&aNewTextEffect, 1); + } + else if(bHasOutline) + { + // create outline using an own helper primitive since this will + // be view-dependent + Primitive2DReference aNewTextEffect(new TextEffectPrimitive2D( + aRetval, + aDecTrans.getTranslate(), + aDecTrans.getRotate(), + TEXTEFFECTSTYLE2D_OUTLINE)); + aRetval = Primitive2DSequence(&aNewTextEffect, 1); + } + + if(aShadow.is()) + { + // put shadow in front if there is one to paint timely before + // but placed behind content + const Primitive2DSequence aContent(aRetval); + aRetval = Primitive2DSequence(&aShadow, 1); + appendPrimitive2DSequenceToPrimitive2DSequence(aRetval, aContent); + } + } } return aRetval; @@ -472,7 +673,7 @@ namespace drawinglayer // TextSimplePortionPrimitive2D parameters const basegfx::B2DHomMatrix& rNewTransform, - const String& rText, + const rtl::OUString& rText, const ::std::vector< double >& rDXArray, const FontAttributes& rFontAttributes, const ::com::sun::star::lang::Locale& rLocale, diff --git a/drawinglayer/source/primitive2d/texteffectprimitive2d.cxx b/drawinglayer/source/primitive2d/texteffectprimitive2d.cxx new file mode 100644 index 000000000000..91171d35f2fd --- /dev/null +++ b/drawinglayer/source/primitive2d/texteffectprimitive2d.cxx @@ -0,0 +1,255 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: texteffectprimitive2d.cxx,v $ + * + * $Revision: 1.1 $ + * + * last change: $Author: aw $ $Date: 2007-09-26 11:36:36 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library 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 for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#ifndef INCLUDED_DRAWINGLAYER_PRIMITIVE_TEXTEFFECTPRIMITIVE2D_HXX +#include <drawinglayer/primitive2d/texteffectprimitive2d.hxx> +#endif + +#ifndef INCLUDED_DRAWINGLAYER_GEOMETRY_VIEWINFORMATION2D_HXX +#include <drawinglayer/geometry/viewinformation2d.hxx> +#endif + +#ifndef INCLUDED_DRAWINGLAYER_PRIMITIVE2D_MODIFIEDCOLORPRIMITIVE2D_HXX +#include <drawinglayer/primitive2d/modifiedcolorprimitive2d.hxx> +#endif + +#ifndef INCLUDED_DRAWINGLAYER_PRIMITIVE2D_TRANSFORMPRIMITIVE2D_HXX +#include <drawinglayer/primitive2d/transformprimitive2d.hxx> +#endif + +#ifndef INCLUDED_DRAWINGLAYER_PRIMITIVE2D_PRIMITIVETYPES2D_HXX +#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx> +#endif + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace primitive2d + { + static double fDiscreteSize(1.1); + + Primitive2DSequence TextEffectPrimitive2D::createLocalDecomposition(const geometry::ViewInformation2D& rViewInformation) const + { + Primitive2DSequence aRetval; + + // get the distance of one discrete units from target display. Use between 1.0 and sqrt(2) to + // have good results on rotated objects, too + const basegfx::B2DVector aDistance(rViewInformation.getInverseViewTransformation() * basegfx::B2DVector(fDiscreteSize, fDiscreteSize)); + const basegfx::B2DVector aDiagonalDistance(aDistance * (1.0 / 1.44)); + + switch(getTextEffectStyle2D()) + { + case TEXTEFFECTSTYLE2D_RELIEF_EMBOSSED: + case TEXTEFFECTSTYLE2D_RELIEF_ENGRAVED: + case TEXTEFFECTSTYLE2D_RELIEF_EMBOSSED_DEFAULT: + case TEXTEFFECTSTYLE2D_RELIEF_ENGRAVED_DEFAULT: + { + // prepare transform of sub-group back to (0,0) and align to X-Axis + basegfx::B2DHomMatrix aBackTransform; + aBackTransform.translate(-getRotationCenter().getX(), -getRotationCenter().getY()); + aBackTransform.rotate(-getDirection()); + + // prepare transform of sub-group back to it's position and rotation + basegfx::B2DHomMatrix aForwardTransform; + aForwardTransform.rotate(getDirection()); + aForwardTransform.translate(getRotationCenter().getX(), getRotationCenter().getY()); + + // create transformation for one discrete unit + const bool bEmbossed( + TEXTEFFECTSTYLE2D_RELIEF_EMBOSSED == getTextEffectStyle2D() + || TEXTEFFECTSTYLE2D_RELIEF_EMBOSSED_DEFAULT == getTextEffectStyle2D()); + const bool bDefaultTextColor( + TEXTEFFECTSTYLE2D_RELIEF_EMBOSSED_DEFAULT == getTextEffectStyle2D() + || TEXTEFFECTSTYLE2D_RELIEF_ENGRAVED_DEFAULT == getTextEffectStyle2D()); + basegfx::B2DHomMatrix aTransform(aBackTransform); + aRetval.realloc(2); + + if(bEmbossed) + { + // to bottom-right + aTransform.translate(aDiagonalDistance.getX(), aDiagonalDistance.getY()); + } + else + { + // to top-left + aTransform.translate(-aDiagonalDistance.getX(), -aDiagonalDistance.getY()); + } + + aTransform *= aForwardTransform; + + if(bDefaultTextColor) + { + // emboss/engrave in black, original forced to white + const basegfx::BColorModifier aBColorModifierToGray(basegfx::BColor(0.0)); + const Primitive2DReference xModifiedColor(new ModifiedColorPrimitive2D(getChildren(), aBColorModifierToGray)); + aRetval[0] = Primitive2DReference(new TransformPrimitive2D(aTransform, Primitive2DSequence(&xModifiedColor, 1))); + + // add original, too + const basegfx::BColorModifier aBColorModifierToWhite(basegfx::BColor(1.0)); + aRetval[1] = Primitive2DReference(new ModifiedColorPrimitive2D(getChildren(), aBColorModifierToWhite)); + } + else + { + // emboss/engrave in gray, keep original's color + const basegfx::BColorModifier aBColorModifierToGray(basegfx::BColor(0.75)); // 192 + const Primitive2DReference xModifiedColor(new ModifiedColorPrimitive2D(getChildren(), aBColorModifierToGray)); + aRetval[0] = Primitive2DReference(new TransformPrimitive2D(aTransform, Primitive2DSequence(&xModifiedColor, 1))); + + // add original, too + aRetval[1] = Primitive2DReference(new GroupPrimitive2D(getChildren())); + } + + break; + } + case TEXTEFFECTSTYLE2D_OUTLINE: + { + // create transform primitives in all directions + basegfx::B2DHomMatrix aTransform; + aRetval.realloc(9); + + aTransform.set(0, 2, aDistance.getX()); + aTransform.set(1, 2, 0.0); + aRetval[0] = Primitive2DReference(new TransformPrimitive2D(aTransform, getChildren())); + + aTransform.set(0, 2, aDiagonalDistance.getX()); + aTransform.set(1, 2, aDiagonalDistance.getY()); + aRetval[1] = Primitive2DReference(new TransformPrimitive2D(aTransform, getChildren())); + + aTransform.set(0, 2, 0.0); + aTransform.set(1, 2, aDistance.getY()); + aRetval[2] = Primitive2DReference(new TransformPrimitive2D(aTransform, getChildren())); + + aTransform.set(0, 2, -aDiagonalDistance.getX()); + aTransform.set(1, 2, aDiagonalDistance.getY()); + aRetval[3] = Primitive2DReference(new TransformPrimitive2D(aTransform, getChildren())); + + aTransform.set(0, 2, -aDistance.getX()); + aTransform.set(1, 2, 0.0); + aRetval[4] = Primitive2DReference(new TransformPrimitive2D(aTransform, getChildren())); + + aTransform.set(0, 2, -aDiagonalDistance.getX()); + aTransform.set(1, 2, -aDiagonalDistance.getY()); + aRetval[5] = Primitive2DReference(new TransformPrimitive2D(aTransform, getChildren())); + + aTransform.set(0, 2, 0.0); + aTransform.set(1, 2, -aDistance.getY()); + aRetval[6] = Primitive2DReference(new TransformPrimitive2D(aTransform, getChildren())); + + aTransform.set(0, 2, aDiagonalDistance.getX()); + aTransform.set(1, 2, -aDiagonalDistance.getY()); + aRetval[7] = Primitive2DReference(new TransformPrimitive2D(aTransform, getChildren())); + + // at last, place original over it, but force to white + const basegfx::BColorModifier aBColorModifierToWhite(basegfx::BColor(1.0, 1.0, 1.0)); + aRetval[8] = Primitive2DReference(new ModifiedColorPrimitive2D(getChildren(), aBColorModifierToWhite)); + + break; + } + } + + return aRetval; + } + + TextEffectPrimitive2D::TextEffectPrimitive2D( + const Primitive2DSequence& rChildren, + const basegfx::B2DPoint& rRotationCenter, + double fDirection, + TextEffectStyle2D eTextEffectStyle2D) + : GroupPrimitive2D(rChildren), + maRotationCenter(rRotationCenter), + mfDirection(fDirection), + meTextEffectStyle2D(eTextEffectStyle2D) + { + } + + bool TextEffectPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const + { + if(GroupPrimitive2D::operator==(rPrimitive)) + { + const TextEffectPrimitive2D& rCompare = (TextEffectPrimitive2D&)rPrimitive; + + return (getRotationCenter() == rCompare.getRotationCenter() + && getDirection() == rCompare.getDirection() + && getTextEffectStyle2D() == rCompare.getTextEffectStyle2D()); + } + + return false; + } + + basegfx::B2DRange TextEffectPrimitive2D::getB2DRange(const geometry::ViewInformation2D& rViewInformation) const + { + // get range of content and grow by used fDiscreteSize. That way it is not necessary to ask + // the whole decomposition for it's ranges (which may be expensive with outline mode which + // then will ask 9 times at nearly the same content. This may even be refined here using the + // TextEffectStyle information, e.g. for TEXTEFFECTSTYLE2D_RELIEF the grow needs only to + // be in two directions + basegfx::B2DRange aRetval(getB2DRangeFromPrimitive2DSequence(getChildren(), rViewInformation)); + aRetval.grow(fDiscreteSize); + + return aRetval; + } + + Primitive2DSequence TextEffectPrimitive2D::get2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const + { + ::osl::MutexGuard aGuard( m_aMutex ); + + if(getLocalDecomposition().hasElements()) + { + if(maLastViewTransformation != rViewInformation.getViewTransformation()) + { + // conditions of last local decomposition have changed, delete + const_cast< TextEffectPrimitive2D* >(this)->setLocalDecomposition(Primitive2DSequence()); + } + } + + if(!getLocalDecomposition().hasElements()) + { + // remember ViewRange and ViewTransformation + const_cast< TextEffectPrimitive2D* >(this)->maLastViewTransformation = rViewInformation.getViewTransformation(); + } + + // use parent implementation + return BasePrimitive2D::get2DDecomposition(rViewInformation); + } + + // provide unique ID + ImplPrimitrive2DIDBlock(TextEffectPrimitive2D, PRIMITIVE2D_ID_TEXTEFFECTPRIMITIVE2D) + + } // end of namespace primitive2d +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/drawinglayer/source/primitive2d/texthierarchyprimitive2d.cxx b/drawinglayer/source/primitive2d/texthierarchyprimitive2d.cxx index 76aff361226f..f712070afb6d 100644 --- a/drawinglayer/source/primitive2d/texthierarchyprimitive2d.cxx +++ b/drawinglayer/source/primitive2d/texthierarchyprimitive2d.cxx @@ -4,9 +4,9 @@ * * $RCSfile: texthierarchyprimitive2d.cxx,v $ * - * $Revision: 1.1 $ + * $Revision: 1.2 $ * - * last change: $Author: aw $ $Date: 2007-08-03 10:43:05 $ + * last change: $Author: aw $ $Date: 2007-09-26 11:36:36 $ * * The Contents of this file are made available subject to * the terms of GNU Lesser General Public License Version 2.1. @@ -105,7 +105,7 @@ namespace drawinglayer TextHierarchyFieldPrimitive2D::TextHierarchyFieldPrimitive2D( const Primitive2DSequence& rChildren, const FieldType& rFieldType, - const String& rString) + const rtl::OUString& rString) : GroupPrimitive2D(rChildren), meType(rFieldType), maString(rString) diff --git a/drawinglayer/source/primitive2d/textlayoutdevice.cxx b/drawinglayer/source/primitive2d/textlayoutdevice.cxx index 769f7cffea1e..c8af9e53f8b3 100644 --- a/drawinglayer/source/primitive2d/textlayoutdevice.cxx +++ b/drawinglayer/source/primitive2d/textlayoutdevice.cxx @@ -4,9 +4,9 @@ * * $RCSfile: textlayoutdevice.cxx,v $ * - * $Revision: 1.4 $ + * $Revision: 1.5 $ * - * last change: $Author: hdu $ $Date: 2007-02-14 14:53:01 $ + * last change: $Author: aw $ $Date: 2007-09-26 11:36:36 $ * * The Contents of this file are made available subject to * the terms of GNU Lesser General Public License Version 2.1. @@ -210,23 +210,34 @@ namespace drawinglayer return mrDevice.GetTextHeight(); } - double TextLayouterDevice::getTextWidth(const String& rText, xub_StrLen nIndex, xub_StrLen nLength) const + double TextLayouterDevice::getTextWidth(const rtl::OUString& rText, sal_Int32 nIndex, sal_Int32 nLength) const { - return mrDevice.GetTextWidth(rText, nIndex, nLength); + return mrDevice.GetTextWidth(rText, static_cast< sal_uInt16 >(nIndex), static_cast< sal_uInt16 >(nLength)); } - bool TextLayouterDevice::getTextOutlines( basegfx::B2DPolyPolygonVector& rB2DPolyPolyVector, const String& rText, xub_StrLen nIndex, xub_StrLen nLength, const ::std::vector< sal_Int32 >& rDXArray) + bool TextLayouterDevice::getTextOutlines( basegfx::B2DPolyPolygonVector& rB2DPolyPolyVector, const rtl::OUString& rText, sal_Int32 nIndex, sal_Int32 nLength, const ::std::vector< sal_Int32 >& rDXArray) { const sal_Int32* pDXArray = rDXArray.size() ? &rDXArray[0] : NULL; - return mrDevice.GetTextOutlines( rB2DPolyPolyVector, rText, nIndex, nIndex, nLength, true, 0, pDXArray); + return mrDevice.GetTextOutlines( + rB2DPolyPolyVector, + rText, + static_cast< sal_uInt16 >(nIndex), + static_cast< sal_uInt16 >(nIndex), + static_cast< sal_uInt16 >(nLength), + true, 0, pDXArray); } - basegfx::B2DRange TextLayouterDevice::getTextBoundRect(const String& rText, xub_StrLen nIndex, xub_StrLen nLength) const + basegfx::B2DRange TextLayouterDevice::getTextBoundRect(const rtl::OUString& rText, sal_Int32 nIndex, sal_Int32 nLength) const { - if(rText.Len() && nLength) + if(rText.getLength() && nLength) { Rectangle aRect; - mrDevice.GetTextBoundRect(aRect, rText, nIndex, nIndex, nLength); + mrDevice.GetTextBoundRect( + aRect, + rText, + static_cast< sal_uInt16 >(nIndex), + static_cast< sal_uInt16 >(nIndex), + static_cast< sal_uInt16 >(nLength)); return basegfx::B2DRange(aRect.Left(), aRect.Top(), aRect.Right(), aRect.Bottom()); } diff --git a/drawinglayer/source/primitive2d/textprimitive2d.cxx b/drawinglayer/source/primitive2d/textprimitive2d.cxx index 520439e54ada..5aa896346519 100644 --- a/drawinglayer/source/primitive2d/textprimitive2d.cxx +++ b/drawinglayer/source/primitive2d/textprimitive2d.cxx @@ -4,9 +4,9 @@ * * $RCSfile: textprimitive2d.cxx,v $ * - * $Revision: 1.15 $ + * $Revision: 1.16 $ * - * last change: $Author: aw $ $Date: 2007-08-02 11:43:44 $ + * last change: $Author: aw $ $Date: 2007-09-26 11:36:36 $ * * The Contents of this file are made available subject to * the terms of GNU Lesser General Public License Version 2.1. @@ -53,6 +53,29 @@ #include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx> #endif +#ifndef INCLUDED_DRAWINGLAYER_PRIMITIVE_TEXTEFFECTPRIMITIVE2D_HXX +#include <drawinglayer/primitive2d/texteffectprimitive2d.hxx> +#endif + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace primitive2d + { + bool FontAttributes::operator==(const FontAttributes& rCompare) const + { + return (getFamilyName() == rCompare.getFamilyName() + && getStyleName() == rCompare.getStyleName() + && getWeight() == rCompare.getWeight() + && getSymbol() == rCompare.getSymbol() + && getVertical() == rCompare.getVertical() + && getItalic() == rCompare.getItalic() + && getOutline() == rCompare.getOutline()); + } + } // end of namespace primitive2d +} // end of namespace drawinglayer + ////////////////////////////////////////////////////////////////////////////// namespace drawinglayer @@ -79,8 +102,8 @@ namespace drawinglayer } Font aRetval( - rFontAttributes.maFamilyName, - rFontAttributes.maStyleName, + rFontAttributes.getFamilyName(), + rFontAttributes.getStyleName(), Size(nWidth, nHeight)); if(!basegfx::fTools::equalZero(fFontRotation)) @@ -90,30 +113,30 @@ namespace drawinglayer } aRetval.SetAlign(ALIGN_BASELINE); - aRetval.SetCharSet(rFontAttributes.mbSymbol ? RTL_TEXTENCODING_SYMBOL : RTL_TEXTENCODING_UNICODE); - aRetval.SetVertical(rFontAttributes.mbVertical ? TRUE : FALSE); - aRetval.SetWeight(static_cast<FontWeight>(rFontAttributes.mnWeight)); - aRetval.SetItalic(rFontAttributes.mbItalic ? ITALIC_NORMAL : ITALIC_NONE); - aRetval.SetOutline(rFontAttributes.mbOutline); + aRetval.SetCharSet(rFontAttributes.getSymbol() ? RTL_TEXTENCODING_SYMBOL : RTL_TEXTENCODING_UNICODE); + aRetval.SetVertical(rFontAttributes.getVertical() ? TRUE : FALSE); + aRetval.SetWeight(static_cast<FontWeight>(rFontAttributes.getWeight())); + aRetval.SetItalic(rFontAttributes.getItalic() ? ITALIC_NORMAL : ITALIC_NONE); + aRetval.SetOutline(rFontAttributes.getOutline()); return aRetval; } FontAttributes getFontAttributesFromVclFont(basegfx::B2DVector& rSize, const Font& rFont) { - FontAttributes aRetval; - - aRetval.maFamilyName = rFont.GetName(); - aRetval.maStyleName = rFont.GetStyleName(); - aRetval.mbSymbol = (RTL_TEXTENCODING_SYMBOL == rFont.GetCharSet()); - aRetval.mbVertical = rFont.IsVertical(); - aRetval.mnWeight = static_cast<sal_uInt16>(rFont.GetWeight()); - aRetval.mbItalic = (rFont.GetItalic() != ITALIC_NONE); - aRetval.mbOutline = rFont.IsOutline(); + FontAttributes aRetval( + rFont.GetName(), + rFont.GetStyleName(), + static_cast<sal_uInt16>(rFont.GetWeight()), + RTL_TEXTENCODING_SYMBOL == rFont.GetCharSet(), + rFont.IsVertical(), + ITALIC_NONE != rFont.GetItalic(), + rFont.IsOutline()); // TODO: eKerning const sal_Int32 nWidth(rFont.GetSize().getWidth()); const sal_Int32 nHeight(rFont.GetSize().getHeight()); + rSize.setX(nWidth ? nWidth : nHeight); rSize.setY(nHeight); @@ -134,39 +157,47 @@ namespace drawinglayer { Primitive2DSequence TextSimplePortionPrimitive2D::createLocalDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const { - // get integer DXArray for getTextOutlines call (ATM uses vcl) - ::std::vector< sal_Int32 > aNewIntegerDXArray; - getIntegerDXArray(aNewIntegerDXArray); + Primitive2DSequence aRetval; - // prepare transformation matrices - 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 ); - - // prepare textlayoutdevice - TextLayouterDevice aTextLayouter; - aTextLayouter.setFontAttributes(getFontAttributes(), aUnrotatedTransform ); - - // get the text outlines - basegfx::B2DPolyPolygonVector aB2DPolyPolyVector; - aTextLayouter.getTextOutlines( aB2DPolyPolyVector, - getText(), 0L, getText().Len(), aNewIntegerDXArray); - - // create primitives for the outlines - const sal_uInt32 nCount = aB2DPolyPolyVector.size(); - Primitive2DSequence aRetval( nCount ); - - if(nCount) + if(getText().getLength()) { - if( !getFontAttributes().mbOutline ) + // get integer DXArray for getTextOutlines call (ATM uses vcl) + ::std::vector< sal_Int32 > aNewIntegerDXArray; + getIntegerDXArray(aNewIntegerDXArray); + + // prepare transformation matrices + basegfx::B2DVector aScale, aTranslate; + double fRotate, fShearX; + getTextTransform().decompose(aScale, aTranslate, fRotate, fShearX); + + // unscaled transform is needed for transformations since the scale is the font height/width already + basegfx::B2DHomMatrix aUnscaledTransform; + aUnscaledTransform.rotate( fRotate ); + aUnscaledTransform.shearX( fShearX ); + aUnscaledTransform.translate( aTranslate.getX(), aTranslate.getY() ); + + // unrotated transform is needed for text layouter. He works always with + // X-Axis aligned text + basegfx::B2DHomMatrix aUnrotatedTransform(getTextTransform()); + aUnrotatedTransform.rotate( -fRotate ); + + // prepare textlayoutdevice + TextLayouterDevice aTextLayouter; + aTextLayouter.setFontAttributes(getFontAttributes(), aUnrotatedTransform ); + + // get the text outlines + basegfx::B2DPolyPolygonVector aB2DPolyPolyVector; + aTextLayouter.getTextOutlines( aB2DPolyPolyVector, getText(), 0L, getText().getLength(), aNewIntegerDXArray); + + // create primitives for the outlines + const sal_uInt32 nCount(aB2DPolyPolyVector.size()); + + if(nCount) { - // for the glyph shapes as color-filled polypolygons + // alloc space for the primitives + aRetval.realloc(nCount); + + // color-filled polypolygons for(sal_uInt32 a(0L); a < nCount; a++) { // prepare polypolygon @@ -174,23 +205,16 @@ namespace drawinglayer rPolyPolygon.transform(aUnscaledTransform); aRetval[a] = new PolyPolygonColorPrimitive2D(rPolyPolygon, getFontColor()); } - } - else - { - // for the glyph shapes as outline-only polypolygons - double fStrokeWidth = 1.0 + aScale.getY() * 0.02; - if( getFontAttributes().mnWeight > WEIGHT_SEMIBOLD ) - fStrokeWidth *= 1.4; - else if( getFontAttributes().mnWeight < WEIGHT_SEMILIGHT ) - fStrokeWidth *= 0.7; - const drawinglayer::attribute::StrokeAttribute aStrokeAttr( getFontColor(), - fStrokeWidth, basegfx::tools::B2DLINEJOIN_NONE ); - for(sal_uInt32 a(0L); a < nCount; a++) + if(getFontAttributes().getOutline()) { - basegfx::B2DPolyPolygon& rPolyPolygon = aB2DPolyPolyVector[a]; - rPolyPolygon.transform(aUnscaledTransform); - aRetval[a] = new PolyPolygonStrokePrimitive2D(rPolyPolygon, aStrokeAttr); + // create outline text effect with current content and replace + Primitive2DReference aNewTextEffect(new TextEffectPrimitive2D( + aRetval, + aTranslate, + fRotate, + TEXTEFFECTSTYLE2D_OUTLINE)); + aRetval = Primitive2DSequence(&aNewTextEffect, 1); } } } @@ -200,7 +224,7 @@ namespace drawinglayer TextSimplePortionPrimitive2D::TextSimplePortionPrimitive2D( const basegfx::B2DHomMatrix& rNewTransform, - const String& rText, + const rtl::OUString& rText, const ::std::vector< double >& rDXArray, const FontAttributes& rFontAttributes, const ::com::sun::star::lang::Locale& rLocale, @@ -258,7 +282,7 @@ namespace drawinglayer basegfx::B2DRange TextSimplePortionPrimitive2D::getB2DRange(const geometry::ViewInformation2D& /*rViewInformation*/) const { - const xub_StrLen aStrLen(getText().Len()); + const sal_Int32 aStrLen(getText().getLength()); basegfx::B2DRange aRetval; if(aStrLen) diff --git a/drawinglayer/source/primitive2d/wrongspellprimitive2d.cxx b/drawinglayer/source/primitive2d/wrongspellprimitive2d.cxx index bb59c16cb882..748ebcfd2d0b 100644 --- a/drawinglayer/source/primitive2d/wrongspellprimitive2d.cxx +++ b/drawinglayer/source/primitive2d/wrongspellprimitive2d.cxx @@ -4,9 +4,9 @@ * * $RCSfile: wrongspellprimitive2d.cxx,v $ * - * $Revision: 1.1 $ + * $Revision: 1.2 $ * - * last change: $Author: aw $ $Date: 2007-09-20 09:51:38 $ + * last change: $Author: aw $ $Date: 2007-09-26 11:36:36 $ * * The Contents of this file are made available subject to * the terms of GNU Lesser General Public License Version 2.1. @@ -93,8 +93,11 @@ namespace drawinglayer aPolygon.append(getTransformation() * aStart); aPolygon.append(getTransformation() * aStop); + // prepare stroke attribute + const attribute::StrokeAttribute aStrokeAttribute(getColor(), 0.0); + // create the waveline primitive - Primitive2DReference xPrimitive(new PolygonWavePrimitive2D(aPolygon, getColor(), fWaveWidth, 0.5 * fWaveWidth)); + Primitive2DReference xPrimitive(new PolygonWavePrimitive2D(aPolygon, aStrokeAttribute, fWaveWidth, 0.5 * fWaveWidth)); Primitive2DSequence xRetval(&xPrimitive, 1); return xRetval; diff --git a/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx b/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx index 21939c6e2658..3302f45b223d 100644 --- a/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx +++ b/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx @@ -4,9 +4,9 @@ * * $RCSfile: vclmetafileprocessor2d.cxx,v $ * - * $Revision: 1.7 $ + * $Revision: 1.8 $ * - * last change: $Author: aw $ $Date: 2007-09-20 09:51:38 $ + * last change: $Author: aw $ $Date: 2007-09-26 11:36:36 $ * * The Contents of this file are made available subject to * the terms of GNU Lesser General Public License Version 2.1. @@ -446,7 +446,8 @@ namespace drawinglayer // MapMode was not changed, no restore necessary } - /* + /*********************************************************************************************** + Support of MetaCommentActions in the VclMetafileProcessor2D Found MetaCommentActions and how they are supported: @@ -568,16 +569,7 @@ namespace drawinglayer bitmap sizes. Nothing to do here for the primitive renderer. - - - - To be done: - - - - - Evtl. support for vcl::PDFExtOutDevData ?!?! - + Support for vcl::PDFExtOutDevData: PL knows that SJ did that stuff, it's used to hold a pointer to PDFExtOutDevData at the OutDev. When set, some extra data is written there. Trying simple PDF export and watching if i get those infos. @@ -590,19 +582,20 @@ namespace drawinglayer i need to discuss which ones. In the future, all those infos would be taken from the primitive sequence anyways, thus these extensions would potentially be temporary, too. + Discussed with SJ, added the necessary support and tested it. Details follow. - In ImpEditEngine::Paint, paragraph infos and URL stuff is added. - May be added in primitive MetaFile renderer. + Added in primitive MetaFile renderer. Checking URL: Indeed, current version exports it, but it is missing in primitive CWS version. Adding support. - Okay, URLs work. Done. + Okay, URLs work. Checked, Done. - UnoControlPDFExportContact is only created when PDFExtOutDevData is used at the target and uno control data is created in UnoControlPDFExportContact::doPaintObject. This may be added in primitive MetaFile renderer. Adding support... OOps, the necessary helper stuff is in svx/source/form/formpdxexport.cxx in namespace - svxform. Have to talk to FS if thhis has to be like that. Especially since + svxform. Have to talk to FS if this has to be like that. Especially since ::vcl::PDFWriter::AnyWidget is filled out, which is already part of vcl. Wrote an eMail to FS, he is on vacation currently. I see no reason why not to move that stuff to somewhere else, maybe tools or svtools ?!? We will see... @@ -612,22 +605,24 @@ namespace drawinglayer the lowest move,ment plave is toolkit. Checked form control export, it works well. Done. - - - - In goodies, in GraphicObject::Draw, when the used Graphic is linked, infos are generated. I will need to check what happens here with primitives. To support, use of GraphicPrimitive2D (PRIMITIVE2D_ID_GRAPHICPRIMITIVE2D) may be needed. Added support, but feature is broken in main version, so i cannot test at all. - Writing a bug to CL (or SJ) and seeing what happens (#i80380#) ... - TODO! + Writing a bug to CL (or SJ) and seeing what happens (#i80380#). + SJ took a look and we got it working. Tested VCL MetaFile Renderer based export, + as intended, the original file is exported. Works, Done. + + + + + To be done: - - Maybe there are more places to take care of! - TODO! + - Maybe there are more places to take care of for vcl::PDFExtOutDevData! - */ + ****************************************************************************************************/ void VclMetafileProcessor2D::processBasePrimitive2D(const primitive2d::BasePrimitive2D& rCandidate) { @@ -799,8 +794,9 @@ namespace drawinglayer } case drawinglayer::primitive2d::FIELD_TYPE_URL : { - const String& rURL = rFieldPrimitive.getString(); - mrMetaFile.AddAction(new MetaCommentAction(aCommentStringCommon, 0, reinterpret_cast< const BYTE* >(rURL.GetBuffer()), 2 * rURL.Len())); + const rtl::OUString& rURL = rFieldPrimitive.getString(); + const String aOldString(rURL); + mrMetaFile.AddAction(new MetaCommentAction(aCommentStringCommon, 0, reinterpret_cast< const BYTE* >(aOldString.GetBuffer()), 2 * aOldString.Len())); break; } } @@ -896,10 +892,10 @@ namespace drawinglayer if(mxBreakIterator.is()) { - const String& rTxt = rTextCandidate.getText(); - const sal_uInt16 nLen(rTxt.Len()); + const rtl::OUString& rTxt = rTextCandidate.getText(); + const sal_Int32 nTextLength(rTxt.getLength()); - if(nLen) + if(nTextLength) { const ::com::sun::star::lang::Locale& rLocale = rTextCandidate.getLocale(); @@ -911,7 +907,7 @@ namespace drawinglayer static const ByteString aCommentStringB("XTEXT_EOW"); static const ByteString aCommentStringC("XTEXT_EOS"); - for(sal_Int32 i(0); i < nLen; i++) + for(sal_Int32 i(0); i < nTextLength; i++) { // create the entries for the respective break positions if(i == nNextCellBreak) diff --git a/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx b/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx index d0dca1bece22..c8ba3e516b06 100644 --- a/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx +++ b/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx @@ -4,9 +4,9 @@ * * $RCSfile: vclpixelprocessor2d.cxx,v $ * - * $Revision: 1.3 $ + * $Revision: 1.4 $ * - * last change: $Author: aw $ $Date: 2007-09-20 09:51:38 $ + * last change: $Author: aw $ $Date: 2007-09-26 11:36:36 $ * * The Contents of this file are made available subject to * the terms of GNU Lesser General Public License Version 2.1. @@ -140,12 +140,26 @@ namespace drawinglayer break; } case PRIMITIVE2D_ID_TEXTSIMPLEPORTIONPRIMITIVE2D : + { + // directdraw of text simple portion; added test possibility to check text decompose + static bool bHandleSimpleTextDirectly(true); + + if(bHandleSimpleTextDirectly) + { + RenderTextSimpleOrDecoratedPortionPrimitive2D(static_cast< const primitive2d::TextSimplePortionPrimitive2D& >(rCandidate)); + } + else + { + process(rCandidate.get2DDecomposition(getViewInformation2D())); + } + break; + } case PRIMITIVE2D_ID_TEXTDECORATEDPORTIONPRIMITIVE2D : { // directdraw of text simple portion; added test possibility to check text decompose - static bool bHandleTextDirectly(false); + static bool bHandleComplexTextDirectly(false); - if(bHandleTextDirectly) + if(bHandleComplexTextDirectly) { RenderTextSimpleOrDecoratedPortionPrimitive2D(static_cast< const primitive2d::TextSimplePortionPrimitive2D& >(rCandidate)); } |