From 841e11c98a444218df99317b7df4b6a4b53e7c33 Mon Sep 17 00:00:00 2001 From: Armin Weiss Date: Mon, 19 Nov 2007 09:21:42 +0000 Subject: #i39532# Lot of changes to make polygon stuff bezier-able --- .../drawinglayer/primitive2d/textlayoutdevice.hxx | 30 ++- .../drawinglayer/primitive2d/textprimitive2d.hxx | 36 ++- .../source/primitive2d/fillgradientprimitive2d.cxx | 5 +- .../source/primitive2d/gridprimitive2d.cxx | 6 +- .../source/primitive2d/polygonprimitive2d.cxx | 30 ++- .../source/primitive2d/polypolygonprimitive2d.cxx | 10 +- .../primitive2d/textdecoratedprimitive2d.cxx | 13 +- .../source/primitive2d/textlayoutdevice.cxx | 109 +++++++++- .../source/primitive2d/textprimitive2d.cxx | 241 +++++++++++---------- .../source/processor2d/vclmetafileprocessor2d.cxx | 32 ++- drawinglayer/source/processor2d/vclprocessor2d.cxx | 13 +- 11 files changed, 344 insertions(+), 181 deletions(-) (limited to 'drawinglayer') diff --git a/drawinglayer/inc/drawinglayer/primitive2d/textlayoutdevice.hxx b/drawinglayer/inc/drawinglayer/primitive2d/textlayoutdevice.hxx index f023705d2fb6..5b4f8879c873 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.5 $ + * $Revision: 1.6 $ * - * last change: $Author: aw $ $Date: 2007-10-01 09:13:53 $ + * last change: $Author: aw $ $Date: 2007-11-19 10:21:42 $ * * The Contents of this file are made available subject to * the terms of GNU Lesser General Public License Version 2.1. @@ -59,6 +59,7 @@ class VirtualDevice; class Font; class String; +class OutputDevice; namespace drawinglayer { namespace primitive2d { class FontAttributes; @@ -87,6 +88,7 @@ namespace drawinglayer void setFont(const Font& rFont); void setFontAttributes(const FontAttributes& rFontAttributes, const basegfx::B2DHomMatrix& rTransform); + void setFontAttributes(const FontAttributes& rFontAttributes, double fFontScaleX, double fFontScaleY); double getTextHeight() const; double getUnderlineHeight() const; @@ -115,4 +117,28 @@ namespace drawinglayer ////////////////////////////////////////////////////////////////////////////// +namespace drawinglayer +{ + namespace primitive2d + { + // helper methods for vcl font handling + Font getVclFontFromFontAttributes( + const FontAttributes& rFontAttributes, + double fFontScaleX, + double fFontScaleY, + double fFontRotation, + const OutputDevice& rOutDev); + + Font getVclFontFromFontAttributes( + const FontAttributes& rFontAttributes, + const basegfx::B2DHomMatrix& rTransform, + const OutputDevice& rOutDev); + + FontAttributes getFontAttributesFromVclFont(basegfx::B2DVector& rSize, const Font& rFont, bool bRTL, bool bBiDiStrong); + + } // end of namespace primitive2d +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// + #endif //_DRAWINGLAYER_TEXTLAYOUTDEVICE_HXX diff --git a/drawinglayer/inc/drawinglayer/primitive2d/textprimitive2d.hxx b/drawinglayer/inc/drawinglayer/primitive2d/textprimitive2d.hxx index 0d0775f6a4c6..cb97c29a851f 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.11 $ + * $Revision: 1.12 $ * - * last change: $Author: aw $ $Date: 2007-10-02 16:54:52 $ + * last change: $Author: aw $ $Date: 2007-11-19 10:21:42 $ * * The Contents of this file are made available subject to * the terms of GNU Lesser General Public License Version 2.1. @@ -62,6 +62,16 @@ #include #endif +////////////////////////////////////////////////////////////////////////////// +// predefines + +namespace basegfx { + class B2DPolyPolygon; + typedef ::std::vector< B2DPolyPolygon > B2DPolyPolygonVector; +} + +class OutputDevice; + ////////////////////////////////////////////////////////////////////////////// namespace drawinglayer @@ -122,12 +132,6 @@ namespace drawinglayer bool getRTL() const { return mbRTL; } bool getBiDiStrong() const { return mbBiDiStrong; } }; - - // helper methods for vcl font - Font getVclFontFromFontAttributes(const FontAttributes& rFontAttributes, const basegfx::B2DVector& rFontSize, double fFontRotation); - Font getVclFontFromFontAttributes(const FontAttributes& rFontAttributes, const basegfx::B2DHomMatrix& rTransform); - FontAttributes getFontAttributesFromVclFont(basegfx::B2DVector& rSize, const Font& rFont, bool bRTL, bool bBiDiStrong); - } // end of namespace primitive2d } // end of namespace drawinglayer @@ -164,6 +168,19 @@ namespace drawinglayer const ::com::sun::star::lang::Locale& rLocale, const basegfx::BColor& rFontColor); + // helpers + // get text outlines as polygons and their according ObjectTransformation. Handles all + // the necessary VCL outline extractins, scaling adaptions and other stuff. + void getTextOutlinesAndTransformation(basegfx::B2DPolyPolygonVector& rTarget, basegfx::B2DHomMatrix& rTransformation) const; + + // adapts fontScale for usage with TextLayouter. Input is rScale which is the extracted + // scale from a text transformation. A copy goes to rFontScale and is modified so that + // it contains only positive scalings and XY-equal scalings to allow to get a non-X-scaled + // Vcl-Font for TextLayouter. rScale is adapted accordingly to contain the corrected scale + // which would need to be applied to e.g. outlines received from TextLayouter under + // usage of fontScale. This includes Y-Scale, X-Scale-correction and mirrorings. + void getCorrectedScaleAndFontScale(basegfx::B2DVector& rScale, basegfx::B2DVector& rFontScale) const; + // get data const basegfx::B2DHomMatrix& getTextTransform() const { return maTextTransform; } const String& getText() const { return maText; } @@ -174,9 +191,6 @@ namespace drawinglayer const ::com::sun::star::lang::Locale& getLocale() const { return maLocale; } const basegfx::BColor& getFontColor() const { return maFontColor; } - // helper to have a central conversion to font-size-scaled integer DXArray - void getIntegerDXArray(::std::vector< sal_Int32 >& rDXArray) const; - // compare operator virtual bool operator==( const BasePrimitive2D& rPrimitive ) const; diff --git a/drawinglayer/source/primitive2d/fillgradientprimitive2d.cxx b/drawinglayer/source/primitive2d/fillgradientprimitive2d.cxx index 5c4f9df8ceae..be45936f5cfb 100644 --- a/drawinglayer/source/primitive2d/fillgradientprimitive2d.cxx +++ b/drawinglayer/source/primitive2d/fillgradientprimitive2d.cxx @@ -4,9 +4,9 @@ * * $RCSfile: fillgradientprimitive2d.cxx,v $ * - * $Revision: 1.3 $ + * $Revision: 1.4 $ * - * last change: $Author: aw $ $Date: 2007-03-06 12:34:29 $ + * last change: $Author: aw $ $Date: 2007-11-19 10:21:42 $ * * The Contents of this file are made available subject to * the terms of GNU Lesser General Public License Version 2.1. @@ -83,7 +83,6 @@ namespace drawinglayer { const basegfx::B2DPoint aCircleCenter(0.5, 0.5); aUnitPolygon = basegfx::tools::createPolygonFromEllipse(aCircleCenter, 0.5, 0.5); - aUnitPolygon = basegfx::tools::adaptiveSubdivideByAngle(aUnitPolygon); } else { diff --git a/drawinglayer/source/primitive2d/gridprimitive2d.cxx b/drawinglayer/source/primitive2d/gridprimitive2d.cxx index 4d776fb90aca..7174782457eb 100644 --- a/drawinglayer/source/primitive2d/gridprimitive2d.cxx +++ b/drawinglayer/source/primitive2d/gridprimitive2d.cxx @@ -4,9 +4,9 @@ * * $RCSfile: gridprimitive2d.cxx,v $ * - * $Revision: 1.5 $ + * $Revision: 1.6 $ * - * last change: $Author: aw $ $Date: 2007-07-27 09:03:33 $ + * last change: $Author: aw $ $Date: 2007-11-19 10:21:42 $ * * The Contents of this file are made available subject to * the terms of GNU Lesser General Public License Version 2.1. @@ -80,8 +80,8 @@ namespace drawinglayer // create grid matrix which transforms from scaled logic to view basegfx::B2DHomMatrix aRST; - aRST.rotate(fRotate); aRST.shearX(fShearX); + aRST.rotate(fRotate); aRST.translate(aTranslate.getX(), aTranslate.getY()); aRST *= rViewInformation.getViewTransformation(); diff --git a/drawinglayer/source/primitive2d/polygonprimitive2d.cxx b/drawinglayer/source/primitive2d/polygonprimitive2d.cxx index 22d799bf26f6..c423571dbe71 100644 --- a/drawinglayer/source/primitive2d/polygonprimitive2d.cxx +++ b/drawinglayer/source/primitive2d/polygonprimitive2d.cxx @@ -4,9 +4,9 @@ * * $RCSfile: polygonprimitive2d.cxx,v $ * - * $Revision: 1.6 $ + * $Revision: 1.7 $ * - * last change: $Author: aw $ $Date: 2007-11-07 14:27:26 $ + * last change: $Author: aw $ $Date: 2007-11-19 10:21:42 $ * * The Contents of this file are made available subject to * the terms of GNU Lesser General Public License Version 2.1. @@ -92,7 +92,7 @@ namespace drawinglayer basegfx::B2DRange PolygonHairlinePrimitive2D::getB2DRange(const geometry::ViewInformation2D& /*rViewInformation*/) const { // return range - return basegfx::tools::getRange(basegfx::tools::adaptiveSubdivideByAngle(getB2DPolygon())); + return basegfx::tools::getRange(getB2DPolygon()); } // provide unique ID @@ -166,7 +166,7 @@ namespace drawinglayer basegfx::B2DRange PolygonMarkerPrimitive2D::getB2DRange(const geometry::ViewInformation2D& /*rViewInformation*/) const { // return range - return basegfx::tools::getRange(basegfx::tools::adaptiveSubdivideByAngle(getB2DPolygon())); + return basegfx::tools::getRange(getB2DPolygon()); } // provide unique ID @@ -189,6 +189,7 @@ namespace drawinglayer if(0.0 == getStrokeAttribute().getFullDotDashLen()) { + // no line dashing, just copy aHairLinePolyPolygon.append(getB2DPolygon()); } else @@ -201,14 +202,7 @@ namespace drawinglayer if(getLineAttribute().getWidth()) { - static bool bTestNewMethod(true); - // create fat line data - if(!bTestNewMethod) - { - aHairLinePolyPolygon = basegfx::tools::adaptiveSubdivideByAngle(aHairLinePolyPolygon); - } - const double fHalfLineWidth(getLineAttribute().getWidth() / 2.0); const double fMiterMinimumAngle(15.0 * F_PI180); const basegfx::B2DLineJoin aLineJoin(getLineAttribute().getLineJoin()); @@ -231,7 +225,8 @@ namespace drawinglayer // to be painted as a single PolyPolygon (XORed as fill rule). Alternatively, a // melting process may be used here one day. const basegfx::B2DPolyPolygon aNewPolyPolygon(aAreaPolyPolygon.getB2DPolygon(b)); - const basegfx::BColor aColor(bTestNewMethod + static bool bTestByUsingRandomColor(true); + const basegfx::BColor aColor(bTestByUsingRandomColor ? basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0) : getLineAttribute().getColor()); const Primitive2DReference xRef(new PolyPolygonColorPrimitive2D(aNewPolyPolygon, aColor)); @@ -291,7 +286,7 @@ namespace drawinglayer basegfx::B2DRange PolygonStrokePrimitive2D::getB2DRange(const geometry::ViewInformation2D& /*rViewInformation*/) const { // get range of it (subdivided) - basegfx::B2DRange aRetval(basegfx::tools::getRange(basegfx::tools::adaptiveSubdivideByAngle(getB2DPolygon()))); + basegfx::B2DRange aRetval(basegfx::tools::getRange(getB2DPolygon())); // if width, grow by line width if(getLineAttribute().getWidth()) @@ -436,8 +431,7 @@ namespace drawinglayer if(!aLocalPolygon.isClosed()) { - // apply arrows. To do that, make sure it's not a curve (necessary at the moment, maybe optimized later) - aLocalPolygon = basegfx::tools::adaptiveSubdivideByAngle(aLocalPolygon); + // apply arrows const double fPolyLength(basegfx::tools::getLength(aLocalPolygon)); double fStart(0.0); double fEnd(0.0); @@ -446,7 +440,8 @@ namespace drawinglayer { // create start arrow primitive and consume aArrowA = basegfx::tools::createAreaGeometryForLineStartEnd( - aLocalPolygon, getStart().getB2DPolyPolygon(), true, getStart().getWidth(), getStart().isCentered() ? 0.5 : 0.0, &fStart); + aLocalPolygon, getStart().getB2DPolyPolygon(), true, getStart().getWidth(), + fPolyLength, getStart().isCentered() ? 0.5 : 0.0, &fStart); // create some overlapping fStart *= 0.8; @@ -456,7 +451,8 @@ namespace drawinglayer { // create end arrow primitive and consume aArrowB = basegfx::tools::createAreaGeometryForLineStartEnd( - aLocalPolygon, getEnd().getB2DPolyPolygon(), false, getEnd().getWidth(), getEnd().isCentered() ? 0.5 : 0.0, &fEnd); + aLocalPolygon, getEnd().getB2DPolyPolygon(), false, getEnd().getWidth(), + fPolyLength, getEnd().isCentered() ? 0.5 : 0.0, &fEnd); // create some overlapping fEnd *= 0.8; diff --git a/drawinglayer/source/primitive2d/polypolygonprimitive2d.cxx b/drawinglayer/source/primitive2d/polypolygonprimitive2d.cxx index 025cb07afcf6..61a808d291d7 100644 --- a/drawinglayer/source/primitive2d/polypolygonprimitive2d.cxx +++ b/drawinglayer/source/primitive2d/polypolygonprimitive2d.cxx @@ -4,9 +4,9 @@ * * $RCSfile: polypolygonprimitive2d.cxx,v $ * - * $Revision: 1.5 $ + * $Revision: 1.6 $ * - * last change: $Author: aw $ $Date: 2007-11-07 14:27:26 $ + * last change: $Author: aw $ $Date: 2007-11-19 10:21:42 $ * * The Contents of this file are made available subject to * the terms of GNU Lesser General Public License Version 2.1. @@ -128,7 +128,7 @@ namespace drawinglayer basegfx::B2DRange PolyPolygonHairlinePrimitive2D::getB2DRange(const geometry::ViewInformation2D& /*rViewInformation*/) const { // return range - return basegfx::tools::getRange(basegfx::tools::adaptiveSubdivideByAngle(getB2DPolyPolygon())); + return basegfx::tools::getRange(getB2DPolyPolygon()); } // provide unique ID @@ -203,7 +203,7 @@ namespace drawinglayer basegfx::B2DRange PolyPolygonStrokePrimitive2D::getB2DRange(const geometry::ViewInformation2D& /*rViewInformation*/) const { // get range of it (subdivided) - basegfx::B2DRange aRetval(basegfx::tools::getRange(basegfx::tools::adaptiveSubdivideByAngle(getB2DPolyPolygon()))); + basegfx::B2DRange aRetval(basegfx::tools::getRange(getB2DPolyPolygon())); // if width, grow by line width if(getLineAttribute().getWidth()) @@ -347,7 +347,7 @@ namespace drawinglayer basegfx::B2DRange PolyPolygonColorPrimitive2D::getB2DRange(const geometry::ViewInformation2D& /*rViewInformation*/) const { // return range - return basegfx::tools::getRange(basegfx::tools::adaptiveSubdivideByAngle(getB2DPolyPolygon())); + return basegfx::tools::getRange(getB2DPolyPolygon()); } // provide unique ID diff --git a/drawinglayer/source/primitive2d/textdecoratedprimitive2d.cxx b/drawinglayer/source/primitive2d/textdecoratedprimitive2d.cxx index d4c6e5a46b75..4007d591f6e4 100644 --- a/drawinglayer/source/primitive2d/textdecoratedprimitive2d.cxx +++ b/drawinglayer/source/primitive2d/textdecoratedprimitive2d.cxx @@ -4,9 +4,9 @@ * * $RCSfile: textdecoratedprimitive2d.cxx,v $ * - * $Revision: 1.9 $ + * $Revision: 1.10 $ * - * last change: $Author: aw $ $Date: 2007-11-07 14:27:26 $ + * last change: $Author: aw $ $Date: 2007-11-19 10:21:42 $ * * The Contents of this file are made available subject to * the terms of GNU Lesser General Public License Version 2.1. @@ -118,16 +118,13 @@ namespace drawinglayer TextLayouterDevice aTextLayouter; // unscaled is needed since scale contains already the font size - aUnscaledTransform.rotate(rDecTrans.getRotate()); aUnscaledTransform.shearX(rDecTrans.getShearX()); + aUnscaledTransform.rotate(rDecTrans.getRotate()); 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); + // underline/strikeout/emphasis marks from it. For setup, the font size is needed + aTextLayouter.setFontAttributes(getFontAttributes(), rDecTrans.getScale().getX(), rDecTrans.getScale().getY()); // get text width double fTextWidth(0.0); diff --git a/drawinglayer/source/primitive2d/textlayoutdevice.cxx b/drawinglayer/source/primitive2d/textlayoutdevice.cxx index 18ee93a36c62..56d7ea292bba 100644 --- a/drawinglayer/source/primitive2d/textlayoutdevice.cxx +++ b/drawinglayer/source/primitive2d/textlayoutdevice.cxx @@ -4,9 +4,9 @@ * * $RCSfile: textlayoutdevice.cxx,v $ * - * $Revision: 1.6 $ + * $Revision: 1.7 $ * - * last change: $Author: aw $ $Date: 2007-10-01 09:14:08 $ + * last change: $Author: aw $ $Date: 2007-11-19 10:21:42 $ * * The Contents of this file are made available subject to * the terms of GNU Lesser General Public License Version 2.1. @@ -57,6 +57,10 @@ #include #endif +//#ifndef _SV_OUTDEV_HXX +//#include +//#endif + ////////////////////////////////////////////////////////////////////////////// // VDev RevDevice provider @@ -181,7 +185,12 @@ namespace drawinglayer void TextLayouterDevice::setFontAttributes(const FontAttributes& rFontAttributes, const basegfx::B2DHomMatrix& rTransform) { - setFont( getVclFontFromFontAttributes(rFontAttributes, rTransform) ); + setFont(getVclFontFromFontAttributes(rFontAttributes, rTransform, mrDevice)); + } + + void TextLayouterDevice::setFontAttributes(const FontAttributes& rFontAttributes, double fFontScaleX, double fFontScaleY) + { + setFont(getVclFontFromFontAttributes(rFontAttributes, fFontScaleX, fFontScaleY, 0.0, mrDevice)); } double TextLayouterDevice::getUnderlineOffset() const @@ -264,5 +273,99 @@ namespace drawinglayer } // end of namespace primitive2d } // end of namespace drawinglayer +////////////////////////////////////////////////////////////////////////////// +// helper methods for vcl font handling + +namespace drawinglayer +{ + namespace primitive2d + { + Font getVclFontFromFontAttributes( + const FontAttributes& rFontAttributes, + const basegfx::B2DHomMatrix& rTransform, + const OutputDevice& rOutDev) + { + // decompose matrix to have position and size of text + basegfx::B2DVector aScale, aTranslate; + double fRotate, fShearX; + + rTransform.decompose(aScale, aTranslate, fRotate, fShearX); + + return getVclFontFromFontAttributes(rFontAttributes, aScale.getX(), aScale.getY(), fRotate, rOutDev); + } + + Font getVclFontFromFontAttributes( + const FontAttributes& rFontAttributes, + double fFontScaleX, + double fFontScaleY, + double fFontRotation, + const OutputDevice& rOutDev) + { +#ifndef WIN32 + // not used under unix, but reference for warning-free + (void)rOutDev; +#endif + sal_uInt32 nWidth(basegfx::fround(fabs(fFontScaleX))); + sal_uInt32 nHeight(basegfx::fround(fabs(fFontScaleY))); + Font aRetval( + rFontAttributes.getFamilyName(), + rFontAttributes.getStyleName(), +#ifdef WIN32 + Size(0, nHeight)); +#else + Size(nWidth, nHeight)); +#endif + + aRetval.SetAlign(ALIGN_BASELINE); + aRetval.SetCharSet(rFontAttributes.getSymbol() ? RTL_TEXTENCODING_SYMBOL : RTL_TEXTENCODING_UNICODE); + aRetval.SetVertical(rFontAttributes.getVertical() ? TRUE : FALSE); + aRetval.SetWeight(static_cast(rFontAttributes.getWeight())); + aRetval.SetItalic(rFontAttributes.getItalic() ? ITALIC_NORMAL : ITALIC_NONE); + aRetval.SetOutline(rFontAttributes.getOutline()); + +#ifdef WIN32 + if(nWidth != nHeight) + { + const FontMetric aFontMetric(rOutDev.GetFontMetric(aRetval)); + const double fCurrentWidth(aFontMetric.GetWidth()); + + aRetval.SetWidth(basegfx::fround(fCurrentWidth * (nWidth/nHeight))); + } +#endif + + if(!basegfx::fTools::equalZero(fFontRotation)) + { + sal_Int16 aRotate10th((sal_Int16)(fFontRotation * (-1800.0/F_PI))); + aRetval.SetOrientation(aRotate10th % 3600); + } + + return aRetval; + } + + FontAttributes getFontAttributesFromVclFont(basegfx::B2DVector& rSize, const Font& rFont, bool bRTL, bool bBiDiStrong) + { + FontAttributes aRetval( + rFont.GetName(), + rFont.GetStyleName(), + static_cast(rFont.GetWeight()), + RTL_TEXTENCODING_SYMBOL == rFont.GetCharSet(), + rFont.IsVertical(), + ITALIC_NONE != rFont.GetItalic(), + rFont.IsOutline(), + bRTL, + bBiDiStrong); + // TODO: eKerning + + const sal_Int32 nWidth(rFont.GetSize().getWidth()); + const sal_Int32 nHeight(rFont.GetSize().getHeight()); + + rSize.setX(nWidth ? nWidth : nHeight); + rSize.setY(nHeight); + + return aRetval; + } + } // end of namespace primitive2d +} // end of namespace drawinglayer + ////////////////////////////////////////////////////////////////////////////// // eof diff --git a/drawinglayer/source/primitive2d/textprimitive2d.cxx b/drawinglayer/source/primitive2d/textprimitive2d.cxx index d11a75ac5116..59c9e9281a8f 100644 --- a/drawinglayer/source/primitive2d/textprimitive2d.cxx +++ b/drawinglayer/source/primitive2d/textprimitive2d.cxx @@ -4,9 +4,9 @@ * * $RCSfile: textprimitive2d.cxx,v $ * - * $Revision: 1.18 $ + * $Revision: 1.19 $ * - * last change: $Author: aw $ $Date: 2007-10-02 16:55:00 $ + * last change: $Author: aw $ $Date: 2007-11-19 10:21:42 $ * * The Contents of this file are made available subject to * the terms of GNU Lesser General Public License Version 2.1. @@ -59,6 +59,10 @@ ////////////////////////////////////////////////////////////////////////////// +using namespace com::sun::star; + +////////////////////////////////////////////////////////////////////////////// + namespace drawinglayer { namespace primitive2d @@ -84,114 +88,111 @@ namespace drawinglayer { namespace primitive2d { - Font getVclFontFromFontAttributes(const FontAttributes& rFontAttributes, const basegfx::B2DHomMatrix& rTransform) + void TextSimplePortionPrimitive2D::getCorrectedScaleAndFontScale(basegfx::B2DVector& rScale, basegfx::B2DVector& rFontScale) const { - // decompose matrix to have position and size of text - basegfx::B2DVector aScale, aTranslate; - double fRotate, fShearX; - rTransform.decompose(aScale, aTranslate, fRotate, fShearX); - return getVclFontFromFontAttributes(rFontAttributes, aScale, fRotate); - } - - Font getVclFontFromFontAttributes(const FontAttributes& rFontAttributes, const basegfx::B2DVector& rFontSize, double fFontRotation) - { - sal_uInt32 nWidth(basegfx::fround(fabs(rFontSize.getX()))); - sal_uInt32 nHeight(basegfx::fround(fabs(rFontSize.getY()))); + // copy input value + rFontScale = rScale; - if(nWidth == nHeight) + if(basegfx::fTools::equalZero(rFontScale.getY())) { - nWidth = 0L; + // no font height; choose one and adapt scale to get back to original scaling + static double fDefaultFontScale(100.0); + rScale.setY(1.0 / fDefaultFontScale); + rFontScale.setY(fDefaultFontScale); } - - Font aRetval( - rFontAttributes.getFamilyName(), - rFontAttributes.getStyleName(), - Size(nWidth, nHeight)); - - if(!basegfx::fTools::equalZero(fFontRotation)) + else if(basegfx::fTools::less(rFontScale.getY(), 0.0)) { - sal_Int16 aRotate10th((sal_Int16)(fFontRotation * (-1800.0/F_PI))); - aRetval.SetOrientation(aRotate10th % 3600); + // negative font height; invert and adapt scale to get back to original scaling + rFontScale.setY(-rFontScale.getY()); + rScale.setY(-1.0); + } + else + { + // positive font height; adapt scale; scaling will be part of the polygons + rScale.setY(1.0); } - aRetval.SetAlign(ALIGN_BASELINE); - aRetval.SetCharSet(rFontAttributes.getSymbol() ? RTL_TEXTENCODING_SYMBOL : RTL_TEXTENCODING_UNICODE); - aRetval.SetVertical(rFontAttributes.getVertical() ? TRUE : FALSE); - aRetval.SetWeight(static_cast(rFontAttributes.getWeight())); - aRetval.SetItalic(rFontAttributes.getItalic() ? ITALIC_NORMAL : ITALIC_NONE); - aRetval.SetOutline(rFontAttributes.getOutline()); - - return aRetval; + if(basegfx::fTools::equal(rFontScale.getX(), rFontScale.getY())) + { + // adapt scale in X + rScale.setX(1.0); + } + else + { + // If font scale is different in X and Y, force font scale to equal + // in X and Y to get a non-scaled VCL font. + // Adapt scaling in X accordingly. FontScaleY cannot be zero here. + rScale.setX(rFontScale.getX()/rFontScale.getY()); + rFontScale.setX(rFontScale.getY()); + } } - FontAttributes getFontAttributesFromVclFont(basegfx::B2DVector& rSize, const Font& rFont, bool bRTL, bool bBiDiStrong) + void TextSimplePortionPrimitive2D::getTextOutlinesAndTransformation(basegfx::B2DPolyPolygonVector& rTarget, basegfx::B2DHomMatrix& rTransformation) const { - FontAttributes aRetval( - rFont.GetName(), - rFont.GetStyleName(), - static_cast(rFont.GetWeight()), - RTL_TEXTENCODING_SYMBOL == rFont.GetCharSet(), - rFont.IsVertical(), - ITALIC_NONE != rFont.GetItalic(), - rFont.IsOutline(), - bRTL, - bBiDiStrong); - // TODO: eKerning - - const sal_Int32 nWidth(rFont.GetSize().getWidth()); - const sal_Int32 nHeight(rFont.GetSize().getHeight()); - - rSize.setX(nWidth ? nWidth : nHeight); - rSize.setY(nHeight); + if(getTextLength()) + { + // decompose object transformation to single values + basegfx::B2DVector aScale, aTranslate; + double fRotate, fShearX; - return aRetval; - } - } // end of namespace primitive2d -} // end of namespace drawinglayer + // if decomposition returns false, create no geometry since e.g. scaling may + // be zero + if(getTextTransform().decompose(aScale, aTranslate, fRotate, fShearX)) + { + // handle special case: If scale is negative in (x,y) (3rd quadrant), it can + // be expressed as rotation by PI + if(basegfx::fTools::less(aScale.getX(), 0.0) && basegfx::fTools::less(aScale.getY(), 0.0)) + { + aScale = basegfx::absolute(aScale); + fRotate += F_PI; + } -////////////////////////////////////////////////////////////////////////////// + // for the TextLayouterDevice, it is necessary to have a scaling representing + // the font size. Since we want to extract polygons here, it is okay to + // work just with scaling and to ignore shear, rotation and translation, + // all that can be applied to the polygons later + basegfx::B2DVector aFontScale; + getCorrectedScaleAndFontScale(aScale, aFontScale); -using namespace com::sun::star; + // prepare textlayoutdevice + TextLayouterDevice aTextLayouter; + aTextLayouter.setFontAttributes(getFontAttributes(), aFontScale.getX(), aFontScale.getY()); -////////////////////////////////////////////////////////////////////////////// + // get integer DXArray for getTextOutlines call (ATM uses vcl, so this + // is needed) + const basegfx::B2DVector aPixelVector(getTextTransform() * basegfx::B2DVector(1.0, 0.0)); + const ::std::vector< sal_Int32 > aNewIntegerDXArray(getDXArray().size(), basegfx::fround(aPixelVector.getLength())); + + // get the text outlines + aTextLayouter.getTextOutlines(rTarget, getText(), getTextPosition(), getTextLength(), aNewIntegerDXArray); + + // create primitives for the outlines + const sal_uInt32 nCount(rTarget.size()); + + if(nCount) + { + // prepare object transformation for polygons + rTransformation.identity(); + rTransformation.scale(aScale.getX(), aScale.getY()); + rTransformation.shearX(fShearX); + rTransformation.rotate(fRotate); + rTransformation.translate(aTranslate.getX(), aTranslate.getY()); + } + } + } + } -namespace drawinglayer -{ - namespace primitive2d - { Primitive2DSequence TextSimplePortionPrimitive2D::createLocalDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const { Primitive2DSequence aRetval; if(getTextLength()) { - // 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(), getTextPosition(), getTextLength(), aNewIntegerDXArray); + basegfx::B2DHomMatrix aPolygonTransform; + + // get text outlines and their object transformation + getTextOutlinesAndTransformation(aB2DPolyPolyVector, aPolygonTransform); // create primitives for the outlines const sal_uInt32 nCount(aB2DPolyPolyVector.size()); @@ -206,12 +207,17 @@ namespace drawinglayer { // prepare polypolygon basegfx::B2DPolyPolygon& rPolyPolygon = aB2DPolyPolyVector[a]; - rPolyPolygon.transform(aUnscaledTransform); + rPolyPolygon.transform(aPolygonTransform); aRetval[a] = new PolyPolygonColorPrimitive2D(rPolyPolygon, getFontColor()); } if(getFontAttributes().getOutline()) { + // decompose polygon transformation to single values + basegfx::B2DVector aScale, aTranslate; + double fRotate, fShearX; + aPolygonTransform.decompose(aScale, aTranslate, fRotate, fShearX); + // create outline text effect with current content and replace Primitive2DReference aNewTextEffect(new TextEffectPrimitive2D( aRetval, @@ -253,23 +259,6 @@ namespace drawinglayer #endif } - void TextSimplePortionPrimitive2D::getIntegerDXArray(::std::vector< sal_Int32 >& rDXArray) const - { - rDXArray.clear(); - - if(getDXArray().size()) - { - rDXArray.reserve(getDXArray().size()); - const basegfx::B2DVector aPixelVector(getTextTransform() * basegfx::B2DVector(1.0, 0.0)); - const double fPixelVectorLength(aPixelVector.getLength()); - - for(::std::vector< double >::const_iterator aStart(getDXArray().begin()); aStart != getDXArray().end(); aStart++) - { - rDXArray.push_back(basegfx::fround((*aStart) * fPixelVectorLength)); - } - } - } - bool impLocalesAreEqual(const ::com::sun::star::lang::Locale& rA, const ::com::sun::star::lang::Locale& rB) { return (rA.Language == rB.Language @@ -303,21 +292,37 @@ namespace drawinglayer if(getTextLength()) { // get TextBoundRect as base size - TextLayouterDevice aTextLayouter; - aTextLayouter.setFontAttributes(getFontAttributes(), getTextTransform()); - aRetval = aTextLayouter.getTextBoundRect(getText(), getTextPosition(), getTextLength()); - - // apply textTransform to it, but without scaling. The scale defines the font size - // which is already part of the fetched textRange + // decompose object transformation to single values basegfx::B2DVector aScale, aTranslate; double fRotate, fShearX; - basegfx::B2DHomMatrix aTextTransformWithoutScale; - getTextTransform().decompose(aScale, aTranslate, fRotate, fShearX); - aTextTransformWithoutScale.shearX(fShearX); - aTextTransformWithoutScale.rotate(fRotate); - aTextTransformWithoutScale.translate(aTranslate.getX(), aTranslate.getY()); - aRetval.transform(aTextTransformWithoutScale); + if(getTextTransform().decompose(aScale, aTranslate, fRotate, fShearX)) + { + // for the TextLayouterDevice, it is necessary to have a scaling representing + // the font size. Since we want to extract polygons here, it is okay to + // work just with scaling and to ignore shear, rotation and translation, + // all that can be applied to the polygons later + basegfx::B2DVector aFontScale; + getCorrectedScaleAndFontScale(aScale, aFontScale); + + // prepare textlayoutdevice + TextLayouterDevice aTextLayouter; + aTextLayouter.setFontAttributes(getFontAttributes(), aFontScale.getX(), aFontScale.getY()); + + // get basic text range + aRetval = aTextLayouter.getTextBoundRect(getText(), getTextPosition(), getTextLength()); + + // prepare object transformation for range + basegfx::B2DHomMatrix aRangeTransformation; + + aRangeTransformation.scale(aScale.getX(), aScale.getY()); + aRangeTransformation.shearX(fShearX); + aRangeTransformation.rotate(fRotate); + aRangeTransformation.translate(aTranslate.getX(), aTranslate.getY()); + + // apply range transformation to it + aRetval.transform(aRangeTransformation); + } } return aRetval; diff --git a/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx b/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx index 70d4b5fc5d14..63149fe24d1d 100644 --- a/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx +++ b/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx @@ -4,9 +4,9 @@ * * $RCSfile: vclmetafileprocessor2d.cxx,v $ * - * $Revision: 1.12 $ + * $Revision: 1.13 $ * - * last change: $Author: aw $ $Date: 2007-11-07 14:27:27 $ + * last change: $Author: aw $ $Date: 2007-11-19 10:21:42 $ * * The Contents of this file are made available subject to * the terms of GNU Lesser General Public License Version 2.1. @@ -169,6 +169,10 @@ #include #endif +#ifndef _BGFX_POLYGON_B2DPOLYGONTOOLS_HXX +#include +#endif + ////////////////////////////////////////////////////////////////////////////// // for PDFExtOutDevData Graphic support @@ -369,17 +373,30 @@ namespace drawinglayer if(!rB2DPolygon.isClosed()) { + double fPolyLength(0.0); + if(pStart && pStart->isActive()) { + fPolyLength = basegfx::tools::getLength(rB2DPolygon); + const basegfx::B2DPolyPolygon aStartArrow(basegfx::tools::createAreaGeometryForLineStartEnd( - rB2DPolygon, pStart->getB2DPolyPolygon(), true, pStart->getWidth(), pStart->isCentered() ? 0.5 : 0.0, 0)); + rB2DPolygon, pStart->getB2DPolyPolygon(), true, pStart->getWidth(), + fPolyLength, pStart->isCentered() ? 0.5 : 0.0, 0)); + aStartPolyPolygon = PolyPolygon(aStartArrow); } if(pEnd && pEnd->isActive()) { + if(basegfx::fTools::equalZero(fPolyLength)) + { + fPolyLength = basegfx::tools::getLength(rB2DPolygon); + } + const basegfx::B2DPolyPolygon aEndArrow(basegfx::tools::createAreaGeometryForLineStartEnd( - rB2DPolygon, pEnd->getB2DPolyPolygon(), false, pEnd->getWidth(), pEnd->isCentered() ? 0.5 : 0.0, 0)); + rB2DPolygon, pEnd->getB2DPolyPolygon(), false, pEnd->getWidth(), + fPolyLength, pEnd->isCentered() ? 0.5 : 0.0, 0)); + aEndPolyPolygon = PolyPolygon(aEndArrow); } } @@ -1097,7 +1114,7 @@ namespace drawinglayer // calculate transformation. Get real object size, all values in FillBitmapAttribute // are relative to the unified object const attribute::FillBitmapAttribute& rFillBitmapAttribute = rBitmapCandidate .getFillBitmap(); - const basegfx::B2DRange aOutlineRange(basegfx::tools::getRange(basegfx::tools::adaptiveSubdivideByAngle(aLocalPolyPolygon))); + const basegfx::B2DRange aOutlineRange(basegfx::tools::getRange(aLocalPolyPolygon)); const basegfx::B2DVector aOutlineSize(aOutlineRange.getRange()); // get absolute values @@ -1375,8 +1392,9 @@ namespace drawinglayer if(maClipPolyPolygon.count()) { - // set VCL clip region; subdivide before conversion to tools polygon + // set VCL clip region; subdivide before conversion to tools polygon. Subdivision necessary (!) mpOutputDevice->Push(PUSH_CLIPREGION); + mpOutputDevice->SetClipRegion(Region(PolyPolygon(maClipPolyPolygon))); mpOutputDevice->SetClipRegion(Region(PolyPolygon(basegfx::tools::adaptiveSubdivideByAngle(maClipPolyPolygon)))); } @@ -1463,7 +1481,7 @@ namespace drawinglayer mpOutputDevice->SetFillColor(Color(aPolygonColor)); mpOutputDevice->SetLineColor(); mpOutputDevice->DrawTransparent( - PolyPolygon(basegfx::tools::adaptiveSubdivideByAngle(aLocalPolyPolygon)), + PolyPolygon(aLocalPolyPolygon), nTransPercentVcl); impEndSvtGraphicFill(pSvtGraphicFill); } diff --git a/drawinglayer/source/processor2d/vclprocessor2d.cxx b/drawinglayer/source/processor2d/vclprocessor2d.cxx index c29bc052ef29..f40146b86d09 100644 --- a/drawinglayer/source/processor2d/vclprocessor2d.cxx +++ b/drawinglayer/source/processor2d/vclprocessor2d.cxx @@ -4,9 +4,9 @@ * * $RCSfile: vclprocessor2d.cxx,v $ * - * $Revision: 1.18 $ + * $Revision: 1.19 $ * - * last change: $Author: aw $ $Date: 2007-10-16 15:46:43 $ + * last change: $Author: aw $ $Date: 2007-11-19 10:21:42 $ * * The Contents of this file are made available subject to * the terms of GNU Lesser General Public License Version 2.1. @@ -164,6 +164,10 @@ #include #endif +#ifndef INCLUDED_DRAWINGLAYER_TEXTLAYOUTDEVICE_HXX +#include +#endif + ////////////////////////////////////////////////////////////////////////////// namespace drawinglayer @@ -171,7 +175,7 @@ namespace drawinglayer namespace processor2d { ////////////////////////////////////////////////////////////////////////////// - // UNO usings + // UNO class usages using ::com::sun::star::uno::Reference; using ::com::sun::star::uno::UNO_QUERY; using ::com::sun::star::uno::UNO_QUERY_THROW; @@ -209,7 +213,8 @@ namespace drawinglayer if(basegfx::fTools::more(aScale.getX(), 0.0) && basegfx::fTools::more(aScale.getY(), 0.0)) { // prepare everything that is not sheared and mirrored - Font aFont(primitive2d::getVclFontFromFontAttributes(rTextCandidate.getFontAttributes(), aScale, fRotate)); + Font aFont(getVclFontFromFontAttributes( + rTextCandidate.getFontAttributes(), aScale.getX(), aScale.getY(), fRotate, *mpOutputDevice)); // handle additional font attributes const primitive2d::TextDecoratedPortionPrimitive2D* pTCPP = -- cgit